aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/advancedDetector.cpp2
-rw-r--r--engines/agi/console.cpp92
-rw-r--r--engines/agi/preagi_mickey.cpp4
-rw-r--r--engines/agi/preagi_winnie.cpp2
-rw-r--r--engines/agos/agos.cpp25
-rw-r--r--engines/agos/agos.h14
-rw-r--r--engines/agos/debugger.cpp117
-rw-r--r--engines/agos/debugger.h1
-rw-r--r--engines/agos/gfx.cpp5
-rw-r--r--engines/agos/midi.cpp4
-rw-r--r--engines/agos/script.cpp3
-rw-r--r--engines/agos/subroutine.cpp8
-rw-r--r--engines/agos/vga.cpp8
-rw-r--r--engines/avalanche/avalot.cpp2
-rw-r--r--engines/avalanche/console.cpp4
-rw-r--r--engines/avalanche/dialogs.cpp2
-rw-r--r--engines/avalanche/ghostroom.cpp3
-rw-r--r--engines/avalanche/ghostroom.h2
-rw-r--r--engines/avalanche/graphics.cpp10
-rw-r--r--engines/avalanche/help.cpp4
-rw-r--r--engines/avalanche/module.mk2
-rw-r--r--engines/avalanche/nim.cpp20
-rw-r--r--engines/avalanche/parser.cpp2
-rw-r--r--engines/avalanche/shootemup.cpp4
-rw-r--r--engines/bbvs/minigames/bbtennis.cpp56
-rw-r--r--engines/bbvs/walk.cpp14
-rw-r--r--engines/cge/POTFILES2
-rw-r--r--engines/cge/cge.cpp2
-rw-r--r--engines/cge/cge.h6
-rw-r--r--engines/cge/console.cpp4
-rw-r--r--engines/cge/detection.cpp175
-rw-r--r--engines/cge/fileio.cpp18
-rw-r--r--engines/cge/vga13h.cpp70
-rw-r--r--engines/cge/vga13h.h32
-rw-r--r--engines/cge2/POTFILES1
-rw-r--r--engines/cge2/bitmap.cpp458
-rw-r--r--engines/cge2/bitmap.h94
-rw-r--r--engines/cge2/cge2.cpp207
-rw-r--r--engines/cge2/cge2.h338
-rw-r--r--engines/cge2/cge2_main.cpp959
-rw-r--r--engines/cge2/cge2_main.h52
-rw-r--r--engines/cge2/configure.engine3
-rw-r--r--engines/cge2/console.cpp33
-rw-r--r--engines/cge2/console.h40
-rw-r--r--engines/cge2/detection.cpp270
-rw-r--r--engines/cge2/events.cpp293
-rw-r--r--engines/cge2/events.h116
-rw-r--r--engines/cge2/fileio.cpp282
-rw-r--r--engines/cge2/fileio.h133
-rw-r--r--engines/cge2/general.h45
-rw-r--r--engines/cge2/hero.cpp622
-rw-r--r--engines/cge2/hero.h114
-rw-r--r--engines/cge2/inventory.cpp104
-rw-r--r--engines/cge2/map.cpp92
-rw-r--r--engines/cge2/map.h55
-rw-r--r--engines/cge2/module.mk30
-rw-r--r--engines/cge2/saveload.cpp279
-rw-r--r--engines/cge2/snail.cpp865
-rw-r--r--engines/cge2/snail.h129
-rw-r--r--engines/cge2/sound.cpp273
-rw-r--r--engines/cge2/sound.h131
-rw-r--r--engines/cge2/spare.cpp128
-rw-r--r--engines/cge2/spare.h56
-rw-r--r--engines/cge2/talk.cpp312
-rw-r--r--engines/cge2/talk.h94
-rw-r--r--engines/cge2/text.cpp197
-rw-r--r--engines/cge2/text.h68
-rw-r--r--engines/cge2/toolbar.cpp224
-rw-r--r--engines/cge2/vga13h.cpp1219
-rw-r--r--engines/cge2/vga13h.h308
-rw-r--r--engines/cge2/vmenu.cpp162
-rw-r--r--engines/cge2/vmenu.h89
-rw-r--r--engines/cine/console.cpp2
-rw-r--r--engines/cine/gfx.cpp4
-rw-r--r--engines/cine/pal.cpp6
-rw-r--r--engines/composer/composer.cpp5
-rw-r--r--engines/composer/scripting.cpp1
-rw-r--r--engines/cruise/actor.cpp61
-rw-r--r--engines/cruise/background.cpp6
-rw-r--r--engines/cruise/backgroundIncrust.cpp90
-rw-r--r--engines/cruise/cruise.cpp24
-rw-r--r--engines/cruise/cruise.h2
-rw-r--r--engines/cruise/cruise_main.cpp174
-rw-r--r--engines/cruise/cruise_main.h3
-rw-r--r--engines/cruise/ctp.cpp19
-rw-r--r--engines/cruise/dataLoader.cpp182
-rw-r--r--engines/cruise/debugger.cpp10
-rw-r--r--engines/cruise/decompiler.cpp325
-rw-r--r--engines/cruise/font.cpp16
-rw-r--r--engines/cruise/function.cpp115
-rw-r--r--engines/cruise/gfxModule.cpp17
-rw-r--r--engines/cruise/linker.cpp34
-rw-r--r--engines/cruise/mainDraw.cpp49
-rw-r--r--engines/cruise/mainDraw.h2
-rw-r--r--engines/cruise/menu.cpp19
-rw-r--r--engines/cruise/object.cpp16
-rw-r--r--engines/cruise/overlay.cpp130
-rw-r--r--engines/cruise/perso.cpp17
-rw-r--r--engines/cruise/polys.cpp32
-rw-r--r--engines/cruise/saveload.cpp35
-rw-r--r--engines/cruise/script.cpp253
-rw-r--r--engines/cruise/sound.cpp25
-rw-r--r--engines/cruise/stack.cpp4
-rw-r--r--engines/cruise/various.cpp4
-rw-r--r--engines/cruise/various.h4
-rw-r--r--engines/cruise/vars.cpp4
-rw-r--r--engines/cruise/vars.h4
-rw-r--r--engines/cruise/volume.cpp61
-rw-r--r--engines/dialogs.cpp5
-rw-r--r--engines/draci/game.cpp155
-rw-r--r--engines/draci/game.h9
-rw-r--r--engines/draci/saveload.cpp7
-rw-r--r--engines/draci/saveload.h2
-rw-r--r--engines/draci/script.cpp21
-rw-r--r--engines/draci/walking.cpp10
-rw-r--r--engines/draci/walking.h5
-rw-r--r--engines/drascula/animation.cpp28
-rw-r--r--engines/drascula/console.cpp4
-rw-r--r--engines/drascula/drascula.cpp3
-rw-r--r--engines/dreamweb/POTFILES2
-rw-r--r--engines/fullpipe/configure.engine2
-rw-r--r--engines/fullpipe/console.cpp6
-rw-r--r--engines/fullpipe/constants.h47
-rw-r--r--engines/fullpipe/detection.cpp64
-rw-r--r--engines/fullpipe/fullpipe.cpp101
-rw-r--r--engines/fullpipe/fullpipe.h18
-rw-r--r--engines/fullpipe/gameloader.cpp78
-rw-r--r--engines/fullpipe/gameloader.h16
-rw-r--r--engines/fullpipe/gfx.cpp450
-rw-r--r--engines/fullpipe/gfx.h34
-rw-r--r--engines/fullpipe/input.cpp33
-rw-r--r--engines/fullpipe/messagehandlers.cpp68
-rw-r--r--engines/fullpipe/messages.cpp19
-rw-r--r--engines/fullpipe/messages.h1
-rw-r--r--engines/fullpipe/mgm.cpp719
-rw-r--r--engines/fullpipe/mgm.h95
-rw-r--r--engines/fullpipe/modal.cpp388
-rw-r--r--engines/fullpipe/modal.h49
-rw-r--r--engines/fullpipe/module.mk1
-rw-r--r--engines/fullpipe/motion.cpp1697
-rw-r--r--engines/fullpipe/motion.h139
-rw-r--r--engines/fullpipe/scene.cpp118
-rw-r--r--engines/fullpipe/scene.h11
-rw-r--r--engines/fullpipe/scenes.cpp36
-rw-r--r--engines/fullpipe/scenes/scene04.cpp20
-rw-r--r--engines/fullpipe/scenes/scene06.cpp8
-rw-r--r--engines/fullpipe/scenes/scene16.cpp2
-rw-r--r--engines/fullpipe/scenes/scene25.cpp4
-rw-r--r--engines/fullpipe/scenes/scene27.cpp2
-rw-r--r--engines/fullpipe/scenes/scene29.cpp2
-rw-r--r--engines/fullpipe/sound.cpp381
-rw-r--r--engines/fullpipe/sound.h14
-rw-r--r--engines/fullpipe/stateloader.cpp43
-rw-r--r--engines/fullpipe/statics.cpp213
-rw-r--r--engines/fullpipe/statics.h12
-rw-r--r--engines/fullpipe/utils.h3
-rw-r--r--engines/gob/POTFILES2
-rw-r--r--engines/gob/cheater_geisha.cpp2
-rw-r--r--engines/gob/console.cpp48
-rw-r--r--engines/gob/detection/tables_ween.h87
-rw-r--r--engines/groovie/configure.engine2
-rw-r--r--engines/groovie/cursor.cpp32
-rw-r--r--engines/groovie/debug.cpp34
-rw-r--r--engines/groovie/groovie.cpp45
-rw-r--r--engines/groovie/groovie.h26
-rw-r--r--engines/groovie/module.mk6
-rw-r--r--engines/groovie/music.cpp38
-rw-r--r--engines/groovie/player.cpp6
-rw-r--r--engines/groovie/resource.cpp10
-rw-r--r--engines/groovie/roq.cpp180
-rw-r--r--engines/groovie/roq.h4
-rw-r--r--engines/groovie/script.cpp304
-rw-r--r--engines/groovie/vdx.cpp37
-rw-r--r--engines/hopkins/POTFILES2
-rw-r--r--engines/hopkins/computer.cpp48
-rw-r--r--engines/hopkins/computer.h26
-rw-r--r--engines/hopkins/debugger.cpp22
-rw-r--r--engines/hopkins/files.cpp3
-rw-r--r--engines/hugo/console.cpp34
-rw-r--r--engines/kyra/POTFILES1
-rw-r--r--engines/kyra/debugger.cpp334
-rw-r--r--engines/kyra/debugger.h60
-rw-r--r--engines/kyra/items_lol.cpp2
-rw-r--r--engines/kyra/sound_adlib.cpp327
-rw-r--r--engines/lastexpress/debug.cpp224
-rw-r--r--engines/lastexpress/entities/abbot.cpp10
-rw-r--r--engines/lastexpress/entities/alexei.cpp2
-rw-r--r--engines/lastexpress/entities/anna.cpp14
-rw-r--r--engines/lastexpress/entities/august.cpp47
-rw-r--r--engines/lastexpress/entities/boutarel.cpp8
-rw-r--r--engines/lastexpress/entities/chapters.cpp35
-rw-r--r--engines/lastexpress/entities/chapters.h2
-rw-r--r--engines/lastexpress/entities/cooks.cpp43
-rw-r--r--engines/lastexpress/entities/cooks.h24
-rw-r--r--engines/lastexpress/entities/entity.cpp4
-rw-r--r--engines/lastexpress/entities/gendarmes.cpp111
-rw-r--r--engines/lastexpress/entities/gendarmes.h18
-rw-r--r--engines/lastexpress/entities/hadija.cpp62
-rw-r--r--engines/lastexpress/entities/hadija.h10
-rw-r--r--engines/lastexpress/entities/ivo.cpp64
-rw-r--r--engines/lastexpress/entities/ivo.h18
-rw-r--r--engines/lastexpress/entities/kahina.cpp94
-rw-r--r--engines/lastexpress/entities/kahina.h34
-rw-r--r--engines/lastexpress/entities/kronos.cpp74
-rw-r--r--engines/lastexpress/entities/kronos.h18
-rw-r--r--engines/lastexpress/entities/max.cpp38
-rw-r--r--engines/lastexpress/entities/max.h19
-rw-r--r--engines/lastexpress/entities/milos.cpp4
-rw-r--r--engines/lastexpress/entities/pascale.cpp82
-rw-r--r--engines/lastexpress/entities/pascale.h24
-rw-r--r--engines/lastexpress/entities/rebecca.cpp18
-rw-r--r--engines/lastexpress/entities/tatiana.cpp4
-rw-r--r--engines/lastexpress/entities/waiter1.cpp (renamed from engines/lastexpress/entities/servers0.cpp)343
-rw-r--r--engines/lastexpress/entities/waiter1.h (renamed from engines/lastexpress/entities/servers0.h)78
-rw-r--r--engines/lastexpress/entities/waiter2.cpp (renamed from engines/lastexpress/entities/servers1.cpp)268
-rw-r--r--engines/lastexpress/entities/waiter2.h (renamed from engines/lastexpress/entities/servers1.h)66
-rw-r--r--engines/lastexpress/game/action.cpp2
-rw-r--r--engines/lastexpress/game/entities.cpp16
-rw-r--r--engines/lastexpress/game/inventory.cpp19
-rw-r--r--engines/lastexpress/game/savepoint.cpp16
-rw-r--r--engines/lastexpress/game/savepoint.h4
-rw-r--r--engines/lastexpress/lastexpress.cpp2
-rw-r--r--engines/lastexpress/module.mk4
-rw-r--r--engines/lastexpress/shared.h8
-rw-r--r--engines/lastexpress/sound/entry.cpp9
-rw-r--r--engines/lastexpress/sound/sound.cpp10
-rw-r--r--engines/lure/debugger.cpp206
-rw-r--r--engines/made/database.cpp2
-rw-r--r--engines/made/resource.cpp3
-rw-r--r--engines/made/screen.cpp3
-rw-r--r--engines/mads/action.cpp708
-rw-r--r--engines/mads/action.h176
-rw-r--r--engines/mads/animation.cpp592
-rw-r--r--engines/mads/animation.h233
-rw-r--r--engines/mads/assets.cpp228
-rw-r--r--engines/mads/assets.h114
-rw-r--r--engines/mads/audio.cpp129
-rw-r--r--engines/mads/audio.h64
-rw-r--r--engines/mads/compression.cpp194
-rw-r--r--engines/mads/compression.h89
-rw-r--r--engines/mads/configure.engine3
-rw-r--r--engines/mads/debugger.cpp351
-rw-r--r--engines/mads/debugger.h61
-rw-r--r--engines/mads/detection.cpp194
-rw-r--r--engines/mads/detection_tables.h122
-rw-r--r--engines/mads/dialogs.cpp398
-rw-r--r--engines/mads/dialogs.h231
-rw-r--r--engines/mads/dragonsphere/dragonsphere_scenes.cpp235
-rw-r--r--engines/mads/dragonsphere/dragonsphere_scenes.h695
-rw-r--r--engines/mads/dragonsphere/game_dragonsphere.cpp163
-rw-r--r--engines/mads/dragonsphere/game_dragonsphere.h151
-rw-r--r--engines/mads/events.cpp267
-rw-r--r--engines/mads/events.h176
-rw-r--r--engines/mads/font.cpp256
-rw-r--r--engines/mads/font.h95
-rw-r--r--engines/mads/game.cpp589
-rw-r--r--engines/mads/game.h239
-rw-r--r--engines/mads/game_data.cpp66
-rw-r--r--engines/mads/game_data.h73
-rw-r--r--engines/mads/globals.cpp33
-rw-r--r--engines/mads/globals.h47
-rw-r--r--engines/mads/hotspots.cpp216
-rw-r--r--engines/mads/hotspots.h120
-rw-r--r--engines/mads/inventory.cpp225
-rw-r--r--engines/mads/inventory.h141
-rw-r--r--engines/mads/mads.cpp162
-rw-r--r--engines/mads/mads.h153
-rw-r--r--engines/mads/messages.cpp569
-rw-r--r--engines/mads/messages.h192
-rw-r--r--engines/mads/module.mk59
-rw-r--r--engines/mads/msurface.cpp556
-rw-r--r--engines/mads/msurface.h251
-rw-r--r--engines/mads/nebular/dialogs_nebular.cpp1181
-rw-r--r--engines/mads/nebular/dialogs_nebular.h301
-rw-r--r--engines/mads/nebular/game_nebular.cpp862
-rw-r--r--engines/mads/nebular/game_nebular.h160
-rw-r--r--engines/mads/nebular/globals_nebular.cpp55
-rw-r--r--engines/mads/nebular/globals_nebular.h315
-rw-r--r--engines/mads/nebular/menu_nebular.cpp1103
-rw-r--r--engines/mads/nebular/menu_nebular.h323
-rw-r--r--engines/mads/nebular/nebular_scenes.cpp628
-rw-r--r--engines/mads/nebular/nebular_scenes.h1418
-rw-r--r--engines/mads/nebular/nebular_scenes1.cpp3164
-rw-r--r--engines/mads/nebular/nebular_scenes1.h264
-rw-r--r--engines/mads/nebular/nebular_scenes2.cpp5380
-rw-r--r--engines/mads/nebular/nebular_scenes2.h325
-rw-r--r--engines/mads/nebular/nebular_scenes3.cpp5820
-rw-r--r--engines/mads/nebular/nebular_scenes3.h548
-rw-r--r--engines/mads/nebular/nebular_scenes4.cpp4194
-rw-r--r--engines/mads/nebular/nebular_scenes4.h258
-rw-r--r--engines/mads/nebular/nebular_scenes5.cpp2870
-rw-r--r--engines/mads/nebular/nebular_scenes5.h254
-rw-r--r--engines/mads/nebular/nebular_scenes6.cpp4741
-rw-r--r--engines/mads/nebular/nebular_scenes6.h322
-rw-r--r--engines/mads/nebular/nebular_scenes7.cpp2679
-rw-r--r--engines/mads/nebular/nebular_scenes7.h238
-rw-r--r--engines/mads/nebular/nebular_scenes8.cpp1616
-rw-r--r--engines/mads/nebular/nebular_scenes8.h165
-rw-r--r--engines/mads/nebular/sound_nebular.cpp3424
-rw-r--r--engines/mads/nebular/sound_nebular.h781
-rw-r--r--engines/mads/palette.cpp838
-rw-r--r--engines/mads/palette.h323
-rw-r--r--engines/mads/phantom/game_phantom.cpp148
-rw-r--r--engines/mads/phantom/game_phantom.h124
-rw-r--r--engines/mads/phantom/phantom_scenes.cpp203
-rw-r--r--engines/mads/phantom/phantom_scenes.h521
-rw-r--r--engines/mads/player.cpp794
-rw-r--r--engines/mads/player.h228
-rw-r--r--engines/mads/rails.cpp277
-rw-r--r--engines/mads/rails.h134
-rw-r--r--engines/mads/resources.cpp417
-rw-r--r--engines/mads/resources.h89
-rw-r--r--engines/mads/scene.cpp731
-rw-r--r--engines/mads/scene.h253
-rw-r--r--engines/mads/scene_data.cpp480
-rw-r--r--engines/mads/scene_data.h225
-rw-r--r--engines/mads/screen.cpp678
-rw-r--r--engines/mads/screen.h250
-rw-r--r--engines/mads/sequence.cpp541
-rw-r--r--engines/mads/sequence.h131
-rw-r--r--engines/mads/sound.cpp144
-rw-r--r--engines/mads/sound.h104
-rw-r--r--engines/mads/sprites.cpp417
-rw-r--r--engines/mads/sprites.h240
-rw-r--r--engines/mads/staticres.cpp58
-rw-r--r--engines/mads/staticres.h47
-rw-r--r--engines/mads/user_interface.cpp1096
-rw-r--r--engines/mads/user_interface.h306
-rw-r--r--engines/mohawk/console.cpp266
-rw-r--r--engines/mohawk/detection_tables.h20
-rw-r--r--engines/mohawk/myst_stacks/mechanical.cpp6
-rw-r--r--engines/mohawk/myst_stacks/stoneship.cpp1
-rw-r--r--engines/mohawk/myst_state.cpp3
-rw-r--r--engines/mohawk/riven.cpp82
-rw-r--r--engines/mohawk/riven.h22
-rw-r--r--engines/mohawk/riven_external.cpp6
-rw-r--r--engines/mohawk/riven_graphics.cpp2
-rw-r--r--engines/mohawk/riven_saveload.cpp79
-rw-r--r--engines/mohawk/riven_scripts.cpp4
-rw-r--r--engines/mohawk/riven_vars.cpp418
-rw-r--r--engines/mortevielle/debugger.cpp6
-rw-r--r--engines/mortevielle/detection_tables.h30
-rw-r--r--engines/neverhood/console.cpp86
-rw-r--r--engines/neverhood/gamevars.cpp2
-rw-r--r--engines/neverhood/graphics.cpp11
-rw-r--r--engines/neverhood/modules/module1000.cpp10
-rw-r--r--engines/neverhood/modules/module1400.cpp7
-rw-r--r--engines/neverhood/modules/module1400_sprites.cpp5
-rw-r--r--engines/neverhood/modules/module1400_sprites.h2
-rw-r--r--engines/neverhood/modules/module1600_sprites.cpp3
-rw-r--r--engines/neverhood/modules/module2700.cpp1
-rw-r--r--engines/neverhood/scene.cpp2
-rw-r--r--engines/neverhood/sprite.cpp14
-rw-r--r--engines/neverhood/staticdata.cpp47
-rw-r--r--engines/parallaction/debug.cpp76
-rw-r--r--engines/parallaction/debug.h1
-rw-r--r--engines/pegasus/console.cpp16
-rw-r--r--engines/pegasus/energymonitor.cpp4
-rw-r--r--engines/pegasus/input.cpp16
-rw-r--r--engines/pegasus/interaction.cpp38
-rw-r--r--engines/pegasus/interaction.h6
-rw-r--r--engines/pegasus/menu.cpp2
-rw-r--r--engines/pegasus/module.mk1
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoria.cpp150
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp42
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp15
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriabomb.h3
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp6
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriamessages.h2
-rw-r--r--engines/pegasus/neighborhood/mars/mars.cpp11
-rw-r--r--engines/pegasus/neighborhood/mars/shuttlehud.cpp42
-rw-r--r--engines/pegasus/neighborhood/neighborhood.cpp11
-rw-r--r--engines/pegasus/neighborhood/neighborhood.h2
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp4
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp118
-rw-r--r--engines/pegasus/neighborhood/norad/delta/globegame.cpp35
-rw-r--r--engines/pegasus/neighborhood/norad/delta/globegame.h2
-rw-r--r--engines/pegasus/neighborhood/norad/delta/noraddelta.cpp18
-rw-r--r--engines/pegasus/neighborhood/norad/delta/noraddelta.h3
-rw-r--r--engines/pegasus/neighborhood/norad/subcontrolroom.cpp191
-rw-r--r--engines/pegasus/neighborhood/tsa/fulltsa.cpp845
-rw-r--r--engines/pegasus/neighborhood/tsa/tinytsa.cpp124
-rw-r--r--engines/pegasus/neighborhood/wsc/wsc.cpp698
-rw-r--r--engines/pegasus/pegasus.cpp9
-rw-r--r--engines/queen/POTFILES2
-rw-r--r--engines/queen/debug.cpp72
-rw-r--r--engines/saga/actor_walk.cpp2
-rw-r--r--engines/saga/animation.cpp8
-rw-r--r--engines/saga/console.cpp122
-rw-r--r--engines/saga/console.h4
-rw-r--r--engines/saga/detection_tables.h24
-rw-r--r--engines/saga/events.cpp12
-rw-r--r--engines/saga/events.h9
-rw-r--r--engines/saga/interface.cpp5
-rw-r--r--engines/saga/introproc_ite.cpp626
-rw-r--r--engines/saga/introproc_saga2.cpp6
-rw-r--r--engines/saga/itedata.cpp486
-rw-r--r--engines/saga/itedata.h37
-rw-r--r--engines/saga/music.cpp24
-rw-r--r--engines/saga/music.h5
-rw-r--r--engines/saga/objectmap.cpp2
-rw-r--r--engines/saga/resource.cpp14
-rw-r--r--engines/saga/resource.h16
-rw-r--r--engines/saga/resource_hrs.cpp45
-rw-r--r--engines/saga/saga.cpp1
-rw-r--r--engines/saga/scene.cpp10
-rw-r--r--engines/saga/scene.h35
-rw-r--r--engines/saga/sfuncs.cpp2
-rw-r--r--engines/saga/sfuncs_ihnm.cpp9
-rw-r--r--engines/saga/shorten.cpp60
-rw-r--r--engines/saga/sndres.h1
-rw-r--r--engines/savestate.h2
-rw-r--r--engines/sci/console.cpp1761
-rw-r--r--engines/sci/detection_tables.h104
-rw-r--r--engines/sci/engine/features.cpp6
-rw-r--r--engines/sci/engine/kernel_tables.h5
-rw-r--r--engines/sci/engine/kevent.cpp12
-rw-r--r--engines/sci/engine/kfile.cpp15
-rw-r--r--engines/sci/engine/kmisc.cpp3
-rw-r--r--engines/sci/engine/kpathing.cpp2
-rw-r--r--engines/sci/engine/script_patches.cpp167
-rw-r--r--engines/sci/engine/scriptdebug.cpp16
-rw-r--r--engines/sci/engine/seg_manager.cpp2
-rw-r--r--engines/sci/engine/workarounds.cpp13
-rw-r--r--engines/sci/engine/workarounds.h1
-rw-r--r--engines/sci/graphics/animate.cpp2
-rw-r--r--engines/sci/graphics/frameout.cpp16
-rw-r--r--engines/sci/graphics/paint32.cpp8
-rw-r--r--engines/sci/graphics/ports.cpp2
-rw-r--r--engines/sci/graphics/screen.cpp156
-rw-r--r--engines/sci/graphics/screen.h14
-rw-r--r--engines/sci/parser/grammar.cpp22
-rw-r--r--engines/sci/parser/said.cpp35
-rw-r--r--engines/sci/parser/vocabulary.cpp35
-rw-r--r--engines/sci/resource_audio.cpp1
-rw-r--r--engines/sci/sci.cpp1
-rw-r--r--engines/sci/sound/drivers/midi.cpp5
-rw-r--r--engines/sci/sound/music.cpp56
-rw-r--r--engines/sci/sound/music.h2
-rw-r--r--engines/sci/sound/soundcmd.cpp2
-rw-r--r--engines/scumm/POTFILES3
-rw-r--r--engines/scumm/cdda.cpp120
-rw-r--r--engines/scumm/cdda.h57
-rw-r--r--engines/scumm/charset.cpp95
-rw-r--r--engines/scumm/charset.h29
-rw-r--r--engines/scumm/debugger.cpp258
-rw-r--r--engines/scumm/debugger.h4
-rw-r--r--engines/scumm/detection.cpp54
-rw-r--r--engines/scumm/detection.h2
-rw-r--r--engines/scumm/detection_tables.h31
-rw-r--r--engines/scumm/dialogs.cpp4
-rw-r--r--engines/scumm/file.cpp24
-rw-r--r--engines/scumm/file.h27
-rw-r--r--engines/scumm/he/sprite_he.cpp14
-rw-r--r--engines/scumm/input.cpp5
-rw-r--r--engines/scumm/module.mk1
-rw-r--r--engines/scumm/music.h3
-rw-r--r--engines/scumm/nut_renderer.cpp55
-rw-r--r--engines/scumm/object.cpp1
-rw-r--r--engines/scumm/players/player_ad.cpp948
-rw-r--r--engines/scumm/players/player_ad.h140
-rw-r--r--engines/scumm/players/player_mac.cpp1
-rw-r--r--engines/scumm/saveload.cpp2
-rw-r--r--engines/scumm/saveload.h2
-rw-r--r--engines/scumm/script.cpp12
-rw-r--r--engines/scumm/script_v5.cpp2
-rw-r--r--engines/scumm/scumm-md5.h11
-rw-r--r--engines/scumm/scumm.cpp59
-rw-r--r--engines/scumm/scumm.h6
-rw-r--r--engines/scumm/smush/smush_font.cpp66
-rw-r--r--engines/scumm/sound.cpp75
-rw-r--r--engines/scumm/sound.h7
-rw-r--r--engines/scumm/vars.cpp3
-rw-r--r--engines/sky/debug.cpp106
-rw-r--r--engines/sword1/POTFILES2
-rw-r--r--engines/sword1/animation.cpp4
-rw-r--r--engines/sword1/console.cpp23
-rw-r--r--engines/sword1/console.h1
-rw-r--r--engines/sword1/sound.cpp51
-rw-r--r--engines/sword1/sound.h2
-rw-r--r--engines/sword1/sword1.cpp2
-rw-r--r--engines/sword1/sword1.h1
-rw-r--r--engines/sword2/animation.cpp2
-rw-r--r--engines/sword2/console.cpp264
-rw-r--r--engines/sword2/resman.cpp2
-rw-r--r--engines/sword2/sound.cpp2
-rw-r--r--engines/sword25/gfx/animation.cpp8
-rw-r--r--engines/sword25/gfx/bitmapresource.h18
-rw-r--r--engines/sword25/gfx/dynamicbitmap.cpp8
-rw-r--r--engines/sword25/gfx/graphicengine.cpp10
-rw-r--r--engines/sword25/gfx/image/image.h22
-rw-r--r--engines/sword25/gfx/image/imgloader.cpp4
-rw-r--r--engines/sword25/gfx/image/renderedimage.cpp292
-rw-r--r--engines/sword25/gfx/image/renderedimage.h11
-rw-r--r--engines/sword25/gfx/image/swimage.h2
-rw-r--r--engines/sword25/gfx/image/vectorimage.h2
-rw-r--r--engines/sword25/gfx/image/vectorimagerenderer.cpp10
-rw-r--r--engines/sword25/gfx/staticbitmap.cpp8
-rw-r--r--engines/sword25/gfx/text.cpp6
-rw-r--r--engines/sword25/kernel/persistenceservice.cpp2
-rw-r--r--engines/sword25/sfx/soundengine.cpp6
-rw-r--r--engines/sword25/sword25.cpp2
-rw-r--r--engines/sword25/util/lua/loslib.cpp10
-rw-r--r--engines/sword25/util/pluto/pluto.cpp29
-rw-r--r--engines/teenagent/actor.cpp4
-rw-r--r--engines/teenagent/console.cpp46
-rw-r--r--engines/testbed/sound.cpp2
-rw-r--r--engines/tinsel/debugger.cpp42
-rw-r--r--engines/toltecs/console.cpp14
-rw-r--r--engines/toltecs/detection.cpp14
-rw-r--r--engines/tony/debugger.cpp12
-rw-r--r--engines/tony/detection_tables.h19
-rw-r--r--engines/toon/character.cpp14
-rw-r--r--engines/toon/toon.cpp22
-rw-r--r--engines/touche/console.cpp6
-rw-r--r--engines/touche/detection.cpp1
-rw-r--r--engines/touche/menu.cpp161
-rw-r--r--engines/touche/resource.cpp20
-rw-r--r--engines/touche/touche.cpp68
-rw-r--r--engines/touche/touche.h108
-rw-r--r--engines/tsage/POTFILES3
-rw-r--r--engines/tsage/blue_force/blueforce_dialogs.cpp2
-rw-r--r--engines/tsage/debugger.cpp392
-rw-r--r--engines/tsage/debugger.h4
-rw-r--r--engines/tsage/graphics.cpp2
-rw-r--r--engines/tsage/graphics.h2
-rw-r--r--engines/tsage/ringworld/ringworld_dialogs.cpp2
-rw-r--r--engines/tsage/ringworld/ringworld_scenes10.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_dialogs.cpp32
-rw-r--r--engines/tsage/ringworld2/ringworld2_dialogs.h2
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp11
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.h2
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.cpp243
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.h6
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.cpp15
-rw-r--r--engines/tsage/ringworld2/ringworld2_speakers.cpp2
-rw-r--r--engines/tsage/sound.cpp7
-rw-r--r--engines/tsage/user_interface.cpp7
-rw-r--r--engines/tucker/resource.cpp114
-rw-r--r--engines/tucker/sequences.cpp9
-rw-r--r--engines/tucker/tucker.cpp13
-rw-r--r--engines/tucker/tucker.h1
-rw-r--r--engines/voyeur/animation.cpp24
-rw-r--r--engines/voyeur/animation.h2
-rw-r--r--engines/voyeur/configure.engine2
-rw-r--r--engines/voyeur/data.cpp6
-rw-r--r--engines/voyeur/data.h12
-rw-r--r--engines/voyeur/debugger.cpp47
-rw-r--r--engines/voyeur/events.cpp18
-rw-r--r--engines/voyeur/events.h2
-rw-r--r--engines/voyeur/files.cpp73
-rw-r--r--engines/voyeur/files.h24
-rw-r--r--engines/voyeur/files_threads.cpp85
-rw-r--r--engines/voyeur/graphics.cpp20
-rw-r--r--engines/voyeur/graphics.h9
-rw-r--r--engines/voyeur/sound.cpp2
-rw-r--r--engines/voyeur/staticres.cpp50
-rw-r--r--engines/voyeur/voyeur.cpp39
-rw-r--r--engines/voyeur/voyeur.h5
-rw-r--r--engines/voyeur/voyeur_game.cpp70
-rw-r--r--engines/wintermute/POTFILES1
-rw-r--r--engines/wintermute/base/base_file_manager.cpp9
-rw-r--r--engines/wintermute/base/base_file_manager.h1
-rw-r--r--engines/wintermute/base/base_frame.cpp2
-rw-r--r--engines/wintermute/base/base_frame.h3
-rw-r--r--engines/wintermute/base/base_game.cpp4
-rw-r--r--engines/wintermute/base/base_game_settings.cpp4
-rw-r--r--engines/wintermute/base/base_game_settings.h3
-rw-r--r--engines/wintermute/base/base_object.cpp8
-rw-r--r--engines/wintermute/base/base_object.h3
-rw-r--r--engines/wintermute/base/base_persistence_manager.cpp4
-rw-r--r--engines/wintermute/base/base_sprite.cpp2
-rw-r--r--engines/wintermute/base/base_sprite.h10
-rw-r--r--engines/wintermute/base/base_string_table.cpp25
-rw-r--r--engines/wintermute/base/base_string_table.h4
-rw-r--r--engines/wintermute/base/base_sub_frame.cpp36
-rw-r--r--engines/wintermute/base/base_sub_frame.h3
-rw-r--r--engines/wintermute/base/file/base_package.cpp4
-rw-r--r--engines/wintermute/base/font/base_font_truetype.cpp2
-rw-r--r--engines/wintermute/base/gfx/base_image.cpp6
-rw-r--r--engines/wintermute/base/gfx/base_renderer.h1
-rw-r--r--engines/wintermute/base/gfx/base_surface.cpp2
-rw-r--r--engines/wintermute/base/gfx/base_surface.h14
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.cpp6
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.h4
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp58
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.h20
-rw-r--r--engines/wintermute/base/gfx/osystem/render_ticket.cpp18
-rw-r--r--engines/wintermute/base/gfx/osystem/render_ticket.h8
-rw-r--r--engines/wintermute/base/scriptables/script.cpp3
-rw-r--r--engines/wintermute/base/scriptables/script_ext_file.cpp2
-rw-r--r--engines/wintermute/base/sound/base_sound.cpp18
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.cpp29
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.h15
-rw-r--r--engines/wintermute/base/sound/base_sound_manager.cpp9
-rw-r--r--engines/wintermute/dcgf.h4
-rw-r--r--engines/wintermute/dctypes.h8
-rw-r--r--engines/wintermute/debugger.cpp10
-rw-r--r--engines/wintermute/detection_tables.h214
-rw-r--r--engines/wintermute/graphics/transform_struct.cpp119
-rw-r--r--engines/wintermute/graphics/transform_struct.h89
-rw-r--r--engines/wintermute/graphics/transform_tools.cpp87
-rw-r--r--engines/wintermute/graphics/transform_tools.h53
-rw-r--r--engines/wintermute/graphics/transparent_surface.cpp950
-rw-r--r--engines/wintermute/graphics/transparent_surface.h176
-rw-r--r--engines/wintermute/module.mk3
-rw-r--r--engines/wintermute/utils/utils.cpp5
-rw-r--r--engines/zvision/POTFILES1
-rw-r--r--engines/zvision/core/console.cpp48
-rw-r--r--engines/zvision/scripting/actions.cpp12
-rw-r--r--engines/zvision/scripting/controls/input_control.cpp2
-rw-r--r--engines/zvision/sound/zork_raw.cpp4
612 files changed, 85999 insertions, 11989 deletions
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index fa23f5fa1a..72629a833e 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -122,7 +122,7 @@ bool cleanupPirated(ADGameDescList &matched) {
// We ruled out all variants and now have nothing
if (matched.empty()) {
- warning("Illegitimate game copy detected. We give no support in such cases %d", matched.size());
+ warning("Illegitimate game copy detected. We provide no support in such cases");
return true;
}
}
diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp
index 5f222adf89..6d7f9384cd 100644
--- a/engines/agi/console.cpp
+++ b/engines/agi/console.cpp
@@ -32,27 +32,27 @@ namespace Agi {
Console::Console(AgiEngine *vm) : GUI::Debugger() {
_vm = vm;
- DCmd_Register("debug", WRAP_METHOD(Console, Cmd_Debug));
- DCmd_Register("cont", WRAP_METHOD(Console, Cmd_Cont));
- DCmd_Register("agiver", WRAP_METHOD(Console, Cmd_Agiver));
- DCmd_Register("flags", WRAP_METHOD(Console, Cmd_Flags));
- DCmd_Register("logic0", WRAP_METHOD(Console, Cmd_Logic0));
- DCmd_Register("objs", WRAP_METHOD(Console, Cmd_Objs));
- DCmd_Register("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode));
- DCmd_Register("opcode", WRAP_METHOD(Console, Cmd_Opcode));
- DCmd_Register("step", WRAP_METHOD(Console, Cmd_Step));
- DCmd_Register("trigger", WRAP_METHOD(Console, Cmd_Trigger));
- DCmd_Register("vars", WRAP_METHOD(Console, Cmd_Vars));
- DCmd_Register("setvar", WRAP_METHOD(Console, Cmd_SetVar));
- DCmd_Register("setflag", WRAP_METHOD(Console, Cmd_SetFlag));
- DCmd_Register("setobj", WRAP_METHOD(Console, Cmd_SetObj));
- DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room));
- DCmd_Register("bt", WRAP_METHOD(Console, Cmd_BT));
+ registerCmd("debug", WRAP_METHOD(Console, Cmd_Debug));
+ registerCmd("cont", WRAP_METHOD(Console, Cmd_Cont));
+ registerCmd("agiver", WRAP_METHOD(Console, Cmd_Agiver));
+ registerCmd("flags", WRAP_METHOD(Console, Cmd_Flags));
+ registerCmd("logic0", WRAP_METHOD(Console, Cmd_Logic0));
+ registerCmd("objs", WRAP_METHOD(Console, Cmd_Objs));
+ registerCmd("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode));
+ registerCmd("opcode", WRAP_METHOD(Console, Cmd_Opcode));
+ registerCmd("step", WRAP_METHOD(Console, Cmd_Step));
+ registerCmd("trigger", WRAP_METHOD(Console, Cmd_Trigger));
+ registerCmd("vars", WRAP_METHOD(Console, Cmd_Vars));
+ registerCmd("setvar", WRAP_METHOD(Console, Cmd_SetVar));
+ registerCmd("setflag", WRAP_METHOD(Console, Cmd_SetFlag));
+ registerCmd("setobj", WRAP_METHOD(Console, Cmd_SetObj));
+ registerCmd("room", WRAP_METHOD(Console, Cmd_Room));
+ registerCmd("bt", WRAP_METHOD(Console, Cmd_BT));
}
bool Console::Cmd_SetVar(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Usage: setvar <varnum> <value>\n");
+ debugPrintf("Usage: setvar <varnum> <value>\n");
return true;
}
int p1 = (int)atoi(argv[1]);
@@ -64,7 +64,7 @@ bool Console::Cmd_SetVar(int argc, const char **argv) {
bool Console::Cmd_SetFlag(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Usage: setvar <varnum> <value>\n");
+ debugPrintf("Usage: setvar <varnum> <value>\n");
return true;
}
int p1 = (int)atoi(argv[1]);
@@ -76,7 +76,7 @@ bool Console::Cmd_SetFlag(int argc, const char **argv) {
bool Console::Cmd_SetObj(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Usage: setvar <varnum> <value>\n");
+ debugPrintf("Usage: setvar <varnum> <value>\n");
return true;
}
int p1 = (int)atoi(argv[1]);
@@ -88,7 +88,7 @@ bool Console::Cmd_SetObj(int argc, const char **argv) {
bool Console::Cmd_RunOpcode(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: runopcode <name> <parameter0> ....\n");
+ debugPrintf("Usage: runopcode <name> <parameter0> ....\n");
return true;
}
@@ -96,7 +96,7 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) {
if (!strcmp(argv[1], logicNamesCmd[i].name)) {
uint8 p[16];
if ((argc - 2) != logicNamesCmd[i].argumentsLength()) {
- DebugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].argumentsLength());
+ debugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].argumentsLength());
return 0;
}
p[0] = argv[2] ? (char)strtoul(argv[2], NULL, 0) : 0;
@@ -113,7 +113,7 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) {
}
}
- DebugPrintf("Unknown opcode\n");
+ debugPrintf("Unknown opcode\n");
return true;
}
@@ -125,7 +125,7 @@ bool Console::Cmd_Agiver(int argc, const char **argv) {
maj = (ver >> 12) & 0xf;
min = ver & 0xfff;
- DebugPrintf(maj <= 2 ? "%x.%03x\n" : "%x.002.%03x\n", maj, min);
+ debugPrintf(maj <= 2 ? "%x.%03x\n" : "%x.002.%03x\n", maj, min);
return true;
}
@@ -133,17 +133,17 @@ bool Console::Cmd_Agiver(int argc, const char **argv) {
bool Console::Cmd_Flags(int argc, const char **argv) {
int i, j;
- DebugPrintf(" ");
+ debugPrintf(" ");
for (j = 0; j < 10; j++)
- DebugPrintf("%d ", j);
- DebugPrintf("\n");
+ debugPrintf("%d ", j);
+ debugPrintf("\n");
for (i = 0; i < 255;) {
- DebugPrintf("%3d ", i);
+ debugPrintf("%3d ", i);
for (j = 0; j < 10; j++, i++) {
- DebugPrintf("%c ", _vm->getflag(i) ? 'T' : 'F');
+ debugPrintf("%c ", _vm->getflag(i) ? 'T' : 'F');
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
return true;
@@ -154,9 +154,9 @@ bool Console::Cmd_Vars(int argc, const char **argv) {
for (i = 0; i < 255;) {
for (j = 0; j < 5; j++, i++) {
- DebugPrintf("%03d:%3d ", i, _vm->getvar(i));
+ debugPrintf("%03d:%3d ", i, _vm->getvar(i));
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
return true;
@@ -166,7 +166,7 @@ bool Console::Cmd_Objs(int argc, const char **argv) {
unsigned int i;
for (i = 0; i < _vm->_game.numObjects; i++) {
- DebugPrintf("%3d]%-24s(%3d)\n", i, _vm->objectName(i), _vm->objectGetLocation(i));
+ debugPrintf("%3d]%-24s(%3d)\n", i, _vm->objectName(i), _vm->objectGetLocation(i));
}
return true;
@@ -174,7 +174,7 @@ bool Console::Cmd_Objs(int argc, const char **argv) {
bool Console::Cmd_Opcode(int argc, const char **argv) {
if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) {
- DebugPrintf("Usage: opcode on|off\n");
+ debugPrintf("Usage: opcode on|off\n");
return true;
}
@@ -185,7 +185,7 @@ bool Console::Cmd_Opcode(int argc, const char **argv) {
bool Console::Cmd_Logic0(int argc, const char **argv) {
if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) {
- DebugPrintf("Usage: logic0 on|off\n");
+ debugPrintf("Usage: logic0 on|off\n");
return true;
}
@@ -196,7 +196,7 @@ bool Console::Cmd_Logic0(int argc, const char **argv) {
bool Console::Cmd_Trigger(int argc, const char **argv) {
if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) {
- DebugPrintf("Usage: trigger on|off\n");
+ debugPrintf("Usage: trigger on|off\n");
return true;
}
_vm->_debug.ignoretriggers = strcmp (argv[1], "on");
@@ -236,13 +236,13 @@ bool Console::Cmd_Room(int argc, const char **argv) {
_vm->newRoom(strtoul(argv[1], NULL, 0));
}
- DebugPrintf("Current room: %d\n", _vm->getvar(0));
+ debugPrintf("Current room: %d\n", _vm->getvar(0));
return true;
}
bool Console::Cmd_BT(int argc, const char **argv) {
- DebugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.lognum, _vm->_game.execStack.size());
+ debugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.lognum, _vm->_game.execStack.size());
uint8 *code = NULL;
uint8 op = 0;
@@ -257,12 +257,12 @@ bool Console::Cmd_BT(int argc, const char **argv) {
memmove(p, &code[it->curIP], num);
memset(p + num, 0, CMD_BSIZE - num);
- DebugPrintf("%d(%d): %s(", it->script, it->curIP, logicNamesCmd[op].name);
+ debugPrintf("%d(%d): %s(", it->script, it->curIP, logicNamesCmd[op].name);
for (int i = 0; i < num; i++)
- DebugPrintf("%d, ", p[i]);
+ debugPrintf("%d, ", p[i]);
- DebugPrintf(")\n");
+ debugPrintf(")\n");
}
return true;
@@ -271,9 +271,9 @@ bool Console::Cmd_BT(int argc, const char **argv) {
MickeyConsole::MickeyConsole(MickeyEngine *mickey) : GUI::Debugger() {
_mickey = mickey;
- DCmd_Register("room", WRAP_METHOD(MickeyConsole, Cmd_Room));
- DCmd_Register("drawPic", WRAP_METHOD(MickeyConsole, Cmd_DrawPic));
- DCmd_Register("drawObj", WRAP_METHOD(MickeyConsole, Cmd_DrawObj));
+ registerCmd("room", WRAP_METHOD(MickeyConsole, Cmd_Room));
+ registerCmd("drawPic", WRAP_METHOD(MickeyConsole, Cmd_DrawPic));
+ registerCmd("drawObj", WRAP_METHOD(MickeyConsole, Cmd_DrawObj));
}
bool MickeyConsole::Cmd_Room(int argc, const char **argv) {
@@ -287,7 +287,7 @@ bool MickeyConsole::Cmd_Room(int argc, const char **argv) {
bool MickeyConsole::Cmd_DrawPic(int argc, const char **argv) {
if (argc != 2)
- DebugPrintf("Usage: %s <Picture number>\n", argv[0]);
+ debugPrintf("Usage: %s <Picture number>\n", argv[0]);
else
_mickey->drawPic(atoi(argv[1]));
return true;
@@ -295,7 +295,7 @@ bool MickeyConsole::Cmd_DrawPic(int argc, const char **argv) {
bool MickeyConsole::Cmd_DrawObj(int argc, const char **argv) {
if (argc != 2)
- DebugPrintf("Usage: %s <Object number>\n", argv[0]);
+ debugPrintf("Usage: %s <Object number>\n", argv[0]);
else
_mickey->drawObj((ENUM_MSA_OBJECT)atoi(argv[1]), 0, 0);
return true;
@@ -304,7 +304,7 @@ bool MickeyConsole::Cmd_DrawObj(int argc, const char **argv) {
WinnieConsole::WinnieConsole(WinnieEngine *winnie) : GUI::Debugger() {
_winnie = winnie;
- DCmd_Register("curRoom", WRAP_METHOD(WinnieConsole, Cmd_CurRoom));
+ registerCmd("curRoom", WRAP_METHOD(WinnieConsole, Cmd_CurRoom));
}
bool WinnieConsole::Cmd_CurRoom(int argc, const char **argv) {
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index 561b56d199..4ca8d00824 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -2228,10 +2228,10 @@ void MickeyEngine::waitAnyKey(bool anim) {
// Console-related functions
void MickeyEngine::debugCurRoom() {
- _console->DebugPrintf("Current Room = %d\n", _gameStateMickey.iRoom);
+ _console->debugPrintf("Current Room = %d\n", _gameStateMickey.iRoom);
if (_gameStateMickey.iRmObj[_gameStateMickey.iRoom] != IDI_MSA_OBJECT_NONE) {
- _console->DebugPrintf("Object %d is in the room\n", _gameStateMickey.iRmObj[_gameStateMickey.iRoom]);
+ _console->debugPrintf("Object %d is in the room\n", _gameStateMickey.iRmObj[_gameStateMickey.iRoom]);
}
}
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp
index d5ae0b59a0..a91ad24fc6 100644
--- a/engines/agi/preagi_winnie.cpp
+++ b/engines/agi/preagi_winnie.cpp
@@ -1308,7 +1308,7 @@ void WinnieEngine::printStrWinnie(char *szMsg) {
// Console-related functions
void WinnieEngine::debugCurRoom() {
- _console->DebugPrintf("Current Room = %d\n", _room);
+ _console->debugPrintf("Current Room = %d\n", _room);
}
WinnieEngine::WinnieEngine(OSystem *syst, const AGIGameDescription *gameDesc) : PreAgiEngine(syst, gameDesc) {
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index 7266c75474..6eda2eb9aa 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -21,6 +21,7 @@
*/
#include "common/config-manager.h"
+#include "common/debug-channels.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/textconsole.h"
@@ -144,6 +145,14 @@ AGOSEngine_Elvira1::AGOSEngine_Elvira1(OSystem *system, const AGOSGameDescriptio
AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
: Engine(system), _rnd("agos"), _gameDescription(gd) {
+ DebugMan.addDebugChannel(kDebugOpcode, "opcode", "Opcode debug level");
+ DebugMan.addDebugChannel(kDebugVGAOpcode, "vga_opcode", "VGA Opcode debug level");
+ DebugMan.addDebugChannel(kDebugSubroutine, "subroutine", "Subroutine debug level");
+ DebugMan.addDebugChannel(kDebugVGAScript, "vga_script", "VGA Script debug level");
+ //Image dumping command disabled as it doesn't work well
+#if 0
+ DebugMan.addDebugChannel(kDebugImageDump, "image_dump", "Enable dumping of images to files");
+#endif
_vcPtr = 0;
_vcGetOutOfCode = 0;
_gameOffsetsPtr = 0;
@@ -243,13 +252,6 @@ AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
_backFlag = false;
- _debugMode = 0;
- _dumpScripts = false;
- _dumpOpcodes = false;
- _dumpVgaScripts = false;
- _dumpVgaOpcodes = false;
- _dumpImages = false;
-
_copyProtection = false;
_pause = false;
_speech = false;
@@ -675,15 +677,6 @@ Common::Error AGOSEngine::init() {
_subtitles = true;
}
- // TODO: Use special debug levels instead of the following hack.
- _debugMode = (gDebugLevel >= 0);
- switch (gDebugLevel) {
- case 2: _dumpOpcodes = true; break;
- case 3: _dumpVgaOpcodes = true; break;
- case 4: _dumpScripts = true; break;
- case 5: _dumpVgaScripts = true; break;
- }
-
return Common::kNoError;
}
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index 5e49fce5ff..b6b5e427e1 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -61,6 +61,14 @@ struct Surface;
namespace AGOS {
+enum {
+ kDebugOpcode = 1 << 0,
+ kDebugVGAOpcode = 1 << 1,
+ kDebugSubroutine = 1 << 2,
+ kDebugVGAScript = 1 << 3,
+ kDebugImageDump = 1 << 4
+};
+
uint fileReadItemID(Common::SeekableReadStream *in);
#define CHECK_BOUNDS(x, y) assert((uint)(x) < ARRAYSIZE(y))
@@ -324,15 +332,9 @@ protected:
bool _fastMode;
bool _backFlag;
- uint16 _debugMode;
Common::Language _language;
bool _copyProtection;
bool _pause;
- bool _dumpScripts;
- bool _dumpOpcodes;
- bool _dumpVgaScripts;
- bool _dumpVgaOpcodes;
- bool _dumpImages;
bool _speech;
bool _subtitles;
bool _vgaVar9;
diff --git a/engines/agos/debugger.cpp b/engines/agos/debugger.cpp
index 512137b685..7ad742c928 100644
--- a/engines/agos/debugger.cpp
+++ b/engines/agos/debugger.cpp
@@ -32,44 +32,21 @@ Debugger::Debugger(AGOSEngine *vm)
: GUI::Debugger() {
_vm = vm;
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("level", WRAP_METHOD(Debugger, Cmd_DebugLevel));
- DCmd_Register("music", WRAP_METHOD(Debugger, Cmd_PlayMusic));
- DCmd_Register("sound", WRAP_METHOD(Debugger, Cmd_PlaySound));
- DCmd_Register("voice", WRAP_METHOD(Debugger, Cmd_PlayVoice));
- DCmd_Register("bit", WRAP_METHOD(Debugger, Cmd_SetBit));
- DCmd_Register("bit2", WRAP_METHOD(Debugger, Cmd_SetBit2));
- DCmd_Register("bit3", WRAP_METHOD(Debugger, Cmd_SetBit3));
- DCmd_Register("var", WRAP_METHOD(Debugger, Cmd_SetVar));
- DCmd_Register("obj", WRAP_METHOD(Debugger, Cmd_SetObjectFlag));
- DCmd_Register("sub", WRAP_METHOD(Debugger, Cmd_StartSubroutine));
- DCmd_Register("dumpimage", WRAP_METHOD(Debugger, Cmd_dumpImage));
- DCmd_Register("dumpscript", WRAP_METHOD(Debugger, Cmd_dumpScript));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("music", WRAP_METHOD(Debugger, Cmd_PlayMusic));
+ registerCmd("sound", WRAP_METHOD(Debugger, Cmd_PlaySound));
+ registerCmd("voice", WRAP_METHOD(Debugger, Cmd_PlayVoice));
+ registerCmd("bit", WRAP_METHOD(Debugger, Cmd_SetBit));
+ registerCmd("bit2", WRAP_METHOD(Debugger, Cmd_SetBit2));
+ registerCmd("bit3", WRAP_METHOD(Debugger, Cmd_SetBit3));
+ registerCmd("var", WRAP_METHOD(Debugger, Cmd_SetVar));
+ registerCmd("obj", WRAP_METHOD(Debugger, Cmd_SetObjectFlag));
+ registerCmd("sub", WRAP_METHOD(Debugger, Cmd_StartSubroutine));
+ registerCmd("dumpimage", WRAP_METHOD(Debugger, Cmd_dumpImage));
+ registerCmd("dumpscript", WRAP_METHOD(Debugger, Cmd_dumpScript));
}
-
-bool Debugger::Cmd_DebugLevel(int argc, const char **argv) {
- if (argc == 1) {
- if (_vm->_debugMode == false)
- DebugPrintf("Debugging is not enabled at this time\n");
- else
- DebugPrintf("Debugging is currently set at level %d\n", gDebugLevel);
- } else { // set level
- gDebugLevel = atoi(argv[1]);
- if (0 <= gDebugLevel && gDebugLevel < 11) {
- _vm->_debugMode = true;
- DebugPrintf("Debug level set to level %d\n", gDebugLevel);
- } else if (gDebugLevel < 0) {
- _vm->_debugMode = false;
- DebugPrintf("Debugging is now disabled\n");
- } else
- DebugPrintf("Not a valid debug level (0 - 10)\n");
- }
-
- return true;
-}
-
bool Debugger::Cmd_PlayMusic(int argc, const char **argv) {
if (argc > 1) {
uint music = atoi(argv[1]);
@@ -83,9 +60,9 @@ bool Debugger::Cmd_PlayMusic(int argc, const char **argv) {
_vm->playMusic(music, 0);
}
} else
- DebugPrintf("Music out of range (0 - %d)\n", _vm->_numMusic);
+ debugPrintf("Music out of range (0 - %d)\n", _vm->_numMusic);
} else
- DebugPrintf("Syntax: music <musicnum>\n");
+ debugPrintf("Syntax: music <musicnum>\n");
return true;
}
@@ -96,9 +73,9 @@ bool Debugger::Cmd_PlaySound(int argc, const char **argv) {
if (sound <= _vm->_numSFX)
_vm->_sound->playEffects(sound);
else
- DebugPrintf("Sound out of range (0 - %d)\n", _vm->_numSFX);
+ debugPrintf("Sound out of range (0 - %d)\n", _vm->_numSFX);
} else
- DebugPrintf("Syntax: sound <soundnum>\n");
+ debugPrintf("Syntax: sound <soundnum>\n");
return true;
}
@@ -109,9 +86,9 @@ bool Debugger::Cmd_PlayVoice(int argc, const char **argv) {
if (voice <= _vm->_numSpeech)
_vm->_sound->playVoice(voice);
else
- DebugPrintf("Voice out of range (0 - %d)\n", _vm->_numSpeech);
+ debugPrintf("Voice out of range (0 - %d)\n", _vm->_numSpeech);
} else
- DebugPrintf("Syntax: voice <voicenum>\n");
+ debugPrintf("Syntax: voice <voicenum>\n");
return true;
}
@@ -123,15 +100,15 @@ bool Debugger::Cmd_SetBit(int argc, const char **argv) {
value = atoi(argv[2]);
if (value <= 1) {
_vm->setBitFlag(bit, value != 0);
- DebugPrintf("Set bit %d to %d\n", bit, value);
+ debugPrintf("Set bit %d to %d\n", bit, value);
} else
- DebugPrintf("Bit value out of range (0 - 1)\n");
+ debugPrintf("Bit value out of range (0 - 1)\n");
} else if (argc > 1) {
bit = atoi(argv[1]);
value = _vm->getBitFlag(bit);
- DebugPrintf("Bit %d is %d\n", bit, value);
+ debugPrintf("Bit %d is %d\n", bit, value);
} else
- DebugPrintf("Syntax: bit <bitnum> <value>\n");
+ debugPrintf("Syntax: bit <bitnum> <value>\n");
return true;
}
@@ -143,18 +120,18 @@ bool Debugger::Cmd_SetBit2(int argc, const char **argv) {
value = atoi(argv[2]);
if (value == 0) {
_vm->_bitArrayTwo[bit / 16] &= ~(1 << (bit & 15));
- DebugPrintf("Set bit2 %d to %d\n", bit, value);
+ debugPrintf("Set bit2 %d to %d\n", bit, value);
} else if (value == 1) {
_vm->_bitArrayTwo[bit / 16] |= (1 << (bit & 15));
- DebugPrintf("Set bit2 %d to %d\n", bit, value);
+ debugPrintf("Set bit2 %d to %d\n", bit, value);
} else
- DebugPrintf("Bit2 value out of range (0 - 1)\n");
+ debugPrintf("Bit2 value out of range (0 - 1)\n");
} else if (argc > 1) {
bit = atoi(argv[1]);
value = (_vm->_bitArrayTwo[bit / 16] & (1 << (bit & 15))) != 0;
- DebugPrintf("Bit2 %d is %d\n", bit, value);
+ debugPrintf("Bit2 %d is %d\n", bit, value);
} else
- DebugPrintf("Syntax: bit2 <bitnum> <value>\n");
+ debugPrintf("Syntax: bit2 <bitnum> <value>\n");
return true;
}
@@ -166,18 +143,18 @@ bool Debugger::Cmd_SetBit3(int argc, const char **argv) {
value = atoi(argv[2]);
if (value == 0) {
_vm->_bitArrayThree[bit / 16] &= ~(1 << (bit & 15));
- DebugPrintf("Set bit3 %d to %d\n", bit, value);
+ debugPrintf("Set bit3 %d to %d\n", bit, value);
} else if (value == 1) {
_vm->_bitArrayThree[bit / 16] |= (1 << (bit & 15));
- DebugPrintf("Set bit3 %d to %d\n", bit, value);
+ debugPrintf("Set bit3 %d to %d\n", bit, value);
} else
- DebugPrintf("Bit3 value out of range (0 - 1)\n");
+ debugPrintf("Bit3 value out of range (0 - 1)\n");
} else if (argc > 1) {
bit = atoi(argv[1]);
value = (_vm->_bitArrayThree[bit / 16] & (1 << (bit & 15))) != 0;
- DebugPrintf("Bit3 %d is %d\n", bit, value);
+ debugPrintf("Bit3 %d is %d\n", bit, value);
} else
- DebugPrintf("Syntax: bit3 <bitnum> <value>\n");
+ debugPrintf("Syntax: bit3 <bitnum> <value>\n");
return true;
}
@@ -190,15 +167,15 @@ bool Debugger::Cmd_SetVar(int argc, const char **argv) {
if (argc > 2) {
value = atoi(argv[2]);
_vm->writeVariable(var, value);
- DebugPrintf("Set var %d to %d\n", var, value);
+ debugPrintf("Set var %d to %d\n", var, value);
} else {
value = _vm->readVariable(var);
- DebugPrintf("Var %d is %d\n", var, value);
+ debugPrintf("Var %d is %d\n", var, value);
}
} else
- DebugPrintf("Var out of range (0 - %d)\n", _vm->_numVars - 1);
+ debugPrintf("Var out of range (0 - %d)\n", _vm->_numVars - 1);
} else
- DebugPrintf("Syntax: var <varnum> <value>\n");
+ debugPrintf("Syntax: var <varnum> <value>\n");
return true;
}
@@ -217,22 +194,22 @@ bool Debugger::Cmd_SetObjectFlag(int argc, const char **argv) {
if (argc > 3) {
value = atoi(argv[3]);
o->objectFlagValue[offs] = value;
- DebugPrintf("Object %d Flag %d set to %d\n", obj, prop, value);
+ debugPrintf("Object %d Flag %d set to %d\n", obj, prop, value);
} else {
value = o->objectFlagValue[offs];
- DebugPrintf("Object %d Flag %d is %d\n", obj, prop, value);
+ debugPrintf("Object %d Flag %d is %d\n", obj, prop, value);
}
} else {
- DebugPrintf("Object flag out of range\n");
+ debugPrintf("Object flag out of range\n");
}
} else {
- DebugPrintf("Item isn't an object\n");
+ debugPrintf("Item isn't an object\n");
}
} else {
- DebugPrintf("Item out of range (1 - %d)\n", _vm->_itemArraySize - 1);
+ debugPrintf("Item out of range (1 - %d)\n", _vm->_itemArraySize - 1);
}
} else {
- DebugPrintf("Syntax: obj <itemnum> <flag> <value>\n");
+ debugPrintf("Syntax: obj <itemnum> <flag> <value>\n");
}
return true;
@@ -246,7 +223,7 @@ bool Debugger::Cmd_StartSubroutine(int argc, const char **argv) {
if (sub != NULL)
_vm->startSubroutine(sub);
} else
- DebugPrintf("Subroutine %d\n", _vm->_currentTable->id);
+ debugPrintf("Subroutine %d\n", _vm->_currentTable->id);
return true;
}
@@ -259,11 +236,11 @@ bool Debugger::Cmd_dumpImage(int argc, const char **argv) {
if (vpe->vgaFile2 != NULL) {
_vm->dumpVgaBitmaps(zoneNum);
} else {
- DebugPrintf("Invalid Zone Number %d\n", zoneNum);
+ debugPrintf("Invalid Zone Number %d\n", zoneNum);
}
} else
- DebugPrintf("Syntax: dumpimage <zonenum>\n");
+ debugPrintf("Syntax: dumpimage <zonenum>\n");
return true;
}
@@ -276,11 +253,11 @@ bool Debugger::Cmd_dumpScript(int argc, const char **argv) {
if (vpe->vgaFile1 != NULL) {
_vm->dumpVgaFile(vpe->vgaFile1);
} else {
- DebugPrintf("Invalid Zone Number %d\n", zoneNum);
+ debugPrintf("Invalid Zone Number %d\n", zoneNum);
}
} else
- DebugPrintf("Syntax: dumpscript <zonenum>\n");
+ debugPrintf("Syntax: dumpscript <zonenum>\n");
return true;
}
diff --git a/engines/agos/debugger.h b/engines/agos/debugger.h
index caac6e2caf..026194410f 100644
--- a/engines/agos/debugger.h
+++ b/engines/agos/debugger.h
@@ -37,7 +37,6 @@ public:
private:
AGOSEngine *_vm;
- bool Cmd_DebugLevel(int argc, const char **argv);
bool Cmd_PlayMusic(int argc, const char **argv);
bool Cmd_PlaySound(int argc, const char **argv);
bool Cmd_PlayVoice(int argc, const char **argv);
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index 6e97084811..33145b7d0d 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "common/debug-channels.h"
#include "common/endian.h"
#include "common/system.h"
#include "common/textconsole.h"
@@ -1129,7 +1130,7 @@ void AGOSEngine::animate(uint16 windowNum, uint16 zoneNum, uint16 vgaSpriteId, i
assert(READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId);
}
- if (_dumpVgaScripts) {
+ if (DebugMan.isDebugChannelEnabled(kDebugVGAScript)) {
if (getGameType() == GType_FF || getGameType() == GType_PP) {
dumpVgaScript(_curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), zoneNum, vgaSpriteId);
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
@@ -1235,7 +1236,7 @@ void AGOSEngine::setImage(uint16 vgaSpriteId, bool vgaScript) {
}
}
- if (_dumpVgaScripts) {
+ if (DebugMan.isDebugChannelEnabled(kDebugVGAScript)) {
if (getGameType() == GType_FF || getGameType() == GType_PP) {
dumpVgaScript(_curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble*)b)->scriptOffs), zoneNum, vgaSpriteId);
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index 392ee08ea1..c26fbe3331 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -235,10 +235,6 @@ void MidiPlayer::startTrack(int track) {
_music.parser = parser; // That plugs the power cord into the wall
} else if (_music.parser) {
if (!_music.parser->setTrack(track)) {
- // The Roland MT32 music in Simon the Sorcerer 2
- // is missing the extra tracks in many scenes,
- // like the introduction sequence.
- stop();
return;
}
_currentTrack = (byte)track;
diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp
index 6f809d9e2d..1dbb9c255a 100644
--- a/engines/agos/script.cpp
+++ b/engines/agos/script.cpp
@@ -22,6 +22,7 @@
// Item script opcodes for Simon1/Simon2
+#include "common/debug-channels.h"
#include "common/endian.h"
#include "common/system.h"
#include "common/textconsole.h"
@@ -987,7 +988,7 @@ int AGOSEngine::runScript() {
return 1;
do {
- if (_dumpOpcodes)
+ if (DebugMan.isDebugChannelEnabled(kDebugOpcode))
dumpOpcode(_codePtr);
if (getGameType() == GType_ELVIRA1) {
diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp
index 39bc468dea..1e6ecaa829 100644
--- a/engines/agos/subroutine.cpp
+++ b/engines/agos/subroutine.cpp
@@ -20,8 +20,7 @@
*
*/
-
-
+#include "common/debug-channels.h"
#include "common/file.h"
#include "common/textconsole.h"
@@ -531,7 +530,7 @@ int AGOSEngine::startSubroutine(Subroutine *sub) {
_classMode1 = 0;
_classMode2 = 0;
- if (_dumpScripts)
+ if (DebugMan.isDebugChannelEnabled(kDebugSubroutine))
dumpSubroutine(sub);
if (++_recursionDepth > 40)
@@ -564,8 +563,7 @@ restart:
else
_codePtr += 8;
- if (_dumpOpcodes)
- debug("; %d", sub->id);
+ debugC(kDebugOpcode, "; %d", sub->id);
result = runScript();
if (result != 0) {
break;
diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp
index c656c0167a..f761c3fc3f 100644
--- a/engines/agos/vga.cpp
+++ b/engines/agos/vga.cpp
@@ -27,6 +27,7 @@
#include "agos/intern.h"
#include "agos/vga.h"
+#include "common/debug-channels.h"
#include "common/endian.h"
#include "common/system.h"
#include "common/textconsole.h"
@@ -152,7 +153,7 @@ void AGOSEngine::runVgaScript() {
for (;;) {
uint opcode;
- if (_dumpVgaOpcodes) {
+ if (DebugMan.isDebugChannelEnabled(kDebugVGAOpcode)) {
if (_vcPtr != (const byte *)&_vcGetOutOfCode) {
debugN("%.5d %.5X: %5d %4d ", _vgaTickCounter, (unsigned int)(_vcPtr - _curVgaFile1), _vgaCurSpriteId, _vgaCurZoneNum);
dumpVideoScript(_vcPtr, true);
@@ -381,8 +382,7 @@ void AGOSEngine::vcSkipNextInstruction() {
_vcPtr += opcodeParamLenPN[opcode];
}
- if (_dumpVgaOpcodes)
- debugN("; skipped\n");
+ debugCN(kDebugVGAOpcode, "; skipped\n");
}
// VGA Script commands
@@ -648,7 +648,7 @@ void AGOSEngine::drawImage_init(int16 image, uint16 palette, int16 x, int16 y, u
if (height == 0 || width == 0)
return;
- if (_dumpImages)
+ if (DebugMan.isDebugChannelEnabled(kDebugImageDump))
dumpSingleBitmap(_vgaCurZoneNum, state.image, state.srcPtr, width, height,
state.palette);
state.width = state.draw_width = width; /* cl */
diff --git a/engines/avalanche/avalot.cpp b/engines/avalanche/avalot.cpp
index c8f5599687..0ffe7d3f9d 100644
--- a/engines/avalanche/avalot.cpp
+++ b/engines/avalanche/avalot.cpp
@@ -217,7 +217,7 @@ void AvalancheEngine::setup() {
delete mainmenu;
if (_letMeOut)
return;
-
+
newGame();
thinkAbout(kObjectMoney, kThing);
diff --git a/engines/avalanche/console.cpp b/engines/avalanche/console.cpp
index 29ae5cf9c3..d4923affc1 100644
--- a/engines/avalanche/console.cpp
+++ b/engines/avalanche/console.cpp
@@ -31,7 +31,7 @@
namespace Avalanche {
AvalancheConsole::AvalancheConsole(AvalancheEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("magic_lines", WRAP_METHOD(AvalancheConsole, Cmd_MagicLines));
+ registerCmd("magic_lines", WRAP_METHOD(AvalancheConsole, Cmd_MagicLines));
}
AvalancheConsole::~AvalancheConsole() {
@@ -42,7 +42,7 @@ AvalancheConsole::~AvalancheConsole() {
*/
bool AvalancheConsole::Cmd_MagicLines(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
diff --git a/engines/avalanche/dialogs.cpp b/engines/avalanche/dialogs.cpp
index e843d17c5b..f95440900b 100644
--- a/engines/avalanche/dialogs.cpp
+++ b/engines/avalanche/dialogs.cpp
@@ -105,7 +105,7 @@ void Dialogs::setReadyLight(byte state) {
color = kColorGreen;
break; // Hit a key
}
-
+
_vm->_graphics->drawReadyLight(color);
CursorMan.showMouse(true);
_vm->_ledStatus = state;
diff --git a/engines/avalanche/ghostroom.cpp b/engines/avalanche/ghostroom.cpp
index 16c79fdee0..047a3670c2 100644
--- a/engines/avalanche/ghostroom.cpp
+++ b/engines/avalanche/ghostroom.cpp
@@ -49,6 +49,9 @@ GhostRoom::GhostRoom(AvalancheEngine *vm) {
_greldetCount = 0;
_redGreldet = false;
_wasLoaded = false;
+
+ _ghost = nullptr;
+ _glerk = nullptr;
}
GhostRoom::~GhostRoom() {
diff --git a/engines/avalanche/ghostroom.h b/engines/avalanche/ghostroom.h
index 4c659128ce..ca1e8ac806 100644
--- a/engines/avalanche/ghostroom.h
+++ b/engines/avalanche/ghostroom.h
@@ -56,7 +56,7 @@ private:
static const byte kWaveOrder[5];
static const byte kGlerkFade[26];
static const byte kGreldetFade[18];
-
+
Common::Point dummyCoord;
byte ****_ghost;// [5][2][66][26]
Graphics::Surface _eyes[2];
diff --git a/engines/avalanche/graphics.cpp b/engines/avalanche/graphics.cpp
index 513cd72c8c..60c23594d3 100644
--- a/engines/avalanche/graphics.cpp
+++ b/engines/avalanche/graphics.cpp
@@ -198,7 +198,7 @@ void GraphicManager::drawToolbar() {
Common::Point GraphicManager::drawArc(Graphics::Surface &surface, int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color) {
Common::Point endPoint;
- const double convfac = M_PI / 180.0;
+ const float convfac = (float)M_PI / 180.0f;
int32 xRadius = radius;
int32 yRadius = radius * kScreenWidth / (8 * kScreenHeight); // Just don't ask why...
@@ -231,7 +231,7 @@ Common::Point GraphicManager::drawArc(Graphics::Surface &surface, int16 x, int16
uint16 numOfPixels = (uint16)floor(sqrt(3.0) * sqrt(pow(double(xRadius), 2) + pow(double(yRadius), 2)) + 0.5);
// Calculate the angle precision required.
- float delta = 90.0 / numOfPixels;
+ float delta = 90.0f / numOfPixels;
// Always just go over the first 90 degrees. Could be optimized a
// bit if startAngle and endAngle lie in the same quadrant, left as an
@@ -533,7 +533,7 @@ void GraphicManager::ghostDrawMonster(byte ***picture, uint16 destX, int16 destY
// Only for the Ghost:
const byte kPlaneToUse[4] = { 0, 0, 0, 1 };
int yStart = 0;
-
+
// Constants from the original code:
switch (type) {
case kMonsterTypeGhost:
@@ -820,7 +820,7 @@ void GraphicManager::menuLoadPictures() {
int height = 33;
int width = 9 * 8;
-
+
for (int plane = 0; plane < 4; plane++) {
// The icons themselves:
int n = 0;
@@ -853,7 +853,7 @@ void GraphicManager::menuLoadPictures() {
_menu.fillRect(Common::Rect(114, 70 + i * 33, 584, 73 + i * 33), kColorWhite);
_menu.fillRect(Common::Rect(114, 100 + i * 33, 584, 103 + i * 33), kColorDarkgray);
}
-
+
file.close();
// The title on the top of the screen:
diff --git a/engines/avalanche/help.cpp b/engines/avalanche/help.cpp
index 9b077eb4fb..4d08e3d58b 100644
--- a/engines/avalanche/help.cpp
+++ b/engines/avalanche/help.cpp
@@ -196,9 +196,9 @@ bool Help::handleMouse(const Common::Event &event) {
}
// Erase the previous highlight only if it's needed:
- if (_highlightWas != highlightIs)
+ if (_highlightWas != highlightIs)
_vm->_graphics->helpDrawHighlight(_highlightWas, kColorBlue);
-
+
// Highlight the current one with the proper color:
if ((highlightIs != 177) && (_buttons[highlightIs]._trigger != Common::KEYCODE_INVALID)) {
_highlightWas = highlightIs;
diff --git a/engines/avalanche/module.mk b/engines/avalanche/module.mk
index 29bc039b42..919ff0334f 100644
--- a/engines/avalanche/module.mk
+++ b/engines/avalanche/module.mk
@@ -22,7 +22,7 @@ MODULE_OBJS = \
shootemup.o \
mainmenu.o \
highscore.o
-
+
# This module can be built as a plugin
ifeq ($(ENABLE_AVALANCHE), DYNAMIC_PLUGIN)
PLUGIN := 1
diff --git a/engines/avalanche/nim.cpp b/engines/avalanche/nim.cpp
index 9457a5065b..79be16d3c3 100644
--- a/engines/avalanche/nim.cpp
+++ b/engines/avalanche/nim.cpp
@@ -77,7 +77,7 @@ void Nim::playNim() {
_vm->_dialogs->displayScrollChain('Q', 3);
_playedNim++;
-
+
_vm->_graphics->saveScreen();
_vm->fadeOut();
@@ -87,7 +87,7 @@ void Nim::playNim() {
//CursorMan.showMouse(true);
do {
-
+
startMove();
if (_dogfoodsTurn)
dogFood();
@@ -122,7 +122,7 @@ void Nim::playNim() {
_vm->refreshObjectList();
_vm->_wonNim = true;
_vm->_background->draw(-1, -1, 0); // Show the settle with no lute on it.
-
+
// 7 points for winning!
_vm->incScore(7);
}
@@ -135,7 +135,7 @@ void Nim::playNim() {
void Nim::chalk(int x, int y, Common::String text) {
const Color greys[] = { kColorBlack, kColorDarkgray, kColorLightgray, kColorWhite };
-
+
for (int i = 0; i < 4; i++) {
_vm->_graphics->drawNormalText(text, _vm->_font, 8, x - i, y, greys[i]);
_vm->_graphics->refreshScreen();
@@ -159,7 +159,7 @@ void Nim::setup() {
// Bottom right rectangle.
_vm->_graphics->drawRectangle(Common::Rect(394, 50, 635, 198), kColorRed);
_vm->_graphics->drawFilledRectangle(Common::Rect(395, 51, 634, 197), kColorBrown);
-
+
_vm->_graphics->nimDrawLogo();
_vm->_graphics->nimDrawInitials();
@@ -167,7 +167,7 @@ void Nim::setup() {
_vm->_graphics->drawNormalText("Turn:", _vm->_font, 8, 420, 55, kColorYellow);
_vm->_graphics->drawNormalText("Player:", _vm->_font, 8, 490, 55, kColorYellow);
_vm->_graphics->drawNormalText("Move:", _vm->_font, 8, 570, 55, kColorYellow);
-
+
chalk(27, 7, "Take pieces away with:");
chalk(77, 17, "1) the mouse (click leftmost)");
chalk(53, 27, "or 2) the keyboard:");
@@ -364,7 +364,7 @@ bool Nim::checkInput() {
void Nim::takeSome() {
_number = 1;
-
+
do {
byte sr;
do {
@@ -377,7 +377,7 @@ void Nim::takeSome() {
_number = 1;
}
} while (sr == 0);
-
+
if (_number > sr)
_number = sr;
@@ -391,7 +391,7 @@ void Nim::takeSome() {
bool confirm = false;
do {
confirm = checkInput();
-
+
if (!confirm) {
_vm->_graphics->drawRectangle(Common::Rect(x1, y1, x2, y2), kColorBlack); // Erase the previous selection.
x1 = 63 + (_stones[_row] - _number) * 64;
@@ -402,7 +402,7 @@ void Nim::takeSome() {
_vm->_graphics->refreshScreen();
}
} while (!confirm);
-
+
return;
} while (true);
diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp
index b152747ab0..220186ca5e 100644
--- a/engines/avalanche/parser.cpp
+++ b/engines/avalanche/parser.cpp
@@ -2495,7 +2495,7 @@ void Parser::synchronize(Common::Serializer &sz) {
sz.syncAsByte(_sworeNum);
sz.syncAsByte(_alcoholLevel);
if (sz.isLoading() && sz.getVersion() < 2) {
- int dummy;
+ int dummy;
sz.syncAsByte(dummy);
}
sz.syncAsByte(_boughtOnion);
diff --git a/engines/avalanche/shootemup.cpp b/engines/avalanche/shootemup.cpp
index cabd19d6f9..e5e44ed934 100644
--- a/engines/avalanche/shootemup.cpp
+++ b/engines/avalanche/shootemup.cpp
@@ -116,7 +116,7 @@ uint16 ShootEmUp::run() {
}
setup();
-
+
while ((_time != 0) && (!_vm->shouldQuit())) {
uint32 beginLoop = _vm->_system->getMillis();
@@ -142,7 +142,7 @@ uint16 ShootEmUp::run() {
if (delay <= 55)
_vm->_system->delayMillis(55 - delay); // Replaces slowdown(); 55 comes from 18.2 Hz (B Flight).
};
-
+
_vm->fadeOut();
_vm->_graphics->restoreScreen();
_vm->_graphics->removeBackup();
diff --git a/engines/bbvs/minigames/bbtennis.cpp b/engines/bbvs/minigames/bbtennis.cpp
index 926642cc5f..ddd5cfc804 100644
--- a/engines/bbvs/minigames/bbtennis.cpp
+++ b/engines/bbvs/minigames/bbtennis.cpp
@@ -412,10 +412,10 @@ bool MinigameBbTennis::updateStatus1(int mouseX, int mouseY, uint mouseButtons)
obj->targetY = mouseY;
obj->ballStep = 12;
obj->ballStepCtr = 0;
- obj->fltX = 160.0;
- obj->fltY = 240.0;
- obj->fltStepX = ((160 - mouseX) * 0.75) / 12.0;
- obj->fltStepY = ((240 - mouseY) * 0.75) / 12.0;
+ obj->fltX = 160.0f;
+ obj->fltY = 240.0f;
+ obj->fltStepX = ((160 - mouseX) * 0.75f) / 12.0f;
+ obj->fltStepY = ((240 - mouseY) * 0.75f) / 12.0f;
_newBallTimer = _initBallTimer;
++_numBalls;
playSound(31);
@@ -582,21 +582,21 @@ void MinigameBbTennis::updateTennisBall(int objIndex) {
obj->ballStep = 12;
++obj->ballStepCtr;
if (obj->ballStepCtr == 1) {
- obj->fltStepX = ((obj->fltX - (float)obj->targetX) * 0.75) / 12.0;
- obj->fltStepY = ((obj->fltY - (float)obj->targetY) * 0.75) / 12.0;
+ obj->fltStepX = ((obj->fltX - (float)obj->targetX) * 0.75f) / 12.0f;
+ obj->fltStepY = ((obj->fltY - (float)obj->targetY) * 0.75f) / 12.0f;
} else if (obj->ballStepCtr == 2) {
- obj->fltStepX = (obj->fltX - (float)obj->targetX) / 12.0;
- obj->fltStepY = (obj->fltY - (float)obj->targetY) / 12.0;
+ obj->fltStepX = (obj->fltX - (float)obj->targetX) / 12.0f;
+ obj->fltStepY = (obj->fltY - (float)obj->targetY) / 12.0f;
} else {
- obj->fltStepX = 0.0;
- obj->fltStepY = 0.0;
+ obj->fltStepX = 0.0f;
+ obj->fltStepY = 0.0f;
}
}
obj->fltX = obj->fltX - obj->fltStepX;
- obj->x = obj->fltX;
+ obj->x = (int)obj->fltX;
obj->fltY = obj->fltY - obj->fltStepY;
- obj->y = obj->fltY;
+ obj->y = (int)obj->fltY;
}
@@ -1087,11 +1087,11 @@ void MinigameBbTennis::updateEnemyTennisBall(int objIndex) {
obj->ballStep = 12;
--obj->ballStepCtr;
if (obj->ballStepCtr == 1) {
- obj->fltStepX = (obj->fltX - (float)obj->targetX) / 12.0;
- obj->fltStepY = (obj->fltY - (float)obj->targetY) / 12.0;
+ obj->fltStepX = (obj->fltX - (float)obj->targetX) / 12.0f;
+ obj->fltStepY = (obj->fltY - (float)obj->targetY) / 12.0f;
} else if (obj->ballStepCtr == 2) {
- obj->fltStepX = ((obj->fltX - (float)obj->targetX) * 0.18) / 12.0;
- obj->fltStepY = ((obj->fltY - (float)obj->targetY) * 0.18) / 12.0;
+ obj->fltStepX = ((obj->fltX - (float)obj->targetX) * 0.18f) / 12.0f;
+ obj->fltStepY = ((obj->fltY - (float)obj->targetY) * 0.18f) / 12.0f;
} else {
obj->kind = 0;
if (_numHearts > 0 && --_numHearts == 0)
@@ -1100,9 +1100,9 @@ void MinigameBbTennis::updateEnemyTennisBall(int objIndex) {
}
obj->fltX = obj->fltX - obj->fltStepX;
- obj->x = obj->fltX;
+ obj->x = (int)obj->fltX;
obj->fltY = obj->fltY - obj->fltStepY;
- obj->y = obj->fltY;
+ obj->y = (int)obj->fltY;
}
@@ -1125,36 +1125,36 @@ void MinigameBbTennis::makeEnemyBall(int x, int y, int frameIndex) {
case 6:
obj->ballStep = 18;
obj->ballStepCtr = 3;
- obj->fltStepX = 0.0;
- obj->fltStepY = 0.0;
+ obj->fltStepX = 0.0f;
+ obj->fltStepY = 0.0f;
break;
case 5:
obj->ballStep = 12;
obj->ballStepCtr = 3;
- obj->fltStepX = ((float)(x - 160) * 0.07) / 12.0;
- obj->fltStepY = ((float)(y - 180) * 0.07) / 12.0;
+ obj->fltStepX = ((float)(x - 160) * 0.07f) / 12.0f;
+ obj->fltStepY = ((float)(y - 180) * 0.07f) / 12.0f;
break;
case 4:
obj->ballStep = 6;
obj->ballStepCtr = 3;
- obj->fltStepX = ((float)(x - 160) * 0.07) / 6.0;
- obj->fltStepY = ((float)(y - 180) * 0.07) / 6.0;
+ obj->fltStepX = ((float)(x - 160) * 0.07f) / 6.0f;
+ obj->fltStepY = ((float)(y - 180) * 0.07f) / 6.0f;
break;
case 3:
obj->ballStep = 12;
obj->ballStepCtr = 2;
- obj->fltStepX = ((float)(x - 160) * 0.18) / 12.0;
- obj->fltStepY = ((float)(y - 180) * 0.18) / 12.0;
+ obj->fltStepX = ((float)(x - 160) * 0.18f) / 12.0f;
+ obj->fltStepY = ((float)(y - 180) * 0.18f) / 12.0f;
break;
case 2:
obj->ballStep = 6;
obj->ballStepCtr = 2;
- obj->fltStepX = ((float)(x - 160) * 0.18) / 6.0;
- obj->fltStepY = ((float)(y - 180) * 0.18) / 6.0;
+ obj->fltStepX = ((float)(x - 160) * 0.18f) / 6.0f;
+ obj->fltStepY = ((float)(y - 180) * 0.18f) / 6.0f;
break;
case 1:
diff --git a/engines/bbvs/walk.cpp b/engines/bbvs/walk.cpp
index cf8942e525..077110b867 100644
--- a/engines/bbvs/walk.cpp
+++ b/engines/bbvs/walk.cpp
@@ -109,12 +109,12 @@ void BbvsEngine::updateWalkObject(SceneObject *sceneObject) {
void BbvsEngine::walkObject(SceneObject *sceneObject, const Common::Point &destPt, int walkSpeed) {
int deltaX = destPt.x - (sceneObject->x >> 16);
int deltaY = destPt.y - (sceneObject->y >> 16);
- float distance = sqrt((double)(deltaX * deltaX + deltaY * deltaY));
+ float distance = (float)sqrt((double)(deltaX * deltaX + deltaY * deltaY));
// NOTE The original doesn't have this check but without it the whole pathfinding breaks
- if (distance > 0.0) {
- sceneObject->walkCount = distance / ((((float)ABS(deltaX) / distance) + 1.0) * ((float)walkSpeed / 120));
- sceneObject->xIncr = ((float)deltaX / sceneObject->walkCount) * 65536.0;
- sceneObject->yIncr = ((float)deltaY / sceneObject->walkCount) * 65536.0;
+ if (distance > 0.0f) {
+ sceneObject->walkCount = (int)(distance / ((((float)ABS(deltaX) / distance) + 1.0f) * ((float)walkSpeed / 120)));
+ sceneObject->xIncr = (int)(((float)deltaX / sceneObject->walkCount) * 65536.0f);
+ sceneObject->yIncr = (int)(((float)deltaY / sceneObject->walkCount) * 65536.0f);
sceneObject->x = (sceneObject->x & 0xFFFF0000) | 0x8000;
sceneObject->y = (sceneObject->y & 0xFFFF0000) | 0x8000;
} else
@@ -334,10 +334,10 @@ bool BbvsEngine::walkTestLineWalkable(const Common::Point &sourcePt, const Commo
return true;
if (walkInfo->direction) {
const float nDeltaY = wDeltaX * ptDeltaY / ptDeltaX + (float)sourcePt.y - (float)walkInfo->y;
- return (nDeltaY >= 0.0) && (nDeltaY < (float)walkInfo->delta);
+ return (nDeltaY >= 0.0f) && (nDeltaY < (float)walkInfo->delta);
} else {
const float nDeltaX = wDeltaY / ptDeltaX * ptDeltaY + (float)sourcePt.x - (float)walkInfo->x;
- return (nDeltaX >= 0.0) && (nDeltaX < (float)walkInfo->delta);
+ return (nDeltaX >= 0.0f) && (nDeltaX < (float)walkInfo->delta);
}
return false;
}
diff --git a/engines/cge/POTFILES b/engines/cge/POTFILES
new file mode 100644
index 0000000000..55430683c3
--- /dev/null
+++ b/engines/cge/POTFILES
@@ -0,0 +1,2 @@
+engines/cge/detection.cpp
+
diff --git a/engines/cge/cge.cpp b/engines/cge/cge.cpp
index 3f7aa4abc9..7058314b9d 100644
--- a/engines/cge/cge.cpp
+++ b/engines/cge/cge.cpp
@@ -219,7 +219,7 @@ Common::Error CGEEngine::run() {
}
// Initialize graphics using following:
- initGraphics(320, 200, false);
+ initGraphics(kScrWidth, kScrHeight, false);
// Setup necessary game objects
init();
diff --git a/engines/cge/cge.h b/engines/cge/cge.h
index a65069ff46..c43358f252 100644
--- a/engines/cge/cge.h
+++ b/engines/cge/cge.h
@@ -80,12 +80,6 @@ class Talk;
#define kSayTheEnd 41
-enum GameType {
- kGameTypeNone = 0,
- kGameTypeSoltys,
- kGameTypeSfinx
-};
-
// our engine debug channels
enum {
kCGEDebugBitmap = 1 << 0,
diff --git a/engines/cge/console.cpp b/engines/cge/console.cpp
index 447875c06f..e926e89506 100644
--- a/engines/cge/console.cpp
+++ b/engines/cge/console.cpp
@@ -26,7 +26,7 @@
namespace CGE {
CGEConsole::CGEConsole(CGEEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("Boundaries", WRAP_METHOD(CGEConsole, Cmd_boundaries));
+ registerCmd("Boundaries", WRAP_METHOD(CGEConsole, Cmd_boundaries));
}
CGEConsole::~CGEConsole() {
@@ -37,7 +37,7 @@ CGEConsole::~CGEConsole() {
*/
bool CGEConsole::Cmd_boundaries(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index 4c2f81c1ae..da5eb2b1f2 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -28,134 +28,75 @@
#include "base/plugins.h"
#include "graphics/thumbnail.h"
#include "cge/cge.h"
+#include "cge/fileio.h"
namespace CGE {
-struct CgeGameDescription {
- ADGameDescription desc;
- GameType gameType;
-};
-
#define GAMEOPTION_COLOR_BLIND_DEFAULT_OFF GUIO_GAMEOPTIONS1
-} // End of namespace CGE
-
static const PlainGameDescriptor CGEGames[] = {
{ "soltys", "Soltys" },
- { "sfinx", "Sfinx" },
{ 0, 0 }
};
-namespace CGE {
-
-static const CgeGameDescription gameDescriptions[] = {
-
- {
- {
- "soltys", "",
- {
- {"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
- {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437572},
- AD_LISTEND
- },
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
- },
- kGameTypeSoltys
- },
+static const ADGameDescription gameDescriptions[] = {
{
+ "soltys", "Freeware",
{
- "soltys", "Soltys Freeware",
- {
- {"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
- {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437676},
- AD_LISTEND
- },
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ {"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
+ {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437676},
+ AD_LISTEND
},
- kGameTypeSoltys
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
{
+ "soltys", "Demo (not supported)",
{
- "soltys", "Soltys Demo (not supported)",
- {
- {"vol.cat", 0, "1e077c8ff58109a187f07ac54b0c873a", 18788},
- {"vol.dat", 0, "75d385a6074c58b69f7730481f256051", 1796710},
- AD_LISTEND
- },
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ {"vol.cat", 0, "1e077c8ff58109a187f07ac54b0c873a", 18788},
+ {"vol.dat", 0, "75d385a6074c58b69f7730481f256051", 1796710},
+ AD_LISTEND
},
- kGameTypeSoltys
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
{
+ "soltys", "Demo (not supported)",
{
- "soltys", "Soltys Demo (not supported)",
- {
- {"vol.cat", 0, "f17987487fab1ebddd781d8d02fedecc", 7168},
- {"vol.dat", 0, "c5d9b15863cab61dc125551576dece04", 1075272},
- AD_LISTEND
- },
- Common::PL_POL, Common::kPlatformDOS, ADGF_DEMO , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ {"vol.cat", 0, "f17987487fab1ebddd781d8d02fedecc", 7168},
+ {"vol.dat", 0, "c5d9b15863cab61dc125551576dece04", 1075272},
+ AD_LISTEND
},
- kGameTypeSoltys
+ Common::PL_POL, Common::kPlatformDOS, ADGF_DEMO , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
{
+ "soltys", "Freeware v1.0",
{
- "soltys", "Soltys Freeware v1.0",
- {
- {"vol.cat", 0, "f1675684c68ab90272f5776f8f2c3974", 50176},
- {"vol.dat", 0, "4ffeff4abc99ac5999b55ccfc56ab1df", 8430868},
- AD_LISTEND
- },
- Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ {"vol.cat", 0, "f1675684c68ab90272f5776f8f2c3974", 50176},
+ {"vol.dat", 0, "4ffeff4abc99ac5999b55ccfc56ab1df", 8430868},
+ AD_LISTEND
},
- kGameTypeSoltys
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
{
+ "soltys", "Freeware v1.0",
{
- "soltys", "Soltys Freeware v1.0",
- {
- {"vol.cat", 0, "20fdce799adb618100ef9ee2362be875", 50176},
- {"vol.dat", 0, "0e43331c846094d77f5dd201827e0a3b", 8439339},
- AD_LISTEND
- },
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ {"vol.cat", 0, "20fdce799adb618100ef9ee2362be875", 50176},
+ {"vol.dat", 0, "0e43331c846094d77f5dd201827e0a3b", 8439339},
+ AD_LISTEND
},
- kGameTypeSoltys
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
{
+ "soltys", "Freeware v1.0",
{
- "soltys", "Soltys Freeware v1.0",
- {
- {"vol.cat", 0, "fcae86b20eaa5cedec17b24fa5e85eb4", 50176},
- {"vol.dat", 0, "ff10d54acc2c95696c57e05819b6906f", 8450151},
- AD_LISTEND
- },
- Common::ES_ESP, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ {"vol.cat", 0, "fcae86b20eaa5cedec17b24fa5e85eb4", 50176},
+ {"vol.dat", 0, "ff10d54acc2c95696c57e05819b6906f", 8450151},
+ AD_LISTEND
},
- kGameTypeSoltys
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
- {
- {
- // Polish version, provided by Strangerke
- "sfinx", "Sfinx Freeware",
- {
- {"vol.cat", 0, "21197b287d397c53261b6616bf0dd880", 129024},
- {"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844},
- AD_LISTEND
- },
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
- },
- kGameTypeSfinx
- },
-
- {AD_TABLE_END_MARKER, kGameTypeNone}
-};
-static const ADFileBasedFallback fileBasedFallback[] = {
- { &gameDescriptions[0].desc, { "vol.cat", "vol.dat", 0 } },
- { 0, { 0 } }
+ AD_TABLE_END_MARKER
};
-} // End of namespace CGE
static const ADExtraGuiOptionsMap optionsList[] = {
{
@@ -173,14 +114,10 @@ static const ADExtraGuiOptionsMap optionsList[] = {
class CGEMetaEngine : public AdvancedMetaEngine {
public:
- CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(CGE::CgeGameDescription), CGEGames, optionsList) {
+ CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(ADGameDescription), CGEGames, optionsList) {
_singleid = "soltys";
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- return detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback);
- }
-
virtual const char *getName() const {
return "CGE";
}
@@ -189,6 +126,7 @@ public:
return "Soltys (c) 1994-1996 L.K. Avalon";
}
+ virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual int getMaximumSaveSlot() const;
@@ -197,6 +135,44 @@ public:
virtual void removeSaveState(const char *target, int slot) const;
};
+static const ADFileBasedFallback fileBasedFallback[] = {
+ { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } },
+ { 0, { 0 } }
+};
+
+static ADGameDescription s_fallbackDesc = {
+ "Soltys",
+ "Unknown version",
+ AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
+ Common::UNK_LANG,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+};
+
+const ADGameDescription *CGEMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADFilePropertiesMap filesProps;
+
+ const ADGameDescription *game;
+ game = detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback, &filesProps);
+
+ if (!game)
+ return nullptr;
+
+ SearchMan.clear();
+ SearchMan.addDirectory(fslist.begin()->getParent().getPath(), fslist.begin()->getParent());
+ ResourceManager *resman;
+ resman = new ResourceManager();
+ bool result = resman->exist("CGE.SAY");
+ delete resman;
+
+ if (!result)
+ return nullptr;
+
+ reportUnknown(fslist.begin()->getParent(), filesProps);
+ return &s_fallbackDesc;
+}
+
bool CGEMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
@@ -306,9 +282,10 @@ bool CGEMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD
}
return desc != 0;
}
+} // End of namespace CGE
#if PLUGIN_ENABLED_DYNAMIC(CGE)
- REGISTER_PLUGIN_DYNAMIC(CGE, PLUGIN_TYPE_ENGINE, CGEMetaEngine);
+REGISTER_PLUGIN_DYNAMIC(CGE, PLUGIN_TYPE_ENGINE, CGE::CGEMetaEngine);
#else
- REGISTER_PLUGIN_STATIC(CGE, PLUGIN_TYPE_ENGINE, CGEMetaEngine);
+REGISTER_PLUGIN_STATIC(CGE, PLUGIN_TYPE_ENGINE, CGE::CGEMetaEngine);
#endif
diff --git a/engines/cge/fileio.cpp b/engines/cge/fileio.cpp
index 2b1f74db02..8609110782 100644
--- a/engines/cge/fileio.cpp
+++ b/engines/cge/fileio.cpp
@@ -121,7 +121,10 @@ BtPage *ResourceManager::getPage(int level, uint16 pageId) {
if (_buff[level]._pageNo != pageId) {
int32 pos = pageId * kBtSize;
_buff[level]._pageNo = pageId;
- assert(_catFile->size() > pos);
+
+ if (_catFile->size() <= pos)
+ return nullptr;
+
// In the original, there was a check verifying if the
// purpose was to write a new file. This should only be
// to create a new file, thus it was removed.
@@ -146,6 +149,9 @@ BtKeypack *ResourceManager::find(const char *key) {
uint16 nxt = kBtValRoot;
while (!_catFile->eos()) {
BtPage *pg = getPage(lev, nxt);
+ if (!pg)
+ return nullptr;
+
// search
if (pg->_header._down != kBtValNone) {
int i;
@@ -167,13 +173,17 @@ BtKeypack *ResourceManager::find(const char *key) {
return &pg->_leaf[i];
}
}
- return NULL;
+ return nullptr;
}
bool ResourceManager::exist(const char *name) {
debugC(1, kCGEDebugFile, "ResourceManager::exist(%s)", name);
- return scumm_stricmp(find(name)->_key, name) == 0;
+ BtKeypack* result = find(name);
+ if (!result)
+ return false;
+
+ return scumm_stricmp(result->_key, name) == 0;
}
uint16 ResourceManager::catRead(byte *buf, uint16 length) {
@@ -228,7 +238,7 @@ uint32 EncryptedStream::read(byte *dataPtr, uint32 dataSize) {
}
bool EncryptedStream::err() {
- return (_error & _readStream->err());
+ return (_error || _readStream->err());
}
bool EncryptedStream::eos() {
diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp
index d5e1be5122..babcb7e667 100644
--- a/engines/cge/vga13h.cpp
+++ b/engines/cge/vga13h.cpp
@@ -482,39 +482,39 @@ void Sprite::sync(Common::Serializer &s) {
uint16 flags = 0;
if (s.isLoading()) {
s.syncAsUint16LE(flags);
- _flags._hide = flags & 0x0001 ? true : false;
- _flags._near = flags & 0x0002 ? true : false;
- _flags._drag = flags & 0x0004 ? true : false;
- _flags._hold = flags & 0x0008 ? true : false;
- _flags._dummy = flags & 0x0010 ? true : false;
- _flags._slav = flags & 0x0020 ? true : false;
- _flags._syst = flags & 0x0040 ? true : false;
- _flags._kill = flags & 0x0080 ? true : false;
- _flags._xlat = flags & 0x0100 ? true : false;
- _flags._port = flags & 0x0200 ? true : false;
- _flags._kept = flags & 0x0400 ? true : false;
- _flags._east = flags & 0x0800 ? true : false;
- _flags._shad = flags & 0x1000 ? true : false;
- _flags._back = flags & 0x2000 ? true : false;
- _flags._bDel = flags & 0x4000 ? true : false;
- _flags._tran = flags & 0x8000 ? true : false;
+ _flags._hide = flags & 0x0001;
+ _flags._near = flags & 0x0002;
+ _flags._drag = flags & 0x0004;
+ _flags._hold = flags & 0x0008;
+ _flags._dummy = flags & 0x0010;
+ _flags._slav = flags & 0x0020;
+ _flags._syst = flags & 0x0040;
+ _flags._kill = flags & 0x0080;
+ _flags._xlat = flags & 0x0100;
+ _flags._port = flags & 0x0200;
+ _flags._kept = flags & 0x0400;
+ _flags._east = flags & 0x0800;
+ _flags._shad = flags & 0x1000;
+ _flags._back = flags & 0x2000;
+ _flags._bDel = flags & 0x4000;
+ _flags._tran = flags & 0x8000;
} else {
- flags = (flags << 1) | _flags._tran;
- flags = (flags << 1) | _flags._bDel;
- flags = (flags << 1) | _flags._back;
- flags = (flags << 1) | _flags._shad;
- flags = (flags << 1) | _flags._east;
- flags = (flags << 1) | _flags._kept;
- flags = (flags << 1) | _flags._port;
- flags = (flags << 1) | _flags._xlat;
- flags = (flags << 1) | _flags._kill;
- flags = (flags << 1) | _flags._syst;
- flags = (flags << 1) | _flags._slav;
- flags = (flags << 1) | _flags._dummy;
- flags = (flags << 1) | _flags._hold;
- flags = (flags << 1) | _flags._drag;
- flags = (flags << 1) | _flags._near;
- flags = (flags << 1) | _flags._hide;
+ flags = (flags << 1) | (_flags._tran ? 1 : 0);
+ flags = (flags << 1) | (_flags._bDel ? 1 : 0);
+ flags = (flags << 1) | (_flags._back ? 1 : 0);
+ flags = (flags << 1) | (_flags._shad ? 1 : 0);
+ flags = (flags << 1) | (_flags._east ? 1 : 0);
+ flags = (flags << 1) | (_flags._kept ? 1 : 0);
+ flags = (flags << 1) | (_flags._port ? 1 : 0);
+ flags = (flags << 1) | (_flags._xlat ? 1 : 0);
+ flags = (flags << 1) | (_flags._kill ? 1 : 0);
+ flags = (flags << 1) | (_flags._syst ? 1 : 0);
+ flags = (flags << 1) | (_flags._slav ? 1 : 0);
+ flags = (flags << 1) | (_flags._dummy ? 1 : 0);
+ flags = (flags << 1) | (_flags._hold ? 1 : 0);
+ flags = (flags << 1) | (_flags._drag ? 1 : 0);
+ flags = (flags << 1) | (_flags._near ? 1 : 0);
+ flags = (flags << 1) | (_flags._hide ? 1 : 0);
s.syncAsUint16LE(flags);
}
@@ -819,14 +819,14 @@ void Vga::update() {
_setPal = false;
}
if (_vm->_showBoundariesFl) {
- Vga::_page[0]->hLine(0, 200 - kPanHeight, 320, 0xee);
+ Vga::_page[0]->hLine(0, kScrHeight - kPanHeight, kScrWidth, 0xee);
if (_vm->_barriers[_vm->_now]._horz != 255) {
for (int i = 0; i < 8; i++)
- Vga::_page[0]->vLine((_vm->_barriers[_vm->_now]._horz * 8) + i, 0, 200, 0xff);
+ Vga::_page[0]->vLine((_vm->_barriers[_vm->_now]._horz * 8) + i, 0, kScrHeight, 0xff);
}
if (_vm->_barriers[_vm->_now]._vert != 255) {
for (int i = 0; i < 4; i++)
- Vga::_page[0]->hLine(0, 80 + (_vm->_barriers[_vm->_now]._vert * 4) + i, 320, 0xff);
+ Vga::_page[0]->hLine(0, 80 + (_vm->_barriers[_vm->_now]._vert * 4) + i, kScrWidth, 0xff);
}
}
diff --git a/engines/cge/vga13h.h b/engines/cge/vga13h.h
index 9511559df0..a976d7078c 100644
--- a/engines/cge/vga13h.h
+++ b/engines/cge/vga13h.h
@@ -88,22 +88,22 @@ public:
int _ref;
signed char _scene;
struct Flags {
- uint16 _hide : 1; // general visibility switch
- uint16 _near : 1; // Near action lock
- uint16 _drag : 1; // sprite is moveable
- uint16 _hold : 1; // sprite is held with mouse
- uint16 _dummy : 1; // intrrupt driven animation
- uint16 _slav : 1; // slave object
- uint16 _syst : 1; // system object
- uint16 _kill : 1; // dispose memory after remove
- uint16 _xlat : 1; // 2nd way display: xlat table
- uint16 _port : 1; // portable
- uint16 _kept : 1; // kept in pocket
- uint16 _east : 1; // talk to east (in opposite to west)
- uint16 _shad : 1; // shadow
- uint16 _back : 1; // 'send to background' request
- uint16 _bDel : 1; // delete bitmaps in ~SPRITE
- uint16 _tran : 1; // transparent (untouchable)
+ bool _hide; // general visibility switch
+ bool _near; // Near action lock
+ bool _drag; // sprite is moveable
+ bool _hold; // sprite is held with mouse
+ bool _dummy; // interrupt driven animation
+ bool _slav; // slave object
+ bool _syst; // system object
+ bool _kill; // dispose memory after remove
+ bool _xlat; // 2nd way display: xlat table
+ bool _port; // portable
+ bool _kept; // kept in pocket
+ bool _east; // talk to east (in opposite to west)
+ bool _shad; // shadow
+ bool _back; // 'send to background' request
+ bool _bDel; // delete bitmaps in ~SPRITE
+ bool _tran; // transparent (untouchable)
} _flags;
int _x;
int _y;
diff --git a/engines/cge2/POTFILES b/engines/cge2/POTFILES
new file mode 100644
index 0000000000..1e904763ec
--- /dev/null
+++ b/engines/cge2/POTFILES
@@ -0,0 +1 @@
+engines/cge2/detection.cpp
diff --git a/engines/cge2/bitmap.cpp b/engines/cge2/bitmap.cpp
new file mode 100644
index 0000000000..0f442b8c77
--- /dev/null
+++ b/engines/cge2/bitmap.cpp
@@ -0,0 +1,458 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/bitmap.h"
+#include "cge2/cge2.h"
+#include "cge2/vga13h.h"
+#include "cge2/talk.h"
+#include "common/system.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+
+namespace CGE2 {
+
+Bitmap::Bitmap() : _w(0), _h(0), _v(nullptr), _b(nullptr), _map(0), _vm(nullptr) {
+}
+
+void Bitmap::setVM(CGE2Engine *vm) {
+ _vm = vm;
+}
+
+Bitmap::Bitmap(CGE2Engine *vm, const char *fname) : _w(0), _h(0), _v(nullptr), _b(nullptr), _map(0), _vm(vm) {
+ Common::String path;
+
+ if (!strcmp(fname, "04tal201")) {
+ path = "04tal202";
+ warning("Workaround for missing VBM: 04tal201");
+ } else if (!strcmp(fname, "11oqlist-")) {
+ path = "11oqlist";
+ warning("Workaround for wrong VBM name: 11oqlist-");
+ } else
+ path = fname;
+
+ path = setExtension(path, ".VBM");
+
+ if (_vm->_resman->exist(path.c_str())) {
+ EncryptedStream file(_vm, path.c_str());
+ if (file.err())
+ error("Unable to find VBM [%s]", fname);
+ if (!loadVBM(&file))
+ error("Bad VBM [%s]", fname);
+ } else {
+ warning("Missing VBM [%s]", path.c_str());
+ }
+}
+
+Bitmap::Bitmap(CGE2Engine *vm, uint16 w, uint16 h, uint8 *map) : _w(w), _h(h), _v(nullptr), _map(0), _b(nullptr), _vm(vm) {
+ if (map)
+ code(map);
+}
+
+// following routine creates filled rectangle
+// immediately as VGA video chunks, in near memory as fast as possible,
+// especially for text line real time display
+Bitmap::Bitmap(CGE2Engine *vm, uint16 w, uint16 h, uint8 fill)
+ : _w((w + 3) & ~3), // only full uint32 allowed!
+ _h(h), _map(0), _b(nullptr), _vm(vm) {
+
+ uint16 dsiz = _w >> 2; // data size (1 plane line size)
+ uint16 lsiz = 2 + dsiz + 2; // uint16 for line header, uint16 for gap
+ uint16 psiz = _h * lsiz; // - last gape, but + plane trailer
+ uint8 *v = new uint8[4 * psiz + _h * sizeof(*_b)];// the same for 4 planes
+ // + room for wash table
+
+ WRITE_LE_UINT16(v, (kBmpCPY | dsiz)); // data chunk hader
+ memset(v + 2, fill, dsiz); // data bytes
+ WRITE_LE_UINT16(v + lsiz - 2, (kBmpSKP | ((kScrWidth / 4) - dsiz))); // gap
+
+ // Replicate lines
+ byte *destP;
+ for (destP = v + lsiz; destP < (v + psiz); destP += lsiz)
+ Common::copy(v, v + lsiz, destP);
+
+ WRITE_LE_UINT16(v + psiz - 2, kBmpEOI); // plane trailer uint16
+
+ // Replicate planes
+ for (destP = v + psiz; destP < (v + 4 * psiz); destP += psiz)
+ Common::copy(v, v + psiz, destP);
+
+ HideDesc *b = (HideDesc *)(v + 4 * psiz);
+ b->_skip = (kScrWidth - _w) >> 2;
+ b->_hide = _w >> 2;
+
+ // 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;
+}
+
+Bitmap::Bitmap(CGE2Engine *vm, const Bitmap &bmp) : _w(bmp._w), _h(bmp._h), _v(nullptr), _map(0), _b(nullptr), _vm(vm) {
+ uint8 *v0 = bmp._v;
+ if (!v0)
+ return;
+
+ uint16 vsiz = (uint8 *)(bmp._b) - (uint8 *)(v0);
+ uint16 siz = vsiz + _h * sizeof(HideDesc);
+ uint8 *v1 = new uint8[siz];
+ memcpy(v1, v0, siz);
+ _b = (HideDesc *)((_v = v1) + vsiz);
+}
+
+Bitmap::~Bitmap() {
+ release();
+}
+
+void Bitmap::release() {
+ if (_v != nullptr)
+ delete[] _v;
+ _v = nullptr;
+}
+
+Bitmap &Bitmap::operator=(const Bitmap &bmp) {
+ if (this == &bmp)
+ return *this;
+
+ uint8 *v0 = bmp._v;
+ _w = bmp._w;
+ _h = bmp._h;
+ _map = 0;
+ _vm = bmp._vm;
+ delete[] _v;
+ _v = nullptr;
+
+ if (v0) {
+ uint16 vsiz = (uint8 *)bmp._b - (uint8 *)v0;
+ uint16 siz = vsiz + _h * sizeof(HideDesc);
+ uint8 *v1 = new uint8[siz];
+ memcpy(v1, v0, siz);
+ _b = (HideDesc *)((_v = v1) + vsiz);
+ }
+ return *this;
+}
+
+// Blatant rip from hopkins engine where it's ripped from gob engine. Hi DrMcCoy, hi Strangerke! ;>
+Common::String Bitmap::setExtension(const Common::String &str, const Common::String &ext) {
+ if (str.empty())
+ return str;
+
+ const char *dot = strrchr(str.c_str(), '.');
+ if (dot)
+ return Common::String(str.c_str(), dot - str.c_str()) + ext;
+
+ return str + ext;
+}
+
+BitmapPtr Bitmap::code(uint8 *map) {
+ if (!map)
+ return nullptr;
+
+ uint16 cnt;
+
+ if (_v) { // old X-map exists, so remove it
+ delete[] _v;
+ _v = nullptr;
+ }
+
+ while (true) { // at most 2 times: for (V == NULL) & for allocated block;
+ uint8 *im = _v + 2;
+ uint16 *cp = (uint16 *) _v;
+
+ if (_v) { // 2nd pass - fill the hide table
+ for (uint i = 0; i < _h; i++) {
+ _b[i]._skip = 0xFFFF;
+ _b[i]._hide = 0x0000;
+ }
+ }
+ for (int bpl = 0; bpl < 4; bpl++) { // once per each bitplane
+ uint8 *bm = map;
+ bool skip = (bm[bpl] == kPixelTransp);
+ uint16 j;
+
+ cnt = 0;
+ for (uint i = 0; i < _h; i++) { // once per each line
+ uint8 pix;
+ for (j = bpl; j < _w; j += 4) {
+ pix = bm[j];
+ if (_v && (pix != kPixelTransp)) {
+ if (j < _b[i]._skip)
+ _b[i]._skip = j;
+
+ if (j >= _b[i]._hide)
+ _b[i]._hide = j + 1;
+ }
+ if (((pix == kPixelTransp) != skip) || (cnt >= 0x3FF0)) { // end of block
+ cnt |= (skip) ? kBmpSKP : kBmpCPY;
+ if (_v)
+ WRITE_LE_UINT16(cp, cnt); // store block description uint16
+
+ cp = (uint16 *) im;
+ im += 2;
+ skip = (pix == kPixelTransp);
+ cnt = 0;
+ }
+ if (!skip) {
+ if (_v)
+ *im = pix;
+ im++;
+ }
+ cnt++;
+ }
+
+ bm += _w;
+ if (_w < kScrWidth) {
+ if (skip)
+ cnt += (kScrWidth - j + 3) / 4;
+ else {
+ cnt |= kBmpCPY;
+ if (_v)
+ WRITE_LE_UINT16(cp, cnt);
+
+ cp = (uint16 *) im;
+ im += 2;
+ skip = true;
+ cnt = (kScrWidth - j + 3) / 4;
+ }
+ }
+ }
+ if (cnt && ! skip) {
+ cnt |= kBmpCPY;
+ if (_v)
+ WRITE_LE_UINT16(cp, cnt);
+
+ cp = (uint16 *) im;
+ im += 2;
+ }
+ if (_v)
+ WRITE_LE_UINT16(cp, kBmpEOI);
+ cp = (uint16 *) im;
+ im += 2;
+ }
+ if (_v)
+ break;
+
+ uint16 sizV = (uint16)(im - 2 - _v);
+ _v = new uint8[sizV + _h * sizeof(*_b)];
+ _b = (HideDesc *)(_v + sizV);
+ }
+ cnt = 0;
+ for (uint i = 0; i < _h; i++) {
+ if (_b[i]._skip == 0xFFFF) { // whole line is skipped
+ _b[i]._skip = (cnt + kScrWidth) >> 2;
+ cnt = 0;
+ } else {
+ uint16 s = _b[i]._skip & ~3;
+ uint16 h = (_b[i]._hide + 3) & ~3;
+ _b[i]._skip = (cnt + s) >> 2;
+ _b[i]._hide = (h - s) >> 2;
+ cnt = kScrWidth - h;
+ }
+ }
+
+ return this;
+}
+
+bool Bitmap::solidAt(V2D pos) {
+ pos.x += _w >> 1;
+ pos.y = _h - pos.y;
+
+ if (!pos.limited(V2D(_vm, _w, _h)))
+ return false;
+
+ uint8 *m = _v;
+ uint16 r = static_cast<uint16>(pos.x) % 4;
+ uint16 n0 = (kScrWidth * pos.y + pos.x) / 4;
+ uint16 n = 0;
+
+ while (r) {
+ uint16 w, t;
+
+ w = READ_LE_UINT16(m);
+ m += 2;
+ t = w & 0xC000;
+ w &= 0x3FFF;
+
+ switch (t) {
+ case kBmpEOI:
+ r--;
+ // No break on purpose
+ case kBmpSKP:
+ w = 0;
+ break;
+ case kBmpREP:
+ w = 1;
+ break;
+ }
+ m += w;
+ }
+
+ while (true) {
+ uint16 w, t;
+
+ w = READ_LE_UINT16(m);
+ m += 2;
+ t = w & 0xC000;
+ w &= 0x3FFF;
+
+ if (n > n0)
+ return false;
+
+ n += w;
+ switch (t) {
+ case kBmpEOI:
+ return false;
+ case kBmpSKP:
+ w = 0;
+ break;
+ case kBmpREP:
+ case kBmpCPY:
+ if ((n - w <= n0) && (n > n0))
+ return true;
+ break;
+ }
+ m += ((t == kBmpREP) ? 1 : w);
+ }
+}
+
+bool Bitmap::loadVBM(EncryptedStream *f) {
+ uint16 p = 0, n = 0;
+ if (!f->err())
+ f->read((uint8 *)&p, sizeof(p));
+ p = FROM_LE_16(p);
+
+ if (!f->err())
+ f->read((uint8 *)&n, sizeof(n));
+ n = FROM_LE_16(n);
+
+ if (!f->err())
+ f->read((uint8 *)&_w, sizeof(_w));
+ _w = FROM_LE_16(_w);
+
+ if (!f->err())
+ f->read((uint8 *)&_h, sizeof(_h));
+ _h = FROM_LE_16(_h);
+
+ if (!f->err()) {
+ if (p) {
+ if (_vm->_bitmapPalette) {
+ // 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;
+ _vm->_bitmapPalette[idx]._g = *(srcP + 1);
+ _vm->_bitmapPalette[idx]._b = *(srcP + 2);
+ }
+ } else
+ f->seek(f->pos() + kPalSize);
+ }
+ }
+ _v = new uint8[n];
+
+ if (!f->err())
+ f->read(_v, n);
+
+ _b = (HideDesc *)(_v + n - _h * sizeof(HideDesc));
+ return (!f->err());
+}
+
+void Bitmap::xLatPos(V2D& p) {
+ p.x -= (_w >> 1);
+ p.y = kWorldHeight - p.y - _h;
+}
+
+#define _ kPixelTransp,
+#define L 1,
+#define G 2,
+#define D 3,
+#define kDesignSize 240
+
+uint8 *Bitmap::makeSpeechBubbleTail(int which, uint8 colorSet[][4]) {
+ static const uint8 kSLDesign[kDesignSize] = {
+ G G G G G G G G G _ _ _ _ _ _
+ L G G G G G G G G D _ _ _ _ _
+ _ L G G G G G G G D _ _ _ _ _
+ _ _ L G G G G G G G D _ _ _ _
+ _ _ _ L G G G G G G D _ _ _ _
+ _ _ _ _ L G G G G G D _ _ _ _
+ _ _ _ _ _ L G G G G G D _ _ _
+ _ _ _ _ _ _ L G G G G D _ _ _
+ _ _ _ _ _ _ _ L G G G D _ _ _
+ _ _ _ _ _ _ _ _ L G G G D _ _
+ _ _ _ _ _ _ _ _ _ L G G D _ _
+ _ _ _ _ _ _ _ _ _ _ L G D _ _
+ _ _ _ _ _ _ _ _ _ _ _ L G D _
+ _ _ _ _ _ _ _ _ _ _ _ _ L D _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ L D
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ D
+ };
+
+ static const uint8 kSRDesign[kDesignSize] = {
+ _ _ _ _ _ _ G G G G G G G G G
+ _ _ _ _ _ L G G G G G G G G D
+ _ _ _ _ _ L G G G G G G G D _
+ _ _ _ _ L G G G G G G G D _ _
+ _ _ _ _ L G G G G G G D _ _ _
+ _ _ _ _ L G G G G G D _ _ _ _
+ _ _ _ L G G G G G D _ _ _ _ _
+ _ _ _ L G G G G D _ _ _ _ _ _
+ _ _ _ L G G G D _ _ _ _ _ _ _
+ _ _ L G G G D _ _ _ _ _ _ _ _
+ _ _ L G G D _ _ _ _ _ _ _ _ _
+ _ _ L G D _ _ _ _ _ _ _ _ _ _
+ _ L G D _ _ _ _ _ _ _ _ _ _ _
+ _ L D _ _ _ _ _ _ _ _ _ _ _ _
+ L D _ _ _ _ _ _ _ _ _ _ _ _ _
+ D _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ };
+
+ uint8 *des = new uint8[kDesignSize];
+ switch (which) {
+ case 0:
+ memcpy(des, kSLDesign, sizeof(kSLDesign));
+ break;
+ case 1:
+ memcpy(des, kSRDesign, sizeof(kSRDesign));
+ break;
+ default:
+ error("Wrong parameter in Bitmap::makeSpeechBubbleTail!");
+ break;
+ }
+
+ for (int i = 0; i < kDesignSize; i++) {
+ if ((des[i] >= 1) && (des[i] <= 3))
+ des[i] = colorSet[kCBSay][des[i]];
+ }
+
+ return des;
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/bitmap.h b/engines/cge2/bitmap.h
new file mode 100644
index 0000000000..613222fc6e
--- /dev/null
+++ b/engines/cge2/bitmap.h
@@ -0,0 +1,94 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_BITMAP_H
+#define CGE2_BITMAP_H
+
+#include "cge2/general.h"
+#include "common/file.h"
+
+namespace CGE2 {
+
+class CGE2Engine;
+class EncryptedStream;
+class V2D;
+
+#define kMaxPath 128
+
+enum {
+ kBmpEOI = 0x0000,
+ kBmpSKP = 0x4000,
+ kBmpREP = 0x8000,
+ kBmpCPY = 0xC000
+};
+
+#include "common/pack-start.h"
+
+struct HideDesc {
+ uint16 _skip;
+ uint16 _hide;
+};
+
+#include "common/pack-end.h"
+
+class Bitmap {
+ CGE2Engine *_vm;
+
+ Common::String setExtension(const Common::String &str, const Common::String &ext);
+ bool loadVBM(EncryptedStream *f);
+public:
+ uint16 _w;
+ uint16 _h;
+ uint8 *_v;
+ int32 _map;
+ HideDesc *_b;
+
+ Bitmap();
+ Bitmap(CGE2Engine *vm, const char *fname);
+ Bitmap(CGE2Engine *vm, uint16 w, uint16 h, uint8 *map);
+ Bitmap(CGE2Engine *vm, uint16 w, uint16 h, uint8 fill);
+ Bitmap(CGE2Engine *vm, const Bitmap &bmp);
+ ~Bitmap();
+
+ void setVM(CGE2Engine *vm);
+ Bitmap *code(uint8 *map);
+ Bitmap &operator=(const Bitmap &bmp);
+ void release();
+ void hide(V2D pos);
+ void show(V2D pos);
+ bool solidAt(V2D pos);
+ void xLatPos(V2D &p);
+
+ static uint8 *makeSpeechBubbleTail(int des, uint8 colorSet[][4]);
+};
+
+
+typedef Bitmap *BitmapPtr;
+
+} // End of namespace CGE2
+
+#endif // CGE2_BITMAP_H
diff --git a/engines/cge2/cge2.cpp b/engines/cge2/cge2.cpp
new file mode 100644
index 0000000000..37d87ba09c
--- /dev/null
+++ b/engines/cge2/cge2.cpp
@@ -0,0 +1,207 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "engines/util.h"
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "cge2/cge2.h"
+#include "cge2/bitmap.h"
+#include "cge2/vga13h.h"
+#include "cge2/sound.h"
+#include "cge2/text.h"
+#include "cge2/hero.h"
+#include "cge2/general.h"
+#include "cge2/spare.h"
+#include "cge2/talk.h"
+#include "cge2/cge2_main.h"
+#include "cge2/map.h"
+
+namespace CGE2 {
+
+CGE2Engine::CGE2Engine(OSystem *syst, const ADGameDescription *gameDescription)
+ : Engine(syst), _gameDescription(gameDescription), _randomSource("cge2") {
+
+ // Debug/console setup
+ DebugMan.addDebugChannel(kCGE2DebugOpcode, "opcode", "CGE2 opcode debug channel");
+
+ _resman = nullptr;
+ _vga = nullptr;
+ _midiPlayer = nullptr;
+ _fx = nullptr;
+ _sound = nullptr;
+ _text = nullptr;
+ for (int i = 0; i < 2; i++)
+ _heroTab[i] = nullptr;
+ _eye = nullptr;
+ for (int i = 0; i < kSceneMax; i++)
+ _eyeTab[i] = nullptr;
+ _spare = nullptr;
+ _commandHandler = nullptr;
+ _commandHandlerTurbo = nullptr;
+ _font = nullptr;
+ _infoLine = nullptr;
+ _mouse = nullptr;
+ _keyboard = nullptr;
+ _talk = nullptr;
+ for (int i = 0; i < kMaxPoint; i++)
+ _point[i] = nullptr;
+ _sys = nullptr;
+ _busyPtr = nullptr;
+ for (int i = 0; i < 2; i++)
+ _vol[i] = nullptr;
+ _eventManager = nullptr;
+ _map = nullptr;
+ _console = nullptr;
+ _quitFlag = false;
+ _bitmapPalette = nullptr;
+ _gamePhase = kPhaseIntro;
+ _now = 1;
+ _sex = 1;
+ _mouseTop = kWorldHeight / 3;
+ _dark = false;
+ _lastFrame = 0;
+ _lastTick = 0;
+ _waitSeq = 0;
+ _waitRef = 0;
+ _soundStat._wait = nullptr;
+ _soundStat._ref[0] = 0;
+ _soundStat._ref[1] = 0;
+ _taken = false;
+ _endGame = false;
+ _req = 1;
+ _midiNotify = nullptr;
+ _spriteNotify = nullptr;
+ _startGameSlot = 0;
+
+ _sayCap = ConfMan.getBool("subtitles");
+ _sayVox = !ConfMan.getBool("speech_mute");
+ _muteAll = ConfMan.getBool("mute");
+ if (_muteAll) {
+ _oldMusicVolume = _oldSfxVolume = 0;
+ _music = _sayVox = false;
+ } else {
+ _oldMusicVolume = ConfMan.getInt("music_volume");
+ _oldSfxVolume = ConfMan.getInt("sfx_volume");
+ _music = _oldMusicVolume != 0;
+ }
+}
+
+void CGE2Engine::init() {
+ // Create debugger console
+ _console = new CGE2Console(this);
+ _resman = new ResourceManager();
+ _vga = new Vga(this);
+ _fx = new Fx(this, 16);
+ _sound = new Sound(this);
+ _midiPlayer = new MusicPlayer(this);
+ _text = new Text(this, "CGE");
+
+ for (int i = 0; i < 2; i++)
+ _heroTab[i] = new HeroTab(this);
+
+ _eye = new V3D();
+ for (int i = 0; i < kSceneMax; i++)
+ _eyeTab[i] = new V3D();
+
+ _spare = new Spare(this);
+ _commandHandler = new CommandHandler(this, false);
+ _commandHandlerTurbo = new CommandHandler(this, true);
+ _font = new Font(this);
+ _infoLine = new InfoLine(this, kInfoW);
+ _mouse = new Mouse(this);
+ _keyboard = new Keyboard(this);
+
+ for (int i = 0; i < kMaxPoint; i++)
+ _point[i] = new V3D();
+
+ _sys = new System(this);
+ _eventManager = new EventManager(this);
+ _map = new Map(this);
+ _startGameSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
+}
+
+void CGE2Engine::deinit() {
+ // Remove all of our debug levels here
+ DebugMan.clearAllDebugChannels();
+
+ delete _console;
+
+ delete _spare;
+ delete _resman;
+ delete _vga;
+ delete _fx;
+ delete _sound;
+ delete _midiPlayer;
+ delete _text;
+
+ for (int i = 0; i < 2; i++)
+ delete _heroTab[i];
+
+ for (int i = 0; i < kSceneMax; i++)
+ delete _eyeTab[i];
+
+ delete _eye;
+ delete _commandHandler;
+ delete _commandHandlerTurbo;
+ delete _font;
+ delete _infoLine;
+ delete _mouse;
+ delete _keyboard;
+
+ if (_talk != nullptr)
+ delete _talk;
+
+ for (int i = 0; i < kMaxPoint; i++)
+ delete _point[i];
+
+ delete _sys;
+ delete _eventManager;
+ delete _map;
+}
+
+bool CGE2Engine::hasFeature(EngineFeature f) const {
+ return (f == kSupportsLoadingDuringRuntime) || (f == kSupportsSavingDuringRuntime)
+ || (f == kSupportsRTL);
+}
+
+Common::Error CGE2Engine::run() {
+ syncSoundSettings();
+ initGraphics(kScrWidth, kScrHeight, false);
+
+ init();
+ cge2_main();
+ deinit();
+
+ ConfMan.setBool("subtitles", _sayCap);
+ ConfMan.setBool("speech_mute", !_sayVox);
+ ConfMan.flushToDisk();
+
+ return Common::kNoError;
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/cge2.h b/engines/cge2/cge2.h
new file mode 100644
index 0000000000..50b418f294
--- /dev/null
+++ b/engines/cge2/cge2.h
@@ -0,0 +1,338 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_H
+#define CGE2_H
+
+#include "common/random.h"
+#include "common/savefile.h"
+#include "common/serializer.h"
+#include "engines/engine.h"
+#include "engines/advancedDetector.h"
+#include "common/system.h"
+#include "cge2/fileio.h"
+#include "cge2/console.h"
+#include "audio/mixer.h"
+
+namespace CGE2 {
+
+class Vga;
+class Sprite;
+class MusicPlayer;
+class Fx;
+class Sound;
+class Text;
+struct HeroTab;
+class FXP;
+class V3D;
+class V2D;
+struct Dac;
+class Spare;
+class CommandHandler;
+class InfoLine;
+class Mouse;
+class Keyboard;
+class Talk;
+class Hero;
+class Bitmap;
+class System;
+class EventManager;
+class Font;
+class Map;
+struct SavegameHeader;
+
+#define kScrWidth 320
+#define kScrHeight 240
+#define kScrDepth 480
+#define kPanHeight 40
+#define kWorldHeight (kScrHeight - kPanHeight)
+#define kMaxFile 128
+#define kPathMax 128
+#define kDimMax 8
+#define kWayMax 10
+#define kPocketMax 4
+#define kSceneMax 100
+#define kMaxPoint 4
+#define kInfoX 160
+#define kInfoY -11
+#define kInfoW 180
+#define kPocketsWidth 59
+#define kLineMax 512
+
+#define kIntroExt ".I80"
+#define kTabName "CGE.TAB"
+#define kPocketFull 170
+#define kGameFrameDelay (750 / 50)
+#define kGameTickDelay (750 / 62)
+
+#define kMusicRef 122
+#define kPowerRef 123
+#define kDvolRef 124
+#define kMvolRef 125
+#define kBusyRef 127
+
+#define kOffUseCount 130
+#define kOffUseText 131
+
+#define kSysTimeRate 6 // 12 Hz
+#define kBlinkRate 4 // 3 Hz
+
+#define kQuitTitle 200
+#define kQuitText 201
+#define kNoQuitText 202
+
+#define kSavegameVersion 1
+#define kSavegameStrSize 12
+#define kSavegameStr "SCUMMVM_CGE2"
+
+#define kColorNum 6
+
+struct SavegameHeader {
+ uint8 version;
+ Common::String saveName;
+ Graphics::Surface *thumbnail;
+ int saveYear, saveMonth, saveDay;
+ int saveHour, saveMinutes;
+};
+
+enum ColorBank { kCBRel, kCBStd, kCBSay, kCBInf, kCBMnu, kCBWar };
+
+enum GamePhase { kPhaseInGame, kPhaseIntro, kPhaseOver };
+
+// our engine debug channels
+enum {
+ kCGE2DebugOpcode = 1 << 0
+};
+
+enum CallbackType {
+ kNullCB = 0, kQGame, kXScene
+};
+
+enum Action { kNear, kMTake, kFTake, kActions };
+
+typedef void (CGE2Engine::*NotifyFunctionType)();
+
+class CGE2Engine : public Engine {
+private:
+ uint32 _lastFrame, _lastTick;
+ void tick();
+
+ CGE2Console *_console;
+ void init();
+ void deinit();
+
+ Common::String generateSaveName(int slot);
+ void writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header);
+ void saveGame(int slotNumber, const Common::String &desc);
+ bool loadGame(int slotNumber);
+ void syncHeader(Common::Serializer &s);
+ void syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream);
+ void resetGame();
+public:
+ CGE2Engine(OSystem *syst, const ADGameDescription *gameDescription);
+ virtual bool hasFeature(EngineFeature f) const;
+ virtual bool canSaveGameStateCurrently();
+ virtual bool canLoadGameStateCurrently();
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+ virtual Common::Error loadGameState(int slot);
+ virtual Common::Error run();
+
+ static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header);
+
+ GUI::Debugger *getDebugger() {
+ return _console;
+ }
+
+ bool showTitle(const char *name);
+ void cge2_main();
+ char *mergeExt(char *buf, const char *name, const char *ext);
+ void inf(const char *text, ColorBank col = kCBInf);
+ void movie(const char *ext);
+ void runGame();
+ void loadHeroes();
+ void loadScript(const char *fname, bool onlyToolbar = false);
+ Sprite *loadSprite(const char *fname, int ref, int scene, V3D &pos);
+ void badLab(const char *fn);
+ void sceneUp(int cav);
+ void sceneDown();
+ void closePocket();
+ void switchScene(int scene);
+ void storeHeroPos();
+ void showBak(int ref);
+ void loadTab();
+ int newRandom(int range);
+ void openPocket();
+ void selectPocket(int n);
+ void busy(bool on);
+ void feedSnail(Sprite *spr, Action snq, Hero *hero);
+ int freePockets(int sx);
+ int findActivePocket(int ref);
+ void pocFul();
+ void killText();
+ void mainLoop();
+ void handleFrame();
+ Sprite *locate(int ref);
+ bool isHero(Sprite *spr);
+ void loadUser();
+ void loadPos();
+ void releasePocket(Sprite *spr);
+ void switchHero(int sex);
+ void offUse();
+ void setAutoColors();
+ bool cross(const V2D &a, const V2D &b, const V2D &c, const V2D &d);
+ bool contain(const V2D &a, const V2D &b, const V2D &p);
+ long det(const V2D &a, const V2D &b, const V2D &c);
+ int sgn(long n);
+ int mapCross(const V2D &a, const V2D &b);
+ Sprite *spriteAt(V2D pos);
+ void keyClick();
+ void swapInPocket(Sprite *spr, Sprite *xspr);
+ void busyStep();
+
+ void optionTouch(int opt, uint16 mask);
+ void switchColorMode();
+ void switchMusic();
+ void quit();
+ void setVolume(int idx, int cnt);
+ void checkVolumeSwitches();
+ void switchCap();
+ void switchVox();
+ void switchSay();
+ void initToolbar();
+ void initVolumeSwitch(Sprite *volSwitch, int val);
+ void checkMute();
+
+ void checkSounds();
+
+ void setEye(const V3D &e);
+ void setEye(const V2D& e2, int z = -kScrWidth);
+ void setEye(const char *s);
+
+ int number(char *s);
+ char *token(char *s);
+ char *tail(char *s);
+ int takeEnum(const char **tab, const char *text);
+ ID ident(const char *s);
+ bool testBool(char *s);
+
+ void snKill(Sprite *spr);
+ void snHide(Sprite *spr, int val);
+ void snMidi(int val);
+ void snSeq(Sprite *spr, int val);
+ void snRSeq(Sprite *spr, int val);
+ void snSend(Sprite *spr, int val);
+ void snSwap(Sprite *spr, int val);
+ void snCover(Sprite *spr, int val);
+ void snUncover(Sprite *spr, Sprite *spr2);
+ void snKeep(Sprite *spr, int val);
+ void snGive(Sprite *spr, int val);
+ void snGoto(Sprite *spr, int val);
+ void snPort(Sprite *spr, int port);
+ void snMouse(bool on);
+ void snNNext(Sprite *spr, Action act, int val);
+ void snRNNext(Sprite *spr, int val);
+ void snRMTNext(Sprite *spr, int val);
+ void snRFTNext(Sprite *spr, int val);
+ void snRmNear(Sprite *spr);
+ void snRmMTake(Sprite *spr);
+ void snRmFTake(Sprite *spr);
+ void snSetRef(Sprite *spr, int val);
+ void snFlash(bool on);
+ void snCycle(int cnt);
+ void snWalk(Sprite *spr, int val);
+ void snReach(Sprite *spr, int val);
+ void snSound(Sprite *spr, int wav, Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
+ void snRoom(Sprite *spr, bool on);
+ void snGhost(Bitmap *bmp);
+ void snSay(Sprite *spr, int val);
+
+ void hide1(Sprite *spr);
+ Sprite *expandSprite(Sprite *spr);
+ void qGame();
+ void xScene();
+
+ const ADGameDescription *_gameDescription;
+
+ Common::RandomSource _randomSource;
+
+ bool _quitFlag;
+ Dac *_bitmapPalette;
+ GamePhase _gamePhase; // Original name: startupmode
+ int _now;
+ int _sex;
+ int _mouseTop;
+ bool _dark;
+ int _waitSeq;
+ int _waitRef;
+
+ struct {
+ int *_wait;
+ int _ref[2];
+ } _soundStat;
+
+ bool _taken;
+ bool _endGame;
+ int _req;
+ NotifyFunctionType _midiNotify;
+ NotifyFunctionType _spriteNotify;
+ int _startGameSlot;
+
+ bool _sayCap;
+ bool _sayVox;
+ int _oldMusicVolume;
+ int _oldSfxVolume;
+ bool _music;
+ bool _muteAll;
+
+ ResourceManager *_resman;
+ Vga *_vga;
+ MusicPlayer *_midiPlayer;
+ Fx *_fx;
+ Sound *_sound;
+ Text *_text;
+ HeroTab *_heroTab[2];
+ V3D *_eye;
+ V3D *_eyeTab[kSceneMax];
+ Spare *_spare;
+ CommandHandler *_commandHandler;
+ CommandHandler *_commandHandlerTurbo;
+ Font *_font;
+ InfoLine *_infoLine;
+ Mouse *_mouse;
+ Keyboard *_keyboard;
+ Talk *_talk;
+ V3D *_point[kMaxPoint];
+ System *_sys;
+ Sprite *_busyPtr;
+ Sprite *_vol[2];
+ EventManager *_eventManager;
+ Map *_map;
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_H
diff --git a/engines/cge2/cge2_main.cpp b/engines/cge2/cge2_main.cpp
new file mode 100644
index 0000000000..3e3d615a91
--- /dev/null
+++ b/engines/cge2/cge2_main.cpp
@@ -0,0 +1,959 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "sound.h"
+#include "cge2/cge2_main.h"
+#include "cge2/cge2.h"
+#include "cge2/vga13h.h"
+#include "cge2/text.h"
+#include "cge2/snail.h"
+#include "cge2/hero.h"
+#include "cge2/spare.h"
+#include "cge2/map.h"
+
+namespace CGE2 {
+
+System::System(CGE2Engine *vm) : Sprite(vm), _vm(vm) {
+ _blinkCounter = 0;
+ _blinkSprite = nullptr;
+ tick();
+}
+
+void System::touch(uint16 mask, V2D pos, Common::KeyCode keyCode) {
+ if (mask & kEventKeyb) {
+ if (keyCode == Common::KEYCODE_ESCAPE) {
+ // The original was calling keyClick()
+ // The sound is uselessly annoying and noisy, so it has been removed
+ _vm->killText();
+ if (_vm->_gamePhase == kPhaseIntro) {
+ _vm->_commandHandler->addCommand(kCmdClear, -1, 0, nullptr);
+ return;
+ }
+ }
+ } else {
+ if (_vm->_gamePhase != kPhaseInGame)
+ return;
+ _vm->_infoLine->setText(nullptr);
+
+ if (mask & kMouseLeftUp) {
+ if (pos.y >= 0) { // world
+ if (!_vm->_talk && pos.y < _vm->_mouseTop)
+ _vm->_heroTab[_vm->_sex]->_ptr->walkTo(pos);
+ } else { // panel
+ if (_vm->_commandHandler->idle()) {
+ int sex = pos.x < kPocketsWidth;
+ if (sex || pos.x >= kScrWidth - kPocketsWidth) {
+ _vm->switchHero(sex);
+ if (_vm->_sex == sex) {
+ int dx = kPocketsWidth >> 1,
+ dy = 1 - (kPanHeight >> 1);
+ Sprite *s;
+ if (!sex)
+ pos.x -= kScrWidth - kPocketsWidth;
+ dx -= pos.x;
+ dy -= pos.y;
+ if (dx * dx + dy * dy > 10 * 10) {
+ int n = 0;
+ if (1 - pos.y >= (kPanHeight >> 1))
+ n += 2;
+ if (pos.x >= (kPocketsWidth >> 1))
+ ++n;
+ s = _vm->_heroTab[_vm->_sex]->_pocket[n];
+ if (_vm->_sys->_blinkSprite)
+ _vm->_sys->_blinkSprite->_flags._hide = false;
+ if (_vm->_sys->_blinkSprite == s)
+ _vm->_sys->_blinkSprite = nullptr;
+ else
+ _vm->_sys->_blinkSprite = s;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void System::tick() {
+ _time = kSysTimeRate;
+
+ if (_blinkCounter)
+ --_blinkCounter;
+ else {
+ if (_blinkSprite)
+ _blinkSprite->_flags._hide ^= 1;
+ _blinkCounter = kBlinkRate;
+ }
+}
+
+int CGE2Engine::number(char *str) {
+ char *s = token(str);
+ if (s == nullptr)
+ error("Wrong input for CGE2Engine::number()");
+ int r = atoi(s);
+ char *pp = strchr(s, ':');
+ if (pp)
+ r = (r << 8) + atoi(pp + 1);
+ return r;
+}
+
+char *CGE2Engine::token(char *s) {
+ return strtok(s, " =\t,;/()");
+}
+
+char *CGE2Engine::tail(char *s) {
+ if (s && (*s == '='))
+ s++;
+ return s;
+}
+
+int CGE2Engine::takeEnum(const char **tab, const char *text) {
+ if (text) {
+ for (const char **e = tab; *e; e++) {
+ if (scumm_stricmp(text, *e) == 0)
+ return e - tab;
+ }
+ }
+ return -1;
+}
+
+ID CGE2Engine::ident(const char *s) {
+ return ID(takeEnum(EncryptedStream::kIdTab, s));
+}
+
+bool CGE2Engine::testBool(char *s) {
+ return number(s) != 0;
+}
+
+void CGE2Engine::badLab(const char *fn) {
+ error("Misplaced label in %s!", fn);
+}
+
+Sprite *CGE2Engine::loadSprite(const char *fname, int ref, int scene, V3D &pos) {
+ int shpcnt = 0;
+ int seqcnt = 0;
+ int cnt[kActions];
+
+ for (int i = 0; i < kActions; i++)
+ cnt[i] = 0;
+
+ ID section = kIdPhase;
+ bool frnt = true;
+ bool east = false;
+ bool port = false;
+ bool tran = false;
+ Hero *h;
+ ID id;
+
+ char tmpStr[kLineMax + 1];
+ mergeExt(tmpStr, fname, kSprExt);
+
+ if (_resman->exist(tmpStr)) { // sprite description file exist
+ EncryptedStream sprf(this, tmpStr);
+ if (sprf.err())
+ error("Bad SPR [%s]", tmpStr);
+
+ int label = kNoByte;
+ Common::String line;
+
+ for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()){
+ if (line.empty())
+ continue;
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+
+ char *p = token(tmpStr);
+ if (*p == '@') {
+ if (label != kNoByte)
+ badLab(fname);
+ label = atoi(p + 1);
+ continue;
+ }
+
+ id = ident(p);
+ switch (id) {
+ case kIdName: // will be taken in Expand routine
+ if (label != kNoByte)
+ badLab(fname);
+ break;
+ case kIdType:
+ if (label != kNoByte)
+ badLab(fname);
+ break;
+ case kIdNear:
+ case kIdMTake:
+ case kIdFTake:
+ case kIdPhase:
+ case kIdSeq:
+ if (label != kNoByte)
+ badLab(fname);
+ section = id;
+ break;
+ case kIdFront:
+ if (label != kNoByte)
+ badLab(fname);
+ p = token(nullptr);
+ frnt = testBool(p);
+ break;
+ case kIdEast:
+ if (label != kNoByte)
+ badLab(fname);
+ p = token(nullptr);
+ east = testBool(p);
+ break;
+ case kIdPortable:
+ if (label != kNoByte)
+ badLab(fname);
+ p = token(nullptr);
+ port = testBool(p);
+ break;
+ case kIdTransparent:
+ if (label != kNoByte)
+ badLab(fname);
+ p = token(nullptr);
+ tran = testBool(p);
+ break;
+ default:
+ if (id >= kIdNear)
+ break;
+ switch (section) {
+ case kIdNear:
+ case kIdMTake:
+ case kIdFTake:
+ if (_commandHandler->getComId(p) >= 0)
+ ++cnt[section];
+ else
+ error("Bad line %d [%s]", sprf.getLineCount(), tmpStr);
+ break;
+ case kIdPhase:
+ if (label != kNoByte)
+ badLab(fname);
+ ++shpcnt;
+ break;
+ case kIdSeq:
+ if (label != kNoByte)
+ badLab(fname);
+ ++seqcnt;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ label = kNoByte;
+ }
+
+ if (!shpcnt)
+ error("No shapes - %s", fname);
+ } else // No sprite description: mono-shaped sprite with only .BMP file.
+ ++shpcnt;
+
+ // Make sprite of chosen type:
+ Sprite *sprite = nullptr;
+ char c = *fname | 0x20;
+ if (c >= 'a' && c <= 'z' && fname[1] == '0' && fname[2] == '\0') {
+ h = new Hero(this);
+ h->gotoxyz(pos);
+ sprite = h;
+ } else {
+ sprite = new Sprite(this);
+ sprite->gotoxyz(pos);
+ }
+
+ if (sprite) {
+ sprite->_ref = ref;
+ sprite->_scene = scene;
+
+ sprite->_flags._frnt = frnt;
+ sprite->_flags._east = east;
+ sprite->_flags._port = port;
+ sprite->_flags._tran = tran;
+ sprite->_flags._kill = true;
+
+ // Extract the filename, without the extension
+ Common::strlcpy(sprite->_file, fname, sizeof(sprite->_file));
+ char *p = strchr(sprite->_file, '.');
+ if (p)
+ *p = '\0';
+
+ sprite->_shpCnt = shpcnt;
+ sprite->_seqCnt = seqcnt;
+
+ for (int i = 0; i < kActions; i++)
+ sprite->_actionCtrl[i]._cnt = cnt[i];
+ }
+
+ return sprite;
+}
+
+void CGE2Engine::loadScript(const char *fname, bool onlyToolbar) {
+ EncryptedStream scrf(this, fname);
+
+ if (scrf.err())
+ return;
+
+ bool ok = true;
+ int lcnt = 0;
+
+ char tmpStr[kLineMax + 1];
+ Common::String line;
+
+ for (line = scrf.readLine(); !scrf.eos(); line = scrf.readLine()) {
+ if (line.empty())
+ continue;
+
+ lcnt++;
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+
+ ok = false; // not OK if break
+
+ V3D P;
+
+ // sprite ident number
+ int SpI = number(tmpStr);
+
+ if (onlyToolbar && SpI >= 141)
+ return;
+
+ // sprite file name
+ char *SpN;
+ if ((SpN = token(nullptr)) == nullptr)
+ break;
+
+ // sprite scene
+ int SpA = number(nullptr);
+
+ // sprite column
+ P._x = number(nullptr);
+
+ // sprite row
+ P._y = number(nullptr);
+
+ // sprite Z pos
+ P._z = number(nullptr);
+
+ // sprite life
+ bool BkG = number(nullptr) == 0;
+
+ ok = true; // no break: OK
+
+ Sprite *sprite = loadSprite(SpN, SpI, SpA, P);
+ if (sprite) {
+ if (BkG)
+ sprite->_flags._back = true;
+
+ int n = _spare->count();
+ if (_spare->locate(sprite->_ref) == nullptr)
+ _spare->dispose(sprite);
+ else
+ delete sprite;
+
+ if (_spare->count() == n)
+ error("Duplicate reference! %s", SpN);
+ }
+ }
+
+ if (!ok)
+ error("Bad INI line %d [%s]", scrf.getLineCount(), fname);
+}
+
+void CGE2Engine::movie(const char *ext) {
+ assert(ext);
+
+ if (_quitFlag)
+ return;
+
+ char fn[12];
+ snprintf(fn, 12, "CGE%s", ext);
+
+ if (_resman->exist(fn)) {
+ int now = _now;
+ _now = atoi(ext + 2);
+ loadScript(fn);
+ sceneUp(_now);
+ _keyboard->setClient(_sys);
+
+ while (!_commandHandler->idle() && !_quitFlag)
+ mainLoop();
+
+ _keyboard->setClient(nullptr);
+ _commandHandler->addCommand(kCmdClear, -1, 0, nullptr);
+ _commandHandlerTurbo->addCommand(kCmdClear, -1, 0, nullptr);
+ _spare->clear();
+ _vga->_showQ->clear();
+ _now = now;
+ }
+}
+
+void CGE2Engine::sceneUp(int cav) {
+ _now = cav;
+ int bakRef = _now << 8;
+ if (_music)
+ _midiPlayer->loadMidi(bakRef);
+ showBak(bakRef);
+ *_eye = *(_eyeTab[_now]);
+ _mouseTop = V2D(this, V3D(0, 1, kScrDepth)).y;
+ _map->load(_now);
+ _spare->takeScene(_now);
+ openPocket();
+
+ for (int i = 0; i < 2; i++) {
+ Hero *h = _heroTab[i]->_ptr;
+ if (h && h->_scene == _now) {
+ V2D p = *_heroTab[i]->_posTab[_now];
+ h->gotoxyz(V3D(p.x, 0, p.y));
+ h->clrHide();
+ _vga->_showQ->insert(h);
+ h->park();
+ h->setCurrent();
+ h->setContact();
+ }
+ }
+
+ _sound->stop();
+ _fx->clear();
+
+ selectPocket(-1);
+ _infoLine->setText(nullptr);
+ busy(false);
+
+ if (!_dark)
+ _vga->sunset();
+
+ _vga->show();
+ _vga->copyPage(1, 0);
+ _vga->show();
+ _vga->sunrise(_vga->_sysPal);
+
+ _dark = false;
+
+ if (_gamePhase == kPhaseInGame)
+ _mouse->on();
+
+ feedSnail(_vga->_showQ->locate(bakRef + 255), kNear, _heroTab[_sex]->_ptr);
+}
+
+void CGE2Engine::sceneDown() {
+ busy(true);
+ _soundStat._wait = nullptr; // unlock snail
+ Sprite *spr = _vga->_showQ->locate((_now << 8) | 254);
+
+ if (spr)
+ feedSnail(spr, kNear, _heroTab[_sex]->_ptr);
+
+ while (!(_commandHandler->idle() && _commandHandlerTurbo->idle())) {
+ _commandHandlerTurbo->runCommand();
+ _commandHandler->runCommand();
+ }
+
+ closePocket();
+ for (int i = 0; i < 2; i++)
+ _spare->update(_vga->_showQ->remove(_heroTab[i]->_ptr));
+ _spare->dispose();
+}
+
+void CGE2Engine::switchScene(int scene) {
+ if (scene == _now)
+ return;
+
+ _req = scene;
+ storeHeroPos();
+ *(_eyeTab[_now]) = *_eye;
+
+ if (scene < 0)
+ _commandHandler->addCallback(kCmdExec, -1, 0, kQGame); // quit game
+ else {
+ if (_heroTab[_sex]->_ptr->_scene == _now) {
+ _heroTab[_sex]->_ptr->setScene(scene);
+ if (_heroTab[!_sex]->_ptr->_scene == _now)
+ _heroTab[!_sex]->_ptr->setScene(scene);
+ }
+ _mouse->off();
+ if (_heroTab[_sex]->_ptr)
+ _heroTab[_sex]->_ptr->park();
+ killText();
+ _commandHandler->addCallback(kCmdExec, -1, 0, kXScene); // switch scene
+ }
+}
+
+void CGE2Engine::storeHeroPos() {
+ for (int i = 0; i < 2; i++) {
+ Hero *h = _heroTab[i]->_ptr;
+ if (h->_scene == _now) {
+ delete _heroTab[i]->_posTab[_now];
+ V2D *temp = new V2D(this, h->_pos3D._x.trunc(), h->_pos3D._z.trunc());
+ _heroTab[i]->_posTab[_now] = temp;
+ }
+ }
+}
+
+void CGE2Engine::showBak(int ref) {
+ Sprite *spr = _spare->locate(ref);
+ if (spr != nullptr) {
+ _bitmapPalette = _vga->_sysPal;
+ spr->expand();
+ _bitmapPalette = nullptr;
+ spr->show(2);
+ _vga->copyPage(1, 2);
+ }
+}
+
+void CGE2Engine::mainLoop() {
+ if (_gamePhase == kPhaseInGame)
+ checkSounds();
+
+ _vga->show();
+ _commandHandlerTurbo->runCommand();
+ _commandHandler->runCommand();
+
+ // Handle a delay between game frames
+ handleFrame();
+
+ // Handle any pending events
+ _eventManager->poll();
+
+ // Check shouldQuit()
+ _quitFlag = shouldQuit();
+}
+
+void CGE2Engine::checkSounds() {
+ checkMute();
+ _sound->checkSoundHandles();
+ checkVolumeSwitches();
+ _midiPlayer->syncVolume();
+ syncSoundSettings();
+}
+
+void CGE2Engine::handleFrame() {
+ // Game frame delay
+ uint32 millis = g_system->getMillis();
+ while (!_quitFlag && (millis < (_lastFrame + kGameFrameDelay))) {
+ // Handle any pending events
+ _eventManager->poll();
+
+ if (millis >= (_lastTick + kGameTickDelay)) {
+ // Dispatch the tick to any active objects
+ tick();
+ _lastTick = millis;
+ }
+
+ // Slight delay
+ g_system->delayMillis(5);
+ millis = g_system->getMillis();
+ }
+ _lastFrame = millis;
+
+ if (millis >= (_lastTick + kGameTickDelay)) {
+ // Dispatch the tick to any active objects
+ tick();
+ _lastTick = millis;
+ }
+}
+
+Sprite *CGE2Engine::locate(int ref) {
+ _taken = false;
+ Sprite *spr = _vga->_showQ->locate(ref);
+ if (!spr) {
+ spr = _spare->locate(ref);
+ if (spr)
+ _taken = true;
+ }
+ return spr;
+}
+
+bool CGE2Engine::isHero(Sprite *spr) {
+ return spr && spr->_ref / 10 == 14;
+}
+
+void CGE2Engine::tick() {
+ // system pseudo-sprite
+ if (_sys && _sys->_time && (--_sys->_time == 0))
+ _sys->tick();
+
+ for (Sprite *spr = _vga->_showQ->first(); spr; spr = spr->_next) {
+ if (spr->_time && (--spr->_time == 0))
+ spr->tick();
+
+ if (_waitRef && (_waitRef == spr->_ref) && spr->seqTest(_waitSeq))
+ _waitRef = 0;
+ }
+
+ _mouse->tick();
+}
+
+void CGE2Engine::busy(bool on) {
+ if (on) {
+ _spriteNotify = _midiNotify = &CGE2::CGE2Engine::busyStep;
+ busyStep();
+ } else {
+ if (_busyPtr)
+ _busyPtr->step(0);
+ _spriteNotify = _midiNotify = nullptr;
+ }
+}
+
+void CGE2Engine::busyStep() {
+ if (_busyPtr) {
+ _busyPtr->step((_busyPtr->_seqPtr) ? -1 : 1);
+ _busyPtr->show(0);
+ }
+}
+
+void CGE2Engine::runGame() {
+ if (_quitFlag)
+ return;
+
+ loadUser();
+ sceneUp(_now);
+ initToolbar();
+
+ // main loop
+ while (!_endGame && !_quitFlag)
+ mainLoop();
+
+ // If leaving the game (close window, return to launcher, etc.
+ // - except finishing the game), explicitly save it's state:
+ if (!_endGame && canSaveGameStateCurrently())
+ qGame();
+
+ _keyboard->setClient(nullptr);
+ _commandHandler->addCommand(kCmdClear, -1, 0, nullptr);
+ _commandHandlerTurbo->addCommand(kCmdClear, -1, 0, nullptr);
+ _mouse->off();
+}
+
+void CGE2Engine::loadUser() {
+ loadPos();
+
+ if (_startGameSlot != -1)
+ loadGame(_startGameSlot);
+ else {
+ loadScript("CGE.INI");
+ loadHeroes();
+ }
+}
+
+void CGE2Engine::loadHeroes() { // Original name: loadGame()
+ // load sprites & pocket
+
+ Sprite *s;
+ Hero *h = nullptr;
+
+ // initialize Andzia/Anna
+ s = _spare->take(142);
+ if (s) {
+ h = new Hero(this);
+ *(Sprite*)h = *s;
+ delete s;
+ h->expand();
+ _spare->update(h);
+ }
+ _heroTab[0]->_ptr = h;
+ s = _spare->locate(152);
+ _vga->_showQ->insert(s);
+ _heroTab[0]->_face = s;
+
+ // initialize Wacek/Vincent
+ s = _spare->take(141);
+ if (s) {
+ h = new Hero(this);
+ *(Sprite*)h = *s;
+ delete s;
+ h->expand();
+ _spare->update(h);
+ }
+ _heroTab[1]->_ptr = h;
+ s = _spare->locate(151);
+ _vga->_showQ->insert(s);
+ _heroTab[1]->_face = s;
+
+ //--- start!
+ switchHero(_sex);
+}
+
+void CGE2Engine::loadPos() {
+ if (_resman->exist("CGE.HXY")) {
+ for (int cav = 0; cav < kSceneMax; cav++)
+ _heroTab[1]->_posTab[cav] = new V2D(this, 180, 10);
+
+ EncryptedStream file(this, "CGE.HXY");
+
+ for (int cav = 0; cav < kSceneMax; cav++) {
+ _heroTab[0]->_posTab[cav] = new V2D(this);
+ _heroTab[0]->_posTab[cav]->x = file.readSint16LE();
+ _heroTab[0]->_posTab[cav]->y = file.readSint16LE();
+ }
+
+ for (int cav = 0; cav < 41; cav++) { // (564 - 400) / 4 = 41
+ _heroTab[1]->_posTab[cav]->x = file.readSint16LE();
+ _heroTab[1]->_posTab[cav]->y = file.readSint16LE();
+ }
+ } else
+ error("Missing file: CGE.HXY");
+}
+
+void CGE2Engine::loadTab() {
+ setEye(_text->getText(240));
+ for (int i = 0; i < kSceneMax; i++)
+ *(_eyeTab[i]) = *_eye;
+
+ if (_resman->exist(kTabName)) {
+ EncryptedStream f(this, kTabName);
+
+ for (int i = 0; i < kSceneMax; i++) {
+ uint32 v = f.readUint32LE();
+ _eyeTab[i]->_x = FXP(v >> 8, static_cast<int>((int8)(v & 0xff)));
+
+ v = f.readUint32LE();
+ _eyeTab[i]->_y = FXP(v >> 8, static_cast<int>((int8)(v & 0xff)));
+
+ v = f.readUint32LE();
+ _eyeTab[i]->_z = FXP(v >> 8, static_cast<int>((int8)(v & 0xff)));
+ }
+ }
+}
+
+void CGE2Engine::cge2_main() {
+ loadTab();
+
+ if (_startGameSlot != -1) {
+ // Starting up a savegame from the launcher
+ runGame();
+ return;
+ }
+
+ if (showTitle("WELCOME")) {
+ movie(kIntroExt);
+
+ if (_text->getText(255) != nullptr) {
+ runGame();
+ _gamePhase = kPhaseOver;
+ }
+
+ _vga->sunset();
+ } else
+ _vga->sunset();
+}
+
+char *CGE2Engine::mergeExt(char *buf, const char *name, const char *ext) {
+ strcpy(buf, name);
+ char *dot = strrchr(buf, '.');
+ if (!dot)
+ strcat(buf, ext);
+
+ return buf;
+}
+
+void CGE2Engine::setEye(const V3D &e) {
+ *_eye = e;
+}
+
+void CGE2Engine::setEye(const V2D& e2, int z) {
+ _eye->_x = e2.x;
+ _eye->_y = e2.y;
+ _eye->_z = z;
+}
+
+void CGE2Engine::setEye(const char *s) {
+ char *tempStr = new char[strlen(s) + 1];
+ strcpy(tempStr, s);
+ _eye->_x = atoi(token(tempStr));
+ _eye->_y = atoi(token(nullptr));
+ _eye->_z = atoi(token(nullptr));
+ delete[] tempStr;
+}
+
+int CGE2Engine::newRandom(int range) {
+ if (!range)
+ return 0;
+
+ return _randomSource.getRandomNumber(range - 1);
+}
+
+bool CGE2Engine::showTitle(const char *name) {
+ if (_quitFlag)
+ return false;
+
+ _bitmapPalette = _vga->_sysPal;
+ BitmapPtr LB = new Bitmap[1];
+ LB[0] = Bitmap(this, name);
+ _bitmapPalette = nullptr;
+
+ Sprite D(this, LB, 1);
+ D._flags._kill = true;
+ D.gotoxyz(kScrWidth >> 1, -(kPanHeight >> 1));
+
+ _vga->sunset();
+ D.show(2);
+ _vga->copyPage(1, 2);
+ _vga->copyPage(0, 1);
+ _vga->sunrise(_vga->_sysPal);
+ _vga->update();
+
+ g_system->delayMillis(2500);
+
+ return true;
+}
+
+void CGE2Engine::killText() {
+ if (!_talk)
+ return;
+
+ _commandHandlerTurbo->addCommand(kCmdKill, -1, 0, _talk);
+ _talk = nullptr;
+}
+
+void CGE2Engine::switchHero(int sex) {
+ if (sex != _sex) {
+ int scene = _heroTab[sex]->_ptr->_scene;
+ if (_sys->_blinkSprite) {
+ _sys->_blinkSprite->_flags._hide = false;
+ _sys->_blinkSprite = nullptr;
+ }
+
+ if (scene >= 0) {
+ _commandHandler->addCommand(kCmdSeq, -1, 2, _heroTab[_sex]->_face);
+ _sex ^= 1;
+ switchScene(scene);
+ }
+ }
+ Sprite *face = _heroTab[_sex]->_face;
+ if (face->_seqPtr == 0)
+ _commandHandler->addCommand(kCmdSeq, -1, 1, face);
+}
+
+void Sprite::touch(uint16 mask, V2D pos, Common::KeyCode keyCode) {
+ if ((mask & kEventAttn) != 0)
+ return;
+
+ if (_vm->_gamePhase == kPhaseInGame)
+ _vm->_infoLine->setText(name());
+
+ if (_ref < 0)
+ return; // cannot access system sprites
+
+ if (_ref / 10 == 12) {
+ _vm->optionTouch(_ref % 10, mask);
+ return;
+ }
+
+ if ((mask & kMouseLeftUp) && _vm->_commandHandler->idle()) {
+ if (_vm->isHero(this) && !_vm->_sys->_blinkSprite) {
+ _vm->switchHero((this == _vm->_heroTab[1]->_ptr) ? 1 : 0);
+ } else if (_flags._kept) { // sprite in pocket
+ for (int sex = 0; sex < 2; ++sex) {
+ for (int p = 0; p < kPocketMax; ++p) {
+ if (_vm->_heroTab[sex]->_pocket[p] == this) {
+ _vm->switchHero(sex);
+ if (_vm->_sex == sex) {
+ if (_vm->_sys->_blinkSprite)
+ _vm->_sys->_blinkSprite->_flags._hide = false;
+
+ if (_vm->_sys->_blinkSprite == this)
+ _vm->_sys->_blinkSprite = nullptr;
+ else
+ _vm->_sys->_blinkSprite = this;
+ }
+ }
+ }
+ }
+ } else { // sprite NOT in pocket
+ Hero *h = _vm->_heroTab[_vm->_sex]->_ptr;
+ if (!_vm->_talk) {
+ // the "+3" is a hack used to work around a script issue in scene 5
+ if ((_ref & 0xFF) < 200 && h->distance(this) > (h->_maxDist << 1) + 3)
+ h->walkTo(this);
+ else if (_vm->_sys->_blinkSprite) {
+ if (works(_vm->_sys->_blinkSprite)) {
+ _vm->feedSnail(_vm->_sys->_blinkSprite, (_vm->_sex) ? kMTake : kFTake, _vm->_heroTab[_vm->_sex]->_ptr);
+ _vm->_sys->_blinkSprite->_flags._hide = false;
+ _vm->_sys->_blinkSprite = nullptr;
+ } else
+ _vm->offUse();
+
+ _vm->selectPocket(-1);
+ // else, no pocket sprite selected
+ } else if (_flags._port) { // portable
+ if (_vm->findActivePocket(-1) < 0)
+ _vm->pocFul();
+ else {
+ _vm->_commandHandler->addCommand(kCmdReach, -2, _ref, nullptr);
+ _vm->_commandHandler->addCommand(kCmdKeep, -1, -1, this);
+ _flags._port = false;
+ }
+ } else { // non-portable
+ Action a = h->action();
+ if (_actionCtrl[a]._cnt) {
+ CommandHandler::Command *cmdList = snList(a);
+ if (cmdList[_actionCtrl[a]._ptr]._commandType == kCmdNext)
+ _vm->offUse();
+ else
+ _vm->feedSnail(this, a, h);
+ } else
+ _vm->offUse();
+ }
+ }
+ }
+ }
+}
+
+void CGE2Engine::keyClick() {
+ _commandHandlerTurbo->addCommand(kCmdSound, -1, 5, nullptr);
+}
+
+void CGE2Engine::offUse() {
+ int seq = 0;
+ int offUseCount = atoi(_text->getText(kOffUseCount));
+
+ // This fixes the issue of empty speech bubbles in the original.
+ // Now we only let this cycle pass if it randoms a valid value for getText().
+ int txt = 0;
+ do {
+ txt = kOffUseText + _sex * offUseCount + newRandom(offUseCount);
+ } while (_text->getText(txt) == nullptr);
+
+ Hero *h = _heroTab[_sex]->_ptr;
+ h->park();
+ _commandHandler->addCommand(kCmdWait, -1, -1, h);
+ _commandHandler->addCommand(kCmdSeq, -1, seq, h);
+ if (!_sayVox)
+ _commandHandler->addCommand(kCmdSound, -1, 6 + _sex, h);
+ _commandHandler->addCommand(kCmdWait, -1, -1, h);
+ _commandHandler->addCommand(kCmdSay, -1, txt, h);
+}
+
+Sprite *CGE2Engine::spriteAt(V2D pos) {
+ Sprite *spr;
+
+ for (spr = _vga->_showQ->last(); spr; spr = spr->_prev) {
+ if (!spr->_flags._hide && !spr->_flags._tran && (spr->getShp()->solidAt(pos - spr->_pos2D)))
+ break;
+ }
+
+ return spr;
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/cge2_main.h b/engines/cge2/cge2_main.h
new file mode 100644
index 0000000000..88cca1cc1e
--- /dev/null
+++ b/engines/cge2/cge2_main.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_MAIN_H
+#define CGE2_MAIN_H
+
+#include "cge2/events.h"
+
+namespace CGE2 {
+
+#define kShowScummVMVersion 15
+
+class System : public Sprite {
+public:
+ int _blinkCounter;
+ Sprite *_blinkSprite;
+
+ System(CGE2Engine *vm);
+
+ virtual void touch(uint16 mask, V2D pos, Common::KeyCode keyCode);
+ void tick();
+private:
+ CGE2Engine *_vm;
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_MAIN_H
diff --git a/engines/cge2/configure.engine b/engines/cge2/configure.engine
new file mode 100644
index 0000000000..6ccbfee088
--- /dev/null
+++ b/engines/cge2/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine cge2 "CGE2" no
diff --git a/engines/cge2/console.cpp b/engines/cge2/console.cpp
new file mode 100644
index 0000000000..c67c7ab788
--- /dev/null
+++ b/engines/cge2/console.cpp
@@ -0,0 +1,33 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 "cge2/console.h"
+
+namespace CGE2 {
+
+CGE2Console::CGE2Console(CGE2Engine *vm) : GUI::Debugger() {
+}
+
+CGE2Console::~CGE2Console() {
+}
+
+} // End of namespace CGE
diff --git a/engines/cge2/console.h b/engines/cge2/console.h
new file mode 100644
index 0000000000..15956bf728
--- /dev/null
+++ b/engines/cge2/console.h
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 CGE2_CONSOLE_H
+#define CGE2_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace CGE2 {
+
+class CGE2Engine;
+
+class CGE2Console : public GUI::Debugger {
+public:
+ CGE2Console(CGE2Engine *vm);
+ virtual ~CGE2Console();
+};
+
+} // End of namespace CGE
+
+#endif // CGE2_CONSOLE_H
diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp
new file mode 100644
index 0000000000..c05ce70c3d
--- /dev/null
+++ b/engines/cge2/detection.cpp
@@ -0,0 +1,270 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/cge2.h"
+#include "cge2/fileio.h"
+#include "engines/advancedDetector.h"
+#include "common/translation.h"
+#include "graphics/surface.h"
+
+namespace CGE2 {
+
+#define GAMEOPTION_COLOR_BLIND_DEFAULT_OFF GUIO_GAMEOPTIONS1
+
+static const PlainGameDescriptor CGE2Games[] = {
+ { "sfinx", "Sfinx" },
+ { 0, 0 }
+};
+
+static const ADGameDescription gameDescriptions[] = {
+ {
+ "sfinx", "Freeware",
+ {
+ { "vol.cat", 0, "21197b287d397c53261b6616bf0dd880", 129024 },
+ { "vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844 },
+ AD_LISTEND
+ },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ },
+
+ {
+ "sfinx", "Freeware v1.0",
+ {
+ {"vol.cat", 0, "aa402aed24a72c53a4d1211c456b79dd", 129024},
+ {"vol.dat", 0, "5966ac26d91d664714349669f9dd09b5", 34180164},
+ AD_LISTEND
+ },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ },
+
+ {
+ "sfinx", "Freeware v0.3",
+ {
+ {"vol.cat", 0, "f158e469dccbebc5a632eb848df89779", 129024},
+ {"vol.dat", 0, "d40a6b4ae173d6930be54ba56bee15d5", 34183430},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ },
+
+ AD_TABLE_END_MARKER
+};
+
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_COLOR_BLIND_DEFAULT_OFF,
+ {
+ _s("Color Blind Mode"),
+ _s("Enable Color Blind Mode by default"),
+ "enable_color_blind",
+ false
+ }
+ },
+
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
+class CGE2MetaEngine : public AdvancedMetaEngine {
+public:
+ CGE2MetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), CGE2Games, optionsList) {
+ _singleid = "sfinx";
+ }
+
+ virtual const char *getName() const {
+ return "CGE2";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Sfinx (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon";
+ }
+
+ virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual int getMaximumSaveSlot() const;
+ virtual SaveStateList listSaves(const char *target) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+ virtual void removeSaveState(const char *target, int slot) const;
+};
+
+static const ADFileBasedFallback fileBasedFallback[] = {
+ { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } },
+ { 0, { 0 } }
+};
+
+static ADGameDescription s_fallbackDesc = {
+ "Sfinx",
+ "Unknown version",
+ AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
+ Common::UNK_LANG,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+};
+
+// This fallback detection looks identical to the one used for CGE. In fact, the difference resides
+// in the ResourceManager which handles a different archive format. The rest of the detection is identical.
+const ADGameDescription *CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADFilePropertiesMap filesProps;
+
+ const ADGameDescription *game;
+ game = detectGameFilebased(allFiles, fslist, CGE2::fileBasedFallback, &filesProps);
+
+ if (!game)
+ return 0;
+
+ SearchMan.clear();
+ SearchMan.addDirectory(fslist.begin()->getParent().getPath(), fslist.begin()->getParent());
+ ResourceManager *resman;
+ resman = new ResourceManager();
+ bool result = resman->exist("CGE.SAY");
+ delete resman;
+
+ if (!result)
+ return 0;
+
+ reportUnknown(fslist.begin()->getParent(), filesProps);
+ return &s_fallbackDesc;
+}
+
+bool CGE2MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ if (desc)
+ *engine = new CGE2::CGE2Engine(syst, desc);
+
+ return desc != 0;
+}
+
+bool CGE2MetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup);
+}
+
+int CGE2MetaEngine::getMaximumSaveSlot() const {
+ return 99;
+}
+
+SaveStateList CGE2MetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String pattern = target;
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(filename->c_str() + filename->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 99) {
+
+ Common::InSaveFile *file = saveFileMan->openForLoading(*filename);
+ if (file) {
+ CGE2::SavegameHeader header;
+
+ // Check to see if it's a ScummVM savegame or not
+ char buffer[kSavegameStrSize + 1];
+ file->read(buffer, kSavegameStrSize + 1);
+
+ if (!strncmp(buffer, kSavegameStr, kSavegameStrSize + 1)) {
+ // Valid savegame
+ if (CGE2::CGE2Engine::readSavegameHeader(file, header)) {
+ saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
+ if (header.thumbnail) {
+ header.thumbnail->free();
+ delete header.thumbnail;
+ }
+ }
+ } else {
+ // Must be an original format savegame
+ saveList.push_back(SaveStateDescriptor(slotNum, "Unknown"));
+ }
+
+ delete file;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+SaveStateDescriptor CGE2MetaEngine::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) {
+ CGE2::SavegameHeader header;
+
+ // Check to see if it's a ScummVM savegame or not
+ char buffer[kSavegameStrSize + 1];
+ f->read(buffer, kSavegameStrSize + 1);
+
+ bool hasHeader = !strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) &&
+ CGE2::CGE2Engine::readSavegameHeader(f, header);
+ delete f;
+
+ if (!hasHeader) {
+ // Original savegame perhaps?
+ SaveStateDescriptor desc(slot, "Unknown");
+ return desc;
+ } else {
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header.saveName);
+ desc.setThumbnail(header.thumbnail);
+ desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
+ desc.setSaveTime(header.saveHour, header.saveMinutes);
+
+ // Slot 0 is used for the 'automatic save on exit' save in Soltys, thus
+ // we prevent it from being deleted or overwritten by accident.
+ desc.setDeletableFlag(slot != 0);
+ desc.setWriteProtectedFlag(slot == 0);
+
+ return desc;
+ }
+ }
+
+ return SaveStateDescriptor();
+}
+
+void CGE2MetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+
+} // End of namespace CGE2
+
+#if PLUGIN_ENABLED_DYNAMIC(CGE2)
+ REGISTER_PLUGIN_DYNAMIC(CGE2, PLUGIN_TYPE_ENGINE, CGE2::CGE2MetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(CGE2, PLUGIN_TYPE_ENGINE, CGE2::CGE2MetaEngine);
+#endif
diff --git a/engines/cge2/events.cpp b/engines/cge2/events.cpp
new file mode 100644
index 0000000000..ed1ec66bb1
--- /dev/null
+++ b/engines/cge2/events.cpp
@@ -0,0 +1,293 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "gui/saveload.h"
+#include "gui/about.h"
+#include "gui/message.h"
+#include "common/config-manager.h"
+#include "common/events.h"
+#include "engines/advancedDetector.h"
+#include "cge2/events.h"
+#include "cge2/text.h"
+#include "cge2/cge2_main.h"
+
+namespace CGE2 {
+
+/*----------------- KEYBOARD interface -----------------*/
+
+Keyboard::Keyboard(CGE2Engine *vm) : _client(nullptr), _vm(vm) {
+}
+
+Keyboard::~Keyboard() {
+}
+
+Sprite *Keyboard::setClient(Sprite *spr) {
+ SWAP(_client, spr);
+ return spr;
+}
+
+bool Keyboard::getKey(Common::Event &event) {
+ Common::KeyCode keycode = event.kbd.keycode;
+
+ switch (keycode) {
+ case Common::KEYCODE_F1:
+ if (event.type == Common::EVENT_KEYUP)
+ return false;
+ // Display ScummVM version and translation strings
+ for (int i = 0; i < 3; i++)
+ _vm->_commandHandler->addCommand(kCmdInf, 1, kShowScummVMVersion + i, NULL);
+ return false;
+ case Common::KEYCODE_F5:
+ if (_vm->canSaveGameStateCurrently()) {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
+ int16 savegameId = dialog->runModalWithCurrentTarget();
+ Common::String savegameDescription = dialog->getResultString();
+ delete dialog;
+
+ if (savegameId != -1)
+ _vm->saveGameState(savegameId, savegameDescription);
+ }
+ return false;
+ case Common::KEYCODE_F7:
+ if (_vm->canLoadGameStateCurrently()) {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore", false);
+ int16 savegameId = dialog->runModalWithCurrentTarget();
+ delete dialog;
+
+ if (savegameId != -1)
+ _vm->loadGameState(savegameId);
+ }
+ return false;
+ case Common::KEYCODE_d:
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ // Start the debugger
+ _vm->getDebugger()->attach();
+ _vm->getDebugger()->onFrame();
+ return false;
+ }
+ break;
+ case Common::KEYCODE_x:
+ if (event.kbd.flags & Common::KBD_ALT) {
+ _vm->quit();
+ return false;
+ }
+ break;
+ case Common::KEYCODE_F10:
+ if (_vm->_commandHandler->idle())
+ _vm->switchScene(-1); // Exits the game.
+ return false;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Keyboard::newKeyboard(Common::Event &event) {
+ if (!getKey(event))
+ return;
+
+ if ((event.type == Common::EVENT_KEYDOWN) && _client) {
+ CGE2Event &evt = _vm->_eventManager->getNextEvent();
+ evt._x = 0;
+ evt._y = 0;
+ evt._keyCode = event.kbd.keycode; // Keycode
+ evt._mask = kEventKeyb; // Event mask
+ evt._spritePtr = _client; // Sprite pointer
+ }
+}
+
+/*----------------- MOUSE interface -----------------*/
+
+Mouse::Mouse(CGE2Engine *vm) : Sprite(vm), _busy(nullptr), _hold(nullptr), _hx(0), _point(vm), _vm(vm) {
+ _hold = nullptr;
+ _hx = 0;
+ _hy = 0;
+ _exist = true;
+ _buttons = 0;
+ _busy = nullptr;
+ _active = false;
+ _flags._kill = false;
+
+ setSeq(_stdSeq8);
+
+ BitmapPtr MC = new Bitmap[2];
+ MC[0] = Bitmap(_vm, "MOUSE");
+ MC[1] = Bitmap(_vm, "DUMMY");
+ setShapeList(MC, 2);
+
+ step(1);
+ on();
+ off();
+}
+
+Mouse::~Mouse() {
+ off();
+}
+
+void Mouse::on() {
+ if (_seqPtr && _exist) {
+ _active = true;
+ step(0);
+ if (_busy)
+ _busy->step(0);
+ }
+}
+
+void Mouse::off() {
+ if (_seqPtr == 0) {
+ if (_exist)
+ _active = false;
+
+ step(1);
+ if (_busy)
+ _busy->step(1);
+ }
+}
+
+void Mouse::newMouse(Common::Event &event) {
+ if (!_active)
+ return;
+
+ CGE2Event &evt = _vm->_eventManager->getNextEvent();
+ evt._x = event.mouse.x;
+ evt._y = event.mouse.y;
+ evt._keyCode = Common::KEYCODE_INVALID;
+ evt._spritePtr = _vm->spriteAt(V2D(_vm, evt._x, evt._y));
+
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ evt._mask = kMouseRoll;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ evt._mask = kMouseLeftDown;
+ _buttons |= 1;
+ break;
+ case Common::EVENT_LBUTTONUP:
+ evt._mask = kMouseLeftUp;
+ _buttons &= ~1;
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ evt._mask = kMouseRightDown;
+ _buttons |= 2;
+ break;
+ case Common::EVENT_RBUTTONUP:
+ evt._mask = kMouseRightUp;
+ _buttons &= ~2;
+ break;
+ default:
+ break;
+ }
+}
+
+/*----------------- EventManager interface -----------------*/
+
+EventManager::EventManager(CGE2Engine *vm) : _vm(vm) {
+ _eventQueueHead = 0;
+ _eventQueueTail = 0;
+ memset(&_eventQueue, 0, kEventMax * sizeof(CGE2Event));
+ memset(&_event, 0, sizeof(Common::Event));
+}
+
+void EventManager::poll() {
+ while (g_system->getEventManager()->pollEvent(_event)) {
+ _event.mouse.y = kWorldHeight - _event.mouse.y;
+ switch (_event.type) {
+ case Common::EVENT_KEYDOWN:
+ case Common::EVENT_KEYUP:
+ // Handle keyboard events
+ _vm->_keyboard->newKeyboard(_event);
+ handleEvents();
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONDOWN:
+ case Common::EVENT_RBUTTONUP:
+ // Handle mouse events
+ _vm->_mouse->newMouse(_event);
+ handleEvents();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void EventManager::handleEvents() {
+ while (_eventQueueTail != _eventQueueHead) {
+ CGE2Event e = _eventQueue[_eventQueueTail];
+ _vm->_mouse->_point = V2D(_vm, e._x, e._y);
+ if (e._mask) {
+ if (e._mask & kMouseMask) {
+ e._spritePtr = _vm->spriteAt(_vm->_mouse->_point);
+ e._x += (_vm->_mouse->_siz.x >> 1);
+ e._y -= _vm->_mouse->_siz.y;
+ if (_vm->_mouse->_hold && (e._spritePtr != _vm->_mouse->_hold)) {
+ _vm->_mouse->_hold->touch(e._mask | kEventAttn,
+ V2D(_vm, e._x - _vm->_mouse->_hold->_pos2D.x, e._y - _vm->_mouse->_hold->_pos2D.y), e._keyCode);
+ }
+ // update mouse cursor position
+ if (e._mask & kMouseRoll)
+ _vm->_mouse->gotoxyz(V2D(_vm, e._x, e._y));
+ }
+
+ // activate current touched SPRITE
+ if (e._spritePtr) {
+ if (e._mask & kEventKeyb)
+ e._spritePtr->touch(e._mask, _vm->_mouse->_point, e._keyCode);
+ else
+ e._spritePtr->touch(e._mask, _vm->_mouse->_point - e._spritePtr->_pos2D, e._keyCode);
+ } else if (_vm->_sys)
+ _vm->_sys->touch(e._mask, _vm->_mouse->_point, e._keyCode);
+
+ // discard Text if button released
+ if (e._mask & (kMouseLeftUp | kMouseRightUp))
+ _vm->killText();
+ }
+ _eventQueueTail = (_eventQueueTail + 1) % kEventMax;
+ }
+}
+
+void EventManager::clearEvent(Sprite *spr) {
+ if (spr) {
+ for (uint16 e = _eventQueueTail; e != _eventQueueHead; e = (e + 1) % kEventMax) {
+ if (_eventQueue[e]._spritePtr == spr)
+ _eventQueue[e]._mask = 0;
+ }
+ } else
+ _eventQueueTail = _eventQueueHead;
+}
+
+CGE2Event &EventManager::getNextEvent() {
+ CGE2Event &evt = _eventQueue[_eventQueueHead];
+ _eventQueueHead = (_eventQueueHead + 1) % kEventMax;
+
+ return evt;
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/events.h b/engines/cge2/events.h
new file mode 100644
index 0000000000..d1aaca2ded
--- /dev/null
+++ b/engines/cge2/events.h
@@ -0,0 +1,116 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_EVENTS_H
+#define CGE2_EVENTS_H
+
+#include "common/events.h"
+#include "cge2/talk.h"
+#include "cge2/vga13h.h"
+
+namespace CGE2 {
+
+/*----------------- KEYBOARD interface -----------------*/
+
+#define kEventMax 256
+
+enum EventMask {
+ kMouseRoll = 1 << 0,
+ kMouseLeftDown = 1 << 1,
+ kMouseLeftUp = 1 << 2,
+ kMouseRightDown = 1 << 3,
+ kMouseRightUp = 1 << 4,
+ kEventAttn = 1 << 5,
+ kMouseMask = (kMouseRoll | kMouseLeftDown | kMouseLeftUp | kMouseRightDown | kMouseRightUp),
+ kEventKeyb = 1 << 7
+};
+
+class Keyboard {
+private:
+ bool getKey(Common::Event &event);
+ CGE2Engine *_vm;
+public:
+ Sprite *_client;
+
+ void newKeyboard(Common::Event &event);
+ Sprite *setClient(Sprite *spr);
+
+ Keyboard(CGE2Engine *vm);
+ ~Keyboard();
+};
+
+/*----------------- MOUSE interface -----------------*/
+
+struct CGE2Event {
+ uint16 _mask;
+ uint16 _x;
+ uint16 _y;
+ Common::KeyCode _keyCode;
+ Sprite *_spritePtr;
+};
+
+class Mouse : public Sprite {
+public:
+ V2D _point;
+ Sprite *_hold;
+ bool _active;
+ int _hx;
+ int _hy;
+ bool _exist;
+ int _buttons;
+ Sprite *_busy;
+ Mouse(CGE2Engine *vm);
+ ~Mouse();
+ void on();
+ void off();
+ void newMouse(Common::Event &event);
+private:
+ CGE2Engine *_vm;
+};
+
+/*----------------- EventManager interface -----------------*/
+
+class EventManager {
+private:
+ CGE2Engine *_vm;
+ Common::Event _event;
+ CGE2Event _eventQueue[kEventMax];
+ uint16 _eventQueueHead;
+ uint16 _eventQueueTail;
+
+ void handleEvents();
+public:
+ EventManager(CGE2Engine *vm);
+ void poll();
+ void clearEvent(Sprite *spr);
+
+ CGE2Event &getNextEvent();
+};
+
+} // End of namespace CGE
+
+#endif // #define CGE2_EVENTS_H
diff --git a/engines/cge2/fileio.cpp b/engines/cge2/fileio.cpp
new file mode 100644
index 0000000000..acb5bb870f
--- /dev/null
+++ b/engines/cge2/fileio.cpp
@@ -0,0 +1,282 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "common/system.h"
+#include "common/str.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/memstream.h"
+#include "cge2/cge2.h"
+#include "cge2/fileio.h"
+
+namespace CGE2 {
+
+/*-----------------------------------------------------------------------
+ * BtPage
+ *-----------------------------------------------------------------------*/
+void BtPage::readBTree(Common::ReadStream &s) {
+ _header._count = s.readUint16LE();
+ _header._down = s.readUint16LE();
+
+ if (_header._down == kBtValNone) {
+ // Leaf list
+ for (int i = 0; i < kBtLeafCount; ++i) {
+ s.read(_leaf[i]._key, kBtKeySize);
+ _leaf[i]._pos = s.readUint32LE();
+ _leaf[i]._size = s.readUint32LE();
+ }
+ } else {
+ // Root index
+ for (int i = 0; i < kBtInnerCount; ++i) {
+ s.read(_inner[i]._key, kBtKeySize);
+ _inner[i]._down = s.readUint16LE();
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------
+ * ResourceManager
+ *-----------------------------------------------------------------------*/
+ResourceManager::ResourceManager() {
+ _datFile = new Common::File();
+ _datFile->open(kDatName);
+
+ _catFile = new Common::File();
+ _catFile->open(kCatName);
+
+ if (!_datFile->isOpen() || !_catFile->isOpen())
+ error("Unable to open data files");
+
+ for (int i = 0; i < kBtLevel; i++) {
+ _buff[i]._page = new BtPage;
+ _buff[i]._pageNo = kBtValNone;
+ _buff[i]._index = -1;
+ assert(_buff[i]._page != nullptr);
+ }
+}
+
+ResourceManager::~ResourceManager() {
+ _datFile->close();
+ delete _datFile;
+
+ _catFile->close();
+ delete _catFile;
+
+ for (int i = 0; i < kBtLevel; i++)
+ delete _buff[i]._page;
+}
+
+void ResourceManager::xCrypt(byte *buf, uint16 length) {
+ byte *b = buf;
+
+ for (uint16 i = 0; i < length; i++)
+ *b++ ^= kCryptSeed;
+}
+
+bool ResourceManager::seek(int32 offs, int whence) {
+ return _datFile->seek(offs, whence);
+}
+
+uint16 ResourceManager::read(byte *buf, uint16 length) {
+ if (!_datFile->isOpen())
+ return 0;
+
+ uint16 bytesRead = _datFile->read(buf, length);
+ if (!bytesRead)
+ error("Read %s - %d bytes", _datFile->getName(), length);
+ xCrypt(buf, length);
+ return bytesRead;
+}
+
+BtPage *ResourceManager::getPage(int level, uint16 pageId) {
+ if (_buff[level]._pageNo != pageId) {
+ int32 pos = pageId * kBtSize;
+ _buff[level]._pageNo = pageId;
+
+ if (_catFile->size() <= pos)
+ return nullptr;
+
+ // In the original, there was a check verifying if the
+ // purpose was to write a new file. This should only be
+ // to create a new file, thus it was removed.
+ _catFile->seek(pageId * kBtSize, SEEK_SET);
+
+ // Read in the page
+ byte buffer[kBtSize];
+ int bytesRead = catRead(buffer, kBtSize);
+
+ // Unpack it into the page structure
+ Common::MemoryReadStream stream(buffer, bytesRead, DisposeAfterUse::NO);
+ _buff[level]._page->readBTree(stream);
+ _buff[level]._index = -1;
+ }
+ return _buff[level]._page;
+}
+
+BtKeypack *ResourceManager::find(const char *key) {
+ int lev = 0;
+ uint16 nxt = kBtValRoot;
+ while (!_catFile->eos()) {
+ BtPage *pg = getPage(lev, nxt);
+ if (!pg)
+ return nullptr;
+
+ // search
+ if (pg->_header._down != kBtValNone) {
+ int i;
+ for (i = 0; i < pg->_header._count; i++) {
+ // Does this work, or does it have to compare the entire buffer?
+ if (scumm_strnicmp((const char *)key, (const char*)pg->_inner[i]._key, kBtKeySize) < 0)
+ break;
+ }
+ nxt = (i) ? pg->_inner[i - 1]._down : pg->_header._down;
+ _buff[lev]._index = i - 1;
+ lev++;
+ } else {
+ int i;
+ for (i = 0; i < pg->_header._count - 1; i++) {
+ if (scumm_stricmp((const char *)key, (const char *)pg->_leaf[i]._key) <= 0)
+ break;
+ }
+
+ // Hack to work around a mix between 24piram_ and 24pirami
+ if (!strcmp(key, "24piram_.SPR") && (scumm_stricmp((const char *)key, (const char *)pg->_leaf[i]._key) < 0))
+ ++i;
+ //
+
+ _buff[lev]._index = i;
+ return &pg->_leaf[i];
+ }
+ }
+ return nullptr;
+}
+
+bool ResourceManager::exist(const char *name) {
+ BtKeypack *result = find(name);
+ if (!result)
+ return false;
+
+ return scumm_stricmp(result->_key, name) == 0;
+}
+
+uint16 ResourceManager::catRead(byte *buf, uint16 length) {
+ if (!_catFile->isOpen())
+ return 0;
+
+ uint16 bytesRead = _catFile->read(buf, length);
+ if (!bytesRead)
+ error("Read %s - %d bytes", _catFile->getName(), length);
+ xCrypt(buf, length);
+ return bytesRead;
+}
+
+/*-----------------------------------------------------------------------
+ * EncryptedStream
+ *-----------------------------------------------------------------------*/
+EncryptedStream::EncryptedStream(CGE2Engine *vm, const char *name) : _vm(vm), _lineCount(0) {
+ _error = false;
+ BtKeypack *kp = _vm->_resman->find(name);
+ if (scumm_stricmp(kp->_key, name) != 0)
+ _error = true;
+
+ _vm->_resman->seek(kp->_pos);
+ byte *dataBuffer;
+ int bufSize;
+
+ if ((strlen(name) > 4) && (scumm_stricmp(name + strlen(name) - 4, ".SPR") == 0)) {
+ // SPR files have some inconsistencies. Some have extra 0x1A at the end, some others
+ // do not have a carriage return at the end of the last line
+ // Therefore, we remove this ending 0x1A and add extra new lines.
+ // This fixes bug #3537527
+ dataBuffer = (byte *)malloc(kp->_size + 2);
+ _vm->_resman->read(dataBuffer, kp->_size);
+ if (dataBuffer[kp->_size - 1] == 0x1A)
+ dataBuffer[kp->_size - 1] = '\n';
+ dataBuffer[kp->_size] = '\n';
+ dataBuffer[kp->_size + 1] = '\n';
+ bufSize = kp->_size + 2;
+ } else {
+ dataBuffer = (byte *)malloc(kp->_size);
+ _vm->_resman->read(dataBuffer, kp->_size);
+ bufSize = kp->_size;
+ }
+
+ _readStream = new Common::MemoryReadStream(dataBuffer, bufSize, DisposeAfterUse::YES);
+}
+
+uint32 EncryptedStream::read(byte *dataPtr, uint32 dataSize) {
+ return _readStream->read(dataPtr, dataSize);
+}
+
+int16 EncryptedStream::readSint16LE() {
+ return _readStream->readSint16LE();
+}
+
+uint32 EncryptedStream::readUint32LE() {
+ return _readStream->readUint32LE();
+}
+
+bool EncryptedStream::err() {
+ return (_error || _readStream->err());
+}
+
+bool EncryptedStream::eos() {
+ return _readStream->eos();
+}
+
+bool EncryptedStream::seek(int32 offset) {
+ return _readStream->seek(offset);
+}
+
+Common::String EncryptedStream::readLine() {
+ _lineCount++;
+ Common::String line = _readStream->readLine();
+ if (!line.empty() && (line[0] == ';' || line[0] == '.' || line[0] == '*'))
+ line.clear(); // Returns an empty string, if the line is invalid.
+ return line;
+}
+
+int32 EncryptedStream::size() {
+ return _readStream->size();
+}
+
+int32 EncryptedStream::pos() {
+ return _readStream->pos();
+}
+
+EncryptedStream::~EncryptedStream() {
+ delete _readStream;
+}
+
+const char *EncryptedStream::kIdTab[] = {
+ "[near]", "[mtake]", "[ftake]", "[phase]", "[seq]",
+ "Name", "Type", "Front", "East",
+ "Portable", "Transparent",
+ nullptr
+};
+
+} // End of namespace CGE2
diff --git a/engines/cge2/fileio.h b/engines/cge2/fileio.h
new file mode 100644
index 0000000000..e236c73b49
--- /dev/null
+++ b/engines/cge2/fileio.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_FILEIO_H
+#define CGE2_FILEIO_H
+
+#include "common/file.h"
+
+namespace CGE2 {
+
+class CGE2Engine;
+
+#define kBtSize 2048
+#define kBtKeySize 13
+#define kBtLevel 2
+#define kBtInnerCount ((kBtSize - 4 /*sizeof(Header) */) / (kBtKeySize + 2 /*sizeof(Inner) */))
+#define kBtLeafCount ((kBtSize - 4 /*sizeof(Header) */) / (kBtKeySize + 4 + 4 /*sizeof(BtKeypack) */))
+#define kBtValNone 0xFFFF
+#define kBtValRoot 0
+#define kCatName "VOL.CAT"
+#define kDatName "VOL.DAT"
+#define kCryptSeed 0xA5
+
+enum ID {
+ kIdNear, kIdMTake, kIdFTake, kIdPhase, kIdSeq,
+ kIdName, kIdType, kIdFront, kIdEast,
+ kIdPortable, kIdTransparent,
+ kIdNone = -1
+};
+
+struct BtKeypack {
+ char _key[kBtKeySize];
+ uint32 _pos;
+ uint32 _size;
+};
+
+struct Inner {
+ uint8 _key[kBtKeySize];
+ uint16 _down;
+};
+
+struct Header {
+ uint16 _count;
+ uint16 _down;
+};
+
+struct BtPage {
+ Header _header;
+ union {
+ // dummy filler to make proper size of union
+ uint8 _data[kBtSize - 4]; /* 4 is the size of struct Header */
+ // inner version of data: key + word-sized page link
+ Inner _inner[kBtInnerCount];
+ // leaf version of data: key + all user data
+ BtKeypack _leaf[kBtLeafCount];
+ };
+
+ void readBTree(Common::ReadStream &s);
+};
+
+class ResourceManager {
+private:
+ struct {
+ BtPage *_page;
+ uint16 _pageNo;
+ int _index;
+ } _buff[kBtLevel];
+
+ BtPage *getPage(int level, uint16 pageId);
+ uint16 catRead(byte *buf, uint16 length);
+ Common::File *_catFile;
+ Common::File *_datFile;
+ void xCrypt(byte *buf, uint16 length);
+public:
+ ResourceManager();
+ ~ResourceManager();
+ uint16 read(byte *buf, uint16 length);
+ bool seek(int32 offs, int whence = SEEK_SET);
+
+ BtKeypack *find(const char *key);
+ bool exist(const char *name);
+};
+
+class EncryptedStream {
+private:
+ CGE2Engine *_vm;
+ Common::SeekableReadStream *_readStream;
+ int _lineCount;
+ bool _error;
+public:
+ EncryptedStream(CGE2Engine *vm, const char *name);
+ ~EncryptedStream();
+ bool err();
+ bool eos();
+ bool seek(int32 offset);
+ int32 pos();
+ int32 size();
+ uint32 read(byte *dataPtr, uint32 dataSize);
+ int16 readSint16LE();
+ uint32 readUint32LE();
+ Common::String readLine();
+ int getLineCount() { return _lineCount; }
+
+ static const char *kIdTab[];
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_FILEIO_H
diff --git a/engines/cge2/general.h b/engines/cge2/general.h
new file mode 100644
index 0000000000..7213c2e24d
--- /dev/null
+++ b/engines/cge2/general.h
@@ -0,0 +1,45 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_GENERAL_H
+#define CGE2_GENERAL_H
+
+#include "common/file.h"
+
+namespace CGE2 {
+
+class CGE2Engine;
+
+struct Dac {
+ uint8 _r;
+ uint8 _g;
+ uint8 _b;
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_GENERAL_H
diff --git a/engines/cge2/hero.cpp b/engines/cge2/hero.cpp
new file mode 100644
index 0000000000..225df54bd1
--- /dev/null
+++ b/engines/cge2/hero.cpp
@@ -0,0 +1,622 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/hero.h"
+#include "cge2/text.h"
+#include "cge2/map.h"
+
+namespace CGE2 {
+
+Hero::Hero(CGE2Engine *vm) : Sprite(vm), _contact(nullptr), _dir(kNoDir),
+ _curDim(0), _tracePtr(-1), _ignoreMap(false), _maxDist(0) {
+
+ for (int i = 0; i < kDimMax; i++)
+ _dim[i] = nullptr;
+
+ _reachStart = _reachCycle = _sayStart = _funStart = 0;
+ _funDel0 = _funDel = 0;
+}
+
+Hero::~Hero() {
+ contract();
+}
+
+Sprite *Hero::expand() {
+ if (_ext)
+ return this;
+
+ char fname[kMaxPath];
+ _vm->mergeExt(fname, _file, kSprExt);
+
+ if (_ext != nullptr)
+ delete _ext;
+
+ _ext = new SprExt(_vm);
+
+ if (!*_file)
+ return this;
+
+ for (int i = 0; i < kDimMax; i++) {
+ if (_dim[i] != nullptr) {
+ delete[] _dim[i];
+ _dim[i] = nullptr;
+ }
+ }
+ for (int i = 0; i < kDimMax; i++) {
+ _dim[i] = new Bitmap[_shpCnt];
+ for (int j = 0; j < _shpCnt; j++)
+ _dim[i][j].setVM(_vm);
+ }
+
+ int cnt[kActions];
+
+ for (int i = 0; i < kActions; i++)
+ cnt[i] = 0;
+
+ for (int i = 0; i < kActions; i++) {
+ byte n = _actionCtrl[i]._cnt;
+ if (n)
+ _ext->_actions[i] = new CommandHandler::Command[n];
+ else
+ _ext->_actions[i] = nullptr;
+ }
+
+ Seq *curSeq = nullptr;
+ if (_seqCnt)
+ curSeq = new Seq[_seqCnt];
+
+ if (_vm->_resman->exist(fname)) { // sprite description file exist
+ EncryptedStream sprf(_vm, fname);
+ if (sprf.err())
+ error("Bad SPR [%s]", fname);
+
+ ID section = kIdPhase;
+ ID id;
+ Common::String line;
+ char tmpStr[kLineMax + 1];
+ int shpcnt = 0;
+ int seqcnt = 0;
+ int maxnow = 0;
+ int maxnxt = 0;
+
+ for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) {
+ if (line.empty())
+ continue;
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+
+ char *p = _vm->token(tmpStr);
+
+ id = _vm->ident(p);
+ switch (id) {
+ case kIdNear:
+ case kIdMTake:
+ case kIdFTake:
+ case kIdPhase:
+ case kIdSeq:
+ section = id;
+ break;
+ case kIdName:
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+ for (p = tmpStr; *p != '='; p++) // We search for the =
+ ;
+ setName(_vm->tail(p));
+ break;
+ default:
+ if (id >= kIdNear)
+ break;
+ Seq *s;
+ switch (section) {
+ case kIdNear:
+ case kIdMTake:
+ case kIdFTake:
+ id = (ID)_vm->_commandHandler->getComId(p);
+ if (_actionCtrl[section]._cnt) {
+ CommandHandler::Command *c = &_ext->_actions[section][cnt[section]++];
+ c->_commandType = CommandType(id);
+ c->_ref = _vm->number(nullptr);
+ c->_val = _vm->number(nullptr);
+ c->_spritePtr = nullptr;
+ }
+ break;
+ case kIdSeq:
+ s = &curSeq[seqcnt++];
+ s->_now = atoi(p);
+ if (s->_now > maxnow)
+ maxnow = s->_now;
+ s->_next = _vm->number(nullptr);
+ switch (s->_next) {
+ case 0xFF:
+ s->_next = seqcnt;
+ break;
+ case 0xFE:
+ s->_next = seqcnt - 1;
+ break;
+ }
+ if (s->_next > maxnxt)
+ maxnxt = s->_next;
+ s->_dx = _vm->number(nullptr);
+ s->_dy = _vm->number(nullptr);
+ s->_dz = _vm->number(nullptr);
+ s->_dly = _vm->number(nullptr);
+ break;
+ case kIdPhase:
+ for (int i = 0; i < kDimMax; i++) {
+ char *q = p;
+ q[1] = '0' + i;
+ Bitmap b(_vm, q);
+ _dim[i][shpcnt] = b;
+ if (!shpcnt)
+ _hig[i] = b._h;
+ }
+ ++shpcnt;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (curSeq) {
+ if (maxnow >= shpcnt)
+ error("Bad PHASE in SEQ %s", fname);
+ if (maxnxt >= seqcnt)
+ error("Bad JUMP in SEQ %s", fname);
+ setSeq(curSeq);
+ } else
+ setSeq(_stdSeq8);
+
+ setShapeList(_dim[0], shpcnt);
+ }
+
+ char *tempStr = _vm->_text->getText(_ref + 100);
+ char *text = new char[strlen(tempStr) + 1];
+ strcpy(text, tempStr);
+ _reachStart = atoi(_vm->token(text));
+ _reachCycle = atoi(_vm->token(nullptr));
+ _sayStart = atoi(_vm->token(nullptr));
+ _funStart = atoi(_vm->token(nullptr));
+ _funDel = _funDel0 = (72 / _ext->_seq[0]._dly) * atoi(_vm->token(nullptr));
+ delete[] text;
+
+ int i = stepSize() / 2;
+ _maxDist = (int)sqrt(double(i * i * 2));
+ setCurrent();
+
+ return this;
+}
+
+Sprite *Hero::contract() {
+ for (int i = 0; i < kDimMax; i++) {
+ if (_dim[i] != nullptr) {
+ delete[] _dim[i];
+ if (_ext->_shpList == _dim[i])
+ _ext->_shpList = nullptr;
+ _dim[i] = nullptr;
+ }
+ }
+ Sprite::contract();
+ return this;
+}
+
+void Hero::setCurrent() {
+ FXP m = _vm->_eye->_z / (_pos3D._z - _vm->_eye->_z);
+ FXP tmp = m * _siz.y;
+ int h = -(tmp.trunc());
+
+ int i = 0;
+ for (; i < kDimMax - 1; i++) {
+ if (h >= (_hig[i] + _hig[i + 1]) / 2)
+ break;
+ }
+
+ _ext->_shpList = _dim[_curDim = i];
+}
+
+void Hero::hStep() {
+ if (!_ignoreMap && _ext) {
+ Seq *seq = _ext->_seq;
+ int ptr = seq[_seqPtr]._next;
+ seq += ptr;
+ if (seq->_dx | seq->_dz) {
+ V2D p0(_vm, _pos3D._x.round(), _pos3D._z.round());
+ V2D p1(_vm, p0.x + seq->_dx, p0.y + seq->_dz);
+ if (mapCross(p0, p1)) {
+ park();
+ return;
+ }
+ }
+ }
+ step();
+}
+
+Sprite *Hero::setContact() {
+ Sprite *spr;
+ int md = _maxDist << 1;
+ for (spr = _vm->_vga->_showQ->first(); spr; spr = spr->_next) {
+ if (spr->_actionCtrl[kNear]._cnt && ((spr->_ref & 255) != 255) && (distance(spr) <= md)) {
+ if (spr == _contact)
+ return nullptr;
+ else
+ break;
+ }
+ }
+ return (_contact = spr);
+}
+
+void Hero::tick() {
+ int z = _pos3D._z.trunc();
+ //-- maybe not exactly wid/2, but wid/3 ?
+ int d = ((_siz.x / 2) * _vm->_eye->_z.trunc()) / (_vm->_eye->_z.trunc() - z);
+
+ if (_dir != kNoDir) { // just walking...
+ if (_flags._hold || _tracePtr < 0)
+ park();
+ else {
+ Sprite *spr = setContact();
+ if (spr)
+ _vm->feedSnail(spr, kNear, this);
+ }
+ }
+ //---------------------------------------------------------------
+ if (_tracePtr >= 0) {
+ if (distance(_trace[_tracePtr]) <= _maxDist)
+ --_tracePtr;
+
+ if (_tracePtr < 0)
+ park();
+ else {
+ int stp = stepSize() / 2;
+ int dx = _trace[_tracePtr]._x.round() - _pos3D._x.round();
+ int dz = _trace[_tracePtr]._z.round() - _pos3D._z.round();
+ Dir dir = (dx > stp) ? kEE : ((-dx > stp) ? kWW : ((dz > stp) ? kNN : kSS));
+ turn(dir);
+ }
+ }
+
+ //---------------------------------------------------------------
+ hStep();
+ setCurrent();
+ switch (_dir) {
+ case kSS:
+ if (_pos3D._z < stepSize() / 2)
+ park();
+ break;
+ case kWW:
+ if (_pos2D.x <= d)
+ park();
+ break;
+ case kNN:
+ if (_pos3D._z > kScrDepth)
+ park();
+ break;
+ case kEE:
+ if (_pos2D.x >= kScrWidth - 1 - d)
+ park();
+ break;
+ default:
+ break;
+ }
+ if (_flags._trim)
+ gotoxyz_(_pos2D);
+
+ if (_pos3D._z.trunc() != z)
+ _flags._zmov = true;
+
+ if (--_funDel == 0)
+ fun();
+}
+
+int Hero::distance(V3D pos) {
+ V3D di = _pos3D - pos;
+ int x = di._x.round();
+ int z = di._z.round();
+ int retval = (int)sqrt((double)x * x + z * z);
+ return retval;
+}
+
+int Hero::distance(Sprite *spr) {
+ V3D pos = spr->_pos3D;
+ int mdx = (spr->_siz.x >> 1) + (_siz.x >> 1);
+ int dx = (_pos3D._x - spr->_pos3D._x).round();
+ if (dx < 0) {
+ mdx = -mdx;
+ if (dx > mdx)
+ pos._x = _pos3D._x;
+ else
+ pos._x += mdx;
+ } else if (dx < mdx)
+ pos._x = _pos3D._x;
+ else
+ pos._x += mdx;
+
+ return distance(pos);
+}
+
+void Hero::turn(Dir d) {
+ Dir dir = (_dir == kNoDir) ? kSS : _dir;
+ if (d != _dir) {
+ step((d == dir) ? 57 : (8 + 4 * dir + d));
+ _dir = d;
+ }
+ resetFun();
+}
+
+void Hero::park() {
+ if (_dir != kNoDir) {
+ step(8 + 5 * _dir);
+ _dir = kNoDir;
+ _trace[0] = _pos3D;
+ _tracePtr = -1;
+ setCurrent();
+ _flags._zmov = true;
+ }
+ _ignoreMap = false;
+ if (_time == 0)
+ ++_time;
+}
+
+bool Hero::lower(Sprite * spr) {
+ return (spr->_pos3D._y + (spr->_siz.y >> 2) < 10);
+}
+
+void Hero::reach(int mode) {
+ Sprite *spr = nullptr;
+ if (mode >= 4) {
+ spr = _vm->_vga->_showQ->locate(mode);
+ if (spr) {
+ mode = !spr->_flags._east; // 0-1
+ if (lower(spr)) // 2-3
+ mode += 2;
+ }
+ }
+ // note: insert SNAIL commands in reverse order
+ _vm->_commandHandler->insertCommand(kCmdPause, -1, 24, nullptr);
+ _vm->_commandHandler->insertCommand(kCmdSeq, -1, _reachStart + _reachCycle * mode, this);
+ if (spr) {
+ _vm->_commandHandler->insertCommand(kCmdWait, -1, -1, this);
+ _vm->_commandHandler->insertCommand(kCmdWalk, -1, spr->_ref, this);
+ }
+ // sequence is not finished,
+ // now it is just at sprite appear (disappear) point
+ resetFun();
+}
+
+void Hero::fun() {
+ if (_vm->_commandHandler->idle()) {
+ park();
+ _vm->_commandHandler->addCommand(kCmdWait, -1, -1, this);
+ _vm->_commandHandler->addCommand(kCmdSeq, -1, _funStart, this);
+ }
+ _funDel = _funDel0 >> 2;
+}
+
+int Hero::len(V2D v) {
+ return (int)sqrt(double(v.x * v.x + v.y * v.y));
+}
+
+bool Hero::findWay(){
+ V2D p0(_vm, _pos3D._x.round(), _pos3D._z.round());
+ V2D p1(_vm, _trace[_tracePtr]._x.round(), _trace[_tracePtr]._z.round());
+ V2D ph(_vm, p1.x, p0.y);
+ V2D pv(_vm, p0.x, p1.y);
+ bool pvOk = (!mapCross(p0, pv) && !mapCross(pv, p1));
+ bool phOk = (!mapCross(p0, ph) && !mapCross(ph, p1));
+ int md = (_maxDist >> 1);
+ if (pvOk && (len(ph - p0) <= md || len(p1 - ph) <= md))
+ return true;
+
+ if (phOk && (len(pv - p0) <= md || len(p1 - pv) <= md))
+ return true;
+
+ if (pvOk) {
+ _trace[++_tracePtr] = V3D(pv.x, 0, pv.y);
+ return true;
+ }
+
+ if (phOk) {
+ _trace[++_tracePtr] = V3D(ph.x, 0, ph.y);
+ return true;
+ }
+
+ return false;
+}
+
+int Hero::snap(int p, int q, int grid) {
+ int d = abs(q - p) % grid;
+ if (d > (grid >> 1))
+ d -= grid;
+ return (q >= p) ? (q - d) : (q + d);
+}
+
+void Hero::walkTo(V3D pos) {
+ if (distance(pos) <= _maxDist)
+ return;
+
+ int stp = stepSize();
+ pos._x = snap(_pos3D._x.round(), pos._x.round(), stp);
+ pos._y = 0;
+ pos._z = snap(_pos3D._z.round(), pos._z.round(), stp);
+
+ V2D p0(_vm, _pos3D._x.round(), _pos3D._z.round());
+ V2D p1(_vm, pos._x.round(), pos._z.round());
+ resetFun();
+ int cnt = mapCross(p0, p1);
+ if ((cnt & 1) == 0) { // even == way exists
+ _trace[_tracePtr = 0] = pos;
+ if (!findWay()) {
+ int i;
+ ++_tracePtr;
+ for (i = stp; i < kMaxTry; i += stp) {
+ _trace[_tracePtr] = pos + V3D(i, 0, 0);
+ if (!mapCross(_trace[_tracePtr - 1], _trace[_tracePtr]) && findWay())
+ break;
+
+ _trace[_tracePtr] = pos + V3D(-i, 0, 0);
+ if (!mapCross(_trace[_tracePtr - 1], _trace[_tracePtr]) && findWay())
+ break;
+
+ _trace[_tracePtr] = pos + V3D(0, 0, i);
+ if (!mapCross(_trace[_tracePtr - 1], _trace[_tracePtr]) && findWay())
+ break;
+
+ _trace[_tracePtr] = pos + V3D(0, 0, -i);
+ if (!mapCross(_trace[_tracePtr - 1], _trace[_tracePtr]) && findWay())
+ break;
+ }
+ if (i >= kMaxTry)
+ _trace[_tracePtr] = V3D(_pos3D._x, 0, pos._z); // not found
+ }
+ }
+}
+
+void Hero::walkTo(Sprite *spr) {
+ int mdx = _siz.x >> 1;
+ int stp = (stepSize() + 1) / 2;
+ if (!spr->_flags._east)
+ mdx = -mdx;
+ walkTo(spr->_pos3D + V3D(mdx, 0, (!spr->_flags._frnt || spr->_pos3D._z < 8) ? stp : -stp));
+}
+
+V3D Hero::screenToGround(V2D pos) {
+ FXP z = _vm->_eye->_z + (_vm->_eye->_y * _vm->_eye->_z) / (FXP(pos.y) - _vm->_eye->_y);
+ FXP x = _vm->_eye->_x - ((FXP(pos.x) - _vm->_eye->_x) * (z - _vm->_eye->_z)) / _vm->_eye->_z;
+ return V3D(x.round(), 0, z.round());
+}
+
+int Hero::cross(const V2D &a, const V2D &b) {
+ int x = _pos3D._x.trunc();
+ int z = _pos3D._z.trunc();
+ int r = ((_siz.x / 3) * _vm->_eye->_z.trunc()) / (_vm->_eye->_z.trunc() - z);
+ return _vm->cross(a, b, V2D(_vm, x - r, z), V2D(_vm, x + r, z)) << 1;
+}
+
+bool CGE2Engine::cross(const V2D &a, const V2D &b, const V2D &c, const V2D &d) {
+ if (contain(a, b, c) || contain(a, b, d) || contain(c, d, a) || contain(c, d, b))
+ return true;
+
+ return sgn(det(a, b, c)) != sgn(det(a, b, d)) && sgn(det(c, d, a)) != sgn(det(c, d, b));
+}
+
+bool CGE2Engine::contain(const V2D &a, const V2D &b, const V2D &p) {
+ if (det(a, b, p))
+ return false;
+
+ return ((long)(a.x - p.x) * (p.x - b.x) >= 0 && (long)(a.y - p.y) * (p.y - b.y) >= 0);
+}
+
+long CGE2Engine::det(const V2D &a, const V2D &b, const V2D &c) {
+ return ((long)a.x * b.y + (long)b.x * c.y + (long)c.x * a.y) - ((long)c.x * b.y + (long)b.x * a.y + (long)a.x * c.y);
+}
+
+int CGE2Engine::sgn(long n) {
+ return (n == 0) ? 0 : ((n > 0) ? 1 : -1);
+}
+
+int Hero::mapCross(const V2D &a, const V2D &b) {
+ Hero *o = other();
+ int n = (o->_scene == _scene) ? o->cross(a, b) : 0;
+ if (!_ignoreMap)
+ n += _vm->mapCross(a, b);
+
+ return n;
+}
+
+int Hero::mapCross(const V3D &a, const V3D &b) {
+ return mapCross(V2D(_vm, a._x.round(), a._z.round()), V2D(_vm, b._x.round(), b._z.round()));
+}
+
+int CGE2Engine::mapCross(const V2D &a, const V2D &b) {
+ int cnt = 0;
+ V2D *n0 = nullptr;
+ V2D *p = nullptr;
+ for (int i = 0; i < _map->size(); i++) {
+ V2D *n = _map->getCoord(i);
+ if (p) {
+ if (cross(a, b, *n0, *n))
+ ++cnt;
+
+ if (*n == *p)
+ p = nullptr;
+ } else {
+ p = n;
+ }
+ n0 = n;
+ }
+ return cnt;
+}
+
+void Hero::setScene(int c) {
+ Sprite::setScene(c);
+ resetFun();
+}
+
+void Hero::operator++() {
+ if (_curDim > 0)
+ _ext->_shpList = _dim[--_curDim];
+}
+
+void Hero::operator--() {
+ if (_curDim < kDimMax - 1)
+ _ext->_shpList = _dim[++_curDim];
+}
+
+bool Sprite::works(Sprite *spr) {
+ if (!spr || !spr->_ext)
+ return false;
+
+ bool ok = false;
+
+ Action a = _vm->_heroTab[_vm->_sex]->_ptr->action();
+ CommandHandler::Command *ct = spr->_ext->_actions[a];
+ if (ct) {
+ int i = spr->_actionCtrl[a]._ptr;
+ int n = spr->_actionCtrl[a]._cnt;
+ while (i < n && !ok) {
+ CommandHandler::Command *c = &ct[i++];
+ if (c->_commandType != kCmdUse)
+ break;
+ ok = (c->_ref == _ref);
+ if (c->_val > 255) {
+ if (ok) {
+ int p = spr->labVal(a, c->_val >> 8);
+ if (p >= 0)
+ spr->_actionCtrl[a]._ptr = p;
+ else
+ ok = false;
+ }
+ } else {
+ if (c->_val && c->_val != _vm->_now)
+ ok = false;
+ break;
+ }
+ }
+ }
+
+ return ok;
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/hero.h b/engines/cge2/hero.h
new file mode 100644
index 0000000000..3b5329e12c
--- /dev/null
+++ b/engines/cge2/hero.h
@@ -0,0 +1,114 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_HERO_H
+#define CGE2_HERO_H
+
+#include "cge2/cge2.h"
+#include "cge2/vga13h.h"
+#include "cge2/snail.h"
+
+namespace CGE2 {
+
+#define kMaxTry 400
+
+class Hero;
+
+struct HeroTab {
+ Hero *_ptr;
+ Sprite *_face;
+ Sprite *_pocket[kPocketMax + 1];
+ int _downPocketId[kPocketMax + 1];
+ int _pocPtr;
+ V2D *_posTab[kSceneMax];
+ HeroTab(CGE2Engine *vm) {
+ _ptr = nullptr;
+ _face = nullptr;
+ for (int i = 0; i < kPocketMax + 1; i++) {
+ _pocket[i] = nullptr;
+ _downPocketId[i] = -1;
+ }
+ _pocPtr = 0;
+ for (int i = 0; i < kSceneMax; i++)
+ _posTab[i] = nullptr;
+ }
+ ~HeroTab() {
+ for (int i = 0; i < kSceneMax; i++)
+ delete _posTab[i];
+ }
+};
+
+class Hero : public Sprite {
+ int _hig[kDimMax];
+ Sprite *_contact;
+public:
+ BitmapPtr _dim[kDimMax];
+ V3D _trace[kWayMax];
+ enum Dir { kNoDir = -1, kSS, kWW, kNN, kEE } _dir;
+ int _curDim;
+ int _tracePtr;
+ int _reachStart, _reachCycle, _sayStart, _funStart;
+ int _funDel0, _funDel;
+ int _maxDist;
+ bool _ignoreMap;
+ Hero(CGE2Engine *vm);
+ ~Hero();
+ void tick();
+ Sprite *expand();
+ Sprite *contract();
+ Sprite *setContact();
+ int stepSize() { return _ext->_seq[7]._dx; }
+ int distance(V3D pos);
+ int distance(Sprite * spr);
+ void turn(Dir d);
+ void park();
+ int len(V2D v);
+ bool findWay();
+ static int snap(int p, int q, int grid);
+ void walkTo(V3D pos);
+ void walkTo(V2D pos) { walkTo(screenToGround(pos)); }
+ V3D screenToGround(V2D pos);
+ void walkTo(Sprite *spr);
+ void say() { step(_sayStart); }
+ void fun();
+ void resetFun() { _funDel = _funDel0; }
+ void hStep();
+ bool lower(Sprite * spr);
+ int cross(const V2D &a, const V2D &b);
+ int mapCross(const V2D &a, const V2D &b);
+ int mapCross(const V3D &a, const V3D &b);
+ Hero *other() { return _vm->_heroTab[!(_ref & 1)]->_ptr;}
+ Action action() { return (Action)(_ref % 10); }
+ void reach(int mode);
+ void setCurrent();
+ void setScene(int c);
+ void operator++();
+ void operator--();
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_HERO_H
diff --git a/engines/cge2/inventory.cpp b/engines/cge2/inventory.cpp
new file mode 100644
index 0000000000..e62aa01e99
--- /dev/null
+++ b/engines/cge2/inventory.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/cge2.h"
+#include "cge2/hero.h"
+
+namespace CGE2 {
+
+int CGE2Engine::findActivePocket(int ref) {
+ for (int i = 0; i < kPocketMax; i++) {
+ Sprite *spr = _heroTab[_sex]->_pocket[i];
+ if (ref >= 0) {
+ if (spr && (spr->_ref == ref))
+ return i;
+ } else if (!spr)
+ return i;
+ }
+ return -1;
+}
+
+void CGE2Engine::selectPocket(int n) {
+ Sprite **p = _heroTab[_sex]->_pocket;
+ int &pp = _heroTab[_sex]->_pocPtr;
+ if ((n < 0) || (pp == n)) {
+ n = findActivePocket(-1);
+ if (n >= 0)
+ pp = n;
+ } else if (p[n])
+ pp = n;
+}
+
+void CGE2Engine::pocFul() {
+ Hero *h = _heroTab[_sex]->_ptr;
+ h->park();
+ _commandHandler->addCommand(kCmdWait, -1, -1, h);
+ _commandHandler->addCommand(kCmdSound, -1, 2, h);
+ _commandHandler->addCommand(kCmdSay, -1, kPocketFull + _sex, h);
+}
+
+void CGE2Engine::releasePocket(Sprite *spr) {
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < kPocketMax; j++) {
+ Sprite *&poc = _heroTab[i]->_pocket[j];
+ if (poc == spr) {
+ spr->_flags._kept = false;
+ poc = nullptr;
+ return;
+ }
+ }
+ }
+}
+
+int CGE2Engine::freePockets(int sx) {
+ int n = 0;
+ for (int i = 0; i < kPocketMax; i++){
+ if (_heroTab[sx]->_pocket[i] == nullptr)
+ ++n;
+ }
+ return n;
+}
+
+void CGE2Engine::openPocket() {
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < kPocketMax + 1; j++) {
+ int ref = (int)_heroTab[i]->_downPocketId[j];
+ _heroTab[i]->_pocket[j] = (ref == -1) ? nullptr : _vga->_showQ->locate(ref);
+ }
+ }
+}
+
+void CGE2Engine::closePocket() {
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < kPocketMax + 1; j++) {
+ Sprite *spr = _heroTab[i]->_pocket[j];
+ _heroTab[i]->_downPocketId[j] = (spr) ? spr->_ref : -1;
+ }
+ }
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/map.cpp b/engines/cge2/map.cpp
new file mode 100644
index 0000000000..8c1f00048f
--- /dev/null
+++ b/engines/cge2/map.cpp
@@ -0,0 +1,92 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/map.h"
+
+namespace CGE2 {
+
+Map::Map(CGE2Engine *vm) :_vm(vm) {}
+
+Map::~Map() {
+ _container.clear();
+}
+
+void Map::clear() {
+ _container.clear();
+}
+
+void Map::load(int scene) {
+ clear();
+
+ const char *fname = "%.2d.MAP";
+ Common::String fileName = Common::String::format(fname, scene);
+ if (!_vm->_resman->exist(fileName.c_str()))
+ return;
+
+ EncryptedStream file(_vm, fileName.c_str());
+
+ Common::String line;
+ for (line = file.readLine(); !file.eos(); line = file.readLine()) {
+ if (line.empty())
+ continue;
+
+ char tmpStr[kLineMax + 1];
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+
+ char *currPos = tmpStr;
+ int x = nextNum(currPos);
+ while (true) {
+ int y = nextNum(nullptr);
+ _container.push_back(V2D(_vm, convertCoord(x), convertCoord(y)));
+ x = nextNum(nullptr);
+ if (x == -1) // We stop if there are no more data left to process in the current line.
+ break;
+ }
+ }
+}
+
+int Map::nextNum(char *currPos) {
+ currPos = strtok(currPos, " (),");
+ if (currPos == nullptr)
+ return -1;
+ int num = atoi(currPos);
+ return num;
+}
+
+int Map::convertCoord(int coord) {
+ return (coord + (kMapGrid >> 1)) & kMapMask;
+}
+
+int Map::size() {
+ return _container.size();
+}
+
+V2D *Map::getCoord(int idx) {
+ return &_container[idx];
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/map.h b/engines/cge2/map.h
new file mode 100644
index 0000000000..206479b929
--- /dev/null
+++ b/engines/cge2/map.h
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_MAP_H
+#define CGE2_MAP_H
+
+#include "cge2/vga13h.h"
+
+namespace CGE2 {
+
+#define kMapGrid 4
+#define kMapMask (~(kMapGrid - 1))
+
+class Map {
+ CGE2Engine *_vm;
+ Common::Array<V2D> _container;
+
+ int convertCoord(int coord);
+ int nextNum(char *currPos);
+public:
+ Map(CGE2Engine *vm);
+ ~Map();
+ void clear();
+ void load(int scene);
+ int size();
+ V2D *getCoord(int idx);
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_MAP_H
diff --git a/engines/cge2/module.mk b/engines/cge2/module.mk
new file mode 100644
index 0000000000..4b321d88a8
--- /dev/null
+++ b/engines/cge2/module.mk
@@ -0,0 +1,30 @@
+MODULE := engines/cge2
+
+MODULE_OBJS = \
+ cge2.o \
+ detection.o \
+ fileio.o \
+ vga13h.o \
+ bitmap.o \
+ sound.o \
+ cge2_main.o \
+ text.o \
+ hero.o \
+ snail.o \
+ spare.o \
+ talk.o \
+ events.o \
+ map.o \
+ vmenu.o \
+ saveload.o \
+ toolbar.o \
+ inventory.o \
+ console.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_CGE2), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/cge2/saveload.cpp b/engines/cge2/saveload.cpp
new file mode 100644
index 0000000000..fd60422dff
--- /dev/null
+++ b/engines/cge2/saveload.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "common/config-manager.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "graphics/thumbnail.h"
+#include "graphics/surface.h"
+#include "graphics/palette.h"
+#include "graphics/scaler.h"
+#include "cge2/events.h"
+#include "cge2/snail.h"
+#include "cge2/hero.h"
+#include "cge2/text.h"
+#include "cge2/sound.h"
+#include "cge2/cge2_main.h"
+
+namespace CGE2 {
+
+#define kSavegameCheckSum (1997 + _now + _sex + kWorldHeight)
+#define kBadSVG 99
+
+bool CGE2Engine::canSaveGameStateCurrently() {
+ return (_gamePhase == kPhaseInGame) && _mouse->_active &&
+ _commandHandler->idle() && (_soundStat._wait == nullptr);
+}
+
+Common::Error CGE2Engine::saveGameState(int slot, const Common::String &desc) {
+ storeHeroPos();
+ saveGame(slot, desc);
+ sceneUp(_now);
+ return Common::kNoError;
+}
+
+void CGE2Engine::saveGame(int slotNumber, const Common::String &desc) {
+ // Set up the serializer
+ Common::String slotName = generateSaveName(slotNumber);
+ Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(slotName);
+
+ // Write out the ScummVM savegame header
+ SavegameHeader header;
+ header.saveName = desc;
+ header.version = kSavegameVersion;
+ writeSavegameHeader(saveFile, header);
+
+ // Write out the data of the savegame
+ sceneDown();
+ syncGame(nullptr, saveFile);
+
+ // Finish writing out game data
+ saveFile->finalize();
+ delete saveFile;
+}
+
+bool CGE2Engine::canLoadGameStateCurrently() {
+ return (_gamePhase == kPhaseInGame) && _mouse->_active;
+}
+
+Common::Error CGE2Engine::loadGameState(int slot) {
+ _commandHandler->clear();
+ _commandHandlerTurbo->clear();
+ sceneDown();
+ if (!loadGame(slot))
+ return Common::kReadingFailed;
+ sceneUp(_now);
+ initToolbar();
+ return Common::kNoError;
+}
+
+bool CGE2Engine::loadGame(int slotNumber) {
+ Common::MemoryReadStream *readStream;
+
+ // Open up the savegame file
+ Common::String slotName = generateSaveName(slotNumber);
+ Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(slotName);
+
+ // Read the data into a data buffer
+ int size = saveFile->size();
+ byte *dataBuffer = (byte *)malloc(size);
+ saveFile->read(dataBuffer, size);
+ readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES);
+ delete saveFile;
+
+ // Check to see if it's a ScummVM savegame or not
+ char buffer[kSavegameStrSize + 1];
+ readStream->read(buffer, kSavegameStrSize + 1);
+
+ if (strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) != 0) {
+ delete readStream;
+ return false;
+ } else {
+ SavegameHeader saveHeader;
+
+ if (!readSavegameHeader(readStream, saveHeader)) {
+ delete readStream;
+ return false;
+ }
+
+ // Delete the thumbnail
+ saveHeader.thumbnail->free();
+ delete saveHeader.thumbnail;
+ }
+
+ resetGame();
+
+ // Get in the savegame
+ syncGame(readStream, nullptr);
+ delete readStream;
+
+ loadHeroes();
+
+ return true;
+}
+
+void CGE2Engine::resetGame() {
+ _busyPtr = nullptr;
+ busy(false);
+ _spare->clear();
+ _vga->_showQ->clear();
+ loadScript("CGE.INI", true);
+ delete _infoLine;
+ _infoLine = new InfoLine(this, kInfoW);
+}
+
+void CGE2Engine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header) {
+ // Write out a savegame header
+ out->write(kSavegameStr, kSavegameStrSize + 1);
+
+ out->writeByte(kSavegameVersion);
+
+ // Write savegame name
+ out->write(header.saveName.c_str(), header.saveName.size() + 1);
+
+ // Get the active palette
+ uint8 thumbPalette[256 * 3];
+ g_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256);
+
+ // Stop the heroes from moving and redraw them before taking the picture.
+ for (int i = 0; i < 2; i++)
+ _heroTab[i]->_ptr->park();
+ _vga->show();
+
+ // Create a thumbnail and save it
+ Graphics::Surface *thumb = new Graphics::Surface();
+ Graphics::Surface *s = _vga->_page[0];
+ ::createThumbnail(thumb, (const byte *)s->getPixels(), kScrWidth, kScrHeight, thumbPalette);
+ Graphics::saveThumbnail(*out, *thumb);
+ thumb->free();
+ delete thumb;
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ out->writeSint16LE(td.tm_year + 1900);
+ out->writeSint16LE(td.tm_mon + 1);
+ out->writeSint16LE(td.tm_mday);
+ out->writeSint16LE(td.tm_hour);
+ out->writeSint16LE(td.tm_min);
+}
+
+bool CGE2Engine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) {
+ header.thumbnail = nullptr;
+
+ // Get the savegame version
+ header.version = in->readByte();
+ if (header.version > kSavegameVersion)
+ return false;
+
+ // Read in the string
+ header.saveName.clear();
+ char ch;
+ while ((ch = (char)in->readByte()) != '\0')
+ header.saveName += ch;
+
+ // Get the thumbnail
+ header.thumbnail = Graphics::loadThumbnail(*in);
+ if (!header.thumbnail)
+ return false;
+
+ // Read in save date/time
+ header.saveYear = in->readSint16LE();
+ header.saveMonth = in->readSint16LE();
+ header.saveDay = in->readSint16LE();
+ header.saveHour = in->readSint16LE();
+ header.saveMinutes = in->readSint16LE();
+
+ return true;
+}
+
+void CGE2Engine::syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream) {
+ Common::Serializer s(readStream, writeStream);
+
+ // Synchronise header data
+ syncHeader(s);
+
+ // Synchronise _spare
+ _spare->sync(s);
+
+ if (s.isSaving()) {
+ // Save the references of the items in the heroes pockets:
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < kPocketMax; j++) {
+ int ref = _heroTab[i]->_downPocketId[j];
+ s.syncAsSint16LE(ref);
+ }
+ }
+ } else {
+ // Load items to the pockets
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < kPocketMax; j++) {
+ int ref = 0;
+ s.syncAsSint16LE(ref);
+ _heroTab[i]->_downPocketId[j] = ref;
+ }
+ }
+ }
+
+ // Heroes' _posTabs
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < kSceneMax; j++) {
+ s.syncAsSint16LE(_heroTab[i]->_posTab[j]->x);
+ s.syncAsSint16LE(_heroTab[i]->_posTab[j]->y);
+ }
+ }
+}
+
+void CGE2Engine::syncHeader(Common::Serializer &s) {
+ s.syncAsUint16LE(_now);
+ s.syncAsUint16LE(_sex);
+ s.syncAsUint16LE(_vga->_rot._len);
+ s.syncAsUint16LE(_waitSeq);
+ s.syncAsUint16LE(_waitRef);
+
+ if (s.isSaving()) {
+ // Write checksum
+ int checksum = kSavegameCheckSum;
+ s.syncAsUint16LE(checksum);
+ } else {
+ // Read checksum and validate it
+ uint16 checksum = 0;
+ s.syncAsUint16LE(checksum);
+ if (checksum != kSavegameCheckSum)
+ error("%s", _text->getText(kBadSVG));
+ }
+}
+
+/**
+* Support method that generates a savegame name
+* @param slot Slot number
+*/
+Common::String CGE2Engine::generateSaveName(int slot) {
+ return Common::String::format("%s.%03d", _targetName.c_str(), slot);
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/snail.cpp b/engines/cge2/snail.cpp
new file mode 100644
index 0000000000..0bf63839e9
--- /dev/null
+++ b/engines/cge2/snail.cpp
@@ -0,0 +1,865 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/snail.h"
+#include "cge2/fileio.h"
+#include "cge2/hero.h"
+#include "cge2/text.h"
+#include "cge2/sound.h"
+#include "cge2/events.h"
+
+namespace CGE2 {
+
+const char *CommandHandler::_commandText[] = {
+ "NOP", "USE", "PAUSE", "INF", "CAVE", "SETX", "SETY", "SETZ", "ADD",
+ "FLASH", "CYCLE", "CLEAR", "MOUSE", "MAP", "MIDI", ".DUMMY.", "WAIT",
+ "HIDE", "ROOM", "SAY", "SOUND", "KILL", "RSEQ", "SEQ", "SEND", "SWAP",
+ "KEEP", "GIVE", "GETPOS", "GOTO", "PORT", "NEXT", "NNEXT", "MTNEXT",
+ "FTNEXT", "RNNEXT", "RMTNEXT", "RFTNEXT", "RMNEAR", "RMMTAKE", "RMFTAKE",
+ "SETREF", "WALKTO", "REACH", "COVER", "UNCOVER", "EXEC", "GHOST",
+ nullptr };
+
+CommandHandler::CommandHandler(CGE2Engine *vm, bool turbo)
+ : _turbo(turbo), _textDelay(false), _timerExpiry(0), _talkEnable(true),
+ _head(0), _tail(0), _commandList((Command *)malloc(sizeof(Command)* 256)),
+ _vm(vm) {
+}
+
+CommandHandler::~CommandHandler() {
+ free(_commandList);
+}
+
+void CommandHandler::runCommand() {
+ if (!_turbo && _vm->_soundStat._wait) {
+ if (*(_vm->_soundStat._wait))
+ return;
+
+ ++_vm->_soundStat._ref[0];
+ if (_vm->_fx->exist(_vm->_soundStat._ref[1], _vm->_soundStat._ref[0])) {
+ int16 oldRepeat = _vm->_sound->getRepeat();
+ _vm->_sound->setRepeat(1);
+ _vm->_sound->play(Audio::Mixer::kSFXSoundType, _vm->_fx->load(_vm->_soundStat._ref[1], _vm->_soundStat._ref[0]), _vm->_sound->_smpinf._span);
+ _vm->_sound->setRepeat(oldRepeat);
+ return;
+ }
+ _vm->_soundStat._wait = nullptr;
+ }
+
+ uint8 tmpHead = _head;
+ while (_tail != tmpHead) {
+ Command tailCmd = _commandList[_tail];
+
+ if (!_turbo) { // only for the slower one
+ if (_vm->_waitRef)
+ break;
+
+ if (_timerExpiry) {
+ // Delay in progress
+ if (_timerExpiry > g_system->getMillis())
+ // Delay not yet ended
+ break;
+
+ // Delay is finished
+ _timerExpiry = 0;
+ } else if (_textDelay) {
+ if (_vm->_talk) {
+ _vm->snKill((Sprite *)_vm->_talk);
+ _vm->_talk = nullptr;
+ }
+ _textDelay = false;
+ }
+
+ if (_vm->_talk && tailCmd._commandType != kCmdPause)
+ break;
+ }
+ ++_tail;
+ _vm->_taken = false;
+ Sprite *spr = nullptr;
+ if (tailCmd._commandType > kCmdSpr)
+ spr = (tailCmd._ref < 0) ? ((Sprite *)tailCmd._spritePtr) : _vm->locate(tailCmd._ref);
+
+ Common::String sprStr;
+ if (spr && *spr->_file && (tailCmd._commandType != kCmdGhost))
+ // In case of kCmdGhost _spritePtr stores a pointer to a Bitmap, not to a Sprite...
+ sprStr = Common::String(spr->_file);
+ else
+ sprStr = "None";
+
+ if (sprStr.empty())
+ sprStr = "None";
+ debugC(1, kCGE2DebugOpcode, "Command: %s; Ref: %d; Val: %d; Sprite: %s;", getComStr(tailCmd._commandType), tailCmd._ref, tailCmd._val, sprStr.c_str());
+
+ switch (tailCmd._commandType) {
+ case kCmdUse:
+ break;
+ case kCmdPause:
+ _timerExpiry = g_system->getMillis() + tailCmd._val * kCommandFrameDelay;
+ if (_vm->_talk)
+ _textDelay = true;
+ break;
+ case kCmdWait:
+ if (spr && spr->active() && (spr->_scene == _vm->_now || spr->_scene == 0)) {
+ _vm->_waitSeq = tailCmd._val;
+ _vm->_waitRef = spr->_ref;
+ }
+ break;
+ case kCmdHide:
+ _vm->snHide(spr, tailCmd._val);
+ break;
+ case kCmdSay:
+ _vm->snSay(spr, tailCmd._val);
+ break;
+ case kCmdInf:
+ if (_talkEnable)
+ _vm->inf(((tailCmd._val) >= 0) ? _vm->_text->getText(tailCmd._val) : (const char *)tailCmd._spritePtr);
+ break;
+ case kCmdCave:
+ _vm->switchScene(tailCmd._val);
+ break;
+ case kCmdMidi:
+ _vm->snMidi(tailCmd._val);
+ break;
+ case kCmdKill:
+ _vm->snKill(spr);
+ break;
+ case kCmdSeq:
+ _vm->snSeq(spr, tailCmd._val);
+ break;
+ case kCmdRSeq:
+ _vm->snRSeq(spr, tailCmd._val);
+ break;
+ case kCmdSend:
+ _vm->snSend(spr, tailCmd._val);
+ break;
+ case kCmdSwap:
+ _vm->snSwap(spr, tailCmd._val);
+ break;
+ case kCmdCover:
+ _vm->snCover(spr, tailCmd._val);
+ break;
+ case kCmdUncover:
+ _vm->snUncover(spr, (tailCmd._val >= 0) ? _vm->locate(tailCmd._val) : ((Sprite *)tailCmd._spritePtr));
+ break;
+ case kCmdKeep:
+ _vm->snKeep(spr, tailCmd._val);
+ break;
+ case kCmdGive:
+ _vm->snGive(spr, tailCmd._val);
+ break;
+ case kCmdSetX:
+ _vm->_point[tailCmd._val]->_x = tailCmd._ref;
+ break;
+ case kCmdSetY:
+ _vm->_point[tailCmd._val]->_y = tailCmd._ref;
+ break;
+ case kCmdSetZ:
+ _vm->_point[tailCmd._val]->_z = tailCmd._ref;
+ break;
+ case kCmdAdd:
+ *(_vm->_point[tailCmd._ref]) = *(_vm->_point[tailCmd._ref]) + *(_vm->_point[tailCmd._val]);
+ break;
+ case kCmdGetPos:
+ if (spr)
+ *(_vm->_point[tailCmd._val]) = spr->_pos3D;
+ break;
+ case kCmdGoto:
+ _vm->snGoto(spr, tailCmd._val);
+ break;
+ case kCmdPort:
+ _vm->snPort(spr, tailCmd._val);
+ break;
+ case kCmdNext:
+ break;
+ case kCmdMouse:
+ _vm->snMouse(tailCmd._val != 0);
+ break;
+ case kCmdNNext:
+ _vm->snNNext(spr, kNear, tailCmd._val);
+ break;
+ case kCmdMTNext:
+ _vm->snNNext(spr, kMTake, tailCmd._val);
+ break;
+ case kCmdFTNext:
+ _vm->snNNext(spr, kFTake, tailCmd._val);
+ break;
+ case kCmdRNNext:
+ _vm->snRNNext(spr, tailCmd._val);
+ break;
+ case kCmdRMTNext:
+ _vm->snRMTNext(spr, tailCmd._val);
+ break;
+ case kCmdRFTNext:
+ _vm->snRFTNext(spr, tailCmd._val);
+ break;
+ case kCmdRMNear:
+ _vm->snRmNear(spr);
+ break;
+ case kCmdRMMTake:
+ _vm->snRmMTake(spr);
+ break;
+ case kCmdRMFTake:
+ _vm->snRmFTake(spr);
+ break;
+ case kCmdSetRef:
+ _vm->snSetRef(spr, tailCmd._val);
+ break;
+ case kCmdFlash:
+ _vm->snFlash(tailCmd._val != 0);
+ break;
+ case kCmdCycle:
+ _vm->snCycle(tailCmd._val);
+ break;
+ case kCmdWalk:
+ _vm->snWalk(spr, tailCmd._val);
+ break;
+ case kCmdReach:
+ _vm->snReach(spr, tailCmd._val);
+ break;
+ case kCmdSound:
+ _vm->snSound(spr, tailCmd._val);
+ _vm->_sound->setRepeat(1);
+ break;
+ case kCmdMap:
+ _vm->_heroTab[tailCmd._ref & 1]->_ptr->_ignoreMap = tailCmd._val == 0;
+ break;
+ case kCmdRoom:
+ _vm->snRoom(spr, tailCmd._val);
+ break;
+ case kCmdExec:
+ switch (tailCmd._cbType) {
+ case kQGame:
+ _vm->qGame();
+ break;
+ case kXScene:
+ _vm->xScene();
+ break;
+ default:
+ error("Unknown Callback Type in SNEXEC");
+ break;
+ }
+ break;
+ case kCmdGhost:
+ _vm->snGhost((Bitmap *)tailCmd._spritePtr);
+ break;
+ case kCmdNop: // Do nothing.
+ break;
+ default:
+ warning("Unhandled command");
+ break;
+ }
+
+ if (_vm->_taken && spr)
+ _vm->_spare->dispose(spr);
+
+ if (!_turbo)
+ break;
+ }
+}
+
+void CGE2Engine::snKill(Sprite *spr) {
+ if (spr) {
+ if (spr->_flags._kept)
+ releasePocket(spr);
+ Sprite *nx = spr->_next;
+ hide1(spr);
+ _vga->_showQ->remove(spr);
+ _eventManager->clearEvent(spr);
+ if (spr->_flags._kill) {
+ _spare->take(spr->_ref);
+ delete spr;
+ } else {
+ spr->setScene(-1);
+ _spare->dispose(spr);
+ }
+ if (nx && nx->_flags._slav)
+ snKill(nx);
+ }
+}
+
+void CGE2Engine::snHide(Sprite *spr, int val) {
+ if (spr) {
+ spr->_flags._hide = (val >= 0) ? (val != 0) : (!spr->_flags._hide);
+ if (spr->_flags._shad)
+ spr->_prev->_flags._hide = spr->_flags._hide;
+ }
+}
+
+void CGE2Engine::snMidi(int val) {
+ if (val < 0)
+ _midiPlayer->killMidi();
+ else if (_music)
+ _midiPlayer->loadMidi(val);
+}
+
+void CGE2Engine::snSeq(Sprite *spr, int val) {
+ if (spr) {
+ if (isHero(spr) && (val == 0))
+ ((Hero*)spr)->park();
+ else
+ spr->step(val);
+ }
+}
+
+void CGE2Engine::snRSeq(Sprite *spr, int val) {
+ if (spr)
+ snSeq(spr, spr->_seqPtr + val);
+}
+
+void CGE2Engine::snSend(Sprite *spr, int val) {
+ if (!spr)
+ return;
+
+ // Sending", spr->_file
+ // from scene", spr->_scene
+ // to scene", val
+ bool was1 = (_vga->_showQ->locate(spr->_ref) != nullptr);
+ bool val1 = (val == 0 || val == _now);
+ spr->_scene = val;
+ releasePocket(spr);
+ if (val1 != was1) {
+ if (was1) {
+ // deactivating
+ hide1(spr);
+ spr->_flags._slav = false;
+ if ((spr == _heroTab[_sex]->_ptr) && (_heroTab[!_sex]->_ptr->_scene == _now))
+ switchHero(!_sex);
+ _spare->dispose(spr);
+ } else {
+ // activating
+ if (byte(spr->_ref) == 0)
+ _bitmapPalette = _vga->_sysPal;
+ _vga->_showQ->insert(spr);
+ if (isHero(spr)) {
+ V2D p = *_heroTab[spr->_ref & 1]->_posTab[val];
+ spr->gotoxyz(V3D(p.x, 0, p.y));
+ ((Hero*)spr)->setCurrent();
+ }
+ _taken = false;
+ _bitmapPalette = nullptr;
+ }
+ }
+}
+
+void CGE2Engine::snSwap(Sprite *spr, int val) {
+ bool tak = _taken;
+ Sprite *xspr = locate(val);
+ if (spr && xspr) {
+ bool was1 = (_vga->_showQ->locate(spr->_ref) != nullptr);
+ bool xwas1 = (_vga->_showQ->locate(val) != nullptr);
+
+ int tmp = spr->_scene;
+ spr->setScene(xspr->_scene);
+ xspr->setScene(tmp);
+
+ SWAP(spr->_pos2D, xspr->_pos2D);
+ SWAP(spr->_pos3D, xspr->_pos3D);
+ if (spr->_flags._kept)
+ swapInPocket(spr, xspr);
+ if (xwas1 != was1) {
+ if (was1) {
+ hide1(spr);
+ _spare->dispose(spr);
+ } else
+ expandSprite(spr);
+ if (xwas1) {
+ hide1(xspr);
+ _spare->dispose(xspr);
+ } else {
+ expandSprite(xspr);
+ _taken = false;
+ }
+ }
+ }
+ if (_taken)
+ _spare->dispose(xspr);
+ _taken = tak;
+}
+
+void CGE2Engine::snCover(Sprite *spr, int val) {
+ bool tak = _taken;
+ Sprite *xspr = locate(val);
+ if (spr && xspr) {
+ spr->_flags._hide = true;
+ xspr->setScene(spr->_scene);
+ xspr->gotoxyz(spr->_pos3D);
+ expandSprite(xspr);
+ if ((xspr->_flags._shad = spr->_flags._shad) == true) {
+ _vga->_showQ->insert(_vga->_showQ->remove(spr->_prev), xspr);
+ spr->_flags._shad = false;
+ }
+ feedSnail(xspr, kNear, _heroTab[_sex]->_ptr);
+ _taken = false;
+ }
+ if (_taken)
+ _spare->dispose(xspr);
+ _taken = tak;
+}
+
+void CGE2Engine::snUncover(Sprite *spr, Sprite *spr2) {
+ if (spr && spr2) {
+ spr->_flags._hide = false;
+ spr->setScene(spr2->_scene);
+ if ((spr->_flags._shad = spr2->_flags._shad) == true) {
+ _vga->_showQ->insert(_vga->_showQ->remove(spr2->_prev), spr);
+ spr2->_flags._shad = false;
+ }
+ spr->gotoxyz(spr2->_pos3D);
+ snSend(spr2, -1);
+ if (spr->_time == 0)
+ ++spr->_time;
+ }
+}
+
+void CGE2Engine::snKeep(Sprite *spr, int stp) {
+ int sex = _sex;
+ if (stp > 127) {
+ _sex = stp & 1; // for another hero
+ stp = -1;
+ }
+ HeroTab *ht = _heroTab[_sex];
+ selectPocket(-1);
+ int pp = ht->_pocPtr;
+
+ if (spr && !spr->_flags._kept && ht->_pocket[pp] == nullptr) {
+ V3D pos(14, -10, -1);
+ int16 oldRepeat = _sound->getRepeat();
+ _sound->setRepeat(1);
+ snSound(ht->_ptr, 3);
+ _sound->setRepeat(oldRepeat);
+ if (_taken) {
+ _vga->_showQ->insert(spr);
+ _taken = false;
+ }
+ ht->_pocket[pp] = spr;
+ spr->setScene(0);
+ spr->_flags._kept = true;
+ if (!_sex)
+ pos._x += kScrWidth - 58;
+ if (pp & 1)
+ pos._x += 29;
+ if (pp >> 1)
+ pos._y -= 20;
+ pos._y -= (spr->_siz.y / 2);
+ spr->gotoxyz(pos);
+ if (stp >= 0)
+ spr->step(stp);
+ }
+ _sex = sex;
+ selectPocket(-1);
+}
+
+void CGE2Engine::snGive(Sprite *spr, int val) {
+ if (spr) {
+ int p = findActivePocket(spr->_ref);
+ if (p >= 0) {
+ releasePocket(spr);
+ spr->setScene(_now);
+ if (val >= 0)
+ spr->step(val);
+ }
+ }
+ selectPocket(-1);
+}
+
+void CGE2Engine::snGoto(Sprite *spr, int val) {
+ if (spr) {
+ V3D eye = *_eye;
+ if (spr->_scene > 0)
+ setEye(*_eyeTab[spr->_scene]);
+ spr->gotoxyz(*_point[val]);
+ setEye(eye);
+ }
+}
+
+void CGE2Engine::snPort(Sprite *spr, int port) {
+ if (spr)
+ spr->_flags._port = (port < 0) ? !spr->_flags._port : (port != 0);
+}
+
+void CGE2Engine::snMouse(bool on) {
+ if (on)
+ _mouse->on();
+ else
+ _mouse->off();
+}
+
+void CGE2Engine::snNNext(Sprite *spr, Action act, int val) {
+ if (spr) {
+ if (val > 255)
+ val = spr->labVal(act, val >> 8);
+ spr->_actionCtrl[act]._ptr = val;
+ }
+}
+
+void CGE2Engine::snRNNext(Sprite *spr, int val) {
+ if (spr)
+ spr->_actionCtrl[kNear]._ptr += val;
+}
+
+void CGE2Engine::snRMTNext(Sprite *spr, int val) {
+ if (spr)
+ spr->_actionCtrl[kMTake]._ptr += val;
+}
+
+void CGE2Engine::snRFTNext(Sprite * spr, int val) {
+ if (spr)
+ spr->_actionCtrl[kFTake]._ptr += val;
+}
+
+void CGE2Engine::snRmNear(Sprite *spr) {
+ if (spr)
+ spr->_actionCtrl[kNear]._cnt = 0;
+}
+
+void CGE2Engine::snRmMTake(Sprite *spr) {
+ if (spr)
+ spr->_actionCtrl[kMTake]._cnt = 0;
+}
+
+void CGE2Engine::snRmFTake(Sprite *spr) {
+ if (spr)
+ spr->_actionCtrl[kFTake]._cnt = 0;
+}
+
+void CGE2Engine::snSetRef(Sprite *spr, int val) {
+ if (spr)
+ spr->_ref = val;
+}
+
+void CGE2Engine::snFlash(bool on) {
+ if (on) {
+ Dac *pal = (Dac *)malloc(sizeof(Dac) * kPalCount);
+ if (pal) {
+ memcpy(pal, _vga->_sysPal, kPalSize);
+ for (int i = 0; i < kPalCount; i++) {
+ register int c;
+ c = pal[i]._r << 1;
+ pal[i]._r = (c < 64) ? c : 63;
+ c = pal[i]._g << 1;
+ pal[i]._g = (c < 64) ? c : 63;
+ c = pal[i]._b << 1;
+ pal[i]._b = (c < 64) ? c : 63;
+ }
+ _vga->setColors(pal, 64);
+ }
+
+ free(pal);
+ } else
+ _vga->setColors(_vga->_sysPal, 64);
+ _dark = false;
+}
+
+void CGE2Engine::snCycle(int cnt) {
+ _vga->_rot._len = cnt;
+}
+
+void CGE2Engine::snWalk(Sprite *spr, int val) {
+ if (isHero(spr)) {
+ if (val < kMaxPoint)
+ ((Hero *)spr)->walkTo(*_point[val]);
+ else {
+ Sprite *s = _vga->_showQ->locate(val);
+ if (s)
+ ((Hero *)spr)->walkTo(s);
+ }
+ ((Hero *)spr)->_time = 1;
+ }
+}
+
+void CGE2Engine::snReach(Sprite *spr, int val) {
+ if (isHero(spr))
+ ((Hero *)spr)->reach(val);
+}
+
+void CGE2Engine::snSound(Sprite *spr, int wav, Audio::Mixer::SoundType soundType) {
+ if (wav == -1)
+ _sound->stop();
+ else {
+ if (_sound->_smpinf._counter && wav < 20)
+ return;
+ if (_soundStat._wait && ((wav & 255) > 80))
+ return;
+
+ _soundStat._ref[1] = wav;
+ _soundStat._ref[0] = !_fx->exist(_soundStat._ref[1]);
+ _sound->play(soundType, _fx->load(_soundStat._ref[1], _soundStat._ref[0]),
+ (spr) ? (spr->_pos2D.x / (kScrWidth / 16)) : 8);
+ }
+}
+
+void CGE2Engine::snRoom(Sprite *spr, bool on) {
+ if (!isHero(spr))
+ return;
+
+ int sex = spr->_ref & 1;
+ Sprite **p = _heroTab[sex]->_pocket;
+ if (on) {
+ if (freePockets(sex) == 0 && p[kPocketMax] == nullptr) {
+ SWAP(p[kPocketMax], p[kPocketMax - 1]);
+ snHide(p[kPocketMax], 1);
+ }
+ } else if (p[kPocketMax]) {
+ for (int i = 0; i < kPocketMax; i++) {
+ if (p[i] == nullptr) {
+ snHide(p[kPocketMax], 0);
+ SWAP(p[kPocketMax], p[i]);
+ break;
+ }
+ }
+ }
+}
+
+void CGE2Engine::snGhost(Bitmap *bmp) {
+ V2D p(this, bmp->_map & 0xFFFF, bmp->_map >> 16);
+ bmp->hide(p);
+ bmp->release();
+ delete[] bmp->_b;
+ bmp->_b = nullptr;
+ delete bmp;
+ bmp = nullptr;
+}
+
+void CGE2Engine::snSay(Sprite *spr, int val) {
+ if (spr && spr->active() && _commandHandler->_talkEnable) {
+ //-- mouth animation
+ if (isHero(spr) && spr->seqTest(-1))
+ ((Hero *)spr)->say();
+ if (_sayCap)
+ _text->say(_text->getText(val), spr);
+ if (_sayVox) {
+ int i = val;
+ if (i < 256)
+ i -= 100;
+ int16 oldRepeat = _sound->getRepeat();
+ _sound->setRepeat(1);
+ snSound(spr, i, Audio::Mixer::kSpeechSoundType);
+ _sound->setRepeat(oldRepeat);
+ _soundStat._wait = &_sound->_smpinf._counter;
+ }
+ }
+}
+
+void CGE2Engine::hide1(Sprite *spr) {
+ _commandHandlerTurbo->addCommand(kCmdGhost, -1, 0, spr->ghost());
+}
+
+void CGE2Engine::swapInPocket(Sprite *spr, Sprite *xspr) {
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < kPocketMax; j++) {
+ Sprite *&poc = _heroTab[i]->_pocket[j];
+ if (poc == spr) {
+ spr->_flags._kept = false;
+ poc = xspr;
+ xspr->_flags._kept = true;
+ xspr->_flags._port = false;
+ return;
+ }
+ }
+ }
+}
+
+Sprite *CGE2Engine::expandSprite(Sprite *spr) {
+ if (spr)
+ _vga->_showQ->insert(spr);
+ return spr;
+}
+
+void CGE2Engine::qGame() {
+ // Write out the user's progress
+ saveGame(0, Common::String("Automatic Savegame"));
+
+ busy(false);
+ _vga->sunset();
+ _endGame = true;
+}
+
+void CGE2Engine::xScene() {
+ sceneDown();
+ sceneUp(_req);
+}
+
+void CommandHandler::addCommand(CommandType com, int ref, int val, void *ptr) {
+ if (ref == -2)
+ ref = 142 - _vm->_sex;
+ Command *headCmd = &_commandList[_head++];
+ headCmd->_commandType = com;
+ headCmd->_ref = ref;
+ headCmd->_val = val;
+ headCmd->_spritePtr = ptr;
+ headCmd->_cbType = kNullCB;
+ if (headCmd->_commandType == kCmdClear) {
+ clear();
+ }
+}
+
+void CommandHandler::addCallback(CommandType com, int ref, int val, CallbackType cbType) {
+ Command *headCmd = &_commandList[_head++];
+ headCmd->_commandType = com;
+ headCmd->_ref = ref;
+ headCmd->_val = val;
+ headCmd->_spritePtr = nullptr;
+ headCmd->_cbType = cbType;
+ if (headCmd->_commandType == kCmdClear) {
+ _tail = _head;
+ _vm->killText();
+ _timerExpiry = 0;
+ }
+}
+
+void CommandHandler::insertCommand(CommandType com, int ref, int val, void *ptr) {
+ if (ref == -2)
+ ref = 142 - _vm->_sex;
+ --_tail;
+ Command *tailCmd = &_commandList[_tail];
+ tailCmd->_commandType = com;
+ tailCmd->_ref = ref;
+ tailCmd->_val = val;
+ tailCmd->_spritePtr = ptr;
+ tailCmd->_cbType = kNullCB;
+ if (com == kCmdClear) {
+ _tail = _head;
+ _vm->killText();
+ _timerExpiry = 0;
+ }
+}
+
+bool CommandHandler::idle() {
+ return (!_vm->_waitRef && _head == _tail);
+}
+
+void CommandHandler::clear() {
+ _tail = _head;
+ _vm->killText();
+ _timerExpiry = 0;
+}
+
+int CommandHandler::getComId(const char *com) {
+ int i = _vm->takeEnum(_commandText, com);
+ return (i < 0) ? i : i + kCmdCom0 + 1;
+}
+
+const char *CommandHandler::getComStr(CommandType cmdType) {
+ return _commandText[cmdType - kCmdNop];
+}
+
+void CGE2Engine::feedSnail(Sprite *spr, Action snq, Hero *hero) {
+ if (!spr || !spr->active())
+ return;
+
+ int cnt = spr->_actionCtrl[snq]._cnt;
+ if (cnt) {
+ byte ptr = spr->_actionCtrl[snq]._ptr;
+ CommandHandler::Command *comtab = spr->snList(snq);
+ CommandHandler::Command *c = &comtab[ptr];
+ CommandHandler::Command *q = &comtab[cnt];
+
+ if (hero != nullptr) {
+ int pocFre = freePockets(hero->_ref & 1);
+ int pocReq = 0;
+ CommandHandler::Command *p = c;
+ for (; p < q && p->_commandType != kCmdNext; p++) { // scan commands
+ // drop from pocket?
+ if ((p->_commandType == kCmdSend && p->_val != _now)
+ || p->_commandType == kCmdGive) {
+ int ref = p->_ref;
+ if (ref < 0)
+ ref = spr->_ref;
+ if (findActivePocket(ref) >= 0)
+ --pocReq;
+ }
+ // make/dispose additional room?
+ if (p->_commandType == kCmdRoom) {
+ if (p->_val == 0)
+ ++pocReq;
+ else
+ --pocReq;
+ }
+ // put into pocket?
+ if (p->_commandType == kCmdKeep)
+ ++pocReq;
+ // overloaded?
+ if (pocReq > pocFre) {
+ pocFul();
+ return;
+ }
+ }
+ }
+
+ while (c < q) {
+ if ((c->_val == -1) && (c->_commandType == kCmdWalk || c->_commandType == kCmdReach))
+ c->_val = spr->_ref;
+
+ if (c->_commandType == kCmdNext) {
+ Sprite *s;
+
+ switch (c->_ref) {
+ case -2:
+ s = hero;
+ break;
+ case -1:
+ s = spr;
+ break;
+ default:
+ s = _vga->_showQ->locate(c->_ref);
+ break;
+ }
+
+ if (s && s->_actionCtrl[snq]._cnt) {
+ int v;
+ switch (c->_val) {
+ case -1:
+ v = int(c - comtab + 1);
+ break;
+ case -2:
+ v = int(c - comtab);
+ break;
+ case -3:
+ v = -1;
+ break;
+ default:
+ v = c->_val;
+ if ((v > 255) && s)
+ v = s->labVal(snq, v >> 8);
+ break;
+ }
+ if (v >= 0)
+ s->_actionCtrl[snq]._ptr = v;
+ }
+
+ if (s == spr)
+ break;
+ }
+
+ _commandHandler->addCommand(c->_commandType, c->_ref, c->_val, spr);
+
+ ++c;
+ }
+ }
+
+}
+
+} // End of namespace CGE2.
diff --git a/engines/cge2/snail.h b/engines/cge2/snail.h
new file mode 100644
index 0000000000..7e618daac8
--- /dev/null
+++ b/engines/cge2/snail.h
@@ -0,0 +1,129 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_SNAIL_H
+#define CGE2_SNAIL_H
+
+#include "cge2/cge2.h"
+
+namespace CGE2 {
+
+#define kCommandFrameRate 80
+#define kCommandFrameDelay (1000 / kCommandFrameRate)
+#define kNoByte -1 // Recheck this! We have no proof for it's original value.
+
+
+enum CommandType {
+ kCmdCom0 = 128,
+ kCmdNop, // NOP :: do nothing
+ kCmdUse, // USE <spr> <cav>|<lab> :: hint for using
+ kCmdPause, // PAUSE -1 <dly> :: delay <dly>/72 seconds
+ kCmdInf, // INF -1 <ref> :: show text referrenced by <ref>
+ kCmdCave, // CAVE -1 <cav> :: go to board <cav>
+ kCmdSetX, // SETX <x> <idx> :: set sprite shift in x axis
+ kCmdSetY, // SETX <y> <idx> :: set sprite shift in y axis
+ kCmdSetZ, // SETX <z> <idx> :: set sprite shift in z axis
+ kCmdAdd, // ADD <idx1> <idx2> :: sum vectors
+ kCmdFlash, // FLASH -1 0|1 :: lighten whole image (on/off)
+ kCmdCycle, // CYCLE <cnt> :: rotate <cnt> colors from 1
+ kCmdClear, // CLEAR -1 0 :: clear kCmdAIL queue
+ kCmdMouse, // MOUSE -1 0|1 :: enable mouse (on/off)
+ kCmdMap, // MAP 0|1 0 :: temporarily turn off map for hero
+ kCmdMidi, // MIDI -1 <midi> :: play MIDI referenced by <midi> (-1 = off)
+
+ kCmdSpr,
+
+ kCmdWait, // WAIT <spr> <seq>|-1 :: wait for SEQ <seq> (-1 = freeze)
+ kCmdHide, // HIDE <spr> 0|1 :: visibility of sprite
+ kCmdRoom, // ROOM <hero> 0|1 :: additional room in pocket (no/yes)
+ kCmdSay, // SAY <spr> <ref> :: say text referenced by <ref>
+ kCmdSound, // SOUND <spr> <ref> :: play sound effect referenced by <ref>
+ kCmdKill, // KILL <spr> 0 :: remove sprite
+ kCmdRSeq, // RSEQ <spr> <nr> :: relative jump SEQ <nr> lines
+ kCmdSeq, // SEQ <spr> <seq> :: jump to certain SEQ
+ kCmdSend, // SEND <spr> <cav> :: move sprite to board <cav>
+ kCmdSwap, // SWAP <spr1> spr2> :: sprite exchange
+ kCmdKeep, // KEEP <spr> <seq> :: take sprite into pocket and jump to <seq>
+ kCmdGive, // GIVE <spr> <seq> :: remove sprite from pocket and jump to <seq>
+ kCmdGetPos, // GETPOS <spr> <idx> :: take sprite's position
+ kCmdGoto, // GOTO <spr> <idx> :: move sprite to position
+ kCmdPort, // PORT <spr> 0|1 :: clear/set "takeability" of sprite
+ kCmdNext, // NEXT <spr> <nr> :: jump to <nr> - NEAR or TAKE
+ kCmdNNext, // NNEXT <spr> <nr> :: jump to <nr> - NEAR
+ kCmdMTNext, // MTNEXT <spr> <nr> :: jump to <nr> - TAKE
+ kCmdFTNext, // FTNEXT <spr> <nr> :: jump to <nr> - TAKE
+ kCmdRNNext, // RNNEXT <spr> <nr> :: relative jump to <nr> - NEAR
+ kCmdRMTNext, // RMTNEXT <spr> <nr> :: relative jump to <nr> - TAKE
+ kCmdRFTNext, // RFTNEXT <spr> <nr> :: relative jump to <nr> - TAKE
+ kCmdRMNear, // RMNEAR <spr> 0 :: remove NEAR list
+ kCmdRMMTake, // RMMTAKE <spr> 0 :: remove TAKE list
+ kCmdRMFTake, // RMFTAKE <spr> 0 :: remove TAKE list
+ kCmdSetRef, // SETREF <spr> <ref> :: change reference of sprite <spr> to <ref>
+ kCmdWalk, // WALKTO <hero> <ref>|<point> :: go close to the sprite or point
+ kCmdReach, // REACH <hero> <ref>|<m> :: reach the sprite or point with <m> method
+ kCmdCover, // COVER <sp1> <sp2> :: cover sprite <sp1> with sprite <sp2>
+ kCmdUncover, // UNCOVER <sp1> <sp2> :: restore the state before COVER
+
+ kCmdExec,
+ kCmdGhost
+};
+
+class CommandHandler {
+public:
+ struct Command {
+ CommandType _commandType;
+ byte _lab;
+ int _ref;
+ int _val;
+ void *_spritePtr;
+ CallbackType _cbType;
+ } *_commandList;
+ static const char *_commandText[];
+ bool _talkEnable;
+
+ CommandHandler(CGE2Engine *vm, bool turbo);
+ ~CommandHandler();
+ void runCommand();
+ void addCommand(CommandType com, int ref, int val, void *ptr);
+ void addCallback(CommandType com, int ref, int val, CallbackType cbType);
+ void insertCommand(CommandType com, int ref, int val, void *ptr);
+ bool idle();
+ void clear();
+ int getComId(const char *com);
+ const char *getComStr(CommandType cmdType);
+private:
+ CGE2Engine *_vm;
+ bool _turbo;
+ uint8 _head;
+ uint8 _tail;
+ bool _textDelay;
+ uint32 _timerExpiry; // "pause" in the original.
+};
+
+} // End of namespace CGE2
+
+#endif
diff --git a/engines/cge2/sound.cpp b/engines/cge2/sound.cpp
new file mode 100644
index 0000000000..57ec5983e8
--- /dev/null
+++ b/engines/cge2/sound.cpp
@@ -0,0 +1,273 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/sound.h"
+#include "common/config-manager.h"
+#include "common/memstream.h"
+#include "audio/decoders/raw.h"
+#include "audio/audiostream.h"
+#include "cge2/cge2.h"
+
+namespace CGE2 {
+
+DataCk::DataCk(byte *buf, int bufSize) {
+ _buf = buf;
+ _ckSize = bufSize;
+}
+
+DataCk::~DataCk() {
+ free(_buf);
+}
+
+Sound::Sound(CGE2Engine *vm) : _vm(vm) {
+ _audioStream = nullptr;
+ _soundRepeatCount = 1;
+ open();
+}
+
+Sound::~Sound() {
+ close();
+}
+
+void Sound::close() {
+ _vm->_midiPlayer->killMidi();
+}
+
+void Sound::open() {
+ setRepeat(1);
+ if (_vm->_commandHandlerTurbo != nullptr)
+ _vm->switchSay();
+ play(Audio::Mixer::kSFXSoundType, _vm->_fx->load(99, 99));
+}
+
+void Sound::setRepeat(int16 count) {
+ _soundRepeatCount = count;
+}
+
+int16 Sound::getRepeat() {
+ return _soundRepeatCount;
+}
+
+void Sound::play(Audio::Mixer::SoundType soundType, DataCk *wav, int pan) {
+ if (wav) {
+ stop();
+ _smpinf._saddr = &*(wav->addr());
+ _smpinf._slen = (uint16)wav->size();
+ _smpinf._span = pan;
+ _smpinf._counter = getRepeat();
+ sndDigiStart(&_smpinf, soundType);
+ }
+}
+
+void Sound::sndDigiStart(SmpInfo *PSmpInfo, Audio::Mixer::SoundType soundType) {
+ // Create an audio stream wrapper for sound
+ Common::MemoryReadStream *stream = new Common::MemoryReadStream(PSmpInfo->_saddr,
+ PSmpInfo->_slen, DisposeAfterUse::NO);
+ _audioStream = Audio::makeWAVStream(stream, DisposeAfterUse::YES);
+
+ // Decide which handle to use
+ Audio::SoundHandle *handle = nullptr;
+ switch (soundType) {
+ case Audio::Mixer::kSFXSoundType:
+ handle = &_sfxHandle;
+ break;
+ case Audio::Mixer::kSpeechSoundType:
+ handle = &_speechHandle;
+ break;
+ default:
+ error("Wrong sound type passed to sndDigiStart()");
+ }
+
+ // Start the new sound
+ _vm->_mixer->playStream(soundType, handle,
+ Audio::makeLoopingAudioStream(_audioStream, (uint)PSmpInfo->_counter));
+
+ // CGE pan:
+ // 8 = Center
+ // Less = Left
+ // More = Right
+ _vm->_mixer->setChannelBalance(*handle, (int8)CLIP(((PSmpInfo->_span - 8) * 16), -127, 127));
+}
+
+void Sound::stop() {
+ sndDigiStop(_sfxHandle);
+ sndDigiStop(_speechHandle);
+ _audioStream = nullptr;
+}
+
+void Sound::checkSoundHandles() {
+ if (!_vm->_mixer->isSoundHandleActive(_speechHandle) && !_vm->_mixer->isSoundHandleActive(_sfxHandle))
+ _smpinf._counter = 0;
+}
+
+void Sound::sndDigiStop(Audio::SoundHandle &handle) {
+ if (_vm->_mixer->isSoundHandleActive(handle))
+ _vm->_mixer->stopHandle(handle);
+}
+
+Fx::Fx(CGE2Engine *vm, int size) : _current(nullptr), _vm(vm) {
+}
+
+Fx::~Fx() {
+ clear();
+}
+
+void Fx::clear() {
+ if (_current)
+ delete _current;
+ _current = nullptr;
+}
+
+Common::String Fx::name(int ref, int sub) {
+ const char *fxname = "%.2dfx%.2d.WAV";
+ const char *subName = "%.2dfx%.2d?.WAV";
+ const char *p = (sub) ? subName : fxname;
+ Common::String filename = Common::String::format(p, ref >> 8, ref & 0xFF);
+ if (sub)
+ filename.setChar('@' + sub, 6);
+ return filename;
+}
+
+bool Fx::exist(int ref, int sub) {
+ return _vm->_resman->exist(name(ref, sub).c_str());
+}
+
+DataCk *Fx::load(int ref, int sub) {
+ Common::String filename = name(ref, sub);
+ EncryptedStream file(_vm, filename.c_str());
+ clear();
+ return (_current = loadWave(&file));
+}
+
+DataCk *Fx::loadWave(EncryptedStream *file) {
+ byte *data = (byte *)malloc(file->size());
+
+ if (!data)
+ return 0;
+
+ file->read(data, file->size());
+
+ return new DataCk(data, file->size());
+}
+
+MusicPlayer::MusicPlayer(CGE2Engine *vm) : _vm(vm) {
+ _data = nullptr;
+ _isGM = false;
+
+ MidiPlayer::createDriver();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ // TODO: Load cmf.ins with the instrument table. It seems that an
+ // interface for such an operation is supported for AdLib. Maybe for
+ // this card, setting instruments is necessary.
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+ _dataSize = -1;
+}
+
+MusicPlayer::~MusicPlayer() {
+ killMidi();
+}
+
+void MusicPlayer::killMidi() {
+ Audio::MidiPlayer::stop();
+
+ free(_data);
+ _data = nullptr;
+}
+
+void MusicPlayer::loadMidi(int ref) {
+ if (_vm->_midiNotify != nullptr)
+ (_vm->*_vm->_midiNotify)();
+
+ // Work out the filename and check the given MIDI file exists
+ Common::String filename = Common::String::format("%.2dSG%.2d.MID", ref >> 8, ref & 0xFF);
+ if (!_vm->_resman->exist(filename.c_str()))
+ return;
+
+ // Stop any currently playing MIDI file
+ killMidi();
+
+ // Read in the data for the file
+ EncryptedStream mid(_vm, filename.c_str());
+ _dataSize = mid.size();
+ _data = (byte *)malloc(_dataSize);
+ mid.read(_data, _dataSize);
+
+ // Start playing the music
+ sndMidiStart();
+}
+
+void MusicPlayer::sndMidiStart() {
+ _isGM = true;
+
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_data, _dataSize)) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(_driver->getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+ _parser = parser;
+
+ syncVolume();
+
+ // Al the tracks are supposed to loop
+ _isLooping = true;
+ _isPlaying = true;
+ }
+}
+
+void MusicPlayer::send(uint32 b) {
+ if (((b & 0xF0) == 0xC0) && !_isGM && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+
+ Audio::MidiPlayer::send(b);
+}
+
+void MusicPlayer::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // If a new channel is allocated during the playback, make sure
+ // its volume is correctly initialized.
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
+ }
+
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/sound.h b/engines/cge2/sound.h
new file mode 100644
index 0000000000..6673b67b7a
--- /dev/null
+++ b/engines/cge2/sound.h
@@ -0,0 +1,131 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_SOUND_H
+#define CGE2_SOUND_H
+
+#include "cge2/fileio.h"
+#include "audio/audiostream.h"
+#include "audio/decoders/wave.h"
+#include "audio/fmopl.h"
+#include "audio/mididrv.h"
+#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
+#include "audio/mixer.h"
+#include "common/memstream.h"
+
+namespace CGE2 {
+
+class CGE2Engine;
+
+// sample info
+struct SmpInfo {
+ const uint8 *_saddr; // address
+ uint16 _slen; // length
+ uint16 _span; // left/right pan (0-15)
+ int _counter; // number of time the sample should be played
+};
+
+class DataCk {
+ byte *_buf;
+ int _ckSize;
+public:
+ DataCk(byte *buf, int bufSize);
+ ~DataCk();
+ inline const byte *addr() {
+ return _buf;
+ }
+ inline int size() {
+ return _ckSize;
+ }
+};
+
+class Sound {
+public:
+ SmpInfo _smpinf;
+
+ Sound(CGE2Engine *vm);
+ ~Sound();
+ void open();
+ void close();
+ void play(Audio::Mixer::SoundType soundType, DataCk *wav, int pan = 8);
+ int16 getRepeat();
+ void setRepeat(int16 count);
+ void stop();
+ void checkSoundHandles();
+private:
+ int _soundRepeatCount;
+ CGE2Engine *_vm;
+ Audio::SoundHandle _sfxHandle;
+ Audio::SoundHandle _speechHandle;
+ Audio::RewindableAudioStream *_audioStream;
+
+ void sndDigiStart(SmpInfo *PSmpInfo, Audio::Mixer::SoundType soundType);
+ void sndDigiStop(Audio::SoundHandle &handle);
+};
+
+class Fx {
+ CGE2Engine *_vm;
+
+ DataCk *loadWave(EncryptedStream *file);
+ Common::String name(int ref, int sub);
+public:
+ DataCk *_current;
+
+ Fx(CGE2Engine *vm, int size);
+ ~Fx();
+ void clear();
+ bool exist(int ref, int sub = 0);
+ DataCk *load(int ref, int sub = 0);
+};
+
+class MusicPlayer: public Audio::MidiPlayer {
+private:
+ CGE2Engine *_vm;
+ byte *_data;
+ int _dataSize;
+ bool _isGM;
+
+ // Start MIDI File
+ void sndMidiStart();
+
+ // Stop MIDI File
+ void sndMidiStop();
+public:
+ MusicPlayer(CGE2Engine *vm);
+ ~MusicPlayer();
+
+ void loadMidi(int ref);
+ void killMidi();
+
+ virtual void send(uint32 b);
+ virtual void sendToChannel(byte channel, uint32 b);
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_SOUND_H
diff --git a/engines/cge2/spare.cpp b/engines/cge2/spare.cpp
new file mode 100644
index 0000000000..76bdbfa7ef
--- /dev/null
+++ b/engines/cge2/spare.cpp
@@ -0,0 +1,128 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/spare.h"
+
+namespace CGE2 {
+
+void Spare::sync(Common::Serializer &s) {
+ int size = 0;
+ if (s.isSaving()) {
+ for (uint i = 0; i < _container.size(); i++)
+ if (_container[i]->_ref >= 141)
+ size++;
+ s.syncAsSint16LE(size);
+
+ for (uint i = 0; i < _container.size(); i++) {
+ if (_container[i]->_ref >= 141)
+ _container[i]->sync(s);
+ }
+ } else {
+ s.syncAsSint16LE(size);
+
+ for (int i = 0; i < size; i++) {
+ Sprite *sprite = new Sprite(_vm);
+ sprite->sync(s);
+ update(sprite);
+ }
+ }
+}
+
+void Spare::clear() {
+ for (uint i = 0; i < _container.size(); i++)
+ delete _container[i];
+
+ _container.clear();
+}
+
+Sprite *Spare::locate(int ref) {
+ for (uint i = 0; i < _container.size(); ++i) {
+ if (_container[i]->_ref == ref)
+ return _container[i];
+ }
+ return nullptr;
+}
+
+Sprite *Spare::take(int ref) {
+ Sprite *spr = nullptr;
+ if ((spr = locate(ref)) != nullptr) {
+ for (uint i = 0; i < _container.size(); ++i) {
+ if (spr == _container[i]) {
+ _container.remove_at(i);
+ break;
+ }
+ }
+ }
+ return spr;
+}
+
+void Spare::takeScene(int cav) {
+ int bakRef = cav << 8;
+ Common::Array<Sprite*> tempCont = _container;
+ for (uint i = 0; i < tempCont.size(); ++i) {
+ Sprite *spr = tempCont[i];
+ int c = spr->_scene;
+ if ((c == _vm->_now || c == 0) && spr->_ref != bakRef) {
+ spr = locate(spr->_ref);
+ _vm->_vga->_showQ->insert(spr);
+ }
+ }
+}
+
+void Spare::store(Sprite *spr) {
+ _container.push_back(spr);
+}
+
+void Spare::update(Sprite *spr) {
+ Sprite *sp = locate(spr->_ref);
+ if (sp == nullptr)
+ store(spr);
+ else {
+ sp->contract();
+ *sp = *spr;
+ }
+}
+
+void Spare::dispose(Sprite *spr) {
+ if (spr) {
+ _vm->_vga->_showQ->remove(spr);
+ update(spr->contract());
+ }
+}
+
+void Spare::dispose(int ref) {
+ dispose(_vm->_vga->_showQ->locate(ref));
+}
+
+void Spare::dispose() {
+ for (uint i = 0; i < _container.size(); ++i) {
+ if (_container[i]->_ref > 255)
+ dispose(_container[i]);
+ }
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/spare.h b/engines/cge2/spare.h
new file mode 100644
index 0000000000..7dc6ce60f5
--- /dev/null
+++ b/engines/cge2/spare.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_SPARE_H
+#define CGE2_SPARE_H
+
+#include "cge2/vga13h.h"
+
+namespace CGE2 {
+
+class Spare {
+ CGE2Engine *_vm;
+ Common::Array<Sprite*> _container;
+public:
+ Spare(CGE2Engine *vm) : _vm(vm) {}
+ ~Spare() { clear(); }
+ void store(Sprite *spr);
+ Sprite *locate(int ref);
+ Sprite *take(int ref);
+ void takeScene(int cav);
+ void update(Sprite *spr);
+ void dispose(Sprite *spr);
+ void dispose(int ref);
+ void dispose();
+ void sync(Common::Serializer &s);
+ uint16 count() { return _container.size(); }
+ void clear();
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_SPARE_H
diff --git a/engines/cge2/talk.cpp b/engines/cge2/talk.cpp
new file mode 100644
index 0000000000..9109da90f1
--- /dev/null
+++ b/engines/cge2/talk.cpp
@@ -0,0 +1,312 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/general.h"
+#include "cge2/talk.h"
+
+namespace CGE2 {
+
+void CGE2Engine::setAutoColors() {
+ Dac def[4] = {
+ { 0, 0, 0 },
+ { 220 >> 2, 220 >> 2, 220 >> 2 },
+ { 190 >> 2, 190 >> 2, 190 >> 2 },
+ { 160 >> 2, 160 >> 2, 160 >> 2 },
+ };
+ Dac pal[kPalCount];
+ _vga->getColors(pal);
+ for (int i = 0; i < 4; i++)
+ _font->_colorSet[kCBRel][i] = _vga->closest(pal, def[i]);
+}
+
+Font::Font(CGE2Engine *vm) : _vm(vm) {
+ _map = new uint8[kMapSize];
+ _pos = new uint16[kPosSize];
+ _widthArr = new uint8[kWidSize];
+
+ load();
+}
+
+Font::~Font() {
+ delete[] _map;
+ delete[] _pos;
+ delete[] _widthArr;
+}
+
+void Font::load() {
+ char path[10];
+ strcpy(path, "CGE.CFT");
+ if (!_vm->_resman->exist(path))
+ error("Missing Font file! %s", path);
+
+ EncryptedStream fontFile(_vm, path);
+ assert(!fontFile.err());
+
+ fontFile.read(_widthArr, kWidSize);
+ assert(!fontFile.err());
+
+ uint16 p = 0;
+ for (uint16 i = 0; i < kPosSize; i++) {
+ _pos[i] = p;
+ p += _widthArr[i];
+ }
+ fontFile.read(_map, p);
+
+ strcpy(path, "CGE.TXC");
+ if (!_vm->_resman->exist(path))
+ error("Missing Color file! %s", path);
+
+ // Reading in _colorSet:
+ EncryptedStream colorFile(_vm, path);
+ assert(!colorFile.err());
+
+ char tmpStr[kLineMax + 1];
+ int n = 0;
+
+ for (Common::String line = colorFile.readLine(); !colorFile.eos(); line = colorFile.readLine()){
+ if (line.empty())
+ continue;
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+ _colorSet[n][0] = _vm->number(tmpStr);
+
+ for (int i = 1; i < 4; i++)
+ _colorSet[n][i] = _vm->number(nullptr);
+
+ n++;
+ }
+}
+
+uint16 Font::width(const char *text) {
+ uint16 w = 0;
+ if (!text)
+ return 0;
+ while (*text)
+ w += _widthArr[(unsigned char)*(text++)];
+ return w;
+}
+
+Talk::Talk(CGE2Engine *vm, const char *text, TextBoxStyle mode, ColorBank color, bool wideSpace)
+ : Sprite(vm), _mode(mode), _created(false), _wideSpace(wideSpace), _vm(vm) {
+ _color = _vm->_font->_colorSet[color];
+
+ if (color == kCBRel)
+ _vm->setAutoColors();
+ update(text);
+}
+
+Talk::Talk(CGE2Engine *vm, ColorBank color)
+ : Sprite(vm), _mode(kTBPure), _created(false), _wideSpace(false), _vm(vm) {
+ _color = _vm->_font->_colorSet[color];
+
+ if (color == kCBRel)
+ _vm->setAutoColors();
+}
+
+uint8 *Talk::box(V2D siz) {
+ uint16 n, r = (_mode == kTBRound) ? kTextRoundCorner : 0;
+ const byte lt = _color[1], bg = _color[2], dk = _color[3];
+
+ if (siz.x < 8)
+ siz.x = 8;
+ if (siz.y < 8)
+ siz.y = 8;
+ uint8 *b = new uint8[n = siz.area()];
+ memset(b, bg, n);
+
+ if (_mode) {
+ uint8 *p = b;
+ uint8 *q = b + n - siz.x;
+ memset(p, lt, siz.x);
+ memset(q, dk, siz.x);
+ while (p < q) {
+ p += siz.x;
+ *(p - 1) = dk;
+ *p = lt;
+ }
+ p = b;
+ for (int i = 0; i < r; i++) {
+ int j = 0;
+ for (; j < r - i; j++) {
+ p[j] = kPixelTransp;
+ p[siz.x - j - 1] = kPixelTransp;
+ q[j] = kPixelTransp;
+ q[siz.x - j - 1] = kPixelTransp;
+ }
+ p[j] = lt;
+ p[siz.x - j - 1] = dk;
+ q[j] = lt;
+ q[siz.x - j - 1] = dk;
+ p += siz.x;
+ q -= siz.x;
+ }
+ }
+ return b;
+}
+
+void Talk::update(const char *text) {
+ const uint16 vmarg = (_mode) ? kTextVMargin : 0;
+ const uint16 hmarg = (_mode) ? kTextHMargin : 0;
+ uint16 mw;
+ uint16 mh;
+ uint16 ln = vmarg;
+ uint8 *m;
+ uint8 *map;
+ uint8 fg = _color[0];
+
+ if (_created) {
+ mw = _ext->_shpList->_w;
+ mh = _ext->_shpList->_h;
+ delete _ext->_shpList;
+ } else {
+ uint16 k = 2 * hmarg;
+ mh = 2 * vmarg + kFontHigh;
+ mw = 0;
+ for (const char *p = text; *p; p++) {
+ if ((*p == '|') || (*p == '\n')) {
+ mh += kFontHigh + kTextLineSpace;
+ if (k > mw)
+ mw = k;
+ k = 2 * hmarg;
+ } else if ((*p == 0x20) && (_vm->_font->_widthArr[(unsigned char)*p] > 4) && (!_wideSpace))
+ k += _vm->_font->_widthArr[(unsigned char)*p] - 2;
+ else
+ k += _vm->_font->_widthArr[(unsigned char)*p];
+ }
+ if (k > mw)
+ mw = k;
+
+ _created = true;
+ }
+
+ V2D sz(_vm, mw, mh);
+ map = box(sz);
+
+ m = map + ln * mw + hmarg;
+
+ while (*text) {
+ if ((*text == '|') || (*text == '\n'))
+ m = map + (ln += kFontHigh + kTextLineSpace) * mw + hmarg;
+ else {
+ int cw = _vm->_font->_widthArr[(unsigned char)*text];
+ uint8 *f = _vm->_font->_map + _vm->_font->_pos[(unsigned char)*text];
+
+ // Handle properly space size, after it was enlarged to display properly
+ // 'F1' text.
+ int8 fontStart = 0;
+ if ((*text == 0x20) && (cw > 4) && (!_wideSpace))
+ fontStart = 2;
+
+ for (int i = fontStart; i < cw; i++) {
+ uint8 *pp = m;
+ uint16 n;
+ uint16 b = *(f++);
+ for (n = 0; n < kFontHigh; n++) {
+ if (b & 1)
+ *pp = fg;
+ b >>= 1;
+ pp += mw;
+ }
+ m++;
+ }
+ }
+ text++;
+ }
+ BitmapPtr b = new Bitmap[1];
+ b[0] = Bitmap(_vm, sz.x, sz.y, map);
+ delete[] map;
+ setShapeList(b, 1);
+}
+
+InfoLine::InfoLine(CGE2Engine *vm, uint16 w, ColorBank color)
+: Talk(vm), _oldText(nullptr), _newText(nullptr), _realTime(false), _vm(vm) {
+ _wideSpace = false;
+ BitmapPtr b = new Bitmap[1];
+ if (color == kCBRel)
+ _vm->setAutoColors();
+ _color = _vm->_font->_colorSet[color];
+ V2D siz = V2D(_vm, w, kFontHigh);
+ b[0] = Bitmap(_vm, siz.x, siz.y, _color[2]);
+ setShapeList(b, 1);
+}
+
+void InfoLine::update(const char *text) {
+ if (!_realTime && (text == _oldText))
+ return;
+
+ _oldText = text;
+
+ uint16 w = _ext->_shpList->_w;
+ uint16 h = _ext->_shpList->_h;
+ uint8 *v = _ext->_shpList->_v;
+ uint16 dsiz = w >> 2; // data size (1 plane line size)
+ uint16 lsiz = 2 + dsiz + 2; // uint16 for line header, uint16 for gap
+ uint16 psiz = h * lsiz; // - last gape, but + plane trailer
+ uint16 size = 4 * psiz; // whole map size
+ uint8 fg = _color[0];
+ uint8 bg = _color[2];
+
+ // clear whole rectangle
+ memset(v + 2, bg, dsiz); // data bytes
+ for (byte *pDest = v + lsiz; pDest < (v + psiz); pDest += lsiz) {
+ Common::copy(v, v + lsiz, pDest);
+ }
+ *(uint16 *)(v + psiz - 2) = TO_LE_16(kBmpEOI); // plane trailer uint16
+ for (byte *pDest = v + psiz; pDest < (v + 4 * psiz); pDest += psiz) {
+ Common::copy(v, v + psiz, pDest);
+ }
+
+ // paint text line
+ if (_newText) {
+ uint8 *p = v + 2, *q = p + size;
+
+ while (*text) {
+ uint16 cw = _vm->_font->_widthArr[(unsigned char)*text];
+ uint8 *fp = _vm->_font->_map + _vm->_font->_pos[(unsigned char)*text];
+
+ // Handle properly space size, after it was enlarged to display properly
+ // 'F1' text.
+ int8 fontStart = 0;
+ if ((*text == 0x20) && (cw > 4) && (!_wideSpace))
+ fontStart = 2;
+
+ for (int i = fontStart; i < cw; i++) {
+ uint16 b = fp[i];
+ for (uint16 n = 0; n < kFontHigh; n++) {
+ if (b & 1)
+ *p = fg;
+ b >>= 1;
+ p += lsiz;
+ }
+ if (p >= q)
+ p = p - size + 1;
+ }
+ text++;
+ }
+ }
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/talk.h b/engines/cge2/talk.h
new file mode 100644
index 0000000000..d7484655cc
--- /dev/null
+++ b/engines/cge2/talk.h
@@ -0,0 +1,94 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_TALK_H
+#define CGE2_TALK_H
+
+#include "cge2/general.h"
+#include "cge2/vga13h.h"
+
+namespace CGE2 {
+
+#define kTextHMargin (6&~1) // EVEN horizontal margins!
+#define kTextVMargin 5 // vertical margins
+#define kTextLineSpace 2 // line spacing
+#define kTextRoundCorner 3 // rounded corners
+#define kWidSize 256
+#define kPosSize 256
+#define kMapSize (256*8)
+#define kFontHigh 8
+#define kCaptionSide 24
+#define kInfName 101
+#define kSayName 102
+
+class Font {
+ void load();
+ CGE2Engine *_vm;
+public:
+ uint8 *_widthArr;
+ uint16 *_pos;
+ uint8 *_map;
+ uint8 _colorSet[kColorNum][4];
+ Font(CGE2Engine *vm);
+ ~Font();
+ uint16 width(const char *text);
+};
+
+enum TextBoxStyle { kTBPure, kTBRect, kTBRound };
+
+class Talk : public Sprite {
+protected:
+ TextBoxStyle _mode;
+ bool _created;
+ uint8 *box(V2D siz);
+ bool _wideSpace;
+public:
+ uint8 *_color;
+
+ Talk(CGE2Engine *vm, const char *text, TextBoxStyle mode = kTBPure, ColorBank color = kCBStd, bool wideSpace = false);
+ Talk(CGE2Engine *vm, ColorBank color = kCBStd);
+
+ void update(const char *text);
+private:
+ CGE2Engine *_vm;
+};
+
+class InfoLine : public Talk {
+ const char *_oldText, *_newText;
+public:
+ bool _realTime;
+ InfoLine(CGE2Engine *vm, uint16 wid, ColorBank color = kCBStd);
+ void update(const char *text);
+ void update() { update(_newText); }
+ void setText(const char *txt) { _newText = txt; }
+private:
+ CGE2Engine *_vm;
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_TALK_H
diff --git a/engines/cge2/text.cpp b/engines/cge2/text.cpp
new file mode 100644
index 0000000000..d51c04843d
--- /dev/null
+++ b/engines/cge2/text.cpp
@@ -0,0 +1,197 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/text.h"
+#include "common/str.h"
+
+namespace CGE2 {
+
+Text::Text(CGE2Engine *vm, const char *fname) : _vm(vm) {
+ _vm->mergeExt(_fileName, fname, kSayExt);
+ if (!_vm->_resman->exist(_fileName))
+ error("No talk (%s)", _fileName);
+ _txtCount = count();
+ if (_txtCount == -1)
+ error("Unable to read dialog file %s", _fileName);
+
+ _txtCount += 2;
+ _cache = new Handler[_txtCount];
+ for (_size = 0; _size < _txtCount; _size++) {
+ _cache[_size]._ref = 0;
+ _cache[_size]._text = nullptr;
+ }
+ load();
+
+ _cache[_txtCount - 1]._ref = -1;
+ _cache[_txtCount - 1]._text = new char[3];
+ strcpy(_cache[_txtCount - 1]._text, "");
+}
+
+Text::~Text() {
+ clear();
+ delete[] _cache;
+}
+
+int16 Text::count() {
+ EncryptedStream tf(_vm, _fileName);
+ if (tf.err())
+ return -1;
+
+ Common::String line;
+ char tmpStr[kLineMax + 1];
+
+ int counter = 0;
+
+ for (line = tf.readLine(); !tf.eos(); line = tf.readLine()) {
+ char *s;
+ assert(line.size() <= 513);
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+ if ((s = strtok(tmpStr, " =,;/\t\n")) == nullptr)
+ continue;
+ if (!Common::isDigit(*s))
+ continue;
+
+ counter++;
+ }
+ return counter;
+}
+
+void Text::clear() {
+ for (int i = 0; i < _txtCount; i++) {
+ if (_cache[i]._ref) {
+ _cache[i]._ref = 0;
+ delete[] _cache[i]._text;
+ _cache[i]._text = nullptr;
+ }
+ }
+}
+
+void Text::load() {
+ EncryptedStream tf(_vm, _fileName);
+ assert(!tf.err());
+
+ Common::String line;
+ char tmpStr[kLineMax + 1];
+ int idx;
+
+ for (idx = 0, line = tf.readLine(); !tf.eos(); line = tf.readLine()) {
+ int n = line.size();
+ char *s;
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+ if ((s = strtok(tmpStr, " =,;/\t\n")) == nullptr)
+ continue;
+ if (!Common::isDigit(*s))
+ continue;
+
+ int r = _vm->number(s);
+
+ s += strlen(s);
+ if (s < tmpStr + n)
+ ++s;
+
+ _cache[idx]._ref = r;
+ _cache[idx]._text = new char[strlen(s) + 1];
+ strcpy(_cache[idx]._text, s);
+ idx++;
+ }
+}
+
+char *Text::getText(int ref) {
+ int i;
+ for (i = 0; (i < _size) && (_cache[i]._ref != ref); i++)
+ ;
+
+ if (i < _size)
+ return _cache[i]._text;
+
+ warning("getText: Unable to find ref %d:%d", ref / 256, ref % 256);
+ return nullptr;
+}
+
+void Text::say(const char *text, Sprite *spr) {
+ _vm->killText();
+
+ _vm->_talk = new Talk(_vm, text, kTBRound, kCBSay);
+
+ Speaker *speaker = new Speaker(_vm);
+
+ bool east = spr->_flags._east;
+ V2D d(_vm, 20, spr->_siz.y - 2);
+ if (!east)
+ d.x = -d.x;
+ if (_vm->isHero(spr))
+ d = d.scale(spr->_pos3D._z.trunc());
+ V2D pos = spr->_pos2D + d;
+ uint16 sw = (speaker->_siz.x >> 1);
+ if (!east)
+ sw = -sw;
+
+ if (east) {
+ if (pos.x + sw + kTextRoundCorner + kCaptionSide >= kScrWidth)
+ east = false;
+ } else if (pos.x <= kCaptionSide + kTextRoundCorner - sw)
+ east = true;
+
+ if (east != (d.x > 0)) {
+ d.x = -d.x;
+ sw = -sw;
+ }
+ pos.x = spr->_pos2D.x + d.x + sw;
+
+ _vm->_talk->_flags._kill = true;
+ _vm->_talk->setName(getText(kSayName));
+ _vm->_talk->gotoxyz(pos.x, pos.y + speaker->_siz.y - 1, 0);
+
+ speaker->gotoxyz(pos.x, _vm->_talk->_pos3D._y.trunc() - speaker->_siz.y + 1, 0);
+ speaker->_flags._slav = true;
+ speaker->_flags._kill = true;
+ speaker->setName(getText(kSayName));
+ speaker->step(east);
+
+ _vm->_vga->_showQ->append(_vm->_talk);
+ _vm->_vga->_showQ->append(speaker);
+}
+
+void CGE2Engine::inf(const char *text, ColorBank col) {
+ killText();
+ _talk = new Talk(this, text, kTBRect, col, true);
+ _talk->_flags._kill = true;
+ _talk->setName(_text->getText(kInfName));
+ _talk->center();
+ _vga->_showQ->append(_talk);
+}
+
+void Text::sayTime(Sprite *spr) {
+ TimeDate curTime;
+ _vm->_system->getTimeAndDate(curTime);
+
+ char t[6];
+ snprintf(t, 6, "%d:%02d", curTime.tm_hour, curTime.tm_min);
+ say(t, spr);
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/text.h b/engines/cge2/text.h
new file mode 100644
index 0000000000..88ed501158
--- /dev/null
+++ b/engines/cge2/text.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.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_TEXT_H
+#define CGE2_TEXT_H
+
+#include "cge2/talk.h"
+#include "cge2/cge2.h"
+
+namespace CGE2 {
+
+#define kSayExt ".SAY"
+#define kSysTextMax 1000
+#define kTextNoMouse 95
+#define kInfName 101
+#define kSayName 102
+#define kInfRef 301
+#define kSayRef 302
+
+
+class Text {
+ struct Handler {
+ int _ref;
+ char *_text;
+ } *_cache;
+ int _size;
+ int16 _txtCount;
+ char _fileName[kPathMax];
+ void load();
+ int16 count();
+public:
+ Text(CGE2Engine *vm, const char *fname);
+ ~Text();
+ void clear();
+ char *getText(int ref);
+ void say(const char *text, Sprite *spr);
+ void sayTime(Sprite *spr);
+private:
+ CGE2Engine *_vm;
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_TEXT_H
diff --git a/engines/cge2/toolbar.cpp b/engines/cge2/toolbar.cpp
new file mode 100644
index 0000000000..0cd220c984
--- /dev/null
+++ b/engines/cge2/toolbar.cpp
@@ -0,0 +1,224 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "sound.h"
+#include "common/config-manager.h"
+#include "cge2/cge2.h"
+#include "cge2/events.h"
+#include "cge2/vmenu.h"
+#include "cge2/text.h"
+#include "cge2/cge2_main.h"
+
+namespace CGE2 {
+
+#define kSoundNumToStateRate 25.7
+// == 257 / 10; where 10 equals to the volume switches' number of states [0..9]
+// and ScummVM has a scale of 257 different values for setting sounds.
+
+#define kSoundStateToNumRate 28.45
+// == 256 / 9 + 0.1; where 256 is the positive range of numbers we can set the volume to
+// and the 10 states of a switch cut this range up to 9 equally big parts.
+// We don't take into account 0 regarding the 256 different values (it would be the 257th),
+// since 0 * x == 0.
+// 0.1 is only for correct rounding at the 10th state.
+
+void CGE2Engine::optionTouch(int opt, uint16 mask) {
+ bool notMuted = !ConfMan.getBool("mute");
+ switch (opt) {
+ case 1:
+ if (mask & kMouseLeftUp)
+ switchColorMode();
+ break;
+ case 2:
+ if ((mask & kMouseLeftUp) && notMuted)
+ switchMusic();
+ break;
+ case 3:
+ if (mask & kMouseLeftUp)
+ quit();
+ break;
+ case 4:
+ if ((mask & (kMouseLeftUp | kMouseRightUp)) && notMuted)
+ setVolume(opt - 4, (mask & kMouseLeftUp) ? 1 : -1);
+ break;
+ case 5:
+ if ((mask & (kMouseLeftUp | kMouseRightUp)) && notMuted)
+ setVolume(opt - 4, (mask & kMouseLeftUp) ? 1 : -1);
+ break;
+ case 8:
+ if ((mask & kMouseLeftUp) && notMuted)
+ switchCap();
+ break;
+ case 9:
+ if ((mask & kMouseLeftUp) && notMuted)
+ switchVox();
+ break;
+ default:
+ break;
+ }
+}
+
+void CGE2Engine::switchColorMode() {
+ _commandHandlerTurbo->addCommand(kCmdSeq, 121, _vga->_mono = !_vga->_mono, nullptr);
+ ConfMan.setBool("enable_color_blind", _vga->_mono);
+ ConfMan.flushToDisk();
+ keyClick();
+ _vga->setColors(_vga->_sysPal, 64);
+}
+
+void CGE2Engine::switchMusic() {
+ _music = !_music;
+ _mixer->muteSoundType(Audio::Mixer::kMusicSoundType, !_music);
+ _commandHandlerTurbo->addCommand(kCmdSeq, kMusicRef, _music, nullptr);
+ keyClick();
+ _commandHandlerTurbo->addCommand(kCmdMidi, -1, _music ? (_now << 8) : -1, nullptr);
+}
+
+void CGE2Engine::quit() {
+ if (_commandHandler->idle()) {
+ if (VMenu::_addr) {
+ _commandHandlerTurbo->addCommand(kCmdKill, -1, 0, VMenu::_addr);
+ ReturnToGameChoice rqsChoice(this);
+ rqsChoice.proc();
+ } else {
+ Common::Array<Choice *> quitMenu; // Deleted in VMenu's destructor.
+ quitMenu.push_back(new ExitGameChoice(this));
+ quitMenu.push_back(new ReturnToGameChoice(this));
+ (new VMenu(this, quitMenu, V2D(this, -1, -1), kCBMnu))->setName(_text->getText(kQuitTitle));
+ _commandHandlerTurbo->addCommand(kCmdSeq, kPowerRef, 0, nullptr);
+ keyClick();
+ }
+ }
+}
+
+void CGE2Engine::setVolume(int idx, int cnt) {
+ if (cnt && _vol[idx]) {
+ int p = _vol[idx]->_seqPtr + cnt;
+ if ((p >= 0) && (p < _vol[idx]->_seqCnt)) {
+ _vol[idx]->step(p);
+ int newVolume = (int)(p * kSoundStateToNumRate);
+ switch (idx) {
+ case 0:
+ _oldSfxVolume = ConfMan.getInt("sfx_volume");
+ ConfMan.setInt("sfx_volume", newVolume);
+ break;
+ case 1:
+ _oldMusicVolume = ConfMan.getInt("music_volume");
+ ConfMan.setInt("music_volume", newVolume);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void CGE2Engine::checkVolumeSwitches() {
+ int musicVolume = ConfMan.getInt("music_volume");
+ if (musicVolume != _oldMusicVolume)
+ _vol[1]->step((int)(musicVolume / kSoundNumToStateRate));
+
+ int sfxVolume = ConfMan.getInt("sfx_volume");
+ if (sfxVolume != _oldSfxVolume)
+ _vol[0]->step((int)(sfxVolume / kSoundNumToStateRate));
+}
+
+void CGE2Engine::switchCap() {
+ _sayCap = !_sayCap;
+ if (!_sayCap)
+ _sayVox = true;
+ keyClick();
+ switchSay();
+}
+
+void CGE2Engine::switchVox() {
+ _sayVox = !_sayVox;
+ _mixer->muteSoundType(Audio::Mixer::kSpeechSoundType, _sayVox);
+ if (!_sayVox)
+ _sayCap = true;
+ keyClick();
+ switchSay();
+}
+
+void CGE2Engine::switchSay() {
+ _commandHandlerTurbo->addCommand(kCmdSeq, 129, _sayVox, nullptr);
+ _commandHandlerTurbo->addCommand(kCmdSeq, 128, _sayCap, nullptr);
+}
+
+void CGE2Engine::initToolbar() {
+ selectPocket(-1);
+
+ _commandHandlerTurbo->addCommand(kCmdSeq, kMusicRef, _music, nullptr);
+ if (!_music)
+ _midiPlayer->killMidi();
+
+ switchSay();
+
+ _infoLine->gotoxyz(V3D(kInfoX, kInfoY, 0));
+ _infoLine->setText(nullptr);
+ _vga->_showQ->insert(_infoLine);
+
+ _gamePhase = kPhaseInGame;
+ _mouse->center();
+ _mouse->off();
+ _mouse->on();
+
+ _keyboard->setClient(_sys);
+ _commandHandler->addCommand(kCmdSeq, kPowerRef, 1, nullptr);
+
+ _busyPtr = _vga->_showQ->locate(kBusyRef);
+
+ _vol[0] = _vga->_showQ->locate(kDvolRef);
+ _vol[1] = _vga->_showQ->locate(kMvolRef);
+
+ if (_vol[0]) {
+ int val = ConfMan.getInt("sfx_volume");
+ initVolumeSwitch(_vol[0], val);
+ }
+
+ if (_vol[1]) {
+ int val = ConfMan.getInt("music_volume");
+ initVolumeSwitch(_vol[1], val);
+ }
+}
+
+void CGE2Engine::initVolumeSwitch(Sprite *volSwitch, int val) {
+ int state = 0;
+ state = (int)(val / kSoundNumToStateRate);
+ volSwitch->step(state);
+}
+
+void CGE2Engine::checkMute() {
+ bool mute = ConfMan.getBool("mute");
+ if (mute != _muteAll) {
+ switchMusic();
+ switchVox();
+ _muteAll = mute;
+ }
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp
new file mode 100644
index 0000000000..227633579e
--- /dev/null
+++ b/engines/cge2/vga13h.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "common/array.h"
+#include "common/config-manager.h"
+#include "common/rect.h"
+#include "graphics/palette.h"
+#include "cge2/general.h"
+#include "cge2/vga13h.h"
+#include "cge2/bitmap.h"
+#include "cge2/text.h"
+#include "cge2/cge2_main.h"
+#include "cge2/cge2.h"
+#include "cge2/vga13h.h"
+
+namespace CGE2 {
+
+void V3D::sync(Common::Serializer &s) {
+ _x.sync(s);
+ _y.sync(s);
+ _z.sync(s);
+}
+
+FXP FXP::operator*(const FXP& x) const {
+ FXP y;
+ int32 t1 = (v >> 8) * x.v;
+ int32 t2 = ((v & 0xFF) * x.v) >> 8;
+
+ y.v = t1 + t2;
+ return y;
+}
+
+FXP FXP::operator/(const FXP& x) const {
+ FXP y;
+ if (x.v != 0) {
+ int32 v1 = this->v;
+ int32 v2 = x.v;
+ bool negFlag = false;
+
+ if (v1 < 0) {
+ v1 = -v1;
+ negFlag = true;
+ }
+ if (v2 < 0) {
+ v2 = -v2;
+ negFlag ^= true;
+ }
+
+ int32 v3 = v1 / v2;
+ v1 -= v3 * v2;
+ v3 <<= 8;
+
+ if (v1 < 0xFFFFFF)
+ v1 <<= 8;
+ else
+ v2 >>= 8;
+
+ v3 += v1 / v2;
+
+ if (negFlag)
+ v3 = -v3;
+
+ y.v = v3;
+ }
+
+ return y;
+}
+
+void FXP::sync(Common::Serializer &s) {
+ s.syncAsSint32LE(v);
+}
+
+Seq *getConstantSeq(bool seqFlag) {
+ const Seq seq1[] = { { 0, 0, 0, 0, 0, 0 } };
+ const Seq seq2[] = { { 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 0, 0, 0 } };
+
+ Seq *seq;
+ if (seqFlag) {
+ seq = (Seq *)malloc(1 * sizeof(Seq));
+ *seq = seq1[0];
+ } else {
+ seq = (Seq *)malloc(2 * sizeof(Seq));
+ seq[0] = seq2[0];
+ seq[1] = seq2[1];
+ }
+
+ return seq;
+}
+
+byte Sprite::_constY = 0;
+byte Sprite::_follow = 0;
+
+Seq Sprite::_stdSeq8[] =
+{ { 0, 0, 0, 0, 0, 0 },
+ { 1, 1, 0, 0, 0, 0 },
+ { 2, 2, 0, 0, 0, 0 },
+ { 3, 3, 0, 0, 0, 0 },
+ { 4, 4, 0, 0, 0, 0 },
+ { 5, 5, 0, 0, 0, 0 },
+ { 6, 6, 0, 0, 0, 0 },
+ { 7, 7, 0, 0, 0, 0 },
+};
+
+SprExt::SprExt(CGE2Engine *vm)
+ : _p0(vm, 0, 0), _p1(vm, 0, 0),
+ _b0(nullptr), _b1(nullptr), _shpList(nullptr),
+ _location(0), _seq(nullptr), _name(nullptr) {
+ for (int i = 0; i < kActions; i++)
+ _actions[i] = nullptr;
+}
+
+Sprite::Sprite(CGE2Engine *vm)
+ : _siz(_vm, 0, 0), _seqPtr(kNoSeq), _seqCnt(0), _shpCnt(0),
+ _next(nullptr), _prev(nullptr), _time(0),
+ _ext(nullptr), _ref(-1), _scene(0), _vm(vm),
+ _pos2D(_vm, kScrWidth >> 1, 0), _pos3D(kScrWidth >> 1, 0, 0) {
+ memset(_actionCtrl, 0, sizeof(_actionCtrl));
+ memset(_file, 0, sizeof(_file));
+ memset(&_flags, 0, sizeof(_flags));
+ _flags._frnt = 1;
+}
+
+Sprite::Sprite(CGE2Engine *vm, BitmapPtr shpP, int cnt)
+ : _siz(_vm, 0, 0), _seqPtr(kNoSeq), _seqCnt(0), _shpCnt(0),
+ _next(nullptr), _prev(nullptr), _time(0),
+ _ext(nullptr), _ref(-1), _scene(0), _vm(vm),
+ _pos2D(_vm, kScrWidth >> 1, 0), _pos3D(kScrWidth >> 1, 0, 0) {
+ memset(_actionCtrl, 0, sizeof(_actionCtrl));
+ memset(_file, 0, sizeof(_file));
+ memset(&_flags, 0, sizeof(_flags));
+ _flags._frnt = 1;
+
+ setShapeList(shpP, cnt);
+}
+
+Sprite::~Sprite() {
+ contract();
+}
+
+BitmapPtr Sprite::getShp() {
+ SprExt *e = _ext;
+ if (!e || !e->_seq)
+ return nullptr;
+
+ int i = e->_seq[_seqPtr]._now;
+ if (i >= _shpCnt)
+ error("Invalid PHASE in SPRITE::Shp() %s - %d", _file, i);
+ return e->_shpList + i;
+}
+
+void Sprite::setShapeList(BitmapPtr shp, int cnt) {
+ _shpCnt = cnt;
+ _siz.x = 0;
+ _siz.y = 0;
+
+ if (shp) {
+ for (int i = 0; i < cnt; i++) {
+ BitmapPtr p = shp + i;
+ if (p->_w > _siz.x)
+ _siz.x = p->_w;
+ if (p->_h > _siz.y)
+ _siz.y = p->_h;
+ }
+ expand();
+ _ext->_shpList = shp;
+ if (!_ext->_seq) {
+ setSeq(_stdSeq8);
+ _seqCnt = (cnt < ARRAYSIZE(_stdSeq8)) ? cnt : ARRAYSIZE(_stdSeq8);
+ }
+ }
+}
+
+Seq *Sprite::setSeq(Seq *seq) {
+ expand();
+
+ Seq *s = _ext->_seq;
+ _ext->_seq = seq;
+ if (_seqPtr == kNoSeq)
+ step(0);
+ else if (_time == 0)
+ step(_seqPtr);
+ return s;
+}
+
+bool Sprite::seqTest(int n) {
+ if (n >= 0)
+ return (_seqPtr == n);
+ if (_ext)
+ return (_ext->_seq[_seqPtr]._next == _seqPtr);
+ return true;
+}
+
+void Sprite::setName(char *newName) {
+ if (!_ext)
+ return;
+
+ if (_ext->_name) {
+ delete[] _ext->_name;
+ _ext->_name = nullptr;
+ }
+ if (newName) {
+ _ext->_name = new char[strlen(newName) + 1];
+ strcpy(_ext->_name, newName);
+ }
+}
+
+int Sprite::labVal(Action snq, int lab) {
+ int lv = -1;
+ if (active()) {
+ int count = _actionCtrl[snq]._cnt;
+ CommandHandler::Command *com = snList(snq);
+
+ int i = 0;
+ for (; i < count; i++) {
+ if (com[i]._lab == lab)
+ break;
+ }
+
+ if (i < count)
+ return i;
+ } else {
+ char tmpStr[kLineMax + 1];
+ _vm->mergeExt(tmpStr, _file, kSprExt);
+
+ if (_vm->_resman->exist(tmpStr)) { // sprite description file exist
+ EncryptedStream sprf(_vm, tmpStr);
+ if (sprf.err())
+ error("Bad SPR [%s]", tmpStr);
+
+ int cnt = 0;
+ ID section = kIdPhase;
+ ID id;
+ Common::String line;
+
+ while (lv == -1 && !sprf.eos()) {
+ line = sprf.readLine();
+ if (line.empty())
+ continue;
+
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+
+ char *p;
+ p = _vm->token(tmpStr);
+
+ if (*p == '@') {
+ if ((int)section == (int)snq && atoi(p + 1) == lab)
+ lv = cnt;
+ } else {
+ id = _vm->ident(p);
+ switch (id) {
+ case kIdMTake:
+ case kIdFTake:
+ case kIdNear:
+ case kIdPhase:
+ case kIdSeq:
+ section = id;
+ break;
+ default:
+ if (id < 0 && (int)section == (int)snq)
+ ++cnt;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return lv;
+}
+
+CommandHandler::Command *Sprite::snList(Action type) {
+ SprExt *e = _ext;
+ return (e) ? e->_actions[type] : nullptr;
+}
+
+Sprite *Sprite::expand() {
+ if (_ext)
+ return this;
+
+ if (_vm->_spriteNotify != nullptr)
+ (_vm->*_vm->_spriteNotify)();
+
+ char fname[kPathMax];
+ _vm->mergeExt(fname, _file, kSprExt);
+
+ if (_ext != nullptr)
+ delete _ext;
+ _ext = new SprExt(_vm);
+
+ if (!*_file)
+ return this;
+
+ BitmapPtr shplist = new Bitmap[_shpCnt];
+
+ int cnt[kActions],
+ shpcnt = 0,
+ seqcnt = 0,
+ maxnow = 0,
+ maxnxt = 0;
+
+ for (int i = 0; i < kActions; i++)
+ cnt[i] = 0;
+
+ for (int i = 0; i < kActions; i++){
+ byte n = _actionCtrl[i]._cnt;
+ if (n)
+ _ext->_actions[i] = new CommandHandler::Command[n];
+ else
+ _ext->_actions[i] = nullptr;
+ }
+
+ Seq *curSeq = nullptr;
+ if (_seqCnt)
+ curSeq = new Seq[_seqCnt];
+
+ if (_vm->_resman->exist(fname)) { // sprite description file exist
+ EncryptedStream sprf(_vm, fname);
+ if (sprf.err())
+ error("Bad SPR [%s]", fname);
+
+ int label = kNoByte;
+ ID section = kIdPhase;
+ ID id;
+ Common::String line;
+ char tmpStr[kLineMax + 1];
+
+ for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) {
+ if (line.empty())
+ continue;
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+
+ char *p = _vm->token(tmpStr);
+ if (*p == '@') {
+ label = atoi(p + 1);
+ continue;
+ }
+
+ id = _vm->ident(p);
+ switch (id) {
+ case kIdType:
+ break;
+ case kIdNear:
+ case kIdMTake:
+ case kIdFTake:
+ case kIdPhase:
+ case kIdSeq:
+ section = id;
+ break;
+ case kIdName:
+ Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+ for (p = tmpStr; *p != '='; p++) // We search for the =
+ ;
+ setName(_vm->tail(p));
+ break;
+ default:
+ if (id >= kIdNear)
+ break;
+ Seq *s;
+ switch (section) {
+ case kIdNear:
+ case kIdMTake:
+ case kIdFTake:
+ id = (ID)_vm->_commandHandler->getComId(p);
+ if (_actionCtrl[section]._cnt) {
+ CommandHandler::Command *c = &_ext->_actions[section][cnt[section]++];
+ c->_commandType = CommandType(id);
+ c->_lab = label;
+ c->_ref = _vm->number(nullptr);
+ c->_val = _vm->number(nullptr);
+ c->_spritePtr = nullptr;
+ }
+ break;
+ case kIdSeq:
+ s = &curSeq[seqcnt++];
+ s->_now = atoi(p);
+ if (s->_now > maxnow)
+ maxnow = s->_now;
+ s->_next = _vm->number(nullptr);
+ switch (s->_next) {
+ case 0xFF:
+ s->_next = seqcnt;
+ break;
+ case 0xFE:
+ s->_next = seqcnt - 1;
+ break;
+ }
+ if (s->_next > maxnxt)
+ maxnxt = s->_next;
+ s->_dx = _vm->number(nullptr);
+ s->_dy = _vm->number(nullptr);
+ s->_dz = _vm->number(nullptr);
+ s->_dly = _vm->number(nullptr);
+ break;
+ case kIdPhase:
+ shplist[shpcnt] = Bitmap(_vm, p);
+ shpcnt++;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ label = kNoByte;
+ }
+
+ if (!shpcnt)
+ error("No shapes - %s", fname);
+ } else // no sprite description: try to read immediately from .BMP
+ shplist[shpcnt++] = Bitmap(_vm, _file);
+
+ if (curSeq) {
+ if (maxnow >= shpcnt)
+ error("Bad PHASE in SEQ %s", fname);
+ if (maxnxt && (maxnxt >= seqcnt))
+ error("Bad JUMP in SEQ %s", fname);
+ setSeq(curSeq);
+ } else {
+ setSeq(_stdSeq8);
+ _seqCnt = (shpcnt < ARRAYSIZE(_stdSeq8)) ? shpcnt : ARRAYSIZE(_stdSeq8);
+ }
+
+ setShapeList(shplist, shpcnt);
+
+ if (_file[2] == '~') { // FLY-type sprite
+ Seq *nextSeq = _ext->_seq;
+ int x = (nextSeq + 1)->_dx, y = (nextSeq + 1)->_dy, z = (nextSeq + 1)->_dz;
+ // random position
+ nextSeq->_dx = _vm->newRandom(x + x) - x;
+ nextSeq->_dy = _vm->newRandom(y + y) - y;
+ nextSeq->_dz = _vm->newRandom(z + z) - z;
+ gotoxyz(_pos3D + V3D(nextSeq->_dx, nextSeq->_dy, nextSeq->_dz));
+ }
+
+ return this;
+}
+
+Sprite *Sprite::contract() {
+ SprExt *e = _ext;
+ if (!e)
+ return this;
+
+ if (_file[2] == '~') { // FLY-type sprite
+ Seq *curSeq = _ext->_seq;
+ // return to middle
+ gotoxyz(_pos3D - V3D(curSeq->_dx, curSeq->_dy, curSeq->_dz));
+ curSeq->_dx = curSeq->_dy = curSeq->_dz = 0;
+ }
+
+ if (_vm->_spriteNotify != nullptr)
+ (_vm->*_vm->_spriteNotify)();
+
+ if (e->_name) {
+ delete[] e->_name;
+ e->_name = nullptr;
+ }
+
+ if (e->_shpList) {
+ for (int i = 0; i < _shpCnt; i++)
+ e->_shpList[i].release();
+ delete[] e->_shpList;
+ e->_shpList = nullptr;
+ }
+
+ if (e->_seq) {
+ if (e->_seq == _stdSeq8)
+ _seqCnt = 0;
+ else {
+ delete[] e->_seq;
+ e->_seq = nullptr;
+ }
+ }
+
+ for (int i = 0; i < kActions; i++) {
+ if (e->_actions[i]) {
+ delete[] e->_actions[i];
+ e->_actions[i] = nullptr;
+ }
+ }
+
+ delete _ext;
+ _ext = nullptr;
+
+ return this;
+}
+
+void Sprite::backShow() {
+ expand();
+ show(2);
+ show(1);
+ _vm->_spare->dispose(this);
+}
+
+void Sprite::step(int nr) {
+ if (nr >= 0)
+ _seqPtr = nr;
+
+ if (_ext && _ext->_seq) {
+ V3D p = _pos3D;
+ Seq *seq = nullptr;
+
+ if (nr < 0)
+ _seqPtr = _ext->_seq[_seqPtr]._next;
+
+ if (_file[2] == '~') { // FLY-type sprite
+ seq = _ext->_seq;
+ // return to middle
+ p._x -= seq->_dx;
+ p._y -= seq->_dy;
+ p._z -= seq->_dz;
+ // generate motion
+ if (_vm->newRandom(10) < 5) {
+ if ((seq + 1)->_dx)
+ seq->_dx += _vm->newRandom(3) - 1;
+ if ((seq + 1)->_dy)
+ seq->_dy += _vm->newRandom(3) - 1;
+ if ((seq + 1)->_dz)
+ seq->_dz += _vm->newRandom(3) - 1;
+ }
+ if (seq->_dx < -(seq + 1)->_dx)
+ seq->_dx += 2;
+ if (seq->_dx >= (seq + 1)->_dx)
+ seq->_dx -= 2;
+ if (seq->_dy < -(seq + 1)->_dy)
+ seq->_dy += 2;
+ if (seq->_dy >= (seq + 1)->_dy)
+ seq->_dy -= 2;
+ if (seq->_dz < -(seq + 1)->_dz)
+ seq->_dz += 2;
+ if (seq->_dz >= (seq + 1)->_dz)
+ seq->_dz -= 2;
+ p._x += seq->_dx;
+ p._y += seq->_dy;
+ p._z += seq->_dz;
+ gotoxyz(p);
+ } else {
+ seq = _ext->_seq + _seqPtr;
+ if (seq) {
+ if (seq->_dz == 127 && seq->_dx != 0) {
+ _vm->_commandHandlerTurbo->addCommand(kCmdSound, -1, 256 * seq->_dy + seq->_dx, this);
+ } else {
+ p._x += seq->_dx;
+ p._y += seq->_dy;
+ p._z += seq->_dz;
+ gotoxyz(p);
+ }
+ }
+ }
+ if (seq && (seq->_dly >= 0))
+ _time = seq->_dly;
+ } else if (_vm->_waitRef && _vm->_waitRef == _ref)
+ _vm->_waitRef = 0;
+}
+
+void Sprite::tick() {
+ step();
+}
+
+void Sprite::setScene(int c) {
+ _scene = c;
+}
+
+void Sprite::gotoxyz(int x, int y, int z) {
+ gotoxyz(V3D(x, y, z));
+}
+
+void Sprite::gotoxyz() {
+ gotoxyz(_pos3D);
+}
+
+void Sprite::gotoxyz(V2D pos) {
+ V2D o = _pos2D;
+ int ctr = _siz.x >> 1;
+ int rem = _siz.x - ctr;
+ byte trim = 0;
+
+ if (_ref / 10 == 14) { // HERO
+ int z = _pos3D._z.trunc();
+ ctr = (ctr * _vm->_eye->_z.trunc()) / (_vm->_eye->_z.trunc() - z);
+ rem = (rem * _vm->_eye->_z.trunc()) / (_vm->_eye->_z.trunc() - z);
+ ctr = (ctr * 3) / 4;
+ rem = (rem * 3) / 4;
+ }
+
+ if (pos.x - ctr < 0) {
+ pos.x = ctr;
+ ++trim;
+ }
+ if (pos.x + rem > kScrWidth) {
+ pos.x = kScrWidth - rem;
+ ++trim;
+ }
+ _pos2D.x = pos.x;
+
+ if (pos.y < -kPanHeight) {
+ pos.y = -kPanHeight;
+ ++trim;
+ }
+ if (pos.y + _siz.y > kWorldHeight) {
+ pos.y = kWorldHeight - _siz.y;
+ ++trim;
+ }
+ _pos2D.y = pos.y;
+
+ _flags._trim = (trim != 0);
+
+ if (!_follow) {
+ FXP m = _vm->_eye->_z / (_pos3D._z - _vm->_eye->_z);
+ _pos3D._x = (_vm->_eye->_x + (_vm->_eye->_x - _pos2D.x) / m);
+ _pos3D._x.round();
+
+ if (!_constY) {
+ _pos3D._y = _vm->_eye->_y + (_vm->_eye->_y - _pos2D.y) / m;
+ _pos3D._y.round();
+ }
+ }
+
+ if (_next && _next->_flags._slav)
+ _next->gotoxyz(_next->_pos2D - o + _pos2D);
+
+ if (_flags._shad)
+ _prev->gotoxyz(_prev->_pos2D - o + _pos2D);
+}
+
+void Sprite::gotoxyz_(V2D pos) {
+ _constY++;
+ gotoxyz(pos);
+ --_constY;
+}
+
+void Sprite::gotoxyz(V3D pos) {
+ _follow++;
+ if (pos._z != _pos3D._z)
+ _flags._zmov = true;
+ gotoxyz(V2D(_vm, _pos3D = pos));
+ --_follow;
+}
+
+void Sprite::center() {
+ gotoxyz(kScrWidth >> 1, (kWorldHeight - _siz.y) >> 1, 0);
+}
+
+void Sprite::show() {
+ SprExt *e = _ext;
+ if (e) {
+ e->_p0 = e->_p1;
+ e->_b0 = e->_b1;
+ e->_p1 = _pos2D;
+ e->_b1 = getShp();
+
+ if (!_flags._hide)
+ e->_b1->show(e->_p1);
+ }
+}
+
+void Sprite::show(uint16 pg) {
+ assert(pg < 4);
+ Graphics::Surface *a = _vm->_vga->_page[1];
+ _vm->_vga->_page[1] = _vm->_vga->_page[pg];
+ getShp()->show(_pos2D);
+ _vm->_vga->_page[1] = a;
+}
+
+void Sprite::hide() {
+ SprExt *e = _ext;
+ if (e->_b0)
+ e->_b0->hide(e->_p0);
+}
+
+BitmapPtr Sprite::ghost() {
+ SprExt *e = _ext;
+ if (!e->_b1)
+ return nullptr;
+
+ BitmapPtr bmp = new Bitmap(_vm, 0, 0, (uint8 *)nullptr);
+ bmp->_w = e->_b1->_w;
+ bmp->_h = e->_b1->_h;
+ bmp->_b = new HideDesc[bmp->_h];
+ memcpy(bmp->_b, e->_b1->_b, sizeof(HideDesc)* bmp->_h);
+ uint8 *v = new uint8[1];
+ *v = (e->_p1.y << 16) + e->_p1.x;
+ bmp->_v = v;
+ bmp->_map = (e->_p1.y << 16) + e->_p1.x;
+
+ return bmp;
+}
+
+void Sprite::sync(Common::Serializer &s) {
+ s.syncAsUint16LE(_ref);
+ s.syncAsByte(_scene);
+
+ // bitfield in-memory storage is unpredictable, so to avoid
+ // any issues, pack/unpack everything manually
+ uint16 flags = 0;
+ if (s.isLoading()) {
+ s.syncAsUint16LE(flags);
+ _flags._hide = flags & 0x0001;
+ _flags._drag = flags & 0x0002;
+ _flags._hold = flags & 0x0004;
+ _flags._trim = flags & 0x0008;
+ _flags._slav = flags & 0x0010;
+ _flags._kill = flags & 0x0020;
+ _flags._xlat = flags & 0x0040;
+ _flags._port = flags & 0x0080;
+ _flags._kept = flags & 0x0100;
+ _flags._frnt = flags & 0x0200;
+ _flags._east = flags & 0x0400;
+ _flags._near = flags & 0x0800;
+ _flags._shad = flags & 0x1000;
+ _flags._back = flags & 0x2000;
+ _flags._zmov = flags & 0x4000;
+ _flags._tran = flags & 0x8000;
+ } else {
+ flags = (flags << 1) | (_flags._tran ? 1 : 0);
+ flags = (flags << 1) | (_flags._zmov ? 1 : 0);
+ flags = (flags << 1) | (_flags._back ? 1 : 0);
+ flags = (flags << 1) | (_flags._shad ? 1 : 0);
+ flags = (flags << 1) | (_flags._near ? 1 : 0);
+ flags = (flags << 1) | (_flags._east ? 1 : 0);
+ flags = (flags << 1) | (_flags._frnt ? 1 : 0);
+ flags = (flags << 1) | (_flags._kept ? 1 : 0);
+ flags = (flags << 1) | (_flags._port ? 1 : 0);
+ flags = (flags << 1) | (_flags._xlat ? 1 : 0);
+ flags = (flags << 1) | (_flags._kill ? 1 : 0);
+ flags = (flags << 1) | (_flags._slav ? 1 : 0);
+ flags = (flags << 1) | (_flags._trim ? 1 : 0);
+ flags = (flags << 1) | (_flags._hold ? 1 : 0);
+ flags = (flags << 1) | (_flags._drag ? 1 : 0);
+ flags = (flags << 1) | (_flags._hide ? 1 : 0);
+ s.syncAsUint16LE(flags);
+ }
+
+ s.syncAsSint16LE(_pos2D.x);
+ s.syncAsSint16LE(_pos2D.y);
+
+ _pos3D.sync(s);
+
+ s.syncAsSint16LE(_siz.x);
+ s.syncAsSint16LE(_siz.y);
+
+ s.syncAsUint16LE(_time);
+ for (int i = 0; i < kActions; i++){
+ s.syncAsByte(_actionCtrl[i]._ptr);
+ s.syncAsByte(_actionCtrl[i]._cnt);
+ }
+ s.syncAsSint16LE(_seqPtr);
+ s.syncAsSint16LE(_seqCnt);
+ s.syncAsUint16LE(_shpCnt);
+ s.syncBytes((byte *)&_file[0], 9);
+ _file[8] = '\0';
+}
+
+Queue::Queue(bool show) : _head(nullptr), _tail(nullptr) {
+}
+
+void Queue::append(Sprite *spr) {
+ if (spr->_flags._back)
+ spr->backShow();
+ else {
+ spr->expand();
+ if (_tail) {
+ spr->_prev = _tail;
+ _tail->_next = spr;
+ } else
+ _head = spr;
+
+ _tail = spr;
+ }
+}
+
+void Queue::insert(Sprite *spr, Sprite *nxt) {
+ if (spr->_flags._back)
+ spr->backShow();
+ else {
+ spr->expand();
+ if (nxt == _head) {
+ spr->_next = _head;
+ _head = spr;
+ if (!_tail)
+ _tail = spr;
+ } else {
+ spr->_next = nxt;
+ spr->_prev = nxt->_prev;
+ if (spr->_prev)
+ spr->_prev->_next = spr;
+ }
+ if (spr->_next)
+ spr->_next->_prev = spr;
+ }
+}
+
+void Queue::insert(Sprite *spr) {
+ if (locate(spr))
+ return; // We only queue it if it's not already queued.
+
+ Sprite *s;
+ for (s = _head; s; s = s->_next) {
+ if (s->_pos3D._z < spr->_pos3D._z)
+ break;
+ }
+
+ if (s)
+ insert(spr, s);
+ else
+ append(spr);
+}
+
+Sprite *Queue::remove(Sprite *spr) {
+ if (spr == _head)
+ _head = spr->_next;
+
+ if (spr == _tail)
+ _tail = spr->_prev;
+
+ if (spr->_next)
+ spr->_next->_prev = spr->_prev;
+
+ if (spr->_prev)
+ spr->_prev->_next = spr->_next;
+
+ spr->_prev = nullptr;
+ spr->_next = nullptr;
+ return spr;
+}
+
+Sprite *Queue::locate(int ref) {
+ for (Sprite *spr = _head; spr; spr = spr->_next) {
+ if (spr->_ref == ref)
+ return spr;
+ }
+ return nullptr;
+}
+
+bool Queue::locate(Sprite *spr) {
+ Sprite *s;
+ for (s = _head; s; s = s->_next) {
+ if (s == spr)
+ return true;
+ }
+
+ return false;
+}
+
+Vga::Vga(CGE2Engine *vm) : _frmCnt(0), _msg(nullptr), _name(nullptr), _setPal(false), _vm(vm) {
+ _rot._org = 1;
+ _rot._len = 0;
+ _rot._cnt = 0;
+ _rot._dly = 1;
+
+ _oldColors = nullptr;
+ _newColors = nullptr;
+ _showQ = new Queue(true);
+ _sysPal = new Dac[kPalCount];
+
+ for (int idx = 0; idx < 4; idx++) {
+ _page[idx] = new Graphics::Surface();
+ _page[idx]->create(kScrWidth, kScrHeight, Graphics::PixelFormat::createFormatCLUT8());
+ }
+
+ _mono = ConfMan.getBool("enable_color_blind");
+
+ _oldColors = (Dac *)malloc(sizeof(Dac) * kPalCount);
+ _newColors = (Dac *)malloc(sizeof(Dac) * kPalCount);
+ getColors(_oldColors);
+ sunset();
+ setColors();
+ clear(0);
+}
+
+Vga::~Vga() {
+ Common::String buffer = "";
+
+ free(_oldColors);
+ free(_newColors);
+ if (_msg)
+ buffer = Common::String(_msg);
+
+ if (_name)
+ buffer = buffer + " [" + _name + "]";
+
+ debugN("%s", buffer.c_str());
+
+ delete _showQ;
+ delete[] _sysPal;
+
+ for (int idx = 0; idx < 4; idx++) {
+ _page[idx]->free();
+ delete _page[idx];
+ }
+}
+
+void Vga::waitVR() {
+ // Since some of the game parts rely on using vertical sync as a delay mechanism,
+ // we're introducing a short delay to simulate it
+ g_system->delayMillis(5);
+}
+
+void Vga::getColors(Dac *tab) {
+ byte palData[kPalSize];
+ g_system->getPaletteManager()->grabPalette(palData, 0, kPalCount);
+ palToDac(palData, tab);
+}
+
+uint8 Vga::closest(Dac *pal, const uint8 colR, const uint8 colG, const uint8 colB) {
+#define f(col, lum) ((((uint16)(col)) << 8) / lum)
+ uint16 i, dif = 0xFFFF, found = 0;
+ uint16 L = colR + colG + colB;
+ if (!L)
+ L++;
+ uint16 R = f(colR, L), G = f(colG, L), B = f(colB, L);
+ for (i = 0; i < 256; i++) {
+ uint16 l = pal[i]._r + pal[i]._g + pal[i]._b;
+ if (!l)
+ l++;
+ int r = f(pal[i]._r, l), g = f(pal[i]._g, l), b = f(pal[i]._b, l);
+ uint16 D = ((r > R) ? (r - R) : (R - r)) +
+ ((g > G) ? (g - G) : (G - g)) +
+ ((b > B) ? (b - B) : (B - b)) +
+ ((l > L) ? (l - L) : (L - l)) * 10 ;
+
+ if (D < dif) {
+ found = i;
+ dif = D;
+ if (D == 0)
+ break; // exact!
+ }
+ }
+ return found;
+#undef f
+}
+
+uint8 Vga::closest(Dac *pal, Dac x) {
+ int exp = (sizeof(long) * 8 - 1);
+ long D = (1 << exp) - 1; // Maximum value of long.
+ long R = x._r;
+ long G = x._g;
+ long B = x._b;
+ int idx = 255;
+ for (int n = 0; n < 256; n++) {
+ long dR = R - pal[n]._r;
+ long dG = G - pal[n]._g;
+ long dB = B - pal[n]._b,
+ d = dR * dR + dG * dG + dB * dB;
+ if (d < D) {
+ idx = n;
+ D = d;
+ if (!d)
+ break;
+ }
+ }
+ return idx;
+}
+
+uint8 *Vga::glass(Dac *pal, const uint8 colR, const uint8 colG, const uint8 colB) {
+ uint8 *x = (uint8 *)malloc(256);
+ if (x) {
+ for (uint16 i = 0; i < 256; i++) {
+ x[i] = closest(pal, ((uint16)(pal[i]._r) * colR) / 255,
+ ((uint16)(pal[i]._g) * colG) / 255,
+ ((uint16)(pal[i]._b) * colB) / 255);
+ }
+ }
+ return x;
+}
+
+void Vga::palToDac(const byte *palData, Dac *tab) {
+ const byte *colP = palData;
+ for (int idx = 0; idx < kPalCount; idx++, colP += 3) {
+ tab[idx]._r = *colP >> 2;
+ tab[idx]._g = *(colP + 1) >> 2;
+ tab[idx]._b = *(colP + 2) >> 2;
+ }
+}
+
+void Vga::dacToPal(const Dac *tab, byte *palData) {
+ for (int idx = 0; idx < kPalCount; idx++, palData += 3) {
+ *palData = tab[idx]._r << 2;
+ *(palData + 1) = tab[idx]._g << 2;
+ *(palData + 2) = tab[idx]._b << 2;
+ }
+}
+
+void Vga::setColors(Dac *tab, int lum) {
+ Dac *palP = tab, *destP = _newColors;
+ for (int idx = 0; idx < kPalCount; idx++, palP++, destP++) {
+ destP->_r = (palP->_r * lum) >> 6;
+ destP->_g = (palP->_g * lum) >> 6;
+ destP->_b = (palP->_b * lum) >> 6;
+ }
+
+ if (_mono) {
+ destP = _newColors;
+ for (int idx = 0; idx < kPalCount; idx++, destP++) {
+ // Form a grayscale color from 30% R, 59% G, 11% B
+ uint8 intensity = (((int)destP->_r * 77) + ((int)destP->_g * 151) + ((int)destP->_b * 28)) >> 8;
+ destP->_r = intensity;
+ destP->_g = intensity;
+ destP->_b = intensity;
+ }
+ }
+
+ _setPal = true;
+}
+
+void Vga::setColors() {
+ memset(_newColors, 0, kPalSize);
+ updateColors();
+}
+
+void Vga::sunrise(Dac *tab) {
+ for (int i = 0; i <= 64; i += kFadeStep) {
+ setColors(tab, i);
+ waitVR();
+ updateColors();
+ g_system->updateScreen();
+ }
+}
+
+void Vga::sunset() {
+ Dac tab[256];
+ getColors(tab);
+ for (int i = 64; i >= 0; i -= kFadeStep) {
+ setColors(tab, i);
+ waitVR();
+ updateColors();
+ g_system->updateScreen();
+ }
+}
+
+void Vga::show() {
+ _vm->_infoLine->update();
+
+ for (Sprite *spr = _showQ->first(); spr; spr = spr->_next) {
+ spr->show();
+ }
+
+ _vm->_mouse->show();
+ update();
+ rotate();
+
+ for (Sprite *spr = _showQ->first(); spr; spr = spr->_next) {
+ spr->hide();
+ if (spr->_flags._zmov) {
+ Sprite *s = nullptr;
+ Sprite *p = spr->_prev;
+ Sprite *n = spr->_next;
+
+ if (spr->_flags._shad) {
+ s = p;
+ p = s->_prev;
+ }
+
+ if ((p && spr->_pos3D._z > p->_pos3D._z) ||
+ (n && spr->_pos3D._z < n->_pos3D._z)) {
+ _showQ->insert(_showQ->remove(spr));
+ }
+ spr->_flags._zmov = false;
+ }
+ }
+ _vm->_mouse->hide();
+}
+
+void Vga::updateColors() {
+ byte palData[kPalSize];
+ dacToPal(_newColors, palData);
+ g_system->getPaletteManager()->setPalette(palData, 0, 256);
+}
+
+void Vga::update() {
+ SWAP(Vga::_page[0], Vga::_page[1]);
+
+ if (_setPal) {
+ updateColors();
+ _setPal = false;
+ }
+
+ g_system->copyRectToScreen(Vga::_page[0]->getPixels(), kScrWidth, 0, 0, kScrWidth, kScrHeight);
+ g_system->updateScreen();
+}
+
+void Vga::rotate() {
+ if (_rot._len) {
+ Dac c;
+ getColors(_newColors);
+ c = _newColors[_rot._org];
+ memmove(_newColors + _rot._org, _newColors + _rot._org + 1, (_rot._len - 1) * sizeof(Dac));
+ _newColors[_rot._org + _rot._len - 1] = c;
+ _setPal = true;
+ }
+}
+
+void Vga::clear(uint8 color) {
+ for (int paneNum = 0; paneNum < 4; paneNum++)
+ _page[paneNum]->fillRect(Common::Rect(0, 0, kScrWidth, kScrHeight), color);
+}
+
+void Vga::copyPage(uint16 d, uint16 s) {
+ _page[d]->copyFrom(*_page[s]);
+}
+
+void Bitmap::show(V2D pos) {
+ xLatPos(pos);
+
+ const byte *srcP = (const byte *)_v;
+ byte *screenStartP = (byte *)_vm->_vga->_page[1]->getPixels();
+ byte *screenEndP = (byte *)_vm->_vga->_page[1]->getBasePtr(0, kScrHeight);
+
+ // Loop through processing data for each plane. The game originally ran in plane mapped mode, where a
+ // given plane holds each fourth pixel sequentially. So to handle an entire picture, each plane's data
+ // must be decompressed and inserted into the surface
+ for (int planeCtr = 0; planeCtr < 4; planeCtr++) {
+ byte *destP = (byte *)_vm->_vga->_page[1]->getBasePtr(pos.x + planeCtr, pos.y);
+
+ for (;;) {
+ uint16 v = READ_LE_UINT16(srcP);
+ srcP += 2;
+ int cmd = v >> 14;
+ int count = v & 0x3FFF;
+
+ if (cmd == 0) {
+ // End of image
+ break;
+ }
+
+ // Handle a set of pixels
+ while (count-- > 0) {
+ // Transfer operation
+ switch (cmd) {
+ case 1:
+ // SKIP
+ break;
+ case 2:
+ // REPEAT
+ if (destP >= screenStartP && destP < screenEndP)
+ *destP = *srcP;
+ break;
+ case 3:
+ // COPY
+ if (destP >= screenStartP && destP < screenEndP)
+ *destP = *srcP;
+ srcP++;
+ break;
+ }
+
+ // Move to next dest position
+ destP += 4;
+ }
+
+ if (cmd == 2)
+ srcP++;
+ }
+ }
+}
+
+void Bitmap::hide(V2D pos) {
+ xLatPos(pos);
+
+ // Perform clipping to screen
+ int w = MIN<int>(_w, kScrWidth - pos.x);
+ int h = MIN<int>(_h, kScrHeight - pos.y);
+ if (pos.x < 0) {
+ w -= -pos.x;
+ pos.x = 0;
+ if (w < 0)
+ return;
+ }
+ if (pos.y < 0) {
+ h -= -pos.y;
+ pos.y = 0;
+ if (h < 0)
+ return;
+ }
+
+ // Perform copying of screen section
+ for (int yp = pos.y; yp < pos.y + h; yp++) {
+ if (yp >= 0 && yp < kScrHeight) {
+ const byte *srcP = (const byte *)_vm->_vga->_page[2]->getBasePtr(pos.x, yp);
+ byte *destP = (byte *)_vm->_vga->_page[1]->getBasePtr(pos.x, yp);
+
+ Common::copy(srcP, srcP + w, destP);
+ }
+ }
+}
+
+Speaker::Speaker(CGE2Engine *vm): Sprite(vm), _vm(vm) {
+ // Set the sprite list
+ BitmapPtr SP = new Bitmap[2];
+ uint8 *map = Bitmap::makeSpeechBubbleTail(0, _vm->_font->_colorSet);
+ SP[0] = Bitmap(_vm, 15, 16, map);
+ delete[] map;
+ map = Bitmap::makeSpeechBubbleTail(1, _vm->_font->_colorSet);
+ SP[1] = Bitmap(_vm, 15, 16, map);
+ delete[] map;
+ setShapeList(SP, 2);
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/vga13h.h b/engines/cge2/vga13h.h
new file mode 100644
index 0000000000..553f183de4
--- /dev/null
+++ b/engines/cge2/vga13h.h
@@ -0,0 +1,308 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_VGA13H_H
+#define CGE2_VGA13H_H
+
+#include "common/serializer.h"
+#include "common/events.h"
+#include "graphics/surface.h"
+#include "cge2/general.h"
+#include "cge2/bitmap.h"
+#include "cge2/snail.h"
+#include "cge2/spare.h"
+#include "cge2/cge2.h"
+
+namespace CGE2 {
+
+#define kFadeStep 2
+#define kVgaColDark 207
+#define kVgaColDarkGray 225 /*219*/
+#define kVgaColGray 231
+#define kVgaColLightGray 237
+#define kPixelTransp 0xFE
+#define kNoSeq (-1)
+#define kNoPtr ((uint8)-1)
+#define kSprExt ".SPR"
+#define kPalCount 256
+#define kPalSize (kPalCount * 3)
+
+class FXP {
+ int32 v;
+public:
+ FXP(void) : v(0) {}
+ FXP (int i0, int f0 = 0) : v((i0 * 256) + ((i0 < 0) ? -f0 : f0)) {}
+ FXP &operator=(const int &x) { v = x << 8; return *this; }
+ FXP operator+(const FXP &x) const { FXP y; y.v = v + x.v; return y; }
+ FXP operator-(const FXP &x) const { FXP y; y.v = v - x.v; return y; }
+ FXP operator*(const FXP &x) const;
+ FXP operator/(const FXP &x) const;
+
+ friend int &operator+=(int &a, const FXP &b) { return a += b.trunc(); }
+ friend int &operator-=(int &a, const FXP &b) { return a -= b.trunc(); }
+ friend FXP &operator+=(FXP &a, const int &b) { a.v += b << 8; return a; }
+ friend FXP &operator-=(FXP &a, const int &b) { a.v -= b << 8; return a; }
+ friend bool operator==(const FXP &a, const FXP &b) { return a.v == b.v; }
+ friend bool operator!=(const FXP &a, const FXP &b) { return a.v != b.v; }
+ friend bool operator<(const FXP &a, const FXP &b) { return a.v < b.v; }
+ friend bool operator>(const FXP &a, const FXP &b) { return a.v > b.v; }
+ int trunc(void) const { return v >> 8; }
+ int round(void) const { return (v + 0x80) >> 8; }
+ bool empty() const { return v == 0; }
+ void sync(Common::Serializer &s);
+};
+
+class V3D {
+public:
+ FXP _x, _y, _z;
+ V3D() { }
+ V3D(FXP x, FXP y, FXP z = 0) : _x(x), _y(y), _z(z) { }
+ V3D(const V3D &p) : _x(p._x), _y(p._y), _z(p._z) { }
+ V3D operator+(const V3D &p) const { return V3D(_x + p._x, _y + p._y, _z + p._z); }
+ V3D operator-(const V3D &p) const { return V3D(_x - p._x, _y - p._y, _z - p._z); }
+ V3D operator*(long n) const { return V3D(_x * n, _y * n, _z * n); }
+ V3D operator/ (long n) const { return V3D(_x / n, _y / n, _z / n); }
+ bool operator==(const V3D &p) const { return _x == p._x && _y == p._y && _z == p._z; }
+ bool operator!=(const V3D &p) const { return _x != p._x || _y != p._y || _z != p._z; }
+ V3D& operator+=(const V3D &x) { return *this = *this + x; }
+ V3D& operator-=(const V3D &x) { return *this = *this - x; }
+ void sync(Common::Serializer &s);
+};
+
+class V2D : public Common::Point {
+ CGE2Engine *_vm;
+public:
+ V2D &operator=(const V3D &p3) {
+ FXP m = _vm->_eye->_z / (p3._z - _vm->_eye->_z);
+ FXP posx = _vm->_eye->_x + (_vm->_eye->_x - p3._x) * m;
+ x = posx.round();
+ FXP posy = _vm->_eye->_y + (_vm->_eye->_y - p3._y) * m;
+ y = posy.round();
+ return *this;
+ }
+ V2D(CGE2Engine *vm) : _vm(vm) { }
+ V2D(CGE2Engine *vm, const V3D &p3) : _vm(vm) { *this = p3; }
+ V2D(CGE2Engine *vm, int posx, int posy) : _vm(vm), Common::Point(posx, posy) { }
+ bool operator<(const V2D &p) const { return (x < p.x) && (y < p.y); }
+ bool operator<=(const V2D &p) const { return (x <= p.x) && (y <= p.y); }
+ bool operator>(const V2D &p) const { return (x > p.x) && (y > p.y); }
+ bool operator>=(const V2D &p) const { return (x >= p.x) && (y >= p.y); }
+ V2D operator+(const V2D &p) const { return V2D(_vm, x + p.x, y + p.y); }
+ V2D operator-(const V2D &p) const { return V2D(_vm, x - p.x, y - p.y); }
+ bool operator==(const V3D &p) const { V3D tmp(x, y); return tmp._x == p._x && tmp._y == p._y && tmp._z == p._z; }
+ bool operator!=(const V3D &p) const { V3D tmp(x, y); return tmp._x != p._x || tmp._y != p._y || tmp._z == p._z; }
+ bool operator==(const V2D &p) const { return x == p.x && y == p.y; }
+ uint16 area() { return x * y; }
+ bool limited(const V2D &p) {
+ return ((x < p.x) && (y < p.y));
+ }
+ V2D scale (int z) {
+ FXP m = _vm->_eye->_z / (_vm->_eye->_z - z);
+ FXP posx = m * x;
+ FXP posy = m * y;
+ return V2D(_vm, posx.trunc(), posy.trunc());
+ }
+};
+
+struct Seq {
+ uint8 _now;
+ uint8 _next;
+ int8 _dx;
+ int8 _dy;
+ int8 _dz;
+ int _dly;
+};
+
+class SprExt {
+public:
+ V2D _p0;
+ V2D _p1;
+ BitmapPtr _b0;
+ BitmapPtr _b1;
+ BitmapPtr _shpList;
+ int _location;
+ Seq *_seq;
+ char *_name;
+ CommandHandler::Command *_actions[kActions];
+ SprExt(CGE2Engine *vm);
+};
+
+class Sprite {
+protected:
+ SprExt *_ext;
+ CGE2Engine *_vm;
+public:
+ int _ref;
+ signed char _scene;
+ struct Flags {
+ bool _hide; // general visibility switch
+ bool _drag; // sprite is moveable
+ bool _hold; // sprite is held with mouse
+ bool _trim; // Trim flag
+ bool _slav; // slave object
+ bool _kill; // dispose memory after remove
+ bool _xlat; // 2nd way display: xlat table
+ bool _port; // portable
+ bool _kept; // kept in pocket
+ bool _frnt; // stay in front of sprite
+ bool _east; // talk to east (in opposite to west)
+ bool _near; // Near action lock
+ bool _shad; // shadow
+ bool _back; // 'send to background' request
+ bool _zmov; // sprite needs Z-update in queue
+ bool _tran; // transparent (untouchable)
+ } _flags;
+ V2D _pos2D;
+ V3D _pos3D;
+ V2D _siz;
+ uint16 _time;
+ struct { byte _ptr, _cnt; } _actionCtrl[kActions];
+ int _seqPtr;
+ int _seqCnt;
+ int _shpCnt;
+ char _file[kMaxFile];
+ // Following trailer is not saved with the game:
+ Sprite *_prev;
+ Sprite *_next;
+ static byte _constY;
+ static byte _follow;
+ static Seq _stdSeq8[];
+
+ bool works(Sprite *spr);
+ bool seqTest(int n);
+ inline bool active() {
+ return _ext != nullptr;
+ }
+ Sprite(CGE2Engine *vm);
+ Sprite(CGE2Engine *vm, BitmapPtr shp, int cnt);
+ virtual ~Sprite();
+ BitmapPtr getShp();
+ void setShapeList(BitmapPtr shp, int cnt);
+ void moveShapesHi();
+ void moveShapesLo();
+ int labVal(Action snq, int lab);
+ virtual Sprite *expand();
+ virtual Sprite *contract();
+ void backShow();
+ void setName(char *newName);
+ inline char *name() {
+ return (_ext) ? _ext->_name : nullptr;
+ }
+ void gotoxyz(int x, int y, int z = 0);
+ void gotoxyz();
+ void gotoxyz(V2D pos);
+ void gotoxyz_(V2D pos);
+ void gotoxyz(V3D pos);
+ void center();
+ void show(uint16 pg);
+ void hide(uint16 pg);
+ void show();
+ void hide();
+ BitmapPtr ghost();
+ void step(int nr = -1);
+ Seq *setSeq(Seq *seq);
+ CommandHandler::Command *snList(Action type);
+ virtual void touch(uint16 mask, V2D pos, Common::KeyCode keyCode);
+ virtual void tick();
+ virtual void setScene(int c);
+ void clrHide() { if (_ext) _ext->_b0 = nullptr; }
+
+ void sync(Common::Serializer &s);
+
+ static void (*notify) ();
+};
+
+class Queue {
+ Sprite *_head;
+ Sprite *_tail;
+public:
+ Queue(bool show);
+
+ void append(Sprite *spr);
+ void insert(Sprite *spr, Sprite *nxt);
+ void insert(Sprite *spr);
+ Sprite *remove(Sprite *spr);
+ Sprite *first() {
+ return _head;
+ }
+ Sprite *last() {
+ return _tail;
+ }
+ Sprite *locate(int ref);
+ bool locate(Sprite *spr);
+ void clear() { _head = _tail = nullptr; }
+};
+
+class Vga {
+ CGE2Engine *_vm;
+ bool _setPal;
+ Dac *_oldColors;
+ Dac *_newColors;
+ const char *_msg;
+ const char *_name;
+
+ void updateColors();
+ void setColors();
+ void waitVR();
+ uint8 closest(Dac *pal, const uint8 colR, const uint8 colG, const uint8 colB);
+
+public:
+ uint32 _frmCnt;
+ Queue *_showQ;
+ bool _mono;
+ Graphics::Surface *_page[4];
+ Dac *_sysPal;
+ struct { uint8 _org, _len, _cnt, _dly; } _rot;
+
+ Vga(CGE2Engine *vm);
+ ~Vga();
+
+ uint8 *glass(Dac *pal, const uint8 colR, const uint8 colG, const uint8 colB);
+ void getColors(Dac *tab);
+ void setColors(Dac *tab, int lum);
+ void clear(uint8 color);
+ void copyPage(uint16 d, uint16 s);
+ void sunrise(Dac *tab);
+ void sunset();
+ void show();
+ void update();
+ void rotate();
+ uint8 closest(Dac *pal, Dac x);
+
+ void palToDac(const byte *palData, Dac *tab);
+ void dacToPal(const Dac *tab, byte *palData);
+};
+
+class Speaker: public Sprite {
+ CGE2Engine *_vm;
+public:
+ Speaker(CGE2Engine *vm);
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_VGA13H_H
diff --git a/engines/cge2/vmenu.cpp b/engines/cge2/vmenu.cpp
new file mode 100644
index 0000000000..6afe5e9a61
--- /dev/null
+++ b/engines/cge2/vmenu.cpp
@@ -0,0 +1,162 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/text.h"
+#include "cge2/vmenu.h"
+#include "cge2/events.h"
+
+namespace CGE2 {
+
+Choice::Choice(CGE2Engine *vm) : _vm(vm), _text(nullptr) {}
+
+ExitGameChoice::ExitGameChoice(CGE2Engine *vm) : Choice(vm) {
+ _text = _vm->_text->getText(kQuitText);
+}
+
+void ExitGameChoice::proc() {
+ _vm->switchScene(-1);
+}
+
+ReturnToGameChoice::ReturnToGameChoice(CGE2Engine *vm) : Choice(vm) {
+ _text = _vm->_text->getText(kNoQuitText);
+}
+
+void ReturnToGameChoice::proc() {
+ _vm->_commandHandlerTurbo->addCommand(kCmdSeq, kPowerRef, 1, nullptr);
+ _vm->keyClick();
+}
+
+MenuBar::MenuBar(CGE2Engine *vm, uint16 w, byte *c) : Talk(vm) {
+ _color = c;
+ int h = kFontHigh + 2 * kMenuBarVerticalMargin, i = (w += 2 * kMenuBarHorizontalMargin) * h;
+ uint8 *p = new uint8[i];
+ uint8 *p1;
+ uint8 *p2;
+ uint8 lt = _color[kLt];
+ uint8 rb = _color[kRb];
+ BitmapPtr b;
+
+ memset(p + w, kPixelTransp, i - 2 * w);
+ memset(p, lt, w);
+ memset(p + i - w, rb, w);
+ p1 = p;
+ p2 = p + i - 1;
+ for (i = 0; i < h; i++) {
+ *p1 = lt;
+ *p2 = rb;
+ p1 += w;
+ p2 -= w;
+ }
+ b = new Bitmap[1];
+ b[0] = Bitmap(vm, w, h, p);
+ delete[] p;
+ setShapeList(b, 1);
+ _flags._slav = true;
+ _flags._tran = true;
+ _flags._kill = true;
+}
+
+VMenu *VMenu::_addr = nullptr;
+
+VMenu::VMenu(CGE2Engine *vm, Common::Array<Choice *> list, V2D pos, ColorBank col)
+ : Talk(vm, vmGather(list), kTBRect, col), _menu(list), _bar(nullptr), _items(list.size()), _vm(vm) {
+ delete[] _vmgt; // Lefotver of vmGather.
+
+ _addr = this;
+ _recent = -1;
+ _flags._kill = true;
+
+ if (pos.x < 0 || pos.y < 0)
+ center();
+ else
+ gotoxyz(V2D(_vm, pos.x - _siz.x / 2, pos.y - (kTextVMargin + kFontHigh / 2)));
+
+ _vm->_vga->_showQ->append(this);
+ _bar = new MenuBar(_vm, _siz.x - 2 * kTextHMargin, _color);
+ _bar->gotoxyz(V2D(_vm, _pos2D.x, _pos2D.y + kTextVMargin - kMenuBarVerticalMargin));
+ _vm->_vga->_showQ->append(_bar);
+}
+
+char *VMenu::vmGather(Common::Array<Choice *> list) {
+ int len = 0;
+ int h = 0;
+
+ for (uint i = 0; i < list.size(); i++) {
+ len += strlen(list[i]->_text);
+ ++h;
+ }
+ _vmgt = new char[len + h];
+ *_vmgt = '\0';
+ for (uint i = 0; i < list.size(); i++) {
+ if (*_vmgt)
+ strcat(_vmgt, "|");
+ strcat(_vmgt, list[i]->_text);
+ ++h;
+ }
+
+ return _vmgt;
+}
+
+
+VMenu::~VMenu() {
+ _addr = nullptr;
+
+ for (uint i = 0; i < _menu.size(); i++) {
+ delete _menu[i];
+ }
+}
+
+void VMenu::touch(uint16 mask, V2D pos, Common::KeyCode keyCode) {
+ if (_items) {
+ Sprite::touch(mask, pos, keyCode);
+
+ int n = 0;
+ bool ok = false;
+ int h = kFontHigh + kTextLineSpace;
+ pos.y -= kTextVMargin - 1;
+ if (pos.y >= 0) {
+ if (pos.x < 0)
+ pos.x = -pos.x;
+ n = pos.y / h;
+ if (n < _items)
+ ok = (pos.x <= (_siz.x >> 1) - kTextHMargin);
+ else
+ n = _items - 1;
+ }
+
+ _bar->gotoxyz(V2D(_vm, _pos2D.x, _pos2D.y + kTextVMargin + n * h - kMenuBarVerticalMargin));
+ n = _items - 1 - n;
+
+ if (ok && (mask & kMouseLeftUp)) {
+ _items = 0;
+ _vm->_commandHandlerTurbo->addCommand(kCmdKill, -1, 0, this);
+ _menu[_recent = n]->proc();
+ }
+ }
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/vmenu.h b/engines/cge2/vmenu.h
new file mode 100644
index 0000000000..f34812dcf4
--- /dev/null
+++ b/engines/cge2/vmenu.h
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_VMENU_H
+#define CGE2_VMENU_H
+
+#define kMenuBarVerticalMargin 1
+#define kMenuBarHorizontalMargin 3
+#define kLt 3
+#define kRb 1
+
+#include "cge2/cge2.h"
+#include "cge2/talk.h"
+
+namespace CGE2 {
+
+class Choice {
+protected:
+ CGE2Engine *_vm;
+public:
+ char *_text;
+
+ virtual void proc() = 0;
+
+ Choice(CGE2Engine *vm);
+ virtual ~Choice() {};
+};
+
+class ExitGameChoice : public Choice {
+public:
+ ExitGameChoice(CGE2Engine *vm);
+ void proc();
+};
+
+class ReturnToGameChoice : public Choice {
+public:
+ ReturnToGameChoice(CGE2Engine *vm);
+ void proc();
+};
+
+class MenuBar : public Talk {
+public:
+ MenuBar(CGE2Engine *vm, uint16 w, byte *c);
+};
+
+class VMenu : public Talk {
+ CGE2Engine *_vm;
+
+ uint16 _items;
+ Common::Array<Choice *> _menu;
+public:
+ char *_vmgt;
+ static VMenu *_addr;
+ int _recent;
+ MenuBar *_bar;
+
+ VMenu(CGE2Engine *vm, Common::Array<Choice *> list, V2D pos, ColorBank col);
+ ~VMenu();
+ void touch(uint16 mask, V2D pos, Common::KeyCode keyCode);
+ char *vmGather(Common::Array<Choice *> list);
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_VMENU_H
diff --git a/engines/cine/console.cpp b/engines/cine/console.cpp
index 82197693d4..4646bdf280 100644
--- a/engines/cine/console.cpp
+++ b/engines/cine/console.cpp
@@ -29,7 +29,7 @@ bool labyrinthCheat;
CineConsole::CineConsole(CineEngine *vm) : GUI::Debugger(), _vm(vm) {
assert(_vm);
- DCmd_Register("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat));
+ registerCmd("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat));
labyrinthCheat = false;
}
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index f6419ecafc..b9175cac72 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -1902,7 +1902,9 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he
destPtr++;
srcPtr++;
- maskPtr++;
+
+ if (maskPtr)
+ maskPtr++;
}
}
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index f3985c691e..18f260cab7 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -332,9 +332,9 @@ byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat form
// Save the palette to the output in the specified format
for (uint i = firstIndex; i < firstIndex + numColors; i++) {
- const uint r = (_colors[i].r * rNewMax) / rOrigMax;
- const uint g = (_colors[i].g * gNewMax) / gOrigMax;
- const uint b = (_colors[i].b * bNewMax) / bOrigMax;
+ const uint r = (_colors[i].r * rNewMax) / (rOrigMax == 0 ? 1 : rOrigMax);
+ const uint g = (_colors[i].g * gNewMax) / (gOrigMax == 0 ? 1 : gOrigMax);
+ const uint b = (_colors[i].b * bNewMax) / (bOrigMax == 0 ? 1 : bOrigMax);
buf[i * format.bytesPerPixel + rBytePos] |= r << (format.rShift % 8);
buf[i * format.bytesPerPixel + gBytePos] |= g << (format.gShift % 8);
diff --git a/engines/composer/composer.cpp b/engines/composer/composer.cpp
index 471a29030b..f070338978 100644
--- a/engines/composer/composer.cpp
+++ b/engines/composer/composer.cpp
@@ -135,7 +135,7 @@ Common::Error ComposerEngine::run() {
else
loadLibrary(_pendingPageChanges[i]._pageId);
- lastDrawTime = _system->getMillis();
+ lastDrawTime = 0;
}
_pendingPageChanges.clear();
@@ -168,9 +168,10 @@ Common::Error ComposerEngine::run() {
else
lastDrawTime += frameTime;
+ tickOldScripts();
+
redraw();
- tickOldScripts();
processAnimFrame();
} else if (_needsUpdate) {
redraw();
diff --git a/engines/composer/scripting.cpp b/engines/composer/scripting.cpp
index 94ca2c1bc8..cd78202ecd 100644
--- a/engines/composer/scripting.cpp
+++ b/engines/composer/scripting.cpp
@@ -746,6 +746,7 @@ void ComposerEngine::stopOldScript(uint16 id) {
for (Common::List<OldScript *>::iterator i = _oldScripts.begin(); i != _oldScripts.end(); i++) {
if ((*i)->_id == id) {
+ removeSprite(0, id);
delete *i;
i = _oldScripts.reverse_erase(i);
}
diff --git a/engines/cruise/actor.cpp b/engines/cruise/actor.cpp
index ab3b581825..331b1c1edd 100644
--- a/engines/cruise/actor.cpp
+++ b/engines/cruise/actor.cpp
@@ -289,16 +289,15 @@ void poly2(int x1, int y1, int x2, int y2) {
}
int point_proche(int16 table[][2]) {
- int x1, y1, i, x, y, p;
int d1 = 1000;
_vm->_polyStructs = &_vm->_polyStructNorm;
if (nclick_noeud == 1) {
- x = x_mouse;
- y = y_mouse;
- x1 = table_ptselect[0][0];
- y1 = table_ptselect[0][1];
+ int x = x_mouse;
+ int y = y_mouse;
+ int x1 = table_ptselect[0][0];
+ int y1 = table_ptselect[0][1];
_vm->_polyStructs = &_vm->_polyStructExp;
@@ -326,10 +325,10 @@ int point_proche(int16 table[][2]) {
}
_vm->_polyStructs = &_vm->_polyStructNorm;
- p = -1;
- for (i = 0; i < ctp_routeCoordCount; i++) {
- x = table[i][0];
- y = table[i][1];
+ int p = -1;
+ for (int i = 0; i < ctp_routeCoordCount; i++) {
+ int x = table[i][0];
+ int y = table[i][1];
int pointDistance = computeDistance(x_mouse, y_mouse, x, y);
if (pointDistance < d1) {
@@ -363,9 +362,7 @@ int8 Fsol[NBNOEUD + 1];
int D;
void explore(int depart, int arrivee) {
- int id1, id2, i;
-
- id1 = depart;
+ int id1 = depart;
fl[id1]++;
sol[idsol++] = (char)id1;
@@ -377,8 +374,9 @@ void explore(int depart, int arrivee) {
return;
}
+ int i;
while ((i = fl[id1]) < 20) {
- id2 = ctp_routes[id1][i + 1];
+ int id2 = ctp_routes[id1][i + 1];
if (id2 == arrivee) {
if (idsol < solmax) {
@@ -426,16 +424,13 @@ void explore(int depart, int arrivee) {
}
void chemin0(int depart, int arrivee) {
- int i;
- //int y=30;
-
prem = 0;
prem2 = 0;
dist_chemin = 0;
idsol = 0;
solmax = 999;
- for (i = 0; i < 20 + 1; i++)
+ for (int i = 0; i < 20 + 1; i++)
fl[i] = -1;
X = 0, Y = 30;
@@ -444,9 +439,6 @@ void chemin0(int depart, int arrivee) {
}
void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2]) {
- int a, b, d, i, p1, x1, x2, y1, y2;
- //int y=30;
-
table[*nclick] = p;
table[(*nclick) + 1] = -1;
table_ptselect[*nclick][0] = x_mouse;
@@ -455,10 +447,10 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
_vm->_polyStructs = &_vm->_polyStructNorm;
if (*nclick == 2) { // second point
- x1 = table_ptselect[0][0];
- y1 = table_ptselect[0][1];
- x2 = table_ptselect[1][0];
- y2 = table_ptselect[1][1];
+ int x1 = table_ptselect[0][0];
+ int y1 = table_ptselect[0][1];
+ int x2 = table_ptselect[1][0];
+ int y2 = table_ptselect[1][1];
if ((x1 == x2) && (y1 == y2)) {
return;
}
@@ -507,13 +499,11 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
} else {
solution0[0][0] = x1;
solution0[0][1] = y1;
- i = 0;
+ int i = 0;
while (solution[i] != -1) {
- p1 = solution[i];
- solution0[i + 1][0] =
- ctp_routeCoords[p1][0];
- solution0[++i][1] =
- ctp_routeCoords[p1][1];
+ int p1 = solution[i];
+ solution0[i + 1][0] = ctp_routeCoords[p1][0];
+ solution0[++i][1] = ctp_routeCoords[p1][1];
}
_vm->_polyStructs = &_vm->_polyStructExp;
poly2(x2, y2,
@@ -530,8 +520,8 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
/****** Trim down any un-necessary walk points ******/
i++;
- d = 0;
- a = i;
+ int d = 0;
+ int a = i;
flag_obstacle = 1;
while (d != a) {
x1 = solution0[d][0];
@@ -547,7 +537,7 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
flag_obstacle = 1;
if (d != i) {
i++;
- for (b = d + 1; b < i; b++) {
+ for (int b = d + 1; b < i; b++) {
solution0[b][0] = -2;
}
} else
@@ -582,10 +572,9 @@ int16 computePathfinding(MovementEntry &moveInfo, int16 x, int16 y, int16 destX,
}
if (!flagCt) {
- int i;
int16 *ptr;
-
- for (i = 0; i < NUM_PERSONS; i++) { // 10 = num perso
+ int i = 0;
+ for (; i < NUM_PERSONS; i++) { // 10 = num perso
if (!persoTable[i]) {
break;
}
diff --git a/engines/cruise/background.cpp b/engines/cruise/background.cpp
index a59db8ef95..4cf52f62e1 100644
--- a/engines/cruise/background.cpp
+++ b/engines/cruise/background.cpp
@@ -65,12 +65,10 @@ int loadCVT(uint8 **ptr) {
char *localPtr = (char *) * ptr;
if (!strcmp(localPtr, "CVT")) {
- int i;
localPtr += 4;
- for (i = 0; i < 0x20; i++) {
+ for (int i = 0; i < 0x20; i++)
cvtPalette[i] = *(localPtr++);
- }
*ptr = (uint8 *) localPtr;
@@ -180,7 +178,7 @@ int loadBackground(const char *name, int idx) {
break;
default:
- ASSERT(0);
+ assert(0);
}
gfxModuleData_setPal256(palScreen[idx]);
diff --git a/engines/cruise/backgroundIncrust.cpp b/engines/cruise/backgroundIncrust.cpp
index 3286cd6ebf..77e15ccf4c 100644
--- a/engines/cruise/backgroundIncrust.cpp
+++ b/engines/cruise/backgroundIncrust.cpp
@@ -59,6 +59,8 @@ void backupBackground(backgroundIncrustStruct *pIncrust, int X, int Y, int width
}
void restoreBackground(backgroundIncrustStruct *pIncrust) {
+ if (!pIncrust)
+ return;
if (pIncrust->type != 1)
return;
if (pIncrust->ptr == NULL)
@@ -87,39 +89,32 @@ void restoreBackground(backgroundIncrustStruct *pIncrust) {
}
backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx, backgroundIncrustStruct *pHead, int16 scriptNumber, int16 scriptOverlay, int16 backgroundIdx, int16 saveBuffer) {
- uint8 *backgroundPtr;
- uint8 *ptr;
objectParamsQuery params;
- backgroundIncrustStruct *newElement;
- backgroundIncrustStruct *currentHead;
- backgroundIncrustStruct *currentHead2;
-
getMultipleObjectParam(overlayIdx, objectIdx, &params);
- ptr = filesDatabase[params.fileIdx].subData.ptr;
+ uint8 *ptr = filesDatabase[params.fileIdx].subData.ptr;
// Don't process any further if not a sprite or polygon
- if (!ptr) return NULL;
- if ((filesDatabase[params.fileIdx].subData.resourceType != OBJ_TYPE_SPRITE) &&
- (filesDatabase[params.fileIdx].subData.resourceType != OBJ_TYPE_POLY)) {
+ if (!ptr)
return NULL;
- }
- backgroundPtr = backgroundScreens[backgroundIdx];
-
- backgroundChanged[backgroundIdx] = true;
+ if ((filesDatabase[params.fileIdx].subData.resourceType != OBJ_TYPE_SPRITE) &&
+ (filesDatabase[params.fileIdx].subData.resourceType != OBJ_TYPE_POLY))
+ return NULL;
+ uint8 *backgroundPtr = backgroundScreens[backgroundIdx];
assert(backgroundPtr != NULL);
- currentHead = pHead;
- currentHead2 = currentHead->next;
+ backgroundChanged[backgroundIdx] = true;
+ backgroundIncrustStruct *currentHead = pHead;
+ backgroundIncrustStruct *currentHead2 = currentHead->next;
while (currentHead2) {
currentHead = currentHead2;
currentHead2 = currentHead->next;
}
- newElement = (backgroundIncrustStruct *)mallocAndZero(sizeof(backgroundIncrustStruct));
+ backgroundIncrustStruct *newElement = (backgroundIncrustStruct *)mallocAndZero(sizeof(backgroundIncrustStruct));
if (!newElement)
return NULL;
@@ -127,13 +122,11 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx,
newElement->next = currentHead->next;
currentHead->next = newElement;
- if (!currentHead2) {
+ if (!currentHead2)
currentHead2 = pHead;
- }
newElement->prev = currentHead2->prev;
currentHead2->prev = newElement;
-
newElement->objectIdx = objectIdx;
newElement->type = saveBuffer;
newElement->backgroundIdx = backgroundIdx;
@@ -152,9 +145,8 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx,
// sprite
int width = filesDatabase[params.fileIdx].width;
int height = filesDatabase[params.fileIdx].height;
- if (saveBuffer == 1) {
+ if (saveBuffer == 1)
backupBackground(newElement, newElement->X, newElement->Y, width, height, backgroundPtr);
- }
drawSprite(width, height, NULL, filesDatabase[params.fileIdx].subData.ptr, newElement->Y,
newElement->X, backgroundPtr, filesDatabase[params.fileIdx].subData.ptrMask);
@@ -168,7 +160,7 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx,
int sizeTable[4]; // 0 = left, 1 = right, 2 = bottom, 3 = top
- // this function checks if the dataPtr is not 0, else it retrives the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1)
+ // this function checks if the dataPtr is not 0, else it retrieves the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1)
flipPoly(params.fileIdx, (int16 *)filesDatabase[params.fileIdx].subData.ptr, params.scale, &newFrame, newElement->X, newElement->Y, &newX, &newY, &newScale);
// this function fills the sizeTable for the poly (OLD: mainDrawSub1Sub2)
@@ -187,16 +179,15 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx,
}
void regenerateBackgroundIncrust(backgroundIncrustStruct *pHead) {
-
lastAni[0] = 0;
-
- backgroundIncrustStruct* pl = pHead->next;
+ backgroundIncrustStruct *pl = pHead->next;
while (pl) {
backgroundIncrustStruct* pl2 = pl->next;
int frame = pl->frame;
- //int screen = pl->backgroundIdx;
+ if (frame < 0)
+ error("regenerateBackgroundIncrust() : Unexpected use of negative frame index");
if ((filesDatabase[frame].subData.ptr == NULL) || (strcmp(pl->name, filesDatabase[frame].subData.name))) {
frame = NUM_FILE_ENTRIES - 1;
@@ -235,7 +226,6 @@ void freeBackgroundIncrustList(backgroundIncrustStruct *pHead) {
MemFree(pCurrent->ptr);
MemFree(pCurrent);
-
pCurrent = pNext;
}
@@ -244,52 +234,41 @@ void freeBackgroundIncrustList(backgroundIncrustStruct *pHead) {
void removeBackgroundIncrust(int overlay, int idx, backgroundIncrustStruct * pHead) {
objectParamsQuery params;
- int var_4;
- int var_6;
-
- backgroundIncrustStruct *pCurrent;
- backgroundIncrustStruct *pCurrentHead;
getMultipleObjectParam(overlay, idx, &params);
- var_4 = params.X;
- var_6 = params.Y;
-
- pCurrent = pHead->next;
+ int x = params.X;
+ int y = params.Y;
+ backgroundIncrustStruct *pCurrent = pHead->next;
while (pCurrent) {
- if ((pCurrent->overlayIdx == overlay || overlay == -1) && (pCurrent->objectIdx == idx || idx == -1) && (pCurrent->X == var_4) && (pCurrent->Y == var_6)) {
- pCurrent->type = - 1;
- }
+ if ((pCurrent->overlayIdx == overlay || overlay == -1) && (pCurrent->objectIdx == idx || idx == -1) && (pCurrent->X == x) && (pCurrent->Y == y))
+ pCurrent->type = -1;
pCurrent = pCurrent->next;
}
- pCurrentHead = pHead;
+ backgroundIncrustStruct *pCurrentHead = pHead;
pCurrent = pHead->next;
while (pCurrent) {
- if (pCurrent->type == - 1) {
+ if (pCurrent->type == -1) {
backgroundIncrustStruct *pNext = pCurrent->next;
backgroundIncrustStruct *bx = pCurrentHead;
- backgroundIncrustStruct *cx;
bx->next = pNext;
- cx = pNext;
+ backgroundIncrustStruct *cx = pNext;
- if (!pNext) {
+ if (!pNext)
cx = pHead;
- }
bx = cx;
bx->prev = pCurrent->next;
- if (pCurrent->ptr) {
+ if (pCurrent->ptr)
MemFree(pCurrent->ptr);
- }
MemFree(pCurrent);
-
pCurrent = pNext;
} else {
pCurrentHead = pCurrent;
@@ -299,25 +278,24 @@ void removeBackgroundIncrust(int overlay, int idx, backgroundIncrustStruct * pHe
}
void unmergeBackgroundIncrust(backgroundIncrustStruct * pHead, int ovl, int idx) {
- backgroundIncrustStruct *pl;
- backgroundIncrustStruct *pl2;
-
objectParamsQuery params;
getMultipleObjectParam(ovl, idx, &params);
int x = params.X;
int y = params.Y;
- pl = pHead;
- pl2 = pl;
+ backgroundIncrustStruct *pl = pHead;
+ backgroundIncrustStruct *pl2 = pl;
pl = pl2->next;
while (pl) {
pl2 = pl;
- if ((pl->overlayIdx == ovl) || (ovl == -1))
- if ((pl->objectIdx == idx) || (idx == -1))
+ if ((pl->overlayIdx == ovl) || (ovl == -1)) {
+ if ((pl->objectIdx == idx) || (idx == -1)) {
if ((pl->X == x) && (pl->Y == y))
restoreBackground(pl);
+ }
+ }
pl = pl2->next;
}
diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp
index 6dcb0b1432..eebd8fdc15 100644
--- a/engines/cruise/cruise.cpp
+++ b/engines/cruise/cruise.cpp
@@ -50,6 +50,15 @@ CruiseEngine::CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc
_debugger = new Debugger();
_sound = new PCSound(_mixer, this);
+ PCFadeFlag = false;
+ _preLoad = false;
+ _savedCursor = CURSOR_NOMOUSE;
+ _lastTick = 0;
+ _gameSpeed = GAME_FRAME_DELAY_1;
+ _speedFlag = false;
+ _polyStructs = nullptr;
+ _polyStruct = nullptr;
+
// Setup mixer
syncSoundSettings();
}
@@ -87,9 +96,6 @@ Common::Error CruiseEngine::run() {
Cruise::changeCursor(Cruise::CURSOR_NORMAL);
CursorMan.showMouse(true);
- lastTick = 0;
- lastTickDebug = 0;
-
mainLoop();
deinitialize();
@@ -98,24 +104,12 @@ Common::Error CruiseEngine::run() {
}
void CruiseEngine::initialize() {
- PCFadeFlag = 0;
- _gameSpeed = GAME_FRAME_DELAY_1;
- _speedFlag = false;
-
- /*volVar1 = 0;
- * fileData1 = 0; */
-
- /*PAL_fileHandle = -1; */
-
// video init stuff
-
initSystem();
gfxModuleData_Init();
// another bit of video init
-
readVolCnf();
- _vm->_polyStruct = NULL;
}
void CruiseEngine::deinitialize() {
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h
index c81e5dd5ec..8624ba693e 100644
--- a/engines/cruise/cruise.h
+++ b/engines/cruise/cruise.h
@@ -60,7 +60,7 @@ private:
PCSound *_sound;
Common::StringArray _langStrings;
CursorType _savedCursor;
- uint32 lastTick, lastTickDebug;
+ uint32 _lastTick;
int _gameSpeed;
bool _speedFlag;
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index 9227eca8cb..0ad1416df2 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -35,10 +35,10 @@ namespace Cruise {
enum RelationType {RT_REL = 30, RT_MSG = 50};
-static int playerDontAskQuit;
+static bool _playerDontAskQuit;
unsigned int timer = 0;
-gfxEntryStruct* linkedMsgList = NULL;
+gfxEntryStruct *linkedMsgList = nullptr;
typedef CruiseEngine::MemInfo MemInfo;
@@ -110,7 +110,6 @@ void loadPackedFileToMem(int fileIdx, uint8 *buffer) {
int getNumObjectsByClass(int scriptIdx, int param) {
objDataStruct *ptr2;
int counter;
- int i;
if (!overlayTable[scriptIdx].ovlData)
return (0);
@@ -125,7 +124,7 @@ int getNumObjectsByClass(int scriptIdx, int param) {
counter = 0;
- for (i = 0; i < overlayTable[scriptIdx].ovlData->numObj; i++) {
+ for (int i = 0; i < overlayTable[scriptIdx].ovlData->numObj; i++) {
if (ptr2[i]._class == param) {
counter++;
}
@@ -135,15 +134,12 @@ int getNumObjectsByClass(int scriptIdx, int param) {
}
void resetFileEntryRange(int start, int count) {
- int i;
-
- for (i = 0; i < count; ++i)
+ for (int i = 0; i < count; ++i)
resetFileEntry(start + i);
}
int getProcParam(int overlayIdx, int param2, const char *name) {
int numSymbGlob;
- int i;
exportEntryStruct *arraySymbGlob;
char *exportNamePtr;
char exportName[80];
@@ -161,9 +157,9 @@ int getProcParam(int overlayIdx, int param2, const char *name) {
if (!exportNamePtr)
return 0;
- for (i = 0; i < numSymbGlob; i++) {
+ for (int i = 0; i < numSymbGlob; i++) {
if (arraySymbGlob[i].var4 == param2) {
- strcpy(exportName, arraySymbGlob[i].offsetToName + exportNamePtr);
+ Common::strlcpy(exportName, arraySymbGlob[i].offsetToName + exportNamePtr, sizeof(exportName));
if (!strcmp(exportName, name)) {
return (arraySymbGlob[i].idx);
@@ -188,9 +184,7 @@ void changeScriptParamInList(int param1, int param2, scriptInstanceStruct *pScri
}
void initBigVar3() {
- int i;
-
- for (i = 0; i < NUM_FILE_ENTRIES; i++) {
+ for (int i = 0; i < NUM_FILE_ENTRIES; i++) {
if (filesDatabase[i].subData.ptr) {
MemFree(filesDatabase[i].subData.ptr);
}
@@ -338,13 +332,12 @@ void removeExtention(const char *name, char *buffer) { // not like in original
int lastFileSize;
int loadFileSub1(uint8 **ptr, const char *name, uint8 *ptr2) {
- int i;
char buffer[256];
int fileIdx;
int unpackedSize;
uint8 *unpackedBuffer;
- for (i = 0; i < 64; i++) {
+ for (int i = 0; i < 64; i++) {
if (preloadData[i].ptr) {
if (!strcmp(preloadData[i].name, name)) {
error("Unsupported code in loadFIleSub1");
@@ -371,7 +364,7 @@ int loadFileSub1(uint8 **ptr, const char *name, uint8 *ptr2) {
* strcatuint8(buffer,".HP");
* } */
} else {
- strcpy(buffer, name);
+ Common::strlcpy(buffer, name, sizeof(buffer));
}
fileIdx = findFileInDisks(buffer);
@@ -434,14 +427,12 @@ void resetFileEntry(int32 entryNumber) {
}
uint8 *mainProc14(uint16 overlay, uint16 idx) {
- ASSERT(0);
+ assert(0);
return NULL;
}
void CruiseEngine::initAllData() {
- int i;
-
setupFuncArray();
initOverlayTable();
@@ -457,15 +448,13 @@ void CruiseEngine::initAllData() {
menuTable[0] = NULL;
- for (i = 0; i < 2000; i++) {
+ for (int i = 0; i < 2000; i++)
globalVars[i] = 0;
- }
- for (i = 0; i < 8; i++) {
+ for (int i = 0; i < 8; i++)
backgroundTable[i].name[0] = 0;
- }
- for (i = 0; i < NUM_FILE_ENTRIES; i++) {
+ for (int i = 0; i < NUM_FILE_ENTRIES; i++) {
filesDatabase[i].subData.ptr = NULL;
filesDatabase[i].subData.ptrMask = NULL;
}
@@ -653,8 +642,7 @@ int findObject(int mouseX, int mouseY, int *outObjOvl, int *outObjIdx) {
(currentObject->type == OBJ_TYPE_SPRITE || currentObject->type == OBJ_TYPE_MASK ||
currentObject->type == OBJ_TYPE_EXIT || currentObject->type == OBJ_TYPE_VIRTUAL)) {
const char* pObjectName = getObjectName(currentObject->idx, overlayTable[currentObject->overlay].ovlData->arrayNameObj);
-
- strcpy(objectName, pObjectName);
+ Common::strlcpy(objectName, pObjectName, sizeof(objectName));
if (strlen(objectName) && (currentObject->freeze == 0)) {
int objIdx = currentObject->idx;
@@ -863,7 +851,6 @@ bool createDialog(int objOvl, int objIdx, int x, int y) {
bool found = false;
int testState1 = -1;
int testState2 = -1;
- int j;
int16 objectState;
int16 objectState2;
@@ -871,7 +858,7 @@ bool createDialog(int objOvl, int objIdx, int x, int y) {
menuTable[0] = createMenu(x, y, _vm->langString(ID_SPEAK_ABOUT));
- for (j = 1; j < numOfLoadedOverlay; j++) {
+ for (int j = 1; j < numOfLoadedOverlay; j++) {
if (overlayTable[j].alreadyLoaded) {
int idHeader = overlayTable[j].ovlData->numMsgRelHeader;
@@ -895,24 +882,26 @@ bool createDialog(int objOvl, int objIdx, int x, int y) {
}
if ((thisOvl == objOvl) && (ptrHead->obj2Number == objIdx)) {
- int verbeOvl = ptrHead->verbOverlay;
+ int verbOvl = ptrHead->verbOverlay;
int obj1Ovl = ptrHead->obj1Overlay;
int obj2Ovl = ptrHead->obj2Overlay;
- if (!verbeOvl) verbeOvl = j;
- if (!obj1Ovl) obj1Ovl = j;
- if (!obj2Ovl) obj2Ovl = j;
-
- char verbe_name[80];
+ if (!verbOvl)
+ verbOvl = j;
+ if (!obj1Ovl)
+ obj1Ovl = j;
+ if (!obj2Ovl)
+ obj2Ovl = j;
- verbe_name[0] = 0;
+ char verbName[80];
+ verbName[0] = 0;
ovlDataStruct *ovl2 = NULL;
ovlDataStruct *ovl3 = NULL;
ovlDataStruct *ovl4 = NULL;
- if (verbeOvl > 0)
- ovl2 = overlayTable[verbeOvl].ovlData;
+ if (verbOvl > 0)
+ ovl2 = overlayTable[verbOvl].ovlData;
if (obj1Ovl > 0)
ovl3 = overlayTable[obj1Ovl].ovlData;
@@ -920,21 +909,21 @@ bool createDialog(int objOvl, int objIdx, int x, int y) {
if (obj2Ovl > 0)
ovl4 = overlayTable[obj2Ovl].ovlData;
- if ((ovl3) && (ptrHead->obj1Number >= 0)) {
+ if (ovl3 && (ptrHead->obj1Number >= 0)) {
testState1 = ptrHead->obj1OldState;
}
- if ((ovl4) && (ptrHead->obj2Number >= 0)) {
+ if (ovl4 && (ptrHead->obj2Number >= 0)) {
testState2 = ptrHead->obj2OldState;
}
- if ((ovl4) && (ptrHead->verbNumber >= 0) &&
+ if (ovl4 && ovl2 && (ptrHead->verbNumber >= 0) &&
((testState1 == -1) || (testState1 == objectState2)) &&
((testState2 == -1) || (testState2 == objectState))) {
if (ovl2->nameVerbGlob) {
const char *ptr = getObjectName(ptrHead->verbNumber, ovl2->nameVerbGlob);
- strcpy(verbe_name, ptr);
+ Common::strlcpy(verbName, ptr, sizeof(verbName));
- if (!strlen(verbe_name))
+ if (!strlen(verbName))
attacheNewScriptToTail(&relHead, j, ptrHead->id, 30, currentScriptPtr->scriptNumber, currentScriptPtr->overlayNumber, scriptType_REL);
else if (ovl2->nameVerbGlob) {
found = true;
@@ -945,8 +934,11 @@ bool createDialog(int objOvl, int objIdx, int x, int y) {
else
color = -1;
- ptr = getObjectName(ptrHead->obj1Number, ovl3->arrayNameObj);
- addSelectableMenuEntry(j, i, menuTable[0], 1, color, ptr);
+ if (ovl3) {
+ ptr = getObjectName(ptrHead->obj1Number, ovl3->arrayNameObj);
+ addSelectableMenuEntry(j, i, menuTable[0], 1, color, ptr);
+ } else
+ error("Unexpected null pointer in createDialog()");
}
}
}
@@ -963,12 +955,11 @@ bool findRelation(int objOvl, int objIdx, int x, int y) {
bool found = false;
bool first = true;
int testState = -1;
- int j;
int16 objectState;
getSingleObjectParam(objOvl, objIdx, 5, &objectState);
- for (j = 1; j < numOfLoadedOverlay; j++) {
+ for (int j = 1; j < numOfLoadedOverlay; j++) {
if (overlayTable[j].alreadyLoaded) {
int idHeader = overlayTable[j].ovlData->numMsgRelHeader;
@@ -985,23 +976,27 @@ bool findRelation(int objOvl, int objIdx, int x, int y) {
objDataStruct* pObject = getObjectDataFromOverlay(thisOvl, ptrHead->obj1Number);
if ((thisOvl == objOvl) && (objIdx == ptrHead->obj1Number) && pObject && (pObject->_class != THEME)) {
- int verbeOvl = ptrHead->verbOverlay;
+ int verbOvl = ptrHead->verbOverlay;
int obj1Ovl = ptrHead->obj1Overlay;
- int obj2Ovl = ptrHead->obj2Overlay;
+ // Unused variable
+ // int obj2Ovl = ptrHead->obj2Overlay;
- if (!verbeOvl) verbeOvl = j;
- if (!obj1Ovl) obj1Ovl = j;
- if (!obj2Ovl) obj2Ovl = j;
+ if (!verbOvl)
+ verbOvl = j;
+ if (!obj1Ovl)
+ obj1Ovl = j;
+ // Unused variable
+ // if (!obj2Ovl)
+ // obj2Ovl = j;
- char verbe_name[80];
- verbe_name[0] = 0;
+ char verbName[80];
+ verbName[0] = 0;
ovlDataStruct *ovl2 = NULL;
ovlDataStruct *ovl3 = NULL;
- //ovlDataStruct *ovl4 = NULL;
- if (verbeOvl > 0)
- ovl2 = overlayTable[verbeOvl].ovlData;
+ if (verbOvl > 0)
+ ovl2 = overlayTable[verbOvl].ovlData;
if (obj1Ovl > 0)
ovl3 = overlayTable[obj1Ovl].ovlData;
@@ -1022,10 +1017,10 @@ bool findRelation(int objOvl, int objIdx, int x, int y) {
if ((ovl2) && (ptrHead->verbNumber >= 0)) {
if (ovl2->nameVerbGlob) {
const char *ptr = getObjectName(ptrHead->verbNumber, ovl2->nameVerbGlob);
- strcpy(verbe_name, ptr);
+ Common::strlcpy(verbName, ptr, sizeof(verbName));
if ((!first) && ((testState == -1) || (testState == objectState))) {
- if (!strlen(verbe_name)) {
+ if (!strlen(verbName)) {
if (currentScriptPtr) {
attacheNewScriptToTail(&relHead, j, ptrHead->id, 30, currentScriptPtr->scriptNumber, currentScriptPtr->overlayNumber, scriptType_REL);
} else {
@@ -1088,9 +1083,6 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) {
}
if ((obj2Ovl == nOvl) && (pHeader->obj2Number != -1) && (pHeader->obj2Number == nObj)) {
- int x = 60;
- int y = 60;
-
objectParamsQuery params;
memset(&params, 0, sizeof(objectParamsQuery)); // to remove warning
@@ -1138,6 +1130,8 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) {
}
}
} else if (pHeader->type == RT_MSG) {
+ int x = 60;
+ int y = 60;
if (pHeader->obj2Number >= 0) {
if ((pHeader->trackX !=-1) && (pHeader->trackY !=-1) &&
@@ -1166,7 +1160,7 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) {
createTextObject(&cellHead, ovlIdx, pHeader->id, x, y, 200, findHighColor(), masterScreen, 0, 0);
}
- userWait = 1;
+ userWait = true;
autoOvl = ovlIdx;
autoMsg = pHeader->id;
@@ -1195,7 +1189,7 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) {
pTrack->flag = 1;
autoTrack = true;
- userWait = 0;
+ userWait = false;
userEnabled = 0;
freezeCell(&cellHead, ovlIdx, pHeader->id, 5, -1, 0, 9998);
}
@@ -1312,7 +1306,7 @@ void callRelation(menuElementSubStruct *pMenuElement, int nObj2) {
createTextObject(&cellHead, ovlIdx, pHeader->id, x, y, 200, findHighColor(), masterScreen, 0, 0);
}
- userWait = 1;
+ userWait = true;
autoOvl = ovlIdx;
autoMsg = pHeader->id;
@@ -1343,7 +1337,7 @@ void callRelation(menuElementSubStruct *pMenuElement, int nObj2) {
pTrack->flag = 1;
autoTrack = true;
- userWait = 0;
+ userWait = false;
userEnabled = 0;
freezeCell(&cellHead, ovlIdx, pHeader->id, 5, -1, 0, 9998);
}
@@ -1368,7 +1362,7 @@ void closeAllMenu() {
menuTable[1] = NULL;
}
if (linkedMsgList) {
- ASSERT(0);
+ assert(0);
// freeMsgList(linkedMsgList);
}
@@ -1464,7 +1458,7 @@ int CruiseEngine::processInput() {
if (userWait) {
// Check for left mouse button click or Space to end user waiting
if ((keyboardCode == Common::KEYCODE_SPACE) || (button == CRS_MB_LEFT))
- userWait = 0;
+ userWait = false;
keyboardCode = Common::KEYCODE_INVALID;
return 0;
@@ -1523,7 +1517,7 @@ int CruiseEngine::processInput() {
menuTable[0] = NULL;
if (linkedMsgList) {
- ASSERT(0);
+ assert(0);
// freeMsgList(linkedMsgList);
}
@@ -1715,7 +1709,7 @@ bool manageEvents() {
break;
case Common::EVENT_QUIT:
case Common::EVENT_RTL:
- playerDontAskQuit = 1;
+ _playerDontAskQuit = true;
break;
case Common::EVENT_KEYUP:
switch (event.kbd.keycode) {
@@ -1781,16 +1775,12 @@ void CruiseEngine::mainLoop() {
currentActiveMenu = -1;
autoMsg = -1;
linkedRelation = 0;
- main21 = 0;
- main22 = 0;
- userWait = 0;
+ userWait = false;
autoTrack = false;
initAllData();
- playerDontAskQuit = 0;
- int quitValue2 = 1;
- int quitValue = 0;
+ _playerDontAskQuit = false;
if (ConfMan.hasKey("save_slot"))
loadGameState(ConfMan.getInt("save_slot"));
@@ -1840,23 +1830,20 @@ void CruiseEngine::mainLoop() {
if (!skipEvents || bFastMode)
skipEvents = manageEvents();
- if (bFastMode) {
- if (currentTick >= (lastTickDebug + 10))
- lastTickDebug = currentTick;
- } else {
+ if (!bFastMode) {
g_system->delayMillis(10);
currentTick = g_system->getMillis();
}
- if (playerDontAskQuit)
+ if (_playerDontAskQuit)
break;
_vm->getDebugger()->onFrame();
- } while (currentTick < lastTick + _gameSpeed && !bFastMode);
- if (playerDontAskQuit)
+ } while (currentTick < _lastTick + _gameSpeed && !bFastMode);
+ if (_playerDontAskQuit)
break;
- lastTick = g_system->getMillis();
+ _lastTick = g_system->getMillis();
// Handle switchover in game speed after intro
if (!_speedFlag && canLoadGameStateCurrently()) {
@@ -1871,7 +1858,7 @@ void CruiseEngine::mainLoop() {
// readKeyboard();
- bool isUserWait = userWait != 0;
+ bool isUserWait = userWait;
// WORKAROUND: This prevents hotspots responding during
// delays i.e. Menu opening if you click fast on another
// hotspot after trying to open a locked door, which
@@ -1880,8 +1867,8 @@ void CruiseEngine::mainLoop() {
currentMouseButton = 0;
}
- playerDontAskQuit = processInput();
- if (playerDontAskQuit)
+ _playerDontAskQuit = processInput();
+ if (_playerDontAskQuit)
break;
if (enableUser) {
@@ -1906,11 +1893,10 @@ void CruiseEngine::mainLoop() {
// Raoul appearing when looking at the book is being there are 3 script iterations separation between the
// scene being changed to the book, and the Raoul actor being frozen/disabled. This loop is a hack to ensure
// that does a few extra script executions for that scene
- bool bgChanged;
int numIterations = 1;
while (numIterations-- > 0) {
- bgChanged = backgroundChanged[masterScreen];
+ bool bgChanged = backgroundChanged[masterScreen];
manageScripts(&relHead);
manageScripts(&procHead);
@@ -1928,7 +1914,7 @@ void CruiseEngine::mainLoop() {
processAnimation();
if (remdo) {
- // ASSERT(0);
+ // assert(0);
/* main3 = 0;
* var24 = 0;
* var23 = 0;
@@ -1937,7 +1923,7 @@ void CruiseEngine::mainLoop() {
}
if (cmdLine[0]) {
- ASSERT(0);
+ assert(0);
/* redrawStrings(0,&cmdLine,8);
waitForPlayerInput();
@@ -1947,13 +1933,13 @@ void CruiseEngine::mainLoop() {
if (displayOn) {
if (doFade)
- PCFadeFlag = 0;
+ PCFadeFlag = false;
/*if (!PCFadeFlag)*/
mainDraw(userWait);
flipScreen();
- if (userWait == 1) {
+ if (userWait) {
// Waiting for press - original wait loop has been integrated into the
// main event loop
continue;
@@ -1968,7 +1954,7 @@ void CruiseEngine::mainLoop() {
char* pText = getText(autoMsg, autoOvl);
if (strlen(pText))
- userWait = 1;
+ userWait = true;
}
changeScriptParamInList(-1, -1, &relHead, 9998, 0);
@@ -1986,7 +1972,7 @@ void CruiseEngine::mainLoop() {
g_system->updateScreen();
}
- } while (!playerDontAskQuit && quitValue2 && quitValue != 7);
+ } while (!_playerDontAskQuit);
// Free data
removeAllScripts(&relHead);
diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h
index caaaad2068..f9d0e2fc78 100644
--- a/engines/cruise/cruise_main.h
+++ b/engines/cruise/cruise_main.h
@@ -62,9 +62,6 @@ enum MouseButton {
/*#define DUMP_SCRIPT
#define DUMP_OBJECT*/
-#define ASSERT_PTR assert
-#define ASSERT assert
-
enum ResType {
OBJ_TYPE_LINE = 0,
OBJ_TYPE_MASK = 1,
diff --git a/engines/cruise/ctp.cpp b/engines/cruise/ctp.cpp
index b5151f3f7a..9515b552e1 100644
--- a/engines/cruise/ctp.cpp
+++ b/engines/cruise/ctp.cpp
@@ -95,7 +95,6 @@ void getWalkBoxCenter(int n, int16 table[][40]) {
// ax dx bx
void renderCTPWalkBox(int16 *walkboxData, int hotPointX, int hotPointY, int X, int Y, int scale) {
int numPoints;
- int i;
int16 *destination;
int startX = X - ((upscaleValue(hotPointX, scale) + 0x8000) >> 16);
@@ -105,7 +104,7 @@ void renderCTPWalkBox(int16 *walkboxData, int hotPointX, int hotPointY, int X, i
destination = polyBuffer2;
- for (i = 0; i < numPoints; i++) {
+ for (int i = 0; i < numPoints; i++) {
int pointX = *(walkboxData++);
int pointY = *(walkboxData++);
@@ -119,7 +118,7 @@ void renderCTPWalkBox(int16 *walkboxData, int hotPointX, int hotPointY, int X, i
m_color = 0;
ctpVarUnk = 0;
- for (i = 0; i < numPoints; i++) {
+ for (int i = 0; i < numPoints; i++) {
walkboxTable[i] = i;
}
@@ -245,7 +244,7 @@ int initCt(const char *ctpName) {
}
// get the path-finding coordinates
- ASSERT((segementSizeTable[0] % 4) == 0);
+ assert((segementSizeTable[0] % 4) == 0);
for (int i = 0; i < segementSizeTable[0] / 4; i++) {
ctp_routeCoords[i][0] = (int16)READ_BE_UINT16(dataPointer);
dataPointer += 2;
@@ -254,7 +253,7 @@ int initCt(const char *ctpName) {
}
// get the path-finding line informations (indexing the routeCoords array)
- ASSERT((segementSizeTable[1] % 20) == 0);
+ assert((segementSizeTable[1] % 20) == 0);
for (int i = 0; i < segementSizeTable[1] / 20; i++) {
for (int j = 0; j < 10; j++) {
ctp_routes[i][j] = (int16)READ_BE_UINT16(dataPointer);
@@ -263,7 +262,7 @@ int initCt(const char *ctpName) {
}
// read polygons
- ASSERT((segementSizeTable[2] % 80) == 0);
+ assert((segementSizeTable[2] % 80) == 0);
for (int i = 0; i < segementSizeTable[2] / 80; i++) {
for (int j = 0; j < 40; j++) {
ctp_walkboxTable[i][j] = (int16)READ_BE_UINT16(dataPointer);
@@ -278,14 +277,14 @@ int initCt(const char *ctpName) {
} else {
// get the walkbox type
// Type: 0x00 - non walkable, 0x01 - walkable, 0x02 - exit zone
- ASSERT((segementSizeTable[3] % 2) == 0);
+ assert((segementSizeTable[3] % 2) == 0);
for (int i = 0; i < segementSizeTable[3] / 2; i++) {
walkboxColor[i] = (int16)READ_BE_UINT16(dataPointer);
dataPointer += 2;
}
// change indicator, walkbox type can change, i.e. blocked by object (values are either 0x00 or 0x01)
- ASSERT((segementSizeTable[4] % 2) == 0);
+ assert((segementSizeTable[4] % 2) == 0);
for (int i = 0; i < segementSizeTable[4] / 2; i++) {
walkboxState[i] = (int16)READ_BE_UINT16(dataPointer);
dataPointer += 2;
@@ -293,14 +292,14 @@ int initCt(const char *ctpName) {
}
//
- ASSERT((segementSizeTable[5] % 2) == 0);
+ assert((segementSizeTable[5] % 2) == 0);
for (int i = 0; i < segementSizeTable[5] / 2; i++) {
walkboxColorIndex[i] = (int16)READ_BE_UINT16(dataPointer);
dataPointer += 2;
}
//
- ASSERT((segementSizeTable[6] % 2) == 0);
+ assert((segementSizeTable[6] % 2) == 0);
for (int i = 0; i < segementSizeTable[6] / 2; i++) {
walkboxZoom[i] = (int16)READ_BE_UINT16(dataPointer);
dataPointer += 2;
diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp
index e38343c215..7a1258dbde 100644
--- a/engines/cruise/dataLoader.cpp
+++ b/engines/cruise/dataLoader.cpp
@@ -170,11 +170,11 @@ int createResFileEntry(int width, int height, int size, int resType) {
return 0; // for compilers that don't support NORETURN
#if 0
- int i;
int entryNumber;
int div = 0;
- for (i = 0; i < NUM_FILE_ENTRIES; i++) {
+ int i = 0;
+ for (; i < NUM_FILE_ENTRIES; i++) {
if (!filesDatabase[i].subData.ptr)
break;
}
@@ -225,7 +225,7 @@ fileTypeEnum getFileType(const char *name) {
newFileType = type_FNT;
}
- ASSERT(newFileType != type_UNK);
+ assert(newFileType != type_UNK);
return newFileType;
}
@@ -280,10 +280,9 @@ int loadFileRange(const char *name, int startIdx, int currentEntryIdx, int numId
switch (fileType) {
case type_SET: {
- int i;
int numMaxEntriesInSet = getNumMaxEntiresInSet(ptr);
- for (i = 0; i < numIdx; i++) {
+ for (int i = 0; i < numIdx; i++) {
if ((startIdx + i) > numMaxEntriesInSet) {
MemFree(ptr);
return 0; // exit if limit is reached
@@ -325,12 +324,9 @@ int loadFullBundle(const char *name, int startIdx) {
switch (fileType) {
case type_SET: {
// Sprite set
- int i;
- int numMaxEntriesInSet;
+ int numMaxEntriesInSet = getNumMaxEntiresInSet(ptr); // get maximum number of sprites/animations in SET file
- numMaxEntriesInSet = getNumMaxEntiresInSet(ptr); // get maximum number of sprites/animations in SET file
-
- for (i = 0; i < numMaxEntriesInSet; i++) {
+ for (int i = 0; i < numMaxEntriesInSet; i++) {
loadSetEntry(name, ptr, i, startIdx + i);
}
@@ -356,39 +352,32 @@ int loadFullBundle(const char *name, int startIdx) {
}
int loadFNTSub(uint8 *ptr, int destIdx) {
- uint8 *ptr2 = ptr;
- uint8 *destPtr;
- int fileIndex;
- //uint32 fontSize;
-
- ptr2 += 4;
+ uint8 *ptr2 = ptr + 4;
loadFileVar1 = READ_BE_UINT32(ptr2);
- if (destIdx == -1) {
+ int fileIndex;
+ if (destIdx == -1)
fileIndex = createResFileEntry(loadFileVar1, 1, loadFileVar1, 1);
- } else {
+ else
fileIndex = updateResFileEntry(loadFileVar1, 1, loadFileVar1, destIdx, 1);
- }
- destPtr = filesDatabase[fileIndex].subData.ptr;
+ if (fileIndex < 0)
+ error("Unable to load FNT resource");
- if (destPtr != NULL) {
- int32 i;
- uint8 *currentPtr;
+ uint8 *destPtr = filesDatabase[fileIndex].subData.ptr;
+ if (destPtr != NULL) {
memcpy(destPtr, ptr2, loadFileVar1);
- //fontSize = READ_BE_UINT32(ptr2);
-
destPtr = filesDatabase[fileIndex].subData.ptr;
bigEndianLongToNative((int32 *) destPtr);
bigEndianLongToNative((int32 *)(destPtr + 4));
flipGen(destPtr + 8, 6);
- currentPtr = destPtr + 14;
+ uint8 *currentPtr = destPtr + 14;
- for (i = 0; i < (int16)READ_UINT16(destPtr + 8); i++) {
+ for (int i = 0; i < (int16)READ_UINT16(destPtr + 8); i++) {
bigEndianLongToNative((int32 *) currentPtr);
currentPtr += 4;
@@ -401,16 +390,17 @@ int loadFNTSub(uint8 *ptr, int destIdx) {
}
int loadSPLSub(uint8 *ptr, int destIdx) {
- uint8 *destPtr;
int fileIndex;
- if (destIdx == -1) {
+ if (destIdx == -1)
fileIndex = createResFileEntry(loadFileVar1, 1, loadFileVar1, 1);
- } else {
+ else
fileIndex = updateResFileEntry(loadFileVar1, 1, loadFileVar1, destIdx, 1);
- }
- destPtr = filesDatabase[fileIndex].subData.ptr;
+ if (fileIndex < 0)
+ error("Unable to load SPL resource");
+
+ uint8* destPtr = filesDatabase[fileIndex].subData.ptr;
memcpy(destPtr, ptr, loadFileVar1);
return 1;
@@ -423,135 +413,119 @@ int loadSetEntry(const char *name, uint8 *ptr, int currentEntryIdx, int currentD
int sec = 0;
uint16 numIdx;
- if (!strcmp((char *)ptr, "SEC")) {
+ if (!strcmp((char *)ptr, "SEC"))
sec = 1;
- }
numIdx = READ_BE_UINT16(ptr + 4);
-
ptr3 = ptr + 6;
-
offset = currentEntryIdx * 16;
- {
- int resourceSize;
- int fileIndex;
- setHeaderEntry localBuffer;
- uint8 *ptr5;
-
- Common::MemoryReadStream s4(ptr + offset + 6, 16);
-
- localBuffer.offset = s4.readUint32BE();
- localBuffer.width = s4.readUint16BE();
- localBuffer.height = s4.readUint16BE();
- localBuffer.type = s4.readUint16BE();
- localBuffer.transparency = s4.readUint16BE() & 0x1F;
- localBuffer.hotspotY = s4.readUint16BE();
- localBuffer.hotspotX = s4.readUint16BE();
+ int resourceSize;
+ int fileIndex;
+ setHeaderEntry localBuffer;
- if (sec == 1)
- // Type 1: Width - (1*2) , Type 5: Width - (5*2)
- localBuffer.width -= localBuffer.type * 2;
+ Common::MemoryReadStream s4(ptr + offset + 6, 16);
- resourceSize = localBuffer.width * localBuffer.height;
+ localBuffer.offset = s4.readUint32BE();
+ localBuffer.width = s4.readUint16BE();
+ localBuffer.height = s4.readUint16BE();
+ localBuffer.type = s4.readUint16BE();
+ localBuffer.transparency = s4.readUint16BE() & 0x1F;
+ localBuffer.hotspotY = s4.readUint16BE();
+ localBuffer.hotspotX = s4.readUint16BE();
- if (!sec && (localBuffer.type == 5))
- // Type 5: Width - (2*5)
- localBuffer.width -= 10;
+ if (sec == 1)
+ // Type 1: Width - (1*2) , Type 5: Width - (5*2)
+ localBuffer.width -= localBuffer.type * 2;
- if (currentDestEntry == -1) {
- fileIndex = createResFileEntry(localBuffer.width, localBuffer.height, resourceSize, localBuffer.type);
- } else {
- fileIndex = updateResFileEntry(localBuffer.height, localBuffer.width, resourceSize, currentDestEntry, localBuffer.type);
- }
+ resourceSize = localBuffer.width * localBuffer.height;
- if (fileIndex < 0) {
- return -1; // TODO: buffer is not freed
- }
+ if (!sec && (localBuffer.type == 5))
+ // Type 5: Width - (2*5)
+ localBuffer.width -= 10;
- if (!sec && (localBuffer.type == 5)) {
- // There are sometimes sprites with a reduced width than what their pixels provide.
- // The original handled this here by copy parts of each line - for ScummVM, we're
- // simply setting the width in bytes and letting the decoder do the rest
- filesDatabase[fileIndex].width += 2;
- }
+ if (currentDestEntry == -1)
+ fileIndex = createResFileEntry(localBuffer.width, localBuffer.height, resourceSize, localBuffer.type);
+ else
+ fileIndex = updateResFileEntry(localBuffer.height, localBuffer.width, resourceSize, currentDestEntry, localBuffer.type);
- ptr5 = ptr3 + localBuffer.offset + numIdx * 16;
+ if (fileIndex < 0)
+ return -1; // TODO: buffer is not freed
- memcpy(filesDatabase[fileIndex].subData.ptr, ptr5, resourceSize);
+ if (!sec && (localBuffer.type == 5)) {
+ // There are sometimes sprites with a reduced width than what their pixels provide.
+ // The original handled this here by copy parts of each line - for ScummVM, we're
+ // simply setting the width in bytes and letting the decoder do the rest
+ filesDatabase[fileIndex].width += 2;
+ }
- ptr5 += resourceSize;
+ uint8 *ptr5 = ptr3 + localBuffer.offset + numIdx * 16;
+ memcpy(filesDatabase[fileIndex].subData.ptr, ptr5, resourceSize);
- switch (localBuffer.type) {
- case 0: { // polygon
+ switch (localBuffer.type) {
+ case 0: // polygon
filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_POLY;
filesDatabase[fileIndex].subData.index = currentEntryIdx;
break;
- }
- case 1: {
+
+ case 1:
filesDatabase[fileIndex].width = filesDatabase[fileIndex].widthInColumn * 8;
filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_BGMASK;
decodeGfxUnified(&filesDatabase[fileIndex], localBuffer.type);
filesDatabase[fileIndex].subData.index = currentEntryIdx;
filesDatabase[fileIndex].subData.transparency = 0;
break;
- }
- case 4: {
+
+ case 4:
filesDatabase[fileIndex].width = filesDatabase[fileIndex].widthInColumn * 2;
filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_SPRITE;
decodeGfxUnified(&filesDatabase[fileIndex], localBuffer.type);
filesDatabase[fileIndex].subData.index = currentEntryIdx;
filesDatabase[fileIndex].subData.transparency = localBuffer.transparency % 0x10;
break;
- }
- case 5: {
+
+ case 5:
filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_SPRITE;
decodeGfxUnified(&filesDatabase[fileIndex], localBuffer.type);
filesDatabase[fileIndex].width = filesDatabase[fileIndex].widthInColumn;
filesDatabase[fileIndex].subData.index = currentEntryIdx;
filesDatabase[fileIndex].subData.transparency = localBuffer.transparency;
break;
- }
- case 8: {
+
+ case 8:
filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_SPRITE;
filesDatabase[fileIndex].width = filesDatabase[fileIndex].widthInColumn;
filesDatabase[fileIndex].subData.index = currentEntryIdx;
filesDatabase[fileIndex].subData.transparency = localBuffer.transparency;
break;
- }
- default: {
- warning("Unsuported gfx loading type: %d", localBuffer.type);
+
+ default:
+ warning("Unsupported gfx loading type: %d", localBuffer.type);
break;
- }
- }
+ }
- if (name != filesDatabase[fileIndex].subData.name)
- strcpy(filesDatabase[fileIndex].subData.name, name);
+ if (name != filesDatabase[fileIndex].subData.name)
+ Common::strlcpy(filesDatabase[fileIndex].subData.name, name, sizeof(filesDatabase[fileIndex].subData.name));
- // create the mask
- switch (localBuffer.type) {
+ // create the mask
+ switch (localBuffer.type) {
case 1:
case 4:
case 5:
- case 8: {
- int maskX;
- int maskY;
-
+ case 8:
memset(filesDatabase[fileIndex].subData.ptrMask, 0, filesDatabase[fileIndex].width / 8 * filesDatabase[fileIndex].height);
- for (maskY = 0; maskY < filesDatabase[fileIndex].height; maskY++) {
- for (maskX = 0; maskX < filesDatabase[fileIndex].width; maskX++) {
+ for (int maskY = 0; maskY < filesDatabase[fileIndex].height; maskY++) {
+ for (int maskX = 0; maskX < filesDatabase[fileIndex].width; maskX++) {
if (*(filesDatabase[fileIndex].subData.ptr + filesDatabase[fileIndex].width * maskY + maskX) != filesDatabase[fileIndex].subData.transparency) {
*(filesDatabase[fileIndex].subData.ptrMask + filesDatabase[fileIndex].width / 8 * maskY + maskX / 8) |= 0x80 >> (maskX & 7);
}
}
}
+ break;
+ default:
break;
- }
- default: {
- }
- }
}
// TODO: free
diff --git a/engines/cruise/debugger.cpp b/engines/cruise/debugger.cpp
index 4ef66ee11e..d4e706a094 100644
--- a/engines/cruise/debugger.cpp
+++ b/engines/cruise/debugger.cpp
@@ -29,9 +29,9 @@
namespace Cruise {
Debugger::Debugger(): GUI::Debugger() {
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("hotspots", WRAP_METHOD(Debugger, cmd_hotspots));
- DCmd_Register("items", WRAP_METHOD(Debugger, cmd_items));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("hotspots", WRAP_METHOD(Debugger, cmd_hotspots));
+ registerCmd("items", WRAP_METHOD(Debugger, cmd_items));
}
/**
@@ -70,7 +70,7 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) {
if (*pObjectName) {
getMultipleObjectParam(currentObject->overlay, currentObject->idx, &params);
- DebugPrintf("%s %s - %d,%d\n", pObjectName, pObjType, params.X, params.Y);
+ debugPrintf("%s %s - %d,%d\n", pObjectName, pObjType, params.X, params.Y);
}
}
@@ -96,7 +96,7 @@ bool Debugger::cmd_items(int argc, const char **argv) {
getSingleObjectParam(i, j, 5, &returnVar);
if (returnVar < -1)
- DebugPrintf("%s\n", getObjectName(j, pOvlData->arrayNameObj));
+ debugPrintf("%s\n", getObjectName(j, pOvlData->arrayNameObj));
}
}
}
diff --git a/engines/cruise/decompiler.cpp b/engines/cruise/decompiler.cpp
index 0c83bd6968..7691a1bba7 100644
--- a/engines/cruise/decompiler.cpp
+++ b/engines/cruise/decompiler.cpp
@@ -130,13 +130,12 @@ void pushDecomp(char *string, ...) {
void resolveDecompShort(char *buffer) {
ovlData3Struct *data3Ptr = currentScript;
- int i;
importScriptStruct *importEntry =
(importScriptStruct *)(data3Ptr->dataPtr +
data3Ptr->offsetToImportData);
- for (i = 0; i < data3Ptr->numRelocGlob; i++) {
+ for (int i = 0; i < data3Ptr->numRelocGlob; i++) {
switch (importEntry->type) {
case 20: // script
case 30:
@@ -177,13 +176,12 @@ void resolveDecompShort(char *buffer) {
void resolveDecompChar(char *buffer) {
ovlData3Struct *data3Ptr = currentScript;
- int i;
importScriptStruct *importEntry =
(importScriptStruct *)(data3Ptr->dataPtr +
data3Ptr->offsetToImportData);
- for (i = 0; i < data3Ptr->numRelocGlob; i++) {
+ for (int i = 0; i < data3Ptr->numRelocGlob; i++) {
switch (importEntry->type) {
default: {
if (importEntry->offset ==
@@ -315,9 +313,7 @@ void resolveVarName(char *ovlIdxString, int varType, char *varIdxString,
}
if (!strcmp(ovlIdxString, "0")) {
- int i;
-
- for (i = 0; i < currentDecompOvl->numSymbGlob; i++) {
+ for (int i = 0; i < currentDecompOvl->numSymbGlob; i++) {
if (varIdx == currentDecompOvl->arraySymbGlob[i].idx) {
if (((currentDecompOvl->arraySymbGlob[i].var4 & 0xF0) == 0) && varType != 0x20) { // var
strcpy(outputName,
@@ -495,7 +491,7 @@ int decompOpcodeType2() {
char buffer3[256];
char varName[256];
int byte1 = getByteFromDecompScriptReal();
- int byte2 = getByteFromDecompScriptReal();
+ getByteFromDecompScriptReal();
getShortFromDecompScript(buffer3);
resolveVarName("0", byte1 & 7, buffer3, varName);
@@ -506,7 +502,7 @@ int decompOpcodeType2() {
}
case 5: {
int byte1 = getByteFromDecompScriptReal();
- int byte2 = getByteFromDecompScriptReal();
+ getByteFromDecompScriptReal();
short int short1 = getShortFromDecompScriptReal();
int8 *ptr = scriptDataPtrTable[byte1 & 7] + short1;
@@ -559,7 +555,7 @@ int decompMath() {
break;
}
case 4: {
- sprintf(tempbuffer, "%s\%%s", param1, param2);
+ sprintf(tempbuffer, "%s % %s", param1, param2);
pushDecomp(tempbuffer);
break;
}
@@ -701,49 +697,41 @@ int decompSwapStack() {
int decompFunction() {
currentScriptOpcodeType = getByteFromDecompScriptReal();
-// addDecomp("OP_%X", currentScriptOpcodeType);
switch (currentScriptOpcodeType) {
- case 0x1: {
- pushDecomp("_setdoFade()");
+ case 0x1:
+ pushDecomp("Op_FadeIn()");
break;
- }
- case 0x2: {
- pushDecomp("_prepareFade()");
+
+ case 0x2:
+ pushDecomp("Op_FadeOut()");
break;
- }
- case 0x3: {
- sprintf(tempbuffer, "_loadBackground(%s,%s)",
- popDecomp(), popDecomp());
+
+ case 0x3:
+ sprintf(tempbuffer, "Op_loadBackground(%s,%s)", popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x4: {
- sprintf(tempbuffer, "_loadFullBundle(%s,%s)",
- popDecomp(), popDecomp());
+
+ case 0x4:
+ sprintf(tempbuffer, "Op_LoadAbs(%s,%s)", popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x5: {
- sprintf(tempbuffer, "_addCell(%s,%s,%s)", popDecomp(),
- popDecomp(), popDecomp());
+
+ case 0x5:
+ sprintf(tempbuffer, "Op_AddCell(%s,%s,%s)", popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
+
case 0x6: {
unsigned long int numArg = atoi(popDecomp());
- char *ovlStr;
- char *idxStr;
- int i;
char functionName[100];
- idxStr = popDecomp();
- ovlStr = popDecomp();
+ char *idxStr = popDecomp();
+ char *ovlStr = popDecomp();
resolveVarName(ovlStr, 0x20, idxStr, functionName);
+ sprintf(tempbuffer, "Op_AddProc(%s", functionName);
- sprintf(tempbuffer, "_startASync(%s", functionName);
-
- for (i = 0; i < numArg; i++) {
+ for (int i = 0; i < numArg; i++) {
strcatuint8(tempbuffer, ",");
strcatuint8(tempbuffer, popDecomp());
}
@@ -752,196 +740,165 @@ int decompFunction() {
pushDecomp(tempbuffer);
break;
- }
- case 0x7: {
- char *var1;
- char *objIdxStr;
- char *ovlStr;
+ }
- var1 = popDecomp();
- objIdxStr = popDecomp();
- ovlStr = popDecomp();
+ case 0x7: {
+ char *var1 = popDecomp();
+ char *objIdxStr = popDecomp();
+ char *ovlStr = popDecomp();
- sprintf(tempbuffer,
- "_createObjectFromOvlData(ovl:%s,dataIdx:%s,%s)",
- ovlStr, objIdxStr, var1);
+ sprintf(tempbuffer, "Op_InitializeState(ovl:%s,dataIdx:%s,%s)", ovlStr, objIdxStr, var1);
pushDecomp(tempbuffer);
break;
- }
- case 0x8: {
- sprintf(tempbuffer, "_removeCell(%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp());
+ }
+
+ case 0x8:
+ sprintf(tempbuffer, "Op_RemoveCell(%s,%s,%s)", popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x9: {
- pushDecomp("_freeobjectList()");
+
+ case 0x9:
+ pushDecomp("Op_FreeCell()");
break;
- }
- case 0xA: {
- sprintf(tempbuffer, "_removeScript(ovl(%s),%s)",
- popDecomp(), popDecomp());
+
+ case 0xA:
+ sprintf(tempbuffer, "Op_RemoveProc(ovl(%s),%s)", popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0xB: {
- sprintf(tempbuffer, "_resetFilesEntries(%s,%s)",
- popDecomp(), popDecomp());
+
+ case 0xB:
+ sprintf(tempbuffer, "Op_RemoveFrame(%s,%s)", popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0xC: {
- sprintf(tempbuffer, "_loadOverlay(%s)", popDecomp());
+
+ case 0xC:
+ sprintf(tempbuffer, "Op_LoadOverlay(%s)", popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0xD: {
- sprintf(tempbuffer, "_palManipulation(%s,%s,%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp(), popDecomp(),
- popDecomp());
+
+ case 0xD:
+ sprintf(tempbuffer, "Op_SetColor(%s,%s,%s,%s,%s)", popDecomp(), popDecomp(), popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0xE: {
- sprintf(tempbuffer, "_playSample(%s,%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp(),
- popDecomp());
+
+ case 0xE:
+ sprintf(tempbuffer, "Op_PlayFX(%s,%s,%s,%s)", popDecomp(), popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x10: {
- sprintf(tempbuffer, "_releaseScript2(%s)",
- popDecomp());
+
+ case 0x10:
+ sprintf(tempbuffer, "Op_FreeOverlay(%s)", popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x11: {
- sprintf(tempbuffer, "_getOverlayIdx(%s)", popDecomp());
+
+ case 0x11:
+ sprintf(tempbuffer, "Op_FindOverlay(%s)", popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x13: {
- sprintf(tempbuffer,
- "_displayMessage(%s,\"%s\",%s,%s,%s,%s)",
- popDecomp(), resolveMessage(popDecomp()),
- popDecomp(), popDecomp(), popDecomp(),
- popDecomp());
+
+ case 0x13:
+ sprintf(tempbuffer, "Op_AddMessage(%s,\"%s\",%s,%s,%s,%s)", popDecomp(),
+ resolveMessage(popDecomp()), popDecomp(), popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x14: {
- sprintf(tempbuffer, "_removeObject(ovl(%s),%s)",
- popDecomp(), popDecomp());
+
+ case 0x14:
+ sprintf(tempbuffer, "Op_RemoveMessage(ovl(%s),%s)", popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x15: {
- pushDecomp("_pauseScript()");
+
+ case 0x15:
+ pushDecomp("Op_UserWait()");
break;
- }
- case 0x16: {
- sprintf(tempbuffer,
- "_Op_FreezeCell(%s,%s,%s,%s,%s,%s)", popDecomp(),
- popDecomp(), popDecomp(), popDecomp(), popDecomp(),
- popDecomp());
+
+ case 0x16:
+ sprintf(tempbuffer, "Op_FreezeCell(%s,%s,%s,%s,%s,%s)", popDecomp(), popDecomp(),
+ popDecomp(), popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x17: {
- sprintf(tempbuffer, "_loadCtp(%s)", popDecomp());
+
+ case 0x17:
+ sprintf(tempbuffer, "Op_LoadCt(%s)", popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x18: {
- sprintf(tempbuffer,
- "_Op_AddAnimation(%s,%s,%s,%s,%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp(), popDecomp(),
- popDecomp(), popDecomp(), popDecomp());
+
+ case 0x18:
+ sprintf(tempbuffer, "Op_AddAnimation(%s,%s,%s,%s,%s,%s,%s)", popDecomp(), popDecomp(),
+ popDecomp(), popDecomp(), popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x19: {
- sprintf(tempbuffer, "_Op_RemoveAnimation(%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp());
+
+ case 0x19:
+ sprintf(tempbuffer, "Op_RemoveAnimation(%s,%s,%s)", popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x1A: {
- sprintf(tempbuffer, "_setupScaleFormula(%s,%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp(),
- popDecomp());
+
+ case 0x1A:
+ sprintf(tempbuffer, "Op_SetZoom(%s,%s,%s,%s)", popDecomp(), popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x1E: {
- sprintf(tempbuffer, "_Op_TrackAnim(%s,%s,%s,%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp(), popDecomp(),
- popDecomp(), popDecomp());
+
+ case 0x1E:
+ sprintf(tempbuffer, "Op_TrackAnim(%s,%s,%s,%s,%s,%s)", popDecomp(), popDecomp(),
+ popDecomp(), popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x21: {
- sprintf(tempbuffer, "_isActorLoaded(%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp());
+
+ case 0x21:
+ sprintf(tempbuffer, "Op_EndAnim(%s,%s,%s)", popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x22: {
- sprintf(tempbuffer, "_computeScale(%s)", popDecomp());
+
+ case 0x22:
+ sprintf(tempbuffer, "Op_GetZoom(%s)", popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x23: {
- sprintf(tempbuffer, "_convertToScale(%s,%s)",
- popDecomp(), popDecomp());
+
+ case 0x23:
+ sprintf(tempbuffer, "Op_GetStep(%s,%s)", popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x24: {
- sprintf(tempbuffer, "_op_24(%s,%s,%s,%s)", popDecomp(),
- popDecomp(), popDecomp(), popDecomp());
+
+ case 0x24:
+ sprintf(tempbuffer, "Op_SetStringColors(%s,%s,%s,%s)", popDecomp(), popDecomp(),
+ popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x27: {
- sprintf(tempbuffer, "_getWalkBoxCollision(%s,%s)",
- popDecomp(), popDecomp());
+
+ case 0x27:
+ sprintf(tempbuffer, "Op_getPixel(%s,%s)", popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x28: {
- sprintf(tempbuffer, "_changeSaveAllowedState(%s)",
- popDecomp());
+
+ case 0x28:
+ sprintf(tempbuffer, "Op_UserOn(%s)", popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x29: {
- pushDecomp("_freeAllPerso()");
+
+ case 0x29:
+ pushDecomp("Op_FreeCT()");
break;
- }
- case 0x2B: {
- sprintf(tempbuffer, "_getProcIdx(%s,%s)", popDecomp(),
- popDecomp());
+
+ case 0x2B:
+ sprintf(tempbuffer, "Op_FindProc(%s,%s)", popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x2C: {
- sprintf(tempbuffer, "_setObjectPosition(%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp());
+
+ case 0x2C:
+ sprintf(tempbuffer, "Op_WriteObject(%s,%s,%s)", popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x2E: {
- sprintf(tempbuffer, "_releaseScript(%s)", popDecomp());
+
+ case 0x2E:
+ sprintf(tempbuffer, "Op_RemoveOverlay(%s)", popDecomp());
pushDecomp(tempbuffer);
break;
- }
- case 0x2F: {
- sprintf(tempbuffer, "_addBackgroundIncrust(%s,%s,%s)",
- popDecomp(), popDecomp(), popDecomp());
+
+ case 0x2F:
+ sprintf(tempbuffer, "Op_AddBackgroundIncrust(%s,%s,%s)", popDecomp(), popDecomp(), popDecomp());
pushDecomp(tempbuffer);
break;
- }
+
case 0x30: {
sprintf(tempbuffer, "_removeBackgroundIncrust(%s,%s)",
popDecomp(), popDecomp());
@@ -1094,7 +1051,6 @@ int decompFunction() {
unsigned long int numArg = atoi(popDecomp());
char *ovlStr;
char *idxStr;
- int i;
char functionName[256];
idxStr = popDecomp();
@@ -1104,7 +1060,7 @@ int decompFunction() {
sprintf(tempbuffer, "%s(", functionName);
- for (i = 0; i < numArg; i++) {
+ for (int i = 0; i < numArg; i++) {
if (i)
strcatuint8(tempbuffer, ",");
strcatuint8(tempbuffer, popDecomp());
@@ -1174,14 +1130,13 @@ int decompFunction() {
unsigned long int numArg = atoi(popDecomp());
char *ovlStr;
char *idxStr;
- int i;
idxStr = popDecomp();
ovlStr = popDecomp();
sprintf(tempbuffer, "_op_6F(%s,%s", idxStr, ovlStr);
- for (i = 0; i < numArg; i++) {
+ for (int i = 0; i < numArg; i++) {
strcatuint8(tempbuffer, ",");
strcatuint8(tempbuffer, popDecomp());
}
@@ -1286,9 +1241,7 @@ int decompBreak() {
}
void generateIndentation() {
- int i, j;
-
- for (i = 0; i < positionInDecompileLineTable; i++) {
+ for (int i = 0; i < positionInDecompileLineTable; i++) {
if (decompileLineTable[i].type != 0) {
char *gotoStatement;
int destLine;
@@ -1302,7 +1255,7 @@ void generateIndentation() {
destLine = atoi(gotoStatement);
destLineIdx = -1;
- for (j = 0; j < positionInDecompileLineTable; j++) {
+ for (int j = 0; j < positionInDecompileLineTable; j++) {
if (decompileLineTable[j].lineOffset == destLine) {
destLineIdx = j;
break;
@@ -1312,7 +1265,7 @@ void generateIndentation() {
assert(destLineIdx != -1);
if (destLineIdx > i) {
- for (j = i + 1; j < destLineIdx; j++) {
+ for (int j = i + 1; j < destLineIdx; j++) {
decompileLineTable[j].indent++;
}
@@ -1328,7 +1281,6 @@ void generateIndentation() {
void dumpScript(uint8 *ovlName, ovlDataStruct *ovlData, int idx) {
uint8 opcodeType;
char buffer[256];
- int i;
char temp[256];
char scriptName[256];
@@ -1367,9 +1319,8 @@ void dumpScript(uint8 *ovlName, ovlDataStruct *ovlData, int idx) {
decompileStackPosition = 0;
- for (i = 0; i < 64; i++) {
+ for (int i = 0; i < 64; i++)
decompOpcodeTypeTable[i] = NULL;
- }
decompOpcodeTypeTable[1] = decompLoadVar;
decompOpcodeTypeTable[2] = decompSaveVar;
@@ -1412,22 +1363,18 @@ void dumpScript(uint8 *ovlName, ovlDataStruct *ovlData, int idx) {
generateIndentation();
- for (i = 0; i < positionInDecompileLineTable; i++) {
- int j;
-
+ for (int i = 0; i < positionInDecompileLineTable; i++) {
if (decompileLineTable[i].pendingElse) {
fprintf(fHandle, "%05d:\t",
decompileLineTable[i].lineOffset);
- fprintf(fHandle, "else", decompileLineTable[i].line);
- fprintf(fHandle, "\n");
+ fprintf(fHandle, "else %s\n", decompileLineTable[i].line);
}
fprintf(fHandle, "%05d:\t", decompileLineTable[i].lineOffset);
- for (j = 0; j < decompileLineTable[i].indent; j++) {
+ for (int j = 0; j < decompileLineTable[i].indent; j++)
fprintf(fHandle, "\t");
- }
- fprintf(fHandle, "%s", decompileLineTable[i].line);
- fprintf(fHandle, "\n");
+
+ fprintf(fHandle, "%s\n", decompileLineTable[i].line);
}
fclose(fHandle);
diff --git a/engines/cruise/font.cpp b/engines/cruise/font.cpp
index 80fb0e8a02..43fbf8c79b 100644
--- a/engines/cruise/font.cpp
+++ b/engines/cruise/font.cpp
@@ -50,7 +50,7 @@ int32 getLineHeight(int16 charCount, const FontEntry *fontPtr) {
}
/**
- * This function determins how many lines the text will have
+ * This function determines how many lines the text will have
*/
int32 getTextLineCount(int32 rightBorder_X, int16 wordSpacingWidth,
const FontEntry *fontData, const char *textString) {
@@ -59,6 +59,9 @@ int32 getTextLineCount(int32 rightBorder_X, int16 wordSpacingWidth,
uint8 ch;
int32 total = 0, lineLength = 0;
+ if (rightBorder_X == 0)
+ error("getTextLineCount() - invalid parameter");
+
if (!*textString)
return (0);
@@ -89,6 +92,7 @@ int32 getTextLineCount(int32 rightBorder_X, int16 wordSpacingWidth,
if (lineLength > 0)
total += rightBorder_X;
+
return (total / rightBorder_X);
}
@@ -176,30 +180,26 @@ void bigEndianLongToNative(void *var) {
}
void flipGen(void *var, int32 length) {
- int i;
short int *varPtr = (int16 *) var;
- for (i = 0; i < (length / 2); i++) {
+ for (int i = 0; i < (length / 2); i++) {
bigEndianShortToNative(&varPtr[i]);
}
}
void renderWord(const uint8 *fontPtr_Data, uint8 *outBufferPtr, int xOffset, int yOffset,
int32 height, int32 param4, int32 stringRenderBufferSize, int32 width, int32 charWidth) {
- int i;
- int j;
const uint8 *fontPtr_Data2 = fontPtr_Data + height * 2;
-
outBufferPtr += yOffset * width + xOffset;
- for (i = 0; i < height; i++) { // y++
+ for (int i = 0; i < height; i++) { // y++
uint16 bitSet1 = READ_BE_UINT16(fontPtr_Data);
uint16 bitSet2 = READ_BE_UINT16(fontPtr_Data2);
fontPtr_Data += sizeof(uint16);
fontPtr_Data2 += sizeof(uint16);
- for (j = 0; j < charWidth; j++) {
+ for (int j = 0; j < charWidth; j++) {
*outBufferPtr = ((bitSet1 >> 15) & 1) | ((bitSet2 >> 14) & 2);
outBufferPtr++;
diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp
index 7af6b73238..3f794c4e70 100644
--- a/engines/cruise/function.cpp
+++ b/engines/cruise/function.cpp
@@ -87,9 +87,7 @@ int16 Op_Exec() {
int numOfArgToPop = popVar();
- int i = 0;
-
- for (i = 0; i < numOfArgToPop; i++) {
+ for (int i = 0; i < numOfArgToPop; i++) {
popTable[numOfArgToPop - i - 1] = popVar();
}
@@ -111,7 +109,7 @@ int16 Op_Exec() {
ptr2 = ptr;
- for (i = 0; i < numOfArgToPop; i++) {
+ for (int i = 0; i < numOfArgToPop; i++) {
WRITE_BE_UINT16(ptr2, popTable[i]);
ptr2 += 2;
}
@@ -198,13 +196,22 @@ int16 Op_Random() {
int16 Op_PlayFX() {
int volume = popVar();
+
+#if 0
int speed = popVar();
- /*int channelNum = */popVar();
+ int channelNum = popVar();
+#else
+ popVar();
+ popVar();
+#endif
+
int sampleNum = popVar();
if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) {
+#if 0
if (speed == -1)
speed = filesDatabase[sampleNum].subData.transparency;
+#endif
_vm->sound().playSound(filesDatabase[sampleNum].subData.ptr,
filesDatabase[sampleNum].width, volume);
@@ -215,13 +222,23 @@ int16 Op_PlayFX() {
int16 Op_LoopFX() {
int volume = popVar();
+
+#if 0
int speed = popVar();
- /*int channelNum = */popVar();
+ int channelNum = popVar();
+#else
+ popVar();
+ popVar();
+#endif
+
int sampleNum = popVar();
if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) {
+
+#if 0
if (speed == -1)
speed = filesDatabase[sampleNum].subData.transparency;
+#endif
_vm->sound().playSound(filesDatabase[sampleNum].subData.ptr,
filesDatabase[sampleNum].width, volume);
@@ -335,20 +352,15 @@ int16 Op_RemoveMessage() {
}
int16 Op_FindSet() {
- int16 i;
- char name[36] = "";
- char *ptr;
-
- ptr = (char *) popPtr();
-
- if (!ptr) {
+ char *ptr = (char *) popPtr();
+ if (!ptr)
return -1;
- }
- strcpy(name, ptr);
+ char name[36] = "";
+ Common::strlcpy(name, ptr, sizeof(name));
strToUpper(name);
- for (i = 0; i < NUM_FILE_ENTRIES; i++) {
+ for (int i = 0; i < NUM_FILE_ENTRIES; i++) {
if (!strcmp(name, filesDatabase[i].subData.name)) {
return (i);
}
@@ -397,8 +409,7 @@ int16 Op_FreeOverlay() {
char *namePtr;
namePtr = (char *) popPtr();
-
- strcpy(localName, namePtr);
+ Common::strlcpy(localName, namePtr, sizeof(localName));
if (localName[0]) {
strToUpper(localName);
@@ -410,14 +421,10 @@ int16 Op_FreeOverlay() {
int16 Op_FindProc() {
char name[36] = "";
- char *ptr;
- int param;
-
- ptr = (char *)popPtr();
- strcpy(name, ptr);
-
- param = getProcParam(popVar(), 20, name);
+ char *ptr = (char *)popPtr();
+ Common::strlcpy(name, ptr, sizeof(name));
+ int param = getProcParam(popVar(), 20, name);
return param;
}
@@ -497,7 +504,7 @@ int16 Op_LoadBackground() {
ptr = (char *) popPtr();
- strcpy(bgName, ptr);
+ Common::strlcpy(bgName, ptr, sizeof(bgName));
bgIdx = popVar();
@@ -537,12 +544,10 @@ int16 Op_LoadFrame() {
int param1;
int param2;
int param3;
- char name[36] = "";
- char *ptr;
-
- ptr = (char *) popPtr();
- strcpy(name, ptr);
+ char name[36] = "";
+ char *ptr = (char *) popPtr();
+ Common::strlcpy(name, ptr, sizeof(name));
param1 = popVar();
param2 = popVar();
@@ -566,16 +571,14 @@ int16 Op_LoadFrame() {
}
int16 Op_LoadAbs() {
- int slot;
- char name[36] = "";
- char *ptr;
int result = 0;
- ptr = (char *) popPtr();
- slot = popVar();
+ char *ptr = (char *) popPtr();
+ int slot = popVar();
if ((slot >= 0) && (slot < NUM_FILE_ENTRIES)) {
- strcpy(name, ptr);
+ char name[36] = "";
+ Common::strlcpy(name, ptr, sizeof(name));
strToUpper(name);
gfxModuleData_gfxWaitVSync();
@@ -641,7 +644,7 @@ int16 Op_FadeOut() {
flip();
fadeFlag = 1;
- PCFadeFlag = 1;
+ PCFadeFlag = true;
return 0;
}
@@ -663,8 +666,7 @@ int16 Op_FindOverlay() {
char *ptr;
ptr = (char *) popPtr();
-
- strcpy(name, ptr);
+ Common::strlcpy(name, ptr, sizeof(name));
strToUpper(name);
return (isOverlayLoaded(name));
@@ -996,11 +998,9 @@ int16 Op_SetColor() {
int endIdx = popVar();
int startIdx = popVar();
- int i;
-
#define convertRatio 36.571428571428571428571428571429
- for (i = startIdx; i <= endIdx; i++) {
+ for (int i = startIdx; i <= endIdx; i++) {
int offsetTable[3];
offsetTable[0] = (int)(colorR * convertRatio);
@@ -1099,11 +1099,6 @@ actorStruct *addAnimation(actorStruct * pHead, int overlay, int objIdx, int para
pCurrent = pPrevious->next;
}
- if (pCurrent && (pCurrent->overlayNumber == overlay)
- && (pCurrent->idx == objIdx) && (pCurrent->type == param2)) {
- return NULL;
- }
-
actorStruct *pNewElement = (actorStruct *) MemAlloc(sizeof(actorStruct));
if (!pNewElement)
return NULL;
@@ -1353,7 +1348,7 @@ int16 Op_LoadSong() {
const char *ptr = (const char *)popPtr();
char buffer[33];
- strcpy(buffer, ptr);
+ Common::strlcpy(buffer, ptr, sizeof(buffer));
strToUpper(buffer);
_vm->sound().loadMusic(buffer);
@@ -1382,12 +1377,11 @@ int16 Op_RestoreSong() {
}
int16 Op_SongSize() {
- int size, oldSize;
-
+ int oldSize;
if (_vm->sound().songLoaded()) {
oldSize = _vm->sound().numOrders();
- size = popVar();
+ int size = popVar();
if ((size >= 1) && (size < 128))
_vm->sound().setNumOrders(size);
} else
@@ -1517,8 +1511,9 @@ int16 Op_Itoa() {
int nbp = popVar();
int param[160];
char txt[40];
- char format[30];
- char nbf[20];
+
+ for (int i = 0; i < 160; ++i)
+ param[i] = 0;
for (int i = nbp - 1; i >= 0; i--)
param[i] = popVar();
@@ -1529,6 +1524,8 @@ int16 Op_Itoa() {
if (!nbp)
sprintf(txt, "%d", val);
else {
+ char format[30];
+ char nbf[20];
strcpy(format, "%");
sprintf(nbf, "%d", param[0]);
strcat(format, nbf);
@@ -1576,7 +1573,7 @@ int16 Op_FindObject() {
var_26[0] = 0;
if (ptr) {
- strcpy(var_26, ptr);
+ Common::strlcpy(var_26, ptr, sizeof(var_26));
}
overlayIdx = popVar();
@@ -1614,7 +1611,7 @@ int16 Op_GetNodeX() {
int result = getNode(nodeInfo, node);
- ASSERT(result == 0);
+ assert(result == 0);
return nodeInfo[0];
}
@@ -1626,7 +1623,7 @@ int16 Op_GetNodeY() {
int result = getNode(nodeInfo, node);
- ASSERT(result == 0);
+ assert(result == 0);
return nodeInfo[1];
}
@@ -1649,7 +1646,7 @@ int16 Op_SongExist() {
if (songName) {
char name[33];
- strcpy(name, songName);
+ Common::strlcpy(name, songName, sizeof(name));
strToUpper(name);
if (!strcmp(_vm->sound().musicName(), name))
@@ -1835,7 +1832,7 @@ int16 Op_ThemeReset() {
}
int16 Op_UserWait() {
- userWait = 1;
+ userWait = true;
if (currentScriptPtr->type == scriptType_PROC) {
changeScriptParamInList(currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber, &procHead, -1, 9999);
} else if (currentScriptPtr->type == scriptType_REL) {
diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp
index 39385459d9..9fd94d7ea6 100644
--- a/engines/cruise/gfxModule.cpp
+++ b/engines/cruise/gfxModule.cpp
@@ -121,12 +121,10 @@ void gfxModuleData_setPalColor(int idx, int r, int g, int b) {
}
void gfxModuleData_setPalEntries(const byte *ptr, int start, int num) {
- int R, G, B, i;
-
- for (i = start; i < start + num; i++) {
- R = *(ptr++);
- G = *(ptr++);
- B = *(ptr++);
+ for (int i = start; i < start + num; i++) {
+ int R = *(ptr++);
+ int G = *(ptr++);
+ int B = *(ptr++);
lpalette[i].R = R;
lpalette[i].G = G;
@@ -142,12 +140,11 @@ void gfxModuleData_setPal256(const byte *ptr) {
}
/*void gfxModuleData_setPal(uint8 *ptr) {
- int i;
int R;
int G;
int B;
- for (i = 0; i < 256; i++) {
+ for (int i = 0; i < 256; i++) {
#define convertRatio 36.571428571428571428571428571429
uint16 atariColor = *ptr;
//bigEndianShortToNative(&atariColor);
@@ -340,7 +337,6 @@ void resetBitmap(uint8 *dataPtr, int32 dataSize) {
*/
void switchBackground(const byte *newBg) {
const byte *bg = gfxModuleData.pPage00;
- int sliceXStart, sliceXEnd;
// If both the upper corners are different, presume it's a full screen change
if ((*newBg != *bg) && (*(newBg + 319) != *(bg + 319))) {
@@ -353,7 +349,8 @@ void switchBackground(const byte *newBg) {
*/
for (int yp = 0; yp < 200; ++yp) {
- sliceXStart = -1; sliceXEnd = -1;
+ int sliceXStart = -1;
+ int sliceXEnd = -1;
for (int xp = 0; xp < 320; ++xp, ++bg, ++newBg) {
if (*bg != *newBg) {
if (sliceXStart == -1) {
diff --git a/engines/cruise/linker.cpp b/engines/cruise/linker.cpp
index 817345d06e..9786de775f 100644
--- a/engines/cruise/linker.cpp
+++ b/engines/cruise/linker.cpp
@@ -35,23 +35,22 @@ exportEntryStruct *parseExport(int *out1, int *pExportedFuncionIdx, char *buffer
int numSymbGlob;
exportEntryStruct *currentExportEntry;
char *entity1Name;
- int i;
*out1 = 0;
*pExportedFuncionIdx = 0;
- strcpy(localBuffer, buffer);
+ Common::strlcpy(localBuffer, buffer, sizeof(localBuffer));
dotPtr = strchr(localBuffer, '.');
if (dotPtr) {
- strcpy(functionName, dotPtr + 1);
+ Common::strlcpy(functionName, dotPtr + 1, sizeof(functionName));
*dotPtr = 0;
strcpy(overlayName, localBuffer);
} else {
overlayName[0] = 0;
- strcpy(functionName, buffer);
+ Common::strlcpy(functionName, buffer, sizeof(functionName));
}
ptr2 = strchr((char *)functionName, ':');
@@ -85,11 +84,11 @@ exportEntryStruct *parseExport(int *out1, int *pExportedFuncionIdx, char *buffer
if (!entity1Name)
return (0);
- for (i = 0; i < numSymbGlob; i++) {
+ for (int i = 0; i < numSymbGlob; i++) {
char exportedName[256];
char *name = entity1Name + currentExportEntry->offsetToName;
- strcpy(exportedName, name);
+ Common::strlcpy(exportedName, name, sizeof(exportedName));
strToUpper(exportedName);
if (!strcmp(functionName, exportedName)) {
@@ -130,8 +129,6 @@ int updateScriptImport(int ovlIdx) {
// do it for the 2 first string types
do {
- int i = 0;
-
if (param == 0) {
var_32 = numData3;
} else {
@@ -139,16 +136,16 @@ int updateScriptImport(int ovlIdx) {
}
if (var_32) {
+ int i = 0;
do {
importScriptStruct *ptrImportData;
const char *ptrImportName;
uint8 *ptrData;
- if (param == 0) {
+ if (param == 0)
pScript = getOvlData3Entry(ovlIdx, i);
- } else {
+ else
pScript = scriptFunc1Sub2(ovlIdx, i);
- }
ptrImportData = (importScriptStruct *)(pScript->dataPtr + pScript->offsetToImportData); // import data
ptrImportName = (const char*)(pScript->dataPtr + pScript->offsetToImportName); // import name
@@ -165,7 +162,7 @@ int updateScriptImport(int ovlIdx) {
int out1;
int out2;
- strcpy(buffer, ptrImportName + ptrImportData->offsetToName);
+ Common::strlcpy(buffer, ptrImportName + ptrImportData->offsetToName, sizeof(buffer));
ptrDest2 = parseExport(&out1, &out2, buffer);
if (ptrDest2 && out2) {
@@ -221,16 +218,14 @@ int updateScriptImport(int ovlIdx) {
if (ovlData->arrayRelocGlob && ovlData->arrayNameRelocGlob && numRelocGlob) {
int numImport2 = numRelocGlob;
- int i;
-
- for (i = 0; i < numImport2; i++) {
+ for (int i = 0; i < numImport2; i++) {
int out1;
int foundExportIdx;
exportEntryStruct *pFoundExport;
int linkType;
int linkEntryIdx;
- strcpy(buffer, ovlData->arrayNameRelocGlob + ovlData->arrayRelocGlob[i].nameOffset);
+ Common::strlcpy(buffer, ovlData->arrayNameRelocGlob + ovlData->arrayRelocGlob[i].nameOffset, sizeof(buffer));
pFoundExport = parseExport(&out1, &foundExportIdx, buffer);
@@ -264,12 +259,9 @@ int updateScriptImport(int ovlIdx) {
// check that the newly loaded isn't used by the already loaded overlays
void updateAllScriptsImports() {
- int i;
-
- for (i = 0; i < 90; i++) {
- if (overlayTable[i].ovlData && overlayTable[i].alreadyLoaded) {
+ for (int i = 0; i < 90; i++) {
+ if (overlayTable[i].ovlData && overlayTable[i].alreadyLoaded)
updateScriptImport(i);
- }
}
}
diff --git a/engines/cruise/mainDraw.cpp b/engines/cruise/mainDraw.cpp
index 0863a2a84e..5777b846b4 100644
--- a/engines/cruise/mainDraw.cpp
+++ b/engines/cruise/mainDraw.cpp
@@ -120,7 +120,7 @@ void fadeIn() {
gfxModuleData_setPal256(workpal);
fadeFlag = 0;
- PCFadeFlag = 0;
+ PCFadeFlag = false;
}
void flipScreen() {
@@ -479,10 +479,7 @@ void buildSegment() {
// swap again ?
SWAP(X1, X2);
- int patchAdd = 2;
-
int dy = Y2 - Y1;
-
if (dy == 0) {
// hline
int16* ptr = (Y1 - ydep) * 2 + XMIN_XMAX + 1;
@@ -503,6 +500,8 @@ void buildSegment() {
ptr[1] = SI;
}
} else {
+ int patchAdd = 2;
+
if (dy < 0) {
dy = -dy;
patchAdd = -2;
@@ -721,7 +720,6 @@ void buildPolyModel(int positionX, int positionY, int scale, char *pMask, char *
int startX = 0; // first X in model
int startY = 0; // first Y in model
int x = 0; // current X
- int y = 0; // current Y
int offsetXinModel = 0; // offset of the X value in the model
int offsetYinModel = 0; // offset of the Y value in the model
unsigned char *dataPointer = (unsigned char *)dataPtr;
@@ -761,9 +759,8 @@ void buildPolyModel(int positionX, int positionY, int scale, char *pMask, char *
startY >>= 1;
}
- if (m_flipLeftRight) {
+ if (m_flipLeftRight)
startX = -startX;
- }
/*
* NOTE:
@@ -796,7 +793,7 @@ void buildPolyModel(int positionX, int positionY, int scale, char *pMask, char *
ptrPoly_1_Buf++;
offsetXinModel = x;
- y = *(dataPointer) - m_first_Y;
+ int y = *(dataPointer) - m_first_Y;
dataPointer++;
if (m_useSmallScale) {
y >>= 1;
@@ -881,7 +878,6 @@ bool findPoly(char* dataPtr, int positionX, int positionY, int scale, int mouseX
int startX = 0; // first X in model
int startY = 0; // first Y in model
int x = 0; // current X
- int y = 0; // current Y
int offsetXinModel = 0; // offset of the X value in the model
int offsetYinModel = 0; // offset of the Y value in the model
unsigned char *dataPointer = (unsigned char *)dataPtr;
@@ -955,11 +951,11 @@ bool findPoly(char* dataPtr, int positionX, int positionY, int scale, int mouseX
ptrPoly_1_Buf++;
offsetXinModel = x;
- y = *(dataPointer) - m_first_Y;
+ int y = *(dataPointer) - m_first_Y;
dataPointer++;
- if (m_useSmallScale) {
+ if (m_useSmallScale)
y >>= 1;
- }
+
ptrPoly_1_Buf[0] = -(offsetYinModel - y);
ptrPoly_1_Buf++;
offsetYinModel = y;
@@ -1150,10 +1146,6 @@ void drawMessage(const gfxEntryStruct *pGfxPtr, int globalX, int globalY, int wi
// this is used for font only
if (pGfxPtr) {
- uint8 *initialOuput;
- uint8 *output;
- int xp, yp;
- int x, y;
const uint8 *ptr = pGfxPtr->imagePtr;
int height = pGfxPtr->height;
@@ -1172,14 +1164,14 @@ void drawMessage(const gfxEntryStruct *pGfxPtr, int globalX, int globalY, int wi
gfxModuleData_addDirtyRect(Common::Rect(globalX, globalY, globalX + width, globalY + height));
- initialOuput = ouputPtr + (globalY * 320) + globalX;
+ uint8 *initialOuput = ouputPtr + (globalY * 320) + globalX;
- for (yp = 0; yp < height; yp++) {
- output = initialOuput + 320 * yp;
- y = globalY + yp;
+ for (int yp = 0; yp < height; yp++) {
+ uint8 *output = initialOuput + 320 * yp;
+ int y = globalY + yp;
- for (xp = 0; xp < pGfxPtr->width; xp++) {
- x = globalX + xp;
+ for (int xp = 0; xp < pGfxPtr->width; xp++) {
+ int x = globalX + xp;
uint8 color = *(ptr++);
if (color) {
@@ -1255,18 +1247,15 @@ void drawSprite(int width, int height, cellStruct *currentObjPtr, const uint8 *d
#ifdef _DEBUG
void drawCtp() {
- /* int i;
-
- if (ctp_walkboxTable) {
- for (i = 0; i < 15; i++) {
+ /* if (ctp_walkboxTable) {
+ for (int i = 0; i < 15; i++) {
uint16 *dataPtr = &ctp_walkboxTable[i * 40];
int type = walkboxColor[i]; // show different types in different colors
if (*dataPtr) {
- int j;
fillpoly((short *)dataPtr + 1, *dataPtr, type);
- for (j = 0; j < (*dataPtr - 1); j++) {
+ for (int j = 0; j < (*dataPtr - 1); j++) {
line(dataPtr[1 + j * 2],
dataPtr[1 + j * 2 + 1],
dataPtr[1 + (j + 1) * 2],
@@ -1388,7 +1377,7 @@ int getValueFromObjectQuerry(objectParamsQuery *params, int idx) {
return 0;
}
-void mainDraw(int16 param) {
+void mainDraw(bool waitFl) {
uint8 *bgPtr;
cellStruct *currentObjPtr;
int16 currentObjIdx;
@@ -1472,7 +1461,7 @@ void mainDraw(int16 param) {
}
// automatic animation process
- if (currentObjPtr->animStep && !param) {
+ if (currentObjPtr->animStep && !waitFl) {
if (currentObjPtr->animCounter <= 0) {
bool change = true;
diff --git a/engines/cruise/mainDraw.h b/engines/cruise/mainDraw.h
index bb71b9759b..1af403fca5 100644
--- a/engines/cruise/mainDraw.h
+++ b/engines/cruise/mainDraw.h
@@ -33,7 +33,7 @@ extern int m_color;
int upscaleValue(int value, int scale);
void pixel(int x, int y, char color);
-void mainDraw(int16 param);
+void mainDraw(bool waitFl);
void flipScreen();
void buildPolyModel(int X, int Y, int scale, char *ptr2, char *destBuffer, char *dataPtr);
void drawSprite(int width, int height, cellStruct *currentObjPtr, const uint8 *dataIn, int ys, int xs, uint8 *output, const uint8 *dataBuf);
diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp
index 8f162ee1ad..cf0b872646 100644
--- a/engines/cruise/menu.cpp
+++ b/engines/cruise/menu.cpp
@@ -39,7 +39,7 @@ menuStruct *createMenu(int X, int Y, const char *menuName) {
menuStruct *entry;
entry = (menuStruct *) MemAlloc(sizeof(menuStruct));
- ASSERT(entry);
+ assert(entry);
entry->x = X - 160 / 2;
entry->y = Y;
@@ -69,7 +69,7 @@ void addSelectableMenuEntry(int ovlIdx, int headerIdx, menuStruct *pMenu, int pa
if (!strcmp(var_6->string, menuText)) {
pNewElement = var_6;
pSubStruct = (menuElementSubStruct *)allocAndZero(sizeof(menuElementSubStruct));
- ASSERT(pSubStruct);
+ assert(pSubStruct);
pSubStruct->pNext = NULL;
pSubStruct->ovlIdx = ovlIdx;
@@ -99,9 +99,9 @@ void addSelectableMenuEntry(int ovlIdx, int headerIdx, menuStruct *pMenu, int pa
}
pNewElement = (menuElementStruct *)allocAndZero(sizeof(menuElementStruct));
- ASSERT(pNewElement);
+ assert(pNewElement);
pSubStruct = (menuElementSubStruct *)allocAndZero(sizeof(menuElementSubStruct));
- ASSERT(pSubStruct);
+ assert(pSubStruct);
pNewElement->string = menuText;
pNewElement->next = NULL;
@@ -160,7 +160,7 @@ int processMenu(menuStruct *pMenu) {
int si;
currentActiveMenu = 0;
- mainDraw(1);
+ mainDraw(true);
flipScreen();
di = 0;
@@ -179,7 +179,7 @@ int processMenu(menuStruct *pMenu) {
di = 1;
}
- mainDraw(1);
+ mainDraw(true);
flipScreen();
manageEvents();
@@ -190,7 +190,7 @@ int processMenu(menuStruct *pMenu) {
currentActiveMenu = -1;
- mainDraw(1);
+ mainDraw(true);
flipScreen();
if (mouseButton & 1) {
@@ -233,7 +233,6 @@ static void handleSaveLoad(bool saveFlag) {
}
int playerMenu(int menuX, int menuY) {
- int retourMenu;
//int restartGame = 0;
if (playerMenuEnabled && displayOn) {
@@ -267,7 +266,7 @@ int playerMenu(int menuX, int menuY) {
freeDisk();
menuTable[0] = createMenu(menuX, menuY, _vm->langString(ID_PLAYER_MENU));
- ASSERT(menuTable[0]);
+ assert(menuTable[0]);
//addSelectableMenuEntry(0, 3, menuTable[0], 1, -1, "Save game disk");
if (userEnabled) {
@@ -277,7 +276,7 @@ int playerMenu(int menuX, int menuY) {
addSelectableMenuEntry(0, 6, menuTable[0], 1, -1, _vm->langString(ID_RESTART));
addSelectableMenuEntry(0, 7, menuTable[0], 1, -1, _vm->langString(ID_QUIT));
- retourMenu = processMenu(menuTable[0]);
+ int retourMenu = processMenu(menuTable[0]);
freeMenu(menuTable[0]);
menuTable[0] = NULL;
diff --git a/engines/cruise/object.cpp b/engines/cruise/object.cpp
index 3e61ff4d7d..845fc34d1f 100644
--- a/engines/cruise/object.cpp
+++ b/engines/cruise/object.cpp
@@ -116,14 +116,10 @@ int16 getMultipleObjectParam(int16 overlayIdx, int16 objectIdx, objectParamsQuer
}
void setObjectPosition(int16 ovlIdx, int16 objIdx, int16 param3, int16 param4) {
- objDataStruct *ptr;
- objectParams *ptr2;
-
- ptr = getObjectDataFromOverlay(ovlIdx, objIdx);
-
- if (!ptr) {
+ objDataStruct *ptr = getObjectDataFromOverlay(ovlIdx, objIdx);
+ if (!ptr)
return;
- }
+
//overlayTable[param1].ovlData
switch (ptr->_class) {
@@ -138,7 +134,7 @@ void setObjectPosition(int16 ovlIdx, int16 objIdx, int16 param3, int16 param4) {
case UNIQUE:
return;
case VARIABLE: {
- ptr2 = &overlayTable[ovlIdx].ovlData->arrayObjVar[ptr->_varTableIdx];
+ objectParams *ptr2 = &overlayTable[ovlIdx].ovlData->arrayObjVar[ptr->_varTableIdx];
switch (param3) {
case 0: { // x
@@ -167,14 +163,14 @@ void setObjectPosition(int16 ovlIdx, int16 objIdx, int16 param3, int16 param4) {
break;
}
default: {
- ASSERT(0);
+ assert(0);
}
}
break;
}
default: {
- ASSERT(0);
+ assert(0);
}
}
}
diff --git a/engines/cruise/overlay.cpp b/engines/cruise/overlay.cpp
index 61df716742..f7df741892 100644
--- a/engines/cruise/overlay.cpp
+++ b/engines/cruise/overlay.cpp
@@ -32,9 +32,7 @@ overlayStruct overlayTable[90];
int numOfLoadedOverlay;
void initOverlayTable() {
- int i;
-
- for (i = 0; i < 90; i++) {
+ for (int i = 0; i < 90; i++) {
overlayTable[i].overlayName[0] = 0;
overlayTable[i].ovlData = NULL;
overlayTable[i].alreadyLoaded = 0;
@@ -53,7 +51,6 @@ void freeOverlayTable() {
int freeOverlay(int overlayIdx) {
ovlDataStruct *ovlDataPtr;
- int i;
if (overlayTable[overlayIdx].alreadyLoaded == 0)
return -4;
@@ -65,7 +62,6 @@ int freeOverlay(int overlayIdx) {
if (!ovlDataPtr)
return -4;
-
/*
if (overlayTable[overlayIdx].var1E) {
MemFree(overlayTable[overlayIdx].var1E);
@@ -84,19 +80,19 @@ int freeOverlay(int overlayIdx) {
removeScript(overlayIdx, -1, &relHead);
if (ovlDataPtr->stringTable) {
- for (i = 0; i < ovlDataPtr->numStrings; ++i)
+ for (int i = 0; i < ovlDataPtr->numStrings; ++i)
MemFree(ovlDataPtr->stringTable[i].string);
MemFree(ovlDataPtr->stringTable);
}
if (ovlDataPtr->arrayProc) {
ovlData3Struct *tempPtr = ovlDataPtr->arrayProc;
- for (i = 0; i < ovlDataPtr->numProc; ++i, ++tempPtr)
+ for (int i = 0; i < ovlDataPtr->numProc; ++i, ++tempPtr)
MemFree(tempPtr->dataPtr);
MemFree(ovlDataPtr->arrayProc);
}
if (ovlDataPtr->ptr1) {
ovlData3Struct *tempPtr = (ovlData3Struct *)ovlDataPtr->ptr1;
- for (i = 0; i < ovlDataPtr->numRel; ++i, ++tempPtr)
+ for (int i = 0; i < ovlDataPtr->numRel; ++i, ++tempPtr)
MemFree(tempPtr->dataPtr);
MemFree(ovlDataPtr->ptr1);
}
@@ -159,7 +155,7 @@ int loadOverlay(const char *scriptName) {
return (-2);
if (scriptName != overlayTable[scriptIdx].overlayName)
- strcpy(overlayTable[scriptIdx].overlayName, scriptName);
+ Common::strlcpy(overlayTable[scriptIdx].overlayName, scriptName, sizeof(overlayTable[scriptIdx].overlayName));
overlayTable[scriptIdx].alreadyLoaded = 1;
@@ -167,9 +163,8 @@ int loadOverlay(const char *scriptName) {
overlayTable[scriptIdx].ovlData->scriptNumber = scriptIdx;
- strcpy(fileName, scriptName);
-
- strcat(fileName, ".OVL");
+ Common::strlcpy(fileName, scriptName, sizeof(fileName));
+ Common::strlcat(fileName, ".OVL", sizeof(fileName));
debug(1, "Attempting to load overlay file %s...", fileName);
@@ -247,15 +242,13 @@ int loadOverlay(const char *scriptName) {
ovlData->scriptNumber = s.readUint16BE();
if (ovlData->numSymbGlob) { // export data
- int i;
ovlData->arraySymbGlob =
(exportEntryStruct *) mallocAndZero(ovlData->numSymbGlob * sizeof(exportEntryStruct));
- if (!ovlData->arraySymbGlob) {
+ if (!ovlData->arraySymbGlob)
return (-2);
- }
- for (i = 0; i < ovlData->numSymbGlob; i++) {
+ for (int i = 0; i < ovlData->numSymbGlob; i++) {
ovlData->arraySymbGlob[i].var0 = s.readUint16BE();
ovlData->arraySymbGlob[i].var2 = s.readUint16BE();
ovlData->arraySymbGlob[i].var4 = s.readUint16BE();
@@ -275,17 +268,14 @@ int loadOverlay(const char *scriptName) {
}
if (ovlData->numRelocGlob) { // import data
- int i;
-
ovlData->arrayRelocGlob =
(importDataStruct *) mallocAndZero(ovlData->numRelocGlob *
sizeof(importDataStruct));
- if (!ovlData->arrayRelocGlob) {
+ if (!ovlData->arrayRelocGlob)
return (-2);
- }
- for (i = 0; i < ovlData->numRelocGlob; i++) {
+ for (int i = 0; i < ovlData->numRelocGlob; i++) {
ovlData->arrayRelocGlob[i].var0 = s.readUint16BE();
ovlData->arrayRelocGlob[i].var1 = s.readUint16BE();
ovlData->arrayRelocGlob[i].linkType = s.readUint16BE();
@@ -305,16 +295,14 @@ int loadOverlay(const char *scriptName) {
}
if (ovlData->numMsgRelHeader) { // link data
- int i;
- ASSERT(sizeof(linkDataStruct) == 0x22);
+ assert(sizeof(linkDataStruct) == 0x22);
ovlData->arrayMsgRelHeader = (linkDataStruct *) mallocAndZero(ovlData->numMsgRelHeader * sizeof(linkDataStruct));
- if (!ovlData->arrayMsgRelHeader) {
+ if (!ovlData->arrayMsgRelHeader)
return (-2);
- }
- for (i = 0; i < ovlData->numMsgRelHeader; i++) {
+ for (int i = 0; i < ovlData->numMsgRelHeader; i++) {
ovlData->arrayMsgRelHeader[i].type = s.readUint16BE();
ovlData->arrayMsgRelHeader[i].id = s.readUint16BE();
ovlData->arrayMsgRelHeader[i].offsetVerbeName = s.readUint16BE();
@@ -342,16 +330,13 @@ int loadOverlay(const char *scriptName) {
if (ovlData->numProc) { // script
ovlData3Struct *tempPtr;
- int i;
- ovlData->arrayProc =
- (ovlData3Struct *) mallocAndZero(ovlData->numProc * sizeof(ovlData3Struct));
+ ovlData->arrayProc = (ovlData3Struct *) mallocAndZero(ovlData->numProc * sizeof(ovlData3Struct));
- if (!ovlData->arrayProc) {
+ if (!ovlData->arrayProc)
return (-2);
- }
- for (i = 0; i < ovlData->numProc; i++) {
+ for (int i = 0; i < ovlData->numProc; i++) {
s.skip(4);
ovlData->arrayProc[i].dataPtr = NULL;
ovlData->arrayProc[i].sizeOfData = s.readUint16BE();
@@ -370,7 +355,7 @@ int loadOverlay(const char *scriptName) {
tempPtr = ovlData->arrayProc;
- for (i = 0; i < ovlData->numProc; i++) {
+ for (int i = 0; i < ovlData->numProc; i++) {
tempPtr->dataPtr = (uint8 *) mallocAndZero(tempPtr->sizeOfData);
if (!tempPtr->dataPtr) {
@@ -395,16 +380,13 @@ int loadOverlay(const char *scriptName) {
if (ovlData->numRel) {
ovlData3Struct *tempPtr;
- int i;
- ovlData->ptr1 =
- (ovlData3Struct *) mallocAndZero(ovlData->numRel * sizeof(ovlData3Struct));
+ ovlData->ptr1 = (ovlData3Struct *) mallocAndZero(ovlData->numRel * sizeof(ovlData3Struct));
- if (!ovlData->ptr1) {
+ if (!ovlData->ptr1)
return (-2);
- }
- for (i = 0; i < ovlData->numRel; i++) {
+ for (int i = 0; i < ovlData->numRel; i++) {
s.skip(4);
ovlData->ptr1[i].dataPtr = NULL;
ovlData->ptr1[i].sizeOfData = s.readUint16BE();
@@ -423,12 +405,11 @@ int loadOverlay(const char *scriptName) {
tempPtr = (ovlData3Struct *) ovlData->ptr1;
- for (i = 0; i < ovlData->numRel; i++) {
+ for (int i = 0; i < ovlData->numRel; i++) {
tempPtr->dataPtr = (uint8 *) mallocAndZero(tempPtr->sizeOfData);
- if (!tempPtr->dataPtr) {
+ if (!tempPtr->dataPtr)
return (-2);
- }
s.read(tempPtr->dataPtr, tempPtr->sizeOfData);
@@ -463,16 +444,12 @@ int loadOverlay(const char *scriptName) {
}
if (ovlData->numObj) {
- int i;
- ovlData->arrayObject =
- (objDataStruct *) mallocAndZero(ovlData->numObj *
- sizeof(objDataStruct));
+ ovlData->arrayObject = (objDataStruct *) mallocAndZero(ovlData->numObj * sizeof(objDataStruct));
- if (!ovlData->arrayObject) {
+ if (!ovlData->arrayObject)
return (-2);
- }
- for (i = 0; i < ovlData->numObj; i++) {
+ for (int i = 0; i < ovlData->numObj; i++) {
ovlData->arrayObject[i]._type = s.readUint16BE();
ovlData->arrayObject[i]._class = (eClass) s.readUint16BE();
ovlData->arrayObject[i]._nameOffset = s.readUint16BE();
@@ -501,16 +478,12 @@ int loadOverlay(const char *scriptName) {
}
if (ovlData->size8) {
- int i;
- ovlData->arrayStates =
- (objectParams *) mallocAndZero(ovlData->size8 *
- sizeof(objectParams));
+ ovlData->arrayStates = (objectParams *) mallocAndZero(ovlData->size8 * sizeof(objectParams));
- if (!ovlData->arrayStates) {
+ if (!ovlData->arrayStates)
return (-2);
- }
- for (i = 0; i < ovlData->size8; i++) {
+ for (int i = 0; i < ovlData->size8; i++) {
ovlData->arrayStates[i].X = s.readUint16BE();
ovlData->arrayStates[i].Y = s.readUint16BE();
ovlData->arrayStates[i].Z = s.readUint16BE();
@@ -521,38 +494,28 @@ int loadOverlay(const char *scriptName) {
}
if (ovlData->numStrings) {
- int i;
-
- ovlData->stringTable =
- (stringEntryStruct *) mallocAndZero(ovlData->numStrings *
- sizeof(stringEntryStruct));
+ ovlData->stringTable = (stringEntryStruct *) mallocAndZero(ovlData->numStrings * sizeof(stringEntryStruct));
- for (i = 0; i < ovlData->numStrings; i++) {
+ for (int i = 0; i < ovlData->numStrings; i++)
ovlData->stringTable[i].idx = s.readUint16BE();
- }
}
if (ovlData->sizeOfData4) {
- ovlData->data4Ptr =
- (uint8 *) mallocAndZero(ovlData->sizeOfData4);
+ ovlData->data4Ptr = (uint8 *) mallocAndZero(ovlData->sizeOfData4);
- if (!ovlData->data4Ptr) {
+ if (!ovlData->data4Ptr)
return (-2);
- }
}
- if (ovlData->
- specialString1Length /*|| ovlData->specialString2Length */
+ if (ovlData->specialString1Length /*|| ovlData->specialString2Length */
|| ovlData->stringTable) {
- int i;
//int unpackedSize;
//int fileIdx;
//uint8 fileName[50];
//char* unpackedBuffer;
- strcpy(fileName, scriptName);
-
- strcat(fileName, ".FR");
+ Common::strlcpy(fileName, scriptName, sizeof(fileName));
+ Common::strlcat(fileName, ".FR", sizeof(fileName));
fileIdx = findFileInDisks(fileName);
@@ -625,7 +588,7 @@ int loadOverlay(const char *scriptName) {
s2.read(ovlData->arrayNameObj, ovlData->specialString2Length);
}
- for (i = 0; i < ovlData->numStrings; i++) {
+ for (int i = 0; i < ovlData->numStrings; i++) {
ovlData->stringTable[i].length = s2.readUint16BE();
if (ovlData->stringTable[i].length) {
@@ -650,8 +613,7 @@ int loadOverlay(const char *scriptName) {
}
#ifdef DUMP_SCRIPT
{
- int i;
- for (i = 0; i < ovlData->numProc; i++) {
+ for (int i = 0; i < ovlData->numProc; i++) {
dumpScript(scriptName, ovlData, i);
}
}
@@ -659,15 +621,14 @@ int loadOverlay(const char *scriptName) {
#ifdef DUMP_OBJECT
{
// TODO: Rewrite this to use Common::DumpFile
- int i;
FILE *fHandle;
char nameBundle[100];
sprintf(nameBundle, "%s-objs.txt", scriptName);
fHandle = fopen(nameBundle, "w+");
- ASSERT(fHandle);
+ assert(fHandle);
- for (i = 0; i < ovlData->numMsgRelHeader; i++) {
+ for (int i = 0; i < ovlData->numMsgRelHeader; i++) {
linkDataStruct *var_34;
var_34 = &ovlData->arrayMsgRelHeader[i];
@@ -700,9 +661,7 @@ int releaseOverlay(const char *name) {
}
int32 findOverlayByName2(const char *name) {
- int i;
-
- for (i = 1; i < numOfLoadedOverlay; i++) {
+ for (int i = 1; i < numOfLoadedOverlay; i++) {
if (!strcmp(overlayTable[i].overlayName, name))
return (i);
}
@@ -711,12 +670,9 @@ int32 findOverlayByName2(const char *name) {
}
int findOverlayByName(const char *overlayName) {
- int i;
-
- for (i = 1; i < numOfLoadedOverlay; i++) {
- if (!strcmp(overlayTable[i].overlayName, overlayName)) {
+ for (int i = 1; i < numOfLoadedOverlay; i++) {
+ if (!strcmp(overlayTable[i].overlayName, overlayName))
return (i);
- }
}
return (-4);
diff --git a/engines/cruise/perso.cpp b/engines/cruise/perso.cpp
index 3a599bca22..ff33eca14b 100644
--- a/engines/cruise/perso.cpp
+++ b/engines/cruise/perso.cpp
@@ -172,23 +172,20 @@ void processActorWalk(MovementEntry &resx_y, int16 *inc_droite, int16 *inc_droit
int16 *inc_chemin, point* cor_joueur,
int16 solution0[NUM_NODES + 3][2], int16 *inc_jo1, int16 *inc_jo2,
int16 *dir_perso, int16 *inc_jo0, int16 num) {
- int x1, x2, y1, y2;
- int i, u;
-
- u = 0;
+ int u = 0;
inc_jo = *inc_jo0;
- i = *inc_chemin;
+ int i = *inc_chemin;
if (!*inc_droite) {
- x1 = solution0[i][0];
- y1 = solution0[i][1];
+ int x1 = solution0[i][0];
+ int y1 = solution0[i][1];
i++;
if (solution0[i][0] != -1) {
do {
if (solution0[i][0] != -2) {
- x2 = solution0[i][0];
- y2 = solution0[i][1];
+ int x2 = solution0[i][0];
+ int y2 = solution0[i][1];
if ((x1 == x2) && (y1 == y2)) {
resx_y.x = -1;
resx_y.y = -1;
@@ -240,7 +237,7 @@ void processActorWalk(MovementEntry &resx_y, int16 *inc_droite, int16 *inc_droit
void affiche_chemin(int16 persoIdx, MovementEntry &data) {
persoStruct *pPerso = persoTable[persoIdx];
- ASSERT(pPerso);
+ assert(pPerso);
processActorWalk(data, &pPerso->inc_droite, &pPerso->inc_droite0,
&pPerso->inc_chemin, pPerso->coordinates, pPerso->solution,
diff --git a/engines/cruise/polys.cpp b/engines/cruise/polys.cpp
index bec03a06a6..f6d0691c69 100644
--- a/engines/cruise/polys.cpp
+++ b/engines/cruise/polys.cpp
@@ -183,11 +183,10 @@ void line(int x1, int y1, int x2, int y2, char c) {
static void add_intersect(int *intersect, int x, byte &num) {
if (num < MAXPTS) {
- int i;
- for (i = num; i > 0 && intersect[i - 1] > x; i--) {
+ int i = 0;
+ for (i = num; i > 0 && intersect[i - 1] > x; i--)
intersect[i] = intersect[i - 1];
- }
intersect[i] = x;
num++;
@@ -212,20 +211,15 @@ void fillpoly(int16 *point_data, int lineCount, ColorP color) {
}
// Reinit array counters
-
- int x1, y1, x2, y2;
- int y, i;
-
- for (i = 0; i < SCREENHEIGHT; i++) {
+ for (int i = 0; i < SCREENHEIGHT; i++) {
num_intersect[i] = 0;
}
// Find the top/bottom of the polygon.
-
int top = point_data[1];
int bottom = point_data[1];
- for (i = 1; i < lineCount; i++) {
+ for (int i = 1; i < lineCount; i++) {
if (point_data[2 * i + 1] < top)
top = point_data[2 * i + 1];
else if (point_data[2 * i + 1] > bottom)
@@ -238,14 +232,13 @@ void fillpoly(int16 *point_data, int lineCount, ColorP color) {
bottom = SCREENHEIGHT - 1;
// Calculate intersections for each scan line
+ for (int y = top; y <= bottom; y++) {
+ int x2 = point_data[2 * lineCount - 2];
+ int y2 = point_data[2 * lineCount - 1];
- for (y = top; y <= bottom; y++) {
- x2 = point_data[2 * lineCount - 2];
- y2 = point_data[2 * lineCount - 1];
-
- for (i = 0; i < lineCount; i++) {
- x1 = x2;
- y1 = y2;
+ for (int i = 0; i < lineCount; i++) {
+ int x1 = x2;
+ int y1 = y2;
x2 = point_data[2 * i];
y2 = point_data[2 * i + 1];
@@ -265,9 +258,8 @@ void fillpoly(int16 *point_data, int lineCount, ColorP color) {
}
// Drawing.
-
- for (y = top; y <= bottom; y++) {
- for (i = 0; i < num_intersect[y]; i += 2) {
+ for (int y = top; y <= bottom; y++) {
+ for (int i = 0; i < num_intersect[y]; i += 2) {
hline(intersect[y][i], intersect[y][i + 1], y, color);
}
}
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index a734db4b3b..a62648df08 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -284,7 +284,7 @@ static void syncOverlays2(Common::Serializer &s) {
if (ovlRestoreData[i]._sBssSize) {
ovlRestoreData[i]._pBss = (uint8 *) mallocAndZero(ovlRestoreData[i]._sBssSize);
- ASSERT(ovlRestoreData[i]._pBss);
+ assert(ovlRestoreData[i]._pBss);
s.syncBytes(ovlRestoreData[i]._pBss, ovlRestoreData[i]._sBssSize);
}
@@ -293,7 +293,7 @@ static void syncOverlays2(Common::Serializer &s) {
if (ovlRestoreData[i]._sNumObj) {
ovlRestoreData[i]._pObj = (objectParams *) mallocAndZero(ovlRestoreData[i]._sNumObj * sizeof(objectParams));
- ASSERT(ovlRestoreData[i]._pObj);
+ assert(ovlRestoreData[i]._pObj);
for (int j = 0; j < ovlRestoreData[i]._sNumObj; j++) {
s.syncAsSint16LE(ovlRestoreData[i]._pObj[j].X);
@@ -735,7 +735,7 @@ void initVars() {
resetBackgroundIncrustList(&backgroundIncrustHead);
vblLimit = 0;
- remdo = 0;
+ remdo = false;
songLoaded = 0;
songPlayed = 0;
songLoop = 1;
@@ -777,7 +777,7 @@ void initVars() {
buttonDown = 0;
var41 = 0;
playerMenuEnabled = 0;
- PCFadeFlag = 0;
+ PCFadeFlag = false;
}
Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName) {
@@ -881,17 +881,15 @@ Common::Error loadSavegameData(int saveGameIdx) {
for (int i = 0; i < NUM_FILE_ENTRIES; i++) {
if (filesDatabase[i].subData.ptr) {
- int j;
- int k;
-
- for (j = i + 1; j < NUM_FILE_ENTRIES &&
+ int j = i + 1;
+ for (; j < NUM_FILE_ENTRIES &&
filesDatabase[j].subData.ptr &&
!strcmp(filesDatabase[i].subData.name, filesDatabase[j].subData.name) &&
(filesDatabase[j].subData.index == (j - i));
j++)
;
- for (k = i; k < j; k++) {
+ for (int k = i; k < j; k++) {
filesDatabase[k].subData.ptr = NULL;
filesDatabase[k].subData.ptrMask = NULL;
}
@@ -917,17 +915,14 @@ Common::Error loadSavegameData(int saveGameIdx) {
while (currentcellHead) {
if (currentcellHead->type == 5) {
+ assert(0);
+#if 0
uint8 *ptr = mainProc14(currentcellHead->overlay, currentcellHead->idx);
-
- ASSERT(0);
-
- if (ptr) {
- ASSERT(0);
- //*(int16 *)(currentcellHead->datas+0x2E) = getSprite(ptr,*(int16 *)(currentcellHead->datas+0xE));
- } else {
- ASSERT(0);
- //*(int16 *)(currentcellHead->datas+0x2E) = 0;
- }
+ if (ptr)
+ *(int16 *)(currentcellHead->datas+0x2E) = getSprite(ptr,*(int16 *)(currentcellHead->datas+0xE));
+ else
+ *(int16 *)(currentcellHead->datas+0x2E) = 0;
+#endif
}
currentcellHead = currentcellHead->next;
@@ -952,7 +947,7 @@ Common::Error loadSavegameData(int saveGameIdx) {
// to finish
changeCursor(CURSOR_NORMAL);
- mainDraw(1);
+ mainDraw(true);
flipScreen();
return Common::kNoError;
diff --git a/engines/cruise/script.cpp b/engines/cruise/script.cpp
index 65da84b9ce..1f308714f7 100644
--- a/engines/cruise/script.cpp
+++ b/engines/cruise/script.cpp
@@ -51,12 +51,13 @@ int32 opcodeType0() {
int index = 0;
switch (currentScriptOpcodeType) {
- case 0: {
+ case 0:
pushVar(getShortFromScript());
return (0);
- }
+
case 5:
index = saveOpcodeVar;
+ // No break on purpose
case 1: {
uint8 *address = 0;
int type = getByteFromScript();
@@ -131,12 +132,12 @@ int32 opcodeType1() {
int offset = 0;
switch (currentScriptOpcodeType) {
- case 0: {
+ case 0:
return (0); // strange, but happens also in original interpreter
- }
- case 5: {
+
+ case 5:
offset = saveOpcodeVar;
- }
+ //no break on purpose
case 1: {
int var_A = 0;
@@ -169,7 +170,7 @@ int32 opcodeType1() {
if (var_6 == 5) {
ptr = overlayTable[byte2].ovlData->data4Ptr + var_C;
} else {
- ASSERT(0);
+ assert(0);
}
} else {
ptr = scriptDataPtrTable[var_6] + var_C;
@@ -226,6 +227,7 @@ int32 opcodeType2() {
switch (currentScriptOpcodeType) {
case 5:
index = saveOpcodeVar;
+ // No break on purpose
case 1: {
uint8* adresse = NULL;
int type = getByteFromScript();
@@ -247,7 +249,7 @@ int32 opcodeType2() {
if (!overlayTable[overlay].ovlData) {
return (-4);
}
- ASSERT(0);
+ assert(0);
}
adresse += offset;
@@ -261,6 +263,7 @@ int32 opcodeType2() {
}
}
+ break;
}
return 0;
@@ -281,39 +284,37 @@ int32 opcodeType4() { // test
int var2 = popVar();
switch (currentScriptOpcodeType) {
- case 0: {
+ case 0:
if (var2 != var1)
boolVar = 1;
break;
- }
- case 1: {
+
+ case 1:
if (var2 == var1)
boolVar = 1;
break;
- }
- case 2: {
+
+ case 2:
if (var2 < var1)
boolVar = 1;
break;
- }
- case 3: {
+
+ case 3:
if (var2 <= var1)
boolVar = 1;
break;
- }
- case 4: {
+
+ case 4:
if (var2 > var1)
boolVar = 1;
break;
- }
- case 5: {
+
+ case 5:
if (var2 >= var1)
boolVar = 1;
break;
}
- }
-
pushVar(boolVar);
return (0);
@@ -327,13 +328,11 @@ int32 opcodeType6() {
if (!pop)
si = 1;
- if (pop < 0) {
+ if (pop < 0)
si |= 4;
- }
- if (pop > 0) {
+ if (pop > 0)
si |= 2;
- }
currentScriptPtr->ccr = si;
@@ -357,50 +356,49 @@ int32 opcodeType5() {
int bitMask = currentScriptPtr->ccr;
switch (currentScriptOpcodeType) {
- case 0: {
- if (!(bitMask & 1)) {
+ case 0:
+ if (!(bitMask & 1))
currentScriptPtr->scriptOffset = newSi;
- }
+
break;
- }
- case 1: {
- if (bitMask & 1) {
+
+ case 1:
+ if (bitMask & 1)
currentScriptPtr->scriptOffset = newSi;
- }
+
break;
- }
- case 2: {
- if (bitMask & 2) {
+
+ case 2:
+ if (bitMask & 2)
currentScriptPtr->scriptOffset = newSi;
- }
+
break;
- }
- case 3: {
- if (bitMask & 3) {
+
+ case 3:
+ if (bitMask & 3)
currentScriptPtr->scriptOffset = newSi;
- }
+
break;
- }
- case 4: {
- if (bitMask & 4) {
+
+ case 4:
+ if (bitMask & 4)
currentScriptPtr->scriptOffset = newSi;
- }
+
break;
- }
- case 5: {
- if (bitMask & 5) {
+
+ case 5:
+ if (bitMask & 5)
currentScriptPtr->scriptOffset = newSi;
- }
+
break;
- }
- case 6: {
+
+ case 6:
break; // never
- }
- case 7: {
+
+ case 7:
currentScriptPtr->scriptOffset = newSi; //always
break;
}
- }
return (0);
}
@@ -410,35 +408,39 @@ int32 opcodeType3() { // math
int pop2 = popVar();
switch (currentScriptOpcodeType) {
- case 0: {
+ case 0:
pushVar(pop1 + pop2);
return (0);
- }
- case 1: {
+
+ case 1:
+ if (pop2 == 0)
+ error("opcodeType3 - Invalid value for pop2");
pushVar(pop1 / pop2);
return (0);
- }
- case 2: {
+
+ case 2:
pushVar(pop1 - pop2);
return (0);
- }
- case 3: {
+
+ case 3:
pushVar(pop1 * pop2);
return (0);
- }
- case 4: {
+
+ case 4:
+ if (pop2 == 0)
+ error("opcodeType3 - Invalid value for pop2");
pushVar(pop1 % pop2);
return (0);
- }
+
case 7:
- case 5: {
+ case 5:
pushVar(pop2 | pop1);
return (0);
- }
- case 6: {
+
+ case 6:
pushVar(pop2 & pop1);
return (0);
- }
+
}
return 0;
@@ -451,11 +453,8 @@ int32 opcodeType9() { // stop script
}
void setupFuncArray() {
- int i;
-
- for (i = 0; i < 64; i++) {
+ for (int i = 0; i < 64; i++)
opcodeTypeTable[i] = NULL;
- }
opcodeTypeTable[1] = opcodeType0;
opcodeTypeTable[2] = opcodeType1;
@@ -472,19 +471,13 @@ void setupFuncArray() {
}
int removeScript(int overlay, int idx, scriptInstanceStruct *headPtr) {
- scriptInstanceStruct *scriptPtr;
-
- scriptPtr = headPtr->nextScriptPtr;
+ scriptInstanceStruct *scriptPtr = headPtr->nextScriptPtr;
- if (scriptPtr) {
- do {
- if (scriptPtr->overlayNumber == overlay
- && (scriptPtr->scriptNumber == idx || idx == -1)) {
- scriptPtr->scriptNumber = -1;
- }
+ while (scriptPtr) {
+ if (scriptPtr->overlayNumber == overlay && (scriptPtr->scriptNumber == idx || idx == -1))
+ scriptPtr->scriptNumber = -1;
- scriptPtr = scriptPtr->nextScriptPtr;
- } while (scriptPtr);
+ scriptPtr = scriptPtr->nextScriptPtr;
}
return (0);
@@ -493,77 +486,61 @@ int removeScript(int overlay, int idx, scriptInstanceStruct *headPtr) {
uint8 *attacheNewScriptToTail(scriptInstanceStruct *scriptHandlePtr, int16 overlayNumber, int16 param, int16 arg0, int16 arg1, int16 arg2, scriptTypeEnum scriptType) {
int useArg3Neg = 0;
ovlData3Struct *data3Ptr;
- scriptInstanceStruct *tempPtr;
int var_C;
scriptInstanceStruct *oldTail;
- //debug("Starting script %d of overlay %s", param,overlayTable[overlayNumber].overlayName);
-
if (scriptType < 0) {
useArg3Neg = 1;
- scriptType = (scriptTypeEnum) - scriptType;
+ scriptType = (scriptTypeEnum) -scriptType;
}
- if (scriptType == 20) {
+ if (scriptType == 20)
data3Ptr = getOvlData3Entry(overlayNumber, param);
- } else {
- if (scriptType == 30) {
- data3Ptr = scriptFunc1Sub2(overlayNumber, param);
- } else {
- return (NULL);
- }
- }
+ else if (scriptType == 30)
+ data3Ptr = scriptFunc1Sub2(overlayNumber, param);
+ else
+ return (NULL);
- if (!data3Ptr) {
+ if (!data3Ptr)
return (NULL);
- }
- if (!data3Ptr->dataPtr) {
+ if (!data3Ptr->dataPtr)
return (NULL);
- }
var_C = data3Ptr->sysKey;
-
oldTail = scriptHandlePtr;
- while (oldTail->nextScriptPtr) { // go to the end of the list
+ while (oldTail->nextScriptPtr) // go to the end of the list
oldTail = oldTail->nextScriptPtr;
- }
- tempPtr =
- (scriptInstanceStruct *)
- mallocAndZero(sizeof(scriptInstanceStruct));
+ scriptInstanceStruct *tempPtr = (scriptInstanceStruct *)mallocAndZero(sizeof(scriptInstanceStruct));
if (!tempPtr)
return (NULL);
tempPtr->data = NULL;
- if (var_C) {
+ if (var_C)
tempPtr->data = (uint8 *) mallocAndZero(var_C);
- }
tempPtr->dataSize = var_C;
tempPtr->nextScriptPtr = NULL;
tempPtr->scriptOffset = 0;
-
tempPtr->scriptNumber = param;
tempPtr->overlayNumber = overlayNumber;
- if (scriptType == 20) { // Obj or not ?
+ if (scriptType == 20) // Obj or not ?
tempPtr->sysKey = useArg3Neg;
- } else {
+ else
tempPtr->sysKey = 1;
- }
tempPtr->freeze = 0;
tempPtr->type = scriptType;
tempPtr->var18 = arg2;
tempPtr->var16 = arg1;
tempPtr->var1A = arg0;
- tempPtr->nextScriptPtr = oldTail->nextScriptPtr; // should always be NULL as it's the tail
-
- oldTail->nextScriptPtr = tempPtr; // attache the new node to the list
+ tempPtr->nextScriptPtr = oldTail->nextScriptPtr; // should always be NULL as it's the tail
+ oldTail->nextScriptPtr = tempPtr; // attach the new node to the list
return (tempPtr->data);
}
@@ -576,27 +553,18 @@ int executeScripts(scriptInstanceStruct *ptr) {
numScript2 = ptr->scriptNumber;
- if (ptr->type == 20) {
+ if (ptr->type == 20)
ptr2 = getOvlData3Entry(ptr->overlayNumber, numScript2);
+ else if (ptr->type == 30)
+ ptr2 = scriptFunc1Sub2(ptr->overlayNumber, numScript2);
+ else
+ return (-6);
- if (!ptr2) {
- return (-4);
- }
- } else {
- if (ptr->type == 30) {
- ptr2 = scriptFunc1Sub2(ptr->overlayNumber, numScript2);
-
- if (!ptr2) {
- return (-4);
- }
- } else {
- return (-6);
- }
- }
+ if (!ptr2)
+ return (-4);
- if (!overlayTable[ptr->overlayNumber].alreadyLoaded) {
+ if (!overlayTable[ptr->overlayNumber].alreadyLoaded)
return (-7);
- }
ovlData = overlayTable[ptr->overlayNumber].ovlData;
@@ -604,14 +572,11 @@ int executeScripts(scriptInstanceStruct *ptr) {
return (-4);
currentData3DataPtr = ptr2->dataPtr;
-
scriptDataPtrTable[1] = (uint8 *) ptr->data;
scriptDataPtrTable[2] = getDataFromData3(ptr2, 1);
scriptDataPtrTable[5] = ovlData->data4Ptr; // free strings
scriptDataPtrTable[6] = ovlData->ptr8;
-
currentScriptPtr = ptr;
-
positionInStack = 0;
do {
@@ -645,21 +610,15 @@ int executeScripts(scriptInstanceStruct *ptr) {
void manageScripts(scriptInstanceStruct *scriptHandle) {
scriptInstanceStruct *ptr = scriptHandle;
- if (ptr) {
- do {
- if (!overlayTable[ptr->overlayNumber].executeScripts) {
- if ((ptr->scriptNumber != -1) && (ptr->freeze == 0) && (ptr->sysKey != 0)) {
- executeScripts(ptr);
- }
-
- if (ptr->sysKey == 0) {
- ptr->sysKey = 1;
- }
- }
-
- ptr = ptr->nextScriptPtr;
+ while (ptr) {
+ if (!overlayTable[ptr->overlayNumber].executeScripts) {
+ if ((ptr->scriptNumber != -1) && (ptr->freeze == 0) && (ptr->sysKey != 0))
+ executeScripts(ptr);
- } while (ptr);
+ if (ptr->sysKey == 0)
+ ptr->sysKey = 1;
+ }
+ ptr = ptr->nextScriptPtr;
}
}
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 86146e3189..0b0fab8c4a 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -342,9 +342,7 @@ void AdLibSoundDriver::adjustVolume(int channel, int volume) {
volume = 0;
}
volume += volume / 4;
- if (volume > 127) {
- volume = 127;
- }
+ // The higher possible value for volume is 100
int volAdjust = (channel == 4) ? _sfxVolume : _musicVolume;
volume = (volume * volAdjust) / 128;
@@ -379,13 +377,12 @@ void AdLibSoundDriver::stopChannel(int channel) {
}
void AdLibSoundDriver::stopAll() {
- int i;
- for (i = 0; i < 18; ++i) {
+ for (int i = 0; i < 18; ++i)
OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 63);
- }
- for (i = 0; i < 9; ++i) {
+
+ for (int i = 0; i < 9; ++i)
OPLWriteReg(_opl, 0xB0 | i, 0);
- }
+
OPLWriteReg(_opl, 0xBD, 0);
}
@@ -610,6 +607,13 @@ PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver)
_sfxData = NULL;
_fadeOutCounter = 0;
_driver->setUpdateCallback(updateCallback, this);
+
+ _currentPos = 0;
+ _currentOrder = 0;
+ _numOrders = 0;
+ _eventsDelay = 0;
+ _looping = false;
+ _updateTicksCounter = 0;
}
PCSoundFxPlayer::~PCSoundFxPlayer() {
@@ -630,7 +634,7 @@ bool PCSoundFxPlayer::load(const char *song) {
stop();
}
- strcpy(_musicName, song);
+ Common::strlcpy(_musicName, song, sizeof(_musicName));
_songPlayed = false;
_looping = false;
_sfxData = readBundleSoundFile(song);
@@ -652,7 +656,7 @@ bool PCSoundFxPlayer::load(const char *song) {
if (dot) {
*dot = '\0';
}
- strcat(instrument, _driver->getInstrumentExtension());
+ Common::strlcat(instrument, _driver->getInstrumentExtension(), sizeof(instrument));
_instrumentsData[i] = readBundleSoundFile(instrument);
if (!_instrumentsData[i]) {
warning("Unable to load soundfx instrument '%s'", instrument);
@@ -795,6 +799,7 @@ PCSound::PCSound(Audio::Mixer *mixer, CruiseEngine *vm) {
_mixer = mixer;
_soundDriver = new AdLibSoundDriverADL(_mixer);
_player = new PCSoundFxPlayer(_soundDriver);
+ _genVolume = 0;
}
PCSound::~PCSound() {
diff --git a/engines/cruise/stack.cpp b/engines/cruise/stack.cpp
index e4ecf72133..52a7a84814 100644
--- a/engines/cruise/stack.cpp
+++ b/engines/cruise/stack.cpp
@@ -44,7 +44,7 @@ int16 popVar() {
positionInStack--;
- ASSERT(scriptStack[positionInStack].type == STACK_SHORT);
+ assert(scriptStack[positionInStack].type == STACK_SHORT);
return (scriptStack[positionInStack].data.shortVar);
}
@@ -66,7 +66,7 @@ void *popPtr() {
positionInStack--;
- ASSERT(scriptStack[positionInStack].type == STACK_PTR);
+ assert(scriptStack[positionInStack].type == STACK_PTR);
return (scriptStack[positionInStack].data.ptrVar);
}
diff --git a/engines/cruise/various.cpp b/engines/cruise/various.cpp
index a7d701f9a1..df09ac92c8 100644
--- a/engines/cruise/various.cpp
+++ b/engines/cruise/various.cpp
@@ -24,8 +24,8 @@
namespace Cruise {
-uint16 remdo = 0;
-uint16 PCFadeFlag;
+bool remdo = false;
+bool PCFadeFlag;
char *getText(int textIndex, int overlayIndex) {
if (!overlayTable[overlayIndex].ovlData) {
diff --git a/engines/cruise/various.h b/engines/cruise/various.h
index c2ff1e22bb..94fc29173a 100644
--- a/engines/cruise/various.h
+++ b/engines/cruise/various.h
@@ -27,8 +27,8 @@
namespace Cruise {
-extern uint16 remdo;
-extern uint16 PCFadeFlag;
+extern bool remdo;
+extern bool PCFadeFlag;
int16 objInit(int ovlIdx, int param1, int param2);
char *getText(int textIndex, int overlayIndex);
diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp
index 9a59c8a714..e9b68968ef 100644
--- a/engines/cruise/vars.cpp
+++ b/engines/cruise/vars.cpp
@@ -53,9 +53,7 @@ char nextOverlay[38];
int16 currentActiveMenu;
int16 autoMsg;
menuElementSubStruct* linkedRelation;
-int16 main21;
-int16 main22;
-int16 userWait;
+bool userWait;
int16 autoTrack;
int16 currentDiskNumber = 1;
diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h
index fe3f7d6303..e7c687d5fb 100644
--- a/engines/cruise/vars.h
+++ b/engines/cruise/vars.h
@@ -156,9 +156,7 @@ extern char nextOverlay[38];
extern int16 currentActiveMenu;
extern int16 autoMsg;
extern menuElementSubStruct* linkedRelation;
-extern int16 main21;
-extern int16 main22;
-extern int16 userWait;
+extern bool userWait;
extern int16 autoTrack;
extern int16 currentDiskNumber;
diff --git a/engines/cruise/volume.cpp b/engines/cruise/volume.cpp
index 5b125a5142..99d86e48bb 100644
--- a/engines/cruise/volume.cpp
+++ b/engines/cruise/volume.cpp
@@ -83,14 +83,12 @@ int closeBase() {
int getVolumeDataEntry(volumeDataStruct *entry) {
char buffer[256];
- int i;
volumeNumEntry = 0;
volumeNumberOfEntry = 0;
- if (_vm->_currentVolumeFile.isOpen()) {
+ if (_vm->_currentVolumeFile.isOpen())
freeDisk();
- }
askDisk(-1);
@@ -98,9 +96,8 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
_vm->_currentVolumeFile.open(buffer);
- if (!_vm->_currentVolumeFile.isOpen()) {
+ if (!_vm->_currentVolumeFile.isOpen())
return (-14);
- }
changeCursor(CURSOR_DISK);
@@ -113,7 +110,7 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
volumePtrToFileDescriptor = (fileEntry *) mallocAndZero(sizeof(fileEntry) * volumeNumEntry);
- for (i = 0; i < volumeNumEntry; i++) {
+ for (int i = 0; i < volumeNumEntry; i++) {
volumePtrToFileDescriptor[i].name[0] = 0;
volumePtrToFileDescriptor[i].offset = 0;
volumePtrToFileDescriptor[i].size = 0;
@@ -121,7 +118,7 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
volumePtrToFileDescriptor[i].unk3 = 0;
}
- for (i = 0; i < volumeNumEntry; i++) {
+ for (int i = 0; i < volumeNumEntry; i++) {
_vm->_currentVolumeFile.read(&volumePtrToFileDescriptor[i].name, 14);
volumePtrToFileDescriptor[i].offset = _vm->_currentVolumeFile.readSint32BE();
volumePtrToFileDescriptor[i].size = _vm->_currentVolumeFile.readSint32BE();
@@ -138,14 +135,12 @@ int getVolumeDataEntry(volumeDataStruct *entry) {
int searchFileInVolCnf(const char *fileName, int32 diskNumber) {
int foundDisk = -1;
- int i;
- for (i = 0; i < numOfDisks; i++) {
+ for (int i = 0; i < numOfDisks; i++) {
if (volumeData[i].diskNumber == diskNumber) {
- int j;
int numOfEntry = volumeData[i].size / 13;
- for (j = 0; j < numOfEntry; j++) {
+ for (int j = 0; j < numOfEntry; j++) {
if (!strcmp(volumeData[i].ptr[j].name, fileName)) {
return (i);
}
@@ -158,13 +153,11 @@ int searchFileInVolCnf(const char *fileName, int32 diskNumber) {
int32 findFileInDisksSub1(const char *fileName) {
int foundDisk = -1;
- int i;
- for (i = 0; i < numOfDisks; i++) {
- int j;
+ for (int i = 0; i < numOfDisks; i++) {
int numOfEntry = volumeData[i].size / 13;
- for (j = 0; j < numOfEntry; j++) {
+ for (int j = 0; j < numOfEntry; j++) {
if (!strcmp(volumeData[i].ptr[j].name, fileName)) {
return (i);
}
@@ -189,19 +182,15 @@ void freeDisk() {
}
int16 findFileInList(char *fileName) {
- int i;
-
- if (!_vm->_currentVolumeFile.isOpen()) {
+ if (!_vm->_currentVolumeFile.isOpen())
return (-1);
- }
strToUpper(fileName);
- if (volumeNumEntry <= 0) {
+ if (volumeNumEntry <= 0)
return (-1);
- }
- for (i = 0; i < volumeNumEntry; i++) {
+ for (int i = 0; i < volumeNumEntry; i++) {
if (!strcmp(volumePtrToFileDescriptor[i].name, fileName)) {
return (i);
}
@@ -213,24 +202,25 @@ int16 findFileInList(char *fileName) {
void askDisk(int16 discNumber) {
char fileName[256];
char string[256];
- char messageDrawn = 0;
if (discNumber != -1) {
currentDiskNumber = discNumber;
}
- // skip drive selection stuff
sprintf(fileName, "VOL.%d", currentDiskNumber);
-
sprintf(string, "INSERER LE DISQUE %d EN ", currentDiskNumber);
- //while (Common::File::exists((const char*)fileName))
- {
+#if 0 // skip drive selection stuff
+ bool messageDrawn = false;
+ while (Common::File::exists((const char*)fileName)) {
if (!messageDrawn) {
drawMsgString(string);
- messageDrawn = 1;
+ messageDrawn = true;
}
}
+#else
+ drawMsgString(string);
+#endif
changeCursor(currentCursor);
}
@@ -240,7 +230,7 @@ int16 findFileInDisks(const char *name) {
int disk;
int fileIdx;
- strcpy(fileName, name);
+ Common::strlcpy(fileName, name, sizeof(fileName));
strToUpper(fileName);
if (!volumeDataLoaded) {
@@ -324,13 +314,12 @@ int closeCnf() {
}
int16 readVolCnf() {
- int i;
Common::File fileHandle;
//short int sizeHEntry;
volumeDataLoaded = 0;
- for (i = 0; i < 20; i++) {
+ for (int i = 0; i < 20; i++) {
volumeData[i].ident[0] = 0;
volumeData[i].ptr = NULL;
volumeData[i].diskNumber = i + 1;
@@ -339,14 +328,13 @@ int16 readVolCnf() {
fileHandle.open("VOL.CNF");
- if (!fileHandle.isOpen()) {
+ if (!fileHandle.isOpen())
return (0);
- }
numOfDisks = fileHandle.readSint16BE();
/*sizeHEntry =*/ fileHandle.readSint16BE(); // size of one header entry - 20 bytes
- for (i = 0; i < numOfDisks; i++) {
+ for (int i = 0; i < numOfDisks; i++) {
// fread(&volumeData[i],20,1,fileHandle);
fileHandle.read(&volumeData[i].ident, 10);
fileHandle.read(&volumeData[i].ptr, 4);
@@ -356,7 +344,7 @@ int16 readVolCnf() {
debug(1, "Disk number: %d", volumeData[i].diskNumber);
}
- for (i = 0; i < numOfDisks; i++) {
+ for (int i = 0; i < numOfDisks; i++) {
dataFileName *ptr;
volumeData[i].size = fileHandle.readSint32BE();
@@ -381,7 +369,6 @@ int16 readVolCnf() {
#ifdef dumpResources
for (i = 0; i < numOfDisks; i++) {
- int j;
char nameBuffer[256];
fileEntry *buffer;
@@ -397,7 +384,7 @@ int16 readVolCnf() {
buffer = (fileEntry *) mallocAndZero(numEntry * sizeEntry);
- for (j = 0; j < numEntry; j++) {
+ for (int j = 0; j < numEntry; j++) {
fileHandle.seek(4 + j*0x1E);
fileHandle.read(buffer[j].name, 14);
buffer[j].offset = fileHandle.readSint32BE();
diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index 65840ae174..8498e50b8d 100644
--- a/engines/dialogs.cpp
+++ b/engines/dialogs.cpp
@@ -217,6 +217,11 @@ void MainMenuDialog::reflowLayout() {
void MainMenuDialog::save() {
int slot = _saveDialog->runModalWithCurrentTarget();
+ #if defined(__PLAYSTATION2__) && defined(DYNAMIC_MODULES)
+ char pokeme[32];
+ snprintf(pokeme,32,"hack");
+ #endif
+
if (slot >= 0) {
Common::String result(_saveDialog->getResultString());
if (result.empty()) {
diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp
index e5ff1f079a..4fbf2d31ea 100644
--- a/engines/draci/game.cpp
+++ b/engines/draci/game.cpp
@@ -50,43 +50,46 @@ enum {
};
Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
- uint i;
-
_dialogueLinesNum = 0;
_blockNum = 0;
- for (i = 0; i < kDialogueLines; i++)
- _dialogueAnims[0] = 0;
+ for (uint i = 0; i < kDialogueLines; i++)
+ _dialogueAnims[0] = nullptr;
_loopStatus = kStatusOrdinary;
_loopSubstatus = kOuterLoop;
- _shouldQuit = 0;
- _shouldExitLoop = 0;
- _isReloaded = 0;
_speechTick = 0;
_speechDuration = 0;
- _objUnderCursor = 0;
- _animUnderCursor = 0;
_markedAnimationIndex = 0;
_scheduledPalette = 0;
_fadePhases = 0;
_fadePhase = 0;
_fadeTick = 0;
_mouseChangeTick = 0;
- _enableQuickHero = 0;
- _wantQuickHero = 0;
- _enableSpeedText = 0;
- _titleAnim = 0;
- _inventoryAnim = 0;
- _walkingMapOverlay = 0;
- _walkingShortestPathOverlay = 0;
- _walkingObliquePathOverlay = 0;
- _currentItem = 0;
- _itemUnderCursor = 0;
_previousItemPosition = 0;
- for (i = 0; i < kInventorySlots; i++)
- _inventory[i] = 0;
+ _shouldQuit = false;
+ _shouldExitLoop = false;
+ _isReloaded = false;
+ _isPositionLoaded = false;
+ _isFadeOut = true;
+ _enableQuickHero = false;
+ _wantQuickHero = false;
+ _enableSpeedText = false;
+ _isPositionLoaded = false;
+
+ _objUnderCursor = nullptr;
+ _animUnderCursor = nullptr;
+ _titleAnim = nullptr;
+ _inventoryAnim = nullptr;
+ _walkingMapOverlay = nullptr;
+ _walkingShortestPathOverlay = nullptr;
+ _walkingObliquePathOverlay = nullptr;
+ _currentItem = nullptr;
+ _itemUnderCursor = nullptr;
+
+ for (int i = 0; i < kInventorySlots; i++)
+ _inventory[i] = nullptr;
_newRoom = 0;
_newGate = 0;
@@ -94,10 +97,10 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
_pushedNewRoom = 0;
_pushedNewGate = 0;
_currentDialogue = 0;
- _dialogueArchive = 0;
- _dialogueBlocks = 0;
- _dialogueBegin = 0;
- _dialogueExit = 0;
+ _dialogueArchive = nullptr;
+ _dialogueBlocks = nullptr;
+ _dialogueBegin = false;
+ _dialogueExit = false;
_currentBlock = 0;
_lastBlock = 0;
@@ -112,7 +115,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
uint numPersons = file->_length / personSize;
_persons = new Person[numPersons];
- for (i = 0; i < numPersons; ++i) {
+ for (uint i = 0; i < numPersons; ++i) {
_persons[i]._x = personData.readUint16LE();
_persons[i]._y = personData.readUint16LE();
_persons[i]._fontColor = personData.readByte();
@@ -125,9 +128,9 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
uint numDialogues = file->_length / sizeof(uint16);
_dialogueOffsets = new uint[numDialogues];
- uint curOffset;
- for (i = 0, curOffset = 0; i < numDialogues; ++i) {
- _dialogueOffsets[i] = curOffset;
+ uint curOffset, idx;
+ for (idx = 0, curOffset = 0; idx < numDialogues; ++idx) {
+ _dialogueOffsets[idx] = curOffset;
curOffset += dialogueData.readUint16LE();
}
@@ -162,7 +165,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
_variables = new int[numVariables];
Common::MemoryReadStream variableData(file->_data, file->_length);
- for (i = 0; i < numVariables; ++i) {
+ for (uint i = 0; i < numVariables; ++i) {
_variables[i] = variableData.readUint16LE();
}
@@ -180,7 +183,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
_objects = new GameObject[numObjects];
Common::MemoryReadStream objStatus(file->_data, file->_length);
- for (i = 0; i < numObjects; ++i) {
+ for (uint i = 0; i < numObjects; ++i) {
byte tmp = objStatus.readByte();
// Set object visibility
@@ -216,6 +219,7 @@ void Game::start() {
// init scripts. This flag was turned on to skip the rest of
// those programs. Don't call loop(), because the
// location may have changed.
+ fadePalette(true);
continue;
}
@@ -249,14 +253,14 @@ void Game::init() {
setLoopStatus(kStatusGate);
setLoopSubstatus(kOuterLoop);
- _animUnderCursor = NULL;
+ _animUnderCursor = nullptr;
- _currentItem = _itemUnderCursor = NULL;
+ _currentItem = _itemUnderCursor = nullptr;
_previousItemPosition = -1;
_vm->_mouse->setCursorType(kHighlightedCursor); // anything different from kNormalCursor
- _objUnderCursor = NULL;
+ _objUnderCursor = nullptr;
// Set the inventory to empty initially
memset(_inventory, 0, kInventorySlots * sizeof(GameItem *));
@@ -400,12 +404,12 @@ void Game::handleInventoryLoop() {
// an overlay, for which we check. Item animations have their IDs
// calculated by offseting their itemID from the ID of the last "special"
// animation ID. In this way, we obtain its itemID.
- if (_animUnderCursor != NULL && _animUnderCursor != _inventoryAnim && _animUnderCursor->getID() != kOverlayImage) {
+ if (_animUnderCursor != nullptr && _animUnderCursor != _inventoryAnim && _animUnderCursor->getID() != kOverlayImage) {
_itemUnderCursor = getItem(kInventoryItemsID - _animUnderCursor->getID());
- assert(_itemUnderCursor != NULL);
+ assert(_itemUnderCursor != nullptr);
assert(_itemUnderCursor->_anim == _animUnderCursor);
} else {
- _itemUnderCursor = NULL;
+ _itemUnderCursor = nullptr;
}
// If the user pressed the left mouse button
@@ -478,6 +482,7 @@ void Game::handleDialogueLoop() {
}
void Game::fadePalette(bool fading_out) {
+ _isFadeOut = fading_out;
const byte *startPal = NULL;
const byte *endPal = _currentRoom._palette >= 0
? _vm->_paletteArchive->getFile(_currentRoom._palette)->_data
@@ -551,6 +556,19 @@ void Game::advanceAnimationsAndTestLoopExit() {
_vm->_anims->drawScene(_vm->_screen->getSurface());
_vm->_screen->copyToScreen();
_vm->_system->delayMillis(kTimeUnit);
+ if(_isFadeOut) {
+ fadePalette(false);
+ // Set cursor state
+ // Need to do this after we set the palette since the cursors use it
+ if (_currentRoom._mouseOn) {
+ debugC(6, kDraciLogicDebugLevel, "Mouse: ON");
+ _vm->_mouse->cursorOn();
+ _vm->_mouse->setCursorType(kNormalCursor);
+ } else {
+ debugC(6, kDraciLogicDebugLevel, "Mouse: OFF");
+ _vm->_mouse->cursorOff();
+ }
+ }
// If the hero has arrived at his destination, after even the last
// phase was correctly animated, run the callback.
@@ -598,6 +616,8 @@ void Game::loop(LoopSubstatus substatus, bool shouldExit) {
break;
}
+ advanceAnimationsAndTestLoopExit();
+
if (_vm->_mouse->isCursorOn()) {
// Find animation under cursor and the game object
// corresponding to it
@@ -629,8 +649,6 @@ void Game::loop(LoopSubstatus substatus, bool shouldExit) {
}
}
- advanceAnimationsAndTestLoopExit();
-
} while (!shouldExitLoop());
setLoopSubstatus(kOuterLoop);
@@ -808,7 +826,7 @@ void Game::removeItem(GameItem *item) {
return;
for (uint i = 0; i < kInventorySlots; ++i) {
if (_inventory[i] == item) {
- _inventory[i] = NULL;
+ _inventory[i] = nullptr;
item->_anim->stop();
break;
}
@@ -875,9 +893,6 @@ void Game::putItem(GameItem *item, int position) {
void Game::inventoryInit() {
// Pause all "background" animations
_vm->_anims->pauseAnimations();
- if (_walkingState.isActive()) {
- walkHero(_hero.x, _hero.y, kDirectionLast);
- }
// Draw the inventory and the current items
inventoryDraw();
@@ -888,6 +903,13 @@ void Game::inventoryInit() {
// Set the appropriate loop status
setLoopStatus(kStatusInventory);
+ if (_walkingState.isActive()) {
+ _walkingState.stopWalking();
+ walkHero(_hero.x, _hero.y, kDirectionLast);
+ } else {
+ _lastTarget = _hero;
+ }
+
// Don't return from the inventory mode immediately if the mouse is out.
_mouseChangeTick = kMouseDoNotSwitch;
}
@@ -906,8 +928,12 @@ void Game::inventoryDone() {
}
}
+ // Start moving to last target
+ walkHero(_lastTarget.x, _lastTarget.y, kDirectionLast);
+ _walkingState.callbackLast();
+
// Reset item under cursor
- _itemUnderCursor = NULL;
+ _itemUnderCursor = nullptr;
// Don't start the inventory mode again if the mouse is on the top.
_mouseChangeTick = kMouseDoNotSwitch;
@@ -926,10 +952,12 @@ void Game::inventoryDraw() {
void Game::inventoryReload() {
// Make sure all items are loaded into memory (e.g., after loading a
// savegame) by re-putting them on the same spot in the inventory.
+ GameItem *tempItem = _currentItem;
for (uint i = 0; i < kInventorySlots; ++i) {
putItem(_inventory[i], i);
}
setPreviousItemPosition(0);
+ _currentItem = tempItem;
}
void Game::inventorySwitch(int keycode) {
@@ -1190,6 +1218,12 @@ void Game::walkHero(int x, int y, SightDirection dir) {
debug(1, "Unreachable point [%d,%d]", target.x, target.y);
return;
}
+
+ // Save point of player's last target.
+ if (_loopStatus != kStatusInventory) {
+ _lastTarget = target;
+ }
+
_walkingMap.obliquePath(shortestPath, &obliquePath);
debugC(2, kDraciWalkingDebugLevel, "Walking path lengths: shortest=%d oblique=%d", shortestPath.size(), obliquePath.size());
if (_vm->_showWalkingMap) {
@@ -1433,7 +1467,6 @@ void Game::enterNewRoom() {
_vm->_screen->setPalette(NULL, 0, kNumColors);
_vm->_anims->drawScene(_vm->_screen->getSurface());
_vm->_screen->copyToScreen();
- fadePalette(false);
// Run the program for the gate the dragon came through
debugC(6, kDraciLogicDebugLevel, "Running program for gate %d", _newGate);
@@ -1446,17 +1479,6 @@ void Game::enterNewRoom() {
// Don't immediately switch to the map or inventory even if the mouse
// position tell us to.
_mouseChangeTick = kMouseDoNotSwitch;
-
- // Set cursor state
- // Need to do this after we set the palette since the cursors use it
- if (_currentRoom._mouseOn) {
- debugC(6, kDraciLogicDebugLevel, "Mouse: ON");
- _vm->_mouse->cursorOn();
- _vm->_mouse->setCursorType(kNormalCursor);
- } else {
- debugC(6, kDraciLogicDebugLevel, "Mouse: OFF");
- _vm->_mouse->cursorOff();
- }
}
void Game::positionAnimAsHero(Animation *anim) {
@@ -1572,7 +1594,7 @@ Game::~Game() {
delete[] _items;
}
-void Game::DoSync(Common::Serializer &s) {
+void Game::DoSync(Common::Serializer &s, uint8 saveVersion) {
s.syncAsUint16LE(_currentRoom._roomNum);
for (uint i = 0; i < _info._numObjects; ++i) {
@@ -1603,6 +1625,25 @@ void Game::DoSync(Common::Serializer &s) {
s.syncAsSint16LE(_dialogueVars[i]);
}
+ if(saveVersion >= 2) {
+ setPositionLoaded(true);
+ if (s.isSaving()) {
+ s.syncAsSint16LE(_hero.x);
+ s.syncAsSint16LE(_hero.y);
+
+ int handItemID = _currentItem ? _currentItem->_absNum : -1;
+ s.syncAsSint16LE(handItemID);
+ } else {
+ s.syncAsSint16LE(_heroLoading.x);
+ s.syncAsSint16LE(_heroLoading.y);
+
+ int handItemID = -1;
+ s.syncAsSint16LE(handItemID);
+ _currentItem = getItem(handItemID);
+ }
+ } else {
+ _currentItem = nullptr;
+ }
}
static double real_to_double(byte real[6]) {
diff --git a/engines/draci/game.h b/engines/draci/game.h
index 4a8f3de269..53a472a552 100644
--- a/engines/draci/game.h
+++ b/engines/draci/game.h
@@ -215,6 +215,7 @@ public:
void walkHero(int x, int y, SightDirection dir); // start walking and leave callback as is
void setHeroPosition(const Common::Point &p);
const Common::Point &getHeroPosition() const { return _hero; }
+ const Common::Point &getHeroLoadingPosition() const { return _heroLoading; }
void positionAnimAsHero(Animation *anim);
void positionHeroAsAnim(Animation *anim);
@@ -290,6 +291,8 @@ public:
void setExitLoop(bool exit) { _shouldExitLoop = exit; }
bool isReloaded() const { return _isReloaded; }
void setIsReloaded(bool value) { _isReloaded = value; }
+ bool isPositionLoaded() { return _isPositionLoaded; }
+ void setPositionLoaded(bool value) { _isPositionLoaded = value; }
void setSpeechTiming(uint tick, uint duration);
void shiftSpeechAndFadeTick(int delta);
@@ -327,7 +330,7 @@ public:
void setEnableSpeedText(bool value) { _enableSpeedText = value; }
bool getEnableSpeedText() const { return _enableSpeedText; }
- void DoSync(Common::Serializer &s);
+ void DoSync(Common::Serializer &s, uint8 saveVersion);
private:
void updateOrdinaryCursor();
@@ -352,6 +355,8 @@ private:
GameInfo _info;
Common::Point _hero;
+ Common::Point _heroLoading;
+ Common::Point _lastTarget;
int *_variables;
Person *_persons;
@@ -395,6 +400,7 @@ private:
bool _shouldQuit;
bool _shouldExitLoop;
bool _isReloaded;
+ bool _isPositionLoaded;
uint _speechTick;
uint _speechDuration;
@@ -408,6 +414,7 @@ private:
int _fadePhases;
int _fadePhase;
uint _fadeTick;
+ bool _isFadeOut;
int _mouseChangeTick;
bool _enableQuickHero;
diff --git a/engines/draci/saveload.cpp b/engines/draci/saveload.cpp
index 31ac63b791..3e7f8651c1 100644
--- a/engines/draci/saveload.cpp
+++ b/engines/draci/saveload.cpp
@@ -45,7 +45,8 @@ bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header) {
return false;
header.version = in->readByte();
- if (header.version != DRACI_SAVEGAME_VERSION)
+ // Version 1 is compatible with Version 2
+ if (header.version > DRACI_SAVEGAME_VERSION)
return false;
// Read in the string
@@ -106,7 +107,7 @@ Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName,
} else {
// Create the remainder of the savegame
Common::Serializer s(NULL, f);
- vm._game->DoSync(s);
+ vm._game->DoSync(s, header.version);
f->finalize();
delete f;
@@ -140,7 +141,7 @@ Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm) {
// Synchronise the remaining data of the savegame
Common::Serializer s(f, NULL);
- vm->_game->DoSync(s);
+ vm->_game->DoSync(s, header.version);
delete f;
// Post-processing
diff --git a/engines/draci/saveload.h b/engines/draci/saveload.h
index 8b38ccb94f..6f951a3409 100644
--- a/engines/draci/saveload.h
+++ b/engines/draci/saveload.h
@@ -29,7 +29,7 @@
namespace Draci {
-#define DRACI_SAVEGAME_VERSION 1
+#define DRACI_SAVEGAME_VERSION 2
struct DraciSavegameHeader {
uint8 version;
diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp
index 97dde39809..09c74f5e0d 100644
--- a/engines/draci/script.cpp
+++ b/engines/draci/script.cpp
@@ -634,8 +634,16 @@ void Script::stayOn(const Common::Array<int> &params) {
return;
}
- int x = params[0];
- int y = params[1];
+ int x, y;
+ Common::Point afterLoadingPos = _vm->_game->getHeroLoadingPosition();
+ if(_vm->_game->isPositionLoaded() == true) {
+ x = afterLoadingPos.x;
+ y = afterLoadingPos.y;
+ }
+ else {
+ x = params[0];
+ y = params[1];
+ }
SightDirection dir = static_cast<SightDirection> (params[2]);
// Jumps into the given position regardless of the walking map.
@@ -670,6 +678,11 @@ void Script::walkOnPlay(const Common::Array<int> &params) {
return;
}
+ if(_vm->_game->isPositionLoaded() == true) {
+ _vm->_game->setPositionLoaded(false);
+ return;
+ }
+
int x = params[0];
int y = params[1];
SightDirection dir = static_cast<SightDirection> (params[2]);
@@ -687,6 +700,10 @@ void Script::newRoom(const Common::Array<int> &params) {
return;
}
+ if(_vm->_game->isPositionLoaded() == true) {
+ _vm->_game->setPositionLoaded(false);
+ }
+
int room = params[0] - 1;
int gate = params[1] - 1;
diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp
index 1467ecee35..04cd929ac6 100644
--- a/engines/draci/walking.cpp
+++ b/engines/draci/walking.cpp
@@ -439,8 +439,8 @@ void WalkingState::startWalking(const Common::Point &p1, const Common::Point &p2
}
void WalkingState::setCallback(const GPL2Program *program, uint16 offset) {
- _callback = program;
- _callbackOffset = offset;
+ _callback = _callbackLast = program;
+ _callbackOffset = _callbackOffsetLast = offset;
}
void WalkingState::callback() {
@@ -452,6 +452,12 @@ void WalkingState::callback() {
const GPL2Program &originalCallback = *_callback;
_callback = NULL;
_vm->_script->runWrapper(originalCallback, _callbackOffset, true, false);
+ _callbackLast = NULL;
+ _callbackOffset = 0;
+}
+
+void WalkingState::callbackLast() {
+ setCallback(_callbackLast, _callbackOffsetLast);
}
bool WalkingState::continueWalkingOrClearPath() {
diff --git a/engines/draci/walking.h b/engines/draci/walking.h
index ee2b48d083..fcdef3830e 100644
--- a/engines/draci/walking.h
+++ b/engines/draci/walking.h
@@ -110,6 +110,8 @@ public:
_lastAnimPhase = 0;
_turningFinished = 0;
_callbackOffset = 0;
+ _callbackOffsetLast = 0;
+ _callbackLast = 0;
stopWalking();
}
@@ -124,6 +126,7 @@ public:
void setCallback(const GPL2Program *program, uint16 offset);
void callback();
+ void callbackLast();
bool isActive() const { return _path.size() > 0; }
@@ -157,7 +160,9 @@ private:
bool _turningFinished;
const GPL2Program *_callback;
+ const GPL2Program *_callbackLast;
uint16 _callbackOffset;
+ uint16 _callbackOffsetLast;
// Initiates turning of the dragon into the direction for the next
// segment / after walking. Returns false when there is nothing left
diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp
index b158969f46..5009a62e84 100644
--- a/engines/drascula/animation.cpp
+++ b/engines/drascula/animation.cpp
@@ -45,9 +45,6 @@ void DrasculaEngine::updateAnim(int y, int destX, int destY, int width, int heig
void DrasculaEngine::animation_1_1() {
debug(4, "animation_1_1()");
- int l, l2, p;
- //int pixelPos[6];
-
while (term_int == 0 && !shouldQuit()) {
playMusic(29);
playFLI("logoddm.bin", 9);
@@ -119,8 +116,8 @@ void DrasculaEngine::animation_1_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit())
break;
- for (l2 = 0; l2 < 3; l2++)
- for (l = 0; l < 7; l++) {
+ for (int l2 = 0; l2 < 3; l2++)
+ for (int l = 0; l < 7; l++) {
copyBackground();
copyBackground(interf_x[l], interf_y[l], 156, 45, 63, 31, drawSurface2, screenSurface);
updateScreen();
@@ -133,9 +130,7 @@ void DrasculaEngine::animation_1_1() {
if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit())
break;
- l2 = 0; p = 0;
-
- for (l = 0; l < 180; l++) {
+ for (int l = 0, l2 = 0, p = 0; l < 180; l++) {
copyBackground(0, 0, 320 - l, 0, l, 200, drawSurface3, screenSurface);
copyBackground(l, 0, 0, 0, 320 - l, 200, bgSurface, screenSurface);
@@ -703,17 +698,15 @@ void DrasculaEngine::animation_4_2() {
void DrasculaEngine::animation_14_2() {
debug(4, "animation_14_2()");
- int cY = -160;
- int l = 0;
-
loadPic("an14_2.alg", backSurface);
+ int l = 0;
for (int n = -160; n <= 0; n = n + 5 + l) {
copyBackground();
updateRefresh_pre();
moveCharacters();
moveVonBraun();
- cY = n;
+ int cY = n;
copyRect(150, 6, 69, cY, 158, 161, backSurface, screenSurface);
updateRefresh();
updateScreen();
@@ -959,8 +952,6 @@ void DrasculaEngine::animation_23_2() {
void DrasculaEngine::animation_25_2() {
debug(4, "animation_25_2()");
- int cY = 0;
-
loadPic("an14_2.alg", backSurface);
loadPic(18, bgSurface);
@@ -975,8 +966,7 @@ void DrasculaEngine::animation_25_2() {
moveCharacters();
moveVonBraun();
- cY = n;
-
+ int cY = n;
copyRect(150, 6, 69, cY, 158, 161, backSurface, screenSurface);
updateRefresh();
@@ -1594,20 +1584,18 @@ void DrasculaEngine::animation_1_6() {
void DrasculaEngine::animation_5_6() {
debug(4, "animation_5_6()");
- int pY = -125;
-
animate("man.bin", 14);
for (int n = -125; n <= 0; n = n + 2) {
copyBackground();
updateRefresh_pre();
- pY = n;
+ int pY = n;
copyRect(1, 29, 204, pY, 18, 125, drawSurface3, screenSurface);
updateRefresh();
-
updateScreen();
updateEvents();
+
pause(2);
}
diff --git a/engines/drascula/console.cpp b/engines/drascula/console.cpp
index 50e96c8757..b545c096d0 100644
--- a/engines/drascula/console.cpp
+++ b/engines/drascula/console.cpp
@@ -27,7 +27,7 @@
namespace Drascula {
Console::Console(DrasculaEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room));
+ registerCmd("room", WRAP_METHOD(Console, Cmd_Room));
}
Console::~Console() {
@@ -35,7 +35,7 @@ Console::~Console() {
bool Console::Cmd_Room(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: room <number>\n");
+ debugPrintf("Usage: room <number>\n");
return true;
}
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index 35461f1d71..797b6d94b0 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -194,6 +194,9 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam
_console = 0;
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ SearchMan.addSubDirectoryMatching(gameDataDir, "audio");
+
int cd_num = ConfMan.getInt("cdrom");
if (cd_num >= 0)
_system->getAudioCDManager()->openCD(cd_num);
diff --git a/engines/dreamweb/POTFILES b/engines/dreamweb/POTFILES
index d05d239bb7..64fb20db67 100644
--- a/engines/dreamweb/POTFILES
+++ b/engines/dreamweb/POTFILES
@@ -1 +1,3 @@
engines/dreamweb/detection.cpp
+engines/dreamweb/saveload.cpp
+
diff --git a/engines/fullpipe/configure.engine b/engines/fullpipe/configure.engine
index fce5951e26..a9042449db 100644
--- a/engines/fullpipe/configure.engine
+++ b/engines/fullpipe/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine fullpipe "Full Pipe" no
+add_engine fullpipe "Full Pipe" no "" "" "16bit"
diff --git a/engines/fullpipe/console.cpp b/engines/fullpipe/console.cpp
index cb76345d66..dd3d1bf693 100644
--- a/engines/fullpipe/console.cpp
+++ b/engines/fullpipe/console.cpp
@@ -28,14 +28,14 @@
namespace Fullpipe {
Console::Console(FullpipeEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("scene", WRAP_METHOD(Console, Cmd_Scene));
+ registerCmd("scene", WRAP_METHOD(Console, Cmd_Scene));
}
bool Console::Cmd_Scene(int argc, const char **argv) {
if (argc != 2) {
int sceneTag = _vm->_currentScene->_sceneId;
- DebugPrintf("Current scene: %d (scene tag: %d)\n", _vm->getSceneFromTag(sceneTag), sceneTag);
- DebugPrintf("Use %s <scene> to change the current scene\n", argv[0]);
+ debugPrintf("Current scene: %d (scene tag: %d)\n", _vm->getSceneFromTag(sceneTag), sceneTag);
+ debugPrintf("Use %s <scene> to change the current scene\n", argv[0]);
return true;
} else {
int scene = _vm->convertScene(atoi(argv[1]));
diff --git a/engines/fullpipe/constants.h b/engines/fullpipe/constants.h
index 8f3f587714..b257fca949 100644
--- a/engines/fullpipe/constants.h
+++ b/engines/fullpipe/constants.h
@@ -43,6 +43,8 @@ namespace Fullpipe {
#define MV_LFT_OPEN 1048
#define MV_MAN_GOLADDER 451
#define MV_MAN_GOLADDER2 2844
+#define MV_MAN_HMRKICK 1028
+#define MV_MAN_HMRKICK_COINLESS 1445
#define MV_MAN_LIFTDOWN 1052
#define MV_MAN_LIFTUP 1051
#define MV_MAN_LOOKUP 4773
@@ -219,8 +221,11 @@ namespace Fullpipe {
#define SC_MAINMENU 4620
#define SC_MAP 5222
#define SC_TITLES 5166
+#define SND_CMN_015 3139
#define SND_CMN_031 3516
#define SND_CMN_032 3517
+#define SND_CMN_054 4762
+#define SND_CMN_055 4763
#define SND_CMN_060 4921
#define SND_CMN_061 4922
#define SND_CMN_070 5199
@@ -287,6 +292,48 @@ namespace Fullpipe {
#define PIC_MOV_CANCEL 5345
#define PIC_MOV_OK 5344
+// Saveload dialog
+#define PIC_MLD_BGR 4645
+#define PIC_MLD_CANCEL_D 4648
+#define PIC_MLD_CANCEL_L 4649
+#define PIC_MLD_OK_D 4646
+#define PIC_MLD_OK_L 4647
+#define PIC_MSV_0_D 4643
+#define PIC_MSV_0_L 4644
+#define PIC_MSV_1_D 4651
+#define PIC_MSV_1_L 4660
+#define PIC_MSV_2_D 4652
+#define PIC_MSV_2_L 4661
+#define PIC_MSV_3_D 4653
+#define PIC_MSV_3_L 4662
+#define PIC_MSV_4_D 4654
+#define PIC_MSV_4_L 4663
+#define PIC_MSV_5_D 4655
+#define PIC_MSV_5_L 4664
+#define PIC_MSV_6_D 4656
+#define PIC_MSV_6_L 4665
+#define PIC_MSV_7_D 4657
+#define PIC_MSV_7_L 4666
+#define PIC_MSV_8_D 4658
+#define PIC_MSV_8_L 4667
+#define PIC_MSV_9_D 4659
+#define PIC_MSV_9_L 4668
+#define PIC_MSV_BGR 4634
+#define PIC_MSV_CANCEL_D 4637
+#define PIC_MSV_CANCEL_L 4638
+#define PIC_MSV_DOTS_D 4670
+#define PIC_MSV_DOTS_L 4669
+#define PIC_MSV_DOT_D 5188
+#define PIC_MSV_DOT_L 5189
+#define PIC_MSV_EMPTY_D 4639
+#define PIC_MSV_EMPTY_L 4640
+#define PIC_MSV_FULL_D 4641
+#define PIC_MSV_FULL_L 4642
+#define PIC_MSV_OK_D 4635
+#define PIC_MSV_OK_L 4636
+#define PIC_MSV_SPACE_D 5190
+#define PIC_MSV_SPACE_L 5191
+
// Intro
#define ANI_IN1MAN 5110
#define MSG_INTR_ENDINTRO 5139
diff --git a/engines/fullpipe/detection.cpp b/engines/fullpipe/detection.cpp
index 62c5dd3b80..de0ed04d25 100644
--- a/engines/fullpipe/detection.cpp
+++ b/engines/fullpipe/detection.cpp
@@ -26,6 +26,7 @@
#include "common/file.h"
#include "fullpipe/fullpipe.h"
+#include "fullpipe/gameloader.h"
namespace Fullpipe {
@@ -87,15 +88,72 @@ public:
}
virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual int getMaximumSaveSlot() const { return 8; }
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual void removeSaveState(const char *target, int slot) const;
+ virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
};
bool FullpipeMetaEngine::hasFeature(MetaEngineFeature f) const {
- return false;
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate) ||
+ (f == kSupportsLoadingDuringStartup);
}
-bool Fullpipe::FullpipeEngine::hasFeature(EngineFeature f) const {
- return false;
+SaveStateList FullpipeMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String pattern("fullpipe.s??");
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 2 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 2);
+
+ if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(*file);
+ if (in) {
+ Fullpipe::FullpipeSavegameHeader header;
+ Fullpipe::readSavegameHeader(in, header);
+ saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
+ delete header.thumbnail;
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void FullpipeMetaEngine::removeSaveState(const char *target, int slot) const {
+ g_system->getSavefileManager()->removeSavefile(Fullpipe::getSavegameFile(slot));
+}
+
+SaveStateDescriptor FullpipeMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(
+ Fullpipe::getSavegameFile(slot));
+
+ if (f) {
+ Fullpipe::FullpipeSavegameHeader header;
+ Fullpipe::readSavegameHeader(f, header);
+ delete f;
+
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header.saveName);
+ desc.setThumbnail(header.thumbnail);
+
+ return desc;
+ }
+
+ return SaveStateDescriptor();
}
bool FullpipeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp
index 246510e227..bb0838395d 100644
--- a/engines/fullpipe/fullpipe.cpp
+++ b/engines/fullpipe/fullpipe.cpp
@@ -34,9 +34,11 @@
#include "fullpipe/modal.h"
#include "fullpipe/input.h"
#include "fullpipe/motion.h"
+#include "fullpipe/statics.h"
#include "fullpipe/scenes.h"
#include "fullpipe/floaters.h"
#include "fullpipe/console.h"
+#include "fullpipe/constants.h"
namespace Fullpipe {
@@ -82,6 +84,7 @@ FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc)
_currentCheatPos = 0;
_modalObject = 0;
+ _origFormat = 0;
_liftEnterMQ = 0;
_liftExitMQ = 0;
@@ -104,6 +107,18 @@ FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc)
_musicAllowed = -1;
_musicGameVar = 0;
+ _musicMinDelay = 0;
+ _musicMaxDelay = 0;
+ _musicLocal = 0;
+ _trackStartDelay = 0;
+
+ memset(_sceneTracks, 0, sizeof(_sceneTracks));
+ memset(_trackName, 0, sizeof(_trackName));
+ memset(_sceneTracksCurrentTrack, 0, sizeof(_sceneTracksCurrentTrack));
+
+ _numSceneTracks = 0;
+ _sceneTrackHasSequence = false;
+ _sceneTrackIsPlaying = false;
_aniMan = 0;
_aniMan2 = 0;
@@ -193,16 +208,50 @@ void FullpipeEngine::initialize() {
}
void FullpipeEngine::restartGame() {
- warning("STUB: FullpipeEngine::restartGame()");
+ _floaters->stopAll();
+
+ clearGlobalMessageQueueList();
+ clearMessages();
+
+ initObjectStates();
+
+ if (_scene2) {
+ _scene2->getAniMan();
+ _scene2 = 0;
+ }
+
+ if (_currentScene) {
+ _gameLoader->unloadScene(_currentScene->_sceneId);
+
+ _currentScene = 0;
+ }
+
+ _gameLoader->restoreDefPicAniInfos();
+
+ getGameLoaderInventory()->clear();
+ getGameLoaderInventory()->addItem(ANI_INV_MAP, 1);
+ getGameLoaderInventory()->rebuildItemRects();
+
+ initMap();
+
+ if (_flgPlayIntro) {
+ _gameLoader->loadScene(SC_INTRO1);
+ _gameLoader->gotoScene(SC_INTRO1, TrubaUp);
+ } else {
+ _gameLoader->loadScene(SC_1);
+ _gameLoader->gotoScene(SC_1, TrubaLeft);
+ }
}
Common::Error FullpipeEngine::run() {
- const Graphics::PixelFormat format(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ const Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
// Initialize backend
initGraphics(800, 600, true, &format);
_backgroundSurface.create(800, 600, format);
+ _origFormat = new Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+
_console = new Console(this);
initialize();
@@ -335,7 +384,7 @@ void FullpipeEngine::updateEvents() {
case Common::EVENT_QUIT:
_gameContinue = false;
break;
- case Common::EVENT_RBUTTONDOWN:
+ case Common::EVENT_RBUTTONDOWN:
if (!_inputArFlag && (_updateTicks - _lastInputTicks) >= 2) {
ex = new ExCommand(0, 17, 107, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0);
ex->_excFlags |= 3;
@@ -368,21 +417,34 @@ void FullpipeEngine::updateEvents() {
}
}
-
-#if 0
- warning("STUB: FullpipeEngine::updateEvents() <mainWindowProc>");
- if (Msg == MSG_SC11_SHOWSWING && _modalObject) {
- _modalObject->method14();
- }
-#endif
+ // pollEvent() is implemented only for video player. So skip it.
+ //if (event.kbd.keycode == MSG_SC11_SHOWSWING && _modalObject) {
+ // _modalObject->pollEvent();
+ //}
}
void FullpipeEngine::freeGameLoader() {
- warning("STUB: FullpipeEngine::freeGameLoader()");
+ setCursor(0);
+ delete _movTable;
+ _floaters->stopAll();
+ delete _gameLoader;
+ _currentScene = 0;
+ _scene2 = 0;
+ _loaderScene = 0;
}
void FullpipeEngine::cleanup() {
- warning("STUB: FullpipeEngine::cleanup()");
+ //cleanRecorder();
+ clearMessageHandlers();
+ clearMessages();
+ _globalMessageQueueList->compact();
+
+ for (uint i = 0; i < _globalMessageQueueList->size(); i++)
+ delete (*_globalMessageQueueList)[i];
+
+ stopAllSoundStreams();
+
+ delete _origFormat;
}
void FullpipeEngine::updateScreen() {
@@ -465,7 +527,20 @@ void FullpipeEngine::setObjectState(const char *name, int state) {
}
void FullpipeEngine::disableSaves(ExCommand *ex) {
- warning("STUB: FullpipeEngine::disableSaves()");
+ if (_isSaveAllowed) {
+ _isSaveAllowed = false;
+
+ if (_globalMessageQueueList->size() && (*_globalMessageQueueList)[0] != 0) {
+ for (uint i = 0; i < _globalMessageQueueList->size(); i++) {
+ if ((*_globalMessageQueueList)[i]->_flags & 1)
+ if ((*_globalMessageQueueList)[i]->_id != ex->_parId && !(*_globalMessageQueueList)[i]->_isFinished)
+ return;
+ }
+ }
+
+ if (_currentScene)
+ _gameLoader->writeSavegame(_currentScene, "savetmp.sav");
+ }
}
diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h
index 5718b16ab3..7f20a6d6af 100644
--- a/engines/fullpipe/fullpipe.h
+++ b/engines/fullpipe/fullpipe.h
@@ -32,7 +32,7 @@
#include "audio/mixer.h"
-#include "graphics/surface.h"
+#include "graphics/transparent_surface.h"
#include "engines/engine.h"
@@ -99,7 +99,6 @@ public:
const ADGameDescription *_gameDescription;
const char *getGameId() const;
Common::Platform getPlatform() const;
- bool hasFeature(EngineFeature f) const;
Common::RandomSource *_rnd;
@@ -109,6 +108,7 @@ public:
void updateEvents();
Graphics::Surface _backgroundSurface;
+ Graphics::PixelFormat *_origFormat;
GameLoader *_gameLoader;
GameProject *_gameProject;
@@ -151,12 +151,24 @@ public:
int _currSoundListCount;
bool _soundEnabled;
bool _flgSoundList;
+ char _sceneTracks[10][260];
+ int _numSceneTracks;
+ bool _sceneTrackHasSequence;
+ int _musicMinDelay;
+ int _musicMaxDelay;
+ int _musicLocal;
+ char _trackName[2600];
+ int _trackStartDelay;
+ char _sceneTracksCurrentTrack[260];
+ bool _sceneTrackIsPlaying;
void stopAllSounds();
void toggleMute();
void playSound(int id, int flag);
void playTrack(GameVar *sceneVar, const char *name, bool delayed);
+ int getSceneTrack();
void startSceneTrack();
+ void startSoundStream1(char *trackName);
void stopSoundStream2();
void stopAllSoundStreams();
void stopAllSoundInstances(int id);
@@ -231,6 +243,7 @@ public:
int (*_updateCursorCallback)();
void drawAlphaRectangle(int x1, int y1, int x2, int y2, int alpha);
+ void sceneFade(Scene *sc, bool direction);
int _cursorId;
int _minCursorId;
@@ -300,6 +313,7 @@ public:
GameVar *_musicGameVar;
Audio::SoundHandle _sceneTrackHandle;
+
public:
bool _isSaveAllowed;
diff --git a/engines/fullpipe/gameloader.cpp b/engines/fullpipe/gameloader.cpp
index d9f7327a6b..fbf96b3060 100644
--- a/engines/fullpipe/gameloader.cpp
+++ b/engines/fullpipe/gameloader.cpp
@@ -21,6 +21,7 @@
*/
#include "fullpipe/fullpipe.h"
+#include "graphics/thumbnail.h"
#include "fullpipe/gameloader.h"
#include "fullpipe/scene.h"
@@ -83,7 +84,29 @@ GameLoader::~GameLoader() {
delete _interactionController;
delete _inputController;
- warning("STUB: GameLoader::~GameLoader()");
+ g_fp->_gameLoader = 0;
+
+ for (uint i = 0; i < _sc2array.size(); i++) {
+ if (_sc2array[i]._defPicAniInfos)
+ delete _sc2array[i]._defPicAniInfos;
+
+ if (_sc2array[i]._picAniInfos)
+ delete _sc2array[i]._picAniInfos;
+
+ if (_sc2array[i]._motionController)
+ delete _sc2array[i]._motionController;
+
+ if (_sc2array[i]._data1)
+ free(_sc2array[i]._data1);
+
+ if (_sc2array[i]._entranceData)
+ free(_sc2array[i]._entranceData);
+ }
+
+ delete _gameVar;
+ _gameVar = 0;
+
+ _sc2array.clear();
}
bool GameLoader::load(MfcArchive &file) {
@@ -501,6 +524,14 @@ void GameLoader::updateSystems(int counterdiff) {
}
}
+void GameLoader::readSavegame(const char *fname) {
+ warning("STUB: readSavegame(%s)", fname);
+}
+
+void GameLoader::writeSavegame(Scene *sc, const char *fname) {
+ warning("STUB: writeSavegame(sc, %s)", fname);
+}
+
Sc2::Sc2() {
_sceneId = 0;
_field_2 = 0;
@@ -593,6 +624,51 @@ bool PreloadItems::load(MfcArchive &file) {
return true;
}
+const char *getSavegameFile(int saveGameIdx) {
+ static char buffer[20];
+ sprintf(buffer, "fullpipe.s%02d", saveGameIdx);
+ return buffer;
+}
+
+bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header) {
+ char saveIdentBuffer[6];
+ header.thumbnail = NULL;
+
+ // Validate the header Id
+ in->read(saveIdentBuffer, 6);
+ if (strcmp(saveIdentBuffer, "SVMCR"))
+ return false;
+
+ header.version = in->readByte();
+ if (header.version != FULLPIPE_SAVEGAME_VERSION)
+ return false;
+
+ // Read in the string
+ header.saveName.clear();
+ char ch;
+ while ((ch = (char)in->readByte()) != '\0') header.saveName += ch;
+
+ // Get the thumbnail
+ header.thumbnail = Graphics::loadThumbnail(*in);
+ if (!header.thumbnail)
+ return false;
+
+ return true;
+}
+
+void GameLoader::restoreDefPicAniInfos() {
+ for (uint i = 0; i < _sc2array.size(); i++) {
+ if (_sc2array[i]._picAniInfos) {
+ free(_sc2array[i]._picAniInfos);
+ _sc2array[i]._picAniInfos = 0;
+ _sc2array[i]._picAniInfosCount = 0;
+ }
+
+ if (_sc2array[i]._scene)
+ applyPicAniInfos(_sc2array[i]._scene, _sc2array[i]._defPicAniInfos, _sc2array[i]._defPicAniInfosCount);
+ }
+}
+
GameVar *FullpipeEngine::getGameLoaderGameVar() {
if (_gameLoader)
return _gameLoader->_gameVar;
diff --git a/engines/fullpipe/gameloader.h b/engines/fullpipe/gameloader.h
index a79c0e11b4..772cc51130 100644
--- a/engines/fullpipe/gameloader.h
+++ b/engines/fullpipe/gameloader.h
@@ -29,6 +29,8 @@
namespace Fullpipe {
+#define FULLPIPE_SAVEGAME_VERSION 1
+
class SceneTag;
class MctlCompound;
class InputController;
@@ -72,6 +74,12 @@ class PreloadItems : public Common::Array<PreloadItem *>, public CObject {
virtual bool load(MfcArchive &file);
};
+struct FullpipeSavegameHeader {
+ uint8 version;
+ Common::String saveName;
+ Graphics::Surface *thumbnail;
+};
+
class GameLoader : public CObject {
public:
GameLoader();
@@ -89,6 +97,11 @@ class GameLoader : public CObject {
void applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAniInfoCount);
void saveScenePicAniInfos(int sceneId);
+ void readSavegame(const char *fname);
+ void writeSavegame(Scene *sc, const char *fname);
+
+ void restoreDefPicAniInfos();
+
GameProject *_gameProject;
InteractionController *_interactionController;
InputController *_inputController;
@@ -108,6 +121,9 @@ class GameLoader : public CObject {
int _preloadEntranceId;
};
+const char *getSavegameFile(int saveGameIdx);
+bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header);
+
Inventory2 *getGameLoaderInventory();
InteractionController *getGameLoaderInteractionController();
MctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId);
diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp
index 7c66a9a747..61fbf7192f 100644
--- a/engines/fullpipe/gfx.cpp
+++ b/engines/fullpipe/gfx.cpp
@@ -33,51 +33,6 @@
namespace Fullpipe {
-Bitmap::Bitmap() {
- _x = 0;
- _y = 0;
- _width = 0;
- _height = 0;
- _pixels = 0;
- _type = 0;
- _dataSize = 0;
- _flags = 0;
-}
-
-Bitmap::Bitmap(Bitmap *src) {
- _x = src->_x;
- _y = src->_y;
- _flags = src->_flags;
- _dataSize = src->_dataSize;
- _type = src->_type;
- _width = src->_width;
- _height = src->_height;
- _pixels = src->_pixels;
-}
-
-Bitmap::~Bitmap() {
- if (_pixels)
- free(_pixels);
-
- _pixels = 0;
-}
-
-void Bitmap::load(Common::ReadStream *s) {
- debug(5, "Bitmap::load()");
-
- _x = s->readUint32LE();
- _y = s->readUint32LE();
- _width = s->readUint32LE();
- _height = s->readUint32LE();
- s->readUint32LE(); // pixels
- _type = s->readUint32LE();
- _dataSize = s->readUint32LE();
- _flags = s->readUint32LE();
-
- debug(8, "Bitmap: x: %d y: %d w: %d h: %d dataSize: 0x%x", _x, _y, _width, _height, _dataSize);
- debug(8, "Bitmap: type: %s (0x%04x) flags: 0x%x", Common::tag2string(_type).c_str(), _type, _flags);
-}
-
Background::Background() {
_x = 0;
_y = 0;
@@ -145,7 +100,7 @@ void Background::addPictureObject(PictureObject *pct) {
bool inserted = false;
for (uint i = 1; i < _picObjList.size(); i++) {
- if (((PictureObject *)_picObjList[i])->_priority <= pct->_priority) {
+ if (_picObjList[i]->_priority <= pct->_priority) {
_picObjList.insert_at(i, pct);
inserted = true;
break;
@@ -192,7 +147,7 @@ bool PictureObject::load(MfcArchive &file, bool bigPicture) {
_picture->load(file);
- _pictureObject2List = new PtrList();
+ _pictureObject2List = new Common::Array<GameObject *>;
int count = file.readUint16LE();
@@ -351,7 +306,25 @@ void GameObject::setOXY(int x, int y) {
_oy = y;
}
-void GameObject::renumPictures(PtrList *lst) {
+void GameObject::renumPictures(Common::Array<StaticANIObject *> *lst) {
+ int *buf = (int *)calloc(lst->size() + 2, sizeof(int));
+
+ for (uint i = 0; i < lst->size(); i++) {
+ if (_id == ((GameObject *)((*lst)[i]))->_id)
+ buf[((GameObject *)((*lst)[i]))->_okeyCode] = 1;
+ }
+
+ if (buf[_okeyCode]) {
+ uint count;
+ for (count = 1; buf[count] && count < lst->size() + 2; count++)
+ ;
+ _okeyCode = count;
+ }
+
+ free(buf);
+}
+
+void GameObject::renumPictures(Common::Array<PictureObject *> *lst) {
int *buf = (int *)calloc(lst->size() + 2, sizeof(int));
for (uint i = 0; i < lst->size(); i++) {
@@ -380,6 +353,7 @@ bool GameObject::getPicAniInfo(PicAniInfo *info) {
info->ox = _ox;
info->oy = _oy;
info->priority = _priority;
+ warning("Yep %d", _id);
return true;
}
@@ -495,7 +469,7 @@ void Picture::freePicture() {
if (_bitmap) {
if (testFlags() && !_field_54) {
freeData();
- free(_bitmap);
+ //free(_bitmap);
_bitmap = 0;
}
}
@@ -614,6 +588,10 @@ void Picture::getDibInfo() {
_bitmap->load(s);
_bitmap->_pixels = _data;
+
+ _bitmap->decode((int32 *)(_paletteData ? _paletteData : g_fp->_globalPalette));
+
+ _bitmap->_pixels = 0;
}
Bitmap *Picture::getPixelData() {
@@ -658,12 +636,12 @@ void Picture::draw(int x, int y, int style, int angle) {
case 1:
//flip
getDimensions(&point);
- _bitmap->flipVertical()->drawShaded(1, x1, y1 + 30 + point.y, pal);
+ _bitmap->flipVertical()->drawShaded(1, x1, y1 + 30 + point.y, pal, _alpha);
break;
case 2:
//vrtSetFadeRatio(g_vrtDrawHandle, 0.34999999);
//vrtSetFadeTable(g_vrtDrawHandle, &unk_477F88, 1.0, 1000.0, 0, 0);
- _bitmap->drawShaded(2, x1, y1, pal);
+ _bitmap->drawShaded(2, x1, y1, pal, _alpha);
//vrtSetFadeRatio(g_vrtDrawHandle, 0.0);
//vrtSetFadeTable(g_vrtDrawHandle, &unk_477F90, 1.0, 1000.0, 0, 0);
break;
@@ -671,7 +649,7 @@ void Picture::draw(int x, int y, int style, int angle) {
if (angle)
drawRotated(x1, y1, angle);
else {
- _bitmap->putDib(x1, y1, (int32 *)pal);
+ _bitmap->putDib(x1, y1, (int32 *)pal, _alpha);
}
}
}
@@ -770,54 +748,71 @@ int Picture::getPixelAtPosEx(int x, int y) {
return 0;
}
-bool Bitmap::isPixelHitAtPos(int x, int y) {
- if (x < _x || x >= _width + _x || y < _y || y >= _y + _height)
- return false;
+Bitmap::Bitmap() {
+ _x = 0;
+ _y = 0;
+ _width = 0;
+ _height = 0;
+ _pixels = 0;
+ _type = 0;
+ _dataSize = 0;
+ _flags = 0;
+ _surface = 0;
+ _flipping = Graphics::FLIP_NONE;
+}
- int off;
+Bitmap::Bitmap(Bitmap *src) {
+ _x = src->_x;
+ _y = src->_y;
+ _flags = src->_flags;
+ _dataSize = src->_dataSize;
+ _type = src->_type;
+ _width = src->_width;
+ _height = src->_height;
+ _pixels = src->_pixels;
+ _surface = new Graphics::TransparentSurface(*src->_surface);
+ _flipping = src->_flipping;
+}
- if (_type == 'CB\x05e')
- off = 2 * ((_width + 1) / 2);
- else
- off = 4 * ((_width + 3) / 4);
+Bitmap::~Bitmap() {
+ if (_pixels)
+ free(_pixels);
- off = x + off * (_y + _height - y - 1) - _x;
+ delete _surface;
- if (_flags & 0x1000000) {
- switch (_type) {
- case 'CB\0\0':
- if (_pixels[off] == (_flags & 0xff))
- return false;
- break;
- case 'CB\x05e':
- if (!*(int16 *)&_pixels[2 * off])
- return false;
- break;
- case 'RB\0\0':
- return isPixelAtHitPosRB(x, y);
- }
- }
- return true;
+ _pixels = 0;
}
-bool Bitmap::isPixelAtHitPosRB(int x, int y) {
- int ox = _x;
- int oy = _y;
+void Bitmap::load(Common::ReadStream *s) {
+ debug(5, "Bitmap::load()");
- _x = _y = 0;
+ _x = s->readUint32LE();
+ _y = s->readUint32LE();
+ _width = s->readUint32LE();
+ _height = s->readUint32LE();
+ s->readUint32LE(); // pixels
+ _type = s->readUint32LE();
+ _dataSize = s->readUint32LE();
+ _flags = s->readUint32LE();
- bool res = putDibRB(0, x, y);
- _x = ox;
- _y = oy;
+ debug(8, "Bitmap: x: %d y: %d w: %d h: %d dataSize: 0x%x", _x, _y, _width, _height, _dataSize);
+ debug(8, "Bitmap: type: %s (0x%04x) flags: 0x%x", Common::tag2string(_type).c_str(), _type, _flags);
+}
- return res;
+bool Bitmap::isPixelHitAtPos(int x, int y) {
+ if (x < _x || x >= _width + _x || y < _y || y >= _y + _height)
+ return false;
+
+ if (!_surface)
+ return false;
+
+ return ((*((int32 *)_surface->getBasePtr(x, y)) & 0xff000000) != 0);
}
-void Bitmap::putDib(int x, int y, int32 *palette) {
- debug(7, "Bitmap::putDib(%d, %d)", x, y);
+void Bitmap::decode(int32 *palette) {
+ _surface = new Graphics::TransparentSurface;
- _x = x - g_fp->_sceneRect.left;
- _y = y - g_fp->_sceneRect.top;
+ _surface->create(_width, _height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
if (_type == MKTAG('R', 'B', '\0', '\0'))
putDibRB(palette);
@@ -825,46 +820,64 @@ void Bitmap::putDib(int x, int y, int32 *palette) {
putDibCB(palette);
}
-bool Bitmap::putDibRB(int32 *palette, int pX, int pY) {
- uint16 *curDestPtr;
+void Bitmap::putDib(int x, int y, int32 *palette, int alpha) {
+ debug(7, "Bitmap::putDib(%d, %d)", x, y);
+
+ int x1 = x - g_fp->_sceneRect.left;
+ int y1 = y - g_fp->_sceneRect.top;
+
+ if (!_width || !_height || !_surface)
+ return;
+
+ Common::Rect sub(0, 0, _width, _height);
+
+ if (x1 < 0) {
+ sub.left = -x1;
+ x1 = 0;
+ }
+
+ if (y1 < 0) {
+ sub.top = -y1;
+ y1 = 0;
+ }
+
+ if (x1 + sub.width() > 799)
+ sub.right -= x1 + sub.width() - 799;
+
+ if (y1 + sub.height() > 599)
+ sub.bottom -= y1 + sub.height() - 599;
+
+ if (sub.width() <= 0 || sub.height() <= 0)
+ return;
+
+ int alphac = TS_ARGB(0xff, alpha, 0xff, 0xff);
+
+ _surface->blit(g_fp->_backgroundSurface, x1, y1, _flipping, &sub, alphac);
+ g_fp->_system->copyRectToScreen(g_fp->_backgroundSurface.getBasePtr(x1, y1), g_fp->_backgroundSurface.pitch, x1, y1, sub.width(), sub.height());
+}
+
+bool Bitmap::putDibRB(int32 *palette) {
+ uint32 *curDestPtr;
int endy;
int x;
int start1;
int fillLen;
uint16 pixel;
- int endx;
int y;
uint16 *srcPtr2;
uint16 *srcPtr;
- if (!palette && pX == -1) {
+ if (!palette) {
debug(2, "Bitmap::putDibRB(): Both global and local palettes are empty");
return false;
}
debug(8, "Bitmap::putDibRB()");
- endx = _width + _x - 1;
- endy = _height + _y - 1;
-
- if (_x > 799 || endx < 0 || _y > 599 || endy < 0)
- return false;
+ endy = _height - 1;
- if (pX == -1) {
- if (endy > 599)
- endy = 599;
-
- if (endx > 799)
- endx = 799;
- }
-
- int startx = _x;
- if (startx < 0)
- startx = 0;
-
- int starty = _y;
- if (starty < 0)
- starty = 0;
+ int startx = 0;
+ int starty = 0;
y = endy;
@@ -908,14 +921,9 @@ bool Bitmap::putDibRB(int32 *palette, int pX, int pY) {
if (fillLen > 0 || start1 >= 0) {
if (x <= 799 + 1 || (fillLen += 799 - x + 1, fillLen > 0)) {
if (y <= endy) {
- if (pX == -1) {
- int bgcolor = palette[(pixel >> 8) & 0xff];
- curDestPtr = (uint16 *)g_fp->_backgroundSurface.getBasePtr(start1, y);
- colorFill(curDestPtr, fillLen, bgcolor);
- } else {
- if (y == pY && pX >= start1 && pX < start1 + fillLen)
- return true;
- }
+ int bgcolor = palette[(pixel >> 8) & 0xff];
+ curDestPtr = (uint32 *)_surface->getBasePtr(start1, y);
+ colorFill(curDestPtr, fillLen, bgcolor);
}
}
}
@@ -940,45 +948,26 @@ bool Bitmap::putDibRB(int32 *palette, int pX, int pY) {
}
if (y <= endy) {
- if (pX == -1) {
- curDestPtr = (uint16 *)g_fp->_backgroundSurface.getBasePtr(start1, y);
- paletteFill(curDestPtr, (byte *)srcPtr2, fillLen, (int32 *)palette);
- } else {
- if (y == pY && pX >= start1 && pX < start1 + fillLen)
- return true;
- }
+ curDestPtr = (uint32 *)_surface->getBasePtr(start1, y);
+ paletteFill(curDestPtr, (byte *)srcPtr2, fillLen, (int32 *)palette);
}
}
}
}
- if (pX == -1)
- g_fp->_system->copyRectToScreen(g_fp->_backgroundSurface.getBasePtr(startx, starty), g_fp->_backgroundSurface.pitch, startx, starty, endx + 1 - startx, endy + 1 - starty);
-
return false;
}
void Bitmap::putDibCB(int32 *palette) {
- uint16 *curDestPtr;
+ uint32 *curDestPtr;
int endx;
int endy;
int bpp;
uint pitch;
bool cb05_format;
- endx = _width + _x - 1;
- endy = _height + _y - 1;
-
- debug(8, "Bitmap::putDibCB(): %d, %d, %d, %d [%d, %d]", _x, _y, endx, endy, _width, _height);
-
- if (_x > 799 || endx < 0 || _y > 599 || endy < 0)
- return;
-
- if (endy > 599)
- endy = 599;
-
- if (endx > 799)
- endx = 799;
+ endx = _width - 1;
+ endy = _height - 1;
cb05_format = (_type == MKTAG('C', 'B', '\05', 'e'));
@@ -988,39 +977,28 @@ void Bitmap::putDibCB(int32 *palette) {
bpp = cb05_format ? 2 : 1;
pitch = (bpp * _width + 3) & 0xFFFFFFFC;
- byte *srcPtr = &_pixels[pitch * (endy - _y)];
+ byte *srcPtr = &_pixels[pitch * endy];
- if (endy - _y < _height)
+ if (endy < _height)
srcPtr = &_pixels[pitch * (_height - 1)];
- int starty = _y;
- if (starty < 0) {
- starty = 0;
- srcPtr = &_pixels[pitch * (_height + _y)];
- }
-
- int startx = _x;
- if (startx < 0) {
- srcPtr += bpp * -_x;
- startx = 0;
- }
+ int starty = 0;
+ int startx = 0;
if (_flags & 0x1000000) {
for (int y = starty; y <= endy; srcPtr -= pitch, y++) {
- curDestPtr = (uint16 *)g_fp->_backgroundSurface.getBasePtr(startx, y);
+ curDestPtr = (uint32 *)_surface->getBasePtr(startx, y);
copierKeyColor(curDestPtr, srcPtr, endx - startx + 1, _flags & 0xff, (int32 *)palette, cb05_format);
}
} else {
for (int y = starty; y <= endy; srcPtr -= pitch, y++) {
- curDestPtr = (uint16 *)g_fp->_backgroundSurface.getBasePtr(startx, y);
+ curDestPtr = (uint32 *)_surface->getBasePtr(startx, y);
copier(curDestPtr, srcPtr, endx - startx + 1, (int32 *)palette, cb05_format);
}
}
-
- g_fp->_system->copyRectToScreen(g_fp->_backgroundSurface.getBasePtr(startx, starty), g_fp->_backgroundSurface.pitch, startx, starty, endx + 1 - startx, endy + 1 - starty);
}
-void Bitmap::colorFill(uint16 *dest, int len, int32 color) {
+void Bitmap::colorFill(uint32 *dest, int len, int32 color) {
#if 0
if (blendMode) {
if (blendMode != 1)
@@ -1031,12 +1009,17 @@ void Bitmap::colorFill(uint16 *dest, int len, int32 color) {
colorFill = ptrfillColor16bit;
}
#endif
+ byte r, g, b;
+
+ g_fp->_origFormat->colorToRGB(color, r, g, b);
+
+ uint32 c = TS_ARGB(0xff, r, g, b);
for (int i = 0; i < len; i++)
- *dest++ = (int16)(color & 0xffff);
+ *dest++ = c;
}
-void Bitmap::paletteFill(uint16 *dest, byte *src, int len, int32 *palette) {
+void Bitmap::paletteFill(uint32 *dest, byte *src, int len, int32 *palette) {
#if 0
if (blendMode) {
if (blendMode != 1)
@@ -1048,11 +1031,16 @@ void Bitmap::paletteFill(uint16 *dest, byte *src, int len, int32 *palette) {
}
#endif
- for (int i = 0; i < len; i++)
- *dest++ = READ_LE_UINT32(&palette[*src++]) & 0xffff;
+ byte r, g, b;
+
+ for (int i = 0; i < len; i++) {
+ g_fp->_origFormat->colorToRGB(READ_LE_UINT32(&palette[*src++]) & 0xffff, r, g, b);
+
+ *dest++ = TS_ARGB(0xff, r, g, b);
+ }
}
-void Bitmap::copierKeyColor(uint16 *dest, byte *src, int len, int keyColor, int32 *palette, bool cb05_format) {
+void Bitmap::copierKeyColor(uint32 *dest, byte *src, int len, int keyColor, int32 *palette, bool cb05_format) {
#if 0
if (blendMode) {
if (blendMode == 1) {
@@ -1070,10 +1058,14 @@ void Bitmap::copierKeyColor(uint16 *dest, byte *src, int len, int keyColor, int3
}
#endif
+ byte r, g, b;
+
if (!cb05_format) {
for (int i = 0; i < len; i++) {
- if (*src != keyColor)
- *dest = READ_LE_UINT32(&palette[*src]) & 0xffff;
+ if (*src != keyColor) {
+ g_fp->_origFormat->colorToRGB(READ_LE_UINT32(&palette[*src]) & 0xffff, r, g, b);
+ *dest = TS_ARGB(0xff, r, g, b);
+ }
dest++;
src++;
@@ -1082,8 +1074,10 @@ void Bitmap::copierKeyColor(uint16 *dest, byte *src, int len, int keyColor, int3
int16 *src16 = (int16 *)src;
for (int i = 0; i < len; i++) {
- if (*src16 != 0)
- *dest = *src16;
+ if (*src16 != 0) {
+ g_fp->_origFormat->colorToRGB(READ_LE_UINT16(src16) & 0xffff, r, g, b);
+ *dest = TS_ARGB(0xff, r, g, b);
+ }
dest++;
src16++;
@@ -1091,7 +1085,7 @@ void Bitmap::copierKeyColor(uint16 *dest, byte *src, int len, int keyColor, int3
}
}
-void Bitmap::copier(uint16 *dest, byte *src, int len, int32 *palette, bool cb05_format) {
+void Bitmap::copier(uint32 *dest, byte *src, int len, int32 *palette, bool cb05_format) {
#if 0
if (blendMode) {
if (blendMode == 1) {
@@ -1109,100 +1103,49 @@ void Bitmap::copier(uint16 *dest, byte *src, int len, int32 *palette, bool cb05_
}
#endif
- if (!cb05_format) {
- for (int i = 0; i < len; i++)
- *dest++ = READ_LE_UINT32(&palette[*src++]) & 0xffff;
- } else {
- int16 *src16 = (int16 *)src;
-
- for (int i = 0; i < len; i++)
- *dest++ = *src16++;
- }
-}
-
-Bitmap *Bitmap::reverseImage() {
- switch (_type) {
- case MKTAG('R', 'B', '\0', '\0'):
- return reverseImageRB();
- case MKTAG('C', 'B', '\0', '\0'):
- return reverseImageCB();
- case MKTAG('C', 'B', '\05', 'e'):
- return reverseImageCB05();
- default:
- error("Bitmap::reverseImage: Unknown image type: %x", _type);
- }
-
- return 0;
-}
-
-Bitmap *Bitmap::reverseImageRB() {
- uint16 *newpixels = (uint16 *)calloc(((_dataSize + 15) & 0xfffffff0) + sizeof(Bitmap), 1);
- uint16 *srcPtr = (uint16 *)_pixels;
+ byte r, g, b;
- int idx = 0;
- while (srcPtr[idx] != 0x100) {
- uint16 *srcPtr2 = &srcPtr[idx];
-
- int prevIdx = idx;
- int i = idx;
+ if (!cb05_format) {
+ for (int i = 0; i < len; i++) {
+ g_fp->_origFormat->colorToRGB(READ_LE_UINT32(&palette[*src++]) & 0xffff, r, g, b);
- while (*srcPtr2) {
- ++srcPtr2;
- ++idx;
+ *dest++ = TS_ARGB(0xff, r, g, b);
}
+ } else {
+ int16 *src16 = (int16 *)src;
- int idx2 = idx;
-
- newpixels[idx] = srcPtr[idx];
-
- while (i != idx) {
- int fillLen = 2 - ((srcPtr[prevIdx] & 0xff) != 0 ? 1 : 0);
- idx2 -= fillLen;
- memcpy(&newpixels[idx2], &srcPtr[prevIdx], 2 * fillLen);
- prevIdx = fillLen + i;
- i += fillLen;
+ for (int i = 0; i < len; i++) {
+ g_fp->_origFormat->colorToRGB(READ_LE_UINT32(src16++) & 0xffff, r, g, b);
+ *dest++ = TS_ARGB(0xff, r, g, b);
}
- ++idx;
}
- newpixels[idx] = 256;
-
- int oldBmp = ((_dataSize + 15) >> 1) & 0x7FFFFFF8;
- memcpy(&newpixels[oldBmp], &srcPtr[oldBmp], sizeof(Bitmap));
-
- Bitmap *res = new Bitmap(this);
- res->_pixels = (byte *)newpixels;
-
- return res;
}
-Bitmap *Bitmap::reverseImageCB() {
- warning("STUB: Bitmap::reverseImageCB()");
-
- return this;
-}
-
-Bitmap *Bitmap::reverseImageCB05() {
- warning("STUB: Bitmap::reverseImageCB05()");
+Bitmap *Bitmap::reverseImage(bool flip) {
+ if (flip)
+ _flipping = Graphics::FLIP_H;
+ else
+ _flipping = Graphics::FLIP_NONE;
return this;
}
Bitmap *Bitmap::flipVertical() {
- warning("STUB: Bitmap::flipVertical()");
+ _flipping = Graphics::FLIP_V;
return this;
}
-void Bitmap::drawShaded(int type, int x, int y, byte *palette) {
+void Bitmap::drawShaded(int type, int x, int y, byte *palette, int alpha) {
warning("STUB: Bitmap::drawShaded(%d, %d, %d)", type, x, y);
- putDib(x, y, (int32 *)palette);
+ putDib(x, y, (int32 *)palette, alpha);
}
- void Bitmap::drawRotated(int x, int y, int angle, byte *palette) {
+void Bitmap::drawRotated(int x, int y, int angle, byte *palette, int alpha) {
warning("STUB: Bitmap::drawShaded(%d, %d, %d)", x, y, angle);
- putDib(x, y, (int32 *)palette);
+ putDib(x, y, (int32 *)palette, alpha);
}
bool BigPicture::load(MfcArchive &file) {
@@ -1232,7 +1175,7 @@ void BigPicture::draw(int x, int y, int style, int angle) {
//vrtSetAlphaBlendMode(g_vrtDrawHandle, 1, v9);
}
- _bitmap->putDib(nx, ny, 0);
+ _bitmap->putDib(nx, ny, 0, 0xff);
if (_alpha < 0xFF) {
//vrtSetAlphaBlendMode(g_vrtDrawHandle, 0, 255);
@@ -1313,4 +1256,23 @@ void FullpipeEngine::drawAlphaRectangle(int x1, int y1, int x2, int y2, int alph
warning("STUB: FullpipeEngine::drawAlphaRectangle()");
}
+void FullpipeEngine::sceneFade(Scene *sc, bool direction) {
+ warning("STUB: FullpipeEngine::sceneFade()");
+
+#if 0
+ for (int dim = 0; dim < 255; dim += 20) {
+ v5 = GetTickCount();
+ vrtSetAlphaBlendMode(*(_DWORD *)virt, 0, 255);
+ sc->draw();
+ drawAlphaRectangle(0, 0, 800, 600, direction ? 255 - dim : dim);
+ vrtFlush(*(_DWORD *)virt);
+ v7 = GetTickCount();
+ if ( v7 - v5 < 42 )
+ Sleep(v5 - v7 + 42);
+ }
+ vrtSetAlphaBlendMode(*(_DWORD *)virt, 0, 255);
+#endif
+
+}
+
} // End of namespace Fullpipe
diff --git a/engines/fullpipe/gfx.h b/engines/fullpipe/gfx.h
index b3e22b610b..d94dd40452 100644
--- a/engines/fullpipe/gfx.h
+++ b/engines/fullpipe/gfx.h
@@ -38,32 +38,31 @@ struct Bitmap {
int _type;
int _dataSize;
int _flags;
+ Graphics::TransparentSurface *_surface;
+ int _flipping;
Bitmap();
Bitmap(Bitmap *src);
~Bitmap();
void load(Common::ReadStream *s);
- void putDib(int x, int y, int32 *palette);
- bool putDibRB(int32 *palette, int x = -1, int y = -1);
+ void decode(int32 *palette);
+ void putDib(int x, int y, int32 *palette, int alpha);
+ bool putDibRB(int32 *palette);
void putDibCB(int32 *palette);
- void colorFill(uint16 *dest, int len, int32 color);
- void paletteFill(uint16 *dest, byte *src, int len, int32 *palette);
- void copierKeyColor(uint16 *dest, byte *src, int len, int keyColor, int32 *palette, bool cb05_format);
- void copier(uint16 *dest, byte *src, int len, int32 *palette, bool cb05_format);
+ void colorFill(uint32 *dest, int len, int32 color);
+ void paletteFill(uint32 *dest, byte *src, int len, int32 *palette);
+ void copierKeyColor(uint32 *dest, byte *src, int len, int keyColor, int32 *palette, bool cb05_format);
+ void copier(uint32 *dest, byte *src, int len, int32 *palette, bool cb05_format);
- Bitmap *reverseImage();
- Bitmap *reverseImageRB();
- Bitmap *reverseImageCB();
- Bitmap *reverseImageCB05();
+ Bitmap *reverseImage(bool flip = true);
Bitmap *flipVertical();
- void drawShaded(int type, int x, int y, byte *palette);
- void drawRotated(int x, int y, int angle, byte *palette);
+ void drawShaded(int type, int x, int y, byte *palette, int alpha);
+ void drawRotated(int x, int y, int angle, byte *palette, int alpha);
bool isPixelHitAtPos(int x, int y);
- bool isPixelAtHitPosRB(int x, int y);
};
class Picture : public MemoryObject {
@@ -92,7 +91,7 @@ class Picture : public MemoryObject {
virtual bool load(MfcArchive &file);
void setAOIDs();
- void init();
+ virtual void init();
void getDibInfo();
Bitmap *getPixelData();
virtual void draw(int x, int y, int style, int angle);
@@ -141,7 +140,8 @@ class GameObject : public CObject {
virtual bool load(MfcArchive &file);
void setOXY(int x, int y);
- void renumPictures(PtrList *lst);
+ void renumPictures(Common::Array<StaticANIObject *> *lst);
+ void renumPictures(Common::Array<PictureObject *> *lst);
void setFlags(int16 flags) { _flags = flags; }
void clearFlags() { _flags = 0; }
const char *getName() { return _objectName; }
@@ -153,7 +153,7 @@ class GameObject : public CObject {
class PictureObject : public GameObject {
public:
Picture *_picture;
- PtrList *_pictureObject2List;
+ Common::Array<GameObject *> *_pictureObject2List;
int _ox2;
int _oy2;
@@ -178,7 +178,7 @@ class PictureObject : public GameObject {
class Background : public CObject {
public:
- PtrList _picObjList;
+ Common::Array<PictureObject *> _picObjList;
char *_bgname;
int _x;
diff --git a/engines/fullpipe/input.cpp b/engines/fullpipe/input.cpp
index 0678d15368..7c97461a24 100644
--- a/engines/fullpipe/input.cpp
+++ b/engines/fullpipe/input.cpp
@@ -275,6 +275,8 @@ void FullpipeEngine::updateCursorCommon() {
}
void FullpipeEngine::initArcadeKeys(const char *varname) {
+ _arcadeKeys.clear();
+
GameVar *var = getGameLoaderGameVar()->getSubVarByName(varname)->getSubVarByName("KEYPOS");
if (!var)
@@ -294,6 +296,37 @@ void FullpipeEngine::initArcadeKeys(const char *varname) {
}
}
+void FullpipeEngine::processArcade(ExCommand *cmd) {
+ if (!g_fp->_aniMan2)
+ return;
+
+ int idx;
+
+ if (cmd->_sceneClickX <= g_fp->_aniMan2->_ox) {
+ for (idx = (int)_arcadeKeys.size() - 1; idx >= 0; idx--) {
+ if (_arcadeKeys[idx]->x < g_fp->_aniMan2->_ox)
+ break;
+ }
+
+ if (idx < 0)
+ return;
+ } else {
+ for (idx = 0; idx < (int)_arcadeKeys.size(); idx++) {
+ if (_arcadeKeys[idx]->x > g_fp->_aniMan2->_ox)
+ break;
+ }
+
+ if (idx >= (int)_arcadeKeys.size())
+ return;
+ }
+
+ cmd->_sceneClickX = _arcadeKeys[idx]->x;
+ cmd->_sceneClickY = _arcadeKeys[idx]->y;
+
+ cmd->_x = cmd->_sceneClickX - g_fp->_sceneRect.left;
+ cmd->_y = cmd->_sceneClickY - g_fp->_sceneRect.top;
+}
+
void FullpipeEngine::setArcadeOverlay(int picId) {
Common::Point point;
Common::Point point2;
diff --git a/engines/fullpipe/messagehandlers.cpp b/engines/fullpipe/messagehandlers.cpp
index 17af2bf4fd..d4f79d1dd8 100644
--- a/engines/fullpipe/messagehandlers.cpp
+++ b/engines/fullpipe/messagehandlers.cpp
@@ -34,11 +34,69 @@
namespace Fullpipe {
void global_messageHandler_KickStucco() {
- warning("STUB: global_messageHandler_KickStucco()");
+ Movement *mov = g_fp->_aniMan->getMovementById(MV_MAN_HMRKICK);
+ int end = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+ bool flip = false;
+
+ for (int i = 0; i < end; i++) {
+ ExCommand *ex = mov->getDynamicPhaseByIndex(i)->_exCommand;
+
+ if (ex)
+ if (ex->_messageKind == 35)
+ if (ex->_messageNum == SND_CMN_015) {
+ if (flip) {
+ ex->_messageNum = SND_CMN_055;
+ } else {
+ ex->_messageNum = SND_CMN_054;
+ flip = true;
+ }
+ }
+ }
+
+ mov = g_fp->_aniMan->getMovementById(MV_MAN_HMRKICK_COINLESS);
+ end = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+ flip = false;
+
+ for (int i = 0; i < end; i++) {
+ ExCommand *ex = mov->getDynamicPhaseByIndex(i)->_exCommand;
+
+ if (ex)
+ if (ex->_messageKind == 35)
+ if (ex->_messageNum == SND_CMN_015) {
+ if (flip) {
+ ex->_messageNum = SND_CMN_055;
+ } else {
+ ex->_messageNum = SND_CMN_054;
+ flip = true;
+ }
+ }
+ }
}
void global_messageHandler_KickMetal() {
- warning("STUB: global_messageHandler_KickMetal()");
+ Movement *mov = g_fp->_aniMan->getMovementById(MV_MAN_HMRKICK);
+ int end = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+
+ for (int i = 0; i < end; i++) {
+ ExCommand *ex = mov->getDynamicPhaseByIndex(i)->_exCommand;
+
+ if (ex)
+ if (ex->_messageKind == 35)
+ if (ex->_messageNum == SND_CMN_054 || ex->_messageNum == SND_CMN_055)
+ ex->_messageNum = SND_CMN_015;
+ }
+
+ mov = g_fp->_aniMan->getMovementById(MV_MAN_HMRKICK_COINLESS);
+ end = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+
+ for (int i = 0; i < end; i++) {
+ ExCommand *ex = mov->getDynamicPhaseByIndex(i)->_exCommand;
+
+ if (ex)
+ if (ex->_messageKind == 35)
+ if (ex->_messageNum == SND_CMN_054 || ex->_messageNum == SND_CMN_055)
+ ex->_messageNum = SND_CMN_015;
+ }
}
int global_messageHandler1(ExCommand *cmd) {
@@ -334,12 +392,10 @@ int global_messageHandler3(ExCommand *cmd) {
}
return result;
case 29:
- if (!g_fp->_currentScene)
- return result;
-
- if (g_fp->_gameLoader->_interactionController->_flag24) {
+ if (g_fp->_gameLoader->_interactionController->_flag24 && g_fp->_currentScene) {
ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY);
ani2 = g_fp->_currentScene->getStaticANIObject1ById(g_fp->_gameLoader->_field_FA, -1);
+
if (ani) {
if (g_fp->_msgObjectId2 == ani->_id && g_fp->_msgId == ani->_okeyCode) {
cmd->_messageKind = 0;
diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp
index 9c8f5ac4e2..a7337b98ed 100644
--- a/engines/fullpipe/messages.cpp
+++ b/engines/fullpipe/messages.cpp
@@ -26,6 +26,7 @@
#include "fullpipe/messages.h"
#include "fullpipe/modal.h"
#include "fullpipe/statics.h"
+#include "fullpipe/gameloader.h"
namespace Fullpipe {
@@ -394,8 +395,18 @@ void MessageQueue::update() {
}
void MessageQueue::messageQueueCallback1(int par) {
- // Autosave
- debug(3, "STUB: MessageQueue::messageQueueCallback1()");
+ if (g_fp->_isSaveAllowed && par == 16) {
+ if (g_fp->_globalMessageQueueList->size() && (*g_fp->_globalMessageQueueList)[0] != 0) {
+ for (uint i = 0; i < g_fp->_globalMessageQueueList->size(); i++) {
+ if ((*g_fp->_globalMessageQueueList)[i]->_flags & 1)
+ if ((*g_fp->_globalMessageQueueList)[i] != this && !(*g_fp->_globalMessageQueueList)[i]->_isFinished)
+ return;
+ }
+ }
+
+ if (g_fp->_currentScene)
+ g_fp->_gameLoader->writeSavegame(g_fp->_currentScene, "savetmp.sav");
+ }
}
void MessageQueue::addExCommand(ExCommand *ex) {
@@ -699,6 +710,10 @@ void GlobalMessageQueueList::addMessageQueue(MessageQueue *msg) {
push_back(msg);
}
+void clearGlobalMessageQueueList() {
+ g_fp->_globalMessageQueueList->clear();
+}
+
void clearGlobalMessageQueueList1() {
clearMessages();
diff --git a/engines/fullpipe/messages.h b/engines/fullpipe/messages.h
index da579d58c0..e6f7f05150 100644
--- a/engines/fullpipe/messages.h
+++ b/engines/fullpipe/messages.h
@@ -193,6 +193,7 @@ void clearMessageHandlers();
void processMessages();
void updateGlobalMessageQueue(int id, int objid);
void clearMessages();
+void clearGlobalMessageQueueList();
void clearGlobalMessageQueueList1();
bool chainQueue(int queueId, int flags);
diff --git a/engines/fullpipe/mgm.cpp b/engines/fullpipe/mgm.cpp
new file mode 100644
index 0000000000..aacfd5452a
--- /dev/null
+++ b/engines/fullpipe/mgm.cpp
@@ -0,0 +1,719 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "fullpipe/fullpipe.h"
+
+#include "fullpipe/utils.h"
+#include "fullpipe/statics.h"
+#include "fullpipe/motion.h"
+#include "fullpipe/messages.h"
+
+namespace Fullpipe {
+
+void MGM::clear() {
+ _items.clear();
+}
+
+MessageQueue *MGM::genMQ(StaticANIObject *ani, int staticsIndex, int staticsId, int *resStatId, Common::Point **pointArr) {
+ int idx = getItemIndexById(ani->_id);
+
+ if (idx == -1)
+ return 0;
+
+ int stid = staticsId;
+
+ if (!staticsId) {
+ if (ani->_movement) {
+ stid = ani->_movement->_staticsObj2->_staticsId;
+ } else {
+ if (!ani->_statics)
+ return 0;
+
+ stid = ani->_statics->_staticsId;
+ }
+ }
+
+ if (stid == staticsIndex)
+ return new MessageQueue(g_fp->_globalMessageQueueList->compact());
+
+ int startidx = getStaticsIndexById(idx, stid);
+ int endidx = getStaticsIndexById(idx, staticsIndex);
+ int subidx = startidx + endidx * _items[idx]->statics.size();
+
+ if (!_items[idx]->subItems[subidx]->movement) {
+ clearMovements2(idx);
+ recalcOffsets(idx, startidx, endidx, 0, 1);
+ }
+
+ if (!_items[idx]->subItems[subidx]->movement)
+ return 0;
+
+ MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
+ Common::Point point;
+ ExCommand *ex;
+
+ int i = 0;
+ do {
+ subidx = startidx + endidx * _items[idx]->statics.size();
+
+ _items[idx]->subItems[subidx]->movement->calcSomeXY(point, 0, -1);
+
+ if (pointArr) {
+ int sz;
+
+ if (_items[idx]->subItems[subidx]->movement->_currMovement)
+ sz = _items[idx]->subItems[subidx]->movement->_currMovement->_dynamicPhases.size();
+ else
+ sz = _items[idx]->subItems[subidx]->movement->_dynamicPhases.size();
+
+ ex = new ExCommand2(20, ani->_id, &pointArr[i], sz);
+
+ ex->_messageNum = _items[idx]->subItems[subidx]->movement->_id;
+ } else {
+ ex = new ExCommand(ani->_id, 1, _items[idx]->subItems[subidx]->movement->_id, 0, 0, 0, 1, 0, 0, 0);
+ }
+
+ ex->_keyCode = ani->_okeyCode;
+ ex->_field_3C = 1;
+ ex->_field_24 = 1;
+
+ mq->addExCommandToEnd(ex);
+
+ if (resStatId)
+ *resStatId = _items[idx]->subItems[subidx]->movement->_id;
+
+ startidx = _items[idx]->subItems[subidx]->staticsIndex;
+
+ uint step;
+
+ if (_items[idx]->subItems[subidx]->movement->_currMovement)
+ step = _items[idx]->subItems[subidx]->movement->_currMovement->_dynamicPhases.size();
+ else
+ step = _items[idx]->subItems[subidx]->movement->_dynamicPhases.size();
+
+ i += step;
+ } while (startidx != endidx);
+
+ return mq;
+}
+
+MGMItem::MGMItem() {
+ objId = 0;
+}
+
+MGMSubItem::MGMSubItem() {
+ movement = 0;
+ staticsIndex = 0;
+ field_8 = 0;
+ field_C = 0;
+ x = 0;
+ y = 0;
+}
+
+void MGM::addItem(int objId) {
+ if (getItemIndexById(objId) == -1) {
+ MGMItem *item = new MGMItem();
+
+ item->objId = objId;
+ _items.push_back(item);
+ }
+ rebuildTables(objId);
+}
+
+void MGM::rebuildTables(int objId) {
+ int idx = getItemIndexById(objId);
+
+ if (idx == -1)
+ return;
+
+ _items[idx]->subItems.clear();
+ _items[idx]->statics.clear();
+ _items[idx]->movements1.clear();
+ _items[idx]->movements2.clear();
+
+ StaticANIObject *obj = g_fp->_currentScene->getStaticANIObject1ById(objId, -1);
+
+ if (!obj)
+ return;
+
+ for (uint i = 0; i < obj->_staticsList.size(); i++)
+ _items[idx]->statics.push_back((Statics *)obj->_staticsList[i]);
+
+ for (uint i = 0; i < obj->_movements.size(); i++)
+ _items[idx]->movements1.push_back((Movement *)obj->_movements[i]);
+
+ _items[idx]->subItems.clear();
+}
+
+int MGM::getItemIndexById(int objId) {
+ for (uint i = 0; i < _items.size(); i++)
+ if (_items[i]->objId == objId)
+ return i;
+
+ return -1;
+}
+
+MessageQueue *MGM::genMovement(MGMInfo *mgminfo) {
+ if (!mgminfo->ani)
+ return 0;
+
+ Movement *mov = mgminfo->ani->_movement;
+
+ if (!mov && !mgminfo->ani->_statics)
+ return 0;
+
+ if (!(mgminfo->flags & 1)) {
+ if (mov)
+ mgminfo->staticsId1 = mov->_staticsObj2->_staticsId;
+ else
+ mgminfo->staticsId1 = mgminfo->ani->_statics->_staticsId;
+ }
+
+ Common::Point point;
+
+ if (!(mgminfo->flags & 0x10) || !(mgminfo->flags & 0x20)) {
+ int nx = mgminfo->ani->_ox;
+ int ny = mgminfo->ani->_oy;
+
+ if (mgminfo->ani->_movement) {
+ mgminfo->ani->calcNextStep(&point);
+
+ nx += point.x;
+ ny += point.y;
+ }
+
+ if (!(mgminfo->flags & 0x10))
+ mgminfo->x2 = nx;
+
+ if (!(mgminfo->flags & 0x20))
+ mgminfo->y2 = ny;
+ }
+
+ mov = mgminfo->ani->getMovementById(mgminfo->movementId);
+
+ if (!mov)
+ return 0;
+
+ int itemIdx = getItemIndexById(mgminfo->ani->_id);
+ int subIdx = getStaticsIndexById(itemIdx, mgminfo->staticsId1);
+ int st2idx = getStaticsIndexById(itemIdx, mov->_staticsObj1->_staticsId);
+ int st1idx = getStaticsIndexById(itemIdx, mov->_staticsObj2->_staticsId);
+ int subOffset = getStaticsIndexById(itemIdx, mgminfo->staticsId2);
+
+ clearMovements2(itemIdx);
+ recalcOffsets(itemIdx, subIdx, st2idx, 0, 1);
+ clearMovements2(itemIdx);
+ recalcOffsets(itemIdx, st1idx, subOffset, 0, 1);
+
+ MGMSubItem *sub1 = _items[itemIdx]->subItems[subIdx + st2idx * _items[itemIdx]->statics.size()];
+ MGMSubItem *sub2 = _items[itemIdx]->subItems[st1idx + subOffset * _items[itemIdx]->statics.size()];
+
+ if (subIdx != st2idx && !sub1->movement)
+ return 0;
+
+ if (st1idx != subOffset && !sub2->movement)
+ return 0;
+
+ int n1x = mgminfo->x1 - mgminfo->x2 - sub1->x - sub2->x;
+ int n1y = mgminfo->y1 - mgminfo->y2 - sub1->y - sub2->y;
+
+ Common::Point point1;
+
+ mov->calcSomeXY(point1, 0, -1);
+
+ int n2x = point1.x;
+ int n2y = point1.y;
+ int mult;
+ int len = -1;
+
+ if (mgminfo->flags & 0x40) {
+ mult = mgminfo->field_10;
+ len = -1;
+ n2x *= mult;
+ n2y *= mult;
+ } else {
+ calcLength(&point, mov, n1x, n1y, &mult, &len, 1);
+ n2x = point.x;
+ n2y = point.y;
+ }
+
+ if (!(mgminfo->flags & 2)) {
+ len = -1;
+ n2x = mult * point1.x;
+ n1x = mult * point1.x;
+ mgminfo->x1 = mgminfo->x2 + mult * point1.x + sub1->x + sub2->x;
+ }
+
+ if (!(mgminfo->flags & 4)) {
+ n2y = mult * point1.y;
+ n1y = mult * point1.y;
+ len = -1;
+ mgminfo->y1 = mgminfo->y2 + mult * point1.y + sub1->y + sub2->y;
+ }
+
+ int px = 0;
+ int py = 0;
+
+ if (sub1->movement) {
+ px = countPhases(itemIdx, subIdx, st2idx, 1);
+ py = countPhases(itemIdx, subIdx, st2idx, 2);
+ }
+
+ if (mult > 1) {
+ px += (mult - 1) * mov->countPhasesWithFlag(-1, 1);
+ py += (mult - 1) * mov->countPhasesWithFlag(-1, 2);
+ }
+
+ if (mult > 0) {
+ px += mov->countPhasesWithFlag(len, 1);
+ py += mov->countPhasesWithFlag(len, 2);
+ }
+
+ if (sub2->movement) {
+ px += countPhases(itemIdx, st1idx, subOffset, 1);
+ py += countPhases(itemIdx, st1idx, subOffset, 2);
+ }
+
+ int dx1 = n1x - n2x;
+ int dy1 = n1y - n2y;
+ int x1, y1;
+
+ if (px) {
+ x1 = (int)((double)dx1 / (double)px);
+ } else {
+ x1 = 0;
+ }
+
+ if (py) {
+ y1 = (int)((double)dy1 / (double)py);
+ } else {
+ y1 = 0;
+ }
+
+ Common::Point x2, y2;
+
+ y2.x = dx1 - px * x1;
+ y2.y = dy1 - py * y1;
+
+ if (n1x - n2x == px * x1)
+ x2.x = 0;
+ else
+ x2.x = (dx1 - px * x1) / abs(dx1 - px * x1);
+
+ if (dy1 == py * y1)
+ x2.y = 0;
+ else
+ x2.y = (dy1 - py * y1) / abs(dy1 - py * y1);
+
+ MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
+ ExCommand2 *ex2;
+
+ for (int i = subIdx; i != st2idx;) {
+ MGMSubItem *s = _items[itemIdx]->subItems[i + subOffset * _items[itemIdx]->statics.size()];
+
+ ex2 = buildExCommand2(s->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+
+ i = s->staticsIndex;
+ }
+
+ for (int i = 0; i < mult; ++i) {
+ int plen;
+
+ if (i == mult - 1)
+ plen = len;
+ else
+ plen = -1;
+
+ ex2 = buildExCommand2(mov, mgminfo->ani->_id, x1, y1, &x2, &y2, plen);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+ }
+
+ for (int j = st1idx; j != subOffset;) {
+ MGMSubItem *s = _items[itemIdx]->subItems[j + subOffset * _items[itemIdx]->statics.size()];
+
+ ex2 = buildExCommand2(s->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+
+ j = s->staticsIndex;
+ }
+
+ ExCommand *ex = new ExCommand(mgminfo->ani->_id, 5, -1, mgminfo->x1, mgminfo->y1, 0, 1, 0, 0, 0);
+
+ ex->_field_14 = mgminfo->field_1C;
+ ex->_keyCode = mgminfo->ani->_okeyCode;
+ ex->_field_24 = 0;
+ ex->_excFlags |= 3;
+
+ mq->addExCommandToEnd(ex);
+
+ return mq;
+}
+
+int MGM::countPhases(int idx, int subIdx, int endIdx, int flag) {
+ int res = 0;
+
+ if (endIdx < 0)
+ return 0;
+
+ while (subIdx != endIdx) {
+ if (subIdx < 0)
+ break;
+
+ res += _items[idx]->subItems[subIdx + endIdx * _items[idx]->statics.size()]->movement->countPhasesWithFlag(-1, flag);
+
+ subIdx = _items[idx]->subItems[subIdx + 6 * endIdx * _items[idx]->statics.size()]->staticsIndex;
+ }
+
+ return res;
+}
+void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) {
+ if (getItemIndexById(ani->_id) == -1)
+ return;
+
+ if (ani->_movement) {
+ ani->queueMessageQueue(0);
+ ani->_movement->gotoLastFrame();
+ ani->_statics = ani->_movement->_staticsObj2;
+
+ int x = ani->_movement->_ox;
+ int y = ani->_movement->_oy;
+
+ ani->_movement = 0;
+
+ ani->setOXY(x, y);
+ }
+
+ if (ani->_statics) {
+ Common::Point point;
+
+ getPoint(&point, ani->_id, ani->_statics->_staticsId, staticsId);
+
+ ani->setOXY(ani->_ox + point.x, ani->_oy + point.y);
+
+ ani->_statics = ani->getStaticsById(staticsId);
+ }
+}
+
+Common::Point *MGM::getPoint(Common::Point *point, int objectId, int staticsId1, int staticsId2) {
+ int idx = getItemIndexById(objectId);
+
+ if (idx == -1) {
+ point->x = -1;
+ point->y = -1;
+ } else {
+ int st1idx = getStaticsIndexById(idx, staticsId1);
+ int st2idx = getStaticsIndexById(idx, staticsId2);
+
+ if (st1idx == st2idx) {
+ point->x = 0;
+ point->y = 0;
+ } else {
+ int subidx = st1idx + st2idx * _items[idx]->statics.size();
+
+ if (!_items[idx]->subItems[subidx]->movement) {
+ clearMovements2(idx);
+ recalcOffsets(idx, st1idx, st2idx, false, true);
+
+ if (!_items[idx]->subItems[subidx]->movement) {
+ clearMovements2(idx);
+ recalcOffsets(idx, st1idx, st2idx, true, false);
+ }
+ }
+
+ MGMSubItem *sub = _items[idx]->subItems[subidx];
+
+ if (sub->movement) {
+ point->x = sub->x;
+ point->y = sub->y;
+ } else {
+ point->x = 0;
+ point->y = 0;
+ }
+ }
+ }
+
+ return point;
+}
+
+int MGM::getStaticsIndexById(int idx, int16 id) {
+ if (!_items[idx]->statics.size())
+ return -1;
+
+ for (uint i = 0; i < _items[idx]->statics.size(); i++) {
+ if (_items[idx]->statics[i]->_staticsId == id)
+ return i;
+ }
+
+ return 0;
+}
+
+int MGM::getStaticsIndex(int idx, Statics *st) {
+ if (!_items[idx]->statics.size())
+ return -1;
+
+ for (uint i = 0; i < _items[idx]->statics.size(); i++) {
+ if (_items[idx]->statics[i] == st)
+ return i;
+ }
+
+ return 0;
+}
+
+void MGM::clearMovements2(int idx) {
+ _items[idx]->movements2.clear();
+}
+
+int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) {
+ MGMItem *item = _items[idx];
+ int subIdx = st1idx + st2idx * item->statics.size();
+
+ if (st1idx == st2idx) {
+ memset(&item->subItems[subIdx], 0, sizeof(item->subItems[subIdx]));
+ return 0;
+ }
+
+ if (item->subItems[subIdx])
+ return item->subItems[subIdx]->field_8;
+
+ Common::Point point;
+
+ for (uint i = 0; i < item->movements1.size(); i++) {
+ Movement *mov = item->movements1[i];
+
+ if (mov->_staticsObj1 == item->statics[st1idx]) {
+ if (!item->movements2[i] && (!flop || mov->_field_50)) {
+ item->movements2[i] = 1;
+
+ int stidx = getStaticsIndex(idx, item->movements1[i]->_staticsObj2);
+ int recalc = recalcOffsets(idx, stidx, st2idx, flip, flop);
+ int sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+ int newsz = sz + item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->field_C;
+
+ if (recalc >= 0) {
+ if (!item->subItems[subIdx]->movement || item->subItems[subIdx]->field_8 > recalc + 1 ||
+ (item->subItems[subIdx]->field_8 == recalc + 1 && item->subItems[subIdx]->field_C > newsz)) {
+ item->subItems[subIdx]->movement = mov;
+ item->subItems[subIdx]->staticsIndex = stidx;
+ item->subItems[subIdx]->field_8 = recalc + 1;
+ item->subItems[subIdx]->field_C = newsz;
+
+ mov->calcSomeXY(point, 0, -1);
+
+ item->subItems[subIdx]->x = item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->x + point.x;
+ item->subItems[subIdx]->y = item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->y + point.y;
+ }
+ }
+ }
+ } else if (flip) {
+ if (mov->_staticsObj2 == item->statics[st1idx]) {
+ if (!item->movements2[i] && (!flop || mov->_field_50)) {
+ item->movements2[i] = 1;
+
+ int stidx = getStaticsIndex(idx, mov->_staticsObj1);
+ int recalc = recalcOffsets(idx, stidx, st2idx, flip, flop);
+
+ if (recalc >= 0) {
+ if (!item->subItems[subIdx]->movement || item->subItems[subIdx]->field_8 > recalc + 1) {
+ item->subItems[subIdx]->movement = mov;
+ item->subItems[subIdx]->staticsIndex = stidx;
+ item->subItems[subIdx]->field_8 = recalc + 1;
+
+ int sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+
+ item->subItems[subIdx]->field_C = sz + item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->field_C;
+
+ mov->calcSomeXY(point, 0, -1);
+
+ item->subItems[subIdx]->x = item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->x - point.x;
+ item->subItems[subIdx]->y = item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->y - point.y;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (item->subItems[subIdx]->movement)
+ return item->subItems[subIdx]->field_8;
+
+ return -1;
+}
+
+int MGM::refreshOffsets(int objectId, int idx1, int idx2) {
+ int idx = getItemIndexById(objectId);
+
+ if (idx != -1) {
+ int from = getStaticsIndexById(idx, idx1);
+ int to = getStaticsIndexById(idx, idx2);
+
+ MGMSubItem *sub = _items[idx]->subItems[from + to * _items[idx]->statics.size()];
+
+ if (sub->movement) {
+ idx = sub->field_8;
+ } else {
+ clearMovements2(idx);
+ idx = recalcOffsets(idx, from, to, 0, 1);
+ }
+ }
+
+ return idx;
+}
+
+Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *mult, int *len, int flag) {
+ Common::Point point;
+
+ mov->calcSomeXY(point, 0, -1);
+ int p1x = point.x;
+ int p1y = point.y;
+
+ int newmult = 0;
+ int oldlen = *len;
+
+ if (abs(p1y) > abs(p1x)) {
+ if (mov->calcSomeXY(point, 0, -1)->y)
+ newmult = (int)((double)y / mov->calcSomeXY(point, 0, -1)->y);
+ } else if (mov->calcSomeXY(point, 0, -1)->x) {
+ newmult = (int)((double)x / mov->calcSomeXY(point, 0, -1)->x);
+ }
+
+ if (newmult < 0)
+ newmult = 0;
+
+ *mult = newmult;
+
+ int phase = 1;
+ int sz;
+
+ if (flag) {
+ if (abs(p1y) > abs(p1x)) {
+ while (abs(p1y * newmult + mov->calcSomeXY(point, 0, phase)->y) < abs(y)) {
+ sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+
+ if (phase > sz)
+ break;
+
+ phase++;
+ }
+ } else {
+ while (abs(p1x * newmult + mov->calcSomeXY(point, 0, phase)->x) < abs(x)) {
+ sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+
+ if (phase >= sz)
+ break;
+
+ phase++;
+ }
+ }
+
+ *len = phase - 1;
+ } else {
+ *len = -1;
+ }
+
+ int p2x = 0;
+ int p2y = 0;
+
+ if (!oldlen)
+ oldlen = -1;
+
+ if (oldlen > 0) {
+ ++*mult;
+
+ mov->calcSomeXY(point, 0, oldlen);
+ p2x = point.x;
+ p2y = point.y;
+
+ if (abs(p1y) > abs(p1x))
+ p2x = p1x;
+ else
+ p2y = p1y;
+ }
+
+ pRes->x = p2x + p1x * newmult;
+ pRes->y = p2y + p1y * newmult;
+
+ return pRes;
+}
+
+ExCommand2 *MGM::buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len) {
+ uint cnt;
+
+ if (mov->_currMovement)
+ cnt = mov->_currMovement->_dynamicPhases.size();
+ else
+ cnt = mov->_dynamicPhases.size();
+
+ if (len > 0 && cnt > (uint)len)
+ cnt = len;
+
+ Common::Point **points = (Common::Point **)malloc(sizeof(Common::Point *) * cnt);
+
+ for (uint i = 0; i < cnt; i++) {
+ int flags = mov->getDynamicPhaseByIndex(i)->getDynFlags();
+
+ points[i] = new Common::Point;
+
+ if (flags & 1) {
+ points[i]->x = x1 + x2->x;
+
+ y2->x -= x2->x;
+
+ if (!y2->x)
+ x2->x = 0;
+ }
+
+ if (flags & 2) {
+ points[i]->y = y1 + x2->y;
+
+ y2->y -= x2->y;
+
+ if (!y2->y)
+ x2->y = 0;
+ }
+ }
+
+ ExCommand2 *ex = new ExCommand2(20, objId, points, cnt);
+ ex->_excFlags = 2;
+ ex->_messageNum = mov->_id;
+ ex->_field_14 = len;
+ ex->_field_24 = 1;
+ ex->_keyCode = -1;
+
+ for (uint i = 0; i < cnt; i++)
+ delete points[i];
+
+ free(points);
+
+ return ex;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/mgm.h b/engines/fullpipe/mgm.h
new file mode 100644
index 0000000000..13195891da
--- /dev/null
+++ b/engines/fullpipe/mgm.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FULLPIPE_MGM_H
+#define FULLPIPE_MGM_H
+
+namespace Fullpipe {
+
+class ExCommand2;
+class Movement;
+class Statics;
+
+struct MGMSubItem {
+ Movement *movement;
+ int staticsIndex;
+ int field_8;
+ int field_C;
+ int x;
+ int y;
+
+ MGMSubItem();
+};
+
+struct MGMItem {
+ int16 objId;
+ Common::Array<MGMSubItem *> subItems;
+ Common::Array<Statics *> statics;
+ Common::Array<Movement *> movements1;
+ Common::Array<int> movements2;
+
+ MGMItem();
+};
+
+struct MGMInfo {
+ StaticANIObject *ani;
+ int staticsId1;
+ int staticsId2;
+ int movementId;
+ int field_10;
+ int x1;
+ int y1;
+ int field_1C;
+ int x2;
+ int y2;
+ int flags;
+
+ MGMInfo() { memset(this, 0, sizeof(MGMInfo)); }
+};
+
+class MGM : public CObject {
+public:
+ Common::Array<MGMItem *> _items;
+
+public:
+ void clear();
+ void addItem(int objId);
+ void rebuildTables(int objId);
+ int getItemIndexById(int objId);
+
+ MessageQueue *genMovement(MGMInfo *mgminfo);
+ void updateAnimStatics(StaticANIObject *ani, int staticsId);
+ Common::Point *getPoint(Common::Point *point, int aniId, int staticsId1, int staticsId2);
+ int getStaticsIndexById(int idx, int16 id);
+ int getStaticsIndex(int idx, Statics *st);
+ void clearMovements2(int idx);
+ int recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop);
+ Common::Point *calcLength(Common::Point *point, Movement *mov, int x, int y, int *mult, int *len, int flag);
+ ExCommand2 *buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len);
+ MessageQueue *genMQ(StaticANIObject *ani, int staticsIndex, int staticsId, int *resStatId, Common::Point **pointArr);
+ int countPhases(int idx, int subIdx, int subOffset, int flag);
+ int refreshOffsets(int objectId, int idx1, int idx2);
+};
+
+} // End of namespace Fullpipe
+
+#endif /* FULLPIPE_MGM_H */
diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp
index 65274bfcf1..2fd7ef0c21 100644
--- a/engines/fullpipe/modal.cpp
+++ b/engines/fullpipe/modal.cpp
@@ -34,6 +34,8 @@
#include "graphics/palette.h"
#include "video/avi_decoder.h"
+#include "engines/savestate.h"
+
namespace Fullpipe {
ModalIntro::ModalIntro() {
@@ -196,11 +198,9 @@ bool ModalIntro::init(int counterdiff) {
}
void ModalIntro::update() {
- warning("STUB: ModalIntro::update()");
-
if (g_fp->_currentScene) {
if (_introFlags & 1) {
- //sceneFade(virt, g_currentScene, 1);
+ g_fp->sceneFade(g_fp->_currentScene, true);
_stillRunning = 255;
_introFlags &= 0xfe;
@@ -208,12 +208,12 @@ void ModalIntro::update() {
g_fp->playSound(SND_INTR_019, 0);
} else if (_introFlags & 2) {
if (g_vars->sceneIntro_needBlackout) {
- //vrtRectangle(*(_DWORD *)virt, 0, 0, 0, 800, 600);
+ g_fp->drawAlphaRectangle(0, 0, 800, 600, 0);
g_vars->sceneIntro_needBlackout = 0;
_stillRunning = 0;
_introFlags &= 0xfd;
} else {
- //sceneFade(virt, g_currentScene, 0);
+ g_fp->sceneFade(g_fp->_currentScene, false);
_stillRunning = 0;
_introFlags &= 0xfd;
}
@@ -726,8 +726,6 @@ bool ModalCredits::init(int counterdiff) {
}
void ModalCredits::update() {
- warning("STUB: ModalCredits::update()");
-
if (_fadeOut) {
if (_fadeIn) {
_sceneTitles->draw();
@@ -735,14 +733,14 @@ void ModalCredits::update() {
return;
}
} else if (_fadeIn) {
- //sceneFade(virt, this->_sceneTitles, 1); // TODO
+ g_fp->sceneFade(_sceneTitles, true);
_fadeOut = 1;
return;
}
if (_fadeOut) {
- //sceneFade(virt, this->_sceneTitles, 0); // TODO
+ g_fp->sceneFade(_sceneTitles, false);
_fadeOut = 0;
return;
}
@@ -920,7 +918,7 @@ bool ModalMainMenu::init(int counterdiff) {
g_fp->_modalObject = mq;
mq->_parentObj = this;
- mq->create(_scene, (PictureObject *)_scene->_picObjList[0], PIC_MEX_BGR);
+ mq->create(_scene, _scene, PIC_MEX_BGR);
_hoverAreaId = 0;
@@ -1084,17 +1082,17 @@ void ModalMainMenu::updateSoundVolume(Sound *snd) {
b = 800 - dx;
}
- int32 pp = b * a; //(0x51EB851F * b * a) >> 32) >> 8; // TODO FIXME
+ int32 pp = b * a;
- snd->setPanAndVolume(pan + (pp >> 31) + pp, par);
+ snd->setPanAndVolume(pan + pp / 800, par);
return;
}
int dx = _screct.left - ani->_ox;
if (dx <= 800) {
- int32 s = 0x51EB851F * (800 - dx) * (g_fp->_sfxVolume - (-3500)); // TODO FIXME
- int32 p = -3500 + (s >> 31) + (s >> 8);
+ int32 s = (800 - dx) * (g_fp->_sfxVolume - (-3500));
+ int32 p = -3500 + s / 800;
if (p > g_fp->_sfxVolume)
p = g_fp->_sfxVolume;
@@ -1103,8 +1101,6 @@ void ModalMainMenu::updateSoundVolume(Sound *snd) {
} else {
snd->setPanAndVolume(-3500, 0);
}
-
- warning("STUB: ModalMainMenu::updateSoundVolume()");
}
void ModalMainMenu::updateSliderPos() {
@@ -1322,7 +1318,7 @@ void ModalHelp::launch() {
}
ModalQuery::ModalQuery() {
- _picObjList = 0;
+ _bgScene = 0;
_bg = 0;
_okBtn = 0;
_cancelBtn = 0;
@@ -1335,7 +1331,7 @@ ModalQuery::~ModalQuery() {
_okBtn->_flags &= 0xFFFB;
}
-bool ModalQuery::create(Scene *sc, PictureObject *picObjList, int id) {
+bool ModalQuery::create(Scene *sc, Scene *bgScene, int id) {
if (id == PIC_MEX_BGR) {
_bg = sc->getPictureObjectById(PIC_MEX_BGR, 0);
@@ -1372,14 +1368,14 @@ bool ModalQuery::create(Scene *sc, PictureObject *picObjList, int id) {
}
_queryResult = -1;
- _picObjList = picObjList;
+ _bgScene = bgScene;
return true;
}
void ModalQuery::update() {
- if (_picObjList)
- _picObjList->draw();
+ if (_bgScene)
+ _bgScene->draw();
_bg->draw();
@@ -1430,9 +1426,12 @@ bool ModalQuery::init(int counterdiff) {
_okBtn->_flags &= 0xFFFB;
if (_queryResult == 1) {
+ if (_bgScene)
+ g_fp->sceneFade(_bgScene, false);
+
warning("STUB: ModalQuery::init()");
- //sceneFade(g_vrtDrawHandle, (Scene *)this->_picObjList, 0);
+ // Quit game
//if (inputArFlag) {
// g_needRestart = 1;
// return 0;
@@ -1446,18 +1445,355 @@ bool ModalQuery::init(int counterdiff) {
}
ModalSaveGame::ModalSaveGame() {
- warning("STUB: ModalSaveGame::ModalSaveGame()");
-
_oldBgX = 0;
_oldBgY = 0;
+
+ _bgr = 0;
+ _okD = 0;
+ _okL = 0;
+ _cancelD = 0;
+ _cancelL = 0;
+ _emptyD = 0;
+ _emptyL = 0;
+ _fullD = 0;
+ _fullL = 0;
+ _menuScene = 0;
+ _queryRes = -1;
+ _rect = g_fp->_sceneRect;
+ _queryDlg = 0;
+ _mode = 1;
+
+ _objtype = kObjTypeModalSaveGame;
+}
+
+ModalSaveGame::~ModalSaveGame() {
+ g_fp->_sceneRect = _rect;
+
+ _arrayD.clear();
+ _arrayL.clear();
+
+ for (uint i = 0; i < _files.size(); i++)
+ free(_files[i]);
+
+ _files.clear();
}
void ModalSaveGame::setScene(Scene *sc) {
- warning("STUB: ModalSaveGame::setScene()");
+ _queryRes = -1;
+ _menuScene = sc;
+}
+
+void ModalSaveGame::processKey(int key) {
+ if (key == 27)
+ _queryRes = 0;
+}
+
+bool ModalSaveGame::init(int counterdiff) {
+ if (_queryDlg) {
+ if (!_queryDlg->init(counterdiff)) {
+ if (!_queryDlg->getQueryResult())
+ _queryRes = -1;
+
+ delete _queryDlg;
+ _queryDlg = 0;
+ }
+
+ return true;
+ }
+
+ if (_queryRes == -1)
+ return true;
+
+ g_fp->_sceneRect = _rect;
+
+ if (g_fp->_currentScene) {
+ g_fp->_currentScene->_x = _oldBgX;
+ g_fp->_currentScene->_y = _oldBgY;
+ }
+
+ if (!_queryRes) {
+ ModalMainMenu *m = new ModalMainMenu;
+
+ g_fp->_modalObject = m;
+
+ m->_parentObj = _parentObj;
+ m->_screct = _rect;
+ m->_bgX = _oldBgX;
+ m->_bgY = _oldBgY;
+
+ delete this;
+
+ return true;
+ }
+
+ return false;
}
void ModalSaveGame::setup(Scene *sc, int mode) {
- warning("STUB: ModalSaveGame::setup()");
+ _files.clear();
+ _arrayL.clear();
+ _arrayD.clear();
+ _mode = mode;
+
+ if (mode) {
+ _bgr = sc->getPictureObjectById(PIC_MSV_BGR, 0);
+ _cancelD = sc->getPictureObjectById(PIC_MSV_CANCEL_D, 0);
+ _cancelL = sc->getPictureObjectById(PIC_MSV_CANCEL_L, 0);
+ _okD = sc->getPictureObjectById(PIC_MSV_OK_D, 0);
+ _okL = sc->getPictureObjectById(PIC_MSV_OK_L, 0);
+ _emptyD = sc->getPictureObjectById(PIC_MSV_EMPTY_D, 0);
+ _emptyL = sc->getPictureObjectById(PIC_MSV_EMPTY_L, 0);
+ } else {
+ _bgr = sc->getPictureObjectById(PIC_MLD_BGR, 0);
+ _cancelD = sc->getPictureObjectById(PIC_MLD_CANCEL_D, 0);
+ _cancelL = sc->getPictureObjectById(PIC_MLD_CANCEL_L, 0);
+ _okD = sc->getPictureObjectById(PIC_MLD_OK_D, 0);
+ _okL = sc->getPictureObjectById(PIC_MLD_OK_L, 0);
+ _emptyD = sc->getPictureObjectById(PIC_MSV_EMPTY_D, 0);
+ _emptyL = sc->getPictureObjectById(PIC_MSV_EMPTY_D, 0);
+ }
+
+ _fullD = sc->getPictureObjectById(PIC_MSV_FULL_D, 0);
+ _fullL = sc->getPictureObjectById(PIC_MSV_FULL_L, 0);
+ _queryRes = -1;
+
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_0_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_0_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_1_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_1_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_2_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_2_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_3_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_3_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_4_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_4_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_5_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_5_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_6_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_6_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_7_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_7_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_8_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_8_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_9_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_9_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_DOTS_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_DOTS_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_DOT_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_DOT_L, 0));
+ _arrayL.push_back(sc->getPictureObjectById(PIC_MSV_SPACE_D, 0));
+ _arrayD.push_back(sc->getPictureObjectById(PIC_MSV_SPACE_L, 0));
+
+ Common::Point point;
+
+ int x = _bgr->_ox + _bgr->getDimensions(&point)->x / 2;
+ int y = _bgr->_oy + 90;
+ int w;
+ FileInfo *fileinfo;
+
+ for (int i = 0; i < 7; i++) {
+ fileinfo = new FileInfo;
+ memset(fileinfo, 0, sizeof(FileInfo));
+
+ Common::strlcpy(fileinfo->filename, getSavegameFile(i), 160);
+
+ if (!getFileInfo(i, fileinfo)) {
+ fileinfo->empty = true;
+ w = _emptyD->getDimensions(&point)->x;
+ } else {
+ w = 0;
+
+ for (int j = 0; j < 16; j++) {
+ _arrayL[j]->getDimensions(&point);
+ w += point.x + 2;
+ }
+ }
+
+ fileinfo->fx1 = x - w / 2;
+ fileinfo->fx2 = x + w / 2;
+ fileinfo->fy1 = y;
+ fileinfo->fy2 = y + _emptyD->getDimensions(&point)->y;
+
+ _files.push_back(fileinfo);
+
+ y = fileinfo->fy2 + 3;
+ }
+}
+
+char *ModalSaveGame::getSaveName() {
+ if (_queryRes < 0)
+ return 0;
+
+ return _files[_queryRes]->filename;
+}
+
+bool ModalSaveGame::getFileInfo(int slot, FileInfo *fileinfo) {
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(
+ Fullpipe::getSavegameFile(slot));
+
+ if (!f)
+ return false;
+
+ Fullpipe::FullpipeSavegameHeader header;
+ Fullpipe::readSavegameHeader(f, header);
+ delete f;
+
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header.saveName);
+ char res[17];
+
+ snprintf(res, 17, "%s %s", desc.getSaveDate().c_str(), desc.getSaveTime().c_str());
+
+ for (int i = 0; i < 16; i++) {
+ switch(res[i]) {
+ case '.':
+ fileinfo->date[i] = 11;
+ break;
+ case ' ':
+ fileinfo->date[i] = 12;
+ break;
+ case ':':
+ fileinfo->date[i] = 10;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ fileinfo->date[i] = res[i] - '0';
+ break;
+ default:
+ error("Incorrect date format: %s", res);
+ }
+ }
+
+ return true;
+}
+
+void ModalSaveGame::update() {
+ if (_menuScene)
+ _menuScene->draw();
+
+ _bgr->draw();
+
+ if (_queryDlg) {
+ _queryDlg->update();
+
+ return;
+ }
+
+ g_fp->_cursorId = PIC_CSR_DEFAULT;
+
+ g_fp->setCursor(g_fp->_cursorId);
+
+ Common::Point point;
+
+ for (uint i = 0; i < _files.size(); i++) {
+ if (g_fp->_mouseScreenPos.x < _files[i]->fx1 || g_fp->_mouseScreenPos.x > _files[i]->fx2 ||
+ g_fp->_mouseScreenPos.y < _files[i]->fy1 || g_fp->_mouseScreenPos.y > _files[i]->fy2 ) {
+ if (_files[i]->empty) {
+ _emptyD->setOXY(_files[i]->fx1, _files[i]->fy1);
+ _emptyD->draw();
+ } else {
+ int x = _files[i]->fx1;
+
+ for (int j = 0; j < 16; j++) {
+ _arrayL[_files[i]->date[j]]->setOXY(x + 1, _files[i]->fy1);
+ _arrayL[_files[i]->date[j]]->draw();
+
+ x += _arrayL[_files[i]->date[j]]->getDimensions(&point)->x + 2;
+ }
+ }
+ } else {
+ if (_files[i]->empty) {
+ _emptyL->setOXY(_files[i]->fx1, _files[i]->fy1);
+ _emptyL->draw();
+ } else {
+ int x = _files[i]->fx1;
+
+ for (int j = 0; j < 16; j++) {
+ _arrayD[_files[i]->date[j]]->setOXY(x + 1, _files[i]->fy1);
+ _arrayD[_files[i]->date[j]]->draw();
+
+ x += _arrayD[_files[i]->date[j]]->getDimensions(&point)->x + 2;
+ }
+ }
+ }
+ }
+ if (_cancelL->isPixelHitAtPos(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y))
+ _cancelL->draw();
+ else if (_okL->isPixelHitAtPos(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y))
+ _okL->draw();
+}
+
+bool ModalSaveGame::handleMessage(ExCommand *cmd) {
+ if (_queryDlg)
+ return _queryDlg->handleMessage(cmd);
+
+ if (cmd->_messageNum == 29)
+ processMouse(cmd->_x, cmd->_y);
+ else if (cmd->_messageNum == 36)
+ processKey(cmd->_keyCode);
+
+ return false;
+}
+
+void ModalSaveGame::processMouse(int x, int y) {
+ for (uint i = 0; i < _files.size(); i++) {
+ if (x >= _files[i]->fx1 && x <= _files[i]->fx2 && y >= _files[i]->fy1 && y <= _files[i]->fy2) {
+ _queryRes = i + 1;
+
+ if (_mode) {
+ if (!_files[i]->empty) {
+ _queryDlg = new ModalQuery;
+
+ _queryDlg->create(_menuScene, 0, PIC_MOV_BGR);
+ }
+ }
+
+ return;
+ }
+ }
+
+ if (_cancelL->isPixelHitAtPos(x, y))
+ _queryRes = 0;
+}
+
+void ModalSaveGame::saveload() {
+ if (_objtype != kObjTypeModalSaveGame)
+ return;
+
+ if (_mode) {
+ if (getSaveName()) {
+ bool allowed = true;
+
+ for (Common::Array<MessageQueue *>::iterator s = g_fp->_globalMessageQueueList->begin(); s != g_fp->_globalMessageQueueList->end(); ++s) {
+ if (!(*s)->_isFinished && ((*s)->getFlags() & 1))
+ allowed = false;
+ }
+
+ if (g_fp->_isSaveAllowed && allowed)
+ g_fp->_gameLoader->writeSavegame(g_fp->_currentScene, getSaveName());
+ }
+ } else {
+ if (getSaveName()) {
+ if (_parentObj) {
+ delete _parentObj;
+
+ _parentObj = 0;
+ }
+
+ g_fp->stopAllSoundStreams();
+ g_fp->stopSoundStream2();
+
+ g_fp->_gameLoader->readSavegame(getSaveName());
+ }
+ }
}
void FullpipeEngine::openHelp() {
diff --git a/engines/fullpipe/modal.h b/engines/fullpipe/modal.h
index f7264057fb..a08cb3bce2 100644
--- a/engines/fullpipe/modal.h
+++ b/engines/fullpipe/modal.h
@@ -29,13 +29,24 @@ class PictureObject;
class Picture;
class Sound;
+struct FileInfo {
+ char filename[260];
+ bool empty;
+ char date[16];
+ int fx1;
+ int fx2;
+ int fy1;
+ int fy2;
+};
+
class BaseModalObject {
public:
BaseModalObject *_parentObj;
+ ObjType _objtype;
public:
- BaseModalObject() : _parentObj(0) {}
+ BaseModalObject() : _parentObj(0) { _objtype = kObjTypeDefault; }
virtual ~BaseModalObject() {}
@@ -224,12 +235,12 @@ public:
virtual void update();
virtual void saveload() {}
- bool create(Scene *sc, PictureObject *picObjList, int picId);
+ bool create(Scene *sc, Scene *bgScene, int picId);
int getQueryResult() { return _queryResult; }
private:
- PictureObject *_picObjList;
+ Scene *_bgScene;
PictureObject *_bg;
PictureObject *_okBtn;
PictureObject *_cancelBtn;
@@ -240,20 +251,42 @@ private:
class ModalSaveGame : public BaseModalObject {
public:
ModalSaveGame();
- virtual ~ModalSaveGame() {}
+ virtual ~ModalSaveGame();
virtual bool pollEvent() { return true; }
- virtual bool handleMessage(ExCommand *message) { return false; }
- virtual bool init(int counterdiff) { return true; }
- virtual void update() {}
- virtual void saveload() {}
+ virtual bool handleMessage(ExCommand *message);
+ virtual bool init(int counterdiff);
+ virtual void update();
+ virtual void saveload();
+
+ void processMouse(int x, int y);
void setScene(Scene *sc);
void setup(Scene *sc, int mode);
+ void processKey(int key);
+
+ char *getSaveName();
+ bool getFileInfo(int slot, FileInfo *fileinfo);
Common::Rect _rect;
int _oldBgX;
int _oldBgY;
+ PictureObject *_bgr;
+ PictureObject *_okD;
+ PictureObject *_okL;
+ PictureObject *_cancelD;
+ PictureObject *_cancelL;
+ PictureObject *_emptyD;
+ PictureObject *_emptyL;
+ PictureObject *_fullD;
+ PictureObject *_fullL;
+ Scene *_menuScene;
+ int _mode;
+ ModalQuery *_queryDlg;
+ Common::Array <FileInfo *> _files;
+ Common::Array <PictureObject *> _arrayL;
+ Common::Array <PictureObject *> _arrayD;
+ int _queryRes;
};
diff --git a/engines/fullpipe/module.mk b/engines/fullpipe/module.mk
index 3962fe64ba..96bd91fd39 100644
--- a/engines/fullpipe/module.mk
+++ b/engines/fullpipe/module.mk
@@ -15,6 +15,7 @@ MODULE_OBJS = \
lift.o \
messagehandlers.o \
messages.o \
+ mgm.o \
modal.o \
motion.o \
ngiarchive.o \
diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp
index 0dcb0ac2cf..49cf88434e 100644
--- a/engines/fullpipe/motion.cpp
+++ b/engines/fullpipe/motion.cpp
@@ -22,15 +22,10 @@
#include "fullpipe/fullpipe.h"
-#include "common/file.h"
-#include "common/array.h"
-#include "common/list.h"
-
-#include "fullpipe/objects.h"
+#include "fullpipe/utils.h"
#include "fullpipe/statics.h"
#include "fullpipe/gameloader.h"
#include "fullpipe/motion.h"
-#include "fullpipe/messages.h"
namespace Fullpipe {
@@ -125,9 +120,10 @@ void MctlCompound::addObject(StaticANIObject *obj) {
}
int MctlCompound::removeObject(StaticANIObject *obj) {
- warning("STUB: MctlCompound::removeObject()");
+ for (uint i = 0; i < _motionControllers.size(); i++)
+ _motionControllers[i]->_motionControllerObj->removeObject(obj);
- return 0;
+ return 1;
}
void MctlCompound::initMovGraph2() {
@@ -193,7 +189,8 @@ MessageQueue *MctlCompound::method34(StaticANIObject *ani, int sourceX, int sour
if (idx == sourceIdx)
return _motionControllers[idx]->_motionControllerObj->method34(ani, sourceX, sourceY, fuzzyMatch, staticsId);
- MctlConnectionPoint *cp = findClosestConnectionPoint(ani->_ox, ani->_oy, idx, sourceX, sourceY, sourceIdx, &sourceIdx);
+ double dist;
+ MctlConnectionPoint *cp = findClosestConnectionPoint(ani->_ox, ani->_oy, idx, sourceX, sourceY, sourceIdx, &dist);
if (!cp)
return 0;
@@ -261,7 +258,8 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos,
if (match1 == match2)
return _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, xpos, ypos, fuzzyMatch, staticsId);
- MctlConnectionPoint *closestP = findClosestConnectionPoint(subj->_ox, subj->_oy, match1, xpos, ypos, match2, &match2);
+ double dist;
+ MctlConnectionPoint *closestP = findClosestConnectionPoint(subj->_ox, subj->_oy, match1, xpos, ypos, match2, &dist);
if (!closestP)
return 0;
@@ -334,7 +332,7 @@ void MctlLadder::addObject(StaticANIObject *obj) {
if (initMovement(obj, movement)) {
_mgm.addItem(obj->_id);
- _movements.push_back(movement);
+ _ladmovements.push_back(movement);
} else {
delete movement;
}
@@ -342,13 +340,11 @@ void MctlLadder::addObject(StaticANIObject *obj) {
}
int MctlLadder::findObjectPos(StaticANIObject *obj) {
- int res = -1;
-
- for (Common::List<MctlLadderMovement *>::iterator it = _movements.begin(); it != _movements.end(); ++it, ++res)
- if ((*it)->objId == obj->_id)
- break;
+ for (uint i = 0; i < _ladmovements.size(); i++)
+ if (_ladmovements[i]->objId == obj->_id)
+ return i;
- return res;
+ return -1;
}
bool MctlLadder::initMovement(StaticANIObject *ani, MctlLadderMovement *movement) {
@@ -398,12 +394,12 @@ bool MctlLadder::initMovement(StaticANIObject *ani, MctlLadderMovement *movement
void MctlLadder::freeItems() {
_mgm.clear();
- for (Common::List<MctlLadderMovement *>::iterator it = _movements.begin(); it != _movements.end(); ++it) {
- delete (*it)->movVars;
- delete [] (*it)->staticIds;
+ for (uint i = 0; i < _ladmovements.size(); i++) {
+ delete _ladmovements[i]->movVars;
+ delete[] _ladmovements[i]->staticIds;
}
- _movements.clear();
+ _ladmovements.clear();
}
MessageQueue *MctlLadder::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
@@ -417,24 +413,257 @@ MessageQueue *MctlLadder::method34(StaticANIObject *subj, int xpos, int ypos, in
return 0;
}
-MessageQueue *MctlLadder::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
- warning("STUB: MctlLadder::doWalkTo()");
+MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ int pos = findObjectPos(ani);
- return 0;
+ if (pos < 0)
+ return 0;
+
+ double dh = _height;
+ double corr = (double)(ani->_oy - _ladderY) / dh;
+ int dl = (int)(corr + (corr < 0.0 ? -0.5 : 0.5));
+
+ corr = (double)(ypos - _ladderY) / dh;
+ int dl2 = (int)(corr + (corr < 0.0 ? -0.5 : 0.5));
+
+ int normx = _ladderX + dl2 * _width;
+ int normy = _ladderY + dl2 * _height;
+
+ if (dl == dl2 || dl2 < 0)
+ return 0;
+
+ int direction = (normy - ani->_oy) < 0 ? 0 : 1;
+
+ MGMInfo mgminfo;
+ PicAniInfo picinfo;
+ MessageQueue *mq;
+ ExCommand *ex;
+ Common::Point point;
+
+ if (ani->_movement) {
+ ani->getPicAniInfo(&picinfo);
+
+ int ox = ani->_ox;
+ int oy = ani->_oy;
+
+ ani->_movement->calcSomeXY(point, 1, ani->_someDynamicPhaseIndex);
+ ani->_statics = ani->_movement->_staticsObj2;
+ ani->_movement = 0;
+ ani->setOXY(point.x + ox, point.y + oy);
+
+ mq = doWalkTo(ani, normx, normy, fuzzyMatch, staticsId);
+
+ ani->setPicAniInfo(&picinfo);
+
+ return mq;
+ }
+
+ if (ani->_statics->_staticsId == _ladmovements[pos]->staticIds[0]) {
+ mgminfo.ani = ani;
+
+ if (staticsId)
+ mgminfo.staticsId2 = staticsId;
+ else
+ mgminfo.staticsId2 = _ladmovements[pos]->staticIds[direction];
+
+ mgminfo.x1 = normx;
+ mgminfo.y1 = normy;
+ mgminfo.field_1C = _ladder_field_14;
+ mgminfo.flags = 14;
+ mgminfo.movementId = direction ? _ladmovements[pos]->movVars->varDownGo : _ladmovements[pos]->movVars->varUpGo;
+
+ return _mgm.genMovement(&mgminfo);
+ }
+
+ if (ani->_statics->_staticsId == _ladmovements[pos]->staticIds[2]) {
+ if (!direction) {
+ mgminfo.ani = ani;
+
+ if (staticsId)
+ mgminfo.staticsId2 = staticsId;
+ else
+ mgminfo.staticsId2 = _ladmovements[pos]->staticIds[0];
+
+ mgminfo.x1 = normx;
+ mgminfo.y1 = normy;
+ mgminfo.field_1C = _ladder_field_14;
+ mgminfo.flags = 14;
+ mgminfo.movementId = _ladmovements[pos]->movVars->varUpGo;
+
+ return _mgm.genMovement(&mgminfo);
+ }
+
+ int ox = ani->_ox;
+ int oy = ani->_oy;
+
+ ani->getMovementById(_ladmovements[pos]->movVars->varUpStop)->calcSomeXY(point, 0, -1);
+
+ mgminfo.ani = ani;
+
+ if (staticsId)
+ mgminfo.staticsId2 = staticsId;
+ else
+ mgminfo.staticsId2 = _ladmovements[pos]->staticIds[1];
+
+ mgminfo.field_1C = _ladder_field_14;
+ mgminfo.x1 = normx;
+ mgminfo.y1 = normy;
+ mgminfo.y2 = point.y + oy;
+ mgminfo.x2 = point.x + ox;
+ mgminfo.flags = 63;
+ mgminfo.staticsId1 = _ladmovements[pos]->staticIds[0];
+ mgminfo.movementId = _ladmovements[pos]->movVars->varDownGo;
+
+ mq = _mgm.genMovement(&mgminfo);
+
+ ex = new ExCommand(ani->_id, 1, _ladmovements[pos]->movVars->varUpStop, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = ani->_okeyCode;
+ ex->_excFlags |= 2;
+
+ mq->insertExCommandAt(0, ex);
+
+ return mq;
+ }
+
+ if (ani->_statics->_staticsId != _ladmovements[pos]->staticIds[3]) {
+ mq = _mgm.genMQ(ani, _ladmovements[pos]->staticIds[0], 0, 0, 0);
+
+ if (!mq)
+ return 0;
+
+ int nx = ani->_ox;
+ int ny = ani->_oy;
+
+ _mgm.getPoint(&point, ani->_id, ani->_statics->_staticsId, _ladmovements[pos]->staticIds[0]);
+
+ nx += point.x;
+ ny += point.y;
+
+ ani->getPicAniInfo(&picinfo);
+
+ ani->_statics = ani->getStaticsById(_ladmovements[pos]->staticIds[0]);
+ ani->_movement = 0;
+ ani->setOXY(nx, ny);
+
+ MessageQueue *newmq = doWalkTo(ani, normx, normy, fuzzyMatch, staticsId);
+
+ mq->transferExCommands(newmq);
+
+ delete newmq;
+
+ ani->setPicAniInfo(&picinfo);
+
+ return mq;
+ }
+
+ if (!direction) {
+ int nx = ani->_ox;
+ int ny = ani->_oy;
+
+ ani->getMovementById(_ladmovements[pos]->movVars->varDownStop)->calcSomeXY(point, 0, -1);
+
+ nx += point.x;
+ ny += point.y;
+
+ mgminfo.ani = ani;
+ if (staticsId)
+ mgminfo.staticsId2 = staticsId;
+ else
+ mgminfo.staticsId2 = _ladmovements[pos]->staticIds[0];
+
+ mgminfo.field_1C = _ladder_field_14;
+ mgminfo.x1 = normx;
+ mgminfo.y1 = normy;
+ mgminfo.y2 = ny;
+ mgminfo.x2 = nx;
+ mgminfo.flags = 63;
+ mgminfo.staticsId1 = _ladmovements[pos]->staticIds[1];
+ mgminfo.movementId = _ladmovements[pos]->movVars->varUpGo;
+
+ mq = _mgm.genMovement(&mgminfo);
+
+ ex = new ExCommand(ani->_id, 1, _ladmovements[pos]->movVars->varDownStop, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = ani->_okeyCode;
+ ex->_excFlags |= 2;
+
+ mq->insertExCommandAt(0, ex);
+
+ return mq;
+ }
+
+
+ mgminfo.ani = ani;
+
+ if (staticsId)
+ mgminfo.staticsId2 = staticsId;
+ else
+ mgminfo.staticsId2 = _ladmovements[pos]->staticIds[1];
+
+ mgminfo.x1 = normx;
+ mgminfo.y1 = normy;
+ mgminfo.field_1C = _ladder_field_14;
+ mgminfo.flags = 14;
+ mgminfo.movementId = _ladmovements[pos]->movVars->varDownGo;
+
+ return _mgm.genMovement(&mgminfo);
}
MessageQueue *MctlLadder::controllerWalkTo(StaticANIObject *ani, int off) {
return doWalkTo(ani, _ladderX + off * _width, _ladderY + off * _height, 1, 0);
}
-MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr) {
- warning("STUB: MctlCompound::findClosestConnectionPoint()");
+MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIdx, double *minDistancePtr) {
+ if (destIndex == sourceIdx) {
+ *minDistancePtr = sqrt((double)((oy - connectionY) * (oy - connectionY) + (ox - connectionX) * (ox - connectionX)));
- return 0;
+ return 0;
+ }
+
+ double currDistance = 0.0;
+ double minDistance = 1.0e10;
+ MctlConnectionPoint *minConnectionPoint = 0;
+
+ for (uint i = 0; i < _motionControllers[sourceIdx]->_connectionPoints.size(); i++) {
+ for (uint j = 0; j < _motionControllers.size(); j++) {
+ if (_motionControllers[j]->_movGraphReactObj) {
+ MctlConnectionPoint *pt = _motionControllers[sourceIdx]->_connectionPoints[i];
+
+ if (_motionControllers[j]->_movGraphReactObj->pointInRegion(pt->_connectionX, pt->_connectionY)) {
+ MctlConnectionPoint *npt = findClosestConnectionPoint(ox, oy, destIndex, pt->_connectionX, pt->_connectionY, j, &currDistance);
+
+ if (currDistance < minDistance) {
+ minDistance = currDistance;
+
+ if (npt)
+ minConnectionPoint = npt;
+ else
+ minConnectionPoint = pt;
+ }
+ }
+ }
+ }
+ }
+
+ *minDistancePtr = minDistance;
+
+ return minConnectionPoint;
}
void MctlCompound::replaceNodeX(int from, int to) {
- warning("STUB: MctlCompound::replaceNodeX()");
+ for (uint i = 0; i < _motionControllers.size(); i++) {
+ if (_motionControllers[i]->_motionControllerObj->_objtype == kObjTypeMovGraph) {
+ MovGraph *gr = (MovGraph *)_motionControllers[i]->_motionControllerObj;
+
+ for (ObList::iterator n = gr->_nodes.begin(); n != gr->_nodes.end(); ++n) {
+ MovGraphNode *node = (MovGraphNode *)*n;
+
+ if (node->_x == from)
+ node->_x = to;
+ }
+
+ gr->calcNodeDistancesAndAngles();
+ }
+ }
}
MctlConnectionPoint::MctlConnectionPoint() {
@@ -493,15 +722,7 @@ bool MctlCompoundArray::load(MfcArchive &file) {
MovGraphItem::MovGraphItem() {
ani = 0;
field_4 = 0;
- field_8 = 0;
- field_C = 0;
- field_10 = 0;
- field_14 = 0;
- field_18 = 0;
- field_1C = 0;
- field_20 = 0;
- field_24 = 0;
- items = 0;
+ movitems = 0;
count = 0;
field_30 = 0;
field_34 = 0;
@@ -509,16 +730,36 @@ MovGraphItem::MovGraphItem() {
field_3C = 0;
}
+void MovGraphItem::free() {
+ for (uint i = 0; i < movitems->size(); i++) {
+ (*movitems)[i]->movarr->_movSteps.clear();
+ delete (*movitems)[i]->movarr;
+ }
+
+ delete movitems;
+
+ movitems = 0;
+}
+
int MovGraph_messageHandler(ExCommand *cmd);
-int MovGraphCallback(int a1, int a2, int a3) {
- warning("STUB: MovgraphCallback");
+MovArr *movGraphCallback(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter) {
+ int residx = 0;
+ int itemidx = 0;
- return 0;
+ while (counter > 1) {
+ if ((*items)[itemidx]->_mfield_4 > (*items)[itemidx + 1]->_mfield_4)
+ residx = itemidx;
+
+ counter--;
+ itemidx++;
+ }
+
+ return (*items)[residx]->movarr;
}
MovGraph::MovGraph() {
- _callback1 = MovGraphCallback;
+ _callback1 = movGraphCallback;
_field_44 = 0;
insertMessageHandler(MovGraph_messageHandler, getMessageHandlersCount() - 1, 129);
@@ -562,54 +803,485 @@ int MovGraph::removeObject(StaticANIObject *obj) {
}
void MovGraph::freeItems() {
- warning("STUB: MovGraph::freeItems()");
+ for (uint i = 0; i < _items.size(); i++) {
+ _items[i]->free();
+
+ _items[i]->movarr._movSteps.clear();
+ }
+
+ _items.clear();
}
-int MovGraph::method28() {
- warning("STUB: MovGraph::method28()");
+Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) {
+ *rescount = 0;
+
+ if (_items.size() <= 0)
+ return 0;
+
+ uint idx = 0;
+
+ while (_items[idx]->ani != ani) {
+ idx++;
+
+ if (idx >= _items.size())
+ return 0;
+ }
+ _items[idx]->free();
+
+ calcNodeDistancesAndAngles();
+
+ _items[idx]->movarr._movSteps.clear();
+
+ Common::Point point;
+
+ point.x = ani->_ox;
+ point.y = ani->_oy;
+
+ if (!calcChunk(idx, ani->_ox, ani->_oy, &_items[idx]->movarr, 0))
+ findClosestLink(idx, &point, &_items[idx]->movarr);
+
+ _items[idx]->count = 0;
+
+ delete _items[idx]->movitems;
+ _items[idx]->movitems = 0;
+
+ int arrSize;
+ Common::Array<MovArr *> *movarr = genMovArr(x, y, &arrSize, flag1, 0);
+
+ if (movarr) {
+ for (int i = 0; i < arrSize; i++) {
+ int sz;
+ Common::Array<MovItem *> *movitems = calcMovItems(&_items[idx]->movarr, (*movarr)[i], &sz);
+
+ if (sz > 0) {
+ for (int j = 0; j < sz; j++)
+ _items[idx]->movitems->push_back(movitems[j]);
+
+ delete movitems;
+ }
+ }
+
+ delete movarr;
+ }
+
+ if (_items[idx]->count) {
+ *rescount = _items[idx]->count;
+
+ return _items[idx]->movitems;
+ }
return 0;
}
-int MovGraph::method2C(StaticANIObject *obj, int x, int y) {
+bool MovGraph::method2C(StaticANIObject *obj, int x, int y) {
obj->setOXY(x, y);
return method3C(obj, 1);
}
-MessageQueue *MovGraph::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
- warning("STUB: MovGraph::method34()");
+MessageQueue *MovGraph::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ if (!ani) {
+ if (!_items.size())
+ return 0;
- return 0;
-}
+ ani = _items[0]->ani;
+ }
+
+ if (ABS(ani->_ox - xpos) < 50 && ABS(ani->_oy - ypos) < 50)
+ return 0;
-int MovGraph::changeCallback() {
- warning("STUB: MovGraph::changeCallback()");
+ if (!ani->isIdle())
+ return 0;
- return 0;
+ if (ani->_flags & 0x100)
+ return 0;
+
+ int count;
+ Common::Array<MovItem *> *movitems = method28(ani, xpos, ypos, fuzzyMatch, &count);
+
+ if (!movitems)
+ return 0;
+
+ if (ani->_movement) {
+ Common::Point point;
+
+ ani->calcStepLen(&point);
+
+ MessageQueue *mq = sub1(ani, ani->_ox - point.x, ani->_oy - point.y, ani->_movement->_staticsObj1->_staticsId, xpos, ypos, 0, fuzzyMatch);
+
+ if (!mq || !mq->getExCommandByIndex(0))
+ return 0;
+
+ ExCommand *ex = mq->getExCommandByIndex(0);
+
+ if ((ex->_messageKind != 1 && ex->_messageKind != 20) || ex->_messageNum != ani->_movement->_id ||
+ (ex->_field_14 >= 1 && ex->_field_14 <= ani->_movement->_currDynamicPhaseIndex)) {
+ mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
+
+ ex = new ExCommand(ani->_id, 21, 0, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = ani->_okeyCode;
+ ex->_field_3C = 1;
+ ex->_field_24 = 0;
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(ani->_id, 51, 0, xpos, ypos, 0, 1, 0, 0, 0);
+ ex->_keyCode = ani->_okeyCode;
+ ex->_field_3C = 1;
+ ex->_field_24 = 0;
+ ex->_field_20 = fuzzyMatch;
+ mq->addExCommandToEnd(ex);
+
+ if (mq->chain(0))
+ return mq;
+
+ delete mq;
+
+ return 0;
+ }
+
+ int count2;
+
+ ani->setSomeDynamicPhaseIndex(ex->_field_14);
+ method28(ani, xpos, ypos, fuzzyMatch, &count2);
+
+ int idx = getItemIndexByStaticAni(ani);
+ count = _items[idx]->count;
+ movitems = _items[idx]->movitems;
+ }
+
+ return method50(ani, _callback1(ani, movitems, count), staticsId);
}
-int MovGraph::method3C(StaticANIObject *ani, int flag) {
- warning("STUB: MovGraph::method3C()");
+void MovGraph::changeCallback(MovArr *(*callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) {
+ _callback1 = callback1;
+}
- return 0;
+bool MovGraph::method3C(StaticANIObject *ani, int flag) {
+ int idx = getItemIndexByStaticAni(ani);
+
+ if (idx == -1)
+ return false;
+
+ Common::Point point;
+ MovArr movarr;
+
+ point.x = ani->_ox;
+ point.y = ani->_oy;
+
+ findClosestLink(idx, &point, &movarr);
+ ani->setOXY(point.x, point.y);
+
+ if (flag) {
+ Statics *st;
+
+ if (ani->_statics) {
+ int t = _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44]);
+ if (t > _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44 + 1]))
+ st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44 + 1]);
+ else
+ st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44]);
+ } else {
+ ani->stopAnim_maybe();
+ st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44]);
+ }
+
+ ani->_statics = st;
+ }
+
+ return true;
}
-int MovGraph::method44() {
- warning("STUB: MovGraph::method44()");
+bool MovGraph::method44(StaticANIObject *ani, int x, int y) {
+ int idx = getItemIndexByStaticAni(ani);
+ MovArr m;
- return 0;
+ if (idx != -1) {
+ if (x != -1 || y != -1) {
+ int counter;
+
+ Common::Array<MovItem *> *movitem = method28(ani, x, y, 0, &counter);
+
+ if (movitem) {
+ MovArr *movarr = _callback1(ani, movitem, counter);
+ int cnt = movarr->_movStepCount;
+
+ if (cnt > 0) {
+ if (movarr->_movSteps[cnt - 1]->link->_flags & 0x4000000)
+ return true;
+ }
+ }
+ } else if (calcChunk(idx, ani->_ox, ani->_oy, &m, 0) && m._link && (m._link->_flags & 0x4000000)) {
+ return true;
+ }
+ }
+
+ return false;
}
MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
- warning("STUB: MovGraph::doWalkTo()");
+ PicAniInfo picAniInfo;
+ int ss;
+
+ Common::Array<MovItem *> *movitem = method28(subj, xpos, ypos, fuzzyMatch, &ss);
+
+ subj->getPicAniInfo(&picAniInfo);
+
+ if (movitem) {
+ MovArr *goal = _callback1(subj, movitem, ss);
+ int idx = getItemIndexByStaticAni(subj);
+
+ for (int i = 0; i < _items[idx]->count; i++) {
+ if ((*_items[idx]->movitems)[i]->movarr == goal) {
+ if (subj->_movement) {
+ Common::Point point;
+
+ subj->calcStepLen(&point);
+
+ MessageQueue *mq = sub1(subj, subj->_ox - point.x, subj->_oy - point.y, subj->_movement->_staticsObj1->_staticsId, xpos, ypos, 0, fuzzyMatch);
+
+ if (!mq || !mq->getExCommandByIndex(0))
+ return 0;
+
+ ExCommand *ex = mq->getExCommandByIndex(0);
+
+ if ((ex->_messageKind != 1 && ex->_messageKind != 20) ||
+ ex->_messageNum != subj->_movement->_id ||
+ (ex->_field_14 >= 1 && ex->_field_14 <= subj->_movement->_currDynamicPhaseIndex))
+ subj->playIdle();
+ }
+ }
+ }
+ }
+
+ movitem = method28(subj, xpos, ypos, fuzzyMatch, &ss);
+ if (movitem) {
+ MovArr *goal = _callback1(subj, movitem, ss);
+ int idx = getItemIndexByStaticAni(subj);
+
+ if (_items[idx]->count > 0) {
+ int arridx = 0;
+
+ while ((*_items[idx]->movitems)[arridx]->movarr != goal) {
+ arridx++;
+
+ if (arridx >= _items[idx]->count) {
+ subj->setPicAniInfo(&picAniInfo);
+ return 0;
+ }
+ }
+
+ _items[idx]->movarr._movSteps.clear();
+ _items[idx]->movarr = *(*_items[idx]->movitems)[arridx]->movarr;
+ _items[idx]->movarr._movSteps = (*_items[idx]->movitems)[arridx]->movarr->_movSteps;
+ _items[idx]->movarr._afield_8 = -1;
+ _items[idx]->movarr._link = 0;
+
+ MessageQueue *mq = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, staticsId);
+ if (mq) {
+ ExCommand *ex = new ExCommand();
+ ex->_messageKind = 17;
+ ex->_messageNum = 54;
+ ex->_parentId = subj->_id;
+ ex->_field_3C = 1;
+ mq->addExCommandToEnd(ex);
+ }
+ subj->setPicAniInfo(&picAniInfo);
+
+ return mq;
+ }
+ }
+
+ subj->setPicAniInfo(&picAniInfo);
return 0;
}
-int MovGraph::method50() {
- warning("STUB: MovGraph::method50()");
+MessageQueue *MovGraph::sub1(StaticANIObject *ani, int x, int y, int stid, int x1, int y1, int stid2, int flag1) {
+ PicAniInfo picinfo;
- return 0;
+ ani->getPicAniInfo(&picinfo);
+
+ ani->_statics = ani->getStaticsById(stid);
+ ani->_movement = 0;
+ ani->setOXY(x, y);
+
+ int rescount;
+
+ Common::Array<MovItem *> *movitems = method28(ani, x1, y1, flag1, &rescount);
+
+ if (!movitems) {
+ ani->setPicAniInfo(&picinfo);
+
+ return 0;
+ }
+
+ MessageQueue *res = 0;
+
+ MovArr *goal = _callback1(ani, movitems, rescount);
+ int idx = getItemIndexByStaticAni(ani);
+
+ MovGraphItem *movgitem = _items[idx];
+ int cnt = movgitem->count;
+
+ for (int nidx = 0; nidx < cnt; nidx++) {
+ if ((*movgitem->movitems)[nidx]->movarr == goal) {
+ movgitem->movarr._movSteps.clear();
+ _items[idx]->movarr = *(*movgitem->movitems)[nidx]->movarr;
+ _items[idx]->movarr._movSteps = (*movgitem->movitems)[nidx]->movarr->_movSteps;
+ _items[idx]->movarr._afield_8 = -1;
+ _items[idx]->movarr._link = 0;
+
+ res = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, stid2);
+
+ break;
+ }
+ }
+
+ ani->setPicAniInfo(&picinfo);
+
+ return res;
+}
+
+MessageQueue *MovGraph::fillMGMinfo(StaticANIObject *ani, MovArr *movarr, int staticsId) {
+ if (!movarr->_movStepCount)
+ return 0;
+
+ MessageQueue *mq = 0;
+ int ox = ani->_ox;
+ int oy = ani->_oy;
+ int id1 = 0;
+ int id2;
+
+ for (int i = 0; i < movarr->_movStepCount; i++) {
+ while (i < movarr->_movStepCount - 1) {
+ if (movarr->_movSteps[i ]->link->_dwordArray1[movarr->_movSteps[i - 1]->sfield_0 + _field_44] !=
+ movarr->_movSteps[i + 1]->link->_dwordArray1[movarr->_movSteps[i ]->sfield_0 + _field_44])
+ break;
+ i++;
+ }
+
+ MovStep *st = movarr->_movSteps[i];
+
+ ani->getMovementById(st->link->_dwordArray1[_field_44 + st->sfield_0]);
+
+ if (i == movarr->_movStepCount - 1 && staticsId) {
+ id2 = staticsId;
+ } else {
+ if (i < movarr->_movStepCount - 1)
+ id2 = ani->getMovementById(movarr->_movSteps[i + 1]->link->_dwordArray1[_field_44 + st->sfield_0])->_staticsObj1->_staticsId;
+ else
+ id2 = st->link->_dwordArray2[_field_44 + st->sfield_0];
+ }
+
+ int nx, ny, nd;
+
+ if (i == movarr->_movStepCount - 1) {
+ nx = movarr->_point.x;
+ ny = movarr->_point.y;
+ nd = st->link->_movGraphNode1->_distance;
+ } else {
+ if (st->sfield_0) {
+ nx = st->link->_movGraphNode1->_x;
+ ny = st->link->_movGraphNode1->_y;
+ nd = st->link->_movGraphNode1->_distance;
+ } else {
+ nx = st->link->_movGraphNode2->_x;
+ ny = st->link->_movGraphNode2->_y;
+ nd = st->link->_movGraphNode2->_distance;
+ }
+ }
+
+ MGMInfo mgminfo;
+
+ memset(&mgminfo, 0, sizeof(mgminfo));
+ mgminfo.ani = ani;
+ mgminfo.staticsId2 = id2;
+ mgminfo.staticsId1 = id1;
+ mgminfo.x1 = nx;
+ mgminfo.x2 = ox;
+ mgminfo.y2 = oy;
+ mgminfo.y1 = ny;
+ mgminfo.field_1C = nd;
+ mgminfo.movementId = st->link->_dwordArray1[_field_44 + st->sfield_0];
+
+ mgminfo.flags = 0xe;
+ if (mq)
+ mgminfo.flags |= 0x31;
+
+ MessageQueue *newmq = _mgm.genMovement(&mgminfo);
+
+ if (mq) {
+ if (newmq) {
+ mq->transferExCommands(newmq);
+
+ delete newmq;
+ }
+ } else {
+ mq = newmq;
+ }
+
+ ox = nx;
+ oy = ny;
+ id1 = id2;
+ }
+
+ return mq;
+}
+
+MessageQueue *MovGraph::method50(StaticANIObject *ani, MovArr *movarr, int staticsId) {
+ if (_items.size() == 0)
+ return 0;
+
+ uint idx;
+ int movidx;
+ bool done = false;
+
+ for (idx = 0; idx <= _items.size() && !done; idx++) {
+ if (idx == _items.size())
+ return 0;
+
+ if (_items[idx]->ani == ani) {
+ if (!_items[idx]->movitems)
+ return 0;
+
+ if (_items[idx]->count < 1)
+ return 0;
+
+ for (movidx = 0; movidx < _items[idx]->count; movidx++) {
+ if ((*_items[idx]->movitems)[movidx]->movarr == movarr) {
+ done = true;
+
+ break;
+ }
+ }
+ }
+ }
+
+ _items[idx]->movarr._movSteps.clear();
+ _items[idx]->movarr = *(*_items[idx]->movitems)[movidx]->movarr;
+ _items[idx]->movarr._movSteps = (*_items[idx]->movitems)[movidx]->movarr->_movSteps;
+ _items[idx]->movarr._afield_8 = -1;
+ _items[idx]->movarr._link = 0;
+
+ MessageQueue *mq = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, 0);
+
+ if (!mq)
+ return 0;
+
+ ExCommand *ex = new ExCommand();
+
+ ex->_messageKind = 17;
+ ex->_messageNum = 54;
+ ex->_parentId = ani->_id;
+ ex->_field_3C = 1;
+ mq->addExCommandToEnd(ex);
+
+ if (!mq->chain(ani)) {
+ delete mq;
+
+ return 0;
+ }
+
+ return mq;
}
double MovGraph::calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch) {
@@ -660,6 +1332,61 @@ void MovGraph::calcNodeDistancesAndAngles() {
}
}
+bool MovGraph::findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr) {
+ MovGraphLink *link = 0;
+ double mindist = 1.0e20;
+ int resx = 0, resy = 0;
+
+ for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) {
+ MovGraphLink *lnk = (MovGraphLink *)*i;
+
+ if ((lnk->_flags & 0x10000000) && !(lnk->_flags & 0x20000000) ) {
+ double dx1 = lnk->_movGraphNode1->_x - p->x;
+ double dy1 = lnk->_movGraphNode1->_y - p->y;
+ double dx2 = lnk->_movGraphNode2->_x - p->x;
+ double dy2 = lnk->_movGraphNode2->_y - p->y;
+ double dx3 = lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x;
+ double dy3 = lnk->_movGraphNode2->_y - lnk->_movGraphNode1->_y;
+ double sq1 = sqrt(dy1 * dy1 + dx1 * dx1);
+ double sdist = (dy3 * dy1 + dx3 * dx1) / lnk->_distance / sq1;
+ double ldist = sdist * sq1;
+ double dist = sqrt(1.0 - sdist * sdist) * sq1;
+
+ if (ldist < 0.0) {
+ ldist = 0.0;
+ dist = sqrt(dx1 * dx1 + dy1 * dy1);
+ }
+
+ if (ldist > lnk->_distance) {
+ ldist = lnk->_distance;
+ dist = sqrt(dx2 * dx2 + dy2 * dy2);
+ }
+
+ if (ldist >= 0.0 && ldist <= lnk->_distance && dist < mindist) {
+ resx = lnk->_movGraphNode1->_x + (int)(dx3 * ldist / lnk->_distance);
+ resy = lnk->_movGraphNode1->_y + (int)(dy3 * ldist / lnk->_distance);
+
+ mindist = dist;
+ link = lnk;
+ }
+ }
+ }
+
+ if (mindist < 1.0e20) {
+ if (movarr)
+ movarr->_link = link;
+
+ if (p) {
+ p->x = resx;
+ p->y = resy;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
int MovGraph::getItemIndexByStaticAni(StaticANIObject *ani) {
for (uint i = 0; i < _items.size(); i++)
if (_items[i]->ani == ani)
@@ -668,6 +1395,214 @@ int MovGraph::getItemIndexByStaticAni(StaticANIObject *ani) {
return -1;
}
+Common::Array<MovArr *> *MovGraph::genMovArr(int x, int y, int *arrSize, int flag1, int flag2) {
+ if (!_links.size()) {
+ *arrSize = 0;
+
+ return 0;
+ }
+
+ Common::Array<MovArr *> *arr = new Common::Array<MovArr *>;
+ MovArr *movarr;
+
+ for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) {
+ MovGraphLink *lnk = (MovGraphLink *)*i;
+
+ if (flag1) {
+ Common::Point point(x, y);
+ double dist = calcDistance(&point, lnk, 0);
+
+ if (dist >= 0.0 && dist < 2.0) {
+ movarr = new MovArr;
+
+ movarr->_link = lnk;
+ movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - point.y) +
+ (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(point.x - lnk->_movGraphNode1->_x)) /
+ lnk->_distance / lnk->_distance;
+ movarr->_point = point;
+
+ arr->push_back(movarr);
+ }
+ } else {
+ if (lnk->_movGraphReact) {
+ if (lnk->_movGraphReact->pointInRegion(x, y)) {
+ if (!(lnk->_flags & 0x10000000) || lnk->_flags & 0x20000000) {
+ if (!flag2) {
+ movarr = new MovArr;
+ movarr->_link = lnk;
+ movarr->_dist = 0.0;
+ movarr->_point.x = lnk->_movGraphNode1->_x;
+ movarr->_point.y = lnk->_movGraphNode1->_y;
+ arr->push_back(movarr);
+
+ movarr = new MovArr;
+ movarr->_link = lnk;
+ movarr->_dist = 1.0;
+ movarr->_point.x = lnk->_movGraphNode1->_x;
+ movarr->_point.y = lnk->_movGraphNode1->_y;
+ arr->push_back(movarr);
+ }
+ } else {
+ movarr = new MovArr;
+ movarr->_link = lnk;
+ movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - y) +
+ (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(x - lnk->_movGraphNode1->_x)) /
+ lnk->_distance / lnk->_distance;
+ movarr->_point.x = x;
+ movarr->_point.y = y;
+
+ calcDistance(&movarr->_point, lnk, 0);
+
+ arr->push_back(movarr);
+ }
+ }
+ }
+ }
+ }
+
+ *arrSize = arr->size();
+
+ return arr;
+}
+
+void MovGraph::findAllPaths(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array<MovGraphLink *> &tempObList1, Common::Array<MovGraphLink *> &allPaths) {
+ if (lnk == lnk2) {
+ for (uint i = 0; i < tempObList1.size(); i++)
+ allPaths.push_back(tempObList1[i]);
+
+ allPaths.push_back(lnk);
+ } else {
+ lnk->_flags |= 0x80000000;
+
+ tempObList1.push_back(lnk);
+
+ for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) {
+ MovGraphLink *l = (MovGraphLink *)*i;
+
+ if (l->_movGraphNode1 != lnk->_movGraphNode1) {
+ if (l->_movGraphNode2 != lnk->_movGraphNode1) {
+ if (l->_movGraphNode1 != lnk->_movGraphNode2 && l->_movGraphNode2 != lnk->_movGraphNode2)
+ continue;
+ }
+ }
+
+ if (!(l->_flags & 0xA0000000))
+ findAllPaths(l, lnk2, tempObList1, allPaths);
+ }
+
+ lnk->_flags &= 0x7FFFFFFF;
+ }
+}
+
+// Returns a list of possible paths two points in graph space
+Common::Array<MovItem *> *MovGraph::calcMovItems(MovArr *currPos, MovArr *destPos, int *pathCount) {
+ Common::Array<MovGraphLink *> tempObList1;
+ Common::Array<MovGraphLink *> allPaths;
+
+ // Get all paths between two edges of the graph
+ findAllPaths(currPos->_link, destPos->_link, tempObList1, allPaths);
+
+ *pathCount = 0;
+
+ if (!allPaths.size())
+ return 0;
+
+ *pathCount = allPaths.size();
+
+ Common::Array<MovItem *> *res = new Common::Array<MovItem *>;
+
+ for (int i = 0; i < *pathCount; i++) {
+ MovItem *r = new MovItem;
+
+ genMovItem(r, allPaths[i], currPos, destPos);
+
+ res->push_back(r);
+
+ delete allPaths[i];
+ }
+
+ // Start the resulting path from current position
+ destPos->_link = currPos->_link;
+
+ return res;
+}
+
+void MovGraph::genMovItem(MovItem *movitem, MovGraphLink *grlink, MovArr *movarr1, MovArr *movarr2) {
+ warning("STUB: MovGraph::genMovItem()");
+}
+
+bool MovGraph::calcChunk(int idx, int x, int y, MovArr *arr, int a6) {
+ int staticsId;
+
+ if (_items[idx]->ani->_statics) {
+ staticsId = _items[idx]->ani->_statics->_staticsId;
+ } else {
+ if (!_items[idx]->ani->_movement->_staticsObj2)
+ return 0;
+
+ staticsId = _items[idx]->ani->_movement->_staticsObj2->_staticsId;
+ }
+
+ int arrSize;
+
+ Common::Array<MovArr *> *movarr = genMovArr(x, y, &arrSize, 0, 1);
+
+ if (!movarr)
+ return findClosestLink(idx, 0, arr);
+
+ bool res = false;
+
+ int idxmin = -1;
+ int offmin = 100;
+
+ for (int i = 0; i < arrSize; i++) {
+ int off = _mgm.refreshOffsets(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44]);
+
+ if (off < offmin) {
+ offmin = off;
+ idxmin = i;
+ }
+
+ off = _mgm.refreshOffsets(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44 + 1]);
+ if (off < offmin) {
+ offmin = off;
+ idxmin = i;
+ }
+ }
+
+ if (idxmin != -1) {
+ *arr = *(*movarr)[idxmin];
+
+ res = true;
+ }
+
+ delete movarr;
+
+ return res;
+}
+
+void MovGraph::setEnds(MovStep *step1, MovStep *step2) {
+ if (step1->link->_movGraphNode1 == step2->link->_movGraphNode2) {
+ step1->sfield_0 = 1;
+ step2->sfield_0 = 1;
+
+ return;
+ }
+
+ if (step1->link->_movGraphNode1 == step2->link->_movGraphNode1) {
+ step1->sfield_0 = 1;
+ step2->sfield_0 = 0;
+ } else {
+ step1->sfield_0 = 0;
+
+ if (step1->link->_movGraphNode2 != step2->link->_movGraphNode1) {
+ step2->sfield_0 = 1;
+ } else {
+ step2->sfield_0 = 0;
+ }
+ }
+}
+
int MovGraph2::getItemIndexByGameObjectId(int objectId) {
for (uint i = 0; i < _items2.size(); i++)
if (_items2[i]->_objectId == objectId)
@@ -693,8 +1628,22 @@ int MovGraph2::getItemSubIndexByMovementId(int idx, int movId) {
return -1;
}
-int MovGraph2::getItemSubIndexByMGM(int idx, StaticANIObject *ani) {
- warning("STUB: MovGraph2::getItemSubIndexByMGM()");
+int MovGraph2::getItemSubIndexByMGM(int index, StaticANIObject *ani) {
+ if (findNode(ani->_ox, ani->_oy, 0) || findLink1(ani->_ox, ani->_oy, -1, 0) || findLink2(ani->_ox, ani->_oy)) {
+ int minidx = -1;
+ int min = 0;
+
+ for (int i = 0; i < 4; i++) {
+ int tmp = _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, _items2[index]->_subItems[i]._staticsId1);
+
+ if (tmp >= 0 && (minidx == -1 || tmp < min)) {
+ minidx = i;
+ min = tmp;
+ }
+ }
+
+ return minidx;
+ }
return -1;
}
@@ -755,7 +1704,7 @@ bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) {
item->_subItems[dir]._walk[act]._mov = mov;
if (mov) {
- mov->calcSomeXY(point, 0);
+ mov->calcSomeXY(point, 0, -1);
item->_subItems[dir]._walk[act]._mx = point.x;
item->_subItems[dir]._walk[act]._my = point.y;
}
@@ -785,7 +1734,7 @@ bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) {
item->_subItems[dir]._turn[act]._mov = mov;
if (mov) {
- mov->calcSomeXY(point, 0);
+ mov->calcSomeXY(point, 0, -1);
item->_subItems[dir]._turn[act]._mx = point.x;
item->_subItems[dir]._turn[act]._my = point.y;
}
@@ -815,7 +1764,7 @@ bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) {
item->_subItems[dir]._turnS[act]._mov = mov;
if (mov) {
- mov->calcSomeXY(point, 0);
+ mov->calcSomeXY(point, 0, -1);
item->_subItems[dir]._turnS[act]._mx = point.x;
item->_subItems[dir]._turnS[act]._my = point.y;
}
@@ -1089,7 +2038,10 @@ int MovGraph2::removeObject(StaticANIObject *obj) {
}
void MovGraph2::freeItems() {
- warning("STUB: MovGraph2::freeItems()");
+ for (uint i = 0; i < _items2.size(); i++)
+ delete _items2[i];
+
+ _items2.clear();
}
MessageQueue *MovGraph2::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) {
@@ -1140,6 +2092,8 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int
PicAniInfo picAniInfo;
Common::Point point;
+ debug(0, "MovGraph2::doWalkTo(%d, %d, %d, %d, %d)", obj->_id, xpos, ypos, fuzzyMatch, staticsId);
+
int idx = getItemIndexByGameObjectId(obj->_id);
if (idx < 0)
@@ -1181,7 +2135,7 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int
newx = obj->_ox;
newy = obj->_oy;
} else {
- obj->_movement->calcSomeXY(point, 0);
+ obj->_movement->calcSomeXY(point, 0, picAniInfo.dynamicPhaseIndex);
newx = obj->_movement->_ox - point.x;
newy = obj->_movement->_oy - point.y;
if (idxsub != 1 && idxsub) {
@@ -1474,7 +2428,7 @@ MessageQueue *MovGraph2::genMovement(MovInfo1 *info) {
int y = info->pt2.y - info->pt1.y - my2 - my1;
int x = info->pt2.x - info->pt1.x - mx2 - mx1;
- int a2;
+ int a2 = 0;
int mgmLen;
_mgm.calcLength(&point, _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov, x, y, &mgmLen, &a2, info->flags & 1);
@@ -1820,592 +2774,6 @@ MovGraphNode *MovGraph::calcOffset(int ox, int oy) {
return res;
}
-void MGM::clear() {
- _items.clear();
-}
-
-MGMItem::MGMItem() {
- objId = 0;
-}
-
-MGMSubItem::MGMSubItem() {
- movement = 0;
- staticsIndex = 0;
- field_8 = 0;
- field_C = 0;
- x = 0;
- y = 0;
-}
-
-void MGM::addItem(int objId) {
- if (getItemIndexById(objId) == -1) {
- MGMItem *item = new MGMItem();
-
- item->objId = objId;
- _items.push_back(item);
- }
- rebuildTables(objId);
-}
-
-void MGM::rebuildTables(int objId) {
- int idx = getItemIndexById(objId);
-
- if (idx == -1)
- return;
-
- _items[idx]->subItems.clear();
- _items[idx]->statics.clear();
- _items[idx]->movements1.clear();
- _items[idx]->movements2.clear();
-
- StaticANIObject *obj = g_fp->_currentScene->getStaticANIObject1ById(objId, -1);
-
- if (!obj)
- return;
-
- for (uint i = 0; i < obj->_staticsList.size(); i++)
- _items[idx]->statics.push_back((Statics *)obj->_staticsList[i]);
-
- for (uint i = 0; i < obj->_movements.size(); i++)
- _items[idx]->movements1.push_back((Movement *)obj->_movements[i]);
-
- _items[idx]->subItems.clear();
-}
-
-int MGM::getItemIndexById(int objId) {
- for (uint i = 0; i < _items.size(); i++)
- if (_items[i]->objId == objId)
- return i;
-
- return -1;
-}
-
-MessageQueue *MGM::genMovement(MGMInfo *mgminfo) {
- warning("STUB: MGM::genMovement()");
-
- return 0;
-
-#if 0
- if (!mgminfo->ani)
- return 0;
-
- mov = mgminfo->ani->_movement;
-
- if (!mov && !mgminfo->ani->_statics)
- return 0;
-
- if (!(mgminfo->flags & 1)) {
- if (mov)
- mgminfo->staticsId1 = mov->_staticsObj2->_staticsId;
- else
- mgminfo->staticsId1 = mgminfo->ani->_statics->_staticsId;
- }
-
- if (!(mgminfo->flags & 0x10) || !(mgminfo->flags & 0x20)) {
- int nx = mgminfo->ani->_ox;
- int ny = mgminfo->ani->_oy;
-
- if (mgminfo->ani->_movement) {
- mgminfo->ani->calcNextStep(&point2);
- nx += point2.x;
- ny += point2.y;
- }
-
- if (!(mgminfo->flags & 0x10))
- mgminfo->x2 = nx;
-
- if (!(mgminfo->flags & 0x20))
- mgminfo->y2 = ny;
- }
-
- mov = mgminfo->ani->getMovementById(mgminfo->movementId);
-
- if (!mov)
- return 0;
-
- itemIdx = getItemIndexById(mgminfo->ani->_id);
- subIdx = getStaticsIndexById(itemIdx, mgminfo->staticsId1);
- st2idx = getStaticsIndexById(itemIdx, mov->_staticsObj1->_staticsId);
- st1idx = getStaticsIndexById(itemIdx, mov->_staticsObj2->_staticsId);
- subOffset = getStaticsIndexById(itemIdx, mgminfo->staticsId2);
-
- clearMovements2(itemIdx);
- recalcOffsets(itemIdx, subIdx, st2idx, 0, 1);
- clearMovements2(itemIdx);
- recalcOffsets(itemIdx, st1idx, subOffset, 0, 1);
-
- v71 = (Message *)(28 * itemIdx);
- v16 = items[itemIdx].objId;
- v17 = *(_DWORD *)(v16 + offsetof(MGMItem, staticsListCount));
- off = *(_DWORD *)(v16 + offsetof(MGMItem, subItems));
- v18 = (MGMSubItem *)(off + 24 * (subIdx + st2idx * v17));
- x1 = (int)&v18->movement->go.CObject.vmt;
- v19 = (MGMSubItem *)(off + 24 * (st1idx + subOffset * v17));
- v69 = (LONG)&v19->movement->go.CObject.vmt;
-
- if (subIdx != st2idx && !x1)
- return 0;
-
- if (st1idx != subOffset && !v69)
- return 0;
-
- int n1x = mgminfo->x1 - mgminfo->x2 - v18->x - v19->x;
- int n1y = mgminfo->y1 - mgminfo->y2 - v18->y - v19->y;
-
- mov->calcSomeXY(&point1, 0);
-
- int n2x = point1.x;
- int n2y = point1.y;
- int mult;
-
- if (mgminfo->flags & 0x40) {
- mult = mgminfo->field_10;
- len = -1;
- n2x *= mult;
- n2y *= mult;
- } else {
- calcLength(&point, mov, n1x, n1y, &mult, &len, 1);
- n2x = point.x;
- n2y = point.y;
- }
-
- if (!(mgminfo->flags & 2)) {
- len = -1;
- n2x = mult * point1.x;
- n1x = mult * point1.x;
- mgminfo->x1 = mgminfo->x2 + mult * point1.x + v18->x + v19->x;
- }
-
- if (!(mgminfo->flags & 4)) {
- n2y = mult * point1.y;
- n1y = mult * point1.y;
- len = -1;
- mgminfo->y1 = mgminfo->y2 + mult * point1.y + v18->y + v19->y;
- }
-
- int px = 0;
- int py = 0;
-
- if (x1) {
- px = countPhases(itemIdx, subIdx, st2idx, 1);
- py = countPhases(itemIdx, subIdx, st2idx, 2);
- }
-
- if (mult > 1) {
- px += (mult - 1) * mov->countPhasesWithFlag(-1, 1);
- py += (mult - 1) * mov->countPhasesWithFlag(-1, 2);
- }
-
- if (mult > 0) {
- px += mov->countPhasesWithFlag(len, 1);
- py += mov->countPhasesWithFlag(len, 2);
- }
-
- if (v69) {
- px += countPhases(itemIdx, st1idx, subOffset, 1);
- py += countPhases(itemIdx, st1idx, subOffset, 2);
- }
-
- int dx1 = n1x - n2x;
- int dy1 = n1y - n2y;
-
- if (px) {
- x1 = (int)((double)dx1 / (double)px);
- } else {
- x1 = 0;
- }
-
- if (py) {
- y1 = (int)((double)dy1 / (double)py);
- } else {
- y1 = 0;
- }
-
- y2.x = dx1 - px * x1;
- y2.y = dy1 - py * y1;
-
- if (n1x - n2x == px * x1)
- x2.x = 0;
- else
- x2.x = (dx1 - px * x1) / abs(dx1 - px * x1);
-
- if (dy1 == py * y1)
- x2.y = 0;
- else
- x2.y = (dy1 - py * y1) / abs(dy1 - py * y1);
-
- MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
- ExCommand2 *ex2;
-
- for (v42 = subIdx; v42 != st2idx; v42 = v43->staticsIndex) {
- v43 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[v42 + st2idx * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)];
- ex2 = buildExCommand2(v43->movement, mgminfo->ani->go._id, x1, y1, &x2, &y2, -1);
- ex2->_parId = mq->_id;
- ex2->_keyCode = mgminfo->ani->_okeyCode;
-
- mq->addExCommandToEnd(ex2);
- }
-
- for (i = 0; i < mult; ++i) {
- int plen;
-
- if (i == mult - 1)
- plen = len;
- else
- plen = -1;
-
- ex2 = buildExCommand2(mov, mgminfo->ani->_id, x1, y1, &x2, &y2, plen);
- ex2->_parId = mq->_id;
- ex2->_keyCode = mgminfo->ani->_okeyCode;
-
- mq->addExCommandToEnd(ex2);
- }
-
- for (j = st1idx; j != subOffset; j = v50->staticsIndex) {
- v50 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[j + subOffset * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)];
-
- ex2 = buildExCommand2(v50->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1);
- ex2->_parId = mq->_id;
- ex2->_keyCode = mgminfo->ani->_okeyCode;
-
- mq->addExCommandToEnd(ex2);
- }
-
- ExCommand *ex = new ExCommand(mgminfo->ani->_id, 5, -1, mgminfo->x1, mgminfo->y1, 0, 1, 0, 0, 0);
-
- ex->_field_14 = mgminfo->field_1C;
- ex->_keyCode = mgminfo->ani->_okeyCode;
- ex->_field_24 = 0;
- ex->_excFlags |= 3;
-
- mq->addExCommandToEnd(ex);
-
- return mq;
-#endif
-}
-
-void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) {
- if (getItemIndexById(ani->_id) == -1)
- return;
-
- if (ani->_movement) {
- ani->queueMessageQueue(0);
- ani->_movement->gotoLastFrame();
- ani->_statics = ani->_movement->_staticsObj2;
-
- int x = ani->_movement->_ox;
- int y = ani->_movement->_oy;
-
- ani->_movement = 0;
-
- ani->setOXY(x, y);
- }
-
- if (ani->_statics) {
- Common::Point point;
-
- getPoint(&point, ani->_id, ani->_statics->_staticsId, staticsId);
-
- ani->setOXY(ani->_ox + point.x, ani->_oy + point.y);
-
- ani->_statics = ani->getStaticsById(staticsId);
- }
-}
-
-Common::Point *MGM::getPoint(Common::Point *point, int objectId, int staticsId1, int staticsId2) {
- int idx = getItemIndexById(objectId);
-
- if (idx == -1) {
- point->x = -1;
- point->y = -1;
- } else {
- int st1idx = getStaticsIndexById(idx, staticsId1);
- int st2idx = getStaticsIndexById(idx, staticsId2);
-
- if (st1idx == st2idx) {
- point->x = 0;
- point->y = 0;
- } else {
- int subidx = st1idx + st2idx * _items[idx]->statics.size();
-
- if (!_items[idx]->subItems[subidx]->movement) {
- clearMovements2(idx);
- recalcOffsets(idx, st1idx, st2idx, false, true);
-
- if (!_items[idx]->subItems[subidx]->movement) {
- clearMovements2(idx);
- recalcOffsets(idx, st1idx, st2idx, true, false);
- }
- }
-
- MGMSubItem *sub = _items[idx]->subItems[subidx];
-
- if (sub->movement) {
- point->x = sub->x;
- point->y = sub->y;
- } else {
- point->x = 0;
- point->y = 0;
- }
- }
- }
-
- return point;
-}
-
-int MGM::getStaticsIndexById(int idx, int16 id) {
- if (!_items[idx]->statics.size())
- return -1;
-
- for (uint i = 0; i < _items[idx]->statics.size(); i++) {
- if (_items[idx]->statics[i]->_staticsId == id)
- return i;
- }
-
- return 0;
-}
-
-int MGM::getStaticsIndex(int idx, Statics *st) {
- if (!_items[idx]->statics.size())
- return -1;
-
- for (uint i = 0; i < _items[idx]->statics.size(); i++) {
- if (_items[idx]->statics[i] == st)
- return i;
- }
-
- return 0;
-}
-
-void MGM::clearMovements2(int idx) {
- _items[idx]->movements2.clear();
-}
-
-int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) {
-#if 0
- MGMItem *item = _items[idx];
- int subIdx = st1idx + st2idx * item->staticsListCount;
-
- if (st1idx == st2idx) {
- memset(&item->subItems[subIdx], 0, sizeof(item->subItems[subIdx]));
- return 0;
- }
-
- if (item->subItems[subIdx])
- return item->subItems[subIdx]->field_8;
-
- Common::Point point;
-
- for (int i = 0; i < item->movementListCount; i++) {
- mov = item->movements1[i];
-
- if (mov->_staticsObj1 == item->statics[st1idx]) {
- if (!item->movements2[i] && (!flop || mov->_field_50)) {
- item->movements2[i] = 1;
-
- int stidx = getStaticsIndex(idx, item->movements1[i]->_staticsObj2);
- int recalc = recalcOffsets(idx, stidx, st2idx, flip, flop);
-
- int sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
-
- v20 = sz + *(&item->subItems[stidx].field_C + 6 * st2idx * _items[idx].staticsListCount);
-
- if (recalc >= 0) {
- if (!item->subItems[subIdx].movement || item->subItems[subIdx].field_8 > recalc + 1 ||
- (item->subItems[subIdx].field_8 == recalc + 1 && item->subItems[subIdx].field_C > v20) {
- item->subItems[subIdx].movement = mov;
- item->subItems[subIdx].staticsIndex = stidx;
- item->subItems[subIdx].field_8 = recalc + 1;
- item->subItems[subIdx].field_C = v20;
-
- mov->calcSomeXY(&point, 0);
-
- v25 = point.x + *(&item->subItems[stidx]->x + 6 * st2idx * _items[idx]->staticsListCount);
- v26 = point.y + *(&item->subItems[stidx]->y + 6 * st2idx * _items[idx]->staticsListCount);
-
- item->subItems[subIdx]->x = v25;
- item->subItems[subIdx]->y = v26;
- }
- }
- }
- } else if (flip) {
- if (mov->_staticsObj2 == item->statics[st1idx]) {
- if (!item->movements2[i] && (!flop || mov->_field_50)) {
- item->movements2[i] = 1;
-
- int stidx = getStaticsIndex(idx, mov->_staticsObj1);
- int recalc = recalcOffsets(idx, stidx, st2idx, flip, flop);
-
- if (recalc >= 0) {
- if (!item->subItems[subIdx]->movement || item->subItems[subIdx]->field_8 > recalc + 1) {
- item->subItems[subIdx]->movement = mov;
- item->subItems[subIdx].staticsIndex = stidx;
- item->subItems[subIdx].field_8 = recalc + 1;
-
- int sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
-
- item->subItems[subIdx].field_C = sz + *(&item->subItems[stidx].field_C + 6 * st2idx * _items[idx].staticsListCount);
-
- mov->calcSomeXY(&point, 0);
-
- v25 = *(&item->subItems[stidx].x + 6 * st2idx * _items[idx].staticsListCount) - point.x;
- v26 = *(&item->subItems[stidx].y + 6 * st2idx * _items[idx].staticsListCount) - point.y;
-
- item->subItems[subIdx].x = v25;
- item->subItems[subIdx].y = v26;
-
- continue;
- }
- }
- }
- }
- }
- }
-
- if (item->subItems[subIdx]->movement)
- return item->subItems[subIdx]->field_8;
-
- return -1;
-#endif
- warning("STUB: MGM::recalcOffsets()");
-
- return 0;
-}
-
-Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *mult, int *len, int flag) {
- Common::Point point;
-
- mov->calcSomeXY(point, 0);
- int p1x = point.x;
- int p1y = point.y;
-
- int newmult = 0;
- int oldlen = *len;
-
- if (abs(p1y) > abs(p1x)) {
- if (mov->calcSomeXY(point, 0)->y)
- newmult = (int)((double)y / point.y);
- } else if (mov->calcSomeXY(point, 0)->x) {
- newmult = (int)((double)x / point.y);
- }
-
- if (newmult < 0)
- newmult = 0;
-
- *mult = newmult;
-
- int phase = 1;
- int sz;
-
- if (flag) {
- if (abs(p1y) > abs(p1x)) {
- while (abs(p1y * newmult + mov->calcSomeXY(point, 0)->y) < abs(y)) {
- sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
-
- if (phase >= sz) {
- phase--;
-
- break;
- }
-
- phase++;
- }
- } else {
- while (abs(p1x * newmult + mov->calcSomeXY(point, 0)->x) < abs(x)) {
- sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
-
- if (phase >= sz) {
- phase--;
-
- break;
- }
-
- phase++;
- }
- }
-
- *len = phase - 1;
- } else {
- *len = -1;
- }
-
- int p2x = 0;
- int p2y = 0;
-
- if (!oldlen)
- oldlen = -1;
-
- if (oldlen > 0) {
- ++*mult;
-
- mov->calcSomeXY(point, 0);
- p2x = point.x;
- p2y = point.y;
-
- if (abs(p1y) > abs(p1x))
- p2x = p1x;
- else
- p2y = p1y;
- }
-
- pRes->x = p2x + p1x * newmult;
- pRes->y = p2y + p1y * newmult;
-
- return pRes;
-}
-
-ExCommand2 *MGM::buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len) {
- uint cnt;
-
- if (mov->_currMovement)
- cnt = mov->_currMovement->_dynamicPhases.size();
- else
- cnt = mov->_dynamicPhases.size();
-
- if (len > 0 && cnt > (uint)len)
- cnt = len;
-
- Common::Point **points = (Common::Point **)malloc(sizeof(Common::Point *) * cnt);
-
- for (uint i = 0; i < cnt; i++) {
- int flags = mov->getDynamicPhaseByIndex(i)->getDynFlags();
-
- points[i] = new Common::Point;
-
- if (flags & 1) {
- points[i]->x = x1 + x2->x;
-
- y2->x -= x2->x;
-
- if (!y2->x)
- x2->x = 0;
- }
-
- if (flags & 2) {
- points[i]->y = y1 + x2->y;
-
- y2->y -= x2->y;
-
- if (!y2->y)
- x2->y = 0;
- }
- }
-
- ExCommand2 *ex = new ExCommand2(20, objId, points, cnt);
- ex->_excFlags = 2;
- ex->_messageNum = mov->_id;
- ex->_field_14 = len;
- ex->_field_24 = 1;
- ex->_keyCode = -1;
-
- for (uint i = 0; i < cnt; i++)
- delete points[i];
-
- free(points);
-
- return ex;
-}
-
MovGraphLink::MovGraphLink() {
_distance = 0;
_angle = 0;
@@ -2421,7 +2789,10 @@ MovGraphLink::MovGraphLink() {
}
MovGraphLink::~MovGraphLink() {
- warning("STUB: MovGraphLink::~MovGraphLink()");
+ delete _movGraphReact;
+
+ _dwordArray1.clear();
+ _dwordArray2.clear();
}
@@ -2657,26 +3028,26 @@ bool MovGraphReact::pointInRegion(int x, int y) {
}
}
-int startWalkTo(int objId, int objKey, int x, int y, int a5) {
- MctlCompound *mc = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId);
+int startWalkTo(int objId, int objKey, int x, int y, int fuzzyMatch) {
+ MctlCompound *mc = getCurrSceneSc2MotionController();
if (mc)
- return (mc->method34(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, a5, 0) != 0);
+ return (mc->method34(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, fuzzyMatch, 0) != 0);
return 0;
}
-int doSomeAnimation(int objId, int objKey, int a3) {
+bool doSomeAnimation(int objId, int objKey, int a3) {
StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(objId, objKey);
MctlCompound *cmp = getCurrSceneSc2MotionController();
if (ani && cmp)
return cmp->method3C(ani, a3);
- return 0;
+ return false;
}
-int doSomeAnimation2(int objId, int objKey) {
+bool doSomeAnimation2(int objId, int objKey) {
return doSomeAnimation(objId, objKey, 0);
}
diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h
index 96442cac51..c488039e22 100644
--- a/engines/fullpipe/motion.h
+++ b/engines/fullpipe/motion.h
@@ -23,18 +23,19 @@
#ifndef FULLPIPE_MOTION_H
#define FULLPIPE_MOTION_H
+#include "fullpipe/mgm.h"
+
namespace Fullpipe {
-class Statics;
-class Movement;
class MctlConnectionPoint;
class MovGraphLink;
class MessageQueue;
-class ExCommand2;
+struct MovArr;
+struct MovItem;
int startWalkTo(int objId, int objKey, int x, int y, int a5);
-int doSomeAnimation(int objId, int objKey, int a3);
-int doSomeAnimation2(int objId, int objKey);
+bool doSomeAnimation(int objId, int objKey, int a3);
+bool doSomeAnimation2(int objId, int objKey);
class MotionController : public CObject {
public:
@@ -52,14 +53,14 @@ public:
virtual void addObject(StaticANIObject *obj) {}
virtual int removeObject(StaticANIObject *obj) { return 0; }
virtual void freeItems() {}
- virtual int method28() { return 0; }
- virtual int method2C(StaticANIObject *obj, int x, int y) { return 0; }
+ virtual Common::Array<MovItem *> *method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { return 0; }
+ virtual bool method2C(StaticANIObject *obj, int x, int y) { return false; }
virtual int method30() { return 0; }
virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; }
- virtual int changeCallback() { return 0; }
- virtual int method3C(StaticANIObject *ani, int flag) { return 0; }
+ virtual void changeCallback(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) {}
+ virtual bool method3C(StaticANIObject *ani, int flag) { return 0; }
virtual int method40() { return 0; }
- virtual int method44() { return 0; }
+ virtual bool method44(StaticANIObject *ani, int x, int y) { return false; }
virtual int method48() { return -1; }
virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; }
@@ -115,71 +116,13 @@ public:
virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
void initMovGraph2();
- MctlConnectionPoint *findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr);
+ MctlConnectionPoint *findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, double *minDistancePtr);
void replaceNodeX(int from, int to);
uint getMotionControllerCount() { return _motionControllers.size(); }
MotionController *getMotionController(int num) { return _motionControllers[num]->_motionControllerObj; }
};
-struct MGMSubItem {
- Movement *movement;
- int staticsIndex;
- int field_8;
- int field_C;
- int x;
- int y;
-
- MGMSubItem();
-};
-
-struct MGMItem {
- int16 objId;
- Common::Array<MGMSubItem *> subItems;
- Common::Array<Statics *> statics;
- Common::Array<Movement *> movements1;
- Common::Array<Movement *> movements2;
-
- MGMItem();
-};
-
-struct MGMInfo {
- StaticANIObject *ani;
- int staticsId1;
- int staticsId2;
- int movementId;
- int field_10;
- int x1;
- int y1;
- int field_1C;
- int x2;
- int y2;
- int flags;
-
- MGMInfo() { memset(this, 0, sizeof(MGMInfo)); }
-};
-
-class MGM : public CObject {
-public:
- Common::Array<MGMItem *> _items;
-
-public:
- void clear();
- void addItem(int objId);
- void rebuildTables(int objId);
- int getItemIndexById(int objId);
-
- MessageQueue *genMovement(MGMInfo *mgminfo);
- void updateAnimStatics(StaticANIObject *ani, int staticsId);
- Common::Point *getPoint(Common::Point *point, int aniId, int staticsId1, int staticsId2);
- int getStaticsIndexById(int idx, int16 id);
- int getStaticsIndex(int idx, Statics *st);
- void clearMovements2(int idx);
- int recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop);
- Common::Point *calcLength(Common::Point *point, Movement *mov, int x, int y, int *mult, int *len, int flag);
- ExCommand2 *buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len);
-};
-
struct MctlLadderMovementVars {
int varUpGo;
int varDownGo;
@@ -205,7 +148,7 @@ public:
int _height;
int _ladder_field_20;
int _ladder_field_24;
- Common::List<MctlLadderMovement *> _movements;
+ Common::Array<MctlLadderMovement *> _ladmovements;
MGM _mgm;
public:
@@ -296,18 +239,32 @@ class MovGraphLink : public CObject {
void calcNodeDistanceAndAngle();
};
+struct MovStep {
+ int sfield_0;
+ MovGraphLink *link;
+};
+
+struct MovArr {
+ Common::Array<MovStep *> _movSteps;
+ int _movStepCount;
+ int _afield_8;
+ MovGraphLink *_link;
+ double _dist;
+ Common::Point _point;
+};
+
+struct MovItem {
+ MovArr *movarr;
+ int _mfield_4;
+ int _mfield_8;
+ int _mfield_C;
+};
+
struct MovGraphItem {
StaticANIObject *ani;
int field_4;
- int field_8;
- int field_C;
- int field_10;
- int field_14;
- int field_18;
- int field_1C;
- int field_20;
- int field_24;
- int items;
+ MovArr movarr;
+ Common::Array<MovItem *> *movitems;
int count;
int field_30;
int field_34;
@@ -315,6 +272,7 @@ struct MovGraphItem {
int field_3C;
MovGraphItem();
+ void free();
};
class MovGraph : public MotionController {
@@ -323,7 +281,7 @@ public:
ObList _links;
int _field_44;
Common::Array<MovGraphItem *> _items;
- int (*_callback1)(int, int, int);
+ MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter);
MGM _mgm;
public:
@@ -335,19 +293,28 @@ public:
virtual void addObject(StaticANIObject *obj);
virtual int removeObject(StaticANIObject *obj);
virtual void freeItems();
- virtual int method28();
- virtual int method2C(StaticANIObject *obj, int x, int y);
+ virtual Common::Array<MovItem *> *method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount);
+ virtual bool method2C(StaticANIObject *obj, int x, int y);
virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
- virtual int changeCallback();
- virtual int method3C(StaticANIObject *ani, int flag);
- virtual int method44();
+ virtual void changeCallback(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter));
+ virtual bool method3C(StaticANIObject *ani, int flag);
+ virtual bool method44(StaticANIObject *ani, int x, int y);
virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
- virtual int method50();
+ virtual MessageQueue *method50(StaticANIObject *ani, MovArr *movarr, int staticsId);
double calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch);
void calcNodeDistancesAndAngles();
+ bool findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr);
MovGraphNode *calcOffset(int ox, int oy);
int getItemIndexByStaticAni(StaticANIObject *ani);
+ Common::Array<MovArr *> *genMovArr(int x, int y, int *arrSize, int flag1, int flag2);
+ void findAllPaths(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array<MovGraphLink *> &tempObList1, Common::Array<MovGraphLink *> &tempObList2);
+ Common::Array<MovItem *> *calcMovItems(MovArr *movarr1, MovArr *movarr2, int *listCount);
+ void genMovItem(MovItem *movitem, MovGraphLink *grlink, MovArr *movarr1, MovArr *movarr2);
+ bool calcChunk(int idx, int x, int y, MovArr *arr, int a6);
+ MessageQueue *sub1(StaticANIObject *ani, int x, int y, int a5, int x1, int y1, int a8, int a9);
+ MessageQueue *fillMGMinfo(StaticANIObject *ani, MovArr *movarr, int staticsId);
+ void setEnds(MovStep *step1, MovStep *step2);
};
class Movement;
diff --git a/engines/fullpipe/scene.cpp b/engines/fullpipe/scene.cpp
index 462401b3b2..8463b3ab40 100644
--- a/engines/fullpipe/scene.cpp
+++ b/engines/fullpipe/scene.cpp
@@ -133,7 +133,27 @@ Scene::Scene() {
}
Scene::~Scene() {
- warning("STUB: Scene::~Scene()");
+ delete _soundList;
+ delete _shadows;
+ delete _palette;
+
+ // _faObjlist is not used
+
+ for (uint i = 0; i < _messageQueueList.size(); i++)
+ delete _messageQueueList[i];
+
+ _messageQueueList.clear();
+
+ for (uint i = 0; i < _staticANIObjectList1.size(); i++)
+ delete _staticANIObjectList1[i];
+
+ _staticANIObjectList1.clear();
+
+ delete _libHandle;
+
+ // delete _field_BC;
+
+ free(_sceneName);
}
bool Scene::load(MfcArchive &file) {
@@ -249,7 +269,7 @@ bool Scene::load(MfcArchive &file) {
void Scene::initStaticANIObjects() {
for (uint i = 0; i < _staticANIObjectList1.size(); i++)
- ((StaticANIObject *)_staticANIObjectList1[i])->initMovements();
+ _staticANIObjectList1[i]->initMovements();
}
void Scene::init() {
@@ -262,13 +282,13 @@ void Scene::init() {
((PictureObject *)_picObjList[i])->clearFlags();
for (uint i = 0; i < _staticANIObjectList1.size(); i++)
- ((StaticANIObject *)_staticANIObjectList1[i])->clearFlags();
+ _staticANIObjectList1[i]->clearFlags();
if (_staticANIObjectList2.size() != _staticANIObjectList1.size()) {
_staticANIObjectList2.clear();
- for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s)
- _staticANIObjectList2.push_back(*s);
+ for (uint i = 0; i < _staticANIObjectList1.size(); i++)
+ _staticANIObjectList2.push_back(_staticANIObjectList1[i]);
}
}
@@ -281,35 +301,33 @@ StaticANIObject *Scene::getAniMan() {
}
StaticANIObject *Scene::getStaticANIObject1ById(int obj, int a3) {
- for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s) {
- StaticANIObject *o = (StaticANIObject *)*s;
- if (o->_id == obj && (a3 == -1 || o->_okeyCode == a3))
- return o;
+ for (uint i = 0; i < _staticANIObjectList1.size(); i++) {
+ if (_staticANIObjectList1[i]->_id == obj && (a3 == -1 || _staticANIObjectList1[i]->_okeyCode == a3))
+ return _staticANIObjectList1[i];
}
return 0;
}
StaticANIObject *Scene::getStaticANIObject1ByName(char *name, int a3) {
- for (uint n = 0; n < _staticANIObjectList1.size(); n++) {
- StaticANIObject *o = (StaticANIObject *)_staticANIObjectList1[n];
- if (!strcmp(o->_objectName, name) && (a3 == -1 || o->_okeyCode == a3))
- return o;
+ for (uint i = 0; i < _staticANIObjectList1.size(); i++) {
+ if (!strcmp(_staticANIObjectList1[i]->_objectName, name) && (a3 == -1 || _staticANIObjectList1[i]->_okeyCode == a3))
+ return _staticANIObjectList1[i];
}
return 0;
}
void Scene::deleteStaticANIObject(StaticANIObject *obj) {
- for (uint n = 0; n < _staticANIObjectList1.size(); n++)
- if ((StaticANIObject *)_staticANIObjectList1[n] == obj) {
- _staticANIObjectList1.remove_at(n);
+ for (uint i = 0; i < _staticANIObjectList1.size(); i++)
+ if (_staticANIObjectList1[i] == obj) {
+ _staticANIObjectList1.remove_at(i);
break;
}
- for (uint n = 0; n < _staticANIObjectList2.size(); n++)
- if ((StaticANIObject *)_staticANIObjectList2[n] == obj) {
- _staticANIObjectList2.remove_at(n);
+ for (uint i = 0; i < _staticANIObjectList2.size(); i++)
+ if (_staticANIObjectList2[i] == obj) {
+ _staticANIObjectList2.remove_at(i);
break;
}
}
@@ -335,11 +353,12 @@ void Scene::setPictureObjectsFlag4() {
}
void Scene::stopAllSounds() {
- warning("STUB: Scene:stopAllSounds()");
+ for (int i = 0; i < _soundList->getCount(); i++)
+ _soundList->getSoundByIndex(i)->stop();
}
PictureObject *Scene::getPictureObjectById(int objId, int flags) {
- for (uint i = 0; i < _picObjList.size(); i++) {
+ for (uint i = 1; i < _picObjList.size(); i++) {
if (((PictureObject *)_picObjList[i])->_id == objId && ((PictureObject *)_picObjList[i])->_okeyCode == flags)
return (PictureObject *)_picObjList[i];
}
@@ -369,16 +388,16 @@ void Scene::deletePictureObject(PictureObject *obj) {
MessageQueue *Scene::getMessageQueueById(int messageId) {
for (uint i = 0; i < _messageQueueList.size(); i++)
- if (((MessageQueue *)_messageQueueList[i])->_dataId == messageId)
- return (MessageQueue *)_messageQueueList[i];
+ if (_messageQueueList[i]->_dataId == messageId)
+ return _messageQueueList[i];
return 0;
}
MessageQueue *Scene::getMessageQueueByName(char *name) {
for (uint i = 0; i < _messageQueueList.size(); i++)
- if (!strcmp(((MessageQueue *)_messageQueueList[i])->_queueName, name))
- return (MessageQueue *)_messageQueueList[i];
+ if (!strcmp(_messageQueueList[i]->_queueName, name))
+ return _messageQueueList[i];
return 0;
}
@@ -447,15 +466,27 @@ void Scene::initObjectCursors(const char *varname) {
}
bool Scene::compareObjPriority(const void *p1, const void *p2) {
- if (((const StaticANIObject *)p1)->_priority > ((const StaticANIObject *)p2)->_priority)
+ if (((const GameObject *)p1)->_priority > ((const GameObject *)p2)->_priority)
return true;
return false;
}
-void Scene::objectList_sortByPriority(PtrList &list, bool skipFirst) {
+void Scene::objectList_sortByPriority(Common::Array<StaticANIObject *> &list, bool skipFirst) {
if (skipFirst) {
- PtrList::iterator s = list.begin();
+ Common::Array<StaticANIObject *>::iterator s = list.begin();
+
+ ++s;
+
+ Common::sort(s, list.end(), Scene::compareObjPriority);
+ } else {
+ Common::sort(list.begin(), list.end(), Scene::compareObjPriority);
+ }
+}
+
+void Scene::objectList_sortByPriority(Common::Array<PictureObject *> &list, bool skipFirst) {
+ if (skipFirst) {
+ Common::Array<PictureObject *>::iterator s = list.begin();
++s;
@@ -476,16 +507,15 @@ void Scene::draw() {
objectList_sortByPriority(_staticANIObjectList2);
- for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) {
- ((StaticANIObject *)*s)->draw2();
- }
+ for (uint i = 0; i < _staticANIObjectList2.size(); i++)
+ _staticANIObjectList2[i]->draw2();
int priority = -1;
- for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) {
- drawContent(((StaticANIObject *)*s)->_priority, priority, false);
- ((StaticANIObject *)*s)->draw();
+ for (uint i = 0; i < _staticANIObjectList2.size(); i++) {
+ drawContent(_staticANIObjectList2[i]->_priority, priority, false);
+ _staticANIObjectList2[i]->draw();
- priority = ((StaticANIObject *)*s)->_priority;
+ priority = _staticANIObjectList2[i]->_priority;
}
drawContent(-1, priority, false);
@@ -566,7 +596,7 @@ StaticANIObject *Scene::getStaticANIObjectAtPos(int x, int y) {
StaticANIObject *res = 0;
for (uint i = 0; i < _staticANIObjectList1.size(); i++) {
- StaticANIObject *p = (StaticANIObject *)_staticANIObjectList1[i];
+ StaticANIObject *p = _staticANIObjectList1[i];
int pixel;
if ((p->_field_8 & 0x100) && (p->_flags & 4) &&
@@ -612,8 +642,8 @@ int Scene::getPictureObjectIdAtPos(int x, int y) {
void Scene::update(int counterdiff) {
debug(6, "Scene::update(%d)", counterdiff);
- for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s)
- ((StaticANIObject *)*s)->update(counterdiff);
+ for (uint i = 0; i < _staticANIObjectList2.size(); i++)
+ _staticANIObjectList2[i]->update(counterdiff);
}
void Scene::drawContent(int minPri, int maxPri, bool drawBg) {
@@ -624,7 +654,7 @@ void Scene::drawContent(int minPri, int maxPri, bool drawBg) {
g_fp->_globalPalette = _palette->_data;
}
- debug(8, "Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg);
+ debug(1, "Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg);
if (_picObjList.size() > 2) { // We need to z-sort them
objectList_sortByPriority(_picObjList, true);
@@ -636,11 +666,17 @@ void Scene::drawContent(int minPri, int maxPri, bool drawBg) {
if (maxPri == -1)
maxPri = 60000;
- debug(8, "-> Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg);
+ debug(1, "-> Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg);
Common::Point point;
- debug(8, "_bigPict: %d objlist: %d", _bigPictureArray1Count, _picObjList.size());
+ debug(1, "_bigPict: %d objlist: %d", _bigPictureArray1Count, _picObjList.size());
+
+ for (uint i = 0; i < _picObjList.size(); i++) {
+ debug(1, "%d: %d", i, ((PictureObject *)_picObjList[i])->_priority);
+ }
+
+
if (drawBg && _bigPictureArray1Count && _picObjList.size()) {
_bigPictureArray[0][0]->getDimensions(&point);
diff --git a/engines/fullpipe/scene.h b/engines/fullpipe/scene.h
index 8306974f7b..1e2dae81fe 100644
--- a/engines/fullpipe/scene.h
+++ b/engines/fullpipe/scene.h
@@ -31,10 +31,10 @@ class MessageQueue;
class Scene : public Background {
public:
- PtrList _staticANIObjectList1;
- PtrList _staticANIObjectList2;
- PtrList _messageQueueList;
- PtrList _faObjectList;
+ Common::Array<StaticANIObject *> _staticANIObjectList1;
+ Common::Array<StaticANIObject *> _staticANIObjectList2;
+ Common::Array<MessageQueue *> _messageQueueList;
+ // PtrList _faObjectList; // not used
Shadows *_shadows;
SoundList *_soundList;
int16 _sceneId;
@@ -82,7 +82,8 @@ class Scene : public Background {
private:
static bool compareObjPriority(const void *p1, const void *p2);
- void objectList_sortByPriority(PtrList &list, bool skipFirst = false);
+ void objectList_sortByPriority(Common::Array<StaticANIObject *> &list, bool skipFirst = false);
+ void objectList_sortByPriority(Common::Array<PictureObject *> &list, bool skipFirst = false);
};
class SceneTag : public CObject {
diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp
index 47c6a3c8cd..13c653ad09 100644
--- a/engines/fullpipe/scenes.cpp
+++ b/engines/fullpipe/scenes.cpp
@@ -590,10 +590,8 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
scene->setPictureObjectsFlag4();
- for (PtrList::iterator s = scene->_staticANIObjectList1.begin(); s != scene->_staticANIObjectList1.end(); ++s) {
- StaticANIObject *o = (StaticANIObject *)*s;
- o->setFlags(o->_flags & 0xFE7F);
- }
+ for (uint i = 0; i < scene->_staticANIObjectList1.size(); i++)
+ scene->_staticANIObjectList1[i]->_flags &= 0xFE7F;
PictureObject *p = accessScene(SC_INV)->getPictureObjectById(PIC_INV_MENU, 0);
p->setFlags(p->_flags & 0xFFFB);
@@ -1106,10 +1104,6 @@ int defaultUpdateCursor() {
return g_fp->_cursorId;
}
-void FullpipeEngine::processArcade(ExCommand *ex) {
- warning("STUB: FullpipeEngine::processArcade()");
-}
-
void FullpipeEngine::updateMapPiece(int mapId, int update) {
for (int i = 0; i < 200; i++) {
int hiWord = (_mapTable[i] >> 16) & 0xffff;
@@ -1460,9 +1454,31 @@ void BallChain::init(Ball **ball) {
}
Ball *BallChain::sub04(Ball *ballP, Ball *ballN) {
- warning("STUB: BallChain::sub04");
+ if (!pTail) {
+ if (!cPlexLen)
+ error("BallChain::sub04: cPlexLen is 0");
+
+ cPlex = (byte *)calloc(cPlexLen, sizeof(Ball));
+
+ Ball *runPtr = (Ball *)&cPlex[(cPlexLen - 1) * sizeof(Ball)];
+
+ for (int i = 0; i < cPlexLen; i++) {
+ runPtr->p0 = pTail;
+ pTail = runPtr;
+
+ runPtr--;
+ }
+ }
+
+ Ball *res = pTail;
+
+ pTail = res->p0;
+ res->p1 = ballP;
+ res->p0 = ballN;
+ numBalls++;
+ res->ani = 0;
- return pTail;
+ return res;
}
void BallChain::removeBall(Ball *ball) {
diff --git a/engines/fullpipe/scenes/scene04.cpp b/engines/fullpipe/scenes/scene04.cpp
index b47553ef6f..fd1ececdf2 100644
--- a/engines/fullpipe/scenes/scene04.cpp
+++ b/engines/fullpipe/scenes/scene04.cpp
@@ -324,15 +324,15 @@ void sceneHandler04_walkClimbLadder(ExCommand *ex) {
g_vars->scene04_ladder->addObject(g_fp->_aniMan);
if (g_vars->scene04_soundPlaying) {
- g_vars->scene04_ladder->_movements.front()->movVars->varUpStart = MV_MAN_STARTLADDER2;
- g_vars->scene04_ladder->_movements.front()->movVars->varUpGo = MV_MAN_GOLADDER2;
- g_vars->scene04_ladder->_movements.front()->movVars->varUpStop = MV_MAN_STOPLADDER2;
- g_vars->scene04_ladder->_movements.front()->staticIds[2] = ST_MAN_GOLADDER2;
+ g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStart = MV_MAN_STARTLADDER2;
+ g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpGo = MV_MAN_GOLADDER2;
+ g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStop = MV_MAN_STOPLADDER2;
+ g_vars->scene04_ladder->_ladmovements.front()->staticIds[2] = ST_MAN_GOLADDER2;
} else {
- g_vars->scene04_ladder->_movements.front()->movVars->varUpStart = MV_MAN_STARTLADDER;
- g_vars->scene04_ladder->_movements.front()->movVars->varUpGo = MV_MAN_GOLADDER;
- g_vars->scene04_ladder->_movements.front()->movVars->varUpStop = MV_MAN_STOPLADDER;
- g_vars->scene04_ladder->_movements.front()->staticIds[2] = ST_MAN_GOLADDER;
+ g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStart = MV_MAN_STARTLADDER;
+ g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpGo = MV_MAN_GOLADDER;
+ g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStop = MV_MAN_STOPLADDER;
+ g_vars->scene04_ladder->_ladmovements.front()->staticIds[2] = ST_MAN_GOLADDER;
}
g_fp->_aniMan->_priority = 12;
@@ -633,6 +633,7 @@ MessageQueue *sceneHandler04_kozFly5(StaticANIObject *ani, double phase) {
mq1->addExCommandToEnd(mq2->getExCommandByIndex(0)->createClone());
delete mq2;
+ mq2 = 0;
ExCommand *ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_STANDUP, 0, 0, 0, 1, 0, 0, 0);
ex->_excFlags |= 2;
@@ -662,6 +663,9 @@ MessageQueue *sceneHandler04_kozFly5(StaticANIObject *ani, double phase) {
mq1->addExCommandToEnd(ex);
}
+ if (mq2)
+ delete mq2;
+
return mq1;
}
diff --git a/engines/fullpipe/scenes/scene06.cpp b/engines/fullpipe/scenes/scene06.cpp
index d54ebf4514..06ec20dcb5 100644
--- a/engines/fullpipe/scenes/scene06.cpp
+++ b/engines/fullpipe/scenes/scene06.cpp
@@ -438,23 +438,23 @@ void sceneHandler06_catchBall() {
if (g_vars->scene06_mumsy->_movement->_id == MV_MOM_JUMPFW) {
if (g_vars->scene06_mumsy->_movement->_currDynamicPhaseIndex <= 5) {
- g_vars->scene06_mumsy->_movement->calcSomeXY(point, 0);
+ g_vars->scene06_mumsy->_movement->calcSomeXY(point, 0, g_vars->scene06_mumsy->_movement->_currDynamicPhaseIndex);
point.x = -point.x;
point.y = -point.y;
} else {
- g_vars->scene06_mumsy->_movement->calcSomeXY(point, 1);
+ g_vars->scene06_mumsy->_movement->calcSomeXY(point, 1, -1);
g_vars->scene06_mumsyPos++;
}
} else if (g_vars->scene06_mumsy->_movement->_id == MV_MOM_JUMPBK) {
if (g_vars->scene06_mumsy->_movement->_currDynamicPhaseIndex <= 4) {
- g_vars->scene06_mumsy->_movement->calcSomeXY(point, 0);
+ g_vars->scene06_mumsy->_movement->calcSomeXY(point, 0, g_vars->scene06_mumsy->_movement->_currDynamicPhaseIndex);
point.x = -point.x;
point.y = -point.y;
} else {
- g_vars->scene06_mumsy->_movement->calcSomeXY(point, 1);
+ g_vars->scene06_mumsy->_movement->calcSomeXY(point, 1, -1);
g_vars->scene06_mumsyPos--;
}
diff --git a/engines/fullpipe/scenes/scene16.cpp b/engines/fullpipe/scenes/scene16.cpp
index 9ed355fdd9..ed3c51a6c2 100644
--- a/engines/fullpipe/scenes/scene16.cpp
+++ b/engines/fullpipe/scenes/scene16.cpp
@@ -182,7 +182,7 @@ void sceneHandler16_fillMug() {
mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC16_BOYOUT), 0, 1);
mq->replaceKeyCode(-1, g_vars->scene16_walkingBoy->_okeyCode);
- if (mq->chain(g_vars->scene16_walkingBoy) || !mq)
+ if (!mq || mq->chain(g_vars->scene16_walkingBoy))
return;
} else {
if (!g_vars->scene16_walkingGirl)
diff --git a/engines/fullpipe/scenes/scene25.cpp b/engines/fullpipe/scenes/scene25.cpp
index fae311efad..a07330f057 100644
--- a/engines/fullpipe/scenes/scene25.cpp
+++ b/engines/fullpipe/scenes/scene25.cpp
@@ -442,7 +442,7 @@ void sceneHandler25_walkOnLadder(StaticANIObject *ani, Common::Point *pnt, Messa
if (flag) {
if (ani->_movement) {
- ani->_movement->calcSomeXY(point, 0);
+ ani->_movement->calcSomeXY(point, 0, ani->_movement->_currDynamicPhaseIndex);
newx = point.x;
aniY = ani->_oy - point.y;
}
@@ -479,7 +479,7 @@ void sceneHandler25_walkOnLadder(StaticANIObject *ani, Common::Point *pnt, Messa
newy = pnty;
}
- ani->getMovementById(ex->_messageNum)->calcSomeXY(point, 0);
+ ani->getMovementById(ex->_messageNum)->calcSomeXY(point, 0, -1);
pntx += point.x;
pnty += point.y;
}
diff --git a/engines/fullpipe/scenes/scene27.cpp b/engines/fullpipe/scenes/scene27.cpp
index 1431ceffba..8ec05caaff 100644
--- a/engines/fullpipe/scenes/scene27.cpp
+++ b/engines/fullpipe/scenes/scene27.cpp
@@ -340,7 +340,7 @@ void sceneHandler27_wipeDo() {
bool sceneHandler27_batFallLogic(uint batn) {
Bat *bat = g_vars->scene27_bats[batn];
- int y = (bat->currY - 458.0) * 0.4848484848484849 + 734.0;
+ int y = (int)((bat->currY - 458.0) * 0.4848484848484849 + 734.0);
if (y >= bat->currX)
return false;
diff --git a/engines/fullpipe/scenes/scene29.cpp b/engines/fullpipe/scenes/scene29.cpp
index 2d5127137d..8f82e99ad1 100644
--- a/engines/fullpipe/scenes/scene29.cpp
+++ b/engines/fullpipe/scenes/scene29.cpp
@@ -972,7 +972,7 @@ int sceneHandler29(ExCommand *cmd) {
break;
case MSG_SC29_SHOWLASTRED:
- if (g_vars->scene29_balls.numBalls) {
+ if (g_vars->scene29_redBalls.numBalls) { // original uses scene29_balls which looks like a copy/paste error
g_vars->scene29_redBalls.field_8->ani->show1(-1, -1, -1, 0);
g_vars->scene29_redBalls.field_8->ani->startAnim(MV_SHR_HITASS, 0, -1);
}
diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp
index aa91f25087..a4ca06f489 100644
--- a/engines/fullpipe/sound.cpp
+++ b/engines/fullpipe/sound.cpp
@@ -26,6 +26,9 @@
#include "fullpipe/scene.h"
#include "fullpipe/sound.h"
#include "fullpipe/ngiarchive.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/statics.h"
+
#include "common/memstream.h"
#include "audio/audiostream.h"
#include "audio/decoders/vorbis.h"
@@ -73,6 +76,18 @@ bool SoundList::loadFile(const char *fname, char *libname) {
return load(archive, libname);
}
+Sound *SoundList::getSoundItemById(int id) {
+ if (_soundItemsCount == 0) {
+ return _soundItems[0]->getId() != id ? 0 : _soundItems[0];
+ }
+
+ for (int i = 0; i < _soundItemsCount; i++) {
+ if (_soundItems[i]->getId() == id)
+ return _soundItems[i];
+ }
+ return NULL;
+}
+
Sound::Sound() {
_id = 0;
_directSoundBuffer = 0;
@@ -80,10 +95,13 @@ Sound::Sound() {
_objectId = 0;
memset(_directSoundBuffers, 0, sizeof(_directSoundBuffers));
_description = 0;
+ _volume = 100;
}
Sound::~Sound() {
- warning("STUB: Sound::~Sound()");
+ freeSound();
+
+ free(_description);
}
bool Sound::load(MfcArchive &file, NGIArchive *archive) {
@@ -116,31 +134,228 @@ void Sound::updateVolume() {
}
void Sound::setPanAndVolumeByStaticAni() {
- debug(3, "STUB Sound::setPanAndVolumeByStaticAni()");
+ if (!_objectId)
+ return;
+
+ StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(_objectId, -1);
+ if (!ani)
+ return;
+
+ int a, b;
+
+ if (ani->_ox >= g_fp->_sceneRect.left) {
+ int par, pan;
+
+ if (ani->_ox <= g_fp->_sceneRect.right) {
+ int dx;
+
+ if (ani->_oy <= g_fp->_sceneRect.bottom) {
+ if (ani->_oy >= g_fp->_sceneRect.top) {
+ setPanAndVolume(g_fp->_sfxVolume, 0);
+
+ return;
+ }
+ dx = g_fp->_sceneRect.top - ani->_oy;
+ } else {
+ dx = ani->_oy - g_fp->_sceneRect.bottom;
+ }
+
+ par = 0;
+
+ if (dx > 800) {
+ setPanAndVolume(-3500, 0);
+ return;
+ }
+
+ pan = -3500;
+ a = g_fp->_sfxVolume - (-3500);
+ b = 800 - dx;
+ } else {
+ int dx = ani->_ox - g_fp->_sceneRect.right;
+
+ if (dx > 800) {
+ setPanAndVolume(-3500, 0);
+ return;
+ }
+
+ pan = -3500;
+ par = dx * (-3500) / -800;
+ a = g_fp->_sfxVolume - (-3500);
+ b = 800 - dx;
+ }
+
+ int32 pp = b * a;
+
+ setPanAndVolume(pan + pp / 800, par);
+
+ return;
+ }
+
+ int dx = g_fp->_sceneRect.left - ani->_ox;
+ if (dx <= 800) {
+ int32 s = (800 - dx) * (g_fp->_sfxVolume - (-3500));
+ int32 p = -3500 + s / 800;
+
+ if (p > g_fp->_sfxVolume)
+ p = g_fp->_sfxVolume;
+
+ setPanAndVolume(p, dx * (-3500) / 800);
+ } else {
+ setPanAndVolume(-3500, 0);
+ }
}
void Sound::setPanAndVolume(int vol, int pan) {
- warning("STUB: Sound::setPanAndVolume");
+ g_fp->_mixer->setChannelVolume(_handle, vol / 39); // 0..10000
+ g_fp->_mixer->setChannelBalance(_handle, pan / 78); // -10000..10000
}
-void FullpipeEngine::setSceneMusicParameters(GameVar *var) {
+void Sound::play(int flag) {
+ Audio::SoundHandle handle = getHandle();
+
+ if (g_fp->_mixer->isSoundHandleActive(handle))
+ return;
+
+ byte *soundData = loadData();
+ Common::MemoryReadStream *dataStream = new Common::MemoryReadStream(soundData, getDataSize());
+ Audio::RewindableAudioStream *wav = Audio::makeWAVStream(dataStream, DisposeAfterUse::YES);
+ Audio::AudioStream *audioStream = new Audio::LoopingAudioStream(wav, (flag == 1) ? 0 : 1);
+
+ g_fp->_mixer->playStream(Audio::Mixer::kSFXSoundType, &handle, audioStream);
+}
+
+void Sound::freeSound() {
+ stop();
+
+ free(_soundData);
+}
+
+int Sound::getVolume() {
+ return g_fp->_mixer->getChannelVolume(_handle) * 39; // 0..10000
+}
+
+void Sound::stop() {
+ g_fp->_mixer->stopHandle(_handle);
+}
+
+void FullpipeEngine::setSceneMusicParameters(GameVar *gvar) {
warning("STUB: FullpipeEngine::setSceneMusicParameters()");
- // TODO: Finish this (MINDELAY, MAXDELAY, LOCAL, SEQUENCE, STARTDELAY etc)
- stopAllSoundStreams();
+#if 0
+ stopSoundStream2();
+
+ if (soundStream3)
+ FSOUND_Stream_Stop(soundStream4);
+#endif
+
+ if (_musicLocal)
+ stopAllSoundStreams();
+
+ GameVar *var = gvar->getSubVarByName("MUSIC");
+
+ memset(_sceneTracks, 0, sizeof(_sceneTracks));
+
+ _numSceneTracks = 0;
+ _sceneTrackHasSequence = false;
+
+ if (!var)
+ return;
+
_musicGameVar = var;
+
+ GameVar *tr = var->getSubVarByName("TRACKS");
+ if (tr) {
+ GameVar *sub = tr->_subVars;
+
+ while (sub) {
+ if (_musicAllowed & sub->_value.intValue) {
+ Common::strlcpy(_sceneTracks[_numSceneTracks], sub->_varName, 260);
+
+ _numSceneTracks++;
+ }
+
+ sub = sub->_nextVarObj;
+ }
+ }
+
+ _musicMinDelay = var->getSubVarAsInt("MINDELAY");
+ _musicMaxDelay = var->getSubVarAsInt("MAXDELAY");
+ _musicLocal = var->getSubVarAsInt("LOCAL");
+
+ GameVar *seq = var->getSubVarByName("SEQUENCE");
+
+ if (seq) {
+ _sceneTrackHasSequence = true;
+
+ Common::strlcpy(_trackName, seq->_value.stringValue, 2600);
+ }
+
+ if (_musicLocal)
+ stopAllSoundStreams();
+
+ if (!_sceneTrackIsPlaying || _musicLocal)
+ _trackStartDelay = var->getSubVarAsInt("STARTDELAY");
}
void FullpipeEngine::startSceneTrack() {
- // TODO: Finish this
-#ifdef USE_VORBIS
- if (g_fp->_mixer->isSoundHandleActive(_sceneTrackHandle))
- return;
+ if (!_sceneTrackIsPlaying && _numSceneTracks > 0) {
+ if (_trackStartDelay > 0) {
+ _trackStartDelay--;
+ } else {
+ int trackNum = getSceneTrack();
- GameVar *musicTrackVar = _musicGameVar->getSubVarByName("MUSIC")->getSubVarByName("TRACKS")->_subVars;
- if (!musicTrackVar)
+ if (trackNum == -1) {
+ strcpy(_sceneTracksCurrentTrack, "silence");
+
+ _trackStartDelay = 2880;
+ _sceneTrackIsPlaying = 0;
+ } else {
+ strcpy(_sceneTracksCurrentTrack, _sceneTracks[trackNum]);
+
+ startSoundStream1(_sceneTracksCurrentTrack);
+
+ _sceneTrackIsPlaying = true;
+ }
+ }
+ }
+}
+
+int FullpipeEngine::getSceneTrack() {
+ int res;
+
+ if (_sceneTrackHasSequence) {
+ int num = _musicGameVar->getSubVarAsInt("TRACKS");
+
+ if (_trackName[num + 1] == 's') { // 'silence'
+ res = -1;
+ } else {
+ res = _trackName[num + 1] - '0';
+
+ if (res < 0 || res >= _numSceneTracks)
+ res = 0;
+ }
+
+ int track = num + 1;
+
+ if (!_trackName[num + 2])
+ track = 0;
+
+ _musicGameVar->setSubVarAsInt("TRACKS", track);
+ } else {
+ res = _numSceneTracks * (_updateTicks % 10) / 10;
+ }
+
+ return res;
+}
+
+void FullpipeEngine::startSoundStream1(char *trackName) {
+ warning("STUB: FullpipeEngine::startSoundStream1(%s)", trackName);
+
+ stopAllSoundStreams();
+
+#ifdef USE_VORBIS
+ if (_mixer->isSoundHandleActive(_sceneTrackHandle))
return;
- char *trackName = musicTrackVar->_varName;
Common::File *track = new Common::File();
if (!track->open(trackName)) {
warning("Could not open %s", trackName);
@@ -148,40 +363,134 @@ void FullpipeEngine::startSceneTrack() {
return;
}
Audio::RewindableAudioStream *ogg = Audio::makeVorbisStream(track, DisposeAfterUse::YES);
- g_fp->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_sceneTrackHandle, ogg);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_sceneTrackHandle, ogg);
#endif
}
void FullpipeEngine::stopAllSounds() {
- // TODO: Differences from stopAllSoundStreams()
- g_fp->_mixer->stopAll();
+ // _mixer->stopAll();
+
+ for (int i = 0; i < _currSoundListCount; i++)
+ for (int j = 0; j < _currSoundList1[i]->getCount(); j++) {
+ _currSoundList1[i]->getSoundByIndex(j)->stop();
+ }
}
void FullpipeEngine::toggleMute() {
- warning("STUB: FullpipeEngine::toggleMute()");
+ if (_soundEnabled) {
+ _sfxVolume = _sfxVolume != -10000 ? -10000 : 0;
+
+ updateSoundVolume();
+ }
}
void FullpipeEngine::playSound(int id, int flag) {
- SoundList *soundList = g_fp->_currentScene->_soundList;
- Sound *sound = soundList->getSoundById(id);
+ Sound *sound = 0;
+
+ for (int i = 0; i < _currSoundListCount; i++) {
+ sound = _currSoundList1[i]->getSoundItemById(id);
+
+ if (sound)
+ break;
+ }
+
if (!sound) {
warning("playSound: Can't find sound with ID %d", id);
return;
}
- byte *soundData = sound->loadData();
- Common::MemoryReadStream *dataStream = new Common::MemoryReadStream(soundData, sound->getDataSize());
- Audio::RewindableAudioStream *wav = Audio::makeWAVStream(dataStream, DisposeAfterUse::YES);
- Audio::AudioStream *audioStream = new Audio::LoopingAudioStream(wav, (flag == 1) ? 0 : 1);
- Audio::SoundHandle handle = sound->getHandle();
- g_fp->_mixer->playStream(Audio::Mixer::kSFXSoundType, &handle, audioStream);
+
+ sound->play(flag);
}
void FullpipeEngine::playTrack(GameVar *sceneVar, const char *name, bool delayed) {
warning("STUB: FullpipeEngine::playTrack(var, %s, %d)", name, delayed);
+#if 0
+ stopSoundStream2();
+
+ if (soundStream3)
+ FSOUND_Stream_Stop(soundStream4);
+#endif
+
+ if (_musicLocal)
+ stopAllSoundStreams();
+
+ GameVar *var = sceneVar->getSubVarByName(name);
+
+ memset(_sceneTracks, 0, sizeof(_sceneTracks));
+
+ _numSceneTracks = 0;
+ _sceneTrackHasSequence = false;
+
+ if (!var)
+ return;
+
+ _musicGameVar = var;
+
+ GameVar *tr = var->getSubVarByName("TRACKS");
+ if (tr) {
+ GameVar *sub = tr->_subVars;
+
+ while (sub) {
+ if (_musicAllowed & sub->_value.intValue) {
+ Common::strlcpy(_sceneTracks[_numSceneTracks], sub->_varName, 260);
+
+ _numSceneTracks++;
+ }
+
+ sub = sub->_nextVarObj;
+ }
+ }
+
+ _musicMinDelay = var->getSubVarAsInt("MINDELAY");
+ _musicMaxDelay = var->getSubVarAsInt("MAXDELAY");
+ _musicLocal = var->getSubVarAsInt("LOCAL");
+
+ GameVar *seq = var->getSubVarByName("SEQUENCE");
+
+ if (seq) {
+ _sceneTrackHasSequence = true;
+
+ Common::strlcpy(_trackName, seq->_value.stringValue, 2600);
+ }
+
+ if (delayed) {
+ if (_sceneTrackIsPlaying && _numSceneTracks == 1) {
+ if (strcmp(_sceneTracksCurrentTrack, _sceneTracks[0]))
+ stopAllSoundStreams();
+ }
+
+ _trackStartDelay = var->getSubVarAsInt("STARTDELAY");
+ }
}
void global_messageHandler_handleSound(ExCommand *cmd) {
- debug(0, "STUB: global_messageHandler_handleSound()");
+ if (!g_fp->_soundEnabled)
+ return;
+
+ Sound *snd = 0;
+
+ for (int i = 0; i < g_fp->_currSoundListCount; i++)
+ snd = g_fp->_currSoundList1[i]->getSoundItemById(cmd->_messageNum);
+
+ if (!snd)
+ return;
+
+ if (cmd->_field_14 & 1) {
+ if (!g_fp->_flgSoundList && (cmd->_field_14 & 4))
+ snd->freeSound();
+
+ snd->updateVolume();
+
+ if (snd->_objectId && g_fp->_currentScene->getStaticANIObject1ById(snd->_objectId, -1))
+ snd->setPanAndVolumeByStaticAni();
+ else
+ snd->setPanAndVolume(g_fp->_sfxVolume, 0);
+
+ if (snd->getVolume() > -3500)
+ snd->play(cmd->_keyCode);
+ } else if (cmd->_field_14 & 2) {
+ snd->stop();
+ }
}
void FullpipeEngine::stopSoundStream2() {
@@ -190,27 +499,29 @@ void FullpipeEngine::stopSoundStream2() {
void FullpipeEngine::stopAllSoundStreams() {
// TODO: Differences from stopAllSounds()
- g_fp->_mixer->stopAll();
+ _mixer->stopAll();
}
void FullpipeEngine::stopAllSoundInstances(int id) {
- SoundList *soundList = g_fp->_currentScene->_soundList;
- for (int i = 0; i < soundList->getCount(); i++) {
- Sound *sound = soundList->getSoundByIndex(i);
- if (sound->getId() == id) {
- g_fp->_mixer->stopHandle(sound->getHandle());
- }
+ for (int i = 0; i < _currSoundListCount; i++) {
+ Sound *sound = _currSoundList1[i]->getSoundItemById(id);
+
+ if (sound)
+ sound->stop();
}
}
void FullpipeEngine::updateSoundVolume() {
- debug(3, "STUB FullpipeEngine::updateSoundVolume()");
+ for (int i = 0; i < _currSoundListCount; i++)
+ for (int j = 0; i < _currSoundList1[i]->getCount(); j++) {
+ _currSoundList1[i]->getSoundByIndex(j)->setPanAndVolume(_sfxVolume, 0);
+ }
}
void FullpipeEngine::setMusicVolume(int vol) {
_musicVolume = vol;
- debug(3, "STUB FullpipeEngine::setMusicVolume()");
+ g_fp->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol);
}
} // End of namespace Fullpipe
diff --git a/engines/fullpipe/sound.h b/engines/fullpipe/sound.h
index e284e5efab..14e766f5bb 100644
--- a/engines/fullpipe/sound.h
+++ b/engines/fullpipe/sound.h
@@ -32,6 +32,7 @@ class Sound : public MemoryObject {
int _directSoundBuffers[7];
byte *_soundData;
Audio::SoundHandle _handle;
+ int _volume;
public:
int16 _objectId;
@@ -46,6 +47,11 @@ public:
int getId() const { return _id; }
Audio::SoundHandle getHandle() const { return _handle; }
+ void play(int flag);
+ void freeSound();
+ int getVolume();
+ void stop();
+
void setPanAndVolumeByStaticAni();
void setPanAndVolume(int vol, int pan);
};
@@ -63,13 +69,7 @@ class SoundList : public CObject {
int getCount() { return _soundItemsCount; }
Sound *getSoundByIndex(int idx) { return _soundItems[idx]; }
- Sound *getSoundById(int id) {
- for (int i = 0; i < _soundItemsCount; i++) {
- if (_soundItems[i]->getId() == id)
- return _soundItems[i];
- }
- return NULL;
- }
+ Sound *getSoundItemById(int id);
};
} // End of namespace Fullpipe
diff --git a/engines/fullpipe/stateloader.cpp b/engines/fullpipe/stateloader.cpp
index e36b196517..141196c7d7 100644
--- a/engines/fullpipe/stateloader.cpp
+++ b/engines/fullpipe/stateloader.cpp
@@ -55,9 +55,8 @@ bool FullpipeEngine::loadGam(const char *fname, int scene) {
_inventory->rebuildItemRects();
- for (PtrList::iterator p = _inventory->getScene()->_picObjList.begin(); p != _inventory->getScene()->_picObjList.end(); ++p) {
- ((MemoryObject *)((PictureObject *)*p)->_picture)->load();
- }
+ for (uint i = 0; i < _inventory->getScene()->_picObjList.size(); i++)
+ ((MemoryObject *)_inventory->getScene()->_picObjList[i]->_picture)->load();
// _sceneSwitcher = sceneSwitcher; // substituted with direct call
_gameLoader->_preloadCallback = preloadCallback;
@@ -163,7 +162,43 @@ GameVar::GameVar() {
}
GameVar::~GameVar() {
- warning("STUB: GameVar::~GameVar()");
+ if (_varType == 2)
+ free(_value.stringValue);
+
+ if (_parentVarObj && !_prevVarObj ) {
+ if (_parentVarObj->_subVars == this) {
+ _parentVarObj->_subVars = _nextVarObj;
+ } else if (_parentVarObj->_field_14 == this) {
+ _parentVarObj->_field_14 = _nextVarObj;
+ } else {
+ _parentVarObj = 0;
+ }
+ }
+
+ if (_prevVarObj)
+ _prevVarObj->_nextVarObj = _nextVarObj;
+
+ if (_nextVarObj)
+ _nextVarObj->_prevVarObj = _prevVarObj;
+
+ _prevVarObj = 0;
+ _nextVarObj = 0;
+
+ GameVar *s = _subVars;
+
+ while (s) {
+ delete s;
+ s = _subVars;
+ }
+
+ s = _field_14;
+
+ while (s) {
+ delete s;
+ s = _field_14;
+ }
+
+ free(_varName);
}
bool GameVar::load(MfcArchive &file) {
diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp
index a3a160b5b2..717de84925 100644
--- a/engines/fullpipe/statics.cpp
+++ b/engines/fullpipe/statics.cpp
@@ -141,7 +141,17 @@ StaticANIObject::StaticANIObject() {
}
StaticANIObject::~StaticANIObject() {
- warning("STUB: StaticANIObject::~StaticANIObject()");
+ for (uint i = 0; i < _staticsList.size(); i++)
+ delete _staticsList[i];
+
+ _staticsList.clear();
+
+ for (uint i = 0; i < _movements.size(); i++)
+ delete _movements[i];
+
+ _movements.clear();
+
+ g_fp->_mgm->clear();
}
StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) {
@@ -164,22 +174,21 @@ StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) {
_objtype = kObjTypeStaticANIObject;
for (uint i = 0; i < src->_staticsList.size(); i++)
- _staticsList.push_back(new Statics((Statics *)src->_staticsList[i], 0));
+ _staticsList.push_back(new Statics(src->_staticsList[i], 0));
_movement = 0;
_statics = 0;
for (uint i = 0; i < src->_movements.size(); i++) {
Movement *newmov;
- Movement *mov = (Movement *)src->_movements[i];
- if (mov->_currMovement) {
+ if (src->_movements[i]->_currMovement) {
// WORKAROUND: Original uses weird construction here:
// new Movement(getMovementById(src->getMovementIdById(mov->_id)), this);
- newmov = new Movement(src->getMovementById(src->getMovementIdById(mov->_id)), this);
- newmov->_id = mov->_id;
+ newmov = new Movement(src->getMovementById(src->getMovementIdById(src->_movements[i]->_id)), this);
+ newmov->_id = src->_movements[i]->_id;
} else {
- newmov = new Movement(mov, 0, -1, this);
+ newmov = new Movement(src->_movements[i], 0, -1, this);
}
_movements.push_back(newmov);
@@ -224,7 +233,7 @@ bool StaticANIObject::load(MfcArchive &file) {
Common::Point pt;
if (count) { // We have movements
- ((Movement *)_movements[0])->getCurrDynamicPhaseXY(pt);
+ _movements[0]->getCurrDynamicPhaseXY(pt);
} else {
pt.x = pt.y = 100;
}
@@ -277,8 +286,11 @@ void StaticANIObject::deleteFromGlobalMessageQueue() {
}
}
-void StaticANIObject::queueMessageQueue(MessageQueue *mq) {
- if (isIdle() && !(_flags & 0x80)) {
+bool StaticANIObject::queueMessageQueue(MessageQueue *mq) {
+ if (_flags & 0x80)
+ return false;
+
+ if (isIdle()) {
deleteFromGlobalMessageQueue();
_messageQueueId = 0;
_messageNum = 0;
@@ -296,6 +308,8 @@ void StaticANIObject::queueMessageQueue(MessageQueue *mq) {
_messageQueueId = 0;
}
}
+
+ return true;
}
void StaticANIObject::restartMessageQueue(MessageQueue *mq) {
@@ -387,34 +401,36 @@ bool StaticANIObject::isIdle() {
Statics *StaticANIObject::getStaticsById(int itemId) {
for (uint i = 0; i < _staticsList.size(); i++)
- if (((Statics *)_staticsList[i])->_staticsId == itemId)
- return (Statics *)_staticsList[i];
+ if (_staticsList[i]->_staticsId == itemId)
+ return _staticsList[i];
return 0;
}
Statics *StaticANIObject::getStaticsByName(char *name) {
for (uint i = 0; i < _staticsList.size(); i++)
- if (!strcmp(((Statics *)_staticsList[i])->_staticsName, name))
- return (Statics *)_staticsList[i];
+ if (!strcmp(_staticsList[i]->_staticsName, name))
+ return _staticsList[i];
return 0;
}
Movement *StaticANIObject::getMovementById(int itemId) {
for (uint i = 0; i < _movements.size(); i++)
- if (((Movement *)_movements[i])->_id == itemId)
- return (Movement *)_movements[i];
+ if (_movements[i]->_id == itemId)
+ return _movements[i];
return 0;
}
int StaticANIObject::getMovementIdById(int itemId) {
for (uint i = 0; i < _movements.size(); i++) {
- Movement *mov = (Movement *)_movements[i];
+ Movement *mov = _movements[i];
+
if (mov->_currMovement) {
if (mov->_id == itemId)
return mov->_id;
+
if (mov->_currMovement->_id == itemId)
return mov->_id;
}
@@ -425,8 +441,8 @@ int StaticANIObject::getMovementIdById(int itemId) {
Movement *StaticANIObject::getMovementByName(char *name) {
for (uint i = 0; i < _movements.size(); i++)
- if (!strcmp(((Movement *)_movements[i])->_objectName, name))
- return (Movement *)_movements[i];
+ if (!strcmp(_movements[i]->_objectName, name))
+ return _movements[i];
return 0;
}
@@ -512,15 +528,15 @@ void Movement::draw(bool flipFlag, int angle) {
if (_currMovement) {
bmp = _currDynamicPhase->getPixelData()->reverseImage();
} else {
- bmp = _currDynamicPhase->getPixelData();
+ bmp = _currDynamicPhase->getPixelData()->reverseImage(false);
}
if (flipFlag) {
- bmp->flipVertical()->drawShaded(1, x, y + 30 + _currDynamicPhase->_rect->bottom, _currDynamicPhase->_paletteData);
+ bmp->flipVertical()->drawShaded(1, x, y + 30 + _currDynamicPhase->_rect->bottom, _currDynamicPhase->_paletteData, _currDynamicPhase->_alpha);
} if (angle) {
- bmp->drawRotated(x, y, angle, _currDynamicPhase->_paletteData);
+ bmp->drawRotated(x, y, angle, _currDynamicPhase->_paletteData, _currDynamicPhase->_alpha);
} else {
- bmp->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData);
+ bmp->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData, _currDynamicPhase->_alpha);
}
if (_currDynamicPhase->_rect->top) {
@@ -533,11 +549,11 @@ void Movement::draw(bool flipFlag, int angle) {
if (_currDynamicPhase->_convertedBitmap) {
if (_currMovement) {
//vrtSetAlphaBlendMode(g_vrtDrawHandle, 1, LOBYTE(_currDynamicPhase->rect.top));
- _currDynamicPhase->_convertedBitmap->reverseImage()->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData);
+ _currDynamicPhase->_convertedBitmap->reverseImage()->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData, _currDynamicPhase->_alpha);
//vrtSetAlphaBlendMode(g_vrtDrawHandle, 0, 255);
} else {
//vrtSetAlphaBlendMode(g_vrtDrawHandle, 1, LOBYTE(_currDynamicPhase->rect.top));
- _currDynamicPhase->_convertedBitmap->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData);
+ _currDynamicPhase->_convertedBitmap->reverseImage(false)->putDib(x, y, (int32 *)_currDynamicPhase->_paletteData, _currDynamicPhase->_alpha);
//vrtSetAlphaBlendMode(g_vrtDrawHandle, 0, 255);
}
}
@@ -546,12 +562,12 @@ void Movement::draw(bool flipFlag, int angle) {
void StaticANIObject::loadMovementsPixelData() {
for (uint i = 0; i < _movements.size(); i++)
- ((Movement *)_movements[i])->loadPixelData();
+ _movements[i]->loadPixelData();
}
void StaticANIObject::freeMovementsPixelData() {
for (uint i = 0; i < _movements.size(); i++)
- ((Movement *)_movements[i])->freePixelData();
+ _movements[i]->freePixelData();
}
Statics *StaticANIObject::addReverseStatics(Statics *st) {
@@ -660,11 +676,10 @@ MovTable *StaticANIObject::countMovements() {
movTable->movs = (int16 *)calloc(_movements.size(), sizeof(int16));
for (uint i = 0; i < _movements.size(); i++) {
- GameObject *obj = (GameObject *)_movements[i];
movTable->movs[i] = 2;
for (GameVar *sub = preloadSubVar->_subVars; sub; sub = sub->_nextVarObj) {
- if (scumm_stricmp(obj->getName(), sub->_varName) == 0) {
+ if (scumm_stricmp(_movements[i]->getName(), sub->_varName) == 0) {
movTable->movs[i] = 1;
break;
}
@@ -697,21 +712,21 @@ void StaticANIObject::setSpeed(int speed) {
void StaticANIObject::setAlpha(int alpha) {
for (uint i = 0; i < _movements.size(); i++)
- ((Movement *)_movements[i])->setAlpha(alpha);
+ _movements[i]->setAlpha(alpha);
for (uint i = 0; i < _staticsList.size(); i++)
- ((Statics *)_staticsList[i])->setAlpha(alpha);
+ _staticsList[i]->setAlpha(alpha);
}
void StaticANIObject::initMovements() {
for (uint i = 0; i < _movements.size(); i++)
- ((Movement *)_movements[i])->removeFirstPhase();
+ _movements[i]->removeFirstPhase();
}
void StaticANIObject::preloadMovements(MovTable *mt) {
- if ( mt ) {
+ if (mt) {
for (uint i = 0; i < _movements.size(); i++) {
- Movement *mov = (Movement *)_movements[i];
+ Movement *mov = _movements[i];
if (mt->movs[i] == 1)
mov->loadPixelData();
@@ -878,7 +893,7 @@ void StaticANIObject::updateStepPos() {
int ox = _movement->_ox;
int oy = _movement->_oy;
- _movement->calcSomeXY(point, 1);
+ _movement->calcSomeXY(point, 1, _someDynamicPhaseIndex);
int x = point.x;
int y = point.y;
@@ -902,7 +917,7 @@ Common::Point *StaticANIObject::calcNextStep(Common::Point *pRes) {
Common::Point point;
- _movement->calcSomeXY(point, 1);
+ _movement->calcSomeXY(point, 1, _someDynamicPhaseIndex);
int resX = point.x;
int resY = point.y;
@@ -964,11 +979,12 @@ void StaticANIObject::stopAnim_maybe() {
_ox += point.x;
_oy += point.y;
}
+ } else {
+ _statics = _movement->_staticsObj2;
}
- }
-
- if (_movement->_currDynamicPhaseIndex || !(_flags & 0x40))
+ } else {
_statics = _movement->_staticsObj2;
+ }
_statics->getSomeXY(point);
@@ -1001,11 +1017,11 @@ void StaticANIObject::adjustSomeXY() {
if (_movement) {
Common::Point point;
- _movement->calcSomeXY(point, 0);
+ _movement->calcSomeXY(point, 0, -1);
int diff = abs(point.y) - abs(point.x);
- _movement->calcSomeXY(point, 1);
+ _movement->calcSomeXY(point, 1, -1);
if (diff > 0)
_ox += point.x;
@@ -1019,9 +1035,26 @@ void StaticANIObject::adjustSomeXY() {
}
MessageQueue *StaticANIObject::changeStatics1(int msgNum) {
- warning("STUB: StaticANIObject::changeStatics1(%d)", msgNum);
+ g_fp->_mgm->addItem(_id);
- return 0;
+ MessageQueue *mq = g_fp->_mgm->genMQ(this, msgNum, 0, 0, 0);
+
+ if (!mq)
+ return 0;
+
+ if (mq->getCount() <= 0) {
+ g_fp->_globalMessageQueueList->addMessageQueue(mq);
+
+ if (_flags & 1)
+ _messageQueueId = mq->_id;
+ } else {
+ if (!queueMessageQueue(mq))
+ return 0;
+
+ g_fp->_globalMessageQueueList->addMessageQueue(mq);
+ }
+
+ return mq;
}
void StaticANIObject::changeStatics2(int objId) {
@@ -1155,8 +1188,8 @@ void StaticANIObject::startAnimSteps(int movementId, int messageQueueId, int x,
if (!(_flags & 0x80)) {
if (!_messageQueueId)
for (uint i = 0; i < _movements.size(); i++) {
- if (((Movement *)_movements[i])->_id == movementId) {
- mov = (Movement *)_movements[i];
+ if (_movements[i]->_id == movementId) {
+ mov = _movements[i];
break;
}
}
@@ -1244,7 +1277,7 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase
if (_flags & 0x80)
return false;
- debug(0, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy);
+ debug(4, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy);
if (_messageQueueId) {
updateGlobalMessageQueue(messageQueueId, _id);
@@ -1254,9 +1287,8 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase
Movement *mov = 0;
for (uint i = 0; i < _movements.size(); i++) {
-
- if (((Movement *)_movements[i])->_id == movementId) {
- mov = (Movement *)_movements[i];
+ if (_movements[i]->_id == movementId) {
+ mov = _movements[i];
break;
}
}
@@ -1347,6 +1379,31 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase
return true;
}
+Common::Point *StaticANIObject::calcStepLen(Common::Point *p) {
+ if (_movement) {
+ Common::Point point;
+
+ _movement->calcSomeXY(point, 0, _movement->_currDynamicPhaseIndex);
+
+ p->x = point.x;
+ p->y = point.y;
+
+ int idx = _stepArray.getCurrPointIndex() - _movement->_currDynamicPhaseIndex - 1;
+
+ if (idx >= 0) {
+ _stepArray.getPoint(&point, idx, _movement->_currDynamicPhaseIndex + 2);
+
+ p->x += point.x;
+ p->y += point.y;
+ }
+ } else {
+ p->x = 0;
+ p->y = 0;
+ }
+
+ return p;
+}
+
Statics::Statics() {
_staticsId = 0;
_picture = 0;
@@ -1394,6 +1451,13 @@ bool Statics::load(MfcArchive &file) {
return true;
}
+void Statics::init() {
+ Picture::init();
+
+ if (_staticsId & 0x4000)
+ _bitmap->reverseImage();
+}
+
Common::Point *Statics::getSomeXY(Common::Point &p) {
p.x = _someX;
p.y = _someY;
@@ -1446,7 +1510,17 @@ Movement::Movement() {
}
Movement::~Movement() {
- warning("STUB: Movement::~Movement()");
+ for (uint i = 0; i < _dynamicPhases.size(); i++)
+ delete _framePosOffsets[i];
+
+ if (!_currMovement ) {
+ if (_updateFlag1)
+ _dynamicPhases.remove_at(0);
+
+ _dynamicPhases.clear();
+ }
+
+ free(_framePosOffsets);
}
Movement::Movement(Movement *src, StaticANIObject *ani) {
@@ -1663,7 +1737,7 @@ Common::Point *Movement::getCurrDynamicPhaseXY(Common::Point &p) {
return &p;
}
-Common::Point *Movement::calcSomeXY(Common::Point &p, int idx) {
+Common::Point *Movement::calcSomeXY(Common::Point &p, int idx, int dynidx) {
int oldox = _ox;
int oldoy = _oy;
int oldidx = _currDynamicPhaseIndex;
@@ -1686,8 +1760,8 @@ Common::Point *Movement::calcSomeXY(Common::Point &p, int idx) {
setOXY(x, y);
- while (_currDynamicPhaseIndex != idx)
- gotoNextFrame(0, 0);
+ while (_currDynamicPhaseIndex != dynidx && gotoNextFrame(0, 0))
+ ;
p.x = _ox;
p.y = _oy;
@@ -1701,11 +1775,11 @@ Common::Point *Movement::calcSomeXY(Common::Point &p, int idx) {
void Movement::setAlpha(int alpha) {
if (_currMovement)
for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) {
- ((DynamicPhase *)_currMovement->_dynamicPhases[i])->setAlpha(alpha);
+ _currMovement->_dynamicPhases[i]->setAlpha(alpha);
}
else
for (uint i = 0; i < _dynamicPhases.size(); i++) {
- ((DynamicPhase *)_dynamicPhases[i])->setAlpha(alpha);
+ _dynamicPhases[i]->setAlpha(alpha);
}
}
@@ -1718,9 +1792,9 @@ Common::Point *Movement::getDimensionsOfPhase(Common::Point *p, int phaseIndex)
DynamicPhase *dyn;
if (_currMovement)
- dyn = (DynamicPhase *)_currMovement->_dynamicPhases[idx];
+ dyn = _currMovement->_dynamicPhases[idx];
else
- dyn = (DynamicPhase *)_dynamicPhases[idx];
+ dyn = _dynamicPhases[idx];
Common::Point point;
@@ -1769,13 +1843,13 @@ void Movement::updateCurrDynamicPhase() {
return;
if (_currMovement->_dynamicPhases[_currDynamicPhaseIndex])
- _currDynamicPhase = (DynamicPhase *)_currMovement->_dynamicPhases[_currDynamicPhaseIndex];
+ _currDynamicPhase = _currMovement->_dynamicPhases[_currDynamicPhaseIndex];
} else {
if (_dynamicPhases.size() == 0 || (uint)_currDynamicPhaseIndex >= _dynamicPhases.size())
return;
if (_dynamicPhases[_currDynamicPhaseIndex])
- _currDynamicPhase = (DynamicPhase *)_dynamicPhases[_currDynamicPhaseIndex];
+ _currDynamicPhase = _dynamicPhases[_currDynamicPhaseIndex];
}
}
@@ -1784,11 +1858,11 @@ int Movement::calcDuration() {
if (_currMovement)
for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) {
- res += ((DynamicPhase *)_currMovement->_dynamicPhases[i])->_initialCountdown;
+ res += _currMovement->_dynamicPhases[i]->_initialCountdown;
}
else
for (uint i = 0; i < _dynamicPhases.size(); i++) {
- res += ((DynamicPhase *)_dynamicPhases[i])->_initialCountdown;
+ res += _dynamicPhases[i]->_initialCountdown;
}
return res;
@@ -1829,12 +1903,12 @@ DynamicPhase *Movement::getDynamicPhaseByIndex(int idx) {
if (_currMovement->_dynamicPhases.size() == 0 || (uint)idx >= _currMovement->_dynamicPhases.size())
return 0;
- return (DynamicPhase *)_currMovement->_dynamicPhases[idx];
+ return _currMovement->_dynamicPhases[idx];
} else {
if (_dynamicPhases.size() == 0 || (uint)idx >= _dynamicPhases.size())
return 0;
- return (DynamicPhase *)_dynamicPhases[idx];
+ return _dynamicPhases[idx];
}
}
@@ -1845,7 +1919,7 @@ void Movement::loadPixelData() {
for (uint i = 0; i < _dynamicPhases.size(); i++) {
if ((Statics *)_dynamicPhases[i] != mov->_staticsObj2 || !(mov->_staticsObj2->_staticsId & 0x4000))
- ((Statics *)_dynamicPhases[i])->getPixelData();
+ _dynamicPhases[i]->getPixelData();
}
if (!(mov->_staticsObj1->_staticsId & 0x4000))
@@ -1855,7 +1929,7 @@ void Movement::loadPixelData() {
void Movement::freePixelData() {
if (!_currMovement)
for (uint i = 0; i < _dynamicPhases.size(); i++)
- ((DynamicPhase *)_dynamicPhases[i])->freePixelData();
+ _dynamicPhases[i]->freePixelData();
if (_staticsObj1)
_staticsObj1->freePixelData();
@@ -1887,11 +1961,11 @@ bool Movement::gotoNextFrame(void (*callback1)(int, Common::Point *point, int, i
if (!callback2) {
if (_currMovement) {
if ((uint)_currDynamicPhaseIndex == _currMovement->_dynamicPhases.size() - 1
- && !(((DynamicPhase *)(_currMovement->_dynamicPhases.back()))->_countdown)) {
+ && !(_currMovement->_dynamicPhases.back()->_countdown)) {
return false;
}
} else if ((uint)_currDynamicPhaseIndex == _dynamicPhases.size() - 1
- && !(((DynamicPhase *)(_dynamicPhases.back()))->_countdown)) {
+ && !(_dynamicPhases.back()->_countdown)) {
return false;
}
}
@@ -2132,9 +2206,12 @@ DynamicPhase::DynamicPhase(DynamicPhase *src, bool reverse) {
_libHandle = src->_libHandle;
_bitmap = src->_bitmap;
- if (_bitmap)
+ if (_bitmap) {
_field_54 = 1;
+ _bitmap = src->_bitmap->reverseImage(false);
+ }
+
_someX = src->_someX;
_someY = src->_someY;
}
diff --git a/engines/fullpipe/statics.h b/engines/fullpipe/statics.h
index 89703965cd..c7baac7502 100644
--- a/engines/fullpipe/statics.h
+++ b/engines/fullpipe/statics.h
@@ -98,6 +98,7 @@ class Statics : public DynamicPhase {
virtual ~Statics();
virtual bool load(MfcArchive &file);
+ virtual void init();
Statics *getStaticsById(int itemId);
Common::Point *getSomeXY(Common::Point &p);
@@ -121,7 +122,7 @@ class Movement : public GameObject {
int _field_50;
int _counterMax;
int _counter;
- PtrList _dynamicPhases;
+ Common::Array<DynamicPhase *> _dynamicPhases;
int _field_78;
Common::Point **_framePosOffsets;
Movement *_currMovement;
@@ -145,7 +146,7 @@ class Movement : public GameObject {
Common::Point *getCenter(Common::Point *p);
Common::Point *getDimensionsOfPhase(Common::Point *p, int phaseIndex);
- Common::Point *calcSomeXY(Common::Point &p, int idx);
+ Common::Point *calcSomeXY(Common::Point &p, int idx, int dynidx);
void initStatics(StaticANIObject *ani);
void updateCurrDynamicPhase();
@@ -181,8 +182,8 @@ class StaticANIObject : public GameObject {
int _initialCounter;
void (*_callback1)(int, Common::Point *point, int, int);
void (*_callback2)(int *);
- PtrList _movements;
- PtrList _staticsList;
+ Common::Array<Movement *> _movements;
+ Common::Array<Statics *> _staticsList;
StepArray _stepArray;
int16 _field_96;
int _messageQueueId;
@@ -217,7 +218,7 @@ public:
void setAlpha(int alpha);
void deleteFromGlobalMessageQueue();
- void queueMessageQueue(MessageQueue *msg);
+ bool queueMessageQueue(MessageQueue *msg);
void restartMessageQueue(MessageQueue *msg);
MessageQueue *getMessageQueue();
bool trySetMessageQueue(int msgNum, int qId);
@@ -246,6 +247,7 @@ public:
void draw2();
MovTable *countMovements();
+ Common::Point *calcStepLen(Common::Point *p);
void setSpeed(int speed);
void updateStepPos();
diff --git a/engines/fullpipe/utils.h b/engines/fullpipe/utils.h
index 72e746cd03..da3ab7ee4f 100644
--- a/engines/fullpipe/utils.h
+++ b/engines/fullpipe/utils.h
@@ -68,6 +68,7 @@ enum ObjType {
kObjTypeDefault,
kObjTypeExCommand,
kObjTypeExCommand2,
+ kObjTypeModalSaveGame,
kObjTypeMovGraph,
kObjTypeMovGraphLink,
kObjTypeMovGraphNode,
@@ -148,8 +149,6 @@ class DWordArray : public Common::Array<int32>, public CObject {
virtual bool load(MfcArchive &file);
};
-typedef Common::Array<void *> PtrList;
-
char *genFileName(int superId, int sceneId, const char *ext);
byte *transCyrillic(byte *s);
diff --git a/engines/gob/POTFILES b/engines/gob/POTFILES
index 9a512469dd..ca7aa14177 100644
--- a/engines/gob/POTFILES
+++ b/engines/gob/POTFILES
@@ -1,3 +1,5 @@
engines/gob/inter_playtoons.cpp
engines/gob/inter_v2.cpp
engines/gob/inter_v5.cpp
+engines/gob/inter_geisha.cpp
+
diff --git a/engines/gob/cheater_geisha.cpp b/engines/gob/cheater_geisha.cpp
index 8c4deec370..ec6fe09d59 100644
--- a/engines/gob/cheater_geisha.cpp
+++ b/engines/gob/cheater_geisha.cpp
@@ -61,7 +61,7 @@ bool Cheater_Geisha::cheat(GUI::Debugger &console) {
uint32 digit5 = READ_VARO_UINT32(0x778);
if (digit1 && digit2 && digit3 && digit4 && digit5)
- console.DebugPrintf("Mastermind solution: %d %d %d %d %d\n",
+ console.debugPrintf("Mastermind solution: %d %d %d %d %d\n",
digit1, digit2, digit3, digit4, digit5);
return true;
diff --git a/engines/gob/console.cpp b/engines/gob/console.cpp
index b0f6006284..2252606243 100644
--- a/engines/gob/console.cpp
+++ b/engines/gob/console.cpp
@@ -29,14 +29,14 @@
namespace Gob {
GobConsole::GobConsole(GobEngine *vm) : GUI::Debugger(), _vm(vm), _cheater(0) {
- DCmd_Register("varSize", WRAP_METHOD(GobConsole, cmd_varSize));
- DCmd_Register("dumpVars", WRAP_METHOD(GobConsole, cmd_dumpVars));
- DCmd_Register("var8", WRAP_METHOD(GobConsole, cmd_var8));
- DCmd_Register("var16", WRAP_METHOD(GobConsole, cmd_var16));
- DCmd_Register("var32", WRAP_METHOD(GobConsole, cmd_var32));
- DCmd_Register("varString", WRAP_METHOD(GobConsole, cmd_varString));
- DCmd_Register("cheat", WRAP_METHOD(GobConsole, cmd_cheat));
- DCmd_Register("listArchives", WRAP_METHOD(GobConsole, cmd_listArchives));
+ registerCmd("varSize", WRAP_METHOD(GobConsole, cmd_varSize));
+ registerCmd("dumpVars", WRAP_METHOD(GobConsole, cmd_dumpVars));
+ registerCmd("var8", WRAP_METHOD(GobConsole, cmd_var8));
+ registerCmd("var16", WRAP_METHOD(GobConsole, cmd_var16));
+ registerCmd("var32", WRAP_METHOD(GobConsole, cmd_var32));
+ registerCmd("varString", WRAP_METHOD(GobConsole, cmd_varString));
+ registerCmd("cheat", WRAP_METHOD(GobConsole, cmd_cheat));
+ registerCmd("listArchives", WRAP_METHOD(GobConsole, cmd_listArchives));
}
GobConsole::~GobConsole() {
@@ -51,7 +51,7 @@ void GobConsole::unregisterCheater() {
}
bool GobConsole::cmd_varSize(int argc, const char **argv) {
- DebugPrintf("Size of the variable space: %d bytes\n", _vm->_inter->_variables->getSize());
+ debugPrintf("Size of the variable space: %d bytes\n", _vm->_inter->_variables->getSize());
return true;
}
@@ -74,14 +74,14 @@ bool GobConsole::cmd_dumpVars(int argc, const char **argv) {
bool GobConsole::cmd_var8(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: var8 <var offset> (<value>)\n");
+ debugPrintf("Usage: var8 <var offset> (<value>)\n");
return true;
}
uint32 varNum = atoi(argv[1]);
if (varNum >= _vm->_inter->_variables->getSize()) {
- DebugPrintf("Variable offset out of range\n");
+ debugPrintf("Variable offset out of range\n");
return true;
}
@@ -90,21 +90,21 @@ bool GobConsole::cmd_var8(int argc, const char **argv) {
_vm->_inter->_variables->writeOff8(varNum, varVal);
}
- DebugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff8(varNum));
+ debugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff8(varNum));
return true;
}
bool GobConsole::cmd_var16(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: var16 <var offset> (<value>)\n");
+ debugPrintf("Usage: var16 <var offset> (<value>)\n");
return true;
}
uint32 varNum = atoi(argv[1]);
if ((varNum + 1) >= _vm->_inter->_variables->getSize()) {
- DebugPrintf("Variable offset out of range\n");
+ debugPrintf("Variable offset out of range\n");
return true;
}
@@ -113,21 +113,21 @@ bool GobConsole::cmd_var16(int argc, const char **argv) {
_vm->_inter->_variables->writeOff16(varNum, varVal);
}
- DebugPrintf("var16_%d = %d\n", varNum, _vm->_inter->_variables->readOff16(varNum));
+ debugPrintf("var16_%d = %d\n", varNum, _vm->_inter->_variables->readOff16(varNum));
return true;
}
bool GobConsole::cmd_var32(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: var32 <var offset> (<value>)\n");
+ debugPrintf("Usage: var32 <var offset> (<value>)\n");
return true;
}
uint32 varNum = atoi(argv[1]);
if ((varNum + 3) >= _vm->_inter->_variables->getSize()) {
- DebugPrintf("Variable offset out of range\n");
+ debugPrintf("Variable offset out of range\n");
return true;
}
@@ -136,21 +136,21 @@ bool GobConsole::cmd_var32(int argc, const char **argv) {
_vm->_inter->_variables->writeOff32(varNum, varVal);
}
- DebugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff32(varNum));
+ debugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff32(varNum));
return true;
}
bool GobConsole::cmd_varString(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: varString <var offset> (<value>)\n");
+ debugPrintf("Usage: varString <var offset> (<value>)\n");
return true;
}
uint32 varNum = atoi(argv[1]);
if (varNum >= _vm->_inter->_variables->getSize()) {
- DebugPrintf("Variable offset out of range\n");
+ debugPrintf("Variable offset out of range\n");
return true;
}
@@ -160,7 +160,7 @@ bool GobConsole::cmd_varString(int argc, const char **argv) {
Common::strlcpy(_vm->_inter->_variables->getAddressOffString(varNum), argv[2], maxLength);
}
- DebugPrintf("varString_%d = \"%s\"\n", varNum, _vm->_inter->_variables->getAddressOffString(varNum));
+ debugPrintf("varString_%d = \"%s\"\n", varNum, _vm->_inter->_variables->getAddressOffString(varNum));
return true;
}
@@ -177,11 +177,11 @@ bool GobConsole::cmd_listArchives(int argc, const char **argv) {
_vm->_dataIO->getArchiveInfo(info);
- DebugPrintf(" Archive | Base | FileCount\n");
- DebugPrintf("--------------------------------\n");
+ debugPrintf(" Archive | Base | FileCount\n");
+ debugPrintf("--------------------------------\n");
for (Common::Array<ArchiveInfo>::const_iterator it = info.begin(); it != info.end(); ++it)
if (!it->name.empty())
- DebugPrintf("%13s | %d | %d\n", it->name.c_str(), it->base, it->fileCount);
+ debugPrintf("%13s | %d | %d\n", it->name.c_str(), it->base, it->fileCount);
return true;
}
diff --git a/engines/gob/detection/tables_ween.h b/engines/gob/detection/tables_ween.h
index 66a83aff0f..bf65685d46 100644
--- a/engines/gob/detection/tables_ween.h
+++ b/engines/gob/detection/tables_ween.h
@@ -228,93 +228,6 @@
0, 0, 0
},
-// -- DOS VGA Floppy --
-
-{
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"),
- EN_GRB,
- kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
-},
-{
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568),
- EN_USA,
- kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
-},
-{ // Supplied by cybot_tmin in bug report #1667743
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426),
- ES_ESP,
- kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
-},
-{
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"),
- FR_FRA,
- kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
-},
-{ // Supplied by cartman_ on #scummvm
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"),
- DE_DEU,
- kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
-},
-{ // Supplied by glorfindel in bugreport #1722142
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771),
- IT_ITA,
- kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
-},
-
// -- Demos --
{
diff --git a/engines/groovie/configure.engine b/engines/groovie/configure.engine
index 84e95a70df..212a49bec8 100644
--- a/engines/groovie/configure.engine
+++ b/engines/groovie/configure.engine
@@ -1,4 +1,4 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
add_engine groovie "Groovie" yes "groovie2" "7th Guest"
-add_engine groovie2 "Groovie 2 games" no "" "" "jpeg"
+add_engine groovie2 "Groovie 2 games" no "" "" "jpeg 16bit"
diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp
index 080463a8b3..442f0bfada 100644
--- a/engines/groovie/cursor.cpp
+++ b/engines/groovie/cursor.cpp
@@ -107,8 +107,8 @@ Cursor_t7g::Cursor_t7g(uint8 *img, uint8 *pal) :
_img = img + 5;
- debugC(1, kGroovieDebugCursor | kGroovieDebugAll, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames);
- debugC(1, kGroovieDebugCursor | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::Cursor: elinor: 0x%02X (%d), 0x%02X (%d)", elinor1, elinor1, elinor2, elinor2);
+ debugC(1, kDebugCursor, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames);
+ debugC(1, kDebugCursor | kDebugUnknown, "Groovie::Cursor: elinor: 0x%02X (%d), 0x%02X (%d)", elinor1, elinor1, elinor2, elinor2);
}
void Cursor_t7g::enable() {
@@ -260,32 +260,32 @@ Cursor_v2::Cursor_v2(Common::File &file) {
_width = file.readUint16LE();
_height = file.readUint16LE();
- _img = new byte[_width * _height * _numFrames * 2];
+ _img = new byte[_width * _height * _numFrames * 4];
- debugC(1, kGroovieDebugCursor | kGroovieDebugAll, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames);
+ debugC(1, kDebugCursor, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames);
uint16 tmp16 = file.readUint16LE();
- debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "hotspot x?: %d\n", tmp16);
+ debugC(5, kDebugCursor, "hotspot x?: %d\n", tmp16);
tmp16 = file.readUint16LE();
- debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "hotspot y?: %d\n", tmp16);
+ debugC(5, kDebugCursor, "hotspot y?: %d\n", tmp16);
int loop2count = file.readUint16LE();
- debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2count?: %d\n", loop2count);
+ debugC(5, kDebugCursor, "loop2count?: %d\n", loop2count);
for (int l = 0; l < loop2count; l++) {
tmp16 = file.readUint16LE();
- debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2a: %d\n", tmp16); // Index frame can merge to/from?
+ debugC(5, kDebugCursor, "loop2a: %d\n", tmp16); // Index frame can merge to/from?
tmp16 = file.readUint16LE();
- debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2b: %d\n", tmp16); // Number of frames?
+ debugC(5, kDebugCursor, "loop2b: %d\n", tmp16); // Number of frames?
}
file.read(pal, 0x20 * 3);
for (int f = 0; f < _numFrames; f++) {
uint32 tmp32 = file.readUint32LE();
- debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop3: %d\n", tmp32);
+ debugC(5, kDebugCursor, "loop3: %d\n", tmp32);
byte *data = new byte[tmp32];
file.read(data, tmp32);
- decodeFrame(pal, data, _img + (f * _width * _height * 2));
+ decodeFrame(pal, data, _img + (f * _width * _height * 4));
delete[] data;
}
@@ -364,16 +364,16 @@ void Cursor_v2::decodeFrame(byte *pal, byte *data, byte *dest) {
}
// Convert to screen format
- // NOTE: Currently locked to 16bit
+ // NOTE: Currently locked to 32bpp
ptr = tmp;
for (int y = 0; y < _height; y++) {
for (int x = 0; x < _width; x++) {
if (*ptr == 1) {
- *(uint16 *)dest = (uint16)_format.RGBToColor(*(ptr + 1), *(ptr + 2), *(ptr + 3));
+ *(uint32 *)dest = _format.RGBToColor(*(ptr + 1), *(ptr + 2), *(ptr + 3));
} else {
- *(uint16 *)dest = 0;
+ *(uint32 *)dest = 0;
}
- dest += 2;
+ dest += 4;
ptr += 4;
}
}
@@ -385,7 +385,7 @@ void Cursor_v2::enable() {
}
void Cursor_v2::showFrame(uint16 frame) {
- int offset = _width * _height * frame * 2;
+ int offset = _width * _height * frame * 4;
CursorMan.replaceCursor((const byte *)(_img + offset), _width, _height, _width >> 1, _height >> 1, 0, false, &_format);
}
diff --git a/engines/groovie/debug.cpp b/engines/groovie/debug.cpp
index 8103e4f4c6..16db20413f 100644
--- a/engines/groovie/debug.cpp
+++ b/engines/groovie/debug.cpp
@@ -36,16 +36,16 @@ Debugger::Debugger(GroovieEngine *vm) :
_vm(vm), _script(_vm->_script) {
// Register the debugger comands
- DCmd_Register("step", WRAP_METHOD(Debugger, cmd_step));
- DCmd_Register("go", WRAP_METHOD(Debugger, cmd_go));
- DCmd_Register("pc", WRAP_METHOD(Debugger, cmd_pc));
- DCmd_Register("fg", WRAP_METHOD(Debugger, cmd_fg));
- DCmd_Register("bg", WRAP_METHOD(Debugger, cmd_bg));
- DCmd_Register("mem", WRAP_METHOD(Debugger, cmd_mem));
- DCmd_Register("load", WRAP_METHOD(Debugger, cmd_loadgame));
- DCmd_Register("save", WRAP_METHOD(Debugger, cmd_savegame));
- DCmd_Register("playref", WRAP_METHOD(Debugger, cmd_playref));
- DCmd_Register("dumppal", WRAP_METHOD(Debugger, cmd_dumppal));
+ registerCmd("step", WRAP_METHOD(Debugger, cmd_step));
+ registerCmd("go", WRAP_METHOD(Debugger, cmd_go));
+ registerCmd("pc", WRAP_METHOD(Debugger, cmd_pc));
+ registerCmd("fg", WRAP_METHOD(Debugger, cmd_fg));
+ registerCmd("bg", WRAP_METHOD(Debugger, cmd_bg));
+ registerCmd("mem", WRAP_METHOD(Debugger, cmd_mem));
+ registerCmd("load", WRAP_METHOD(Debugger, cmd_loadgame));
+ registerCmd("save", WRAP_METHOD(Debugger, cmd_savegame));
+ registerCmd("playref", WRAP_METHOD(Debugger, cmd_playref));
+ registerCmd("dumppal", WRAP_METHOD(Debugger, cmd_dumppal));
}
Debugger::~Debugger() {
@@ -81,7 +81,7 @@ bool Debugger::cmd_pc(int argc, const char **argv) {
int val = getNumber(argv[1]);
_script->_currentInstruction = val;
}
- DebugPrintf("pc = 0x%04X (%d)\n", _script->_currentInstruction, _script->_currentInstruction);
+ debugPrintf("pc = 0x%04X (%d)\n", _script->_currentInstruction, _script->_currentInstruction);
return true;
}
@@ -97,9 +97,9 @@ bool Debugger::cmd_mem(int argc, const char **argv) {
// Get
val = _script->_variables[pos];
}
- DebugPrintf("mem[0x%04X] = 0x%02X\n", pos, val);
+ debugPrintf("mem[0x%04X] = 0x%02X\n", pos, val);
} else {
- DebugPrintf("Syntax: mem <addr> [<val>]\n");
+ debugPrintf("Syntax: mem <addr> [<val>]\n");
}
return true;
}
@@ -109,7 +109,7 @@ bool Debugger::cmd_loadgame(int argc, const char **argv) {
int slot = getNumber(argv[1]);
_script->loadgame(slot);
} else {
- DebugPrintf("Syntax: load <slot>\n");
+ debugPrintf("Syntax: load <slot>\n");
}
return true;
}
@@ -119,7 +119,7 @@ bool Debugger::cmd_savegame(int argc, const char **argv) {
int slot = getNumber(argv[1]);
_script->savegame(slot);
} else {
- DebugPrintf("Syntax: save <slot>\n");
+ debugPrintf("Syntax: save <slot>\n");
}
return true;
}
@@ -129,7 +129,7 @@ bool Debugger::cmd_playref(int argc, const char **argv) {
int ref = getNumber(argv[1]);
_script->playvideofromref(ref);
} else {
- DebugPrintf("Syntax: playref <videorefnum>\n");
+ debugPrintf("Syntax: playref <videorefnum>\n");
}
return true;
}
@@ -140,7 +140,7 @@ bool Debugger::cmd_dumppal(int argc, const char **argv) {
_vm->_system->getPaletteManager()->grabPalette(palettedump, 0, 256);
for (i = 0; i < 256; i++) {
- DebugPrintf("%3d: %3d,%3d,%3d\n", i, palettedump[(i * 3)], palettedump[(i * 3) + 1], palettedump[(i * 3) + 2]);
+ debugPrintf("%3d: %3d,%3d,%3d\n", i, palettedump[(i * 3)], palettedump[(i * 3) + 1], palettedump[(i * 3) + 2]);
}
return true;
}
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index e65031ec38..b42cf09245 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -29,10 +29,13 @@
#include "groovie/graphics.h"
#include "groovie/music.h"
#include "groovie/resource.h"
-#include "groovie/roq.h"
#include "groovie/stuffit.h"
#include "groovie/vdx.h"
+#ifdef ENABLE_GROOVIE2
+#include "groovie/roq.h"
+#endif
+
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
@@ -50,7 +53,8 @@ namespace Groovie {
GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) :
Engine(syst), _gameDescription(gd), _debugger(NULL), _script(NULL),
_resMan(NULL), _grvCursorMan(NULL), _videoPlayer(NULL), _musicPlayer(NULL),
- _graphicsMan(NULL), _macResFork(NULL), _waitingForInput(false), _font(NULL) {
+ _graphicsMan(NULL), _macResFork(NULL), _waitingForInput(false), _font(NULL),
+ _spookyMode(false) {
// Adding the default directories
const Common::FSNode gameDataDir(ConfMan.get("path"));
@@ -64,17 +68,16 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) :
_modeSpeed = kGroovieSpeedFast;
// Initialize the custom debug levels
- DebugMan.addDebugChannel(kGroovieDebugAll, "All", "Debug everything");
- DebugMan.addDebugChannel(kGroovieDebugVideo, "Video", "Debug video and audio playback");
- DebugMan.addDebugChannel(kGroovieDebugResource, "Resource", "Debug resouce management");
- DebugMan.addDebugChannel(kGroovieDebugScript, "Script", "Debug the scripts");
- DebugMan.addDebugChannel(kGroovieDebugUnknown, "Unknown", "Report values of unknown data in files");
- DebugMan.addDebugChannel(kGroovieDebugHotspots, "Hotspots", "Show the hotspots");
- DebugMan.addDebugChannel(kGroovieDebugCursor, "Cursor", "Debug cursor decompression / switching");
- DebugMan.addDebugChannel(kGroovieDebugMIDI, "MIDI", "Debug MIDI / XMIDI files");
- DebugMan.addDebugChannel(kGroovieDebugScriptvars, "Scriptvars", "Print out any change to script variables");
- DebugMan.addDebugChannel(kGroovieDebugCell, "Cell", "Debug the cell game (in the microscope)");
- DebugMan.addDebugChannel(kGroovieDebugFast, "Fast", "Play videos quickly, with no sound (unstable)");
+ DebugMan.addDebugChannel(kDebugVideo, "Video", "Debug video and audio playback");
+ DebugMan.addDebugChannel(kDebugResource, "Resource", "Debug resouce management");
+ DebugMan.addDebugChannel(kDebugScript, "Script", "Debug the scripts");
+ DebugMan.addDebugChannel(kDebugUnknown, "Unknown", "Report values of unknown data in files");
+ DebugMan.addDebugChannel(kDebugHotspots, "Hotspots", "Show the hotspots");
+ DebugMan.addDebugChannel(kDebugCursor, "Cursor", "Debug cursor decompression / switching");
+ DebugMan.addDebugChannel(kDebugMIDI, "MIDI", "Debug MIDI / XMIDI files");
+ DebugMan.addDebugChannel(kDebugScriptvars, "Scriptvars", "Print out any change to script variables");
+ DebugMan.addDebugChannel(kDebugCell, "Cell", "Debug the cell game (in the microscope)");
+ DebugMan.addDebugChannel(kDebugFast, "Fast", "Play videos quickly, with no sound (unstable)");
}
GroovieEngine::~GroovieEngine() {
@@ -103,14 +106,18 @@ Common::Error GroovieEngine::run() {
// Initialize the graphics
switch (_gameDescription->version) {
- case kGroovieV2:
+ case kGroovieV2: {
// Request the mode with the highest precision available
- initGraphics(640, 480, true, NULL);
+ Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
+ initGraphics(640, 480, true, &format);
+
+ if (_system->getScreenFormat() != format)
+ return Common::kUnsupportedColorMode;
- // Save the enabled mode as it can be both an RGB mode or CLUT8
- _pixelFormat = _system->getScreenFormat();
- _mode8bit = (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8());
+ // Save the enabled mode
+ _pixelFormat = format;
break;
+ }
case kGroovieT7G:
initGraphics(640, 480, true);
_pixelFormat = Graphics::PixelFormat::createFormatCLUT8();
@@ -154,7 +161,9 @@ Common::Error GroovieEngine::run() {
case kGroovieV2:
_resMan = new ResMan_v2();
_grvCursorMan = new GrvCursorMan_v2(_system);
+#ifdef ENABLE_GROOVIE2
_videoPlayer = new ROQPlayer(this);
+#endif
break;
}
diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h
index c3d3146cca..d442d39cb2 100644
--- a/engines/groovie/groovie.h
+++ b/engines/groovie/groovie.h
@@ -58,18 +58,18 @@ class Script;
class VideoPlayer;
enum DebugLevels {
- kGroovieDebugAll = 1 << 0,
- kGroovieDebugVideo = 1 << 1,
- kGroovieDebugResource = 1 << 2,
- kGroovieDebugScript = 1 << 3,
- kGroovieDebugUnknown = 1 << 4,
- kGroovieDebugHotspots = 1 << 5,
- kGroovieDebugCursor = 1 << 6,
- kGroovieDebugMIDI = 1 << 7,
- kGroovieDebugScriptvars = 1 << 8,
- kGroovieDebugCell = 1 << 9,
- kGroovieDebugFast = 1 << 10
- // the current limitation is 32 debug levels (1 << 31 is the last one)
+ kDebugVideo = 1 << 0,
+ kDebugResource = 1 << 1,
+ kDebugScript = 1 << 2,
+ kDebugUnknown = 1 << 3,
+ kDebugHotspots = 1 << 4,
+ kDebugCursor = 1 << 5,
+ kDebugMIDI = 1 << 6,
+ kDebugScriptvars = 1 << 7,
+ kDebugCell = 1 << 8,
+ kDebugFast = 1 << 9
+ // the current limitation is 32 debug levels (1 << 31 is the last one)
+ // but some are used by system, so avoid high values.
};
/**
@@ -110,7 +110,7 @@ public:
void waitForInput();
Graphics::PixelFormat _pixelFormat;
- bool _mode8bit;
+ bool _spookyMode;
Script *_script;
ResMan *_resMan;
GrvCursorMan *_grvCursorMan;
diff --git a/engines/groovie/module.mk b/engines/groovie/module.mk
index b47eed912b..84d6222c59 100644
--- a/engines/groovie/module.mk
+++ b/engines/groovie/module.mk
@@ -12,12 +12,16 @@ MODULE_OBJS := \
music.o \
player.o \
resource.o \
- roq.o \
saveload.o \
script.o \
stuffit.o \
vdx.o
+ifdef ENABLE_GROOVIE2
+MODULE_OBJS += \
+ roq.o
+endif
+
# This module can be built as a plugin
ifeq ($(ENABLE_GROOVIE), DYNAMIC_PLUGIN)
PLUGIN := 1
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 390f47f084..2c164e020c 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -64,7 +64,7 @@ void MusicPlayer::playSong(uint32 fileref) {
void MusicPlayer::setBackgroundSong(uint32 fileref) {
Common::StackLock lock(_mutex);
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Changing the background song: %04X", fileref);
+ debugC(1, kDebugMIDI, "Groovie::Music: Changing the background song: %04X", fileref);
_backgroundFileRef = fileref;
}
@@ -86,7 +86,7 @@ void MusicPlayer::playCD(uint8 track) {
// Stop the MIDI playback
unload();
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Playing CD track %d", track);
+ debugC(1, kDebugMIDI, "Groovie::Music: Playing CD track %d", track);
if (track == 3) {
// This is the credits song, start at 23:20
@@ -136,9 +136,9 @@ void MusicPlayer::playCD(uint8 track) {
}
void MusicPlayer::startBackground() {
- debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: startBackground()");
+ debugC(3, kDebugMIDI, "Groovie::Music: startBackground()");
if (!_isPlaying && _backgroundFileRef) {
- debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the background song (0x%4X)", _backgroundFileRef);
+ debugC(3, kDebugMIDI, "Groovie::Music: Starting the background song (0x%4X)", _backgroundFileRef);
play(_backgroundFileRef, true);
}
}
@@ -158,7 +158,7 @@ void MusicPlayer::setUserVolume(uint16 volume) {
void MusicPlayer::setGameVolume(uint16 volume, uint16 time) {
Common::StackLock lock(_mutex);
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Setting game volume from %d to %d in %dms", _gameVolume, volume, time);
+ debugC(1, kDebugMIDI, "Groovie::Music: Setting game volume from %d to %d in %dms", _gameVolume, volume, time);
// Save the start parameters of the fade
_fadingStartTime = _vm->_system->getMillis();
@@ -183,12 +183,12 @@ bool MusicPlayer::play(uint32 fileref, bool loop) {
}
void MusicPlayer::applyFading() {
- debugC(6, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: applyFading() _fadingStartTime = %d, _fadingDuration = %d, _fadingStartVolume = %d, _fadingEndVolume = %d", _fadingStartTime, _fadingDuration, _fadingStartVolume, _fadingEndVolume);
+ debugC(6, kDebugMIDI, "Groovie::Music: applyFading() _fadingStartTime = %d, _fadingDuration = %d, _fadingStartVolume = %d, _fadingEndVolume = %d", _fadingStartTime, _fadingDuration, _fadingStartVolume, _fadingEndVolume);
Common::StackLock lock(_mutex);
// Calculate the passed time
uint32 time = _vm->_system->getMillis() - _fadingStartTime;
- debugC(6, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: time = %d, _gameVolume = %d", time, _gameVolume);
+ debugC(6, kDebugMIDI, "Groovie::Music: time = %d, _gameVolume = %d", time, _gameVolume);
if (time >= _fadingDuration) {
// Set the end volume
_gameVolume = _fadingEndVolume;
@@ -200,7 +200,7 @@ void MusicPlayer::applyFading() {
if (_gameVolume == _fadingEndVolume) {
// If we were fading to 0, stop the playback and restore the volume
if (_fadingEndVolume == 0) {
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Faded to zero: end of song. _fadingEndVolume set to 100");
+ debugC(1, kDebugMIDI, "Groovie::Music: Faded to zero: end of song. _fadingEndVolume set to 100");
unload();
}
}
@@ -210,7 +210,7 @@ void MusicPlayer::applyFading() {
}
void MusicPlayer::onTimer(void *refCon) {
- debugC(9, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: onTimer()");
+ debugC(9, kDebugMIDI, "Groovie::Music: onTimer()");
MusicPlayer *music = (MusicPlayer *)refCon;
Common::StackLock lock(music->_mutex);
@@ -225,7 +225,7 @@ void MusicPlayer::onTimer(void *refCon) {
}
void MusicPlayer::unload() {
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Stopping the playback");
+ debugC(1, kDebugMIDI, "Groovie::Music: Stopping the playback");
// Set the new state
_isPlaying = false;
@@ -319,7 +319,7 @@ void MusicPlayerMidi::updateChanVolume(byte channel) {
}
void MusicPlayerMidi::endTrack() {
- debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: endTrack()");
+ debugC(3, kDebugMIDI, "Groovie::Music: endTrack()");
unload();
}
@@ -439,7 +439,7 @@ void MusicPlayerXMI::send(uint32 b) {
byte chan = b & 0xF;
byte bank = (b >> 16) & 0xFF;
- debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Selecting bank %X for channel %X", bank, chan);
+ debugC(5, kDebugMIDI, "Groovie::Music: Selecting bank %X for channel %X", bank, chan);
_chanBanks[chan] = bank;
return;
} else if ((b & 0xF0) == 0xC0) { // Program change
@@ -450,7 +450,7 @@ void MusicPlayerXMI::send(uint32 b) {
byte chan = b & 0xF;
byte patch = (b >> 8) & 0xFF;
- debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Setting custom patch %X from bank %X to channel %X", patch, _chanBanks[chan], chan);
+ debugC(5, kDebugMIDI, "Groovie::Music: Setting custom patch %X from bank %X to channel %X", patch, _chanBanks[chan], chan);
// Try to find the requested patch from the previously
// specified bank
@@ -475,7 +475,7 @@ void MusicPlayerXMI::send(uint32 b) {
}
bool MusicPlayerXMI::load(uint32 fileref, bool loop) {
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref);
+ debugC(1, kDebugMIDI, "Groovie::Music: Starting the playback of song: %04X", fileref);
// Open the song resource
Common::SeekableReadStream *file = _vm->_resMan->open(fileref);
@@ -489,7 +489,7 @@ bool MusicPlayerXMI::load(uint32 fileref, bool loop) {
void MusicPlayerXMI::loadTimbres(const Common::String &filename) {
// Load the Global Timbre Library format as documented in AIL2
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Loading the GTL file %s", filename.c_str());
+ debugC(1, kDebugMIDI, "Groovie::Music: Loading the GTL file %s", filename.c_str());
// Does it exist?
if (!Common::File::exists(filename)) {
@@ -537,7 +537,7 @@ void MusicPlayerXMI::loadTimbres(const Common::String &filename) {
// Read the timbre data
gtl->read(_timbres[i].data, _timbres[i].size);
- debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Loaded patch %x in bank %x with size %d",
+ debugC(5, kDebugMIDI, "Groovie::Music: Loaded patch %x in bank %x with size %d",
_timbres[i].patch, _timbres[i].bank, _timbres[i].size);
}
@@ -636,7 +636,7 @@ void setRolandInstrument(MidiDriver *drv, byte channel, byte *instrument) {
// Show the timbre name as extra debug information
Common::String name((char *)instrument, 10);
- debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Setting MT32 timbre '%s' to channel %d", name.c_str(), channel);
+ debugC(5, kDebugMIDI, "Groovie::Music: Setting MT32 timbre '%s' to channel %d", name.c_str(), channel);
sysex.roland_id = 0x41;
sysex.device_id = channel; // Unit#
@@ -702,7 +702,7 @@ MusicPlayerMac_t7g::MusicPlayerMac_t7g(GroovieEngine *vm) : MusicPlayerMidi(vm)
}
bool MusicPlayerMac_t7g::load(uint32 fileref, bool loop) {
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref);
+ debugC(1, kDebugMIDI, "Groovie::Music: Starting the playback of song: %04X", fileref);
// First try for compressed MIDI
Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKTAG('c','m','i','d'), fileref & 0x3FF);
@@ -789,7 +789,7 @@ MusicPlayerMac_v2::MusicPlayerMac_v2(GroovieEngine *vm) : MusicPlayerMidi(vm) {
}
bool MusicPlayerMac_v2::load(uint32 fileref, bool loop) {
- debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref);
+ debugC(1, kDebugMIDI, "Groovie::Music: Starting the playback of song: %04X", fileref);
// Find correct filename
ResInfo info;
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index 16cb3c47ff..c1b90fbd2c 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -94,13 +94,13 @@ void VideoPlayer::waitFrame() {
} else {
uint32 millisDiff = currTime - _lastFrameTime;
if (millisDiff < _millisBetweenFrames) {
- debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Delaying %d (currTime=%d, _lastFrameTime=%d, millisDiff=%d, _millisBetweenFrame=%d)",
+ debugC(7, kDebugVideo, "Groovie::Player: Delaying %d (currTime=%d, _lastFrameTime=%d, millisDiff=%d, _millisBetweenFrame=%d)",
_millisBetweenFrames - millisDiff, currTime, _lastFrameTime, millisDiff, _millisBetweenFrames);
_syst->delayMillis(_millisBetweenFrames - millisDiff);
currTime = _syst->getMillis();
- debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Finished delay at %d", currTime);
+ debugC(7, kDebugVideo, "Groovie::Player: Finished delay at %d", currTime);
}
- debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Frame displayed at %d (%f FPS)", currTime, 1000.0 / (currTime - _lastFrameTime));
+ debugC(6, kDebugVideo, "Groovie::Player: Frame displayed at %d (%f FPS)", currTime, 1000.0 / (currTime - _lastFrameTime));
_lastFrameTime = currTime;
}
}
diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp
index 8229d02d91..75eba95240 100644
--- a/engines/groovie/resource.cpp
+++ b/engines/groovie/resource.cpp
@@ -47,7 +47,7 @@ Common::SeekableReadStream *ResMan::open(uint32 fileRef) {
return NULL;
}
- debugC(1, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Opening resource 0x%04X (%s, %d, %d)", fileRef, _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size);
+ debugC(1, kDebugResource, "Groovie::Resource: Opening resource 0x%04X (%s, %d, %d)", fileRef, _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size);
// Does it exist?
if (!Common::File::exists(_gjds[resInfo.gjd])) {
@@ -120,7 +120,7 @@ uint32 ResMan_t7g::getRef(Common::String name, Common::String scriptname) {
// Test whether it's the resource we're searching
Common::String resname(readname, 12);
if (resname.hasPrefix(name.c_str())) {
- debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource %12s matches %s", readname, name.c_str());
+ debugC(2, kDebugResource, "Groovie::Resource: Resource %12s matches %s", readname, name.c_str());
found = true;
}
@@ -173,7 +173,7 @@ bool ResMan_t7g::getResInfo(uint32 fileRef, ResInfo &resInfo) {
char resname[13];
rlFile->read(resname, 12);
resname[12] = 0;
- debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %12s", resname);
+ debugC(2, kDebugResource, "Groovie::Resource: Resource name: %12s", resname);
resInfo.filename = resname;
// Read the resource information
@@ -240,7 +240,7 @@ uint32 ResMan_v2::getRef(Common::String name, Common::String scriptname) {
// Test whether it's the resource we're searching
Common::String resname(readname, 18);
if (resname.hasPrefix(name.c_str())) {
- debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource %18s matches %s", readname, name.c_str());
+ debugC(2, kDebugResource, "Groovie::Resource: Resource %18s matches %s", readname, name.c_str());
found = true;
break;
}
@@ -284,7 +284,7 @@ bool ResMan_v2::getResInfo(uint32 fileRef, ResInfo &resInfo) {
char resname[19];
resname[18] = 0;
rlFile.read(resname, 18);
- debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %18s", resname);
+ debugC(2, kDebugResource, "Groovie::Resource: Resource name: %18s", resname);
resInfo.filename = resname;
// 6 padding bytes? (it looks like they're always 0)
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 2776a0455d..379fcabc07 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -28,6 +28,7 @@
#include "groovie/groovie.h"
#include "common/debug.h"
+#include "common/rect.h"
#include "common/substream.h"
#include "common/textconsole.h"
@@ -45,24 +46,12 @@ namespace Groovie {
ROQPlayer::ROQPlayer(GroovieEngine *vm) :
VideoPlayer(vm), _codingTypeCount(0),
- _bg(&_vm->_graphicsMan->_background) {
+ _bg(&_vm->_graphicsMan->_background),
+ _firstFrame(true) {
// Create the work surfaces
_currBuf = new Graphics::Surface();
_prevBuf = new Graphics::Surface();
-
- if (_vm->_mode8bit) {
- byte pal[256 * 3];
-
- // Set a grayscale palette
- for (int i = 0; i < 256; i++) {
- pal[(i * 3) + 0] = i;
- pal[(i * 3) + 1] = i;
- pal[(i * 3) + 2] = i;
- }
-
- _syst->getPaletteManager()->setPalette(pal, 0, 256);
- }
}
ROQPlayer::~ROQPlayer() {
@@ -75,7 +64,7 @@ ROQPlayer::~ROQPlayer() {
uint16 ROQPlayer::loadInternal() {
// Begin reading the file
- debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Loading video");
+ debugC(1, kDebugVideo, "Groovie::ROQ: Loading video");
// Read the file header
ROQBlockHeader blockHeader;
@@ -95,6 +84,9 @@ uint16 ROQPlayer::loadInternal() {
_num2blocks = 0;
_num4blocks = 0;
+ // Reset the first frame flag
+ _firstFrame = true;
+
if ((blockHeader.size == 0) && (blockHeader.param == 0)) {
// Set the offset scaling to 2
_offScale = 2;
@@ -115,35 +107,31 @@ uint16 ROQPlayer::loadInternal() {
void ROQPlayer::buildShowBuf() {
for (int line = 0; line < _bg->h; line++) {
- byte *out = (byte *)_bg->getBasePtr(0, line);
- byte *in = (byte *)_currBuf->getBasePtr(0, line / _scaleY);
+ uint32 *out = (uint32 *)_bg->getBasePtr(0, line);
+ uint32 *in = (uint32 *)_currBuf->getBasePtr(0, line / _scaleY);
+
for (int x = 0; x < _bg->w; x++) {
- if (_vm->_mode8bit) {
- // Just use the luminancy component
- *out = *in;
-#ifdef USE_RGB_COLOR
- } else {
- // Do the format conversion (YUV -> RGB -> Screen format)
- byte r, g, b;
- Graphics::YUV2RGB(*in, *(in + 1), *(in + 2), r, g, b);
- // FIXME: this is fixed to 16bit
- *(uint16 *)out = (uint16)_vm->_pixelFormat.RGBToColor(r, g, b);
-#endif // USE_RGB_COLOR
- }
+ // Copy a pixel
+ *out++ = *in;
// Skip to the next pixel
- out += _vm->_pixelFormat.bytesPerPixel;
if (!(x % _scaleX))
- in += _currBuf->format.bytesPerPixel;
+ in++;
}
}
+ // On the first frame, copy from the current buffer to the prev buffer
+ if (_firstFrame) {
+ _prevBuf->copyFrom(*_currBuf);
+ _firstFrame = false;
+ }
+
// Swap buffers
SWAP(_prevBuf, _currBuf);
}
bool ROQPlayer::playFrameInternal() {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Playing frame");
+ debugC(5, kDebugVideo, "Groovie::ROQ: Playing frame");
// Process the needed blocks until the next video frame
bool endframe = false;
@@ -180,9 +168,9 @@ bool ROQPlayer::readBlockHeader(ROQBlockHeader &blockHeader) {
blockHeader.size = _file->readUint32LE();
blockHeader.param = _file->readUint16LE();
- debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block type = 0x%02X", blockHeader.type);
- debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block size = 0x%08X", blockHeader.size);
- debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block param = 0x%04X", blockHeader.param);
+ debugC(10, kDebugVideo, "Groovie::ROQ: Block type = 0x%02X", blockHeader.type);
+ debugC(10, kDebugVideo, "Groovie::ROQ: Block size = 0x%08X", blockHeader.size);
+ debugC(10, kDebugVideo, "Groovie::ROQ: Block param = 0x%04X", blockHeader.param);
return true;
}
@@ -250,7 +238,7 @@ bool ROQPlayer::processBlock() {
}
bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing info block");
+ debugC(5, kDebugVideo, "Groovie::ROQ: Processing info block");
// Verify the block header
if (blockHeader.type != 0x1001 || blockHeader.size != 8 || (blockHeader.param != 0 && blockHeader.param != 1)) {
@@ -258,6 +246,9 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
return false;
}
+ // Reset the first frame flag
+ _firstFrame = true;
+
// Save the alpha channel size
_alpha = blockHeader.param;
@@ -282,32 +273,19 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
_prevBuf->free();
// Allocate new buffers
- // These buffers use YUV data, since we can not describe it with a
- // PixelFormat struct we just add some dummy PixelFormat with the
- // correct bytes per pixel value. Since the surfaces are only used
- // internally and no code assuming RGB data is present is used on
- // 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->getPixels();
- byte *ptr2 = (byte *)_prevBuf->getPixels();
- for (int i = 0; i < width * height; i++) {
- *ptr1++ = 0;
- *ptr1++ = 128;
- *ptr1++ = 128;
- *ptr2++ = 0;
- *ptr2++ = 128;
- *ptr2++ = 128;
+ _currBuf->create(width, height, _vm->_pixelFormat);
+ _prevBuf->create(width, height, _vm->_pixelFormat);
}
+ // Clear the buffers with black
+ _currBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
+ _prevBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
+
return true;
}
bool ROQPlayer::processBlockQuadCodebook(ROQBlockHeader &blockHeader) {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad codebook block");
+ debugC(5, kDebugVideo, "Groovie::ROQ: Processing quad codebook block");
// Get the number of 2x2 pixel blocks to read
int newNum2blocks = blockHeader.param >> 8;
@@ -324,15 +302,28 @@ bool ROQPlayer::processBlockQuadCodebook(ROQBlockHeader &blockHeader) {
}
// Read the 2x2 codebook
+ uint32 *codebook = _codebook2;
+
for (int i = 0; i < newNum2blocks; i++) {
// Read the 4 Y components and their alpha channel
+ byte y[4];
+ byte a[4];
+
for (int j = 0; j < 4; j++) {
- _codebook2[i * 10 + j * 2] = _file->readByte();
- _codebook2[i * 10 + j * 2 + 1] = _alpha ? _file->readByte() : 255;
+ y[j] = _file->readByte();
+ a[j] = _alpha ? _file->readByte() : 255;
}
// Read the subsampled Cb and Cr
- _file->read(&_codebook2[i * 10 + 8], 2);
+ byte u = _file->readByte();
+ byte v = _file->readByte();
+
+ // Convert the codebook to RGB right here
+ for (int j = 0; j < 4; j++) {
+ byte r, g, b;
+ Graphics::YUV2RGB(y[j], u, v, r, g, b);
+ *codebook++ = _vm->_pixelFormat.ARGBToColor(a[j], r, g, b);
+ }
}
// Read the 4x4 codebook
@@ -342,7 +333,7 @@ bool ROQPlayer::processBlockQuadCodebook(ROQBlockHeader &blockHeader) {
}
bool ROQPlayer::processBlockQuadVector(ROQBlockHeader &blockHeader) {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad vector block");
+ debugC(5, kDebugVideo, "Groovie::ROQ: Processing quad vector block");
// Get the mean motion vectors
int8 Mx = blockHeader.param >> 8;
@@ -405,7 +396,7 @@ void ROQPlayer::processBlockQuadVectorBlock(int baseX, int baseY, int8 Mx, int8
}
void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, int8 My) {
- debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad vector sub block");
+ debugC(6, kDebugVideo, "Groovie::ROQ: Processing quad vector sub block");
uint16 codingType = getCodingType();
switch (codingType) {
@@ -431,28 +422,25 @@ 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 (unfinished)");
+ debugC(5, kDebugVideo, "Groovie::ROQ: Processing still (JPEG) block");
Image::JPEGDecoder jpg;
- jpg.setOutputColorSpace(Image::JPEGDecoder::kColorSpaceYUV);
uint32 startPos = _file->pos();
Common::SeekableSubReadStream subStream(_file, startPos, startPos + blockHeader.size, DisposeAfterUse::NO);
jpg.loadStream(subStream);
const Graphics::Surface *srcSurf = jpg.getSurface();
- const byte *src = (const byte *)srcSurf->getPixels();
- byte *ptr = (byte *)_currBuf->getPixels();
- memcpy(ptr, src, _currBuf->w * _currBuf->h * srcSurf->format.bytesPerPixel);
+ _currBuf->free();
+ delete _currBuf;
+ _currBuf = srcSurf->convertTo(_vm->_pixelFormat);
_file->seek(startPos + blockHeader.size);
return true;
}
bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing mono sound block");
+ debugC(5, kDebugVideo, "Groovie::ROQ: Processing mono sound block");
// Verify the block header
if (blockHeader.type != 0x1020) {
@@ -495,7 +483,7 @@ bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) {
}
bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing stereo sound block");
+ debugC(5, kDebugVideo, "Groovie::ROQ: Processing stereo sound block");
// Verify the block header
if (blockHeader.type != 0x1021) {
@@ -551,7 +539,7 @@ bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) {
}
bool ROQPlayer::processBlockAudioContainer(ROQBlockHeader &blockHeader) {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing audio container block: 0x%04X", blockHeader.param);
+ debugC(5, kDebugVideo, "Groovie::ROQ: Processing audio container block: 0x%04X", blockHeader.param);
return true;
}
@@ -571,25 +559,14 @@ void ROQPlayer::paint2(byte i, int destx, int desty) {
error("Groovie::ROQ: Invalid 2x2 block %d (%d available)", i, _num2blocks);
}
- byte *block = &_codebook2[i * 10];
- byte u = block[8];
- byte v = block[9];
+ uint32 *block = _codebook2 + i * 4;
+ uint32 *ptr = (uint32 *)_currBuf->getBasePtr(destx, desty);
+ uint32 pitch = _currBuf->pitch / 4;
- byte *ptr = (byte *)_currBuf->getBasePtr(destx, desty);
- for (int y = 0; y < 2; y++) {
- for (int x = 0; x < 2; x++) {
- // Basic alpha test
- // TODO: Blending
- if (*(block + 1) > 128) {
- *ptr = *block;
- *(ptr + 1) = u;
- *(ptr + 2) = v;
- }
- ptr += 3;
- block += 2;
- }
- ptr += _currBuf->pitch - 6;
- }
+ ptr[0] = block[0];
+ ptr[1] = block[1];
+ ptr[pitch] = block[2];
+ ptr[pitch + 1] = block[3];
}
void ROQPlayer::paint4(byte i, int destx, int desty) {
@@ -614,25 +591,14 @@ void ROQPlayer::paint8(byte i, int destx, int desty) {
byte *block4 = &_codebook4[i * 4];
for (int y4 = 0; y4 < 2; y4++) {
for (int x4 = 0; x4 < 2; x4++) {
- byte *block2 = &_codebook2[(*block4) * 10];
- byte u = block2[8];
- byte v = block2[9];
- block4++;
+ uint32 *block2 = _codebook2 + *block4++ * 4;
+
for (int y2 = 0; y2 < 2; y2++) {
for (int x2 = 0; x2 < 2; x2++) {
- for (int repy = 0; repy < 2; repy++) {
- for (int repx = 0; repx < 2; repx++) {
- // Basic alpha test
- // TODO: Blending
- if (*(block2 + 1) > 128) {
- byte *ptr = (byte *)_currBuf->getBasePtr(destx + x4*4 + x2*2 + repx, desty + y4*4 + y2*2 + repy);
- *ptr = *block2;
- *(ptr + 1) = u;
- *(ptr + 2) = v;
- }
- }
- }
- block2 += 2;
+ uint32 *ptr = (uint32 *)_currBuf->getBasePtr(destx + x4 * 4 + x2 * 2, desty + y4 * 4 + y2 * 2);
+ uint32 pitch = _currBuf->pitch / 4;
+ uint32 color = *block2++;
+ ptr[0] = ptr[1] = ptr[pitch] = ptr[pitch + 1] = color;
}
}
}
@@ -653,7 +619,7 @@ void ROQPlayer::copy(byte size, int destx, int desty, int offx, int offy) {
// Move to the beginning of the next line
dst += _currBuf->pitch;
- src += _currBuf->pitch;
+ src += _prevBuf->pitch;
}
}
diff --git a/engines/groovie/roq.h b/engines/groovie/roq.h
index cd5e91c82b..7e7d38580e 100644
--- a/engines/groovie/roq.h
+++ b/engines/groovie/roq.h
@@ -71,7 +71,7 @@ private:
// Codebooks
uint16 _num2blocks;
uint16 _num4blocks;
- byte _codebook2[256 * 10];
+ uint32 _codebook2[256 * 4];
byte _codebook4[256 * 4];
// Buffers
@@ -82,7 +82,7 @@ private:
byte _offScale;
bool _dirty;
byte _alpha;
-
+ bool _firstFrame;
};
} // End of Groovie namespace
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 25c421f699..7625151082 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -47,26 +47,6 @@
namespace Groovie {
-static void debugScript(int level, bool nl, const char *s, ...) GCC_PRINTF(3, 4);
-
-static void debugScript(int level, bool nl, const char *s, ...) {
- char buf[STRINGBUFLEN];
- va_list va;
-
- if (!DebugMan.isDebugChannelEnabled(kGroovieDebugScript) &&
- !DebugMan.isDebugChannelEnabled(kGroovieDebugAll))
- return;
-
- va_start(va, s);
- vsnprintf(buf, STRINGBUFLEN, s, va);
- va_end(va);
-
- if (nl)
- debug(level, "%s", buf);
- else
- debugN(level, "%s", buf);
-}
-
Script::Script(GroovieEngine *vm, EngineVersion version) :
_code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm),
_videoFile(NULL), _videoRef(0), _staufsMove(NULL), _lastCursor(0xff),
@@ -120,7 +100,7 @@ Script::~Script() {
void Script::setVariable(uint16 variablenum, byte value) {
_variables[variablenum] = value;
- debugC(1, kGroovieDebugScriptvars | kGroovieDebugAll, "script variable[0x%03X] = %d (0x%04X)", variablenum, value, value);
+ debugC(1, kDebugScriptvars, "script variable[0x%03X] = %d (0x%04X)", variablenum, value, value);
}
void Script::setDebugger(Debugger *debugger) {
@@ -229,7 +209,7 @@ void Script::step() {
// Only output if we're not re-doing the previous instruction
if (_currentInstruction != _oldInstruction) {
- debugScript(1, false, "%s", _debugString.c_str());
+ debugCN(1, kDebugScript, "%s", _debugString.c_str());
_oldInstruction = _currentInstruction;
}
@@ -354,7 +334,7 @@ uint32 Script::getVideoRefString() {
// Add a trailing dot
str += 0x2E;
- debugScript(0, false, "%s", str.c_str());
+ debugCN(0, kDebugScript, "%s", str.c_str());
// Extract the script name.
Common::String scriptname(_scriptFile.c_str(), _scriptFile.size() - 4);
@@ -369,8 +349,7 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) {
bool contained = rect.contains(mousepos);
// Show hotspots when debugging
- if (DebugMan.isDebugChannelEnabled(kGroovieDebugHotspots) ||
- DebugMan.isDebugChannelEnabled(kGroovieDebugAll)) {
+ if (DebugMan.isDebugChannelEnabled(kDebugHotspots)) {
rect.translate(0, -80);
_vm->_graphicsMan->_foreground.frameRect(rect, 250);
_vm->_system->copyRectToScreen(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_foreground.pitch, 0, 80, 640, 320);
@@ -416,7 +395,7 @@ void Script::savegame(uint slot) {
Common::OutSaveFile *file = SaveLoad::openForSaving(ConfMan.getActiveDomainName(), slot);
if (!file) {
- debugC(9, kGroovieDebugScript, "Save file pointer is null");
+ debugC(9, kDebugScript, "Save file pointer is null");
GUI::MessageDialog dialog(_("Failed to save game"), _("OK"));
dialog.runModal();
return;
@@ -462,32 +441,32 @@ void Script::o_invalid() {
}
void Script::o_nop() {
- debugScript(1, true, "NOP");
+ debugC(1, kDebugScript, "NOP");
}
void Script::o_nop8() {
uint8 tmp = readScript8bits();
- debugScript(1, true, "NOP8: 0x%02X", tmp);
+ debugC(1, kDebugScript, "NOP8: 0x%02X", tmp);
}
void Script::o_nop16() {
uint16 tmp = readScript16bits();
- debugScript(1, true, "NOP16: 0x%04X", tmp);
+ debugC(1, kDebugScript, "NOP16: 0x%04X", tmp);
}
void Script::o_nop32() {
uint32 tmp = readScript32bits();
- debugScript(1, true, "NOP32: 0x%08X", tmp);
+ debugC(1, kDebugScript, "NOP32: 0x%08X", tmp);
}
void Script::o_nop8or16() {
uint16 tmp = readScript8or16bits();
- debugScript(1, true, "NOP8OR16: 0x%04X", tmp);
+ debugC(1, kDebugScript, "NOP8OR16: 0x%04X", tmp);
}
void Script::o_playsong() { // 0x02
uint16 fileref = readScript16bits();
- debugScript(1, true, "PlaySong(0x%04X): Play xmidi file", fileref);
+ debugC(1, kDebugScript, "PlaySong(0x%04X): Play xmidi file", fileref);
if (fileref == 0x4C17) {
warning("this song is special somehow");
// don't save the reference?
@@ -496,33 +475,33 @@ void Script::o_playsong() { // 0x02
}
void Script::o_bf9on() { // 0x03
- debugScript(1, true, "BF9ON: bitflag 9 turned on");
+ debugC(1, kDebugScript, "BF9ON: bitflag 9 turned on");
_bitflags |= 1 << 9;
}
void Script::o_palfadeout() {
- debugScript(1, true, "PALFADEOUT");
+ debugC(1, kDebugScript, "PALFADEOUT");
_vm->_graphicsMan->fadeOut();
}
void Script::o_bf8on() { // 0x05
- debugScript(1, true, "BF8ON: bitflag 8 turned on");
+ debugC(1, kDebugScript, "BF8ON: bitflag 8 turned on");
_bitflags |= 1 << 8;
}
void Script::o_bf6on() { // 0x06
- debugScript(1, true, "BF6ON: bitflag 6 turned on");
+ debugC(1, kDebugScript, "BF6ON: bitflag 6 turned on");
_bitflags |= 1 << 6;
}
void Script::o_bf7on() { // 0x07
- debugScript(1, true, "BF7ON: bitflag 7 turned on");
+ debugC(1, kDebugScript, "BF7ON: bitflag 7 turned on");
_bitflags |= 1 << 7;
}
void Script::o_setbackgroundsong() { // 0x08
uint16 fileref = readScript16bits();
- debugScript(1, true, "SetBackgroundSong(0x%04X)", fileref);
+ debugC(1, kDebugScript, "SetBackgroundSong(0x%04X)", fileref);
_vm->_musicPlayer->setBackgroundSong(fileref);
}
@@ -531,15 +510,15 @@ void Script::o_videofromref() { // 0x09
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugScript(1, false, "VIDEOFROMREF(0x%04X) (Not fully imp): Play video file from ref", fileref);
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%04X via 0x09", fileref);
+ debugC(1, kDebugScript, "VIDEOFROMREF(0x%04X) (Not fully imp): Play video file from ref", fileref);
+ debugC(5, kDebugVideo, "Playing video 0x%04X via 0x09", fileref);
}
switch (fileref) {
case 0x1C03: // Trilobyte logo
case 0x1C04: // Virgin logo
case 0x1C05: // Credits
if (fileref != _videoRef) {
- debugScript(1, true, "Use external file if available");
+ debugC(1, kDebugScript, "Use external file if available");
}
break;
@@ -551,12 +530,12 @@ void Script::o_videofromref() { // 0x09
case 0x206D: // Cards on table puzzle (bedroom)
case 0x2001: // Coins on table puzzle (bedroom)
if (fileref != _videoRef) {
- debugScript(1, false, " (This video is special somehow!)");
+ debugCN(1, kDebugScript, " (This video is special somehow!)");
warning("(This video (0x%04X) is special somehow!)", fileref);
}
}
if (fileref != _videoRef) {
- debugScript(1, false, "\n");
+ debugCN(1, kDebugScript, "\n");
}
// Play the video
if (!playvideofromref(fileref)) {
@@ -570,14 +549,14 @@ bool Script::playvideofromref(uint32 fileref) {
if (fileref != _videoRef) {
// Debug bitflags
- debugScript(1, false, "Play video 0x%04X (bitflags:", fileref);
+ debugCN(1, kDebugScript, "Play video 0x%04X (bitflags:", fileref);
for (int i = 15; i >= 0; i--) {
- debugScript(1, false, "%d", _bitflags & (1 << i)? 1 : 0);
+ debugCN(1, kDebugScript, "%d", _bitflags & (1 << i)? 1 : 0);
if (i % 4 == 0) {
- debugScript(1, false, " ");
+ debugCN(1, kDebugScript, " ");
}
}
- debugScript(1, true, " <- 0)");
+ debugC(1, kDebugScript, " <- 0)");
// Close the previous video file
if (_videoFile) {
@@ -634,7 +613,7 @@ bool Script::playvideofromref(uint32 fileref) {
_eventKbdChar = 0;
// Newline
- debugScript(1, false, "\n");
+ debugCN(1, kDebugScript, "\n");
}
// Let the caller know if the video has ended
@@ -646,12 +625,12 @@ bool Script::playvideofromref(uint32 fileref) {
}
void Script::o_bf5on() { // 0x0A
- debugScript(1, true, "BF5ON: bitflag 5 turned on");
+ debugC(1, kDebugScript, "BF5ON: bitflag 5 turned on");
_bitflags |= 1 << 5;
}
void Script::o_inputloopstart() { //0x0B
- debugScript(5, true, "Input loop start");
+ debugC(5, kDebugScript, "Input loop start");
// Reset the input action and the mouse cursor
_inputAction = -1;
@@ -675,7 +654,7 @@ void Script::o_keyboardaction() {
uint8 val = readScript8bits();
uint16 address = readScript16bits();
- debugScript(5, true, "Test key == 0x%02X @0x%04X", val, address);
+ debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X", val, address);
// If there's an already planned action, do nothing
if (_inputAction != -1) {
@@ -700,7 +679,7 @@ void Script::o_hotspot_rect() {
uint16 address = readScript16bits();
uint8 cursor = readScript8bits();
- debugScript(5, true, "HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d", left, top, right, bottom, address, cursor);
+ debugC(5, kDebugScript, "HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d", left, top, right, bottom, address, cursor);
// Mark the specified rectangle
Common::Rect rect(left, top, right, bottom);
@@ -710,7 +689,7 @@ void Script::o_hotspot_rect() {
void Script::o_hotspot_left() {
uint16 address = readScript16bits();
- debugScript(5, true, "HOTSPOT-LEFT @0x%04X", address);
+ debugC(5, kDebugScript, "HOTSPOT-LEFT @0x%04X", address);
// Mark the leftmost 100 pixels of the game area
Common::Rect rect(0, 80, 100, 400);
@@ -720,7 +699,7 @@ void Script::o_hotspot_left() {
void Script::o_hotspot_right() {
uint16 address = readScript16bits();
- debugScript(5, true, "HOTSPOT-RIGHT @0x%04X", address);
+ debugC(5, kDebugScript, "HOTSPOT-RIGHT @0x%04X", address);
// Mark the rightmost 100 pixels of the game area
Common::Rect rect(540, 80, 640, 400);
@@ -730,7 +709,7 @@ void Script::o_hotspot_right() {
void Script::o_hotspot_center() {
uint16 address = readScript16bits();
- debugScript(5, true, "HOTSPOT-CENTER @0x%04X", address);
+ debugC(5, kDebugScript, "HOTSPOT-CENTER @0x%04X", address);
// Mark the centermost 240 pixels of the game area
Common::Rect rect(200, 80, 440, 400);
@@ -740,7 +719,7 @@ void Script::o_hotspot_center() {
void Script::o_hotspot_current() {
uint16 address = readScript16bits();
- debugScript(5, true, "HOTSPOT-CURRENT @0x%04X", address);
+ debugC(5, kDebugScript, "HOTSPOT-CURRENT @0x%04X", address);
// The original interpreter doesn't check the position, so accept the
// whole screen
@@ -749,7 +728,7 @@ void Script::o_hotspot_current() {
}
void Script::o_inputloopend() {
- debugScript(5, true, "Input loop end");
+ debugC(5, kDebugScript, "Input loop end");
// Handle the predefined hotspots
if (_hotspotTopAction) {
@@ -802,7 +781,7 @@ void Script::o_random() {
uint16 varnum = readScript8or16bits();
uint8 maxnum = readScript8bits();
- debugScript(1, true, "RANDOM: var[0x%04X] = rand(%d)", varnum, maxnum);
+ debugC(1, kDebugScript, "RANDOM: var[0x%04X] = rand(%d)", varnum, maxnum);
setVariable(varnum, _random.getRandomNumber(maxnum));
}
@@ -810,7 +789,7 @@ void Script::o_random() {
void Script::o_jmp() {
uint16 address = readScript16bits();
- debugScript(1, true, "JMP @0x%04X", address);
+ debugC(1, kDebugScript, "JMP @0x%04X", address);
// Set the current address
_currentInstruction = address;
@@ -819,18 +798,18 @@ void Script::o_jmp() {
void Script::o_loadstring() {
uint16 varnum = readScript8or16bits();
- debugScript(1, false, "LOADSTRING var[0x%04X..] =", varnum);
+ debugCN(1, kDebugScript, "LOADSTRING var[0x%04X..] =", varnum);
do {
setVariable(varnum++, readScriptChar(true, true, true));
- debugScript(1, false, " 0x%02X", _variables[varnum - 1]);
+ debugCN(1, kDebugScript, " 0x%02X", _variables[varnum - 1]);
} while (!(getCodeByte(_currentInstruction - 1) & 0x80));
- debugScript(1, false, "\n");
+ debugCN(1, kDebugScript, "\n");
}
void Script::o_ret() {
uint8 val = readScript8bits();
- debugScript(1, true, "RET %d", val);
+ debugC(1, kDebugScript, "RET %d", val);
// Set the return value
setVariable(0x102, val);
@@ -847,7 +826,7 @@ void Script::o_ret() {
void Script::o_call() {
uint16 address = readScript16bits();
- debugScript(1, true, "CALL @0x%04X", address);
+ debugC(1, kDebugScript, "CALL @0x%04X", address);
// Save return address in the call stack
_stack[_stacktop] = _currentInstruction;
@@ -860,7 +839,7 @@ void Script::o_call() {
void Script::o_sleep() {
uint16 time = readScript16bits();
- debugScript(1, true, "SLEEP 0x%04X", time);
+ debugC(1, kDebugScript, "SLEEP 0x%04X", time);
_vm->_system->delayMillis(time * 3);
}
@@ -869,7 +848,7 @@ void Script::o_strcmpnejmp() { // 0x1A
uint16 varnum = readScript8or16bits();
uint8 result = 1;
- debugScript(1, false, "STRCMP-NEJMP: var[0x%04X..],", varnum);
+ debugCN(1, kDebugScript, "STRCMP-NEJMP: var[0x%04X..],", varnum);
do {
uint8 val = readScriptChar(true, true, true);
@@ -878,33 +857,33 @@ void Script::o_strcmpnejmp() { // 0x1A
result = 0;
}
varnum++;
- debugScript(1, false, " 0x%02X", val);
+ debugCN(1, kDebugScript, " 0x%02X", val);
} while (!(getCodeByte(_currentInstruction - 1) & 0x80));
uint16 address = readScript16bits();
if (!result) {
- debugScript(1, true, " jumping to @0x%04X", address);
+ debugC(1, kDebugScript, " jumping to @0x%04X", address);
_currentInstruction = address;
} else {
- debugScript(1, true, " not jumping");
+ debugC(1, kDebugScript, " not jumping");
}
}
void Script::o_xor_obfuscate() {
uint16 varnum = readScript8or16bits();
- debugScript(1, false, "XOR OBFUSCATE: var[0x%04X..] = ", varnum);
+ debugCN(1, kDebugScript, "XOR OBFUSCATE: var[0x%04X..] = ", varnum);
do {
uint8 val = readScript8bits();
_firstbit = ((val & 0x80) != 0);
val &= 0x4F;
setVariable(varnum, _variables[varnum] ^ val);
- debugScript(1, false, "%c", _variables[varnum]);
+ debugCN(1, kDebugScript, "%c", _variables[varnum]);
varnum++;
} while (!_firstbit);
- debugScript(1, false, "\n");
+ debugCN(1, kDebugScript, "\n");
}
void Script::o_vdxtransition() { // 0x1C
@@ -912,8 +891,8 @@ void Script::o_vdxtransition() { // 0x1C
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugScript(1, true, "VDX transition fileref = 0x%04X", fileref);
- debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%04X with transition", fileref);
+ debugC(1, kDebugScript, "VDX transition fileref = 0x%04X", fileref);
+ debugC(1, kDebugVideo, "Playing video 0x%04X with transition", fileref);
}
// Set bit 1
@@ -938,7 +917,7 @@ void Script::o_swap() {
uint16 varnum1 = readScript8or16bits();
uint16 varnum2 = readScript16bits();
- debugScript(1, true, "SWAP var[0x%04X] <-> var[0x%04X]", varnum1, varnum2);
+ debugC(1, kDebugScript, "SWAP var[0x%04X] <-> var[0x%04X]", varnum1, varnum2);
uint8 tmp = _variables[varnum1];
setVariable(varnum1, _variables[varnum2]);
@@ -948,7 +927,7 @@ void Script::o_swap() {
void Script::o_inc() {
uint16 varnum = readScript8or16bits();
- debugScript(1, true, "INC var[0x%04X]", varnum);
+ debugC(1, kDebugScript, "INC var[0x%04X]", varnum);
setVariable(varnum, _variables[varnum] + 1);
}
@@ -956,7 +935,7 @@ void Script::o_inc() {
void Script::o_dec() {
uint16 varnum = readScript8or16bits();
- debugScript(1, true, "DEC var[0x%04X]", varnum);
+ debugC(1, kDebugScript, "DEC var[0x%04X]", varnum);
setVariable(varnum, _variables[varnum] - 1);
}
@@ -982,7 +961,7 @@ void Script::o_strcmpnejmp_var() { // 0x21
}
void Script::o_copybgtofg() { // 0x22
- debugScript(1, true, "COPY_BG_TO_FG");
+ debugC(1, kDebugScript, "COPY_BG_TO_FG");
memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * 320);
}
@@ -990,7 +969,7 @@ void Script::o_strcmpeqjmp() { // 0x23
uint16 varnum = readScript8or16bits();
uint8 result = 1;
- debugScript(1, false, "STRCMP-EQJMP: var[0x%04X..],", varnum);
+ debugCN(1, kDebugScript, "STRCMP-EQJMP: var[0x%04X..],", varnum);
do {
uint8 val = readScriptChar(true, true, true);
@@ -998,15 +977,15 @@ void Script::o_strcmpeqjmp() { // 0x23
result = 0;
}
varnum++;
- debugScript(1, false, " 0x%02X", val);
+ debugCN(1, kDebugScript, " 0x%02X", val);
} while (!(getCodeByte(_currentInstruction - 1) & 0x80));
uint16 address = readScript16bits();
if (result) {
- debugScript(1, true, " jumping to @0x%04X", address);
+ debugC(1, kDebugScript, " jumping to @0x%04X", address);
_currentInstruction = address;
} else {
- debugScript(1, true, " not jumping");
+ debugC(1, kDebugScript, " not jumping");
}
}
@@ -1014,7 +993,7 @@ void Script::o_mov() {
uint16 varnum1 = readScript8or16bits();
uint16 varnum2 = readScript16bits();
- debugScript(1, true, "MOV var[0x%04X] = var[0x%04X]", varnum1, varnum2);
+ debugC(1, kDebugScript, "MOV var[0x%04X] = var[0x%04X]", varnum1, varnum2);
setVariable(varnum1, _variables[varnum2]);
}
@@ -1023,7 +1002,7 @@ void Script::o_add() {
uint16 varnum1 = readScript8or16bits();
uint16 varnum2 = readScript16bits();
- debugScript(1, true, "ADD var[0x%04X] += var[0x%04X]", varnum1, varnum2);
+ debugC(1, kDebugScript, "ADD var[0x%04X] += var[0x%04X]", varnum1, varnum2);
setVariable(varnum1, _variables[varnum1] + _variables[varnum2]);
}
@@ -1034,7 +1013,7 @@ void Script::o_videofromstring1() {
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugScript(0, true, "VIDEOFROMSTRING1 0x%04X", fileref);
+ debugC(0, kDebugScript, "VIDEOFROMSTRING1 0x%04X", fileref);
}
// Play the video
@@ -1050,7 +1029,7 @@ void Script::o_videofromstring2() {
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugScript(0, true, "VIDEOFROMSTRING2 0x%04X", fileref);
+ debugC(0, kDebugScript, "VIDEOFROMSTRING2 0x%04X", fileref);
}
// Set bit 1
@@ -1069,11 +1048,11 @@ void Script::o_videofromstring2() {
}
void Script::o_stopmidi() {
- debugScript(1, true, "STOPMIDI (TODO)");
+ debugC(1, kDebugScript, "STOPMIDI (TODO)");
}
void Script::o_endscript() {
- debugScript(1, true, "END OF SCRIPT");
+ debugC(1, kDebugScript, "END OF SCRIPT");
_vm->quitGame();
}
@@ -1081,7 +1060,7 @@ void Script::o_sethotspottop() {
uint16 address = readScript16bits();
uint8 cursor = readScript8bits();
- debugScript(5, true, "SETHOTSPOTTOP @0x%04X cursor=%d", address, cursor);
+ debugC(5, kDebugScript, "SETHOTSPOTTOP @0x%04X cursor=%d", address, cursor);
_hotspotTopAction = address;
_hotspotTopCursor = cursor;
@@ -1091,7 +1070,7 @@ void Script::o_sethotspotbottom() {
uint16 address = readScript16bits();
uint8 cursor = readScript8bits();
- debugScript(5, true, "SETHOTSPOTBOTTOM @0x%04X cursor=%d", address, cursor);
+ debugC(5, kDebugScript, "SETHOTSPOTBOTTOM @0x%04X cursor=%d", address, cursor);
_hotspotBottomAction = address;
_hotspotBottomCursor = cursor;
@@ -1101,7 +1080,7 @@ void Script::o_loadgame() {
uint16 varnum = readScript8or16bits();
uint8 slot = _variables[varnum];
- debugScript(1, true, "LOADGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
+ debugC(1, kDebugScript, "LOADGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
loadgame(slot);
_vm->_system->fillScreen(0);
@@ -1111,7 +1090,7 @@ void Script::o_savegame() {
uint16 varnum = readScript8or16bits();
uint8 slot = _variables[varnum];
- debugScript(1, true, "SAVEGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
+ debugC(1, kDebugScript, "SAVEGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
savegame(slot);
}
@@ -1119,7 +1098,7 @@ void Script::o_savegame() {
void Script::o_hotspotbottom_4() { //0x30
uint16 address = readScript16bits();
- debugScript(5, true, "HOTSPOT-BOTTOM @0x%04X", address);
+ debugC(5, kDebugScript, "HOTSPOT-BOTTOM @0x%04X", address);
// Mark the 80 pixels under the game area
Common::Rect rect(0, 400, 640, 480);
@@ -1130,7 +1109,7 @@ void Script::o_midivolume() {
uint16 arg1 = readScript16bits();
uint16 arg2 = readScript16bits();
- debugScript(1, true, "MIDI volume: %d %d", arg1, arg2);
+ debugC(1, kDebugScript, "MIDI volume: %d %d", arg1, arg2);
_vm->_musicPlayer->setGameVolume(arg1, arg2);
}
@@ -1139,13 +1118,13 @@ void Script::o_jne() {
uint16 varnum2 = readScript16bits();
uint16 address = readScript16bits();
- debugScript(1, false, "JNE: var[var[0x%04X] - 0x31] != var[0x%04X] @0x%04X", varnum1, varnum2, address);
+ debugCN(1, kDebugScript, "JNE: var[var[0x%04X] - 0x31] != var[0x%04X] @0x%04X", varnum1, varnum2, address);
if (_variables[_variables[varnum1] - 0x31] != _variables[varnum2]) {
_currentInstruction = address;
- debugScript(1, true, " jumping to @0x%04X", address);
+ debugC(1, kDebugScript, " jumping to @0x%04X", address);
} else {
- debugScript(1, true, " not jumping");
+ debugC(1, kDebugScript, " not jumping");
}
}
@@ -1153,19 +1132,19 @@ void Script::o_loadstringvar() {
uint16 varnum = readScript8or16bits();
varnum = _variables[varnum] - 0x31;
- debugScript(1, false, "LOADSTRINGVAR var[0x%04X..] =", varnum);
+ debugCN(1, kDebugScript, "LOADSTRINGVAR var[0x%04X..] =", varnum);
do {
setVariable(varnum++, readScriptChar(true, true, true));
- debugScript(1, false, " 0x%02X", _variables[varnum - 1]);
+ debugCN(1, kDebugScript, " 0x%02X", _variables[varnum - 1]);
} while (!(getCodeByte(_currentInstruction - 1) & 0x80));
- debugScript(1, false, "\n");
+ debugCN(1, kDebugScript, "\n");
}
void Script::o_chargreatjmp() {
uint16 varnum = readScript8or16bits();
uint8 result = 0;
- debugScript(1, false, "CHARGREAT-JMP: var[0x%04X..],", varnum);
+ debugCN(1, kDebugScript, "CHARGREAT-JMP: var[0x%04X..],", varnum);
do {
uint8 val = readScriptChar(true, true, true);
@@ -1173,20 +1152,20 @@ void Script::o_chargreatjmp() {
result = 1;
}
varnum++;
- debugScript(1, false, " 0x%02X", val);
+ debugCN(1, kDebugScript, " 0x%02X", val);
} while (!(getCodeByte(_currentInstruction - 1) & 0x80));
uint16 address = readScript16bits();
if (result) {
- debugScript(1, true, " jumping to @0x%04X", address);
+ debugC(1, kDebugScript, " jumping to @0x%04X", address);
_currentInstruction = address;
} else {
- debugScript(1, true, " not jumping");
+ debugC(1, kDebugScript, " not jumping");
}
}
void Script::o_bf7off() {
- debugScript(1, true, "BF7OFF: bitflag 7 turned off");
+ debugC(1, kDebugScript, "BF7OFF: bitflag 7 turned off");
_bitflags &= ~(1 << 7);
}
@@ -1194,7 +1173,7 @@ void Script::o_charlessjmp() {
uint16 varnum = readScript8or16bits();
uint8 result = 0;
- debugScript(1, false, "CHARLESS-JMP: var[0x%04X..],", varnum);
+ debugCN(1, kDebugScript, "CHARLESS-JMP: var[0x%04X..],", varnum);
do {
uint8 val = readScriptChar(true, true, true);
@@ -1202,15 +1181,15 @@ void Script::o_charlessjmp() {
result = 1;
}
varnum++;
- debugScript(1, false, " 0x%02X", val);
+ debugCN(1, kDebugScript, " 0x%02X", val);
} while (!(getCodeByte(_currentInstruction - 1) & 0x80));
uint16 address = readScript16bits();
if (result) {
- debugScript(1, true, " jumping to @0x%04X", address);
+ debugC(1, kDebugScript, " jumping to @0x%04X", address);
_currentInstruction = address;
} else {
- debugScript(1, true, " not jumping");
+ debugC(1, kDebugScript, " not jumping");
}
}
@@ -1219,11 +1198,50 @@ void Script::o_copyrecttobg() { // 0x37
uint16 top = readScript16bits();
uint16 right = readScript16bits();
uint16 bottom = readScript16bits();
+
+ // Sanity checks to prevent bad pointer access crashes
+ if (left > right) {
+ warning("COPYRECT left:%d > right:%d", left, right);
+ // swap over left and right parameters
+ uint16 j;
+ j = right;
+ right = left;
+ left = j;
+ }
+ if (top > bottom) {
+ warning("COPYRECT top:%d > bottom:%d", top, bottom);
+ // swap over top and bottom parameters
+ uint16 j;
+ j = bottom;
+ bottom = top;
+ top = j;
+ }
+ if (top < 80) {
+ warning("COPYRECT top < 80... clamping");
+ top = 80;
+ }
+ if (top >= 480) {
+ warning("COPYRECT top >= 480... clamping");
+ top = 480 - 1;
+ }
+ if (bottom >= 480) {
+ warning("COPYRECT bottom >= 480... clamping");
+ bottom = 480 - 1;
+ }
+ if (left >= 640) {
+ warning("COPYRECT left >= 640... clamping");
+ left = 640 - 1;
+ }
+ if (right >= 640) {
+ warning("COPYRECT right >= 640... clamping");
+ right = 640 - 1;
+ }
+
uint16 i, width = right - left, height = bottom - top;
uint32 offset = 0;
byte *fg, *bg;
- debugScript(1, true, "COPYRECT((%d,%d)->(%d,%d))", left, top, right, bottom);
+ debugC(1, kDebugScript, "COPYRECT((%d,%d)->(%d,%d))", left, top, right, bottom);
fg = (byte *)_vm->_graphicsMan->_foreground.getBasePtr(left, top - 80);
bg = (byte *)_vm->_graphicsMan->_background.getBasePtr(left, top - 80);
@@ -1236,13 +1254,13 @@ void Script::o_copyrecttobg() { // 0x37
}
void Script::o_restorestkpnt() {
- debugScript(1, true, "Restore stack pointer from saved (TODO)");
+ debugC(1, kDebugScript, "Restore stack pointer from saved (TODO)");
}
void Script::o_obscureswap() {
uint16 var1, var2, tmp;
- debugScript(1, true, "OBSCSWAP");
+ debugC(1, kDebugScript, "OBSCSWAP");
// Read the first variable
var1 = readScriptChar(false, true, true) * 10;
@@ -1262,7 +1280,7 @@ void Script::o_printstring() {
char stringstorage[15];
uint8 counter = 0;
- debugScript(1, true, "PRINTSTRING");
+ debugC(1, kDebugScript, "PRINTSTRING");
memset(stringstorage, 0, 15);
do {
@@ -1300,7 +1318,7 @@ void Script::o_hotspot_slot() {
uint16 address = readScript16bits();
uint16 cursor = readScript8bits();
- debugScript(1, true, "HOTSPOT-SLOT %d (%d,%d,%d,%d) @0x%04X cursor=%d (TODO)", slot, left, top, right, bottom, address, cursor);
+ debugC(1, kDebugScript, "HOTSPOT-SLOT %d (%d,%d,%d,%d) @0x%04X cursor=%d (TODO)", slot, left, top, right, bottom, address, cursor);
Common::Rect rect(left, top, right, bottom);
if (hotspot(rect, address, cursor)) {
@@ -1338,7 +1356,7 @@ void Script::o_hotspot_slot() {
}
void Script::o_checkvalidsaves() {
- debugScript(1, true, "CHECKVALIDSAVES");
+ debugC(1, kDebugScript, "CHECKVALIDSAVES");
// Reset the array of valid saves and the savegame names cache
for (int i = 0; i < 10; i++) {
@@ -1355,7 +1373,7 @@ void Script::o_checkvalidsaves() {
while (it != list.end()) {
int8 slot = it->getSaveSlot();
if (SaveLoad::isSlotValid(slot)) {
- debugScript(2, true, " Found valid savegame: %s", it->getDescription().c_str());
+ debugC(2, kDebugScript, " Found valid savegame: %s", it->getDescription().c_str());
// Mark this slot as used
setVariable(slot, 1);
@@ -1369,11 +1387,11 @@ void Script::o_checkvalidsaves() {
// Save the number of valid saves
setVariable(0x104, count);
- debugScript(1, true, " Found %d valid savegames", count);
+ debugC(1, kDebugScript, " Found %d valid savegames", count);
}
void Script::o_resetvars() {
- debugScript(1, true, "RESETVARS");
+ debugC(1, kDebugScript, "RESETVARS");
for (int i = 0; i < 0x100; i++) {
setVariable(i, 0);
}
@@ -1383,7 +1401,7 @@ void Script::o_mod() {
uint16 varnum = readScript8or16bits();
uint8 val = readScript8bits();
- debugScript(1, true, "MOD var[0x%04X] %%= %d", varnum, val);
+ debugC(1, kDebugScript, "MOD var[0x%04X] %%= %d", varnum, val);
setVariable(varnum, _variables[varnum] % val);
}
@@ -1395,7 +1413,7 @@ void Script::o_loadscript() {
while ((c = readScript8bits())) {
filename += c;
}
- debugScript(1, true, "LOADSCRIPT %s", filename.c_str());
+ debugC(1, kDebugScript, "LOADSCRIPT %s", filename.c_str());
// Just 1 level of sub-scripts are allowed
if (_savedCode) {
@@ -1430,7 +1448,7 @@ void Script::o_setvideoorigin() {
// Set bitflag 7
_bitflags |= 1 << 7;
- debugScript(1, true, "SetVideoOrigin(0x%04X,0x%04X) (%d, %d)", origX, origY, origX, origY);
+ debugC(1, kDebugScript, "SetVideoOrigin(0x%04X,0x%04X) (%d, %d)", origX, origY, origX, origY);
_vm->_videoPlayer->setOrigin(origX, origY);
}
@@ -1438,7 +1456,7 @@ void Script::o_sub() {
uint16 varnum1 = readScript8or16bits();
uint16 varnum2 = readScript16bits();
- debugScript(1, true, "SUB var[0x%04X] -= var[0x%04X]", varnum1, varnum2);
+ debugC(1, kDebugScript, "SUB var[0x%04X] -= var[0x%04X]", varnum1, varnum2);
setVariable(varnum1, _variables[varnum1] - _variables[varnum2]);
}
@@ -1448,7 +1466,7 @@ void Script::o_cellmove() {
byte *scriptBoard = &_variables[0x19];
byte startX, startY, endX, endY;
- debugScript(1, true, "CELL MOVE var[0x%02X]", depth);
+ debugC(1, kDebugScript, "CELL MOVE var[0x%02X]", depth);
if (!_staufsMove)
_staufsMove = new CellGame;
@@ -1471,7 +1489,7 @@ void Script::o_cellmove() {
void Script::o_returnscript() {
uint8 val = readScript8bits();
- debugScript(1, true, "RETURNSCRIPT @0x%02X", val);
+ debugC(1, kDebugScript, "RETURNSCRIPT @0x%02X", val);
// Are we returning from a sub-script?
if (!_savedCode) {
@@ -1504,7 +1522,7 @@ void Script::o_returnscript() {
void Script::o_sethotspotright() {
uint16 address = readScript16bits();
- debugScript(1, true, "SETHOTSPOTRIGHT @0x%04X", address);
+ debugC(1, kDebugScript, "SETHOTSPOTRIGHT @0x%04X", address);
_hotspotRightAction = address;
}
@@ -1512,13 +1530,13 @@ void Script::o_sethotspotright() {
void Script::o_sethotspotleft() {
uint16 address = readScript16bits();
- debugScript(1, true, "SETHOTSPOTLEFT @0x%04X", address);
+ debugC(1, kDebugScript, "SETHOTSPOTLEFT @0x%04X", address);
_hotspotLeftAction = address;
}
void Script::o_getcd() {
- debugScript(1, true, "GETCD");
+ debugC(1, kDebugScript, "GETCD");
// By default set it to no CD available
int8 cd = -1;
@@ -1545,7 +1563,7 @@ void Script::o_getcd() {
void Script::o_playcd() {
uint8 val = readScript8bits();
- debugScript(1, true, "PLAYCD %d", val);
+ debugC(1, kDebugScript, "PLAYCD %d", val);
if (val == 2) {
// TODO: Play the alternative logo
@@ -1557,7 +1575,7 @@ void Script::o_playcd() {
void Script::o_musicdelay() {
uint16 delay = readScript16bits();
- debugScript(1, true, "MUSICDELAY %d", delay);
+ debugC(1, kDebugScript, "MUSICDELAY %d", delay);
_vm->_musicPlayer->setBackgroundDelay(delay);
}
@@ -1569,7 +1587,7 @@ void Script::o_hotspot_outrect() {
uint16 bottom = readScript16bits();
uint16 address = readScript16bits();
- debugScript(1, true, "HOTSPOT-OUTRECT(%d,%d,%d,%d) @0x%04X (TODO)", left, top, right, bottom, address);
+ debugC(1, kDebugScript, "HOTSPOT-OUTRECT(%d,%d,%d,%d) @0x%04X (TODO)", left, top, right, bottom, address);
// Test if the current mouse position is outside the specified rectangle
Common::Rect rect(left, top, right, bottom);
@@ -1587,25 +1605,25 @@ void Script::o_stub56() {
uint8 val2 = readScript8bits();
uint8 val3 = readScript8bits();
- debugScript(1, true, "STUB56: 0x%08X 0x%02X 0x%02X", val1, val2, val3);
+ debugC(1, kDebugScript, "STUB56: 0x%08X 0x%02X 0x%02X", val1, val2, val3);
}
void Script::o_stub59() {
uint16 val1 = readScript8or16bits();
uint8 val2 = readScript8bits();
- debugScript(1, true, "STUB59: 0x%04X 0x%02X", val1, val2);
+ debugC(1, kDebugScript, "STUB59: 0x%04X 0x%02X", val1, val2);
}
void Script::o2_playsong() {
uint32 fileref = readScript32bits();
- debugScript(1, true, "PlaySong(0x%08X): Play xmidi file", fileref);
+ debugC(1, kDebugScript, "PlaySong(0x%08X): Play xmidi file", fileref);
_vm->_musicPlayer->playSong(fileref);
}
void Script::o2_setbackgroundsong() {
uint32 fileref = readScript32bits();
- debugScript(1, true, "SetBackgroundSong(0x%08X)", fileref);
+ debugC(1, kDebugScript, "SetBackgroundSong(0x%08X)", fileref);
_vm->_musicPlayer->setBackgroundSong(fileref);
}
@@ -1614,8 +1632,8 @@ void Script::o2_videofromref() {
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugScript(1, true, "VIDEOFROMREF(0x%08X) (Not fully imp): Play video file from ref", fileref);
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%08X via 0x09", fileref);
+ debugC(1, kDebugScript, "VIDEOFROMREF(0x%08X) (Not fully imp): Play video file from ref", fileref);
+ debugC(5, kDebugVideo, "Playing video 0x%08X via 0x09", fileref);
}
// Play the video
@@ -1630,8 +1648,8 @@ void Script::o2_vdxtransition() {
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugScript(1, true, "VDX transition fileref = 0x%08X", fileref);
- debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%08X with transition", fileref);
+ debugC(1, kDebugScript, "VDX transition fileref = 0x%08X", fileref);
+ debugC(1, kDebugVideo, "Playing video 0x%08X with transition", fileref);
}
// Set bit 1
@@ -1652,30 +1670,30 @@ void Script::o2_vdxtransition() {
void Script::o2_copyscreentobg() {
uint16 val = readScript16bits();
- debugScript(1, true, "CopyScreenToBG3: 0x%04X", val);
+ debugC(1, kDebugScript, "CopyScreenToBG3: 0x%04X", val);
error("Unimplemented Opcode 0x4F");
}
void Script::o2_copybgtoscreen() {
uint16 val = readScript16bits();
- debugScript(1, true, "CopyBG3ToScreen: 0x%04X", val);
+ debugC(1, kDebugScript, "CopyBG3ToScreen: 0x%04X", val);
error("Unimplemented Opcode 0x50");
}
void Script::o2_setvideoskip() {
_videoSkipAddress = readScript16bits();
- debugScript(1, true, "SetVideoSkip (0x%04X)", _videoSkipAddress);
+ debugC(1, kDebugScript, "SetVideoSkip (0x%04X)", _videoSkipAddress);
}
void Script::o2_stub52() {
uint8 arg = readScript8bits();
- debugScript(1, true, "STUB52 (0x%02X)", arg);
+ debugC(1, kDebugScript, "STUB52 (0x%02X)", arg);
}
void Script::o2_setscriptend() {
uint16 arg = readScript16bits();
- debugScript(1, true, "SetScriptEnd (0x%04X)", arg);
+ debugC(1, kDebugScript, "SetScriptEnd (0x%04X)", arg);
}
Script::OpcodeFunc Script::_opcodesT7G[NUM_OPCODES] = {
diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp
index 4626a6f81b..09c2e0d3ea 100644
--- a/engines/groovie/vdx.cpp
+++ b/engines/groovie/vdx.cpp
@@ -56,8 +56,7 @@ void VDXPlayer::setOrigin(int16 x, int16 y) {
}
uint16 VDXPlayer::loadInternal() {
- if (DebugMan.isDebugChannelEnabled(kGroovieDebugVideo) ||
- DebugMan.isDebugChannelEnabled(kGroovieDebugAll)) {
+ if (DebugMan.isDebugChannelEnabled(kDebugVideo)) {
int8 i;
debugN(1, "Groovie::VDX: New VDX: bitflags are ");
for (i = 15; i >= 0; i--) {
@@ -106,24 +105,24 @@ uint16 VDXPlayer::loadInternal() {
//_flagUpdateStill = _flagNine || _flagSix;
// Begin reading the file
- debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Playing video");
+ debugC(1, kDebugVideo, "Groovie::VDX: Playing video");
if (_file->readUint16LE() != VDX_IDENT) {
error("Groovie::VDX: This does not appear to be a 7th guest VDX file");
return 0;
} else {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: VDX file identified correctly");
+ debugC(5, kDebugVideo, "Groovie::VDX: VDX file identified correctly");
}
uint16 tmp;
// Skip unknown data: 6 bytes, ref Martine
tmp = _file->readUint16LE();
- debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine1 = 0x%04X", tmp);
+ debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine1 = 0x%04X", tmp);
tmp = _file->readUint16LE();
- debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine2 = 0x%04X", tmp);
+ debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine2 = 0x%04X", tmp);
tmp = _file->readUint16LE();
- debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine3 (FPS?) = %d", tmp);
+ debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine3 (FPS?) = %d", tmp);
return tmp;
}
@@ -144,7 +143,7 @@ bool VDXPlayer::playFrameInternal() {
if (_file->eos())
break;
- debugC(5, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Edward = 0x%04X", tmp);
+ debugC(5, kDebugVideo | kDebugUnknown, "Groovie::VDX: Edward = 0x%04X", tmp);
// Read the chunk data and decompress if needed
if (compSize)
@@ -159,18 +158,18 @@ bool VDXPlayer::playFrameInternal() {
// Use the current chunk
switch (currRes) {
case 0x00:
- debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Replay frame");
+ debugC(6, kDebugVideo, "Groovie::VDX: Replay frame");
break;
case 0x20:
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Still frame");
+ debugC(5, kDebugVideo, "Groovie::VDX: Still frame");
getStill(vdxData);
break;
case 0x25:
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Animation frame");
+ debugC(5, kDebugVideo, "Groovie::VDX: Animation frame");
getDelta(vdxData);
break;
case 0x80:
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Sound resource");
+ debugC(5, kDebugVideo, "Groovie::VDX: Sound resource");
chunkSound(vdxData);
break;
default:
@@ -182,7 +181,7 @@ bool VDXPlayer::playFrameInternal() {
// Wait until the current frame can be shown
- if (!DebugMan.isDebugChannelEnabled(kGroovieDebugFast)) {
+ if (!DebugMan.isDebugChannelEnabled(kDebugFast)) {
waitFrame();
}
// TODO: Move it to a better place
@@ -344,13 +343,13 @@ void VDXPlayer::getDelta(Common::ReadStream *in) {
void VDXPlayer::getStill(Common::ReadStream *in) {
uint16 numXTiles = in->readUint16LE();
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: numXTiles=%d", numXTiles);
+ debugC(5, kDebugVideo, "Groovie::VDX: numXTiles=%d", numXTiles);
uint16 numYTiles = in->readUint16LE();
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: numYTiles=%d", numYTiles);
+ debugC(5, kDebugVideo, "Groovie::VDX: numYTiles=%d", numYTiles);
// It's skipped in the original:
uint16 colorDepth = in->readUint16LE();
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: colorDepth=%d", colorDepth);
+ debugC(5, kDebugVideo, "Groovie::VDX: colorDepth=%d", colorDepth);
uint16 imageWidth = TILE_SIZE * numXTiles;
@@ -423,7 +422,7 @@ void VDXPlayer::getStill(Common::ReadStream *in) {
*/
} else {
// Skip the remaining data
- debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Skipping still frame");
+ debugC(10, kDebugVideo, "Groovie::VDX: Skipping still frame");
while (!in->eos()) {
in->readByte();
}
@@ -538,7 +537,7 @@ void VDXPlayer::chunkSound(Common::ReadStream *in) {
byte *data = (byte *)malloc(60000);
int chunksize = in->read(data, 60000);
- if (!DebugMan.isDebugChannelEnabled(kGroovieDebugFast)) {
+ if (!DebugMan.isDebugChannelEnabled(kDebugFast)) {
_audioStream->queueBuffer(data, chunksize, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
}
}
@@ -563,7 +562,7 @@ void VDXPlayer::setPalette(uint8 *palette) {
if (_flagSkipPalette)
return;
- debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Setting palette");
+ debugC(7, kDebugVideo, "Groovie::VDX: Setting palette");
_syst->getPaletteManager()->setPalette(palette, 0, 256);
}
diff --git a/engines/hopkins/POTFILES b/engines/hopkins/POTFILES
new file mode 100644
index 0000000000..1ea7d5111b
--- /dev/null
+++ b/engines/hopkins/POTFILES
@@ -0,0 +1,2 @@
+engines/hopkins/detection.cpp
+
diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp
index 1307cd5796..84d5c631c7 100644
--- a/engines/hopkins/computer.cpp
+++ b/engines/hopkins/computer.cpp
@@ -38,10 +38,9 @@ namespace Hopkins {
ComputerManager::ComputerManager(HopkinsEngine *vm) {
_vm = vm;
- for (int i = 0; i < 50; i++) {
- _menuText[i]._actvFl = false;
+ for (int i = 0; i < ARRAYSIZE(_menuText); i++) {
_menuText[i]._lineSize = 0;
- memset(_menuText[i]._line, 0, 90);
+ memset(_menuText[i]._line, 0, ARRAYSIZE(_menuText[0]._line));
}
Common::fill(&_inputBuf[0], &_inputBuf[200], '\0');
_breakoutSpr = NULL;
@@ -346,6 +345,7 @@ static const char _spanishText[] =
* Load Menu data
*/
void ComputerManager::loadMenu() {
+ debug(9, "ComputerManager::loadMenu()");
char *ptr;
if (_vm->_fileIO->fileExists("COMPUTAN.TXT")) {
ptr = (char *)_vm->_fileIO->loadFile("COMPUTAN.TXT");
@@ -353,46 +353,52 @@ void ComputerManager::loadMenu() {
switch (_vm->_globals->_language) {
case LANG_FR:
ptr = (char *)_vm->_globals->allocMemory(sizeof(_frenchText));
- strcpy(ptr, _frenchText);
+ Common::strlcpy(ptr, _frenchText, sizeof(_frenchText));
break;
case LANG_SP:
ptr = (char *)_vm->_globals->allocMemory(sizeof(_spanishText));
- strcpy(ptr, _spanishText);
+ Common::strlcpy(ptr, _spanishText, sizeof(_spanishText));
break;
default:
ptr = (char *)_vm->_globals->allocMemory(sizeof(_englishText));
- strcpy(ptr, _englishText);
+ Common::strlcpy(ptr, _englishText, sizeof(_englishText));
break;
}
}
char *tmpPtr = ptr;
int lineNum = 0;
- int strPos;
- bool loopCond = false;
- do {
- if (tmpPtr[0] == '%') {
- if (tmpPtr[1] == '%') {
- loopCond = true;
- break;
- }
- _menuText[lineNum]._actvFl = 1;
- strPos = 0;
- while (strPos <= 89) {
+ const char lineSep = tmpPtr[0];
+
+ while (tmpPtr[0] != '\0' && lineNum < ARRAYSIZE(_menuText)) {
+ if (tmpPtr[0] == '%' && tmpPtr[1] == '%') {
+ // End of file marker found - Break out of parse loop
+ break;
+ }
+
+ if (tmpPtr[0] == lineSep) {
+ int strPos = 0;
+ while (strPos < ARRAYSIZE(_menuText[0]._line)) {
char curChar = tmpPtr[strPos + 2];
- if (curChar == '%' || curChar == 10)
+ if (curChar == '\0' || curChar == lineSep || curChar == 0x0a) // Line Feed
break;
_menuText[lineNum]._line[strPos++] = curChar;
}
- if (strPos <= 89) {
+
+ if (strPos < ARRAYSIZE(_menuText[0]._line)) {
_menuText[lineNum]._line[strPos] = 0;
_menuText[lineNum]._lineSize = strPos - 1;
}
- ++lineNum;
+
+ if (strPos != 0) {
+ debug(9, "_menuText[%d]._line (size: %d): \"%s\"", lineNum, _menuText[lineNum]._lineSize, _menuText[lineNum]._line);
+ ++lineNum;
+ }
}
++tmpPtr;
- } while (!loopCond);
+ }
+
_vm->_globals->freeMemory((byte *)ptr);
}
diff --git a/engines/hopkins/computer.h b/engines/hopkins/computer.h
index e8857a234b..ba50dca4cf 100644
--- a/engines/hopkins/computer.h
+++ b/engines/hopkins/computer.h
@@ -31,22 +31,22 @@ namespace Hopkins {
class HopkinsEngine;
-struct MenuItem {
- bool _actvFl;
- int _lineSize;
- char _line[90];
-};
-
-struct ScoreItem {
- Common::String _name;
- Common::String _score;
-};
-
enum ComputerEnum { COMPUTER_HOPKINS = 1, COMPUTER_SAMANTHA = 2, COMPUTER_PUBLIC = 3 };
class ComputerManager {
private:
HopkinsEngine *_vm;
+
+ struct MenuItem {
+ int _lineSize;
+ char _line[90];
+ };
+
+ struct ScoreItem {
+ Common::String _name;
+ Common::String _score;
+ };
+
MenuItem _menuText[50];
char _inputBuf[200];
ScoreItem _score[6];
@@ -84,14 +84,14 @@ private:
void displayLives();
void displayBricks();
void displayGamesSubMenu();
- int displayHiscores();
+ int displayHiscores();
void displayHiscoreLine(const byte *objectData, int x, int y, int curChar);
void displayMessage(int xp, int yp, int textIdx);
void displayScore();
void displayScoreChar(int charPos, int charDisp);
void getScoreName();
void playBreakout();
- int moveBall();
+ int moveBall();
void saveScore();
void checkBallCollisions();
diff --git a/engines/hopkins/debugger.cpp b/engines/hopkins/debugger.cpp
index 14b1c183a8..3dcfdfea7b 100644
--- a/engines/hopkins/debugger.cpp
+++ b/engines/hopkins/debugger.cpp
@@ -30,18 +30,18 @@ namespace Hopkins {
Debugger::Debugger(HopkinsEngine *vm) : GUI::Debugger() {
_vm = vm;
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("rects", WRAP_METHOD(Debugger, cmd_DirtyRects));
- DCmd_Register("teleport", WRAP_METHOD(Debugger, cmd_Teleport));
- DCmd_Register("show_room", WRAP_METHOD(Debugger, cmd_ShowCurrentRoom));
- DCmd_Register("zones", WRAP_METHOD(Debugger, cmd_Zones));
- DCmd_Register("lines", WRAP_METHOD(Debugger, cmd_Lines));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("rects", WRAP_METHOD(Debugger, cmd_DirtyRects));
+ registerCmd("teleport", WRAP_METHOD(Debugger, cmd_Teleport));
+ registerCmd("show_room", WRAP_METHOD(Debugger, cmd_ShowCurrentRoom));
+ registerCmd("zones", WRAP_METHOD(Debugger, cmd_Zones));
+ registerCmd("lines", WRAP_METHOD(Debugger, cmd_Lines));
}
// Turns dirty rects on or off
bool Debugger::cmd_DirtyRects(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("%s: [on | off]\n", argv[0]);
+ debugPrintf("%s: [on | off]\n", argv[0]);
return true;
} else {
_vm->_graphicsMan->_showDirtyRects = !strcmp(argv[1], "on");
@@ -52,7 +52,7 @@ bool Debugger::cmd_DirtyRects(int argc, const char **argv) {
// Change room number
bool Debugger::cmd_Teleport(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("%s: [Room number]\n", argv[0]);
+ debugPrintf("%s: [Room number]\n", argv[0]);
return true;
} else {
_vm->_globals->_exitId = atoi(argv[1]);
@@ -62,13 +62,13 @@ bool Debugger::cmd_Teleport(int argc, const char **argv) {
// Display room number
bool Debugger::cmd_ShowCurrentRoom(int argc, const char **argv) {
- DebugPrintf("Current room: %d\n", _vm->_globals->_curRoomNum);
+ debugPrintf("Current room: %d\n", _vm->_globals->_curRoomNum);
return true;
}
bool Debugger::cmd_Zones(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("%s: [on | off]\n", argv[0]);
+ debugPrintf("%s: [on | off]\n", argv[0]);
return true;
} else {
_vm->_graphicsMan->_showZones = !strcmp(argv[1], "on");
@@ -78,7 +78,7 @@ if (argc != 2) {
bool Debugger::cmd_Lines(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("%s: [on | off]\n", argv[0]);
+ debugPrintf("%s: [on | off]\n", argv[0]);
return true;
} else {
_vm->_graphicsMan->_showLines = !strcmp(argv[1], "on");
diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp
index 75f429f860..6620f2878c 100644
--- a/engines/hopkins/files.cpp
+++ b/engines/hopkins/files.cpp
@@ -51,12 +51,13 @@ byte *FileManager::loadFile(const Common::String &file) {
// Allocate space for the file contents
size_t filesize = f.size();
- byte *data = _vm->_globals->allocMemory(filesize);
+ byte *data = _vm->_globals->allocMemory(filesize+1);
if (!data)
error("Error allocating space for file being loaded - %s", file.c_str());
readStream(f, data, filesize);
f.close();
+ data[filesize] = '\0';
return data;
}
diff --git a/engines/hugo/console.cpp b/engines/hugo/console.cpp
index 56025bfbfd..d02c42658f 100644
--- a/engines/hugo/console.cpp
+++ b/engines/hugo/console.cpp
@@ -30,12 +30,12 @@
namespace Hugo {
HugoConsole::HugoConsole(HugoEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("listscreens", WRAP_METHOD(HugoConsole, Cmd_listScreens));
- DCmd_Register("listobjects", WRAP_METHOD(HugoConsole, Cmd_listObjects));
- DCmd_Register("getobject", WRAP_METHOD(HugoConsole, Cmd_getObject));
- DCmd_Register("getallobjects", WRAP_METHOD(HugoConsole, Cmd_getAllObjects));
- DCmd_Register("gotoscreen", WRAP_METHOD(HugoConsole, Cmd_gotoScreen));
- DCmd_Register("Boundaries", WRAP_METHOD(HugoConsole, Cmd_boundaries));
+ registerCmd("listscreens", WRAP_METHOD(HugoConsole, Cmd_listScreens));
+ registerCmd("listobjects", WRAP_METHOD(HugoConsole, Cmd_listObjects));
+ registerCmd("getobject", WRAP_METHOD(HugoConsole, Cmd_getObject));
+ registerCmd("getallobjects", WRAP_METHOD(HugoConsole, Cmd_getAllObjects));
+ registerCmd("gotoscreen", WRAP_METHOD(HugoConsole, Cmd_gotoScreen));
+ registerCmd("Boundaries", WRAP_METHOD(HugoConsole, Cmd_boundaries));
}
HugoConsole::~HugoConsole() {
@@ -62,7 +62,7 @@ static int strToInt(const char *s) {
*/
bool HugoConsole::Cmd_gotoScreen(int argc, const char **argv) {
if ((argc != 2) || (strToInt(argv[1]) > _vm->_numScreens)){
- DebugPrintf("Usage: %s <screen number>\n", argv[0]);
+ debugPrintf("Usage: %s <screen number>\n", argv[0]);
return true;
}
@@ -75,13 +75,13 @@ bool HugoConsole::Cmd_gotoScreen(int argc, const char **argv) {
*/
bool HugoConsole::Cmd_listScreens(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
- DebugPrintf("Available screens for this game are:\n");
+ debugPrintf("Available screens for this game are:\n");
for (int i = 0; i < _vm->_numScreens; i++)
- DebugPrintf("%2d - %s\n", i, _vm->_text->getScreenNames(i));
+ debugPrintf("%2d - %s\n", i, _vm->_text->getScreenNames(i));
return true;
}
@@ -90,14 +90,14 @@ bool HugoConsole::Cmd_listScreens(int argc, const char **argv) {
*/
bool HugoConsole::Cmd_listObjects(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
- DebugPrintf("Available objects for this game are:\n");
+ debugPrintf("Available objects for this game are:\n");
for (int i = 0; i < _vm->_object->_numObj; i++) {
if (_vm->_object->_objects[i]._genericCmd & TAKE)
- DebugPrintf("%2d - %s\n", i, _vm->_text->getNoun(_vm->_object->_objects[i]._nounIndex, 2));
+ debugPrintf("%2d - %s\n", i, _vm->_text->getNoun(_vm->_object->_objects[i]._nounIndex, 2));
}
return true;
}
@@ -107,14 +107,14 @@ bool HugoConsole::Cmd_listObjects(int argc, const char **argv) {
*/
bool HugoConsole::Cmd_getObject(int argc, const char **argv) {
if ((argc != 2) || (strToInt(argv[1]) > _vm->_object->_numObj)) {
- DebugPrintf("Usage: %s <object number>\n", argv[0]);
+ debugPrintf("Usage: %s <object number>\n", argv[0]);
return true;
}
if (_vm->_object->_objects[strToInt(argv[1])]._genericCmd & TAKE)
_vm->_parser->takeObject(&_vm->_object->_objects[strToInt(argv[1])]);
else
- DebugPrintf("Object not available\n");
+ debugPrintf("Object not available\n");
return true;
}
@@ -124,7 +124,7 @@ bool HugoConsole::Cmd_getObject(int argc, const char **argv) {
*/
bool HugoConsole::Cmd_getAllObjects(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
@@ -141,7 +141,7 @@ bool HugoConsole::Cmd_getAllObjects(int argc, const char **argv) {
*/
bool HugoConsole::Cmd_boundaries(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
diff --git a/engines/kyra/POTFILES b/engines/kyra/POTFILES
index 16888e2c5a..e5b380e52e 100644
--- a/engines/kyra/POTFILES
+++ b/engines/kyra/POTFILES
@@ -1,3 +1,4 @@
engines/kyra/detection.cpp
engines/kyra/lol.cpp
engines/kyra/sound_midi.cpp
+engines/kyra/saveload_eob.cpp
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index e4806afb70..4a90722a35 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -40,45 +40,45 @@ Debugger::Debugger(KyraEngine_v1 *vm)
}
void Debugger::initialize() {
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("screen_debug_mode", WRAP_METHOD(Debugger, cmd_setScreenDebug));
- DCmd_Register("load_palette", WRAP_METHOD(Debugger, cmd_loadPalette));
- DCmd_Register("facings", WRAP_METHOD(Debugger, cmd_showFacings));
- DCmd_Register("gamespeed", WRAP_METHOD(Debugger, cmd_gameSpeed));
- DCmd_Register("flags", WRAP_METHOD(Debugger, cmd_listFlags));
- DCmd_Register("toggleflag", WRAP_METHOD(Debugger, cmd_toggleFlag));
- DCmd_Register("queryflag", WRAP_METHOD(Debugger, cmd_queryFlag));
- DCmd_Register("timers", WRAP_METHOD(Debugger, cmd_listTimers));
- DCmd_Register("settimercountdown", WRAP_METHOD(Debugger, cmd_setTimerCountdown));
-}
-
-bool Debugger::cmd_setScreenDebug(int argc, const char **argv) {
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("screen_debug_mode", WRAP_METHOD(Debugger, cmdSetScreenDebug));
+ registerCmd("load_palette", WRAP_METHOD(Debugger, cmdLoadPalette));
+ registerCmd("facings", WRAP_METHOD(Debugger, cmdShowFacings));
+ registerCmd("gamespeed", WRAP_METHOD(Debugger, cmdGameSpeed));
+ registerCmd("flags", WRAP_METHOD(Debugger, cmdListFlags));
+ registerCmd("toggleflag", WRAP_METHOD(Debugger, cmdToggleFlag));
+ registerCmd("queryflag", WRAP_METHOD(Debugger, cmdQueryFlag));
+ registerCmd("timers", WRAP_METHOD(Debugger, cmdListTimers));
+ registerCmd("settimercountdown", WRAP_METHOD(Debugger, cmdSetTimerCountdown));
+}
+
+bool Debugger::cmdSetScreenDebug(int argc, const char **argv) {
if (argc > 1) {
if (scumm_stricmp(argv[1], "enable") == 0)
_vm->screen()->enableScreenDebug(true);
else if (scumm_stricmp(argv[1], "disable") == 0)
_vm->screen()->enableScreenDebug(false);
else
- DebugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n");
+ debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n");
} else {
- DebugPrintf("Screen debug mode is %s.\n", (_vm->screen()->queryScreenDebug() ? "enabled" : "disabled"));
- DebugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n");
+ debugPrintf("Screen debug mode is %s.\n", (_vm->screen()->queryScreenDebug() ? "enabled" : "disabled"));
+ debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n");
}
return true;
}
-bool Debugger::cmd_loadPalette(int argc, const char **argv) {
+bool Debugger::cmdLoadPalette(int argc, const char **argv) {
Palette palette(_vm->screen()->getPalette(0).getNumColors());
if (argc <= 1) {
- DebugPrintf("Use load_palette <file> [start_col] [end_col]\n");
+ debugPrintf("Use load_palette <file> [start_col] [end_col]\n");
return true;
}
if (_vm->game() != GI_KYRA1 && _vm->resource()->getFileSize(argv[1]) != 768) {
uint8 *buffer = new uint8[320 * 200 * sizeof(uint8)];
if (!buffer) {
- DebugPrintf("ERROR: Cannot allocate buffer for screen region!\n");
+ debugPrintf("ERROR: Cannot allocate buffer for screen region!\n");
return true;
}
@@ -89,7 +89,7 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) {
delete[] buffer;
} else if (!_vm->screen()->loadPalette(argv[1], palette)) {
- DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]);
+ debugPrintf("ERROR: Palette '%s' not found!\n", argv[1]);
return true;
}
@@ -111,87 +111,87 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) {
return true;
}
-bool Debugger::cmd_showFacings(int argc, const char **argv) {
- DebugPrintf("Facing directions:\n");
- DebugPrintf("7 0 1\n");
- DebugPrintf(" \\ | / \n");
- DebugPrintf("6--*--2\n");
- DebugPrintf(" / | \\\n");
- DebugPrintf("5 4 3\n");
+bool Debugger::cmdShowFacings(int argc, const char **argv) {
+ debugPrintf("Facing directions:\n");
+ debugPrintf("7 0 1\n");
+ debugPrintf(" \\ | / \n");
+ debugPrintf("6--*--2\n");
+ debugPrintf(" / | \\\n");
+ debugPrintf("5 4 3\n");
return true;
}
-bool Debugger::cmd_gameSpeed(int argc, const char **argv) {
+bool Debugger::cmdGameSpeed(int argc, const char **argv) {
if (argc == 2) {
int val = atoi(argv[1]);
if (val < 1 || val > 1000) {
- DebugPrintf("speed must lie between 1 and 1000 (default: 60)\n");
+ debugPrintf("speed must lie between 1 and 1000 (default: 60)\n");
return true;
}
_vm->_tickLength = (uint8)(1000.0 / val);
} else {
- DebugPrintf("Syntax: gamespeed <value>\n");
+ debugPrintf("Syntax: gamespeed <value>\n");
}
return true;
}
-bool Debugger::cmd_listFlags(int argc, const char **argv) {
+bool Debugger::cmdListFlags(int argc, const char **argv) {
for (int i = 0, p = 0; i < (int)sizeof(_vm->_flagsTable) * 8; i++, ++p) {
- DebugPrintf("(%-3i): %-2i", i, _vm->queryGameFlag(i));
+ debugPrintf("(%-3i): %-2i", i, _vm->queryGameFlag(i));
if (p == 5) {
- DebugPrintf("\n");
+ debugPrintf("\n");
p -= 6;
}
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
-bool Debugger::cmd_toggleFlag(int argc, const char **argv) {
+bool Debugger::cmdToggleFlag(int argc, const char **argv) {
if (argc > 1) {
uint flag = atoi(argv[1]);
if (_vm->queryGameFlag(flag))
_vm->resetGameFlag(flag);
else
_vm->setGameFlag(flag);
- DebugPrintf("Flag %i is now %i\n", flag, _vm->queryGameFlag(flag));
+ debugPrintf("Flag %i is now %i\n", flag, _vm->queryGameFlag(flag));
} else {
- DebugPrintf("Syntax: toggleflag <flag>\n");
+ debugPrintf("Syntax: toggleflag <flag>\n");
}
return true;
}
-bool Debugger::cmd_queryFlag(int argc, const char **argv) {
+bool Debugger::cmdQueryFlag(int argc, const char **argv) {
if (argc > 1) {
uint flag = atoi(argv[1]);
- DebugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag));
+ debugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag));
} else {
- DebugPrintf("Syntax: queryflag <flag>\n");
+ debugPrintf("Syntax: queryflag <flag>\n");
}
return true;
}
-bool Debugger::cmd_listTimers(int argc, const char **argv) {
- DebugPrintf("Current time: %-8u\n", g_system->getMillis());
+bool Debugger::cmdListTimers(int argc, const char **argv) {
+ debugPrintf("Current time: %-8u\n", g_system->getMillis());
for (int i = 0; i < _vm->timer()->count(); i++)
- DebugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i %-8u\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i), _vm->timer()->getNextRun(i));
+ debugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i %-8u\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i), _vm->timer()->getNextRun(i));
return true;
}
-bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) {
+bool Debugger::cmdSetTimerCountdown(int argc, const char **argv) {
if (argc > 2) {
uint timer = atoi(argv[1]);
uint countdown = atoi(argv[2]);
_vm->timer()->setCountdown(timer, countdown);
- DebugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer));
+ debugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer));
} else {
- DebugPrintf("Syntax: settimercountdown <timer> <countdown>\n");
+ debugPrintf("Syntax: settimercountdown <timer> <countdown>\n");
}
return true;
@@ -204,21 +204,21 @@ Debugger_LoK::Debugger_LoK(KyraEngine_LoK *vm)
}
void Debugger_LoK::initialize() {
- DCmd_Register("enter", WRAP_METHOD(Debugger_LoK, cmd_enterRoom));
- DCmd_Register("scenes", WRAP_METHOD(Debugger_LoK, cmd_listScenes));
- DCmd_Register("give", WRAP_METHOD(Debugger_LoK, cmd_giveItem));
- DCmd_Register("birthstones", WRAP_METHOD(Debugger_LoK, cmd_listBirthstones));
+ registerCmd("enter", WRAP_METHOD(Debugger_LoK, cmdEnterRoom));
+ registerCmd("scenes", WRAP_METHOD(Debugger_LoK, cmdListScenes));
+ registerCmd("give", WRAP_METHOD(Debugger_LoK, cmdGiveItem));
+ registerCmd("birthstones", WRAP_METHOD(Debugger_LoK, cmdListBirthstones));
Debugger::initialize();
}
-bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) {
+bool Debugger_LoK::cmdEnterRoom(int argc, const char **argv) {
uint direction = 0;
if (argc > 1) {
int room = atoi(argv[1]);
// game will crash if entering a non-existent room
if (room >= _vm->_roomTableSize) {
- DebugPrintf("room number must be any value between (including) 0 and %d\n", _vm->_roomTableSize - 1);
+ debugPrintf("room number must be any value between (including) 0 and %d\n", _vm->_roomTableSize - 1);
return true;
}
@@ -246,44 +246,44 @@ bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) {
return false;
}
- DebugPrintf("Syntax: room <roomnum> <direction>\n");
+ debugPrintf("Syntax: room <roomnum> <direction>\n");
return true;
}
-bool Debugger_LoK::cmd_listScenes(int argc, const char **argv) {
+bool Debugger_LoK::cmdListScenes(int argc, const char **argv) {
for (int i = 0; i < _vm->_roomTableSize; i++) {
- DebugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]);
+ debugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]);
if (!(i % 8))
- DebugPrintf("\n");
+ debugPrintf("\n");
}
- DebugPrintf("\n");
- DebugPrintf("Current room: %i\n", _vm->_currentRoom);
+ debugPrintf("\n");
+ debugPrintf("Current room: %i\n", _vm->_currentRoom);
return true;
}
-bool Debugger_LoK::cmd_giveItem(int argc, const char **argv) {
+bool Debugger_LoK::cmdGiveItem(int argc, const char **argv) {
if (argc == 2) {
int item = atoi(argv[1]);
// Kyrandia 1 has only 108 items (-1 to 106), otherwise it will crash
if (item < -1 || item > 106) {
- DebugPrintf("'itemid' must be any value between (including) -1 and 106\n");
+ debugPrintf("'itemid' must be any value between (including) -1 and 106\n");
return true;
}
_vm->setMouseItem(item);
_vm->_itemInHand = item;
} else {
- DebugPrintf("Syntax: give <itemid>\n");
+ debugPrintf("Syntax: give <itemid>\n");
}
return true;
}
-bool Debugger_LoK::cmd_listBirthstones(int argc, const char **argv) {
- DebugPrintf("Needed birthstone gems:\n");
+bool Debugger_LoK::cmdListBirthstones(int argc, const char **argv) {
+ debugPrintf("Needed birthstone gems:\n");
for (int i = 0; i < ARRAYSIZE(_vm->_birthstoneGemTable); ++i)
- DebugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]);
+ debugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]);
return true;
}
@@ -293,23 +293,23 @@ Debugger_v2::Debugger_v2(KyraEngine_v2 *vm) : Debugger(vm), _vm(vm) {
}
void Debugger_v2::initialize() {
- DCmd_Register("character_info", WRAP_METHOD(Debugger_v2, cmd_characterInfo));
- DCmd_Register("enter", WRAP_METHOD(Debugger_v2, cmd_enterScene));
- DCmd_Register("scenes", WRAP_METHOD(Debugger_v2, cmd_listScenes));
- DCmd_Register("scene_info", WRAP_METHOD(Debugger_v2, cmd_sceneInfo));
- DCmd_Register("scene_to_facing", WRAP_METHOD(Debugger_v2, cmd_sceneToFacing));
- DCmd_Register("give", WRAP_METHOD(Debugger_v2, cmd_giveItem));
+ registerCmd("character_info", WRAP_METHOD(Debugger_v2, cmdCharacterInfo));
+ registerCmd("enter", WRAP_METHOD(Debugger_v2, cmdEnterScene));
+ registerCmd("scenes", WRAP_METHOD(Debugger_v2, cmdListScenes));
+ registerCmd("scene_info", WRAP_METHOD(Debugger_v2, cmdSceneInfo));
+ registerCmd("scene_to_facing", WRAP_METHOD(Debugger_v2, cmdSceneToFacing));
+ registerCmd("give", WRAP_METHOD(Debugger_v2, cmdGiveItem));
Debugger::initialize();
}
-bool Debugger_v2::cmd_enterScene(int argc, const char **argv) {
+bool Debugger_v2::cmdEnterScene(int argc, const char **argv) {
uint direction = 0;
if (argc > 1) {
int scene = atoi(argv[1]);
// game will crash if entering a non-existent scene
if (scene >= _vm->_sceneListSize) {
- DebugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize - 1);
+ debugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize - 1);
return true;
}
@@ -337,40 +337,40 @@ bool Debugger_v2::cmd_enterScene(int argc, const char **argv) {
return false;
}
- DebugPrintf("Syntax: %s <scenenum> <direction>\n", argv[0]);
+ debugPrintf("Syntax: %s <scenenum> <direction>\n", argv[0]);
return true;
}
-bool Debugger_v2::cmd_listScenes(int argc, const char **argv) {
+bool Debugger_v2::cmdListScenes(int argc, const char **argv) {
int shown = 1;
for (int i = 0; i < _vm->_sceneListSize; ++i) {
if (_vm->_sceneList[i].filename1[0]) {
- DebugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1);
+ debugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1);
if (!(shown % 5))
- DebugPrintf("\n");
+ debugPrintf("\n");
++shown;
}
}
- DebugPrintf("\n");
- DebugPrintf("Current scene: %i\n", _vm->_currentScene);
+ debugPrintf("\n");
+ debugPrintf("Current scene: %i\n", _vm->_currentScene);
return true;
}
-bool Debugger_v2::cmd_sceneInfo(int argc, const char **argv) {
- DebugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1);
- DebugPrintf("\n");
- DebugPrintf("Exit information:\n");
- DebugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1);
- DebugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2);
- DebugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3);
- DebugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4);
- DebugPrintf("Special exit information:\n");
+bool Debugger_v2::cmdSceneInfo(int argc, const char **argv) {
+ debugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1);
+ debugPrintf("\n");
+ debugPrintf("Exit information:\n");
+ debugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1);
+ debugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2);
+ debugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3);
+ debugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4);
+ debugPrintf("Special exit information:\n");
if (!_vm->_specialExitCount) {
- DebugPrintf("No special exits.\n");
+ debugPrintf("No special exits.\n");
} else {
- DebugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount);
+ debugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount);
for (int i = 0; i < _vm->_specialExitCount; ++i) {
- DebugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i,
+ debugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i,
_vm->_specialExitTable[20 + i], _vm->_specialExitTable[0 + i], _vm->_specialExitTable[5 + i],
_vm->_specialExitTable[10 + i], _vm->_specialExitTable[15 + i]);
}
@@ -379,20 +379,20 @@ bool Debugger_v2::cmd_sceneInfo(int argc, const char **argv) {
return true;
}
-bool Debugger_v2::cmd_characterInfo(int argc, const char **argv) {
- DebugPrintf("Main character is in scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1);
- DebugPrintf("Position: %dx%d\n", _vm->_mainCharacter.x1, _vm->_mainCharacter.y1);
- DebugPrintf("Facing: %d\n", _vm->_mainCharacter.facing);
- DebugPrintf("Inventory:\n");
+bool Debugger_v2::cmdCharacterInfo(int argc, const char **argv) {
+ debugPrintf("Main character is in scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1);
+ debugPrintf("Position: %dx%d\n", _vm->_mainCharacter.x1, _vm->_mainCharacter.y1);
+ debugPrintf("Facing: %d\n", _vm->_mainCharacter.facing);
+ debugPrintf("Inventory:\n");
for (int i = 0; i < 20; ++i) {
- DebugPrintf("%-2d ", int8(_vm->_mainCharacter.inventory[i]));
+ debugPrintf("%-2d ", int8(_vm->_mainCharacter.inventory[i]));
if (i == 9 || i == 19)
- DebugPrintf("\n");
+ debugPrintf("\n");
}
return true;
}
-bool Debugger_v2::cmd_sceneToFacing(int argc, const char **argv) {
+bool Debugger_v2::cmdSceneToFacing(int argc, const char **argv) {
if (argc == 2) {
int facing = atoi(argv[1]);
int16 exit = -1;
@@ -418,26 +418,26 @@ bool Debugger_v2::cmd_sceneToFacing(int argc, const char **argv) {
break;
}
- DebugPrintf("Exit to facing %d leads to room %d.\n", facing, exit);
+ debugPrintf("Exit to facing %d leads to room %d.\n", facing, exit);
} else {
- DebugPrintf("Usage: %s <facing>\n", argv[0]);
+ debugPrintf("Usage: %s <facing>\n", argv[0]);
}
return true;
}
-bool Debugger_v2::cmd_giveItem(int argc, const char **argv) {
+bool Debugger_v2::cmdGiveItem(int argc, const char **argv) {
if (argc == 2) {
int item = atoi(argv[1]);
if (item < -1 || item > _vm->engineDesc().maxItemId) {
- DebugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId);
+ debugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId);
return true;
}
_vm->setHandItem(item);
} else {
- DebugPrintf("Syntax: give <itemid>\n");
+ debugPrintf("Syntax: give <itemid>\n");
}
return true;
@@ -449,22 +449,22 @@ Debugger_HoF::Debugger_HoF(KyraEngine_HoF *vm) : Debugger_v2(vm), _vm(vm) {
}
void Debugger_HoF::initialize() {
- DCmd_Register("pass_codes", WRAP_METHOD(Debugger_HoF, cmd_passcodes));
+ registerCmd("pass_codes", WRAP_METHOD(Debugger_HoF, cmdPasscodes));
Debugger_v2::initialize();
}
-bool Debugger_HoF::cmd_passcodes(int argc, const char **argv) {
+bool Debugger_HoF::cmdPasscodes(int argc, const char **argv) {
if (argc == 2) {
int val = atoi(argv[1]);
if (val < 0 || val > 1) {
- DebugPrintf("value must be either 1 (on) or 0 (off)\n");
+ debugPrintf("value must be either 1 (on) or 0 (off)\n");
return true;
}
_vm->_dbgPass = val;
} else {
- DebugPrintf("Syntax: pass_codes <0/1>\n");
+ debugPrintf("Syntax: pass_codes <0/1>\n");
}
return true;
@@ -482,43 +482,43 @@ Debugger_EoB::Debugger_EoB(EoBCoreEngine *vm) : Debugger(vm), _vm(vm) {
}
void Debugger_EoB::initialize() {
- DCmd_Register("import_savefile", WRAP_METHOD(Debugger_EoB, cmd_importSaveFile));
- DCmd_Register("save_original", WRAP_METHOD(Debugger_EoB, cmd_saveOriginal));
- DCmd_Register("list_monsters", WRAP_METHOD(Debugger_EoB, cmd_listMonsters));
- DCmd_Register("show_position", WRAP_METHOD(Debugger_EoB, cmd_showPosition));
- DCmd_Register("set_position", WRAP_METHOD(Debugger_EoB, cmd_setPosition));
- DCmd_Register("open_door", WRAP_METHOD(Debugger_EoB, cmd_openDoor));
- DCmd_Register("close_door", WRAP_METHOD(Debugger_EoB, cmd_closeDoor));
- DCmd_Register("list_flags", WRAP_METHOD(Debugger_EoB, cmd_listFlags));
- DCmd_Register("set_flag", WRAP_METHOD(Debugger_EoB, cmd_setFlag));
- DCmd_Register("clear_flag", WRAP_METHOD(Debugger_EoB, cmd_clearFlag));
-}
-
-bool Debugger_EoB::cmd_importSaveFile(int argc, const char **argv) {
+ registerCmd("import_savefile", WRAP_METHOD(Debugger_EoB, cmdImportSaveFile));
+ registerCmd("save_original", WRAP_METHOD(Debugger_EoB, cmdSaveOriginal));
+ registerCmd("list_monsters", WRAP_METHOD(Debugger_EoB, cmdListMonsters));
+ registerCmd("show_position", WRAP_METHOD(Debugger_EoB, cmdShowPosition));
+ registerCmd("set_position", WRAP_METHOD(Debugger_EoB, cmdSetPosition));
+ registerCmd("open_door", WRAP_METHOD(Debugger_EoB, cmdOpenDoor));
+ registerCmd("close_door", WRAP_METHOD(Debugger_EoB, cmdCloseDoor));
+ registerCmd("list_flags", WRAP_METHOD(Debugger_EoB, cmdListFlags));
+ registerCmd("set_flag", WRAP_METHOD(Debugger_EoB, cmdSetFlag));
+ registerCmd("clear_flag", WRAP_METHOD(Debugger_EoB, cmdClearFlag));
+}
+
+bool Debugger_EoB::cmdImportSaveFile(int argc, const char **argv) {
if (!_vm->_allowImport) {
- DebugPrintf("This command only works from the main menu.\n");
+ debugPrintf("This command only works from the main menu.\n");
return true;
}
if (argc == 3) {
int slot = atoi(argv[1]);
if (slot < -1 || slot > 989) {
- DebugPrintf("slot must be between (including) -1 and 989 \n");
+ debugPrintf("slot must be between (including) -1 and 989 \n");
return true;
}
- DebugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n");
+ debugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n");
_vm->loadItemDefs();
} else {
- DebugPrintf("Syntax: import_savefile <dest slot> <source file>\n (Imports source save game file to dest slot.)\n import_savefile -1\n (Imports all original save game files found and puts them into the first available slots.)\n\n");
+ debugPrintf("Syntax: import_savefile <dest slot> <source file>\n (Imports source save game file to dest slot.)\n import_savefile -1\n (Imports all original save game files found and puts them into the first available slots.)\n\n");
}
return true;
}
-bool Debugger_EoB::cmd_saveOriginal(int argc, const char **argv) {
+bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) {
if (!_vm->_runFlag) {
- DebugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n");
+ debugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n");
return true;
}
@@ -535,57 +535,57 @@ bool Debugger_EoB::cmd_saveOriginal(int argc, const char **argv) {
if (_vm->saveAsOriginalSaveFile()) {
Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA.SAV"));
if (nf.isReadable())
- DebugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
+ debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
else
- DebugPrintf("Failure.\n");
+ debugPrintf("Failure.\n");
} else {
- DebugPrintf("Failure.\n");
+ debugPrintf("Failure.\n");
}
} else {
- DebugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the orginal game executable.)\n\n");
+ debugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the orginal game executable.)\n\n");
}
return true;
} else if (argc == 2) {
int slot = atoi(argv[1]);
if (slot < 0 || slot > 5) {
- DebugPrintf("Slot must be between (including) 0 and 5.\n");
+ debugPrintf("Slot must be between (including) 0 and 5.\n");
} else if (_vm->saveAsOriginalSaveFile(slot)) {
Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA%d.SAV", slot));
if (nf.isReadable())
- DebugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
+ debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
else
- DebugPrintf("Failure.\n");
+ debugPrintf("Failure.\n");
} else {
- DebugPrintf("Failure.\n");
+ debugPrintf("Failure.\n");
}
return true;
}
- DebugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the orginal game executable.\n A save slot between 0 and 5 must be specified.)\n\n");
+ debugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the orginal game executable.\n A save slot between 0 and 5 must be specified.)\n\n");
return true;
}
-bool Debugger_EoB::cmd_listMonsters(int, const char **) {
- DebugPrintf("\nCurrent level: %d\n----------------------\n\n", _vm->_currentLevel);
- DebugPrintf("Id Type Unit Block Position Direction Sub Level Mode Dst.block HP Flags\n--------------------------------------------------------------------------------------------------------------\n");
+bool Debugger_EoB::cmdListMonsters(int, const char **) {
+ debugPrintf("\nCurrent level: %d\n----------------------\n\n", _vm->_currentLevel);
+ debugPrintf("Id Type Unit Block Position Direction Sub Level Mode Dst.block HP Flags\n--------------------------------------------------------------------------------------------------------------\n");
for (int i = 0; i < 30; i++) {
EoBMonsterInPlay *m = &_vm->_monsters[i];
- DebugPrintf("%.02d %.02d %.02d 0x%.04x %d %d %d %.02d 0x%.04x %.03d/%.03d 0x%.02x\n", i, m->type, m->unit, m->block, m->pos, m->dir, m->sub, m->mode, m->dest, m->hitPointsCur, m->hitPointsMax, m->flags);
+ debugPrintf("%.02d %.02d %.02d 0x%.04x %d %d %d %.02d 0x%.04x %.03d/%.03d 0x%.02x\n", i, m->type, m->unit, m->block, m->pos, m->dir, m->sub, m->mode, m->dest, m->hitPointsCur, m->hitPointsMax, m->flags);
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
-bool Debugger_EoB::cmd_showPosition(int, const char **) {
- DebugPrintf("\nCurrent level: %d\nCurrent Sub Level: %d\nCurrent block: %d (0x%.04x)\nNext block: %d (0x%.04x)\nCurrent direction: %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection);
+bool Debugger_EoB::cmdShowPosition(int, const char **) {
+ debugPrintf("\nCurrent level: %d\nCurrent Sub Level: %d\nCurrent block: %d (0x%.04x)\nNext block: %d (0x%.04x)\nCurrent direction: %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection);
return true;
}
-bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) {
+bool Debugger_EoB::cmdSetPosition(int argc, const char **argv) {
if (argc == 4) {
_vm->_currentBlock = atoi(argv[3]);
int sub = atoi(argv[2]);
@@ -593,7 +593,7 @@ bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) {
int maxLevel = (_vm->game() == GI_EOB1) ? 12 : 16;
if (level < 1 || level > maxLevel) {
- DebugPrintf("<level> must be a value from 1 to %d.\n\n", maxLevel);
+ debugPrintf("<level> must be a value from 1 to %d.\n\n", maxLevel);
return true;
}
@@ -613,83 +613,83 @@ bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) {
_vm->_sceneUpdateRequired = true;
_vm->gui_drawAllCharPortraitsWithStats();
- DebugPrintf("Success.\n\n");
+ debugPrintf("Success.\n\n");
} else {
- DebugPrintf("Syntax: set_position <level>, <sub level>, <block>\n");
- DebugPrintf(" (Warning: The sub level and block position parameters will not be checked. Invalid parameters may cause problems.)\n\n");
+ debugPrintf("Syntax: set_position <level>, <sub level>, <block>\n");
+ debugPrintf(" (Warning: The sub level and block position parameters will not be checked. Invalid parameters may cause problems.)\n\n");
}
return true;
}
-bool Debugger_EoB::cmd_openDoor(int, const char **) {
- DebugPrintf("Warning: Using this command may cause glitches.\n");
+bool Debugger_EoB::cmdOpenDoor(int, const char **) {
+ debugPrintf("Warning: Using this command may cause glitches.\n");
uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection);
int c = (_vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1;
int v = _vm->_levelBlockProperties[block].walls[c];
int flg = (_vm->_flags.gameID == GI_EOB1) ? 1 : 0x10;
if (_vm->_wllWallFlags[v] & flg) {
- DebugPrintf("Couldn't open any door. Make sure you're facing the door you wish to open and standing right in front of it.\n\n");
+ debugPrintf("Couldn't open any door. Make sure you're facing the door you wish to open and standing right in front of it.\n\n");
} else {
_vm->openDoor(block);
- DebugPrintf("Trying to open door at block %d.\n\n", block);
+ debugPrintf("Trying to open door at block %d.\n\n", block);
}
return true;
}
-bool Debugger_EoB::cmd_closeDoor(int, const char **) {
- DebugPrintf("Warning: Using this command may cause glitches.\n");
+bool Debugger_EoB::cmdCloseDoor(int, const char **) {
+ debugPrintf("Warning: Using this command may cause glitches.\n");
uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection);
int c = (_vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1;
int v = _vm->_levelBlockProperties[block].walls[c];
if ((_vm->_flags.gameID == GI_EOB1 && !(_vm->_wllWallFlags[v] & 1)) || (_vm->_flags.gameID == GI_EOB2 && (_vm->_wllWallFlags[v] & 0x20))) {
- DebugPrintf("Couldn't close any door. Make sure you're facing the door you wish to close and standing right in front of it.\n\n");
+ debugPrintf("Couldn't close any door. Make sure you're facing the door you wish to close and standing right in front of it.\n\n");
} else {
_vm->closeDoor(block);
- DebugPrintf("Trying to close door at block %d.\n\n", block);
+ debugPrintf("Trying to close door at block %d.\n\n", block);
}
return true;
}
-bool Debugger_EoB::cmd_listFlags(int, const char **) {
- DebugPrintf("Flag Status\n----------------------\n\n");
+bool Debugger_EoB::cmdListFlags(int, const char **) {
+ debugPrintf("Flag Status\n----------------------\n\n");
for (int i = 0; i < 32; i++) {
uint32 flag = 1 << i;
- DebugPrintf("%.2d %s\n", i, _vm->checkScriptFlags(flag) ? "TRUE" : "FALSE");
+ debugPrintf("%.2d %s\n", i, _vm->checkScriptFlags(flag) ? "TRUE" : "FALSE");
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
-bool Debugger_EoB::cmd_setFlag(int argc, const char **argv) {
+bool Debugger_EoB::cmdSetFlag(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Syntax: set_flag <flag>\n\n");
+ debugPrintf("Syntax: set_flag <flag>\n\n");
return true;
}
int flag = atoi(argv[1]);
if (flag < 0 || flag > 31) {
- DebugPrintf("<flag> must be a value from 0 to 31.\n\n");
+ debugPrintf("<flag> must be a value from 0 to 31.\n\n");
} else {
_vm->setScriptFlags(1 << flag);
- DebugPrintf("Flag '%.2d' has been set.\n\n", flag);
+ debugPrintf("Flag '%.2d' has been set.\n\n", flag);
}
return true;
}
-bool Debugger_EoB::cmd_clearFlag(int argc, const char **argv) {
+bool Debugger_EoB::cmdClearFlag(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Syntax: clear_flag <flag>\n\n");
+ debugPrintf("Syntax: clear_flag <flag>\n\n");
return true;
}
int flag = atoi(argv[1]);
if (flag < 0 || flag > 31) {
- DebugPrintf("<flag> must be a value from 0 to 31.\n\n");
+ debugPrintf("<flag> must be a value from 0 to 31.\n\n");
} else {
_vm->clearScriptFlags(1 << flag);
- DebugPrintf("Flag '%.2d' has been cleared.\n\n", flag);
+ debugPrintf("Flag '%.2d' has been cleared.\n\n", flag);
}
return true;
diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h
index aaf7c51c18..15cee2d592 100644
--- a/engines/kyra/debugger.h
+++ b/engines/kyra/debugger.h
@@ -42,15 +42,15 @@ public:
protected:
KyraEngine_v1 *_vm;
- bool cmd_setScreenDebug(int argc, const char **argv);
- bool cmd_loadPalette(int argc, const char **argv);
- bool cmd_showFacings(int argc, const char **argv);
- bool cmd_gameSpeed(int argc, const char **argv);
- bool cmd_listFlags(int argc, const char **argv);
- bool cmd_toggleFlag(int argc, const char **argv);
- bool cmd_queryFlag(int argc, const char **argv);
- bool cmd_listTimers(int argc, const char **argv);
- bool cmd_setTimerCountdown(int argc, const char **argv);
+ bool cmdSetScreenDebug(int argc, const char **argv);
+ bool cmdLoadPalette(int argc, const char **argv);
+ bool cmdShowFacings(int argc, const char **argv);
+ bool cmdGameSpeed(int argc, const char **argv);
+ bool cmdListFlags(int argc, const char **argv);
+ bool cmdToggleFlag(int argc, const char **argv);
+ bool cmdQueryFlag(int argc, const char **argv);
+ bool cmdListTimers(int argc, const char **argv);
+ bool cmdSetTimerCountdown(int argc, const char **argv);
};
class Debugger_LoK : public Debugger {
@@ -62,10 +62,10 @@ public:
protected:
KyraEngine_LoK *_vm;
- bool cmd_enterRoom(int argc, const char **argv);
- bool cmd_listScenes(int argc, const char **argv);
- bool cmd_giveItem(int argc, const char **argv);
- bool cmd_listBirthstones(int argc, const char **argv);
+ bool cmdEnterRoom(int argc, const char **argv);
+ bool cmdListScenes(int argc, const char **argv);
+ bool cmdGiveItem(int argc, const char **argv);
+ bool cmdListBirthstones(int argc, const char **argv);
};
class Debugger_v2 : public Debugger {
@@ -77,12 +77,12 @@ public:
protected:
KyraEngine_v2 *_vm;
- bool cmd_enterScene(int argc, const char **argv);
- bool cmd_listScenes(int argc, const char **argv);
- bool cmd_sceneInfo(int argc, const char **argv);
- bool cmd_characterInfo(int argc, const char **argv);
- bool cmd_sceneToFacing(int argc, const char **argv);
- bool cmd_giveItem(int argc, const char **argv);
+ bool cmdEnterScene(int argc, const char **argv);
+ bool cmdListScenes(int argc, const char **argv);
+ bool cmdSceneInfo(int argc, const char **argv);
+ bool cmdCharacterInfo(int argc, const char **argv);
+ bool cmdSceneToFacing(int argc, const char **argv);
+ bool cmdGiveItem(int argc, const char **argv);
};
class Debugger_HoF : public Debugger_v2 {
@@ -93,7 +93,7 @@ public:
protected:
KyraEngine_HoF *_vm;
- bool cmd_passcodes(int argc, const char **argv);
+ bool cmdPasscodes(int argc, const char **argv);
};
#ifdef ENABLE_LOL
@@ -119,16 +119,16 @@ public:
protected:
EoBCoreEngine *_vm;
- bool cmd_importSaveFile(int argc, const char **argv);
- bool cmd_saveOriginal(int argc, const char **argv);
- bool cmd_listMonsters(int argc, const char **argv);
- bool cmd_showPosition(int argc, const char **argv);
- bool cmd_setPosition(int argc, const char **argv);
- bool cmd_openDoor(int argc, const char **argv);
- bool cmd_closeDoor(int argc, const char **argv);
- bool cmd_listFlags(int argc, const char **argv);
- bool cmd_setFlag(int argc, const char **argv);
- bool cmd_clearFlag(int argc, const char **argv);
+ bool cmdImportSaveFile(int argc, const char **argv);
+ bool cmdSaveOriginal(int argc, const char **argv);
+ bool cmdListMonsters(int argc, const char **argv);
+ bool cmdShowPosition(int argc, const char **argv);
+ bool cmdSetPosition(int argc, const char **argv);
+ bool cmdOpenDoor(int argc, const char **argv);
+ bool cmdCloseDoor(int argc, const char **argv);
+ bool cmdListFlags(int argc, const char **argv);
+ bool cmdSetFlag(int argc, const char **argv);
+ bool cmdClearFlag(int argc, const char **argv);
};
#endif // ENABLE_EOB
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index f2a9637dfe..e1f864ddd2 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -265,7 +265,7 @@ bool LoLEngine::addItemToInventory(Item itemIndex) {
gui_drawInventory();
}
- assert(pos > 0 && pos < 48);
+ assert(pos >= 0 && pos < 48);
_inventory[pos] = itemIndex;
gui_drawInventory();
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index f950f9d5aa..89ee41e859 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -61,7 +61,7 @@ public:
~AdLibDriver();
void initDriver();
- void setSoundData(uint8 *data);
+ void setSoundData(uint8 *data, uint32 size);
void queueTrack(int track, int volume);
bool isChannelPlaying(int channel) const;
void stopAllChannels();
@@ -130,13 +130,13 @@ private:
struct Channel {
bool lock; // New to ScummVM
uint8 opExtraLevel2;
- uint8 *dataptr;
+ const uint8 *dataptr;
uint8 duration;
uint8 repeatCounter;
int8 baseOctave;
uint8 priority;
uint8 dataptrStackPos;
- uint8 *dataptrStack[4];
+ const uint8 *dataptrStack[4];
int8 baseNote;
uint8 unk29;
uint8 unk31;
@@ -194,7 +194,7 @@ private:
void setupDuration(uint8 duration, Channel &channel);
void setupNote(uint8 rawNote, Channel &channel, bool flag = false);
- void setupInstrument(uint8 regOffset, uint8 *dataptr, Channel &channel);
+ void setupInstrument(uint8 regOffset, const uint8 *dataptr, Channel &channel);
void noteOn(Channel &channel);
void adjustVolume(Channel &channel);
@@ -216,14 +216,24 @@ private:
// * One for instruments, starting at offset 500.
uint8 *getProgram(int progId) {
- uint16 offset = READ_LE_UINT16(_soundData + 2 * progId);
- //TODO: Check in LoL CD AdLib driver
- if (offset == 0xFFFF)
- return 0;
- return _soundData + READ_LE_UINT16(_soundData + 2 * progId);
+ const uint16 offset = READ_LE_UINT16(_soundData + 2 * progId);
+
+ // In case an invalid offset is specified we return nullptr to
+ // indicate an error. 0xFFFF seems to indicate "this is not a valid
+ // program/instrument". However, 0 is also invalid because it points
+ // inside the offset table itself. We also ignore any offsets outside
+ // of the actual data size.
+ // The original does not contain any safety checks and will simply
+ // read outside of the valid sound data in case an invalid offset is
+ // encountered.
+ if (offset == 0 || offset >= _soundDataSize) {
+ return nullptr;
+ } else {
+ return _soundData + offset;
+ }
}
- uint8 *getInstrument(int instrumentId) {
+ const uint8 *getInstrument(int instrumentId) {
return getProgram(_numPrograms + instrumentId);
}
@@ -231,7 +241,7 @@ private:
void executePrograms();
struct ParserOpcode {
- typedef int (AdLibDriver::*POpcode)(uint8 *&dataptr, Channel &channel, uint8 value);
+ typedef int (AdLibDriver::*POpcode)(const uint8 *&dataptr, Channel &channel, uint8 value);
POpcode function;
const char *name;
};
@@ -240,61 +250,61 @@ private:
const ParserOpcode *_parserOpcodeTable;
int _parserOpcodeTableSize;
- int update_setRepeat(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_checkRepeat(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setupProgram(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setNoteSpacing(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_jump(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_jumpToSubroutine(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_returnFromSubroutine(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setBaseOctave(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_stopChannel(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_playRest(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_writeAdLib(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setupNoteAndDuration(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setBaseNote(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setupSecondaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_stopOtherChannel(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_waitForEndOfProgram(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setupInstrument(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setupPrimaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_removePrimaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setBaseFreq(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setupPrimaryEffect2(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setPriority(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback23(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback24(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setExtraLevel1(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setupDuration(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_playNote(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setFractionalNoteSpacing(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setTempo(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_removeSecondaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setChannelTempo(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setExtraLevel3(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setExtraLevel2(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_changeExtraLevel2(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setAMDepth(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setVibratoDepth(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_changeExtraLevel1(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback38(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback39(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_removePrimaryEffect2(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_pitchBend(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_resetToGlobalTempo(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_nop(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setDurationRandomness(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_changeChannelTempo(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback46(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setupRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_playRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_removeRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback51(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback52(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback53(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setSoundTrigger(uint8 *&dataptr, Channel &channel, uint8 value);
- int update_setTempoReset(uint8 *&dataptr, Channel &channel, uint8 value);
- int updateCallback56(uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setRepeat(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_checkRepeat(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setupProgram(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setNoteSpacing(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_jump(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_jumpToSubroutine(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_returnFromSubroutine(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setBaseOctave(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_stopChannel(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_playRest(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_writeAdLib(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setupNoteAndDuration(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setBaseNote(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setupSecondaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_stopOtherChannel(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_waitForEndOfProgram(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setupInstrument(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setupPrimaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_removePrimaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setBaseFreq(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setupPrimaryEffect2(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setPriority(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback23(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback24(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setExtraLevel1(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setupDuration(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_playNote(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setFractionalNoteSpacing(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setTempo(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_removeSecondaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setChannelTempo(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setExtraLevel3(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setExtraLevel2(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_changeExtraLevel2(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setAMDepth(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setVibratoDepth(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_changeExtraLevel1(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback38(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback39(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_removePrimaryEffect2(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_pitchBend(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_resetToGlobalTempo(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_nop(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setDurationRandomness(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_changeChannelTempo(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback46(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setupRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_playRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_removeRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback51(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback52(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback53(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setSoundTrigger(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int update_setTempoReset(const uint8 *&dataptr, Channel &channel, uint8 value);
+ int updateCallback56(const uint8 *&dataptr, Channel &channel, uint8 value);
private:
// These variables have not yet been named, but some of them are partly
// known nevertheless:
@@ -358,6 +368,7 @@ private:
FM_OPL *_adlib;
uint8 *_soundData;
+ uint32 _soundDataSize;
struct QueueEntry {
QueueEntry() : data(0), id(0), volume(0) {}
@@ -421,6 +432,7 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, int version) {
memset(_channels, 0, sizeof(_channels));
_soundData = 0;
+ _soundDataSize = 0;
_vibratoAndAMDepthBits = _curRegOffset = 0;
@@ -522,7 +534,7 @@ void AdLibDriver::initDriver() {
resetAdLibState();
}
-void AdLibDriver::setSoundData(uint8 *data) {
+void AdLibDriver::setSoundData(uint8 *data, uint32 size) {
Common::StackLock lock(_mutex);
// Drop all tracks that are still queued. These would point to the old
@@ -536,6 +548,7 @@ void AdLibDriver::setSoundData(uint8 *data) {
}
_soundData = data;
+ _soundDataSize = size;
}
void AdLibDriver::queueTrack(int track, int volume) {
@@ -791,7 +804,7 @@ void AdLibDriver::executePrograms() {
// This fixes a subtle music bug where the
// wrong music would play when getting the
// quill in Kyra 1.
- uint8 *dataptr = channel.dataptr;
+ const uint8 *dataptr = channel.dataptr;
while (dataptr) {
uint8 opcode = *dataptr++;
uint8 param = *dataptr++;
@@ -1030,7 +1043,7 @@ void AdLibDriver::setupNote(uint8 rawNote, Channel &channel, bool flag) {
writeOPL(0xB0 + _curChannel, channel.regBx);
}
-void AdLibDriver::setupInstrument(uint8 regOffset, uint8 *dataptr, Channel &channel) {
+void AdLibDriver::setupInstrument(uint8 regOffset, const uint8 *dataptr, Channel &channel) {
debugC(9, kDebugLevelSound, "setupInstrument(%d, %p, %lu)", regOffset, (const void *)dataptr, (long)(&channel - _channels));
if (_curChannel >= 9)
@@ -1340,12 +1353,12 @@ uint8 AdLibDriver::calculateOpLevel2(Channel &channel) {
// parser opcodes
-int AdLibDriver::update_setRepeat(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setRepeat(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.repeatCounter = value;
return 0;
}
-int AdLibDriver::update_checkRepeat(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_checkRepeat(const uint8 *&dataptr, Channel &channel, uint8 value) {
++dataptr;
if (--channel.repeatCounter) {
int16 add = READ_LE_UINT16(dataptr - 2);
@@ -1354,14 +1367,23 @@ int AdLibDriver::update_checkRepeat(uint8 *&dataptr, Channel &channel, uint8 val
return 0;
}
-int AdLibDriver::update_setupProgram(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setupProgram(const uint8 *&dataptr, Channel &channel, uint8 value) {
if (value == 0xFF)
return 0;
- uint8 *ptr = getProgram(value);
- //TODO: Check in LoL CD AdLib driver
- if (!ptr)
+ const uint8 *ptr = getProgram(value);
+
+ // In case we encounter an invalid program we simply ignore it and do
+ // nothing instead. The original did not care about invalid programs and
+ // simply tried to play them anyway... But to avoid crashes due we ingore
+ // them.
+ // This, for example, happens in the Lands of Lore intro when Scotia gets
+ // the ring in the intro.
+ if (!ptr) {
+ debugC(3, kDebugLevelSound, "AdLibDriver::update_setupProgram: Invalid program %d specified", value);
return 0;
+ }
+
uint8 chan = *ptr++;
uint8 priority = *ptr++;
@@ -1390,12 +1412,12 @@ int AdLibDriver::update_setupProgram(uint8 *&dataptr, Channel &channel, uint8 va
return 0;
}
-int AdLibDriver::update_setNoteSpacing(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setNoteSpacing(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.spacing1 = value;
return 0;
}
-int AdLibDriver::update_jump(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_jump(const uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
int16 add = READ_LE_UINT16(dataptr); dataptr += 2;
if (_version == 1)
@@ -1407,7 +1429,7 @@ int AdLibDriver::update_jump(uint8 *&dataptr, Channel &channel, uint8 value) {
return 0;
}
-int AdLibDriver::update_jumpToSubroutine(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_jumpToSubroutine(const uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
int16 add = READ_LE_UINT16(dataptr); dataptr += 2;
channel.dataptrStack[channel.dataptrStackPos++] = dataptr;
@@ -1418,17 +1440,17 @@ int AdLibDriver::update_jumpToSubroutine(uint8 *&dataptr, Channel &channel, uint
return 0;
}
-int AdLibDriver::update_returnFromSubroutine(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_returnFromSubroutine(const uint8 *&dataptr, Channel &channel, uint8 value) {
dataptr = channel.dataptrStack[--channel.dataptrStackPos];
return 0;
}
-int AdLibDriver::update_setBaseOctave(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setBaseOctave(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.baseOctave = value;
return 0;
}
-int AdLibDriver::update_stopChannel(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_stopChannel(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.priority = 0;
if (_curChannel != 9)
noteOff(channel);
@@ -1436,30 +1458,30 @@ int AdLibDriver::update_stopChannel(uint8 *&dataptr, Channel &channel, uint8 val
return 2;
}
-int AdLibDriver::update_playRest(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_playRest(const uint8 *&dataptr, Channel &channel, uint8 value) {
setupDuration(value, channel);
noteOff(channel);
return (value != 0);
}
-int AdLibDriver::update_writeAdLib(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_writeAdLib(const uint8 *&dataptr, Channel &channel, uint8 value) {
writeOPL(value, *dataptr++);
return 0;
}
-int AdLibDriver::update_setupNoteAndDuration(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setupNoteAndDuration(const uint8 *&dataptr, Channel &channel, uint8 value) {
setupNote(value, channel);
value = *dataptr++;
setupDuration(value, channel);
return (value != 0);
}
-int AdLibDriver::update_setBaseNote(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setBaseNote(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.baseNote = value;
return 0;
}
-int AdLibDriver::update_setupSecondaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setupSecondaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.unk18 = value;
channel.unk19 = value;
channel.unk20 = channel.unk21 = *dataptr++;
@@ -1483,7 +1505,7 @@ int AdLibDriver::update_setupSecondaryEffect1(uint8 *&dataptr, Channel &channel,
return 0;
}
-int AdLibDriver::update_stopOtherChannel(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_stopOtherChannel(const uint8 *&dataptr, Channel &channel, uint8 value) {
Channel &channel2 = _channels[value];
channel2.duration = 0;
channel2.priority = 0;
@@ -1491,8 +1513,16 @@ int AdLibDriver::update_stopOtherChannel(uint8 *&dataptr, Channel &channel, uint
return 0;
}
-int AdLibDriver::update_waitForEndOfProgram(uint8 *&dataptr, Channel &channel, uint8 value) {
- uint8 *ptr = getProgram(value);
+int AdLibDriver::update_waitForEndOfProgram(const uint8 *&dataptr, Channel &channel, uint8 value) {
+ const uint8 *ptr = getProgram(value);
+
+ // Safety check in case an invalid program is specified. This would make
+ // getProgram return a nullptr and thus cause invalid memory reads.
+ if (!ptr) {
+ debugC(3, kDebugLevelSound, "AdLibDriver::update_waitForEndOfProgram: Invalid program %d specified", value);
+ return 0;
+ }
+
uint8 chan = *ptr;
if (!_channels[chan].dataptr)
@@ -1502,12 +1532,25 @@ int AdLibDriver::update_waitForEndOfProgram(uint8 *&dataptr, Channel &channel, u
return 2;
}
-int AdLibDriver::update_setupInstrument(uint8 *&dataptr, Channel &channel, uint8 value) {
- setupInstrument(_curRegOffset, getInstrument(value), channel);
+int AdLibDriver::update_setupInstrument(const uint8 *&dataptr, Channel &channel, uint8 value) {
+ const uint8 *instrument = getInstrument(value);
+
+ // We add a safety check to avoid setting up invalid instruments. This is
+ // not done in the original. However, to avoid crashes due to invalid
+ // memory reads we simply ignore the request.
+ // This happens, for example, in Hand of Fate when using the swampsnake
+ // potion on Zanthia to scare off the rat in the cave in the first chapter
+ // of the game.
+ if (!instrument) {
+ debugC(3, kDebugLevelSound, "AdLibDriver::update_setupInstrument: Invalid instrument %d specified", value);
+ return 0;
+ }
+
+ setupInstrument(_curRegOffset, instrument, channel);
return 0;
}
-int AdLibDriver::update_setupPrimaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setupPrimaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.unk29 = value;
channel.unk30 = READ_BE_UINT16(dataptr);
dataptr += 2;
@@ -1516,19 +1559,19 @@ int AdLibDriver::update_setupPrimaryEffect1(uint8 *&dataptr, Channel &channel, u
return 0;
}
-int AdLibDriver::update_removePrimaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_removePrimaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
channel.primaryEffect = 0;
channel.unk30 = 0;
return 0;
}
-int AdLibDriver::update_setBaseFreq(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setBaseFreq(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.baseFreq = value;
return 0;
}
-int AdLibDriver::update_setupPrimaryEffect2(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setupPrimaryEffect2(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.unk32 = value;
channel.unk33 = *dataptr++;
uint8 temp = *dataptr++;
@@ -1539,12 +1582,12 @@ int AdLibDriver::update_setupPrimaryEffect2(uint8 *&dataptr, Channel &channel, u
return 0;
}
-int AdLibDriver::update_setPriority(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setPriority(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.priority = value;
return 0;
}
-int AdLibDriver::updateCallback23(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback23(const uint8 *&dataptr, Channel &channel, uint8 value) {
value >>= 1;
_unkValue1 = _unkValue2 = value;
_callbackTimer = 0xFF;
@@ -1552,7 +1595,7 @@ int AdLibDriver::updateCallback23(uint8 *&dataptr, Channel &channel, uint8 value
return 0;
}
-int AdLibDriver::updateCallback24(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback24(const uint8 *&dataptr, Channel &channel, uint8 value) {
if (_unkValue5) {
if (_unkValue4 & value) {
_unkValue5 = 0;
@@ -1568,50 +1611,50 @@ int AdLibDriver::updateCallback24(uint8 *&dataptr, Channel &channel, uint8 value
return 2;
}
-int AdLibDriver::update_setExtraLevel1(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setExtraLevel1(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.opExtraLevel1 = value;
adjustVolume(channel);
return 0;
}
-int AdLibDriver::update_setupDuration(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setupDuration(const uint8 *&dataptr, Channel &channel, uint8 value) {
setupDuration(value, channel);
return (value != 0);
}
-int AdLibDriver::update_playNote(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_playNote(const uint8 *&dataptr, Channel &channel, uint8 value) {
setupDuration(value, channel);
noteOn(channel);
return (value != 0);
}
-int AdLibDriver::update_setFractionalNoteSpacing(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setFractionalNoteSpacing(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.fractionalSpacing = value & 7;
return 0;
}
-int AdLibDriver::update_setTempo(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setTempo(const uint8 *&dataptr, Channel &channel, uint8 value) {
_tempo = value;
return 0;
}
-int AdLibDriver::update_removeSecondaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_removeSecondaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
channel.secondaryEffect = 0;
return 0;
}
-int AdLibDriver::update_setChannelTempo(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setChannelTempo(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.tempo = value;
return 0;
}
-int AdLibDriver::update_setExtraLevel3(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setExtraLevel3(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.opExtraLevel3 = value;
return 0;
}
-int AdLibDriver::update_setExtraLevel2(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setExtraLevel2(const uint8 *&dataptr, Channel &channel, uint8 value) {
int channelBackUp = _curChannel;
_curChannel = value;
@@ -1623,7 +1666,7 @@ int AdLibDriver::update_setExtraLevel2(uint8 *&dataptr, Channel &channel, uint8
return 0;
}
-int AdLibDriver::update_changeExtraLevel2(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_changeExtraLevel2(const uint8 *&dataptr, Channel &channel, uint8 value) {
int channelBackUp = _curChannel;
_curChannel = value;
@@ -1638,7 +1681,7 @@ int AdLibDriver::update_changeExtraLevel2(uint8 *&dataptr, Channel &channel, uin
// Apart from initializing to zero, these two functions are the only ones that
// modify _vibratoAndAMDepthBits.
-int AdLibDriver::update_setAMDepth(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setAMDepth(const uint8 *&dataptr, Channel &channel, uint8 value) {
if (value & 1)
_vibratoAndAMDepthBits |= 0x80;
else
@@ -1648,7 +1691,7 @@ int AdLibDriver::update_setAMDepth(uint8 *&dataptr, Channel &channel, uint8 valu
return 0;
}
-int AdLibDriver::update_setVibratoDepth(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setVibratoDepth(const uint8 *&dataptr, Channel &channel, uint8 value) {
if (value & 1)
_vibratoAndAMDepthBits |= 0x40;
else
@@ -1658,13 +1701,13 @@ int AdLibDriver::update_setVibratoDepth(uint8 *&dataptr, Channel &channel, uint8
return 0;
}
-int AdLibDriver::update_changeExtraLevel1(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_changeExtraLevel1(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.opExtraLevel1 += value;
adjustVolume(channel);
return 0;
}
-int AdLibDriver::updateCallback38(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback38(const uint8 *&dataptr, Channel &channel, uint8 value) {
int channelBackUp = _curChannel;
_curChannel = value;
@@ -1693,7 +1736,7 @@ int AdLibDriver::updateCallback38(uint8 *&dataptr, Channel &channel, uint8 value
return 0;
}
-int AdLibDriver::updateCallback39(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback39(const uint8 *&dataptr, Channel &channel, uint8 value) {
if (_curChannel >= 9)
return 0;
@@ -1714,35 +1757,35 @@ int AdLibDriver::updateCallback39(uint8 *&dataptr, Channel &channel, uint8 value
return 0;
}
-int AdLibDriver::update_removePrimaryEffect2(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_removePrimaryEffect2(const uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
channel.primaryEffect = 0;
return 0;
}
-int AdLibDriver::update_pitchBend(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_pitchBend(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.pitchBend = value;
setupNote(channel.rawNote, channel, true);
return 0;
}
-int AdLibDriver::update_resetToGlobalTempo(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_resetToGlobalTempo(const uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
channel.tempo = _tempo;
return 0;
}
-int AdLibDriver::update_nop(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_nop(const uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
return 0;
}
-int AdLibDriver::update_setDurationRandomness(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setDurationRandomness(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.durationRandomness = value;
return 0;
}
-int AdLibDriver::update_changeChannelTempo(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_changeChannelTempo(const uint8 *&dataptr, Channel &channel, uint8 value) {
int tempo = channel.tempo + (int8)value;
if (tempo <= 0)
@@ -1754,7 +1797,7 @@ int AdLibDriver::update_changeChannelTempo(uint8 *&dataptr, Channel &channel, ui
return 0;
}
-int AdLibDriver::updateCallback46(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback46(const uint8 *&dataptr, Channel &channel, uint8 value) {
uint8 entry = *dataptr++;
_tablePtr1 = _unkTable2[entry++];
_tablePtr2 = _unkTable2[entry];
@@ -1765,27 +1808,43 @@ int AdLibDriver::updateCallback46(uint8 *&dataptr, Channel &channel, uint8 value
return 0;
}
-int AdLibDriver::update_setupRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setupRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value) {
int channelBackUp = _curChannel;
int regOffsetBackUp = _curRegOffset;
_curChannel = 6;
_curRegOffset = _regOffset[6];
- setupInstrument(_curRegOffset, getInstrument(value), channel);
+ const uint8 *instrument;
+ instrument = getInstrument(value);
+ if (instrument) {
+ setupInstrument(_curRegOffset, instrument, channel);
+ } else {
+ debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 6 specified", value);
+ }
_unkValue6 = channel.opLevel2;
_curChannel = 7;
_curRegOffset = _regOffset[7];
- setupInstrument(_curRegOffset, getInstrument(*dataptr++), channel);
+ instrument = getInstrument(*dataptr++);
+ if (instrument) {
+ setupInstrument(_curRegOffset, instrument, channel);
+ } else {
+ debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 7 specified", value);
+ }
_unkValue7 = channel.opLevel1;
_unkValue8 = channel.opLevel2;
_curChannel = 8;
_curRegOffset = _regOffset[8];
- setupInstrument(_curRegOffset, getInstrument(*dataptr++), channel);
+ instrument = getInstrument(*dataptr++);
+ if (instrument) {
+ setupInstrument(_curRegOffset, instrument, channel);
+ } else {
+ debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 8 specified", value);
+ }
_unkValue9 = channel.opLevel1;
_unkValue10 = channel.opLevel2;
@@ -1810,7 +1869,7 @@ int AdLibDriver::update_setupRhythmSection(uint8 *&dataptr, Channel &channel, ui
return 0;
}
-int AdLibDriver::update_playRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_playRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value) {
// Any instrument that we want to play, and which was already playing,
// is temporarily keyed off. Instruments that were off already, or
// which we don't want to play, retain their old on/off status. This is
@@ -1830,7 +1889,7 @@ int AdLibDriver::update_playRhythmSection(uint8 *&dataptr, Channel &channel, uin
return 0;
}
-int AdLibDriver::update_removeRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_removeRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
_rhythmSectionBits = 0;
@@ -1841,7 +1900,7 @@ int AdLibDriver::update_removeRhythmSection(uint8 *&dataptr, Channel &channel, u
return 0;
}
-int AdLibDriver::updateCallback51(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback51(const uint8 *&dataptr, Channel &channel, uint8 value) {
uint8 value2 = *dataptr++;
if (value & 1) {
@@ -1882,7 +1941,7 @@ int AdLibDriver::updateCallback51(uint8 *&dataptr, Channel &channel, uint8 value
return 0;
}
-int AdLibDriver::updateCallback52(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback52(const uint8 *&dataptr, Channel &channel, uint8 value) {
uint8 value2 = *dataptr++;
if (value & 1) {
@@ -1923,7 +1982,7 @@ int AdLibDriver::updateCallback52(uint8 *&dataptr, Channel &channel, uint8 value
return 0;
}
-int AdLibDriver::updateCallback53(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback53(const uint8 *&dataptr, Channel &channel, uint8 value) {
uint8 value2 = *dataptr++;
if (value & 1) {
@@ -1964,17 +2023,17 @@ int AdLibDriver::updateCallback53(uint8 *&dataptr, Channel &channel, uint8 value
return 0;
}
-int AdLibDriver::update_setSoundTrigger(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setSoundTrigger(const uint8 *&dataptr, Channel &channel, uint8 value) {
_soundTrigger = value;
return 0;
}
-int AdLibDriver::update_setTempoReset(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setTempoReset(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.tempoReset = value;
return 0;
}
-int AdLibDriver::updateCallback56(uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::updateCallback56(const uint8 *&dataptr, Channel &channel, uint8 value) {
channel.unk39 = value;
channel.unk40 = *dataptr++;
return 0;
@@ -2487,13 +2546,13 @@ void SoundAdLibPC::internalLoadFile(Common::String file) {
_soundDataPtr = new uint8[soundDataSize];
assert(_soundDataPtr);
- memcpy(_soundDataPtr, p, soundDataSize*sizeof(uint8));
+ memcpy(_soundDataPtr, p, soundDataSize);
delete[] fileData;
fileData = p = 0;
fileSize = 0;
- _driver->setSoundData(_soundDataPtr);
+ _driver->setSoundData(_soundDataPtr, soundDataSize);
_soundFileLoaded = file;
}
diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp
index 6c2d833271..a6cecc7408 100644
--- a/engines/lastexpress/debug.cpp
+++ b/engines/lastexpress/debug.cpp
@@ -60,33 +60,33 @@ Debugger::Debugger(LastExpressEngine *engine) : _engine(engine), _command(NULL),
// Register the debugger commands
// General
- DCmd_Register("help", WRAP_METHOD(Debugger, cmdHelp));
+ registerCmd("help", WRAP_METHOD(Debugger, cmdHelp));
// Data
- DCmd_Register("ls", WRAP_METHOD(Debugger, cmdListFiles));
- DCmd_Register("dump", WRAP_METHOD(Debugger, cmdDumpFiles));
+ registerCmd("ls", WRAP_METHOD(Debugger, cmdListFiles));
+ registerCmd("dump", WRAP_METHOD(Debugger, cmdDumpFiles));
- DCmd_Register("showframe", WRAP_METHOD(Debugger, cmdShowFrame));
- DCmd_Register("showbg", WRAP_METHOD(Debugger, cmdShowBg));
- DCmd_Register("playseq", WRAP_METHOD(Debugger, cmdPlaySeq));
- DCmd_Register("playsnd", WRAP_METHOD(Debugger, cmdPlaySnd));
- DCmd_Register("playsbe", WRAP_METHOD(Debugger, cmdPlaySbe));
- DCmd_Register("playnis", WRAP_METHOD(Debugger, cmdPlayNis));
+ registerCmd("showframe", WRAP_METHOD(Debugger, cmdShowFrame));
+ registerCmd("showbg", WRAP_METHOD(Debugger, cmdShowBg));
+ registerCmd("playseq", WRAP_METHOD(Debugger, cmdPlaySeq));
+ registerCmd("playsnd", WRAP_METHOD(Debugger, cmdPlaySnd));
+ registerCmd("playsbe", WRAP_METHOD(Debugger, cmdPlaySbe));
+ registerCmd("playnis", WRAP_METHOD(Debugger, cmdPlayNis));
// Scene & interaction
- DCmd_Register("loadscene", WRAP_METHOD(Debugger, cmdLoadScene));
- DCmd_Register("fight", WRAP_METHOD(Debugger, cmdFight));
- DCmd_Register("beetle", WRAP_METHOD(Debugger, cmdBeetle));
+ registerCmd("loadscene", WRAP_METHOD(Debugger, cmdLoadScene));
+ registerCmd("fight", WRAP_METHOD(Debugger, cmdFight));
+ registerCmd("beetle", WRAP_METHOD(Debugger, cmdBeetle));
// Game
- DCmd_Register("delta", WRAP_METHOD(Debugger, cmdTimeDelta));
- DCmd_Register("time", WRAP_METHOD(Debugger, cmdTime));
- DCmd_Register("show", WRAP_METHOD(Debugger, cmdShow));
- DCmd_Register("entity", WRAP_METHOD(Debugger, cmdEntity));
+ registerCmd("delta", WRAP_METHOD(Debugger, cmdTimeDelta));
+ registerCmd("time", WRAP_METHOD(Debugger, cmdTime));
+ registerCmd("show", WRAP_METHOD(Debugger, cmdShow));
+ registerCmd("entity", WRAP_METHOD(Debugger, cmdEntity));
// Misc
- DCmd_Register("chapter", WRAP_METHOD(Debugger, cmdSwitchChapter));
- DCmd_Register("clear", WRAP_METHOD(Debugger, cmdClear));
+ registerCmd("chapter", WRAP_METHOD(Debugger, cmdSwitchChapter));
+ registerCmd("clear", WRAP_METHOD(Debugger, cmdClear));
resetCommand();
@@ -146,7 +146,7 @@ void Debugger::copyCommand(int argc, const char **argv) {
}
// Exit the debugger!
- Cmd_Exit(0, 0);
+ cmdExit(0, 0);
}
void Debugger::callCommand() {
@@ -156,7 +156,7 @@ void Debugger::callCommand() {
bool Debugger::loadArchive(int index) {
if (index < 1 || index > 3) {
- DebugPrintf("Invalid cd number (was: %d, valid: [1-3])\n", index);
+ debugPrintf("Invalid cd number (was: %d, valid: [1-3])\n", index);
return false;
}
@@ -198,36 +198,36 @@ void Debugger::restoreArchive() const {
// Debugger commands
//////////////////////////////////////////////////////////////////////////
bool Debugger::cmdHelp(int, const char **) {
- DebugPrintf("Debug flags\n");
- DebugPrintf("-----------\n");
- DebugPrintf(" debugflag_list - Lists the available debug flags and their status\n");
- DebugPrintf(" debugflag_enable - Enables a debug flag\n");
- DebugPrintf(" debugflag_disable - Disables a debug flag\n");
- DebugPrintf("\n");
- DebugPrintf("Commands\n");
- DebugPrintf("--------\n");
- DebugPrintf(" ls - list files in the archive\n");
- DebugPrintf(" dump - dump a list of files in all archives\n");
- DebugPrintf("\n");
- DebugPrintf(" showframe - show a frame from a sequence\n");
- DebugPrintf(" showbg - show a background\n");
- DebugPrintf(" playseq - play a sequence\n");
- DebugPrintf(" playsnd - play a sound\n");
- DebugPrintf(" playsbe - play a subtitle\n");
- DebugPrintf(" playnis - play an animation\n");
- DebugPrintf("\n");
- DebugPrintf(" loadscene - load a scene\n");
- DebugPrintf(" fight - start a fight\n");
- DebugPrintf(" beetle - start the beetle game\n");
- DebugPrintf("\n");
- DebugPrintf(" delta - Adjust the time delta\n");
- DebugPrintf(" show - show game data\n");
- DebugPrintf(" entity - show entity data\n");
- DebugPrintf("\n");
- DebugPrintf(" loadgame - load a saved game\n");
- DebugPrintf(" chapter - switch to a specific chapter\n");
- DebugPrintf(" clear - clear the screen\n");
- DebugPrintf("\n");
+ debugPrintf("Debug flags\n");
+ debugPrintf("-----------\n");
+ debugPrintf(" debugflag_list - Lists the available debug flags and their status\n");
+ debugPrintf(" debugflag_enable - Enables a debug flag\n");
+ debugPrintf(" debugflag_disable - Disables a debug flag\n");
+ debugPrintf("\n");
+ debugPrintf("Commands\n");
+ debugPrintf("--------\n");
+ debugPrintf(" ls - list files in the archive\n");
+ debugPrintf(" dump - dump a list of files in all archives\n");
+ debugPrintf("\n");
+ debugPrintf(" showframe - show a frame from a sequence\n");
+ debugPrintf(" showbg - show a background\n");
+ debugPrintf(" playseq - play a sequence\n");
+ debugPrintf(" playsnd - play a sound\n");
+ debugPrintf(" playsbe - play a subtitle\n");
+ debugPrintf(" playnis - play an animation\n");
+ debugPrintf("\n");
+ debugPrintf(" loadscene - load a scene\n");
+ debugPrintf(" fight - start a fight\n");
+ debugPrintf(" beetle - start the beetle game\n");
+ debugPrintf("\n");
+ debugPrintf(" delta - Adjust the time delta\n");
+ debugPrintf(" show - show game data\n");
+ debugPrintf(" entity - show entity data\n");
+ debugPrintf("\n");
+ debugPrintf(" loadgame - load a saved game\n");
+ debugPrintf(" chapter - switch to a specific chapter\n");
+ debugPrintf(" clear - clear the screen\n");
+ debugPrintf("\n");
return true;
}
@@ -252,15 +252,15 @@ bool Debugger::cmdListFiles(int argc, const char **argv) {
Common::ArchiveMemberList list;
int count = _engine->getResourceManager()->listMatchingMembers(list, filter);
- DebugPrintf("Number of matches: %d\n", count);
+ debugPrintf("Number of matches: %d\n", count);
for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it)
- DebugPrintf(" %s\n", (*it)->getName().c_str());
+ debugPrintf(" %s\n", (*it)->getName().c_str());
// Restore archive
if (argc == 3)
restoreArchive();
} else {
- DebugPrintf("Syntax: ls <filter> (use * for all) (<cd number>)\n");
+ debugPrintf("Syntax: ls <filter> (use * for all) (<cd number>)\n");
}
return true;
@@ -287,7 +287,7 @@ bool Debugger::cmdDumpFiles(int argc, const char **) {
for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { \
Common::SeekableReadStream *stream = getArchive((*it)->getName()); \
if (!stream) { \
- DebugPrintf("ERROR: Cannot create stream for file: %s\n", (*it)->getName().c_str()); \
+ debugPrintf("ERROR: Cannot create stream for file: %s\n", (*it)->getName().c_str()); \
restoreArchive(); \
return true; \
} \
@@ -311,7 +311,7 @@ bool Debugger::cmdDumpFiles(int argc, const char **) {
// Restore current loaded archive
restoreArchive();
} else {
- DebugPrintf("Syntax: dump");
+ debugPrintf("Syntax: dump");
}
return true;
@@ -336,7 +336,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) {
}
if (!_engine->getResourceManager()->hasFile(filename)) {
- DebugPrintf("Cannot find file: %s\n", filename.c_str());
+ debugPrintf("Cannot find file: %s\n", filename.c_str());
return true;
}
@@ -345,7 +345,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) {
_command = WRAP_METHOD(Debugger, cmdShowFrame);
copyCommand(argc, argv);
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
} else {
Sequence sequence(filename);
if (sequence.load(getArchive(filename))) {
@@ -354,7 +354,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) {
AnimFrame *frame = sequence.getFrame((uint16)getNumber(argv[2]));
if (!frame) {
- DebugPrintf("Invalid frame index '%s'\n", argv[2]);
+ debugPrintf("Invalid frame index '%s'\n", argv[2]);
resetCommand();
return true;
}
@@ -375,7 +375,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) {
restoreArchive();
}
} else {
- DebugPrintf("Syntax: cmd_showframe <seqname> <index> (<cd number>)\n");
+ debugPrintf("Syntax: cmd_showframe <seqname> <index> (<cd number>)\n");
}
return true;
}
@@ -398,7 +398,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) {
}
if (!_engine->getResourceManager()->hasFile(filename + ".BG")) {
- DebugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str());
+ debugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str());
return true;
}
@@ -407,7 +407,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) {
_command = WRAP_METHOD(Debugger, cmdShowBg);
copyCommand(argc, argv);
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
} else {
clearBg(GraphicsManager::kBackgroundC);
@@ -429,7 +429,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) {
resetCommand();
}
} else {
- DebugPrintf("Syntax: showbg <bgname> (<cd number>)\n");
+ debugPrintf("Syntax: showbg <bgname> (<cd number>)\n");
}
return true;
}
@@ -453,7 +453,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) {
}
if (!_engine->getResourceManager()->hasFile(filename)) {
- DebugPrintf("Cannot find file: %s\n", filename.c_str());
+ debugPrintf("Cannot find file: %s\n", filename.c_str());
return true;
}
@@ -462,7 +462,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) {
_command = WRAP_METHOD(Debugger, cmdPlaySeq);
copyCommand(argc, argv);
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
} else {
Sequence *sequence = new Sequence(filename);
if (sequence->load(getArchive(filename))) {
@@ -510,7 +510,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) {
restoreArchive();
}
} else {
- DebugPrintf("Syntax: playseq <seqname> (<cd number>)\n");
+ debugPrintf("Syntax: playseq <seqname> (<cd number>)\n");
}
return true;
}
@@ -537,7 +537,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) {
name += ".SND";
if (!_engine->getResourceManager()->hasFile(name)) {
- DebugPrintf("Cannot find file: %s\n", name.c_str());
+ debugPrintf("Cannot find file: %s\n", name.c_str());
return true;
}
@@ -548,7 +548,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) {
if (argc == 3)
restoreArchive();
} else {
- DebugPrintf("Syntax: playsnd <sndname> (<cd number>)\n");
+ debugPrintf("Syntax: playsnd <sndname> (<cd number>)\n");
}
return true;
}
@@ -573,7 +573,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) {
filename += ".sbe";
if (!_engine->getResourceManager()->hasFile(filename)) {
- DebugPrintf("Cannot find file: %s\n", filename.c_str());
+ debugPrintf("Cannot find file: %s\n", filename.c_str());
return true;
}
@@ -582,7 +582,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) {
_command = WRAP_METHOD(Debugger, cmdPlaySbe);
copyCommand(argc, argv);
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
} else {
SubtitleManager subtitle(_engine->getFont());
if (subtitle.load(getArchive(filename))) {
@@ -615,7 +615,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) {
resetCommand();
}
} else {
- DebugPrintf("Syntax: playsbe <sbename> (<cd number>)\n");
+ debugPrintf("Syntax: playsbe <sbename> (<cd number>)\n");
}
return true;
}
@@ -639,7 +639,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) {
// If we got a nis filename, check that the file exists
if (name.contains('.') && !_engine->getResourceManager()->hasFile(name)) {
- DebugPrintf("Cannot find file: %s\n", name.c_str());
+ debugPrintf("Cannot find file: %s\n", name.c_str());
return true;
}
@@ -648,12 +648,11 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) {
_command = WRAP_METHOD(Debugger, cmdPlayNis);
copyCommand(argc, argv);
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
} else {
// Make sure we are not called in a loop
_numParams = 0;
-
// Check if we got a nis filename or an animation index
if (name.contains('.')) {
Animation animation;
@@ -672,7 +671,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) {
resetCommand();
}
} else {
- DebugPrintf("Syntax: playnis <nisname.nis or animation index> (<cd number>)\n");
+ debugPrintf("Syntax: playnis <nisname.nis or animation index> (<cd number>)\n");
}
return true;
}
@@ -697,7 +696,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) {
}
if (index > 2500) {
- DebugPrintf("Error: invalid index value (0-2500)");
+ debugPrintf("Error: invalid index value (0-2500)");
return true;
}
@@ -706,7 +705,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) {
_command = WRAP_METHOD(Debugger, cmdLoadScene);
copyCommand(argc, argv);
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
} else {
clearBg(GraphicsManager::kBackgroundAll);
@@ -718,7 +717,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) {
// loadSceneObject(scene, i);
// if (scene.getHeader() && scene.getHeader()->car == 5 && scene.getHeader()->position == 81) {
- // DebugPrintf("Found scene: %d", i);
+ // debugPrintf("Found scene: %d", i);
// // Draw scene found
// _engine->getGraphicsManager()->draw(&scene, GraphicsManager::kBackgroundC);
@@ -738,7 +737,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) {
/*********************************************/
Scene *scene = getScenes()->get(index);
if (!scene) {
- DebugPrintf("Cannot load scene %i from CD %i", index, cd);
+ debugPrintf("Cannot load scene %i from CD %i", index, cd);
resetCommand();
return true;
@@ -758,7 +757,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) {
resetCommand();
}
} else {
- DebugPrintf("Syntax: loadscene <scene index> (<cd number>)\n");
+ debugPrintf("Syntax: loadscene <scene index> (<cd number>)\n");
}
return true;
}
@@ -796,7 +795,10 @@ bool Debugger::cmdFight(int argc, const char **argv) {
break;
}
- loadArchive(index);
+ if (!loadArchive(index)) {
+ debugPrintf("Error: failed to load archive %d\n", index);
+ return true;
+ }
// Store command
if (!hasCommand()) {
@@ -814,7 +816,7 @@ bool Debugger::cmdFight(int argc, const char **argv) {
SceneIndex lastScene = getState()->scene;
- getFight()->setup(type) ? DebugPrintf("Lost fight!\n") : DebugPrintf("Won fight!\n");
+ getFight()->setup(type) ? debugPrintf("Lost fight!\n") : debugPrintf("Won fight!\n");
// Pause for a second to be able to see the final scene
_engine->_system->delayMillis(1000);
@@ -837,7 +839,7 @@ bool Debugger::cmdFight(int argc, const char **argv) {
}
} else {
error:
- DebugPrintf("Syntax: fight <id> (id=2001-2005)\n");
+ debugPrintf("Syntax: fight <id> (id=2001-2005)\n");
}
return true;
@@ -854,7 +856,10 @@ error:
bool Debugger::cmdBeetle(int argc, const char **argv) {
if (argc == 1) {
// Load proper data file (beetle game in in Cd2)
- loadArchive(kArchiveCd2);
+ if (!loadArchive(kArchiveCd2)) {
+ debugPrintf("Error: failed to load archive 2");
+ return true;
+ }
// Store command
if (!hasCommand()) {
@@ -924,7 +929,6 @@ bool Debugger::cmdBeetle(int argc, const char **argv) {
break;
}
-
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
// Update coordinates
@@ -968,7 +972,7 @@ bool Debugger::cmdBeetle(int argc, const char **argv) {
resetCommand();
}
} else {
- DebugPrintf("Syntax: beetle\n");
+ debugPrintf("Syntax: beetle\n");
}
return true;
@@ -992,7 +996,7 @@ bool Debugger::cmdTimeDelta(int argc, const char **argv) {
getState()->timeDelta = (uint)delta;
} else {
label_error:
- DebugPrintf("Syntax: delta <time delta> (delta=1-500)\n");
+ debugPrintf("Syntax: delta <time delta> (delta=1-500)\n");
}
return true;
@@ -1018,10 +1022,10 @@ bool Debugger::cmdTime(int argc, const char **argv) {
uint8 minutes = 0;
State::getHourMinutes((uint32)time, &hours, &minutes);
- DebugPrintf("%02d:%02d\n", hours, minutes);
+ debugPrintf("%02d:%02d\n", hours, minutes);
} else {
label_error:
- DebugPrintf("Syntax: time <time to convert> (time=0-INT_MAX)\n");
+ debugPrintf("Syntax: time <time to convert> (time=0-INT_MAX)\n");
}
return true;
@@ -1037,10 +1041,10 @@ label_error:
*/
bool Debugger::cmdShow(int argc, const char **argv) {
#define OUTPUT_DUMP(name, text) \
- DebugPrintf(#name "\n"); \
- DebugPrintf("--------------------------------------------------------------------\n\n"); \
- DebugPrintf("%s", text); \
- DebugPrintf("\n");
+ debugPrintf(#name "\n"); \
+ debugPrintf("--------------------------------------------------------------------\n\n"); \
+ debugPrintf("%s", text); \
+ debugPrintf("\n");
if (argc == 2) {
@@ -1066,14 +1070,14 @@ bool Debugger::cmdShow(int argc, const char **argv) {
} else {
label_error:
- DebugPrintf("Syntax: state <option>\n");
- DebugPrintf(" state / st\n");
- DebugPrintf(" progress / pr\n");
- DebugPrintf(" flags / fl\n");
- DebugPrintf(" inventory / inv\n");
- DebugPrintf(" objects / obj\n");
- DebugPrintf(" savepoints / pt\n");
- DebugPrintf(" scene / sc\n");
+ debugPrintf("Syntax: state <option>\n");
+ debugPrintf(" state / st\n");
+ debugPrintf(" progress / pr\n");
+ debugPrintf(" flags / fl\n");
+ debugPrintf(" inventory / inv\n");
+ debugPrintf(" objects / obj\n");
+ debugPrintf(" savepoints / pt\n");
+ debugPrintf(" scene / sc\n");
}
return true;
@@ -1096,26 +1100,26 @@ bool Debugger::cmdEntity(int argc, const char **argv) {
if (index > 39)
goto label_error;
- DebugPrintf("Entity %s\n", ENTITY_NAME(index));
- DebugPrintf("--------------------------------------------------------------------\n\n");
- DebugPrintf("%s", getEntities()->getData(index)->toString().c_str());
+ debugPrintf("Entity %s\n", ENTITY_NAME(index));
+ debugPrintf("--------------------------------------------------------------------\n\n");
+ debugPrintf("%s", getEntities()->getData(index)->toString().c_str());
// The Player entity does not have any callback data
if (index != kEntityPlayer) {
EntityData *data = getEntities()->get(index)->getParamData();
for (uint callback = 0; callback < 9; callback++) {
- DebugPrintf("Call parameters %d:\n", callback);
+ debugPrintf("Call parameters %d:\n", callback);
for (byte ix = 0; ix < 4; ix++)
- DebugPrintf(" %s", data->getParameters(callback, ix)->toString().c_str());
+ debugPrintf(" %s", data->getParameters(callback, ix)->toString().c_str());
}
}
- DebugPrintf("\n");
+ debugPrintf("\n");
} else {
label_error:
- DebugPrintf("Syntax: entity <index>\n");
+ debugPrintf("Syntax: entity <index>\n");
for (int i = 0; i < 40; i += 4)
- DebugPrintf(" %s - %d %s - %d %s - %d %s - %d\n", ENTITY_NAME(i), i, ENTITY_NAME(i+1), i+1, ENTITY_NAME(i+2), i+2, ENTITY_NAME(i+3), i+3);
+ debugPrintf(" %s - %d %s - %d %s - %d %s - %d\n", ENTITY_NAME(i), i, ENTITY_NAME(i+1), i+1, ENTITY_NAME(i+2), i+2, ENTITY_NAME(i+3), i+3);
}
return true;
@@ -1152,7 +1156,7 @@ bool Debugger::cmdSwitchChapter(int argc, const char **argv) {
}
} else {
error:
- DebugPrintf("Syntax: chapter <id> (id=2-6)\n");
+ debugPrintf("Syntax: chapter <id> (id=2-6)\n");
}
return true;
@@ -1172,7 +1176,7 @@ bool Debugger::cmdClear(int argc, const char **) {
askForRedraw();
redrawScreen();
} else {
- DebugPrintf("Syntax: clear - clear the screen\n");
+ debugPrintf("Syntax: clear - clear the screen\n");
}
return true;
diff --git a/engines/lastexpress/entities/abbot.cpp b/engines/lastexpress/entities/abbot.cpp
index 5393410add..1581916e07 100644
--- a/engines/lastexpress/entities/abbot.cpp
+++ b/engines/lastexpress/entities/abbot.cpp
@@ -415,7 +415,7 @@ IMPLEMENT_FUNCTION(22, Abbot, haveLunch)
break;
case kActionNone:
- Entity::timeCheckSavepoint(kTime1971000, params->param1, kEntityAbbot, kEntityServers0, kAction218586752);
+ Entity::timeCheckSavepoint(kTime1971000, params->param1, kEntityAbbot, kEntityWaiter1, kAction218586752);
if (getState()->time > kTime1989000 && getEntities()->isSomebodyInsideRestaurantOrSalon()) {
getData()->inventoryItem = kItemNone;
@@ -476,7 +476,7 @@ IMPLEMENT_FUNCTION(23, Abbot, leaveLunch)
case 1:
getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 67);
- getSavePoints()->push(kEntityAbbot, kEntityServers0, kAction270068760);
+ getSavePoints()->push(kEntityAbbot, kEntityWaiter1, kAction270068760);
getSavePoints()->push(kEntityAbbot, kEntityAnna, kAction238936000);
getEntities()->drawSequenceRight(kEntityAbbot, "804DS");
@@ -1324,7 +1324,7 @@ IMPLEMENT_FUNCTION(41, Abbot, chapter4Handler)
break;
case kActionNone:
- Entity::timeCheckSavepoint(kTime2358000, params->param1, kEntityAbbot, kEntityServers0, kAction218128129);
+ Entity::timeCheckSavepoint(kTime2358000, params->param1, kEntityAbbot, kEntityWaiter1, kAction218128129);
if (getState()->time > kTime2389500 && getEntities()->isSomebodyInsideRestaurantOrSalon())
setup_leaveDinner();
@@ -1368,7 +1368,7 @@ IMPLEMENT_FUNCTION(42, Abbot, leaveDinner)
case 1:
getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 67);
- getSavePoints()->push(kEntityAbbot, kEntityServers0, kAction270068760);
+ getSavePoints()->push(kEntityAbbot, kEntityWaiter1, kAction270068760);
getEntities()->drawSequenceRight(kEntityAbbot, "804DS");
if (getEntities()->isInRestaurant(kEntityPlayer))
@@ -1779,7 +1779,7 @@ IMPLEMENT_FUNCTION(49, Abbot, catchCath)
getData()->location = kLocationInsideCompartment;
getSavePoints()->call(kEntityAbbot, kEntityTables4, kActionDrawTablesWithChairs, "029G");
- getSavePoints()->push(kEntityAbbot, kEntityServers0, kAction270068760);
+ getSavePoints()->push(kEntityAbbot, kEntityWaiter1, kAction270068760);
getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction125039808);
getObjects()->update(kObjectCompartment2, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand);
getObjects()->update(kObjectHandleInsideBathroom, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand);
diff --git a/engines/lastexpress/entities/alexei.cpp b/engines/lastexpress/entities/alexei.cpp
index 9b56fca39f..5ea3ff4898 100644
--- a/engines/lastexpress/entities/alexei.cpp
+++ b/engines/lastexpress/entities/alexei.cpp
@@ -607,7 +607,7 @@ IMPLEMENT_FUNCTION(19, Alexei, returnCompartment)
case 7:
getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 63);
- getSavePoints()->push(kEntityAlexei, kEntityServers1, kAction302996448);
+ getSavePoints()->push(kEntityAlexei, kEntityWaiter2, kAction302996448);
setCallback(8);
setup_draw("934");
diff --git a/engines/lastexpress/entities/anna.cpp b/engines/lastexpress/entities/anna.cpp
index ff65be9772..3354964af2 100644
--- a/engines/lastexpress/entities/anna.cpp
+++ b/engines/lastexpress/entities/anna.cpp
@@ -907,7 +907,7 @@ IMPLEMENT_FUNCTION(23, Anna, waitingDinner)
case kActionDefault:
getEntities()->drawSequenceLeft(kEntityAnna, "001D");
- getSavePoints()->push(kEntityAnna, kEntityServers0, kAction270410280);
+ getSavePoints()->push(kEntityAnna, kEntityWaiter1, kAction270410280);
getSavePoints()->push(kEntityAnna, kEntityTables0, kAction136455232);
setCallback(1);
@@ -931,7 +931,7 @@ IMPLEMENT_FUNCTION(23, Anna, waitingDinner)
break;
case 3:
- getSavePoints()->push(kEntityAnna, kEntityServers0, kAction203859488);
+ getSavePoints()->push(kEntityAnna, kEntityWaiter1, kAction203859488);
setup_waitingDinner2();
break;
}
@@ -964,7 +964,7 @@ IMPLEMENT_FUNCTION(24, Anna, waitingDinner2)
break;
case 2:
- getSavePoints()->push(kEntityAnna, kEntityServers0, kAction136702400);
+ getSavePoints()->push(kEntityAnna, kEntityWaiter1, kAction136702400);
setup_eatingDinner();
break;
}
@@ -1034,7 +1034,7 @@ IMPLEMENT_FUNCTION(26, Anna, leaveDinner)
case 1:
getEntities()->updatePositionExit(kEntityAnna, kCarRestaurant, 62);
- getSavePoints()->push(kEntityAnna, kEntityServers0, kAction237485916);
+ getSavePoints()->push(kEntityAnna, kEntityWaiter1, kAction237485916);
getEntities()->drawSequenceRight(kEntityAnna, "801DS");
if (getEntities()->isInRestaurant(kEntityPlayer))
@@ -2145,7 +2145,7 @@ label_callback_4:
break;
case 2:
- getSavePoints()->push(kEntityAnna, kEntityServers0, kAction218983616);
+ getSavePoints()->push(kEntityAnna, kEntityWaiter1, kAction218983616);
break;
case 3:
@@ -2285,7 +2285,7 @@ IMPLEMENT_FUNCTION(51, Anna, afterLunch)
getData()->location = kLocationInsideCompartment;
getEntities()->drawSequenceLeft(kEntityAnna, "112B");
getEntities()->updatePositionExit(kEntityAnna, kCarRestaurant, 57);
- getSavePoints()->push(kEntityAnna, kEntityServers1, kAction219377792);
+ getSavePoints()->push(kEntityAnna, kEntityWaiter2, kAction219377792);
break;
case 2:
@@ -3473,7 +3473,7 @@ IMPLEMENT_FUNCTION(69, Anna, goSalon4)
case 3:
getData()->location = kLocationInsideCompartment;
getEntities()->drawSequenceLeft(kEntityAnna, "127B");
- getSavePoints()->push(kEntityAnna, kEntityServers1, kAction258136010);
+ getSavePoints()->push(kEntityAnna, kEntityWaiter2, kAction258136010);
break;
case 4:
diff --git a/engines/lastexpress/entities/august.cpp b/engines/lastexpress/entities/august.cpp
index c5029537ad..14dcf200f0 100644
--- a/engines/lastexpress/entities/august.cpp
+++ b/engines/lastexpress/entities/august.cpp
@@ -452,11 +452,17 @@ IMPLEMENT_FUNCTION_I(20, August, function20, bool)
}
if (params->param1) {
- strcpy((char *)&parameters->seq2, Common::String::format("%s%s", (char *)&parameters->seq1, "Gc").c_str());
+ Common::String sequence = Common::String::format("%s%s", (char *)&parameters->seq1, "Gc");
+ assert(sequence.size() <= 13);
+
+ strcpy((char *)&parameters->seq2, sequence.c_str());
getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue);
} else {
- strcpy((char *)&parameters->seq2, Common::String::format("%s%s", (char *)&parameters->seq1, "Ec").c_str());
+ Common::String sequence = Common::String::format("%s%s", (char *)&parameters->seq1, "Ec");
+ assert(sequence.size() <= 13);
+
+ strcpy((char *)&parameters->seq2, sequence.c_str());
}
setCallback(1);
@@ -484,15 +490,22 @@ IMPLEMENT_FUNCTION_I(20, August, function20, bool)
setCallback(2);
setup_playSound("AUG2094");
}
+
}
break;
case 2:
- case 3:
+ case 3: {
getSavePoints()->push(kEntityAugust, kEntityMertens, kAction269436673);
- strcpy((char *)&parameters->seq2, Common::String::format("%s%s", (char *)&parameters->seq1, "Qc").c_str());
+
+ Common::String sequence = Common::String::format("%s%s", (char *)&parameters->seq1, "Qc");
+ assert(sequence.size() <= 13);
+
+ strcpy((char *)&parameters->seq2, sequence.c_str());
getEntities()->drawSequenceLeft(kEntityAugust, (char *)&parameters->seq2);
+
+ }
break;
}
break;
@@ -1162,7 +1175,7 @@ IMPLEMENT_FUNCTION(25, August, chapter1Handler)
break;
case 1:
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction204704037);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction204704037);
getEntities()->drawSequenceRight(kEntityAugust, "803DS");
if (getEntities()->isInRestaurant(kEntityPlayer))
getEntities()->updateFrame(kEntityAugust);
@@ -1195,7 +1208,7 @@ IMPLEMENT_FUNCTION(25, August, chapter1Handler)
break;
case 5:
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction204704037);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction204704037);
getEntities()->drawSequenceRight(kEntityAugust, "803DS");
if (getEntities()->isInRestaurant(kEntityPlayer))
getEntities()->updateFrame(kEntityAugust);
@@ -1366,7 +1379,7 @@ IMPLEMENT_FUNCTION(28, August, function28)
params->param1 = kItemInvalid;
getEntities()->drawSequenceLeft(kEntityAugust, "010B");
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction304061224);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction304061224);
getData()->inventoryItem = (InventoryItem)params->param1;
break;
@@ -1376,13 +1389,13 @@ IMPLEMENT_FUNCTION(28, August, function28)
break;
case 1:
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction203859488);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction203859488);
getData()->inventoryItem = (InventoryItem)params->param1;
getEntities()->drawSequenceLeft(kEntityAugust, "010B");
break;
case 2:
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction136702400);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction136702400);
getEntities()->drawSequenceLeft(kEntityAugust, "010B");
setup_function29();
break;
@@ -1399,7 +1412,7 @@ IMPLEMENT_FUNCTION(28, August, function28)
case kAction170016384:
getData()->inventoryItem = kItemNone;
- getEntities()->drawSequenceLeft(kEntityServers0, "BLANK");
+ getEntities()->drawSequenceLeft(kEntityWaiter1, "BLANK");
getEntities()->drawSequenceLeft(kEntityAugust, "010G");
setCallback(2);
@@ -1551,7 +1564,7 @@ IMPLEMENT_FUNCTION(30, August, restaurant)
break;
case 3:
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction292758554);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction292758554);
getSavePoints()->push(kEntityAugust, kEntityAnna, kAction122358304);
getEntities()->drawSequenceLeft(kEntityAugust, "001K");
getSound()->playSound(kEntityAugust, "AUG1003");
@@ -1815,7 +1828,7 @@ IMPLEMENT_FUNCTION(36, August, chapter2Handler)
break;
case kActionNone:
- Entity::timeCheckSavepoint(kTime1755000, params->param2, kEntityAugust, kEntityServers0, kAction252568704);
+ Entity::timeCheckSavepoint(kTime1755000, params->param2, kEntityAugust, kEntityWaiter1, kAction252568704);
if (getState()->time > kTime1773000 && params->param1 && getEntities()->isSomebodyInsideRestaurantOrSalon()) {
getData()->inventoryItem = kItemNone;
@@ -1863,7 +1876,7 @@ IMPLEMENT_FUNCTION(36, August, chapter2Handler)
break;
case 3:
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction286534136);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction286534136);
setCallback(4);
setup_updateEntity(kCarGreenSleeping, kPosition_6470);
@@ -1882,7 +1895,7 @@ IMPLEMENT_FUNCTION(36, August, chapter2Handler)
if (!getEvent(kEventAugustGoodMorning))
getData()->inventoryItem = kItemInvalid;
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction219522616);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction219522616);
getEntities()->drawSequenceLeft(kEntityAugust, "016B");
params->param1 = 1;
break;
@@ -3044,7 +3057,7 @@ IMPLEMENT_FUNCTION(60, August, function60)
}
if (pushSavepoint)
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction207330561);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction207330561);
if (!params->param1)
break;
@@ -3074,7 +3087,7 @@ IMPLEMENT_FUNCTION(60, August, function60)
break;
case 2:
- getSavePoints()->push(kEntityAugust, kEntityServers0, kAction286403504);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter1, kAction286403504);
setup_function61();
break;
}
@@ -3199,7 +3212,7 @@ IMPLEMENT_FUNCTION(62, August, function62)
case 5:
getEntities()->drawSequenceLeft(kEntityAugust, "122B");
- getSavePoints()->push(kEntityAugust, kEntityServers1, kAction291721418);
+ getSavePoints()->push(kEntityAugust, kEntityWaiter2, kAction291721418);
break;
}
break;
diff --git a/engines/lastexpress/entities/boutarel.cpp b/engines/lastexpress/entities/boutarel.cpp
index 979381afb0..32507b0d63 100644
--- a/engines/lastexpress/entities/boutarel.cpp
+++ b/engines/lastexpress/entities/boutarel.cpp
@@ -310,7 +310,7 @@ IMPLEMENT_FUNCTION_I(14, Boutarel, function14, bool)
break;
case 2:
- getSavePoints()->push(kEntityBoutarel, kEntityServers1, kAction326144276);
+ getSavePoints()->push(kEntityBoutarel, kEntityWaiter2, kAction326144276);
getEntities()->drawSequenceRight(kEntityBoutarel, "812DS");
if (getEntities()->isInRestaurant(kEntityPlayer))
getEntities()->updateFrame(kEntityBoutarel);
@@ -674,7 +674,7 @@ IMPLEMENT_FUNCTION(20, Boutarel, function20)
break;
case 2:
- getSavePoints()->push(kEntityBoutarel, kEntityServers1, kAction256200848);
+ getSavePoints()->push(kEntityBoutarel, kEntityWaiter2, kAction256200848);
break;
case 3:
@@ -937,7 +937,7 @@ IMPLEMENT_FUNCTION(29, Boutarel, function29)
case kActionNone:
if (Entity::updateParameter(params->param2, getState()->time, 450)) {
- getSavePoints()->push(kEntityBoutarel, kEntityServers1, kAction256200848);
+ getSavePoints()->push(kEntityBoutarel, kEntityWaiter2, kAction256200848);
}
if (!params->param1)
@@ -1086,7 +1086,7 @@ IMPLEMENT_FUNCTION(33, Boutarel, function33)
break;
case 2:
- getSavePoints()->push(kEntityBoutarel, kEntityServers1, kAction256200848);
+ getSavePoints()->push(kEntityBoutarel, kEntityWaiter2, kAction256200848);
break;
case 3:
diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp
index fe977a577f..f1a7d02384 100644
--- a/engines/lastexpress/entities/chapters.cpp
+++ b/engines/lastexpress/entities/chapters.cpp
@@ -44,13 +44,13 @@
#include "lastexpress/entities/pascale.h"
#include "lastexpress/entities/rebecca.h"
#include "lastexpress/entities/salko.h"
-#include "lastexpress/entities/servers0.h"
-#include "lastexpress/entities/servers1.h"
#include "lastexpress/entities/sophie.h"
#include "lastexpress/entities/tatiana.h"
#include "lastexpress/entities/vassili.h"
#include "lastexpress/entities/verges.h"
#include "lastexpress/entities/vesna.h"
+#include "lastexpress/entities/waiter1.h"
+#include "lastexpress/entities/waiter2.h"
#include "lastexpress/entities/yasmin.h"
#include "lastexpress/game/action.h"
@@ -77,7 +77,7 @@ Chapters::Chapters(LastExpressEngine *engine) : Entity(engine, kEntityChapters)
ADD_CALLBACK_FUNCTION(Chapters, exitStation);
ADD_CALLBACK_FUNCTION(Chapters, chapter1);
ADD_CALLBACK_FUNCTION(Chapters, resetMainEntities);
- ADD_CALLBACK_FUNCTION(Chapters, chapter1End);
+ ADD_CALLBACK_FUNCTION(Chapters, firstDream);
ADD_CALLBACK_FUNCTION(Chapters, chapter1Init);
ADD_CALLBACK_FUNCTION(Chapters, chapter1Handler);
ADD_CALLBACK_FUNCTION(Chapters, chapter1Next);
@@ -154,7 +154,8 @@ IMPLEMENT_FUNCTION(5, Chapters, resetMainEntities)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(6, Chapters, chapter1End)
+IMPLEMENT_FUNCTION(6, Chapters, firstDream)
+ // Chapter 1 end
switch (savepoint.action) {
default:
break;
@@ -207,9 +208,9 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End)
case kActionDefault:
RESET_ENTITY_STATE(kEntityPascale, Pascale, setup_function19);
- RESET_ENTITY_STATE(kEntityServers0, Servers0, setup_function22);
- RESET_ENTITY_STATE(kEntityServers1, Servers1, setup_function16);
- RESET_ENTITY_STATE(kEntityCooks, Cooks, setup_function7);
+ RESET_ENTITY_STATE(kEntityWaiter1, Waiter1, setup_function22);
+ RESET_ENTITY_STATE(kEntityWaiter2, Waiter2, setup_function16);
+ RESET_ENTITY_STATE(kEntityCooks, Cooks, setup_lockUp);
RESET_ENTITY_STATE(kEntityMertens, Mertens, setup_function42);
RESET_ENTITY_STATE(kEntityCoudert, Coudert, setup_chapter1Handler);
@@ -220,7 +221,7 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End)
getSavePoints()->push(kEntityChapters, kEntityVerges, kAction201431954);
RESET_ENTITY_STATE(kEntityKronos, Kronos, setup_function10);
- RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_function13);
+ RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_cathDone);
RESET_ENTITY_STATE(kEntityAnna, Anna, setup_asleep);
RESET_ENTITY_STATE(kEntityAugust, August, setup_function34);
RESET_ENTITY_STATE(kEntityTatiana, Tatiana, setup_function24);
@@ -270,7 +271,6 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End)
if (getSoundQueue()->isBuffered("ZFX1007B"))
getSoundQueue()->processEntry("ZFX1007B");
-
getSound()->playSound(kEntityPlayer, "MUS008", kFlagDefault);
getInventory()->unselectItem();
@@ -385,6 +385,7 @@ IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(8, Chapters, chapter1Handler)
+ // Moving at night
switch (savepoint.action) {
default:
break;
@@ -705,7 +706,7 @@ label_chapter1_next:
setup_chapter1Next();
} else {
setCallback(23);
- setup_chapter1End();
+ setup_firstDream();
}
break;
}
@@ -918,6 +919,7 @@ IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(15, Chapters, chapter3Handler)
+ // Moving during the afternoon
switch (savepoint.action) {
default:
break;
@@ -1078,6 +1080,7 @@ IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(16, Chapters, viennaEvents)
+ // End in Vienna
switch (savepoint.action) {
default:
break;
@@ -1225,6 +1228,7 @@ IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(19, Chapters, chapter4Handler)
+ // Moving during the second night
switch (savepoint.action) {
default:
break;
@@ -1518,8 +1522,8 @@ label_callback_4:
RESET_ENTITY_STATE(kEntityAugust, August, setup_function65);
RESET_ENTITY_STATE(kEntityMertens, Mertens, setup_function48);
RESET_ENTITY_STATE(kEntityCoudert, Coudert, setup_function53);
- RESET_ENTITY_STATE(kEntityServers0, Servers0, setup_chapter4Handler);
- RESET_ENTITY_STATE(kEntityServers1, Servers1, setup_chapter4Handler);
+ RESET_ENTITY_STATE(kEntityWaiter1, Waiter1, setup_serving4);
+ RESET_ENTITY_STATE(kEntityWaiter2, Waiter2, setup_serving4);
RESET_ENTITY_STATE(kEntityPascale, Pascale, setup_chapter4Handler);
RESET_ENTITY_STATE(kEntityVerges, Verges, setup_chapter4Handler);
RESET_ENTITY_STATE(kEntityTatiana, Tatiana, setup_function49);
@@ -1535,12 +1539,12 @@ label_callback_4:
RESET_ENTITY_STATE(kEntityYasmin, Yasmin, setup_function17);
RESET_ENTITY_STATE(kEntityHadija, Hadija, setup_function19);
RESET_ENTITY_STATE(kEntityAlouan, Alouan, setup_function19);
- RESET_ENTITY_STATE(kEntityMax, Max, setup_chapter4Handler);
+ RESET_ENTITY_STATE(kEntityMax, Max, setup_inCageFriendly);
getSavePoints()->push(kEntityChapters, kEntityAnna, kAction201431954);
getSavePoints()->push(kEntityChapters, kEntityMertens, kAction201431954);
getSavePoints()->push(kEntityChapters, kEntityCoudert, kAction201431954);
- getSavePoints()->push(kEntityChapters, kEntityServers0, kAction201431954);
- getSavePoints()->push(kEntityChapters, kEntityServers1, kAction201431954);
+ getSavePoints()->push(kEntityChapters, kEntityWaiter1, kAction201431954);
+ getSavePoints()->push(kEntityChapters, kEntityWaiter2, kAction201431954);
getSavePoints()->push(kEntityChapters, kEntityPascale, kAction201431954);
getSavePoints()->push(kEntityChapters, kEntityVerges, kAction201431954);
@@ -1754,7 +1758,6 @@ IMPLEMENT_FUNCTION(22, Chapters, chapter5Handler)
}
IMPLEMENT_FUNCTION_END
-
//////////////////////////////////////////////////////////////////////////
// Private functions
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/entities/chapters.h b/engines/lastexpress/entities/chapters.h
index 39739aa92e..abc464845f 100644
--- a/engines/lastexpress/entities/chapters.h
+++ b/engines/lastexpress/entities/chapters.h
@@ -70,7 +70,7 @@ public:
/**
* Handle end of Chapter 1 events
*/
- DECLARE_FUNCTION(chapter1End)
+ DECLARE_FUNCTION(firstDream)
/**
* Init Chapter 1 data
diff --git a/engines/lastexpress/entities/cooks.cpp b/engines/lastexpress/entities/cooks.cpp
index e24180e58d..749e93999b 100644
--- a/engines/lastexpress/entities/cooks.cpp
+++ b/engines/lastexpress/entities/cooks.cpp
@@ -37,17 +37,17 @@ namespace LastExpress {
Cooks::Cooks(LastExpressEngine *engine) : Entity(engine, kEntityCooks) {
ADD_CALLBACK_FUNCTION(Cooks, draw);
ADD_CALLBACK_FUNCTION(Cooks, playSound);
- ADD_CALLBACK_FUNCTION(Cooks, function3);
- ADD_CALLBACK_FUNCTION(Cooks, function4);
+ ADD_CALLBACK_FUNCTION(Cooks, uptrainVersion);
+ ADD_CALLBACK_FUNCTION(Cooks, downtrainVersion);
ADD_CALLBACK_FUNCTION(Cooks, chapter1);
- ADD_CALLBACK_FUNCTION(Cooks, chapter1Handler);
- ADD_CALLBACK_FUNCTION(Cooks, function7);
+ ADD_CALLBACK_FUNCTION(Cooks, inKitchenDinner);
+ ADD_CALLBACK_FUNCTION(Cooks, lockUp);
ADD_CALLBACK_FUNCTION(Cooks, chapter2);
- ADD_CALLBACK_FUNCTION(Cooks, chapter2Handler);
+ ADD_CALLBACK_FUNCTION(Cooks, inKitchenBreakfast);
ADD_CALLBACK_FUNCTION(Cooks, chapter3);
- ADD_CALLBACK_FUNCTION(Cooks, chapter3Handler);
+ ADD_CALLBACK_FUNCTION(Cooks, inKitchenLunch);
ADD_CALLBACK_FUNCTION(Cooks, chapter4);
- ADD_CALLBACK_FUNCTION(Cooks, chapter4Handler);
+ ADD_CALLBACK_FUNCTION(Cooks, inKitchenDinner2);
ADD_CALLBACK_FUNCTION(Cooks, chapter5);
}
@@ -62,7 +62,7 @@ IMPLEMENT_FUNCTION_S(2, Cooks, playSound)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(3, Cooks, function3)
+IMPLEMENT_FUNCTION(3, Cooks, uptrainVersion)
switch (savepoint.action) {
default:
break;
@@ -147,7 +147,7 @@ IMPLEMENT_FUNCTION(3, Cooks, function3)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(4, Cooks, function4)
+IMPLEMENT_FUNCTION(4, Cooks, downtrainVersion)
switch (savepoint.action) {
default:
break;
@@ -239,7 +239,7 @@ IMPLEMENT_FUNCTION(5, Cooks, chapter1)
break;
case kActionNone:
- Entity::timeCheck(kTimeChapter1, params->param1, WRAP_SETUP_FUNCTION(Cooks, setup_chapter1Handler));
+ Entity::timeCheck(kTimeChapter1, params->param1, WRAP_SETUP_FUNCTION(Cooks, setup_inKitchenDinner));
break;
case kActionDefault:
@@ -254,7 +254,7 @@ IMPLEMENT_FUNCTION(5, Cooks, chapter1)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(6, Cooks, chapter1Handler)
+IMPLEMENT_FUNCTION(6, Cooks, inKitchenDinner)
switch (savepoint.action) {
default:
break;
@@ -281,7 +281,7 @@ IMPLEMENT_FUNCTION(6, Cooks, chapter1Handler)
if (params->param1) {
if (getEntities()->isPlayerPosition(kCarRestaurant, 73)) {
setCallback(1);
- setup_function3();
+ setup_uptrainVersion();
}
} else {
if (params->param3) {
@@ -311,7 +311,7 @@ IMPLEMENT_FUNCTION(6, Cooks, chapter1Handler)
break;
case kAction101632192:
- setup_function7();
+ setup_lockUp();
break;
case kAction224849280:
@@ -322,7 +322,7 @@ IMPLEMENT_FUNCTION(6, Cooks, chapter1Handler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(7, Cooks, function7)
+IMPLEMENT_FUNCTION(7, Cooks, lockUp)
switch (savepoint.action) {
default:
break;
@@ -350,7 +350,7 @@ IMPLEMENT_FUNCTION(8, Cooks, chapter2)
break;
case kActionNone:
- setup_chapter2Handler();
+ setup_inKitchenBreakfast();
break;
case kActionDefault:
@@ -368,7 +368,7 @@ IMPLEMENT_FUNCTION(8, Cooks, chapter2)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(9, Cooks, chapter2Handler)
+IMPLEMENT_FUNCTION(9, Cooks, inKitchenBreakfast)
switch (savepoint.action) {
default:
break;
@@ -411,7 +411,7 @@ IMPLEMENT_FUNCTION(10, Cooks, chapter3)
break;
case kActionNone:
- setup_chapter3Handler();
+ setup_inKitchenLunch();
break;
case kActionDefault:
@@ -428,7 +428,7 @@ IMPLEMENT_FUNCTION(10, Cooks, chapter3)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(11, Cooks, chapter3Handler)
+IMPLEMENT_FUNCTION(11, Cooks, inKitchenLunch)
switch (savepoint.action) {
default:
break;
@@ -459,7 +459,7 @@ IMPLEMENT_FUNCTION(11, Cooks, chapter3Handler)
if (params->param1) {
if (getEntities()->isPlayerPosition(kCarRestaurant, 80)) {
setCallback(1);
- setup_function4();
+ setup_downtrainVersion();
}
} else {
if (params->param3) {
@@ -502,7 +502,7 @@ IMPLEMENT_FUNCTION(12, Cooks, chapter4)
break;
case kActionNone:
- setup_chapter4Handler();
+ setup_inKitchenDinner2();
break;
case kActionDefault:
@@ -520,7 +520,7 @@ IMPLEMENT_FUNCTION(12, Cooks, chapter4)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(13, Cooks, chapter4Handler)
+IMPLEMENT_FUNCTION(13, Cooks, inKitchenDinner2)
switch (savepoint.action) {
default:
break;
@@ -553,7 +553,6 @@ IMPLEMENT_FUNCTION(13, Cooks, chapter4Handler)
}
break;
-
case kActionCallback:
// Play the next part of background sound
if (getCallback() == 1 || getCallback() == 2) {
diff --git a/engines/lastexpress/entities/cooks.h b/engines/lastexpress/entities/cooks.h
index 79addb0a02..6a65a25801 100644
--- a/engines/lastexpress/entities/cooks.h
+++ b/engines/lastexpress/entities/cooks.h
@@ -48,9 +48,9 @@ public:
*/
DECLARE_FUNCTION_1(playSound, const char *filename)
- DECLARE_FUNCTION(function3)
+ DECLARE_FUNCTION(uptrainVersion)
- DECLARE_FUNCTION(function4)
+ DECLARE_FUNCTION(downtrainVersion)
/**
* Setup Chapter 1
@@ -58,21 +58,21 @@ public:
DECLARE_FUNCTION(chapter1)
/**
- * Handle Chapter 1 events
+ * Chapter 1: Prepare dinner in kitchen
*/
- DECLARE_FUNCTION(chapter1Handler)
+ DECLARE_FUNCTION(inKitchenDinner)
- DECLARE_FUNCTION(function7)
+ DECLARE_FUNCTION(lockUp)
/**
* Setup Chapter 2
*/
DECLARE_FUNCTION(chapter2)
- /**
- * Handle Chapter 2 events
+ /*
+ * Chapter 2: Prepare breakfast in kitchen
*/
- DECLARE_FUNCTION(chapter2Handler)
+ DECLARE_FUNCTION(inKitchenBreakfast)
/**
* Setup Chapter 3
@@ -80,9 +80,9 @@ public:
DECLARE_FUNCTION(chapter3)
/**
- * Handle Chapter 3 events
+ * Chapter 3: Prepare lunch in kitchen
*/
- DECLARE_FUNCTION(chapter3Handler)
+ DECLARE_FUNCTION(inKitchenLunch)
/**
* Setup Chapter 4
@@ -90,9 +90,9 @@ public:
DECLARE_FUNCTION(chapter4)
/**
- * Handle Chapter 4 events
+ * Chapter 4: Prepare second dinner in kitchen
*/
- DECLARE_FUNCTION(chapter4Handler)
+ DECLARE_FUNCTION(inKitchenDinner2)
/**
* Setup Chapter 5
diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp
index 07e82d296e..170248de52 100644
--- a/engines/lastexpress/entities/entity.cpp
+++ b/engines/lastexpress/entities/entity.cpp
@@ -51,6 +51,9 @@ EntityData::EntityCallData::~EntityCallData() {
}
void EntityData::EntityCallData::syncString(Common::Serializer &s, Common::String &string, uint length) const {
+ assert(length <= 13);
+ assert(string.size() <= 13);
+
char seqName[13];
memset(&seqName, 0, length);
@@ -972,5 +975,4 @@ bool Entity::timeCheckPlaySoundUpdatePosition(TimeValue timeValue, uint &paramet
return false;
}
-
} // End of namespace LastExpress
diff --git a/engines/lastexpress/entities/gendarmes.cpp b/engines/lastexpress/entities/gendarmes.cpp
index 7b31c592cd..b628b8dfe7 100644
--- a/engines/lastexpress/entities/gendarmes.cpp
+++ b/engines/lastexpress/entities/gendarmes.cpp
@@ -37,16 +37,16 @@ namespace LastExpress {
Gendarmes::Gendarmes(LastExpressEngine *engine) : Entity(engine, kEntityGendarmes) {
ADD_CALLBACK_FUNCTION(Gendarmes, reset);
ADD_CALLBACK_FUNCTION(Gendarmes, chapter1);
- ADD_CALLBACK_FUNCTION(Gendarmes, arrestDraw);
- ADD_CALLBACK_FUNCTION(Gendarmes, arrestPlaysound);
- ADD_CALLBACK_FUNCTION(Gendarmes, arrestPlaysound16);
- ADD_CALLBACK_FUNCTION(Gendarmes, arrestCallback);
+ ADD_CALLBACK_FUNCTION(Gendarmes, doDraw);
+ ADD_CALLBACK_FUNCTION(Gendarmes, doDialog);
+ ADD_CALLBACK_FUNCTION(Gendarmes, doDialogFullVolume);
+ ADD_CALLBACK_FUNCTION(Gendarmes, doWait);
ADD_CALLBACK_FUNCTION(Gendarmes, savegame);
- ADD_CALLBACK_FUNCTION(Gendarmes, arrestUpdateEntity);
- ADD_CALLBACK_FUNCTION(Gendarmes, function9);
- ADD_CALLBACK_FUNCTION(Gendarmes, function10);
+ ADD_CALLBACK_FUNCTION(Gendarmes, doWalk);
+ ADD_CALLBACK_FUNCTION(Gendarmes, doCompartment);
+ ADD_CALLBACK_FUNCTION(Gendarmes, trappedCath);
ADD_CALLBACK_FUNCTION(Gendarmes, chapter1Handler);
- ADD_CALLBACK_FUNCTION(Gendarmes, function12);
+ ADD_CALLBACK_FUNCTION(Gendarmes, searchTrain);
ADD_CALLBACK_FUNCTION(Gendarmes, function13);
ADD_CALLBACK_FUNCTION(Gendarmes, chapter2);
ADD_CALLBACK_FUNCTION(Gendarmes, chapter3);
@@ -76,23 +76,23 @@ IMPLEMENT_FUNCTION(2, Gendarmes, chapter1)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_S(3, Gendarmes, arrestDraw)
- arrest(savepoint);
+IMPLEMENT_FUNCTION_S(3, Gendarmes, doDraw)
+ handleAction(savepoint);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_S(4, Gendarmes, arrestPlaysound)
- arrest(savepoint, true);
+IMPLEMENT_FUNCTION_S(4, Gendarmes, doDialog)
+ handleAction(savepoint, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_S(5, Gendarmes, arrestPlaysound16)
- arrest(savepoint, true, kFlagDefault);
+IMPLEMENT_FUNCTION_S(5, Gendarmes, doDialogFullVolume)
+ handleAction(savepoint, true, kFlagDefault);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_I(6, Gendarmes, arrestCallback, uint32)
- arrest(savepoint, true, kFlagInvalid, true);
+IMPLEMENT_FUNCTION_I(6, Gendarmes, doWait, uint32)
+ handleAction(savepoint, true, kFlagInvalid, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
@@ -101,12 +101,12 @@ IMPLEMENT_FUNCTION_II(7, Gendarmes, savegame, SavegameType, uint32)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_II(8, Gendarmes, arrestUpdateEntity, CarIndex, EntityPosition)
- arrest(savepoint, true, kFlagInvalid, false, true);
+IMPLEMENT_FUNCTION_II(8, Gendarmes, doWalk, CarIndex, EntityPosition)
+ handleAction(savepoint, true, kFlagInvalid, false, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition)
+IMPLEMENT_FUNCTION_IISS(9, Gendarmes, doCompartment, CarIndex, EntityPosition)
EntityData::EntityParametersSSS *parameters1 = (EntityData::EntityParametersSSS*)_data->getCurrentParameters(1);
EntityData::EntityParametersISII *parameters2 = (EntityData::EntityParametersISII*)_data->getCurrentParameters(2);
@@ -169,6 +169,9 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition)
strcpy((char *)&parameters1->seq3, "632F");
}
+ // The sequence 3 string needs to be a maximum of 9 characters, leaving 5 characters after the initial setup
+ assert(Common::String(params->seq1).size() <= 5);
+
strcat((char *)&parameters1->seq1, (char *)&params->seq1);
strcat((char *)&parameters1->seq2, (char *)&params->seq1);
strcat((char *)&parameters1->seq3, (char *)&params->seq1);
@@ -178,13 +181,13 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition)
|| (params->param1 == kCarGreenSleeping && params->param2 == kPosition_8200 && getEntities()->isOutsideAlexeiWindow()))
&& !getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_7850)) {
setCallback(1);
- setup_function10((CarIndex)params->param1, (EntityPosition)params->param2, (ObjectIndex)parameters2->param5);
+ setup_trappedCath((CarIndex)params->param1, (EntityPosition)params->param2, (ObjectIndex)parameters2->param5);
} else {
getEntities()->drawSequenceLeft(kEntityGendarmes, (char *)&parameters1->seq1);
getEntities()->enterCompartment(kEntityGendarmes, (ObjectIndex)CURRENT_PARAM(2, 5));
setCallback(parameters2->param6 ? 2 : 3);
- setup_arrestPlaysound(parameters2->param6 ? "POL1044A" : "POL1044B");
+ setup_doDialog(parameters2->param6 ? "POL1044A" : "POL1044B");
}
break;
@@ -202,14 +205,14 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition)
getEntities()->drawSequenceLeft(kEntityGendarmes, (char *)&parameters1->seq2);
if (getEntities()->isNobodyInCompartment((CarIndex)params->param1, (EntityPosition)params->param2) || !strcmp(params->seq2, "NODIALOG")) {
setCallback(4);
- setup_arrestCallback(150);
+ setup_doWait(150);
} else {
char *arrestSound = (char *)&parameters2->seq;
strcpy(arrestSound, "POL1045");
strcat(arrestSound, (char *)&params->seq2);
setCallback(5);
- setup_arrestPlaysound(arrestSound);
+ setup_doDialog(arrestSound);
}
break;
@@ -226,7 +229,7 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition)
getData()->location = kLocationInsideCompartment;
setCallback(6);
- setup_arrestDraw((char *)&parameters1->seq3);
+ setup_doDraw((char *)&parameters1->seq3);
break;
case 6:
@@ -240,7 +243,7 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_III(10, Gendarmes, function10, CarIndex, EntityPosition, ObjectIndex)
+IMPLEMENT_FUNCTION_III(10, Gendarmes, trappedCath, CarIndex, EntityPosition, ObjectIndex)
switch (savepoint.action) {
default:
break;
@@ -287,7 +290,7 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, function10, CarIndex, EntityPosition, Obje
getObjects()->update((ObjectIndex)params->param3, kEntityGendarmes, getObjects()->get((ObjectIndex)params->param3).status, kCursorNormal, kCursorNormal);
setCallback(5);
- setup_arrestPlaysound16("POL1046B");
+ setup_doDialogFullVolume("POL1046B");
break;
case kActionOpenDoor:
@@ -299,7 +302,7 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, function10, CarIndex, EntityPosition, Obje
getObjects()->update((ObjectIndex)params->param3, kEntityGendarmes, getObjects()->get((ObjectIndex)params->param3).status, kCursorNormal, kCursorNormal);
setCallback(1);
- setup_arrestPlaysound16("POL1046");
+ setup_doDialogFullVolume("POL1046");
break;
case kActionCallback:
@@ -351,12 +354,12 @@ IMPLEMENT_FUNCTION_END
IMPLEMENT_FUNCTION(11, Gendarmes, chapter1Handler)
if (savepoint.action == kAction169499649) {
getSavePoints()->push(kEntityGendarmes, kEntityMertens, kAction190082817);
- setup_function12();
+ setup_searchTrain();
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(12, Gendarmes, function12)
+IMPLEMENT_FUNCTION(12, Gendarmes, searchTrain)
switch (savepoint.action) {
default:
break;
@@ -369,7 +372,7 @@ IMPLEMENT_FUNCTION(12, Gendarmes, function12)
getProgress().field_14 = 29;
setCallback(1);
- setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_5540);
+ setup_doWalk(kCarGreenSleeping, kPosition_5540);
break;
case kActionCallback:
@@ -379,42 +382,42 @@ IMPLEMENT_FUNCTION(12, Gendarmes, function12)
case 1:
setCallback(2);
- setup_function9(kCarGreenSleeping, kPosition_5790, "d", "A");
+ setup_doCompartment(kCarGreenSleeping, kPosition_5790, "d", "A");
break;
case 2:
setCallback(3);
- setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_6220);
+ setup_doWalk(kCarGreenSleeping, kPosition_6220);
break;
case 3:
setCallback(4);
- setup_function9(kCarGreenSleeping, kPosition_6470, "c", "B");
+ setup_doCompartment(kCarGreenSleeping, kPosition_6470, "c", "B");
break;
case 4:
setCallback(5);
- setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_7250);
+ setup_doWalk(kCarGreenSleeping, kPosition_7250);
break;
case 5:
setCallback(6);
- setup_function9(kCarGreenSleeping, kPosition_7500, "b", "C");
+ setup_doCompartment(kCarGreenSleeping, kPosition_7500, "b", "C");
break;
case 6:
setCallback(7);
- setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_7950);
+ setup_doWalk(kCarGreenSleeping, kPosition_7950);
break;
case 7:
setCallback(8);
- setup_function9(kCarGreenSleeping, kPosition_8200, "a", "NODIALOG");
+ setup_doCompartment(kCarGreenSleeping, kPosition_8200, "a", "NODIALOG");
break;
case 8:
setCallback(9);
- setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_9460);
+ setup_doWalk(kCarGreenSleeping, kPosition_9460);
break;
case 9:
@@ -427,77 +430,77 @@ IMPLEMENT_FUNCTION(12, Gendarmes, function12)
}
setCallback(10);
- setup_arrestUpdateEntity(kCarRedSleeping, kPosition_2490);
+ setup_doWalk(kCarRedSleeping, kPosition_2490);
break;
case 10:
setCallback(11);
- setup_function9(kCarRedSleeping, kPosition_2740, "h", "NODIALOG");
+ setup_doCompartment(kCarRedSleeping, kPosition_2740, "h", "NODIALOG");
break;
case 11:
setCallback(12);
- setup_arrestUpdateEntity(kCarRedSleeping, kPosition_3820);
+ setup_doWalk(kCarRedSleeping, kPosition_3820);
break;
case 12:
setCallback(13);
- setup_function9(kCarRedSleeping, kPosition_4070, "f", "E");
+ setup_doCompartment(kCarRedSleeping, kPosition_4070, "f", "E");
break;
case 13:
setCallback(14);
- setup_arrestUpdateEntity(kCarRedSleeping, kPosition_4590);
+ setup_doWalk(kCarRedSleeping, kPosition_4590);
break;
case 14:
setCallback(15);
- setup_function9(kCarRedSleeping, kPosition_4840, "e", "F");
+ setup_doCompartment(kCarRedSleeping, kPosition_4840, "e", "F");
break;
case 15:
setCallback(16);
- setup_arrestUpdateEntity(kCarRedSleeping, kPosition_5540);
+ setup_doWalk(kCarRedSleeping, kPosition_5540);
break;
case 16:
setCallback(17);
- setup_function9(kCarRedSleeping, kPosition_5790, "d", "G");
+ setup_doCompartment(kCarRedSleeping, kPosition_5790, "d", "G");
break;
case 17:
setCallback(18);
- setup_arrestUpdateEntity(kCarRedSleeping, kPosition_6220);
+ setup_doWalk(kCarRedSleeping, kPosition_6220);
break;
case 18:
setCallback(19);
- setup_function9(kCarRedSleeping, kPosition_6470, "c", "H");
+ setup_doCompartment(kCarRedSleeping, kPosition_6470, "c", "H");
break;
case 19:
setCallback(20);
- setup_arrestUpdateEntity(kCarRedSleeping, kPosition_7250);
+ setup_doWalk(kCarRedSleeping, kPosition_7250);
break;
case 20:
setCallback(21);
- setup_function9(kCarRedSleeping, kPosition_7500, "b", "J");
+ setup_doCompartment(kCarRedSleeping, kPosition_7500, "b", "J");
break;
case 21:
setCallback(22);
- setup_arrestUpdateEntity(kCarRedSleeping, kPosition_7950);
+ setup_doWalk(kCarRedSleeping, kPosition_7950);
break;
case 22:
setCallback(23);
- setup_function9(kCarRedSleeping, kPosition_8200, "a", "NODIALOG");
+ setup_doCompartment(kCarRedSleeping, kPosition_8200, "a", "NODIALOG");
break;
case 23:
setCallback(24);
- setup_arrestUpdateEntity(kCarRedSleeping, kPosition_9460);
+ setup_doWalk(kCarRedSleeping, kPosition_9460);
break;
case 24:
@@ -544,7 +547,7 @@ IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
// Private functions
//////////////////////////////////////////////////////////////////////////
-void Gendarmes::arrest(const SavePoint &savepoint, bool shouldPlaySound, SoundFlag flag, bool checkCallback, bool shouldUpdateEntity) {
+void Gendarmes::handleAction(const SavePoint &savepoint, bool shouldPlaySound, SoundFlag flag, bool checkCallback, bool shouldUpdateEntity) {
switch (savepoint.action) {
default:
break;
diff --git a/engines/lastexpress/entities/gendarmes.h b/engines/lastexpress/entities/gendarmes.h
index 8475c50799..1cde626a22 100644
--- a/engines/lastexpress/entities/gendarmes.h
+++ b/engines/lastexpress/entities/gendarmes.h
@@ -46,10 +46,10 @@ public:
*/
DECLARE_FUNCTION(chapter1)
- DECLARE_FUNCTION_1(arrestDraw, const char *sequence)
- DECLARE_FUNCTION_1(arrestPlaysound, const char *soundName)
- DECLARE_FUNCTION_1(arrestPlaysound16, const char *soundName)
- DECLARE_FUNCTION_1(arrestCallback, uint32 timeValue)
+ DECLARE_FUNCTION_1(doDraw, const char *sequence)
+ DECLARE_FUNCTION_1(doDialog, const char *soundName)
+ DECLARE_FUNCTION_1(doDialogFullVolume, const char *soundName)
+ DECLARE_FUNCTION_1(doWait, uint32 timeValue)
/**
* Saves the game
@@ -59,11 +59,11 @@ public:
*/
DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param)
- DECLARE_FUNCTION_2(arrestUpdateEntity, CarIndex car, EntityPosition entityPosition)
- DECLARE_FUNCTION_4(function9, CarIndex car, EntityPosition entityPosition, const char *sequence1, const char *sequence2)
- DECLARE_FUNCTION_3(function10, CarIndex car, EntityPosition entityPosition, ObjectIndex object)
+ DECLARE_FUNCTION_2(doWalk, CarIndex car, EntityPosition entityPosition)
+ DECLARE_FUNCTION_4(doCompartment, CarIndex car, EntityPosition entityPosition, const char *sequence1, const char *sequence2)
+ DECLARE_FUNCTION_3(trappedCath, CarIndex car, EntityPosition entityPosition, ObjectIndex object)
DECLARE_FUNCTION(chapter1Handler)
- DECLARE_FUNCTION(function12)
+ DECLARE_FUNCTION(searchTrain)
DECLARE_FUNCTION(function13)
/**
@@ -87,7 +87,7 @@ public:
DECLARE_FUNCTION(chapter5)
private:
- void arrest(const SavePoint &savepoint, bool playSound = false, SoundFlag flag = kFlagInvalid, bool checkCallback = false, bool shouldUpdateEntity = false);
+ void handleAction(const SavePoint &savepoint, bool playSound = false, SoundFlag flag = kFlagInvalid, bool checkCallback = false, bool shouldUpdateEntity = false);
};
} // End of namespace LastExpress
diff --git a/engines/lastexpress/entities/hadija.cpp b/engines/lastexpress/entities/hadija.cpp
index 14d5b714ca..eb255d77f8 100644
--- a/engines/lastexpress/entities/hadija.cpp
+++ b/engines/lastexpress/entities/hadija.cpp
@@ -38,10 +38,10 @@ Hadija::Hadija(LastExpressEngine *engine) : Entity(engine, kEntityHadija) {
ADD_CALLBACK_FUNCTION(Hadija, playSound);
ADD_CALLBACK_FUNCTION(Hadija, updateFromTime);
ADD_CALLBACK_FUNCTION(Hadija, updateEntity);
- ADD_CALLBACK_FUNCTION(Hadija, compartment6);
- ADD_CALLBACK_FUNCTION(Hadija, compartment8);
- ADD_CALLBACK_FUNCTION(Hadija, compartment6to8);
- ADD_CALLBACK_FUNCTION(Hadija, compartment8to6);
+ ADD_CALLBACK_FUNCTION(Hadija, peekF);
+ ADD_CALLBACK_FUNCTION(Hadija, peekH);
+ ADD_CALLBACK_FUNCTION(Hadija, goFtoH);
+ ADD_CALLBACK_FUNCTION(Hadija, goHtoF);
ADD_CALLBACK_FUNCTION(Hadija, chapter1);
ADD_CALLBACK_FUNCTION(Hadija, chapter1Handler);
ADD_CALLBACK_FUNCTION(Hadija, function12);
@@ -55,7 +55,7 @@ Hadija::Hadija(LastExpressEngine *engine) : Entity(engine, kEntityHadija) {
ADD_CALLBACK_FUNCTION(Hadija, chapter5);
ADD_CALLBACK_FUNCTION(Hadija, chapter5Handler);
ADD_CALLBACK_FUNCTION(Hadija, function22);
- ADD_CALLBACK_FUNCTION(Hadija, function23);
+ ADD_CALLBACK_FUNCTION(Hadija, hiding);
ADD_NULL_FUNCTION();
}
@@ -85,22 +85,22 @@ IMPLEMENT_FUNCTION_II(5, Hadija, updateEntity, CarIndex, EntityPosition)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(6, Hadija, compartment6)
+IMPLEMENT_FUNCTION(6, Hadija, peekF)
Entity::goToCompartment(savepoint, kObjectCompartment6, kPosition_4070, "619Cf", "619Df");
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(7, Hadija, compartment8)
+IMPLEMENT_FUNCTION(7, Hadija, peekH)
Entity::goToCompartment(savepoint, kObjectCompartment8, kPosition_2740, "619Ch", "619Dh");
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(8, Hadija, compartment6to8)
+IMPLEMENT_FUNCTION(8, Hadija, goFtoH)
Entity::goToCompartmentFromCompartment(savepoint, kObjectCompartment6, kPosition_4070, "619Bf", kObjectCompartment8, kPosition_2740, "619Ah");
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(9, Hadija, compartment8to6)
+IMPLEMENT_FUNCTION(9, Hadija, goHtoF)
Entity::goToCompartmentFromCompartment(savepoint, kObjectCompartment8, kPosition_2740, "619Bh", kObjectCompartment6, kPosition_4070, "619Af");
IMPLEMENT_FUNCTION_END
@@ -134,7 +134,7 @@ IMPLEMENT_FUNCTION(11, Hadija, chapter1Handler)
break;
label_callback1:
- if (Entity::timeCheckCallback(kTime1084500, params->param2, 2, WRAP_SETUP_FUNCTION(Hadija, setup_compartment6to8)))
+ if (Entity::timeCheckCallback(kTime1084500, params->param2, 2, WRAP_SETUP_FUNCTION(Hadija, setup_goFtoH)))
break;
label_callback2:
@@ -147,7 +147,7 @@ label_callback2:
if (!params->param3) {
setCallback(3);
- setup_compartment8();
+ setup_peekH();
return;
}
}
@@ -159,11 +159,11 @@ label_callback2:
params->param3 = kTimeInvalid;
setCallback(3);
- setup_compartment8();
+ setup_peekH();
}
label_callback3:
- if (Entity::timeCheckCallback(kTime1156500, params->param4, 4, WRAP_SETUP_FUNCTION(Hadija, setup_compartment8to6)))
+ if (Entity::timeCheckCallback(kTime1156500, params->param4, 4, WRAP_SETUP_FUNCTION(Hadija, setup_goHtoF)))
break;
label_callback4:
@@ -175,7 +175,7 @@ label_callback4:
if (!params->param5) {
setCallback(5);
- setup_compartment6();
+ setup_peekF();
return;
}
}
@@ -187,7 +187,7 @@ label_callback4:
params->param5 = kTimeInvalid;
setCallback(5);
- setup_compartment6();
+ setup_peekF();
}
break;
@@ -254,7 +254,7 @@ IMPLEMENT_FUNCTION(14, Hadija, chapter2Handler)
}
if (params->param2 == kTimeInvalid || getState()->time <= kTime1786500) {
- Entity::timeCheckCallback(kTime1822500, params->param3, 2, WRAP_SETUP_FUNCTION(Hadija, setup_compartment8to6));
+ Entity::timeCheckCallback(kTime1822500, params->param3, 2, WRAP_SETUP_FUNCTION(Hadija, setup_goHtoF));
break;
}
@@ -264,7 +264,7 @@ IMPLEMENT_FUNCTION(14, Hadija, chapter2Handler)
params->param2 = (uint)getState()->time + 75;
if (params->param2 >= getState()->time) {
- Entity::timeCheckCallback(kTime1822500, params->param3, 2, WRAP_SETUP_FUNCTION(Hadija, setup_compartment8to6));
+ Entity::timeCheckCallback(kTime1822500, params->param3, 2, WRAP_SETUP_FUNCTION(Hadija, setup_goHtoF));
break;
}
}
@@ -272,7 +272,7 @@ IMPLEMENT_FUNCTION(14, Hadija, chapter2Handler)
params->param2 = kTimeInvalid;
setCallback(1);
- setup_compartment8();
+ setup_peekH();
break;
case kActionCallback:
@@ -281,7 +281,7 @@ IMPLEMENT_FUNCTION(14, Hadija, chapter2Handler)
break;
case 1:
- Entity::timeCheckCallback(kTime1822500, params->param3, 2, WRAP_SETUP_FUNCTION(Hadija, setup_compartment8to6));
+ Entity::timeCheckCallback(kTime1822500, params->param3, 2, WRAP_SETUP_FUNCTION(Hadija, setup_goHtoF));
break;
case 2:
@@ -321,24 +321,24 @@ IMPLEMENT_FUNCTION(16, Hadija, chapter3Handler)
break;
case kActionNone:
- if (Entity::timeCheckCallback(kTime1998000, params->param1, 1, WRAP_SETUP_FUNCTION(Hadija, setup_compartment6to8)))
+ if (Entity::timeCheckCallback(kTime1998000, params->param1, 1, WRAP_SETUP_FUNCTION(Hadija, setup_goFtoH)))
break;
label_callback1:
- if (Entity::timeCheckCallback(kTime2020500, params->param2, 2, WRAP_SETUP_FUNCTION(Hadija, setup_compartment8to6)))
+ if (Entity::timeCheckCallback(kTime2020500, params->param2, 2, WRAP_SETUP_FUNCTION(Hadija, setup_goHtoF)))
break;
label_callback2:
- if (Entity::timeCheckCallback(kTime2079000, params->param3, 3, WRAP_SETUP_FUNCTION(Hadija, setup_compartment6to8)))
+ if (Entity::timeCheckCallback(kTime2079000, params->param3, 3, WRAP_SETUP_FUNCTION(Hadija, setup_goFtoH)))
break;
label_callback3:
- if (Entity::timeCheckCallback(kTime2187000, params->param4, 4, WRAP_SETUP_FUNCTION(Hadija, setup_compartment8to6)))
+ if (Entity::timeCheckCallback(kTime2187000, params->param4, 4, WRAP_SETUP_FUNCTION(Hadija, setup_goHtoF)))
break;
label_callback4:
if (params->param5 != kTimeInvalid && getState()->time > kTime2196000) {
- if (Entity::timeCheckCar(kTime2254500, params->param5, 5, WRAP_SETUP_FUNCTION(Hadija, setup_compartment6)))
+ if (Entity::timeCheckCar(kTime2254500, params->param5, 5, WRAP_SETUP_FUNCTION(Hadija, setup_peekF)))
break;
}
break;
@@ -394,21 +394,21 @@ IMPLEMENT_FUNCTION(18, Hadija, chapter4Handler)
case kActionNone:
if (params->param1 != kTimeInvalid) {
- if (Entity::timeCheckCar(kTime1714500, params->param1, 1, WRAP_SETUP_FUNCTION(Hadija, setup_compartment6)))
+ if (Entity::timeCheckCar(kTime1714500, params->param1, 1, WRAP_SETUP_FUNCTION(Hadija, setup_peekF)))
break;
}
label_callback1:
- if (Entity::timeCheckCallback(kTime2367000, params->param2, 2, WRAP_SETUP_FUNCTION(Hadija, setup_compartment6to8)))
+ if (Entity::timeCheckCallback(kTime2367000, params->param2, 2, WRAP_SETUP_FUNCTION(Hadija, setup_goFtoH)))
break;
label_callback2:
- if (Entity::timeCheckCallback(kTime2421000, params->param3, 3, WRAP_SETUP_FUNCTION(Hadija, setup_compartment8to6)))
+ if (Entity::timeCheckCallback(kTime2421000, params->param3, 3, WRAP_SETUP_FUNCTION(Hadija, setup_goHtoF)))
break;
label_callback3:
if (params->param4 != kTimeInvalid && getState()->time > kTime2425500) {
- if (Entity::timeCheckCar(kTime2484000, params->param4, 4, WRAP_SETUP_FUNCTION(Hadija, setup_compartment6)))
+ if (Entity::timeCheckCar(kTime2484000, params->param4, 4, WRAP_SETUP_FUNCTION(Hadija, setup_peekF)))
break;
}
break;
@@ -483,7 +483,7 @@ IMPLEMENT_FUNCTION(22, Hadija, function22)
if (!Entity::updateParameter(params->param1, getState()->time, 2700))
break;
- setup_function23();
+ setup_hiding();
break;
case kActionDefault:
@@ -494,14 +494,14 @@ IMPLEMENT_FUNCTION(22, Hadija, function22)
case kActionDrawScene:
if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) {
- setup_function23();
+ setup_hiding();
}
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(23, Hadija, function23)
+IMPLEMENT_FUNCTION(23, Hadija, hiding)
switch (savepoint.action) {
default:
break;
diff --git a/engines/lastexpress/entities/hadija.h b/engines/lastexpress/entities/hadija.h
index 8e92dc6891..a66aa33628 100644
--- a/engines/lastexpress/entities/hadija.h
+++ b/engines/lastexpress/entities/hadija.h
@@ -70,10 +70,10 @@ public:
*/
DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition)
- DECLARE_FUNCTION(compartment6)
- DECLARE_FUNCTION(compartment8)
- DECLARE_FUNCTION(compartment6to8)
- DECLARE_FUNCTION(compartment8to6)
+ DECLARE_FUNCTION(peekF)
+ DECLARE_FUNCTION(peekH)
+ DECLARE_FUNCTION(goFtoH)
+ DECLARE_FUNCTION(goHtoF)
/**
* Setup Chapter 1
@@ -130,7 +130,7 @@ public:
DECLARE_FUNCTION(chapter5Handler)
DECLARE_FUNCTION(function22)
- DECLARE_FUNCTION(function23)
+ DECLARE_FUNCTION(hiding)
DECLARE_NULL_FUNCTION()
};
diff --git a/engines/lastexpress/entities/ivo.cpp b/engines/lastexpress/entities/ivo.cpp
index b7697d0c52..12a23e7d37 100644
--- a/engines/lastexpress/entities/ivo.cpp
+++ b/engines/lastexpress/entities/ivo.cpp
@@ -47,29 +47,29 @@ Ivo::Ivo(LastExpressEngine *engine) : Entity(engine, kEntityIvo) {
ADD_CALLBACK_FUNCTION(Ivo, playSound);
ADD_CALLBACK_FUNCTION(Ivo, callbackActionRestaurantOrSalon);
ADD_CALLBACK_FUNCTION(Ivo, savegame);
- ADD_CALLBACK_FUNCTION(Ivo, function11);
+ ADD_CALLBACK_FUNCTION(Ivo, goCompartment);
ADD_CALLBACK_FUNCTION(Ivo, sitAtTableWithSalko);
ADD_CALLBACK_FUNCTION(Ivo, leaveTableWithSalko);
ADD_CALLBACK_FUNCTION(Ivo, chapter1);
ADD_CALLBACK_FUNCTION(Ivo, chapter1Handler);
- ADD_CALLBACK_FUNCTION(Ivo, function16);
+ ADD_CALLBACK_FUNCTION(Ivo, inCompartment);
ADD_CALLBACK_FUNCTION(Ivo, function17);
ADD_CALLBACK_FUNCTION(Ivo, chapter2);
- ADD_CALLBACK_FUNCTION(Ivo, function19);
- ADD_CALLBACK_FUNCTION(Ivo, function20);
+ ADD_CALLBACK_FUNCTION(Ivo, goBreakfast);
+ ADD_CALLBACK_FUNCTION(Ivo, atBreakfast);
ADD_CALLBACK_FUNCTION(Ivo, function21);
ADD_CALLBACK_FUNCTION(Ivo, chapter3);
ADD_CALLBACK_FUNCTION(Ivo, chapter3Handler);
ADD_CALLBACK_FUNCTION(Ivo, chapter4);
ADD_CALLBACK_FUNCTION(Ivo, chapter4Handler);
- ADD_CALLBACK_FUNCTION(Ivo, function26);
- ADD_CALLBACK_FUNCTION(Ivo, function27);
- ADD_CALLBACK_FUNCTION(Ivo, function28);
+ ADD_CALLBACK_FUNCTION(Ivo, returnCompartment4);
+ ADD_CALLBACK_FUNCTION(Ivo, inCompartment4);
+ ADD_CALLBACK_FUNCTION(Ivo, hiding);
ADD_CALLBACK_FUNCTION(Ivo, function29);
ADD_CALLBACK_FUNCTION(Ivo, chapter5);
ADD_CALLBACK_FUNCTION(Ivo, chapter5Handler);
- ADD_CALLBACK_FUNCTION(Ivo, fight);
- ADD_CALLBACK_FUNCTION(Ivo, function33);
+ ADD_CALLBACK_FUNCTION(Ivo, fightCath);
+ ADD_CALLBACK_FUNCTION(Ivo, knockedOut);
ADD_CALLBACK_FUNCTION(Ivo, function34);
}
@@ -129,7 +129,7 @@ IMPLEMENT_FUNCTION_II(10, Ivo, savegame, SavegameType, uint32)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(11, Ivo, function11)
+IMPLEMENT_FUNCTION(11, Ivo, goCompartment)
switch (savepoint.action) {
default:
break;
@@ -279,12 +279,12 @@ IMPLEMENT_FUNCTION(15, Ivo, chapter1Handler)
case 1:
setCallback(2);
- setup_function11();
+ setup_goCompartment();
break;
case 2:
getSavePoints()->push(kEntityIvo, kEntityMilos, kAction135024800);
- setup_function16();
+ setup_inCompartment();
break;
}
break;
@@ -297,7 +297,7 @@ IMPLEMENT_FUNCTION(15, Ivo, chapter1Handler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(16, Ivo, function16)
+IMPLEMENT_FUNCTION(16, Ivo, inCompartment)
switch (savepoint.action) {
default:
break;
@@ -371,7 +371,7 @@ IMPLEMENT_FUNCTION(18, Ivo, chapter2)
break;
case kActionNone:
- Entity::timeCheck(kTime1777500, params->param1, WRAP_SETUP_FUNCTION(Ivo, setup_function19));
+ Entity::timeCheck(kTime1777500, params->param1, WRAP_SETUP_FUNCTION(Ivo, setup_goBreakfast));
break;
case kActionDefault:
@@ -391,7 +391,7 @@ IMPLEMENT_FUNCTION(18, Ivo, chapter2)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(19, Ivo, function19)
+IMPLEMENT_FUNCTION(19, Ivo, goBreakfast)
switch (savepoint.action) {
default:
break;
@@ -434,7 +434,7 @@ IMPLEMENT_FUNCTION(19, Ivo, function19)
case 5:
getData()->location = kLocationInsideCompartment;
- setup_function20();
+ setup_atBreakfast();
break;
}
break;
@@ -447,7 +447,7 @@ IMPLEMENT_FUNCTION(19, Ivo, function19)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(20, Ivo, function20)
+IMPLEMENT_FUNCTION(20, Ivo, atBreakfast)
switch (savepoint.action) {
default:
break;
@@ -464,7 +464,7 @@ IMPLEMENT_FUNCTION(20, Ivo, function20)
break;
case kActionDefault:
- getSavePoints()->push(kEntityIvo, kEntityServers1, kAction189688608);
+ getSavePoints()->push(kEntityIvo, kEntityWaiter2, kAction189688608);
getEntities()->drawSequenceLeft(kEntityIvo, "023B");
break;
@@ -474,18 +474,18 @@ IMPLEMENT_FUNCTION(20, Ivo, function20)
break;
case 1:
- getSavePoints()->push(kEntityIvo, kEntityServers1, kAction101106391);
+ getSavePoints()->push(kEntityIvo, kEntityWaiter2, kAction101106391);
getEntities()->drawSequenceLeft(kEntityIvo, "023B");
params->param1 = 1;
break;
case 2:
setCallback(3);
- setup_function11();
+ setup_goCompartment();
break;
case 3:
- getSavePoints()->push(kEntityIvo, kEntityServers1, kAction236237423);
+ getSavePoints()->push(kEntityIvo, kEntityWaiter2, kAction236237423);
setup_function21();
break;
}
@@ -567,7 +567,7 @@ IMPLEMENT_FUNCTION(25, Ivo, chapter4Handler)
case kActionNone:
if (getState()->time > kTime2361600 && getEntities()->isSomebodyInsideRestaurantOrSalon()) {
getData()->location = kLocationOutsideCompartment;
- setup_function26();
+ setup_returnCompartment4();
}
break;
@@ -579,7 +579,7 @@ IMPLEMENT_FUNCTION(25, Ivo, chapter4Handler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(26, Ivo, function26)
+IMPLEMENT_FUNCTION(26, Ivo, returnCompartment4)
switch (savepoint.action) {
default:
break;
@@ -596,11 +596,11 @@ IMPLEMENT_FUNCTION(26, Ivo, function26)
case 1:
setCallback(2);
- setup_function11();
+ setup_goCompartment();
break;
case 2:
- setup_function27();
+ setup_inCompartment4();
break;
}
break;
@@ -608,7 +608,7 @@ IMPLEMENT_FUNCTION(26, Ivo, function26)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(27, Ivo, function27)
+IMPLEMENT_FUNCTION(27, Ivo, inCompartment4)
switch (savepoint.action) {
default:
break;
@@ -634,7 +634,7 @@ IMPLEMENT_FUNCTION(27, Ivo, function27)
case 2:
getEntities()->clearSequences(kEntityIvo);
- setup_function28();
+ setup_hiding();
break;
case 3:
@@ -676,7 +676,7 @@ IMPLEMENT_FUNCTION(27, Ivo, function27)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(28, Ivo, function28)
+IMPLEMENT_FUNCTION(28, Ivo, hiding)
switch (savepoint.action) {
default:
break;
@@ -745,11 +745,11 @@ IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(31, Ivo, chapter5Handler)
if (savepoint.action == kActionProceedChapter5)
- setup_fight();
+ setup_fightCath();
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(32, Ivo, fight)
+IMPLEMENT_FUNCTION(32, Ivo, fightCath)
switch (savepoint.action) {
default:
break;
@@ -783,7 +783,7 @@ IMPLEMENT_FUNCTION(32, Ivo, fight)
getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, true);
} else {
getScenes()->loadSceneFromPosition(kCarBaggageRear, 96);
- setup_function33();
+ setup_knockedOut();
}
break;
}
@@ -792,7 +792,7 @@ IMPLEMENT_FUNCTION(32, Ivo, fight)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(33, Ivo, function33)
+IMPLEMENT_FUNCTION(33, Ivo, knockedOut)
switch (savepoint.action) {
default:
break;
diff --git a/engines/lastexpress/entities/ivo.h b/engines/lastexpress/entities/ivo.h
index a23d06cd3f..3646bc19f2 100644
--- a/engines/lastexpress/entities/ivo.h
+++ b/engines/lastexpress/entities/ivo.h
@@ -102,7 +102,7 @@ public:
*/
DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param)
- DECLARE_FUNCTION(function11)
+ DECLARE_FUNCTION(goCompartment)
DECLARE_FUNCTION(sitAtTableWithSalko)
DECLARE_FUNCTION(leaveTableWithSalko)
@@ -116,7 +116,7 @@ public:
*/
DECLARE_FUNCTION(chapter1Handler)
- DECLARE_FUNCTION(function16)
+ DECLARE_FUNCTION(inCompartment)
DECLARE_FUNCTION(function17)
/**
@@ -124,8 +124,8 @@ public:
*/
DECLARE_FUNCTION(chapter2)
- DECLARE_FUNCTION(function19)
- DECLARE_FUNCTION(function20)
+ DECLARE_FUNCTION(goBreakfast)
+ DECLARE_FUNCTION(atBreakfast)
DECLARE_FUNCTION(function21)
/**
@@ -148,9 +148,9 @@ public:
*/
DECLARE_FUNCTION(chapter4Handler)
- DECLARE_FUNCTION(function26)
- DECLARE_FUNCTION(function27)
- DECLARE_FUNCTION(function28)
+ DECLARE_FUNCTION(returnCompartment4)
+ DECLARE_FUNCTION(inCompartment4)
+ DECLARE_FUNCTION(hiding)
DECLARE_FUNCTION(function29)
/**
@@ -163,8 +163,8 @@ public:
*/
DECLARE_FUNCTION(chapter5Handler)
- DECLARE_FUNCTION(fight)
- DECLARE_FUNCTION(function33)
+ DECLARE_FUNCTION(fightCath)
+ DECLARE_FUNCTION(knockedOut)
DECLARE_FUNCTION(function34)
};
diff --git a/engines/lastexpress/entities/kahina.cpp b/engines/lastexpress/entities/kahina.cpp
index b7af87751f..bbb2853721 100644
--- a/engines/lastexpress/entities/kahina.cpp
+++ b/engines/lastexpress/entities/kahina.cpp
@@ -43,28 +43,28 @@ Kahina::Kahina(LastExpressEngine *engine) : Entity(engine, kEntityKahina) {
ADD_CALLBACK_FUNCTION(Kahina, savegame);
ADD_CALLBACK_FUNCTION(Kahina, updateFromTime);
ADD_CALLBACK_FUNCTION(Kahina, updateFromTicks);
- ADD_CALLBACK_FUNCTION(Kahina, function6);
+ ADD_CALLBACK_FUNCTION(Kahina, lookingForCath);
ADD_CALLBACK_FUNCTION(Kahina, updateEntity2);
ADD_CALLBACK_FUNCTION(Kahina, updateEntity);
ADD_CALLBACK_FUNCTION(Kahina, enterExitCompartment);
ADD_CALLBACK_FUNCTION(Kahina, chapter1);
ADD_CALLBACK_FUNCTION(Kahina, chapter1Handler);
- ADD_CALLBACK_FUNCTION(Kahina, function12);
- ADD_CALLBACK_FUNCTION(Kahina, function13);
+ ADD_CALLBACK_FUNCTION(Kahina, awaitingCath);
+ ADD_CALLBACK_FUNCTION(Kahina, cathDone);
ADD_CALLBACK_FUNCTION(Kahina, function14);
- ADD_CALLBACK_FUNCTION(Kahina, function15);
+ ADD_CALLBACK_FUNCTION(Kahina, searchTrain);
ADD_CALLBACK_FUNCTION(Kahina, chapter2);
- ADD_CALLBACK_FUNCTION(Kahina, chapter2Handler);
+ ADD_CALLBACK_FUNCTION(Kahina, inSeclusionPart2);
ADD_CALLBACK_FUNCTION(Kahina, chapter3);
ADD_CALLBACK_FUNCTION(Kahina, function19);
- ADD_CALLBACK_FUNCTION(Kahina, chapter3Handler);
- ADD_CALLBACK_FUNCTION(Kahina, function21);
- ADD_CALLBACK_FUNCTION(Kahina, function22);
- ADD_CALLBACK_FUNCTION(Kahina, function23);
- ADD_CALLBACK_FUNCTION(Kahina, function24);
- ADD_CALLBACK_FUNCTION(Kahina, function25);
- ADD_CALLBACK_FUNCTION(Kahina, function26);
- ADD_CALLBACK_FUNCTION(Kahina, function27);
+ ADD_CALLBACK_FUNCTION(Kahina, beforeConcert);
+ ADD_CALLBACK_FUNCTION(Kahina, concert);
+ ADD_CALLBACK_FUNCTION(Kahina, finished);
+ ADD_CALLBACK_FUNCTION(Kahina, findFirebird);
+ ADD_CALLBACK_FUNCTION(Kahina, seekCath);
+ ADD_CALLBACK_FUNCTION(Kahina, searchCath);
+ ADD_CALLBACK_FUNCTION(Kahina, searchTatiana);
+ ADD_CALLBACK_FUNCTION(Kahina, killCathAnywhere);
ADD_CALLBACK_FUNCTION(Kahina, chapter4);
ADD_CALLBACK_FUNCTION(Kahina, chapter5);
}
@@ -100,7 +100,7 @@ IMPLEMENT_FUNCTION_NOSETUP(5, Kahina, updateFromTicks)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_I(6, Kahina, function6, TimeValue)
+IMPLEMENT_FUNCTION_I(6, Kahina, lookingForCath, TimeValue)
switch (savepoint.action) {
default:
break;
@@ -270,17 +270,17 @@ IMPLEMENT_FUNCTION(11, Kahina, chapter1Handler)
Entity::timeCheckSavepoint(kTime1107000, params->param1, kEntityKahina, kEntityMertens, kAction238732837);
if (getProgress().eventMertensKronosInvitation)
- setup_function12();
+ setup_awaitingCath();
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(12, Kahina, function12)
+IMPLEMENT_FUNCTION(12, Kahina, awaitingCath)
switch (savepoint.action) {
default:
break;
case kActionNone:
- Entity::timeCheck(kTime1485000, params->param2, WRAP_SETUP_FUNCTION(Kahina, setup_function13));
+ Entity::timeCheck(kTime1485000, params->param2, WRAP_SETUP_FUNCTION(Kahina, setup_cathDone));
break;
case kActionKnock:
@@ -316,13 +316,13 @@ IMPLEMENT_FUNCTION(12, Kahina, function12)
break;
case kAction137685712:
- setup_function13();
+ setup_cathDone();
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(13, Kahina, function13)
+IMPLEMENT_FUNCTION(13, Kahina, cathDone)
switch (savepoint.action) {
default:
break;
@@ -347,7 +347,7 @@ IMPLEMENT_FUNCTION(13, Kahina, function13)
label_callback:
setCallback(1);
- setup_function15();
+ setup_searchTrain();
break;
case kActionDefault:
@@ -387,7 +387,7 @@ IMPLEMENT_FUNCTION(14, Kahina, function14)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(15, Kahina, function15)
+IMPLEMENT_FUNCTION(15, Kahina, searchTrain)
switch (savepoint.action) {
default:
break;
@@ -554,7 +554,7 @@ IMPLEMENT_FUNCTION(16, Kahina, chapter2)
break;
case kActionNone:
- setup_chapter2Handler();
+ setup_inSeclusionPart2();
break;
case kActionDefault:
@@ -573,7 +573,7 @@ IMPLEMENT_FUNCTION(16, Kahina, chapter2)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(17, Kahina, chapter2Handler)
+IMPLEMENT_FUNCTION(17, Kahina, inSeclusionPart2)
switch (savepoint.action) {
default:
break;
@@ -700,7 +700,7 @@ IMPLEMENT_FUNCTION(18, Kahina, chapter3)
break;
case kActionNone:
- setup_chapter3Handler();
+ setup_beforeConcert();
break;
case kActionDefault:
@@ -724,7 +724,7 @@ IMPLEMENT_FUNCTION_II(19, Kahina, function19, CarIndex, EntityPosition)
case kActionNone:
if (getEvent(kEventAnnaBaggageArgument)) {
- RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_function22);
+ RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_finished);
}
if (getEntities()->updateEntity(kEntityKahina, (CarIndex)params->param1, (EntityPosition)params->param2))
@@ -750,7 +750,7 @@ IMPLEMENT_FUNCTION_II(19, Kahina, function19, CarIndex, EntityPosition)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(20, Kahina, chapter3Handler)
+IMPLEMENT_FUNCTION(20, Kahina, beforeConcert)
switch (savepoint.action) {
default:
break;
@@ -781,7 +781,7 @@ label_callback_2:
if (getEntities()->isInKronosSalon(kEntityPlayer))
getScenes()->loadSceneFromPosition(kCarKronos, 87);
- setup_function21();
+ setup_concert();
break;
}
@@ -917,7 +917,7 @@ label_callback_2:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(21, Kahina, function21)
+IMPLEMENT_FUNCTION(21, Kahina, concert)
switch (savepoint.action) {
default:
break;
@@ -930,7 +930,7 @@ IMPLEMENT_FUNCTION(21, Kahina, function21)
if (params->param6 != kTimeInvalid) {
if (Entity::updateParameterTime((TimeValue)params->param3, (getEntities()->isPlayerPosition(kCarKronos, 80) || getEntities()->isPlayerPosition(kCarKronos, 88)), params->param5, 0)) {
setCallback(2);
- setup_function23();
+ setup_findFirebird();
break;
}
}
@@ -961,10 +961,10 @@ label_callback_2:
if (location == kObjectLocation3 || location == kObjectLocation7) {
setCallback(3);
- setup_function25();
+ setup_searchCath();
} else if (location == kObjectLocation1 || location == kObjectLocation2) {
setCallback(4);
- setup_function26();
+ setup_searchTatiana();
}
}
break;
@@ -997,17 +997,17 @@ label_callback_2:
case kAction92186062:
if (params->param1) {
setCallback(1);
- setup_function23();
+ setup_findFirebird();
}
break;
case kAction134611040:
if (getEvent(kEventConcertLeaveWithBriefcase))
- setup_function24();
+ setup_seekCath();
break;
case kAction137503360:
- setup_function22();
+ setup_finished();
break;
case kAction237555748:
@@ -1017,7 +1017,7 @@ label_callback_2:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(22, Kahina, function22)
+IMPLEMENT_FUNCTION(22, Kahina, finished)
switch (savepoint.action) {
default:
break;
@@ -1028,10 +1028,10 @@ IMPLEMENT_FUNCTION(22, Kahina, function22)
if (ENTITY_PARAM(0, 3) || location == kObjectLocation3 || location == kObjectLocation7) {
setCallback(1);
- setup_function25();
+ setup_searchCath();
} else if (location == kObjectLocation2 || location == kObjectLocation1) {
setCallback(2);
- setup_function26();
+ setup_searchTatiana();
}
}
break;
@@ -1050,7 +1050,7 @@ IMPLEMENT_FUNCTION(22, Kahina, function22)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(23, Kahina, function23)
+IMPLEMENT_FUNCTION(23, Kahina, findFirebird)
switch (savepoint.action) {
default:
break;
@@ -1133,7 +1133,7 @@ IMPLEMENT_FUNCTION(23, Kahina, function23)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(24, Kahina, function24)
+IMPLEMENT_FUNCTION(24, Kahina, seekCath)
switch (savepoint.action) {
default:
break;
@@ -1149,12 +1149,12 @@ IMPLEMENT_FUNCTION(24, Kahina, function24)
if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos))
getSavePoints()->push(kEntityKahina, kEntityKronos, kActionOpenDoor);
else
- setup_function27();
+ setup_killCathAnywhere();
break;
case kActionDefault:
setCallback(1);
- setup_function6(kTime2241000);
+ setup_lookingForCath(kTime2241000);
break;
case kActionCallback:
@@ -1170,12 +1170,12 @@ IMPLEMENT_FUNCTION(24, Kahina, function24)
getProgress().field_44 = 0;
- setup_function22();
+ setup_finished();
} else if (ENTITY_PARAM(0, 1)) {
setCallback(2);
setup_savegame(kSavegameTypeEvent, kEventKahinaGunYellow);
} else {
- setup_function27();
+ setup_killCathAnywhere();
}
break;
@@ -1205,13 +1205,13 @@ IMPLEMENT_FUNCTION(24, Kahina, function24)
getProgress().field_44 = 0;
- setup_function22();
+ setup_finished();
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(25, Kahina, function25)
+IMPLEMENT_FUNCTION(25, Kahina, searchCath)
switch (savepoint.action) {
default:
break;
@@ -1369,7 +1369,7 @@ IMPLEMENT_FUNCTION(25, Kahina, function25)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(26, Kahina, function26)
+IMPLEMENT_FUNCTION(26, Kahina, searchTatiana)
switch (savepoint.action) {
default:
break;
@@ -1470,7 +1470,7 @@ IMPLEMENT_FUNCTION(26, Kahina, function26)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(27, Kahina, function27)
+IMPLEMENT_FUNCTION(27, Kahina, killCathAnywhere)
switch (savepoint.action) {
default:
break;
diff --git a/engines/lastexpress/entities/kahina.h b/engines/lastexpress/entities/kahina.h
index ee9ccf5c81..15c446c53d 100644
--- a/engines/lastexpress/entities/kahina.h
+++ b/engines/lastexpress/entities/kahina.h
@@ -69,7 +69,7 @@ public:
*/
DECLARE_FUNCTION_NOSETUP(updateFromTicks)
- DECLARE_FUNCTION_1(function6, TimeValue timeValue)
+ DECLARE_FUNCTION_1(lookingForCath, TimeValue timeValue)
/**
* Updates the entity
@@ -105,20 +105,16 @@ public:
*/
DECLARE_FUNCTION(chapter1Handler)
- DECLARE_FUNCTION(function12)
- DECLARE_FUNCTION(function13)
+ DECLARE_FUNCTION(awaitingCath)
+ DECLARE_FUNCTION(cathDone)
DECLARE_FUNCTION(function14)
- DECLARE_FUNCTION(function15)
+ DECLARE_FUNCTION(searchTrain)
/**
* Setup Chapter 2
*/
DECLARE_FUNCTION(chapter2)
-
- /**
- * Handle Chapter 2 events
- */
- DECLARE_FUNCTION(chapter2Handler)
+ DECLARE_FUNCTION(inSeclusionPart2)
/**
* Setup Chapter 3
@@ -133,18 +129,14 @@ public:
*/
DECLARE_FUNCTION_2(function19, CarIndex car, EntityPosition entityPosition)
- /**
- * Handle Chapter 3 events
- */
- DECLARE_FUNCTION(chapter3Handler)
-
- DECLARE_FUNCTION(function21)
- DECLARE_FUNCTION(function22)
- DECLARE_FUNCTION(function23)
- DECLARE_FUNCTION(function24)
- DECLARE_FUNCTION(function25)
- DECLARE_FUNCTION(function26)
- DECLARE_FUNCTION(function27)
+ DECLARE_FUNCTION(beforeConcert)
+ DECLARE_FUNCTION(concert)
+ DECLARE_FUNCTION(finished)
+ DECLARE_FUNCTION(findFirebird)
+ DECLARE_FUNCTION(seekCath)
+ DECLARE_FUNCTION(searchCath)
+ DECLARE_FUNCTION(searchTatiana)
+ DECLARE_FUNCTION(killCathAnywhere)
/**
* Setup Chapter 4
diff --git a/engines/lastexpress/entities/kronos.cpp b/engines/lastexpress/entities/kronos.cpp
index 8bf158943b..1fe478fea9 100644
--- a/engines/lastexpress/entities/kronos.cpp
+++ b/engines/lastexpress/entities/kronos.cpp
@@ -70,21 +70,21 @@ Kronos::Kronos(LastExpressEngine *engine) : Entity(engine, kEntityKronos) {
ADD_CALLBACK_FUNCTION(Kronos, updateFromTicks);
ADD_CALLBACK_FUNCTION(Kronos, chapter1);
ADD_CALLBACK_FUNCTION(Kronos, chapter1Handler);
- ADD_CALLBACK_FUNCTION(Kronos, function9);
+ ADD_CALLBACK_FUNCTION(Kronos, greetCath);
ADD_CALLBACK_FUNCTION(Kronos, function10);
ADD_CALLBACK_FUNCTION(Kronos, function11);
ADD_CALLBACK_FUNCTION(Kronos, chapter2);
ADD_CALLBACK_FUNCTION(Kronos, chapter3);
ADD_CALLBACK_FUNCTION(Kronos, chapter3Handler);
ADD_CALLBACK_FUNCTION(Kronos, function15);
- ADD_CALLBACK_FUNCTION(Kronos, function16);
- ADD_CALLBACK_FUNCTION(Kronos, function17);
- ADD_CALLBACK_FUNCTION(Kronos, function18);
- ADD_CALLBACK_FUNCTION(Kronos, function19);
- ADD_CALLBACK_FUNCTION(Kronos, function20);
- ADD_CALLBACK_FUNCTION(Kronos, function21);
- ADD_CALLBACK_FUNCTION(Kronos, function22);
- ADD_CALLBACK_FUNCTION(Kronos, function23);
+ ADD_CALLBACK_FUNCTION(Kronos, visitSalon);
+ ADD_CALLBACK_FUNCTION(Kronos, returnCompartment);
+ ADD_CALLBACK_FUNCTION(Kronos, preConcert);
+ ADD_CALLBACK_FUNCTION(Kronos, startConcert);
+ ADD_CALLBACK_FUNCTION(Kronos, duringConcert);
+ ADD_CALLBACK_FUNCTION(Kronos, afterConcert);
+ ADD_CALLBACK_FUNCTION(Kronos, awaitingCath);
+ ADD_CALLBACK_FUNCTION(Kronos, finished);
ADD_CALLBACK_FUNCTION(Kronos, chapter4);
ADD_CALLBACK_FUNCTION(Kronos, chapter5);
}
@@ -155,13 +155,13 @@ IMPLEMENT_FUNCTION(8, Kronos, chapter1Handler)
break;
case kAction202621266:
- setup_function9();
+ setup_greetCath();
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(9, Kronos, function9)
+IMPLEMENT_FUNCTION(9, Kronos, greetCath)
switch (savepoint.action) {
default:
break;
@@ -294,7 +294,7 @@ IMPLEMENT_FUNCTION(15, Kronos, function15)
case kActionNone:
if (params->param1 && !getEntities()->isInSalon(kEntityBoutarel)) {
if (Entity::updateParameter(params->param2, getState()->timeTicks, 75)) {
- setup_function16();
+ setup_visitSalon();
break;
}
}
@@ -311,13 +311,13 @@ IMPLEMENT_FUNCTION(15, Kronos, function15)
params->param3 = kTimeInvalid;
if (getEntities()->isInSalon(kEntityPlayer)) {
- setup_function16();
+ setup_visitSalon();
} else {
getSavePoints()->push(kEntityKronos, kEntityAnna, kAction101169422);
getSavePoints()->push(kEntityKronos, kEntityTatiana, kAction101169422);
getSavePoints()->push(kEntityKronos, kEntityAbbot, kAction101169422);
- setup_function18();
+ setup_preConcert();
}
}
break;
@@ -333,7 +333,7 @@ IMPLEMENT_FUNCTION(15, Kronos, function15)
case kActionDrawScene:
if (params->param1 && getEntities()->isPlayerPosition(kCarRestaurant, 51) && !getEntities()->isInSalon(kEntityBoutarel))
- setup_function16();
+ setup_visitSalon();
else
params->param1 = getEntities()->isPlayerPosition(kCarRestaurant, 60)
|| getEntities()->isPlayerPosition(kCarRestaurant, 59)
@@ -345,7 +345,7 @@ IMPLEMENT_FUNCTION(15, Kronos, function15)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(16, Kronos, function16)
+IMPLEMENT_FUNCTION(16, Kronos, visitSalon)
switch (savepoint.action) {
default:
break;
@@ -363,14 +363,14 @@ IMPLEMENT_FUNCTION(16, Kronos, function16)
getSavePoints()->push(kEntityKronos, kEntityAbbot, kAction101169422);
getScenes()->loadSceneFromPosition(kCarRestaurant, 60);
- setup_function17();
+ setup_returnCompartment();
}
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(17, Kronos, function17)
+IMPLEMENT_FUNCTION(17, Kronos, returnCompartment)
switch (savepoint.action) {
default:
break;
@@ -386,13 +386,13 @@ IMPLEMENT_FUNCTION(17, Kronos, function17)
case kActionCallback:
if (getCallback() == 1)
- setup_function18();
+ setup_preConcert();
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(18, Kronos, function18)
+IMPLEMENT_FUNCTION(18, Kronos, preConcert)
switch (savepoint.action) {
default:
break;
@@ -405,7 +405,7 @@ IMPLEMENT_FUNCTION(18, Kronos, function18)
params->param2 = 1;
}
- if (!Entity::timeCheck(kTime2106000, params->param3, WRAP_SETUP_FUNCTION(Kronos, setup_function19))) {
+ if (!Entity::timeCheck(kTime2106000, params->param3, WRAP_SETUP_FUNCTION(Kronos, setup_startConcert))) {
if (params->param1 && getEntities()->isInKronosSanctum(kEntityPlayer)) {
setCallback(1);
setup_savegame(kSavegameTypeEvent, kEventKahinaPunchSuite4);
@@ -429,7 +429,7 @@ IMPLEMENT_FUNCTION(18, Kronos, function18)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(19, Kronos, function19)
+IMPLEMENT_FUNCTION(19, Kronos, startConcert)
switch (savepoint.action) {
default:
break;
@@ -465,7 +465,7 @@ IMPLEMENT_FUNCTION(19, Kronos, function19)
RESET_ENTITY_STATE(kEntityAnna, Anna, setup_concert);
RESET_ENTITY_STATE(kEntityTatiana, Tatiana, setup_function35);
- setup_function20();
+ setup_duringConcert();
break;
}
break;
@@ -473,7 +473,7 @@ IMPLEMENT_FUNCTION(19, Kronos, function19)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(20, Kronos, function20)
+IMPLEMENT_FUNCTION(20, Kronos, duringConcert)
switch (savepoint.action) {
default:
break;
@@ -585,7 +585,7 @@ IMPLEMENT_FUNCTION(20, Kronos, function20)
getSound()->playSound(kEntityPlayer, "BUMP");
getScenes()->loadSceneFromPosition(kCarGreenSleeping, 26);
- setup_function21();
+ setup_afterConcert();
break;
}
@@ -602,7 +602,7 @@ IMPLEMENT_FUNCTION(20, Kronos, function20)
break;
}
- setup_function21();
+ setup_afterConcert();
break;
case kActionOpenDoor:
@@ -668,7 +668,7 @@ IMPLEMENT_FUNCTION(20, Kronos, function20)
getData()->entityPosition = kPosition_6000;
getAction()->playAnimation(kEventConcertLeaveWithBriefcase);
- RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_function21);
+ RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_concert);
getScenes()->loadSceneFromPosition(kCarKronos, 87);
break;
@@ -678,7 +678,7 @@ IMPLEMENT_FUNCTION(20, Kronos, function20)
getSound()->playSound(kEntityPlayer, "BUMP");
getScenes()->loadSceneFromPosition(kCarGreenSleeping, 26);
- setup_function21();
+ setup_afterConcert();
break;
}
break;
@@ -686,7 +686,7 @@ IMPLEMENT_FUNCTION(20, Kronos, function20)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(21, Kronos, function21)
+IMPLEMENT_FUNCTION(21, Kronos, afterConcert)
switch (savepoint.action) {
default:
break;
@@ -703,7 +703,7 @@ IMPLEMENT_FUNCTION(21, Kronos, function21)
getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorNormal, kCursorNormal);
getSavePoints()->push(kEntityKronos, kEntityRebecca, kAction191668032);
if (!getEvent(kEventConcertLeaveWithBriefcase))
- setup_function22();
+ setup_awaitingCath();
break;
case kActionCallback:
@@ -722,13 +722,13 @@ IMPLEMENT_FUNCTION(21, Kronos, function21)
break;
case kAction235599361:
- setup_function22();
+ setup_awaitingCath();
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(22, Kronos, function22)
+IMPLEMENT_FUNCTION(22, Kronos, awaitingCath)
switch (savepoint.action) {
default:
break;
@@ -791,7 +791,7 @@ IMPLEMENT_FUNCTION(22, Kronos, function22)
getInventory()->removeItem(kItemFirebird);
getInventory()->removeItem(kItemScarf);
- setup_function23();
+ setup_finished();
break;
case 2:
@@ -800,7 +800,7 @@ IMPLEMENT_FUNCTION(22, Kronos, function22)
getInventory()->removeItem(kItemFirebird);
getInventory()->get(kItemFirebird)->location = kObjectLocation5;
- setup_function23();
+ setup_finished();
break;
case 3:
@@ -809,7 +809,7 @@ IMPLEMENT_FUNCTION(22, Kronos, function22)
getAction()->playAnimation(kEventKronosBringEgg);
getScenes()->loadSceneFromPosition(kCarKronos, 87);
getInventory()->addItem(kItemBriefcase);
- setup_function23();
+ setup_finished();
break;
case 4:
@@ -835,12 +835,12 @@ IMPLEMENT_FUNCTION(22, Kronos, function22)
break;
case kAction138085344:
- setup_function23();
+ setup_finished();
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(23, Kronos, function23)
+IMPLEMENT_FUNCTION(23, Kronos, finished)
switch (savepoint.action) {
default:
break;
diff --git a/engines/lastexpress/entities/kronos.h b/engines/lastexpress/entities/kronos.h
index 48da419a6e..00564b8ce5 100644
--- a/engines/lastexpress/entities/kronos.h
+++ b/engines/lastexpress/entities/kronos.h
@@ -89,7 +89,7 @@ public:
*/
DECLARE_FUNCTION(chapter1Handler)
- DECLARE_FUNCTION(function9)
+ DECLARE_FUNCTION(greetCath)
DECLARE_FUNCTION(function10)
DECLARE_FUNCTION(function11)
@@ -109,14 +109,14 @@ public:
DECLARE_FUNCTION(chapter3Handler)
DECLARE_FUNCTION(function15)
- DECLARE_FUNCTION(function16)
- DECLARE_FUNCTION(function17)
- DECLARE_FUNCTION(function18)
- DECLARE_FUNCTION(function19)
- DECLARE_FUNCTION(function20)
- DECLARE_FUNCTION(function21)
- DECLARE_FUNCTION(function22)
- DECLARE_FUNCTION(function23)
+ DECLARE_FUNCTION(visitSalon)
+ DECLARE_FUNCTION(returnCompartment)
+ DECLARE_FUNCTION(preConcert)
+ DECLARE_FUNCTION(startConcert)
+ DECLARE_FUNCTION(duringConcert)
+ DECLARE_FUNCTION(afterConcert)
+ DECLARE_FUNCTION(awaitingCath)
+ DECLARE_FUNCTION(finished)
/**
* Setup Chapter 4
diff --git a/engines/lastexpress/entities/max.cpp b/engines/lastexpress/entities/max.cpp
index 1056e7fd7a..d75b6af7f5 100644
--- a/engines/lastexpress/entities/max.cpp
+++ b/engines/lastexpress/entities/max.cpp
@@ -42,16 +42,16 @@ Max::Max(LastExpressEngine *engine) : Entity(engine, kEntityMax) {
ADD_CALLBACK_FUNCTION(Max, draw);
ADD_CALLBACK_FUNCTION(Max, enterExitCompartment);
ADD_CALLBACK_FUNCTION(Max, savegame);
- ADD_CALLBACK_FUNCTION(Max, chapter12_handler);
- ADD_CALLBACK_FUNCTION(Max, function7);
- ADD_CALLBACK_FUNCTION(Max, chapter4Handler);
+ ADD_CALLBACK_FUNCTION(Max, withAnna);
+ ADD_CALLBACK_FUNCTION(Max, guardingCompartment);
+ ADD_CALLBACK_FUNCTION(Max, inCageFriendly);
ADD_CALLBACK_FUNCTION(Max, function9);
ADD_CALLBACK_FUNCTION(Max, chapter1);
ADD_CALLBACK_FUNCTION(Max, chapter2);
ADD_CALLBACK_FUNCTION(Max, chapter3);
ADD_CALLBACK_FUNCTION(Max, chapter3Handler);
- ADD_CALLBACK_FUNCTION(Max, freeFromCage);
- ADD_CALLBACK_FUNCTION(Max, function15);
+ ADD_CALLBACK_FUNCTION(Max, inCageMad);
+ ADD_CALLBACK_FUNCTION(Max, letMeIn);
ADD_CALLBACK_FUNCTION(Max, chapter4);
ADD_CALLBACK_FUNCTION(Max, function17);
ADD_CALLBACK_FUNCTION(Max, chapter5);
@@ -83,7 +83,7 @@ IMPLEMENT_FUNCTION_II(5, Max, savegame, SavegameType, uint32)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(6, Max, chapter12_handler)
+IMPLEMENT_FUNCTION(6, Max, withAnna)
switch (savepoint.action) {
default:
break;
@@ -105,7 +105,7 @@ IMPLEMENT_FUNCTION(6, Max, chapter12_handler)
case kAction71277948:
setCallback(1);
- setup_function7();
+ setup_guardingCompartment();
break;
case kAction158007856:
@@ -118,7 +118,7 @@ IMPLEMENT_FUNCTION(6, Max, chapter12_handler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(7, Max, function7)
+IMPLEMENT_FUNCTION(7, Max, guardingCompartment)
switch (savepoint.action) {
default:
break;
@@ -208,7 +208,7 @@ IMPLEMENT_FUNCTION(7, Max, function7)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(8, Max, chapter4Handler)
+IMPLEMENT_FUNCTION(8, Max, inCageFriendly)
switch (savepoint.action) {
default:
break;
@@ -296,7 +296,7 @@ IMPLEMENT_FUNCTION(9, Max, function9)
setup_functions:
if (getProgress().chapter == kChapter3)
- setup_function15();
+ setup_letMeIn();
if (getProgress().chapter == kChapter4)
setup_function17();
@@ -324,7 +324,7 @@ IMPLEMENT_FUNCTION(10, Max, chapter1)
break;
case kActionNone:
- Entity::timeCheck(kTimeChapter1, params->param1, WRAP_SETUP_FUNCTION(Max, setup_chapter12_handler));
+ Entity::timeCheck(kTimeChapter1, params->param1, WRAP_SETUP_FUNCTION(Max, setup_withAnna));
break;
case kActionDefault:
@@ -343,7 +343,7 @@ IMPLEMENT_FUNCTION(11, Max, chapter2)
break;
case kActionNone:
- setup_chapter12_handler();
+ setup_withAnna();
break;
case kActionDefault:
@@ -413,7 +413,7 @@ IMPLEMENT_FUNCTION(13, Max, chapter3Handler)
case kAction71277948:
setCallback(1);
- setup_function7();
+ setup_guardingCompartment();
break;
case kAction122358304:
@@ -421,7 +421,7 @@ IMPLEMENT_FUNCTION(13, Max, chapter3Handler)
break;
case kActionMaxFreeFromCage:
- setup_freeFromCage();
+ setup_inCageMad();
break;
case kAction158007856:
@@ -437,7 +437,7 @@ IMPLEMENT_FUNCTION(13, Max, chapter3Handler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(14, Max, freeFromCage)
+IMPLEMENT_FUNCTION(14, Max, inCageMad)
switch (savepoint.action) {
default:
break;
@@ -504,7 +504,7 @@ IMPLEMENT_FUNCTION(14, Max, freeFromCage)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(15, Max, function15)
+IMPLEMENT_FUNCTION(15, Max, letMeIn)
switch (savepoint.action) {
default:
break;
@@ -551,7 +551,7 @@ IMPLEMENT_FUNCTION(15, Max, function15)
case kActionMaxFreeFromCage:
getEntities()->exitCompartment(kEntityMax, kObjectCompartmentF, true);
- setup_chapter4Handler();
+ setup_inCageFriendly();
break;
}
IMPLEMENT_FUNCTION_END
@@ -563,7 +563,7 @@ IMPLEMENT_FUNCTION(16, Max, chapter4)
break;
case kActionNone:
- setup_chapter4Handler();
+ setup_inCageFriendly();
break;
case kActionDefault:
@@ -606,7 +606,7 @@ IMPLEMENT_FUNCTION(17, Max, function17)
case kActionMaxFreeFromCage:
getEntities()->exitCompartment(kEntityMax, kObjectCompartmentF, true);
- setup_chapter4Handler();
+ setup_inCageFriendly();
break;
}
IMPLEMENT_FUNCTION_END
diff --git a/engines/lastexpress/entities/max.h b/engines/lastexpress/entities/max.h
index 7b7780742b..e12b4b6dad 100644
--- a/engines/lastexpress/entities/max.h
+++ b/engines/lastexpress/entities/max.h
@@ -70,18 +70,9 @@ public:
*/
DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param)
- /**
- * Handle Chapter 1 & 2 events
- */
- DECLARE_FUNCTION(chapter12_handler)
-
- DECLARE_FUNCTION(function7)
-
- /**
- * Handle Chapter 4 events
- */
- DECLARE_FUNCTION(chapter4Handler)
-
+ DECLARE_FUNCTION(withAnna)
+ DECLARE_FUNCTION(guardingCompartment)
+ DECLARE_FUNCTION(inCageFriendly)
DECLARE_FUNCTION(function9)
/**
@@ -104,8 +95,8 @@ public:
*/
DECLARE_FUNCTION(chapter3Handler)
- DECLARE_FUNCTION(freeFromCage)
- DECLARE_FUNCTION(function15)
+ DECLARE_FUNCTION(inCageMad)
+ DECLARE_FUNCTION(letMeIn)
/**
* Setup Chapter 4
diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp
index 601187b672..90a397c7cb 100644
--- a/engines/lastexpress/entities/milos.cpp
+++ b/engines/lastexpress/entities/milos.cpp
@@ -722,7 +722,7 @@ IMPLEMENT_FUNCTION(15, Milos, chapter1Handler)
break;
case kActionNone:
- Entity::timeCheckSavepoint(kTime1071000, params->param3, kEntityMilos, kEntityServers1, kAction223002560);
+ Entity::timeCheckSavepoint(kTime1071000, params->param3, kEntityMilos, kEntityWaiter2, kAction223002560);
if (getState()->time > kTime1089000 && getEntities()->isSomebodyInsideRestaurantOrSalon()) {
setup_function16();
@@ -801,7 +801,7 @@ IMPLEMENT_FUNCTION(16, Milos, function16)
break;
case 1:
- getSavePoints()->push(kEntityMilos, kEntityServers1, kAction269485588);
+ getSavePoints()->push(kEntityMilos, kEntityWaiter2, kAction269485588);
getSavePoints()->push(kEntityMilos, kEntityIvo, kAction125242096);
getEntities()->drawSequenceRight(kEntityMilos, "807DS");
if (getEntities()->isInRestaurant(kEntityPlayer))
diff --git a/engines/lastexpress/entities/pascale.cpp b/engines/lastexpress/entities/pascale.cpp
index b6356a0acb..24b7f0409b 100644
--- a/engines/lastexpress/entities/pascale.cpp
+++ b/engines/lastexpress/entities/pascale.cpp
@@ -46,29 +46,29 @@ Pascale::Pascale(LastExpressEngine *engine) : Entity(engine, kEntityPascale) {
ADD_CALLBACK_FUNCTION(Pascale, welcomeSophieAndRebecca);
ADD_CALLBACK_FUNCTION(Pascale, sitSophieAndRebecca);
ADD_CALLBACK_FUNCTION(Pascale, welcomeCath);
- ADD_CALLBACK_FUNCTION(Pascale, function11);
+ ADD_CALLBACK_FUNCTION(Pascale, seatCath);
ADD_CALLBACK_FUNCTION(Pascale, chapter1);
- ADD_CALLBACK_FUNCTION(Pascale, getMessageFromAugustToTyler);
- ADD_CALLBACK_FUNCTION(Pascale, sitAnna);
- ADD_CALLBACK_FUNCTION(Pascale, welcomeAnna);
- ADD_CALLBACK_FUNCTION(Pascale, serveTatianaVassili);
- ADD_CALLBACK_FUNCTION(Pascale, chapter1Handler);
+ ADD_CALLBACK_FUNCTION(Pascale, greetAugust);
+ ADD_CALLBACK_FUNCTION(Pascale, seatAnna);
+ ADD_CALLBACK_FUNCTION(Pascale, greetAnna);
+ ADD_CALLBACK_FUNCTION(Pascale, greetTatiana);
+ ADD_CALLBACK_FUNCTION(Pascale, servingDinner);
ADD_CALLBACK_FUNCTION(Pascale, function18);
ADD_CALLBACK_FUNCTION(Pascale, function19);
ADD_CALLBACK_FUNCTION(Pascale, chapter2);
ADD_CALLBACK_FUNCTION(Pascale, chapter3);
ADD_CALLBACK_FUNCTION(Pascale, chapter3Handler);
- ADD_CALLBACK_FUNCTION(Pascale, function23);
+ ADD_CALLBACK_FUNCTION(Pascale, abbotSeatMe3);
ADD_CALLBACK_FUNCTION(Pascale, welcomeAbbot);
ADD_CALLBACK_FUNCTION(Pascale, chapter4);
ADD_CALLBACK_FUNCTION(Pascale, chapter4Handler);
- ADD_CALLBACK_FUNCTION(Pascale, function27);
- ADD_CALLBACK_FUNCTION(Pascale, messageFromAnna);
- ADD_CALLBACK_FUNCTION(Pascale, function29);
- ADD_CALLBACK_FUNCTION(Pascale, function30);
+ ADD_CALLBACK_FUNCTION(Pascale, meetCoudert);
+ ADD_CALLBACK_FUNCTION(Pascale, tellAugust);
+ ADD_CALLBACK_FUNCTION(Pascale, walkDownTrain);
+ ADD_CALLBACK_FUNCTION(Pascale, walkUpTrain);
ADD_CALLBACK_FUNCTION(Pascale, chapter5);
ADD_CALLBACK_FUNCTION(Pascale, chapter5Handler);
- ADD_CALLBACK_FUNCTION(Pascale, function33);
+ ADD_CALLBACK_FUNCTION(Pascale, hiding);
ADD_NULL_FUNCTION();
}
@@ -118,6 +118,7 @@ IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(8, Pascale, welcomeSophieAndRebecca)
+ // Welcomes Sophie And Rebecca
switch (savepoint.action) {
default:
break;
@@ -244,7 +245,7 @@ IMPLEMENT_FUNCTION(10, Pascale, welcomeCath)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(11, Pascale, function11)
+IMPLEMENT_FUNCTION(11, Pascale, seatCath)
switch (savepoint.action) {
default:
break;
@@ -295,7 +296,7 @@ IMPLEMENT_FUNCTION(12, Pascale, chapter1)
break;
case kActionNone:
- setup_chapter1Handler();
+ setup_servingDinner();
break;
case kActionDefault:
@@ -319,7 +320,7 @@ IMPLEMENT_FUNCTION(12, Pascale, chapter1)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(13, Pascale, getMessageFromAugustToTyler)
+IMPLEMENT_FUNCTION(13, Pascale, greetAugust)
switch (savepoint.action) {
default:
break;
@@ -372,7 +373,7 @@ IMPLEMENT_FUNCTION(13, Pascale, getMessageFromAugustToTyler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(14, Pascale, sitAnna)
+IMPLEMENT_FUNCTION(14, Pascale, seatAnna)
switch (savepoint.action) {
default:
break;
@@ -394,7 +395,7 @@ IMPLEMENT_FUNCTION(14, Pascale, sitAnna)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(15, Pascale, welcomeAnna)
+IMPLEMENT_FUNCTION(15, Pascale, greetAnna)
switch (savepoint.action) {
default:
break;
@@ -416,7 +417,7 @@ IMPLEMENT_FUNCTION(15, Pascale, welcomeAnna)
getSound()->playSound(kEntityPascale, "ANN1047");
setCallback(2);
- setup_sitAnna();
+ setup_seatAnna();
break;
case 2:
@@ -439,7 +440,7 @@ IMPLEMENT_FUNCTION(15, Pascale, welcomeAnna)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(16, Pascale, serveTatianaVassili)
+IMPLEMENT_FUNCTION(16, Pascale, greetTatiana)
switch (savepoint.action) {
default:
break;
@@ -492,7 +493,7 @@ IMPLEMENT_FUNCTION(16, Pascale, serveTatianaVassili)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(17, Pascale, chapter1Handler)
+IMPLEMENT_FUNCTION(17, Pascale, servingDinner)
switch (savepoint.action) {
default:
break;
@@ -521,28 +522,28 @@ switch (savepoint.action) {
if (params->param1 && !params->param2 && getEntities()->isPlayerPosition(kCarRestaurant, 61)) {
setCallback(1);
- setup_function11();
+ setup_seatCath();
break;
}
label_callback1:
if (ENTITY_PARAM(0, 1) && !ENTITY_PARAM(1, 3)) {
setCallback(2);
- setup_getMessageFromAugustToTyler();
+ setup_greetAugust();
break;
}
label_callback2:
if (ENTITY_PARAM(0, 3)) {
setCallback(3);
- setup_serveTatianaVassili();
+ setup_greetTatiana();
break;
}
label_callback3:
if (ENTITY_PARAM(0, 2)) {
setCallback(4);
- setup_welcomeAnna();
+ setup_greetAnna();
break;
}
@@ -584,8 +585,8 @@ IMPLEMENT_FUNCTION(18, Pascale, function18)
if (getState()->time > kTime1242000 && !params->param1) {
params->param1 = 1;
- getSavePoints()->push(kEntityPascale, kEntityServers0, kAction101632192);
- getSavePoints()->push(kEntityPascale, kEntityServers1, kAction101632192);
+ getSavePoints()->push(kEntityPascale, kEntityWaiter1, kAction101632192);
+ getSavePoints()->push(kEntityPascale, kEntityWaiter2, kAction101632192);
getSavePoints()->push(kEntityPascale, kEntityCooks, kAction101632192);
getSavePoints()->push(kEntityPascale, kEntityVerges, kAction101632192);
@@ -674,7 +675,7 @@ IMPLEMENT_FUNCTION(22, Pascale, chapter3Handler)
if (ENTITY_PARAM(0, 7)) {
setCallback(1);
- setup_function23();
+ setup_abbotSeatMe3();
break;
}
@@ -693,7 +694,7 @@ label_callback:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(23, Pascale, function23)
+IMPLEMENT_FUNCTION(23, Pascale, abbotSeatMe3)
switch (savepoint.action) {
default:
break;
@@ -806,7 +807,7 @@ IMPLEMENT_FUNCTION(26, Pascale, chapter4Handler)
if (getEntities()->isSomebodyInsideRestaurantOrSalon()) {
if (ENTITY_PARAM(0, 8)) {
setCallback(1);
- setup_function27();
+ setup_meetCoudert();
break;
}
@@ -820,7 +821,7 @@ label_callback1:
if (params->param3 < getState()->time) {
params->param5 = kTimeInvalid;
setCallback(2);
- setup_messageFromAnna();
+ setup_tellAugust();
break;
}
@@ -830,7 +831,7 @@ label_callback1:
if (params->param5 < getState()->time) {
params->param5 = kTimeInvalid;
setCallback(2);
- setup_messageFromAnna();
+ setup_tellAugust();
break;
}
}
@@ -839,7 +840,7 @@ label_callback1:
label_callback2:
if (params->param1 && !params->param2 && getEntities()->isPlayerPosition(kCarRestaurant, 61)) {
setCallback(3);
- setup_function11();
+ setup_seatCath();
break;
}
}
@@ -906,7 +907,7 @@ label_callback3:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(27, Pascale, function27)
+IMPLEMENT_FUNCTION(27, Pascale, meetCoudert)
switch (savepoint.action) {
default:
break;
@@ -920,7 +921,7 @@ IMPLEMENT_FUNCTION(27, Pascale, function27)
case kActionDefault:
setCallback(1);
- setup_function29();
+ setup_walkDownTrain();
break;
case kActionCallback:
@@ -941,7 +942,7 @@ IMPLEMENT_FUNCTION(27, Pascale, function27)
case 3:
setCallback(4);
- setup_function30();
+ setup_walkUpTrain();
break;
case 4:
@@ -959,7 +960,8 @@ IMPLEMENT_FUNCTION(27, Pascale, function27)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(28, Pascale, messageFromAnna)
+IMPLEMENT_FUNCTION(28, Pascale, tellAugust)
+ // Tell August the message from Anna
switch (savepoint.action) {
default:
break;
@@ -1005,7 +1007,7 @@ IMPLEMENT_FUNCTION(28, Pascale, messageFromAnna)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(29, Pascale, function29)
+IMPLEMENT_FUNCTION(29, Pascale, walkDownTrain)
switch (savepoint.action) {
default:
break;
@@ -1043,7 +1045,7 @@ IMPLEMENT_FUNCTION(29, Pascale, function29)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(30, Pascale, function30)
+IMPLEMENT_FUNCTION(30, Pascale, walkUpTrain)
switch (savepoint.action) {
default:
break;
@@ -1104,11 +1106,11 @@ IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(32, Pascale, chapter5Handler)
if (savepoint.action == kActionProceedChapter5)
- setup_function33();
+ setup_hiding();
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(33, Pascale, function33)
+IMPLEMENT_FUNCTION(33, Pascale, hiding)
switch (savepoint.action) {
default:
break;
diff --git a/engines/lastexpress/entities/pascale.h b/engines/lastexpress/entities/pascale.h
index 1b7777dec9..c8df7587ae 100644
--- a/engines/lastexpress/entities/pascale.h
+++ b/engines/lastexpress/entities/pascale.h
@@ -88,22 +88,22 @@ public:
DECLARE_FUNCTION(welcomeSophieAndRebecca)
DECLARE_FUNCTION(sitSophieAndRebecca)
DECLARE_FUNCTION(welcomeCath)
- DECLARE_FUNCTION(function11)
+ DECLARE_FUNCTION(seatCath)
/**
* Setup Chapter 1
*/
DECLARE_FUNCTION(chapter1)
- DECLARE_FUNCTION(getMessageFromAugustToTyler)
- DECLARE_FUNCTION(sitAnna)
- DECLARE_FUNCTION(welcomeAnna)
- DECLARE_FUNCTION(serveTatianaVassili)
+ DECLARE_FUNCTION(greetAugust)
+ DECLARE_FUNCTION(seatAnna)
+ DECLARE_FUNCTION(greetAnna)
+ DECLARE_FUNCTION(greetTatiana)
/**
* Handle Chapter 1 events
*/
- DECLARE_FUNCTION(chapter1Handler)
+ DECLARE_FUNCTION(servingDinner)
DECLARE_FUNCTION(function18)
DECLARE_FUNCTION(function19)
@@ -123,7 +123,7 @@ public:
*/
DECLARE_FUNCTION(chapter3Handler)
- DECLARE_FUNCTION(function23)
+ DECLARE_FUNCTION(abbotSeatMe3)
DECLARE_FUNCTION(welcomeAbbot)
/**
@@ -136,10 +136,10 @@ public:
*/
DECLARE_FUNCTION(chapter4Handler)
- DECLARE_FUNCTION(function27)
- DECLARE_FUNCTION(messageFromAnna)
- DECLARE_FUNCTION(function29)
- DECLARE_FUNCTION(function30)
+ DECLARE_FUNCTION(meetCoudert)
+ DECLARE_FUNCTION(tellAugust)
+ DECLARE_FUNCTION(walkDownTrain)
+ DECLARE_FUNCTION(walkUpTrain)
/**
* Setup Chapter 5
@@ -151,7 +151,7 @@ public:
*/
DECLARE_FUNCTION(chapter5Handler)
- DECLARE_FUNCTION(function33)
+ DECLARE_FUNCTION(hiding)
DECLARE_NULL_FUNCTION()
};
diff --git a/engines/lastexpress/entities/rebecca.cpp b/engines/lastexpress/entities/rebecca.cpp
index 05211663bd..40175ad8c4 100644
--- a/engines/lastexpress/entities/rebecca.cpp
+++ b/engines/lastexpress/entities/rebecca.cpp
@@ -437,7 +437,7 @@ IMPLEMENT_FUNCTION(19, Rebecca, function19)
break;
case 2:
- getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction337548856);
+ getSavePoints()->push(kEntityRebecca, kEntityWaiter1, kAction337548856);
getEntities()->drawSequenceRight(kEntityRebecca, "810DS");
if (getEntities()->isInRestaurant(kEntityPlayer))
getEntities()->updateFrame(kEntityRebecca);
@@ -850,7 +850,7 @@ IMPLEMENT_FUNCTION(24, Rebecca, function24)
break;
case kActionNone:
- Entity::timeCheckSavepoint(kTime1134000, params->param2, kEntityRebecca, kEntityServers0, kAction223712416);
+ Entity::timeCheckSavepoint(kTime1134000, params->param2, kEntityRebecca, kEntityWaiter1, kAction223712416);
if (!params->param1)
break;
@@ -920,7 +920,7 @@ IMPLEMENT_FUNCTION(24, Rebecca, function24)
break;
case 8:
- getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction136702400);
+ getSavePoints()->push(kEntityRebecca, kEntityWaiter1, kAction136702400);
getEntities()->drawSequenceLeft(kEntityRebecca, "012G");
params->param1 = 1;
break;
@@ -928,7 +928,7 @@ IMPLEMENT_FUNCTION(24, Rebecca, function24)
break;
case kAction123712592:
- getEntities()->drawSequenceLeft(kEntityServers0, "BLANK");
+ getEntities()->drawSequenceLeft(kEntityWaiter1, "BLANK");
getEntities()->drawSequenceLeft(kEntityRebecca, "012E");
setCallback(8);
@@ -1244,7 +1244,7 @@ IMPLEMENT_FUNCTION(34, Rebecca, function34)
params->param2 = kTimeInvalid;
- getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction223712416);
+ getSavePoints()->push(kEntityRebecca, kEntityWaiter1, kAction223712416);
}
Entity::timeCheckCallback(kTime2052000, params->param3, 1, WRAP_SETUP_FUNCTION(Rebecca, setup_function19));
@@ -1280,7 +1280,7 @@ IMPLEMENT_FUNCTION(34, Rebecca, function34)
break;
case 4:
- getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction136702400);
+ getSavePoints()->push(kEntityRebecca, kEntityWaiter1, kAction136702400);
getEntities()->drawSequenceLeft(kEntityRebecca, "012G");
params->param1 = 1;
break;
@@ -1288,7 +1288,7 @@ IMPLEMENT_FUNCTION(34, Rebecca, function34)
break;
case kAction123712592:
- getEntities()->drawSequenceLeft(kEntityServers0, "BLANK");
+ getEntities()->drawSequenceLeft(kEntityWaiter1, "BLANK");
getSound()->playSound(kEntityRebecca, "Reb3003");
setCallback(4);
@@ -1624,7 +1624,7 @@ IMPLEMENT_FUNCTION(44, Rebecca, function44)
params->param3 = kTimeInvalid;
- getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction223712416);
+ getSavePoints()->push(kEntityRebecca, kEntityWaiter1, kAction223712416);
}
label_next:
@@ -1684,7 +1684,7 @@ label_callback_2:
break;
case 4:
- getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction136702400);
+ getSavePoints()->push(kEntityRebecca, kEntityWaiter1, kAction136702400);
getEntities()->drawSequenceLeft(kEntityRebecca, "012G");
params->param2 = 1;
break;
diff --git a/engines/lastexpress/entities/tatiana.cpp b/engines/lastexpress/entities/tatiana.cpp
index c6788fd4b2..951e89d595 100644
--- a/engines/lastexpress/entities/tatiana.cpp
+++ b/engines/lastexpress/entities/tatiana.cpp
@@ -507,7 +507,7 @@ IMPLEMENT_FUNCTION(20, Tatiana, function20)
case 2:
getEntities()->updatePositionExit(kEntityTatiana, kCarRestaurant, 67);
- getSavePoints()->push(kEntityTatiana, kEntityServers0, kAction188893625);
+ getSavePoints()->push(kEntityTatiana, kEntityWaiter1, kAction188893625);
setCallback(3);
setup_function18();
@@ -917,7 +917,7 @@ IMPLEMENT_FUNCTION(29, Tatiana, function29)
case 2:
getEntities()->updatePositionExit(kEntityTatiana, kCarRestaurant, 63);
- getSavePoints()->push(kEntityTatiana, kEntityServers1, kAction302203328);
+ getSavePoints()->push(kEntityTatiana, kEntityWaiter2, kAction302203328);
getEntities()->drawSequenceRight(kEntityTatiana, "805DS");
if (getEntities()->isInRestaurant(kEntityPlayer))
diff --git a/engines/lastexpress/entities/servers0.cpp b/engines/lastexpress/entities/waiter1.cpp
index 590efa7157..80ec471f1b 100644
--- a/engines/lastexpress/entities/servers0.cpp
+++ b/engines/lastexpress/entities/waiter1.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "lastexpress/entities/servers0.h"
+#include "lastexpress/entities/waiter1.h"
#include "lastexpress/game/entities.h"
#include "lastexpress/game/logic.h"
@@ -39,69 +39,69 @@ namespace LastExpress {
break; \
}
-Servers0::Servers0(LastExpressEngine *engine) : Entity(engine, kEntityServers0) {
- ADD_CALLBACK_FUNCTION(Servers0, callSavepoint);
- ADD_CALLBACK_FUNCTION(Servers0, updateFromTime);
- ADD_CALLBACK_FUNCTION(Servers0, draw);
- ADD_CALLBACK_FUNCTION(Servers0, updatePosition);
- ADD_CALLBACK_FUNCTION(Servers0, callbackActionOnDirection);
- ADD_CALLBACK_FUNCTION(Servers0, playSound);
- ADD_CALLBACK_FUNCTION(Servers0, function7);
- ADD_CALLBACK_FUNCTION(Servers0, function8);
- ADD_CALLBACK_FUNCTION(Servers0, function9);
- ADD_CALLBACK_FUNCTION(Servers0, function10);
- ADD_CALLBACK_FUNCTION(Servers0, chapter1);
- ADD_CALLBACK_FUNCTION(Servers0, function12);
- ADD_CALLBACK_FUNCTION(Servers0, function13);
- ADD_CALLBACK_FUNCTION(Servers0, function14);
- ADD_CALLBACK_FUNCTION(Servers0, function15);
- ADD_CALLBACK_FUNCTION(Servers0, function16);
- ADD_CALLBACK_FUNCTION(Servers0, function17);
- ADD_CALLBACK_FUNCTION(Servers0, function18);
- ADD_CALLBACK_FUNCTION(Servers0, function19);
- ADD_CALLBACK_FUNCTION(Servers0, chapter1Handler);
- ADD_CALLBACK_FUNCTION(Servers0, function21);
- ADD_CALLBACK_FUNCTION(Servers0, function22);
- ADD_CALLBACK_FUNCTION(Servers0, chapter2);
- ADD_CALLBACK_FUNCTION(Servers0, chapter2Handler);
- ADD_CALLBACK_FUNCTION(Servers0, function25);
- ADD_CALLBACK_FUNCTION(Servers0, function26);
- ADD_CALLBACK_FUNCTION(Servers0, chapter3);
- ADD_CALLBACK_FUNCTION(Servers0, chapter3Handler);
- ADD_CALLBACK_FUNCTION(Servers0, augustAnnaDateOrder);
- ADD_CALLBACK_FUNCTION(Servers0, function30);
- ADD_CALLBACK_FUNCTION(Servers0, chapter4);
- ADD_CALLBACK_FUNCTION(Servers0, chapter4Handler);
- ADD_CALLBACK_FUNCTION(Servers0, augustOrderSteak);
- ADD_CALLBACK_FUNCTION(Servers0, augustServeDuck);
- ADD_CALLBACK_FUNCTION(Servers0, function35);
- ADD_CALLBACK_FUNCTION(Servers0, chapter5);
- ADD_CALLBACK_FUNCTION(Servers0, chapter5Handler);
+Waiter1::Waiter1(LastExpressEngine *engine) : Entity(engine, kEntityWaiter1) {
+ ADD_CALLBACK_FUNCTION(Waiter1, callSavepoint);
+ ADD_CALLBACK_FUNCTION(Waiter1, updateFromTime);
+ ADD_CALLBACK_FUNCTION(Waiter1, draw);
+ ADD_CALLBACK_FUNCTION(Waiter1, updatePosition);
+ ADD_CALLBACK_FUNCTION(Waiter1, callbackActionOnDirection);
+ ADD_CALLBACK_FUNCTION(Waiter1, playSound);
+ ADD_CALLBACK_FUNCTION(Waiter1, rebeccaFeedUs);
+ ADD_CALLBACK_FUNCTION(Waiter1, rebeccaClearOurTable);
+ ADD_CALLBACK_FUNCTION(Waiter1, abbotCheckMe);
+ ADD_CALLBACK_FUNCTION(Waiter1, abbotClearTable);
+ ADD_CALLBACK_FUNCTION(Waiter1, chapter1);
+ ADD_CALLBACK_FUNCTION(Waiter1, annaOrder);
+ ADD_CALLBACK_FUNCTION(Waiter1, augustOrder);
+ ADD_CALLBACK_FUNCTION(Waiter1, serveAnna);
+ ADD_CALLBACK_FUNCTION(Waiter1, serveAugust);
+ ADD_CALLBACK_FUNCTION(Waiter1, clearAnna);
+ ADD_CALLBACK_FUNCTION(Waiter1, clearTatiana);
+ ADD_CALLBACK_FUNCTION(Waiter1, clearAugust1);
+ ADD_CALLBACK_FUNCTION(Waiter1, clearAugust2);
+ ADD_CALLBACK_FUNCTION(Waiter1, servingDinner);
+ ADD_CALLBACK_FUNCTION(Waiter1, function21);
+ ADD_CALLBACK_FUNCTION(Waiter1, function22);
+ ADD_CALLBACK_FUNCTION(Waiter1, chapter2);
+ ADD_CALLBACK_FUNCTION(Waiter1, inKitchen);
+ ADD_CALLBACK_FUNCTION(Waiter1, augustComeHere2);
+ ADD_CALLBACK_FUNCTION(Waiter1, augustClearTable2);
+ ADD_CALLBACK_FUNCTION(Waiter1, chapter3);
+ ADD_CALLBACK_FUNCTION(Waiter1, serving3);
+ ADD_CALLBACK_FUNCTION(Waiter1, annaComeHere3);
+ ADD_CALLBACK_FUNCTION(Waiter1, abbotServeLunch3);
+ ADD_CALLBACK_FUNCTION(Waiter1, chapter4);
+ ADD_CALLBACK_FUNCTION(Waiter1, serving4);
+ ADD_CALLBACK_FUNCTION(Waiter1, augustOrder4);
+ ADD_CALLBACK_FUNCTION(Waiter1, serveAugust4);
+ ADD_CALLBACK_FUNCTION(Waiter1, augustClearTable);
+ ADD_CALLBACK_FUNCTION(Waiter1, chapter5);
+ ADD_CALLBACK_FUNCTION(Waiter1, chapter5Handler);
ADD_NULL_FUNCTION();
}
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_SIIS(1, Servers0, callSavepoint, EntityIndex, ActionIndex)
+IMPLEMENT_FUNCTION_SIIS(1, Waiter1, callSavepoint, EntityIndex, ActionIndex)
Entity::callSavepoint(savepoint, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_NOSETUP(2, Servers0, updateFromTime)
+IMPLEMENT_FUNCTION_NOSETUP(2, Waiter1, updateFromTime)
Entity::updateFromTime(savepoint);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_S(3, Servers0, draw)
+IMPLEMENT_FUNCTION_S(3, Waiter1, draw)
Entity::draw(savepoint, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_NOSETUP(4, Servers0, updatePosition)
+IMPLEMENT_FUNCTION_NOSETUP(4, Waiter1, updatePosition)
Entity::updatePosition(savepoint, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_NOSETUP(5, Servers0, callbackActionOnDirection)
+IMPLEMENT_FUNCTION_NOSETUP(5, Waiter1, callbackActionOnDirection)
EXPOSE_PARAMS(EntityData::EntityParametersIIII);
switch (savepoint.action) {
@@ -119,7 +119,7 @@ IMPLEMENT_FUNCTION_NOSETUP(5, Servers0, callbackActionOnDirection)
case kActionExcuseMeCath:
if (!params->param1) {
- getSound()->excuseMe(kEntityServers0);
+ getSound()->excuseMe(kEntityWaiter1);
params->param1 = 1;
}
break;
@@ -127,12 +127,12 @@ IMPLEMENT_FUNCTION_NOSETUP(5, Servers0, callbackActionOnDirection)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_S(6, Servers0, playSound)
+IMPLEMENT_FUNCTION_S(6, Waiter1, playSound)
Entity::playSound(savepoint);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(7, Servers0, function7)
+IMPLEMENT_FUNCTION(7, Waiter1, rebeccaFeedUs)
switch (savepoint.action) {
default:
break;
@@ -153,12 +153,12 @@ IMPLEMENT_FUNCTION(7, Servers0, function7)
break;
case 1:
- getEntities()->clearSequences(kEntityServers0);
- getSavePoints()->push(kEntityServers0, kEntityRebecca, kAction123712592);
+ getEntities()->clearSequences(kEntityWaiter1);
+ getSavePoints()->push(kEntityWaiter1, kEntityRebecca, kAction123712592);
break;
case 2:
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
getData()->entityPosition = kPosition_5900;
callbackAction();
break;
@@ -173,12 +173,12 @@ IMPLEMENT_FUNCTION(7, Servers0, function7)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(8, Servers0, function8)
+IMPLEMENT_FUNCTION(8, Waiter1, rebeccaClearOurTable)
serveTable(savepoint, "911", kEntityTables3, "010L", "010M", "913", &ENTITY_PARAM(1, 2));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(9, Servers0, function9)
+IMPLEMENT_FUNCTION(9, Waiter1, abbotCheckMe)
switch (savepoint.action) {
default:
break;
@@ -197,15 +197,15 @@ IMPLEMENT_FUNCTION(9, Servers0, function9)
break;
case 1:
- getSavePoints()->push(kEntityServers0, kEntityAbbot, kAction122358304);
- getEntities()->drawSequenceLeft(kEntityServers0, "029D");
+ getSavePoints()->push(kEntityWaiter1, kEntityAbbot, kAction122358304);
+ getEntities()->drawSequenceLeft(kEntityWaiter1, "029D");
setCallback(2);
setup_playSound(getProgress().chapter == kChapter3 ? "Abb3016" : "Abb4001");
break;
case 2:
- getSavePoints()->push(kEntityServers0, kEntityAbbot, kAction122288808);
+ getSavePoints()->push(kEntityWaiter1, kEntityAbbot, kAction122288808);
setCallback(3);
setup_draw("917");
@@ -213,7 +213,7 @@ IMPLEMENT_FUNCTION(9, Servers0, function9)
case 3:
getData()->entityPosition = kPosition_5900;
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
ENTITY_PARAM(2, 2) = 0;
ENTITY_PARAM(1, 6) = 0;
@@ -225,37 +225,37 @@ IMPLEMENT_FUNCTION(9, Servers0, function9)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(10, Servers0, function10)
+IMPLEMENT_FUNCTION(10, Waiter1, abbotClearTable)
serveTable(savepoint, "916", kEntityTables4, "014E", "014F", "918", &ENTITY_PARAM(2, 3), false);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(11, Servers0, chapter1)
+IMPLEMENT_FUNCTION(11, Waiter1, chapter1)
switch (savepoint.action) {
default:
break;
case kActionNone:
- setup_chapter1Handler();
+ setup_servingDinner();
break;
case kActionDefault:
- getSavePoints()->addData(kEntityServers0, kAction270410280, 0);
- getSavePoints()->addData(kEntityServers0, kAction304061224, 1);
- getSavePoints()->addData(kEntityServers0, kAction252568704, 10);
- getSavePoints()->addData(kEntityServers0, kAction286534136, 11);
- getSavePoints()->addData(kEntityServers0, kAction218983616, 12);
- getSavePoints()->addData(kEntityServers0, kAction218586752, 13);
- getSavePoints()->addData(kEntityServers0, kAction207330561, 14);
- getSavePoints()->addData(kEntityServers0, kAction286403504, 16);
- getSavePoints()->addData(kEntityServers0, kAction218128129, 17);
- getSavePoints()->addData(kEntityServers0, kAction270068760, 18);
- getSavePoints()->addData(kEntityServers0, kAction223712416, 2);
- getSavePoints()->addData(kEntityServers0, kAction237485916, 5);
- getSavePoints()->addData(kEntityServers0, kAction188893625, 8);
- getSavePoints()->addData(kEntityServers0, kAction204704037, 6);
- getSavePoints()->addData(kEntityServers0, kAction292758554, 7);
- getSavePoints()->addData(kEntityServers0, kAction337548856, 9);
+ getSavePoints()->addData(kEntityWaiter1, kAction270410280, 0);
+ getSavePoints()->addData(kEntityWaiter1, kAction304061224, 1);
+ getSavePoints()->addData(kEntityWaiter1, kAction252568704, 10);
+ getSavePoints()->addData(kEntityWaiter1, kAction286534136, 11);
+ getSavePoints()->addData(kEntityWaiter1, kAction218983616, 12);
+ getSavePoints()->addData(kEntityWaiter1, kAction218586752, 13);
+ getSavePoints()->addData(kEntityWaiter1, kAction207330561, 14);
+ getSavePoints()->addData(kEntityWaiter1, kAction286403504, 16);
+ getSavePoints()->addData(kEntityWaiter1, kAction218128129, 17);
+ getSavePoints()->addData(kEntityWaiter1, kAction270068760, 18);
+ getSavePoints()->addData(kEntityWaiter1, kAction223712416, 2);
+ getSavePoints()->addData(kEntityWaiter1, kAction237485916, 5);
+ getSavePoints()->addData(kEntityWaiter1, kAction188893625, 8);
+ getSavePoints()->addData(kEntityWaiter1, kAction204704037, 6);
+ getSavePoints()->addData(kEntityWaiter1, kAction292758554, 7);
+ getSavePoints()->addData(kEntityWaiter1, kAction337548856, 9);
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
@@ -265,47 +265,47 @@ IMPLEMENT_FUNCTION(11, Servers0, chapter1)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(12, Servers0, function12)
+IMPLEMENT_FUNCTION(12, Waiter1, annaOrder)
handleServer(savepoint, "907", kEntityAnna, kAction268773672, &ENTITY_PARAM(0, 1));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(13, Servers0, function13)
+IMPLEMENT_FUNCTION(13, Waiter1, augustOrder)
handleServer(savepoint, "911", kEntityAugust, kAction268773672, &ENTITY_PARAM(0, 2), "010F");
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(14, Servers0, function14)
+IMPLEMENT_FUNCTION(14, Waiter1, serveAnna)
handleServer(savepoint, "908", kEntityAnna, kAction170016384, &ENTITY_PARAM(0, 4));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(15, Servers0, function15)
+IMPLEMENT_FUNCTION(15, Waiter1, serveAugust)
handleServer(savepoint, "912", kEntityAugust, kAction170016384, &ENTITY_PARAM(0, 5));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(16, Servers0, function16)
+IMPLEMENT_FUNCTION(16, Waiter1, clearAnna)
serveTable(savepoint, "907", kEntityTables0, "001N", "001P", "909", &ENTITY_PARAM(0, 6));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(17, Servers0, function17)
+IMPLEMENT_FUNCTION(17, Waiter1, clearTatiana)
serveTable(savepoint, "915", kEntityTables4, "014E", "014F", "917", &ENTITY_PARAM(1, 1), true, false, 67);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(18, Servers0, function18)
+IMPLEMENT_FUNCTION(18, Waiter1, clearAugust1)
serveTable(savepoint, "911", kEntityTables3, "010L", "010H", "913", &ENTITY_PARAM(0, 7));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(19, Servers0, function19)
+IMPLEMENT_FUNCTION(19, Waiter1, clearAugust2)
serveTable(savepoint, "911", kEntityTables3, "010L", "010M", "913", &ENTITY_PARAM(0, 8), true, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(20, Servers0, chapter1Handler)
+IMPLEMENT_FUNCTION(20, Waiter1, servingDinner)
switch (savepoint.action) {
default:
break;
@@ -325,19 +325,19 @@ IMPLEMENT_FUNCTION(20, Servers0, chapter1Handler)
}
}
- if (!getEntities()->isInKitchen(kEntityServers0) && !getEntities()->isSomebodyInsideRestaurantOrSalon())
+ if (!getEntities()->isInKitchen(kEntityWaiter1) && !getEntities()->isSomebodyInsideRestaurantOrSalon())
break;
- HANDLE_TABLE(0, 1, 1, setup_function12);
- HANDLE_TABLE(0, 2, 2, setup_function13);
- HANDLE_TABLE(0, 3, 3, setup_function7);
- HANDLE_TABLE(0, 4, 4, setup_function14);
- HANDLE_TABLE(0, 5, 5, setup_function15);
- HANDLE_TABLE(0, 6, 6, setup_function16);
- HANDLE_TABLE(1, 1, 7, setup_function17);
- HANDLE_TABLE(0, 7, 8, setup_function18);
- HANDLE_TABLE(0, 8, 9, setup_function19);
- HANDLE_TABLE(1, 2, 10, setup_function8);
+ HANDLE_TABLE(0, 1, 1, setup_annaOrder);
+ HANDLE_TABLE(0, 2, 2, setup_augustOrder);
+ HANDLE_TABLE(0, 3, 3, setup_rebeccaFeedUs);
+ HANDLE_TABLE(0, 4, 4, setup_serveAnna);
+ HANDLE_TABLE(0, 5, 5, setup_serveAugust);
+ HANDLE_TABLE(0, 6, 6, setup_clearAnna);
+ HANDLE_TABLE(1, 1, 7, setup_clearTatiana);
+ HANDLE_TABLE(0, 7, 8, setup_clearAugust1);
+ HANDLE_TABLE(0, 8, 9, setup_clearAugust2);
+ HANDLE_TABLE(1, 2, 10, setup_rebeccaClearOurTable);
break;
case kActionCallback:
@@ -346,13 +346,13 @@ IMPLEMENT_FUNCTION(20, Servers0, chapter1Handler)
break;
case 10:
- getSavePoints()->push(kEntityServers0, kEntityPascale, kAction352703104);
+ getSavePoints()->push(kEntityWaiter1, kEntityPascale, kAction352703104);
setup_function21();
break;
case 11:
case 12:
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
getData()->entityPosition = kPosition_5900;
if (getCallback() == 11)
@@ -363,7 +363,7 @@ IMPLEMENT_FUNCTION(20, Servers0, chapter1Handler)
case 13:
case 14:
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
getData()->entityPosition = kPosition_5900;
break;
}
@@ -382,7 +382,7 @@ IMPLEMENT_FUNCTION(20, Servers0, chapter1Handler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(21, Servers0, function21)
+IMPLEMENT_FUNCTION(21, Waiter1, function21)
switch (savepoint.action) {
default:
break;
@@ -398,28 +398,28 @@ IMPLEMENT_FUNCTION(21, Servers0, function21)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(22, Servers0, function22)
+IMPLEMENT_FUNCTION(22, Waiter1, function22)
if (savepoint.action == kActionDefault) {
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
getData()->car = kCarRestaurant;
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(23, Servers0, chapter2)
+IMPLEMENT_FUNCTION(23, Waiter1, chapter2)
switch (savepoint.action) {
default:
break;
case kActionNone:
- setup_chapter2Handler();
+ setup_inKitchen();
break;
case kActionDefault:
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
@@ -434,28 +434,28 @@ IMPLEMENT_FUNCTION(23, Servers0, chapter2)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(24, Servers0, chapter2Handler)
+IMPLEMENT_FUNCTION(24, Waiter1, inKitchen)
switch (savepoint.action) {
default:
break;
case kActionNone:
- if (!getEntities()->isInKitchen(kEntityServers0) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
+ if (!getEntities()->isInKitchen(kEntityWaiter1) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
break;
- HANDLE_TABLE(1, 3, 1, setup_function25);
- HANDLE_TABLE(1, 4, 2, setup_function26);
+ HANDLE_TABLE(1, 3, 1, setup_augustComeHere2);
+ HANDLE_TABLE(1, 4, 2, setup_augustClearTable2);
break;
case kActionCallback:
if (getCallback() == 1)
- HANDLE_TABLE(1, 4, 2, setup_function26);
+ HANDLE_TABLE(1, 4, 2, setup_augustClearTable2);
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(25, Servers0, function25)
+IMPLEMENT_FUNCTION(25, Waiter1, augustComeHere2)
switch (savepoint.action) {
default:
break;
@@ -474,13 +474,13 @@ IMPLEMENT_FUNCTION(25, Servers0, function25)
break;
case 1:
- getSavePoints()->push(kEntityServers0, kEntityAugust, kAction123712592);
- getEntities()->drawSequenceLeft(kEntityServers0, "BLANK");
+ getSavePoints()->push(kEntityWaiter1, kEntityAugust, kAction123712592);
+ getEntities()->drawSequenceLeft(kEntityWaiter1, "BLANK");
break;
case 2:
getData()->entityPosition = kPosition_5900;
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
ENTITY_PARAM(1, 3) = 0;
callbackAction();
@@ -496,22 +496,22 @@ IMPLEMENT_FUNCTION(25, Servers0, function25)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(26, Servers0, function26)
+IMPLEMENT_FUNCTION(26, Waiter1, augustClearTable2)
serveTable(savepoint, "957", kEntityTables0, "016E", "016D", "959", &ENTITY_PARAM(1, 4));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(27, Servers0, chapter3)
+IMPLEMENT_FUNCTION(27, Waiter1, chapter3)
switch (savepoint.action) {
default:
break;
case kActionNone:
- setup_chapter3Handler();
+ setup_serving3();
break;
case kActionDefault:
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
@@ -530,53 +530,53 @@ IMPLEMENT_FUNCTION(27, Servers0, chapter3)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(28, Servers0, chapter3Handler)
+IMPLEMENT_FUNCTION(28, Waiter1, serving3)
switch (savepoint.action) {
default:
break;
case kActionNone:
- if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
+ if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
break;
if (ENTITY_PARAM(1, 5)) {
setCallback(1);
- setup_augustAnnaDateOrder();
+ setup_annaComeHere3();
break;
}
label_callback_1:
if (ENTITY_PARAM(1, 6)) {
setCallback(2);
- setup_function9();
+ setup_abbotCheckMe();
break;
}
label_callback_2:
if (ENTITY_PARAM(2, 4)) {
setCallback(3);
- setup_function30();
+ setup_abbotServeLunch3();
break;
}
label_callback_3:
if (ENTITY_PARAM(2, 3)) {
setCallback(4);
- setup_function10();
+ setup_abbotClearTable();
break;
}
label_callback_4:
if (ENTITY_PARAM(0, 3)) {
setCallback(5);
- setup_function7();
+ setup_rebeccaFeedUs();
break;
}
label_callback_5:
if (ENTITY_PARAM(1, 2)) {
setCallback(6);
- setup_function8();
+ setup_rebeccaClearOurTable();
break;
}
break;
@@ -606,7 +606,8 @@ label_callback_5:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(29, Servers0, augustAnnaDateOrder)
+IMPLEMENT_FUNCTION(29, Waiter1, annaComeHere3)
+ // August and Anna order dinner
switch (savepoint.action) {
default:
break;
@@ -625,15 +626,15 @@ IMPLEMENT_FUNCTION(29, Servers0, augustAnnaDateOrder)
break;
case 1:
- getSavePoints()->push(kEntityServers0, kEntityAnna, kAction122358304);
- getEntities()->drawSequenceLeft(kEntityServers0, "026D");
+ getSavePoints()->push(kEntityWaiter1, kEntityAnna, kAction122358304);
+ getEntities()->drawSequenceLeft(kEntityWaiter1, "026D");
setCallback(2);
setup_playSound("Ann3138");
break;
case 2:
- getSavePoints()->push(kEntityServers0, kEntityAnna, kAction122288808);
+ getSavePoints()->push(kEntityWaiter1, kEntityAnna, kAction122288808);
setCallback(3);
setup_draw("913");
@@ -641,7 +642,7 @@ IMPLEMENT_FUNCTION(29, Servers0, augustAnnaDateOrder)
case 3:
getData()->entityPosition = kPosition_5900;
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
ENTITY_PARAM(1, 5) = 0;
callbackAction();
@@ -652,7 +653,7 @@ IMPLEMENT_FUNCTION(29, Servers0, augustAnnaDateOrder)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(30, Servers0, function30)
+IMPLEMENT_FUNCTION(30, Waiter1, abbotServeLunch3)
switch (savepoint.action) {
default:
break;
@@ -671,15 +672,15 @@ IMPLEMENT_FUNCTION(30, Servers0, function30)
break;
case 1:
- getSavePoints()->push(kEntityServers0, kEntityAbbot, kAction122358304);
- getEntities()->drawSequenceLeft(kEntityServers0, "029D");
+ getSavePoints()->push(kEntityWaiter1, kEntityAbbot, kAction122358304);
+ getEntities()->drawSequenceLeft(kEntityWaiter1, "029D");
setCallback(2);
setup_playSound("Abb3016a");
break;
case 2:
- getSavePoints()->push(kEntityServers0, kEntityAbbot, kAction122288808);
+ getSavePoints()->push(kEntityWaiter1, kEntityAbbot, kAction122288808);
setCallback(3);
setup_draw("918");
@@ -687,7 +688,7 @@ IMPLEMENT_FUNCTION(30, Servers0, function30)
case 3:
getData()->entityPosition = kPosition_5900;
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
ENTITY_PARAM(2, 4) = 0;
callbackAction();
@@ -698,17 +699,17 @@ IMPLEMENT_FUNCTION(30, Servers0, function30)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(31, Servers0, chapter4)
+IMPLEMENT_FUNCTION(31, Waiter1, chapter4)
switch (savepoint.action) {
default:
break;
case kActionNone:
- setup_chapter4Handler();
+ setup_serving4();
break;
case kActionDefault:
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
@@ -727,7 +728,7 @@ IMPLEMENT_FUNCTION(31, Servers0, chapter4)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(32, Servers0, chapter4Handler)
+IMPLEMENT_FUNCTION(32, Waiter1, serving4)
switch (savepoint.action) {
default:
break;
@@ -738,47 +739,47 @@ IMPLEMENT_FUNCTION(32, Servers0, chapter4Handler)
params->param1 = 0;
}
- if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
+ if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
break;
if (ENTITY_PARAM(1, 7)) {
setCallback(1);
- setup_augustOrderSteak();
+ setup_augustOrder4();
break;
}
label_callback_1:
if (ENTITY_PARAM(1, 8)) {
setCallback(2);
- setup_augustServeDuck();
+ setup_serveAugust4();
break;
}
label_callback_2:
if (ENTITY_PARAM(2, 1)) {
setCallback(3);
- setup_function35();
+ setup_augustClearTable();
break;
}
label_callback_3:
if (ENTITY_PARAM(2, 2)) {
setCallback(4);
- setup_function9();
+ setup_abbotCheckMe();
break;
}
label_callback_4:
if (ENTITY_PARAM(2, 3)) {
setCallback(5);
- setup_function10();
+ setup_abbotClearTable();
break;
}
label_callback_5:
if (ENTITY_PARAM(0, 3)) {
setCallback(6);
- setup_function7();
+ setup_rebeccaFeedUs();
break;
}
break;
@@ -821,7 +822,8 @@ label_callback_5:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(33, Servers0, augustOrderSteak)
+IMPLEMENT_FUNCTION(33, Waiter1, augustOrder4)
+ // August orders a steak
switch (savepoint.action) {
default:
break;
@@ -837,7 +839,7 @@ IMPLEMENT_FUNCTION(33, Servers0, augustOrderSteak)
break;
case 1:
- getEntities()->drawSequenceLeft(kEntityServers0, "010F3");
+ getEntities()->drawSequenceLeft(kEntityWaiter1, "010F3");
getEntities()->drawSequenceLeft(kEntityAugust, "010D3");
setCallback(2);
@@ -845,7 +847,7 @@ IMPLEMENT_FUNCTION(33, Servers0, augustOrderSteak)
break;
case 2:
- getSavePoints()->push(kEntityServers0, kEntityAugust, kAction122288808);
+ getSavePoints()->push(kEntityWaiter1, kEntityAugust, kAction122288808);
setCallback(3);
setup_draw("913");
@@ -853,7 +855,7 @@ IMPLEMENT_FUNCTION(33, Servers0, augustOrderSteak)
case 3:
getData()->entityPosition = kPosition_5900;
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
ENTITY_PARAM(1, 7) = 0;
callbackAction();
@@ -864,7 +866,8 @@ IMPLEMENT_FUNCTION(33, Servers0, augustOrderSteak)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(34, Servers0, augustServeDuck)
+IMPLEMENT_FUNCTION(34, Waiter1, serveAugust4)
+ // August is being served
switch (savepoint.action) {
default:
break;
@@ -880,15 +883,15 @@ IMPLEMENT_FUNCTION(34, Servers0, augustServeDuck)
break;
case 1:
- getSavePoints()->push(kEntityServers0, kEntityAugust, kAction122358304);
- getSound()->playSound(kEntityServers0, "AUG1053");
+ getSavePoints()->push(kEntityWaiter1, kEntityAugust, kAction122358304);
+ getSound()->playSound(kEntityWaiter1, "AUG1053");
setCallback(2);
setup_draw("010G3");
break;
case 2:
- getSavePoints()->push(kEntityServers0, kEntityAugust, kAction201964801);
+ getSavePoints()->push(kEntityWaiter1, kEntityAugust, kAction201964801);
setCallback(3);
setup_draw("914");
@@ -896,7 +899,7 @@ IMPLEMENT_FUNCTION(34, Servers0, augustServeDuck)
case 3:
getData()->entityPosition = kPosition_5900;
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
ENTITY_PARAM(1, 8) = 0;
callbackAction();
@@ -907,12 +910,12 @@ IMPLEMENT_FUNCTION(34, Servers0, augustServeDuck)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(35, Servers0, function35)
+IMPLEMENT_FUNCTION(35, Waiter1, augustClearTable)
serveTable(savepoint, "911", kEntityTables3, "010L", "010M", "914", &ENTITY_PARAM(2, 1), false, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(36, Servers0, chapter5)
+IMPLEMENT_FUNCTION(36, Waiter1, chapter5)
switch (savepoint.action) {
default:
break;
@@ -922,7 +925,7 @@ IMPLEMENT_FUNCTION(36, Servers0, chapter5)
break;
case kActionDefault:
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
getData()->entityPosition = kPosition_3969;
getData()->location = kLocationInsideCompartment;
@@ -933,19 +936,19 @@ IMPLEMENT_FUNCTION(36, Servers0, chapter5)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(37, Servers0, chapter5Handler)
+IMPLEMENT_FUNCTION(37, Waiter1, chapter5Handler)
if (savepoint.action == kActionProceedChapter5)
setup_nullfunction();
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_NULL_FUNCTION(38, Servers0)
+IMPLEMENT_NULL_FUNCTION(38, Waiter1)
//////////////////////////////////////////////////////////////////////////
// Private functions
//////////////////////////////////////////////////////////////////////////
-void Servers0::handleServer(const SavePoint &savepoint, const char *name, EntityIndex entity, ActionIndex action, uint *parameter, const char *name2) {
+void Waiter1::handleServer(const SavePoint &savepoint, const char *name, EntityIndex entity, ActionIndex action, uint *parameter, const char *name2) {
switch (savepoint.action) {
default:
break;
@@ -962,11 +965,11 @@ void Servers0::handleServer(const SavePoint &savepoint, const char *name, Entity
if (getCallback() == 1) {
// Prepare or draw sequences depending of value of string
if (strcmp(name2, ""))
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
else
- getEntities()->drawSequenceLeft(kEntityServers0, name2);
+ getEntities()->drawSequenceLeft(kEntityWaiter1, name2);
- getSavePoints()->push(kEntityServers0, entity, action);
+ getSavePoints()->push(kEntityWaiter1, entity, action);
*parameter = 0;
callbackAction();
@@ -976,7 +979,7 @@ void Servers0::handleServer(const SavePoint &savepoint, const char *name, Entity
}
//////////////////////////////////////////////////////////////////////////
-void Servers0::serveTable(const SavePoint &savepoint, const char *seq1, EntityIndex entity, const char *seq2, const char *seq3, const char *seq4, uint *parameter, bool shouldUpdatePosition, bool pushSavepoint, Position position) {
+void Waiter1::serveTable(const SavePoint &savepoint, const char *seq1, EntityIndex entity, const char *seq2, const char *seq3, const char *seq4, uint *parameter, bool shouldUpdatePosition, bool pushSavepoint, Position position) {
switch (savepoint.action) {
default:
break;
@@ -998,9 +1001,9 @@ void Servers0::serveTable(const SavePoint &savepoint, const char *seq1, EntityIn
case 1:
if (position)
- getEntities()->updatePositionEnter(kEntityServers0, kCarRestaurant, position);
+ getEntities()->updatePositionEnter(kEntityWaiter1, kCarRestaurant, position);
- getSavePoints()->push(kEntityServers0, entity, kAction136455232);
+ getSavePoints()->push(kEntityWaiter1, entity, kAction136455232);
setCallback(2);
setup_callSavepoint(seq2, entity, kActionDrawTablesWithChairs, seq3);
@@ -1008,7 +1011,7 @@ void Servers0::serveTable(const SavePoint &savepoint, const char *seq1, EntityIn
case 2:
if (position)
- getEntities()->updatePositionExit(kEntityServers0, kCarRestaurant, position);
+ getEntities()->updatePositionExit(kEntityWaiter1, kCarRestaurant, position);
setCallback(3);
setup_draw(seq4);
@@ -1019,9 +1022,9 @@ void Servers0::serveTable(const SavePoint &savepoint, const char *seq1, EntityIn
// Special case for functions 19 & 35
if (pushSavepoint)
- getSavePoints()->push(kEntityServers0, kEntityRebecca, kAction224253538);
+ getSavePoints()->push(kEntityWaiter1, kEntityRebecca, kAction224253538);
- getEntities()->clearSequences(kEntityServers0);
+ getEntities()->clearSequences(kEntityWaiter1);
*parameter = 0;
callbackAction();
diff --git a/engines/lastexpress/entities/servers0.h b/engines/lastexpress/entities/waiter1.h
index 70f06596b0..64c66550af 100644
--- a/engines/lastexpress/entities/servers0.h
+++ b/engines/lastexpress/entities/waiter1.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef LASTEXPRESS_SERVERS0_H
-#define LASTEXPRESS_SERVERS0_H
+#ifndef LASTEXPRESS_WAITER1_H
+#define LASTEXPRESS_WAITER1_H
#include "lastexpress/entities/entity.h"
@@ -29,10 +29,10 @@ namespace LastExpress {
class LastExpressEngine;
-class Servers0 : public Entity {
+class Waiter1 : public Entity {
public:
- Servers0(LastExpressEngine *engine);
- ~Servers0() {}
+ Waiter1(LastExpressEngine *engine);
+ ~Waiter1() {}
/**
* Call a savepoint (or draw sequence in default case)
@@ -80,29 +80,24 @@ public:
*/
DECLARE_FUNCTION_1(playSound, const char *filename)
- DECLARE_FUNCTION(function7)
- DECLARE_FUNCTION(function8)
- DECLARE_FUNCTION(function9)
- DECLARE_FUNCTION(function10)
+ DECLARE_FUNCTION(rebeccaFeedUs)
+ DECLARE_FUNCTION(rebeccaClearOurTable)
+ DECLARE_FUNCTION(abbotCheckMe)
+ DECLARE_FUNCTION(abbotClearTable)
/**
* Setup Chapter 1
*/
DECLARE_FUNCTION(chapter1)
- DECLARE_FUNCTION(function12)
- DECLARE_FUNCTION(function13)
- DECLARE_FUNCTION(function14)
- DECLARE_FUNCTION(function15)
- DECLARE_FUNCTION(function16)
- DECLARE_FUNCTION(function17)
- DECLARE_FUNCTION(function18)
- DECLARE_FUNCTION(function19)
-
- /**
- * Handle Chapter 1 events
- */
- DECLARE_FUNCTION(chapter1Handler)
-
+ DECLARE_FUNCTION(annaOrder)
+ DECLARE_FUNCTION(augustOrder)
+ DECLARE_FUNCTION(serveAnna)
+ DECLARE_FUNCTION(serveAugust)
+ DECLARE_FUNCTION(clearAnna)
+ DECLARE_FUNCTION(clearTatiana)
+ DECLARE_FUNCTION(clearAugust1)
+ DECLARE_FUNCTION(clearAugust2)
+ DECLARE_FUNCTION(servingDinner)
DECLARE_FUNCTION(function21)
DECLARE_FUNCTION(function22)
@@ -110,41 +105,26 @@ public:
* Setup Chapter 2
*/
DECLARE_FUNCTION(chapter2)
-
- /**
- * Handle Chapter 2 events
- */
- DECLARE_FUNCTION(chapter2Handler)
-
- DECLARE_FUNCTION(function25)
- DECLARE_FUNCTION(function26)
+ DECLARE_FUNCTION(inKitchen)
+ DECLARE_FUNCTION(augustComeHere2)
+ DECLARE_FUNCTION(augustClearTable2)
/**
* Setup Chapter 3
*/
DECLARE_FUNCTION(chapter3)
-
- /**
- * Handle Chapter 3 events
- */
- DECLARE_FUNCTION(chapter3Handler)
-
- DECLARE_FUNCTION(augustAnnaDateOrder)
- DECLARE_FUNCTION(function30)
+ DECLARE_FUNCTION(serving3)
+ DECLARE_FUNCTION(annaComeHere3)
+ DECLARE_FUNCTION(abbotServeLunch3)
/**
* Setup Chapter 4
*/
DECLARE_FUNCTION(chapter4)
-
- /**
- * Handle Chapter 4 events
- */
- DECLARE_FUNCTION(chapter4Handler)
-
- DECLARE_FUNCTION(augustOrderSteak)
- DECLARE_FUNCTION(augustServeDuck)
- DECLARE_FUNCTION(function35)
+ DECLARE_FUNCTION(serving4)
+ DECLARE_FUNCTION(augustOrder4)
+ DECLARE_FUNCTION(serveAugust4)
+ DECLARE_FUNCTION(augustClearTable)
/**
* Setup Chapter 5
@@ -165,4 +145,4 @@ private:
} // End of namespace LastExpress
-#endif // LASTEXPRESS_SERVERS0_H
+#endif // LASTEXPRESS_WAITER1_H
diff --git a/engines/lastexpress/entities/servers1.cpp b/engines/lastexpress/entities/waiter2.cpp
index 153c2b66da..52a48a77d5 100644
--- a/engines/lastexpress/entities/servers1.cpp
+++ b/engines/lastexpress/entities/waiter2.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "lastexpress/entities/servers1.h"
+#include "lastexpress/entities/waiter2.h"
#include "lastexpress/game/entities.h"
#include "lastexpress/game/logic.h"
@@ -32,61 +32,61 @@
namespace LastExpress {
-Servers1::Servers1(LastExpressEngine *engine) : Entity(engine, kEntityServers1) {
- ADD_CALLBACK_FUNCTION(Servers1, updateFromTime);
- ADD_CALLBACK_FUNCTION(Servers1, draw);
- ADD_CALLBACK_FUNCTION(Servers1, updatePosition);
- ADD_CALLBACK_FUNCTION(Servers1, callbackActionOnDirection);
- ADD_CALLBACK_FUNCTION(Servers1, callSavepoint);
- ADD_CALLBACK_FUNCTION(Servers1, playSound);
- ADD_CALLBACK_FUNCTION(Servers1, function7);
- ADD_CALLBACK_FUNCTION(Servers1, chapter1);
- ADD_CALLBACK_FUNCTION(Servers1, function9);
- ADD_CALLBACK_FUNCTION(Servers1, function10);
- ADD_CALLBACK_FUNCTION(Servers1, function11);
- ADD_CALLBACK_FUNCTION(Servers1, function12);
- ADD_CALLBACK_FUNCTION(Servers1, function13);
- ADD_CALLBACK_FUNCTION(Servers1, chapter1Handler);
- ADD_CALLBACK_FUNCTION(Servers1, function15);
- ADD_CALLBACK_FUNCTION(Servers1, function16);
- ADD_CALLBACK_FUNCTION(Servers1, chapter2);
- ADD_CALLBACK_FUNCTION(Servers1, chapter2Handler);
- ADD_CALLBACK_FUNCTION(Servers1, function19);
- ADD_CALLBACK_FUNCTION(Servers1, function20);
- ADD_CALLBACK_FUNCTION(Servers1, function21);
- ADD_CALLBACK_FUNCTION(Servers1, chapter3);
- ADD_CALLBACK_FUNCTION(Servers1, chapter3Handler);
- ADD_CALLBACK_FUNCTION(Servers1, function24);
- ADD_CALLBACK_FUNCTION(Servers1, chapter4);
- ADD_CALLBACK_FUNCTION(Servers1, chapter4Handler);
- ADD_CALLBACK_FUNCTION(Servers1, function27);
- ADD_CALLBACK_FUNCTION(Servers1, function28);
- ADD_CALLBACK_FUNCTION(Servers1, function29);
- ADD_CALLBACK_FUNCTION(Servers1, chapter5);
- ADD_CALLBACK_FUNCTION(Servers1, chapter5Handler);
+Waiter2::Waiter2(LastExpressEngine *engine) : Entity(engine, kEntityWaiter2) {
+ ADD_CALLBACK_FUNCTION(Waiter2, updateFromTime);
+ ADD_CALLBACK_FUNCTION(Waiter2, draw);
+ ADD_CALLBACK_FUNCTION(Waiter2, updatePosition);
+ ADD_CALLBACK_FUNCTION(Waiter2, callbackActionOnDirection);
+ ADD_CALLBACK_FUNCTION(Waiter2, callSavepoint);
+ ADD_CALLBACK_FUNCTION(Waiter2, playSound);
+ ADD_CALLBACK_FUNCTION(Waiter2, monsieurServeUs);
+ ADD_CALLBACK_FUNCTION(Waiter2, chapter1);
+ ADD_CALLBACK_FUNCTION(Waiter2, milosOrder);
+ ADD_CALLBACK_FUNCTION(Waiter2, monsieurOrder);
+ ADD_CALLBACK_FUNCTION(Waiter2, clearAlexei);
+ ADD_CALLBACK_FUNCTION(Waiter2, clearMilos);
+ ADD_CALLBACK_FUNCTION(Waiter2, clearMonsieur);
+ ADD_CALLBACK_FUNCTION(Waiter2, servingDinner);
+ ADD_CALLBACK_FUNCTION(Waiter2, function15);
+ ADD_CALLBACK_FUNCTION(Waiter2, function16);
+ ADD_CALLBACK_FUNCTION(Waiter2, chapter2);
+ ADD_CALLBACK_FUNCTION(Waiter2, inKitchen);
+ ADD_CALLBACK_FUNCTION(Waiter2, tatianaClearTableB);
+ ADD_CALLBACK_FUNCTION(Waiter2, ivoComeHere);
+ ADD_CALLBACK_FUNCTION(Waiter2, ivoClearTableC);
+ ADD_CALLBACK_FUNCTION(Waiter2, chapter3);
+ ADD_CALLBACK_FUNCTION(Waiter2, serving3);
+ ADD_CALLBACK_FUNCTION(Waiter2, annaBringTea3);
+ ADD_CALLBACK_FUNCTION(Waiter2, chapter4);
+ ADD_CALLBACK_FUNCTION(Waiter2, serving4);
+ ADD_CALLBACK_FUNCTION(Waiter2, augustNeedsADrink);
+ ADD_CALLBACK_FUNCTION(Waiter2, serveAugustADrink);
+ ADD_CALLBACK_FUNCTION(Waiter2, annaNeedsADrink);
+ ADD_CALLBACK_FUNCTION(Waiter2, chapter5);
+ ADD_CALLBACK_FUNCTION(Waiter2, chapter5Handler);
ADD_NULL_FUNCTION()
}
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_NOSETUP(1, Servers1, updateFromTime)
+IMPLEMENT_FUNCTION_NOSETUP(1, Waiter2, updateFromTime)
Entity::updateFromTime(savepoint);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_S(2, Servers1, draw)
+IMPLEMENT_FUNCTION_S(2, Waiter2, draw)
Entity::draw(savepoint, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_SII(3, Servers1, updatePosition, CarIndex, Position)
+IMPLEMENT_FUNCTION_SII(3, Waiter2, updatePosition, CarIndex, Position)
Entity::updatePosition(savepoint, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(4, Servers1, callbackActionOnDirection)
+IMPLEMENT_FUNCTION(4, Waiter2, callbackActionOnDirection)
if (savepoint.action == kActionExcuseMeCath) {
if (!params->param1) {
- getSound()->excuseMe(kEntityServers1);
+ getSound()->excuseMe(kEntityWaiter2);
params->param1 = 1;
}
}
@@ -95,17 +95,17 @@ IMPLEMENT_FUNCTION(4, Servers1, callbackActionOnDirection)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_SIIS(5, Servers1, callSavepoint, EntityIndex, ActionIndex)
+IMPLEMENT_FUNCTION_SIIS(5, Waiter2, callSavepoint, EntityIndex, ActionIndex)
Entity::callSavepoint(savepoint, true);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_S(6, Servers1, playSound)
+IMPLEMENT_FUNCTION_S(6, Waiter2, playSound)
Entity::playSound(savepoint);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(7, Servers1, function7)
+IMPLEMENT_FUNCTION(7, Waiter2, monsieurServeUs)
switch (savepoint.action) {
default:
break;
@@ -124,19 +124,19 @@ IMPLEMENT_FUNCTION(7, Servers1, function7)
break;
case 1:
- getSavePoints()->push(kEntityServers1, kEntityBoutarel, kAction122358304);
+ getSavePoints()->push(kEntityWaiter2, kEntityBoutarel, kAction122358304);
setCallback(2);
setup_draw("008C");
break;
case 2:
- getSavePoints()->push(kEntityServers1, kEntityBoutarel, kAction122288808);
+ getSavePoints()->push(kEntityWaiter2, kEntityBoutarel, kAction122288808);
setCallback(2);
setup_draw("926");
break;
case 3:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_5900;
ENTITY_PARAM(1, 2) = 0;
@@ -148,27 +148,27 @@ IMPLEMENT_FUNCTION(7, Servers1, function7)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(8, Servers1, chapter1)
+IMPLEMENT_FUNCTION(8, Waiter2, chapter1)
switch (savepoint.action) {
default:
break;
case kActionNone:
- setup_chapter1Handler();
+ setup_servingDinner();
break;
case kActionDefault:
- getSavePoints()->addData(kEntityServers1, kAction223002560, 0);
- getSavePoints()->addData(kEntityServers1, kAction302996448, 2);
- getSavePoints()->addData(kEntityServers1, kAction269485588, 3);
- getSavePoints()->addData(kEntityServers1, kAction326144276, 4);
- getSavePoints()->addData(kEntityServers1, kAction302203328, 5);
- getSavePoints()->addData(kEntityServers1, kAction189688608, 6);
- getSavePoints()->addData(kEntityServers1, kAction236237423, 7);
- getSavePoints()->addData(kEntityServers1, kAction219377792, 8);
- getSavePoints()->addData(kEntityServers1, kAction256200848, 9);
- getSavePoints()->addData(kEntityServers1, kAction291721418, 10);
- getSavePoints()->addData(kEntityServers1, kAction258136010, 11);
+ getSavePoints()->addData(kEntityWaiter2, kAction223002560, 0);
+ getSavePoints()->addData(kEntityWaiter2, kAction302996448, 2);
+ getSavePoints()->addData(kEntityWaiter2, kAction269485588, 3);
+ getSavePoints()->addData(kEntityWaiter2, kAction326144276, 4);
+ getSavePoints()->addData(kEntityWaiter2, kAction302203328, 5);
+ getSavePoints()->addData(kEntityWaiter2, kAction189688608, 6);
+ getSavePoints()->addData(kEntityWaiter2, kAction236237423, 7);
+ getSavePoints()->addData(kEntityWaiter2, kAction219377792, 8);
+ getSavePoints()->addData(kEntityWaiter2, kAction256200848, 9);
+ getSavePoints()->addData(kEntityWaiter2, kAction291721418, 10);
+ getSavePoints()->addData(kEntityWaiter2, kAction258136010, 11);
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
@@ -178,7 +178,7 @@ IMPLEMENT_FUNCTION(8, Servers1, chapter1)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(9, Servers1, function9)
+IMPLEMENT_FUNCTION(9, Waiter2, milosOrder)
switch (savepoint.action) {
default:
break;
@@ -198,7 +198,7 @@ IMPLEMENT_FUNCTION(9, Servers1, function9)
case 1:
getEntities()->drawSequenceLeft(kEntityMilos, "BLANK");
- getEntities()->drawSequenceLeft(kEntityServers1, "009B");
+ getEntities()->drawSequenceLeft(kEntityWaiter2, "009B");
setCallback(2);
setup_playSound("WAT1001");
@@ -212,7 +212,7 @@ IMPLEMENT_FUNCTION(9, Servers1, function9)
break;
case 3:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_5900;
ENTITY_PARAM(0, 1) = 0;
@@ -224,7 +224,7 @@ IMPLEMENT_FUNCTION(9, Servers1, function9)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(10, Servers1, function10)
+IMPLEMENT_FUNCTION(10, Waiter2, monsieurOrder)
switch (savepoint.action) {
default:
break;
@@ -244,21 +244,21 @@ IMPLEMENT_FUNCTION(10, Servers1, function10)
case 1:
getEntities()->drawSequenceLeft(kEntityBoutarel, "BLANK");
- getEntities()->drawSequenceLeft(kEntityServers1, "008C");
+ getEntities()->drawSequenceLeft(kEntityWaiter2, "008C");
setCallback(2);
setup_playSound("MRB1077");
break;
case 2:
- getSavePoints()->push(kEntityServers1, kEntityBoutarel, kAction168717392);
+ getSavePoints()->push(kEntityWaiter2, kEntityBoutarel, kAction168717392);
setCallback(3);
setup_draw("926");
break;
case 3:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_5900;
ENTITY_PARAM(0, 2) = 0;
@@ -270,63 +270,63 @@ IMPLEMENT_FUNCTION(10, Servers1, function10)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(11, Servers1, function11)
+IMPLEMENT_FUNCTION(11, Waiter2, clearAlexei)
serveTable(savepoint, "919", kEntityTables1, "005H", "005J", "921", &ENTITY_PARAM(0, 3), 63);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(12, Servers1, function12)
+IMPLEMENT_FUNCTION(12, Waiter2, clearMilos)
serveTable(savepoint, "923", kEntityTables2, "009F", "009G", "926", &ENTITY_PARAM(0, 4));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(13, Servers1, function13)
+IMPLEMENT_FUNCTION(13, Waiter2, clearMonsieur)
serveTable(savepoint, "923", kEntityTables2, "009F", "009G", "926", &ENTITY_PARAM(0, 5));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(14, Servers1, chapter1Handler)
+IMPLEMENT_FUNCTION(14, Waiter2, servingDinner)
switch (savepoint.action) {
default:
break;
case kActionDefault:
- if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
+ if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
break;
if (ENTITY_PARAM(0, 1)) {
setCallback(1);
- setup_function9();
+ setup_milosOrder();
break;
}
if (ENTITY_PARAM(1, 2)) {
setCallback(2);
- setup_function10();
+ setup_monsieurOrder();
break;
}
if (ENTITY_PARAM(0, 3)) {
setCallback(3);
- setup_function11();
+ setup_clearAlexei();
break;
}
if (ENTITY_PARAM(0, 4)) {
setCallback(4);
- setup_function12();
+ setup_clearMilos();
break;
}
if (ENTITY_PARAM(0, 5)) {
setCallback(5);
- setup_function13();
+ setup_clearMonsieur();
}
break;
case kActionCallback:
if (getCallback() == 5) {
- getSavePoints()->push(kEntityServers1, kEntityPascale, kAction352768896);
+ getSavePoints()->push(kEntityWaiter2, kEntityPascale, kAction352768896);
setup_function15();
}
break;
@@ -334,7 +334,7 @@ switch (savepoint.action) {
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(15, Servers1, function15)
+IMPLEMENT_FUNCTION(15, Waiter2, function15)
switch (savepoint.action) {
default:
break;
@@ -350,28 +350,28 @@ IMPLEMENT_FUNCTION(15, Servers1, function15)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(16, Servers1, function16)
+IMPLEMENT_FUNCTION(16, Waiter2, function16)
if (savepoint.action == kActionDefault) {
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
getData()->car = kCarRestaurant;
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(17, Servers1, chapter2)
+IMPLEMENT_FUNCTION(17, Waiter2, chapter2)
switch (savepoint.action) {
default:
break;
case kActionNone:
- setup_chapter2Handler();
+ setup_inKitchen();
break;
case kActionDefault:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
@@ -387,32 +387,32 @@ IMPLEMENT_FUNCTION(17, Servers1, chapter2)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(18, Servers1, chapter2Handler)
+IMPLEMENT_FUNCTION(18, Waiter2, inKitchen)
switch (savepoint.action) {
default:
break;
case kActionNone:
- if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
+ if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
break;
if (ENTITY_PARAM(0, 6)) {
setCallback(1);
- setup_function19();
+ setup_tatianaClearTableB();
break;
}
label_callback_1:
if (ENTITY_PARAM(0, 7)) {
setCallback(2);
- setup_function20();
+ setup_ivoComeHere();
break;
}
label_callback_2:
if (ENTITY_PARAM(0, 8) || ENTITY_PARAM(0, 5)) {
setCallback(3);
- setup_function21();
+ setup_ivoClearTableC();
}
break;
@@ -428,7 +428,7 @@ label_callback_2:
goto label_callback_2;
case 4:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_5900;
break;
}
@@ -442,12 +442,12 @@ label_callback_2:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(19, Servers1, function19)
+IMPLEMENT_FUNCTION(19, Waiter2, tatianaClearTableB)
serveTable(savepoint, "969", kEntityTables1, "005H2", "018A", "971", &ENTITY_PARAM(0, 6), 63);
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(20, Servers1, function20)
+IMPLEMENT_FUNCTION(20, Waiter2, ivoComeHere)
switch (savepoint.action) {
default:
break;
@@ -462,8 +462,8 @@ IMPLEMENT_FUNCTION(20, Servers1, function20)
case kActionCallback:
if (getCallback() == 1) {
- getSavePoints()->push(kEntityServers1, kEntityIvo, kAction123712592);
- getEntities()->drawSequenceLeft(kEntityServers1, "BLANK");
+ getSavePoints()->push(kEntityWaiter2, kEntityIvo, kAction123712592);
+ getEntities()->drawSequenceLeft(kEntityWaiter2, "BLANK");
ENTITY_PARAM(0, 7) = 0;
callbackAction();
@@ -473,22 +473,22 @@ IMPLEMENT_FUNCTION(20, Servers1, function20)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(21, Servers1, function21)
+IMPLEMENT_FUNCTION(21, Waiter2, ivoClearTableC)
serveTable(savepoint, "974", kEntityTables2, "009F2", "009G", "976", &ENTITY_PARAM(0, 8), 0, true, &ENTITY_PARAM(0, 5));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(22, Servers1, chapter3)
+IMPLEMENT_FUNCTION(22, Waiter2, chapter3)
switch (savepoint.action) {
default:
break;
case kActionNone:
- setup_chapter3Handler();
+ setup_serving3();
break;
case kActionDefault:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
@@ -503,49 +503,49 @@ IMPLEMENT_FUNCTION(22, Servers1, chapter3)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(23, Servers1, chapter3Handler)
+IMPLEMENT_FUNCTION(23, Waiter2, serving3)
if (savepoint.action != kActionNone)
return;
- if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
+ if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
return;
if (ENTITY_PARAM(1, 1)) {
setCallback(1);
- setup_function24();
+ setup_annaBringTea3();
return;
}
if (ENTITY_PARAM(1, 2)) {
setCallback(2);
- setup_function7();
+ setup_monsieurServeUs();
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(24, Servers1, function24)
+IMPLEMENT_FUNCTION(24, Waiter2, annaBringTea3)
serveSalon(savepoint, "927", "Ann3143A", kEntityAnna, "Ann31444", "112C", kAction122288808, "928", &ENTITY_PARAM(1, 1));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(25, Servers1, chapter4)
+IMPLEMENT_FUNCTION(25, Waiter2, chapter4)
switch (savepoint.action) {
default:
break;
case kActionNone:
- setup_chapter4Handler();
+ setup_serving4();
break;
case kActionDefault:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_5900;
getData()->location = kLocationOutsideCompartment;
getData()->car = kCarRestaurant;
getData()->inventoryItem = kItemNone;
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
ENTITY_PARAM(1, 2) = 0;
ENTITY_PARAM(1, 3) = 0;
@@ -556,7 +556,7 @@ IMPLEMENT_FUNCTION(25, Servers1, chapter4)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(26, Servers1, chapter4Handler)
+IMPLEMENT_FUNCTION(26, Waiter2, serving4)
switch (savepoint.action) {
default:
break;
@@ -569,24 +569,30 @@ IMPLEMENT_FUNCTION(26, Servers1, chapter4Handler)
}
}
- if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
+ if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon())
break;
+ if (ENTITY_PARAM(1, 3)) {
+ setCallback(1);
+ setup_augustNeedsADrink();
+ break;
+ }
+
if (ENTITY_PARAM(1, 5)) {
setCallback(2);
- setup_function28();
+ setup_serveAugustADrink();
break;
}
if (ENTITY_PARAM(1, 4)) {
setCallback(3);
- setup_function29();
+ setup_annaNeedsADrink();
break;
}
if (ENTITY_PARAM(1, 2)) {
setCallback(4);
- setup_function7();
+ setup_monsieurServeUs();
}
break;
@@ -608,22 +614,22 @@ IMPLEMENT_FUNCTION(26, Servers1, chapter4Handler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(27, Servers1, function27)
+IMPLEMENT_FUNCTION(27, Waiter2, augustNeedsADrink)
serveSalon(savepoint, "929", "", kEntityAugust, "Aug4003", "122D", kAction134486752, "930", &ENTITY_PARAM(1, 3));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(28, Servers1, function28)
+IMPLEMENT_FUNCTION(28, Waiter2, serveAugustADrink)
serveSalon(savepoint, "931", "", kEntityAugust, "Aug4004", "122E", kAction125826561, "930", &ENTITY_PARAM(1, 5));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(29, Servers1, function29)
+IMPLEMENT_FUNCTION(29, Waiter2, annaNeedsADrink)
serveSalon(savepoint, "932", "", kEntityAnna, "Ann4151", "127D", kAction122288808, "930", &ENTITY_PARAM(1, 4));
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(30, Servers1, chapter5)
+IMPLEMENT_FUNCTION(30, Waiter2, chapter5)
switch (savepoint.action) {
default:
break;
@@ -633,7 +639,7 @@ IMPLEMENT_FUNCTION(30, Servers1, chapter5)
break;
case kActionDefault:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_3969;
getData()->location = kLocationInsideCompartment;
@@ -644,19 +650,19 @@ IMPLEMENT_FUNCTION(30, Servers1, chapter5)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(31, Servers1, chapter5Handler)
+IMPLEMENT_FUNCTION(31, Waiter2, chapter5Handler)
if (savepoint.action == kActionProceedChapter5)
setup_nullfunction();
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_NULL_FUNCTION(32, Servers1)
+IMPLEMENT_NULL_FUNCTION(32, Waiter2)
//////////////////////////////////////////////////////////////////////////
// Private functions
//////////////////////////////////////////////////////////////////////////
-void Servers1::serveTable(const SavePoint &savepoint, const char *seq1, EntityIndex entity, const char *seq2, const char *seq3, const char *seq4, uint *parameter, Position position, bool shouldUpdatePosition, uint *parameter2) {
+void Waiter2::serveTable(const SavePoint &savepoint, const char *seq1, EntityIndex entity, const char *seq2, const char *seq3, const char *seq4, uint *parameter, Position position, bool shouldUpdatePosition, uint *parameter2) {
switch (savepoint.action) {
default:
break;
@@ -678,9 +684,9 @@ void Servers1::serveTable(const SavePoint &savepoint, const char *seq1, EntityIn
case 1:
if (position)
- getEntities()->updatePositionEnter(kEntityServers1, kCarRestaurant, position);
+ getEntities()->updatePositionEnter(kEntityWaiter2, kCarRestaurant, position);
- getSavePoints()->push(kEntityServers1, entity, kAction136455232);
+ getSavePoints()->push(kEntityWaiter2, entity, kAction136455232);
setCallback(2);
setup_callSavepoint(seq2, entity, kActionDrawTablesWithChairs, seq3);
@@ -688,7 +694,7 @@ void Servers1::serveTable(const SavePoint &savepoint, const char *seq1, EntityIn
case 2:
if (position)
- getEntities()->updatePositionExit(kEntityServers1, kCarRestaurant, position);
+ getEntities()->updatePositionExit(kEntityWaiter2, kCarRestaurant, position);
setCallback(3);
setup_draw(seq4);
@@ -696,7 +702,7 @@ void Servers1::serveTable(const SavePoint &savepoint, const char *seq1, EntityIn
case 3:
getData()->entityPosition = kPosition_5900;
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
*parameter = 0;
if (parameter2 != NULL)
@@ -710,7 +716,7 @@ void Servers1::serveTable(const SavePoint &savepoint, const char *seq1, EntityIn
}
//////////////////////////////////////////////////////////////////////////
-void Servers1::serveSalon(const SavePoint &savepoint, const char *seq1, const char *snd1, EntityIndex entity, const char *snd2, const char *seq2, ActionIndex action, const char *seq3, uint *parameter) {
+void Waiter2::serveSalon(const SavePoint &savepoint, const char *seq1, const char *snd1, EntityIndex entity, const char *snd2, const char *seq2, ActionIndex action, const char *seq3, uint *parameter) {
switch (savepoint.action) {
default:
break;
@@ -729,46 +735,46 @@ void Servers1::serveSalon(const SavePoint &savepoint, const char *seq1, const ch
break;
case 1:
- getEntities()->drawSequenceRight(kEntityServers1, seq1);
+ getEntities()->drawSequenceRight(kEntityWaiter2, seq1);
if (getEntities()->isInRestaurant(kEntityPlayer))
- getEntities()->updateFrame(kEntityServers1);
+ getEntities()->updateFrame(kEntityWaiter2);
if (!strcmp(snd1, ""))
- getSound()->playSound(kEntityServers1, snd1);
+ getSound()->playSound(kEntityWaiter2, snd1);
setCallback(2);
setup_callbackActionOnDirection();
break;
case 2:
- getSavePoints()->push(kEntityServers1, entity, kAction122358304);
+ getSavePoints()->push(kEntityWaiter2, entity, kAction122358304);
- getSound()->playSound(kEntityServers1, snd2);
+ getSound()->playSound(kEntityWaiter2, snd2);
setCallback(3);
setup_updatePosition(seq2, kCarRestaurant, 57);
break;
case 3:
- getSavePoints()->push(kEntityServers1, entity, action);
+ getSavePoints()->push(kEntityWaiter2, entity, action);
setCallback(4);
setup_draw(seq3);
break;
case 4:
- getEntities()->drawSequenceRight(kEntityServers1, "816UD");
+ getEntities()->drawSequenceRight(kEntityWaiter2, "816UD");
if (getEntities()->isInSalon(kEntityPlayer))
- getEntities()->updateFrame(kEntityServers1);
+ getEntities()->updateFrame(kEntityWaiter2);
setCallback(5);
setup_callbackActionOnDirection();
break;
case 5:
- getEntities()->clearSequences(kEntityServers1);
+ getEntities()->clearSequences(kEntityWaiter2);
getData()->entityPosition = kPosition_5900;
*parameter = 0;
diff --git a/engines/lastexpress/entities/servers1.h b/engines/lastexpress/entities/waiter2.h
index 58566cd4d3..e8dc8f48e0 100644
--- a/engines/lastexpress/entities/servers1.h
+++ b/engines/lastexpress/entities/waiter2.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef LASTEXPRESS_SERVERS1_H
-#define LASTEXPRESS_SERVERS1_H
+#ifndef LASTEXPRESS_WAITER2_H
+#define LASTEXPRESS_WAITER2_H
#include "lastexpress/entities/entity.h"
@@ -29,10 +29,10 @@ namespace LastExpress {
class LastExpressEngine;
-class Servers1 : public Entity {
+class Waiter2 : public Entity {
public:
- Servers1(LastExpressEngine *engine);
- ~Servers1() {}
+ Waiter2(LastExpressEngine *engine);
+ ~Waiter2() {}
/**
* Updates parameter 2 using time value
@@ -80,24 +80,19 @@ public:
*/
DECLARE_FUNCTION_1(playSound, const char *filename)
- DECLARE_FUNCTION(function7)
+ DECLARE_FUNCTION(monsieurServeUs)
/**
* Setup Chapter 1
*/
DECLARE_FUNCTION(chapter1)
- DECLARE_FUNCTION(function9)
- DECLARE_FUNCTION(function10)
- DECLARE_FUNCTION(function11)
- DECLARE_FUNCTION(function12)
- DECLARE_FUNCTION(function13)
-
- /**
- * Handle Chapter 1 events
- */
- DECLARE_FUNCTION(chapter1Handler)
-
+ DECLARE_FUNCTION(milosOrder)
+ DECLARE_FUNCTION(monsieurOrder)
+ DECLARE_FUNCTION(clearAlexei)
+ DECLARE_FUNCTION(clearMilos)
+ DECLARE_FUNCTION(clearMonsieur)
+ DECLARE_FUNCTION(servingDinner)
DECLARE_FUNCTION(function15)
DECLARE_FUNCTION(function16)
@@ -105,41 +100,26 @@ public:
* Setup Chapter 2
*/
DECLARE_FUNCTION(chapter2)
-
- /**
- * Handle Chapter 2 events
- */
- DECLARE_FUNCTION(chapter2Handler)
-
- DECLARE_FUNCTION(function19)
- DECLARE_FUNCTION(function20)
- DECLARE_FUNCTION(function21)
+ DECLARE_FUNCTION(inKitchen)
+ DECLARE_FUNCTION(tatianaClearTableB)
+ DECLARE_FUNCTION(ivoComeHere)
+ DECLARE_FUNCTION(ivoClearTableC)
/**
* Setup Chapter 3
*/
DECLARE_FUNCTION(chapter3)
-
- /**
- * Handle Chapter 3 events
- */
- DECLARE_FUNCTION(chapter3Handler)
-
- DECLARE_FUNCTION(function24)
+ DECLARE_FUNCTION(serving3)
+ DECLARE_FUNCTION(annaBringTea3)
/**
* Setup Chapter 4
*/
DECLARE_FUNCTION(chapter4)
-
- /**
- * Handle Chapter 4 events
- */
- DECLARE_FUNCTION(chapter4Handler)
-
- DECLARE_FUNCTION(function27)
- DECLARE_FUNCTION(function28)
- DECLARE_FUNCTION(function29)
+ DECLARE_FUNCTION(serving4)
+ DECLARE_FUNCTION(augustNeedsADrink)
+ DECLARE_FUNCTION(serveAugustADrink)
+ DECLARE_FUNCTION(annaNeedsADrink)
/**
* Setup Chapter 5
@@ -160,4 +140,4 @@ private:
} // End of namespace LastExpress
-#endif // LASTEXPRESS_SERVERS1_H
+#endif // LASTEXPRESS_WAITER2_H
diff --git a/engines/lastexpress/game/action.cpp b/engines/lastexpress/game/action.cpp
index 986c56cb1b..96b97db939 100644
--- a/engines/lastexpress/game/action.cpp
+++ b/engines/lastexpress/game/action.cpp
@@ -1456,7 +1456,7 @@ IMPLEMENT_ACTION(playMusicChapterSetupTrain)
if (!getSoundQueue()->isBuffered(filename) && hotspot.param3 & id) {
getSound()->playSound(kEntityPlayer, filename, kFlagDefault);
- getSavePoints()->call(kEntityPlayer, kEntityTrain, kAction203863200, filename.c_str());
+ getSavePoints()->call(kEntityPlayer, kEntityTrain, kAction203863200, filename);
getSavePoints()->push(kEntityPlayer, kEntityTrain, kAction222746496, hotspot.param2);
}
diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp
index b4b5527f8d..b881d34ebe 100644
--- a/engines/lastexpress/game/entities.cpp
+++ b/engines/lastexpress/game/entities.cpp
@@ -51,8 +51,6 @@
#include "lastexpress/entities/pascale.h"
#include "lastexpress/entities/rebecca.h"
#include "lastexpress/entities/salko.h"
-#include "lastexpress/entities/servers0.h"
-#include "lastexpress/entities/servers1.h"
#include "lastexpress/entities/sophie.h"
#include "lastexpress/entities/tables.h"
#include "lastexpress/entities/tatiana.h"
@@ -60,6 +58,8 @@
#include "lastexpress/entities/vassili.h"
#include "lastexpress/entities/verges.h"
#include "lastexpress/entities/vesna.h"
+#include "lastexpress/entities/waiter1.h"
+#include "lastexpress/entities/waiter2.h"
#include "lastexpress/entities/yasmin.h"
// Game
@@ -134,8 +134,8 @@ Entities::Entities(LastExpressEngine *engine) : _engine(engine) {
ADD_ENTITY(Mertens);
ADD_ENTITY(Coudert);
ADD_ENTITY(Pascale);
- ADD_ENTITY(Servers0);
- ADD_ENTITY(Servers1);
+ ADD_ENTITY(Waiter1);
+ ADD_ENTITY(Waiter2);
ADD_ENTITY(Cooks);
ADD_ENTITY(Verges);
ADD_ENTITY(Tatiana);
@@ -389,7 +389,6 @@ void Entities::resetState(EntityIndex entityIndex) {
getLogic()->updateCursor();
}
-
void Entities::updateFields() const {
if (!getFlags()->isGameRunning)
return;
@@ -897,7 +896,6 @@ void Entities::computeCurrentFrame(EntityIndex entityIndex) const {
}
break;
-
case kDirectionLeft:
if (data->currentFrame == -1 || data->currentFrame >= (int32)data->sequence->count()) {
data->currentFrame = 0;
@@ -1772,8 +1770,7 @@ void Entities::enterCompartment(EntityIndex entity, ObjectIndex compartment, boo
// Update compartments
int index = (compartment < 32 ? compartment - 1 : compartment - 24);
- if (index >= 16)
- error("[Entities::enterCompartment] Invalid compartment index");
+ assert(index < 16);
if (useCompartment1)
_compartments1[index] |= STORE_VALUE(entity);
@@ -1858,8 +1855,7 @@ void Entities::exitCompartment(EntityIndex entity, ObjectIndex compartment, bool
// Update compartments
int index = (compartment < 32 ? compartment - 1 : compartment - 24);
- if (index >= 16)
- error("[Entities::exitCompartment] Invalid compartment index");
+ assert(index < 16);
if (useCompartment1)
_compartments1[index] &= ~STORE_VALUE(entity);
diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp
index 9e02b3bc1d..622d547542 100644
--- a/engines/lastexpress/game/inventory.cpp
+++ b/engines/lastexpress/game/inventory.cpp
@@ -40,7 +40,6 @@
#include "lastexpress/lastexpress.h"
#include "lastexpress/resource.h"
-
namespace LastExpress {
Inventory::Inventory(LastExpressEngine *engine) : _engine(engine), _selectedItem(kItemNone), _highlightedItemIndex(0), _itemsShown(0),
@@ -534,18 +533,18 @@ Common::String Inventory::toString() {
// Private methods
//////////////////////////////////////////////////////////////////////////
InventoryItem Inventory::getFirstExaminableItem() const {
-
int index = 0;
- InventoryEntry entry = _entries[index];
- while (!entry.inPocket || !entry.cursor || entry.floating) {
- index++;
- entry = _entries[index];
+ do {
+ InventoryEntry entry = _entries[index];
- if (index >= kPortraitOriginal)
- return kItemNone;
- }
+ // Check if it is an examinable item
+ if (entry.inPocket && entry.cursor && !entry.floating)
+ return (InventoryItem)index;
+
+ index++;
+ } while (index < kPortraitOriginal);
- return (InventoryItem)index;
+ return kItemNone;
}
bool Inventory::isItemSceneParameter(InventoryItem item) const {
diff --git a/engines/lastexpress/game/savepoint.cpp b/engines/lastexpress/game/savepoint.cpp
index b0186a4ccc..a8483e6d5c 100644
--- a/engines/lastexpress/game/savepoint.cpp
+++ b/engines/lastexpress/game/savepoint.cpp
@@ -28,7 +28,6 @@
#include "lastexpress/lastexpress.h"
-
namespace LastExpress {
SavePoints::SavePoints(LastExpressEngine *engine) : _engine(engine) {
@@ -57,7 +56,7 @@ void SavePoints::push(EntityIndex entity2, EntityIndex entity1, ActionIndex acti
_savepoints.push_back(point);
}
-void SavePoints::push(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const char *param) {
+void SavePoints::push(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const Common::String param) {
if (_savepoints.size() >= _savePointsMaxSize)
return;
@@ -65,7 +64,9 @@ void SavePoints::push(EntityIndex entity2, EntityIndex entity1, ActionIndex acti
point.entity1 = entity1;
point.action = action;
point.entity2 = entity2;
- strcpy((char *)&point.param.charValue, param);
+
+ assert(param.size() <= 5);
+ strncpy((char *)&point.param.charValue, param.c_str(), 5);
_savepoints.push_back(point);
}
@@ -76,7 +77,6 @@ SavePoint SavePoints::pop() {
return point;
}
-
void SavePoints::pushAll(EntityIndex entity, ActionIndex action, uint32 param) {
for (uint32 index = 1; index < 40; index++) {
if ((EntityIndex)index != entity)
@@ -156,16 +156,18 @@ void SavePoints::call(EntityIndex entity2, EntityIndex entity1, ActionIndex acti
}
}
-void SavePoints::call(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const char *param) const {
+void SavePoints::call(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const Common::String param) const {
SavePoint point;
point.entity1 = entity1;
point.action = action;
point.entity2 = entity2;
- strcpy((char *)&point.param.charValue, param);
+
+ assert(param.size() <= 5);
+ strncpy((char *)&point.param.charValue, param.c_str(), 5);
Callback *callback = getCallback(entity1);
if (callback != NULL && callback->isValid()) {
- debugC(8, kLastExpressDebugLogic, "Savepoint: entity1=%s, action=%s, entity2=%s, param=%s", ENTITY_NAME(entity1), ACTION_NAME(action), ENTITY_NAME(entity2), param);
+ debugC(8, kLastExpressDebugLogic, "Savepoint: entity1=%s, action=%s, entity2=%s, param=%s", ENTITY_NAME(entity1), ACTION_NAME(action), ENTITY_NAME(entity2), param.c_str());
(*callback)(point);
}
}
diff --git a/engines/lastexpress/game/savepoint.h b/engines/lastexpress/game/savepoint.h
index 068c54eb0f..ab6490796b 100644
--- a/engines/lastexpress/game/savepoint.h
+++ b/engines/lastexpress/game/savepoint.h
@@ -101,7 +101,7 @@ public:
// Savepoints
void push(EntityIndex entity2, EntityIndex entity1, ActionIndex action, uint32 param = 0);
- void push(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const char *param);
+ void push(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const Common::String param);
void pushAll(EntityIndex entity, ActionIndex action, uint32 param = 0);
void process();
void reset();
@@ -113,7 +113,7 @@ public:
void setCallback(EntityIndex index, Callback *callback);
Callback *getCallback(EntityIndex entity) const;
void call(EntityIndex entity2, EntityIndex entity1, ActionIndex action, uint32 param = 0) const;
- void call(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const char *param) const;
+ void call(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const Common::String param) const;
void callAndProcess();
// Serializable
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index 293c3ab725..90b684ab0b 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -48,7 +48,7 @@
const char *g_actionNames[] = {"None", "Action1", "Action2", "ExitCompartment", "Action4", "ExcuseMeCath", "ExcuseMe", "INVALID", "Knock", "OpenDoor", "Action10", "Action11", "Default", "INVALID", "INVALID", "INVALID", "Action16", "DrawScene", "Callback"};
const char *g_directionNames[] = { "None", "Up", "Down", "Left", "Right", "Switch"};
-const char *g_entityNames[] = { "Player", "Anna", "August", "Mertens", "Coudert", "Pascale", "Servers0", "Servers1", "Cooks", "Verges", "Tatiana", "Vassili", "Alexei", "Abbot", "Milos", "Vesna", "Ivo", "Salko", "Kronos", "Kahina", "Francois", "MmeBoutarel", "Boutarel", "Rebecca", "Sophie", "Mahmud", "Yasmin", "Hadija", "Alouan", "Gendarmes", "Max", "Chapters", "Train", "Tables0", "Tables1", "Tables2", "Tables3", "Tables4", "Tables5", "Entity39"};
+const char *g_entityNames[] = { "Player", "Anna", "August", "Mertens", "Coudert", "Pascale", "Waiter1", "Waiter2", "Cooks", "Verges", "Tatiana", "Vassili", "Alexei", "Abbot", "Milos", "Vesna", "Ivo", "Salko", "Kronos", "Kahina", "Francois", "MmeBoutarel", "Boutarel", "Rebecca", "Sophie", "Mahmud", "Yasmin", "Hadija", "Alouan", "Gendarmes", "Max", "Chapters", "Train", "Tables0", "Tables1", "Tables2", "Tables3", "Tables4", "Tables5", "Entity39"};
namespace LastExpress {
diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk
index 8b3287d5d7..afce0b0749 100644
--- a/engines/lastexpress/module.mk
+++ b/engines/lastexpress/module.mk
@@ -35,8 +35,6 @@ MODULE_OBJS := \
entities/pascale.o \
entities/rebecca.o \
entities/salko.o \
- entities/servers0.o \
- entities/servers1.o \
entities/sophie.o \
entities/tables.o \
entities/tatiana.o \
@@ -44,6 +42,8 @@ MODULE_OBJS := \
entities/vassili.o \
entities/verges.o \
entities/vesna.o \
+ entities/waiter1.o \
+ entities/waiter2.o \
entities/yasmin.o \
fight/fight.o \
fight/fighter.o \
diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h
index c0099db7ac..724c4b3fb4 100644
--- a/engines/lastexpress/shared.h
+++ b/engines/lastexpress/shared.h
@@ -1006,8 +1006,8 @@ enum EntityIndex {
kEntityMertens,
kEntityCoudert,
kEntityPascale, // 5
- kEntityServers0,
- kEntityServers1,
+ kEntityWaiter1,
+ kEntityWaiter2,
kEntityCooks,
kEntityVerges,
kEntityTatiana, // 10
@@ -1409,7 +1409,7 @@ enum ActionIndex {
kAction169032608 = 169032608,
kAction189426612 = 189426612,
kAction203859488 = 203859488,
- kAction219522616 = 219522616, // Servers0
+ kAction219522616 = 219522616, // Waiter1
kAction225182640 = 225182640,
kAction235257824 = 235257824,
@@ -1520,7 +1520,7 @@ enum ActionIndex {
kAction71277948 = 71277948,
kAction158007856 = 158007856,
kAction101687594 = 101687594,
- kAction122358304 = 122358304, // also Servers1/Boutarel?
+ kAction122358304 = 122358304, // also Waiter2/Boutarel?
kActionMaxFreeFromCage = 135204609,
kAction156622016 = 156622016,
diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp
index 6bf1ebc9de..697e6e1269 100644
--- a/engines/lastexpress/sound/entry.cpp
+++ b/engines/lastexpress/sound/entry.cpp
@@ -33,7 +33,6 @@
#include "lastexpress/lastexpress.h"
#include "lastexpress/resource.h"
-
namespace LastExpress {
#define SOUNDCACHE_ENTRY_SIZE 92160
@@ -267,6 +266,8 @@ void SoundEntry::update(uint val) {
}
bool SoundEntry::updateSound() {
+ assert(_name2.size() <= 16);
+
bool result;
char sub[16];
@@ -279,6 +280,7 @@ bool SoundEntry::updateSound() {
_status.status &= ~0x8000;
strcpy(sub, _name2.c_str());
+ // FIXME: Rewrite and document expected behavior
int l = strlen(sub) + 1;
if (l - 1 > 4)
sub[l - (1 + 4)] = 0;
@@ -361,7 +363,10 @@ void SoundEntry::showSubtitle(Common::String filename) {
}
void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) {
- if (_name2.matchString("NISSND?") && (_status.status & kFlagType7) != kFlag3) {
+ assert(_name1.size() <= 16);
+ assert(_name2.size() <= 16);
+
+ if (_name2.matchString("NISSND?") && (_status.status & kFlagType9) != kFlag3) {
s.syncAsUint32LE(_status.status);
s.syncAsUint32LE(_type);
s.syncAsUint32LE(_blockCount); // field_8;
diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp
index 5f55f4e74e..3a2d0c075c 100644
--- a/engines/lastexpress/sound/sound.cpp
+++ b/engines/lastexpress/sound/sound.cpp
@@ -984,22 +984,22 @@ void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag f
playSound(kEntityPlayer, (rnd(2) ? "HDE1002" : "HED1002A"), flag);
break;
- case kEntityServers0:
- case kEntityServers1:
+ case kEntityWaiter1:
+ case kEntityWaiter2:
switch(rnd(3)) {
default:
break;
case 0:
- playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002" : "WAT1003", flag);
+ playSound(kEntityPlayer, (entity == kEntityWaiter1) ? "WAT1002" : "WAT1003", flag);
break;
case 1:
- playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002A" : "WAT1003A", flag);
+ playSound(kEntityPlayer, (entity == kEntityWaiter1) ? "WAT1002A" : "WAT1003A", flag);
break;
case 2:
- playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002B" : "WAT1003B", flag);
+ playSound(kEntityPlayer, (entity == kEntityWaiter1) ? "WAT1002B" : "WAT1003B", flag);
break;
}
break;
diff --git a/engines/lure/debugger.cpp b/engines/lure/debugger.cpp
index bbaa68befa..032186717d 100644
--- a/engines/lure/debugger.cpp
+++ b/engines/lure/debugger.cpp
@@ -35,20 +35,20 @@
namespace Lure {
Debugger::Debugger(): GUI::Debugger() {
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("enter", WRAP_METHOD(Debugger, cmd_enterRoom));
- DCmd_Register("rooms", WRAP_METHOD(Debugger, cmd_listRooms));
- DCmd_Register("fields", WRAP_METHOD(Debugger, cmd_listFields));
- DCmd_Register("setfield", WRAP_METHOD(Debugger, cmd_setField));
- DCmd_Register("queryfield", WRAP_METHOD(Debugger, cmd_queryField));
- DCmd_Register("give", WRAP_METHOD(Debugger, cmd_giveItem));
- DCmd_Register("hotspots", WRAP_METHOD(Debugger, cmd_hotspots));
- DCmd_Register("hotspot", WRAP_METHOD(Debugger, cmd_hotspot));
- DCmd_Register("room", WRAP_METHOD(Debugger, cmd_room));
- DCmd_Register("showanim", WRAP_METHOD(Debugger, cmd_showAnim));
- DCmd_Register("strings", WRAP_METHOD(Debugger, cmd_saveStrings));
- DCmd_Register("debug", WRAP_METHOD(Debugger, cmd_debug));
- DCmd_Register("script", WRAP_METHOD(Debugger, cmd_script));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("enter", WRAP_METHOD(Debugger, cmd_enterRoom));
+ registerCmd("rooms", WRAP_METHOD(Debugger, cmd_listRooms));
+ registerCmd("fields", WRAP_METHOD(Debugger, cmd_listFields));
+ registerCmd("setfield", WRAP_METHOD(Debugger, cmd_setField));
+ registerCmd("queryfield", WRAP_METHOD(Debugger, cmd_queryField));
+ registerCmd("give", WRAP_METHOD(Debugger, cmd_giveItem));
+ registerCmd("hotspots", WRAP_METHOD(Debugger, cmd_hotspots));
+ registerCmd("hotspot", WRAP_METHOD(Debugger, cmd_hotspot));
+ registerCmd("room", WRAP_METHOD(Debugger, cmd_room));
+ registerCmd("showanim", WRAP_METHOD(Debugger, cmd_showAnim));
+ registerCmd("strings", WRAP_METHOD(Debugger, cmd_saveStrings));
+ registerCmd("debug", WRAP_METHOD(Debugger, cmd_debug));
+ registerCmd("script", WRAP_METHOD(Debugger, cmd_script));
}
static int strToInt(const char *s) {
@@ -88,7 +88,7 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) {
// Validate that it's an existing room
if (res.getRoom(roomNumber) == NULL) {
- DebugPrintf("specified number was not a valid room\n");
+ debugPrintf("specified number was not a valid room\n");
return true;
}
@@ -105,9 +105,9 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) {
return false;
}
- DebugPrintf("Syntax: room <roomnum> [<remoteview>]\n");
- DebugPrintf("A non-zero value for reomteview will change the room without ");
- DebugPrintf("moving the player.\n");
+ debugPrintf("Syntax: room <roomnum> [<remoteview>]\n");
+ debugPrintf("A non-zero value for reomteview will change the room without ");
+ debugPrintf("moving the player.\n");
return true;
}
@@ -117,7 +117,7 @@ bool Debugger::cmd_listRooms(int argc, const char **argv) {
char buffer[MAX_DESC_SIZE];
int ctr = 0;
- DebugPrintf("Available rooms are:\n");
+ debugPrintf("Available rooms are:\n");
for (RoomDataList::iterator i = rooms.begin(); i != rooms.end(); ++i) {
RoomData const &room = **i;
// Explictly note the second drawbridge room as "Alt"
@@ -128,20 +128,20 @@ bool Debugger::cmd_listRooms(int argc, const char **argv) {
strings.getString(room.roomNumber, buffer);
}
- DebugPrintf("#%d - %s", room.roomNumber, buffer);
+ debugPrintf("#%d - %s", room.roomNumber, buffer);
- if (++ctr % 3 == 0) DebugPrintf("\n");
+ if (++ctr % 3 == 0) debugPrintf("\n");
else {
// Write out spaces between columns
int numSpaces = 25 - strlen(buffer) - (room.roomNumber >= 10 ? 2 : 1);
char *s = buffer;
while (numSpaces-- > 0) *s++ = ' ';
*s = '\0';
- DebugPrintf("%s", buffer);
+ debugPrintf("%s", buffer);
}
}
- DebugPrintf("\n");
- DebugPrintf("Current room: %d\n", Room::getReference().roomNumber());
+ debugPrintf("\n");
+ debugPrintf("Current room: %d\n", Room::getReference().roomNumber());
return true;
}
@@ -150,11 +150,11 @@ bool Debugger::cmd_listFields(int argc, const char **argv) {
ValueTableData &fields = Resources::getReference().fieldList();
for (int ctr = 0; ctr < fields.size(); ++ctr) {
- DebugPrintf("(%-2d): %-5d", ctr, fields.getField(ctr));
+ debugPrintf("(%-2d): %-5d", ctr, fields.getField(ctr));
if (!((ctr + 1) % 7))
- DebugPrintf("\n");
+ debugPrintf("\n");
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
@@ -167,13 +167,13 @@ bool Debugger::cmd_setField(int argc, const char **argv) {
if ((fieldNum < 0) || (fieldNum >= fields.size())) {
// Invalid field number
- DebugPrintf("Invalid field number specified\n");
+ debugPrintf("Invalid field number specified\n");
} else {
// Set the field value
fields.setField(fieldNum, value);
}
} else {
- DebugPrintf("Syntax: setfield <field_number> <value>\n");
+ debugPrintf("Syntax: setfield <field_number> <value>\n");
}
return true;
@@ -186,14 +186,14 @@ bool Debugger::cmd_queryField(int argc, const char **argv) {
int fieldNum = strToInt(argv[1]);
if ((fieldNum < 0) || (fieldNum >= fields.size())) {
// Invalid field number
- DebugPrintf("Invalid field number specified\n");
+ debugPrintf("Invalid field number specified\n");
} else {
// Get the field value
- DebugPrintf("Field %d is %d (%xh)\n", fieldNum,
+ debugPrintf("Field %d is %d (%xh)\n", fieldNum,
fields.getField(fieldNum), fields.getField(fieldNum));
}
} else {
- DebugPrintf("Syntax: queryfield <field_num>\n");
+ debugPrintf("Syntax: queryfield <field_num>\n");
}
return true;
@@ -215,18 +215,18 @@ bool Debugger::cmd_giveItem(int argc, const char **argv) {
charHotspot = res.getHotspot(charNum);
if (itemHotspot == NULL) {
- DebugPrintf("The specified item does not exist\n");
+ debugPrintf("The specified item does not exist\n");
} else if (itemNum < 0x408) {
- DebugPrintf("The specified item number is not an object\n");
+ debugPrintf("The specified item number is not an object\n");
} else if ((charNum < PLAYER_ID) || (charNum >= 0x408) ||
(charHotspot == NULL)) {
- DebugPrintf("The specified character does not exist");
+ debugPrintf("The specified character does not exist");
} else {
// Set the item's room number to be the destination character
itemHotspot->roomNumber = charNum;
}
} else {
- DebugPrintf("Syntax: give <item_id> [<character_id>]\n");
+ debugPrintf("Syntax: give <item_id> [<character_id>]\n");
}
return true;
@@ -248,7 +248,7 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) {
if (hotspot.nameId() == 0) strcpy(buffer, "none");
else strings.getString(hotspot.nameId(), buffer);
- DebugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId(), buffer,
+ debugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId(), buffer,
hotspot.x(), hotspot.y(), hotspot.roomNumber());
}
} else {
@@ -263,16 +263,16 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) {
if (hotspot.nameId == 0) strcpy(buffer, "none");
else strings.getString(hotspot.nameId, buffer);
- DebugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId, buffer,
+ debugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId, buffer,
hotspot.startX, hotspot.startY, hotspot.roomNumber);
}
}
}
} else {
- DebugPrintf("Syntax: hotspots ['active' | ['room' | 'room' '<room_number>']]\n");
- DebugPrintf("Gives a list of all the currently active hotspots, or the hotspots\n");
- DebugPrintf("present in either the current room or a designated one\n");
+ debugPrintf("Syntax: hotspots ['active' | ['room' | 'room' '<room_number>']]\n");
+ debugPrintf("Gives a list of all the currently active hotspots, or the hotspots\n");
+ debugPrintf("present in either the current room or a designated one\n");
}
return true;
@@ -287,12 +287,12 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) {
Hotspot *h;
if (argc < 2) {
- DebugPrintf("hotspot <hotspot_id> ['paths' | 'schedule' | 'actions' | 'activate' | 'deactivate' | 'setpos']\n");
+ debugPrintf("hotspot <hotspot_id> ['paths' | 'schedule' | 'actions' | 'activate' | 'deactivate' | 'setpos']\n");
return true;
}
hs = res.getHotspot(strToInt(argv[1]));
if (!hs) {
- DebugPrintf("Unknown hotspot specified\n");
+ debugPrintf("Unknown hotspot specified\n");
return true;
}
@@ -300,26 +300,26 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) {
if (argc == 2) {
// Show the hotspot properties
strings.getString(hs->nameId, buffer);
- DebugPrintf("name = %d - %s, descs = (%d,%d)\n", hs->nameId, buffer,
+ debugPrintf("name = %d - %s, descs = (%d,%d)\n", hs->nameId, buffer,
hs->descId, hs->descId2);
- DebugPrintf("actions = %xh, offset = %xh\n", hs->actions, hs->actionsOffset);
- DebugPrintf("flags = %xh, layer = %d\n", hs->flags, hs->layer);
- DebugPrintf("position = %d,%d,%d\n", hs->startX, hs->startY, hs->roomNumber);
- DebugPrintf("size = %d,%d, alt = %d,%d, yCorrection = %d\n",
+ debugPrintf("actions = %xh, offset = %xh\n", hs->actions, hs->actionsOffset);
+ debugPrintf("flags = %xh, layer = %d\n", hs->flags, hs->layer);
+ debugPrintf("position = %d,%d,%d\n", hs->startX, hs->startY, hs->roomNumber);
+ debugPrintf("size = %d,%d, alt = %d,%d, yCorrection = %d\n",
hs->width, hs->height, hs->widthCopy, hs->heightCopy, hs->yCorrection);
- DebugPrintf("Talk bubble offset = %d,%d\n", hs->talkX, hs->talkY);
- DebugPrintf("load offset = %xh, script load = %d\n", hs->loadOffset, hs->scriptLoadFlag);
- DebugPrintf("Animation Id = %xh, Color offset = %d\n", hs->animRecordId, hs->colorOffset);
- DebugPrintf("Talk Script offset = %xh, Tick Script offset = %xh\n",
+ debugPrintf("Talk bubble offset = %d,%d\n", hs->talkX, hs->talkY);
+ debugPrintf("load offset = %xh, script load = %d\n", hs->loadOffset, hs->scriptLoadFlag);
+ debugPrintf("Animation Id = %xh, Color offset = %d\n", hs->animRecordId, hs->colorOffset);
+ debugPrintf("Talk Script offset = %xh, Tick Script offset = %xh\n",
hs->talkScriptOffset, hs->tickScriptOffset);
- DebugPrintf("Tick Proc offset = %xh\n", hs->tickProcId);
- DebugPrintf("Tick timeout = %d\n", hs->tickTimeout);
- DebugPrintf("Character mode = %d, delay ctr = %d, pause ctr = %d\n",
+ debugPrintf("Tick Proc offset = %xh\n", hs->tickProcId);
+ debugPrintf("Tick timeout = %d\n", hs->tickTimeout);
+ debugPrintf("Character mode = %d, delay ctr = %d, pause ctr = %d\n",
hs->characterMode, hs->delayCtr, hs->pauseCtr);
if (h != NULL) {
- DebugPrintf("Frame Number = %d of %d\n", h->frameNumber(), h->numFrames());
- DebugPrintf("Persistent = %s\n", h->persistant() ? "true" : "false");
+ debugPrintf("Frame Number = %d of %d\n", h->frameNumber(), h->numFrames());
+ debugPrintf("Persistent = %s\n", h->persistant() ? "true" : "false");
}
} else if (strcmp(argv[2], "actions") == 0) {
@@ -329,42 +329,42 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) {
const char *actionStr = stringList.getString(action);
if (offset >= 0x8000) {
- DebugPrintf("%s - Message %xh\n", actionStr, offset & 0x7ff);
+ debugPrintf("%s - Message %xh\n", actionStr, offset & 0x7ff);
} else if (offset != 0) {
- DebugPrintf("%s - Script %xh\n", actionStr, offset);
+ debugPrintf("%s - Script %xh\n", actionStr, offset);
}
}
} else if (strcmp(argv[2], "activate") == 0) {
// Activate the hotspot
res.activateHotspot(hs->hotspotId);
hs->flags &= ~HOTSPOTFLAG_MENU_EXCLUSION;
- DebugPrintf("Activated\n");
+ debugPrintf("Activated\n");
} else if (strcmp(argv[2], "deactivate") == 0) {
// Deactivate the hotspot
res.deactivateHotspot(hs->hotspotId);
hs->flags |= HOTSPOTFLAG_MENU_EXCLUSION;
- DebugPrintf("Deactivated\n");
+ debugPrintf("Deactivated\n");
} else {
if (strcmp(argv[2], "schedule") == 0) {
// List any current schedule for the character
- DebugPrintf("%s", hs->npcSchedule.getDebugInfo().c_str());
+ debugPrintf("%s", hs->npcSchedule.getDebugInfo().c_str());
}
if (!h)
- DebugPrintf("The specified hotspot is not currently active\n");
+ debugPrintf("The specified hotspot is not currently active\n");
else if (strcmp(argv[2], "paths") == 0) {
// List any paths for a charcter
- DebugPrintf("%s", h->pathFinder().getDebugInfo().c_str());
+ debugPrintf("%s", h->pathFinder().getDebugInfo().c_str());
}
else if (strcmp(argv[2], "pixels") == 0) {
// List the pixel data for the hotspot
HotspotAnimData &pData = h->anim();
- DebugPrintf("Record Id = %xh\n", pData.animRecordId);
- DebugPrintf("Flags = %d\n", pData.flags);
- DebugPrintf("Frames: up=%d down=%d left=%d right=%d\n",
+ debugPrintf("Record Id = %xh\n", pData.animRecordId);
+ debugPrintf("Flags = %d\n", pData.flags);
+ debugPrintf("Frames: up=%d down=%d left=%d right=%d\n",
pData.upFrame, pData.downFrame, pData.leftFrame, pData.rightFrame);
- DebugPrintf("Current frame = %d of %d\n", h->frameNumber(), h->numFrames());
+ debugPrintf("Current frame = %d of %d\n", h->frameNumber(), h->numFrames());
}
else if (strcmp(argv[2], "setpos") == 0) {
// Set the hotspot position
@@ -372,11 +372,11 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) {
h->setPosition(strToInt(argv[3]), strToInt(argv[4]));
if (argc >= 6)
h->setRoomNumber(strToInt(argv[5]));
- DebugPrintf("Done.\n");
+ debugPrintf("Done.\n");
}
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
@@ -388,56 +388,56 @@ bool Debugger::cmd_room(int argc, const char **argv) {
char buffer[MAX_DESC_SIZE];
if (argc < 2) {
- DebugPrintf("room <room_number>\n");
+ debugPrintf("room <room_number>\n");
return true;
}
int roomNumber = strToInt(argv[1]);
RoomData *room = res.getRoom(roomNumber);
if (!room) {
- DebugPrintf("Unknown room specified\n");
+ debugPrintf("Unknown room specified\n");
return true;
}
// Show the room details
strings.getString(roomNumber, buffer);
- DebugPrintf("room #%d - %s\n", roomNumber, buffer);
+ debugPrintf("room #%d - %s\n", roomNumber, buffer);
strings.getString(room->descId, buffer);
- DebugPrintf("%s\n", buffer);
- DebugPrintf("Horizontal clipping = %d->%d walk area=(%d,%d)-(%d,%d)\n",
+ debugPrintf("%s\n", buffer);
+ debugPrintf("Horizontal clipping = %d->%d walk area=(%d,%d)-(%d,%d)\n",
room->clippingXStart, room->clippingXEnd,
room->walkBounds.left, room->walkBounds.top,
room->walkBounds.right, room->walkBounds.bottom);
- DebugPrintf("Exit hotspots:");
+ debugPrintf("Exit hotspots:");
RoomExitHotspotList &exits = room->exitHotspots;
if (exits.empty())
- DebugPrintf(" none\n");
+ debugPrintf(" none\n");
else {
RoomExitHotspotList::iterator i;
for (i = exits.begin(); i != exits.end(); ++i) {
RoomExitHotspotData const &rec = **i;
- DebugPrintf("\nArea - (%d,%d)-(%d,%d) Room=%d Cursor=%d Hotspot=%xh",
+ debugPrintf("\nArea - (%d,%d)-(%d,%d) Room=%d Cursor=%d Hotspot=%xh",
rec.xs, rec.ys, rec.xe, rec.ye, rec.destRoomNumber, rec.cursorNum, rec.hotspotId);
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
- DebugPrintf("Room exits:");
+ debugPrintf("Room exits:");
if (room->exits.empty())
- DebugPrintf(" none\n");
+ debugPrintf(" none\n");
else {
RoomExitList::iterator i2;
for (i2 = room->exits.begin(); i2 != room->exits.end(); ++i2) {
RoomExitData const &rec2 = **i2;
- DebugPrintf("\nExit - (%d,%d)-(%d,%d) Dest=%d,(%d,%d) Dir=%s Sequence=%xh",
+ debugPrintf("\nExit - (%d,%d)-(%d,%d) Dest=%d,(%d,%d) Dir=%s Sequence=%xh",
rec2.xs, rec2.ys, rec2.xe, rec2.ye, rec2.roomNumber,
rec2.x, rec2.y, directionList[rec2.direction], rec2.sequenceOffset);
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
return true;
@@ -446,7 +446,7 @@ bool Debugger::cmd_room(int argc, const char **argv) {
bool Debugger::cmd_showAnim(int argc, const char **argv) {
Resources &res = Resources::getReference();
if (argc < 2) {
- DebugPrintf("showAnim animId [[frame_width frame_height] | list]\n");
+ debugPrintf("showAnim animId [[frame_width frame_height] | list]\n");
return true;
}
@@ -454,7 +454,7 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) {
int animId = strToInt(argv[1]);
HotspotAnimData *data = res.getAnimation(animId);
if (data == NULL) {
- DebugPrintf("No such animation Id exists\n");
+ debugPrintf("No such animation Id exists\n");
return true;
}
@@ -500,7 +500,7 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) {
height = strToInt(argv[3]);
if ((width * height) != (frameSize * 2)) {
- DebugPrintf("Warning: Total size = %d, Frame size (%d,%d) * %d frames = %d bytes\n",
+ debugPrintf("Warning: Total size = %d, Frame size (%d,%d) * %d frames = %d bytes\n",
destSize, width, height, numFrames, width * height * numFrames / 2);
}
} else {
@@ -511,25 +511,25 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) {
width = frameSize * 3 / 4;
bool descFlag = (argc == 3);
- if (descFlag) DebugPrintf("Target size = %d\n", frameSize * 2);
+ if (descFlag) debugPrintf("Target size = %d\n", frameSize * 2);
while ((width > 0) && (descFlag || (((frameSize * 2) % width) != 0))) {
if (((frameSize * 2) % width) == 0)
- DebugPrintf("Frame size (%d,%d) found\n", width, frameSize * 2 / width);
+ debugPrintf("Frame size (%d,%d) found\n", width, frameSize * 2 / width);
--width;
}
if (argc == 3) {
- DebugPrintf("Done\n");
+ debugPrintf("Done\n");
return true;
} else if (width == 0) {
- DebugPrintf("Total size = %d, # frames = %d, frame Size = %d - No valid frame dimensions\n",
+ debugPrintf("Total size = %d, # frames = %d, frame Size = %d - No valid frame dimensions\n",
destSize, numFrames, frameSize);
return true;
}
height = (frameSize * 2) / width;
- DebugPrintf("# frames = %d, guestimated frame size = (%d,%d)\n",
+ debugPrintf("# frames = %d, guestimated frame size = (%d,%d)\n",
numFrames, width, height);
}
@@ -544,13 +544,13 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) {
hotspot->setAnimation(animId);
- DebugPrintf("Done\n");
+ debugPrintf("Done\n");
return true;
}
bool Debugger::cmd_saveStrings(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("strings <stringId>\n");
+ debugPrintf("strings <stringId>\n");
return true;
}
@@ -558,13 +558,13 @@ bool Debugger::cmd_saveStrings(int argc, const char **argv) {
char *buffer = (char *)malloc(32768);
if (!buffer) {
- DebugPrintf("Cannot allocate strings buffer\n");
+ debugPrintf("Cannot allocate strings buffer\n");
return true;
}
uint16 id = strToInt(argv[1]);
- strings.getString(id, buffer, NULL, NULL);
- DebugPrintf("%s\n", buffer);
+ strings.getString(id, buffer);
+ debugPrintf("%s\n", buffer);
/* Commented out code for saving all text strings - note that 0x1000 is chosen
* arbitrarily, so there'll be a bunch of garbage at the end, or the game will crash
@@ -580,7 +580,7 @@ bool Debugger::cmd_saveStrings(int argc, const char **argv) {
fclose(f);
- DebugPrintf("Done\n");
+ debugPrintf("Done\n");
*/
free(buffer);
@@ -593,16 +593,16 @@ bool Debugger::cmd_debug(int argc, const char **argv) {
Room &room = Room::getReference();
if ((argc == 2) && (strcmp(argv[1], "on") == 0)) {
- DebugPrintf("debug keys are on\n");
+ debugPrintf("debug keys are on\n");
game.debugFlag() = true;
} else if ((argc == 2) && (strcmp(argv[1], "off") == 0)) {
- DebugPrintf("debug keys are off\n");
+ debugPrintf("debug keys are off\n");
game.debugFlag() = false;
room.setShowInfo(false);
} else {
- DebugPrintf("debug [on | off]]\n");
+ debugPrintf("debug [on | off]]\n");
}
return true;
@@ -610,13 +610,13 @@ bool Debugger::cmd_debug(int argc, const char **argv) {
bool Debugger::cmd_script(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("script <script number> [param 1] [param 2] [param 3] [exit flag]\n");
+ debugPrintf("script <script number> [param 1] [param 2] [param 3] [exit flag]\n");
return true;
}
int scriptNumber = strToInt(argv[1]);
if ((scriptNumber < 0) || (scriptNumber > 66)) {
- DebugPrintf("An invalid script number was specified\n");
+ debugPrintf("An invalid script number was specified\n");
return true;
}
@@ -629,7 +629,7 @@ bool Debugger::cmd_script(int argc, const char **argv) {
param3 = strToInt(argv[4]);
Script::executeMethod(scriptNumber, param1, param2, param3);
- DebugPrintf("Script executed\n");
+ debugPrintf("Script executed\n");
return true;
}
diff --git a/engines/made/database.cpp b/engines/made/database.cpp
index 85a8a5ca4a..a9855ba1fe 100644
--- a/engines/made/database.cpp
+++ b/engines/made/database.cpp
@@ -456,7 +456,7 @@ void GameDatabaseV2::load(Common::SeekableReadStream &sourceS) {
for (int section = 0; section < 2; section++) {
while (!sourceS.eos()) {
int16 objIndex = sourceS.readUint16LE();
- debug("objIndex = %04X; section = %d", objIndex, section);
+ debug(1, "objIndex = %04X; section = %d", objIndex, section);
if (objIndex == 0)
break;
Object *obj = new ObjectV1();
diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp
index 1bb328c7a2..2c75965976 100644
--- a/engines/made/resource.cpp
+++ b/engines/made/resource.cpp
@@ -441,7 +441,8 @@ void ResourceReader::openResourceBlocks() {
}
void ResourceReader::openResourceBlock(const char *filename, Common::File *blockFile, uint32 resType) {
- blockFile->open(filename);
+ if (!blockFile->open(filename))
+ error("Failed to open '%s'", filename);
blockFile->readUint16LE(); // Skip unused
uint16 count = blockFile->readUint16LE();
diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp
index c27b781dda..edccb68953 100644
--- a/engines/made/screen.cpp
+++ b/engines/made/screen.cpp
@@ -368,6 +368,9 @@ uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, int16 flipX, int16 f
return 0;
PictureResource *flex = _vm->_res->getPicture(flexIndex);
+ if (!flex)
+ error("Failed to find picture %d", flexIndex);
+
Graphics::Surface *sourceSurface = flex->getPicture();
drawSurface(sourceSurface, x, y, flipX, flipY, mask, clipInfo);
diff --git a/engines/mads/action.cpp b/engines/mads/action.cpp
new file mode 100644
index 0000000000..199ae39000
--- /dev/null
+++ b/engines/mads/action.cpp
@@ -0,0 +1,708 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/action.h"
+#include "mads/inventory.h"
+#include "mads/resources.h"
+#include "mads/scene.h"
+#include "mads/staticres.h"
+
+namespace MADS {
+
+void ActionDetails::synchronize(Common::Serializer &s) {
+ s.syncAsUint16LE(_verbId);
+ s.syncAsUint16LE(_objectNameId);
+ s.syncAsUint16LE(_indirectObjectId);
+}
+
+void ActionSavedFields::synchronize(Common::Serializer &s) {
+ s.syncAsByte(_commandError);
+ s.syncAsSint16LE(_commandSource);
+ s.syncAsSint16LE(_command);
+ s.syncAsSint16LE(_mainObject);
+ s.syncAsSint16LE(_secondObject);
+ s.syncAsSint16LE(_mainObjectSource);
+ s.syncAsSint16LE(_secondObjectSource);
+ s.syncAsSint16LE(_articleNumber);
+ s.syncAsSint16LE(_lookFlag);
+}
+
+/*------------------------------------------------------------------------*/
+
+MADSAction::MADSAction(MADSEngine *vm) : _vm(vm) {
+ clear();
+ _statusTextIndex = -1;
+ _selectedAction = 0;
+ _inProgress = false;
+ _pickedWord = -1;
+
+ _savedFields._commandSource = CAT_NONE;
+ _savedFields._mainObjectSource = CAT_NONE;
+ _savedFields._command = -1;
+ _savedFields._mainObject = 0;
+ _savedFields._secondObject = 0;
+ _savedFields._secondObjectSource = CAT_NONE;
+ _savedFields._articleNumber = PREP_NONE;
+ _savedFields._lookFlag = false;
+
+ _activeAction._verbId = VERB_NONE;
+ _activeAction._objectNameId = -1;
+ _activeAction._indirectObjectId = -1;
+ _savedFields._commandError = false;
+ _verbType = VERB_INIT;
+ _prepType = PREP_NONE;
+}
+
+void MADSAction::clear() {
+ _interAwaiting = AWAITING_COMMAND;
+ _commandSource = CAT_NONE;
+ _mainObjectSource = CAT_NONE;
+ _secondObjectSource = CAT_NONE;
+ _recentCommandSource = CAT_NONE;
+ _articleNumber = 0;
+ _lookFlag = false;
+ _pointEstablished = 0;
+ _statusText.clear();
+ _selectedRow = -1;
+ _hotspotId = -1;
+ _secondObject = -1;
+ _recentCommand = -1;
+ _action._verbId = VERB_NONE;
+ _action._objectNameId = -1;
+ _action._indirectObjectId = -1;
+ _textChanged = true;
+}
+
+void MADSAction::appendVocab(int vocabId, bool capitalize) {
+ Common::String vocabStr = _vm->_game->_scene.getVocab(vocabId);
+ if (capitalize)
+ vocabStr.setChar(toupper(vocabStr[0]), 0);
+
+ _statusText += vocabStr;
+ _statusText += " ";
+}
+
+void MADSAction::startWalkingDirectly(int walkType) {
+ Scene &scene = _vm->_game->_scene;
+ Player &player = _vm->_game->_player;
+
+ if (_pointEstablished && (walkType == -3 || _savedFields._command < 0)) {
+ player._needToWalk = true;
+ player._prepareWalkPos = scene._customDest;
+ }
+}
+
+void MADSAction::set() {
+ Scene &scene = _vm->_game->_scene;
+ UserInterface &userInterface = scene._userInterface;
+ _statusText = "";
+
+ _action._verbId = VERB_NONE;
+ _action._objectNameId = -1;
+ _action._indirectObjectId = -1;
+
+ if (_commandSource == CAT_TALK_ENTRY) {
+ // Handle showing the conversation selection. Rex at least doesn't actually seem to use this
+ if (_selectedRow >= 0) {
+ _action._verbId = userInterface._talkIds[_selectedRow];
+ Common::String desc = userInterface._talkStrings[_selectedRow];
+ if (!desc.empty())
+ _statusText = desc;
+ }
+ } else if (_lookFlag && (_selectedRow == 0)) {
+ // Two 'look' actions in succession, so the action becomes 'Look around'
+ _statusText = kLookAroundStr;
+ } else {
+ bool flag = false;
+ if ((_commandSource == CAT_INV_VOCAB) && (_selectedRow >= 0)
+ && (_verbType == VERB_THAT) && (_prepType == PREP_NONE)) {
+ // Use/to action
+ int invIndex = userInterface._selectedInvIndex;
+ InventoryObject &objEntry = _vm->_game->_objects.getItem(invIndex);
+
+ _action._objectNameId = objEntry._descId;
+ _action._verbId = objEntry._vocabList[_selectedRow]._vocabId;
+
+ // Set up the status text string
+ _statusText = kUseStr;
+ appendVocab(_action._objectNameId);
+ _statusText += kToStr;
+ appendVocab(_action._verbId);
+ } else {
+ // Handling for if an action has been selected
+ if (_selectedRow >= 0) {
+ if (_commandSource == CAT_COMMAND) {
+ // Standard verb action
+ _action._verbId = scene._verbList[_selectedRow]._id;
+ } else {
+ // Selected action on an inventory object
+ int invIndex = userInterface._selectedInvIndex;
+ InventoryObject &objEntry = _vm->_game->_objects.getItem(invIndex);
+
+ _action._verbId = objEntry._vocabList[_selectedRow]._vocabId;
+ }
+
+ appendVocab(_action._verbId, true);
+
+ if (_action._verbId == VERB_LOOK) {
+ // Add in the word 'add'
+ _statusText += kArticleList[PREP_AT];
+ _statusText += " ";
+ }
+ }
+
+ // Add in any necessary article if necessary
+ if ((_hotspotId >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_verbType == VERB_THAT)) {
+ flag = true;
+
+ _statusText += kArticleList[_articleNumber];
+ _statusText += " ";
+ }
+
+ // Handling for hotspot
+ if (_hotspotId >= 0) {
+ if (_selectedRow < 0) {
+ int verbId;
+
+ if (_hotspotId < (int)scene._hotspots.size()) {
+ // Get the verb Id from the hotspot
+ verbId = scene._hotspots[_hotspotId]._verbId;
+ } else {
+ // Get the verb Id from the scene object
+ verbId = scene._dynamicHotspots.get(_hotspotId - scene._hotspots.size())._verbId;
+ }
+
+ if (verbId > 0) {
+ // Set the specified action
+ _action._verbId = verbId;
+ appendVocab(_action._verbId, true);
+ } else {
+ // Default to a standard 'walk to'
+ _action._verbId = VERB_WALKTO;
+ _statusText += kWalkToStr;
+ }
+ }
+
+ if ((_mainObjectSource == CAT_INV_LIST) || (_mainObjectSource == CAT_INV_ANIM)) {
+ // Get name from given inventory object
+ InventoryObject &invObject = _vm->_game->_objects.getItem(_hotspotId);
+ _action._objectNameId = invObject._descId;
+ } else if (_hotspotId < (int)scene._hotspots.size()) {
+ // Get name from scene hotspot
+ _action._objectNameId = scene._hotspots[_hotspotId]._vocabId;
+ } else {
+ // Get name from temporary scene hotspot
+ _action._objectNameId = scene._dynamicHotspots.get(_hotspotId - scene._hotspots.size())._descId;
+ }
+ appendVocab(_action._objectNameId);
+ }
+ }
+
+ if (_secondObject >= 0) {
+ if (_secondObjectSource == CAT_INV_LIST || _secondObjectSource == CAT_INV_ANIM) {
+ InventoryObject &invObject = _vm->_game->_objects.getItem(_secondObject);
+ _action._indirectObjectId = invObject._descId;
+ } else if (_secondObject < (int)scene._hotspots.size()) {
+ _action._indirectObjectId = scene._hotspots[_secondObject]._vocabId;
+ } else {
+ _action._indirectObjectId = scene._dynamicHotspots.get(_secondObject - scene._hotspots.size())._descId;
+ }
+ }
+
+ if ((_hotspotId >= 0) && (_articleNumber > 0) && !flag) {
+ if (_articleNumber == PREP_RELATIONAL) {
+ if (_secondObject >= 0) {
+ int articleNum = 0;
+
+ if ((_secondObjectSource == 2) || (_secondObjectSource == 5)) {
+ InventoryObject &invObject = _vm->_game->_objects.getItem(_secondObject);
+ articleNum = invObject._article;
+ } else if (_secondObject < (int)scene._hotspots.size()) {
+ articleNum = scene._hotspots[_secondObject]._articleNumber;
+ } else {
+ articleNum = scene._dynamicHotspots.get(_secondObject - scene._hotspots.size())._articleNumber;
+ }
+
+ _statusText += kArticleList[articleNum];
+ }
+ } else if ((_articleNumber != VERB_LOOK) || (_vm->getGameID() != GType_RexNebular) ||
+ (_action._indirectObjectId >= 0 && scene.getVocab(_action._indirectObjectId) != kFenceStr)) {
+ // Write out the article
+ _statusText += kArticleList[_articleNumber];
+ } else {
+ // Special case for a 'fence' entry in Rex Nebular
+ _statusText += kOverStr;
+ }
+
+ _statusText += " ";
+ }
+
+ // Append object description if necessary
+ if (_secondObject >= 0)
+ appendVocab(_action._indirectObjectId);
+
+ // Remove any trailing space character
+ if (_statusText.hasSuffix(" "))
+ _statusText.deleteLastChar();
+ }
+
+ _textChanged = true;
+}
+
+void MADSAction::refresh() {
+ Scene &scene = _vm->_game->_scene;
+
+ // Exit immediately if nothing has changed
+ if (!_textChanged)
+ return;
+
+ // Remove any old copy of the status text
+ if (_statusTextIndex >= 0) {
+ scene._textDisplay.expire(_statusTextIndex);
+ _statusTextIndex = -1;
+ }
+
+ if (!_statusText.empty()) {
+ if ((_vm->_game->_screenObjects._inputMode == kInputBuildingSentences) ||
+ (_vm->_game->_screenObjects._inputMode == kInputLimitedSentences)) {
+ Font *font = _vm->_font->getFont(FONT_MAIN);
+ int textSpacing = -1;
+
+ int strWidth = font->getWidth(_statusText);
+ if (strWidth > MADS_SCREEN_WIDTH) {
+ // Too large to fit, so fall back on interface font
+ font = _vm->_font->getFont(FONT_INTERFACE);
+ strWidth = font->getWidth(_statusText, 0);
+ textSpacing = 0;
+ }
+
+ // Add a new text display entry to display the status text at the bottom of the screen area
+ _statusTextIndex = scene._textDisplay.add(160 - (strWidth / 2),
+ MADS_SCENE_HEIGHT + scene._posAdjust.y - 13, 3, textSpacing, _statusText, font);
+ }
+ }
+
+ _textChanged = false;
+}
+
+void MADSAction::startAction() {
+ Game &game = *_vm->_game;
+ Player &player = game._player;
+ Scene &scene = _vm->_game->_scene;
+ DynamicHotspots &dynHotspots = scene._dynamicHotspots;
+ Hotspots &hotspots = scene._hotspots;
+
+ player.cancelCommand();
+
+ _inProgress = true;
+ _savedFields._commandError = false;
+ _savedFields._command = _selectedRow;
+ _savedFields._mainObject = _hotspotId;
+ _savedFields._secondObject = _secondObject;
+ _savedFields._articleNumber = _articleNumber;
+ _savedFields._commandSource = _commandSource;
+ _savedFields._mainObjectSource = _mainObjectSource;
+ _savedFields._secondObjectSource = _secondObjectSource;
+ _savedFields._lookFlag = _lookFlag;
+ _activeAction = _action;
+
+ // Copy the action to be active
+ _activeAction = _action;
+ _sentence = _statusText;
+
+ if ((_mainObjectSource == CAT_HOTSPOT) && (_secondObjectSource == 4))
+ _savedFields._commandError = true;
+
+ player._needToWalk = false;
+ int hotspotId = -1;
+
+ if (!_savedFields._lookFlag && (_vm->_game->_screenObjects._inputMode != kInputConversation)) {
+ if (_savedFields._mainObjectSource == CAT_HOTSPOT)
+ hotspotId = _savedFields._mainObject;
+ else if (_secondObjectSource == 4)
+ hotspotId = _savedFields._secondObject;
+
+ if (hotspotId >= (int)hotspots.size()) {
+ DynamicHotspot &hs = dynHotspots.get(hotspotId - hotspots.size());
+ if ((hs._feetPos.x == -1) || (hs._feetPos.x == -3)) {
+ startWalkingDirectly(hs._feetPos.x);
+ } else if (hs._feetPos.x < 0) {
+ player._prepareWalkFacing = hs._facing;
+ } else if (_savedFields._commandSource == CAT_NONE || hs._cursor < CURSOR_WAIT) {
+ player._needToWalk = true;
+ player._prepareWalkPos = hs._feetPos;
+ }
+
+ player._prepareWalkFacing = hs._facing;
+ hotspotId = -1;
+ }
+ }
+
+ if (hotspotId >= 0) {
+ Hotspot &hs = hotspots[hotspotId];
+
+ if (hs._feetPos.x == -1 || hs._feetPos.x == -3) {
+ startWalkingDirectly(hs._feetPos.x);
+ } else if (hs._feetPos.x >= 0) {
+ if (_savedFields._commandSource == CAT_NONE || hs._cursor < CURSOR_WAIT) {
+ player._needToWalk = true;
+ player._prepareWalkPos = hs._feetPos;
+ }
+ }
+
+ player._prepareWalkFacing = hs._facing;
+ }
+
+ player._readyToWalk = player._needToWalk;
+}
+
+void MADSAction::checkAction() {
+ if (isAction(VERB_LOOK) || isAction(VERB_THROW))
+ _vm->_game->_player._needToWalk = false;
+}
+
+bool MADSAction::isAction(int verbId, int objectNameId, int indirectObjectId) {
+ if (_activeAction._verbId != verbId)
+ return false;
+ if ((objectNameId != 0) && (_activeAction._objectNameId != objectNameId))
+ return false;
+ if ((indirectObjectId != 0) && (_activeAction._indirectObjectId != indirectObjectId))
+ return false;
+
+ return true;
+}
+
+bool MADSAction::isObject(int objectNameId) {
+ return _activeAction._objectNameId == objectNameId;
+}
+
+bool MADSAction::isTarget(int objectNameId) {
+ return _activeAction._indirectObjectId == objectNameId;
+}
+
+void MADSAction::checkActionAtMousePos() {
+ Scene &scene = _vm->_game->_scene;
+ UserInterface &userInterface = scene._userInterface;
+
+ if ((userInterface._category == CAT_COMMAND || userInterface._category == CAT_INV_VOCAB) &&
+ _interAwaiting != AWAITING_COMMAND && _pickedWord >= 0) {
+ if (_recentCommandSource == userInterface._category || _recentCommand != _pickedWord ||
+ (_interAwaiting != AWAITING_THIS && _interAwaiting != 3))
+ clear();
+ else if (_selectedRow != 0 || userInterface._category != CAT_COMMAND)
+ scene._lookFlag = false;
+ else
+ scene._lookFlag = true;
+ }
+
+ if (_vm->_events->_rightMousePressed && _vm->_events->_mouseButtons) {
+ switch (userInterface._category) {
+ case CAT_COMMAND:
+ case CAT_INV_VOCAB:
+ return;
+
+ case CAT_INV_LIST:
+ case CAT_HOTSPOT:
+ case CAT_INV_ANIM:
+ if (_interAwaiting != AWAITING_THAT) {
+ if (userInterface._selectedActionIndex >= 0) {
+ _commandSource = CAT_COMMAND;
+ _selectedRow = userInterface._selectedActionIndex;
+ _verbType = scene._verbList[_selectedRow]._verbType;
+ _prepType = scene._verbList[_selectedRow]._prepType;
+ _interAwaiting = AWAITING_THIS;
+ } else if (userInterface._selectedItemVocabIdx >= 0) {
+ _commandSource = CAT_INV_VOCAB;
+ _selectedRow = userInterface._selectedItemVocabIdx;
+ int objectId = _vm->_game->_objects._inventoryList[_selectedRow];
+ InventoryObject &invObject = _vm->_game->_objects[objectId];
+
+ _verbType = invObject._vocabList[_selectedRow - 1]._verbType;
+ _prepType = invObject._vocabList[_selectedRow - 1]._prepType;
+ _mainObjectSource = CAT_INV_LIST;
+ _hotspotId = userInterface._selectedInvIndex;
+ _articleNumber = _prepType;
+
+ if ((_verbType == VERB_THIS && _prepType == PREP_NONE) ||
+ (_verbType == VERB_THAT && _prepType != PREP_NONE))
+ _interAwaiting = AWAITING_RIGHT_MOUSE;
+ else
+ _interAwaiting = AWAITING_THAT;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ switch (_interAwaiting) {
+ case AWAITING_COMMAND:
+ _articleNumber = 0;
+ switch (userInterface._category) {
+ case CAT_COMMAND:
+ _commandSource = CAT_COMMAND;
+ _selectedRow = _pickedWord;
+ if (_selectedRow >= 0) {
+ _verbType = scene._verbList[_selectedRow]._verbType;
+ _prepType = scene._verbList[_selectedRow]._prepType;
+ }
+ break;
+
+ case CAT_INV_VOCAB:
+ _commandSource = CAT_INV_VOCAB;
+ _selectedRow = _pickedWord;
+ if (_selectedRow < 0) {
+ _hotspotId = -1;
+ _mainObjectSource = CAT_NONE;
+ } else {
+ InventoryObject &invObject = _vm->_game->_objects.getItem(userInterface._selectedInvIndex);
+ _verbType = invObject._vocabList[_selectedRow]._verbType;
+ _prepType = invObject._vocabList[_selectedRow]._prepType;
+ _hotspotId = userInterface._selectedInvIndex;
+ _mainObjectSource = CAT_INV_LIST;
+
+ if (_verbType == VERB_THAT)
+ _articleNumber = _prepType;
+ }
+ break;
+
+ case CAT_HOTSPOT:
+ _selectedRow = -1;
+ _commandSource = CAT_NONE;
+ _mainObjectSource = CAT_HOTSPOT;
+ _hotspotId = _pickedWord;
+ break;
+
+ case CAT_TALK_ENTRY:
+ _commandSource = CAT_TALK_ENTRY;
+ _selectedRow = _pickedWord;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case AWAITING_THIS:
+ _articleNumber = 0;
+ switch (userInterface._category) {
+ case CAT_INV_LIST:
+ case CAT_HOTSPOT:
+ case CAT_INV_ANIM:
+ _mainObjectSource = userInterface._category;
+ _hotspotId = _pickedWord;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case AWAITING_THAT:
+ switch (userInterface._category) {
+ case CAT_INV_LIST:
+ case CAT_HOTSPOT:
+ case CAT_INV_ANIM:
+ _secondObjectSource = userInterface._category;
+ _secondObject = _pickedWord;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void MADSAction::leftClick() {
+ Scene &scene = _vm->_game->_scene;
+ UserInterface &userInterface = scene._userInterface;
+ bool abortFlag = false;
+
+ if ((userInterface._category == CAT_COMMAND || userInterface._category == CAT_INV_VOCAB) &&
+ _interAwaiting != 1 && _pickedWord >= 0 &&
+ _recentCommandSource == userInterface._category && _recentCommand == _pickedWord &&
+ (_interAwaiting == 2 || userInterface._category == CAT_INV_VOCAB)) {
+ abortFlag = true;
+ if (_selectedRow == 0 && userInterface._category == CAT_COMMAND) {
+ _selectedAction = CAT_COMMAND;
+ scene._lookFlag = true;
+ } else {
+ _selectedAction = CAT_NONE;
+ scene._lookFlag = false;
+ clear();
+ }
+ }
+
+ if (abortFlag || (_vm->_events->_rightMousePressed && (userInterface._category == CAT_COMMAND ||
+ userInterface._category == CAT_INV_VOCAB)))
+ return;
+
+ switch (_interAwaiting) {
+ case AWAITING_COMMAND:
+ switch (userInterface._category) {
+ case CAT_COMMAND:
+ if (_selectedRow >= 0) {
+ if (_verbType == VERB_ONLY) {
+ _selectedAction = -1;
+ }
+ else {
+ _recentCommand = _selectedRow;
+ _recentCommandSource = _commandSource;
+ _interAwaiting = AWAITING_THIS;
+ }
+ }
+ break;
+
+ case CAT_INV_LIST:
+ if (_pickedWord >= 0) {
+ userInterface.selectObject(_pickedWord);
+ }
+ break;
+
+ case CAT_INV_VOCAB:
+ if (_selectedRow >= 0) {
+ if (_verbType != VERB_THIS || _prepType != PREP_NONE) {
+ if (_verbType != VERB_THAT || _prepType == PREP_NONE) {
+ _interAwaiting = AWAITING_THAT;
+ _articleNumber = _prepType;
+ } else {
+ _articleNumber = _prepType;
+ _selectedAction = -1;
+ }
+ } else {
+ _selectedAction = -1;
+ }
+
+ _recentCommand = _selectedRow;
+ _recentCommandSource = _commandSource;
+ }
+ break;
+
+ case CAT_HOTSPOT:
+ _recentCommand = -1;
+ _recentCommandSource = CAT_NONE;
+
+ if (_vm->_events->currentPos().y < MADS_SCENE_HEIGHT) {
+ scene._customDest = _vm->_events->currentPos() + scene._posAdjust;
+ _selectedAction = -1;
+ _pointEstablished = true;
+ }
+ break;
+
+ case CAT_TALK_ENTRY:
+ if (_selectedRow >= 0)
+ _selectedAction = -1;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case AWAITING_THIS:
+ switch (userInterface._category) {
+ case CAT_INV_LIST:
+ case CAT_HOTSPOT:
+ case CAT_INV_ANIM:
+ if (_hotspotId >= 0) {
+ if (_prepType) {
+ _articleNumber = _prepType;
+ _interAwaiting = AWAITING_THAT;
+ } else {
+ _selectedAction = -1;
+ }
+
+ if (userInterface._category == CAT_HOTSPOT) {
+ scene._customDest = _vm->_events->mousePos() + scene._posAdjust;
+ _pointEstablished = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case AWAITING_THAT:
+ switch (userInterface._category) {
+ case CAT_INV_LIST:
+ case CAT_HOTSPOT:
+ case CAT_INV_ANIM:
+ if (_secondObject >= 0) {
+ _selectedAction = -1;
+
+ if (userInterface._category == CAT_HOTSPOT) {
+ if (!_pointEstablished) {
+ scene._customDest = _vm->_events->mousePos() + scene._posAdjust;
+ _pointEstablished = true;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void MADSAction::synchronize(Common::Serializer &s) {
+ _action.synchronize(s);
+ _activeAction.synchronize(s);
+ s.syncAsSint16LE(_articleNumber);
+ s.syncAsByte(_lookFlag);
+ s.syncAsByte(_textChanged);
+ s.syncAsSint16LE(_selectedRow);
+ s.syncAsSint16LE(_selectedAction);
+ s.syncAsSint16LE(_statusTextIndex);
+ s.syncAsSint16LE(_hotspotId);
+ _savedFields.synchronize(s);
+
+ // TODO: When saving in Rex Village Hut, _senetence size() doesn't match
+ // string length. Find out why not
+ _sentence = Common::String(_sentence.c_str());
+ s.syncString(_sentence);
+
+ s.syncAsSint16LE(_verbType);
+ s.syncAsSint16LE(_prepType);
+ s.syncAsSint16LE(_commandSource);
+ s.syncAsSint16LE(_mainObjectSource);
+ s.syncAsSint16LE(_secondObject);
+ s.syncAsSint16LE(_secondObjectSource);
+ s.syncAsSint16LE(_recentCommandSource);
+ s.syncAsSint16LE(_recentCommand);
+ s.syncAsSint16LE(_interAwaiting);
+ s.syncAsSint16LE(_pickedWord);
+ s.syncAsByte(_pointEstablished);
+ s.syncAsByte(_inProgress);
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/action.h b/engines/mads/action.h
new file mode 100644
index 0000000000..cfd5a3be3f
--- /dev/null
+++ b/engines/mads/action.h
@@ -0,0 +1,176 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_ACTION_H
+#define MADS_ACTION_H
+
+#include "common/scummsys.h"
+#include "common/serializer.h"
+#include "common/str.h"
+
+namespace MADS {
+
+enum TriggerMode {
+ SEQUENCE_TRIGGER_PARSER = 0, // Triggers parser
+ SEQUENCE_TRIGGER_DAEMON = 1, // Triggers step/daemon code
+ SEQUENCE_TRIGGER_PREPARE = 2 // Triggers preparser
+};
+
+enum InterAwaiting {
+ AWAITING_NONE = 0,
+ AWAITING_COMMAND = 1, // Initial state: waiting for a command verb
+ AWAITING_THIS = 2, // Waiting for object
+ AWAITING_THAT = 3, // Waiting for a second object
+ AWAITING_RIGHT_MOUSE = 4 // Waiting for mouse button release
+};
+
+enum {
+ VERB_NONE = 0,
+ VERB_LOOK = 3,
+ VERB_TAKE = 4,
+ VERB_PUSH = 5,
+ VERB_OPEN = 6,
+ VERB_PUT = 7,
+ VERB_TALKTO = 8,
+ VERB_GIVE = 9,
+ VERB_PULL = 10,
+ VERB_CLOSE = 11,
+ VERB_THROW = 12,
+ VERB_WALKTO = 13
+};
+
+enum VerbType { VERB_ONLY, VERB_THIS, VERB_THAT, VERB_INIT };
+
+enum PrepType {
+ PREP_NONE, PREP_WITH, PREP_TO, PREP_AT, PREP_FROM, PREP_ON, PREP_IN,
+ PREP_UNDER, PREP_BEHIND, PREP_RELATIONAL = 0xff
+};
+
+enum ScrCategory {
+ CAT_NONE = 0, CAT_COMMAND = 1, CAT_INV_LIST = 2, CAT_INV_VOCAB = 3,
+ CAT_HOTSPOT = 4, CAT_INV_ANIM = 5, CAT_TALK_ENTRY = 6, CAT_INV_SCROLLER = 7,
+ CAT_12 = 12
+};
+
+class MADSEngine;
+
+struct ActionDetails {
+ int _verbId;
+ int _objectNameId;
+ int _indirectObjectId;
+
+ /**
+ * Synchronize the action details
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+struct ActionSavedFields {
+ bool _commandError;
+ int _commandSource;
+ int _command;
+ int _mainObject;
+ int _secondObject;
+ int _mainObjectSource;
+ int _secondObjectSource;
+ int _articleNumber;
+ int _lookFlag;
+
+ /**
+ * Synchronize the saved action details
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+class MADSAction {
+private:
+ MADSEngine *_vm;
+ Common::String _statusText;
+
+ void appendVocab(int vocabId, bool capitalize = false);
+
+ void startWalkingDirectly(int walkType);
+public:
+ ActionDetails _action, _activeAction;
+ int _articleNumber;
+ bool _lookFlag;
+ int _selectedRow;
+ bool _textChanged;
+ int _selectedAction;
+ int _statusTextIndex;
+ int _hotspotId;
+ ActionSavedFields _savedFields;
+ Common::String _sentence;
+
+ VerbType _verbType;
+ PrepType _prepType;
+ ScrCategory _commandSource;
+ ScrCategory _mainObjectSource;
+ int _secondObject;
+ ScrCategory _secondObjectSource;
+ ScrCategory _recentCommandSource;
+ bool _pointEstablished;
+ int _recentCommand;
+ InterAwaiting _interAwaiting;
+ bool _inProgress;
+ int _pickedWord;
+
+public:
+ MADSAction(MADSEngine *vm);
+
+ void clear();
+ void set();
+ const Common::String &statusText() const { return _statusText; }
+ void refresh();
+
+ /**
+ * Accepts the currently defined sentence from the ScreenObjects parser.
+ * Copies the data, and checks to see if the action requires the player
+ * to walk to the given hotspot.
+ */
+ void startAction();
+
+ void checkAction();
+ bool isAction(int verbId, int objectNameId = 0, int indirectObjectId = 0);
+ bool isObject(int objectNameId);
+ bool isTarget(int objectNameId);
+
+ /**
+ * Check the result of the current action on the sentence
+ * with the provision that the action is not yet complete.
+ */
+ void checkActionAtMousePos();
+
+ /**
+ * Execute a click within the scene
+ */
+ void leftClick();
+
+ /**
+ * Synchronize the saved action details
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_ACTION_H */
diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp
new file mode 100644
index 0000000000..ace505839c
--- /dev/null
+++ b/engines/mads/animation.cpp
@@ -0,0 +1,592 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "mads/animation.h"
+#include "mads/compression.h"
+
+#define FILENAME_SIZE 13
+
+namespace MADS {
+
+void AAHeader::load(Common::SeekableReadStream *f) {
+ _spriteSetsCount = f->readUint16LE();
+ _miscEntriesCount = f->readUint16LE();
+ _frameEntriesCount = f->readUint16LE();
+ _messagesCount = f->readUint16LE();
+ _loadFlags = f->readUint16LE();
+ _charSpacing = f->readSint16LE();
+ _bgType = (AnimBgType)f->readUint16LE();
+ _roomNumber = f->readUint16LE();
+ f->skip(2);
+ _manualFlag = f->readUint16LE() != 0;
+ _spritesIndex = f->readUint16LE();
+ _scrollPosition.x = f->readSint16LE();
+ _scrollPosition.y = f->readSint16LE();
+ _scrollTicks = f->readUint32LE();
+ f->skip(6);
+
+ char buffer[FILENAME_SIZE];
+ f->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE - 1] = '\0';
+ _backgroundFile = Common::String(buffer);
+
+ for (int i = 0; i < 50; ++i) {
+ f->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE - 1] = '\0';
+ if (i < _spriteSetsCount)
+ _spriteSetNames.push_back(Common::String(buffer));
+ }
+
+ f->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE - 1] = '\0';
+ _soundName = Common::String(buffer);
+
+ f->skip(13);
+ f->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE - 1] = '\0';
+ _dsrName = Common::String(buffer);
+
+ f->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE - 1] = '\0';
+ _fontResource = Common::String(buffer);
+}
+
+/*------------------------------------------------------------------------*/
+
+void AnimMessage::load(Common::SeekableReadStream *f) {
+ _soundId = f->readSint16LE();
+
+ char buffer[64];
+ f->read(&buffer[0], 64);
+ _msg = Common::String(buffer);
+ f->skip(4);
+ _pos.x = f->readSint16LE();
+ _pos.y = f->readSint16LE();
+ _flags = f->readUint16LE();
+ _rgb1[0] = f->readByte() << 2;
+ _rgb1[1] = f->readByte() << 2;
+ _rgb1[2] = f->readByte() << 2;
+ _rgb2[0] = f->readByte() << 2;
+ _rgb2[1] = f->readByte() << 2;
+ _rgb2[2] = f->readByte() << 2;
+ f->skip(2); // Space for kernelMsgIndex
+ _kernelMsgIndex = -1;
+ f->skip(6);
+ _startFrame = f->readUint16LE();
+ _endFrame = f->readUint16LE();
+ f->skip(2);
+}
+
+void AnimFrameEntry::load(Common::SeekableReadStream *f, bool uiFlag) {
+ if (uiFlag) {
+ f->skip(2);
+ _frameNumber = -1; // Unused
+ _seqIndex = f->readByte();
+ _spriteSlot._spritesIndex = f->readByte();
+ _spriteSlot._frameNumber = (int8)f->readByte();
+ f->skip(1);
+ _spriteSlot._position.x = f->readSint16LE();
+ _spriteSlot._position.y = f->readSint16LE();
+ } else {
+ _frameNumber = f->readUint16LE();
+ if (_frameNumber & 0x8000)
+ _frameNumber = -(_frameNumber & 0x7fff);
+
+ _seqIndex = f->readByte();
+ _spriteSlot._spritesIndex = f->readByte();
+ _spriteSlot._frameNumber = f->readUint16LE();
+ if (_spriteSlot._frameNumber & 0x8000)
+ _spriteSlot._frameNumber = -(_spriteSlot._frameNumber & 0x7fff);
+
+ _spriteSlot._position.x = f->readSint16LE();
+ _spriteSlot._position.y = f->readSint16LE();
+ _spriteSlot._depth = f->readSByte();
+ _spriteSlot._scale = (int8)f->readByte();
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+void AnimMiscEntry::load(Common::SeekableReadStream *f) {
+ _soundId = f->readByte();
+ _msgIndex = f->readSByte();
+ _numTicks = f->readUint16LE();
+ _posAdjust.x = f->readSint16LE();
+ _posAdjust.y = f->readSint16LE();
+ _scroll.x = f->readSByte();
+ _scroll.y = f->readSByte();
+}
+
+/*------------------------------------------------------------------------*/
+
+void AnimUIEntry::load(Common::SeekableReadStream *f) {
+ _probability = f->readUint16LE();
+ _imageCount = f->readUint16LE();
+ _firstImage = f->readUint16LE();
+ _lastImage = f->readUint16LE();
+ _counter = f->readSint16LE();
+ for (int i = 0; i < ANIM_SPAWN_COUNT; ++i)
+ _spawn[i] = f->readByte();
+ for (int i = 0; i < ANIM_SPAWN_COUNT; ++i)
+ _spawnFrame[i] = f->readUint16LE();
+ _sound = f->readUint16LE() & 0xFF;
+ _soundFrame = f->readUint16LE();
+}
+
+/*------------------------------------------------------------------------*/
+
+Animation *Animation::init(MADSEngine *vm, Scene *scene) {
+ return new Animation(vm, scene);
+}
+
+Animation::Animation(MADSEngine *vm, Scene *scene) : _vm(vm), _scene(scene) {
+ _font = nullptr;
+ _resetFlag = false;
+ _messageCtr = 0;
+ _skipLoad = false;
+ _freeFlag = false;
+ _unkIndex = -1;
+ _nextFrameTimer = 0;
+ _nextScrollTimer = 0;
+ _trigger = 0;
+ _triggerMode = SEQUENCE_TRIGGER_PREPARE;
+ _actionDetails._verbId = VERB_NONE;
+ _actionDetails._objectNameId = -1;
+ _actionDetails._indirectObjectId = -1;
+ _currentFrame = 0;
+ _oldFrameEntry = 0;
+}
+
+Animation::~Animation() {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_header._manualFlag)
+ scene._sprites.remove(_spriteListIndexes[_header._spritesIndex]);
+
+ for (int idx = 0; idx < _header._spriteSetsCount; ++idx) {
+ if (!_header._manualFlag || _header._spritesIndex != idx)
+ scene._sprites.remove(_spriteListIndexes[idx]);
+ }
+}
+
+void Animation::load(MSurface &backSurface, DepthSurface &depthSurface,
+ const Common::String &resName, int flags, Common::Array<PaletteCycle> *palCycles,
+ SceneInfo *sceneInfo) {
+ Common::String resourceName = resName;
+ if (!resourceName.contains("."))
+ resourceName += ".AA";
+
+ File f(resourceName);
+ MadsPack madsPack(&f);
+
+ Common::SeekableReadStream *stream = madsPack.getItemStream(0);
+ _header.load(stream);
+ delete stream;
+
+ if (_header._bgType == ANIMBG_INTERFACE)
+ flags |= PALFLAG_RESERVED;
+
+ if (flags & ANIMFLAG_LOAD_BACKGROUND) {
+ loadBackground(backSurface, depthSurface, _header, flags, palCycles, sceneInfo);
+ }
+ if (flags & ANIMFLAG_LOAD_BACKGROUND_ONLY) {
+ // No data
+ _header._messagesCount = 0;
+ _header._frameEntriesCount = 0;
+ _header._miscEntriesCount = 0;
+ }
+
+ // Initialize the reference list
+ _spriteListIndexes.clear();
+ for (int i = 0; i < _header._spriteSetsCount; ++i)
+ _spriteListIndexes.push_back(-1);
+
+ int streamIndex = 1;
+ _messages.clear();
+ if (_header._messagesCount > 0) {
+ // Chunk 2: Following is a list of any messages for the animation
+ Common::SeekableReadStream *msgStream = madsPack.getItemStream(streamIndex++);
+
+ for (int i = 0; i < _header._messagesCount; ++i) {
+ AnimMessage rec;
+ rec.load(msgStream);
+ _messages.push_back(rec);
+ }
+
+ delete msgStream;
+ }
+
+ _frameEntries.clear();
+ if (_header._frameEntriesCount > 0) {
+ // Chunk 3: animation frame info
+ Common::SeekableReadStream *frameStream = madsPack.getItemStream(streamIndex++);
+
+ for (int i = 0; i < _header._frameEntriesCount; i++) {
+ AnimFrameEntry rec;
+ rec.load(frameStream, _header._bgType == ANIMBG_INTERFACE);
+ _frameEntries.push_back(rec);
+ }
+
+ delete frameStream;
+ }
+
+ _miscEntries.clear();
+ _uiEntries.clear();
+ if (_header._miscEntriesCount > 0) {
+ // Chunk 4: Misc Data
+ Common::SeekableReadStream *miscStream = madsPack.getItemStream(streamIndex++);
+
+ if (_header._bgType == ANIMBG_INTERFACE) {
+ for (int i = 0; i < _header._miscEntriesCount; ++i) {
+ AnimUIEntry rec;
+ rec.load(miscStream);
+ _uiEntries.push_back(rec);
+ }
+ } else {
+ for (int i = 0; i < _header._miscEntriesCount; ++i) {
+ AnimMiscEntry rec;
+ rec.load(miscStream);
+ _miscEntries.push_back(rec);
+ }
+ }
+
+ delete miscStream;
+ }
+
+ // If the animation specifies a font, then load it for access
+ delete _font;
+ if (_header._loadFlags & ANIMFLAG_CUSTOM_FONT) {
+ Common::String fontName = "*" + _header._fontResource;
+ _font = _vm->_font->getFont(fontName.c_str());
+ } else {
+ _font = nullptr;
+ }
+
+ // Load all the sprite sets for the animation
+ for (uint i = 0; i < _spriteSets.size(); ++i)
+ delete _spriteSets[i];
+ _spriteSets.clear();
+ _spriteSets.resize(_header._spriteSetsCount);
+
+ for (int i = 0; i < _header._spriteSetsCount; ++i) {
+ if (_header._manualFlag && (i == _header._spritesIndex)) {
+ // Skip over field, since it's manually loaded
+ _spriteSets[i] = nullptr;
+ } else {
+ _spriteSets[i] = new SpriteAsset(_vm, _header._spriteSetNames[i], flags);
+ _spriteListIndexes[i] = _vm->_game->_scene._sprites.add(_spriteSets[i]);
+ }
+ }
+
+ if (_header._manualFlag) {
+ Common::String assetResName = "*" + _header._spriteSetNames[_header._spritesIndex];
+ SpriteAsset *sprites = new SpriteAsset(_vm, assetResName, flags);
+ _spriteSets[_header._spritesIndex] = sprites;
+
+ _spriteListIndexes[_header._spritesIndex] = _scene->_sprites.add(sprites);
+ }
+
+ Common::Array<int> usageList;
+ for (int idx = 0; idx < _header._spriteSetsCount; ++idx)
+ usageList.push_back(_spriteSets[idx]->_usageIndex);
+
+ if (usageList.size() > 0) {
+ int spritesUsageIndex = _spriteSets[0]->_usageIndex;
+ _vm->_palette->_paletteUsage.updateUsage(usageList, spritesUsageIndex);
+ }
+
+ // Remaps the sprite list indexes for frames to the loaded sprite list indexes
+ for (uint i = 0; i < _frameEntries.size(); ++i) {
+ int spriteListIndex = _frameEntries[i]._spriteSlot._spritesIndex;
+ _frameEntries[i]._spriteSlot._spritesIndex = _spriteListIndexes[spriteListIndex];
+ }
+
+ f.close();
+}
+
+void Animation::preLoad(const Common::String &resName, int level) {
+ // No implementation in ScummVM, since access is fast enough that data
+ // doesn't need to be preloaded
+}
+
+void Animation::startAnimation(int endTrigger) {
+ _messageCtr = 0;
+ _skipLoad = true;
+
+ if (_header._manualFlag) {
+ _unkIndex = -1;
+ //SpriteAsset *asset = _scene->_sprites[_spriteListIndexes[_header._spritesIndex]];
+
+ // TODO: Weird stuff with _unkList. Seems like it's treated as pointers
+ // here, but in processText, it's used as POINTs?
+
+ loadFrame(1);
+ }
+
+ if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE)
+ _vm->_palette->refreshSceneColors();
+
+ _currentFrame = 0;
+ _oldFrameEntry = 0;
+ _nextFrameTimer = _vm->_game->_scene._frameStartTime;
+ _trigger = endTrigger;
+ _triggerMode = _vm->_game->_triggerSetupMode;
+ _actionDetails = _vm->_game->_scene._action._activeAction;
+
+ for (int idx = 0; idx < _header._messagesCount; ++idx) {
+ _messages[idx]._kernelMsgIndex = -1;
+ }
+}
+
+void Animation::loadFrame(int frameNumber) {
+ Scene &scene = _vm->_game->_scene;
+ if (_skipLoad)
+ return;
+
+ Common::Point pt;
+ int spriteListIndex = _spriteListIndexes[_header._spritesIndex];
+ SpriteAsset &spriteSet = *scene._sprites[spriteListIndex];
+
+ if (_unkIndex < 0) {
+ MSurface *frame = spriteSet.getFrame(0);
+ pt.x = frame->getBounds().left;
+ pt.y = frame->getBounds().top;
+ } else {
+ pt.x = _unkList[_unkIndex].x;
+ pt.y = _unkList[_unkIndex].y;
+ _unkIndex = 1 - _unkIndex;
+ }
+
+ if (drawFrame(spriteSet, pt, frameNumber))
+ error("drawFrame failure");
+}
+
+bool Animation::drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) {
+ return 0;
+}
+
+void Animation::loadBackground(MSurface &backSurface, DepthSurface &depthSurface,
+ AAHeader &header, int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo) {
+ _scene->_depthStyle = 0;
+ if (header._bgType <= ANIMBG_FULL_SIZE) {
+ _vm->_palette->_paletteUsage.setEmpty();
+ sceneInfo->load(header._roomNumber, 0, header._backgroundFile, flags, depthSurface, backSurface);
+ _scene->_depthStyle = sceneInfo->_depthStyle == 2 ? 1 : 0;
+ if (palCycles) {
+ palCycles->clear();
+ for (uint i = 0; i < sceneInfo->_paletteCycles.size(); ++i)
+ palCycles->push_back(sceneInfo->_paletteCycles[i]);
+ }
+ } else if (header._bgType == ANIMBG_INTERFACE) {
+ // Load a scene interface
+ Common::String resourceName = "*" + header._backgroundFile;
+ backSurface.load(resourceName);
+
+ if (palCycles)
+ palCycles->clear();
+ } else {
+ // Original has useless code here
+ }
+}
+
+bool Animation::hasScroll() const {
+ return (_header._scrollPosition.x != 0) || (_header._scrollPosition.y != 0);
+}
+
+void Animation::update() {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_header._manualFlag) {
+ int spriteListIndex = _spriteListIndexes[_header._spritesIndex];
+ int newIndex = -1;
+
+ for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) {
+ if (_frameEntries[idx]._frameNumber > _currentFrame)
+ break;
+ if (_frameEntries[idx]._spriteSlot._spritesIndex == spriteListIndex)
+ newIndex = _frameEntries[idx]._spriteSlot._frameNumber;
+ }
+
+ if (newIndex >= 0)
+ loadFrame(newIndex);
+ }
+
+ // If it's not time for the next frame, then exit
+ if (_vm->_game->_scene._frameStartTime < _nextFrameTimer)
+ return;
+
+ for (uint idx = 0; idx < scene._spriteSlots.size(); ++idx) {
+ if (scene._spriteSlots[idx]._seqIndex >= 0x80)
+ scene._spriteSlots[idx]._flags = IMG_ERASE;
+ }
+
+ // Validate the current frame
+ if (_currentFrame >= (int)_miscEntries.size()) {
+ // Is the animation allowed to be repeated?
+ if (_resetFlag) {
+ _currentFrame = 0;
+ _oldFrameEntry = 0;
+ } else {
+ _freeFlag = true;
+ return;
+ }
+ }
+
+ // Handle executing any sound command for this frame
+ AnimMiscEntry &misc = _miscEntries[_currentFrame];
+ if (misc._soundId)
+ _vm->_sound->command(misc._soundId);
+
+ // Handle any screen scrolling
+ if (hasScroll()) {
+ scene._backgroundSurface.scrollX(_header._scrollPosition.x);
+ scene._backgroundSurface.scrollY(_header._scrollPosition.y);
+ scene._spriteSlots.fullRefresh();
+ }
+
+ // Handle any offset adjustment for sprites as of this frame
+ bool paChanged = false;
+ if (scene._posAdjust.x != misc._posAdjust.x) {
+ scene._posAdjust.x = misc._posAdjust.x;
+ paChanged = true;
+ }
+ if (scene._posAdjust.y != misc._posAdjust.y) {
+ scene._posAdjust.y = misc._posAdjust.y;
+ paChanged = true;
+ }
+
+ if (paChanged) {
+ int newIndex = scene._spriteSlots.add();
+ scene._spriteSlots[newIndex]._seqIndex = -1;
+ scene._spriteSlots[newIndex]._flags = IMG_REFRESH;
+ }
+
+ // Main frame animation loop - frames get animated by being placed, as necessary, into the
+ // main sprite slot array
+ while ((uint)_oldFrameEntry < _frameEntries.size()) {
+ if (_frameEntries[_oldFrameEntry]._frameNumber > _currentFrame)
+ break;
+ else if (_frameEntries[_oldFrameEntry]._frameNumber == _currentFrame) {
+ // Found the correct frame
+ int spriteSlotIndex = 0;
+ int index = 0;
+
+ for (;;) {
+ if ((spriteSlotIndex == 0) && (index < (int)scene._spriteSlots.size())) {
+ int seqIndex = _frameEntries[_oldFrameEntry]._seqIndex - scene._spriteSlots[index]._seqIndex;
+ if (seqIndex == 0x80) {
+ if (scene._spriteSlots[index] == _frameEntries[_oldFrameEntry]._spriteSlot) {
+ scene._spriteSlots[index]._flags = IMG_STATIC;
+ spriteSlotIndex = -1;
+ }
+ }
+ ++index;
+ continue;
+ }
+
+ if (spriteSlotIndex == 0) {
+ int slotIndex = scene._spriteSlots.add();
+ SpriteSlot &slot = scene._spriteSlots[slotIndex];
+ slot.copy(_frameEntries[_oldFrameEntry]._spriteSlot);
+ slot._seqIndex = _frameEntries[_oldFrameEntry]._seqIndex + 0x80;
+
+ SpriteAsset &spriteSet = *scene._sprites[
+ scene._spriteSlots[slotIndex]._spritesIndex];
+ slot._flags = spriteSet.isBackground() ? IMG_DELTA : IMG_UPDATE;
+ }
+ break;
+ }
+ }
+
+ ++_oldFrameEntry;
+ }
+
+ // Handle the display of any messages
+ for (uint idx = 0; idx < _messages.size(); ++idx) {
+ if (_messages[idx]._kernelMsgIndex >= 0) {
+ // Handle currently active message
+ if ((_currentFrame < _messages[idx]._startFrame) || (_currentFrame > _messages[idx]._endFrame)) {
+ scene._kernelMessages.remove(_messages[idx]._kernelMsgIndex);
+ _messages[idx]._kernelMsgIndex = -1;
+ --_messageCtr;
+ }
+ } else if ((_currentFrame >= _messages[idx]._startFrame) && (_currentFrame <= _messages[idx]._endFrame)) {
+ // Start displaying the message
+ AnimMessage &me = _messages[idx];
+
+ // The color index to use is dependant on how many messages are currently on-screen
+ uint8 colIndex;
+ switch (_messageCtr) {
+ case 1:
+ colIndex = 252;
+ break;
+ case 2:
+ colIndex = 16;
+ break;
+ default:
+ colIndex = 250;
+ break;
+ }
+
+ _vm->_palette->setEntry(colIndex, me._rgb1[0], me._rgb1[1], me._rgb1[2]);
+ _vm->_palette->setEntry(colIndex + 1, me._rgb2[0], me._rgb2[1], me._rgb2[2]);
+
+ // Add a kernel message to display the given text
+ me._kernelMsgIndex = scene._kernelMessages.add(me._pos, colIndex * 0x101 + 0x100,
+ 0, 0, INDEFINITE_TIMEOUT, me._msg);
+ assert(me._kernelMsgIndex >= 0);
+ ++_messageCtr;
+ }
+ }
+
+ // Move to the next frame
+ _currentFrame++;
+ if (_currentFrame >= (int)_miscEntries.size()) {
+ // Animation is complete
+ if (_trigger != 0) {
+ _vm->_game->_trigger = _trigger;
+ _vm->_game->_triggerMode = _triggerMode;
+
+ if (_triggerMode != SEQUENCE_TRIGGER_DAEMON) {
+ // Copy the noun list
+ scene._action._activeAction = _actionDetails;
+ }
+ }
+ }
+
+ int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1);
+ _nextFrameTimer = _vm->_game->_scene._frameStartTime + _miscEntries[frameNum]._numTicks;
+}
+
+void Animation::setCurrentFrame(int frameNumber) {
+ _currentFrame = frameNumber;
+ _oldFrameEntry = 0;
+ _freeFlag = false;
+
+ _nextScrollTimer = _nextFrameTimer = _vm->_game->_scene._frameStartTime;
+}
+
+void Animation::setNextFrameTimer(int frameNumber) {
+ _nextFrameTimer = frameNumber;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/animation.h b/engines/mads/animation.h
new file mode 100644
index 0000000000..917d899ec5
--- /dev/null
+++ b/engines/mads/animation.h
@@ -0,0 +1,233 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_ANIMATION_H
+#define MADS_ANIMATION_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "mads/msurface.h"
+#include "mads/scene_data.h"
+#include "mads/font.h"
+#include "mads/user_interface.h"
+
+namespace MADS {
+
+enum AnimFlag {
+ ANIMFLAG_DITHER = 0x1000, // Dither to 16 colors
+ ANIMFLAG_CUSTOM_FONT = 0x2000, // Load ccustom font
+ ANIMFLAG_LOAD_BACKGROUND = 0x0100, // Load background
+ ANIMFLAG_LOAD_BACKGROUND_ONLY = 0x0200 // Load background only
+};
+
+enum AnimBgType {
+ ANIMBG_ROOM = 1, ANIMBG_FULL_SIZE = 2, ANIMBG_BLACK_SCREEN = 3,
+ ANIMBG_INTERFACE = 4
+};
+
+class MADSEngine;
+class Scene;
+
+class AnimMessage {
+public:
+ int16 _soundId;
+ Common::String _msg;
+ Common::Point _pos;
+ byte _rgb1[3], _rgb2[3];
+ int _flags;
+ int _startFrame, _endFrame;
+ int _kernelMsgIndex;
+
+ /**
+ * Loads data for the message from a stream
+ */
+ void load(Common::SeekableReadStream *f);
+};
+
+class AnimFrameEntry {
+public:
+ int _frameNumber;
+ int _seqIndex;
+ SpriteSlotSubset _spriteSlot;
+
+ /**
+ * Loads data for the record
+ */
+ void load(Common::SeekableReadStream *f, bool uiFlag);
+};
+
+class AnimMiscEntry {
+public:
+ int _soundId;
+ int _msgIndex;
+ int _numTicks;
+ Common::Point _posAdjust;
+ Common::Point _scroll;
+
+ /**
+ * Loads data for the record
+ */
+ void load(Common::SeekableReadStream *f);
+};
+
+#define ANIM_SPAWN_COUNT 2
+
+class AnimUIEntry {
+public:
+ int _probability;
+ int _imageCount;
+ int _firstImage;
+ int _lastImage;
+ int _counter;
+ int _spawn[ANIM_SPAWN_COUNT];
+ int _spawnFrame[ANIM_SPAWN_COUNT];
+ int _sound;
+ int _soundFrame;
+
+ /**
+ * Loads the data for the record
+ */
+ void load(Common::SeekableReadStream *f);
+};
+
+class AAHeader {
+public:
+ int _spriteSetsCount;
+ int _miscEntriesCount;
+ int _frameEntriesCount;
+ int _messagesCount;
+ int _loadFlags;
+ int _charSpacing;
+ AnimBgType _bgType;
+ int _roomNumber;
+ bool _manualFlag;
+ int _spritesIndex;
+ Common::Point _scrollPosition;
+ uint32 _scrollTicks;
+ Common::String _backgroundFile;
+ Common::StringArray _spriteSetNames;
+ Common::String _lbmFilename;
+ Common::String _spritesFilename;
+ Common::String _soundName;
+ Common::String _dsrName;
+ Common::String _fontResource;
+
+ /**
+ * Loads the data for a animation file header
+ */
+ void load(Common::SeekableReadStream *f);
+};
+
+class Animation {
+private:
+ MADSEngine *_vm;
+ Scene *_scene;
+
+ Common::Array<AnimMiscEntry> _miscEntries;
+ Common::Array<SpriteAsset *> _spriteSets;
+ Font *_font;
+
+ bool _freeFlag;
+ bool _skipLoad;
+ int _unkIndex;
+ Common::Point _unkList[2];
+ uint32 _nextFrameTimer;
+ uint32 _nextScrollTimer;
+ int _messageCtr;
+ int _trigger;
+ TriggerMode _triggerMode;
+ ActionDetails _actionDetails;
+
+ /**
+ * Load data for a given frame
+ * @param frameNumber Frame number
+ */
+ void loadFrame(int frameNumber);
+
+ bool drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber);
+
+ /**
+ * Load the user interface display or background for an animation
+ */
+ void loadBackground(MSurface &backSurface, DepthSurface &depthSurface,
+ AAHeader &header, int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo);
+
+ /**
+ * Returns true if there is a scroll required
+ */
+ bool hasScroll() const;
+protected:
+ Animation(MADSEngine *vm, Scene *scene);
+public:
+ AAHeader _header;
+ Common::Array<int> _spriteListIndexes;
+ Common::Array<AnimFrameEntry> _frameEntries;
+ Common::Array<AnimUIEntry> _uiEntries;
+ Common::Array<AnimMessage> _messages;
+ bool _resetFlag;
+ int _currentFrame;
+ int _oldFrameEntry;
+
+ static Animation *init(MADSEngine *vm, Scene *scene);
+ /*
+ * Destructor
+ */
+ ~Animation();
+
+ /**
+ * Loads animation data
+ */
+ void load(MSurface &backSurface, DepthSurface &depthSurface, const Common::String &resName,
+ int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo);
+
+ /**
+ * Preload animation data for the scene
+ */
+ void preLoad(const Common::String &resName, int level);
+
+ /**
+ * Setups up a loaded animation for playback
+ */
+ void startAnimation(int endTrigger);
+
+ /**
+ * Update the animation
+ */
+ void update();
+
+ void setNextFrameTimer(int frameNumber);
+ int getNextFrameTimer() const { return _nextFrameTimer; }
+ void setCurrentFrame(int frameNumber);
+ int getCurrentFrame() const { return _currentFrame; }
+
+ bool freeFlag() const { return _freeFlag; }
+ int roomNumber() const { return _header._roomNumber; }
+
+ void resetSpriteSetsCount() { _header._spriteSetsCount = 0; } // CHECKME: See if it doesn't leak the memory when the destructor is called
+
+ SpriteAsset *getSpriteSet(int idx) { return _spriteSets[idx]; }
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_ANIMATION_H */
diff --git a/engines/mads/assets.cpp b/engines/mads/assets.cpp
new file mode 100644
index 0000000000..a2d495f311
--- /dev/null
+++ b/engines/mads/assets.cpp
@@ -0,0 +1,228 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/assets.h"
+#include "mads/compression.h"
+#include "mads/events.h"
+#include "mads/palette.h"
+
+namespace MADS {
+
+SpriteAsset::SpriteAsset(MADSEngine *vm, const Common::String &resourceName, int flags) : _vm(vm) {
+ Common::String resName = resourceName;
+ if (!resName.hasSuffix(".SS") && !resName.hasSuffix(".ss"))
+ resName += ".SS";
+ _srcSize = 0;
+
+ File file(resName);
+ load(&file, flags);
+
+ file.close();
+}
+
+SpriteAsset::SpriteAsset(MADSEngine *vm, Common::SeekableReadStream *stream, int flags) : _vm(vm) {
+ _srcSize = 0;
+
+ load(stream, flags);
+}
+
+SpriteAsset::~SpriteAsset() {
+ if (_usageIndex)
+ _vm->_palette->_paletteUsage.resetPalFlags(_usageIndex);
+
+ for (uint i = 0; i < _frames.size(); ++i)
+ delete _frames[i]._frame;
+
+ delete _charInfo;
+}
+
+void SpriteAsset::load(Common::SeekableReadStream *stream, int flags) {
+ int curFrame = 0;
+ uint32 frameOffset = 0;
+ MadsPack sprite(stream);
+ _frameRate = 0;
+ _pixelSpeed = 0;
+ _maxWidth = 0;
+ _maxHeight = 0;
+ _usageIndex = -1;
+
+ Common::SeekableReadStream *spriteStream = sprite.getItemStream(0);
+ _mode = spriteStream->readByte();
+ spriteStream->skip(1);
+ int type1 = spriteStream->readUint16LE();
+ int type2 = spriteStream->readUint16LE();
+ _isBackground = (type1 != 0) && (type2 < 4);
+ spriteStream->skip(32);
+ _frameCount = spriteStream->readUint16LE();
+
+ if ((flags & ASSET_CHAR_INFO) == 0)
+ _charInfo = nullptr;
+ else
+ _charInfo = new SpriteSetCharInfo(spriteStream);
+
+ delete spriteStream;
+
+ // Get the palette data
+ Common::SeekableReadStream *palStream = sprite.getItemStream(2);
+ Common::Array<RGB6> palette;
+
+ int numColors = palStream->readUint16LE();
+ assert(numColors <= 252);
+ _colorCount = numColors;
+
+ // Load in the palette
+ palette.resize(numColors);
+ for (int i = 0; i < numColors; ++i)
+ palette[i].load(palStream);
+ delete palStream;
+
+ // Process the palette data
+ if (flags & (ASSET_TRANSLATE | ASSET_SPINNING_OBJECT)) {
+ _usageIndex = 0;
+
+ if (flags & ASSET_SPINNING_OBJECT) {
+ int newPalCtr = 0;
+
+ for (uint i = 0; i < palette.size(); ++i) {
+ RGB6 &rgb = palette[i];
+
+ // Scan for existing rgb at beginning of the main palette
+ bool found = false;
+ for (int pIndex = 0; pIndex < 4 && !found; ++pIndex) {
+ byte *palP = &_vm->_palette->_mainPalette[pIndex * 3];
+ if (palP[0] == rgb.r && palP[1] == rgb.g && palP[2] == rgb.b) {
+ rgb._palIndex = pIndex;
+ found = true;
+ }
+ }
+
+ if (!found) {
+ // Existing palette entry not found, so need to add it in
+ int palIndex = (0xF7F607 >> (8 * newPalCtr)) & 0xff;
+ byte *palP = &_vm->_palette->_mainPalette[palIndex * 3];
+ palP[0] = rgb.r;
+ palP[1] = rgb.g;
+ palP[2] = rgb.b;
+ rgb._palIndex = palIndex;
+
+ newPalCtr = MIN(newPalCtr + 1, 2);
+ }
+ }
+ }
+ } else {
+ _usageIndex = _vm->_palette->_paletteUsage.process(palette, flags & 0xF800);
+ assert(_usageIndex >= 0);
+ }
+
+ spriteStream = sprite.getItemStream(1);
+ Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3);
+ SpriteAssetFrame frame;
+ Common::Array<int> frameSizes;
+ for (curFrame = 0; curFrame < _frameCount; curFrame++) {
+ frame._stream = 0;
+ frame._comp = 0;
+ frameOffset = spriteStream->readUint32LE();
+ _frameOffsets.push_back(frameOffset);
+ uint32 frameSize = spriteStream->readUint32LE();
+ frameSizes.push_back(frameSize);
+
+ frame._bounds.left = spriteStream->readSint16LE();
+ frame._bounds.top = spriteStream->readSint16LE();
+ frame._bounds.setWidth(spriteStream->readUint16LE());
+ frame._bounds.setHeight(spriteStream->readUint16LE());
+
+ if (curFrame == 0)
+ debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n",
+ _frameCount, frame._bounds.left, frame._bounds.top,
+ frame._bounds.width(), frame._bounds.height());
+
+ if (_mode == 0) {
+ // Create a frame and decompress the raw pixel data
+ uint32 currPos = (uint32)spriteDataStream->pos();
+ frame._frame = new MSprite(spriteDataStream, palette, frame._bounds);
+ assert((uint32)spriteDataStream->pos() == (currPos + frameSize));
+ }
+
+ _frames.push_back(frame);
+ }
+
+ if (_mode != 0) {
+ // Handle decompressing Fab encoded data
+ for (curFrame = 0; curFrame < _frameCount; curFrame++) {
+ FabDecompressor fab;
+
+ int srcSize = (curFrame == (_frameCount - 1)) ? spriteDataStream->size() - _frameOffsets[curFrame] :
+ _frameOffsets[curFrame + 1] - _frameOffsets[curFrame];
+ byte *srcData = new byte[srcSize];
+ assert(srcData);
+ spriteDataStream->read(srcData, srcSize);
+
+ byte *destData = new byte[frameSizes[curFrame]];
+ assert(destData);
+
+ fab.decompress(srcData, srcSize, destData, frameSizes[curFrame]);
+
+ // Load the frames
+ Common::MemoryReadStream *rs = new Common::MemoryReadStream(destData, frameSizes[curFrame]);
+ _frames[curFrame]._frame = new MSprite(rs, palette, _frames[curFrame]._bounds);
+ delete rs;
+
+ delete[] srcData;
+ delete[] destData;
+ }
+ }
+
+ delete spriteStream;
+ delete spriteDataStream;
+}
+
+MSprite *SpriteAsset::getFrame(int frameIndex) {
+ if ((uint)frameIndex < _frames.size()) {
+ return _frames[frameIndex]._frame;
+ } else {
+ debugC(kDebugGraphics, "SpriteAsset::getFrame: Invalid frame %d, out of %d", frameIndex, _frames.size());
+ return _frames[_frames.size() - 1]._frame;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+SpriteSetCharInfo::SpriteSetCharInfo(Common::SeekableReadStream *s) {
+ _totalFrames = s->readByte();
+ s->skip(1);
+ _numEntries = s->readUint16LE();
+
+ for (int i = 0; i < 16; ++i)
+ _startFrames[i] = s->readUint16LE();
+ for (int i = 0; i < 16; ++i)
+ _stopFrames[i] = s->readUint16LE();
+ for (int i = 0; i < 16; ++i)
+ _ticksList[i] = s->readUint16LE();
+
+ _velocity = s->readUint16LE();
+ _ticksAmount = s->readByte();
+ _centerOfGravity = s->readByte();
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/assets.h b/engines/mads/assets.h
new file mode 100644
index 0000000000..155590f9bd
--- /dev/null
+++ b/engines/mads/assets.h
@@ -0,0 +1,114 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_ASSETS_H
+#define MADS_ASSETS_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "mads/palette.h"
+
+namespace MADS {
+
+enum AssetFlags {
+ ASSET_TRANSLATE = 1, ASSET_HEADER_ONLY = 2, ASSET_CHAR_INFO = 4,
+ ASSET_SPINNING_OBJECT = 8
+};
+
+class MADSEngine;
+class MSprite;
+class MSurface;
+
+struct SpriteAssetFrame {
+ uint32 _stream;
+ Common::Rect _bounds;
+ uint32 _comp;
+ MSprite *_frame;
+};
+
+class SpriteSetCharInfo {
+public:
+ SpriteSetCharInfo(Common::SeekableReadStream *s);
+
+ int _totalFrames;
+ int _numEntries;
+ int _startFrames[16];
+ int _stopFrames[16];
+ int _ticksList[16];
+ int _velocity;
+ int _ticksAmount;
+ int _centerOfGravity;
+};
+
+class SpriteAsset {
+private:
+ MADSEngine *_vm;
+ byte _palette[PALETTE_SIZE];
+ int _colorCount;
+ uint32 _srcSize;
+ int _frameRate, _pixelSpeed;
+ int _maxWidth, _maxHeight;
+ int _frameCount;
+ Common::Array<uint32> _frameOffsets;
+ Common::Array<SpriteAssetFrame> _frames;
+ uint8 _mode;
+ bool _isBackground;
+
+ /**
+ * Load the data for the asset
+ */
+ void load(Common::SeekableReadStream *stream, int flags);
+public:
+ SpriteSetCharInfo *_charInfo;
+ int _usageIndex;
+public:
+ /**
+ * Constructor
+ */
+ SpriteAsset(MADSEngine *vm, const Common::String &resourceName, int flags);
+
+ /**
+ * Constructor
+ */
+ SpriteAsset(MADSEngine *vm, Common::SeekableReadStream *stream, int flags);
+
+ /**
+ * Destructor
+ */
+ ~SpriteAsset();
+
+ int getCount() { return _frameCount; }
+ int getFrameRate() const { return _frameRate; }
+ int getPixelSpeed() const { return _pixelSpeed; }
+ int getFrameWidth(int index);
+ int getFrameHeight(int index);
+ int getMaxFrameWidth() const { return _maxWidth; }
+ int getMaxFrameHeight() const { return _maxHeight; }
+ MSprite *getFrame(int frameIndex);
+ byte *getPalette() { return _palette; }
+ int getColorCount() { return _colorCount; }
+ bool isBackground() const { return _isBackground; }
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_ASSETS_H */
diff --git a/engines/mads/audio.cpp b/engines/mads/audio.cpp
new file mode 100644
index 0000000000..1c61e13957
--- /dev/null
+++ b/engines/mads/audio.cpp
@@ -0,0 +1,129 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mads/audio.h"
+#include "mads/compression.h"
+
+#include "common/stream.h"
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+
+namespace MADS {
+
+AudioPlayer::AudioPlayer(Audio::Mixer *mixer, uint32 gameID) : _mixer(mixer), _gameID(gameID) {
+ setVolume(Audio::Mixer::kMaxChannelVolume);
+ setDefaultSoundGroup();
+}
+
+AudioPlayer::~AudioPlayer() {
+ _dsrEntries.clear();
+}
+
+bool AudioPlayer::isPlaying() const {
+ return _mixer->isSoundHandleActive(_handle);
+}
+
+void AudioPlayer::setVolume(int volume) {
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume);
+}
+
+void AudioPlayer::setDefaultSoundGroup() {
+ switch (_gameID) {
+ case GType_RexNebular:
+ setSoundGroup("rex009.dsr");
+ break;
+ case GType_Dragonsphere:
+ setSoundGroup("drag009.dsr");
+ break;
+ case GType_Phantom:
+ setSoundGroup("phan009.dsr");
+ break;
+ default:
+ error("setDefaultSoundGroup: Unknown game");
+ }
+}
+
+void AudioPlayer::setSoundGroup(const Common::String &filename) {
+ _dsrEntries.clear();
+
+ _filename = filename;
+ _dsrFile.open(filename);
+
+ // Read header
+ uint16 entryCount = _dsrFile.readUint16LE();
+
+ for (uint16 i = 0; i < entryCount; i++) {
+ DSREntry newEntry;
+ newEntry.frequency = _dsrFile.readUint16LE();
+ newEntry.channels = _dsrFile.readUint32LE();
+ newEntry.compSize = _dsrFile.readUint32LE();
+ newEntry.uncompSize = _dsrFile.readUint32LE();
+ newEntry.offset = _dsrFile.readUint32LE();
+ _dsrEntries.push_back(newEntry);
+ }
+
+ _dsrFile.close();
+}
+
+void AudioPlayer::playSound(int soundIndex, bool loop) {
+ if (_dsrEntries.empty()) {
+ warning("DSR file not loaded, not playing sound");
+ return;
+ }
+
+ if (soundIndex < 0 || soundIndex > (int)_dsrEntries.size() - 1) {
+ warning("Invalid sound index: %i (max %i), not playing sound", soundIndex, _dsrEntries.size() - 1);
+ return;
+ }
+
+ // Get sound data
+ FabDecompressor fab;
+ int32 compSize = _dsrEntries[soundIndex].compSize;
+ int32 uncompSize = _dsrEntries[soundIndex].uncompSize;
+ int32 offset = _dsrEntries[soundIndex].offset;
+ int16 frequency = _dsrEntries[soundIndex].frequency;
+ byte *compData = new byte[compSize];
+ byte *buffer = new byte[uncompSize];
+ _dsrFile.open(_filename);
+ _dsrFile.seek(offset, SEEK_SET);
+ _dsrFile.read(compData, compSize);
+ _dsrFile.close();
+
+ fab.decompress(compData, compSize, buffer, uncompSize);
+
+ // Play sound
+ Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
+ Audio::makeRawStream(buffer, uncompSize, frequency, Audio::FLAG_UNSIGNED),
+ loop ? 0 : 1);
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, stream, -1, Audio::Mixer::kMaxChannelVolume);
+
+ /*
+ // Dump the sound file
+ FILE *destFile = fopen("sound.raw", "wb");
+ fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex].uncompSize, 1, destFile);
+ fclose(destFile);
+ */
+}
+
+} // End of namespace M4
diff --git a/engines/mads/audio.h b/engines/mads/audio.h
new file mode 100644
index 0000000000..21f4bed59a
--- /dev/null
+++ b/engines/mads/audio.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_AUDIO_H
+#define MADS_AUDIO_H
+
+#include "mads/resources.h"
+
+#include "common/array.h"
+#include "audio/mixer.h"
+
+namespace MADS {
+
+struct DSREntry {
+ int16 frequency;
+ int channels;
+ int32 compSize;
+ int32 uncompSize;
+ int32 offset;
+};
+
+class AudioPlayer {
+public:
+ AudioPlayer(Audio::Mixer *mixer, uint32 gameID);
+ ~AudioPlayer();
+
+ void setSoundGroup(const Common::String &filename);
+ void setDefaultSoundGroup();
+ void playSound(int soundIndex, bool loop = false);
+ void setVolume(int volume);
+ bool isPlaying() const;
+
+ private:
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle _handle;
+ uint32 _gameID;
+
+ File _dsrFile;
+ Common::String _filename;
+ Common::Array<DSREntry> _dsrEntries;
+};
+
+} // End of namespace MADS
+
+#endif
diff --git a/engines/mads/compression.cpp b/engines/mads/compression.cpp
new file mode 100644
index 0000000000..79cd1786de
--- /dev/null
+++ b/engines/mads/compression.cpp
@@ -0,0 +1,194 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mads/compression.h"
+
+namespace MADS {
+
+const char *const madsPackString = "MADSPACK";
+const char *const FabInputExceededError = "FabDecompressor - Passed end of input buffer during decompression";
+const char *const FabOutputExceededError = "FabDecompressor - Decompressed data exceeded specified size";
+
+bool MadsPack::isCompressed(Common::SeekableReadStream *stream) {
+ // Check whether the passed stream is packed
+
+ char tempBuffer[8];
+ stream->seek(0);
+ if (stream->read(tempBuffer, 8) == 8) {
+ if (!strncmp(tempBuffer, madsPackString, 8))
+ return true;
+ }
+
+ return false;
+}
+
+MadsPack::MadsPack(Common::SeekableReadStream *stream) {
+ initialize(stream);
+}
+
+MadsPack::MadsPack(const Common::String &resourceName, MADSEngine *vm) {
+ File file(resourceName);
+ initialize(&file);
+ file.close();
+}
+
+void MadsPack::initialize(Common::SeekableReadStream *stream) {
+ if (!MadsPack::isCompressed(stream))
+ error("Attempted to decompress a resource that was not MadsPacked");
+
+ stream->seek(14);
+ _count = stream->readUint16LE();
+ _items = new MadsPackEntry[_count];
+
+ byte *headerData = new byte[0xA0];
+ byte *header = headerData;
+ stream->read(headerData, 0xA0);
+
+ for (int i = 0; i < _count; ++i, header += 10) {
+ // Get header data
+ _items[i]._type = (CompressionType)*header;
+ _items[i]._priority = *(header + 1);
+ _items[i]._size = READ_LE_UINT32(header + 2);
+ _items[i]._compressedSize = READ_LE_UINT32(header + 6);
+
+ byte *sourceData = new byte[_items[i]._compressedSize];
+ stream->read(sourceData, _items[i]._compressedSize);
+
+ switch (_items[i]._type) {
+ case COMPRESS_NONE:
+ // Entry isn't compressed
+ _items[i]._data = sourceData;
+ break;
+
+ case COMPRESS_FAB: {
+ // Decompress the entry
+ _items[i]._data = new byte[_items[i]._size];
+
+ FabDecompressor fab;
+ fab.decompress(sourceData, _items[i]._compressedSize, _items[i]._data, _items[i]._size);
+ delete[] sourceData;
+ break;
+ }
+
+ default:
+ error("Unknown compression type encountered");
+ }
+ }
+
+ delete[] headerData;
+ _dataOffset = stream->pos();
+}
+
+MadsPack::~MadsPack() {
+ for (int i = 0; i < _count; ++i)
+ delete[] _items[i]._data;
+ delete[] _items;
+}
+
+//--------------------------------------------------------------------------
+
+void FabDecompressor::decompress(const byte *srcData, int srcSize, byte *destData, int destSize) {
+ byte copyLen, copyOfsShift, copyOfsMask, copyLenMask;
+ unsigned long copyOfs;
+ byte *destP;
+
+ // Validate that the data starts with the FAB header
+ if (strncmp((const char *)srcData, "FAB", 3) != 0)
+ error("FabDecompressor - Invalid compressed data");
+
+ int shiftVal = srcData[3];
+ if ((shiftVal < 10) || (shiftVal > 13))
+ error("FabDecompressor - Invalid shift start");
+
+ copyOfsShift = 16 - shiftVal;
+ copyOfsMask = 0xFF << (shiftVal - 8);
+ copyLenMask = (1 << copyOfsShift) - 1;
+ copyOfs = 0xFFFF0000;
+ destP = destData;
+
+ // Initialize data fields
+ _srcData = srcData;
+ _srcP = _srcData + 6;
+ _srcSize = srcSize;
+ _bitsLeft = 16;
+ _bitBuffer = READ_LE_UINT16(srcData + 4);
+
+ for (;;) {
+ if (getBit() == 0) {
+ if (getBit() == 0) {
+ copyLen = ((getBit() << 1) | getBit()) + 2;
+ copyOfs = *_srcP++ | 0xFFFFFF00;
+ } else {
+ copyOfs = (((_srcP[1] >> copyOfsShift) | copyOfsMask) << 8) | _srcP[0];
+ copyLen = _srcP[1] & copyLenMask;
+ _srcP += 2;
+ if (copyLen == 0) {
+ copyLen = *_srcP++;
+ if (copyLen == 0)
+ break;
+ else if (copyLen == 1)
+ continue;
+ else
+ copyLen++;
+ } else {
+ copyLen += 2;
+ }
+ copyOfs |= 0xFFFF0000;
+ }
+ while (copyLen-- > 0) {
+ if (destP - destData == destSize)
+ error(FabOutputExceededError);
+
+ *destP = destP[(signed int)copyOfs];
+ destP++;
+ }
+ } else {
+ if (_srcP - srcData == srcSize)
+ error(FabInputExceededError);
+ if (destP - destData == destSize)
+ error(FabOutputExceededError);
+
+ *destP++ = *_srcP++;
+ }
+ }
+
+ if (destP - destData != destSize)
+ error("FabDecompressor - Decompressed data does not match header decompressed size");
+}
+
+int FabDecompressor::getBit() {
+ _bitsLeft--;
+ if (_bitsLeft == 0) {
+ if (_srcP - _srcData == _srcSize)
+ error(FabInputExceededError);
+
+ _bitBuffer = (READ_LE_UINT16(_srcP) << 1) | (_bitBuffer & 1);
+ _srcP += 2;
+ _bitsLeft = 16;
+ }
+
+ int bit = _bitBuffer & 1;
+ _bitBuffer >>= 1;
+ return bit;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/compression.h b/engines/mads/compression.h
new file mode 100644
index 0000000000..f7381e4af3
--- /dev/null
+++ b/engines/mads/compression.h
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_COMPRESSION_H
+#define MADS_COMPRESSION_H
+
+#include "common/scummsys.h"
+#include "common/endian.h"
+#include "common/memstream.h"
+#include "common/stream.h"
+
+#include "mads/mads.h"
+
+namespace MADS {
+
+enum CompressionType { COMPRESS_NONE = 0, COMPRESS_FAB = 1 };
+
+struct MadsPackEntry {
+public:
+ CompressionType _type;
+ byte _priority;
+ uint32 _size;
+ uint32 _compressedSize;
+ byte *_data;
+};
+
+class MadsPack {
+private:
+ MadsPackEntry *_items;
+ int _count;
+ int _dataOffset;
+
+ void initialize(Common::SeekableReadStream *stream);
+public:
+ static bool isCompressed(Common::SeekableReadStream *stream);
+ MadsPack(Common::SeekableReadStream *stream);
+ MadsPack(const Common::String &resourceName, MADSEngine *_vm);
+ ~MadsPack();
+
+ int getCount() const { return _count; }
+ MadsPackEntry &getItem(int index) const {
+ assert(index < _count);
+ return _items[index]; }
+ MadsPackEntry &operator[](int index) const {
+ assert(index < _count);
+ return _items[index];
+ }
+ Common::MemoryReadStream *getItemStream(int index) {
+ assert(index < _count);
+ return new Common::MemoryReadStream(_items[index]._data, _items[index]._size,
+ DisposeAfterUse::NO);
+ }
+ int getDataOffset() const { return _dataOffset; }
+};
+
+class FabDecompressor {
+private:
+ int _bitsLeft;
+ uint32 _bitBuffer;
+ const byte *_srcData, *_srcP;
+ int _srcSize;
+
+ int getBit();
+public:
+ void decompress(const byte *srcData, int srcSize, byte *destData, int destSize);
+};
+
+} // End of namespace MADS
+
+#endif
diff --git a/engines/mads/configure.engine b/engines/mads/configure.engine
new file mode 100644
index 0000000000..60d833e9e8
--- /dev/null
+++ b/engines/mads/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine mads "Rex Nebular and the Cosmic Gender Bender" no
diff --git a/engines/mads/debugger.cpp b/engines/mads/debugger.cpp
new file mode 100644
index 0000000000..6bc6cf572d
--- /dev/null
+++ b/engines/mads/debugger.cpp
@@ -0,0 +1,351 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "mads/compression.h"
+#include "mads/mads.h"
+#include "mads/debugger.h"
+
+namespace MADS {
+
+Debugger::Debugger(MADSEngine *vm) : GUI::Debugger(), _vm(vm) {
+ _showMousePos = false;
+
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse));
+ registerCmd("scene", WRAP_METHOD(Debugger, Cmd_LoadScene));
+ registerCmd("show_hotspots", WRAP_METHOD(Debugger, Cmd_ShowHotSpots));
+ registerCmd("list_hotspots", WRAP_METHOD(Debugger, Cmd_ListHotSpots));
+ registerCmd("play_sound", WRAP_METHOD(Debugger, Cmd_PlaySound));
+ registerCmd("play_audio", WRAP_METHOD(Debugger, Cmd_PlayAudio));
+ registerCmd("show_codes", WRAP_METHOD(Debugger, Cmd_ShowCodes));
+ registerCmd("dump_file", WRAP_METHOD(Debugger, Cmd_DumpFile));
+ registerCmd("show_quote", WRAP_METHOD(Debugger, Cmd_ShowQuote));
+ registerCmd("show_vocab", WRAP_METHOD(Debugger, Cmd_ShowVocab));
+ registerCmd("dump_vocab", WRAP_METHOD(Debugger, Cmd_DumpVocab));
+ registerCmd("show_message", WRAP_METHOD(Debugger, Cmd_ShowMessage));
+ registerCmd("show_item", WRAP_METHOD(Debugger, Cmd_ShowItem));
+ registerCmd("dump_items", WRAP_METHOD(Debugger, Cmd_DumpItems));
+ registerCmd("item", WRAP_METHOD(Debugger, Cmd_Item));
+}
+
+static int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+bool Debugger::Cmd_Mouse(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Usage: %s [ on | off ]\n", argv[0]);
+ } else {
+ _showMousePos = strcmp(argv[1], "on") == 0;
+ }
+
+ return true;
+}
+
+bool Debugger::Cmd_LoadScene(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Current scene is: %d\n", _vm->_game->_scene._currentSceneId);
+ debugPrintf("Usage: %s <scene number>\n", argv[0]);
+ return true;
+ } else {
+ _vm->_game->_scene._nextSceneId = strToInt(argv[1]);
+ return false;
+ }
+}
+
+bool Debugger::Cmd_ShowHotSpots(int argc, const char **argv) {
+ Scene &scene = _vm->_game->_scene;
+
+ // hotspots
+ byte hotspotCol = _vm->getRandomNumber(255);
+ for (uint i = 0; i < scene._hotspots.size(); i++) {
+ scene._backgroundSurface.frameRect(scene._hotspots[i]._bounds, hotspotCol);
+ }
+
+ // Dynamic hotspots (red)
+ hotspotCol = _vm->getRandomNumber(255);
+ for (uint i = 0; i < scene._dynamicHotspots.size(); i++) {
+ scene._backgroundSurface.frameRect(scene._dynamicHotspots[i]._bounds, hotspotCol);
+ }
+
+ scene._spriteSlots.fullRefresh();
+ return false;
+}
+
+bool Debugger::Cmd_ListHotSpots(int argc, const char **argv) {
+ Hotspots &hotspots = _vm->_game->_scene._hotspots;
+
+ debugPrintf("%d hotspots present\n", hotspots.size());
+
+ for (uint index = 0; index < hotspots.size(); ++index) {
+ debugPrintf("(%d): %p x1 = %d; y1 = %d; x2 = %d; y2 = %d\n",
+ index, (void *)&hotspots[index],
+ hotspots[index]._bounds.left, hotspots[index]._bounds.top,
+ hotspots[index]._bounds.right, hotspots[index]._bounds.bottom);
+ }
+
+ return true;
+}
+
+bool Debugger::Cmd_PlaySound(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Usage: %s <sound file>\n", argv[0]);
+ } else {
+ int commandId = strToInt(argv[1]);
+ int param = (argc >= 3) ? strToInt(argv[2]) : 0;
+
+ _vm->_sound->command(commandId, param);
+ }
+
+ return false;
+}
+
+bool Debugger::Cmd_PlayAudio(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Usage: %s <sound index> <sound group>\n", argv[0]);
+ debugPrintf("If the sound group isn't defined, the default one will be used\n");
+ } else {
+ int index = strToInt(argv[1]);
+ Common::String soundGroup = (argc >= 3) ? argv[2] : "";
+ if (argc >= 3)
+ _vm->_audio->setSoundGroup(argv[2]);
+ else
+ _vm->_audio->setDefaultSoundGroup();
+
+ _vm->_audio->playSound(index);
+ }
+
+ return true;
+}
+
+bool Debugger::Cmd_ShowCodes(int argc, const char **argv) {
+ Scene &scene = _vm->_game->_scene;
+
+ // Copy the depth/walk surface to the background and flag for screen refresh
+ scene._depthSurface.copyTo(&scene._backgroundSurface);
+ scene._spriteSlots.fullRefresh();
+
+ // Draw the locations of scene nodes onto the background
+ int color = _vm->getRandomNumber(255);
+ for (int i = 0; i < (int)scene._sceneInfo->_nodes.size(); ++i) {
+ Common::Point &pt = scene._sceneInfo->_nodes[i]._walkPos;
+
+ scene._backgroundSurface.hLine(pt.x - 2, pt.y, pt.x + 2, color);
+ scene._backgroundSurface.vLine(pt.x, pt.y - 2, pt.y + 2, color);
+ }
+
+ return false;
+}
+
+bool Debugger::Cmd_DumpFile(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Usage: %s <resource> <unpack>\n", argv[0]);
+ debugPrintf(" resource: the resource name\n");
+ debugPrintf(" unpack: optional, when specified, the FAB/MADSPACK compressed resource is unpacked\n");
+ } else {
+ Common::DumpFile outFile;
+ Common::File inFile;
+
+ if (!inFile.open(argv[1])) {
+ debugPrintf("Specified resource does not exist\n");
+ } else {
+ outFile.open(argv[1]);
+ bool unpack = ((argc >= 3) && !scumm_stricmp(argv[2], "unpack"));
+
+ byte *data;
+ int totalSize = 0;
+
+ if (!unpack) {
+ totalSize = inFile.size();
+ data = new byte[totalSize];
+ inFile.read(data, totalSize);
+ } else {
+ MadsPack dataPack(&inFile);
+ int count = dataPack.getCount();
+ for (int i = 0; i < count; i++) {
+ totalSize += dataPack.getItem(i)._size;
+ }
+ data = new byte[totalSize];
+ byte *ptr = data;
+
+ for (int i = 0; i < count; i++) {
+ Common::SeekableReadStream *readStream = dataPack.getItemStream(i);
+ readStream->read(ptr, readStream->size());
+ ptr += readStream->size();
+ }
+ }
+
+ outFile.write(data, totalSize);
+ outFile.flush();
+
+ delete[] data;
+ inFile.close();
+ outFile.close();
+
+ debugPrintf("File written successfully.\n");
+ }
+ }
+
+ return true;
+}
+
+bool Debugger::Cmd_ShowQuote(int argc, const char **argv) {
+ if (argc != 2)
+ debugPrintf("Usage: %s <quote number>\n", argv[0]);
+ else
+ debugPrintf("%s", _vm->_game->getQuote(strToInt(argv[1])).c_str());
+
+ return true;
+}
+
+bool Debugger::Cmd_ShowVocab(int argc, const char **argv) {
+ if (argc != 2) {
+ for (uint32 i = 0; i < _vm->_game->_scene.getVocabStringsCount(); i++) {
+ debugPrintf("%03d: '%s'\n", i, _vm->_game->_scene.getVocab(i + 1).c_str());
+ }
+ } else {
+ int vocabId = strToInt(argv[1]);
+ debugPrintf("%03d: '%s'\n", vocabId, _vm->_game->_scene.getVocab(vocabId + 1).c_str());
+ }
+
+ return true;
+}
+
+bool Debugger::Cmd_DumpVocab(int argc, const char **argv) {
+ Common::DumpFile outFile;
+ outFile.open("vocab.txt");
+
+ for (uint32 i = 0; i < _vm->_game->_scene.getVocabStringsCount(); i++) {
+ Common::String curId = Common::String::format("%x", i + 1);
+ Common::String curVocab = _vm->_game->_scene.getVocab(i + 1);
+ curVocab.toUppercase();
+
+ for (uint j = 0; j < curVocab.size(); j++) {
+ if (curVocab[j] == ' ' || curVocab[j] == '-')
+ curVocab.setChar('_', j);
+ }
+
+ Common::String cur = "\tNOUN_" + curVocab + " = 0x" + curId + ",\n";
+
+ outFile.writeString(cur.c_str());
+ }
+
+ outFile.flush();
+ outFile.close();
+
+ debugPrintf("Game vocab dumped\n");
+
+ return true;
+}
+
+bool Debugger::Cmd_ShowMessage(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Usage: %s <message number>\n", argv[0]);
+ } else {
+ int messageId = strToInt(argv[1]);
+ Common::StringArray msg = _vm->_game->getMessage(messageId);
+ for (uint idx = 0; idx < msg.size(); ++idx) {
+ Common::String srcLine = msg[idx];
+ debugPrintf("%s\n", srcLine.c_str());
+ }
+ }
+
+ return true;
+}
+
+bool Debugger::Cmd_ShowItem(int argc, const char **argv) {
+ InventoryObjects &objects = _vm->_game->_objects;
+
+ if (argc != 2) {
+ for (uint32 i = 0; i < objects.size(); i++) {
+ Common::String desc = _vm->_game->_scene.getVocab(objects[i]._descId);
+ debugPrintf("%03d: '%s'\n", i, desc.c_str());
+ }
+ } else {
+ int vocabId = strToInt(argv[1]);
+ Common::String desc = _vm->_game->_scene.getVocab(objects[vocabId]._descId);
+ debugPrintf("%03d: '%s'\n", vocabId, desc.c_str());
+ }
+
+ return true;
+}
+
+bool Debugger::Cmd_DumpItems(int argc, const char **argv) {
+ InventoryObjects &objects = _vm->_game->_objects;
+
+ Common::DumpFile outFile;
+ outFile.open("items.txt");
+
+ for (uint32 i = 0; i < objects.size(); i++) {
+ Common::String curId = Common::String::format("%d", i);
+ Common::String desc = _vm->_game->_scene.getVocab(objects[i]._descId);
+ desc.toUppercase();
+
+ for (uint j = 0; j < desc.size(); j++) {
+ if (desc[j] == ' ' || desc[j] == '-')
+ desc.setChar('_', j);
+ }
+
+ Common::String cur = "\tOBJ_" + desc + " = " + curId + ",\n";
+
+ outFile.writeString(cur.c_str());
+ }
+
+ outFile.flush();
+ outFile.close();
+
+ debugPrintf("Game items dumped\n");
+
+ return true;
+}
+
+bool Debugger::Cmd_Item(int argc, const char **argv) {
+ InventoryObjects &objects = _vm->_game->_objects;
+
+ if (argc != 2) {
+ debugPrintf("Usage: %s <item number>\n", argv[0]);
+ return true;
+ } else {
+ int objectId = strToInt(argv[1]);
+
+ if (!objects.isInInventory(objectId))
+ objects.addToInventory(objectId);
+
+ debugPrintf("Item added.\n");
+ return false;
+ }
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/debugger.h b/engines/mads/debugger.h
new file mode 100644
index 0000000000..351eb13615
--- /dev/null
+++ b/engines/mads/debugger.h
@@ -0,0 +1,61 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_DEBUGGER_H
+#define MADS_DEBUGGER_H
+
+#include "common/scummsys.h"
+#include "gui/debugger.h"
+
+namespace MADS {
+
+class MADSEngine;
+
+class Debugger : public GUI::Debugger {
+private:
+ MADSEngine *_vm;
+protected:
+ bool Cmd_Mouse(int argc, const char **argv);
+ bool Cmd_LoadScene(int argc, const char **argv);
+ bool Cmd_ShowHotSpots(int argc, const char **argv);
+ bool Cmd_ListHotSpots(int argc, const char **argv);
+ bool Cmd_PlaySound(int argc, const char **argv);
+ bool Cmd_PlayAudio(int argc, const char **argv);
+ bool Cmd_ShowCodes(int argc, const char **argv);
+ bool Cmd_DumpFile(int argc, const char **argv);
+ bool Cmd_ShowQuote(int argc, const char **argv);
+ bool Cmd_ShowVocab(int argc, const char **argv);
+ bool Cmd_DumpVocab(int argc, const char **argv);
+ bool Cmd_ShowMessage(int argc, const char **argv);
+ bool Cmd_ShowItem(int argc, const char **argv);
+ bool Cmd_DumpItems(int argc, const char **argv);
+ bool Cmd_Item(int argc, const char **argv);
+public:
+ bool _showMousePos;
+public:
+ Debugger(MADSEngine *vm);
+ virtual ~Debugger() {}
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_DEBUGGER_H */
diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp
new file mode 100644
index 0000000000..971acde024
--- /dev/null
+++ b/engines/mads/detection.cpp
@@ -0,0 +1,194 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include "mads/mads.h"
+
+#include "base/plugins.h"
+#include "common/savefile.h"
+#include "common/str-array.h"
+#include "common/memstream.h"
+#include "engines/advancedDetector.h"
+#include "common/system.h"
+#include "graphics/colormasks.h"
+#include "graphics/surface.h"
+#include "mads/events.h"
+#include "mads/game.h"
+
+#define MAX_SAVES 99
+
+namespace MADS {
+
+struct MADSGameDescription {
+ ADGameDescription desc;
+
+ int gameID;
+ uint32 features;
+};
+
+uint32 MADSEngine::getGameID() const {
+ return _gameDescription->gameID;
+}
+
+uint32 MADSEngine::getGameFeatures() const {
+ return _gameDescription->features;
+}
+
+uint32 MADSEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+Common::Language MADSEngine::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
+Common::Platform MADSEngine::getPlatform() const {
+ return _gameDescription->desc.platform;
+}
+
+} // End of namespace MADS
+
+static const PlainGameDescriptor MADSGames[] = {
+ {"MADS", "MADS"},
+ {"dragonsphere", "Dragonsphere"},
+ {"nebular", "Rex Nebular and the Cosmic Gender Bender"},
+ {"phantom", "Return of the Phantom"},
+ {0, 0}
+};
+
+#include "mads/detection_tables.h"
+
+class MADSMetaEngine : public AdvancedMetaEngine {
+public:
+ MADSMetaEngine() : AdvancedMetaEngine(MADS::gameDescriptions, sizeof(MADS::MADSGameDescription), MADSGames) {
+ _maxScanDepth = 3;
+ }
+
+ virtual const char *getName() const {
+ return "MADS Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "MADS (c)";
+ }
+
+ 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;
+ virtual void removeSaveState(const char *target, int slot) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+};
+
+bool MADSMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail);
+}
+
+bool MADS::MADSEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+bool MADSMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const MADS::MADSGameDescription *gd = (const MADS::MADSGameDescription *)desc;
+ if (gd) {
+ *engine = new MADS::MADSEngine(syst, gd);
+ }
+ return gd != 0;
+}
+
+SaveStateList MADSMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String saveDesc;
+ Common::String pattern = Common::String::format("%s.0??", target);
+ MADS::MADSSavegameHeader header;
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ const char *ext = strrchr(file->c_str(), '.');
+ int slot = ext ? atoi(ext + 1) : -1;
+
+ if (slot >= 0 && slot < MAX_SAVES) {
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
+
+ if (in) {
+ MADS::Game::readSavegameHeader(in, header);
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+
+ header._thumbnail->free();
+ delete header._thumbnail;
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+int MADSMetaEngine::getMaximumSaveSlot() const {
+ return MAX_SAVES;
+}
+
+void MADSMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String filename = Common::String::format("%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(filename);
+}
+
+SaveStateDescriptor MADSMetaEngine::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) {
+ MADS::MADSSavegameHeader header;
+ MADS::Game::readSavegameHeader(f, header);
+ delete f;
+
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header._saveName);
+ desc.setThumbnail(header._thumbnail);
+ desc.setSaveDate(header._year, header._month, header._day);
+ desc.setSaveTime(header._hour, header._minute);
+ desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
+
+ return desc;
+ }
+
+ return SaveStateDescriptor();
+}
+
+
+#if PLUGIN_ENABLED_DYNAMIC(MADS)
+ REGISTER_PLUGIN_DYNAMIC(MADS, PLUGIN_TYPE_ENGINE, MADSMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(MADS, PLUGIN_TYPE_ENGINE, MADSMetaEngine);
+#endif
diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h
new file mode 100644
index 0000000000..e68ae380d0
--- /dev/null
+++ b/engines/mads/detection_tables.h
@@ -0,0 +1,122 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+namespace MADS {
+
+static const MADSGameDescription gameDescriptions[] = {
+#if 0
+ {
+ // Rex Nebular and the Cosmic Gender Bender DOS English (compressed)
+ // Removed for now, until the original floppy compression is supported
+ {
+ "nebular",
+ 0,
+ {
+ {"mpslabs.001", 0, "4df5c557b52abb5b661cf4befe5ae301", 1315354},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GType_RexNebular,
+ 0
+ },
+#endif
+
+ {
+ // Rex Nebular and the Cosmic Gender Bender DOS English
+ {
+ "nebular",
+ 0,
+ {
+ {"section1.hag", 0, "6f725eb38660de8af31ec7cdd628d615", 927222},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GType_RexNebular,
+ 0
+ },
+
+ {
+ // Rex Nebular and the Cosmic Gender Bender DOS English 8.49 Alternate
+ {
+ "nebular",
+ 0,
+ {
+ { "section1.hag", 0, "d583576923e3437937fb7f46f4b6274f", 927222 },
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GType_RexNebular,
+ 0
+ },
+
+ {
+ // Return of the Phantom DOS English
+ {
+ "phantom",
+ 0,
+ {
+ {"section1.hag", 0, "76e2d47a7aebafe48edc9884b3d91782", 1130939},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GType_Phantom,
+ 0
+ },
+
+ {
+ // Dragonsphere DOS English
+ {
+ "dragonsphere",
+ 0,
+ {
+ {"section1.hag", 0, "2770e441d296be5e806194693eebd95a", 2061199},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GType_Dragonsphere,
+ 0
+ },
+
+ { AD_TABLE_END_MARKER, 0, 0 }
+};
+
+} // End of namespace MADS
diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp
new file mode 100644
index 0000000000..7e6909d113
--- /dev/null
+++ b/engines/mads/dialogs.cpp
@@ -0,0 +1,398 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "mads/mads.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/nebular/dialogs_nebular.h"
+
+namespace MADS {
+
+Dialog::Dialog(MADSEngine *vm)
+ : _vm(vm), _savedSurface(nullptr), _position(Common::Point(-1, -1)),
+ _width(0), _height(0) {
+ TEXTDIALOG_CONTENT1 = 0XF8;
+ TEXTDIALOG_CONTENT2 = 0XF9;
+ TEXTDIALOG_EDGE = 0XFA;
+ TEXTDIALOG_BACKGROUND = 0XFB;
+ TEXTDIALOG_FC = 0XFC;
+ TEXTDIALOG_FD = 0XFD;
+ TEXTDIALOG_FE = 0XFE;
+ TEXTDIALOG_BLACK = 0;
+}
+
+Dialog::~Dialog() {
+}
+
+void Dialog::save() {
+ _savedSurface = new MSurface(_width, _height);
+ _vm->_screen.copyTo(_savedSurface,
+ Common::Rect(_position.x, _position.y, _position.x + _width, _position.y + _height),
+ Common::Point());
+
+ _vm->_screen.copyRectToScreen(getBounds());
+}
+
+void Dialog::restore() {
+ if (_savedSurface) {
+ _savedSurface->copyTo(&_vm->_screen, _position);
+ delete _savedSurface;
+ _savedSurface = nullptr;
+
+ _vm->_screen.copyRectToScreen(getBounds());
+
+ Common::copy(&_dialogPalette[0], &_dialogPalette[8 * 3],
+ &_vm->_palette->_mainPalette[248 * 3]);
+ _vm->_palette->setPalette(&_vm->_palette->_mainPalette[248 * 3], 248, 8);
+ }
+}
+
+void Dialog::draw() {
+ // Calculate the dialog positioning
+ calculateBounds();
+
+ // Save the screen portion the dialog will overlap
+ save();
+
+ setDialogPalette();
+
+ // Draw the dialog
+ // Fill entire content of dialog
+ Common::Rect bounds = getBounds();
+ _vm->_screen.fillRect(bounds, TEXTDIALOG_BACKGROUND);
+
+ // Draw the outer edge lines
+ _vm->_screen.hLine(_position.x + 1, _position.y + _height - 2,
+ _position.x + _width - 2, TEXTDIALOG_EDGE);
+ _vm->_screen.hLine(_position.x, _position.y + _height - 1,
+ _position.x + _width - 1, TEXTDIALOG_EDGE);
+ _vm->_screen.vLine(_position.x + _width - 2, _position.y + 2,
+ _position.y + _height - 2, TEXTDIALOG_EDGE);
+ _vm->_screen.vLine(_position.x + _width - 1, _position.y + 1,
+ _position.y + _height - 1, TEXTDIALOG_EDGE);
+
+ // Draw the gravelly dialog content
+ drawContent(Common::Rect(_position.x + 2, _position.y + 2,
+ _position.x + _width - 2, _position.y + _height - 2), 0,
+ TEXTDIALOG_CONTENT1, TEXTDIALOG_CONTENT2);
+}
+
+void Dialog::setDialogPalette() {
+ // Save the high end of the palette, and set up the entries for dialog display
+ Common::copy(&_vm->_palette->_mainPalette[TEXTDIALOG_CONTENT1 * 3],
+ &_vm->_palette->_mainPalette[TEXTDIALOG_CONTENT1 * 3 + 8 * 3],
+ &_dialogPalette[0]);
+ Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_CONTENT1, 2, 0x90, 0x80);
+ Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_EDGE, 2, 0x9C, 0x70);
+ Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FC, 2, 0x90, 0x80);
+ Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FE, 1, 0xDC, 0xDC);
+
+ _vm->_palette->setPalette(_vm->_palette->_mainPalette + (TEXTDIALOG_CONTENT1 * 3),
+ TEXTDIALOG_CONTENT1, 8);
+}
+
+void Dialog::calculateBounds() {
+}
+
+void Dialog::drawContent(const Common::Rect &r, int seed, byte color1, byte color2) {
+ uint16 currSeed = seed ? seed : 0xB78E;
+
+ for (int yp = 0; yp < r.height(); ++yp) {
+ byte *destP = _vm->_screen.getBasePtr(r.left, r.top + yp);
+
+ for (int xp = 0; xp < r.width(); ++xp) {
+ uint16 seedAdjust = currSeed;
+ currSeed += 0x181D;
+ seedAdjust = (seedAdjust >> 9) | ((seedAdjust & 0x1ff) << 7);
+ currSeed ^= seedAdjust;
+ seedAdjust = (seedAdjust >> 3) | ((seedAdjust & 7) << 13);
+ currSeed += seedAdjust;
+
+ *destP++ = (currSeed & 0x10) ? color2 : color1;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+TextDialog::TextDialog(MADSEngine *vm, const Common::String &fontName,
+ const Common::Point &pos, int maxChars)
+ : Dialog(vm) {
+ _vm = vm;
+ _font = _vm->_font->getFont(fontName);
+ _position = pos;
+
+ _vm->_font->setColors(TEXTDIALOG_BLACK, TEXTDIALOG_BLACK, TEXTDIALOG_BLACK, TEXTDIALOG_BLACK);
+
+ _innerWidth = (_font->maxWidth() + 1) * maxChars;
+ _width = _innerWidth + 10;
+ _lineSize = maxChars * 2;
+ _lineWidth = 0;
+ _currentX = 0;
+ _numLines = 0;
+ Common::fill(&_lineXp[0], &_lineXp[TEXT_DIALOG_MAX_LINES], 0);
+ _askLineNum = -1;
+ _askXp = 0;
+}
+
+TextDialog::~TextDialog() {
+}
+
+void TextDialog::addLine(const Common::String &line, bool underline) {
+ if (_lineWidth > 0 || _currentX > 0)
+ incNumLines();
+
+ int stringWidth = _font->getWidth(line, 1);
+ if (stringWidth >= _innerWidth || (int)line.size() >= _lineSize) {
+ wordWrap(line);
+ } else {
+ _lineXp[_numLines] = (_innerWidth / 2) - (stringWidth / 2);
+ _lines[_numLines] = line;
+
+ if (underline)
+ underlineLine();
+ }
+
+ incNumLines();
+}
+
+void TextDialog::underlineLine() {
+ _lineXp[_numLines] |= 0x80;
+}
+
+void TextDialog::downPixelLine() {
+ _lineXp[_numLines] |= 0x40;
+}
+
+void TextDialog::incNumLines() {
+ _lineWidth = 0;
+ _currentX = 0;
+ if (++_numLines == TEXT_DIALOG_MAX_LINES)
+ error("Exceeded text dialog line max");
+}
+
+void TextDialog::wordWrap(const Common::String &line) {
+ Common::String tempLine;
+
+ if (!line.empty()) {
+ const char *srcP = line.c_str();
+
+ do {
+ tempLine = "";
+ bool endWord = false;
+ bool newLine = false;
+ bool continueFlag = true;
+
+ do {
+ if (!*srcP) {
+ continueFlag = false;
+ } else {
+ tempLine += *srcP;
+
+ if (*srcP == 10) {
+ continueFlag = false;
+ newLine = true;
+ ++srcP;
+ tempLine.deleteLastChar();
+ } else if (*srcP == ' ') {
+ ++srcP;
+ endWord = true;
+ } else if (!endWord) {
+ ++srcP;
+ } else {
+ tempLine.deleteLastChar();
+ continueFlag = false;
+ }
+ }
+ } while (continueFlag);
+
+ if (tempLine.hasSuffix(" "))
+ tempLine.deleteLastChar();
+
+ Common::String tempLine2;
+ if (_currentX > 0)
+ tempLine2 += ' ';
+ tempLine2 += tempLine;
+
+ int lineWidth = _font->getWidth(tempLine2, 1);
+ if (((_currentX + (int)tempLine2.size()) > _lineSize) ||
+ ((_lineWidth + lineWidth) > _innerWidth)) {
+ incNumLines();
+ appendLine(tempLine);
+ } else {
+ appendLine(tempLine2);
+ }
+
+ if (newLine)
+ incNumLines();
+ } while (*srcP);
+ }
+}
+
+void TextDialog::appendLine(const Common::String &line) {
+ _currentX += line.size();
+ _lineWidth += _font->getWidth(line, 1) + 1;
+ _lines[_numLines] += line;
+}
+
+void TextDialog::addInput() {
+ _askXp = _currentX + 1;
+ _askLineNum = _numLines;
+ incNumLines();
+}
+
+void TextDialog::addBarLine() {
+ if (_lineWidth > 0 || _currentX > 0)
+ incNumLines();
+
+ _lineXp[_numLines] = 0xFF;
+ incNumLines();
+}
+
+void TextDialog::setLineXp(int xp) {
+ _lineXp[_numLines] = xp;
+}
+
+void TextDialog::draw() {
+ if (!_lineWidth)
+ --_numLines;
+
+ // Figure out the size and position for the dialog
+ calculateBounds();
+
+ // Draw the underlying dialog
+ Dialog::draw();
+
+ // Draw the text lines
+ int lineYp = _position.y + 5;
+ for (int lineNum = 0; lineNum <= _numLines; ++lineNum) {
+ if (_lineXp[lineNum] == -1) {
+ // Draw a line across the entire dialog
+ _vm->_screen.hLine(_position.x + 2,
+ lineYp + (_font->getHeight() + 1) / 2,
+ _position.x + _width - 4, TEXTDIALOG_BLACK);
+ } else {
+ // Draw a text line
+ int xp = (_lineXp[lineNum] & 0x7F) + _position.x + 5;
+ int yp = lineYp;
+ if (_lineXp[lineNum] & 0x40)
+ ++yp;
+
+ _font->writeString(&_vm->_screen, _lines[lineNum],
+ Common::Point(xp, yp), 1);
+
+ if (_lineXp[lineNum] & 0x80) {
+ // Draw an underline under the text
+ int lineWidth = _font->getWidth(_lines[lineNum], 1);
+ _vm->_screen.hLine(xp, yp + _font->getHeight(), xp + lineWidth,
+ TEXTDIALOG_BLACK);
+ }
+ }
+
+ lineYp += _font->getHeight() + 1;
+ }
+
+ _vm->_screen.copyRectToScreen(getBounds());
+}
+
+void TextDialog::calculateBounds() {
+ _height = (_font->getHeight() + 1) * (_numLines + 1) + 10;
+ if (_position.x == -1)
+ _position.x = 160 - (_width / 2);
+ if (_position.y == -1)
+ _position.y = 100 - (_height / 2);
+
+ if ((_position.x + _width) > _vm->_screen.getWidth())
+ _position.x = _vm->_screen.getWidth() - (_position.x + _width);
+ if ((_position.y + _height) > _vm->_screen.getHeight())
+ _position.y = _vm->_screen.getHeight() - (_position.y + _height);
+}
+
+void TextDialog::drawWithInput() {
+ //int innerWidth = _innerWidth;
+ //int lineHeight = _font->getHeight() + 1;
+ //int xp = _position.x + 5;
+
+ // Draw the content of the dialog
+ drawContent(Common::Rect(_position.x + 2, _position.y + 2,
+ _position.x + _width - 2, _position.y + _height - 2), 0,
+ TEXTDIALOG_CONTENT1, TEXTDIALOG_CONTENT2);
+
+ error("TODO: drawWithInput");
+}
+
+void TextDialog::show() {
+ // Draw the dialog
+ draw();
+ _vm->_events->showCursor();
+
+ // Wait for mouse click
+ do {
+ _vm->_events->waitForNextFrame();
+ } while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed() && !_vm->_events->_mouseReleased);
+
+ // Allow the mouse release or keypress to be gobbled up
+ if (!_vm->shouldQuit()) {
+ _vm->_events->waitForNextFrame();
+ _vm->_events->_pendingKeys.clear();
+ }
+
+ // Restore the background
+ restore();
+}
+
+/*------------------------------------------------------------------------*/
+
+MessageDialog::MessageDialog(MADSEngine *vm, int maxChars, ...)
+ : TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), maxChars) {
+ // Add in passed line list
+ va_list va;
+ va_start(va, maxChars);
+
+ const char *line = va_arg(va, const char *);
+ while (line) {
+ addLine(line);
+ line = va_arg(va, const char *);
+ }
+ va_end(va);
+}
+
+/*------------------------------------------------------------------------*/
+
+Dialogs *Dialogs::init(MADSEngine *vm) {
+ if (vm->getGameID() == GType_RexNebular)
+ return new Nebular::DialogsNebular(vm);
+
+ // Throw a warning for now, since the associated Dialogs class isn't implemented yet
+ warning("Dialogs: Unknown game");
+ // HACK: Reuse the implemented Nebular dialogs for now, to avoid crashing later on
+ return new Nebular::DialogsNebular(vm);
+}
+
+Dialogs::Dialogs(MADSEngine *vm)
+ : _vm(vm) {
+ _pendingDialog = DIALOG_NONE;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/dialogs.h b/engines/mads/dialogs.h
new file mode 100644
index 0000000000..c586a6f1fe
--- /dev/null
+++ b/engines/mads/dialogs.h
@@ -0,0 +1,231 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_DIALOGS_H
+#define MADS_DIALOGS_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/font.h"
+#include "mads/msurface.h"
+
+namespace MADS {
+
+class Dialog {
+private:
+ void setDialogPalette();
+protected:
+ MADSEngine *_vm;
+ MSurface *_savedSurface;
+ Common::Point _position;
+ int _width;
+ int _height;
+ byte _dialogPalette[8 * 3];
+
+ int TEXTDIALOG_CONTENT1;
+ int TEXTDIALOG_CONTENT2;
+ int TEXTDIALOG_EDGE;
+ int TEXTDIALOG_BACKGROUND;
+ int TEXTDIALOG_FC;
+ int TEXTDIALOG_FD;
+ int TEXTDIALOG_FE;
+ int TEXTDIALOG_BLACK;
+protected:
+ /**
+ * Draw the dialog
+ */
+ virtual void draw();
+
+ /**
+ * Calculate bounds for the dialog
+ */
+ virtual void calculateBounds();
+
+ /**
+ * Save the section of the passed surface the dialog will cover.
+ */
+ virtual void save();
+
+ /**
+ * Restore saved dialog surface
+ */
+ virtual void restore();
+
+ /**
+ * Draws the content of a dialog with a gravelly alternating color.
+ */
+ void drawContent(const Common::Rect &r, int seed, byte color1, byte color2);
+public:
+ /**
+ * Constructor
+ */
+ Dialog(MADSEngine *vm);
+
+ /**
+ * Destructor
+ */
+ virtual ~Dialog();
+
+ /**
+ * Return the bounds of the dialog.
+ */
+ Common::Rect getBounds() const {
+ return Common::Rect(_position.x, _position.y,
+ _position.x + _width, _position.y + _height);
+ }
+};
+
+#define TEXT_DIALOG_MAX_LINES 20
+
+class TextDialog : protected Dialog {
+private:
+ /**
+ * Append text to the currently end line.
+ */
+ void appendLine(const Common::String &line);
+
+ /**
+ * Clean up after finishing displaying the dialog
+ */
+ void restorePalette();
+protected:
+ Font *_font;
+ int _innerWidth;
+ int _lineWidth;
+ int _currentX;
+ int _numLines;
+ int _lineSize;
+ int _askXp;
+ int _askLineNum;
+ Common::String _lines[TEXT_DIALOG_MAX_LINES];
+ int _lineXp[TEXT_DIALOG_MAX_LINES];
+
+ /**
+ * Calculate the bounds for the dialog
+ */
+ virtual void calculateBounds();
+public:
+ /**
+ * Constructor
+ * @param vm Engine reference
+ * @param fontName Font to use for display
+ * @param pos Position for window top-left
+ * @param maxChars Horizontal width of window in characters
+ */
+ TextDialog(MADSEngine *vm, const Common::String &fontName, const Common::Point &pos,
+ int maxChars);
+
+ /**
+ * Destructor
+ */
+ virtual ~TextDialog();
+
+ /**
+ * Draw the dialog
+ */
+ virtual void draw();
+
+ /**
+ * Draw the dialog along with any input box
+ */
+ void drawWithInput();
+
+ /**
+ * Add a new line to the dialog
+ */
+ void addLine(const Common::String &line, bool underline = false);
+
+ /**
+ * Adds one or more lines, word wrapping the passed text
+ */
+ void wordWrap(const Common::String &line);
+
+ /**
+ * Increments the number of text lines the text dialog uses
+ */
+ void incNumLines();
+
+ /**
+ * Adds an input area following previously added text
+ */
+ void addInput();
+
+ /**
+ * Adds a bar line to separate sections of text
+ */
+ void addBarLine();
+
+ /**
+ * Flags the previously added line to be underlined
+ */
+ void underlineLine();
+
+ void downPixelLine();
+
+ /**
+ * Set the x position for the given line
+ */
+ void setLineXp(int xp);
+
+ /**
+ * Show the dialog, and wait until a key or mouse press.
+ */
+ virtual void show();
+};
+
+class MessageDialog : public TextDialog {
+public:
+ MessageDialog(MADSEngine *vm, int lines, ...);
+
+ virtual ~MessageDialog() {}
+};
+
+enum DialogId {
+ DIALOG_NONE = 0, DIALOG_GAME_MENU = 1, DIALOG_SAVE = 2, DIALOG_RESTORE = 3,
+ DIALOG_OPTIONS = 4, DIALOG_DIFFICULTY = 5, DIALOG_ERROR = 6,
+ DIALOG_MAIN_MENU = 7, DIALOG_TEXTVIEW = 8, DIALOG_ANIMVIEW = 9,
+ DIALOG_ADVERT = 10
+};
+
+class Dialogs {
+protected:
+ MADSEngine *_vm;
+
+ Dialogs(MADSEngine *vm);
+public:
+ static Dialogs *init(MADSEngine *vm);
+public:
+ Common::Point _defaultPosition;
+ DialogId _pendingDialog;
+ int _indexList[10];
+
+ virtual ~Dialogs() {}
+
+ virtual void showDialog() = 0;
+ virtual void showItem(int objectId, int messageId, int speech = 0) = 0;
+ virtual Common::String getVocab(int vocabId) = 0;
+ virtual bool show(int messageId, int objectId = -1) = 0;
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_DIALOGS_H */
diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.cpp b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
new file mode 100644
index 0000000000..f32d17d9c9
--- /dev/null
+++ b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
@@ -0,0 +1,235 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "mads/mads.h"
+#include "mads/compression.h"
+#include "mads/resources.h"
+#include "mads/scene.h"
+#include "mads/dragonsphere/game_dragonsphere.h"
+#include "mads/dragonsphere/dragonsphere_scenes.h"
+
+namespace MADS {
+
+namespace Dragonsphere {
+
+SceneLogic *SceneFactory::createScene(MADSEngine *vm) {
+ Scene &scene = vm->_game->_scene;
+
+ // TODO
+ //scene.addActiveVocab(NOUN_DROP);
+
+ switch (scene._nextSceneId) {
+ // Scene group #1 (Castle, river and caves)
+ case 101: // king's bedroom
+ return new DummyScene(vm); // TODO
+ case 102: // queen's bedroom
+ return new DummyScene(vm); // TODO
+ case 103: // outside king's bedroom
+ return new DummyScene(vm); // TODO
+ case 104: // fireplace / bookshelf
+ return new DummyScene(vm); // TODO
+ case 105: // dining room
+ return new DummyScene(vm); // TODO
+ case 106: // throne room
+ return new DummyScene(vm); // TODO
+ case 107: // council chamber
+ return new DummyScene(vm); // TODO
+ case 108: // dungeon, cell entrance
+ return new DummyScene(vm); // TODO
+ case 109: // cell
+ return new DummyScene(vm); // TODO
+ case 110: // outside castle, merchants and well
+ return new DummyScene(vm); // TODO
+ case 111: // Dragonsphere closeup
+ return new DummyScene(vm); // TODO
+ case 112: // well descend
+ return new DummyScene(vm); // TODO
+ case 113: // bottom of well, river and trap door
+ return new DummyScene(vm); // TODO
+ case 114: // cave
+ return new DummyScene(vm); // TODO
+ case 115: // cave with passageway to west
+ return new DummyScene(vm); // TODO
+ case 116: // cave with pedestral
+ return new DummyScene(vm); // TODO
+ case 117: // river
+ return new DummyScene(vm); // TODO
+ case 118: // castle courtyard and gate
+ return new DummyScene(vm); // TODO
+ case 119: // castle stairs
+ return new DummyScene(vm); // TODO
+ case 120: // map
+ return new DummyScene(vm); // TODO
+
+ // Scene group #2 (Slathan ni Patan, land of shapeshifters)
+ case 201: // guardhouse, entrance to Slathan ni Patan
+ return new DummyScene(vm); // TODO
+ case 203: // forest
+ return new DummyScene(vm); // TODO
+ case 204: // cave
+ return new DummyScene(vm); // TODO
+ case 205: // outside village
+ return new DummyScene(vm); // TODO
+ case 206: // village
+ return new DummyScene(vm); // TODO
+
+ // Scene group #3 (Brynn-Fann, Land of faeries)
+ case 301: // maze entrance
+ return new DummyScene(vm); // TODO
+ case 302: // maze
+ return new DummyScene(vm); // TODO
+ case 303: // toads
+ return new DummyScene(vm); // TODO
+
+ // Scene group #4 (The Desert)
+ case 401: // desert
+ return new DummyScene(vm); // TODO
+ case 402: // desert
+ return new DummyScene(vm); // TODO
+ case 403: // desert
+ return new DummyScene(vm); // TODO
+ case 404: // desert with dunes
+ return new DummyScene(vm); // TODO
+ case 405: // oasis
+ return new DummyScene(vm); // TODO
+ case 406: // inside tent
+ return new DummyScene(vm); // TODO
+ case 407: // gem sack closeup
+ return new DummyScene(vm); // TODO
+ case 408: // spirit plane
+ return new DummyScene(vm); // TODO
+ case 409: // spirit plane top down view, disks
+ return new DummyScene(vm); // TODO
+ case 410: // snake pit and spirit tree
+ return new DummyScene(vm); // TODO
+ case 411: // nest
+ return new DummyScene(vm); // TODO
+ case 412: // desert
+ return new DummyScene(vm); // TODO
+ case 454: // cutscene
+ return new DummyScene(vm); // TODO
+
+ // Scene group #5 (The Mountain)
+ case 501: // base of mountain / wall
+ return new DummyScene(vm); // TODO
+ case 502: // base of mountain
+ return new DummyScene(vm); // TODO
+ case 503: // waterfall
+ return new DummyScene(vm); // TODO
+ case 504: // hermit's cave
+ return new DummyScene(vm); // TODO
+ case 505: // rock trees
+ return new DummyScene(vm); // TODO
+ case 506: // nest
+ return new DummyScene(vm); // TODO
+ case 507: // above nest
+ return new DummyScene(vm); // TODO
+ case 508: // ledge, right
+ return new DummyScene(vm); // TODO
+ case 509: // ledge, left
+ return new DummyScene(vm); // TODO
+ case 510: // nest top down view and pillars
+ return new DummyScene(vm); // TODO
+ case 511: // pillars
+ return new DummyScene(vm); // TODO
+ case 512: // nest
+ return new DummyScene(vm); // TODO
+ case 557: // cutscene
+ return new DummyScene(vm); // TODO
+
+ // Scene group #6 (The Tower)
+ case 601: // ??? (tile count mismatch)
+ return new DummyScene(vm); // TODO
+ case 603: // eye chamber
+ return new DummyScene(vm); // TODO
+ case 604: // room of magic
+ return new DummyScene(vm); // TODO
+ case 605: // science room
+ return new DummyScene(vm); // TODO
+ case 606: // doorway
+ return new DummyScene(vm); // TODO
+ case 607: // prison
+ return new DummyScene(vm); // TODO
+ case 609: // stone pedestral chamber
+ return new DummyScene(vm); // TODO
+ case 612: // infernal machine room
+ return new DummyScene(vm); // TODO
+ case 613: // room with lava floor
+ return new DummyScene(vm); // TODO
+ case 614: // sorcerer's room
+ return new DummyScene(vm); // TODO
+
+ default:
+ error("Invalid scene %d called", scene._nextSceneId);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+DragonsphereScene::DragonsphereScene(MADSEngine *vm) : SceneLogic(vm),
+ _globals(static_cast<GameDragonsphere *>(vm->_game)->_globals),
+ _game(*static_cast<GameDragonsphere *>(vm->_game)),
+ _action(vm->_game->_scene._action) {
+}
+
+Common::String DragonsphereScene::formAnimName(char sepChar, int suffixNum) {
+ return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum,
+ EXT_NONE, "");
+}
+
+/*------------------------------------------------------------------------*/
+
+void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, int variant) {
+ Common::String ext = Common::String::format(".WW%d", variant);
+ File f(Resources::formatName(RESPREFIX_RM, _sceneId, ext));
+ MadsPack codesPack(&f);
+ Common::SeekableReadStream *stream = codesPack.getItemStream(0);
+
+ loadCodes(depthSurface, stream);
+
+ delete stream;
+ f.close();
+}
+
+void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
+ byte *destP = depthSurface.getData();
+ byte *walkMap = new byte[stream->size()];
+ stream->read(walkMap, stream->size());
+
+ for (int y = 0; y < 156; ++y) {
+ for (int x = 0; x < 320; ++x) {
+ int offset = x + (y * 320);
+ if ((walkMap[offset / 8] << (offset % 8)) & 0x80)
+ *destP++ = 1; // walkable
+ else
+ *destP++ = 0;
+ }
+ }
+
+ delete[] walkMap;
+}
+
+} // End of namespace Dragonsphere
+
+} // End of namespace MADS
diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.h b/engines/mads/dragonsphere/dragonsphere_scenes.h
new file mode 100644
index 0000000000..a6c778eca7
--- /dev/null
+++ b/engines/mads/dragonsphere/dragonsphere_scenes.h
@@ -0,0 +1,695 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_DRAGONSPHERE_SCENES_H
+#define MADS_DRAGONSPHERE_SCENES_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/dragonsphere/game_dragonsphere.h"
+//#include "mads/dragonsphere/globals_dragonsphere.h"
+
+
+namespace MADS {
+
+namespace Dragonsphere {
+
+enum Noun {
+ NOUN_GAME = 0x1,
+ NOUN_QSAVE = 0x2,
+ NOUN_LOOK = 0x3,
+ NOUN_TAKE = 0x4,
+ NOUN_PUSH = 0x5,
+ NOUN_OPEN = 0x6,
+ NOUN_PUT = 0x7,
+ NOUN_TALK_TO = 0x8,
+ NOUN_GIVE = 0x9,
+ NOUN_PULL = 0xA,
+ NOUN_CLOSE = 0xB,
+ NOUN_THROW = 0xC,
+ NOUN_WALK_TO = 0xD,
+ NOUN_NOTHING = 0xE,
+ NOUN_ = 0xF,
+ NOUN_FLOOR = 0x10,
+ NOUN_WALK_ACROSS = 0x11,
+ NOUN_RUG = 0x12,
+ NOUN_CARPET = 0x13,
+ NOUN_WALL = 0x14,
+ NOUN_BED = 0x15,
+ NOUN_PILLOW = 0x16,
+ NOUN_CHEST = 0x17,
+ NOUN_WINDOW = 0x18,
+ NOUN_NIGHTSTAND = 0x19,
+ NOUN_TAPESTRY = 0x1A,
+ NOUN_DRESSING_SCREEN = 0x1B,
+ NOUN_WALK_BEHIND = 0x1C,
+ NOUN_ROYAL_CREST = 0x1D,
+ NOUN_LOOK_AT = 0x1E,
+ NOUN_WASHBASIN = 0x1F,
+ NOUN_WASH_AT = 0x20,
+ NOUN_BOOK = 0x21,
+ NOUN_FIREPLACE = 0x22,
+ NOUN_FIREPLACE_SCREEN = 0x23,
+ NOUN_DOOR_TO_QUEENS_ROOM = 0x24,
+ NOUN_WALK_THROUGH = 0x25,
+ NOUN_HALL_TO_SOUTH = 0x26,
+ NOUN_WALK_INTO = 0x27,
+ NOUN_WALL_PLAQUE = 0x28,
+ NOUN_DECORATION = 0x29,
+ NOUN_SWORDS = 0x2A,
+ NOUN_WALL_SCONCE = 0x2B,
+ NOUN_BUST_ON_WALL = 0x2C,
+ NOUN_WALL_ARCH = 0x2D,
+ NOUN_SIGNET_RING = 0x2E,
+ NOUN_INVOKE = 0x2F,
+ NOUN_POLISH = 0x30,
+ NOUN_GANGBANG = 0x31,
+ NOUN_BIRD_FIGURINE = 0x32,
+ NOUN_RUB = 0x33,
+ NOUN_BIRDCALL = 0x34,
+ NOUN_USE = 0x35,
+ NOUN_MAKE_NOISE = 0x36,
+ NOUN_SHIELDSTONE = 0x37,
+ NOUN_SWORD = 0x38,
+ NOUN_ATTACK = 0x39,
+ NOUN_CARVE_UP = 0x3A,
+ NOUN_GOBLET = 0x3B,
+ NOUN_FILL = 0x3C,
+ NOUN_DRINK_FROM = 0x3D,
+ NOUN_BONE = 0x3E,
+ NOUN_GNAW = 0x3F,
+ NOUN_FRUIT = 0x40,
+ NOUN_EAT = 0x41,
+ NOUN_DOLL = 0x42,
+ NOUN_PLAY_WITH = 0x43,
+ NOUN_HEAL = 0x44,
+ NOUN_HEAL_THYSELF = 0x45,
+ NOUN_HEAL_SELF = 0x46,
+ NOUN_POLYSTONE = 0x47,
+ NOUN_MIMIC = 0x48,
+ NOUN_RED_POWERSTONE = 0x49,
+ NOUN_YELLOW_POWERSTONE = 0x4A,
+ NOUN_BLUE_POWERSTONE = 0x4B,
+ NOUN_KEY_CROWN = 0x4C,
+ NOUN_WEAR = 0x4D,
+ NOUN_DATES = 0x4E,
+ NOUN_STATUE = 0x4F,
+ NOUN_BOTTLE_OF_FLIES = 0x50,
+ NOUN_LISTEN_TO = 0x51,
+ NOUN_SOUL_EGG = 0x52,
+ NOUN_BREAK = 0x53,
+ NOUN_MAGIC_BELT = 0x54,
+ NOUN_ADJUST = 0x55,
+ NOUN_AMULET = 0x56,
+ NOUN_THRUST = 0x57,
+ NOUN_MUD = 0x58,
+ NOUN_FEEL = 0x59,
+ NOUN_TASTE = 0x5A,
+ NOUN_FEATHERS = 0x5B,
+ NOUN_TICKLE = 0x5C,
+ NOUN_TORCH = 0x5D,
+ NOUN_WAVE = 0x5E,
+ NOUN_FLASK = 0x5F,
+ NOUN_FLASK_FULL_OF_ACID = 0x60,
+ NOUN_POUR_CONTENTS = 0x61,
+ NOUN_POUR = 0x62,
+ NOUN_POUR_CONTENTS_OF = 0x63,
+ NOUN_DRINK = 0x64,
+ NOUN_ROPE = 0x65,
+ NOUN_TIE = 0x66,
+ NOUN_POWER_VACUUM_STONE = 0x67,
+ NOUN_TAKE_MAGIC_FROM = 0x68,
+ NOUN_DEAD_RAT = 0x69,
+ NOUN_PET = 0x6A,
+ NOUN_MAP = 0x6B,
+ NOUN_FOLD = 0x6C,
+ NOUN_CRYSTAL_BALL = 0x6D,
+ NOUN_GAZE_INTO = 0x6E,
+ NOUN_INVOKE_POWER_OF = 0x6F,
+ NOUN_BLACK_SPHERE = 0x70,
+ NOUN_SOPTUS_SOPORIFIC = 0x71,
+ NOUN_SHIFTER_RING = 0x72,
+ NOUN_SHIFT_SELF = 0x73,
+ NOUN_SHIFT_INTO_BEAR = 0x74,
+ NOUN_SHIFT_INTO_SEAL = 0x75,
+ NOUN_SHIFT_INTO_SNAKE = 0x76,
+ NOUN_REVERT = 0x77,
+ NOUN_MEDICINE_BUNDLE = 0x78,
+ NOUN_SHAKE = 0x79,
+ NOUN_PARTLY_BUILT_BUNDLE = 0x7A,
+ NOUN_RATSICLE = 0x7B,
+ NOUN_LICK = 0x7C,
+ NOUN_TENTACLE_PARTS = 0x7D,
+ NOUN_CHEW = 0x7E,
+ NOUN_TELEPORT_DOOR = 0x7F,
+ NOUN_UNROLL = 0x80,
+ NOUN_RARE_COIN = 0x81,
+ NOUN_ADMIRE = 0x82,
+ NOUN_CRYSTAL_FLOWER = 0x83,
+ NOUN_DIAMOND_DUST = 0x84,
+ NOUN_RUBY_RING = 0x85,
+ NOUN_GOLD_NUGGET = 0x86,
+ NOUN_MAGIC_MUSIC_BOX = 0x87,
+ NOUN_EMERALD = 0x88,
+ NOUN_PIECE_OF_PAPER = 0x89,
+ NOUN_SPEAK_WORDS_ON = 0x8A,
+ NOUN_VORTEX_STONE = 0x8B,
+ NOUN_RUG2 = 0x8C,
+ NOUN_FIREPLACE_SCREEN2 = 0x8D,
+ NOUN_BUST_ON_WALL2 = 0x8E,
+ NOUN_LOOK_AT2 = 0x8F,
+ NOUN_DRAGON = 0x90,
+ NOUN_DRAGONSPHERE = 0x91,
+ NOUN_TOUCH = 0x92,
+ NOUN_THRONE_ROOM = 0x93,
+ NOUN_RETURN_TO = 0x94,
+ NOUN_CAVE = 0x95,
+ NOUN_PASSAGEWAY_TO_WEST = 0x96,
+ NOUN_PASSAGEWAY_TO_EAST = 0x97,
+ NOUN_CAVE_FLOOR = 0x98,
+ NOUN_STONE_COLUMN = 0x99,
+ NOUN_ABYSS = 0x9A,
+ NOUN_LOOK_INTO = 0x9B,
+ NOUN_CASTLE = 0x9C,
+ NOUN_CASTLE_GATE = 0x9D,
+ NOUN_GROUND = 0x9E,
+ NOUN_BARREL = 0x9F,
+ NOUN_BARRELS = 0xA0,
+ NOUN_HAYSTACK = 0xA1,
+ NOUN_ROOT_THROUGH = 0xA2,
+ NOUN_BATTLEMENTS = 0xA3,
+ NOUN_GATE_TO_THRONE_ROOM = 0xA4,
+ NOUN_CASTLE_WALL = 0xA5,
+ NOUN_DOOR = 0xA6,
+ NOUN_WALL_SWITCH = 0xA7,
+ NOUN_STAIRS = 0xA8,
+ NOUN_WALK_DOWN = 0xA9,
+ NOUN_EDGE_OF_ABYSS = 0xAA,
+ NOUN_COURTYARD = 0xAB,
+ NOUN_ROCK = 0xAC,
+ NOUN_CAVE_CEILING = 0xAD,
+ NOUN_CAVE_WALL = 0xAE,
+ NOUN_BRAZIER = 0xAF,
+ NOUN_DOOR_TO_THRONE_ROOM = 0xB0,
+ NOUN_GO_THROUGH = 0xB1,
+ NOUN_DINING_TABLE = 0xB2,
+ NOUN_ACTIVATE = 0xB3,
+ NOUN_BATTLEMENT = 0xB4,
+ NOUN_DOOR_TO_GAURDROOM = 0xB5,
+ NOUN_DUNGEON_FLOOR = 0xB6,
+ NOUN_DUNGEON_WALLS = 0xB7,
+ NOUN_DUNGEON_CEILING = 0xB8,
+ NOUN_BEDDING = 0xB9,
+ NOUN_FLOOR_GRATE = 0xBA,
+ NOUN_MANACLES = 0xBB,
+ NOUN_CALENDAR = 0xBC,
+ NOUN_DOOR_TO_GUARDROOM = 0xBD,
+ NOUN_DOOR_TO_COUNCIL_ROOM = 0xBE,
+ NOUN_GUARD_STATION = 0xBF,
+ NOUN_DOOR_TO_DUNGEON_CELL = 0xC0,
+ NOUN_DOORWAY_TO_CELL = 0xC1,
+ NOUN_DUNGEON_DOOR = 0xC2,
+ NOUN_DUNGEON_WALL = 0xC3,
+ NOUN_CEILING = 0xC4,
+ NOUN_DOOR_TO_HALLWAY = 0xC5,
+ NOUN_TABLE = 0xC6,
+ NOUN_BOOKSHELF = 0xC7,
+ NOUN_TROPHY = 0xC8,
+ NOUN_READING_BENCH = 0xC9,
+ NOUN_CHAIR = 0xCA,
+ NOUN_LOVESEAT = 0xCB,
+ NOUN_WOOD_BASKET = 0xCC,
+ NOUN_STOOL = 0xCD,
+ NOUN_GUARD_STOOL = 0xCE,
+ NOUN_ROCKS = 0xCF,
+ NOUN_DIVIDING_WALL = 0xD0,
+ NOUN_ARCHWAY = 0xD1,
+ NOUN_MARKET_GROUNDS = 0xD2,
+ NOUN_HEDGE = 0xD3,
+ NOUN_SKY = 0xD4,
+ NOUN_PLAINS = 0xD5,
+ NOUN_FIELDS = 0xD6,
+ NOUN_GATE_TO_COURTYARD = 0xD7,
+ NOUN_ROAD_TO_EAST = 0xD8,
+ NOUN_TREES = 0xD9,
+ NOUN_CLOUDS = 0xDA,
+ NOUN_MERCHANTS_STALL = 0xDB,
+ NOUN_WELL = 0xDC,
+ NOUN_DOWN_WELL = 0xDD,
+ NOUN_GO = 0xDE,
+ NOUN_GO_DOWN = 0xDF,
+ NOUN_CRANK = 0xE0,
+ NOUN_BUCKET = 0xE1,
+ NOUN_JUMP_DOWN = 0xE2,
+ NOUN_WALLS = 0xE3,
+ NOUN_DOORWAY_TO_SOUTH = 0xE4,
+ NOUN_PEDESTAL = 0xE5,
+ NOUN_DOOR_TO_NORTH = 0xE6,
+ NOUN_PAINTING = 0xE7,
+ NOUN_DOCUMENT = 0xE8,
+ NOUN_INK_BOTTLE = 0xE9,
+ NOUN_QUILL_PEN = 0xEA,
+ NOUN_CHANDELIER = 0xEB,
+ NOUN_COUNCIL_TABLE = 0xEC,
+ NOUN_CANDLESTICK = 0xED,
+ NOUN_DESK = 0xEE,
+ NOUN_TURN = 0xEF,
+ NOUN_POLE = 0xF0,
+ NOUN_THE_SCENE = 0xF1,
+ NOUN_LEAVE = 0xF2,
+ NOUN_END_TABLE = 0xF3,
+ NOUN_BATTLE_AXES = 0xF4,
+ NOUN_DOOR_TO_KINGS_ROOM = 0xF5,
+ NOUN_COAT_OF_ARMS = 0xF6,
+ NOUN_LARGE_WINDOW = 0xF7,
+ NOUN_SMALL_WINDOW = 0xF8,
+ NOUN_DOOR_TO_MEETING_ROOM = 0xF9,
+ NOUN_DOOR_TO_BALLROOM = 0xFA,
+ NOUN_FLOWERS = 0xFB,
+ NOUN_SHUTTERS = 0xFC,
+ NOUN_BOOKCASE = 0xFD,
+ NOUN_DOOR_TO_COURTYARD = 0xFE,
+ NOUN_PLATFORM = 0xFF,
+ NOUN_STEP = 0x100,
+ NOUN_RED_CARPET = 0x101,
+ NOUN_KINGS_THRONE = 0x102,
+ NOUN_SIT_IN = 0x103,
+ NOUN_QUEENS_THRONE = 0x104,
+ NOUN_TRAPDOOR = 0x105,
+ NOUN_GRATE = 0x106,
+ NOUN_RIVER = 0x107,
+ NOUN_DIARIES = 0x108,
+ NOUN_SWIM_DOWN = 0x109,
+ NOUN_SCULLERY_MAID = 0x10A,
+ NOUN_DOORWAY_TO_DUNGEON = 0x10B,
+ NOUN_WARD = 0x10C,
+ NOUN_DARKNESS_BEAST = 0x10D,
+ NOUN_BEAST = 0x10E,
+ NOUN_PUT_MAGIC_INTO = 0x10F,
+ NOUN_GUARD = 0x110,
+ NOUN_CROWN = 0x111,
+ NOUN_BOOKS = 0x112,
+ NOUN_SECRET_DOOR = 0x113,
+ NOUN_WALL_PANEL = 0x114,
+ NOUN_DOORWAY = 0x115,
+ NOUN_FAERIE = 0x116,
+ NOUN_SOPTUS_ECLIPTUS = 0x117,
+ NOUN_GUARD_CAPTAIN = 0x118,
+ NOUN_MERCHANT = 0x119,
+ NOUN_SHAPECHANGER = 0x11A,
+ NOUN_RED_STONE = 0x11B,
+ NOUN_YELLOW_STONE = 0x11C,
+ NOUN_BLUE_STONE = 0x11D,
+ NOUN_FLIES = 0x11E,
+ NOUN_FLASK_OF_ACID = 0x11F,
+ NOUN_PARTIAL_BUNDLE = 0x120,
+ NOUN_SOPORIFIC = 0x121,
+ NOUN_PARCHMENT = 0x122,
+ NOUN_KING = 0x123,
+ NOUN_MACMORN = 0x124,
+ NOUN_MOUNTAINSIDE = 0x125,
+ NOUN_PATH_TO_SOUTH = 0x126,
+ NOUN_ROUGH_STONE = 0x127,
+ NOUN_CLIMB_UP = 0x128,
+ NOUN_LARGE_ROCK = 0x129,
+ NOUN_SMALL_ROCK = 0x12A,
+ NOUN_PATH_TO_WEST = 0x12B,
+ NOUN_CAVE_ENTRANCE = 0x12C,
+ NOUN_PALLET = 0x12D,
+ NOUN_BLANKET = 0x12E,
+ NOUN_FIREPIT = 0x12F,
+ NOUN_FLAT_STONE = 0x130,
+ NOUN_MOVE = 0x131,
+ NOUN_SPIRIT_BUNDLE = 0x132,
+ NOUN_TRAIL_LEADING_UP = 0x133,
+ NOUN_FOLLOW = 0x134,
+ NOUN_TRAIL_LEADING_DOWN = 0x135,
+ NOUN_NEST = 0x136,
+ NOUN_REACH_IN = 0x137,
+ NOUN_TRAIL_LEADING_WEST = 0x138,
+ NOUN_PATH_TO_EAST = 0x139,
+ NOUN_WATERFALL = 0x13A,
+ NOUN_PUDDLE = 0x13B,
+ NOUN_EDGE_OF_CLIFF = 0x13C,
+ NOUN_LEDGE = 0x13D,
+ NOUN_CLIMB_DOWN = 0x13E,
+ NOUN_LANDING = 0x13F,
+ NOUN_BOULDERS = 0x140,
+ NOUN_ROCK_TUMBLE = 0x141,
+ NOUN_ROCK_TREE = 0x142,
+ NOUN_PILLAR = 0x143,
+ NOUN_JUMP_TO = 0x144,
+ NOUN_CLIFF = 0x145,
+ NOUN_PILLARS = 0x146,
+ NOUN_SPECIAL_ROCK = 0x147,
+ NOUN_GAZE_UPON = 0x148,
+ NOUN_SCONCE = 0x149,
+ NOUN_LADDER = 0x14A,
+ NOUN_STAIRWAY = 0x14B,
+ NOUN_MECHANISM = 0x14C,
+ NOUN_SPEARHEADS = 0x14D,
+ NOUN_TRAP_DOOR = 0x14E,
+ NOUN_SWIM = 0x14F,
+ NOUN_DOWN_RIVER = 0x150,
+ NOUN_SWIM_UP = 0x151,
+ NOUN_UP_RIVER = 0x152,
+ NOUN_SHORE = 0x153,
+ NOUN_SWIM_TO = 0x154,
+ NOUN_SWIM_TOWARDS = 0x155,
+ NOUN_KING_CALLASH = 0x156,
+ NOUN_KINGS_THRONE2 = 0x157,
+ NOUN_KING2 = 0x158,
+ NOUN_GROTTO = 0x159,
+ NOUN_CLIMB_THROUGH = 0x15A,
+ NOUN_QUEEN_MOTHER = 0x15B,
+ NOUN_MACMORN2 = 0x15C,
+ NOUN_SMALL_LEDGE = 0x15D,
+ NOUN_MACMORN3 = 0x15E,
+ NOUN_TO_110 = 0x15F,
+ NOUN_TO_KITTY_HEAVEN = 0x160,
+ NOUN_KITTY_HEAVEN = 0x161,
+ NOUN_ROOM_110 = 0x162,
+ NOUN_LLANIE = 0x163,
+ NOUN_CW = 0x164,
+ NOUN_HERMIT = 0x165,
+ NOUN_TROU = 0x166,
+ NOUN_SHAK = 0x167,
+ NOUN_ROOM_501 = 0x168,
+ NOUN_MOON = 0x169,
+ NOUN_UFO = 0x16A,
+ NOUN_SIT_ON = 0x16B,
+ NOUN_STRANGER = 0x16C,
+ NOUN_TOWER_DOOR = 0x16D,
+ NOUN_DOOR_TO_EAST = 0x16E,
+ NOUN_DOOR_TO_WEST = 0x16F,
+ NOUN_EYE = 0x170,
+ NOUN_DOORWAY_TO_EAST = 0x171,
+ NOUN_DOORWAY_TO_WEST = 0x172,
+ NOUN_SKULL = 0x173,
+ NOUN_DOOR_TO_MAGIC_ROOM = 0x174,
+ NOUN_ANCIENT_BARREL = 0x175,
+ NOUN_COBWEBS = 0x176,
+ NOUN_SHELF = 0x177,
+ NOUN_MUSTY_CHART = 0x178,
+ NOUN_LAB_TABLE = 0x179,
+ NOUN_PETCOCK = 0x17A,
+ NOUN_NOZZLE = 0x17B,
+ NOUN_TUBING = 0x17C,
+ NOUN_BEAKER = 0x17D,
+ NOUN_FLAME = 0x17E,
+ NOUN_METAL_PLATE = 0x17F,
+ NOUN_SHAFT_OF_LIGHT = 0x180,
+ NOUN_CABINET = 0x181,
+ NOUN_BALANCE = 0x182,
+ NOUN_CAGE = 0x183,
+ NOUN_FREEZER = 0x184,
+ NOUN_CONTENTS_OF_FREEZER = 0x185,
+ NOUN_CAGE_WITH_RATS = 0x186,
+ NOUN_DOOR_TO_SOUTH = 0x187,
+ NOUN_TRAIL_OF_GREEN_SLIME = 0x188,
+ NOUN_NECK_LOCK = 0x189,
+ NOUN_BENCH = 0x18A,
+ NOUN_SKELETON = 0x18B,
+ NOUN_LEG_CLAMPS = 0x18C,
+ NOUN_LEG_LOCK = 0x18D,
+ NOUN_WAIST_LOCK = 0x18E,
+ NOUN_NER_TOM = 0x18F,
+ NOUN_BELT = 0x190,
+ NOUN_JUMP_INTO = 0x191,
+ NOUN_CLOSET = 0x192,
+ NOUN_DOOR_TO_EYE_CHAMBER = 0x193,
+ NOUN_DRESSER = 0x194,
+ NOUN_SCROLL = 0x195,
+ NOUN_WITCH_PARAPHERNALIA = 0x196,
+ NOUN_SHELVES = 0x197,
+ NOUN_MAGIC_TOMES = 0x198,
+ NOUN_MAGIC_PARAPHERNALIA = 0x199,
+ NOUN_BOOK_OF_MAGIC = 0x19A,
+ NOUN_HOURGLASS = 0x19B,
+ NOUN_STONE_SPHERE = 0x19C,
+ NOUN_SHADOW_OF_WINDOW = 0x19D,
+ NOUN_MUSIC_BOX = 0x19E,
+ NOUN_LARGE_SPIDER_WEB = 0x19F,
+ NOUN_INFERNAL_MACHINE = 0x1A0,
+ NOUN_WATER_SOURCE = 0x1A1,
+ NOUN_FLOW_OF_WATER = 0x1A2,
+ NOUN_RETORT = 0x1A3,
+ NOUN_DOORWAY_TO_CORRIDOR = 0x1A4,
+ NOUN_TELESCOPE = 0x1A5,
+ NOUN_STRANGE_MAP = 0x1A6,
+ NOUN_CIRCLE_OF_SPHERES = 0x1A7,
+ NOUN_STONE_BED = 0x1A8,
+ NOUN_DRAGON_SCULPTURE = 0x1A9,
+ NOUN_RAT = 0x1AA,
+ NOUN_RAT_CAGE = 0x1AB,
+ NOUN_DOWN_BUTTON = 0x1AC,
+ NOUN_DOOR_TO_MACHINE_ROOM = 0x1AD,
+ NOUN_STRANGE_PORTAL = 0x1AE,
+ NOUN_DOOR_FRAME = 0x1AF,
+ NOUN_ELEVATOR_HOLE = 0x1B0,
+ NOUN_UP_BUTTON = 0x1B1,
+ NOUN_DOORWAY_TO_DARK_ROOM = 0x1B2,
+ NOUN_BIG_SKULL = 0x1B3,
+ NOUN_ELEVATOR_PLATFORM = 0x1B4,
+ NOUN_BUTTON = 0x1B5,
+ NOUN_TOP_BUTTON = 0x1B6,
+ NOUN_BOTTOM_BUTTON = 0x1B7,
+ NOUN_TELEPORTAL = 0x1B8,
+ NOUN_EYE_CHAMBER_DOORWAY = 0x1B9,
+ NOUN_MACHINE_ROOM_DOORWAY = 0x1BA,
+ NOUN_GLOWING_FLOOR = 0x1BB,
+ NOUN_BRYNN_FANN = 0x1BC,
+ NOUN_GRAN_CALLAHACH = 0x1BD,
+ NOUN_SLATHAN_NI_PATAN = 0x1BE,
+ NOUN_HIGHTOWER = 0x1BF,
+ NOUN_SOPTUS_ECLIPTUS2 = 0x1C0,
+ NOUN_TOWER = 0x1C1,
+ NOUN_MOUNTAIN_PATH = 0x1C2,
+ NOUN_PATH_BEHIND_TOWER = 0x1C3,
+ NOUN_VINES = 0x1C4,
+ NOUN_SLATHAN_NI_PATAN2 = 0x1C5,
+ NOUN_SICK = 0x1C6,
+ NOUN_PATH_AROUND_TOWER = 0x1C7,
+ NOUN_PATH_TO_HIGHTOWER = 0x1C8,
+ NOUN_SPIRIT_PLANE = 0x1C9,
+ NOUN_SPIRIT_TREE = 0x1CA,
+ NOUN_WALK = 0x1CB,
+ NOUN_REMAINS = 0x1CC,
+ NOUN_DOORWAY_TO_ELEVATOR = 0x1CD,
+ NOUN_DRAGON_DOOR = 0x1CE,
+ NOUN_DRAGON_BONES = 0x1CF,
+ NOUN_IRON_FLOOR = 0x1D0,
+ NOUN_HOLE = 0x1D1,
+ NOUN_STONE = 0x1D2,
+ NOUN_HOMEMADE_BUNDLE = 0x1D3,
+ NOUN_LEFT = 0x1D4,
+ NOUN_RIGHT = 0x1D5,
+ NOUN_UP = 0x1D6,
+ NOUN_DOWN = 0x1D7,
+ NOUN_WEST = 0x1D8,
+ NOUN_DESERT_TO_WEST = 0x1D9,
+ NOUN_CROSS = 0x1DA,
+ NOUN_DESERT_TO_EAST = 0x1DB,
+ NOUN_DESERT_TO_SOUTH = 0x1DC,
+ NOUN_DESERT_TO_NORTH = 0x1DD,
+ NOUN_DESERT = 0x1DE,
+ NOUN_POWERSTONE = 0x1DF,
+ NOUN_BONES = 0x1E0,
+ NOUN_TENT = 0x1E1,
+ NOUN_BUSH = 0x1E2,
+ NOUN_SANWE = 0x1E3,
+ NOUN_TANGLE = 0x1E4,
+ NOUN_SAND = 0x1E5,
+ NOUN_MAGIC_GRAPES = 0x1E6,
+ NOUN_ROCS_NEST = 0x1E7,
+ NOUN_GRAPE_VINE = 0x1E8,
+ NOUN_STRANGE_SQUARE = 0x1E9,
+ NOUN_WATER_SPHERE = 0x1EA,
+ NOUN_EAST_END_OF_ISLAND = 0x1EB,
+ NOUN_ISLAND = 0x1EC,
+ NOUN_SECRET_MESSAGE = 0x1ED,
+ NOUN_FIND = 0x1EE,
+ NOUN_SAND_NEAR_STONES = 0x1EF,
+ NOUN_DESERT_SKY = 0x1F0,
+ NOUN_POOL = 0x1F1,
+ NOUN_PALM_TREE = 0x1F2,
+ NOUN_OASIS = 0x1F3,
+ NOUN_LEAN_TO = 0x1F4,
+ NOUN_TRADER = 0x1F5,
+ NOUN_SIGN = 0x1F6,
+ NOUN_WATER_FLOW = 0x1F7,
+ NOUN_FLOATING_DISK = 0x1F8,
+ NOUN_GNARLED_ROOT = 0x1F9,
+ NOUN_SNAKE_PIT = 0x1FA,
+ NOUN_MARKER = 0x1FB,
+ NOUN_SHAMAN = 0x1FC,
+ NOUN_GUARDHOUSE = 0x1FD,
+ NOUN_BONE_TREE = 0x1FE,
+ NOUN_EAR_ROCK = 0x1FF,
+ NOUN_MOUTH_ROCK = 0x200,
+ NOUN_NOSE_ROCK = 0x201,
+ NOUN_NEW_BUNDLE = 0x202,
+ NOUN_LIZARD = 0x203,
+ NOUN_ROC = 0x204,
+ NOUN_ROCS_NEST2 = 0x205,
+ NOUN_SELECT = 0x206,
+ NOUN_PURPLE_GEM = 0x207,
+ NOUN_PURPLE_STONE = 0x208,
+ NOUN_GREEN_STONE = 0x209,
+ NOUN_PATH = 0x20A,
+ NOUN_GUARDS = 0x20B,
+ NOUN_LAMP = 0x20C,
+ NOUN_SCIMITAR = 0x20D,
+ NOUN_SITTING_PILLOW = 0x20E,
+ NOUN_WATER_GOURD = 0x20F,
+ NOUN_JAR = 0x210,
+ NOUN_TENT_POLE = 0x211,
+ NOUN_EXIT = 0x212,
+ NOUN_PARAPHERNALIA = 0x213,
+ NOUN_SLATHAN_NI_PATAN3 = 0x214,
+ NOUN_EYE_ROCK = 0x215,
+ NOUN_BODY_TREE = 0x216,
+ NOUN_CLEARING = 0x217,
+ NOUN_TENTACLES = 0x218,
+ NOUN_SPELL_SHIELD = 0x219,
+ NOUN_POOL_MONSTER = 0x21A,
+ NOUN_SHIFTER_BOULDER = 0x21B,
+ NOUN_DEAD_TREE = 0x21C,
+ NOUN_PIT = 0x21D,
+ NOUN_SHIFTER_VILLAGE = 0x21E,
+ NOUN_SLATHAN_SKY = 0x21F,
+ NOUN_SHIFTER = 0x220,
+ NOUN_WALK_AROUND = 0x221,
+ NOUN_WRECKED_BRIDGE = 0x222,
+ NOUN_SHACK = 0x223,
+ NOUN_WRECKED_SHACK = 0x224,
+ NOUN_WISE_SHIFTER = 0x225,
+ NOUN_GRASS = 0x226,
+ NOUN_ENTRANCE_TO_MAZE = 0x227,
+ NOUN_TOPIARY_TOAD = 0x228,
+ NOUN_BOULDER = 0x229,
+ NOUN_MUSHROOM = 0x22A,
+ NOUN_SLATHAN_SKY2 = 0x22B,
+ NOUN_GRETA = 0x22C,
+ NOUN_TREE_STUMP = 0x22D,
+ NOUN_SANCTUARY_WOODS = 0x22E,
+ NOUN_TOADS = 0x22F,
+ NOUN_DOOFUS = 0x230,
+ NOUN_SHIFTING_MONSTER = 0x231,
+ NOUN_SPRITE = 0x232,
+ NOUN_MAZE = 0x233,
+ NOUN_TOPIARY_TOADSTOOL = 0x234,
+ NOUN_TOPIARY_GARGOYLE = 0x235,
+ NOUN_TOPIARY_DRAGON = 0x236,
+ NOUN_GUARDIAN = 0x237,
+ NOUN_BUTTERFLY_KING = 0x238,
+ NOUN_ROBE = 0x239,
+ NOUN_CEDAR_CHEST = 0x23A,
+ NOUN_DRAGONSPHERE2 = 0x23B,
+ NOUN_PATH_TO_HIGHTOWER2 = 0x23C,
+ NOUN_CALIPH = 0x23D
+};
+
+class SceneFactory {
+public:
+ static SceneLogic *createScene(MADSEngine *vm);
+};
+
+/**
+ * Specialized base class for Dragonsphere game scenes
+ */
+class DragonsphereScene : public SceneLogic {
+protected:
+ DragonsphereGlobals &_globals;
+ GameDragonsphere &_game;
+ MADSAction &_action;
+
+ /**
+ * Forms an animation resource name
+ */
+ Common::String formAnimName(char sepChar, int suffixNum);
+
+ /**
+ * Plays appropriate sound for entering varous rooms
+ */
+ void lowRoomsEntrySound();
+public:
+ /**
+ * Constructor
+ */
+ DragonsphereScene(MADSEngine *vm);
+
+ void sub7178C();
+};
+
+class SceneInfoDragonsphere : public SceneInfo {
+ friend class SceneInfo;
+protected:
+ virtual void loadCodes(MSurface &depthSurface, int variant);
+
+ virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream);
+
+ /**
+ * Constructor
+ */
+ SceneInfoDragonsphere(MADSEngine *vm) : SceneInfo(vm) {}
+};
+
+// TODO: Temporary, remove once implemented properly
+class Scene1xx : public DragonsphereScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void sceneEntrySound() {}
+
+ /**
+ *Sets the AA file to use for the scene
+ */
+ void setAAName() {}
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix() {}
+public:
+ Scene1xx(MADSEngine *vm) : DragonsphereScene(vm) {}
+};
+
+// TODO: Temporary, remove once implemented properly
+class DummyScene : public DragonsphereScene {
+public:
+ DummyScene(MADSEngine *vm) : DragonsphereScene(vm) {
+ warning("Unimplemented scene");
+ }
+
+ virtual void setup() {}
+ virtual void enter() {}
+ virtual void actions() {}
+};
+
+} // End of namespace Dragonsphere
+
+} // End of namespace MADS
+
+#endif /* MADS_DRAGONSPHERE_SCENES_H */
diff --git a/engines/mads/dragonsphere/game_dragonsphere.cpp b/engines/mads/dragonsphere/game_dragonsphere.cpp
new file mode 100644
index 0000000000..3836adb6d2
--- /dev/null
+++ b/engines/mads/dragonsphere/game_dragonsphere.cpp
@@ -0,0 +1,163 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "mads/mads.h"
+#include "mads/game.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/dragonsphere/game_dragonsphere.h"
+//#include "mads/nebular/dialogs_nebular.h"
+//#include "mads/nebular/globals_nebular.h"
+#include "mads/dragonsphere/dragonsphere_scenes.h"
+
+namespace MADS {
+
+namespace Dragonsphere {
+
+GameDragonsphere::GameDragonsphere(MADSEngine *vm)
+ : Game(vm) {
+ _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+ _storyMode = STORYMODE_NAUGHTY;
+}
+
+void GameDragonsphere::startGame() {
+ _scene._priorSceneId = 0;
+ _scene._currentSceneId = -1;
+ _scene._nextSceneId = 101;
+
+ initializeGlobals();
+}
+
+void GameDragonsphere::initializeGlobals() {
+ //int count, count2;
+ //int bad;
+
+ _globals.reset();
+ //_globals[kTalkInanimateCount] = 8;
+
+ /* Section #1 variables */
+ // TODO
+
+ /* Section #2 variables */
+ // TODO
+
+ /* Section #3 variables */
+ // TODO
+
+ /* Section #4 variables */
+ // TODO
+
+ /* Section #5 variables */
+ // TODO
+
+ /* Section #6 variables */
+ // TODO
+
+ /* Section #9 variables */
+ // TODO
+
+ _player._facing = FACING_NORTH;
+ _player._turnToFacing = FACING_NORTH;
+
+ //Player::preloadSequences("RXM", 1);
+ //Player::preloadSequences("ROX", 1);
+}
+
+void GameDragonsphere::setSectionHandler() {
+ delete _sectionHandler;
+
+ switch (_sectionNumber) {
+ case 1:
+ _sectionHandler = new Section1Handler(_vm);
+ break;
+ case 2:
+ _sectionHandler = new Section2Handler(_vm);
+ break;
+ case 3:
+ _sectionHandler = new Section3Handler(_vm);
+ break;
+ case 4:
+ _sectionHandler = new Section4Handler(_vm);
+ break;
+ case 5:
+ _sectionHandler = new Section5Handler(_vm);
+ break;
+ case 6:
+ _sectionHandler = new Section6Handler(_vm);
+ break;
+ case 7:
+ _sectionHandler = new Section7Handler(_vm);
+ break;
+ case 8:
+ _sectionHandler = new Section8Handler(_vm);
+ break;
+ default:
+ break;
+ }
+}
+
+void GameDragonsphere::checkShowDialog() {
+ // TODO: Copied from Nebular
+ if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[5]) {
+ _player.releasePlayerSprites();
+ _vm->_dialogs->showDialog();
+ _vm->_dialogs->_pendingDialog = DIALOG_NONE;
+ }
+}
+
+void GameDragonsphere::doObjectAction() {
+ // TODO: Copied from Nebular
+ //Scene &scene = _scene;
+ MADSAction &action = _scene._action;
+ //Dialogs &dialogs = *_vm->_dialogs;
+ //int id;
+
+ action._inProgress = false;
+}
+
+void GameDragonsphere::unhandledAction() {
+ // TODO
+}
+
+void GameDragonsphere::step() {
+ if (_player._visible && _player._stepEnabled && !_player._moving &&
+ (_player._facing == _player._turnToFacing)) {
+
+ // TODO
+ }
+
+}
+
+void GameDragonsphere::synchronize(Common::Serializer &s, bool phase1) {
+ Game::synchronize(s, phase1);
+
+ // TODO: Copied from Nebular
+ if (!phase1) {
+ _globals.synchronize(s);
+ }
+}
+
+} // End of namespace Dragonsphere
+
+} // End of namespace MADS
diff --git a/engines/mads/dragonsphere/game_dragonsphere.h b/engines/mads/dragonsphere/game_dragonsphere.h
new file mode 100644
index 0000000000..7869dc87b4
--- /dev/null
+++ b/engines/mads/dragonsphere/game_dragonsphere.h
@@ -0,0 +1,151 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_GAME_DRAGONSPHERE_H
+#define MADS_GAME_DRAGONSPHERE_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/globals.h"
+//#include "mads/nebular/globals_nebular.h"
+
+namespace MADS {
+
+namespace Dragonsphere {
+
+// TODO: Adapt for Dragonsphere's difficulty setting
+enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 };
+
+enum InventoryObject {
+ OBJ_NONE = -1,
+ OBJ_SIGNET_RING = 0,
+ OBJ_BIRD_FIGURINE = 1,
+ OBJ_BIRDCALL = 2,
+ OBJ_SHIELDSTONE = 3,
+ OBJ_SWORD = 4,
+ OBJ_GOBLET = 5,
+ OBJ_BONE = 6,
+ OBJ_FRUIT = 7,
+ OBJ_DOLL = 8,
+ OBJ_POLYSTONE = 9,
+ OBJ_RED_STONE = 10,
+ OBJ_YELLOW_STONE = 11,
+ OBJ_BLUE_STONE = 12,
+ OBJ_KEY_CROWN = 13,
+ OBJ_DATES = 14,
+ OBJ_STATUE = 15,
+ OBJ_FLIES = 16,
+ OBJ_SOUL_EGG = 17,
+ OBJ_MAGIC_BELT = 18,
+ OBJ_AMULET = 19,
+ OBJ_MUD = 20,
+ OBJ_FEATHERS = 21,
+ OBJ_TORCH = 22,
+ OBJ_FLASK = 23,
+ OBJ_FLASK_OF_ACID = 24,
+ OBJ_ROPE = 25,
+ OBJ_VORTEX_STONE = 26,
+ OBJ_DEAD_RAT = 27,
+ OBJ_MAP = 28,
+ OBJ_CRYSTAL_BALL = 29,
+ OBJ_BLACK_SPHERE = 30,
+ OBJ_SOPORIFIC = 31,
+ OBJ_SHIFTER_RING = 32,
+ OBJ_SPIRIT_BUNDLE = 33,
+ OBJ_PARTIAL_BUNDLE = 34,
+ OBJ_RATSICLE = 35,
+ OBJ_TENTACLE_PARTS = 36,
+ OBJ_TELEPORT_DOOR = 37,
+ OBJ_RARE_COIN = 38,
+ OBJ_CRYSTAL_FLOWER = 39,
+ OBJ_DIAMOND_DUST = 40,
+ OBJ_RUBY_RING = 41,
+ OBJ_GOLD_NUGGET = 42,
+ OBJ_MUSIC_BOX = 43,
+ OBJ_EMERALD = 44,
+ OBJ_PARCHMENT = 45,
+ OBJ_GAME = 46,
+ OBJ_GAME2 = 47,
+ OBJ_NEW_BUNDLE = 48
+};
+
+// HACK: A stub for now, remove from here once it's implemented properly
+class DragonsphereGlobals : public Globals {
+public:
+ DragonsphereGlobals() {
+ resize(210); // Rex has 210 globals
+ }
+ virtual ~DragonsphereGlobals() {}
+};
+
+class GameDragonsphere : public Game {
+ friend class Game;
+protected:
+ GameDragonsphere(MADSEngine *vm);
+
+ virtual void startGame();
+
+ virtual void initializeGlobals();
+
+ virtual void setSectionHandler();
+
+ virtual void checkShowDialog();
+public:
+ DragonsphereGlobals _globals;
+ StoryMode _storyMode;
+
+ virtual Globals &globals() { return _globals; }
+
+ virtual void doObjectAction();
+
+ virtual void unhandledAction();
+
+ virtual void step();
+
+ virtual void synchronize(Common::Serializer &s, bool phase1);
+};
+
+
+class Section1Handler : public SectionHandler {
+public:
+ Section1Handler(MADSEngine *vm) : SectionHandler(vm) {}
+
+ // TODO: Properly implement handler methods
+ virtual void preLoadSection() {}
+ virtual void sectionPtr2() {}
+ virtual void postLoadSection() {}
+};
+
+// TODO: Properly implement handler classes
+typedef Section1Handler Section2Handler;
+typedef Section1Handler Section3Handler;
+typedef Section1Handler Section4Handler;
+typedef Section1Handler Section5Handler;
+typedef Section1Handler Section6Handler;
+typedef Section1Handler Section7Handler;
+typedef Section1Handler Section8Handler;
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_GAME_DRAGONSPHERE_H */
diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp
new file mode 100644
index 0000000000..de4dc3c070
--- /dev/null
+++ b/engines/mads/events.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "graphics/cursorman.h"
+#include "common/events.h"
+#include "engines/util.h"
+#include "mads/mads.h"
+#include "mads/events.h"
+#include "mads/scene.h"
+
+namespace MADS {
+
+EventsManager::EventsManager(MADSEngine *vm) {
+ _vm = vm;
+ _cursorSprites = nullptr;
+ _cursorId = CURSOR_NONE;
+ _newCursorId = CURSOR_NONE;
+ _frameCounter = 10;
+ _priorFrameTime = 0;
+ _mouseClicked = false;
+ _mouseReleased = false;
+ _mouseButtons = 0;
+ _mouseStatus = 0;
+ _vD2 = 0;
+ _mouseStatusCopy = 0;
+ _mouseMoved = false;
+ _vD8 = 0;
+ _rightMousePressed = false;
+ _eventTarget = nullptr;
+}
+
+EventsManager::~EventsManager() {
+ freeCursors();
+}
+
+void EventsManager::loadCursors(const Common::String &spritesName) {
+ delete _cursorSprites;
+ _cursorSprites = new SpriteAsset(_vm, spritesName, 0x4000);
+}
+
+void EventsManager::setCursor(CursorType cursorId) {
+ _cursorId = cursorId;
+ changeCursor();
+}
+
+void EventsManager::setCursor2(CursorType cursorId) {
+ _cursorId = cursorId;
+ _newCursorId = cursorId;
+ changeCursor();
+}
+
+void EventsManager::showCursor() {
+ CursorMan.showMouse(true);
+}
+
+void EventsManager::hideCursor() {
+ CursorMan.showMouse(false);
+}
+
+bool EventsManager::isCursorVisible() {
+ return CursorMan.isVisible();
+}
+
+void EventsManager::waitCursor() {
+ CursorType cursorId = (CursorType)MIN(_cursorSprites->getCount(), (int)CURSOR_WAIT);
+ _newCursorId = cursorId;
+ if (_cursorId != _newCursorId) {
+ changeCursor();
+ _cursorId = _newCursorId;
+ }
+}
+
+void EventsManager::changeCursor() {
+ if (_cursorSprites) {
+ MSprite *cursor = _cursorSprites->getFrame(_cursorId - 1);
+ assert(cursor->w == cursor->h);
+ byte transIndex = cursor->getTransparencyIndex();
+
+ // Check for hotspot indication pixels along the right-hand and bottom
+ // row. Put together, these give the cursor's hotspot x,y
+ int hotspotX = 0, hotspotY = 0;
+ byte *cursorData = cursor->getData();
+ for (int idx = 0; idx < cursor->w; ++idx) {
+ if (cursorData[(cursor->h - 1) * cursor->w + idx] != transIndex)
+ hotspotX = idx;
+
+ if (cursorData[(idx + 1) * cursor->w - 1] != transIndex)
+ hotspotY = idx;
+ }
+
+ // Reduce the cursor data to remove the last column from each row, since
+ // the cursor routines don't have a pitch option
+ byte *destCursor = new byte[(cursor->w - 1) * (cursor->h - 1)];
+ byte *srcP = cursorData;
+ byte *destP = destCursor;
+
+ for (int idx = 0; idx < (cursor->h - 1); ++idx) {
+ Common::copy(srcP, srcP + cursor->w - 1, destP);
+ srcP += cursor->w;
+ destP += cursor->w - 1;
+ }
+
+ // Set the raw cursor data to use
+ CursorMan.replaceCursor(destCursor, cursor->w - 1, cursor->h - 1,
+ hotspotX, hotspotY, transIndex);
+ showCursor();
+ delete[] destCursor;
+ }
+}
+
+void EventsManager::freeCursors() {
+ delete _cursorSprites;
+ _cursorSprites = nullptr;
+}
+
+void EventsManager::pollEvents() {
+ checkForNextFrameCounter();
+ _mouseMoved = false;
+
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ // If an event target is specified, pass the event to it
+ if (_eventTarget) {
+ _eventTarget->onEvent(event);
+ continue;
+ }
+
+ // Handle keypress
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RTL:
+ return;
+
+ case Common::EVENT_KEYDOWN:
+ // Check for debugger
+ if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) {
+ // Attach to the debugger
+ _vm->_debugger->attach();
+ _vm->_debugger->onFrame();
+ } else {
+ _pendingKeys.push(event);
+ }
+ return;
+ case Common::EVENT_KEYUP:
+ return;
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_RBUTTONDOWN:
+ _mouseClicked = true;
+ _mouseButtons = 1;
+ _mouseMoved = true;
+ if (event.type == Common::EVENT_RBUTTONDOWN) {
+ _rightMousePressed = true;
+ _mouseStatus |= 2;
+ } else {
+ _mouseStatus |= 1;
+ }
+ return;
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ _mouseClicked = false;
+ _mouseReleased = true;
+ _mouseMoved = true;
+ _rightMousePressed = false;
+ if (event.type == Common::EVENT_RBUTTONUP) {
+ _mouseStatus &= ~2;
+ } else {
+ _mouseStatus &= ~1;
+ }
+ return;
+ case Common::EVENT_MOUSEMOVE:
+ _mousePos = event.mouse;
+ _currentPos = event.mouse;
+ _mouseMoved = true;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+bool EventsManager::checkForNextFrameCounter() {
+ // Check for next game frame
+ uint32 milli = g_system->getMillis();
+ if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
+ ++_frameCounter;
+ _priorFrameTime = milli;
+
+ // Do any palette cycling
+ _vm->_game->_scene.animatePalette();
+
+ // Give time to the debugger
+ _vm->_debugger->onFrame();
+
+ // Display the frame
+ _vm->_screen.updateScreen();
+
+ // Signal the ScummVM debugger
+ _vm->_debugger->onFrame();
+
+ return true;
+ }
+
+ return false;
+}
+
+void EventsManager::delay(int cycles) {
+ uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE;
+ uint32 delayEnd = g_system->getMillis() + totalMilli;
+
+ while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) {
+ g_system->delayMillis(10);
+
+ pollEvents();
+ }
+}
+
+void EventsManager::waitForNextFrame() {
+ _mouseClicked = false;
+ _mouseReleased = false;
+ _mouseButtons = 0;
+
+ bool mouseClicked = false;
+ bool mouseReleased = false;
+ int mouseButtons = 0;
+
+ uint32 frameCtr = getFrameCounter();
+ while (!_vm->shouldQuit() && frameCtr == _frameCounter) {
+ delay(1);
+
+ mouseClicked |= _mouseClicked;
+ mouseReleased |= _mouseReleased;
+ mouseButtons |= _mouseButtons;
+ }
+
+ _mouseClicked = mouseClicked;
+ _mouseReleased = mouseReleased;
+ _mouseButtons = mouseButtons;
+ _mouseMoved |= _mouseClicked || _mouseReleased;
+}
+
+void EventsManager::initVars() {
+ _mousePos = Common::Point(-1, -1);
+ _mouseStatusCopy = _mouseStatus;
+ _vD2 = _vD8 = 0;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/events.h b/engines/mads/events.h
new file mode 100644
index 0000000000..54df337efd
--- /dev/null
+++ b/engines/mads/events.h
@@ -0,0 +1,176 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_EVENTS_H
+#define MADS_EVENTS_H
+
+#include "common/scummsys.h"
+#include "common/events.h"
+#include "common/stack.h"
+#include "mads/assets.h"
+#include "mads/sprites.h"
+
+namespace MADS {
+
+enum CursorType { CURSOR_NONE = 0, CURSOR_ARROW = 1, CURSOR_WAIT = 2, CURSOR_GO_DOWN = 3,
+ CURSOR_GO_UP = 4, CURSOR_GO_LEFT = 5, CURSOR_GO_RIGHT = 6 };
+
+#define GAME_FRAME_RATE 50
+#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
+
+class MADSEngine;
+
+class EventTarget {
+public:
+ virtual ~EventTarget() {}
+ virtual bool onEvent(Common::Event &event) { return false; }
+};
+
+class EventsManager {
+private:
+ MADSEngine *_vm;
+ uint32 _frameCounter;
+ uint32 _priorFrameTime;
+ Common::Point _mousePos;
+ Common::Point _currentPos;
+ EventTarget *_eventTarget;
+
+ /**
+ * Updates the cursor image when the current cursor changes
+ */
+ void changeCursor();
+public:
+ SpriteAsset *_cursorSprites;
+ CursorType _cursorId;
+ CursorType _newCursorId;
+ bool _mouseClicked;
+ bool _mouseReleased;
+ byte _mouseButtons;
+ bool _rightMousePressed;
+ int _mouseStatus;
+ int _vD2;
+ int _mouseStatusCopy;
+ bool _mouseMoved;
+ int _vD8;
+ Common::Stack<Common::Event> _pendingKeys;
+public:
+ /**
+ * Constructor
+ */
+ EventsManager(MADSEngine *vm);
+
+ /**
+ * Destructor
+ */
+ ~EventsManager();
+
+ /**
+ * Loads the sprite set containing the cursors
+ */
+ void loadCursors(const Common::String &spritesName);
+
+ /**
+ * Sets the cursor
+ */
+ void setCursor(CursorType cursorId);
+
+ /**
+ * Sets the cursor
+ */
+ void setCursor2(CursorType cursorId);
+
+ /**
+ * Show the mouse cursor
+ */
+ void showCursor();
+
+ /**
+ * Hide the mouse cursor
+ */
+ void hideCursor();
+
+ /**
+ * Returns if the mouse cursor is visible
+ */
+ bool isCursorVisible();
+
+ /**
+ * Shows the wait cursor
+ */
+ void waitCursor();
+
+ /**
+ * Free currently loaded cursors
+ */
+ void freeCursors();
+
+ /**
+ * Poll any pending events
+ */
+ void pollEvents();
+
+ /**
+ * Sets an event handler other than the events manager
+ */
+ void setEventTarget(EventTarget *target) { _eventTarget = target; }
+
+ /**
+ * Return the current mouse position
+ */
+ Common::Point mousePos() const { return _mousePos; }
+
+ /**
+ * Return the current mouse position
+ */
+ Common::Point currentPos() const { return _currentPos; }
+
+ /**
+ * Delay for a given number of frames
+ */
+ void delay(int amount);
+
+ /**
+ * Wait for the next frame
+ */
+ void waitForNextFrame();
+
+ /**
+ * Checks for whether the next game frame number has been reached.
+ */
+ bool checkForNextFrameCounter();
+
+ /**
+ * Gets the current frame counter
+ */
+ uint32 getFrameCounter() const { return _frameCounter; }
+
+ void initVars();
+
+ /**
+ * Returns true if there's any pending keys to be processed
+ */
+ bool isKeyPressed() const { return !_pendingKeys.empty(); }
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_EVENTS_H */
diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp
new file mode 100644
index 0000000000..f7c1c52703
--- /dev/null
+++ b/engines/mads/font.cpp
@@ -0,0 +1,256 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/compression.h"
+#include "mads/font.h"
+#include "mads/msurface.h"
+
+namespace MADS {
+
+MADSEngine *Font::_vm;
+
+Common::HashMap<Common::String, Font *> *Font::_fonts;
+
+uint8 Font::_fontColors[4];
+
+void Font::init(MADSEngine *vm) {
+ _vm = vm;
+ _fontColors[0] = 0xFF;
+ _fontColors[1] = 0xF;
+ _fontColors[2] = 7;
+ _fontColors[3] = 8;
+
+ _fonts = new Common::HashMap<Common::String, Font *>();
+}
+
+void Font::deinit() {
+ Common::HashMap<Common::String, Font *>::iterator i;
+ for (i = _fonts->begin(); i != _fonts->end(); ++i)
+ delete (*i)._value;
+
+ delete _fonts;
+}
+
+Font *Font::getFont(const Common::String &fontName) {
+ if (_fonts->contains(fontName)) {
+ return _fonts->getVal(fontName);
+ } else {
+ Font *font = new Font(fontName);
+ _fonts->setVal(fontName, font);
+ return font;
+ }
+}
+
+Font::Font() {
+ _charWidths = nullptr;
+ _charOffs = nullptr;
+ _charData = nullptr;
+ setFont(FONT_INTERFACE);
+}
+
+Font::Font(const Common::String &filename) {
+ _charWidths = nullptr;
+ _charOffs = nullptr;
+ _charData = nullptr;
+ setFont(filename);
+}
+
+Font::~Font() {
+ delete[] _charWidths;
+ delete[] _charOffs;
+ delete[] _charData;
+}
+
+void Font::setFont(const Common::String &filename) {
+ if (!_filename.empty() && (filename == _filename))
+ // Already using specified font, so don't bother reloading
+ return;
+
+ _filename = filename;
+
+ Common::String resName = filename;
+ if (!resName.hasSuffix(".FF"))
+ resName += ".FF";
+
+ MadsPack fontData(resName, _vm);
+ Common::SeekableReadStream *fontFile = fontData.getItemStream(0);
+
+ _maxHeight = fontFile->readByte();
+ _maxWidth = fontFile->readByte();
+
+ _charWidths = new uint8[128];
+ // Char data is shifted by 1
+ _charWidths[0] = 0;
+ fontFile->read(_charWidths + 1, 127);
+ fontFile->readByte(); // remainder
+
+ _charOffs = new uint16[128];
+
+ uint startOffs = 2 + 128 + 256;
+ uint fontSize = fontFile->size() - startOffs;
+
+ // Char data is shifted by 1
+ _charOffs[0] = 0;
+ for (int i = 1; i < 128; i++)
+ _charOffs[i] = fontFile->readUint16LE() - startOffs;
+ fontFile->readUint16LE(); // remainder
+
+ _charData = new uint8[fontSize];
+ fontFile->read(_charData, fontSize);
+
+ delete fontFile;
+}
+
+void Font::setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4) {
+ _fontColors[0] = v1;
+ _fontColors[1] = v2;
+ _fontColors[2] = v3;
+ _fontColors[3] = v4;
+}
+
+void Font::setColorMode(SelectionMode mode) {
+ switch (mode) {
+ case SELMODE_UNSELECTED:
+ setColors(0xFF, 4, 4, 0);
+ break;
+ case SELMODE_HIGHLIGHTED:
+ setColors(0xFF, 5, 5, 0);
+ break;
+ case SELMODE_SELECTED:
+ setColors(0xFF, 6, 6, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+int Font::writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt,
+ int spaceWidth, int width) {
+ int xEnd;
+ if (width > 0)
+ xEnd = MIN((int)surface->w, pt.x + width);
+ else
+ xEnd = surface->w;
+
+ int x = pt.x;
+ int y = pt.y;
+
+ int skipY = 0;
+ if (y < 0) {
+ skipY = -y;
+ y = 0;
+ }
+
+ int height = MAX(0, _maxHeight - skipY);
+ if (height == 0)
+ return x;
+
+ int bottom = y + height - 1;
+ if (bottom > surface->getHeight() - 1) {
+ height -= MIN(height, bottom - (surface->getHeight() - 1));
+ }
+
+ if (height <= 0)
+ return x;
+
+ byte *destPtr = surface->getBasePtr(x, y);
+ uint8 *oldDestPtr = destPtr;
+
+ int xPos = x;
+
+ const char *text = msg.c_str();
+ while (*text) {
+ char theChar = (*text++) & 0x7F;
+ int charWidth = _charWidths[(byte)theChar];
+
+ if (charWidth > 0) {
+
+ if (xPos + charWidth > xEnd)
+ return xPos;
+
+ uint8 *charData = &_charData[_charOffs[(byte)theChar]];
+ int bpp = getBpp(charWidth);
+
+ if (skipY != 0)
+ charData += bpp * skipY;
+
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < bpp; j++) {
+ if (*charData & 0xc0)
+ *destPtr = _fontColors[(*charData & 0xc0) >> 6];
+ destPtr++;
+ if (*charData & 0x30)
+ *destPtr = _fontColors[(*charData & 0x30) >> 4];
+ destPtr++;
+ if (*charData & 0x0C)
+ *destPtr = _fontColors[(*charData & 0x0C) >> 2];
+ destPtr++;
+ if (*charData & 0x03)
+ *destPtr = _fontColors[*charData & 0x03];
+ destPtr++;
+ charData++;
+ }
+
+ destPtr += surface->getWidth() - bpp * 4;
+
+ }
+
+ destPtr = oldDestPtr + charWidth + spaceWidth;
+ oldDestPtr = destPtr;
+
+ }
+
+ xPos += charWidth + spaceWidth;
+
+ }
+
+ return xPos;
+
+}
+
+int Font::getWidth(const Common::String &msg, int spaceWidth) {
+ int width = 0;
+ const char *text = msg.c_str();
+
+ if (msg.size() > 0) {
+ while (*text)
+ width += _charWidths[*text++ & 0x7F] + spaceWidth;
+ width -= spaceWidth;
+ }
+
+ return width;
+}
+
+int Font::getBpp(int charWidth) {
+ if (charWidth > 12)
+ return 4;
+ else if (charWidth > 8)
+ return 3;
+ else if (charWidth > 4)
+ return 2;
+ else
+ return 1;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/font.h b/engines/mads/font.h
new file mode 100644
index 0000000000..47df647637
--- /dev/null
+++ b/engines/mads/font.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_FONT_H
+#define MADS_FONT_H
+
+#include "common/scummsys.h"
+#include "common/hashmap.h"
+#include "common/endian.h"
+#include "common/util.h"
+#include "mads/msurface.h"
+
+namespace MADS {
+
+#define FONT_CONVERSATION "*FONTCONV.FF"
+#define FONT_INTERFACE "*FONTINTR.FF"
+#define FONT_MAIN "*FONTMAIN.FF"
+#define FONT_MENU "*FONTMENU.FF" // Not in Rex (uses bitmap files for menu strings)
+#define FONT_MISC "*FONTMISC.FF"
+#define FONT_TELE "*FONTTELE.FF" // Not in Phantom
+#define FONT_PHAN "*FONTPHAN.FF" // Phantom only
+
+enum SelectionMode {
+ SELMODE_UNSELECTED = 0, SELMODE_HIGHLIGHTED = 1, SELMODE_SELECTED = 2
+};
+
+class MADSEngine;
+
+class Font {
+private:
+ static uint8 _fontColors[4];
+ static MADSEngine *_vm;
+ static Common::HashMap<Common::String, Font *> *_fonts;
+public:
+ /**
+ * Initialize the font system
+ */
+ static void init(MADSEngine *vm);
+
+ /**
+ * Free up the resources used by the font
+ */
+ static void deinit();
+
+ /**
+ * Returns a new Font instance using the specified font name
+ */
+ static Font *getFont(const Common::String &fontName);
+private:
+ uint8 _maxWidth, _maxHeight;
+ uint8 *_charWidths;
+ uint16 *_charOffs;
+ uint8 *_charData;
+ Common::String _filename;
+
+ int getBpp(int charWidth);
+
+ void setFont(const Common::String &filename);
+public:
+ Font();
+ Font(const Common::String &filename);
+ virtual ~Font();
+
+ void setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4);
+ void setColorMode(SelectionMode mode);
+
+ int maxWidth() const { return _maxWidth; }
+ int getWidth(const Common::String &msg, int spaceWidth = -1);
+ int getHeight() const { return _maxHeight; }
+ int writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt,
+ int spaceWidth = 0, int width = 0);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_FONT_H */
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
new file mode 100644
index 0000000000..b544eff2db
--- /dev/null
+++ b/engines/mads/game.cpp
@@ -0,0 +1,589 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/memstream.h"
+#include "common/serializer.h"
+#include "graphics/palette.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
+#include "mads/mads.h"
+#include "mads/compression.h"
+#include "mads/game.h"
+#include "mads/game_data.h"
+#include "mads/events.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/resources.h"
+#include "mads/dragonsphere/game_dragonsphere.h"
+#include "mads/nebular/game_nebular.h"
+#include "mads/phantom/game_phantom.h"
+
+namespace MADS {
+
+Game *Game::init(MADSEngine *vm) {
+ switch (vm->getGameID()) {
+ case GType_RexNebular:
+ return new Nebular::GameNebular(vm);
+ case GType_Dragonsphere:
+ return new Dragonsphere::GameDragonsphere(vm);
+ case GType_Phantom:
+ return new Phantom::GamePhantom(vm);
+ default:
+ error("Game: Unknown game");
+ }
+
+ return nullptr;
+}
+
+Game::Game(MADSEngine *vm)
+ : _vm(vm), _surface(nullptr), _objects(vm), _scene(vm),
+ _screenObjects(vm), _player(vm) {
+ _sectionNumber = 1;
+ _priorSectionNumber = 0;
+ _loadGameSlot = -1;
+ _lastSave = -1;
+ _saveFile = nullptr;
+ _saveThumb = nullptr;
+ _statusFlag = 0;
+ _sectionHandler = nullptr;
+ _sectionNumber = 1;
+ _priorSectionNumber = 0;
+ _currentSectionNumber = -1;
+ _kernelMode = KERNEL_GAME_LOAD;
+ _quoteEmergency = false;
+ _vocabEmergency = false;
+ _aaName = "*I0.AA";
+ _priorFrameTimer = 0;
+ _anyEmergency = false;
+ _triggerMode = SEQUENCE_TRIGGER_PARSER;
+ _triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _trigger = 0;
+ _winStatus = 0;
+ _widepipeCtr = 0;
+ _fx = kTransitionNone;
+
+ // Load the inventory object list
+ _objects.load();
+ if (_objects._inventoryList.size() > 0)
+ // At least one item in default inventory, so select first item for display
+ _scene._userInterface._selectedInvIndex = 0;
+
+ // Load the quotes
+ loadQuotes();
+}
+
+Game::~Game() {
+ if (_saveThumb) {
+ _saveThumb->free();
+ delete _saveThumb;
+ }
+
+ delete _saveFile;
+ delete _surface;
+ delete _sectionHandler;
+}
+
+void Game::run() {
+ initializeGlobals();
+
+ // If requested, load a savegame instead of showing the intro
+ if (ConfMan.hasKey("save_slot")) {
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0 && saveSlot <= 999)
+ _loadGameSlot = saveSlot;
+ }
+
+ _statusFlag = true;
+
+ if (_loadGameSlot == -1) {
+ startGame();
+ }
+
+ // Get the initial starting time for the first scene
+ _scene._frameStartTime = _vm->_events->getFrameCounter();
+
+ if (!_vm->shouldQuit())
+ gameLoop();
+}
+
+void Game::splitQuote(const Common::String &source, Common::String &line1, Common::String &line2) {
+ // Make the first line up the end of the word at the half-way point
+ const char *strP = source.c_str() + source.size() / 2;
+ while (*strP != ' ') ++strP;
+
+ line1 = Common::String(source.c_str(), strP);
+
+ // The rest of the string goes in the second line
+ while (*strP == ' ') ++strP;
+ line2 = Common::String(strP);
+}
+
+void Game::gameLoop() {
+ while (!_vm->shouldQuit() && _statusFlag) {
+ if (_loadGameSlot != -1) {
+ loadGame(_loadGameSlot);
+ _loadGameSlot = -1;
+ }
+
+ setSectionHandler();
+ _sectionHandler->preLoadSection();
+ initSection(_sectionNumber);
+ _vm->_sound->init(_sectionNumber);
+ _sectionHandler->postLoadSection();
+
+ _scene._spriteSlots.reset();
+
+ if (_sectionNumber == _currentSectionNumber)
+ sectionLoop();
+
+ _player.releasePlayerSprites();
+ assert(_scene._sprites._assetCount == 0);
+
+ _vm->_palette->unlock();
+ _vm->_events->waitCursor();
+ _vm->_events->freeCursors();
+ _vm->_sound->closeDriver();
+ }
+}
+
+void Game::sectionLoop() {
+ while (!_vm->shouldQuit() && _statusFlag && (_sectionNumber == _currentSectionNumber)) {
+ _kernelMode = KERNEL_ROOM_PRELOAD;
+ _player._spritesChanged = true;
+ _quoteEmergency = false;
+ _vocabEmergency = false;
+ _vm->_events->waitCursor();
+
+ _scene.clearVocab();
+ _scene._dynamicHotspots.clear();
+ _scene.loadSceneLogic();
+
+ _player._walkAnywhere = false;
+ _player._stepEnabled = true;
+ _player._visible = true;
+ _vm->_dialogs->_defaultPosition = Common::Point(-1, -1);
+ _visitedScenes.add(_scene._nextSceneId);
+
+ // Reset the user interface
+ _screenObjects._forceRescan = true;
+ _screenObjects._inputMode = kInputBuildingSentences;
+ _scene._userInterface._scrollbarActive = SCROLLBAR_NONE;
+
+ _player._loadsFirst = true;
+
+ _scene._sceneLogic->setup();
+ if (_player._spritesChanged || _player._loadsFirst) {
+ if (_player._spritesLoaded)
+ _player.releasePlayerSprites();
+ _vm->_palette->resetGamePalette(18, 10);
+ _scene._spriteSlots.reset();
+ } else {
+ _vm->_palette->initPalette();
+ }
+
+ // Set up scene palette usage
+ _scene._scenePaletteUsage.clear();
+ _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF0));
+ _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF1));
+ _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF2));
+ _vm->_palette->_paletteUsage.load(&_scene._scenePaletteUsage);
+
+ if (!_player._spritesLoaded && _player._loadsFirst) {
+ if (_player.loadSprites(""))
+ _vm->quitGame();
+ _player._loadedFirst = true;
+ }
+
+ _scene.loadScene(_scene._nextSceneId, _aaName, 0);
+ _vm->_sound->pauseNewCommands();
+
+ if (!_player._spritesLoaded) {
+ if (_player.loadSprites(""))
+ _vm->quitGame();
+ _player._loadedFirst = false;
+ }
+
+ _vm->_events->initVars();
+ _scene._userInterface._highlightedCommandIndex = -1;
+ _scene._userInterface._highlightedInvIndex = -1;
+ _scene._userInterface._highlightedItemVocabIndex = -1;
+
+ _scene._action.clear();
+ _player.setFinalFacing();
+ _player._facing = _player._turnToFacing;
+ _player.cancelCommand();
+ _kernelMode = KERNEL_ROOM_INIT;
+
+ switch (_vm->_screenFade) {
+ case SCREEN_FADE_SMOOTH:
+ _fx = kTransitionFadeOutIn;
+ break;
+ case SCREEN_FADE_FAST:
+ _fx = kCenterVertTransition;
+ break;
+ default:
+ _fx = kTransitionNone;
+ break;
+ }
+
+ _trigger = 0;
+ _priorFrameTimer = _scene._frameStartTime;
+
+ // If in the middle of restoring a game, handle the rest of the loading
+ if (_saveFile != nullptr) {
+ Common::Serializer s(_saveFile, nullptr);
+ synchronize(s, false);
+ delete _saveFile;
+ _saveFile = nullptr;
+ }
+
+ // Call the scene logic for entering the given scene
+ _triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene._sceneLogic->enter();
+
+ // Set player data
+ _player._targetPos = _player._playerPos;
+ _player._turnToFacing = _player._facing;
+ _player._targetFacing = _player._facing;
+ _player.selectSeries();
+ _player.updateFrame();
+
+ _player._beenVisible = _player._visible;
+ _player._special = _scene.getDepthHighBits(_player._playerPos);
+ _player._priorTimer = _scene._frameStartTime - _player._ticksAmount;
+ _player.idle();
+
+ if (_scene._userInterface._selectedInvIndex >= 0) {
+ _scene._userInterface.loadInventoryAnim(
+ _objects._inventoryList[_scene._userInterface._selectedInvIndex]);
+ } else {
+ _scene._userInterface.noInventoryAnim();
+ }
+
+ _kernelMode = KERNEL_ACTIVE_CODE;
+ _scene._roomChanged = false;
+
+ if ((_quoteEmergency || _vocabEmergency) && !_anyEmergency) {
+ _scene._currentSceneId = _scene._priorSceneId;
+ _anyEmergency = true;
+ } else {
+ _anyEmergency = false;
+ _scene.loop();
+ }
+
+ _vm->_events->waitCursor();
+ _kernelMode = KERNEL_ROOM_PRELOAD;
+
+ delete _scene._activeAnimation;
+ _scene._activeAnimation = nullptr;
+
+ _scene._reloadSceneFlag = false;
+
+ _scene._userInterface.noInventoryAnim();
+ _scene.removeSprites();
+
+ if (!_player._loadedFirst) {
+ _player._spritesLoaded = false;
+ _player._spritesChanged = true;
+ }
+
+ // Clear the scene
+ _scene.freeCurrentScene();
+ _sectionNumber = _scene._nextSceneId / 100;
+
+ // Check whether to show a dialog
+ checkShowDialog();
+ }
+}
+
+void Game::initSection(int sectionNumber) {
+ _priorSectionNumber = _currentSectionNumber;
+ _currentSectionNumber = sectionNumber;
+
+ _vm->_palette->resetGamePalette(18, 10);
+ _vm->_palette->setLowRange();
+
+ if (_scene._layer == LAYER_GUI)
+ _vm->_palette->setPalette(_vm->_palette->_mainPalette, 0, 4);
+
+ _vm->_events->loadCursors("*CURSOR.SS");
+
+ assert(_vm->_events->_cursorSprites);
+ _vm->_events->setCursor2((_vm->_events->_cursorSprites->getCount() <= 1) ?
+ CURSOR_ARROW : CURSOR_WAIT);
+}
+
+void Game::loadQuotes() {
+ File f("*QUOTES.DAT");
+
+ Common::String msg;
+ while (true) {
+ uint8 b = f.readByte();
+
+ msg += b;
+ if (f.eos() || b == '\0') {
+ // end of string, add it to the strings list
+ _quotes.push_back(msg);
+ msg = "";
+ }
+
+ if (f.eos()) break;
+ }
+
+ f.close();
+}
+
+Common::StringArray Game::getMessage(uint32 id) {
+ File f("*MESSAGES.DAT");
+ int count = f.readUint16LE();
+
+ for (int idx = 0; idx < count; ++idx) {
+ uint32 itemId = f.readUint32LE();
+ uint32 offset = f.readUint32LE();
+ uint16 size = f.readUint16LE();
+
+ if (itemId == id) {
+ // Get the source buffer size
+ uint16 sizeIn;
+ if (idx == (count - 1)) {
+ sizeIn = f.size() - offset;
+ } else {
+ f.skip(4);
+ uint32 nextOffset = f.readUint32LE();
+ sizeIn = nextOffset - offset;
+ }
+
+ // Get the compressed data
+ f.seek(offset);
+ byte *bufferIn = new byte[sizeIn];
+ f.read(bufferIn, sizeIn);
+
+ // Decompress it
+ char *bufferOut = new char[size];
+ FabDecompressor fab;
+ fab.decompress(bufferIn, sizeIn, (byte *)bufferOut, size);
+
+ // Form the output string list
+ Common::StringArray result;
+ const char *p = bufferOut;
+ while (p < (bufferOut + size)) {
+ result.push_back(p);
+ p += strlen(p) + 1;
+ }
+
+ delete[] bufferIn;
+ delete[] bufferOut;
+ return result;
+ }
+ }
+
+ error("Invalid message Id specified");
+}
+
+static const char *const DEBUG_STRING = "WIDEPIPE";
+
+void Game::handleKeypress(const Common::Event &event) {
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ if (_widepipeCtr == 8) {
+ // Implement original game cheating keys here someday
+ } else {
+ if (event.kbd.keycode == (Common::KEYCODE_a +
+ (DEBUG_STRING[_widepipeCtr] - 'a'))) {
+ if (++_widepipeCtr == 8) {
+ MessageDialog *dlg = new MessageDialog(_vm, 2,
+ "CHEATING ENABLED", "(for your convenience).");
+ dlg->show();
+ delete dlg;
+ }
+ }
+ }
+ }
+
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_F1:
+ _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU;
+ break;
+ case Common::KEYCODE_F5:
+ _vm->_dialogs->_pendingDialog = DIALOG_SAVE;
+ break;
+ case Common::KEYCODE_F7:
+ _vm->_dialogs->_pendingDialog = DIALOG_RESTORE;
+ break;
+ default:
+ break;
+ }
+
+ warning("TODO: handleKeypress - %d", (int)event.kbd.keycode);
+}
+
+void Game::synchronize(Common::Serializer &s, bool phase1) {
+ if (phase1) {
+ s.syncAsSint16LE(_fx);
+ s.syncAsSint16LE(_trigger);
+ s.syncAsUint16LE(_triggerSetupMode);
+ s.syncAsUint16LE(_triggerMode);
+ s.syncString(_aaName);
+ s.syncAsSint16LE(_lastSave);
+
+ _scene.synchronize(s);
+ _objects.synchronize(s);
+ _visitedScenes.synchronize(s, _scene._nextSceneId);
+ _player.synchronize(s);
+ _screenObjects.synchronize(s);
+ } else {
+ // Load scene specific data for the loaded scene
+ _scene._sceneLogic->synchronize(s);
+ }
+}
+
+void Game::loadGame(int slotNumber) {
+ _saveFile = g_system->getSavefileManager()->openForLoading(
+ _vm->generateSaveName(slotNumber));
+
+ Common::Serializer s(_saveFile, nullptr);
+
+ // Load the savaegame header
+ MADSSavegameHeader header;
+ if (!readSavegameHeader(_saveFile, header))
+ error("Invalid savegame");
+
+ if (header._thumbnail) {
+ header._thumbnail->free();
+ delete header._thumbnail;
+ }
+
+ // Load most of the savegame data with the exception of scene specific info
+ synchronize(s, true);
+
+ // Set up section/scene and other initial states for post-load
+ _currentSectionNumber = -2;
+ _scene._currentSceneId = -2;
+ _sectionNumber = _scene._nextSceneId / 100;
+ _scene._frameStartTime = _vm->_events->getFrameCounter();
+ _vm->_screen._shakeCountdown = -1;
+
+ // Default the selected inventory item to the first one, if the player has any
+ _scene._userInterface._selectedInvIndex = _objects._inventoryList.size() > 0 ? 0 : -1;
+
+ // Set player sprites sets flags
+ _player._spritesLoaded = false;
+ _player._spritesChanged = true;
+}
+
+void Game::saveGame(int slotNumber, const Common::String &saveName) {
+ Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(
+ _vm->generateSaveName(slotNumber));
+
+ MADSSavegameHeader header;
+ header._saveName = saveName;
+ writeSavegameHeader(out, header);
+
+ Common::Serializer s(nullptr, out);
+ synchronize(s, true);
+ synchronize(s, false);
+
+ out->finalize();
+ delete out;
+}
+
+const char *const SAVEGAME_STR = "MADS";
+#define SAVEGAME_STR_SIZE 4
+
+bool Game::readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header) {
+ char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
+ header._thumbnail = nullptr;
+
+ // Validate the header Id
+ in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
+ if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE))
+ return false;
+
+ header._version = in->readByte();
+ if (header._version > MADS_SAVEGAME_VERSION)
+ return false;
+
+ // Read in the string
+ header._saveName.clear();
+ char ch;
+ while ((ch = (char)in->readByte()) != '\0') header._saveName += ch;
+
+ // Get the thumbnail
+ header._thumbnail = Graphics::loadThumbnail(*in);
+ if (!header._thumbnail)
+ return false;
+
+ // Read in save date/time
+ header._year = in->readSint16LE();
+ header._month = in->readSint16LE();
+ header._day = in->readSint16LE();
+ header._hour = in->readSint16LE();
+ header._minute = in->readSint16LE();
+ header._totalFrames = in->readUint32LE();
+
+ return true;
+}
+
+void Game::writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &header) {
+ // Write out a savegame header
+ out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1);
+
+ out->writeByte(MADS_SAVEGAME_VERSION);
+
+ // Write savegame name
+ out->write(header._saveName.c_str(), header._saveName.size());
+ out->writeByte('\0');
+
+ // Handle the thumbnail. If there's already one set by the game, create one
+ if (!_saveThumb)
+ createThumbnail();
+ Graphics::saveThumbnail(*out, *_saveThumb);
+
+ _saveThumb->free();
+ delete _saveThumb;
+ _saveThumb = nullptr;
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ out->writeSint16LE(td.tm_year + 1900);
+ out->writeSint16LE(td.tm_mon + 1);
+ out->writeSint16LE(td.tm_mday);
+ out->writeSint16LE(td.tm_hour);
+ out->writeSint16LE(td.tm_min);
+ out->writeUint32LE(_vm->_events->getFrameCounter());
+}
+
+void Game::createThumbnail() {
+ if (_saveThumb) {
+ _saveThumb->free();
+ delete _saveThumb;
+ }
+
+ uint8 thumbPalette[PALETTE_SIZE];
+ _vm->_palette->grabPalette(thumbPalette, 0, PALETTE_COUNT);
+ _saveThumb = new Graphics::Surface();
+ ::createThumbnail(_saveThumb, _vm->_screen.getData(), MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, thumbPalette);
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/game.h b/engines/mads/game.h
new file mode 100644
index 0000000000..1a61fc8ac8
--- /dev/null
+++ b/engines/mads/game.h
@@ -0,0 +1,239 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_GAME_H
+#define MADS_GAME_H
+
+#include "common/scummsys.h"
+#include "common/savefile.h"
+#include "common/str-array.h"
+#include "common/serializer.h"
+#include "mads/audio.h"
+#include "mads/scene.h"
+#include "mads/game_data.h"
+#include "mads/globals.h"
+#include "mads/inventory.h"
+#include "mads/player.h"
+#include "mads/screen.h"
+
+namespace MADS {
+
+class MADSEngine;
+
+enum KernelMode {
+ KERNEL_GAME_LOAD = 0, KERNEL_SECTION_PRELOAD = 1, KERNEL_SECTION_INIT = 2,
+ KERNEL_ROOM_PRELOAD = 3, KERNEL_ROOM_INIT = 4, KERNEL_ACTIVE_CODE = 5
+};
+
+#define MADS_SAVEGAME_VERSION 1
+
+struct MADSSavegameHeader {
+ uint8 _version;
+ Common::String _saveName;
+ Graphics::Surface *_thumbnail;
+ int _year, _month, _day;
+ int _hour, _minute;
+ int _totalFrames;
+};
+
+class Game {
+private:
+ /**
+ * Main game loop
+ */
+ void gameLoop();
+
+ /**
+ * Inner game loop for executing gameplay within a game section
+ */
+ void sectionLoop();
+
+ /**
+ * Load quotes data
+ */
+ void loadQuotes();
+protected:
+ MADSEngine *_vm;
+ MSurface *_surface;
+ int _statusFlag;
+ Common::StringArray _quotes;
+ bool _quoteEmergency;
+ bool _vocabEmergency;
+ bool _anyEmergency;
+ int _lastSave;
+ Common::String _saveName;
+ Common::InSaveFile *_saveFile;
+ Graphics::Surface *_saveThumb;
+
+ /**
+ * Constructor
+ */
+ Game(MADSEngine *vm);
+
+ /**
+ * Initializes the current section number of the game
+ */
+ void initSection(int sectionNumber);
+
+ //@{
+ /** @name Virtual Method list */
+
+ /**
+ * Perform any game-specifcic startup
+ */
+ virtual void startGame() = 0;
+
+ /**
+ * Initializes global variables for a new game
+ */
+ virtual void initializeGlobals() = 0;
+
+ /**
+ * Set up the section handler specific to each section
+ */
+ virtual void setSectionHandler() = 0;
+
+ /**
+ * Checks for whether to show a dialog
+ */
+ virtual void checkShowDialog() = 0;
+
+ //@}
+
+public:
+ static Game *init(MADSEngine *vm);
+
+public:
+ Player _player;
+ ScreenObjects _screenObjects;
+ int _sectionNumber;
+ int _priorSectionNumber;
+ int _currentSectionNumber;
+ InventoryObjects _objects;
+ SectionHandler *_sectionHandler;
+ VisitedScenes _visitedScenes;
+ Scene _scene;
+ KernelMode _kernelMode;
+ int _trigger;
+ ScreenTransition _fx;
+ TriggerMode _triggerMode;
+ TriggerMode _triggerSetupMode;
+ uint32 _priorFrameTimer;
+ Common::String _aaName;
+ int _winStatus;
+ int _widepipeCtr;
+ int _loadGameSlot;
+
+public:
+ virtual ~Game();
+
+ /**
+ * Main outer loop for the game
+ */
+ void run();
+
+ /**
+ * Return the number of quotes
+ */
+ uint32 getQuotesSize() { return _quotes.size(); }
+
+ /**
+ * Get a specific quote string
+ */
+ const Common::String &getQuote(uint32 index) { return _quotes[index - 1]; }
+
+ /**
+ * Split a quote into two lines for display on-screen
+ */
+ void splitQuote(const Common::String &source, Common::String &line1, Common::String &line2);
+
+ Common::StringArray getMessage(uint32 id);
+
+ /**
+ * Returns the globals for the game
+ */
+ virtual Globals &globals() = 0;
+
+ /**
+ * Standard object handling across the game
+ */
+ virtual void doObjectAction() = 0;
+
+ /**
+ * Fallback handler for any action that isn't explicitly handled
+ */
+ virtual void unhandledAction() = 0;
+
+ /**
+ * Global game step
+ */
+ virtual void step() = 0;
+
+ /**
+ * Synchronize the game data
+ * @param s Serializer
+ * @param phase1 If true, it's synchronizing the basic scene information
+ */
+ virtual void synchronize(Common::Serializer &s, bool phase1);
+
+ // DEPRECATED: ScummVM re-implementation keeps all the quotes loaded, so the methods below are stubs
+ void clearQuotes() {}
+ void loadQuoteRange(int startNum, int endNum) {}
+ void loadQuoteSet(...) {}
+ void loadQuote(int quoteNum) {}
+
+ /**
+ * Handle a keyboard event
+ */
+ void handleKeypress(const Common::Event &event);
+
+ /**
+ * Starts a savegame loading.
+ * @remarks Due to the way the engine is implemented, loading is done in two
+ * parts, the second part after the specific scene has been loaded
+ */
+ void loadGame(int slotNumber);
+
+ /**
+ * Save the current game
+ */
+ void saveGame(int slotNumber, const Common::String &saveName);
+
+ /**
+ * Write out a savegame header
+ */
+ void writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &header);
+
+ /**
+ * Read in a savegame header
+ */
+ static bool readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header);
+
+ /**
+ * Creates a temporary thumbnail for use in saving games
+ */
+ void createThumbnail();
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_GAME_H */
diff --git a/engines/mads/game_data.cpp b/engines/mads/game_data.cpp
new file mode 100644
index 0000000000..70e9e6c30b
--- /dev/null
+++ b/engines/mads/game_data.cpp
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/game.h"
+#include "mads/nebular/game_nebular.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/resources.h"
+
+namespace MADS {
+
+void VisitedScenes::add(int sceneId) {
+ _sceneRevisited = exists(sceneId);
+
+ if (!_sceneRevisited)
+ push_back(sceneId);
+}
+
+bool VisitedScenes::exists(int sceneId) {
+ for (uint i = 0; i < size(); ++i) {
+ if ((*this)[i] == sceneId)
+ return true;
+ }
+
+ return false;
+}
+
+void VisitedScenes::synchronize(Common::Serializer &s, int sceneId) {
+ SynchronizedList::synchronize(s);
+ s.syncAsByte(_sceneRevisited);
+
+ // If the scene hasn't been visited yet, remove it from the visited
+ // scenes list. It'll be readded to the list in add() above, from
+ // Game::sectionLoop()
+ if (s.isLoading() && !_sceneRevisited) {
+ for (uint i = 0; i < size(); ++i) {
+ if ((*this)[i] == sceneId) {
+ remove_at(i);
+ return;
+ }
+ }
+ }
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/game_data.h b/engines/mads/game_data.h
new file mode 100644
index 0000000000..65a9ae1553
--- /dev/null
+++ b/engines/mads/game_data.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_GAME_DATA_H
+#define MADS_GAME_DATA_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "mads/resources.h"
+
+namespace MADS {
+
+class MADSEngine;
+class Game;
+
+class VisitedScenes : public SynchronizedList {
+public:
+ /**
+ * Stores true when a previously visited scene is revisited
+ */
+ bool _sceneRevisited;
+
+ /**
+ * Returns true if a given Scene Id exists in the listed of previously visited scenes.
+ */
+ bool exists(int sceneId);
+
+ /**
+ * Adds a scene Id to the list of previously visited scenes, if it doesn't already exist
+ */
+ void add(int sceneId);
+
+ /**
+ * Synchronizes the list
+ */
+ void synchronize(Common::Serializer &s, int sceneId);
+};
+
+class SectionHandler {
+protected:
+ MADSEngine *_vm;
+public:
+ SectionHandler(MADSEngine *vm) : _vm(vm) {}
+ virtual ~SectionHandler() {}
+
+ virtual void preLoadSection() = 0;
+ virtual void sectionPtr2() = 0;
+ virtual void postLoadSection() = 0;
+ virtual void step() {}
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_GAME_DATA_H */
diff --git a/engines/mads/globals.cpp b/engines/mads/globals.cpp
new file mode 100644
index 0000000000..1d088992ea
--- /dev/null
+++ b/engines/mads/globals.cpp
@@ -0,0 +1,33 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/globals.h"
+
+namespace MADS {
+
+void Globals::reset() {
+ for (uint i = 0; i < size(); ++i)
+ (*this)[i] = 0;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/globals.h b/engines/mads/globals.h
new file mode 100644
index 0000000000..a6c9b628dd
--- /dev/null
+++ b/engines/mads/globals.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_GLOBALS_H
+#define MADS_GLOBALS_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/serializer.h"
+#include "mads/resources.h"
+
+namespace MADS {
+
+class Globals : public SynchronizedList {
+public:
+ Globals() {}
+
+ virtual ~Globals() {}
+
+ /*
+ * Resets all the globals to empty
+ */
+ void reset();
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_GLOBALS_H */
diff --git a/engines/mads/hotspots.cpp b/engines/mads/hotspots.cpp
new file mode 100644
index 0000000000..d75d7ae13e
--- /dev/null
+++ b/engines/mads/hotspots.cpp
@@ -0,0 +1,216 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "mads/mads.h"
+#include "mads/hotspots.h"
+
+namespace MADS {
+
+DynamicHotspot::DynamicHotspot() {
+ _seqIndex = 0;
+ _facing = FACING_NONE;
+ _descId = 0;
+ _verbId = 0;
+ _articleNumber = 0;
+ _cursor = CURSOR_NONE;
+ _active = false;
+}
+
+void DynamicHotspot::synchronize(Common::Serializer &s) {
+
+}
+
+/*------------------------------------------------------------------------*/
+
+DynamicHotspots::DynamicHotspots(MADSEngine *vm) : _vm(vm) {
+ for (int i = 0; i < DYNAMIC_HOTSPOTS_SIZE; ++i) {
+ DynamicHotspot rec;
+ rec._active = false;
+ _entries.push_back(rec);
+ }
+
+ _changed = true;
+ _count = 0;
+}
+
+int DynamicHotspots::add(int descId, int verbId, int seqIndex, const Common::Rect &bounds) {
+ // Find a free slot
+ uint idx = 0;
+ while ((idx < _entries.size()) && _entries[idx]._active)
+ ++idx;
+ if (idx == _entries.size())
+ error("DynamicHotspots overflow");
+
+ _entries[idx]._active = true;
+ _entries[idx]._descId = descId;
+ _entries[idx]._seqIndex = seqIndex;
+ _entries[idx]._bounds = bounds;
+ _entries[idx]._feetPos = Common::Point(-3, 0);
+ _entries[idx]._facing = FACING_NONE;
+ _entries[idx]._verbId = verbId;
+ _entries[idx]._articleNumber = PREP_IN;
+ _entries[idx]._cursor = CURSOR_NONE;
+
+ ++_count;
+ _changed = true;
+
+ if (seqIndex >= 0)
+ _vm->_game->_scene._sequences[seqIndex]._dynamicHotspotIndex = idx;
+
+ return idx;
+}
+
+int DynamicHotspots::setPosition(int index, const Common::Point &pos, Facing facing) {
+ if (index >= 0) {
+ _entries[index]._feetPos = pos;
+ _entries[index]._facing = facing;
+ }
+
+ return index;
+}
+
+int DynamicHotspots::setCursor(int index, CursorType cursor) {
+ if (index >= 0)
+ _entries[index]._cursor = cursor;
+
+ return index;
+}
+
+void DynamicHotspots::remove(int index) {
+ Scene &scene = _vm->_game->_scene;
+
+ if (index >= 0 && _entries[index]._active) {
+ if (_entries[index]._seqIndex >= 0)
+ scene._sequences[_entries[index]._seqIndex]._dynamicHotspotIndex = -1;
+ _entries[index]._active = false;
+
+ --_count;
+ _changed = true;
+ }
+}
+
+void DynamicHotspots::clear() {
+ for (uint i = 0; i < _entries.size(); ++i)
+ _entries[i]._active = false;
+
+ _changed = false;
+ _count = 0;
+}
+
+void DynamicHotspots::reset() {
+ for (uint i = 0; i < _entries.size(); ++i)
+ remove(i);
+
+ _count = 0;
+ _changed = false;
+}
+
+void DynamicHotspots::refresh() {
+ // Reset the screen objects back to only contain UI elements
+ ScreenObjects &scrObjects = _vm->_game->_screenObjects;
+ scrObjects.resize(scrObjects._uiCount);
+
+ // Loop through adding hotspots
+ for (uint i = 0; i < _entries.size(); ++i) {
+ DynamicHotspot &dh = (*this)[i];
+
+ if ((*this)[i]._active) {
+ switch (scrObjects._inputMode) {
+ case kInputBuildingSentences:
+ case kInputLimitedSentences:
+ scrObjects.add(dh._bounds, _vm->_game->_scene._layer, CAT_12, dh._descId);
+ scrObjects._forceRescan = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Reset the list's changed flag
+ _changed = false;
+}
+
+DynamicHotspot &DynamicHotspots::get(int index) {
+ for (uint i = 0; i < _entries.size(); ++i) {
+ if (_entries[i]._active && index-- == 0)
+ return _entries[i];
+ }
+
+ error("Could not find dynamic hotspot");
+}
+
+void DynamicHotspots::synchronize(Common::Serializer &s) {
+ int count = _entries.size();
+ s.syncAsSint16LE(count);
+
+ // The MIN in the below loop is a workaround to fix earlier savegame
+ // loading accidentally adding new dynamic hotspots to the fixed list
+ for (int i = 0; i < count; ++i) {
+ _entries[MIN(i, (int)_entries.size() - 1)].synchronize(s);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Hotspot::Hotspot() {
+ _facing = FACING_NONE;
+ _articleNumber = 0;
+ _cursor = CURSOR_NONE;
+ _vocabId = 0;
+ _verbId = 0;
+ _active = false;
+}
+
+Hotspot::Hotspot(Common::SeekableReadStream &f, bool isV2) {
+ _bounds.left = f.readSint16LE();
+ _bounds.top = f.readSint16LE();
+ _bounds.right = f.readSint16LE();
+ _bounds.bottom = f.readSint16LE();
+ _feetPos.x = f.readSint16LE();
+ _feetPos.y = f.readSint16LE();
+ _facing = (Facing)f.readByte();
+ _articleNumber = f.readByte();
+ _active = f.readByte() != 0;
+ _cursor = (CursorType)f.readByte();
+ if (isV2) {
+ // This looks to be some sort of bitmask. Perhaps it signifies
+ // the valid verbs for this hotspot
+ f.skip(2); // unknown
+ }
+ _vocabId = f.readUint16LE();
+ _verbId = f.readUint16LE();
+}
+
+/*------------------------------------------------------------------------*/
+
+void Hotspots::activate(int vocabId, bool active) {
+ for (uint idx = 0; idx < size(); ++idx) {
+ Hotspot &hotspot = (*this)[idx];
+ if (hotspot._vocabId == vocabId) {
+ hotspot._active = active;
+ _vm->_game->_screenObjects.setActive(CAT_HOTSPOT, idx, active);
+ }
+ }
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/hotspots.h b/engines/mads/hotspots.h
new file mode 100644
index 0000000000..f9334eace8
--- /dev/null
+++ b/engines/mads/hotspots.h
@@ -0,0 +1,120 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_HOTSPOTS_H
+#define MADS_HOTSPOTS_H
+
+#include "common/scummsys.h"
+#include "mads/events.h"
+#include "mads/player.h"
+
+namespace MADS {
+
+class MADSEngine;
+
+class DynamicHotspot {
+public:
+ bool _active;
+ int _seqIndex;
+ Common::Rect _bounds;
+ Common::Point _feetPos;
+ Facing _facing;
+ int _descId;
+ int _verbId;
+ int _articleNumber;
+ CursorType _cursor;
+
+ /**
+ * Constructor
+ */
+ DynamicHotspot();
+
+ /**
+ * Synchronize the data
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+#define DYNAMIC_HOTSPOTS_SIZE 8
+
+class DynamicHotspots {
+private:
+ MADSEngine *_vm;
+ Common::Array<DynamicHotspot> _entries;
+ int _count;
+public:
+ bool _changed;
+public:
+ DynamicHotspots(MADSEngine *vm);
+
+ Common::Array<MADS::DynamicHotspot>::size_type size() const { return _entries.size(); }
+ DynamicHotspot &operator[](uint idx) { return _entries[idx]; }
+ int add(int descId, int verbId, int seqIndex, const Common::Rect &bounds);
+ int setPosition(int index, const Common::Point &pos, Facing facing);
+ int setCursor(int index, CursorType cursor);
+ void remove(int index);
+ void clear();
+ void reset();
+ void refresh();
+
+ /**
+ * Get an active dynamic hotspot
+ * @param index Active index
+ */
+ DynamicHotspot &get(int index);
+
+ /**
+ * Synchronize the data
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+class Hotspot {
+public:
+ Common::Rect _bounds;
+ Common::Point _feetPos;
+ Facing _facing;
+ int _articleNumber;
+ bool _active;
+ CursorType _cursor;
+ int _vocabId;
+ int _verbId;
+
+ Hotspot();
+ Hotspot(Common::SeekableReadStream &f, bool isV2);
+};
+
+class Hotspots : public Common::Array<Hotspot> {
+private:
+ MADSEngine *_vm;
+public:
+ Hotspots(MADSEngine *vm) : _vm(vm) {}
+
+ /**
+ * Sets the active state of a given hotspot
+ */
+ void activate(int vocabId, bool active);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_HOTSPOTS_H */
diff --git a/engines/mads/inventory.cpp b/engines/mads/inventory.cpp
new file mode 100644
index 0000000000..ca05575ec5
--- /dev/null
+++ b/engines/mads/inventory.cpp
@@ -0,0 +1,225 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/inventory.h"
+
+namespace MADS {
+
+void InventoryObject::synchronize(Common::Serializer &s) {
+ s.syncAsUint16LE(_descId);
+ s.syncAsUint16LE(_roomNumber);
+ s.syncAsByte(_article);
+ s.syncAsByte(_vocabCount);
+ s.syncAsByte(_qualitiesCount);
+ s.skip(1);
+
+ for (int i = 0; i < MAX_VOCAB; ++i) {
+ s.syncAsUint16LE(_vocabList[i]._vocabId);
+ s.syncAsByte(_vocabList[i]._verbType);
+ s.syncAsByte(_vocabList[i]._prepType);
+ }
+
+ for (int i = 0; i < MAX_QUALITIES; ++i)
+ s.syncAsByte(_qualityId[i]);
+ for (int i = 0; i < MAX_QUALITIES; ++i)
+ s.syncAsSint32LE(_qualityValue[i]);
+}
+
+bool InventoryObject::hasQuality(int qualityId) const {
+ for (int i = 0; i < _qualitiesCount; ++i) {
+ if (_qualityId[i] == qualityId)
+ return true;
+ }
+
+ return false;
+}
+
+void InventoryObject::setQuality(int qualityId, int qualityValue) {
+ for (int i = 0; i < _qualitiesCount; ++i) {
+ if (_qualityId[i] == qualityId) {
+ _qualityValue[i] = qualityValue;
+ }
+ }
+}
+
+int InventoryObject::getQuality(int qualityId) const {
+ for (int i = 0; i < _qualitiesCount; ++i) {
+ if (_qualityId[i] == qualityId) {
+ return _qualityValue[i];
+ }
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+void InventoryObjects::load() {
+ File f("*OBJECTS.DAT");
+ int count = f.readUint16LE();
+ Common::Serializer s(&f, nullptr);
+
+ // Load the objects data
+ reserve(count);
+ for (int i = 0; i < count; ++i) {
+ InventoryObject obj;
+ obj.synchronize(s);
+ push_back(obj);
+
+ // If it's for the player's inventory, add the index to the inventory list
+ if (obj._roomNumber == PLAYER_INVENTORY) {
+ _inventoryList.push_back(i);
+ assert(_inventoryList.size() <= 32);
+ }
+ }
+}
+
+void InventoryObjects::synchronize(Common::Serializer &s) {
+ int count = size();
+ s.syncAsUint16LE(count);
+
+ if (s.isSaving()) {
+ // Store the data for each object in the inventory lsit
+ for (int idx = 0; idx < count; ++idx)
+ (*this)[idx].synchronize(s);
+
+ // Synchronize the player's inventory
+ _inventoryList.synchronize(s);
+ } else {
+ clear();
+
+ // Read in each object
+ reserve(count);
+ for (int i = 0; i < count; ++i) {
+ InventoryObject obj;
+ obj.synchronize(s);
+ push_back(obj);
+ }
+
+ // Synchronize the player's inventory
+ _inventoryList.synchronize(s);
+ }
+}
+
+void InventoryObjects::setRoom(int objectId, int sceneNumber) {
+ InventoryObject &obj = (*this)[objectId];
+
+ if (obj._roomNumber == PLAYER_INVENTORY)
+ removeFromInventory(objectId, 1);
+
+ if (sceneNumber == PLAYER_INVENTORY)
+ addToInventory(objectId);
+ else
+ obj._roomNumber = sceneNumber;
+}
+
+bool InventoryObjects::isInRoom(int objectId) const {
+ return objectId >= 0 && (*this)[objectId]._roomNumber == _vm->_game->_scene._currentSceneId;
+}
+
+bool InventoryObjects::isInInventory(int objectId) const {
+ return objectId >= 0 && (*this)[objectId]._roomNumber == PLAYER_INVENTORY;
+}
+
+void InventoryObjects::addToInventory(int objectId) {
+ assert(_inventoryList.size() < 32);
+ UserInterface &userInterface = _vm->_game->_scene._userInterface;
+
+ if (!isInInventory(objectId)) {
+ _inventoryList.push_back(objectId);
+ userInterface._selectedInvIndex = _inventoryList.size() - 1;
+ userInterface._inventoryTopIndex = CLIP(userInterface._inventoryTopIndex,
+ 0, userInterface._selectedInvIndex);
+
+ if ((userInterface._inventoryTopIndex + 5) <= (int)_inventoryList.size())
+ userInterface._inventoryTopIndex = _inventoryList.size() - 5;
+ userInterface._inventoryChanged = true;
+
+ (*this)[objectId]._roomNumber = PLAYER_INVENTORY;
+
+ if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE &&
+ _vm->_game->_screenObjects._inputMode == kInputBuildingSentences) {
+ userInterface.categoryChanged();
+ userInterface.selectObject(userInterface._selectedInvIndex);
+ }
+ }
+}
+
+void InventoryObjects::removeFromInventory(int objectId, int newScene) {
+ Scene &scene = _vm->_game->_scene;
+ UserInterface &userInterface = scene._userInterface;
+
+ // Scan the inventory list for the object
+ int invIndex = -1;
+ for (int idx = 0; idx < (int)_inventoryList.size() && invIndex == -1; ++idx) {
+ if (_inventoryList[idx] == objectId)
+ invIndex = idx;
+ }
+
+ // If the object isn't in the player's inventory, stop here
+ if (invIndex < 0)
+ return;
+
+ int selectedIndex = userInterface._selectedInvIndex;
+ bool noSelection = selectedIndex < 0;
+
+ if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE &&
+ _vm->_game->_screenObjects._inputMode == kInputBuildingSentences)
+ userInterface.selectObject(-1);
+
+ // Remove the item from the inventory list
+ _inventoryList.remove_at(invIndex);
+
+ if (!noSelection) {
+ if (selectedIndex >= invIndex)
+ --selectedIndex;
+ if (selectedIndex < 0 && _inventoryList.size() > 0)
+ selectedIndex = 0;
+ }
+
+ if (invIndex <= userInterface._inventoryTopIndex) {
+ userInterface._inventoryTopIndex = MAX(userInterface._inventoryTopIndex, 0);
+ }
+
+ userInterface._inventoryChanged = true;
+ (*this)[objectId]._roomNumber = newScene;
+
+ if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE &&
+ _vm->_game->_screenObjects._inputMode == kInputBuildingSentences) {
+ userInterface.categoryChanged();
+ userInterface.selectObject(selectedIndex);
+ }
+}
+
+int InventoryObjects::getIdFromDesc(int descId) {
+ for (int i = 0; i < (int)size(); ++i) {
+ InventoryObject &obj = (*this)[i];
+ if (obj._descId == descId)
+ return i;
+ }
+
+ return -1;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/inventory.h b/engines/mads/inventory.h
new file mode 100644
index 0000000000..cf82de59f1
--- /dev/null
+++ b/engines/mads/inventory.h
@@ -0,0 +1,141 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_INVENTORY_H
+#define MADS_INVENTORY_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/serializer.h"
+
+namespace MADS {
+
+enum {
+ PLAYER_INVENTORY = 2, NOWHERE = 1
+};
+
+class MADSEngine;
+
+#define MAX_VOCAB 5
+#define MAX_QUALITIES 4
+
+class InventoryObject {
+public:
+ int _descId;
+ int _roomNumber;
+ int _article;
+ int _vocabCount;
+ int _qualitiesCount;
+ int syntax;
+
+ struct {
+ int _vocabId;
+ VerbType _verbType;
+ PrepType _prepType;
+ } _vocabList[MAX_VOCAB];
+
+ int _qualityId[MAX_QUALITIES];
+ int _qualityValue[MAX_QUALITIES];
+
+ /**
+ * Synchronizes the data for a given object
+ */
+ void synchronize(Common::Serializer &s);
+
+ /**
+ * Returns true if the given object has the specified quality
+ */
+ bool hasQuality(int qualityId) const;
+
+ /**
+ * Sets the quality value for a given quality Id
+ */
+ void setQuality(int qualityId, int qualityValue);
+
+ /**
+ * Gets the quality value for a given quality Id
+ */
+ int getQuality(int qualityId) const;
+};
+
+class InventoryObjects : public Common::Array<InventoryObject> {
+private:
+ MADSEngine *_vm;
+
+public:
+ SynchronizedList _inventoryList;
+
+ /**
+ * Constructor
+ */
+ InventoryObjects(MADSEngine *vm) : _vm(vm) {}
+
+ /**
+ * Loads the game's object list
+ */
+ void load();
+
+ /**
+ * Synchronize the objects list in a savegame
+ */
+ void synchronize(Common::Serializer &s);
+
+ /**
+ * Returns the inventory item from the player's inventory
+ */
+ InventoryObject &getItem(int itemIndex) {
+ return (*this)[_inventoryList[itemIndex]];
+ }
+
+ /**
+ * Sets an item's scene number
+ */
+ void setRoom(int objectId, int sceneNumber);
+
+ /**
+ * Returns true if a given object is in the player's current scene
+ */
+ bool isInRoom(int objectId) const;
+
+ /**
+ * Returns true if a given object is in the player's inventory
+ */
+ bool isInInventory(int objectId) const;
+
+ /**
+ * Removes the specified object from the player's inventory
+ */
+ void addToInventory(int objectId);
+
+ /**
+ * Removes the specified object to the player's inventory
+ * @param objectId Object to remove
+ * @param newScene Specifies the new scene to set the item to
+ */
+ void removeFromInventory(int objectId, int newScene);
+
+ int getIdFromDesc(int objectId);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_INVENTORY_H */
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
new file mode 100644
index 0000000000..d56994ab8e
--- /dev/null
+++ b/engines/mads/mads.cpp
@@ -0,0 +1,162 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "engines/util.h"
+#include "mads/mads.h"
+#include "mads/game.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/resources.h"
+#include "mads/sound.h"
+#include "mads/sprites.h"
+
+namespace MADS {
+
+MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) :
+ _gameDescription(gameDesc), Engine(syst), _randomSource("MADS") {
+
+ // Initialize fields
+ _easyMouse = true;
+ _invObjectsAnimated = true;
+ _textWindowStill = false;
+ _screenFade = SCREEN_FADE_SMOOTH;
+ _musicFlag = true;
+ _dithering = false;
+
+ _debugger = nullptr;
+ _dialogs = nullptr;
+ _events = nullptr;
+ _font = nullptr;
+ _game = nullptr;
+ _palette = nullptr;
+ _resources = nullptr;
+ _sound = nullptr;
+ _audio = nullptr;
+ _opl = nullptr;
+}
+
+MADSEngine::~MADSEngine() {
+ delete _debugger;
+ delete _dialogs;
+ delete _events;
+ delete _font;
+ Font::deinit();
+ delete _game;
+ delete _palette;
+ delete _resources;
+ delete _sound;
+ delete _audio;
+
+ _mixer->stopAll();
+ delete _opl;
+}
+
+void MADSEngine::initialize() {
+ // Set up debug channels
+ DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level");
+ DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts");
+ DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling");
+
+ _opl = OPL::Config::create();
+ _opl->init(11025);
+
+ // Initial sub-system engine references
+ MSurface::setVm(this);
+ MSprite::setVm(this);
+
+ Resources::init(this);
+ Conversation::init(this);
+ _debugger = new Debugger(this);
+ _dialogs = Dialogs::init(this);
+ _events = new EventsManager(this);
+ _palette = new Palette(this);
+ Font::init(this);
+ _font = new Font();
+ _screen.init();
+ _sound = new SoundManager(this, _mixer, _opl);
+ _audio = new AudioPlayer(_mixer, getGameID());
+ _game = Game::init(this);
+
+ _screen.empty();
+}
+
+Common::Error MADSEngine::run() {
+ initGraphics(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, false);
+ initialize();
+
+ // Run the game
+ _game->run();
+
+ return Common::kNoError;
+}
+
+int MADSEngine::getRandomNumber(int maxNumber) {
+ return _randomSource.getRandomNumber(maxNumber);
+}
+
+int MADSEngine::getRandomNumber(int minNumber, int maxNumber) {
+ int range = maxNumber - minNumber;
+
+ return minNumber + _randomSource.getRandomNumber(range);
+}
+
+int MADSEngine::hypotenuse(int xv, int yv) {
+ return (int)sqrt((double)(xv * xv + yv * yv));
+}
+
+bool MADSEngine::canLoadGameStateCurrently() {
+ return !_game->_winStatus && !_game->globals()[5]
+ && _dialogs->_pendingDialog == DIALOG_NONE
+ && _events->_cursorId != CURSOR_WAIT;
+}
+
+bool MADSEngine::canSaveGameStateCurrently() {
+ return !_game->_winStatus && !_game->globals()[5]
+ && _dialogs->_pendingDialog == DIALOG_NONE
+ && _events->_cursorId != CURSOR_WAIT;
+}
+
+/**
+* Support method that generates a savegame name
+* @param slot Slot number
+*/
+Common::String MADSEngine::generateSaveName(int slot) {
+ return Common::String::format("%s.%03d", _targetName.c_str(), slot);
+}
+
+Common::Error MADSEngine::loadGameState(int slot) {
+ _game->_loadGameSlot = slot;
+ _game->_scene._currentSceneId = -1;
+ _game->_currentSectionNumber = -1;
+ return Common::kNoError;
+}
+
+Common::Error MADSEngine::saveGameState(int slot, const Common::String &desc) {
+ _game->saveGame(slot, desc);
+ return Common::kNoError;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/mads.h b/engines/mads/mads.h
new file mode 100644
index 0000000000..8fc2788c28
--- /dev/null
+++ b/engines/mads/mads.h
@@ -0,0 +1,153 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_MADS_H
+#define MADS_MADS_H
+
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/error.h"
+#include "common/random.h"
+#include "common/util.h"
+#include "engines/engine.h"
+#include "graphics/surface.h"
+#include "mads/debugger.h"
+#include "mads/dialogs.h"
+#include "mads/events.h"
+#include "mads/font.h"
+#include "mads/game.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/resources.h"
+#include "mads/sound.h"
+
+/**
+ * This is the namespace of the MADS engine.
+ *
+ * Status of this engine: In Development
+ *
+ * Games using this engine:
+ * - Rex Nebular and the Cosmic Gender Bender
+ */
+namespace MADS {
+
+#define DEBUG_BASIC 1
+#define DEBUG_INTERMEDIATE 2
+#define DEBUG_DETAILED 3
+
+enum MADSDebugChannels {
+ kDebugPath = 1 << 0,
+ kDebugScripts = 1 << 1,
+ kDebugGraphics = 1 << 2
+};
+
+enum {
+ GType_RexNebular = 0,
+ GType_Dragonsphere = 1,
+ GType_Phantom = 2
+};
+
+enum ScreenFade {
+ SCREEN_FADE_SMOOTH = 0,
+ SCREEN_FADE_MEDIUM = 1,
+ SCREEN_FADE_FAST = 2
+};
+
+struct MADSGameDescription;
+
+
+class MADSEngine : public Engine {
+private:
+ const MADSGameDescription *_gameDescription;
+ Common::RandomSource _randomSource;
+
+ /**
+ * Handles basic initialisation
+ */
+ void initialize();
+protected:
+ // Engine APIs
+ virtual Common::Error run();
+ virtual bool hasFeature(EngineFeature f) const;
+public:
+ Debugger *_debugger;
+ Dialogs *_dialogs;
+ EventsManager *_events;
+ Font *_font;
+ Game *_game;
+ Palette *_palette;
+ Resources *_resources;
+ ScreenSurface _screen;
+ SoundManager *_sound;
+ AudioPlayer *_audio;
+ FM_OPL *_opl;
+ bool _easyMouse;
+ bool _invObjectsAnimated;
+ bool _textWindowStill;
+ ScreenFade _screenFade;
+ bool _musicFlag;
+ bool _dithering;
+public:
+ MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc);
+ virtual ~MADSEngine();
+
+ uint32 getFeatures() const;
+ Common::Language getLanguage() const;
+ Common::Platform getPlatform() const;
+ uint16 getVersion() const;
+ uint32 getGameID() const;
+ uint32 getGameFeatures() const;
+
+ int getRandomNumber(int maxNumber);
+ int getRandomNumber(int minNumber, int maxNumber);
+ int hypotenuse(int xv, int yv);
+
+ /**
+ * Returns true if it is currently okay to restore a game
+ */
+ bool canLoadGameStateCurrently();
+
+ /**
+ * Returns true if it is currently okay to save the game
+ */
+ bool canSaveGameStateCurrently();
+
+ /**
+ * Support method that generates a savegame name
+ * @param slot Slot number
+ */
+ Common::String generateSaveName(int slot);
+
+ /**
+ * Handles loading a game via the GMM
+ */
+ virtual Common::Error loadGameState(int slot);
+
+ /**
+ * Handles saving the game via the GMM
+ */
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_MADS_H */
diff --git a/engines/mads/messages.cpp b/engines/mads/messages.cpp
new file mode 100644
index 0000000000..e83b69d210
--- /dev/null
+++ b/engines/mads/messages.cpp
@@ -0,0 +1,569 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/font.h"
+#include "mads/screen.h"
+#include "mads/messages.h"
+#include "mads/scene_data.h"
+
+namespace MADS {
+
+RandomMessages::RandomMessages() {
+ reserve(RANDOM_MESSAGE_SIZE);
+ _randomSpacing = 0;
+ _color = -1;
+ _duration = 0;
+ _scrollRate = -1;
+}
+
+void RandomMessages::reset() {
+ for (uint i = 0; i < size(); ++i) {
+ (*this)[i]._handle = -1;
+ (*this)[i]._quoteId = -1;
+ }
+}
+
+
+KernelMessages::KernelMessages(MADSEngine *vm)
+ : _vm(vm) {
+ for (int i = 0; i < KERNEL_MESSAGES_SIZE; ++i) {
+ KernelMessage rec;
+ _entries.push_back(rec);
+ }
+
+ _talkFont = _vm->_font->getFont(FONT_CONVERSATION);
+}
+
+KernelMessages::~KernelMessages() {
+}
+
+void KernelMessages::clear() {
+ Scene &scene = _vm->_game->_scene;
+
+ for (uint i = 0; i < _entries.size(); ++i)
+ _entries[i]._flags = 0;
+
+ _talkFont = _vm->_font->getFont(FONT_CONVERSATION);
+ scene._textSpacing = -1;
+}
+
+int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags,
+ uint8 abortTimers, uint32 timeout, const Common::String &msg) {
+ Scene &scene = _vm->_game->_scene;
+
+ // Find a free slot
+ uint idx = 0;
+ while ((idx < _entries.size()) && ((_entries[idx]._flags & KMSG_ACTIVE) != 0))
+ ++idx;
+ if (idx == _entries.size()) {
+ if (abortTimers == 0)
+ return -1;
+
+ error("KernelMessages overflow");
+ }
+
+ KernelMessage &rec = _entries[idx];
+ rec._msg = msg;
+ rec._flags = flags | KMSG_ACTIVE;
+ rec._color1 = fontColor & 0xff;
+ rec._color2 = fontColor >> 8;
+ rec._position = pt;
+ rec._textDisplayIndex = -1;
+ rec._timeout = timeout;
+ rec._frameTimer = _vm->_game->_priorFrameTimer;
+ rec._trigger = abortTimers;
+ rec._abortMode = _vm->_game->_triggerSetupMode;
+
+ rec._actionDetails = scene._action._activeAction;
+
+ if (flags & KMSG_PLAYER_TIMEOUT)
+ rec._frameTimer = _vm->_game->_player._ticksAmount +
+ _vm->_game->_player._priorTimer;
+
+ return idx;
+}
+
+int KernelMessages::addQuote(int quoteId, int abortTimers, uint32 timeout) {
+ Common::String quoteStr = _vm->_game->getQuote(quoteId);
+ return add(Common::Point(), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN,
+ abortTimers, timeout, quoteStr);
+}
+
+void KernelMessages::scrollMessage(int msgIndex, int numTicks, bool quoted) {
+ if (msgIndex < 0)
+ return;
+
+ _entries[msgIndex]._flags |= quoted ? (KMSG_SCROLL | KMSG_QUOTED) : KMSG_SCROLL;
+ _entries[msgIndex]._msgOffset = 0;
+ _entries[msgIndex]._numTicks = numTicks;
+ _entries[msgIndex]._frameTimer2 = _vm->_game->_priorFrameTimer;
+
+ Common::String msg = _entries[msgIndex]._msg;
+
+ if (_entries[msgIndex]._flags & KMSG_PLAYER_TIMEOUT)
+ _entries[msgIndex]._frameTimer2 = _vm->_game->_player._ticksAmount +
+ _vm->_game->_player._priorTimer;
+
+ _entries[msgIndex]._frameTimer = _entries[msgIndex]._frameTimer2;
+}
+
+void KernelMessages::setSeqIndex(int msgIndex, int seqIndex) {
+ if (msgIndex >= 0) {
+ _entries[msgIndex]._flags |= KMSG_SEQ_ENTRY;
+ _entries[msgIndex]._sequenceIndex = seqIndex;
+ }
+}
+
+void KernelMessages::remove(int msgIndex) {
+ KernelMessage &rec = _entries[msgIndex];
+ Scene &scene = _vm->_game->_scene;
+
+ if (rec._flags & KMSG_ACTIVE) {
+ if (rec._flags & KMSG_SCROLL) {
+ // WORKAROUND: Code here no longer needed in ScummVM
+ }
+
+ if (rec._textDisplayIndex >= 0)
+ scene._textDisplay.expire(rec._textDisplayIndex);
+
+ rec._flags &= ~KMSG_ACTIVE;
+ }
+}
+
+void KernelMessages::reset() {
+ for (uint i = 0; i < _entries.size(); ++i)
+ remove(i);
+
+ _randomMessages.clear();
+}
+
+void KernelMessages::update() {
+ uint32 currentTimer = _vm->_game->_scene._frameStartTime;
+
+ for (uint i = 0; i < _entries.size() && !_vm->_game->_trigger; ++i) {
+ KernelMessage &msg = _entries[i];
+
+ if (((msg._flags & KMSG_ACTIVE) != 0) && (currentTimer >= msg._frameTimer))
+ processText(i);
+ }
+}
+
+void KernelMessages::processText(int msgIndex) {
+ Scene &scene = _vm->_game->_scene;
+ KernelMessage &msg = _entries[msgIndex];
+ uint32 currentTimer = _vm->_game->_priorFrameTimer;
+ bool flag = false;
+
+ if ((msg._flags & KMSG_EXPIRE) != 0) {
+ scene._textDisplay.expire(msg._textDisplayIndex);
+ msg._flags &= ~KMSG_ACTIVE;
+ return;
+ }
+
+ if ((msg._flags & KMSG_SCROLL) == 0) {
+ msg._timeout -= 3;
+ }
+
+ if (msg._flags & KMSG_SEQ_ENTRY) {
+ SequenceEntry &seqEntry = scene._sequences[msg._sequenceIndex];
+ if (seqEntry._doneFlag || !seqEntry._active)
+ msg._timeout = 0;
+ }
+
+ if ((msg._timeout <= 0) && (_vm->_game->_trigger == 0)) {
+ msg._flags |= KMSG_EXPIRE;
+ if (msg._trigger != 0) {
+ _vm->_game->_trigger = msg._trigger;
+ _vm->_game->_triggerMode = msg._abortMode;
+
+ if (_vm->_game->_triggerMode != SEQUENCE_TRIGGER_DAEMON) {
+ scene._action._activeAction = msg._actionDetails;
+ }
+ }
+ }
+
+ msg._frameTimer = currentTimer + 3;
+ int x1 = 0, y1 = 0;
+
+ if (msg._flags & KMSG_SEQ_ENTRY) {
+ SequenceEntry &seqEntry = scene._sequences[msg._sequenceIndex];
+ if (!seqEntry._nonFixed) {
+ SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex];
+ MSprite *frame = spriteSet.getFrame(seqEntry._frameIndex - 1);
+ x1 = frame->getBounds().left;
+ y1 = frame->getBounds().top;
+ } else {
+ x1 = seqEntry._position.x;
+ y1 = seqEntry._position.y;
+ }
+ }
+
+ Player &player = _vm->_game->_player;
+ if (msg._flags & KMSG_PLAYER_TIMEOUT) {
+ if (player._beenVisible) {
+ SpriteAsset &asset = *_vm->_game->_scene._sprites[player._spritesStart + player._spritesIdx];
+ MSprite *frame = asset.getFrame(player._frameNumber - 1);
+
+ int yAmount = player._currentScale * player._centerOfGravity / 100;
+ x1 = player._playerPos.x;
+ y1 = (frame->h * player._currentScale / -100) + yAmount +
+ player._playerPos.y - 15;
+ } else {
+ x1 = 160;
+ y1 = 78;
+ }
+ }
+
+ x1 += msg._position.x;
+ y1 += msg._position.y;
+
+ Common::String displayMsg = msg._msg;
+
+ if ((msg._flags & KMSG_SCROLL) && (msg._frameTimer >= currentTimer)) {
+ ++msg._msgOffset;
+
+ if (msg._msgOffset >= msg._msg.size()) {
+ // End of message
+ msg._flags &= ~KMSG_SCROLL;
+ } else {
+ displayMsg = Common::String(msg._msg.c_str(), msg._msg.c_str() + msg._msgOffset);
+ }
+
+ msg._frameTimer = msg._frameTimer2 = currentTimer + msg._numTicks;
+ flag = true;
+ }
+
+ int strWidth = _talkFont->getWidth(displayMsg, scene._textSpacing);
+
+ if (msg._flags & (KMSG_RIGHT_ALIGN | KMSG_CENTER_ALIGN)) {
+ x1 -= (msg._flags & KMSG_CENTER_ALIGN) ? strWidth / 2 : strWidth;
+ }
+
+ // Make sure text appears entirely on-screen
+ int x2 = x1 + strWidth;
+ if (x2 > MADS_SCREEN_WIDTH)
+ x1 -= x2 - MADS_SCREEN_WIDTH;
+ if (x1 > (MADS_SCREEN_WIDTH - 1))
+ x1 = MADS_SCREEN_WIDTH - 1;
+ if (x1 < 0)
+ x1 = 0;
+
+ if (y1 >(MADS_SCENE_HEIGHT - 1))
+ y1 = MADS_SCENE_HEIGHT - 1;
+ if (y1 < 0)
+ y1 = 0;
+
+ if (msg._textDisplayIndex >= 0) {
+ TextDisplay &textEntry = scene._textDisplay[msg._textDisplayIndex];
+
+ if (flag || (textEntry._bounds.left != x1) || (textEntry._bounds.top != y1)) {
+ // Mark the associated text entry as deleted, so it can be re-created
+ scene._textDisplay.expire(msg._textDisplayIndex);
+ msg._textDisplayIndex = -1;
+ }
+ }
+
+ if (msg._textDisplayIndex < 0) {
+ // Need to create a new text display entry for this message
+ int idx = scene._textDisplay.add(x1, y1, msg._color1 | (msg._color2 << 8),
+ scene._textSpacing, displayMsg, _talkFont);
+ if (idx >= 0)
+ msg._textDisplayIndex = idx;
+ }
+}
+
+void KernelMessages::delay(uint32 priorFrameTime, uint32 currentTime) {
+ for (uint i = 0; i < _entries.size(); ++i) {
+ _entries[i]._timeout += currentTime - priorFrameTime;
+ }
+}
+
+void KernelMessages::setQuoted(int msgIndex, int numTicks, bool quoted) {
+ if (msgIndex >= 0) {
+ KernelMessage &msg = _entries[msgIndex];
+
+ msg._flags |= KMSG_SCROLL;
+ if (quoted)
+ msg._flags |= KMSG_QUOTED;
+
+ msg._msgOffset = 0;
+ msg._numTicks = numTicks;
+ msg._frameTimer2 = _vm->_game->_scene._frameStartTime;
+
+ if (msg._flags & KMSG_PLAYER_TIMEOUT) {
+ msg._frameTimer2 = _vm->_game->_player._priorTimer +
+ _vm->_game->_player._ticksAmount;
+ }
+
+ msg._frameTimer = msg._frameTimer2;
+ }
+}
+
+#define RANDOM_MESSAGE_TRIGGER 240
+
+void KernelMessages::randomServer() {
+ if ((_vm->_game->_trigger >= RANDOM_MESSAGE_TRIGGER) &&
+ (_vm->_game->_trigger < (RANDOM_MESSAGE_TRIGGER + (int)_randomMessages.size()))) {
+ _randomMessages[_vm->_game->_trigger - RANDOM_MESSAGE_TRIGGER]._handle = -1;
+ _randomMessages[_vm->_game->_trigger - RANDOM_MESSAGE_TRIGGER]._quoteId = -1;
+ }
+}
+
+int KernelMessages::checkRandom() {
+ int total = 0;
+
+ for (uint i = 0; i < _randomMessages.size(); ++i) {
+ if (_randomMessages[i]._handle >= 0)
+ ++total;
+ }
+
+ return total;
+}
+
+bool KernelMessages::generateRandom(int major, int minor) {
+ bool generatedMessage = false;
+
+ // Scan through the random messages array
+ for (uint msgCtr = 0; msgCtr < _randomMessages.size(); msgCtr++) {
+ // Find currently active random messages
+ if (_randomMessages[msgCtr]._handle < 0) {
+ // Check whether there's any existing 'scrolling in' message
+ bool bad = false;
+ for (uint scanCtr = 0; scanCtr < _randomMessages.size(); ++scanCtr) {
+ if (_randomMessages[scanCtr]._handle >= 0) {
+ if (_entries[_randomMessages[scanCtr]._handle]._flags & KMSG_SCROLL) {
+ bad = true;
+ break;
+ }
+ }
+ }
+
+ // Do a random check for a new message to appear
+ if (_vm->getRandomNumber(major) <= minor && !bad) {
+ int quoteId;
+
+ // Pick a random quote to display from the available list
+ do {
+ int quoteIdx = _vm->getRandomNumber(_randomQuotes.size() - 1);
+ quoteId = _randomQuotes[quoteIdx];
+
+ // Ensure the quote isn't already in use
+ bad = false;
+ for (uint scanCtr = 0; scanCtr < _randomMessages.size(); ++scanCtr) {
+ if (quoteId == _randomMessages[scanCtr]._quoteId) {
+ bad = true;
+ break;
+ }
+ }
+ } while (bad);
+
+ // Store the quote Id to be used
+ _randomMessages[msgCtr]._quoteId = quoteId;
+
+ // Position the message at a random position
+ Common::Point textPos;
+ textPos.x = _vm->getRandomNumber(_randomMessages._bounds.left,
+ _randomMessages._bounds.right);
+
+ // Figure out Y position, making sure not to be overlapping with
+ // any other on-screen message
+ int abortCounter = 0;
+
+ do {
+ // Ensure we don't get stuck in an infinite loop if too many messages
+ // are alrady on-screen
+ if (abortCounter++ > 100) goto done;
+ bad = false;
+
+ // Set potential new Y position
+ textPos.y = _vm->getRandomNumber(_randomMessages._bounds.top,
+ _randomMessages._bounds.bottom);
+
+ // Ensure it doesn't overlap an existing on-screen message
+ for (uint msgCtr2 = 0; msgCtr2 < _randomMessages.size(); ++msgCtr2) {
+ if (_randomMessages[msgCtr2]._handle >= 0) {
+ int lastY = _entries[_randomMessages[msgCtr2]._handle]._position.y;
+
+ if ((textPos.y >= (lastY - _randomMessages._randomSpacing)) &&
+ (textPos.y <= (lastY + _randomMessages._randomSpacing))) {
+ bad = true;
+ }
+ }
+ }
+ } while (bad);
+
+ // Add the message
+ _randomMessages[msgCtr]._handle = add(textPos, _randomMessages._color, 0,
+ RANDOM_MESSAGE_TRIGGER + msgCtr, _randomMessages._duration,
+ _vm->_game->getQuote(_randomMessages[msgCtr]._quoteId));
+
+ if (_randomMessages._scrollRate > 0) {
+ if (_randomMessages[msgCtr]._handle >= 0) {
+ setQuoted(_randomMessages[msgCtr]._handle,
+ _randomMessages._scrollRate, true);
+ }
+ }
+
+ generatedMessage = true;
+ break;
+ }
+ }
+ }
+
+done:
+ return generatedMessage;
+}
+
+void KernelMessages::initRandomMessages(int maxSimultaneousMessages,
+ const Common::Rect &bounds, int minYSpacing, int scrollRate,
+ int color, int duration, int quoteId, ...) {
+ // Reset the random messages list
+ _randomMessages.clear();
+ _randomMessages.resize(maxSimultaneousMessages);
+
+ // Store passed parameters
+ _randomMessages._bounds = bounds;
+ _randomMessages._randomSpacing = minYSpacing;
+ _randomMessages._scrollRate = scrollRate;
+ _randomMessages._color = color;
+ _randomMessages._duration = duration;
+
+ // Store the variable length random quote list
+ va_list va;
+ va_start(va, quoteId);
+ _randomQuotes.clear();
+
+ while (quoteId > 0) {
+ _randomQuotes.push_back(quoteId);
+ assert(_randomQuotes.size() < 100);
+ quoteId = va_arg(va, int);
+ }
+
+ va_end(va);
+}
+
+
+/*------------------------------------------------------------------------*/
+
+TextDisplay::TextDisplay() {
+ _active = false;
+ _expire = 0;
+ _spacing = 0;
+ _color1 = 0;
+ _color2 = 0;
+ _font = nullptr;
+}
+
+/*------------------------------------------------------------------------*/
+
+TextDisplayList::TextDisplayList(MADSEngine *vm) : _vm(vm) {
+ for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) {
+ TextDisplay rec;
+ rec._active = false;
+ rec._expire = 0;
+ push_back(rec);
+ }
+}
+
+void TextDisplayList::reset() {
+ for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i)
+ (*this)[i]._active = false;
+}
+
+int TextDisplayList::add(int xp, int yp, uint fontColor, int charSpacing,
+ const Common::String &msg, Font *font) {
+ int usedSlot = -1;
+
+ for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
+ TextDisplay &td = (*this)[idx];
+ if (!td._active) {
+ usedSlot = idx;
+
+ td._bounds.left = xp;
+ td._bounds.top = yp;
+ td._font = font;
+ td._msg = msg;
+ td._bounds.setWidth(font->getWidth(msg, charSpacing));
+ td._bounds.setHeight(font->getHeight());
+ td._color1 = fontColor & 0xff;
+ td._color2 = fontColor >> 8;
+ td._spacing = charSpacing;
+ td._expire = 1;
+ td._active = true;
+ break;
+ }
+ }
+
+ return usedSlot;
+}
+
+void TextDisplayList::setDirtyAreas() {
+ Scene &scene = _vm->_game->_scene;
+
+ for (uint idx = 0, dirtyIdx = SPRITE_SLOTS_MAX_SIZE; dirtyIdx < size(); ++idx, ++dirtyIdx) {
+ if (((*this)[idx]._expire >= 0) || !(*this)[idx]._active) {
+ scene._dirtyAreas[dirtyIdx]._active = false;
+ } else {
+ scene._dirtyAreas[dirtyIdx]._textActive = true;
+ scene._dirtyAreas[dirtyIdx].setTextDisplay(&(*this)[idx]);
+ }
+ }
+}
+
+void TextDisplayList::setDirtyAreas2() {
+ Scene &scene = _vm->_game->_scene;
+
+ for (uint idx = 0, dirtyIdx = SPRITE_SLOTS_MAX_SIZE; idx < size(); ++idx, ++dirtyIdx) {
+ if ((*this)[idx]._active && ((*this)[idx]._expire >= 0)) {
+ scene._dirtyAreas[dirtyIdx].setTextDisplay(&(*this)[idx]);
+ scene._dirtyAreas[dirtyIdx]._textActive = ((*this)[idx]._expire <= 0) ? 0 : 1;
+ }
+ }
+}
+
+void TextDisplayList::draw(MSurface *s) {
+ for (uint idx = 0; idx < size(); ++idx) {
+ TextDisplay &td = (*this)[idx];
+ if (td._active && (td._expire >= 0)) {
+ Common::Point destPos(td._bounds.left, td._bounds.top);
+ td._font->setColors(0xFF, td._color1, td._color2, 0);
+ td._font->writeString(s, td._msg, destPos, td._spacing, td._bounds.width());
+ }
+ }
+}
+
+void TextDisplayList::cleanUp() {
+ for (uint idx = 0; idx < size(); ++idx) {
+ if ((*this)[idx]._expire < 0) {
+ (*this)[idx]._active = false;
+ (*this)[idx]._expire = 0;
+ }
+ }
+}
+
+void TextDisplayList::expire(int idx) {
+ (*this)[idx]._expire = -1;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/messages.h b/engines/mads/messages.h
new file mode 100644
index 0000000000..a7411d98d1
--- /dev/null
+++ b/engines/mads/messages.h
@@ -0,0 +1,192 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_MESSAGES_H
+#define MADS_MESSAGES_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "mads/action.h"
+#include "mads/font.h"
+#include "mads/msurface.h"
+
+namespace MADS {
+
+#define KERNEL_MESSAGES_SIZE 10
+#define INDEFINITE_TIMEOUT 9999999
+#define TEXT_DISPLAY_SIZE 40
+#define RANDOM_MESSAGE_SIZE 4
+
+enum KernelMessageFlags {
+ KMSG_QUOTED = 1, KMSG_PLAYER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8,
+ KMSG_RIGHT_ALIGN = 0x10, KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40,
+ KMSG_ACTIVE = 0x80
+};
+
+class MADSEngine;
+
+class KernelMessage {
+public:
+ uint8 _flags;
+ int _sequenceIndex;
+ int _color1;
+ int _color2;
+ Common::Point _position;
+ int _textDisplayIndex;
+ uint32 _msgOffset;
+ int _numTicks;
+ uint32 _frameTimer2;
+ uint32 _frameTimer;
+ int32 _timeout;
+ int _trigger;
+ TriggerMode _abortMode;
+ ActionDetails _actionDetails;
+ Common::String _msg;
+
+ KernelMessage();
+};
+
+struct RandomEntry {
+ int _handle;
+ int _quoteId;
+
+ RandomEntry() { _handle = _quoteId = -1; }
+};
+
+class RandomMessages : public Common::Array<RandomEntry> {
+public:
+ Common::Rect _bounds;
+ int _randomSpacing;
+ int _color;
+ int _duration;
+ int _scrollRate;
+public:
+ RandomMessages();
+
+ void reset();
+};
+
+class KernelMessages {
+private:
+ MADSEngine *_vm;
+
+ Common::Array<int> _randomQuotes;
+ RandomMessages _randomMessages;
+public:
+ Common::Array<KernelMessage> _entries;
+ Font *_talkFont;
+public:
+ KernelMessages(MADSEngine *vm);
+ ~KernelMessages();
+
+ void clear();
+ int add(const Common::Point &pt, uint fontColor, uint8 flags, uint8 abortTimers,
+ uint32 timeout, const Common::String &msg);
+ int addQuote(int quoteId, int abortTimers, uint32 timeout);
+ void scrollMessage(int msgIndex, int numTicks, bool quoted);
+ void setSeqIndex(int msgIndex, int seqIndex);
+ void remove(int msgIndex);
+ void reset();
+ void update();
+ void processText(int msgIndex);
+ void delay(uint32 priorFrameTime, uint32 currentTime);
+ void setQuoted(int msgIndex, int numTicks, bool quoted);
+
+ void initRandomMessages(int maxSimultaneousMessages,
+ const Common::Rect &bounds, int minYSpacing, int scrollRate,
+ int color, int duration, int quoteId, ...);
+
+ /**
+ * Handles expiring any active random messages as necessary
+ */
+ void randomServer();
+
+ /**
+ * Return the number of currently active random messages
+ */
+ int checkRandom();
+
+ /**
+ * Handles generating new random messages
+ */
+ bool generateRandom(int major, int minor);
+};
+
+class TextDisplay {
+public:
+ bool _active;
+ int _expire;
+ int _spacing;
+ Common::Rect _bounds;
+ uint8 _color1;
+ uint8 _color2;
+ Font *_font;
+ Common::String _msg;
+
+ TextDisplay();
+};
+
+#define TEXT_DISPLAY_SIZE 40
+
+class TextDisplayList : public Common::Array<TextDisplay> {
+private:
+ MADSEngine *_vm;
+public:
+ TextDisplayList(MADSEngine *vm);
+
+ /**
+ * Expire a given text display entry
+ */
+ void expire(int idx);
+
+ int add(int xp, int yp, uint fontColor, int charSpacing, const Common::String &, Font *font);
+
+ /**
+ * Reset all of the text display entries in the list to inactive
+ */
+ void reset();
+
+ /**
+ * Draw any text in the list to the specified surface
+ * @param surface Surface
+ */
+ void draw(MSurface *s);
+
+ /**
+ * Determine dirty areas for active text areas
+ */
+ void setDirtyAreas();
+
+ /**
+ * Secondary setup dirty areas for the text areas
+ */
+ void setDirtyAreas2();
+
+ /**
+ * Deactivates any text display entries that are finished
+ */
+ void cleanUp();
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_MESSAGES_H */
diff --git a/engines/mads/module.mk b/engines/mads/module.mk
new file mode 100644
index 0000000000..96353e9ae5
--- /dev/null
+++ b/engines/mads/module.mk
@@ -0,0 +1,59 @@
+MODULE := engines/mads
+
+MODULE_OBJS := \
+ dragonsphere/game_dragonsphere.o \
+ dragonsphere/dragonsphere_scenes.o \
+ phantom/game_phantom.o \
+ phantom/phantom_scenes.o \
+ nebular/dialogs_nebular.o \
+ nebular/game_nebular.o \
+ nebular/globals_nebular.o \
+ nebular/menu_nebular.o \
+ nebular/sound_nebular.o \
+ nebular/nebular_scenes.o \
+ nebular/nebular_scenes1.o \
+ nebular/nebular_scenes2.o \
+ nebular/nebular_scenes3.o \
+ nebular/nebular_scenes4.o \
+ nebular/nebular_scenes5.o \
+ nebular/nebular_scenes6.o \
+ nebular/nebular_scenes7.o \
+ nebular/nebular_scenes8.o \
+ action.o \
+ animation.o \
+ assets.o \
+ audio.o \
+ compression.o \
+ debugger.o \
+ detection.o \
+ dialogs.o \
+ events.o \
+ font.o \
+ game.o \
+ game_data.o \
+ globals.o \
+ hotspots.o \
+ inventory.o \
+ mads.o \
+ messages.o \
+ msurface.o \
+ palette.o \
+ player.o \
+ rails.o \
+ resources.o \
+ scene.o \
+ scene_data.o \
+ screen.o \
+ sequence.o \
+ sound.o \
+ sprites.o \
+ staticres.o \
+ user_interface.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_MADS), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
new file mode 100644
index 0000000000..0cb4530a84
--- /dev/null
+++ b/engines/mads/msurface.cpp
@@ -0,0 +1,556 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "engines/util.h"
+#include "mads/compression.h"
+#include "mads/screen.h"
+#include "mads/mads.h"
+#include "mads/msurface.h"
+#include "mads/resources.h"
+#include "mads/sprites.h"
+
+namespace MADS {
+
+MADSEngine *MSurface::_vm = nullptr;
+
+MSurface::MSurface() {
+ pixels = nullptr;
+ _freeFlag = false;
+}
+
+MSurface::MSurface(int width, int height) {
+ pixels = nullptr;
+ _freeFlag = false;
+ setSize(width, height);
+}
+
+MSurface::~MSurface() {
+ if (_freeFlag)
+ Graphics::Surface::free();
+}
+
+void MSurface::setSize(int width, int height) {
+ if (_freeFlag)
+ Graphics::Surface::free();
+ Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ _freeFlag = true;
+}
+
+void MSurface::setPixels(byte *pData, int horizSize, int vertSize) {
+ _freeFlag = false;
+ pixels = pData;
+ w = pitch = horizSize;
+ h = vertSize;
+ format.bytesPerPixel = 1;
+}
+
+int MSurface::scaleValue(int value, int scale, int err) {
+ int scaled = 0;
+ while (value--) {
+ err -= scale;
+ while (err < 0) {
+ scaled++;
+ err += 100;
+ }
+ }
+ return scaled;
+}
+
+void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect) {
+
+ enum {
+ kStatusSkip,
+ kStatusScale,
+ kStatusDraw
+ };
+
+ // NOTE: The current clipping code assumes that the top left corner of the clip
+ // rectangle is always 0, 0
+ assert(clipRect.top == 0 && clipRect.left == 0);
+
+ // TODO: Put err* and scaled* into SpriteInfo
+ int errX = info.hotX * info.scaleX % 100;
+ int errY = info.hotY * info.scaleY % 100;
+ int scaledWidth = scaleValue(info.width, info.scaleX, errX);
+ int scaledHeight = scaleValue(info.height, info.scaleY, errY);
+
+ int x = pt.x, y = pt.y;
+ int clipX = 0, clipY = 0;
+ // Clip the sprite's width and height according to the clip rectangle's dimensions
+ // This clips the sprite to the bottom and right
+ if (x >= 0) {
+ scaledWidth = MIN<int>(x + scaledWidth, clipRect.right) - x;
+ } else {
+ clipX = x;
+ scaledWidth = x + scaledWidth;
+ }
+ if (y >= 0) {
+ scaledHeight = MIN<int>(y + scaledHeight, clipRect.bottom) - y;
+ } else {
+ clipY = y;
+ scaledHeight = y + scaledHeight;
+ }
+
+ // Check if sprite is inside the screen. If it's not, there's no need to draw it
+ if (scaledWidth + x <= 0 || scaledHeight + y <= 0) // check left and top (in case x,y are negative)
+ return;
+ if (scaledWidth <= 0 || scaledHeight <= 0) // check right and bottom
+ return;
+ int heightAmt = scaledHeight;
+
+ byte *src = info.sprite->getData();
+ byte *dst = getBasePtr(x - info.hotX - clipX, y - info.hotY - clipY);
+
+ int status = kStatusSkip;
+ byte *scaledLineBuf = new byte[scaledWidth];
+
+ while (heightAmt > 0) {
+
+ if (status == kStatusSkip) {
+ // Skip line
+ errY -= info.scaleY;
+ if (errY < 0)
+ status = kStatusScale;
+ else
+ src += info.width;
+ } else {
+
+ if (status == kStatusScale) {
+ // Scale current line
+ byte *lineDst = scaledLineBuf;
+ int curErrX = errX;
+ int width = scaledWidth;
+ byte *tempSrc = src;
+ int startX = clipX;
+ while (width > 0) {
+ byte pixel = *tempSrc++;
+ curErrX -= info.scaleX;
+ while (curErrX < 0) {
+ if (startX == 0) {
+ *lineDst++ = pixel;
+ width--;
+ } else {
+ startX++;
+ }
+ curErrX += 100;
+ }
+ }
+ src += info.width;
+ status = kStatusDraw;
+ }
+
+ if (status == kStatusDraw && clipY == 0) {
+ // Draw previously scaled line
+ // TODO Implement different drawing types (depth, shadow etc.)
+ byte *tempDst = dst;
+ for (int lineX = 0; lineX < scaledWidth; lineX++) {
+ byte pixel = scaledLineBuf[lineX];
+
+ if (info.encoding & 0x80) {
+
+ if (pixel == 0x80) {
+ pixel = 0;
+ } else {
+ byte destPixel = *tempDst;
+ byte r, g, b;
+ r = CLIP((info.palette[destPixel * 3] * pixel) >> 10, 0, 31);
+ g = CLIP((info.palette[destPixel * 3 + 1] * pixel) >> 10, 0, 31);
+ b = CLIP((info.palette[destPixel * 3 + 2] * pixel) >> 10, 0, 31);
+ pixel = info.inverseColorTable[(b << 10) | (g << 5) | r];
+ }
+ }
+
+ if (pixel)
+ *tempDst = pixel;
+
+ tempDst++;
+ }
+ dst += pitch;
+ heightAmt--;
+ // TODO depth etc.
+ //depthAddress += Destination -> Width;
+
+ errY += 100;
+ if (errY >= 0)
+ status = kStatusSkip;
+ } else if (status == kStatusDraw && clipY < 0) {
+ clipY++;
+
+ errY += 100;
+ if (errY >= 0)
+ status = kStatusSkip;
+ }
+
+ }
+
+ }
+
+ delete[] scaledLineBuf;
+
+}
+
+void MSurface::empty() {
+ Common::fill(getBasePtr(0, 0), getBasePtr(0, h), 0);
+}
+
+void MSurface::copyFrom(MSurface *src, const Common::Rect &srcBounds,
+ const Common::Point &destPos, int transparentColor) {
+ // Validation of the rectangle and position
+ int destX = destPos.x, destY = destPos.y;
+ if ((destX >= w) || (destY >= h))
+ return;
+
+ Common::Rect copyRect = srcBounds;
+ if (destX < 0) {
+ copyRect.left += -destX;
+ destX = 0;
+ } else if (destX + copyRect.width() > w) {
+ copyRect.right -= destX + copyRect.width() - w;
+ }
+ if (destY < 0) {
+ copyRect.top += -destY;
+ destY = 0;
+ } else if (destY + copyRect.height() > h) {
+ copyRect.bottom -= destY + copyRect.height() - h;
+ }
+
+ if (!copyRect.isValidRect())
+ return;
+
+ // Copy the specified area
+
+ byte *data = src->getData();
+ byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
+ byte *destPtr = (byte *)pixels + (destY * getWidth()) + destX;
+
+ for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
+ if (transparentColor == -1) {
+ // No transparency, so copy line over
+ Common::copy(srcPtr, srcPtr + copyRect.width(), destPtr);
+ } else {
+ // Copy each byte one at a time checking for the transparency color
+ for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr)
+ if (srcPtr[xCtr] != transparentColor) destPtr[xCtr] = srcPtr[xCtr];
+ }
+
+ srcPtr += src->getWidth();
+ destPtr += getWidth();
+ }
+}
+
+void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
+ DepthSurface *depthSurface, int scale, bool flipped, int transparentColor) {
+ int destX = destPos.x, destY = destPos.y;
+ int frameWidth = src->getWidth();
+ int frameHeight = src->getHeight();
+ int direction = flipped ? -1 : 1;
+
+ int highestDim = MAX(frameWidth, frameHeight);
+ bool lineDist[MADS_SCREEN_WIDTH];
+ int distXCount = 0, distYCount = 0;
+
+ if (scale != -1) {
+ int distCtr = 0;
+ int distIndex = 0;
+ do {
+ distCtr += scale;
+ if (distCtr < 100) {
+ lineDist[distIndex] = false;
+ } else {
+ lineDist[distIndex] = true;
+ distCtr -= 100;
+
+ if (distIndex < frameWidth)
+ ++distXCount;
+
+ if (distIndex < frameHeight)
+ ++distYCount;
+ }
+ } while (++distIndex < highestDim);
+
+ destX -= distXCount / 2;
+ destY -= distYCount - 1;
+ }
+
+ // Special case for quicker drawing of non-scaled images
+ if (scale == 100 || scale == -1) {
+ // Copy the specified area
+ Common::Rect copyRect(0, 0, src->getWidth(), src->getHeight());
+
+ if (destX < 0) {
+ copyRect.left += -destX;
+ destX = 0;
+ } else if (destX + copyRect.width() > w) {
+ copyRect.right -= destX + copyRect.width() - w;
+ }
+ if (destY < 0) {
+ copyRect.top += -destY;
+ destY = 0;
+ } else if (destY + copyRect.height() > h) {
+ copyRect.bottom -= destY + copyRect.height() - h;
+ }
+
+ if (!copyRect.isValidRect())
+ return;
+
+ byte *data = src->getData();
+ byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
+ byte *destPtr = (byte *)pixels + (destY * pitch) + destX;
+ if (flipped)
+ srcPtr += copyRect.width() - 1;
+
+ // 100% scaling variation
+ for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
+ // Copy each byte one at a time checking against the depth
+ for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) {
+ byte *srcP = srcPtr + xCtr * direction;
+ int pixelDepth = depthSurface == nullptr ? 15 :
+ depthSurface->getDepth(Common::Point(destX + xCtr, destY + rowCtr));
+
+ if ((depth <= pixelDepth) && (*srcP != transparentColor))
+ destPtr[xCtr] = *srcP;
+ }
+
+ srcPtr += src->getWidth();
+ destPtr += getWidth();
+ }
+
+ return;
+ }
+
+ // Start of draw logic for scaled sprites
+ const byte *srcPixelsP = src->getData();
+
+ int destRight = this->getWidth() - 1;
+ int destBottom = this->getHeight() - 1;
+
+ // Check x bounding area
+ int spriteLeft = 0;
+ int spriteWidth = distXCount;
+ int widthAmount = destX + distXCount - 1;
+
+ if (destX < 0) {
+ spriteWidth += destX;
+ spriteLeft -= destX;
+ }
+ widthAmount -= destRight;
+ if (widthAmount > 0)
+ spriteWidth -= widthAmount;
+
+ if (spriteWidth <= 0)
+ return;
+
+ int spriteRight = spriteLeft + spriteWidth;
+ if (flipped) {
+ destX += distXCount - 1;
+ spriteLeft = -(distXCount - spriteRight);
+ spriteRight = (-spriteLeft + spriteWidth);
+ }
+
+ // Check y bounding area
+ int spriteTop = 0;
+ int spriteHeight = distYCount;
+ int heightAmount = destY + distYCount - 1;
+
+ if (destY < 0) {
+ spriteHeight += destY;
+ spriteTop -= destY;
+ }
+ heightAmount -= destBottom;
+ if (heightAmount > 0)
+ spriteHeight -= heightAmount;
+ int spriteBottom = spriteTop + spriteHeight;
+
+ if (spriteHeight <= 0)
+ return;
+
+ byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop);
+
+ spriteLeft = spriteLeft * direction;
+
+ // Loop through the lines of the sprite
+ for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) {
+ if (!lineDist[yp])
+ // Not a display line, so skip it
+ continue;
+ // Check whether the sprite line is in the display range
+ ++sprY;
+ if ((sprY >= spriteBottom) || (sprY < spriteTop))
+ continue;
+
+ // Found a line to display. Loop through the pixels
+ const byte *srcP = srcPixelsP;
+ byte *destP = destPixelsP;
+
+ for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) {
+ if (xp < spriteLeft)
+ // Not yet reached start of display area
+ continue;
+ if (!lineDist[sprX++])
+ // Not a display pixel
+ continue;
+
+ // Get depth of current output pixel in depth surface
+ Common::Point pt((destP - (byte *)this->pixels) % this->pitch,
+ (destP - (byte *)this->pixels) / this->pitch);
+ int pixelDepth = (depthSurface == nullptr) ? 15 : depthSurface->getDepth(pt);
+
+ if ((*srcP != transparentColor) && (depth <= pixelDepth))
+ *destP = *srcP;
+
+ destP += direction;
+ }
+
+ // Move to the next destination line
+ destPixelsP += this->pitch;
+ }
+}
+
+void MSurface::scrollX(int xAmount) {
+ if (xAmount == 0)
+ return;
+
+ byte buffer[80];
+ int direction = (xAmount > 0) ? -1 : 1;
+ int xSize = ABS(xAmount);
+ assert(xSize <= 80);
+
+ byte *srcP = getBasePtr(0, 0);
+
+ for (int y = 0; y < this->h; ++y, srcP += pitch) {
+ if (direction < 0) {
+ // Copy area to be overwritten
+ Common::copy(srcP, srcP + xSize, &buffer[0]);
+ // Shift the remainder of the line over the given area
+ Common::copy(srcP + xSize, srcP + this->w, srcP);
+ // Move buffered area to the end of the line
+ Common::copy(&buffer[0], &buffer[xSize], srcP + this->w - xSize);
+ } else {
+ // Copy area to be overwritten
+ Common::copy_backward(srcP + this->w - xSize, srcP + this->w, &buffer[80]);
+ // Shift the remainder of the line over the given area
+ Common::copy_backward(srcP, srcP + this->w - xSize, srcP + this->w);
+ // Move buffered area to the start of the line
+ Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize);
+ }
+ }
+}
+
+void MSurface::scrollY(int yAmount) {
+ if (yAmount == 0)
+ return;
+
+ int direction = (yAmount > 0) ? 1 : -1;
+ int ySize = ABS(yAmount);
+ assert(ySize < (this->h / 2));
+ assert(this->w == pitch);
+
+ int blockSize = ySize * this->w;
+ byte *tempData = new byte[blockSize];
+ byte *pixelsP = getBasePtr(0, 0);
+
+ if (direction > 0) {
+ // Buffer the lines to be overwritten
+ byte *srcP = (byte *)getBasePtr(0, this->h - ySize);
+ Common::copy(srcP, srcP + (pitch * ySize), tempData);
+ // Vertically shift all the lines
+ Common::copy_backward(pixelsP, pixelsP + (pitch * (this->h - ySize)),
+ pixelsP + (pitch * this->h));
+ // Transfer the buffered lines top the top of the screen
+ Common::copy(tempData, tempData + blockSize, pixelsP);
+ } else {
+ // Buffer the lines to be overwritten
+ Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData);
+ // Vertically shift all the lines
+ Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * this->h), pixelsP);
+ // Transfer the buffered lines to the bottom of the screen
+ Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (this->h - ySize)));
+ }
+
+ delete[] tempData;
+}
+
+
+void MSurface::translate(Common::Array<RGB6> &palette) {
+ for (int y = 0; y < this->h; ++y) {
+ byte *pDest = getBasePtr(0, y);
+
+ for (int x = 0; x < this->w; ++x, ++pDest) {
+ if (*pDest < 255) // scene 752 has some palette indices of 255
+ *pDest = palette[*pDest]._palIndex;
+ }
+ }
+}
+
+void MSurface::translate(byte map[PALETTE_COUNT]) {
+ for (int y = 0; y < this->h; ++y) {
+ byte *pDest = getBasePtr(0, y);
+
+ for (int x = 0; x < this->w; ++x, ++pDest) {
+ *pDest = map[*pDest];
+ }
+ }
+}
+
+MSurface *MSurface::flipHorizontal() const {
+ MSurface *dest = new MSurface(this->w, this->h);
+
+ for (int y = 0; y < this->h; ++y) {
+ const byte *srcP = getBasePtr(this->w - 1, y);
+ byte *destP = dest->getBasePtr(0, y);
+
+ for (int x = 0; x < this->w; ++x)
+ *destP++ = *srcP--;
+ }
+
+ return dest;
+}
+
+/*------------------------------------------------------------------------*/
+
+int DepthSurface::getDepth(const Common::Point &pt) {
+ if (_depthStyle == 2) {
+ int bits = (3 - (pt.x % 4)) * 2;
+ byte v = *getBasePtr(pt.x >> 2, pt.y);
+ return v >> bits;
+ } else {
+ if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h)
+ return 0;
+
+ return *getBasePtr(pt.x, pt.y) & 0xF;
+ }
+}
+
+int DepthSurface::getDepthHighBit(const Common::Point &pt) {
+ if (_depthStyle == 2) {
+ int bits = (3 - (pt.x % 4)) * 2;
+ byte v = *getBasePtr(pt.x >> 2, pt.y);
+ return (v >> bits) & 2;
+ } else {
+ if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h)
+ return 0;
+
+ return *getBasePtr(pt.x, pt.y) & 0x80;
+ }
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
new file mode 100644
index 0000000000..ebfb1f437a
--- /dev/null
+++ b/engines/mads/msurface.h
@@ -0,0 +1,251 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_MSURFACE_H
+#define MADS_MSURFACE_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+#include "mads/palette.h"
+
+namespace MADS {
+
+class MADSEngine;
+class MSprite;
+class DepthSurface;
+
+/**
+ * Basic sprite information
+ */
+struct SpriteInfo {
+ MSprite *sprite;
+ int hotX, hotY;
+ int width, height;
+ int scaleX, scaleY;
+ uint8 encoding;
+ byte *inverseColorTable;
+ byte *palette;
+};
+
+/*
+ * MADS graphics surface
+ */
+class MSurface : public Graphics::Surface {
+protected:
+ static MADSEngine *_vm;
+ bool _freeFlag;
+public:
+ /**
+ * Sets the engine refrence used all surfaces
+ */
+ static void setVm(MADSEngine *vm) { _vm = vm; }
+
+ /**
+ * Helper method for calculating new dimensions when scaling a sprite
+ */
+ static int scaleValue(int value, int scale, int err);
+
+ /**
+ * Base method for descendents to load their contents
+ */
+ virtual void load(const Common::String &resName) {}
+public:
+ /**
+ * Basic constructor
+ */
+ MSurface();
+
+ /**
+ * Constructor for a surface with fixed dimensions
+ */
+ MSurface(int width, int height);
+
+ /**
+ * Destructor
+ */
+ virtual ~MSurface();
+
+ /**
+ * Reinitializes a surface to have a given set of dimensions
+ */
+ void setSize(int width, int height);
+
+ /**
+ * Sets the pixels the surface is associated with
+ * @remarks The surface will not free the data block
+ */
+ void setPixels(byte *pData, int horizSize, int vertSize);
+
+ /**
+ * Draws an arbitrary line on the screen using a specified color
+ * @param startPos Starting position
+ * @param endPos Ending position
+ * @param color Color to use
+ */
+ void line(const Common::Point &startPos, const Common::Point &endPos, byte color);
+
+ /**
+ * Draws a sprite
+ * @param pt Position to draw sprite at
+ * @param info General sprite details
+ * @param clipRect Clipping rectangle to constrain sprite drawing within
+ */
+ void drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect);
+
+ /**
+ * Returns the width of the surface
+ */
+ int getWidth() const { return w; }
+
+ /**
+ * Returns the height of the surface
+ */
+ int getHeight() const { return h; }
+
+ /**
+ * Returns the size of the surface as a Rect
+ */
+ Common::Rect getBounds() const {
+ return Common::Rect(0, 0, w, h);
+ }
+
+ /**
+ * Returns a pointer to the surface data
+ */
+ byte *getData() { return (byte *)Graphics::Surface::getPixels(); }
+
+ /**
+ * Returns a pointer to a given position within the surface
+ */
+ byte *getBasePtr(int x, int y) { return (byte *)Graphics::Surface::getBasePtr(x, y); }
+
+ /**
+ * Returns a pointer to a given position within the surface
+ */
+ const byte *getBasePtr(int x, int y) const { return (const byte *)Graphics::Surface::getBasePtr(x, y); }
+
+ /**
+ * Clears the surface
+ */
+ void empty();
+
+ /**
+ * Copys a sub-section of another surface into the current one.
+ * @param src Source surface
+ * @param srcBounds Area of source surface to copy
+ * @param destPos Destination position to draw in current surface
+ * @param transparentColor Transparency palette index
+ */
+ void copyFrom(MSurface *src, const Common::Rect &srcBounds, const Common::Point &destPos,
+ int transparentColor = -1);
+
+ /**
+ * Copys a sub-section of another surface into the current one.
+ * @param src Source surface
+ * @param destPos Destination position to draw in current surface
+ * @param depth Depth of sprite
+ * @param depthSurface Depth surface to use with sprite depth
+ * @param scale Scale for image
+ * @param flipped Flag for whether image is to be flipped
+ * @param transparentColor Transparency palette index
+ */
+ void copyFrom(MSurface *src, const Common::Point &destPos, int depth, DepthSurface *depthSurface,
+ int scale, bool flipped, int transparentColor = -1);
+
+ /**
+ * Copies the surface to a given destination surface
+ */
+ void copyTo(MSurface *dest, int transparentColor = -1) {
+ dest->copyFrom(this, Common::Rect(w, h), Common::Point(), transparentColor);
+ }
+
+ /**
+ * Copies the surface to a given destination surface
+ */
+ void copyTo(MSurface *dest, const Common::Point &pt, int transparentColor = -1) {
+ dest->copyFrom(this, Common::Rect(w, h), pt, transparentColor);
+ }
+
+ /**
+ * Copies the surface to a given destination surface
+ */
+ void copyTo(MSurface *dest, const Common::Rect &srcBounds, const Common::Point &destPos,
+ int transparentColor = -1) {
+ dest->copyFrom(this, srcBounds, destPos, transparentColor);
+ }
+
+ /**
+ * Scroll the screen horizontally by a given amount
+ * @param xAmount Horizontal amount
+ */
+ void scrollX(int xAmount);
+
+ /**
+ * Scroll the screen vertically by a given amount
+ * @param yAmount Vertical amount
+ */
+ void scrollY(int yAmount);
+
+ /**
+ * Translates the pixels of an image used the passed palette with RGB mapping
+ */
+ void translate(Common::Array<RGB6> &palette);
+
+ /**
+ * Translates the pixels of an image used the passed palette with RGB mapping
+ */
+ void translate(byte map[PALETTE_COUNT]);
+
+ /**
+ * Create a new surface which is a flipped horizontal copy of the current one
+ */
+ MSurface *flipHorizontal() const;
+};
+
+class DepthSurface : public MSurface {
+private:
+ MADSEngine *_vm;
+public:
+ /**
+ * Depth style
+ */
+ int _depthStyle;
+
+ /**
+ * Constructor
+ */
+ DepthSurface(MADSEngine *vm) : _vm(vm), _depthStyle(0) {}
+
+ /**
+ * Returns the depth at a given position
+ */
+ int getDepth(const Common::Point &pt);
+
+ /**
+ */
+ int getDepthHighBit(const Common::Point &pt);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_MSURFACE_H */
diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp
new file mode 100644
index 0000000000..35a7d3bdc6
--- /dev/null
+++ b/engines/mads/nebular/dialogs_nebular.cpp
@@ -0,0 +1,1181 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/util.h"
+#include "common/translation.h"
+
+#include "gui/saveload.h"
+
+#include "mads/mads.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/staticres.h"
+#include "mads/nebular/dialogs_nebular.h"
+#include "mads/nebular/game_nebular.h"
+#include "mads/nebular/menu_nebular.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+bool DialogsNebular::show(int messageId, int objectId) {
+ MADSAction &action = _vm->_game->_scene._action;
+ Common::StringArray msg = _vm->_game->getMessage(messageId);
+ Common::String title;
+ Common::String commandText;
+ Common::String valStr;
+ Common::String dialogText;
+ bool result = true;
+ bool centerFlag = false;
+ bool underlineFlag = false;
+ bool commandFlag = false;
+ bool crFlag = false;
+ TextDialog *dialog = nullptr;
+ _dialogWidth = 17;
+ _capitalizationMode = kUppercase;
+
+ // Loop through the lines of the returned text
+ for (uint idx = 0; idx < msg.size(); ++idx) {
+ Common::String srcLine = msg[idx];
+ const char *srcP = srcLine.c_str();
+
+ // Loop through the text of the line
+ while (srcP < srcLine.c_str() + srcLine.size()) {
+ if (*srcP == '[') {
+ // Starting a command
+ commandText = "";
+ commandFlag = true;
+ } else if (*srcP == ']') {
+ // Ending a command
+ if (commandFlag) {
+ if (commandCheck("CENTER", valStr, commandText)) {
+ centerFlag = true;
+ } else if (commandCheck("TITLE", valStr, commandText)) {
+ centerFlag = true;
+ underlineFlag = true;
+ crFlag = true;
+ int v = atoi(valStr.c_str());
+ if (v != 0)
+ _dialogWidth = v;
+ } else if (commandCheck("CR", valStr, commandText)) {
+ if (centerFlag) {
+ crFlag = true;
+ } else {
+ if (objectId == -1) {
+ dialog = new TextDialog(_vm, FONT_INTERFACE, _defaultPosition, _dialogWidth);
+ } else {
+ dialog = new PictureDialog(_vm, _defaultPosition, _dialogWidth, objectId);
+ }
+ dialog->wordWrap(dialogText);
+ dialog->incNumLines();
+ }
+ } else if (commandCheck("ASK", valStr, commandText)) {
+ dialog->addInput();
+ } else if (commandCheck("VERB", valStr, commandText)) {
+ dialogText += getVocab(action._activeAction._verbId);
+ } else if (commandCheck("INDEX", valStr, commandText)) {
+ int idxLocal = atoi(valStr.c_str());
+ if (_indexList[idxLocal])
+ dialogText += getVocab(_indexList[idxLocal]);
+ } else if (commandCheck("NUMBER", valStr, commandText)) {
+ int idxLocal = atoi(valStr.c_str());
+ dialogText += Common::String::format("%.4d", _indexList[idxLocal]);
+ } else if (commandCheck("NOUN1", valStr, commandText)) {
+ if (!textNoun(dialogText, 1, valStr))
+ dialogText += getVocab(action._activeAction._objectNameId);
+ } else if (commandCheck("NOUN2", valStr, commandText)) {
+ if (!textNoun(dialogText, 2, valStr))
+ dialogText += getVocab(action._activeAction._indirectObjectId);
+ } else if (commandCheck("PREP", valStr, commandText)) {
+ dialogText += kArticleList[action._savedFields._articleNumber];
+ } else if (commandCheck("SENTENCE", valStr, commandText)) {
+ dialogText += action._sentence;
+ } else if (commandCheck("WIDTH", valStr, commandText)) {
+ _dialogWidth = atoi(valStr.c_str());
+ } else if (commandCheck("BAR", valStr, commandText)) {
+ dialog->addBarLine();
+ } else if (commandCheck("UNDER", valStr, commandText)) {
+ underlineFlag = true;
+ } else if (commandCheck("DOWN", valStr, commandText)) {
+ dialog->downPixelLine();
+ } else if (commandCheck("TAB", valStr, commandText)) {
+ int xp = atoi(valStr.c_str());
+ dialog->setLineXp(xp);
+ }
+ }
+
+ commandFlag = false;
+ } else if (commandFlag) {
+ // Add the next character to the command
+ commandText += *srcP;
+ } else {
+ // Add to the text to be displayed in the dialog
+ dialogText += *srcP;
+ }
+
+ ++srcP;
+ }
+
+ if (!dialog) {
+ if (objectId == -1) {
+ dialog = new TextDialog(_vm, FONT_INTERFACE, _defaultPosition, _dialogWidth);
+ } else {
+ dialog = new PictureDialog(_vm, _defaultPosition, _dialogWidth, objectId);
+ }
+ }
+
+ if (centerFlag) {
+ dialog->addLine(dialogText, underlineFlag);
+ if (crFlag)
+ dialog->incNumLines();
+ } else {
+ dialog->wordWrap(dialogText);
+ }
+
+ // Reset line processing flags in preparation for next line
+ dialogText = "";
+ commandFlag = false;
+ underlineFlag = false;
+ centerFlag = false;
+ crFlag = false;
+ }
+
+ if (!centerFlag)
+ dialog->incNumLines();
+
+ // Show the dialog
+ _vm->_events->setCursor(CURSOR_ARROW);
+ dialog->show();
+
+ delete dialog;
+ return result;
+}
+
+void DialogsNebular::showItem(int objectId, int messageId, int speech) {
+ // MADS engine doesn't currently support speech
+ assert(!speech);
+
+ show(messageId, objectId);
+}
+
+Common::String DialogsNebular::getVocab(int vocabId) {
+ assert(vocabId > 0);
+
+ Common::String vocab = _vm->_game->_scene.getVocab(vocabId);
+
+ switch (_capitalizationMode) {
+ case kUppercase:
+ vocab.toUppercase();
+ break;
+ case kLowercase:
+ vocab.toLowercase();
+ break;
+ case kUpperAndLower:
+ vocab.toLowercase();
+ vocab.setChar(toupper(vocab[0]), 0);
+ default:
+ break;
+ }
+
+ return vocab;
+}
+
+bool DialogsNebular::textNoun(Common::String &dest, int nounId, const Common::String &source) {
+ // Ensure the destination has parameter specifications
+ if (!source.hasPrefix(":"))
+ return false;
+
+ // Extract the first (singular) result value
+ Common::String param1 = Common::String(source.c_str() + 1);
+ Common::String param2;
+ const char *sepChar = strchr(source.c_str() + 1, ':');
+ if (sepChar) {
+ param1 = Common::String(source.c_str() + 1, sepChar);
+
+ // Get the second, plural form
+ param2 = Common::String(sepChar + 1);
+ }
+
+ // Get the vocab to use
+ MADSAction &action = _vm->_game->_scene._action;
+ Common::String vocab = _vm->_dialogs->getVocab(action._activeAction._verbId);
+ Common::String *str;
+
+ if (vocab.hasSuffix("s") || vocab.hasSuffix("S")) {
+ str = &param2;
+ } else {
+ str = &param1;
+
+ if (param1 == "a ") {
+ switch (toupper(vocab[0])) {
+ case 'A':
+ case 'E':
+ case 'I':
+ case 'O':
+ case 'U':
+ param1 = "an ";
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ dest += *str;
+ return true;
+}
+
+bool DialogsNebular::commandCheck(const char *idStr, Common::String &valStr,
+ const Common::String &command) {
+ uint idLen = strlen(idStr);
+
+ valStr = (command.size() <= idLen) ? "" : Common::String(command.c_str() + idLen);
+
+ // Check whether the command starts with the given Id
+ int result = scumm_strnicmp(idStr, command.c_str(), idLen) == 0;
+ if (!result)
+ return false;
+
+ // It does, so set the command case mode
+ if (Common::isUpper(command[0]) && Common::isUpper(command[1])) {
+ _capitalizationMode = kUppercase;
+ } else if (Common::isUpper(command[0])) {
+ _capitalizationMode = kUpperAndLower;
+ } else {
+ _capitalizationMode = kLowercase;
+ }
+
+ return true;
+}
+
+void DialogsNebular::showDialog() {
+ while (_pendingDialog != DIALOG_NONE && !_vm->shouldQuit()) {
+ DialogId dialogId = _pendingDialog;
+ _pendingDialog = DIALOG_NONE;
+
+ switch (dialogId) {
+ case DIALOG_MAIN_MENU: {
+ MainMenu *menu = new MainMenu(_vm);
+ menu->show();
+ delete menu;
+ break;
+ }
+ case DIALOG_DIFFICULTY: {
+ DifficultyDialog *dlg = new DifficultyDialog(_vm);
+ dlg->show();
+ delete dlg;
+ break;
+ }
+ case DIALOG_GAME_MENU: {
+ GameMenuDialog *dlg = new GameMenuDialog(_vm);
+ dlg->show();
+ delete dlg;
+ break;
+ }
+ case DIALOG_SAVE: {
+ showScummVMSaveDialog();
+ break;
+ }
+ case DIALOG_RESTORE: {
+ showScummVMRestoreDialog();
+ break;
+ }
+ case DIALOG_OPTIONS: {
+ OptionsDialog *dlg = new OptionsDialog(_vm);
+ dlg->show();
+ delete dlg;
+ break;
+ }
+ case DIALOG_ADVERT: {
+ AdvertView *dlg = new AdvertView(_vm);
+ dlg->show();
+ delete dlg;
+ break;
+ }
+ case DIALOG_TEXTVIEW: {
+ TextView *dlg = new TextView(_vm);
+ dlg->show();
+ delete dlg;
+ break;
+ }
+ case DIALOG_ANIMVIEW: {
+ AnimationView *dlg = new AnimationView(_vm);
+ dlg->show();
+ delete dlg;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+void DialogsNebular::showScummVMSaveDialog() {
+ Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game;
+ Scene *scene = &(game._scene);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ Common::String desc = dialog->getResultString();
+
+ if (desc.empty()) {
+ // create our own description for the saved game, the user didn't enter it
+ desc = dialog->createDefaultSaveDescription(slot);
+ }
+
+ scene->_spriteSlots.reset();
+ scene->loadScene(scene->_currentSceneId, game._aaName, true);
+ scene->_userInterface.noInventoryAnim();
+ game._scene.drawElements(kTransitionFadeIn, false);
+
+ game.saveGame(slot, desc);
+ }
+}
+
+void DialogsNebular::showScummVMRestoreDialog() {
+ Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game;
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ game._loadGameSlot = slot;
+ game._scene._currentSceneId = -1;
+ game._currentSectionNumber = -1;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+CopyProtectionDialog::CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong) :
+TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) {
+ getHogAnusEntry(_hogEntry);
+
+ if (priorAnswerWrong) {
+ addLine("ANSWER INCORRECT!", true);
+ wordWrap("\n");
+ addLine("(But we'll give you another chance!)");
+ }
+ else {
+ addLine("REX NEBULAR version 8.43", true);
+ wordWrap("\n");
+ addLine("(Copy Protection, for your convenience)");
+ }
+ wordWrap("\n");
+
+ wordWrap("Now comes the part that everybody hates. But if we don't");
+ wordWrap("do this, nasty rodent-like people will pirate this game");
+ wordWrap("and a whole generation of talented designers, programmers,");
+ wordWrap("artists, and playtesters will go hungry, and will wander");
+ wordWrap("aimlessly through the land at night searching for peace.");
+ wordWrap("So let's grit our teeth and get it over with. Just get");
+
+ Common::String line = "out your copy of ";
+ line += _hogEntry._bookId == 103 ? "the GAME MANUAL" : "REX'S LOGBOOK";
+ line += ". See! That was easy. ";
+ wordWrap(line);
+
+ line = Common::String::format("Next, just turn to page %d. On line %d, find word number %d, ",
+ _hogEntry._pageNum, _hogEntry._lineNum, _hogEntry._wordNum);
+ wordWrap(line);
+
+ wordWrap("and type it on the line below (we',27h,'ve even given you");
+ wordWrap("first letter as a hint). As soon as you do that, we can get");
+ wordWrap("right into this really COOL adventure game!\n");
+ wordWrap("\n");
+ wordWrap(" ");
+ addInput();
+ wordWrap("\n");
+}
+
+void CopyProtectionDialog::show() {
+ draw();
+ _vm->_events->showCursor();
+
+ // TODO: Replace with text input
+ while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed() &&
+ !_vm->_events->_mouseClicked) {
+ _vm->_events->delay(1);
+ }
+
+ _vm->_events->_pendingKeys.clear();
+}
+
+bool CopyProtectionDialog::getHogAnusEntry(HOGANUS &entry) {
+ File f;
+ f.open("*HOGANUS.DAT");
+
+ // Read in the total number of entries, and randomly pick an entry to use
+ int numEntries = f.readUint16LE();
+ int entryIndex = _vm->getRandomNumber(1, numEntries);
+
+ // Read in the encrypted entry
+ f.seek(28 * entryIndex + 2);
+ byte entryData[28];
+ f.read(entryData, 28);
+
+ // Decrypt it
+ for (int i = 0; i < 28; ++i)
+ entryData[i] = ~entryData[i];
+
+ // Fill out the fields
+ entry._bookId = entryData[0];
+ entry._pageNum = READ_LE_UINT16(&entryData[2]);
+ entry._lineNum = READ_LE_UINT16(&entryData[4]);
+ entry._wordNum = READ_LE_UINT16(&entryData[6]);
+ entry._word = Common::String((char *)&entryData[8]);
+
+ f.close();
+ return true;
+}
+
+/*------------------------------------------------------------------------*/
+
+PictureDialog::PictureDialog(MADSEngine *vm, const Common::Point &pos,
+ int maxChars, int objectId) :
+ TextDialog(vm, FONT_INTERFACE, pos, maxChars), _objectId(objectId) {
+ // Turn off cycling if active
+ Scene &scene = _vm->_game->_scene;
+ _cyclingActive = scene._cyclingActive;
+ scene._cyclingActive = false;
+}
+
+PictureDialog::~PictureDialog() {
+ // Restore cycling flag
+ Scene &scene = _vm->_game->_scene;
+ scene._cyclingActive = _cyclingActive;
+}
+
+void PictureDialog::save() {
+ Palette &palette = *_vm->_palette;
+ byte map[PALETTE_COUNT];
+
+ // Save the entire screen
+ _savedSurface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
+ _vm->_screen.copyTo(_savedSurface);
+
+ // Save palette information
+ Common::copy(&palette._mainPalette[0], &palette._mainPalette[PALETTE_SIZE], &_palette[0]);
+ Common::copy(&palette._palFlags[0], &palette._palFlags[PALETTE_COUNT], &_palFlags[0]);
+ _rgbList.copy(palette._rgbList);
+
+ // Set up palette allocation
+ Common::fill(&palette._colorFlags[0], &palette._colorFlags[3], true);
+
+ uint32 *palFlagP = &palette._palFlags[0];
+ for (int idx = 0; idx < PALETTE_COUNT; ++idx, ++palFlagP) {
+ if (idx < PALETTE_RESERVED_LOW_COUNT ||
+ idx >= (PALETTE_COUNT - PALETTE_RESERVED_HIGH_COUNT - 10)) {
+ *palFlagP = 1;
+ map[idx] = idx;
+ } else {
+ *palFlagP = 0;
+ }
+ }
+
+ // Reset the flag list
+ palette._rgbList.reset();
+
+ // Fade the screen to grey
+ int numColors = PALETTE_COUNT - PALETTE_RESERVED_LOW_COUNT - PALETTE_RESERVED_HIGH_COUNT;
+ palette.fadeOut(palette._mainPalette, &map[PALETTE_RESERVED_LOW_COUNT],
+ PALETTE_RESERVED_LOW_COUNT, numColors, 248, 8, 1, 16);
+
+ // Remap the greyed out screen to use the small greyscale range
+ // at the top end of the palette
+ _vm->_screen.translate(map);
+
+ // Load the inventory picture
+ Common::String setName = Common::String::format("*OB%.3d.SS", _objectId);
+ SpriteAsset *asset = new SpriteAsset(_vm, setName, 0x8000);
+ palette.setFullPalette(palette._mainPalette);
+
+ // Get the inventory frame, and adjust the dialog position to allow for it
+ MSprite *frame = asset->getFrame(0);
+ _position.y = frame->h + 12;
+ if ((_position.y + _height) > _vm->_screen.getHeight())
+ _position.y -= (_position.y + _height) - _vm->_screen.getHeight();
+
+ // Draw the inventory picture
+ frame->copyTo(&_vm->_screen, Common::Point(160 - frame->w / 2, 6),
+ frame->getTransparencyIndex());
+ _vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
+
+ // Adjust the dialog colors to use
+ TEXTDIALOG_CONTENT1 -= 10;
+ TEXTDIALOG_CONTENT2 -= 10;
+ TEXTDIALOG_EDGE -= 10;
+ TEXTDIALOG_BACKGROUND -= 10;
+ TEXTDIALOG_FC -= 10;
+ TEXTDIALOG_FD -= 10;
+ TEXTDIALOG_FE -= 10;
+}
+
+void PictureDialog::restore() {
+ if (_savedSurface) {
+ _savedSurface->copyTo(&_vm->_screen);
+ delete _savedSurface;
+ _savedSurface = nullptr;
+
+ _vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
+
+ // Restore palette information
+ Palette &palette = *_vm->_palette;
+ Common::copy(&_palette[0], &_palette[PALETTE_SIZE], &palette._mainPalette[0]);
+ _vm->_palette->setFullPalette(palette._mainPalette);
+ Common::copy(&_palFlags[0], &_palFlags[PALETTE_COUNT], &palette._palFlags[0]);
+ palette._rgbList.copy(_rgbList);
+
+ _vm->_dialogs->_defaultPosition.y = -1;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+FullScreenDialog::FullScreenDialog(MADSEngine *vm) : _vm(vm) {
+ _screenId = 990;
+ _palFlag = true;
+}
+
+FullScreenDialog::~FullScreenDialog() {
+ _vm->_screen.resetClipBounds();
+ _vm->_game->_scene.restrictScene();
+}
+
+void FullScreenDialog::display() {
+ Game &game = *_vm->_game;
+ Scene &scene = game._scene;
+
+ int nextSceneId = scene._nextSceneId;
+ int currentSceneId = scene._currentSceneId;
+ int priorSceneId = scene._priorSceneId;
+
+ if (_screenId > 0) {
+ SceneInfo *sceneInfo = SceneInfo::init(_vm);
+ sceneInfo->load(_screenId, 0, "", 0, scene._depthSurface, scene._backgroundSurface);
+ }
+
+ scene._priorSceneId = priorSceneId;
+ scene._currentSceneId = currentSceneId;
+ scene._nextSceneId = nextSceneId;
+
+ _vm->_events->initVars();
+ game._kernelMode = KERNEL_ROOM_INIT;
+
+ byte pal[768];
+ if (_vm->_screenFade) {
+ Common::fill(&pal[0], &pal[PALETTE_SIZE], 0);
+ _vm->_palette->setFullPalette(pal);
+ } else {
+ _vm->_palette->getFullPalette(pal);
+ _vm->_palette->fadeOut(pal, nullptr, 0, PALETTE_COUNT, 0, 1, 1, 16);
+ }
+
+ // Set Fx state and palette entries
+ game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? kTransitionFadeIn : kCenterVertTransition;
+ game._trigger = 0;
+
+ // Clear the screen and draw the upper and lower horizontal lines
+ _vm->_screen.empty();
+ _vm->_palette->setLowRange();
+ _vm->_screen.hLine(0, 20, MADS_SCREEN_WIDTH, 2);
+ _vm->_screen.hLine(0, 179, MADS_SCREEN_WIDTH, 2);
+ _vm->_screen.copyRectToScreen(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
+
+ // Restrict the screen to the area between the two lines
+ _vm->_screen.setClipBounds(Common::Rect(0, DIALOG_TOP, MADS_SCREEN_WIDTH,
+ DIALOG_TOP + MADS_SCENE_HEIGHT));
+ _vm->_game->_scene.restrictScene();
+
+ if (_screenId > 0)
+ scene._spriteSlots.fullRefresh();
+}
+
+/*------------------------------------------------------------------------*/
+
+GameDialog::DialogLine::DialogLine() {
+ _active = true;
+ _state = DLGSTATE_UNSELECTED;
+ _textDisplayIndex = -1;
+ _font = nullptr;
+ _widthAdjust = 0;
+ _msg = "";
+}
+
+GameDialog::DialogLine::DialogLine(const Common::String &s) {
+ _active = true;
+ _state = DLGSTATE_UNSELECTED;
+ _textDisplayIndex = -1;
+ _font = nullptr;
+ _widthAdjust = -1;
+ _msg = s;
+}
+
+/*------------------------------------------------------------------------*/
+
+GameDialog::GameDialog(MADSEngine *vm) : FullScreenDialog(vm) {
+ Game &game = *_vm->_game;
+ Scene &scene = game._scene;
+
+ _tempLine = 0;
+ _movedFlag = false;
+ _redrawFlag = false;
+ _selectedLine = -1;
+ _dirFlag = false;
+ _textLineCount = 0;
+ _lineIndex = -1;
+ _screenId = 920;
+
+ chooseBackground();
+ game.loadQuoteSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 0);
+ game._kernelMode = KERNEL_ROOM_PRELOAD;
+ _vm->_events->waitCursor();
+ scene.clearVocab();
+ scene._dynamicHotspots.clear();
+ _vm->_dialogs->_defaultPosition = Common::Point(-1, -1);
+ _menuSpritesIndex = 0;
+}
+
+void GameDialog::display() {
+ FullScreenDialog::display();
+
+ Palette &palette = *_vm->_palette;
+ palette.setEntry(10, 0, 63, 0);
+ palette.setEntry(11, 0, 45, 0);
+ palette.setEntry(12, 63, 63, 0);
+ palette.setEntry(13, 45, 45, 0);
+ palette.setEntry(14, 63, 63, 63);
+ palette.setEntry(15, 45, 45, 45);
+
+ Scene &scene = _vm->_game->_scene;
+ SpriteAsset *menuSprites = new SpriteAsset(_vm, "*MENU", 0);
+ _menuSpritesIndex = scene._sprites.add(menuSprites);
+
+ _lineIndex = -1;
+ setClickableLines();
+
+ _vm->_events->setCursor(CURSOR_ARROW);
+}
+
+GameDialog::~GameDialog() {
+ _vm->_screen.resetClipBounds();
+}
+
+void GameDialog::clearLines() {
+ Scene &scene = _vm->_game->_scene;
+ _movedFlag = false;
+ _lines.clear();
+ scene._spriteSlots.fullRefresh(true);
+}
+
+void GameDialog::setClickableLines() {
+ ScreenObjects &screenObjects = _vm->_game->_screenObjects;
+
+ for (uint idx = 0; idx < _lines.size(); ++idx) {
+ if (_lines[idx]._active) {
+ const Common::Point &pt = _lines[idx]._pos;
+ int strWidth = _lines[idx]._font->getWidth(_lines[idx]._msg);
+ int maxHeight = _lines[idx]._font->getHeight();
+
+ screenObjects.add(Common::Rect(pt.x, pt.y, pt.x + strWidth, pt.y + maxHeight - 1),
+ LAYER_GUI, CAT_COMMAND, idx);
+ }
+ }
+
+ if (_vm->_dialogs->_pendingDialog == DIALOG_SAVE ||
+ _vm->_dialogs->_pendingDialog == DIALOG_RESTORE) {
+ screenObjects.add(Common::Rect(293, 26, 312, 75), LAYER_GUI, CAT_INV_LIST, 50);
+ screenObjects.add(Common::Rect(293, 78, 312, 127), LAYER_GUI, CAT_INV_LIST, 51);
+ }
+}
+
+void GameDialog::addQuote(int id1, int id2, DialogTextAlign align,
+ const Common::Point &pt, Font *font) {
+ Common::String msg = _vm->_game->getQuote(id1).c_str(); // c_str() because we need a copy
+
+ if (id2 > 0)
+ msg += _vm->_game->getQuote(id2);
+
+ addLine(msg, align, pt, font);
+}
+
+void GameDialog::addLine(const Common::String &msg, DialogTextAlign align,
+ const Common::Point &pt, Font *font) {
+ Scene &scene = _vm->_game->_scene;
+ DialogLine *line;
+
+ if (font == nullptr)
+ font = _vm->_font->getFont(FONT_CONVERSATION);
+
+ if (_lineIndex < (int)_lines.size()) {
+ if (_lines.size() >= 20) {
+ ++_lineIndex;
+ return;
+ }
+
+ _lines.push_back(msg);
+ line = &_lines[_lines.size() - 1];
+ } else {
+ line = &_lines[_lineIndex];
+ if (msg.compareToIgnoreCase(msg)) {
+ ++_lineIndex;
+ return;
+ }
+
+ if (line->_textDisplayIndex >= 0) {
+ TextDisplay &textDisplay = scene._textDisplay[line->_textDisplayIndex];
+ if (textDisplay._active) {
+ textDisplay._expire = -1;
+ if (_textLineCount < 20) {
+ textDisplay._msg = msg;
+ ++_textLineCount;
+ }
+ }
+ }
+ }
+
+ line->_font = font;
+ line->_state = DLGSTATE_UNSELECTED;
+ line->_pos = pt;
+ line->_widthAdjust = -1;
+ line->_textDisplayIndex = -1;
+
+ int xOffset;
+ switch (align) {
+ case ALIGN_NONE:
+ // No adjustment
+ break;
+
+ case ALIGN_CENTER:
+ xOffset = (MADS_SCREEN_WIDTH / 2) - font->getWidth(msg, -1) / 2;
+ line->_pos.x += xOffset;
+ break;
+
+ case ALIGN_AT_CENTER: {
+ const char *msgP = msg.c_str();
+ const char *ch = strchr(msgP, '@');
+ if (ch) {
+ xOffset = (MADS_SCREEN_WIDTH / 2) - font->getWidth(
+ Common::String(msgP, ch), line->_widthAdjust);
+ line->_pos.x += xOffset;
+
+ Common::String newMsg = msg.c_str();
+ newMsg.deleteChar(ch - msgP);
+ line->_msg = newMsg;
+ }
+ break;
+ }
+
+ case ALIGN_RIGHT:
+ xOffset = font->getWidth(msg, -1);
+ line->_pos.x -= xOffset;
+ break;
+
+ default:
+ break;
+ }
+
+ ++_lineIndex;
+}
+
+void GameDialog::initVars() {
+ _tempLine = -1;
+ _selectedLine = -1;
+ _lineIndex = 0;
+ _textLineCount = 0;
+}
+
+void GameDialog::chooseBackground() {
+ switch (_vm->_game->_currentSectionNumber) {
+ case 1:
+ case 2:
+ _screenId = 921;
+ break;
+ case 3:
+ case 4:
+ _screenId = 922;
+ break;
+ case 5:
+ case 6:
+ case 7:
+ _screenId = 923;
+ break;
+ case 8:
+ _screenId = 924;
+ break;
+ default:
+ _screenId = 920;
+ break;
+ }
+}
+
+void GameDialog::setFrame(int frameNumber, int depth) {
+ Scene &scene = _vm->_game->_scene;
+ SpriteAsset *menuSprites = scene._sprites[_menuSpritesIndex];
+ MSprite *frame = menuSprites->getFrame(frameNumber - 1);
+
+ SpriteSlot &spriteSlot = scene._spriteSlots[scene._spriteSlots.add()];
+ spriteSlot._flags = IMG_UPDATE;
+ spriteSlot._seqIndex = 1;
+ spriteSlot._spritesIndex = _menuSpritesIndex;
+ spriteSlot._frameNumber = frameNumber;
+ spriteSlot._position = frame->_offset;
+ spriteSlot._depth = depth;
+ spriteSlot._scale = 100;
+}
+
+void GameDialog::show() {
+ display();
+
+ Scene &scene = _vm->_game->_scene;
+
+ while (_selectedLine < 1 && !_vm->shouldQuit()) {
+ handleEvents();
+ if (_redrawFlag) {
+ if (!_tempLine)
+ _tempLine = -1;
+
+ refreshText();
+ scene.drawElements(_vm->_game->_fx, _vm->_game->_fx);
+ _redrawFlag = false;
+ }
+
+ _vm->_events->waitForNextFrame();
+ _vm->_game->_fx = kTransitionNone;
+ }
+}
+
+void GameDialog::handleEvents() {
+ ScreenObjects &screenObjects = _vm->_game->_screenObjects;
+ EventsManager &events = *_vm->_events;
+ Nebular::DialogsNebular &dialogs = *(Nebular::DialogsNebular *)_vm->_dialogs;
+ int tempLine = _tempLine;
+
+ // Mark all the lines as initially unselected
+ for (uint i = 0; i < _lines.size(); ++i)
+ _lines[i]._state = DLGSTATE_UNSELECTED;
+
+ // Process pending events
+ _vm->_events->pollEvents();
+
+ // Scan for objects in the dialog
+ Common::Point mousePos = events.currentPos() - Common::Point(0, DIALOG_TOP);
+ int objIndex = screenObjects.scan(mousePos, LAYER_GUI);
+
+ if (_movedFlag) {
+ int yp = mousePos.y;
+ if (yp < screenObjects[1]._bounds.top) {
+ if (!events._mouseReleased)
+ _lines[1]._state = DLGSTATE_SELECTED;
+ objIndex = 19;
+ }
+
+ if (yp < screenObjects[7]._bounds.bottom) {
+ if (!events._mouseReleased)
+ _lines[1]._state = DLGSTATE_SELECTED;
+ objIndex = 20;
+ }
+ }
+
+ int line = -1;
+ if (objIndex > 0 && (events._mouseStatus || events._mouseReleased)) {
+ line = screenObjects[objIndex]._descId;
+ if (dialogs._pendingDialog == DIALOG_SAVE || dialogs._pendingDialog == DIALOG_RESTORE) {
+ if (line > 7 && line <= 14) {
+ _lines[line]._state = DLGSTATE_UNSELECTED;
+ line -= 7;
+ }
+
+ bool movedFlag = line > 0 && line < 8;
+ if (events._mouseMoved)
+ _movedFlag = movedFlag;
+ }
+
+ if (screenObjects[objIndex]._category == CAT_COMMAND) {
+ _lines[line]._state = DLGSTATE_SELECTED;
+ }
+ }
+ if (!line)
+ line = -1;
+
+ if (dialogs._pendingDialog == DIALOG_ERROR && line == 1)
+ line = -1;
+
+ if (events._mouseReleased) {
+ if (!_movedFlag || line <= 18)
+ _selectedLine = line;
+ _redrawFlag = true;
+ }
+
+ _tempLine = line;
+ if (tempLine != line || _selectedLine >= 0)
+ _redrawFlag = true;
+}
+
+void GameDialog::refreshText() {
+ Scene &scene = _vm->_game->_scene;
+
+ for (uint i = 0; i < _lines.size(); ++i) {
+ if (_lines[i]._active) {
+ int fontColor;
+ switch (_lines[i]._state) {
+ case DLGSTATE_UNSELECTED:
+ fontColor = 0xB0A;
+ break;
+ case DLGSTATE_SELECTED:
+ fontColor = 0xD0C;
+ break;
+ default:
+ fontColor = 0xF0E;
+ break;
+ }
+
+ bool skipFlag = false;
+ if (_lines[i]._textDisplayIndex >= 0) {
+ TextDisplay &textDisplay = scene._textDisplay[_lines[i]._textDisplayIndex];
+ int currCol = textDisplay._color1;
+ if (currCol != fontColor) {
+ scene._textDisplay.expire(_lines[i]._textDisplayIndex);
+ _lines[i]._textDisplayIndex = -1;
+ } else {
+ skipFlag = true;
+ }
+ }
+
+ if (!skipFlag) {
+ _lines[i]._textDisplayIndex = scene._textDisplay.add(_lines[i]._pos.x, _lines[i]._pos.y,
+ fontColor, _lines[i]._widthAdjust, _lines[i]._msg, _lines[i]._font);
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+DifficultyDialog::DifficultyDialog(MADSEngine *vm) : GameDialog(vm) {
+ setLines();
+ _vm->_palette->resetGamePalette(18, 10);
+}
+
+void DifficultyDialog::setLines() {
+ Font *font = _vm->_font->getFont(FONT_CONVERSATION);
+ int yp = 78 - ((font->getHeight() + 1) * 4 + 6) / 2;
+
+ addQuote(41, 0, ALIGN_CENTER, Common::Point(0, yp), font);
+ yp += 6;
+
+ for (int id = 42; id <= 44; ++id) {
+ yp += font->getHeight();
+ addQuote(id, 0, ALIGN_CENTER, Common::Point(0, yp));
+ }
+}
+
+void DifficultyDialog::display() {
+ GameDialog::display();
+ setFrame(8, 2);
+}
+
+void DifficultyDialog::show() {
+ GameDialog::show();
+ Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game;
+
+ switch (_selectedLine) {
+ case 1:
+ game._difficulty = Nebular::DIFFICULTY_EASY;
+ break;
+ case 2:
+ game._difficulty = Nebular::DIFFICULTY_MEDIUM;
+ break;
+ case 3:
+ game._difficulty = Nebular::DIFFICULTY_HARD;
+ break;
+ default:
+ _vm->quitGame();
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+GameMenuDialog::GameMenuDialog(MADSEngine *vm) : GameDialog(vm) {
+ setLines();
+}
+
+void GameMenuDialog::setLines() {
+ Font *font = _vm->_font->getFont(FONT_CONVERSATION);
+
+ int yp = 64 - ((font->getHeight() + 1) * 4 + 6) / 2;
+
+ addQuote(10, 0, ALIGN_CENTER, Common::Point(0, yp), font);
+ yp += 6;
+
+ for (int id = 11; id <= 15; ++id) {
+ yp += font->getHeight();
+ addQuote(id, 0, ALIGN_CENTER, Common::Point(0, yp));
+ }
+}
+
+void GameMenuDialog::display() {
+ GameDialog::display();
+ setFrame(1, 2);
+}
+
+void GameMenuDialog::show() {
+ GameDialog::show();
+
+ switch (_selectedLine) {
+ case 1:
+ _vm->_dialogs->_pendingDialog = DIALOG_SAVE;
+ _vm->_dialogs->showDialog();
+ break;
+ case 2:
+ _vm->_dialogs->_pendingDialog = DIALOG_RESTORE;
+ _vm->_dialogs->showDialog();
+ break;
+ case 3:
+ _vm->_dialogs->_pendingDialog = DIALOG_OPTIONS;
+ _vm->_dialogs->showDialog();
+ break;
+ case 4:
+ // Resume game
+ break;
+ case 5:
+ default:
+ _vm->quitGame();
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+OptionsDialog::OptionsDialog(MADSEngine *vm) : GameDialog(vm) {
+ setLines();
+}
+
+int OptionsDialog::getOptionQuote(int option) {
+ Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game;
+
+ // TODO: Hook the rest of the options to the current config
+ switch (option) {
+ case 17: // Music
+ return 24; // 24: ON, 25: OFF
+ case 18: // Sound
+ return 26; // 26: ON, 27: OFF
+ case 19: // Interface
+ return !_vm->_easyMouse ? 28 : 29; // 28: Standard, 29: Easy
+ case 20: // Inventory
+ return _vm->_invObjectsAnimated ? 30 : 31; // 30: Spinning, 31: Still
+ case 21: // Text window
+ return !_vm->_textWindowStill ? 32 : 33; // 32: Animated, 33: Still
+ case 22: // Screen fade
+ return 34 + _vm->_screenFade; // 34: Smooth, 35: Medium, 36: Fast
+ case 23: // Storyline
+ return (game._storyMode == STORYMODE_NAUGHTY) ? 37 : 38; // 37: Naughty, 38: Nice
+ default:
+ error("getOptionQuote: Unknown option");
+ }
+}
+
+void OptionsDialog::setLines() {
+ Font *font = _vm->_font->getFont(FONT_CONVERSATION);
+
+ int yp = 40 - ((font->getHeight() + 1) * 4 + 6) / 2;
+
+ addQuote(16, 0, ALIGN_CENTER, Common::Point(0, yp), font);
+ yp += 6;
+
+ for (int id = 17; id <= 23; ++id) {
+ yp += font->getHeight();
+ addQuote(id, getOptionQuote(id), ALIGN_AT_CENTER, Common::Point(0, yp));
+ }
+
+ yp += 28;
+ addQuote(1, 0, ALIGN_NONE, Common::Point(90, yp));
+ addQuote(2, 0, ALIGN_NONE, Common::Point(190, yp));
+}
+
+void OptionsDialog::display() {
+ GameDialog::display();
+ setFrame(2, 2);
+}
+
+void OptionsDialog::show() {
+ Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game;
+ do {
+ _selectedLine = 0;
+ GameDialog::show();
+
+ switch (_selectedLine) {
+ case 1: // Music
+ warning("STUB: Music toggle");
+ break;
+ case 2: // Sound
+ warning("STUB: Sound toggle");
+ break;
+ case 3: // Interface
+ _vm->_easyMouse = !_vm->_easyMouse;
+ break;
+ case 4: // Inventory
+ _vm->_invObjectsAnimated = !_vm->_invObjectsAnimated;
+ break;
+ case 5: // Text window
+ _vm->_textWindowStill = !_vm->_textWindowStill;
+ break;
+ case 6: // Screen fade
+ if (_vm->_screenFade == SCREEN_FADE_FAST)
+ _vm->_screenFade = SCREEN_FADE_MEDIUM;
+ else if (_vm->_screenFade == SCREEN_FADE_MEDIUM)
+ _vm->_screenFade = SCREEN_FADE_SMOOTH;
+ else
+ _vm->_screenFade = SCREEN_FADE_FAST;
+ break;
+ case 7: // Storyline
+ game._storyMode = (game._storyMode == STORYMODE_NAUGHTY) ? STORYMODE_NICE : STORYMODE_NAUGHTY;
+ break;
+ default:
+ break;
+ }
+
+ // Reload menu
+ _lineIndex = -1;
+ clearLines();
+ setLines();
+ setClickableLines();
+ } while (_selectedLine <= 7);
+
+ switch (_selectedLine) {
+ case 8: // Done
+ // TODO: Copy from temporary config
+ break;
+ case 9: // Cancel
+ // TODO: Ignore all changes to temporary config
+ break;
+ default:
+ break;
+ }
+}
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h
new file mode 100644
index 0000000000..f64f992611
--- /dev/null
+++ b/engines/mads/nebular/dialogs_nebular.h
@@ -0,0 +1,301 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_DIALOGS_NEBULAR_H
+#define MADS_DIALOGS_NEBULAR_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/dialogs.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+#define DIALOG_TOP 22
+
+enum CapitalizationMode { kUppercase = 0, kLowercase = 1, kUpperAndLower = 2 };
+
+class DialogsNebular : public Dialogs {
+ friend class Dialogs;
+private:
+ int _dialogWidth;
+ CapitalizationMode _capitalizationMode;
+
+ DialogsNebular(MADSEngine *vm): Dialogs(vm), _capitalizationMode(kUppercase), _dialogWidth(0) {}
+
+ virtual Common::String getVocab(int vocabId);
+
+ bool textNoun(Common::String &dest, int nounId, const Common::String &source);
+
+ bool commandCheck(const char *idStr, Common::String &valStr, const Common::String &command);
+
+ void showScummVMSaveDialog();
+ void showScummVMRestoreDialog();
+
+public:
+ virtual void showDialog();
+
+ virtual void showItem(int objectId, int messageId, int speech = -1);
+
+ virtual bool show(int messageId, int objectId = -1);
+};
+
+struct HOGANUS {
+ int _bookId;
+ int _pageNum;
+ int _lineNum;
+ int _wordNum;
+ Common::String _word;
+};
+
+class CopyProtectionDialog : public TextDialog {
+private:
+ HOGANUS _hogEntry;
+
+ /**
+ * Get a random copy protection entry from the HOGANUS resource
+ */
+ bool getHogAnusEntry(HOGANUS &entry);
+public:
+ /**
+ * Constructor
+ */
+ CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong);
+
+ /**
+ * Show the dialog
+ */
+ virtual void show();
+};
+
+class PictureDialog : public TextDialog {
+private:
+ int _objectId;
+ bool _cyclingActive;
+ byte _palette[PALETTE_SIZE];
+ uint32 _palFlags[PALETTE_COUNT];
+ RGBList _rgbList;
+protected:
+ virtual void save();
+
+ virtual void restore();
+public:
+ PictureDialog(MADSEngine *vm, const Common::Point &pos, int maxChars, int objectId);
+
+ virtual ~PictureDialog();
+};
+
+enum DialogTextAlign { ALIGN_NONE = 0, ALIGN_CENTER = -1, ALIGN_AT_CENTER = -2, ALIGN_RIGHT = -3 };
+
+enum DialogState { DLGSTATE_UNSELECTED = 0, DLGSTATE_SELECTED = 1, DLGSTATE_FOCUSED = 2 };
+
+class FullScreenDialog: public EventTarget {
+protected:
+ /**
+ * Engine reference
+ */
+ MADSEngine *_vm;
+
+ /**
+ * Screen/scene to show background from
+ */
+ int _screenId;
+
+ /**
+ * Flag for palette initialization
+ */
+ bool _palFlag;
+
+ /**
+ * Handles displaying the screen background and dialog
+ */
+ virtual void display();
+public:
+ /**
+ * Constructor
+ */
+ FullScreenDialog(MADSEngine *vm);
+
+ virtual ~FullScreenDialog();
+};
+
+class GameDialog: public FullScreenDialog {
+ struct DialogLine {
+ bool _active;
+ DialogState _state;
+ Common::Point _pos;
+ int _textDisplayIndex;
+ Common::String _msg;
+ Font *_font;
+ int _widthAdjust;
+
+ DialogLine();
+ DialogLine(const Common::String &s);
+ };
+protected:
+ Common::Array<DialogLine> _lines;
+ int _tempLine;
+ bool _movedFlag;
+ bool _redrawFlag;
+ int _selectedLine;
+ bool _dirFlag;
+ int _menuSpritesIndex;
+ int _lineIndex;
+ int _textLineCount;
+
+ /**
+ * Display the dialog
+ */
+ virtual void display();
+
+ /**
+ * Reset the lines list for the dialog
+ */
+ void clearLines();
+
+ /**
+ * Setup lines to be clickable
+ */
+ void setClickableLines();
+
+ /**
+ * Add a quote to the lines list
+ */
+ void addQuote(int id1, int id2, DialogTextAlign align, const Common::Point &pt, Font *font = nullptr);
+
+ /**
+ * Adds a line to the lines list
+ */
+ void addLine(const Common::String &msg, DialogTextAlign align, const Common::Point &pt, Font *font = nullptr);
+
+ /**
+ * Initializes variables
+ */
+ void initVars();
+
+ /**
+ * Sets the display for the screen background behind the dialog
+ */
+ void setFrame(int frameNumber, int depth);
+
+ /**
+ * Choose the background to display for the dialog
+ */
+ void chooseBackground();
+
+ /**
+ * Handle events whilst the dialog is active
+ */
+ void handleEvents();
+
+ /**
+ * Refresh the display of the dialog's text
+ */
+ void refreshText();
+public:
+ /**
+ * Constructor
+ */
+ GameDialog(MADSEngine *vm);
+
+ /**
+ * Destructor
+ */
+ virtual ~GameDialog();
+
+ /**
+ * Show the dialog
+ */
+ virtual void show();
+};
+
+class DifficultyDialog : public GameDialog {
+private:
+ /**
+ * Set the lines for the dialog
+ */
+ void setLines();
+public:
+ DifficultyDialog(MADSEngine *vm);
+
+ /**
+ * Display the dialog
+ */
+ virtual void display();
+
+ /**
+ * Show the dialog
+ */
+ virtual void show();
+};
+
+class GameMenuDialog : public GameDialog {
+private:
+ /**
+ * Set the lines for the dialog
+ */
+ void setLines();
+public:
+ GameMenuDialog(MADSEngine *vm);
+
+ /**
+ * Display the dialog
+ */
+ virtual void display();
+
+ /**
+ * Show the dialog
+ */
+ virtual void show();
+};
+
+class OptionsDialog : public GameDialog {
+private:
+ /**
+ * Set the lines for the dialog
+ */
+ void setLines();
+
+ /**
+ * Gets the quote to be shown for an option
+ */
+ int getOptionQuote(int option);
+public:
+ OptionsDialog(MADSEngine *vm);
+
+ /**
+ * Display the dialog
+ */
+ virtual void display();
+
+ /**
+ * Show the dialog
+ */
+ virtual void show();
+};
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_DIALOGS_NEBULAR_H */
diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp
new file mode 100644
index 0000000000..902f42507a
--- /dev/null
+++ b/engines/mads/nebular/game_nebular.cpp
@@ -0,0 +1,862 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "graphics/scaler.h"
+#include "mads/mads.h"
+#include "mads/game.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/nebular/game_nebular.h"
+#include "mads/nebular/dialogs_nebular.h"
+#include "mads/nebular/globals_nebular.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+GameNebular::GameNebular(MADSEngine *vm)
+ : Game(vm) {
+ _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+ _storyMode = STORYMODE_NAUGHTY;
+ _difficulty = DIFFICULTY_HARD;
+}
+
+ProtectionResult GameNebular::checkCopyProtection() {
+ /*
+ // DEBUG: Flag copy protection failure
+ _globals[kCopyProtectFailed] = -1;
+
+ if (!ConfMan.getBool("copy_protection"))
+ return true;
+
+ * DEBUG: Disabled for now
+ CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false);
+ dlg->show();
+ delete dlg;
+ */
+ return PROTECTION_SUCCEED;
+}
+
+void GameNebular::startGame() {
+ /*
+ // Check copy protection
+ ProtectionResult protectionResult = checkCopyProtection();
+ switch (protectionResult) {
+ case PROTECTION_FAIL:
+ // Copy protection failed
+ _scene._nextSceneId = 804;
+ initializeGlobals();
+ _globals[kCopyProtectFailed] = true;
+ return;
+ case PROTECTION_ESCAPE:
+ // User escaped out of copy protection dialog
+ _vm->quitGame();
+ return;
+ default:
+ // Copy protection check succeeded
+ break;
+ }
+ */
+
+ initSection(_sectionNumber);
+ _statusFlag = true;
+
+ // Show the main menu
+ _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
+ _vm->_dialogs->showDialog();
+ _vm->_dialogs->_pendingDialog = DIALOG_NONE;
+
+ _priorSectionNumber = 0;
+ _priorSectionNumber = -1;
+ _scene._priorSceneId = 0;
+ _scene._currentSceneId = -1;
+ _scene._nextSceneId = 101;
+
+ initializeGlobals();
+}
+
+void GameNebular::initializeGlobals() {
+ int count, count2;
+ int bad;
+
+ _globals.reset();
+ _globals[kTalkInanimateCount] = 8;
+
+ /* Section #1 variables */
+ _globals[kNeedToStandUp] = true;
+ _globals[kTurkeyExploded] = false;
+ _globals[kMedicineCabinetOpen] = false;
+ _globals[kMedicineCabinetVirgin] = true;
+ _globals[kWatchedViewScreen] = false;
+ _globals[kHoovicAlive] = true;
+ _globals[kWaterInAPuddle] = false;
+
+ _globals[kFishIn105] = true;
+ _globals[kFishIn107] = true;
+ _globals[kFishIn108] = true;
+
+ /* Section #2 variables */
+ _globals[kLadderBroken] = false;
+ _globals[kBone202Status] = 0;
+ _globals[kRhotundaStatus] = RHOTUNDA_HUNGRY;
+ _globals[kMonkeyStatus] = MONKEY_AMBUSH_READY;
+ _globals[kMeteorologistStatus] = METEOROLOGIST_PRESENT;
+ _globals[kMeteorologistEverSeen] = false;
+ _globals[kMeteorologistWatch] = METEOROLOGIST_NORMAL;
+ _globals[kTeleporterCommand] = TELEPORTER_NONE;
+ _globals[kTeleporterUnderstood] = false;
+ _globals[kTwinklesStatus] = TWINKLES_AT_HOME;
+ _globals[kTwinklesApproached] = 0;
+
+ /* Section #3 variables */
+ _globals[kAfterHavoc] = false;
+ _globals[kKickedIn391Grate] = false;
+
+ /* Section #4 variables */
+ _globals[kBadFirstIngredient] = -1;
+ _objects[OBJ_CHARGE_CASES].setQuality(EXPLOSIVES_INSIDE, 0);
+ _globals[kHasPurchased] = false;
+ _globals[kBeenThruHelgaScene] = false;
+ _globals[kNextIngredient] = 0;
+ _globals[kHasSaidTimer] = false;
+ _globals[kHasSaidBinocs] = false;
+ _globals[kBottleDisplayed] = false;
+ _globals[kHasBeenScanned] = false;
+ _globals[kSomeoneHasExploded] = false;
+
+ // Generate a random ingredient list
+ for (count = 0; count < 4; ++count) {
+ do {
+ _globals[kIngredientList + count] = _vm->getRandomNumber(3);
+ bad = false;
+ for (count2 = 0; count2 < count; ++count2) {
+ if (_globals[kIngredientList + count] == _globals[kIngredientList + count2]) {
+ bad = true;
+ }
+ }
+ } while (bad);
+ }
+
+ // Generate random ingredient quantities
+ for (count = 0; count < 4; ++count) {
+ do {
+ _globals[kIngredientQuantity + count] = _vm->getRandomNumber(3);
+ bad = false;
+ for (count2 = 0; count2 < count; ++count2) {
+ if (_globals[kIngredientQuantity + count] == _globals[kIngredientQuantity + count2]) {
+ bad = true;
+ }
+ }
+ } while (bad);
+ }
+
+
+ /* Section #5 variables */
+ _globals[kHoverCarLocation] = 501;
+ _globals[kHoverCarDestination] = -1;
+ _globals[kCityFlooded] = false;
+ _globals[kBoatRaised] = true;
+ _globals[kLaserHoleIsThere] = false;
+ _globals[kLineStatus] = LINE_NOT_DROPPED;
+
+
+ /* Section #6 variables */
+ _globals[kHasTalkedToHermit] = false;
+ _globals[kHandsetCellStatus] = FIRST_TIME_PHONE_CELLS;
+ _globals[kTimebombStatus] = TIMEBOMB_DEACTIVATED;
+ _globals[kWarnedFloodCity] = false;
+ _globals._timebombClock = 0;
+ _globals._timebombTimer = 0;
+
+
+ /* Section #7 variables */
+ _globals[kBottleStatus] = BOTTLE_EMPTY;
+ _globals[kBoatStatus] = BOAT_UNFLOODED;
+
+
+ /* Section #8 variables */
+ _globals[kWindowFixed] = false;
+ _globals[kInSpace] = false;
+ _globals[kReturnFromCut] = false;
+ _globals[kBeamIsUp] = false;
+ _globals[kForceBeamDown] = false;
+ _globals[kCameFromCut] = false;
+ _globals[kDontRepeat] = false;
+ _globals[kHoppyDead] = false;
+ _globals[kHasWatchedAntigrav] = false;
+ _globals[kRemoteSequenceRan] = false;
+ _globals[kRemoteOnGround] = false;
+ _globals[kFromCockpit] = false;
+ _globals[kExitShip] = false;
+ _globals[kBetweenRooms] = false;
+ _globals[kTopButtonPushed] = false;
+ _globals[kShieldModInstalled] = false;
+ _globals[kTargetModInstalled] = false;
+ _globals[kUpBecauseOfRemote] = false;
+
+
+ /* Set up the game's teleporters */
+ _globals[kTeleporterRoom] = 201;
+ _globals[kTeleporterRoom + 1] = 301;
+ _globals[kTeleporterRoom + 2] = 413;
+ _globals[kTeleporterRoom + 3] = 706;
+ _globals[kTeleporterRoom + 4] = 801;
+ _globals[kTeleporterRoom + 5] = 551;
+ _globals[kTeleporterRoom + 6] = 752;
+ _globals[kTeleporterRoom + 7] = 0;
+ _globals[kTeleporterRoom + 8] = 0;
+ _globals[kTeleporterRoom + 9] = 0;
+
+ for (count = 0; count < TELEPORTER_COUNT; ++count) {
+ do {
+ _globals[kTeleporterCode + count] = _vm->getRandomNumber(9999);
+ bad = false;
+ for (count2 = 0; count2 < count; ++count2) {
+ if (_globals[kTeleporterCode + count] == _globals[kTeleporterCode + count2]) {
+ bad = true;
+ }
+ }
+ } while (bad);
+ }
+
+ // Final setup based on selected difficulty level
+ switch (_difficulty) {
+ case DIFFICULTY_HARD:
+ _objects.setRoom(OBJ_PLANT_STALK, NOWHERE);
+ _objects.setRoom(OBJ_PENLIGHT, NOWHERE);
+
+ _globals[kLeavesStatus] = LEAVES_ON_TRAP;
+ break;
+
+ case DIFFICULTY_MEDIUM:
+ _objects.setRoom(OBJ_PLANT_STALK, NOWHERE);
+
+ _globals[kLeavesStatus] = LEAVES_ON_GROUND;
+ _globals[kDurafailRecharged] = 1;
+ _globals[kPenlightCellStatus] = FIRST_TIME_CHARGED_DURAFAIL;
+ break;
+
+ case DIFFICULTY_EASY:
+ _objects.setRoom(OBJ_BLOWGUN, NOWHERE);
+ _objects.setRoom(OBJ_NOTE, NOWHERE);
+
+ _globals[kLeavesStatus] = LEAVES_ON_GROUND;
+ _globals[kPenlightCellStatus] = FIRST_TIME_UNCHARGED_DURAFAIL;
+ _globals[kDurafailRecharged] = 0;
+ break;
+ }
+
+ _player._facing = FACING_NORTH;
+ _player._turnToFacing = FACING_NORTH;
+
+ Player::preloadSequences("RXM", 1);
+ Player::preloadSequences("ROX", 1);
+}
+
+void GameNebular::setSectionHandler() {
+ delete _sectionHandler;
+
+ switch (_sectionNumber) {
+ case 1:
+ _sectionHandler = new Section1Handler(_vm);
+ break;
+ case 2:
+ _sectionHandler = new Section2Handler(_vm);
+ break;
+ case 3:
+ _sectionHandler = new Section3Handler(_vm);
+ break;
+ case 4:
+ _sectionHandler = new Section4Handler(_vm);
+ break;
+ case 5:
+ _sectionHandler = new Section5Handler(_vm);
+ break;
+ case 6:
+ _sectionHandler = new Section6Handler(_vm);
+ break;
+ case 7:
+ _sectionHandler = new Section7Handler(_vm);
+ break;
+ case 8:
+ _sectionHandler = new Section8Handler(_vm);
+ break;
+ default:
+ break;
+ }
+}
+
+void GameNebular::checkShowDialog() {
+ if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[kCopyProtectFailed]) {
+ _player.releasePlayerSprites();
+
+ // Make a thumbnail in case it's needed for making a savegame
+ _vm->_game->createThumbnail();
+
+ // Show the dialog
+ _vm->_dialogs->showDialog();
+ _vm->_dialogs->_pendingDialog = DIALOG_NONE;
+ }
+}
+
+void GameNebular::showRecipe() {
+ Dialogs &dialogs = *_vm->_dialogs;
+ int count;
+
+ for (count = 0; count < 4; count++) {
+ switch(_globals[kIngredientQuantity + count]) {
+ case 0:
+ dialogs._indexList[count] = NOUN_DROP;
+ break;
+ case 1:
+ dialogs._indexList[count] = NOUN_DOLLOP;
+ break;
+ case 2:
+ dialogs._indexList[count] = NOUN_DASH;
+ break;
+ case 3:
+ dialogs._indexList[count] = NOUN_SPLASH;
+ break;
+ default:
+ break;
+ }
+ }
+
+ for (count = 0; count < 4; count++) {
+ switch(_globals[kIngredientList + count]) {
+ case 0:
+ dialogs._indexList[count + 4] = NOUN_ALCOHOL;
+ break;
+ case 1:
+ dialogs._indexList[count + 4] = NOUN_LECITHIN;
+ break;
+ case 2:
+ dialogs._indexList[count + 4] = NOUN_PETROX;
+ break;
+ case 3:
+ dialogs._indexList[count + 4] = NOUN_FORMALDEHYDE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ _vm->_dialogs->show(401);
+}
+
+void GameNebular::doObjectAction() {
+ Scene &scene = _scene;
+ MADSAction &action = _scene._action;
+ Dialogs &dialogs = *_vm->_dialogs;
+ int id;
+
+ if (action.isAction(VERB_SMELL) && scene._currentSceneId > 103 && scene._currentSceneId < 111) {
+ dialogs.show(440);
+ } else if (action.isAction(VERB_EAT) && scene._currentSceneId > 103 && scene._currentSceneId < 111) {
+ dialogs.show(441);
+ } else if (action.isAction(VERB_SMELL, NOUN_BURGER)) {
+ dialogs.show(442);
+ } else if (action.isAction(VERB_EAT, NOUN_BURGER)) {
+ dialogs.show(443);
+ } else if (action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) {
+ dialogs.show(444);
+ } else if (action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) {
+ dialogs.show(445);
+ } else if (action.isAction(VERB_WEAR, NOUN_REBREATHER)) {
+ dialogs.show(scene._currentSceneId > 103 && scene._currentSceneId < 111 ? 446 : 447);
+ } else if (action.isAction(VERB_SET, NOUN_TIMER_MODULE)) {
+ dialogs.show(448);
+ } else if (action.isAction(VERB_NIBBLE_ON, NOUN_BIG_LEAVES)) {
+ dialogs.show(449);
+ } else if (action.isAction(VERB_LICK, NOUN_POISON_DARTS)) {
+ dialogs.show(450);
+ } else if (action.isAction(VERB_EAT, NOUN_TWINKIFRUIT)) {
+ _objects.setRoom(OBJ_TWINKIFRUIT, NOWHERE);
+ dialogs.show(451);
+ } else if (action.isAction(VERB_GORGE_ON, NOUN_TWINKIFRUIT)) {
+ _objects.setRoom(OBJ_TWINKIFRUIT, NOWHERE);
+ dialogs.show(452);
+ } else if (action.isAction(VERB_GNAW_ON)) {
+ dialogs.show(453);
+ } else if (action.isAction(VERB_MASSAGE, NOUN_AUDIO_TAPE)) {
+ dialogs.show(454);
+ } else if (action.isAction(VERB_MANGLE, NOUN_CREDIT_CHIP)) {
+ dialogs.show(455);
+ } else if (action.isAction(VERB_FONDLE, NOUN_CHARGE_CASES)) {
+ dialogs.show(456);
+ } else if (action.isAction(VERB_RUB, NOUN_BOMB)) {
+ dialogs.show(457);
+ } else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) {
+ dialogs.show(458);
+ } else if (action.isAction(VERB_GUZZLE, NOUN_ALIEN_LIQUOR)) {
+ dialogs.show(459);
+ } else if (action.isAction(VERB_SMASH, NOUN_TARGET_MODULE)) {
+ dialogs.show(460);
+ } else if (action.isAction(VERB_JUGGLE)) {
+ dialogs.show(461);
+ } else if (action.isAction(VERB_APPLY, NOUN_POLYCEMENT)) {
+ dialogs.show(462);
+ } else if (action.isAction(VERB_SNIFF, NOUN_POLYCEMENT)) {
+ dialogs.show(465);
+ } else if (action.isAction(VERB_TIE, NOUN_FISHING_LINE)) {
+ dialogs.show(463);
+ } else if (action.isAction(VERB_ATTACH, NOUN_FISHING_LINE)) {
+ dialogs.show(463);
+ } else if (action.isAction(VERB_UNLOCK)) {
+ dialogs.show(464);
+ } else if (action.isAction(VERB_REFLECT)) {
+ dialogs.show(466);
+ } else if (action.isAction(VERB_GAZE_INTO, NOUN_REARVIEW_MIRROR)) {
+ dialogs.show(467);
+ } else if (action.isAction(VERB_EAT, NOUN_CHICKEN_BOMB)) {
+ dialogs.show(469);
+ } else if (action.isAction(VERB_BREAK, NOUN_VASE)) {
+ dialogs.show(471);
+ } else if (action.isAction(VERB_SHAKE_HANDS, NOUN_GUARDS_ARM2)) {
+ dialogs.show(472);
+ } else if (action.isAction(VERB_READ, NOUN_LOG)) {
+ dialogs.show(473);
+ } else if (action.isAction(VERB_RUB, NOUN_BOMBS)) {
+ dialogs.show(474);
+ } else if (action.isAction(VERB_DRINK, NOUN_FORMALDEHYDE)) {
+ dialogs.show(475);
+ } else if (action.isAction(VERB_DRINK, NOUN_PETROX)) {
+ dialogs.show(476);
+ } else if (action.isAction(VERB_DRINK, NOUN_LECITHIN)) {
+ dialogs.show(477);
+ } else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_PLANT_STALK) && _objects.isInInventory(OBJ_POISON_DARTS)
+ && _objects.isInInventory(OBJ_PLANT_STALK)) {
+ _objects.addToInventory(OBJ_BLOWGUN);
+ _objects.setRoom(OBJ_PLANT_STALK, NOWHERE);
+ _globals[kBlowgunStatus] = 0;
+ dialogs.showItem(OBJ_BLOWGUN, 809);
+ } else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_BLOWGUN) && _objects.isInInventory(OBJ_POISON_DARTS)
+ && _objects.isInInventory(OBJ_BLOWGUN)) {
+ dialogs.show(433);
+ } else if (action.isAction(VERB_DEFACE) && action.isAction(VERB_FOLD) && action.isAction(VERB_MUTILATE)) {
+ dialogs.show(434);
+ } else if (action.isAction(VERB_SPINDLE)) {
+ dialogs.show(479);
+ } else if ((action.isAction(VERB_READ) || action.isAction(VERB_LOOK_AT) || action.isAction(VERB_LOOK)) &&
+ action.isObject(NOUN_NOTE) && _objects.isInInventory(OBJ_NOTE)) {
+ _objects.setRoom(OBJ_NOTE, NOWHERE);
+ _objects.addToInventory(OBJ_COMBINATION);
+ dialogs.showItem(OBJ_COMBINATION, 851);
+ } else if ((action.isAction(VERB_LOOK) || action.isAction(VERB_READ)) &&
+ ((id = _objects.getIdFromDesc(action._activeAction._objectNameId)) > 0 ||
+ (action._activeAction._indirectObjectId > 0 &&
+ (id = _objects.getIdFromDesc(action._activeAction._indirectObjectId)))) &&
+ _objects.isInInventory(id)) {
+ if (id == OBJ_REPAIR_LIST) {
+ dialogs._indexList[0] = _globals[kTeleporterCode + 7];
+ dialogs._indexList[1] = _globals[kTeleporterCode + 8];
+ dialogs._indexList[2] = _globals[kTeleporterCode + 6];
+ dialogs._indexList[3] = _globals[kTeleporterCode + 9];
+ dialogs._indexList[4] = _globals[kTeleporterCode + 0];
+ dialogs._indexList[5] = _globals[kTeleporterCode + 1];
+ dialogs._indexList[6] = _globals[kTeleporterCode + 4];
+ dialogs._indexList[7] = _globals[kTeleporterCode + 5];
+ dialogs._indexList[8] = _globals[kTeleporterCode + 2];
+
+ dialogs.showItem(id, 402);
+ } else {
+ int messageId = 800 + id;
+ if ((id == OBJ_CHARGE_CASES) && _objects[OBJ_CHARGE_CASES].getQuality(3) != 0) {
+ messageId = 860;
+ }
+
+ if (id == OBJ_TAPE_PLAYER && _objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER)
+ messageId = 867;
+
+ if (id == 32 && _objects[OBJ_FISHING_LINE]._roomNumber == 3)
+ messageId = 862;
+
+ if (id == OBJ_BOTTLE && _globals[kBottleStatus] != 0)
+ messageId = 862 + _globals[kBottleStatus];
+
+ if (id == OBJ_PHONE_HANDSET && _globals[kHandsetCellStatus])
+ messageId = 861;
+
+ dialogs.showItem(id, messageId);
+ }
+ } else if (action.isAction(VERB_PUT, NOUN_BURGER, NOUN_DEAD_FISH)) {
+ if (_objects.isInInventory(OBJ_BURGER) || _objects.isInInventory(OBJ_DEAD_FISH)) {
+ _objects.removeFromInventory(OBJ_DEAD_FISH, PLAYER_INVENTORY);
+ _objects.removeFromInventory(OBJ_BURGER, PLAYER_INVENTORY);
+ _objects.addToInventory(OBJ_STUFFED_FISH);
+ dialogs.showItem(OBJ_STUFFED_FISH, 803);
+ }
+ } else if (action.isAction(VERB_PUT, NOUN_AUDIO_TAPE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_AUDIO_TAPE) &&
+ _objects.isInInventory(OBJ_TAPE_PLAYER)) {
+ _objects.setRoom(OBJ_AUDIO_TAPE, OBJ_TAPE_PLAYER);
+ } else if (action.isAction(VERB_ACTIVATE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) {
+ if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) {
+ showRecipe();
+ } else {
+ dialogs.show(406);
+ }
+ } else if (action.isAction(VERB_EJECT, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) {
+ if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) {
+ _objects.addToInventory(OBJ_AUDIO_TAPE);
+ } else {
+ dialogs.show(407);
+ }
+ } else if (action.isAction(VERB_DISASSEMBLE, NOUN_TAPE_PLAYER)) {
+ dialogs.show(408);
+ } else if (action.isAction(VERB_ACTIVATE, NOUN_REMOTE)) {
+ dialogs.show(_globals[kTopButtonPushed] ? 502 : 501);
+ } else if ((action.isAction(VERB_ATTACH, NOUN_DETONATORS, NOUN_CHARGE_CASES) || action.isAction(VERB_PUT, NOUN_DETONATORS, NOUN_CHARGE_CASES)) &&
+ _objects.isInInventory(OBJ_DETONATORS) && _objects.isInInventory(OBJ_CHARGE_CASES)) {
+ if (_objects[OBJ_CHARGE_CASES].getQuality(3)) {
+ _objects.setRoom(OBJ_CHARGE_CASES, NOWHERE);
+ _objects.setRoom(OBJ_DETONATORS, NOWHERE);
+ _objects.addToInventory(OBJ_BOMBS);
+ dialogs.showItem(OBJ_BOMBS, 403);
+ } else {
+ dialogs.show(405);
+ }
+ } else if (action.isAction(VERB_ATTACH, NOUN_DETONATORS)) {
+ dialogs.show(470);
+ } else if ((action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMB)
+ || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMB)) && _objects.isInInventory(OBJ_TIMER_MODULE) && (
+ _objects.isInInventory(OBJ_BOMBS) || _objects.isInInventory(OBJ_BOMB))) {
+ if (_objects.isInInventory(OBJ_BOMBS)) {
+ _objects.setRoom(OBJ_BOMBS, NOWHERE);
+ _objects.addToInventory(OBJ_BOMB);
+ } else {
+ _objects.setRoom(OBJ_BOMB, NOWHERE);
+ }
+
+ _objects.setRoom(OBJ_TIMER_MODULE, NOWHERE);
+ _objects.addToInventory(OBJ_TIMEBOMB);
+ dialogs.showItem(OBJ_TIMEBOMB, 404);
+ } else if (action.isAction(VERB_FONDLE, NOUN_PLANT_STALK)) {
+ dialogs.show(410);
+ } else if (action.isAction(VERB_EMPTY, NOUN_BOTTLE)) {
+ _globals[kBottleStatus] = 0;
+ dialogs.show(432);
+ } else if (action.isAction(VERB_DISASSEMBLE, NOUN_FISHING_ROD)) {
+ if (_objects[OBJ_FISHING_LINE]._roomNumber == 3) {
+ _objects.addToInventory(OBJ_FISHING_LINE);
+ dialogs.showItem(OBJ_FISHING_LINE, 409);
+ } else {
+ dialogs.show(428);
+ }
+ } else if (action.isAction(VERB_DISASSEMBLE, NOUN_PENLIGHT)) {
+ switch (_globals[kPenlightCellStatus]) {
+ case 1:
+ case 2:
+ _objects.addToInventory(OBJ_DURAFAIL_CELLS);
+ dialogs.showItem(OBJ_DURAFAIL_CELLS, 412);
+ break;
+ case 3:
+ _objects.addToInventory(OBJ_PHONE_CELLS);
+ dialogs.showItem(OBJ_DURAFAIL_CELLS, 413);
+ break;
+ case 5:
+ _objects.addToInventory(OBJ_DURAFAIL_CELLS);
+ dialogs.showItem(OBJ_DURAFAIL_CELLS, 411);
+ break;
+ case 6:
+ _objects.addToInventory(OBJ_DURAFAIL_CELLS);
+ dialogs.showItem(OBJ_DURAFAIL_CELLS, 429);
+ break;
+ default:
+ dialogs.show(478);
+ break;
+ }
+ } else if (action.isAction(VERB_DISASSEMBLE, NOUN_PHONE_HANDSET)) {
+ switch (_globals[kHandsetCellStatus]) {
+ case 1:
+ _objects.addToInventory(OBJ_DURAFAIL_CELLS);
+ dialogs.showItem(OBJ_DURAFAIL_CELLS,
+ _difficulty != DIFFICULTY_HARD || _globals[kDurafailRecharged] ? 415 : 414);
+ _globals[kDurafailRecharged] = true;
+ break;
+ case 2:
+ _objects.addToInventory(OBJ_DURAFAIL_CELLS);
+ if (_difficulty == DIFFICULTY_HARD) {
+ dialogs.showItem(OBJ_DURAFAIL_CELLS, 416);
+ }
+ _globals[kHandsetCellStatus] = 0;
+ break;
+ case 3:
+ _objects.addToInventory(OBJ_PHONE_CELLS);
+ dialogs.showItem(OBJ_PHONE_CELLS, 418);
+ break;
+ case 4:
+ _objects.addToInventory(OBJ_PHONE_CELLS);
+ dialogs.showItem(OBJ_PHONE_CELLS, 417);
+ _globals[kHandsetCellStatus] = 0;
+ break;
+ default:
+ dialogs.show(478);
+ break;
+ }
+ } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PENLIGHT)) {
+ if (_globals[kPenlightCellStatus] == 0) {
+ _globals[kPenlightCellStatus] = 3;
+ _objects.setRoom(OBJ_PHONE_CELLS, NOWHERE);
+ dialogs.show(419);
+ } else {
+ dialogs.show(420);
+ }
+ } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PHONE_HANDSET)) {
+ if (_globals[kHandsetCellStatus] == 0) {
+ _globals[kHandsetCellStatus] = 3;
+ _objects.setRoom(OBJ_PHONE_CELLS, NOWHERE);
+ dialogs.show(421);
+ } else {
+ dialogs.show(422);
+ }
+ } else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PENLIGHT)) {
+ if (_globals[kPenlightCellStatus]) {
+ dialogs.show(424);
+ } else {
+ _objects.setRoom(OBJ_DURAFAIL_CELLS, NOWHERE);
+ _globals[kPenlightCellStatus] = _difficulty != DIFFICULTY_HARD || _globals[kDurafailRecharged] ? 1 : 2;
+ dialogs.show(423);
+ }
+ } else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PHONE_HANDSET)) {
+ if (_globals[kHandsetCellStatus]) {
+ dialogs.show(426);
+ } else {
+ _objects.setRoom(OBJ_DURAFAIL_CELLS, NOWHERE);
+ _globals[kHandsetCellStatus] = _difficulty != DIFFICULTY_HARD || _globals[kHandsetCellStatus] ? 1 : 2;
+ dialogs.show(425);
+ }
+ } else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) {
+ dialogs.show(427);
+ } else if (action.isAction(VERB_PUT, NOUN_BOMB, NOUN_CHICKEN) || action.isAction(VERB_PUT, NOUN_BOMBS, NOUN_CHICKEN)) {
+ _objects.setRoom(OBJ_CHICKEN, NOWHERE);
+ if (_objects.isInInventory(OBJ_BOMBS)) {
+ _objects.setRoom(OBJ_BOMBS, NOWHERE);
+ _objects.addToInventory(OBJ_BOMB);
+ } else {
+ _objects.setRoom(OBJ_BOMB, NOWHERE);
+ }
+
+ _objects.addToInventory(OBJ_CHICKEN_BOMB);
+ dialogs.showItem(OBJ_CHICKEN_BOMB, 430);
+ } else {
+ return;
+ }
+
+ action._inProgress = false;
+}
+
+void GameNebular::unhandledAction() {
+ int randVal = _vm->getRandomNumber(1, 1000);
+ MADSAction &action = _scene._action;
+
+ if (action.isAction(VERB_THROW, NOUN_BOMB) || action.isAction(VERB_THROW, NOUN_BOMBS)
+ || action.isAction(VERB_THROW, NOUN_TIMEBOMB) || action.isAction(VERB_THROW, NOUN_CHICKEN_BOMB))
+ _vm->_dialogs->show(42);
+ else if (action.isAction(VERB_DISASSEMBLE))
+ _vm->_dialogs->show(435);
+ else if ((action.isAction(VERB_EAT, NOUN_DEAD_FISH) || action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId)))
+ _vm->_dialogs->show(12);
+ else if ((action.isAction(VERB_SMELL, NOUN_DEAD_FISH) || action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId)))
+ _vm->_dialogs->show(13);
+ else if (action.isAction(VERB_EAT, NOUN_CHICKEN) && _vm->_game->_objects.isInInventory(OBJ_CHICKEN))
+ _vm->_dialogs->show(912);
+ else if ((action.isAction(VERB_SHOOT) || action.isAction(VERB_HOSE_DOWN)) && action.isObject(NOUN_BLOWGUN)) {
+ if ((_scene._currentSceneId >= 104) && (_scene._currentSceneId <= 111))
+ _vm->_dialogs->show(38);
+ else if (action.isObject(NOUN_PIRANHA))
+ _vm->_dialogs->show(41);
+ else if (action.isObject(NOUN_CHICKEN) || action.isObject(NOUN_VULTURE) || action.isObject(NOUN_SPIDER)
+ || action.isObject(NOUN_YELLOW_BIRD) || action.isObject(NOUN_SWOOPING_CREATURE) || action.isObject(NOUN_CAPTIVE_CREATURE)) {
+ _vm->_dialogs->show(40);
+ } else
+ _vm->_dialogs->show(39);
+ } else if (action.isAction(VERB_TALKTO)) {
+ _globals[kTalkInanimateCount] = (_globals[kTalkInanimateCount] + 1) % 16;
+ if (!_globals[kTalkInanimateCount]) {
+ _vm->_dialogs->show(2);
+ } else {
+ Common::String tmpMsg = "\"Greetings, ";
+ tmpMsg += _vm->_game->_scene.getVocab(action._activeAction._objectNameId);
+ tmpMsg += "!\"";
+ _scene._kernelMessages.reset();
+ _scene._kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, tmpMsg);
+ }
+ } else if (action.isAction(VERB_GIVE, NOUN_DOOR, NOUN_CEILING) || action.isAction(VERB_CLOSE, NOUN_CHAIR))
+ _vm->_dialogs->show(3);
+ else if (action.isAction(VERB_THROW)) {
+ int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
+ if (objId < 0)
+ _vm->_dialogs->show(4);
+ else if (_vm->_game->_objects[objId]._roomNumber != 2)
+ _vm->_dialogs->show(5);
+ else
+ _vm->_dialogs->show(6);
+ } else if (action.isAction(VERB_LOOK)) {
+ if (action.isObject(NOUN_BINOCULARS) && (action._activeAction._indirectObjectId > 0))
+ _vm->_dialogs->show(10);
+ else if (randVal < 600)
+ _vm->_dialogs->show(7);
+ else
+ _vm->_dialogs->show(21);
+ } else if (action.isAction(VERB_TAKE)) {
+ int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
+ if (_vm->_game->_objects.isInInventory(objId))
+ _vm->_dialogs->show(16);
+ else if (randVal <= 333)
+ _vm->_dialogs->show(8);
+ else if (randVal <= 666)
+ _vm->_dialogs->show(22);
+ else
+ _vm->_dialogs->show(23);
+ } else if (action.isAction(VERB_CLOSE)) {
+ if (randVal <= 333)
+ _vm->_dialogs->show(9);
+ else
+ _vm->_dialogs->show(33);
+ } else if (action.isAction(VERB_OPEN)) {
+ if (randVal <= 500)
+ _vm->_dialogs->show(30);
+ else if (randVal <= 750)
+ _vm->_dialogs->show(31);
+ else
+ _vm->_dialogs->show(32);
+ } else if (action.isAction(VERB_PULL))
+ _vm->_dialogs->show(18);
+ else if (action.isAction(VERB_PUSH)) {
+ if (randVal < 750)
+ _vm->_dialogs->show(19);
+ else
+ _vm->_dialogs->show(20);
+ } else if (action.isAction(VERB_PUT)) {
+ int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
+ if (_vm->_game->_objects.isInInventory(objId))
+ _vm->_dialogs->show(25);
+ else
+ _vm->_dialogs->show(24);
+ } else if (action.isAction(VERB_GIVE)) {
+ int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
+ if (!_vm->_game->_objects.isInInventory(objId))
+ _vm->_dialogs->show(26);
+ else if (randVal <= 500)
+ _vm->_dialogs->show(28);
+ else
+ _vm->_dialogs->show(29);
+ } else if (!action.isAction(VERB_WALKTO) && !action.isAction(VERB_WALK_ACROSS) && !action.isAction(VERB_WALK_TOWARDS) && !action.isAction(VERB_WALK_DOWN)
+ && !action.isAction(VERB_SWIM_TO) && !action.isAction(VERB_SWIM_ACROSS) && !action.isAction(VERB_SWIM_INTO) && !action.isAction(VERB_SWIM_THROUGH)
+ && !action.isAction(VERB_SWIM_UNDER)) {
+ if (randVal <= 100)
+ _vm->_dialogs->show(36);
+ else if (randVal <= 200)
+ _vm->_dialogs->show(1);
+ else if (randVal <= 475)
+ _vm->_dialogs->show(34);
+ else if (randVal <= 750)
+ _vm->_dialogs->show(35);
+ else
+ _vm->_dialogs->show(37);
+ }
+}
+
+void GameNebular::step() {
+ if (_player._visible && _player._stepEnabled && !_player._moving &&
+ (_player._facing == _player._turnToFacing)) {
+ if (_scene._frameStartTime >= *((uint32 *)&_globals[kWalkerTiming])) {
+ if (!_player._stopWalkerIndex) {
+ int randomVal = _vm->getRandomNumber(29999);;
+ if (_globals[kSexOfRex] == REX_MALE) {
+ switch (_player._facing) {
+ case FACING_SOUTHWEST:
+ case FACING_SOUTHEAST:
+ case FACING_NORTHWEST:
+ case FACING_NORTHEAST:
+ if (randomVal < 200) {
+ _player.addWalker(-1, 0);
+ _player.addWalker(1, 0);
+ }
+ break;
+
+ case FACING_WEST:
+ case FACING_EAST:
+ if (randomVal < 500) {
+ for (int count = 0; count < 10; ++count) {
+ _player.addWalker(1, 0);
+ }
+ }
+ break;
+
+ case FACING_SOUTH:
+ if (randomVal < 500) {
+ for (int count = 0; count < 10; ++count) {
+ _player.addWalker((randomVal < 250) ? 1 : 2, 0);
+ }
+ } else if (randomVal < 750) {
+ for (int count = 0; count < 5; ++count) {
+ _player.addWalker(1, 0);
+ }
+
+ _player.addWalker(0, 0);
+ _player.addWalker(0, 0);
+
+ for (int count = 0; count < 5; ++count) {
+ _player.addWalker(2, 0);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ *((uint32 *)&_globals[kWalkerTiming]) += 6;
+ }
+ }
+
+ // Below is countdown to set the timebomb off in room 604
+ if (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) {
+ int diff = _scene._frameStartTime - *((uint32 *)&_globals[kTimebombClock]);
+ if ((diff >= 0) && (diff <= 60)) {
+ *((uint32 *)&_globals[kTimebombTimer]) += diff;
+ } else {
+ ++*((uint32 *)&_globals[kTimebombTimer]);
+ }
+ *((uint32 *)&_globals[kTimebombClock]) = _scene._frameStartTime;
+ }
+}
+
+void GameNebular::synchronize(Common::Serializer &s, bool phase1) {
+ Game::synchronize(s, phase1);
+
+ if (phase1) {
+ _globals.synchronize(s);
+ s.syncAsByte(_storyMode);
+ s.syncAsByte(_difficulty);
+ }
+}
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
diff --git a/engines/mads/nebular/game_nebular.h b/engines/mads/nebular/game_nebular.h
new file mode 100644
index 0000000000..da607d47ee
--- /dev/null
+++ b/engines/mads/nebular/game_nebular.h
@@ -0,0 +1,160 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_GAME_NEBULAR_H
+#define MADS_GAME_NEBULAR_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/globals.h"
+#include "mads/nebular/globals_nebular.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 };
+
+enum Difficulty {
+ DIFFICULTY_HARD = 1, DIFFICULTY_MEDIUM = 2, DIFFICULTY_EASY = 3
+};
+
+
+enum ProtectionResult {
+ PROTECTION_SUCCEED = 0, PROTECTION_FAIL = 1, PROTECTION_ESCAPE = 2
+};
+
+enum InventoryObject {
+ OBJ_NONE = -1,
+ OBJ_BINOCULARS = 0,
+ OBJ_BURGER = 1,
+ OBJ_DEAD_FISH = 2,
+ OBJ_STUFFED_FISH = 3,
+ OBJ_REBREATHER = 4,
+ OBJ_TIMER_MODULE = 5,
+ OBJ_BIG_LEAVES = 6,
+ OBJ_POISON_DARTS = 7,
+ OBJ_PLANT_STALK = 8,
+ OBJ_BLOWGUN = 9,
+ OBJ_TWINKIFRUIT = 10,
+ OBJ_BONE = 11,
+ OBJ_CHICKEN = 12,
+ OBJ_SCALPEL = 13,
+ OBJ_AUDIO_TAPE = 14,
+ OBJ_CREDIT_CHIP = 15,
+ OBJ_SECURITY_CARD = 16,
+ OBJ_CHARGE_CASES = 17,
+ OBJ_ESTROTOXIN = 18,
+ OBJ_BOMB = 19,
+ OBJ_TIMEBOMB = 20,
+ OBJ_REPAIR_LIST = 21,
+ OBJ_ALIEN_LIQUOR = 22,
+ OBJ_TARGET_MODULE = 23,
+ OBJ_SHIELD_MODULATOR = 24,
+ OBJ_TAPE_PLAYER = 25,
+ OBJ_PHONE_CELLS = 26,
+ OBJ_PENLIGHT = 27,
+ OBJ_DURAFAIL_CELLS = 28,
+ OBJ_FAKE_ID = 29,
+ OBJ_ID_CARD = 30,
+ OBJ_POLYCEMENT = 31,
+ OBJ_FISHING_ROD = 32,
+ OBJ_FISHING_LINE = 33,
+ OBJ_PADLOCK_KEY = 34,
+ OBJ_DOOR_KEY = 35,
+ OBJ_REARVIEW_MIRROR = 36,
+ OBJ_COMPACT_CASE = 37,
+ OBJ_DETONATORS = 39,
+ OBJ_BOTTLE = 40,
+ OBJ_CHICKEN_BOMB = 41,
+ OBJ_VASE = 42,
+ OBJ_REMOTE = 43,
+ OBJ_COMPUTER_GAME = 44,
+ OBJ_PHONE_HANDSET = 45,
+ OBJ_BONES = 46,
+ OBJ_GUARDS_ARM = 47,
+ OBJ_LOG = 48,
+ OBJ_BOMBS = 49,
+ OBJ_NOTE = 50,
+ OBJ_COMBINATION = 51,
+ OBJ_FORMALDEHYDE = 52,
+ OBJ_PETROX = 53,
+ OBJ_LECITHIN = 54
+};
+
+class GameNebular : public Game {
+ friend class Game;
+private:
+ ProtectionResult checkCopyProtection();
+protected:
+ GameNebular(MADSEngine *vm);
+
+ virtual void startGame();
+
+ virtual void initializeGlobals();
+
+ virtual void setSectionHandler();
+
+ virtual void checkShowDialog();
+public:
+ NebularGlobals _globals;
+ StoryMode _storyMode;
+ Difficulty _difficulty;
+
+ virtual Globals &globals() { return _globals; }
+
+ virtual void doObjectAction();
+
+ void showRecipe();
+
+ virtual void unhandledAction();
+
+ virtual void step();
+
+ virtual void synchronize(Common::Serializer &s, bool phase1);
+};
+
+
+class Section1Handler : public SectionHandler {
+public:
+ Section1Handler(MADSEngine *vm) : SectionHandler(vm) {}
+
+ // TODO: Properly implement handler methods
+ virtual void preLoadSection() {}
+ virtual void sectionPtr2() {}
+ virtual void postLoadSection() {}
+};
+
+// TODO: Properly implement handler classes
+typedef Section1Handler Section2Handler;
+typedef Section1Handler Section3Handler;
+typedef Section1Handler Section4Handler;
+typedef Section1Handler Section5Handler;
+typedef Section1Handler Section6Handler;
+typedef Section1Handler Section7Handler;
+typedef Section1Handler Section8Handler;
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_GAME_NEBULAR_H */
diff --git a/engines/mads/nebular/globals_nebular.cpp b/engines/mads/nebular/globals_nebular.cpp
new file mode 100644
index 0000000000..9f8b8a7888
--- /dev/null
+++ b/engines/mads/nebular/globals_nebular.cpp
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "mads/nebular/globals_nebular.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+NebularGlobals::NebularGlobals()
+ : Globals() {
+ // Initialize lists
+ resize(210);
+ _spriteIndexes.resize(30);
+ _sequenceIndexes.resize(30);
+
+ // Initialize game flags
+ _timebombClock = 0;
+ _timebombTimer = 0;
+}
+
+void NebularGlobals::synchronize(Common::Serializer &s) {
+ Globals::synchronize(s);
+
+ s.syncAsUint32LE(_timebombClock);
+ s.syncAsUint32LE(_timebombTimer);
+ _spriteIndexes.synchronize(s);
+ _sequenceIndexes.synchronize(s);
+}
+
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
diff --git a/engines/mads/nebular/globals_nebular.h b/engines/mads/nebular/globals_nebular.h
new file mode 100644
index 0000000000..bd1c6d84b0
--- /dev/null
+++ b/engines/mads/nebular/globals_nebular.h
@@ -0,0 +1,315 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_GLOBALS_NEBULAR_H
+#define MADS_GLOBALS_NEBULAR_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "mads/game.h"
+#include "mads/resources.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+enum GlobalId {
+ kSexOfRex = 0,
+ kOldSexOfRex = 1,
+ kWalkerTiming = 2,
+// kWalkerTiming0 = 3,
+ kTalkInanimateCount = 4,
+ kCopyProtectFailed = 5,
+
+ /* Section #1 variables */
+ kNeedToStandUp = 10,
+ kTurkeyExploded = 11,
+ kMedicineCabinetOpen = 12,
+ kMedicineCabinetVirgin = 13,
+ kWatchedViewScreen = 14,
+ kHoovicAlive = 15,
+ kHoovicSated = 16,
+ kHoovicFishEaten = 17,
+ kWaterInAPuddle = 18,
+ kFishIn105 = 19,
+ kFishIn107 = 20,
+ kFishIn108 = 21,
+ kRandomNumber = 29,
+
+ /* Section #2 variables */
+ kCurtainOpen = 30,
+ kLadderBroken = 31,
+ kBone202Status = 32,
+ kMeteorologistStatus = 33,
+ kRhotundaStatus = 34,
+ kLeavesStatus = 35,
+ kMonkeyStatus = 36,
+ kMeteorologistEverSeen = 37,
+ kMeteorologistWatch = 38,
+ kTeleporterCommand = 39,
+
+ kTeleporterDestination = 40,
+ kTeleporterUnderstood = 41,
+ kConv205 = 42,
+ kChickenPermitted = 43,
+ kTwinklesStatus = 44,
+ kTwinklesApproached = 45,
+ kConvTwinkles1 = 46,
+ kConvTwinkles2 = 47,
+ kConvTwinkles3 = 48,
+ kConvTwinkles5 = 49,
+
+ kConvTwinkles6 = 50,
+ kConvTwinkles7 = 51,
+ kConvTwinkles8 = 52,
+ kBlowgunStatus = 53,
+
+ /* Section #3 Variables */
+ kAfterHavoc = 60,
+ kHaveYourStuff = 61,
+ kRightView320 = 62,
+ kConvBuddy1 = 63,
+ kConvBuddy2 = 64,
+ kMetBuddyBeast = 65,
+ kKnowsBuddyBeast = 66,
+ kConvSlache1 = 67,
+ kConvSlache2 = 68,
+ kConvSlache3 = 69,
+
+ kRexHasMetSlache = 70,
+ kConvIntern = 71,
+ kHasSeenProfPyro = 72,
+ kKickedIn391Grate = 73,
+
+ /* Section #4 Variables */
+ kArmoryDoorOpen = 80,
+ kStorageDoorOpen = 81,
+ kNextIngredient = 82,
+ kIngredientList = 83,
+ kIngredientList1 = 84,
+ kIngredientList2 = 85,
+ kIngredientList3 = 86,
+ kIngredientQuantity = 87,
+ kIngredientQuantity1 = 88,
+ kIngredientQuantity2 = 89,
+
+ kIngredientQuantity3 = 90,
+ kconvPyro_1 = 91,
+ kconvPyro_2 = 92,
+ kconvPyro_3 = 93,
+ kconvPyro_4 = 94,
+ kBadFirstIngredient = 95,
+ kConvBartender1 = 96,
+ kConvBartender2 = 97,
+ kConvBartender3 = 98,
+ kConvBartender4 = 99,
+
+ kHasPurchased = 100,
+ kBeenThruHelgaScene = 101,
+ kHasSaidBinocs = 102,
+ kHasSaidTimer = 103,
+ kBottleDisplayed = 104,
+ kHasBeenScanned = 105,
+ kSomeoneHasExploded = 106,
+
+ /* Section #5 Variables */
+ kBoatRaised = 110,
+ kCarStatus = 111,
+ kCityFlooded = 112,
+ kLaserOn = 113,
+ kLaserHoleIsThere = 114,
+ kCarIsGone = 115,
+ kRegisterOpen = 116,
+ kSafeStatus = 117,
+ kDogStatus = 118,
+ kLineStatus = 119,
+
+ kHoverCarLocation = 120,
+ kHoverCarDestination = 121,
+
+ /* Section #6 Variables */
+ kConvHermit1 = 130,
+ kconvHermit2 = 131,
+ kHasTalkedToHermit = 132,
+ kExecuted_1_11 = 133,
+ kHandsetCellStatus = 134,
+ kBeenInVideoStore = 135,
+ kDurafailRecharged = 136,
+ kPenlightCellStatus = 137,
+ kTimebombStatus = 138,
+ kCheckDaemonTimebomb = 140,
+
+ kResurrectRoom = 141,
+
+ /* Section #6 Time-Bomb Variables */
+ kTimebombClock = 142,
+// kTimebombClock0 = 143,
+ kTimebombTimer = 144,
+// kTimebombTimer0 = 145,
+ kWarnedFloodCity = 146,
+
+ /* Section #7 Variables */
+ kBottleStatus = 150,
+ kMonsterAlive = 151,
+ kConvBottleFillNode = 152,
+ kBoatStatus = 153,
+
+ /* Section #8 Variables */
+ kAntigravClock = 160,
+// kAntigravClock0 = 161,
+ kAntigravTiming = 162,
+// kAntigravTiming0 = 163,
+ kWindowFixed = 164,
+ kInSpace = 165,
+ kReturnFromCut = 166,
+ kBeamIsUp = 167,
+ kForceBeamDown = 168,
+ kCameFromCut = 169,
+
+ kCutX = 170,
+ kCutY = 171,
+ kCutFacing = 172,
+ kDontRepeat = 173,
+ kHoppyDead = 174,
+ kHasWatchedAntigrav = 175,
+ kRemoteSequenceRan = 176,
+ kRemoteOnGround = 177,
+ kFromCockpit = 178,
+ kExitShip = 179,
+
+ kBetweenRooms = 180,
+ kTopButtonPushed = 181,
+ kTargetModInstalled = 182,
+ kShieldModInstalled = 183,
+ kUpBecauseOfRemote = 184,
+
+ kTeleporterRoom = 190,
+ kTeleporterCode = 200
+};
+
+// Enums used for specific individual globals
+// Section #1
+// Rex's sex/swimming state
+enum { REX_MALE = 0, REX_MALE_SWIMMER = 1, REX_FEMALE = 2 };
+
+// Section #2
+// State of Meteorologist in the outpost
+enum { METEOROLOGIST_ABSENT = 0, METEOROLOGIST_PRESENT = 1, METEOROLOGIST_GONE = 2 };
+
+// State of watching the Meteorologist
+enum { METEOROLOGIST_NORMAL = 0, METEOROLOGIST_GROUND = 1, METEOROLOGIST_TOWER = 2 };
+
+// The fat bouncy lady that can squish you on the plains
+enum { RHOTUNDA_HUNGRY = 0, RHOTUNDA_STUCK = 1, RHOTUNDA_GONE = 2 };
+
+// Flags for the bones you can take
+enum { BONE_202_LEFT_GONE = 1, BONE_202_RIGHT_GONE = 2 };
+
+// Leaves used to cover the trap
+enum { LEAVES_ON_GROUND = 0, LEAVES_WITH_PLAYER = 1, LEAVES_ON_TRAP = 2 };
+
+// Monkey ambush state
+enum { MONKEY_AMBUSH_READY = 0, MONKEY_HAS_BINOCULARS = 1, MONKEY_IS_GONE = 2 };
+
+// Teleporter status flags
+enum {
+ TELEPORTER_NONE = 0, TELEPORTER_BEAM_IN = 1, TELEPORTER_BEAM_OUT = 2,
+ TELEPORTER_STEP_OUT = 3, TELEPORTER_WRONG = 4
+};
+
+// Twinkles status
+enum { TWINKLES_AT_HOME = 0, TWINKLES_GONE = 1 };
+
+// Section #4
+// Status of the explosives
+enum { EXPLOSIVES_INSIDE = 3 };
+
+// Section #5
+// Dog status (room 602, outside Abdul's garage)
+enum { DOG_PRESENT = 1, DOG_LEFT = 2, DOG_GONE = 3, DOG_DEAD = 4 };
+
+// Dog status (room 608, inside Abdul's garage)
+enum { CAR_UP = 0, CAR_SQUASHES_DOG = 1, CAR_SQUASHES_DOG_AGAIN = 2, CAR_DOWN = 3, CAR_DOWN_ON_SQUASHED_DOG = 4 };
+
+enum { SAFE_CLOSED = 0, SAFE_OPENED = 1, SAFE_CLOSED_WITH_HOLE = 2, SAFE_OPENED_WITH_HOLE = 3 };
+
+enum { LINE_NOT_DROPPED = 1, LINE_DROPPED = 2, LINE_TIED = 3, LINE_NOW_UNTIED = 4 };
+
+// Section #6
+enum {
+ NO_CELLS = 0, // Handset doesn't contain any cells
+ CHARGED_DURAFAIL = 1, // Handset has charged durafail cells
+ UNCHARGED_DURAFAIL = 2, // Handset has uncharged durafail cells */
+ PHONE_CELLS = 3, // Handset has already charged phone cells
+ FIRST_TIME_PHONE_CELLS = 4, // First time phone cells are in the handset
+ FIRST_TIME_UNCHARGED_DURAFAIL = 5, // First time uncharged cells are in penlight
+ FIRST_TIME_CHARGED_DURAFAIL = 6 // First time charged cells are in penlight
+};
+
+// Time bomb status
+enum {
+ TIMEBOMB_DEACTIVATED = 0, TIMEBOMB_ACTIVATED = 1,
+ TIMEBOMB_BLOW_UP = 2, TIMEBOMB_DEAD = 3
+};
+
+/* Section #7 */
+// Status of the the bottle
+enum {
+ BOTTLE_EMPTY = 0, BOTTLE_ONE_QUARTER_FULL = 1, BOTTLE_HALF_FULL = 2,
+ BOTTLE_THREE_QUARTERS_FULL = 3, BOTTLE_FULL = 4
+};
+
+// Status of the boat
+enum {
+ BOAT_UNFLOODED = 0, BOAT_ADRIFT = 1, BOAT_TIED_FLOATING = 2,
+ BOAT_TIED = 3, BOAT_GONE = 4
+};
+
+
+/* Miscellaneous defines */
+#define TELEPORTER_COUNT 10 // Total number of teleporters
+#define TELEPORTER_WORK_COUNT 6 // Total number that actually work
+
+
+class NebularGlobals : public Globals {
+public:
+ SynchronizedList _spriteIndexes;
+ SynchronizedList _sequenceIndexes;
+
+ int _timebombClock, _timebombTimer;
+public:
+ /**
+ * Constructor
+ */
+ NebularGlobals();
+
+ /**
+ * Synchronize the globals data
+ */
+ virtual void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_GLOBALS_NEBULAR_H */
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
new file mode 100644
index 0000000000..a85a67d69b
--- /dev/null
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -0,0 +1,1103 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/mads.h"
+#include "mads/resources.h"
+#include "mads/scene.h"
+#include "mads/screen.h"
+#include "mads/nebular/menu_nebular.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+#define NEBULAR_MENUSCREEN 990
+#define MADS_MENU_Y ((MADS_SCREEN_HEIGHT - MADS_SCENE_HEIGHT) / 2)
+#define MADS_MENU_ANIM_DELAY 70
+
+MenuView::MenuView(MADSEngine *vm) : FullScreenDialog(vm) {
+ _breakFlag = false;
+ _redrawFlag = true;
+ _palFlag = false;
+}
+
+void MenuView::show() {
+ Scene &scene = _vm->_game->_scene;
+ EventsManager &events = *_vm->_events;
+ _vm->_screenFade = SCREEN_FADE_FAST;
+
+ scene._spriteSlots.reset(true);
+ display();
+
+ events.setEventTarget(this);
+ events.hideCursor();
+
+ while (!_breakFlag && !_vm->shouldQuit()) {
+ if (_redrawFlag) {
+ _vm->_game->_scene.drawElements(_vm->_game->_fx, _vm->_game->_fx);
+ _redrawFlag = false;
+ }
+
+ _vm->_events->waitForNextFrame();
+ _vm->_game->_fx = kTransitionNone;
+ doFrame();
+ }
+
+ events.setEventTarget(nullptr);
+ _vm->_sound->stop();
+}
+
+void MenuView::display() {
+ _vm->_palette->resetGamePalette(4, 8);
+
+ FullScreenDialog::display();
+}
+
+bool MenuView::onEvent(Common::Event &event) {
+ if (event.type == Common::EVENT_KEYDOWN || event.type == Common::EVENT_LBUTTONDOWN) {
+ _breakFlag = true;
+ _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
+ return true;
+ }
+
+ return false;
+}
+
+/*------------------------------------------------------------------------*/
+
+MainMenu::MainMenu(MADSEngine *vm): MenuView(vm) {
+ Common::fill(&_menuItems[0], &_menuItems[7], (SpriteAsset *)nullptr);
+ Common::fill(&_menuItemIndexes[0], &_menuItemIndexes[7], -1);
+ _delayTimeout = 0;
+ _menuItemIndex = -1;
+ _frameIndex = 0;
+ _skipFlag = false;
+ _highlightedIndex = -1;
+ _selectedIndex = -1;
+ _buttonDown = false;
+
+ for (int i = 0; i < 7; ++i)
+ _menuItems[i] = nullptr;
+}
+
+MainMenu::~MainMenu() {
+ Scene &scene = _vm->_game->_scene;
+ for (int i = 0; i < 7; ++i) {
+ if (_menuItemIndexes[i] != -1)
+ scene._sprites.remove(_menuItemIndexes[i]);
+ }
+
+ scene._spriteSlots.reset();
+}
+
+void MainMenu::display() {
+ MenuView::display();
+ Scene &scene = _vm->_game->_scene;
+ ScreenObjects &screenObjects = _vm->_game->_screenObjects;
+ screenObjects.clear();
+
+ // Load each of the menu item assets and add to the scene sprites list
+ for (int i = 0; i < 7; ++i) {
+ Common::String spritesName = Resources::formatName(NEBULAR_MENUSCREEN,
+ 'A', i + 1, EXT_SS, "");
+ _menuItems[i] = new SpriteAsset(_vm, spritesName, 0);
+ _menuItemIndexes[i] = scene._sprites.add(_menuItems[i]);
+
+ // Register the menu item area in the screen objects
+ MSprite *frame0 = _menuItems[i]->getFrame(0);
+ Common::Point pt(frame0->_offset.x - (frame0->w / 2),
+ frame0->_offset.y - frame0->h);
+ screenObjects.add(
+ Common::Rect(pt.x, pt.y + DIALOG_TOP, pt.x + frame0->w,
+ pt.y + frame0->h + DIALOG_TOP), LAYER_GUI, CAT_COMMAND, i);
+ }
+
+ // Set the cursor for when it's shown
+ _vm->_events->setCursor(CURSOR_ARROW);
+}
+
+void MainMenu::doFrame() {
+ // Delay between animation frames on the menu
+ uint32 currTime = g_system->getMillis();
+ if (currTime < _delayTimeout)
+ return;
+ _delayTimeout = currTime + MADS_MENU_ANIM_DELAY;
+
+ // If an item has already been selected, handle rotating out the other menu items
+ if (_selectedIndex != -1) {
+ if (_frameIndex == _menuItems[0]->getCount()) {
+ handleAction((MADSGameAction)_selectedIndex);
+ } else {
+ for (_menuItemIndex = 0; _menuItemIndex < 6; ++_menuItemIndex) {
+ if (_menuItemIndex != _selectedIndex) {
+ addSpriteSlot();
+ }
+ }
+
+ // Move the menu items to the next frame
+ ++_frameIndex;
+ }
+ return;
+ }
+
+ // If we've alerady reached the end of the menuitem animation, exit immediately
+ if (_menuItemIndex == 6)
+ return;
+
+ // If the user has chosen to skip the animation, show the full menu immediately
+ if (_skipFlag && _menuItemIndex >= 0) {
+ // Quickly loop through all the menu items to display each's final frame
+ for (; _menuItemIndex < 6; ++_menuItemIndex) {
+ // Draw the final frame of the menuitem
+ _frameIndex = 0;
+ addSpriteSlot();
+ }
+
+ _vm->_events->showCursor();
+ } else {
+ if ((_menuItemIndex == -1) || (_frameIndex == 0)) {
+ if (++_menuItemIndex == 6) {
+ // Reached end of display animation
+ _vm->_events->showCursor();
+ return;
+ }
+
+ _frameIndex = _menuItems[_menuItemIndex]->getCount() - 1;
+ } else {
+ --_frameIndex;
+ }
+
+ // Move to the next menuitem frame
+ addSpriteSlot();
+ }
+}
+
+void MainMenu::addSpriteSlot() {
+ Scene &scene = _vm->_game->_scene;
+ SpriteSlots &spriteSlots = scene._spriteSlots;
+
+ int seqIndex = (_menuItemIndex < 6) ? _menuItemIndex : _frameIndex;
+ spriteSlots.deleteTimer(seqIndex);
+
+ SpriteAsset *menuItem = _menuItems[_menuItemIndex];
+ MSprite *spr = menuItem->getFrame(_frameIndex);
+
+ SpriteSlot &slot = spriteSlots[spriteSlots.add()];
+ slot._flags = IMG_UPDATE;
+ slot._seqIndex = seqIndex;
+ slot._spritesIndex = _menuItemIndexes[_menuItemIndex];
+ slot._frameNumber = _frameIndex + 1;
+ slot._position = spr->_offset;
+ slot._depth = 1;
+ slot._scale = 100;
+
+ _redrawFlag = true;
+}
+
+bool MainMenu::onEvent(Common::Event &event) {
+ Scene &scene = _vm->_game->_scene;
+ if (_selectedIndex != -1)
+ return false;
+
+ // Handle keypresses - these can be done at any time, even when the menu items are being drawn
+ if (event.type == Common::EVENT_KEYDOWN) {
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_F6:
+ handleAction(EXIT);
+ break;
+
+ case Common::KEYCODE_F1:
+ handleAction(START_GAME);
+ break;
+
+ case Common::KEYCODE_F2:
+ handleAction(RESUME_GAME);
+ break;
+
+ case Common::KEYCODE_F3:
+ handleAction(SHOW_INTRO);
+ break;
+
+ case Common::KEYCODE_F4:
+ handleAction(CREDITS);
+ break;
+
+ case Common::KEYCODE_F5:
+ handleAction(QUOTES);
+ break;
+
+ case Common::KEYCODE_s: {
+ // Goodness knows why, but Rex has a key to restart the menuitem animations
+ // Restart the animation
+ _menuItemIndex = -1;
+ for (int i = 0; i < 6; ++i)
+ scene._spriteSlots.deleteTimer(i);
+
+ _skipFlag = false;
+ _vm->_events->hideCursor();
+ break;
+ }
+
+ default:
+ // Any other key skips the menu animation
+ _skipFlag = true;
+ return false;
+ }
+
+ return true;
+ }
+
+ switch (event.type) {
+ case Common::EVENT_LBUTTONDOWN:
+ if (_vm->_events->isCursorVisible()) {
+ _buttonDown = true;
+ int menuIndex = getHighlightedItem(event.mouse);
+
+ if (menuIndex != _highlightedIndex) {
+ scene._spriteSlots.deleteTimer(menuIndex);
+
+ _highlightedIndex = menuIndex;
+ if (_highlightedIndex != -1) {
+ _frameIndex = _highlightedIndex;
+ addSpriteSlot();
+ }
+ }
+ } else {
+ // Skip the menu animation
+ _skipFlag = true;
+ }
+ return true;
+
+ case Common::EVENT_MOUSEMOVE:
+ if (_buttonDown) {
+ int menuIndex = getHighlightedItem(event.mouse);
+ if (menuIndex != _highlightedIndex) {
+ if (_highlightedIndex != -1) {
+ // Revert to the unselected menu item
+ unhighlightItem();
+ }
+
+ if (menuIndex != -1) {
+ // Highlight new item
+ _highlightedIndex = menuIndex;
+ _frameIndex = _highlightedIndex;
+ addSpriteSlot();
+ }
+ }
+ }
+ break;
+
+ case Common::EVENT_LBUTTONUP:
+ _buttonDown = false;
+ if (_highlightedIndex != -1) {
+ _selectedIndex = _highlightedIndex;
+ unhighlightItem();
+ _frameIndex = 0;
+ }
+
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+int MainMenu::getHighlightedItem(const Common::Point &pt) {
+ return _vm->_game->_screenObjects.scan(pt, LAYER_GUI) - 1;
+}
+
+void MainMenu::unhighlightItem() {
+ // Revert to the unselected menu item
+ _vm->_game->_scene._spriteSlots.deleteTimer(_highlightedIndex);
+ _menuItemIndex = _highlightedIndex;
+ _frameIndex = 0;
+ addSpriteSlot();
+
+ _menuItemIndex = 6;
+ _highlightedIndex = -1;
+}
+
+void MainMenu::handleAction(MADSGameAction action) {
+ _vm->_events->hideCursor();
+ _breakFlag = true;
+
+ switch (action) {
+ case START_GAME:
+ // Show the difficulty dialog
+ _vm->_dialogs->_pendingDialog = DIALOG_DIFFICULTY;
+ break;
+
+ case RESUME_GAME:
+ // The original resumed the most recently saved game. Instead,
+ // just show the load game scren
+ _vm->_dialogs->_pendingDialog = DIALOG_RESTORE;
+ return;
+
+ case SHOW_INTRO:
+ AnimationView::execute(_vm, "rexopen");
+ break;
+
+ case CREDITS:
+ TextView::execute(_vm, "credits");
+ return;
+
+ case QUOTES:
+ TextView::execute(_vm, "quotes");
+ return;
+
+ case EXIT:
+ _vm->_dialogs->_pendingDialog = DIALOG_ADVERT;
+ break;
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+AdvertView::AdvertView(MADSEngine *vm): EventTarget(), _vm(vm) {
+ _breakFlag = false;
+}
+
+void AdvertView::show() {
+ bool altAdvert = _vm->getRandomNumber(1000) >= 500;
+ int screenId = altAdvert ? 995 : 996;
+ uint32 expiryTime = g_system->getMillis() + 10 * 1000;
+
+ _vm->_palette->resetGamePalette(4, 8);
+
+ // Load the advert background onto the screen
+ SceneInfo *sceneInfo = SceneInfo::init(_vm);
+ sceneInfo->load(screenId, 0, Common::String(), 0, _vm->_game->_scene._depthSurface,
+ _vm->_screen);
+ _vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
+ _vm->_palette->setFullPalette(_vm->_palette->_mainPalette);
+
+ delete sceneInfo;
+
+ EventsManager &events = *_vm->_events;
+ events.setEventTarget(this);
+ events.hideCursor();
+
+ while (!_breakFlag && !_vm->shouldQuit()) {
+ _vm->_events->waitForNextFrame();
+ _vm->_game->_fx = kTransitionNone;
+
+ _breakFlag |= g_system->getMillis() >= expiryTime;
+ }
+
+ events.setEventTarget(nullptr);
+ _vm->quitGame();
+ events.pollEvents();
+}
+
+bool AdvertView::onEvent(Common::Event &event) {
+ if (event.type == Common::EVENT_KEYDOWN || event.type == Common::EVENT_LBUTTONDOWN) {
+ _breakFlag = true;
+ return true;
+ }
+
+ return false;
+}
+
+/*------------------------------------------------------------------------*/
+
+char TextView::_resourceName[100];
+#define TEXTVIEW_LINE_SPACING 2
+#define TEXT_ANIMATION_DELAY 100
+#define TV_NUM_FADE_STEPS 40
+#define TV_FADE_DELAY_MILLI 50
+
+void TextView::execute(MADSEngine *vm, const Common::String &resName) {
+ assert(resName.size() < 100);
+ Common::strlcpy(_resourceName, resName.c_str(), sizeof(_resourceName));
+ vm->_dialogs->_pendingDialog = DIALOG_TEXTVIEW;
+}
+
+TextView::TextView(MADSEngine *vm) : MenuView(vm) {
+ _animating = false;
+ _panSpeed = 0;
+ _spareScreen = nullptr;
+ _scrollCount = 0;
+ _lineY = -1;
+ _scrollTimeout = 0;
+ _panCountdown = 0;
+ _translationX = 0;
+ _screenId = -1;
+
+ _font = _vm->_font->getFont(FONT_CONVERSATION);
+ _vm->_palette->resetGamePalette(4, 0);
+
+ load();
+}
+
+TextView::~TextView() {
+}
+
+void TextView::load() {
+ Common::String scriptName(_resourceName);
+ scriptName += ".txr";
+
+ if (!_script.open(scriptName))
+ error("Could not open resource %s", _resourceName);
+
+ processLines();
+}
+
+void TextView::processLines() {
+ if (_script.eos())
+ error("Attempted to read past end of response file");
+
+ while (!_script.eos()) {
+ // Read in the next line
+ _script.readLine(_currentLine, 79);
+ char *p = _currentLine + strlen(_currentLine) - 1;
+ if (*p == '\n')
+ *p = '\0';
+
+ // Commented out line, so go loop for another
+ if (_currentLine[0] == '#')
+ continue;
+
+ // Process the line
+ char *cStart = strchr(_currentLine, '[');
+ if (cStart) {
+ while (cStart) {
+ // Loop for possible multiple commands on one line
+ char *cEnd = strchr(_currentLine, ']');
+ if (!cEnd)
+ error("Unterminated command '%s' in response file", _currentLine);
+
+ *cEnd = '\0';
+ processCommand();
+
+ // Copy rest of line (if any) to start of buffer
+ Common::strlcpy(_currentLine, cEnd + 1, sizeof(_currentLine));
+
+ cStart = strchr(_currentLine, '[');
+ }
+
+ if (_currentLine[0]) {
+ processText();
+ break;
+ }
+
+ } else {
+ processText();
+ break;
+ }
+ }
+}
+
+void TextView::processCommand() {
+ Scene &scene = _vm->_game->_scene;
+ Common::String scriptLine(_currentLine + 1);
+ scriptLine.toUppercase();
+ const char *paramP;
+ const char *commandStr = scriptLine.c_str();
+
+ if (!strncmp(commandStr, "BACKGROUND", 10)) {
+ // Set the background
+ paramP = commandStr + 10;
+ resetPalette();
+ int screenId = getParameter(&paramP);
+
+ SceneInfo *sceneInfo = SceneInfo::init(_vm);
+ sceneInfo->load(screenId, 0, "", 0, scene._depthSurface, scene._backgroundSurface);
+ scene._spriteSlots.fullRefresh();
+ _redrawFlag = true;
+
+ } else if (!strncmp(commandStr, "GO", 2)) {
+ _animating = true;
+
+ } else if (!strncmp(commandStr, "PAN", 3)) {
+ // Set panning values
+ paramP = commandStr + 3;
+ int panX = getParameter(&paramP);
+ int panY = getParameter(&paramP);
+ int panSpeed = getParameter(&paramP);
+
+ if ((panX != 0) || (panY != 0)) {
+ _pan = Common::Point(panX, panY);
+ _panSpeed = panSpeed;
+ }
+
+ } else if (!strncmp(commandStr, "DRIVER", 6)) {
+ // Set the driver to use
+ paramP = commandStr + 7;
+
+ if (!strncmp(paramP, "#SOUND.00", 9)) {
+ int driverNum = paramP[9] - '0';
+ _vm->_sound->init(driverNum);
+ }
+ } else if (!strncmp(commandStr, "SOUND", 5)) {
+ // Set sound number
+ paramP = commandStr + 5;
+ int soundId = getParameter(&paramP);
+ _vm->_sound->command(soundId);
+
+ } else if (!strncmp(commandStr, "COLOR", 5) && ((commandStr[5] == '0') ||
+ (commandStr[5] == '1'))) {
+ // Set the text colors
+ int index = commandStr[5] - '0';
+ paramP = commandStr + 6;
+
+ byte r = getParameter(&paramP);
+ byte g = getParameter(&paramP);
+ byte b = getParameter(&paramP);
+
+ _vm->_palette->setEntry(5 + index, r, g, b);
+
+ } else if (!strncmp(commandStr, "SPARE", 5)) {
+ // Sets a secondary background number that can be later switched in with a PAGE command
+ paramP = commandStr + 6;
+ int spareIndex = commandStr[5] - '0';
+ assert(spareIndex < 4);
+ int screenId = getParameter(&paramP);
+
+ // Load the spare background
+ SceneInfo *sceneInfo = SceneInfo::init(_vm);
+ sceneInfo->_width = MADS_SCREEN_WIDTH;
+ sceneInfo->_height = MADS_SCENE_HEIGHT;
+ _spareScreens[spareIndex].setSize(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+ sceneInfo->loadMadsV1Background(screenId, "", SCENEFLAG_TRANSLATE,
+ _spareScreens[spareIndex]);
+ delete sceneInfo;
+
+ } else if (!strncmp(commandStr, "PAGE", 4)) {
+ // Signals to change to a previous specified secondary background
+ paramP = commandStr + 4;
+ int spareIndex = getParameter(&paramP);
+
+ // Only allow background switches if one isn't currently in progress
+ if (!_spareScreen && _spareScreens[spareIndex].getPixels() != nullptr) {
+ _spareScreen = &_spareScreens[spareIndex];
+ _translationX = 0;
+ }
+
+ } else {
+ error("Unknown response command: '%s'", commandStr);
+ }
+}
+
+int TextView::getParameter(const char **paramP) {
+ if ((**paramP != '=') && (**paramP != ','))
+ return 0;
+
+ int result = 0;
+ ++*paramP;
+ while ((**paramP >= '0') && (**paramP <= '9')) {
+ result = result * 10 + (**paramP - '0');
+ ++*paramP;
+ }
+
+ return result;
+}
+
+void TextView::processText() {
+ int xStart;
+
+ if (!strcmp(_currentLine, "***")) {
+ // Special signifier for end of script
+ _scrollCount = _font->getHeight() * 13;
+ _lineY = -1;
+ return;
+ }
+
+ _lineY = 0;
+
+ // Lines are always centered, except if line contains a '@', in which case the
+ // '@' marks the position that must be horizontally centered
+ char *centerP = strchr(_currentLine, '@');
+ if (centerP) {
+ *centerP = '\0';
+ xStart = (MADS_SCREEN_WIDTH / 2) - _font->getWidth(_currentLine);
+
+ // Delete the @ character and shift back the remainder of the string
+ char *p = centerP + 1;
+ if (*p == ' ') ++p;
+ strcpy(centerP, p);
+
+ } else {
+ int lineWidth = _font->getWidth(_currentLine);
+ xStart = (MADS_SCREEN_WIDTH - lineWidth) / 2;
+ }
+
+ // Add the new line to the list of pending lines
+ TextLine tl;
+ tl._pos = Common::Point(xStart, MADS_SCENE_HEIGHT);
+ tl._line = _currentLine;
+ tl._textDisplayIndex = -1;
+ _textLines.push_back(tl);
+}
+
+void TextView::display() {
+ FullScreenDialog::display();
+}
+
+void TextView::resetPalette() {
+ _vm->_palette->resetGamePalette(8, 8);
+ _vm->_palette->setEntry(5, 0, 63, 63);
+ _vm->_palette->setEntry(6, 0, 45, 45);
+}
+
+void TextView::doFrame() {
+ Scene &scene = _vm->_game->_scene;
+ if (!_animating)
+ return;
+
+ // Only update state if wait period has expired
+ uint32 currTime = g_system->getMillis();
+
+ // If a screen transition is in progress and it's time for another column, handle it
+ if (_spareScreen) {
+ byte *srcP = _spareScreen->getBasePtr(_translationX, 0);
+ byte *bgP = scene._backgroundSurface.getBasePtr(_translationX, 0);
+ byte *screenP = (byte *)_vm->_screen.getBasePtr(_translationX, 0);
+
+ for (int y = 0; y < MADS_SCENE_HEIGHT; ++y, srcP += MADS_SCREEN_WIDTH,
+ bgP += MADS_SCREEN_WIDTH, screenP += MADS_SCREEN_WIDTH) {
+ *bgP = *srcP;
+ *screenP = *srcP;
+ }
+
+ // Flag the column of the screen is modified
+ _vm->_screen.copyRectToScreen(Common::Rect(_translationX, 0,
+ _translationX + 1, MADS_SCENE_HEIGHT));
+
+ // Keep moving the column to copy to the right
+ if (++_translationX == MADS_SCREEN_WIDTH) {
+ // Surface transition is complete
+ _spareScreen = nullptr;
+ }
+ }
+
+ // Make sure it's time for an update
+ if (currTime < _scrollTimeout)
+ return;
+ _scrollTimeout = g_system->getMillis() + TEXT_ANIMATION_DELAY;
+ _redrawFlag = true;
+
+ // If any panning values are set, pan the background surface
+ if ((_pan.x != 0) || (_pan.y != 0)) {
+ if (_panCountdown > 0) {
+ --_panCountdown;
+ return;
+ }
+
+ // Handle horizontal panning
+ if (_pan.x != 0) {
+ byte *lineTemp = new byte[_pan.x];
+ for (int y = 0; y < MADS_SCENE_HEIGHT; ++y) {
+ byte *pixelsP = (byte *)scene._backgroundSurface.getBasePtr(0, y);
+
+ // Copy the first X pixels into temp buffer, move the rest of the line
+ // to the start of the line, and then move temp buffer pixels to end of line
+ Common::copy(pixelsP, pixelsP + _pan.x, lineTemp);
+ Common::copy(pixelsP + _pan.x, pixelsP + MADS_SCREEN_WIDTH, pixelsP);
+ Common::copy(lineTemp, lineTemp + _pan.x, pixelsP + MADS_SCREEN_WIDTH - _pan.x);
+ }
+
+ delete[] lineTemp;
+ }
+
+ // Handle vertical panning
+ if (_pan.y != 0) {
+ // Store the bottom Y lines into a temp buffer, move the rest of the lines down,
+ // and then copy the stored lines back to the top of the screen
+ byte *linesTemp = new byte[_pan.y * MADS_SCREEN_WIDTH];
+ byte *pixelsP = (byte *)scene._backgroundSurface.getBasePtr(0, MADS_SCENE_HEIGHT - _pan.y);
+ Common::copy(pixelsP, pixelsP + MADS_SCREEN_WIDTH * _pan.y, linesTemp);
+
+ for (int y = MADS_SCENE_HEIGHT - 1; y >= _pan.y; --y) {
+ byte *destP = (byte *)scene._backgroundSurface.getBasePtr(0, y);
+ byte *srcP = (byte *)scene._backgroundSurface.getBasePtr(0, y - _pan.y);
+ Common::copy(srcP, srcP + MADS_SCREEN_WIDTH, destP);
+ }
+
+ Common::copy(linesTemp, linesTemp + _pan.y * MADS_SCREEN_WIDTH,
+ (byte *)scene._backgroundSurface.getPixels());
+ delete[] linesTemp;
+ }
+
+ // Flag for a full screen refresh
+ scene._spriteSlots.fullRefresh();
+ }
+
+ // Scroll all active text lines up
+ for (int i = _textLines.size() - 1; i >= 0; --i) {
+ TextLine &tl = _textLines[i];
+ if (tl._textDisplayIndex != -1)
+ // Expire the text line that's already on-screen
+ scene._textDisplay.expire(tl._textDisplayIndex);
+
+ tl._pos.y--;
+ if (tl._pos.y < 0) {
+ _textLines.remove_at(i);
+ } else {
+ tl._textDisplayIndex = scene._textDisplay.add(tl._pos.x, tl._pos.y,
+ 0x605, -1, tl._line, _font);
+ }
+ }
+
+ if (_scrollCount > 0) {
+ // Handling final scrolling of text off of screen
+ if (--_scrollCount == 0) {
+ scriptDone();
+ return;
+ }
+ } else {
+ // Handling a text row
+ if (++_lineY == (_font->getHeight() + TEXTVIEW_LINE_SPACING))
+ processLines();
+ }
+}
+
+void TextView::scriptDone() {
+ _breakFlag = true;
+ _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
+}
+
+/*------------------------------------------------------------------------*/
+
+char AnimationView::_resourceName[100];
+
+void AnimationView::execute(MADSEngine *vm, const Common::String &resName) {
+ assert(resName.size() < 100);
+ Common::strlcpy(_resourceName, resName.c_str(), sizeof(_resourceName));
+ vm->_dialogs->_pendingDialog = DIALOG_ANIMVIEW;
+}
+
+AnimationView::AnimationView(MADSEngine *vm) : MenuView(vm) {
+ _soundDriverLoaded = false;
+ _previousUpdate = 0;
+ _screenId = -1;
+ _resetPalette = false;
+ _resyncMode = NEVER;
+ _v1 = 0;
+ _v2 = -1;
+ _resourceIndex = -1;
+ _currentAnimation = nullptr;
+ _sfx = 0;
+ _soundFlag = _bgLoadFlag = true;
+ _showWhiteBars = true;
+ _manualFrameNumber = 0;
+ _manualSpriteSet = nullptr;
+ _manualStartFrame = _manualEndFrame = 0;
+ _manualFrame2 = 0;
+ _hasManual = false;
+ _animFrameNumber = 0;
+ _sceneInfo = SceneInfo::init(_vm);
+
+ load();
+}
+
+AnimationView::~AnimationView() {
+ delete _currentAnimation;
+ delete _sceneInfo;
+}
+
+void AnimationView::load() {
+ Common::String resName(_resourceName);
+ if (!resName.hasSuffix("."))
+ resName += ".res";
+
+ if (!_script.open(resName))
+ error("Could not open resource %s", resName.c_str());
+
+ processLines();
+}
+
+void AnimationView::display() {
+ Scene &scene = _vm->_game->_scene;
+ _vm->_palette->initPalette();
+ Common::fill(&_vm->_palette->_cyclingPalette[0], &_vm->_palette->_cyclingPalette[PALETTE_SIZE], 0);
+
+ _vm->_palette->resetGamePalette(1, 8);
+ scene._spriteSlots.reset();
+ scene._paletteCycles.clear();
+
+ MenuView::display();
+}
+
+bool AnimationView::onEvent(Common::Event &event) {
+ // Wait for the Escape key or a mouse press
+ if (((event.type == Common::EVENT_KEYDOWN) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) ||
+ (event.type == Common::EVENT_RBUTTONUP)) {
+ scriptDone();
+ return true;
+ }
+
+ return false;
+}
+
+void AnimationView::doFrame() {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_resourceIndex == -1 || _currentAnimation->freeFlag()) {
+ if (++_resourceIndex == (int)_resources.size()) {
+ scriptDone();
+ } else {
+ scene._frameStartTime = 0;
+ loadNextResource();
+ }
+ }
+
+ if (_currentAnimation) {
+ ++scene._frameStartTime;
+ _currentAnimation->update();
+ _redrawFlag = true;
+ }
+}
+
+void AnimationView::loadNextResource() {
+ Scene &scene = _vm->_game->_scene;
+ Palette &palette = *_vm->_palette;
+ ResourceEntry &resEntry = _resources[_resourceIndex];
+
+ if (resEntry._bgFlag)
+ palette.resetGamePalette(1, 8);
+
+ // Load the new animation
+ delete _currentAnimation;
+ _currentAnimation = Animation::init(_vm, &scene);
+ _currentAnimation->load(scene._backgroundSurface, scene._depthSurface,
+ resEntry._resourceName, resEntry._bgFlag ? ANIMFLAG_LOAD_BACKGROUND : 0,
+ nullptr, _sceneInfo);
+
+ // Signal for a screen refresh
+ scene._spriteSlots.fullRefresh();
+ palette.setFullPalette(palette._mainPalette);
+
+ // If a sound driver has been specified, then load the correct one
+ if (!_currentAnimation->_header._soundName.empty()) {
+ const char *chP = strchr(_currentAnimation->_header._soundName.c_str(), '.');
+ assert(chP);
+
+ int driverNum = atoi(chP + 1);
+ _vm->_sound->init(driverNum);
+ }
+
+ // Handle any manual setup
+ if (_currentAnimation->_header._manualFlag) {
+ _manualFrameNumber = _currentAnimation->_header._spritesIndex;
+ _manualSpriteSet = _currentAnimation->getSpriteSet(_manualFrameNumber);
+ _hasManual = true;
+ }
+
+ // Set the sound data for the animation
+ _vm->_sound->setEnabled(resEntry._soundFlag);
+
+ Common::String dsrName = _currentAnimation->_header._dsrName;
+ if (!dsrName.empty())
+ _vm->_audio->setSoundGroup(dsrName);
+
+ // Initial frames scan loop
+ /*
+ bool foundFrame = false;
+ for (int frameCtr = 0; frameCtr < (int)_currentAnimation->_frameEntries.size(); ++frameCtr) {
+ int spritesIdx = _currentAnimation->_spriteListIndexes[_manualFrameNumber];
+ AnimFrameEntry &frame = _currentAnimation->_frameEntries[frameCtr];
+
+ if (frame._spriteSlot._spritesIndex == spritesIdx) {
+ _animFrameNumber = frame._frameNumber;
+ _manualStartFrame = _animFrameNumber;
+ _manualEndFrame = _manualSpriteSet->getCount() - 1;
+ _manualFrame2 = _manualStartFrame - 1;
+ break;
+ }
+ }
+ if (!foundFrame)
+ */
+ _hasManual = false;
+
+ // Start the new animation
+ _currentAnimation->startAnimation(0);
+}
+
+void AnimationView::scriptDone() {
+ _breakFlag = true;
+ _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
+}
+
+void AnimationView::processLines() {
+ if (_script.eos()) {
+ // end of script, end animation
+ scriptDone();
+ return;
+ }
+
+ while (!_script.eos()) {
+ // Get in next line
+ _currentLine.clear();
+ char c;
+ while (!_script.eos() && (c = _script.readByte()) != '\n') {
+ if (c != '\r')
+ _currentLine += c;
+ }
+
+ // Process the line
+ while (!_currentLine.empty()) {
+ if (_currentLine.hasPrefix("-")) {
+ _currentLine.deleteChar(0);
+
+ processCommand();
+ } else {
+ // Get resource name
+ Common::String resName;
+ while (!_currentLine.empty() && (c = _currentLine[0]) != ' ') {
+ _currentLine.deleteChar(0);
+ resName += c;
+ }
+
+ _resources.push_back(ResourceEntry(resName, _sfx, _soundFlag,
+ _bgLoadFlag, _showWhiteBars));
+ }
+
+ // Skip any spaces
+ while (_currentLine.hasPrefix(" "))
+ _currentLine.deleteChar(0);
+ }
+ }
+}
+
+void AnimationView::processCommand() {
+ // Get the command character
+ char commandChar = toupper(_currentLine[0]);
+ _currentLine.deleteChar(0);
+
+ // Handle the command
+ switch (commandChar) {
+ case 'B':
+ _soundFlag = !_soundFlag;
+ break;
+ case 'H':
+ // -h[:ex] Disable EMS / XMS high memory support
+ if (_currentLine.hasPrefix(":"))
+ _currentLine.deleteChar(0);
+ while (_currentLine.hasPrefix("e") || _currentLine.hasPrefix("x"))
+ _currentLine.deleteChar(0);
+ break;
+ case 'O':
+ // -o:xxx Specify opening special effect
+ assert(_currentLine[0] == ':');
+ _currentLine.deleteChar(0);
+ _sfx = getParameter();
+ break;
+ case 'P':
+ // Switch to CONCAT mode, which is ignored anyway
+ break;
+ case 'R': {
+ // Resynch timer (always, beginning, never)
+ assert(_currentLine[0] == ':');
+ _currentLine.deleteChar(0);
+
+ char v = toupper(_currentLine[0]);
+ _currentLine.deleteChar(0);
+ if (v == 'N')
+ _resyncMode = NEVER;
+ else if (v == 'A')
+ _resyncMode = ALWAYS;
+ else if (v == 'B')
+ _resyncMode = BEGINNING;
+ else
+ error("Unknown parameter");
+ break;
+ }
+ case 'W':
+ // Switch white bars being visible
+ _showWhiteBars = !_showWhiteBars;
+ break;
+ case 'X':
+ // Exit after animation finishes. Ignore
+ break;
+ case 'Y':
+ // Reset palette on startup
+ _resetPalette = true;
+ break;
+ default:
+ error("Unknown command char: '%c'", commandChar);
+ }
+}
+
+int AnimationView::getParameter() {
+ int result = 0;
+
+ while (!_currentLine.empty()) {
+ char c = _currentLine[0];
+
+ if (c >= '0' && c <= '9') {
+ _currentLine.deleteChar(0);
+ result = result * 10 + (c - '0');
+ } else {
+ break;
+ }
+ }
+
+ return result;
+}
+
+void AnimationView::checkResource(const Common::String &resourceName) {
+ //bool hasSuffix = false;
+
+}
+
+int AnimationView::scanResourceIndex(const Common::String &resourceName) {
+ int foundIndex = -1;
+
+ if (_v1) {
+ const char *chP = strchr(resourceName.c_str(), '\\');
+ if (!chP) {
+ chP = strchr(resourceName.c_str(), '*');
+ }
+
+ Common::String resName = chP ? Common::String(chP + 1) : resourceName;
+
+ if (_v2 != 3) {
+ assert(_resIndex.size() == 0);
+ }
+
+ // Scan for the resource name
+ for (uint resIndex = 0; resIndex < _resIndex.size(); ++resIndex) {
+ ResIndexEntry &resEntry = _resIndex[resIndex];
+ if (resEntry._resourceName.compareToIgnoreCase(resourceName)) {
+ foundIndex = resIndex;
+ break;
+ }
+ }
+ }
+
+ if (foundIndex >= 0) {
+ // TODO
+ }
+ return -1;
+}
+
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
diff --git a/engines/mads/nebular/menu_nebular.h b/engines/mads/nebular/menu_nebular.h
new file mode 100644
index 0000000000..f8e84fa5b6
--- /dev/null
+++ b/engines/mads/nebular/menu_nebular.h
@@ -0,0 +1,323 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_MENU_NEBULAR_H
+#define MADS_MENU_NEBULAR_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/msurface.h"
+#include "mads/nebular/dialogs_nebular.h"
+
+namespace MADS {
+
+class MADSEngine;
+
+namespace Nebular {
+
+enum MADSGameAction { START_GAME, RESUME_GAME, SHOW_INTRO, CREDITS, QUOTES, EXIT };
+
+class MenuView: public FullScreenDialog {
+protected:
+ bool _breakFlag;
+ bool _redrawFlag;
+
+ virtual void doFrame() = 0;
+
+ virtual void display();
+
+ /**
+ * Event handler
+ */
+ virtual bool onEvent(Common::Event &event);
+public:
+ MenuView(MADSEngine *vm);
+
+ virtual ~MenuView() {}
+
+ virtual void show();
+};
+
+class MainMenu: public MenuView {
+private:
+ SpriteAsset *_menuItems[7];
+ int _menuItemIndexes[7];
+ int _menuItemIndex;
+ int _frameIndex;
+ uint32 _delayTimeout;
+ bool _skipFlag;
+
+ /**
+ * Currently highlighted menu item
+ */
+ int _highlightedIndex;
+
+ /**
+ * Flag for mouse button being pressed
+ */
+ bool _buttonDown;
+
+ /**
+ * Stores menu item selection
+ */
+ int _selectedIndex;
+
+ /**
+ * Get the highlighted menu item under the cursor
+ */
+ int getHighlightedItem(const Common::Point &pt);
+
+ /**
+ * Un-highlight a currently highlighted item
+ */
+ void unhighlightItem();
+
+ /**
+ * Execute a given menuitem
+ */
+ void handleAction(MADSGameAction action);
+
+ /**
+ * Add a sprite slot for the current menuitem frame
+ */
+ void addSpriteSlot();
+protected:
+ /**
+ * Display the menu
+ */
+ virtual void display();
+
+ /**
+ * Handle the menu item animations
+ */
+ virtual void doFrame();
+
+ /**
+ * Event handler
+ */
+ virtual bool onEvent(Common::Event &event);
+public:
+ MainMenu(MADSEngine *vm);
+
+ virtual ~MainMenu();
+};
+
+class AdvertView : public EventTarget {
+private:
+ /**
+ * Engine reference
+ */
+ MADSEngine *_vm;
+
+ /**
+ * Signals when to close the dialog
+ */
+ bool _breakFlag;
+protected:
+ /**
+ * Event handler
+ */
+ virtual bool onEvent(Common::Event &event);
+public:
+ AdvertView(MADSEngine *vm);
+
+ virtual ~AdvertView() {}
+
+ /**
+ * Show the dialog
+ */
+ void show();
+};
+
+struct TextLine {
+ Common::Point _pos;
+ Common::String _line;
+ int _textDisplayIndex;
+};
+
+/**
+ * Scrolling text view
+ */
+class TextView : public MenuView {
+private:
+ static char _resourceName[100];
+
+ bool _animating;
+ Common::Array<TextLine> _textLines;
+ Common::Point _pan;
+ int _panSpeed;
+ MSurface _spareScreens[4];
+ int _scrollCount;
+ int _lineY;
+ uint32 _scrollTimeout;
+ int _panCountdown;
+ int _translationX;
+ Common::File _script;
+ char _currentLine[80];
+ MSurface *_spareScreen;
+ Font *_font;
+private:
+ /**
+ * Load the text resource
+ */
+ void load();
+
+ /**
+ * Process the lines
+ */
+ void processLines();
+
+ /**
+ * Process a command from the script file
+ */
+ void processCommand();
+
+ /**
+ * Process text from the script file
+ */
+ void processText();
+
+ /**
+ * Get a parameter from line
+ */
+ int getParameter(const char **paramP);
+
+ /**
+ * Called when the script is finished
+ */
+ void scriptDone();
+
+ /**
+ * Reset the game palette
+ */
+ void resetPalette();
+protected:
+ virtual void display();
+
+ virtual void doFrame();
+public:
+ /**
+ * Queue the given text resource for display
+ */
+ static void execute(MADSEngine *vm, const Common::String &resName);
+
+ TextView(MADSEngine *vm);
+
+ virtual ~TextView();
+};
+
+enum ResyncMode { NEVER, ALWAYS, BEGINNING };
+
+struct ResourceEntry {
+ Common::String _resourceName;
+ int _fx;
+ bool _soundFlag;
+ bool _bgFlag;
+ bool _showWhiteBars;
+
+ ResourceEntry() {}
+ ResourceEntry(const Common::String &resName, int fx, bool soundFlag,
+ bool bgFlag, bool showWhiteBars) {
+ _resourceName = resName;
+ _fx = fx;
+ _soundFlag = soundFlag;
+ _bgFlag = bgFlag;
+ _showWhiteBars = showWhiteBars;
+ }
+};
+
+struct ResIndexEntry {
+ int _id;
+ int _v;
+ Common::String _resourceName;
+
+ ResIndexEntry() {}
+};
+
+/**
+* Animation cutscene view
+*/
+class AnimationView : public MenuView {
+private:
+ static char _resourceName[100];
+
+ Common::File _script;
+ uint32 _previousUpdate;
+ Common::String _currentLine;
+ bool _soundDriverLoaded;
+ bool _resetPalette;
+ ResyncMode _resyncMode;
+ int _sfx;
+ bool _soundFlag;
+ bool _bgLoadFlag;
+ bool _showWhiteBars;
+ Common::Array<ResourceEntry> _resources;
+ Common::Array<ResIndexEntry> _resIndex;
+ int _v1;
+ int _v2;
+ int _resourceIndex;
+ SceneInfo *_sceneInfo;
+ Animation *_currentAnimation;
+ int _manualFrameNumber;
+ SpriteAsset *_manualSpriteSet;
+ int _manualStartFrame, _manualEndFrame;
+ int _manualFrame2;
+ bool _hasManual;
+ int _animFrameNumber;
+private:
+ void checkResource(const Common::String &resourceName);
+
+ int scanResourceIndex(const Common::String &resourceName);
+
+ void load();
+
+ void processLines();
+
+ void processCommand();
+
+ int getParameter();
+
+ void scriptDone();
+
+ void loadNextResource();
+protected:
+ virtual void display();
+
+ virtual void doFrame();
+
+ virtual bool onEvent(Common::Event &event);
+public:
+ /**
+ * Queue the given text resource for display
+ */
+ static void execute(MADSEngine *vm, const Common::String &resName);
+
+ AnimationView(MADSEngine *vm);
+
+ virtual ~AnimationView();
+};
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_MENU_NEBULAR_H */
diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp
new file mode 100644
index 0000000000..b5e2491624
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes.cpp
@@ -0,0 +1,628 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "mads/mads.h"
+#include "mads/compression.h"
+#include "mads/resources.h"
+#include "mads/scene.h"
+#include "mads/nebular/game_nebular.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes1.h"
+#include "mads/nebular/nebular_scenes2.h"
+#include "mads/nebular/nebular_scenes3.h"
+#include "mads/nebular/nebular_scenes4.h"
+#include "mads/nebular/nebular_scenes5.h"
+#include "mads/nebular/nebular_scenes6.h"
+#include "mads/nebular/nebular_scenes7.h"
+#include "mads/nebular/nebular_scenes8.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+SceneLogic *SceneFactory::createScene(MADSEngine *vm) {
+ Scene &scene = vm->_game->_scene;
+
+ scene.addActiveVocab(NOUN_DROP);
+ scene.addActiveVocab(NOUN_DOLLOP);
+ scene.addActiveVocab(NOUN_DASH);
+ scene.addActiveVocab(NOUN_SPLASH);
+ scene.addActiveVocab(NOUN_ALCOHOL);
+
+ switch (scene._nextSceneId) {
+ // Scene group #1 (ship, ocean, cave)
+ case 101: // Ship, cockpit
+ return new Scene101(vm);
+ case 102: // Ship, dining room
+ return new Scene102(vm);
+ case 103: // Ship, engine room
+ return new Scene103(vm);
+ case 104: // Ocean, northwest cliff
+ return new Scene104(vm);
+ case 105: // Ocean, northeast cliff with mine
+ return new Scene105(vm);
+ case 106: // Ocean, outside ship
+ return new Scene106(vm);
+ case 107: // Ocean, bushes
+ return new Scene107(vm);
+ case 108: // Ocean, southwest cliff
+ return new Scene108(vm);
+ case 109: // Ocean, tunnel
+ return new Scene109(vm);
+ case 110: // Ocean, cave with tunnel
+ return new Scene110(vm);
+ case 111: // Cave with pool and opening
+ return new Scene111(vm);
+ case 112: // cutscene, looking at view screen
+ return new Scene112(vm);
+
+ // Scene group #2 (island)
+ case 201: // outside teleporter
+ return new Scene201(vm);
+ case 202: // village
+ return new Scene202(vm);
+ case 203: // tree with Rhotunda (fat woman)
+ return new Scene203(vm);
+ case 205: // village
+ return new Scene205(vm);
+ case 207: // outside witch doctor's hut
+ return new Scene207(vm);
+ case 208: // pit with leaves (trap)
+ return new Scene208(vm);
+ case 209: // palm tree and bamboo plant
+ return new Scene209(vm);
+ case 210: // outside native woman's hut
+ return new Scene210(vm);
+ case 211: // palm tree with monkey
+ return new Scene211(vm);
+ case 212: // outside cave
+ return new Scene212(vm);
+ case 213: // inside teleporter
+ return new Scene213(vm);
+ case 214: // inside witch doctor's hut
+ return new Scene214(vm);
+ case 215: // inside native woman's hut
+ return new Scene215(vm);
+ case 216: // cutscene, monitor showing Rex and native woman
+ return new Scene216(vm);
+
+ // Scene group #3 (women's base, cell block)
+ case 301: // outside teleporter (before chaos)
+ return new Scene301(vm);
+ case 302: // room with statue (before chaos)
+ return new Scene302(vm);
+ case 303: // western corridor (before chaos)
+ return new Scene303(vm);
+ case 304: // crossing with traffic light (before chaos)
+ return new Scene304(vm);
+ case 307: // Rex's cell (before chaos)
+ return new Scene307(vm);
+ case 308: // sauropod's cell (before chaos)
+ return new Scene308(vm);
+ case 309: // multihand monster's cell (before chaos)
+ return new Scene309(vm);
+ case 310: // empty cell (before chaos)
+ return new Scene310(vm);
+ case 311: // warden's desk (before chaos)
+ return new Scene311(vm);
+ case 313: // air shaft overview
+ return new Scene313(vm);
+ case 316: // Gender Bender
+ return new Scene316(vm);
+ case 318: // doctor's gurney
+ return new Scene318(vm);
+ case 319: // doctor Slache closeup (lying on the gurney)
+ return new Scene319(vm);
+ case 320: // warden's desk closeup / monitors
+ return new Scene320(vm);
+ case 321: // gender bender sex change sequence
+ return new Scene321(vm);
+ case 322: // inside teleporter
+ return new Scene322(vm);
+ case 351: // outside teleporter (after chaos)
+ return new Scene351(vm);
+ case 352: // room with statue (after chaos)
+ return new Scene352(vm);
+ case 353: // western corridor (after chaos)
+ return new Scene353(vm);
+ case 354: // crossing with traffic light (after chaos)
+ return new Scene354(vm);
+ case 357: // Rex's cell (after chaos)
+ return new Scene357(vm);
+ case 358: // sauropod's cell (after chaos)
+ return new Scene358(vm);
+ case 359: // multihand monster's cell (after chaos)
+ return new Scene359(vm);
+ case 360: // empty cell (after chaos)
+ return new Scene360(vm);
+ case 361: // warden's desk (after chaos)
+ return new Scene361(vm);
+ case 366: // air shaft ending at Gender Bender
+ return new Scene366(vm);
+ case 387: // air shaft ending at cell
+ return new Scene387(vm);
+ case 388: // air shaft ending at sauropod's cell
+ return new Scene388(vm);
+ case 389: // air shaft ending at multihand monster's cell (before chaos)
+ return new Scene389(vm);
+ case 390: // air shaft ending at cell
+ return new Scene390(vm);
+ case 391: // air shaft ending at warden's desk
+ return new Scene391(vm);
+ case 399: // air shaft ending at multihand monster's cell (after chaos)
+ return new Scene399(vm);
+
+ // Scene group #4 (women's base)
+ case 401: // outside bar
+ return new Scene401(vm);
+ case 402: // inside bar
+ return new Scene402(vm);
+ case 405: // outside armory
+ return new Scene405(vm);
+ case 406: // outside storage room
+ return new Scene406(vm);
+ case 407: // eastern corridor
+ return new Scene407(vm);
+ case 408: // inside armory
+ return new Scene408(vm);
+ case 409: // inside female only teleporter
+ return new Scene409(vm);
+ case 410: // inside storage room
+ return new Scene410(vm);
+ case 411: // lab
+ return new Scene411(vm);
+ case 413: // outside female only teleporter
+ return new Scene413(vm);
+
+ // Scene group #5 (men's city, lower floor)
+ case 501: // outside car
+ return new Scene501(vm);
+ case 502: // inside male only teleporter
+ return new Scene502(vm);
+ case 503: // guard tower
+ return new Scene503(vm);
+ case 504: // inside car
+ return new Scene504(vm);
+ case 505: // car view screen
+ return new Scene505(vm);
+ case 506: // shopping street
+ return new Scene506(vm);
+ case 507: // inside software house
+ return new Scene507(vm);
+ case 508: // laser cannon
+ return new Scene508(vm);
+ case 511: // outside pleasure dome
+ return new Scene511(vm);
+ case 512: // inside pleasure dome
+ return new Scene512(vm);
+ case 513: // outside mall
+ return new Scene513(vm);
+ case 515: // overview
+ return new Scene515(vm);
+ case 551: // outside teleporter (with skeleton)
+ return new Scene551(vm);
+
+ // Scene group #6 (men's city, upper floor)
+ case 601: // outside Bruce's house
+ return new Scene601(vm);
+ case 602: // Bruce's house, living room
+ return new Scene602(vm);
+ case 603: // Bruce's house, bedroom
+ return new Scene603(vm);
+ case 604: // viewport
+ return new Scene604(vm);
+ case 605: // viewport closeup
+ return new Scene605(vm);
+ case 607: // outside Abdul's garage
+ return new Scene607(vm);
+ case 608: // inside Abdul's garage
+ return new Scene608(vm);
+ case 609: // outside Buckluster video store
+ return new Scene609(vm);
+ case 610: // inside Buckluster video store
+ return new Scene610(vm);
+ case 611: // back alley
+ return new Scene611(vm);
+ case 612: // expressway / maintenance building
+ return new Scene612(vm);
+ case 620: // cutscene, viewport glass breaking
+ return new Scene620(vm);
+
+ // Scene group #7 (submerged men's city / upper floor)
+ case 701: // outside elevator (after city is submerged)
+ return new Scene701(vm);
+ case 702: // outside teleporter (after city is submerged)
+ return new Scene702(vm);
+ case 703: // water
+ return new Scene703(vm);
+ case 704: // water, building in the distance
+ return new Scene704(vm);
+ case 705: // water, outside building
+ return new Scene705(vm);
+ case 706: // inside building, pedestral room, outside teleporter
+ return new Scene706(vm);
+ case 707: // teleporter
+ return new Scene707(vm);
+ case 710: // looking at pedestral room through binoculars
+ return new Scene710(vm);
+ case 711: // inside teleporter
+ return new Scene711(vm);
+ case 751: // outside elevator (before city is submerged)
+ return new Scene751(vm);
+ case 752: // outside teleporter (before city is submerged)
+ return new Scene752(vm);
+
+ // Scene group #8
+ case 801: // control room, outside teleporter
+ return new Scene801(vm);
+ case 802: // launch pad with destroyed ship
+ return new Scene802(vm);
+ case 803: // empty launch pad
+ return new Scene803(vm);
+ case 804: // inside Rex's ship - cockpit
+ return new Scene804(vm);
+ case 805: // service panel
+ return new Scene805(vm);
+ case 807: // teleporter
+ return new Scene807(vm);
+ case 808: // antigrav control
+ return new Scene808(vm);
+ case 810: // cutscene: Rex's ship leaving the planet
+ return new Scene810(vm);
+
+ default:
+ error("Invalid scene %d called", scene._nextSceneId);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+NebularScene::NebularScene(MADSEngine *vm) : SceneLogic(vm),
+ _globals(static_cast<GameNebular *>(vm->_game)->_globals),
+ _game(*static_cast<GameNebular *>(vm->_game)),
+ _action(vm->_game->_scene._action) {
+}
+
+Common::String NebularScene::formAnimName(char sepChar, int suffixNum) {
+ return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum,
+ EXT_NONE, "");
+}
+
+/*------------------------------------------------------------------------*/
+
+void SceneInfoNebular::loadCodes(MSurface &depthSurface, int variant) {
+ File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT"));
+ MadsPack codesPack(&f);
+ Common::SeekableReadStream *stream = codesPack.getItemStream(variant + 1);
+
+ loadCodes(depthSurface, stream);
+
+ delete stream;
+ f.close();
+}
+
+void SceneInfoNebular::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
+ byte *destP = depthSurface.getData();
+ byte *endP = depthSurface.getBasePtr(0, depthSurface.h);
+
+ byte runLength = stream->readByte();
+ while (destP < endP && runLength > 0) {
+ byte runValue = stream->readByte();
+
+ // Write out the run length
+ Common::fill(destP, MIN(endP, destP + runLength), runValue);
+ destP += runLength;
+
+ // Get the next run length
+ runLength = stream->readByte();
+ }
+
+ if (destP < endP)
+ Common::fill(destP, endP, 0);
+}
+
+/*------------------------------------------------------------------------*/
+
+SceneTeleporter::SceneTeleporter(MADSEngine *vm) : NebularScene(vm) {
+ _buttonTyped = -1;
+ _curCode = -1;
+ _digitCount = -1;
+ _curMessageId = -1;
+ _handSpriteId = -1;
+ _handSequenceId = -1;
+ _finishedCodeCounter = -1;
+ _meteorologistNextPlace = -1;
+ _meteorologistCurPlace = -1;
+ _teleporterSceneId = -1;
+}
+
+int SceneTeleporter::teleporterAddress(int code, bool working) {
+ int limit = working ? 6 : 10;
+
+ for (int i = 0; i < limit; i++) {
+ if (code == _globals[kTeleporterCode + i])
+ return _globals[kTeleporterRoom + i];
+ }
+
+ return -1;
+}
+
+Common::Point SceneTeleporter::teleporterComputeLocation() {
+ Common::Point result;
+
+ switch (_buttonTyped) {
+ case 0:
+ result = Common::Point(179, 200);
+ break;
+
+ case 1:
+ result = Common::Point(166, 170);
+ break;
+
+ case 2:
+ result = Common::Point(179, 170);
+ break;
+
+ case 3:
+ result = Common::Point(192, 170);
+ break;
+
+ case 4:
+ result = Common::Point(166, 180);
+ break;
+
+ case 5:
+ result = Common::Point(179, 180);
+ break;
+
+ case 6:
+ result = Common::Point(192, 180);
+ break;
+
+ case 7:
+ result = Common::Point(166, 190);
+ break;
+
+ case 8:
+ result = Common::Point(179, 190);
+ break;
+
+ case 9:
+ result = Common::Point(192, 190);
+ break;
+
+ case 10:
+ result = Common::Point(194, 200);
+ break;
+
+ case 11:
+ result = Common::Point(164, 200);
+ break;
+
+ default:
+ error("teleporterComputeLocation() - Unexpected button pressed");
+ }
+
+ return result;
+}
+
+void SceneTeleporter::teleporterHandleKey() {
+ switch (_game._trigger) {
+ case 0: {
+ _game._player._stepEnabled = false;
+ Common::Point msgPos = teleporterComputeLocation();
+ _handSequenceId = _scene->_sequences.startReverseCycle(_handSpriteId, false, 4, 2, 0, 0);
+ _scene->_sequences.setPosition(_handSequenceId, msgPos);
+ _scene->_sequences.setDepth(_handSequenceId, 2);
+ _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_LOOP, 0, 1);
+ _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+
+ if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL)
+ _vm->_events->hideCursor();
+
+ }
+ break;
+
+ case 1:
+ _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_SPRITE, 3, 3);
+ if (_buttonTyped <= 9) {
+ if (_digitCount < 4) {
+ _curCode *= 10;
+ _curCode += _buttonTyped;
+ _digitCount++;
+ _msgText = Common::String::format("%d", _curCode);
+ if (_digitCount < 4)
+ _msgText += "_";
+
+ if (_scene->_currentSceneId != 711)
+ _vm->_sound->command(32);
+ }
+ } else if (_buttonTyped == 11) {
+ _digitCount = 0;
+ _curCode = 0;
+ _msgText = "_";
+ if (_scene->_currentSceneId != 711)
+ _vm->_sound->command(33);
+ } else if (_digitCount == 4) {
+ if (_scene->_currentSceneId != 711)
+ _finishedCodeCounter = 1;
+
+ if (teleporterAddress(_curCode, true) > 0) {
+ _vm->_palette->setEntry(252, 0, 63, 0);
+ if (_scene->_currentSceneId != 711)
+ _vm->_sound->command(34);
+ } else {
+ _vm->_palette->setEntry(252, 63, 0, 0);
+ if (_scene->_currentSceneId != 711)
+ _vm->_sound->command(35);
+ }
+ }
+
+ if (_scene->_currentSceneId != 711) {
+ if (_curMessageId >= 0)
+ _scene->_kernelMessages.remove(_curMessageId);
+ _curMessageId = _scene->_kernelMessages.add(Common::Point(143, 61), 0xFDFC, 16, 0, 9999999, _msgText);
+ }
+ break;
+
+ case 2:
+ if (_finishedCodeCounter == 1) {
+ _finishedCodeCounter++;
+
+ if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL)
+ _scene->_nextSceneId = 202;
+ else {
+ _vm->_events->showCursor();
+ int destination = teleporterAddress(_curCode, true);
+
+ if (destination > 0) {
+ _globals[kTeleporterCommand] = 2;
+ _scene->_nextSceneId = _teleporterSceneId;
+ _globals[kTeleporterDestination] = destination;
+ } else {
+ _globals[kTeleporterCommand] = 4;
+ _scene->_nextSceneId = _teleporterSceneId;
+ }
+ }
+ } else if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL)
+ _scene->_sequences.addTimer(30, 230 + _meteorologistCurPlace);
+
+ break;
+
+ case 3:
+ if (!_finishedCodeCounter) {
+ if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) {
+ _game._player._stepEnabled = true;
+ _vm->_events->showCursor();
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void SceneTeleporter::teleporterEnter() {
+ _game._player._visible = false;
+ _game._player._stepEnabled = (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL);
+ _scene->_kernelMessages._talkFont = _vm->_font->getFont(FONT_TELE);
+ _scene->_textSpacing = 0;
+ _curCode = 0;
+ _digitCount = 0;
+ _finishedCodeCounter = 0;
+ _curMessageId = -1;
+ _msgText = "_";
+
+ if (_scene->_priorSceneId == -2)
+ _scene->_priorSceneId = _globals[kTeleporterDestination];
+
+ if (_scene->_priorSceneId < 101)
+ _scene->_priorSceneId = 201;
+
+ _globals[kTeleporterDestination] = _scene->_priorSceneId;
+ _vm->_palette->setEntry(252, 63, 63, 0);
+ _vm->_palette->setEntry(253, 0, 0, 0);
+ _teleporterSceneId = _scene->_priorSceneId;
+ if (_teleporterSceneId == 202)
+ _teleporterSceneId = 201;
+
+ int codeVal = 0;
+ for (int i = 0; i < 10; i++) {
+ if (_teleporterSceneId == _globals[kTeleporterRoom + i])
+ codeVal = _globals[kTeleporterCode + i];
+
+ if (_globals[kTeleporterRoom + i] == 301)
+ _meteorologistNextPlace = _globals[kTeleporterCode + i];
+ }
+
+ Common::String msgText2 = Common::String::format("#%.4d", codeVal);
+
+ if (_scene->_currentSceneId != 711) {
+ _scene->_kernelMessages.add(Common::Point(133, 34), 0, 32, 0, 9999999, msgText2);
+ _scene->_kernelMessages.add(Common::Point(143, 61), 0xFDFC, 16, 0, 9999999, _msgText);
+ }
+
+ _meteorologistCurPlace = 0;
+
+ if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL)
+ _scene->_sequences.addTimer(30, 230);
+
+ _vm->_sound->command(36);
+}
+
+bool SceneTeleporter::teleporterActions() {
+ bool retVal = false;
+ static int _buttonList[12] = { NOUN_0_KEY, NOUN_1_KEY, NOUN_2_KEY, NOUN_3_KEY, NOUN_4_KEY, NOUN_5_KEY, NOUN_6_KEY, NOUN_7_KEY, NOUN_8_KEY, NOUN_9_KEY, NOUN_SMILE_KEY, NOUN_FROWN_KEY };
+
+ if (_action.isAction(VERB_PRESS) || _action.isAction(VERB_PUSH)) {
+ for (int i = 0; i < 12; i++) {
+ if (_action._activeAction._objectNameId == _buttonList[i])
+ _buttonTyped = i;
+ }
+ teleporterHandleKey();
+ retVal = true;
+ }
+
+ if (_action.isAction(VERB_EXIT_FROM, NOUN_DEVICE)) {
+ _globals[kTeleporterCommand] = 3;
+ _scene->_nextSceneId = _teleporterSceneId;
+ retVal = true;
+ }
+
+ return (retVal);
+}
+
+void SceneTeleporter::teleporterStep() {
+ if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL)
+ return;
+
+ if (_game._trigger >= 230) {
+ int place = _game._trigger - 230;
+ int digit;
+
+ if (place < 4) {
+ digit = _meteorologistNextPlace;
+ for (int i = 0; i < (3 - place); i++)
+ digit = digit / 10;
+
+ digit = digit % 10;
+ } else {
+ digit = 10;
+ }
+ _buttonTyped = digit;
+ _meteorologistCurPlace = place + 1;
+ _game._trigger = -1;
+ }
+
+ if (_game._trigger) {
+ if (_game._trigger == -1)
+ _game._trigger = 0;
+ teleporterHandleKey();
+ }
+}
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes.h b/engines/mads/nebular/nebular_scenes.h
new file mode 100644
index 0000000000..cf33b21aad
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes.h
@@ -0,0 +1,1418 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_NEBULAR_SCENES_H
+#define MADS_NEBULAR_SCENES_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/game_nebular.h"
+#include "mads/nebular/globals_nebular.h"
+
+
+namespace MADS {
+
+namespace Nebular {
+
+enum {
+ SEX_MALE = 0, SEX_UNKNOWN = 1, SEX_FEMALE = 2
+};
+
+enum Verb {
+ VERB_ACTIVATE = 0x00E,
+ VERB_ATTACH = 0x019,
+ VERB_BREAK = 0x032,
+ VERB_BREATHE_AIR = 0x033,
+ VERB_CAST = 0x03D,
+ VERB_CLIMB_DOWN = 0x04E,
+ VERB_CLIMB_THROUGH = 0x04F,
+ VERB_CLIMB_UP = 0x050,
+ VERB_CUT = 0x061,
+ VERB_DAMPEN = 0x064,
+ VERB_DISASSEMBLE = 0x06C,
+ VERB_DIVE_INTO = 0x06D,
+ VERB_DRINK = 0x072,
+ VERB_EAT = 0x075,
+ VERB_EJECT = 0x076,
+ VERB_EMPTY = 0x077,
+ VERB_EXAMINE = 0x07D,
+ VERB_FILL = 0x085,
+ VERB_FONDLE = 0x08C,
+ VERB_HOSE_DOWN = 0x0A6,
+ VERB_IGNITE = 0x0B4,
+ VERB_INFLATE = 0x0B5,
+ VERB_INSERT = 0x0B6,
+ VERB_INSPECT = 0x0B7,
+ VERB_GNAW_ON = 0x098,
+ VERB_GORGE_ON = 0x099,
+ VERB_HURL = 0x0A9,
+ VERB_LICK = 0x0CB,
+ VERB_LOOK_AT = 0x0D1,
+ VERB_LOOK_IN = 0x0D2,
+ VERB_LOOK_THROUGH = 0x0D3,
+ VERB_PEER_THROUGH = 0x103,
+ VERB_PLAY = 0x112,
+ VERB_PRESS = 0x11A,
+ VERB_PRY = 0x11C,
+ VERB_READ = 0x11F,
+ VERB_SET = 0x132,
+ VERB_SHAKE_HANDS = 0x133,
+ VERB_SHARPEN = 0x134,
+ VERB_SHOOT = 0x13A,
+ VERB_SIT_IN = 0x13F,
+ VERB_SMELL = 0x147,
+ VERB_SNIFF = 0x149,
+ VERB_STARE_AT = 0x155,
+ VERB_SWIM_ACROSS = 0x159,
+ VERB_SWIM_INTO = 0x15A,
+ VERB_SWIM_THROUGH = 0x15B,
+ VERB_SWIM_TO = 0x15C,
+ VERB_SWIM_TOWARDS = 0x15D,
+ VERB_SWIM_UNDER = 0x15E,
+ VERB_TIE = 0x170,
+ VERB_UNLOCK = 0x17B,
+ VERB_WALK_ACROSS = 0x187,
+ VERB_WALK_INSIDE = 0x188,
+ VERB_WALK_OUTSIDE = 0x18A,
+ VERB_WALK_THROUGH = 0x18B,
+ VERB_WALK_TOWARDS = 0x18C,
+ VERB_WEAR = 0x191,
+ VERB_WALK_DOWN = 0x1AD,
+ VERB_LEAVE = 0x1CD,
+ VERB_EXIT_FROM = 0x1CE,
+ VERB_USE = 0x20C,
+ VERB_GAZE_INTO = 0x212,
+ VERB_SIT_AT = 0x21F,
+ VERB_WALK_UP = 0x227,
+ VERB_WALK_INTO = 0x242,
+ VERB_EXIT = 0x298,
+ VERB_WALK_ONTO = 0x2B5,
+ VERB_RETURN_TO = 0x2D5,
+ VERB_CLIMB_INTO = 0x2F7,
+ VERB_STEP_INTO = 0x2F9,
+ VERB_CRAWL_TO = 0x2FB,
+ VERB_CRAWL_DOWN = 0x301,
+ VERB_SIT_ON = 0x30B,
+ VERB_WALK_ALONG = 0x312,
+ VERB_GET_INSIDE = 0x325,
+ VERB_WALK = 0x32F,
+ VERB_REFLECT = 0x365,
+ VERB_GET_INTO = 0x36A,
+ VERB_LOOK_OUT = 0x397,
+ VERB_APPLY = 0x3A6,
+ VERB_STEER_TOWARDS = 0x3B1,
+ VERB_NIBBLE_ON = 0x3B7,
+ VERB_ENTER = 0x3B8,
+ VERB_PUT_DOWN = 0x46F,
+ VERB_INSTALL = 0x474,
+ VERB_REMOVE = 0x476,
+ VERB_DEFACE = 0x489,
+ VERB_MASSAGE = 0x4A3,
+ VERB_MANGLE = 0x4A4,
+ VERB_RUB = 0x4A5,
+ VERB_JUGGLE = 0x4A6,
+ VERB_SMASH = 0x4A7,
+ VERB_GUZZLE = 0x4A8,
+ VERB_FOLD = 0x4AB,
+ VERB_SPINDLE = 0x4AC,
+ VERB_MUTILATE = 0x4AD
+};
+
+enum Noun {
+ //NOUN_GAME = 0x1,
+ //NOUN_QSAVE = 0x2,
+ //NOUN_LOOK = 0x3,
+ //NOUN_TAKE = 0x4,
+ //NOUN_PUSH = 0x5,
+ //NOUN_OPEN = 0x6,
+ //NOUN_PUT = 0x7,
+ //NOUN_TALK_TO = 0x8,
+ //NOUN_GIVE = 0x9,
+ //NOUN_PULL = 0xA,
+ //NOUN_CLOSE = 0xB,
+ //NOUN_THROW = 0xC,
+ //NOUN_WALK_TO = 0xD,
+ //NOUN_ACTIVATE = 0xE,
+ //NOUN_ADMIRE = 0xF,
+ NOUN_ADSM = 0x10,
+ NOUN_AIR_VENT = 0x11,
+ NOUN_ALOE_PLANT = 0x12,
+ NOUN_ANEMONE = 0x13,
+ NOUN_ANOMOMETER = 0x14,
+ NOUN_AREA_AROUND_HUT = 0x15,
+ NOUN_AREA_TO_SOUTH = 0x16,
+ NOUN_AREA_TO_WEST = 0x17,
+ NOUN_AROMATIC_MEAT = 0x18,
+ //NOUN_ATTACH = 0x19,
+ NOUN_AUDIO_TAPE = 0x1A,
+ NOUN_AUXILIARY_POWER = 0x1B,
+ NOUN_BADMITTON_BRAT = 0x1C,
+ NOUN_BAG = 0x1D,
+ NOUN_BAMBOO_TREE = 0x1E,
+ NOUN_BATS = 0x1F,
+ NOUN_BAWLEMER_ORIOLE_HUN = 0x20,
+ NOUN_BEAR_RUG = 0x21,
+ NOUN_BEASTLY_TROPHY = 0x22,
+ NOUN_BIG_LEAVES = 0x23,
+ NOUN_BIG_PIPES = 0x24,
+ NOUN_BIG_SKY = 0x25,
+ NOUN_BIG_STONE = 0x26,
+ NOUN_BINOCULARS = 0x27,
+ NOUN_BIRDIES = 0x28,
+ NOUN_BLOWGUN = 0x29,
+ NOUN_BOMB = 0x2A,
+ NOUN_BOMBS = 0x2B,
+ NOUN_BONE = 0x2C,
+ NOUN_BONES = 0x2D,
+ NOUN_BOTTLE = 0x2E,
+ NOUN_BOULDER = 0x2F,
+ NOUN_BOULDERS = 0x30,
+ NOUN_BRA = 0x31,
+ //NOUN_BREAK = 0x32,
+ //NOUN_BREATHE_AIR = 0x33,
+ NOUN_BULKHEAD = 0x34,
+ NOUN_BURGER = 0x35,
+ NOUN_BURN = 0x36,
+ NOUN_BURNT_OUT_WARP_COIL = 0x37,
+ NOUN_BUSH_LIKE_FORMATION = 0x38,
+ NOUN_BUSHES = 0x39,
+ NOUN_BUSHY_FERN = 0x3A,
+ NOUN_CACTUS = 0x3B,
+ NOUN_CARD = 0x3C,
+ //NOUN_CAST = 0x3D,
+ NOUN_CAULDRON = 0x3E,
+ NOUN_CAVE = 0x3F,
+ NOUN_CAVE_CEILING = 0x40,
+ NOUN_CAVE_ENTRANCE = 0x41,
+ NOUN_CAVE_EXIT = 0x42,
+ NOUN_CAVE_FLOOR = 0x43,
+ NOUN_CAVE_TO_EAST = 0x44,
+ NOUN_CAVE_WALL = 0x45,
+ NOUN_CEILING = 0x46,
+ NOUN_CHAIR = 0x47,
+ NOUN_CHARGE_CASES = 0x48,
+ NOUN_CHICKEN = 0x49,
+ NOUN_CHICKEN_BOMB = 0x4A,
+ NOUN_CLEARING_TO_EAST = 0x4B,
+ NOUN_CLEARING_TO_SOUTH = 0x4C,
+ NOUN_CLIFF_FACE = 0x4D,
+ NOUN_CLIMB_DOWN = 0x4E,
+ NOUN_CLIMB_THROUGH = 0x4F,
+ NOUN_CLIMB_UP = 0x50,
+ NOUN_CLOCK = 0x51,
+ NOUN_CLOSET = 0x52,
+ NOUN_CLOTHESLINE = 0x53,
+ NOUN_CLUMP_OF_TREES = 0x54,
+ NOUN_COAL = 0x55,
+ NOUN_COCOANUT = 0x56,
+ NOUN_COMPACT_CASE = 0x57,
+ NOUN_COMPUTER_GAME = 0x58,
+ NOUN_CONTROL_PANEL = 0x59,
+ NOUN_CORAL = 0x5A,
+ NOUN_CRAB = 0x5B,
+ NOUN_CREDIT_CHIP = 0x5C,
+ NOUN_CUMULOUS_CLOUD = 0x5D,
+ NOUN_CURIOUS_WEED_PATCH = 0x5E,
+ NOUN_CURTAIN = 0x5F,
+ NOUN_CURTAINS = 0x60,
+ //NOUN_CUT = 0x61,
+ NOUN_DAMAGE_CONTROL = 0x62,
+ NOUN_DAMAGE_CONTROL_PANEL = 0x63,
+ //NOUN_DAMPEN = 0x64,
+ NOUN_DEAD_FISH = 0x65,
+ NOUN_DEAD_PURPLE_MONSTER = 0x66,
+ NOUN_DECLIVITOUS_CHASM = 0x67,
+ NOUN_DEEP_DARK_FOREST = 0x68,
+ NOUN_DENSE_FOREST = 0x69,
+ NOUN_DETONATORS = 0x6A,
+ NOUN_DINO_MITE = 0x6B,
+ //NOUN_DISASSEMBLE = 0x6C,
+ //NOUN_DIVE_INTO = 0x6D,
+ NOUN_DOOR = 0x6E,
+ NOUN_DOOR_KEY = 0x6F,
+ NOUN_DOORWAY = 0x70,
+ NOUN_DRAWER = 0x71,
+ //NOUN_DRINK = 0x72,
+ NOUN_DURAFAIL_CELLS = 0x73,
+ NOUN_EASTERN_CLIFF_FACE = 0x74,
+ //NOUN_EAT = 0x75,
+ //NOUN_EJECT = 0x76,
+ //NOUN_EMPTY = 0x77,
+ NOUN_ENGINEERING_CONTROLS = 0x78,
+ NOUN_ENGINEERING_SECTION = 0x79,
+ NOUN_ENTER_KEY = 0x7A,
+ NOUN_ESCAPE_HATCH = 0x7B,
+ NOUN_ESTROTOXIN = 0x7C,
+ //NOUN_EXAMINE = 0x7D,
+ NOUN_EXPERIMENT_CAGE = 0x7E,
+ NOUN_EXTINGUISH = 0x7F,
+ NOUN_FACE_ID = 0x80,
+ NOUN_FERN = 0x81,
+ NOUN_FIELD_TO_NORTH = 0x82,
+ NOUN_FIELD_TO_SOUTH = 0x83,
+ NOUN_FIELD_TO_WEST = 0x84,
+ //NOUN_FILL = 0x85,
+ NOUN_FIRE_PIT = 0x86,
+ NOUN_FISHING_LINE = 0x87,
+ NOUN_FISHING_ROD = 0x88,
+ NOUN_FLOOR = 0x89,
+ NOUN_FLOOR_OF_HUT = 0x8A,
+ NOUN_FLOOR_TILE = 0x8B,
+ //NOUN_FONDLE = 0x8C,
+ NOUN_FOREST_TO_EAST = 0x8D,
+ NOUN_FRONT_WINDOW = 0x8E,
+ NOUN_FUNGOIDS = 0x8F,
+ NOUN_FURNACE = 0x90,
+ NOUN_FUZZY_DICE = 0x91,
+ //NOUN_GAZE = 0x92,
+ //NOUN_GAZE_AT = 0x93,
+ //NOUN_GAZE_IN = 0x94,
+ //NOUN_GLANCE_AT = 0x95,
+ NOUN_GLOVE = 0x96,
+ NOUN_GNARLY_SHRUB = 0x97,
+ //NOUN_GNAW_ON = 0x98,
+ //NOUN_GORGE_ON = 0x99,
+ NOUN_GRAIN_ALCHOHOL = 0x9A,
+ NOUN_GRASSLAND_TO_EAST = 0x9B,
+ NOUN_GRASSLAND_TO_SOUTH = 0x9C,
+ NOUN_GRASSY_AREA = 0x9D,
+ NOUN_GRASSY_AREA_TO_NORTH = 0x9E,
+ NOUN_GRASSY_KNOLL = 0x9F,
+ //NOUN_GRIND = 0xA0,
+ NOUN_GROOVILACTIC_TREE = 0xA1,
+ NOUN_GUARDS_ARM = 0xA2,
+ NOUN_HATCHWAY = 0xA3,
+ //NOUN_HOOK_UP = 0xA4,
+ NOUN_HORIZON = 0xA5,
+ //NOUN_HOSE_DOWN = 0xA6,
+ NOUN_HOTPANTS = 0xA7,
+ NOUN_HULL = 0xA8,
+ //NOUN_HURL = 0xA9,
+ NOUN_HUT = 0xAA,
+ NOUN_HUT_AREA = 0xAB,
+ NOUN_HUT_TO_EAST = 0xAC,
+ NOUN_HUT_TO_SOUTH = 0xAD,
+ NOUN_HUT_TO_THE_SOUTH = 0xAE,
+ NOUN_HUT_TO_WEST = 0xAF,
+ NOUN_HUTS_TO_NORTH = 0xB0,
+ NOUN_HYDROSPANNER = 0xB1,
+ NOUN_HYPERDRIVE_JUMP_UNIT = 0xB2,
+ NOUN_ID_CARD = 0xB3,
+ //NOUN_IGNITE = 0xB4,
+ //NOUN_INFLATE = 0xB5,
+ //NOUN_INSERT = 0xB6,
+ //NOUN_INSPECT = 0xB7,
+ NOUN_JUNGLE = 0xB8,
+ NOUN_JUNGLE_TO_EAST = 0xB9,
+ NOUN_JUNGLE_TO_WEST = 0xBA,
+ NOUN_KEY_1 = 0xBB,
+ NOUN_KEY_2 = 0xBC,
+ NOUN_KEY_3 = 0xBD,
+ NOUN_KEY_4 = 0xBE,
+ NOUN_KEY_5 = 0xBF,
+ NOUN_KEY_6 = 0xC0,
+ NOUN_KEY_7 = 0xC1,
+ NOUN_KEY_8 = 0xC2,
+ NOUN_KEY_9 = 0xC3,
+ NOUN_KEYPAD = 0xC4,
+ NOUN_KNEELING_WOMAN = 0xC5,
+ NOUN_KNIFE = 0xC6,
+ NOUN_LADDER = 0xC7,
+ NOUN_LARGE_STALAGMITE = 0xC8,
+ //NOUN_LEER_AT = 0xC9,
+ NOUN_LIBRARY_COMPUTER = 0xCA,
+ //NOUN_LICK = 0xCB,
+ NOUN_LIFE_SUPPORT_SECTION = 0xCC,
+ NOUN_LIGHT = 0xCD,
+ //NOUN_LOAD = 0xCE,
+ //NOUN_LOCK = 0xCF,
+ NOUN_LOG = 0xD0,
+ //NOUN_LOOK_AT = 0xD1,
+ //NOUN_LOOK_IN = 0xD2,
+ //NOUN_LOOK_THROUGH = 0xD3,
+ NOUN_LOUNGE_AREA = 0xD4,
+ NOUN_LOVE_ALTAR = 0xD5,
+ NOUN_LOWLANDS = 0xD6,
+ NOUN_MACHINE = 0xD7,
+ NOUN_MAGNET = 0xD8,
+ NOUN_MAIN_AIRLOCK = 0xD9,
+ NOUN_MANTA_RAY = 0xDA,
+ NOUN_MARSHY_WETLANDS = 0xDB,
+ NOUN_MATCH = 0xDC,
+ NOUN_MEDICAL_WASTE = 0xDD,
+ NOUN_MEDICINE_CABINET = 0xDE,
+ NOUN_MEN_WHO_CAME_BEFORE = 0xDF,
+ NOUN_MINE = 0xE0,
+ NOUN_MIRROR = 0xE1,
+ NOUN_MONITOR = 0xE2,
+ NOUN_MONKEY = 0xE3,
+ NOUN_MONKEY_LIVER_JUICE = 0xE4,
+ NOUN_MONSTER_SLUDGE = 0xE5,
+ NOUN_MOUNTAIN = 0xE6,
+ NOUN_MOUNTAIN_RANGE = 0xE7,
+ NOUN_MOUNTAINS = 0xE8,
+ NOUN_MTAM = 0xE9,
+ NOUN_MUSHROOMS = 0xEA,
+ NOUN_NAVIGATION_CONTROLS = 0xEB,
+ NOUN_NORTH_PATH = 0xEC,
+ NOUN_NORTHERN_EXPOSURE = 0xED,
+ NOUN_NORTHERN_SEA_CLIFF = 0xEE,
+ NOUN_OBSTACLE = 0xEF,
+ NOUN_OCEAN_FLOOR = 0xF0,
+ NOUN_ODD_ROCK_FORMATION = 0xF1,
+ NOUN_OOGLY_BOOGLY_JUICE = 0xF2,
+ NOUN_OPEN_AREA_TO_EAST = 0xF3,
+ NOUN_OPEN_AREA_TO_NORTH = 0xF4,
+ NOUN_OPEN_AREA_TO_SOUTH = 0xF5,
+ NOUN_OPEN_AREA_TO_WEST = 0xF6,
+ NOUN_OPEN_FIELD = 0xF7,
+ NOUN_OUTER_HULL = 0xF8,
+ NOUN_OUTSIDE = 0xF9,
+ NOUN_OVEN = 0xFA,
+ NOUN_OVERHANG_TO_EAST = 0xFB,
+ NOUN_OVERHANG_TO_WEST = 0xFC,
+ NOUN_OVERHEAD_LAMP = 0xFD,
+ NOUN_PAD_OF_PAPER = 0xFE,
+ NOUN_PADLOCK_KEY = 0xFF,
+ NOUN_PALM_TREE = 0x100,
+ NOUN_PASSAGE_WAY_TO_SOUTH = 0x101,
+ NOUN_PASSION_PUSS = 0x102,
+ NOUN_PEER_THROUGH = 0x103,
+ NOUN_PENCIL = 0x104,
+ NOUN_PENDULOUS_CRAG = 0x105,
+ NOUN_PENLIGHT = 0x106,
+ NOUN_PHONE_CELLS = 0x107,
+ NOUN_PHONE_HANDSET = 0x108,
+ NOUN_PILE_OF_ROCKS = 0x109,
+ NOUN_PILLOW = 0x10A,
+ NOUN_PILOTS_CHAIR = 0x10B,
+ NOUN_PIPE = 0x10C,
+ NOUN_PIRANHA = 0x10D,
+ NOUN_PLANT = 0x10E,
+ NOUN_PLANT_STALK = 0x10F,
+ NOUN_PLANTS = 0x110,
+ NOUN_PLASTIC_JESUS = 0x111,
+ //NOUN_PLAY = 0x112,
+ NOUN_PLUNGER = 0x113,
+ NOUN_POISON_DARTS = 0x114,
+ NOUN_POLYCEMENT = 0x115,
+ NOUN_POOL = 0x116,
+ NOUN_POSTER = 0x117,
+ NOUN_POWER_STATUS_PANEL = 0x118,
+ NOUN_PRECIPICE = 0x119,
+ //NOUN_PRESS = 0x11A,
+ NOUN_PRESSURE_GAUGE = 0x11B,
+ //NOUN_PRY = 0x11C,
+ NOUN_RAGING_RIVER = 0x11D,
+ NOUN_RAMOLYAN_RUGBY_RATS = 0x11E,
+ //NOUN_READ = 0x11F,
+ NOUN_REARVIEW_MIRROR = 0x120,
+ NOUN_REBREATHER = 0x121,
+ NOUN_REFRIGERATOR = 0x122,
+ NOUN_REMOTE = 0x123,
+ NOUN_REPAIR_LIST = 0x124,
+ NOUN_RIVER = 0x125,
+ NOUN_RIVER_TO_WEST = 0x126,
+ NOUN_ROBO_KITCHEN = 0x127,
+ NOUN_ROCK = 0x128,
+ NOUN_ROCKS = 0x129,
+ NOUN_ROCKY_AREA = 0x12A,
+ NOUN_ROLLING_HILL = 0x12B,
+ NOUN_SCALPEL = 0x12C,
+ NOUN_SCENIC_MOUNTAINS = 0x12D,
+ NOUN_SEA_CLIFF = 0x12E,
+ NOUN_SEAWEED = 0x12F,
+ NOUN_SEAWEED_BANK = 0x130,
+ NOUN_SECURITY_CARD = 0x131,
+ //NOUN_SET = 0x132,
+ //NOUN_SHAKE_HANDS = 0x133,
+ //NOUN_SHARPEN = 0x134,
+ NOUN_SHIELD_ACCESS_PANEL = 0x135,
+ NOUN_SHIELD_GENERATOR = 0x136,
+ NOUN_SHIELD_MODULATOR = 0x137,
+ NOUN_SHIELD_STATUS_PANEL = 0x138,
+ NOUN_SHIP = 0x139,
+ //NOUN_SHOOT = 0x13A,
+ NOUN_SHOVEL = 0x13B,
+ //NOUN_SHRED = 0x13C,
+ NOUN_SHRUNKEN_HEADS = 0x13D,
+ NOUN_SINGED_MEAT = 0x13E,
+ //NOUN_SIT_IN = 0x13F,
+ NOUN_SKULL = 0x140,
+ NOUN_SKULL_AND_CROSSBONES = 0x141,
+ NOUN_SKY = 0x142,
+ //NOUN_SLEEP_ON = 0x143,
+ NOUN_SLITHERING_SNAKE = 0x144,
+ NOUN_SLUG_SECRETION = 0x145,
+ NOUN_SMALL_HOLE = 0x146,
+ //NOUN_SMELL = 0x147,
+ NOUN_SNAKE = 0x148,
+ //NOUN_SNIFF = 0x149,
+ //NOUN_SOAK = 0x14A,
+ NOUN_SPECIAL_KEY_1 = 0x14B,
+ NOUN_SPECIAL_KEY_2 = 0x14C,
+ NOUN_SPIDER = 0x14D,
+ NOUN_SPILT_MILK = 0x14E,
+ NOUN_SPIT_FIRE = 0x14F,
+ //NOUN_SPRAY = 0x150,
+ //NOUN_STAB = 0x151,
+ NOUN_STAIRS = 0x152,
+ NOUN_STALAGMITES = 0x153,
+ //NOUN_STAND_INSIDE = 0x154,
+ //NOUN_STARE_AT = 0x155,
+ NOUN_STEPS = 0x156,
+ NOUN_STUFFED_FISH = 0x157,
+ NOUN_SURFACE = 0x158,
+ //NOUN_SWIM_ACROSS = 0x159,
+ //NOUN_SWIM_INTO = 0x15A,
+ //NOUN_SWIM_THROUGH = 0x15B,
+ //NOUN_SWIM_TO = 0x15C,
+ //NOUN_SWIM_TOWARDS = 0x15D,
+ //NOUN_SWIM_UNDER = 0x15E,
+ NOUN_SWOOPING_CREATURE = 0x15F,
+ NOUN_TABLE = 0x160,
+ //NOUN_TAKE_LIVER = 0x161,
+ //NOUN_TAKE_OFF = 0x162,
+ //NOUN_TAKE_PAGE = 0x163,
+ NOUN_TALL_GRASS = 0x164,
+ NOUN_TAPE_PLAYER = 0x165,
+ NOUN_TARGET_COMPUTER = 0x166,
+ NOUN_TARGET_MODULE = 0x167,
+ NOUN_TARGETTING_COMPUTER = 0x168,
+ NOUN_TASMANIAN_DEVIL = 0x169,
+ NOUN_TASTY_TURKEY = 0x16A,
+ NOUN_TELEPORT_DEVICE = 0x16B,
+ NOUN_TELEPORTER = 0x16C,
+ NOUN_THATCHED_ROOF = 0x16D,
+ NOUN_THORNS = 0x16E,
+ NOUN_THORNY_BUSH = 0x16F,
+ //NOUN_TIE = 0x170,
+ NOUN_TIMEBOMB = 0x171,
+ NOUN_TIMER = 0x172,
+ NOUN_TIMER_MODULE = 0x173,
+ NOUN_TREE = 0x174,
+ NOUN_TREES = 0x175,
+ NOUN_TRODDEN_PATH = 0x176,
+ NOUN_TUBE = 0x177,
+ NOUN_TUNNEL = 0x178,
+ NOUN_TWINKIE_BUSH = 0x179,
+ NOUN_TWINKIFRUIT = 0x17A,
+ //NOUN_UNLOCK = 0x17B,
+ NOUN_UZI = 0x17C,
+ NOUN_VASE = 0x17D,
+ NOUN_VIDEO_GAME = 0x17E,
+ //NOUN_VIEW = 0x17F,
+ NOUN_VIEW_SCREEN = 0x180,
+ NOUN_VIEWPORT = 0x181,
+ NOUN_VILLAGE_AREA = 0x182,
+ NOUN_VILLAGE_TO_WEST = 0x183,
+ NOUN_VOLCANO = 0x184,
+ NOUN_VULTURE = 0x185,
+ NOUN_WAD_OF_CATTLE_PARTS = 0x186,
+ //NOUN_WALK_ACROSS = 0x187,
+ //NOUN_WALK_INSIDE = 0x188,
+ //NOUN_WALK_ON = 0x189,
+ //NOUN_WALK_OUTSIDE = 0x18A,
+ //NOUN_WALK_THROUGH = 0x18B,
+ //NOUN_WALK_TOWARDS = 0x18C,
+ NOUN_WALL = 0x18D,
+ NOUN_WATCH_TOWER = 0x18E,
+ NOUN_WATER = 0x18F,
+ NOUN_WEAPONS_DISPLAY = 0x190,
+ //NOUN_WEAR = 0x191,
+ NOUN_WEATHER_STATION = 0x192,
+ NOUN_WEATHER_VANE = 0x193,
+ NOUN_WEIGHT_MACHINE = 0x194,
+ NOUN_WESTERN_CLIFF_FACE = 0x195,
+ NOUN_WHEEL = 0x196,
+ NOUN_WINDOW = 0x197,
+ NOUN_WITCHDOCTOR_HUT = 0x198,
+ NOUN_WORKBENCH = 0x199,
+ //NOUN_WRITE_ON = 0x19A,
+ NOUN_YELLOW_BIRDY = 0x19B,
+ NOUN_GRASS = 0x19C,
+ NOUN_BOUNCING_REPTILE = 0x19D,
+ NOUN_DEEP_PIT = 0x19E,
+ NOUN_LOWLANDS_TO_NORTH = 0x19F,
+ NOUN_SMALL_BUSH = 0x1A0,
+ NOUN_SMALL_CACTUS = 0x1A1,
+ NOUN_ROCKY_AREA_TO_NORTH = 0x1A2,
+ NOUN_BAMBOO_LIKE_PLANT = 0x1A3,
+ NOUN_MOUNTAINSIDE = 0x1A4,
+ NOUN_FIELD = 0x1A5,
+ NOUN_GRASSY_FIELD = 0x1A6,
+ NOUN_CRAG = 0x1A7,
+ NOUN_HUGE_LEGS = 0x1A8,
+ NOUN_LEAF_COVERED_PIT = 0x1A9,
+ NOUN_PILE_OF_LEAVES = 0x1AA,
+ NOUN_OPEN_FIELD_TO_EAST = 0x1AB,
+ NOUN_LAWN = 0x1AC,
+ //NOUN_WALK_DOWN = 0x1AD,
+ NOUN_PATH_TO_WEST = 0x1AE,
+ NOUN_HEDGE = 0x1AF,
+ NOUN_VILLAGE_PATH = 0x1B0,
+ NOUN_PATH_TO_NORTHEAST = 0x1B1,
+ NOUN_JUNGLE_PATH = 0x1B2,
+ NOUN_THICK_UNDERGROWTH = 0x1B3,
+ NOUN_OCEAN = 0x1B4,
+ NOUN_OCEAN_IN_DISTANCE = 0x1B5,
+ NOUN_STRANGE_DEVICE = 0x1B6,
+ NOUN_BUSH = 0x1B7,
+ NOUN_ANEMOMETER = 0x1B8,
+ NOUN_ISLAND_IN_DISTANCE = 0x1B9,
+ NOUN_PATH = 0x1BA,
+ NOUN_TROPHY = 0x1BB,
+ NOUN_SPECIMEN_JARS = 0x1BC,
+ NOUN_BOWL = 0x1BD,
+ NOUN_LARGE_BOWL = 0x1BE,
+ NOUN_PATH_TO_NORTH = 0x1BF,
+ NOUN_HUT_TO_NORTH = 0x1C0,
+ NOUN_PATH_TO_EAST = 0x1C1,
+ NOUN_CHICKEN_ON_SPIT = 0x1C2,
+ NOUN_CAPTIVE_CREATURE = 0x1C3,
+ NOUN_TWINKIFRUIT_BUSH = 0x1C4,
+ NOUN_STREAM = 0x1C5,
+ NOUN_OPPOSITE_SHORE = 0x1C6,
+ NOUN_PATH_TO_SOUTH = 0x1C7,
+ NOUN_OPPOSITE_BANK = 0x1C8,
+ NOUN_BROKEN_LADDER = 0x1C9,
+ NOUN_BAG_OF_TWINKIFRUITS = 0x1CA,
+ NOUN_BED = 0x1CB,
+ NOUN_DISPLAY = 0x1CC,
+ //NOUN_LEAVE = 0x1CD,
+ //NOUN_EXIT_FROM = 0x1CE,
+ NOUN_DEVICE = 0x1CF,
+ NOUN_0_KEY = 0x1D0,
+ NOUN_1_KEY = 0x1D1,
+ NOUN_2_KEY = 0x1D2,
+ NOUN_3_KEY = 0x1D3,
+ NOUN_4_KEY = 0x1D4,
+ NOUN_5_KEY = 0x1D5,
+ NOUN_6_KEY = 0x1D6,
+ NOUN_7_KEY = 0x1D7,
+ NOUN_8_KEY = 0x1D8,
+ NOUN_9_KEY = 0x1D9,
+ NOUN_FROWN_KEY = 0x1DA,
+ NOUN_SMILE_KEY = 0x1DB,
+ NOUN_NATIVE_WOMAN = 0x1DC,
+ NOUN_YELLOW_BIRD = 0x1DD,
+ NOUN_BLEEPER = 0x1DE,
+ NOUN_SIZEMOMETER = 0x1DF,
+ NOUN_PANEL = 0x1E0,
+ NOUN_PRINTER = 0x1E1,
+ NOUN_HARD_DRIVE = 0x1E2,
+ NOUN_BATHROOM = 0x1E3,
+ NOUN_DESK = 0x1E4,
+ NOUN_PASSAGEWAY = 0x1E5,
+ NOUN_FIRE_HYDRANT = 0x1E6,
+ NOUN_FREEZER = 0x1E7,
+ NOUN_EQUIDIGITIZER = 0x1E8,
+ NOUN_VISION_VIEW = 0x1E9,
+ NOUN_TELEDETECTOR = 0x1EA,
+ NOUN_POLE = 0x1EB,
+ NOUN_TRANSPOSITION_DEVICE = 0x1EC,
+ NOUN_STATUESQUE = 0x1ED,
+ NOUN_TEMPERATURE_GAUGE = 0x1EE,
+ NOUN_CHECK = 0x1EF,
+ NOUN_WATCH = 0x1F0,
+ NOUN_ELECTRO_SCANNER = 0x1F1,
+ NOUN_HALL = 0x1F2,
+ NOUN_SCANNER = 0x1F3,
+ //NOUN_PLACE_HAND_ON = 0x1F4,
+ NOUN_SECURITY_MONITOR = 0x1F5,
+ NOUN_DIGITORAMA = 0x1F6,
+ NOUN_RAIL_BEAM = 0x1F7,
+ NOUN_VAULT = 0x1F8,
+ NOUN_HALLWAY = 0x1F9,
+ NOUN_PIPES = 0x1FA,
+ NOUN_AIR_VENT_GRATE = 0x1FB,
+ NOUN_SECURITY_OFFICE = 0x1FC,
+ NOUN_SIGNAL = 0x1FD,
+ NOUN_BLEEP = 0x1FE,
+ NOUN_BLIP = 0x1FF,
+ NOUN_LOFT = 0x200,
+ NOUN_ELECTRONIC_ANT_FARM = 0x201,
+ NOUN_ELECTRIC_WIRING = 0x202,
+ NOUN_SECURITY_PANEL = 0x203,
+ NOUN_CORRIDOR = 0x204,
+ NOUN_CIRCUIT_CONTROLS = 0x205,
+ NOUN_AIR_DUCT = 0x206,
+ NOUN_CELL_WALL = 0x207,
+ NOUN_LIGHTS = 0x208,
+ //NOUN_STARE_INTO = 0x209,
+ NOUN_CELL_CONTROLS = 0x20A,
+ NOUN_COMMODE = 0x20B,
+ //NOUN_USE = 0x20C,
+ NOUN_BASIN = 0x20D,
+ //NOUN_JUMP_INSIDE = 0x20E,
+ NOUN_PREVIOUS_CELL = 0x20F,
+ NOUN_NEXT_ROOM = 0x210,
+ NOUN_ZINK = 0x211,
+ //NOUN_GAZE_INTO = 0x212,
+ NOUN_THRONE = 0x213,
+ NOUN_SACK = 0x214,
+ NOUN_LIMB = 0x215,
+ NOUN_SINK = 0x216,
+ NOUN_JOHNNY_ON_THE_SPOT = 0x217,
+ NOUN_DEBRIS = 0x218,
+ NOUN_BUNK = 0x219,
+ NOUN_NEXT_CELL = 0x21A,
+ NOUN_TOILET = 0x21B,
+ NOUN_MONITOR_AREA = 0x21C,
+ NOUN_SIDEWALL = 0x21D,
+ NOUN_COFFEE_MUG = 0x21E,
+ //NOUN_SIT_AT = 0x21F,
+ NOUN_LIGHTING_FIXTURE = 0x220,
+ NOUN_MONITORS = 0x221,
+ NOUN_GENDER_CONTROLS = 0x222,
+ NOUN_NEURO_ANALYZER = 0x223,
+ NOUN_MOLECULAR_RECORDER = 0x224,
+ NOUN_MAINTENANCE_PANEL = 0x225,
+ NOUN_RAMP = 0x226,
+ //NOUN_WALK_UP = 0x227,
+ NOUN_SUBSONIC_ATOMIZER = 0x228,
+ NOUN_EIGHT_BALL = 0x229,
+ NOUN_DNA_INVERTER = 0x22A,
+ NOUN_DNA_CONVERTER = 0x22B,
+ NOUN_PLATFORM = 0x22C,
+ NOUN_GUINEA_PIG_TEST_BOX = 0x22D,
+ NOUN_GASEOUS_PROBE_WARPER = 0x22E,
+ NOUN_TOOL_CABINET = 0x22F,
+ NOUN_SURGICAL_BOXES = 0x230,
+ NOUN_FETAL_HEART_MONITOR = 0x231,
+ NOUN_XRAY_CABINET = 0x232,
+ NOUN_STERILIZATION_SINK = 0x233,
+ NOUN_DRIPOLATOR = 0x234,
+ NOUN_SHOCK_MACHINE = 0x235,
+ NOUN_INTERROGATION_TABLE = 0x236,
+ NOUN_LIE_DOWN_ON = 0x237,
+ //NOUN_DECIPHER = 0x238,
+ NOUN_GUARD = 0x239,
+ NOUN_RIP_IN_FLOOR = 0x23A,
+ NOUN_TELEPORT_AREA = 0x23B,
+ NOUN_BROKEN_BEAM = 0x23C,
+ NOUN_ROCK_CHUNK = 0x23D,
+ NOUN_BLOODY_CELL_WALL = 0x23E,
+ NOUN_WALL_BOARD = 0x23F,
+ NOUN_GENDER_SCANNER = 0x240,
+ NOUN_BAR = 0x241,
+ //NOUN_WALK_INTO = 0x242,
+ NOUN_HALLWAY_TO_SOUTH = 0x243,
+ NOUN_SIGN = 0x244,
+ NOUN_HALLWAY_TO_NORTH = 0x245,
+ NOUN_BOTTLES = 0x246,
+ NOUN_UPPER_DANCE_FLOOR = 0x247,
+ NOUN_DANCE_FLOOR = 0x248,
+ NOUN_RAILING = 0x249,
+ NOUN_BAR_STOOL = 0x24A,
+ NOUN_LADY = 0x24B,
+ NOUN_UPPER_LEVEL = 0x24C,
+ NOUN_ALCOVE = 0x24D,
+ NOUN_DISCO_BALL = 0x24E,
+ NOUN_LADIES = 0x24F,
+ NOUN_COACH_LAMP = 0x250,
+ NOUN_CARD_SLOT = 0x251,
+ NOUN_HOOP = 0x252,
+ NOUN_CANNONBALLS = 0x253,
+ NOUN_WATER_FOUNTAIN = 0x254,
+ NOUN_HALLWAY_TO_EAST = 0x255,
+ NOUN_HALLWAY_TO_WEST = 0x256,
+ NOUN_SUPPORT = 0x257,
+ NOUN_BACKBOARD = 0x258,
+ NOUN_WIDE_DOOR = 0x259,
+ NOUN_SIGN_POST = 0x25A,
+ NOUN_FIRE_EXTINGUISHER = 0x25B,
+ NOUN_TRASH = 0x25C,
+ NOUN_MISSILES = 0x25D,
+ NOUN_TANK = 0x25E,
+ NOUN_TWO_TON_WEIGHT = 0x25F,
+ NOUN_ONE_TON_TOMATO = 0x260,
+ NOUN_ANVIL = 0x261,
+ NOUN_MINUTEMAN_IV_ICBM = 0x262,
+ NOUN_CHEST = 0x263,
+ NOUN_ARMOR = 0x264,
+ NOUN_CARTON = 0x265,
+ NOUN_POWDER = 0x266,
+ NOUN_RAFT = 0x267,
+ NOUN_WHATZIT = 0x268,
+ NOUN_CATAPULT = 0x269,
+ NOUN_HAND_GRENADE = 0x26A,
+ NOUN_BARRELS = 0x26B,
+ NOUN_LOADING_RAMP = 0x26C,
+ NOUN_BLIMP = 0x26D,
+ NOUN_FLOUR = 0x26E,
+ NOUN_FLY_PAPER = 0x26F,
+ NOUN_RUG = 0x270,
+ NOUN_CARPET = 0x271,
+ NOUN_CAN = 0x272,
+ NOUN_RUBBER_DUCKIE = 0x273,
+ NOUN_GOLF_CLUBS = 0x274,
+ NOUN_RAT = 0x275,
+ NOUN_BARREL = 0x276,
+ NOUN_BUCKET_OF_TAR = 0x277,
+ NOUN_SACKS = 0x278,
+ NOUN_STORAGE = 0x279,
+ NOUN_120V_3_PHASE_400HZ = 0x27A,
+ NOUN_LAB_EQUIPMENT = 0x27B,
+ NOUN_AIR_HORN = 0x27C,
+ NOUN_JAR = 0x27D,
+ NOUN_SEVERED_CABLE = 0x27E,
+ NOUN_PROBE_ASSEMBLY = 0x27F,
+ NOUN_KNIFE_SWITCH = 0x280,
+ NOUN_WORK_BENCH = 0x281,
+ NOUN_HEATER = 0x282,
+ NOUN_TOXIC_WASTE = 0x283,
+ NOUN_EXPERIMENT = 0x284,
+ NOUN_DRAWING_BOARD = 0x285,
+ NOUN_MISHAP = 0x286,
+ NOUN_AIR_PURIFIER = 0x287,
+ NOUN_DUMMY = 0x288,
+ NOUN_PICTURE = 0x289,
+ NOUN_BAGGAGE_CHECK = 0x28A,
+ NOUN_DEPARTURE_SCHEDULE = 0x28B,
+ NOUN_SHADE_OF_PALE = 0x28C,
+ NOUN_ITINERARY = 0x28D,
+ NOUN_BARGAIN_VAT = 0x28E,
+ NOUN_PENCILS = 0x28F,
+ NOUN_PAD_IF_PAPER = 0x290,
+ NOUN_DEEPEST_DEPTHS = 0x291,
+ NOUN_ROLODEX = 0x292,
+ NOUN_MONA_TISA = 0x293,
+ NOUN_ABSTRACT_ART = 0x294,
+ NOUN_SPACE_QUESTING_VIII = 0x295,
+ NOUN_THEATRICAL_ART = 0x296,
+ NOUN_METAL_POLE = 0x297,
+ NOUN_EXIT = 0x298,
+ NOUN_SWIRLING_LIGHT = 0x299,
+ NOUN_REGISTER = 0x29A,
+ NOUN_PEACHY_BUNS = 0x29B,
+ NOUN_OUR_TOWN = 0x29C,
+ NOUN_EMBROIDERED_ART = 0x29D,
+ NOUN_GEORGE_BUSH_ALIKE = 0x29E,
+ NOUN_COUNTER = 0x29F,
+ NOUN_SENSOR = 0x2A0,
+ NOUN_SOFTWARE_INFORMATION = 0x2A1,
+ NOUN_WALK_BEHIND = 0x2A2,
+ NOUN_BARGAINS = 0x2A3,
+ NOUN_SCAN_LIGHT = 0x2A4,
+ NOUN_OLD_SOFTWARE_STAND = 0x2A5,
+ NOUN_SOFTWARE_SHELF = 0x2A6,
+ NOUN_HOTTEST_SOFTWARE = 0x2A7,
+ NOUN_GREAT_PAINTBALL_ART = 0x2A8,
+ NOUN_SCENIC_VISTA = 0x2A9,
+ NOUN_LASER = 0x2AA,
+ NOUN_LASER_JET = 0x2AB,
+ NOUN_LEVER = 0x2AC,
+ NOUN_BULLSEYE = 0x2AD,
+ NOUN_STAND = 0x2AE,
+ NOUN_CONTROL_STATION = 0x2AF,
+ NOUN_STRANGE_MONSTER = 0x2B0,
+ NOUN_GHASTLY_BEAST = 0x2B1,
+ //NOUN_GAWK_AT = 0x2B2,
+ NOUN_CORRIDOR_TO_SOUTH = 0x2B3,
+ NOUN_CORRIDOR_TO_NORTH = 0x2B4,
+ NOUN_WALK_ONTO = 0x2B5,
+ NOUN_ROCK_WALL = 0x2B6,
+ NOUN_WOMAN = 0x2B7,
+ NOUN_WOMEN = 0x2B8,
+ NOUN_CORRIDOR_TO_EAST = 0x2B9,
+ NOUN_CORRIDOR_TO_WEST = 0x2BA,
+ NOUN_AMMUNITION = 0x2BB,
+ NOUN_ARMORED_VEHICLE = 0x2BC,
+ NOUN_TOMATO = 0x2BD,
+ NOUN_MISSILE = 0x2BE,
+ NOUN_SUIT_OF_ARMOR = 0x2BF,
+ NOUN_POWDER_CONTAINER = 0x2C0,
+ NOUN_INFLATABLE_RAFT = 0x2C1,
+ NOUN_GRENADE = 0x2C2,
+ NOUN_FENCE = 0x2C3,
+ NOUN_WOODEN_STATUE = 0x2C4,
+ NOUN_CONVEYER_BELT = 0x2C5,
+ NOUN_CONTROLS = 0x2C6,
+ NOUN_EQUIPMENT = 0x2C7,
+ NOUN_SHELF = 0x2C8,
+ NOUN_CABINETS = 0x2C9,
+ NOUN_CONTROL_CONSOLE = 0x2CA,
+ NOUN_FAUCET = 0x2CB,
+ NOUN_PANEL_BOX = 0x2CC,
+ NOUN_STATUE = 0x2CD,
+ NOUN_GAUGE = 0x2CE,
+ NOUN_CIRCUIT_PANEL = 0x2CF,
+ NOUN_CATWALK = 0x2D0,
+ NOUN_CIRCUITS = 0x2D1,
+ NOUN_BLOOD_STAIN = 0x2D2,
+ NOUN_GRATE = 0x2D3,
+ NOUN_AIR_SHAFT = 0x2D4,
+ //NOUN_RETURN_TO = 0x2D5,
+ NOUN_FORMALDEHYDE = 0x2D6,
+ NOUN_PETROX = 0x2D7,
+ NOUN_SODIUM_BENZOATE = 0x2D8,
+ NOUN_GURNEY = 0x2D9,
+ NOUN_IRONING_BOARD = 0x2DA,
+ NOUN_LEFT_MONITOR = 0x2DB,
+ NOUN_RIGHT_MONITOR = 0x2DC,
+ NOUN_RED_BUTTON = 0x2DD,
+ NOUN_GREEN_BUTTON = 0x2DE,
+ NOUN_RIGHT_ONE_KEY = 0x2DF,
+ NOUN_RIGHT_1_KEY = 0x2E0,
+ NOUN_RIGHT_2_KEY = 0x2E1,
+ NOUN_RIGHT_3_KEY = 0x2E2,
+ NOUN_RIGHT_4_KEY = 0x2E3,
+ NOUN_RIGHT_5_KEY = 0x2E4,
+ NOUN_RIGHT_6_KEY = 0x2E5,
+ NOUN_RIGHT_7_KEY = 0x2E6,
+ NOUN_RIGHT_8_KEY = 0x2E7,
+ NOUN_LEFT_1_KEY = 0x2E8,
+ NOUN_LEFT_2_KEY = 0x2E9,
+ NOUN_LEFT_3_KEY = 0x2EA,
+ NOUN_LEFT_4_KEY = 0x2EB,
+ NOUN_CORRIDOR_WALL = 0x2EC,
+ NOUN_MUG = 0x2ED,
+ NOUN_DOUGHNUT = 0x2EE,
+ NOUN_SECURITY_STATION = 0x2EF,
+ NOUN_NEWSPAPER = 0x2F0,
+ NOUN_MAGAZINE = 0x2F1,
+ NOUN_CLIPBOARD = 0x2F2,
+ NOUN_PAPER_FOOTBALL = 0x2F3,
+ NOUN_YOUR_STUFF = 0x2F4,
+ NOUN_OTHER_STUFF = 0x2F5,
+ NOUN_LAMP = 0x2F6,
+ NOUN_CLIMB_INTO = 0x2F7,
+ NOUN_LIGHT_BULB = 0x2F8,
+ //NOUN_STEP_INTO = 0x2F9,
+ NOUN_ROOM = 0x2FA,
+ //NOUN_CRAWL_TO = 0x2FB,
+ NOUN_FOURTH_CELL = 0x2FC,
+ NOUN_THIRD_CELL = 0x2FD,
+ NOUN_SECOND_CELL = 0x2FE,
+ NOUN_FIRST_CELL = 0x2FF,
+ NOUN_EQUIPMENT_ROOM = 0x300,
+ //NOUN_CRAWL_DOWN = 0x301,
+ NOUN_DESCENDING_SHAFT = 0x302,
+ NOUN_SAUROPOD = 0x303,
+ NOUN_MONSTER = 0x304,
+ NOUN_FAKE_ID = 0x305,
+ NOUN_ALIEN_LIQUOR = 0x306,
+ NOUN_INTERN = 0x307,
+ NOUN_INSTRUMENT_TABLE = 0x308,
+ NOUN_WOMAN_ON_BALCONY = 0x309,
+ NOUN_WOMAN_IN_CHAIR = 0x30A,
+ //NOUN_SIT_ON = 0x30B,
+ NOUN_WOMAN_IN_ALCOVE = 0x30C,
+ NOUN_KETTLE = 0x30D,
+ NOUN_BARTENDER = 0x30E,
+ NOUN_WHISKEY = 0x30F,
+ NOUN_ALCOHOL = 0x310,
+ NOUN_RIM = 0x311,
+ //NOUN_WALK_ALONG = 0x312,
+ NOUN_SUBMERGED_CITY = 0x313,
+ NOUN_GOVERNORS_HOUSE = 0x314,
+ NOUN_RIM_TOWARDS_EAST = 0x315,
+ NOUN_CEMENT_PYLON = 0x316,
+ NOUN_ELEVATOR = 0x317,
+ NOUN_ELEVATOR_SHAFT = 0x318,
+ NOUN_CONVEYOR_BELT = 0x319,
+ NOUN_CANNON_BALLS = 0x31A,
+ NOUN_ELECTRICAL_OVERHANG = 0x31B,
+ NOUN_GUTTER_PIPE = 0x31C,
+ NOUN_SIDEWALK = 0x31D,
+ NOUN_STREET = 0x31E,
+ NOUN_BARRICADE = 0x31F,
+ NOUN_DOOR_CONTROL_SLOT = 0x320,
+ NOUN_STREET_TO_EAST = 0x321,
+ NOUN_SIDEWALK_TO_EAST = 0x322,
+ NOUN_BUILDING = 0x323,
+ NOUN_CAR = 0x324,
+ //NOUN_GET_INSIDE = 0x325,
+ NOUN_MARQUEE = 0x326,
+ NOUN_BUILDING_ENTRANCE = 0x327,
+ NOUN_GUARD_STATION = 0x328,
+ NOUN_TECHNICAL_EQUIPMENT = 0x329,
+ NOUN_GUARD_TURRET = 0x32A,
+ NOUN_PILLAR = 0x32B,
+ NOUN_PAPERS = 0x32C,
+ NOUN_FILE_CABINET = 0x32D,
+ NOUN_WINDOWS = 0x32E,
+ //NOUN_WALK = 0x32F,
+ NOUN_STORAGE_BOX = 0x330,
+ NOUN_WATER_COOLER = 0x331,
+ NOUN_BOX = 0x332,
+ NOUN_RIFLES = 0x333,
+ NOUN_SLINGSHOT = 0x334,
+ NOUN_MAUSOLEUM = 0x335,
+ NOUN_SOFTWARE_STORE = 0x336,
+ NOUN_CONCRETE_BUILDING = 0x337,
+ NOUN_HUMONGOUS_MONITOR = 0x338,
+ NOUN_SPACE_BIKE = 0x339,
+ NOUN_BILLBOARD = 0x33A,
+ NOUN_LACK_OF_NOOKIE_MOTEL = 0x33B,
+ NOUN_BIDETS_XCREETZA_HUT = 0x33C,
+ NOUN_BUILDINGS = 0x33D,
+ NOUN_SKYSCRAPER = 0x33E,
+ NOUN_SOFTWARE_LOGO = 0x33F,
+ NOUN_GIANT_TELESCOPE = 0x340,
+ NOUN_HANDLE = 0x341,
+ NOUN_HOLE = 0x342,
+ NOUN_LASER_BEAM = 0x343,
+ NOUN_PEDESTAL = 0x344,
+ NOUN_BOAT = 0x345,
+ NOUN_GIANT_MONUMENT = 0x346,
+ NOUN_ROPE = 0x347,
+ NOUN_SAND_BAR_RESTAURANT = 0x348,
+ NOUN_PORTHOLE = 0x349,
+ NOUN_TICKET_BOOTH = 0x34A,
+ NOUN_POLLYS_ENTRANCE = 0x34B,
+ NOUN_RESTAURANT_ENTRANCE = 0x34C,
+ NOUN_THE_PLEASURE_DOME = 0x34D,
+ NOUN_STARFISH = 0x34E,
+ NOUN_FLIPPER = 0x34F,
+ NOUN_SAND_DOLLAR = 0x350,
+ NOUN_SHELL = 0x351,
+ NOUN_GUEST_LIST = 0x352,
+ NOUN_WEIRD_ANIMAL_HEAD = 0x353,
+ NOUN_SHIPS_WHEEL = 0x354,
+ NOUN_HANDICAP_SIGN = 0x355,
+ NOUN_ELEVATOR_CONTROLS = 0x356,
+ NOUN_BRICK_WALL = 0x357,
+ NOUN_BIKE_RACK = 0x358,
+ NOUN_ODONALDS_SIGN = 0x359,
+ NOUN_ELEVATOR_ENTRANCE = 0x35A,
+ NOUN_SPECIAL_SALE_SIGN = 0x35B,
+ NOUN_ATTORNEYS_AT_LAW = 0x35C,
+ NOUN_SLEDGE_MALL = 0x35D,
+ NOUN_SKELETON = 0x35E,
+ NOUN_STRANGE_EQUIPMENT = 0x35F,
+ NOUN_STREET_TO_WEST = 0x360,
+ NOUN_SIDEWALK_TO_WEST = 0x361,
+ NOUN_TELEPORTER_ENTRANCE = 0x362,
+ NOUN_SOFTWARE_DOOR = 0x363,
+ NOUN_SPINACH_PATCH_DOLL = 0x364,
+ //NOUN_REFLECT = 0x365,
+ NOUN_REGISTER_DRAWER = 0x366,
+ NOUN_ELEVATOR_DOOR = 0x367,
+ NOUN_HYDRAULIC_SUPPORT = 0x368,
+ NOUN_EQUIPMENT_OVERHEAD = 0x369,
+ //NOUN_GET_INTO = 0x36A,
+ NOUN_WARNING_LABEL = 0x36B,
+ NOUN_NUCLEAR_SLINGSHOT = 0x36C,
+ NOUN_DISPLAY_CASE = 0x36D,
+ NOUN_PHOTON_RIFLES = 0x36E,
+ NOUN_MONITORING_EQUIPMENT = 0x36F,
+ NOUN_TELESCOPE = 0x370,
+ NOUN_MOTEL = 0x371,
+ NOUN_RESTAURANT = 0x372,
+ NOUN_SOFTWARE_STORE_SIGN = 0x373,
+ NOUN_ADVERTISING_POSTER = 0x374,
+ NOUN_ADVERTISEMENT = 0x375,
+ NOUN_OLD_SOFTWARE = 0x376,
+ NOUN_CASH_REGISTER = 0x377,
+ NOUN_ENTRANCE = 0x378,
+ NOUN_LASER_CANNON = 0x379,
+ NOUN_SAND_BAGS = 0x37A,
+ NOUN_PLEASURE_DOME = 0x37B,
+ NOUN_DOME_ENTRANCE = 0x37C,
+ NOUN_LABORATORY = 0x37D,
+ NOUN_STREET_TO_SOUTH = 0x37E,
+ NOUN_ELEVATOR_ACCESS_SLOT = 0x37F,
+ NOUN_CAR_CONTROLS = 0x380,
+ NOUN_SCENT_PACKET = 0x381,
+ NOUN_KITTY = 0x382,
+ NOUN_GLOVE_COMPARTMENT = 0x383,
+ NOUN_MOLDY_SOCK = 0x384,
+ NOUN_SODA_CANS = 0x385,
+ NOUN_WINDSHIELD = 0x386,
+ NOUN_DASHBOARD = 0x387,
+ NOUN_INTERIOR_OF_CAR = 0x388,
+ NOUN_VIEW_RIGHT_BUTTON = 0x389,
+ NOUN_BLACK_BUTTON = 0x38A,
+ NOUN_WHITE_BUTTON = 0x38B,
+ NOUN_INSIDE_OF_CAR = 0x38C,
+ NOUN_RIM_TOWARDS_WEST = 0x38D,
+ NOUN_CEMENT_BLOCK = 0x38E,
+ NOUN_CITY = 0x38F,
+ NOUN_SPEAKER = 0x390,
+ NOUN_EYE_CHART = 0x391,
+ NOUN_LAUNCH_PAD = 0x392,
+ NOUN_BUILDING_TO_WEST = 0x393,
+ NOUN_PAD_TO_EAST = 0x394,
+ NOUN_PAD_TO_WEST = 0x395,
+ NOUN_TOWER = 0x396,
+ NOUN_LOOK_OUT = 0x397,
+ NOUN_SERVICE_PANEL = 0x398,
+ NOUN_CRACK = 0x399,
+ NOUN_THROTTLE = 0x39A,
+ NOUN_GRAB = 0x39B,
+ NOUN_INSTRUMENTATION = 0x39C,
+ NOUN_TP = 0x39D,
+ NOUN_SEAT = 0x39E,
+ NOUN_STATUS_PANEL = 0x39F,
+ NOUN_SHIPS_CONTROLS = 0x3A0,
+ NOUN_PROFESSOR = 0x3A1,
+ NOUN_PROFESSORS_GURNEY = 0x3A2,
+ NOUN_WELCOME_MAT = 0x3A3,
+ NOUN_MELON_MUSH = 0x3A4,
+ NOUN_BADMINTON_BRAT = 0x3A5,
+ //NOUN_APPLY = 0x3A6,
+ NOUN_COMBINATION = 0x3A7,
+ NOUN_NOTE = 0x3A8,
+ NOUN_LECITHIN = 0x3A9,
+ NOUN_REPAIR_WOMAN = 0x3AA,
+ NOUN_EXPLOSIVES = 0x3AB,
+ NOUN_DOLLOP = 0x3AC,
+ NOUN_DROP = 0x3AD,
+ NOUN_DASH = 0x3AE,
+ NOUN_SPLASH = 0x3AF,
+ NOUN_DOCK_TO_SOUTH = 0x3B0,
+ //NOUN_STEER_TOWARDS = 0x3B1,
+ NOUN_BUILDING_TO_NORTH = 0x3B2,
+ NOUN_VOLCANO_RIM = 0x3B3,
+ NOUN_OPEN_WATER_TO_SOUTH = 0x3B4,
+ NOUN_PROJECTOR = 0x3B5,
+ NOUN_GUARDS_ARM2 = 0x3B6,
+ //NOUN_NIBBLE_ON = 0x3B7,
+ //NOUN_ENTER = 0x3B8,
+ NOUN_ = 0x3B9,
+ NOUN_TIMER_BUTTON_1 = 0x3BA,
+ NOUN_REMOTE_BUTTON_1 = 0x3BB,
+ NOUN_START_BUTTON_2 = 0x3BC,
+ NOUN_REMOTE_BUTTON_2 = 0x3BD,
+ NOUN_TIMER_BUTTON_2 = 0x3BE,
+ NOUN_START_BUTTON_1 = 0x3BF,
+ NOUN_ANTIGRAV_CONTROLS = 0x3C0,
+ NOUN_BRUCES_TREE = 0x3C1,
+ NOUN_COLISEUM = 0x3C2,
+ NOUN_BRUCES_GARDEN_ROOM = 0x3C3,
+ NOUN_FOUNTAIN = 0x3C4,
+ NOUN_HOUSE_OF_BRUCE = 0x3C5,
+ NOUN_CITY_BACKDROP = 0x3C6,
+ NOUN_BRUCES_BALCONY = 0x3C7,
+ NOUN_BRUCES_ENTRANCE = 0x3C8,
+ NOUN_BRUCES_LOGO = 0x3C9,
+ NOUN_LOUNGE_CHAIR = 0x3CA,
+ NOUN_LIVING_ROOM_FLOOR = 0x3CB,
+ NOUN_LIVINGROOM_FLOOR = 0x3CC,
+ NOUN_PERFUME_BOTTLE = 0x3CD,
+ NOUN_COOL_NEON_LIGHT = 0x3CE,
+ NOUN_FLOWER_POT = 0x3CF,
+ NOUN_COFFEE_TABLE = 0x3D0,
+ NOUN_FLOWERS = 0x3D1,
+ NOUN_ART_DECO_CHAIR = 0x3D2,
+ NOUN_SAFE = 0x3D3,
+ NOUN_SPLASHY_DECOR = 0x3D4,
+ NOUN_THEATRICAL_FACES = 0x3D5,
+ NOUN_ART_DECO_PIECE = 0x3D6,
+ NOUN_END_OF_ROOM = 0x3D7,
+ NOUN_FIREPLACE = 0x3D8,
+ NOUN_ARTWORK = 0x3D9,
+ NOUN_COOL_NEON_LIGHTS = 0x3DA,
+ NOUN_GLASS_PLATED_WINDOW = 0x3DB,
+ NOUN_BEDROOM_FLOOR = 0x3DC,
+ NOUN_BAUBLE = 0x3DD,
+ NOUN_SNAPSHOT = 0x3DE,
+ NOUN_PERFUME = 0x3DF,
+ NOUN_CLAPBOARD = 0x3E0,
+ NOUN_BERET = 0x3E1,
+ NOUN_HORSE_WHIP = 0x3E2,
+ NOUN_CORNER_TABLE = 0x3E3,
+ NOUN_BOA = 0x3E4,
+ NOUN_WIG_STAND = 0x3E5,
+ NOUN_PARTITION = 0x3E6,
+ NOUN_MEGAPHONE = 0x3E7,
+ NOUN_SLIP = 0x3E8,
+ NOUN_SCONCE = 0x3E9,
+ NOUN_VANITY = 0x3EA,
+ NOUN_BEDBOARD = 0x3EB,
+ NOUN_LOVE_SEAT = 0x3EC,
+ NOUN_SOUVENIR_TICKETS = 0x3ED,
+ NOUN_REVIEW = 0x3EE,
+ NOUN_BRUCE_AT_THE_GALA = 0x3EF,
+ NOUN_ART_DECO_RUG = 0x3F0,
+ NOUN_LIVINGROOM = 0x3F1,
+ NOUN_SCULPTURE = 0x3F2,
+ NOUN_SPECIMEN_EPITHET = 0x3F3,
+ NOUN_VENT = 0x3F4,
+ NOUN_FLOWER_BOX = 0x3F5,
+ NOUN_LEDGE = 0x3F6,
+ NOUN_BOLT = 0x3F7,
+ NOUN_OBSERVATION_WINDOW = 0x3F8,
+ NOUN_AIR_HOSE = 0x3F9,
+ NOUN_AUTO_SHOP = 0x3FA,
+ NOUN_MANHOLE = 0x3FB,
+ NOUN_AUTO_SHOP_ENTRANCE = 0x3FC,
+ NOUN_BROKEN_WINDOW = 0x3FD,
+ NOUN_WOMANHOLE = 0x3FE,
+ NOUN_GARAGE_DOOR = 0x3FF,
+ NOUN_SCRATCH_PAD = 0x400,
+ NOUN_GAS_PRICES = 0x401,
+ NOUN_UP_BUTTON = 0x402,
+ NOUN_DOWN_BUTTON = 0x403,
+ NOUN_SPARE_PARTS_LIST = 0x404,
+ NOUN_SKYLIGHT = 0x405,
+ NOUN_TOOL_BOX = 0x406,
+ NOUN_CAR_LIFT = 0x407,
+ NOUN_CAR_SEAT = 0x408,
+ NOUN_GARAGE_FLOOR = 0x409,
+ NOUN_GARAGE_DOOR_CONTROLS = 0x40A,
+ NOUN_AMISH_HAT = 0x40B,
+ NOUN_JACK = 0x40C,
+ NOUN_COILS = 0x40D,
+ NOUN_OIL_CAN = 0x40E,
+ NOUN_FAN_BELTS = 0x40F,
+ NOUN_REAR_OF_GARAGE = 0x410,
+ NOUN_FRONT_OF_GARAGE = 0x411,
+ NOUN_MUFFLER = 0x412,
+ NOUN_SPARE_PART = 0x413,
+ NOUN_HUBCAP = 0x414,
+ NOUN_CANDLE = 0x415,
+ NOUN_RATES = 0x416,
+ NOUN_GREASE_CAN = 0x417,
+ NOUN_CALENDAR = 0x418,
+ NOUN_FORK_LIFT = 0x419,
+ NOUN_TRASH_CAN = 0x41A,
+ NOUN_SHAKER_CHAIR = 0x41B,
+ NOUN_QUARTER_PANEL = 0x41C,
+ NOUN_AREA_BEHIND_CAR = 0x41D,
+ NOUN_DANGER_ZONE = 0x41E,
+ NOUN_NEWSSTAND = 0x41F,
+ NOUN_LADY_GODIVA_MONUMENT = 0x420,
+ NOUN_SPOT_A_POT = 0x421,
+ NOUN_GUARD_RAIL = 0x422,
+ NOUN_ALLEY = 0x423,
+ NOUN_DITCH = 0x424,
+ NOUN_VIDEO_STORE_DOOR = 0x425,
+ NOUN_BUCKLUSTER_MARQUEE = 0x426,
+ NOUN_VIDEO_STORE = 0x427,
+ NOUN_HORMONE_BILLBOARD = 0x428,
+ NOUN_PHONE_ANTENNA = 0x429,
+ NOUN_RETURN_SLOT = 0x42A,
+ NOUN_NOOSE = 0x42B,
+ NOUN_COMEDY_VIDEOS = 0x42C,
+ NOUN_SMELLY_SNEAKER = 0x42D,
+ NOUN_PIPPYS_STOCKING = 0x42E,
+ NOUN_PHONE_CRADLE = 0x42F,
+ NOUN_DRAMA_VIDEOS = 0x430,
+ NOUN_SPOTLIGHT = 0x431,
+ NOUN_STOREROOM_FLOOR = 0x432,
+ NOUN_ALL_SALES_FINAL = 0x433,
+ NOUN_MACHOPROSE_TEE_SHIRT = 0x434,
+ NOUN_UNKNOWN_COMIC_HANDS = 0x435,
+ NOUN_WET_CEMENT = 0x436,
+ NOUN_PIPPYS_TINY_IMPRINT = 0x437,
+ NOUN_OBNOXIOUS_DOG_PAWS = 0x438,
+ NOUN_LEG_AND_A_LEG_JEANS = 0x439,
+ NOUN_VIDEO_STORE_EXIT = 0x43A,
+ NOUN_AISLE = 0x43B,
+ NOUN_VIDEO_MONITOR = 0x43C,
+ NOUN_POLLY_PIGS_IMPRINT = 0x43D,
+ NOUN_JOHN_WYNNS_IMPRINT = 0x43E,
+ NOUN_MR_NEDS_IMPRINT = 0x43F,
+ NOUN_PEG_LEG_PETE_IMPRINT = 0x440,
+ NOUN_MARX_BROS_POSTER = 0x441,
+ NOUN_PIPPY_BILLBOARD = 0x442,
+ NOUN_VIDEOS_NOONE_WANTS = 0x443,
+ NOUN_MORE_CLASSIC_VIDEOS = 0x444,
+ NOUN_JOIN_OUR_PRICE_CLUB = 0x445,
+ NOUN_EDUCATIONAL_VIDEOS = 0x446,
+ NOUN_DEEP_DISCOUNT_TITLES = 0x447,
+ NOUN_WORLD_CHAMPS_POSTER = 0x448,
+ NOUN_WORKOUT_VIDEOS = 0x449,
+ NOUN_20_PERCENT_OFF_SIGN = 0x44A,
+ NOUN_CIVILIZATION_AD = 0x44B,
+ NOUN_NEW_RELEASE_VIDEOS = 0x44C,
+ NOUN_PORNO_VIDEOS = 0x44D,
+ NOUN_FOREIGN_VIDEOS = 0x44E,
+ NOUN_CLASSIC_VIDEOS = 0x44F,
+ NOUN_ADVENTURE_VIDEOS = 0x450,
+ NOUN_BUCKLUSTER_LOGO = 0x451,
+ NOUN_WINE_BOTTLE = 0x452,
+ NOUN_DIRT_PILE = 0x453,
+ NOUN_MAMMOTH_PENCIL_HEAD = 0x454,
+ NOUN_WREAKY_PUMPKIN = 0x455,
+ NOUN_MILK_CARTON = 0x456,
+ NOUN_BUCKET = 0x457,
+ NOUN_EMPTY_BOX = 0x458,
+ NOUN_DIAPER_BOX = 0x459,
+ NOUN_HERMIT = 0x45A,
+ NOUN_METAL_PIPE = 0x45B,
+ NOUN_CONCRETE_SUPPORT = 0x45C,
+ NOUN_VARIOUS_TRASH = 0x45D,
+ NOUN_ARMATURE = 0x45E,
+ NOUN_CONTROL_BOX = 0x45F,
+ NOUN_TOP_OF_DOME = 0x460,
+ NOUN_EXPRESSWAY_TO_EAST = 0x461,
+ NOUN_GO_TOWARDS = 0x462,
+ NOUN_EXPRESSWAY_TO_WEST = 0x463,
+ NOUN_DOME = 0x464,
+ NOUN_VIEW_OF_CITY = 0x465,
+ NOUN_EXPRESSWAY = 0x466,
+ NOUN_HOOK = 0x467,
+ NOUN_SEA_MONSTER = 0x468,
+ NOUN_EDGE_OF_VOLCANO = 0x469,
+ NOUN_JUMP_THROUGH = 0x46A,
+ NOUN_OLD_TEA_CUP = 0x46B,
+ NOUN_NAME_PLATE = 0x46C,
+ NOUN_OLD_VASE = 0x46D,
+ NOUN_PORTRAIT = 0x46E,
+ //NOUN_PUT_DOWN = 0x46F,
+ NOUN_TALL_BUILDING = 0x470,
+ NOUN_OBNOXIOUS_DOG = 0x471,
+ NOUN_GUTS = 0x472,
+ NOUN_BIG_HEADS = 0x473,
+ NOUN_INSTALL = 0x474,
+ NOUN_LIFE_SUPPORT_MODULE = 0x475,
+ //NOUN_REMOVE = 0x476,
+ NOUN_LARGE_BLADE = 0x477,
+ NOUN_SIDE_ENTRANCE = 0x478,
+ NOUN_INDICATOR = 0x479,
+ NOUN_SIGNPOST = 0x47A,
+ NOUN_PIN = 0x47B,
+ NOUN_POWDER_PUFF = 0x47C,
+ NOUN_SHELVES = 0x47D,
+ NOUN_ELECTRODES = 0x47E,
+ NOUN_MISHAP2 = 0x47F,
+ NOUN_ISLD_SUPERSTRUCTURE = 0x480,
+ NOUN_FILE_CABINETS = 0x481,
+ NOUN_CYCLE_SHOP = 0x482,
+ NOUN_AIR_BIKE = 0x483,
+ NOUN_EMERGENCY_LIGHT = 0x484,
+ NOUN_TARGET_AREA = 0x485,
+ NOUN_ICE_CHESTS = 0x486,
+ NOUN_BIRDS = 0x487,
+ NOUN_DOCTORS_OFFICE = 0x488,
+ //NOUN_DEFACE = 0x489,
+ NOUN_LARGE_HEADS = 0x48A,
+ NOUN_SMALL_TABLE = 0x48B,
+ NOUN_COLLOSSEUM = 0x48C,
+ NOUN_HOUSE = 0x48D,
+ NOUN_BALCONY = 0x48E,
+ NOUN_GARDEN_ROOM = 0x48F,
+ NOUN_COVE_LIGHTS = 0x490,
+ NOUN_MASKS = 0x491,
+ NOUN_NEON_LIGHTS = 0x492,
+ NOUN_GLASS_BLOCK_WALL = 0x493,
+ NOUN_SCREEN = 0x494,
+ NOUN_SPARE_RIBS = 0x495,
+ NOUN_BANNER = 0x496,
+ NOUN_INSTRUCTIONAL_VIDEOS = 0x497,
+ NOUN_CEMENT = 0x498,
+ NOUN_STORE = 0x499,
+ NOUN_CARDBOARD_BOX = 0x49A,
+ NOUN_GRAFFITTI = 0x49B,
+ NOUN_GRAFFITI = 0x49C,
+ NOUN_PHOTOGRAPH = 0x49D,
+ NOUN_DIRECTORS_SLATE = 0x49E,
+ NOUN_CROP = 0x49F,
+ NOUN_HAT = 0x4A0,
+ NOUN_LOGO = 0x4A1,
+ NOUN_MAINTENANCE_BUILDING = 0x4A2,
+ //NOUN_MASSAGE = 0x4A3,
+ //NOUN_MANGLE = 0x4A4,
+ //NOUN_RUB = 0x4A5,
+ //NOUN_JUGGLE = 0x4A6,
+ //NOUN_SMASH = 0x4A7,
+ //NOUN_GUZZLE = 0x4A8,
+ NOUN_WEST_END_OF_PLATFORM = 0x4A9,
+ NOUN_EAST_END_OF_PLATFORM = 0x4AA
+ //NOUN_FOLD = 0x4AB,
+ //NOUN_SPINDLE = 0x4AC,
+ //NOUN_MUTILATE = 0x4AD
+};
+
+class SceneFactory {
+public:
+ static SceneLogic *createScene(MADSEngine *vm);
+};
+
+/**
+ * Specialized base class for Rex Nebular game scenes
+ */
+class NebularScene : public SceneLogic {
+protected:
+ NebularGlobals &_globals;
+ GameNebular &_game;
+ MADSAction &_action;
+
+ /**
+ * Forms an animation resource name
+ */
+ Common::String formAnimName(char sepChar, int suffixNum);
+
+ /**
+ * Plays appropriate sound for entering various rooms
+ */
+ void lowRoomsEntrySound();
+public:
+ /**
+ * Constructor
+ */
+ NebularScene(MADSEngine *vm);
+
+ void sub7178C();
+};
+
+class SceneInfoNebular : public SceneInfo {
+ friend class SceneInfo;
+protected:
+ virtual void loadCodes(MSurface &depthSurface, int variant);
+
+ virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream);
+
+ /**
+ * Constructor
+ */
+ SceneInfoNebular(MADSEngine *vm) : SceneInfo(vm) {}
+};
+
+class SceneTeleporter : public NebularScene {
+protected:
+ int _buttonTyped;
+ int _curCode;
+ int _digitCount;
+ int _curMessageId;
+ int _handSpriteId;
+ int _handSequenceId;
+ int _finishedCodeCounter;
+ int _meteorologistNextPlace;
+ int _meteorologistCurPlace;
+ int _teleporterSceneId;
+ Common::String _msgText;
+
+ int teleporterAddress(int code, bool working);
+
+ void teleporterHandleKey();
+ Common::Point teleporterComputeLocation();
+ void teleporterEnter();
+ bool teleporterActions();
+ void teleporterStep();
+
+protected:
+ /**
+ * Constructor
+ */
+ SceneTeleporter(MADSEngine *vm);
+};
+
+} // End of namespace Nebular
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES_H */
diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp
new file mode 100644
index 0000000000..ab072c1d3c
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes1.cpp
@@ -0,0 +1,3164 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes1.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+void Scene1xx::setAAName() {
+ int idx = (_scene->_nextSceneId > 103 && _scene->_nextSceneId < 112) ? 1 : 0;
+ _game._aaName = Resources::formatAAName(idx);
+}
+
+void Scene1xx::sceneEntrySound() {
+ if (_vm->_musicFlag) {
+ switch (_scene->_nextSceneId) {
+ case 101:
+ _vm->_sound->command(11);
+ break;
+ case 102:
+ _vm->_sound->command(12);
+ break;
+ case 103:
+ _vm->_sound->command(3);
+ _vm->_sound->command(25);
+ break;
+ case 109:
+ _vm->_sound->command(13);
+ break;
+ case 110:
+ _vm->_sound->command(10);
+ break;
+ case 111:
+ _vm->_sound->command(3);
+ break;
+ case 112:
+ _vm->_sound->command(15);
+ break;
+ default:
+ if (_scene->_priorSceneId < 104 || _scene->_priorSceneId > 108)
+ _vm->_sound->command(10);
+ break;
+ }
+ }
+}
+
+void Scene1xx::setPlayerSpritesPrefix() {
+ _vm->_sound->command(5);
+ Common::String oldName = _game._player._spritesPrefix;
+ if (_scene->_nextSceneId <= 103 || _scene->_nextSceneId == 111) {
+ if (_globals[kSexOfRex] == SEX_FEMALE)
+ _game._player._spritesPrefix = "ROX";
+ else {
+ _game._player._spritesPrefix = "RXM";
+ _globals[kSexOfRex] = SEX_MALE;
+ }
+ } else if (_scene->_nextSceneId <= 110) {
+ _game._player._spritesPrefix = "RXSW";
+ _globals[kSexOfRex] = SEX_UNKNOWN;
+ } else if (_scene->_nextSceneId == 112)
+ _game._player._spritesPrefix = "";
+
+ if (oldName == _game._player._spritesPrefix)
+ _game._player._spritesChanged = true;
+
+ if (_scene->_nextSceneId == 105 || (_scene->_nextSceneId == 109 && _globals[kHoovicAlive])) {
+ _game._player._spritesChanged = true;
+ _game._player._loadsFirst = false;
+ }
+
+ _game._player._trigger = 0;
+ _vm->_palette->setEntry(16, 10, 63, 63);
+ _vm->_palette->setEntry(17, 10, 45, 45);
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene101::Scene101(MADSEngine *vm) : Scene1xx(vm) {
+ _sittingFl = false;
+ _panelOpened = false;
+ _messageNum = 0;
+ _posY = 0;
+ _shieldSpriteIdx = 0;
+ _chairHotspotId = 0;
+ _oldSpecial = 0;
+}
+
+void Scene101::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_sittingFl);
+ s.syncAsByte(_panelOpened);
+ s.syncAsSint16LE(_messageNum);
+ s.syncAsSint16LE(_posY);
+ s.syncAsSint16LE(_shieldSpriteIdx);
+ s.syncAsSint16LE(_chairHotspotId);
+ s.syncAsSint16LE(_oldSpecial);
+}
+
+void Scene101::setup() {
+ _scene->_animationData->preLoad(formAnimName('A', -1), 3);
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene101::sayDang() {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+
+ switch (_game._trigger) {
+ case 0:
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 6, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ _vm->_sound->command(17);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 3, 2, 0, 0);
+ break;
+
+ case 72:
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17);
+ _scene->_kernelMessages.add(Common::Point(143, 61), 0x1110, 0, 0, 60, _game.getQuote(57));
+ _scene->_sequences.addTimer(120, 73);
+ break;
+
+ case 73:
+ _vm->_dialogs->show(10117);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene101::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 6));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('x', 7));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', -1));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('b', 2));
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('x', 8));
+ _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('x', 0));
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 25);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 0, 1, 0);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 2, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 7, 70);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 10, 0, 0, 60);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 0, 1, 0);
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 2, 0);
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 0, 0, 0);
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 0, 10, 4);
+ _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 6, 0, 32, 47);
+
+ _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false);
+ _panelOpened = false;
+
+ if (_scene->_priorSceneId != -1)
+ _globals[kNeedToStandUp] = false;
+
+ if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(100, 152);
+
+ if ((_scene->_priorSceneId == 112) || ((_scene->_priorSceneId == -2) && _sittingFl )) {
+ _game._player._visible = false;
+ _sittingFl = true;
+ _game._player._playerPos = Common::Point(161, 123);
+ _game._player._facing = FACING_NORTHEAST;
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17);
+ _scene->_hotspots.activate(NOUN_CHAIR, false);
+ _chairHotspotId = _scene->_dynamicHotspots.add(NOUN_CHAIR, VERB_SIT_IN, -1, Common::Rect(159, 84, 159 + 33, 84 + 36));
+ if (_scene->_priorSceneId == 112)
+ sayDang();
+ } else {
+ _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 4);
+ }
+
+ _game.loadQuoteSet(0x31, 0x32, 0x39, 0x36, 0x37, 0x38, 0);
+
+ if (_globals[kNeedToStandUp]) {
+ _scene->loadAnimation(Resources::formatName(101, 'S', -1, EXT_AA, ""), 71);
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _game._player._playerPos = Common::Point(68, 140);
+ _game._player._facing = FACING_WEST;
+
+ _messageNum = 0;
+ _posY = 30;
+ }
+
+ _oldSpecial = false;
+
+ sceneEntrySound();
+}
+
+void Scene101::step() {
+ if (_oldSpecial != _game._player._special) {
+ _oldSpecial = _game._player._special;
+ if (_oldSpecial)
+ _vm->_sound->command(39);
+ else
+ _vm->_sound->command(11);
+ }
+
+ switch (_game._trigger) {
+ case 70:
+ _vm->_sound->command(9);
+ break;
+
+ case 71:
+ _globals[kNeedToStandUp] = false;
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ break;
+
+ case 72:
+ case 73:
+ sayDang();
+ break;
+
+ default:
+ break;
+ }
+
+ if (_scene->_activeAnimation != nullptr) {
+ if ((_scene->_activeAnimation->getCurrentFrame() >= 6) && (_messageNum == 0)) {
+ _messageNum++;
+ _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(49));
+ _posY += 14;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() >= 7) && (_messageNum == 1)) {
+ _messageNum++;
+ _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(54));
+ _posY += 14;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() >= 10) && (_messageNum == 2)) {
+ _messageNum++;
+ _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(55));
+ _posY += 14;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() >= 17) && (_messageNum == 3)) {
+ _messageNum++;
+ _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(56));
+ _posY += 14;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() >= 20) && (_messageNum == 4)) {
+ _messageNum++;
+ _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(50));
+ _posY += 14;
+ }
+ }
+}
+
+void Scene101::preActions() {
+ if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN))
+ _game._player._needToWalk = true;
+
+ if (_sittingFl) {
+ if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_CHAIR) || _action.isAction(VERB_TALKTO) || _action.isAction(VERB_PEER_THROUGH) || _action.isAction(VERB_EXAMINE))
+ _game._player._needToWalk = false;
+
+ if (_game._player._needToWalk) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._readyToWalk = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _globals._sequenceIndexes[11] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 1, 17);
+ _vm->_sound->command(16);
+ break;
+
+ case 1:
+ _sittingFl = false;
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _game._player._readyToWalk = true;
+ _scene->_hotspots.activate(71, true);
+ _scene->_dynamicHotspots.remove(_chairHotspotId);
+ _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 4);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (_panelOpened && !(_action.isObject(NOUN_SHIELD_ACCESS_PANEL) || _action.isObject(NOUN_SHIELD_MODULATOR))) {
+ switch (_game._trigger) {
+ case 0:
+ if (_game._player._needToWalk) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _shieldSpriteIdx = _game._objects.isInRoom(OBJ_SHIELD_MODULATOR) ? 13 : 14;
+ _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(20);
+ }
+ break;
+
+ case 1:
+ _game._player._stepEnabled = true;
+ _panelOpened = false;
+ _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene101::actions() {
+ if (_action._lookFlag) {
+ _vm->_dialogs->show(10125);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALKTO, NOUN_LIFE_SUPPORT_SECTION)) {
+ _scene->_nextSceneId = 102;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_SIT_IN, NOUN_CHAIR) || (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN) && !_sittingFl)) {
+ if (!_sittingFl) {
+ switch (_game._trigger) {
+ case 0:
+ _scene->_sequences.remove(_globals._sequenceIndexes[12]);
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 1);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 1, 17);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_SPRITE, 10, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _action._inProgress = false;
+ return;
+
+ case 1:
+ _vm->_sound->command(16);
+ break;
+
+ case 2:
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17);
+ _game._player._stepEnabled = true;
+ _sittingFl = true;
+ _scene->_hotspots.activate(71, false);
+ _chairHotspotId = _scene->_dynamicHotspots.add(NOUN_CHAIR, VERB_SIT_IN, -1, Common::Rect(159, 84, 159 + 33, 84 + 36));
+ if (!_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) {
+ _action._inProgress = false;
+ return;
+ }
+ _game._trigger = 0;
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ _vm->_dialogs->show(10131);
+ _action._inProgress = false;
+ return;
+ }
+ }
+
+ if ((_action.isAction(VERB_WALKTO, NOUN_SHIELD_ACCESS_PANEL) || _action.isAction(VERB_OPEN, NOUN_SHIELD_ACCESS_PANEL)) && !_panelOpened) {
+ switch (_game._trigger) {
+ case 0:
+ _shieldSpriteIdx = _game._objects.isInRoom(OBJ_SHIELD_MODULATOR) ? 13 : 14;
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(20);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2);
+ _game._player._stepEnabled = true;
+ _panelOpened = true;
+ if (_game._objects.isInRoom(OBJ_SHIELD_MODULATOR))
+ _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, true);
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if ((_action.isAction(VERB_TAKE, NOUN_SHIELD_MODULATOR) || _action.isAction(VERB_PULL, NOUN_SHIELD_MODULATOR)) && _game._objects.isInRoom(OBJ_SHIELD_MODULATOR)) {
+ _game._objects.addToInventory(OBJ_SHIELD_MODULATOR);
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[14], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2);
+ _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false);
+ _vm->_dialogs->showItem(OBJ_SHIELD_MODULATOR, 10120);
+ _vm->_sound->command(22);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_SHIELD_ACCESS_PANEL) || (_action.isAction(VERB_LOOK, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) ) {
+ if (_panelOpened) {
+ if (_game._objects.isInRoom(OBJ_SHIELD_MODULATOR))
+ _vm->_dialogs->show(10128);
+ else
+ _vm->_dialogs->show(10129);
+ } else
+ _vm->_dialogs->show(10127);
+
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_OPEN, NOUN_SHIELD_ACCESS_PANEL) && _panelOpened) {
+ _vm->_dialogs->show(10130);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN) && _sittingFl) {
+ if (_globals[kWatchedViewScreen])
+ sayDang();
+ else {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _vm->_sound->command(17);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[11] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21);
+ break;
+
+ case 2:
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 3, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ _globals[kWatchedViewScreen] = true;
+ _sittingFl = true;
+ _scene->_nextSceneId = 112;
+ break;
+
+ default:
+ break;
+ }
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_CHAIR)) {
+ _vm->_dialogs->show(10101);
+ _action._inProgress = false;
+ return;
+ }
+
+ if ((_action.isAction(VERB_LOOK) || _action.isAction(VERB_PEER_THROUGH)) && (_action.isObject(NOUN_FRONT_WINDOW) || _action.isObject(NOUN_OUTSIDE))) {
+ _vm->_dialogs->show(10102);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_HULL) || _action.isAction(VERB_LOOK, NOUN_OUTER_HULL) || _action.isAction(VERB_EXAMINE, NOUN_HULL) || _action.isAction(VERB_EXAMINE, NOUN_OUTER_HULL)) {
+ _vm->_dialogs->show(10103);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_FUZZY_DICE)) {
+ _vm->_dialogs->show(10104);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_MIRROR) || _action.isAction(VERB_LOOK_IN, NOUN_MIRROR)) {
+ _vm->_dialogs->show(10105);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_CURTAINS)) {
+ _vm->_dialogs->show(10106);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_PLASTIC_JESUS)) {
+ _vm->_dialogs->show(10107);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_ESCAPE_HATCH) || (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH) && !_game._objects.isInInventory(OBJ_REBREATHER))) {
+ _vm->_dialogs->show(10109);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH)) {
+ _vm->_dialogs->show(10110);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_TARGET_COMPUTER)) {
+ _vm->_dialogs->show(10111);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_LIBRARY_COMPUTER)) {
+ _vm->_dialogs->show(10126);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_DAMAGE_CONTROL_PANEL)) {
+ _vm->_dialogs->show(10112);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_NAVIGATION_CONTROLS)) {
+ _vm->_dialogs->show(10113);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_ENGINEERING_CONTROLS)) {
+ _vm->_dialogs->show(10114);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_WEAPONS_DISPLAY)) {
+ _vm->_dialogs->show(10115);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_SHIELD_STATUS_PANEL)) {
+ _vm->_dialogs->show(10116);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_PLASTIC_JESUS)) {
+ _vm->_dialogs->show(10118);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_FUZZY_DICE)) {
+ _vm->_dialogs->show(10119);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_OPEN, NOUN_DAMAGE_CONTROL_PANEL)) {
+ _vm->_dialogs->show(10121);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_OPEN, NOUN_CURTAINS)) {
+ _vm->_dialogs->show(10122);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_CLOSE, NOUN_CURTAINS)) {
+ _vm->_dialogs->show(10123);
+ _action._inProgress = false;
+ return;
+ }
+
+ if ((_action.isAction(VERB_LOOK) || _action.isAction(VERB_PLAY)) && _action.isObject(NOUN_VIDEO_GAME)) {
+ _vm->_dialogs->show(10124);
+ _action._inProgress = false;
+ return;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene102::Scene102(MADSEngine *vm) : Scene1xx(vm) {
+ _fridgeOpenedFl = false;
+ _fridgeOpenedDescr = false;
+ _fridgeFirstOpenFl = false;
+ _chairDescrFl = false;
+ _drawerDescrFl = false;
+ _activeMsgFl = false;
+ _fridgeCommentCount = 0;
+}
+
+void Scene102::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_fridgeOpenedFl);
+ s.syncAsByte(_fridgeOpenedDescr);
+ s.syncAsByte(_fridgeFirstOpenFl);
+ s.syncAsByte(_chairDescrFl);
+ s.syncAsByte(_drawerDescrFl);
+ s.syncAsByte(_activeMsgFl);
+
+ s.syncAsSint16LE(_fridgeCommentCount);
+}
+
+void Scene102::setup() {
+ _scene->_animationData->preLoad(formAnimName('A', -1), 3);
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene102::addRandomMessage() {
+ _scene->_kernelMessages.reset();
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ int quoteId = _vm->getRandomNumber(65, 69);
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 73, 120, _game.getQuote(quoteId));
+ _activeMsgFl = true;
+}
+
+void Scene102::enter() {
+ sceneEntrySound();
+
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', -1));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('e', -1));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('n', -1));
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('g', -1));
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMRC_8");
+ _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('x', 0));
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 0);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 170, 0, 1, 6);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 11, 0, 2, 3);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 0, 1, 0);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 3, 0, 0, 5);
+
+ if (_game._objects.isInRoom(OBJ_BINOCULARS))
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 24, 0, 0, 24);
+ else
+ _scene->_hotspots.activate(NOUN_BINOCULARS, false);
+
+ _scene->_hotspots.activate(NOUN_BURGER, false);
+
+ if (_globals[kMedicineCabinetOpen]) {
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2);
+ }
+
+ if (_scene->_priorSceneId == 101) {
+ _game._player._playerPos = Common::Point(229, 109);
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ } else if (_scene->_priorSceneId == 103)
+ _game._player._playerPos = Common::Point(47, 152);
+ else if (_scene->_priorSceneId != -2) {
+ _game._player._facing = FACING_NORTHWEST;
+ _game._player._playerPos = Common::Point(32, 129);
+ }
+
+ if (_scene->_priorSceneId != 106) {
+ if (_globals[kWaterInAPuddle]) {
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5);
+ }
+ } else {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5);
+ _vm->_sound->command(24);
+ _vm->_sound->command(28);
+ }
+
+ _fridgeOpenedFl = false;
+ _fridgeOpenedDescr = false;
+ _fridgeCommentCount = 0;
+ _fridgeFirstOpenFl = true;
+ _chairDescrFl = false;
+ _activeMsgFl = false;
+
+ _game.loadQuoteSet(0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x45, 0x43, 0);
+
+ if (_scene->_priorSceneId == 101)
+ _vm->_sound->command(20);
+}
+
+void Scene102::step() {
+ if (_game._trigger == 70)
+ _game._player._stepEnabled = true;
+
+ if (_game._trigger == 72) {
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5);
+ _scene->_sequences.addTimer(48, 90);
+ }
+
+ if (_game._trigger >= 90) {
+ if (_game._trigger >= 94) {
+ _scene->loadAnimation(formAnimName('B', -1), 71);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+
+ _globals[kWaterInAPuddle] = true;
+ _vm->_sound->command(24);
+ } else {
+ _vm->_sound->command(23);
+ _scene->_sequences.addTimer(48, _game._trigger + 1);
+ }
+ }
+
+ if (_game._trigger == 71) {
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ }
+
+ if (_fridgeOpenedFl && !_fridgeOpenedDescr) {
+ _fridgeCommentCount++;
+ if (_fridgeCommentCount > 16384) {
+ _fridgeOpenedDescr = true;
+ _vm->_dialogs->show(10213);
+ }
+ }
+
+ if (!_activeMsgFl && (_game._player._playerPos == Common::Point(177, 114)) && (_game._player._facing == FACING_NORTH)
+ && (_vm->getRandomNumber(1, 5000) == 1)) {
+ _scene->_kernelMessages.reset();
+ _activeMsgFl = false;
+ addRandomMessage();
+ }
+
+ if (_game._trigger == 73)
+ _activeMsgFl = false;
+}
+
+void Scene102::preActions() {
+ if (_action.isObject(NOUN_REFRIGERATOR) || _action.isObject(NOUN_POSTER))
+ _game._player._needToWalk = _game._player._readyToWalk;
+
+ if (_fridgeOpenedFl && !_action.isObject(NOUN_REFRIGERATOR)) {
+ switch (_game._trigger) {
+ case 0:
+ if (_game._player._needToWalk) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[7]);
+ _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15);
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(20);
+ }
+ break;
+
+ case 1:
+ if (_game._objects.isInRoom(OBJ_BURGER)) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _scene->_hotspots.activate(NOUN_BURGER, false);
+ }
+ _fridgeOpenedFl = false;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (_game._player._needToWalk)
+ _scene->_kernelMessages.reset();
+}
+
+void Scene102::actions() {
+ if (_action._lookFlag) {
+ _vm->_dialogs->show(10234);
+ _action._inProgress = false;
+ return;
+ }
+
+ bool justOpenedFl = false;
+ if (_action.isObject(NOUN_REFRIGERATOR) && !_fridgeOpenedFl) {
+ switch (_game._trigger) {
+ case 0:
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ if (_game._objects.isInRoom(OBJ_BURGER)) {
+ _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 7, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 14);
+ }
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(20);
+ _action._inProgress = false;
+ return;
+
+ case 1:
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], -2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15);
+ int delay;
+ if (_action.isAction(VERB_WALKTO) && !_fridgeFirstOpenFl)
+ delay = 0;
+ else
+ delay = 48;
+ _scene->_sequences.addTimer(delay, 2);
+ _action._inProgress = false;
+ return;
+
+ case 2:
+ _fridgeOpenedFl = true;
+ _fridgeOpenedDescr = false;
+ _fridgeCommentCount = 0;
+ _game._player._stepEnabled = true;
+ justOpenedFl = true;
+ if (_game._objects.isInRoom(OBJ_BURGER))
+ _scene->_hotspots.activate(NOUN_BURGER, true);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_REFRIGERATOR) || _action.isAction(VERB_OPEN, NOUN_REFRIGERATOR)) {
+ if (_game._objects.isInRoom(OBJ_BURGER))
+ _vm->_dialogs->show(10230);
+ else
+ _vm->_dialogs->show(10229);
+
+ _fridgeFirstOpenFl = false;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALKTO, NOUN_REFRIGERATOR) && justOpenedFl) {
+ _fridgeFirstOpenFl = false;
+ int quoteId = _vm->getRandomNumber(59, 63);
+ Common::String curQuote = _game.getQuote(quoteId);
+ int width = _vm->_font->getWidth(curQuote, -1);
+ _scene->_kernelMessages.reset();
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_kernelMessages.add(Common::Point(210, 60), 0x1110, 0, 73, 120, curQuote);
+ _scene->_kernelMessages.add(Common::Point(214 + width, 60), 0x1110, 0, 73, 120, _game.getQuote(64));
+ _activeMsgFl = true;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_CLOSE, NOUN_REFRIGERATOR)) {
+ _vm->_dialogs->show(10213);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_REFRIGERATOR)) {
+ _vm->_dialogs->show(8);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR)) {
+ switch (_game._trigger) {
+ case 0:
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(20);
+ break;
+
+ case 1:
+ _scene->_nextSceneId = 101;
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALKTO, NOUN_ENGINEERING_SECTION)) {
+ _scene->_nextSceneId = 103;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALKTO, NOUN_POSTER) || _action.isAction(VERB_LOOK, NOUN_POSTER) || _action.isAction(VERB_WALKTO, NOUN_BINOCULARS)) {
+ addRandomMessage();
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_WEIGHT_MACHINE)) {
+ _vm->_dialogs->show(10212);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_ENGINEERING_SECTION)) {
+ _vm->_dialogs->show(10205);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_DOOR)) {
+ _vm->_dialogs->show(10204);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_STARE_AT, NOUN_CEILING) || _action.isAction(VERB_LOOK, NOUN_CEILING)) {
+ _vm->_dialogs->show(10203);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_STARE_AT, NOUN_OVERHEAD_LAMP) || _action.isAction(VERB_LOOK, NOUN_OVERHEAD_LAMP)) {
+ _vm->_dialogs->show(10202);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_ROBO_KITCHEN)) {
+ _vm->_dialogs->show(10215);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_PUT, NOUN_BURGER, NOUN_ROBO_KITCHEN) && _game._objects.isInInventory(OBJ_BURGER)) {
+ _vm->_dialogs->show(10216);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_PUT, NOUN_REFRIGERATOR) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) {
+ _vm->_dialogs->show(10217);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_PUT, NOUN_DEAD_FISH, NOUN_ROBO_KITCHEN) || _action.isAction(VERB_PUT, NOUN_STUFFED_FISH, NOUN_ROBO_KITCHEN)) {
+ _vm->_dialogs->show(10230);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_OPEN, NOUN_ROBO_KITCHEN)) {
+ _vm->_dialogs->show(10218);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_CLOSET)) {
+ _vm->_dialogs->show(10219);
+ _action._inProgress = false;
+ return;
+ }
+
+ if ((_action.isObject(NOUN_LADDER) || _action.isObject(NOUN_HATCHWAY)) && (_action.isAction(VERB_LOOK) || _action.isAction(VERB_CLIMB_UP) || _action.isAction(VERB_CLIMB_THROUGH))) {
+ if (_game._objects.isInInventory(OBJ_REBREATHER)) {
+ if (!_action.isAction(VERB_CLIMB_UP) && !_action.isAction(VERB_CLIMB_THROUGH)) {
+ _vm->_dialogs->show(10231);
+ _action._inProgress = false;
+ return;
+ }
+ } else if (_action.isAction(VERB_LOOK) || (_game._difficulty != DIFFICULTY_HARD)) {
+ _vm->_dialogs->show(10222);
+ _action._inProgress = false;
+ return;
+ }
+ }
+
+ if ((_action.isObject(NOUN_LADDER) || _action.isObject(NOUN_HATCHWAY)) && (_action.isAction(VERB_CLIMB_UP) || _action.isAction(VERB_CLIMB_THROUGH)) ) {
+ switch (_game._trigger) {
+ case 0:
+ _scene->loadAnimation(formAnimName('A', -1), 1);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ break;
+
+ case 1:
+ _vm->_sound->command(24);
+ _scene->_sequences.addTimer(48, 2);
+ break;
+
+ case 2:
+ case 3:
+ case 4:
+ _vm->_sound->command(23);
+ _scene->_sequences.addTimer(48, _game._trigger + 1);
+ break;
+
+ case 5:
+ _vm->_sound->command(24);
+ _scene->_sequences.addTimer(48, _game._trigger + 1);
+ break;
+
+ case 6:
+ if (_game._objects.isInInventory(OBJ_REBREATHER) && !_game._visitedScenes.exists(106))
+ _vm->_dialogs->show(10237);
+ _scene->_nextSceneId = 106;
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_POWER_STATUS_PANEL)) {
+ _vm->_dialogs->show(10226);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_WINDOW) || _action.isAction(VERB_LOOK_THROUGH, NOUN_WINDOW)) {
+ _vm->_dialogs->show(10227);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_DOORWAY) || _action.isAction(VERB_WALKTO, NOUN_DOORWAY)) {
+ _vm->_dialogs->show(10228);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_DRAWER) || ((_action.isAction(VERB_CLOSE, NOUN_DRAWER) || _action.isAction(VERB_PUSH, NOUN_DRAWER)) && !_drawerDescrFl)) {
+ _vm->_dialogs->show(10220);
+ _drawerDescrFl = true;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_CLOSE, NOUN_DRAWER) || _action.isAction(VERB_PUSH, NOUN_DRAWER)) {
+ _vm->_dialogs->show(10221);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_OPEN, NOUN_DRAWER)) {
+ _vm->_dialogs->show(10236);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || (_action.isAction(VERB_SIT_IN, NOUN_CHAIR) && !_chairDescrFl)) {
+ _chairDescrFl = true;
+ _vm->_dialogs->show(10210);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_SIT_IN, NOUN_CHAIR)) {
+ _vm->_dialogs->show(10211);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_MEDICINE_CABINET)) {
+ if (_globals[kMedicineCabinetOpen])
+ _vm->_dialogs->show(10207);
+ else
+ _vm->_dialogs->show(10206);
+
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_CLOSE, NOUN_MEDICINE_CABINET) && _globals[kMedicineCabinetOpen]) {
+ switch (_game._trigger) {
+ case 0:
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(21);
+ break;
+
+ case 1:
+ _scene->_sequences.addTimer(48, 2);
+ break;
+
+ case 2:
+ _game._player._stepEnabled = true;
+ _globals[kMedicineCabinetOpen] = false;
+ _vm->_dialogs->show(10209);
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_OPEN, NOUN_MEDICINE_CABINET) && !_globals[kMedicineCabinetOpen]) {
+ switch (_game._trigger) {
+ case 0:
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(21);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2);
+ _scene->_sequences.addTimer(48, 2);
+ break;
+
+ case 2:
+ _game._player._stepEnabled = true;
+ _globals[kMedicineCabinetOpen] = true;
+ if (_globals[kMedicineCabinetVirgin]) {
+ _vm->_dialogs->show(10208);
+ } else {
+ _vm->_dialogs->show(10207);
+ }
+ _globals[kMedicineCabinetVirgin] = false;
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_BINOCULARS) && _game._objects.isInRoom(OBJ_BINOCULARS)) {
+ switch (_game._trigger) {
+ case 0:
+ _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[11]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ break;
+
+ case 1:
+ _game._objects.addToInventory(OBJ_BINOCULARS);
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _scene->_hotspots.activate(NOUN_BINOCULARS, false);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _vm->_sound->command(22);
+ _vm->_dialogs->showItem(OBJ_BINOCULARS, 10201);
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_BURGER) && _game._objects.isInRoom(OBJ_BURGER)) {
+ if (_game._trigger == 0) {
+ _vm->_dialogs->showItem(OBJ_BURGER, 10235);
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _game._objects.addToInventory(OBJ_BURGER);
+ _scene->_hotspots.activate(NOUN_BURGER, false);
+ _vm->_sound->command(22);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_POSTER)) {
+ _vm->_dialogs->show(10224);
+ _action._inProgress = false;
+ return;
+ }
+
+ if ((_action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL)) && _action.isObject(NOUN_WEIGHT_MACHINE)) {
+ _vm->_dialogs->show(10225);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) {
+ _vm->_dialogs->show(10232);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS) && !_game._objects.isInInventory(OBJ_BINOCULARS)) {
+ _vm->_dialogs->show(10233);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_BURGER) && (_action._mainObjectSource == 4)) {
+ _vm->_dialogs->show(801);
+ _action._inProgress = false;
+ }
+}
+
+void Scene102::postActions() {
+ if (_action.isAction(VERB_PUT, NOUN_ROBO_KITCHEN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) {
+ _vm->_dialogs->show(10217);
+ _action._inProgress = false;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene103::Scene103(MADSEngine *vm) : Scene1xx(vm) {
+ _updateClock = 0;
+}
+
+void Scene103::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ byte dummy = 0;
+ s.syncAsByte(dummy); // In order to avoid to break savegame compatibility
+ s.syncAsUint32LE(_updateClock);
+}
+
+void Scene103::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene103::enter() {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', -1));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('h', -1));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', -1));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('t', -1));
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('r', -1));
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_2");
+ _globals._spriteIndexes[13] = _scene->_sprites.addSprites("*RXMRD_3");
+ _globals._spriteIndexes[15] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 7, 0, 1, 0);
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 2, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 0);
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 25);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 72);
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 1, 37);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 2, 73);
+
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8);
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6);
+
+ if (_game._objects.isInRoom(OBJ_TIMER_MODULE))
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6);
+ else
+ _vm->_game->_scene._hotspots.activate(371, false);
+
+ if (_game._objects.isInRoom(OBJ_REBREATHER))
+ _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 6);
+ else
+ _vm->_game->_scene._hotspots.activate(289, false);
+
+ if (_globals[kTurkeyExploded]) {
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], -2, -2);
+ _scene->_hotspots.activate(362, false);
+ }
+
+ if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(237, 74);
+
+ if (_scene->_priorSceneId == 102) {
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ }
+
+ sceneEntrySound();
+ _vm->_game->loadQuoteSet(70, 51, 71, 7, 73, 0);
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(70));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+
+ if (_scene->_priorSceneId == 102)
+ _vm->_sound->command(20);
+
+ _vm->_palette->setEntry(252, 63, 63, 10);
+ _vm->_palette->setEntry(253, 45, 45, 10);
+ _updateClock = _scene->_frameStartTime;
+}
+
+void Scene103::step() {
+ switch (_vm->_game->_trigger) {
+ case 70:
+ _vm->_game->_player._stepEnabled = true;
+ break;
+
+ case 72: {
+ Common::Point pt = _vm->_game->_player._playerPos;
+ int dist = _vm->hypotenuse(pt.x - 58, pt.y - 93);
+ _vm->_sound->command(27, (dist * -128 / 378) + 127);
+ }
+ break;
+
+ case 73: {
+ Common::Point pt = _vm->_game->_player._playerPos;
+ int dist = _vm->hypotenuse(pt.x - 266, pt.y - 81);
+ _vm->_sound->command(27, (dist * -127 / 378) + 127);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (_scene->_frameStartTime >= _updateClock) {
+ Common::Point pt = _vm->_game->_player._playerPos;
+ int dist = _vm->hypotenuse(pt.x - 79, pt.y - 137);
+ _vm->_sound->command(29, (dist * -127 / 378) + 127);
+
+ pt = _vm->_game->_player._playerPos;
+ dist = _vm->hypotenuse(pt.x - 69, pt.y - 80);
+ _vm->_sound->command(30, (dist * -127 / 378) + 127);
+
+ pt = _vm->_game->_player._playerPos;
+ dist = _vm->hypotenuse(pt.x - 266, pt.y - 138);
+ _vm->_sound->command(32, (dist * -127 / 378) + 127);
+
+ _updateClock = _scene->_frameStartTime + _vm->_game->_player._ticksAmount;
+ }
+}
+
+void Scene103::actions() {
+ if (_action._savedFields._lookFlag)
+ _vm->_dialogs->show(10322);
+ else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR)) {
+ switch (_vm->_game->_trigger) {
+ case 0:
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(20);
+ break;
+
+ case 1:
+ _vm->_sound->command(1);
+ _scene->_nextSceneId = 102;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_TIMER_MODULE) && _game._objects.isInRoom(OBJ_TIMER_MODULE)) {
+ switch (_vm->_game->_trigger) {
+ case 0:
+ _scene->changeVariant(1);
+ _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 3, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[13]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_SPRITE, 7, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ _vm->_game->_player._visible = false;
+ _vm->_game->_player._stepEnabled = false;
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ break;
+
+ case 2:
+ _vm->_sound->command(22);
+ _game._objects.addToInventory(OBJ_TIMER_MODULE);
+ _scene->changeVariant(0);
+ _scene->drawElements(kTransitionNone, false);
+ _scene->_hotspots.activate(371, false);
+ _vm->_game->_player._visible = true;
+ _vm->_game->_player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_REBREATHER, 805);
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, 289, 0) && _game._objects.isInRoom(OBJ_REBREATHER)) {
+ switch (_vm->_game->_trigger) {
+ case 0:
+ _scene->changeVariant(1);
+ _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 3, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ _vm->_game->_player._visible = false;
+ _vm->_game->_player._stepEnabled = false;
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ break;
+
+ case 2:
+ _vm->_sound->command(22);
+ _game._objects.addToInventory(OBJ_REBREATHER);
+ _scene->_hotspots.activate(289, false);
+ _vm->_game->_player._visible = true;
+ _vm->_game->_player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_REBREATHER, 804);
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, 362))
+ _vm->_dialogs->show(10301);
+ else if (_action.isAction(VERB_TAKE, 362)) {
+ // Take Turkey
+ if (!_vm->_game->_trigger)
+ _vm->_sound->command(31);
+
+ if (_vm->_game->_trigger < 2) {
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, _vm->_game->_trigger < 1 ? 1 : 0);
+ if (_vm->_game->_trigger) {
+ // Lock the turkey into a permanent "exploded" frame
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], -2, -2);
+
+ // Rex says "Gads.."
+ Common::String msg = _game.getQuote(51);
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 0, 60, msg);
+ _scene->_sequences.addTimer(120, _vm->_game->_trigger + 1);
+ } else {
+ // Initial turky explosion
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ }
+ }
+
+ // Re-enable player if sequence is ended, and set global flag
+ _game._player._stepEnabled = _game._trigger == 2;
+ _globals[kTurkeyExploded] = -1;
+
+ if (_game._trigger == 2) {
+ // Show exposition dialog at end of sequence
+ _vm->_dialogs->show(10302);
+ _scene->_hotspots.activate(362, false);
+ }
+ } else if (_action.isAction(VERB_LOOK, 250))
+ _vm->_dialogs->show(!_globals[kTurkeyExploded] ? 10323 : 10303);
+ else if (_action.isAction(VERB_TALKTO, 27)) {
+ switch (_vm->_game->_trigger) {
+ case 0: {
+ _game._player._stepEnabled = false;
+ Common::String msg = _game.getQuote(71);
+ _scene->_kernelMessages.add(Common::Point(), 0x1110, 18, 1, 120, msg);
+ break;
+ }
+
+ case 1: {
+ Common::String msg = _game.getQuote(72);
+ _scene->_kernelMessages.add(Common::Point(310, 132), 0xFDFC, 16, 2, 120, msg);
+ break;
+ }
+
+ case 2:
+ _scene->_kernelMessages.reset();
+ _scene->_sequences.addTimer(1, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->show(10306);
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, 27))
+ _vm->_dialogs->show(10304);
+ else if (_action.isAction(VERB_LOOK, 36))
+ _vm->_dialogs->show(10307);
+ else if (_action.isAction(VERB_LOOK, 55))
+ _vm->_dialogs->show(10308);
+ else if (_action.isAction(VERB_TAKE, 315))
+ _vm->_dialogs->show(10309);
+ else if (_action.isAction(VERB_TAKE, 85))
+ _vm->_dialogs->show(10310);
+ else if (_action.isAction(VERB_LOOK, 144))
+ _vm->_dialogs->show(10312);
+ else if (_action.isAction(VERB_OPEN, 144))
+ _vm->_dialogs->show(10313);
+ else if (_action.isAction(VERB_CLOSE, 27))
+ _vm->_dialogs->show(10314);
+ else if (_action.isAction(VERB_LOOK, 310))
+ _vm->_dialogs->show(10315);
+ else if (_action.isAction(VERB_LOOK, 178))
+ _vm->_dialogs->show(10316);
+ else if (_action.isAction(VERB_LOOK, 283))
+ _vm->_dialogs->show(10317);
+ else if (_action.isAction(VERB_LOOK, 120))
+ _vm->_dialogs->show(10318);
+ else if (_action.isAction(VERB_LOOK, 289) && _game._objects.isInInventory(OBJ_REBREATHER))
+ _vm->_dialogs->show(10319);
+ else if (_action.isAction(VERB_LOOK, 371) && _game._objects.isInInventory(OBJ_TIMER_MODULE))
+ _vm->_dialogs->show(10320);
+ else if (_action.isAction(VERB_LOOK, 137))
+ _vm->_dialogs->show(10321);
+ else if (_action.isAction(VERB_LOOK, 409))
+ _vm->_dialogs->show(_game._objects.isInInventory(OBJ_TIMER_MODULE) ? 10324 : 10325);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+void Scene103::postActions() {
+ if (_action.isObject(NOUN_AUXILIARY_POWER) && !_action.isAction(VERB_WALKTO)) {
+ _vm->_dialogs->show(10305);
+ _action._inProgress = false;
+ } else if (_action.isAction(VERB_PUT, NOUN_COAL, NOUN_FURNACE)) {
+ Common::String msg = _game.getQuote(73);
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, msg);
+ _action._inProgress = false;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene104::Scene104(MADSEngine *vm) : Scene1xx(vm) {
+ _kargShootingFl = false;
+ _loseFl = false;
+}
+
+void Scene104::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_kargShootingFl);
+ s.syncAsByte(_loseFl);
+}
+
+void Scene104::setup() {
+ // Preloading has been skipped
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene104::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', -1));
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 0, 0, 1);
+
+ if (_scene->_priorSceneId == 105)
+ _game._player._playerPos = Common::Point(302, 107);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(160, 134);
+
+ _loseFl = false;
+ _game.loadQuoteSet(0x35, 0x34, 0);
+ _kargShootingFl = false;
+
+ if (_vm->getRandomNumber(1, 3) == 1) {
+ _scene->loadAnimation(Resources::formatName(104, 'B', -1, EXT_AA, ""), 0);
+ _kargShootingFl = true;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene104::step() {
+ if ((_game._player._playerPos == Common::Point(189, 70)) && (_game._trigger || !_loseFl)) {
+ if (_game._player._facing == FACING_SOUTHWEST || _game._player._facing == FACING_SOUTHEAST)
+ _game._player._facing = FACING_SOUTH;
+
+ if (_game._player._facing == FACING_NORTHWEST || _game._player._facing == FACING_NORTHEAST)
+ _game._player._facing = FACING_NORTH;
+
+ bool mirrorFl = false;
+ if (_game._player._facing == FACING_WEST) {
+ _game._player._facing = FACING_EAST;
+ mirrorFl = true;
+ }
+
+ _loseFl = true;
+
+ switch (_game._player._facing) {
+ case FACING_EAST:
+ switch (_game._trigger) {
+ case 0:
+ _scene->_kernelMessages.reset();
+ _scene->freeAnimation();
+ _scene->resetScene();
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _vm->_palette->refreshSceneColors();
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], mirrorFl, 7, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(198, 143));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], mirrorFl, 7, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(198, 143));
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -2, -2);
+ _scene->_sequences.addTimer(90, 2);
+ break;
+
+ case 2:
+ _vm->_dialogs->show(10406);
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case FACING_SOUTH:
+ switch (_game._trigger) {
+ case 0:
+ _scene->_kernelMessages.reset();
+ _scene->freeAnimation();
+ _scene->resetScene();
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _vm->_palette->refreshSceneColors();
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 14);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 15, 32);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 3, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143));
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2);
+ _scene->_sequences.addTimer(90, 3);
+ break;
+
+ case 3:
+ _vm->_dialogs->show(10406);
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case FACING_NORTH:
+ switch (_game._trigger) {
+ case 0:
+ _scene->_kernelMessages.reset();
+ _scene->freeAnimation();
+ _scene->resetScene();
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2));
+ _vm->_palette->refreshSceneColors();
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(198, 143));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ if (_game._storyMode >= STORYMODE_NICE)
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 15, 2);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(198, 143));
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -2, -2);
+ _scene->_sequences.addTimer(90, 2);
+ break;
+
+ case 2:
+ _vm->_dialogs->show(10406);
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!_game._trigger)
+ _vm->_sound->command(34);
+ }
+
+ if (_game._player._moving && (_scene->_rails.getNext() > 0)) {
+ _game._player.cancelCommand();
+ _game._player.startWalking(Common::Point(189, 70), FACING_NONE);
+ _scene->_rails.resetNext();
+ }
+
+ if ((_game._player._special > 0) && _game._player._stepEnabled)
+ _game._player._stepEnabled = false;
+
+ if (_kargShootingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52));
+ _kargShootingFl = false;
+ }
+}
+
+void Scene104::preActions() {
+ if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_EASTERN_CLIFF_FACE))
+ _game._player._walkOffScreenSceneId = 105;
+
+ if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH))
+ _game._player._walkOffScreenSceneId = 106;
+}
+
+void Scene104::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(10405);
+ else if (_action.isAction(VERB_LOOK, NOUN_CURIOUS_WEED_PATCH))
+ _vm->_dialogs->show(10404);
+ else if (_action.isAction(VERB_LOOK, NOUN_SURFACE))
+ _vm->_dialogs->show(10403);
+ else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE))
+ _vm->_dialogs->show(10401);
+ else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR))
+ _vm->_dialogs->show(10402);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene105::Scene105(MADSEngine *vm) : Scene1xx(vm) {
+ _explosionFl = false;
+}
+
+void Scene105::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_explosionFl);
+}
+
+void Scene105::setup() {
+ // Preloading has been skipped
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene105::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('m', 1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('f', 4));
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 0);
+
+ if (_globals[kFishIn105]) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(48, 144));
+
+ int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(56, 141), FACING_NORTHWEST);
+ }
+
+ if (_scene->_priorSceneId == 104)
+ _game._player._playerPos = Common::Point(13, 97);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(116, 147);
+
+ _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0);
+ _explosionFl = false;
+
+ sceneEntrySound();
+}
+
+void Scene105::step() {
+ if ((_game._player._playerPos == Common::Point(170, 87)) && (_game._trigger || !_explosionFl)) {
+ _explosionFl = true;
+ switch (_game._trigger) {
+ case 0:
+ _scene->_kernelMessages.reset();
+ _scene->resetScene();
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('m', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', 3));
+ _vm->_sound->command(33);
+ _scene->clearSequenceList();
+ _vm->_palette->refreshSceneColors();
+
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+
+ if (_game._storyMode >= STORYMODE_NICE)
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 8, 3);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 9, 1, 0, 0);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], _globals._sequenceIndexes[0]);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, 7);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 9, 0, 0, 0);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8);
+ _scene->_sequences.addTimer(90, 3);
+ }
+ break;
+
+ case 3:
+ _vm->_dialogs->show(10507);
+ _scene->_reloadSceneFlag = true;
+ _scene->_sequences.addTimer(90, 4);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (_game._player._moving && (_scene->_rails.getNext() > 0)) {
+ _game._player.cancelCommand();
+ _game._player.startWalking(Common::Point(170, 87), FACING_NONE);
+ _scene->_rails.resetNext();
+ }
+
+ if ((_game._player._special > 0) && _game._player._stepEnabled)
+ _game._player._stepEnabled = false;
+}
+
+void Scene105::preActions() {
+ if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_WESTERN_CLIFF_FACE))
+ _game._player._walkOffScreenSceneId = 104;
+
+ if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH))
+ _game._player._walkOffScreenSceneId = 107;
+
+ if (_action.isObject(NOUN_MINE) && (_action.isAction(VERB_TALKTO) || _action.isAction(VERB_LOOK)))
+ _game._player._needToWalk = false;
+}
+
+void Scene105::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(10512);
+ else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn105]) {
+ if (_game._objects.isInInventory(OBJ_DEAD_FISH)) {
+ int randVal = _vm->getRandomNumber(74, 76);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal));
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _game._objects.addToInventory(OBJ_DEAD_FISH);
+ _globals[kFishIn105] = false;
+ _vm->_dialogs->showItem(OBJ_DEAD_FISH, 802, 0);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_WESTERN_CLIFF_FACE))
+ _vm->_dialogs->show(10501);
+ else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE))
+ _vm->_dialogs->show(10502);
+ else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR))
+ _vm->_dialogs->show(10503);
+ else if (_action.isAction(VERB_LOOK, NOUN_MEDICAL_WASTE))
+ _vm->_dialogs->show(10504);
+ else if (_action.isAction(VERB_TAKE, NOUN_MEDICAL_WASTE))
+ _vm->_dialogs->show(10505);
+ else if (_action.isAction(VERB_LOOK, NOUN_MINE))
+ _vm->_dialogs->show(10506);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH))
+ _vm->_dialogs->show(10508);
+ else if (_action.isAction(VERB_LOOK, NOUN_SURFACE))
+ _vm->_dialogs->show(10509);
+ else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_SOUTH))
+ _vm->_dialogs->show(10510);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCKS))
+ _vm->_dialogs->show(10511);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene106::Scene106(MADSEngine *vm) : Scene1xx(vm) {
+ _backToShipFl = false;
+ _shadowFl = false;
+ _firstEmergingFl = false;
+ _positionY = 0;
+}
+
+void Scene106::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_backToShipFl);
+ s.syncAsByte(_shadowFl);
+ s.syncAsByte(_firstEmergingFl);
+ s.syncAsSint32LE(_positionY);
+}
+
+void Scene106::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ if ((_scene->_priorSceneId == 102) && !_game._objects.isInInventory(OBJ_REBREATHER) && !_scene->_roomChanged)
+ _game._player._spritesPrefix = "";
+
+ _vm->_dialogs->_defaultPosition.y = 100;
+}
+
+void Scene106::enter() {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('H', -1));
+
+ if (_game._objects.isInInventory(OBJ_REBREATHER) || (_scene->_priorSceneId != 102) || _scene->_roomChanged) {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('A', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('A', 1));
+ }
+
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('G', -1));
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 21, 0, 0, 0);
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('I', -1));
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 32, 47);
+
+ if (_scene->_priorSceneId == 102) {
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 1, 4, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _game._player._facing = FACING_EAST;
+ _game._player._playerPos = Common::Point(106, 69);
+ } else if (_scene->_priorSceneId != -2) {
+ if (_scene->_priorSceneId == 107) {
+ _game._player._playerPos = Common::Point(319, 84);
+ _game._player._facing = _game._player._prepareWalkFacing = FACING_WEST;
+ } else {
+ _game._player._playerPos = Common::Point(319, 44);
+ _game._player._facing = _game._player._prepareWalkFacing = FACING_SOUTHWEST;
+ _scene->_sprites[_game._player._spritesStart + 3]->_charInfo->_velocity = 24;
+ }
+
+ _game._player._prepareWalkPos = Common::Point(246, 69);
+ _game._player._needToWalk = true;
+ _game._player._readyToWalk = true;
+ }
+
+ if (_scene->_priorSceneId != 102) {
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], -2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 14);
+ }
+
+ _backToShipFl = false;
+ _shadowFl = false;
+ _firstEmergingFl = false;
+
+ _game.loadQuoteSet(0x31, 0x32, 0x34, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0);
+ sceneEntrySound();
+}
+
+void Scene106::step() {
+ if (_game._trigger == 70) {
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], -2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 14);
+
+ if (!_game._objects.isInInventory(OBJ_REBREATHER) && !_scene->_roomChanged) {
+ _scene->loadAnimation(Resources::formatName(106, 'A', -1, EXT_AA, ""), 75);
+ } else {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 28, 71);
+ }
+ }
+
+ if (_game._trigger == 71) {
+ _game._player._prepareWalkPos = Common::Point(246, 69);
+ _game._player._prepareWalkFacing = FACING_EAST;
+ _game._player._needToWalk = true;
+ _game._player._readyToWalk = true;
+ _game._player._visible = true;
+
+ if (_game._visitedScenes._sceneRevisited) {
+ _game._player._stepEnabled = true;
+ } else {
+ _game._player._prepareWalkFacing = FACING_SOUTHWEST;
+ _firstEmergingFl = true;
+ _scene->loadAnimation(Resources::formatName(106, 'B', -1, EXT_AA, ""), 80);
+ }
+ }
+
+ if (_firstEmergingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) {
+ _firstEmergingFl = false;
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52));
+ }
+
+ if ((_game._trigger >= 80) && (_game._trigger <= 87)) {
+ int tmpVal = _game._trigger - 80;
+ int msgId = -1;
+ switch (tmpVal) {
+ case 0:
+ _positionY = 26;
+ msgId = 49;
+ break;
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ msgId = 76 + tmpVal;
+ break;
+
+ case 6:
+ msgId = 50;
+ break;
+
+ default:
+ msgId = -1;
+ _game._player._stepEnabled = true;
+ break;
+ }
+
+ if (msgId >= 0) {
+ int nextAbortVal = _game._trigger + 1;
+ _scene->_kernelMessages.add(Common::Point(15, _positionY), 0x1110, 0, 0, 360, _game.getQuote(msgId));
+ _scene->_sequences.addTimer(150, nextAbortVal);
+ _positionY += 14;
+ }
+ }
+
+ if (_backToShipFl) {
+ if (!_shadowFl) {
+ if (_game._player._playerPos.x < 204) {
+ _shadowFl = true;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 4, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 44, 73);
+ }
+ } else if (_game._trigger == 73)
+ _game._player._visible = false;
+ else if (_game._trigger == 72)
+ _scene->_sequences.addTimer(24, 74);
+ else if (_game._trigger == 74)
+ _scene->_nextSceneId = 102;
+ }
+
+ if (_game._trigger == 75) {
+ _game._visitedScenes.pop_back();
+ _scene->_nextSceneId = 102;
+ }
+}
+
+void Scene106::preActions() {
+ if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_SEA_CLIFF) || _action.isAction(VERB_SWIM_TOWARDS, NOUN_SEAWEED_BANK)) {
+ _game._player._stepEnabled = false;
+ _scene->_sprites[_game._player._spritesStart + 1]->_charInfo->_velocity = 24;
+ _game._player._walkOffScreenSceneId = 104;
+ }
+
+ if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_EAST))
+ _game._player._walkOffScreenSceneId = 107;
+}
+
+void Scene106::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(10614);
+ else if (_action.isAction(VERB_SWIM_TO, NOUN_MAIN_AIRLOCK)) {
+ _game._player._stepEnabled = false;
+ _game._player._prepareWalkPos = Common::Point(95, 72);
+ _game._player._prepareWalkFacing = FACING_WEST;
+ _game._player._needToWalk = true;
+ _game._player._readyToWalk = true;
+ _game._player._frameNumber = 9;
+ _backToShipFl = true;
+ } else if (_action.isAction(VERB_LOOK, NOUN_ANEMONE) || _action.isAction(VERB_LOOK_AT, NOUN_ANEMONE))
+ _vm->_dialogs->show(10601);
+ else if (_action.isAction(VERB_TAKE, NOUN_ANEMONE))
+ _vm->_dialogs->show(10602);
+ else if (_action.isAction(VERB_LOOK, NOUN_SEAWEED) || _action.isAction(VERB_LOOK, NOUN_SEAWEED_BANK))
+ _vm->_dialogs->show(10603);
+ else if (_action.isAction(VERB_TAKE, NOUN_SEAWEED) || _action.isAction(VERB_TAKE, NOUN_SEAWEED_BANK))
+ _vm->_dialogs->show(10604);
+ else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_EAST))
+ _vm->_dialogs->show(10605);
+ else if (_action.isAction(VERB_LOOK, NOUN_PILE_OF_ROCKS) || _action.isAction(VERB_LOOK_AT, NOUN_PILE_OF_ROCKS))
+ _vm->_dialogs->show(10606);
+ else if (_action.isObject(NOUN_PILE_OF_ROCKS) && (_action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL) || _action.isAction(VERB_TAKE)))
+ _vm->_dialogs->show(10607);
+ else if (_action.isAction(VERB_LOOK, NOUN_SHIP) || _action.isAction(VERB_LOOK_AT, NOUN_SHIP))
+ _vm->_dialogs->show(10608);
+ else if (_action.isAction(VERB_LOOK, NOUN_MAIN_AIRLOCK))
+ _vm->_dialogs->show(10609);
+ else if (_action.isAction(VERB_OPEN, NOUN_MAIN_AIRLOCK))
+ _vm->_dialogs->show(10610);
+ else if (_action.isAction(VERB_CLOSE, NOUN_MAIN_AIRLOCK))
+ _vm->_dialogs->show(10611);
+ else if (_action.isAction(VERB_LOOK, NOUN_SEA_CLIFF))
+ _vm->_dialogs->show(10612);
+ else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR))
+ _vm->_dialogs->show(10613);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene107::Scene107(MADSEngine *vm) : Scene1xx(vm) {
+ _shootingFl = false;
+}
+
+void Scene107::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_shootingFl);
+}
+
+void Scene107::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_MANTA_RAY);
+}
+
+void Scene107::enter() {
+ for (int i = 0; i < 3; i++)
+ _globals._spriteIndexes[i + 1] = _scene->_sprites.addSprites(formAnimName('G', i));
+
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(105, 'f', 4, EXT_SS, ""));
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 0, 0, 7);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 13);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 19, 0, 0, 9);
+
+ for (int i = 1; i < 4; i++)
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[i], 0);
+
+ if (_globals[kFishIn107]) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(68, 151));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(78, 135), FACING_SOUTHWEST);
+ }
+
+ if (_scene->_priorSceneId == 105)
+ _game._player._playerPos = Common::Point(132, 47);
+ else if (_scene->_priorSceneId == 106)
+ _game._player._playerPos = Common::Point(20, 91);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(223, 151);
+
+ if (((_scene->_priorSceneId == 105) || (_scene->_priorSceneId == 106)) && (_vm->getRandomNumber(1, 3) == 1)) {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(Resources::formatName(105, 'R', 1, EXT_SS, ""));
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], true, 4, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[0], Common::Point(270, 150));
+ _scene->_sequences.setMotion(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, -200, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 2);
+ _scene->_dynamicHotspots.add(218, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0));
+ }
+
+ _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0);
+ _shootingFl = false;
+
+ if (_vm->getRandomNumber(1, 3) == 1) {
+ _scene->loadAnimation(Resources::formatName(107, 'B', -1, EXT_AA, ""), 0);
+ _shootingFl = true;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene107::step() {
+ if (_shootingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52));
+ _shootingFl = false;
+ }
+}
+
+void Scene107::preActions() {
+ if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_WEST))
+ _game._player._walkOffScreenSceneId = 106;
+
+ if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH))
+ _game._player._walkOffScreenSceneId = 108;
+}
+
+void Scene107::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(10708);
+ else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn107]) {
+ if (_game._objects.isInInventory(OBJ_DEAD_FISH)) {
+ int randVal = _vm->getRandomNumber(74, 76);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal));
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _game._objects.addToInventory(OBJ_DEAD_FISH);
+ _globals[kFishIn107] = false;
+ _vm->_dialogs->showItem(OBJ_DEAD_FISH, 802);
+ }
+ } else if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_NORTHERN_SEA_CLIFF))
+ _scene->_nextSceneId = 105;
+ else if (_action.isAction(VERB_LOOK, NOUN_NORTHERN_SEA_CLIFF))
+ _vm->_dialogs->show(10701);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(10702);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUSH_LIKE_FORMATION))
+ _vm->_dialogs->show(10703);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCK))
+ _vm->_dialogs->show(10704);
+ else if (_action.isAction(VERB_LOOK, NOUN_SEAWEED))
+ _vm->_dialogs->show(10705);
+ else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_SOUTH))
+ _vm->_dialogs->show(10706);
+ else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE))
+ _vm->_dialogs->show(10707);
+ else if (_action.isAction(VERB_LOOK, NOUN_MANTA_RAY))
+ _vm->_dialogs->show(10709);
+ else if (_action.isAction(VERB_TAKE, NOUN_MANTA_RAY))
+ _vm->_dialogs->show(10710);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene108::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene108::enter() {
+ if (_globals[kHoovicSated] == 2)
+ _globals[kHoovicSated] = 0;
+
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 3));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(105, 'f', 4, EXT_SS, ""));
+
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 13, 0, 0, 7);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 16, 0, 0, 9);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 3);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 14, 0, 0, 13);
+
+ for (int i = 0; i <= 3; i++)
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[i], 0);
+
+ if (_globals[kFishIn108]) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(41, 109));
+ int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(41, 109), FACING_NORTHWEST);
+ }
+
+ if (_scene->_priorSceneId == 107)
+ _game._player._playerPos = Common::Point(138, 58);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(305, 98);
+
+ _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0);
+ sceneEntrySound();
+}
+
+void Scene108::preActions() {
+ if (_action.isAction(VERB_SWIM_UNDER, NOUN_OVERHANG_TO_EAST))
+ _game._player._walkOffScreenSceneId = 109;
+}
+
+void Scene108::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(10812);
+ else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn108]) {
+ if (_game._objects.isInInventory(OBJ_DEAD_FISH)) {
+ int randVal = _vm->getRandomNumber(74, 76);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal));
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _game._objects.addToInventory(OBJ_DEAD_FISH);
+ _globals[kFishIn108] = false;
+ _vm->_dialogs->showItem(OBJ_DEAD_FISH, 10808);
+ }
+ } else if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_NORTH))
+ _scene->_nextSceneId = 107;
+ else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE))
+ _vm->_dialogs->show(10801);
+ else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR))
+ _vm->_dialogs->show(10802);
+ else if (_action.isAction(VERB_LOOK, NOUN_ODD_ROCK_FORMATION))
+ _vm->_dialogs->show(10803);
+ else if (_action.isAction(VERB_TAKE, NOUN_ODD_ROCK_FORMATION))
+ _vm->_dialogs->show(10804);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCKS))
+ _vm->_dialogs->show(10805);
+ else if (_action.isAction(VERB_TAKE, NOUN_ROCKS))
+ _vm->_dialogs->show(10806);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH))
+ _vm->_dialogs->show(10807);
+ else if (_action.isAction(VERB_LOOK, NOUN_OVERHANG_TO_EAST))
+ _vm->_dialogs->show(10809);
+ else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_NORTH))
+ _vm->_dialogs->show(10810);
+ else if (_action.isAction(VERB_LOOK, NOUN_SURFACE))
+ _vm->_dialogs->show(10811);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene109::Scene109(MADSEngine *vm) : Scene1xx(vm) {
+ _rexThrowingObject = false;
+ _hoovicDifficultFl = false;
+ _beforeEatingRex = false;
+ _eatingRex = false;
+ _hungryFl = false;
+ _eatingFirstFish = false;
+
+ _throwingObjectId = -1;
+ _hoovicTrigger = 0;
+}
+
+void Scene109::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_rexThrowingObject);
+ s.syncAsByte(_hoovicDifficultFl);
+ s.syncAsByte(_beforeEatingRex);
+ s.syncAsByte(_eatingRex);
+ s.syncAsByte(_hungryFl);
+ s.syncAsByte(_eatingFirstFish);
+ s.syncAsSint32LE(_throwingObjectId);
+ s.syncAsSint32LE(_hoovicTrigger);
+}
+
+void Scene109::setup() {
+ _scene->addActiveVocab(NOUN_DEAD_PURPLE_MONSTER);
+ _scene->addActiveVocab(NOUN_MONSTER_SLUDGE);
+
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene109::enter() {
+ _globals[kFishIn105] = true;
+
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*RXSWRC_6");
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('O', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('O', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('O', 0));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('H', 4));
+
+ _rexThrowingObject = false;
+ _throwingObjectId = 0;
+ _beforeEatingRex = false;
+ _eatingRex = false;
+ _hungryFl = false;
+
+ if (_scene->_priorSceneId == 110) {
+ _game._player._playerPos = Common::Point(248, 38);
+ _globals[kHoovicSated] = 2;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(20, 68);
+ _game._player._facing = FACING_EAST;
+ }
+
+ if (!_globals[kHoovicAlive]) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2);
+
+ int idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(256, 57, 267, 87));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST);
+ idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(242, 79, 265, 90));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST);
+ idx = _scene->_dynamicHotspots.add(229, 348, -1, Common::Rect(231, 88, 253, 94));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST);
+ }
+
+ if (!_globals[kHoovicAlive] || _globals[kHoovicSated])
+ _scene->changeVariant(1);
+
+ if (_game._objects.isInRoom(OBJ_BURGER)) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2);
+ int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST);
+ } else if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_BURGER);
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_DEAD_FISH);
+ _game._objects.addToInventory(OBJ_STUFFED_FISH);
+ }
+
+ _vm->_palette->setEntry(252, 50, 50, 63);
+ _vm->_palette->setEntry(253, 30, 30, 50);
+
+ _game.loadQuoteSet(0x53, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0);
+ _eatingFirstFish = (!_game._visitedScenes._sceneRevisited) && (_scene->_priorSceneId < 110);
+
+ if (_eatingFirstFish) {
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(Resources::formatName(105, 'F', 1, EXT_SS, ""));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('H', 1));
+
+ _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], true, 4, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 5);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(126, 39));
+ _scene->_sequences.setMotion(_globals._sequenceIndexes[10], 0, 200, 0);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[10], 80);
+ _game._player._stepEnabled = false;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene109::step() {
+ if (_beforeEatingRex) {
+ if (!_eatingRex) {
+ if (_game._player._playerPos.x > 205) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 70);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+
+ _eatingRex = true;
+ _vm->_sound->command(34);
+ }
+ } else {
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = false;
+ break;
+
+ case 71:
+ _scene->_reloadSceneFlag = true;
+ break;
+ }
+ }
+ }
+
+ if (_hungryFl && (_game._player._playerPos == Common::Point(160, 32)) && (_game._player._facing == FACING_EAST)) {
+ _game._player.walk(Common::Point(226, 24), FACING_EAST);
+ _game._player._stepEnabled = false;
+ _hungryFl = false;
+ _beforeEatingRex = true;
+ _scene->_sprites.remove(_globals._spriteIndexes[6]);
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('H', 0));
+ _vm->_palette->refreshSceneColors();
+ }
+
+ if (_game._player._moving && (_scene->_rails.getNext() > 0) && _globals[kHoovicAlive] && !_globals[kHoovicSated] && !_hungryFl && !_beforeEatingRex) {
+ _game._player.cancelCommand();
+ _game._player.startWalking(Common::Point(160, 32), FACING_EAST);
+ _scene->_rails.resetNext();
+ _hungryFl = true;
+ }
+
+ if (_eatingFirstFish && (_scene->_sequences[_globals._sequenceIndexes[10]]._position.x >= 178)) {
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 4, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_SPRITE, 29, 72);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 29, 73);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], _globals._sequenceIndexes[9]);
+ _eatingFirstFish = false;
+ _game._player._stepEnabled = true;
+ _vm->_sound->command(34);
+ }
+
+ if (_game._trigger == 72)
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+
+ if (_game._trigger == 73) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _scene->_sprites.remove(_globals._spriteIndexes[9]);
+ _scene->_sprites.remove(_globals._spriteIndexes[10]);
+
+ _scene->_spriteSlots.clear();
+ _scene->_spriteSlots.fullRefresh();
+
+ int randVal = _vm->getRandomNumber(85, 88);
+ int idx = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal));
+ _scene->_kernelMessages.setQuoted(idx, 4, true);
+ _scene->_kernelMessages._entries[idx]._frameTimer = _scene->_frameStartTime + 4;
+ }
+}
+
+void Scene109::preActions() {
+ if (_action.isAction(VERB_SWIM_UNDER, NOUN_OVERHANG_TO_WEST))
+ _game._player._walkOffScreenSceneId = 108;
+
+ if ((_action.isAction(VERB_THROW) || _action.isAction(VERB_GIVE) || _action.isAction(VERB_PUT))
+ && (_action.isObject(NOUN_SMALL_HOLE) || _action.isObject(NOUN_TUNNEL))
+ && (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER))) {
+ int idx = _game._objects.getIdFromDesc(_action._activeAction._objectNameId);
+ if ((idx >= 0) && _game._objects.isInInventory(idx)) {
+ _game._player._prepareWalkPos = Common::Point(106, 38);
+ _game._player._prepareWalkFacing = FACING_EAST;
+ _game._player._needToWalk = true;
+ _game._player._readyToWalk = true;
+ }
+ }
+
+ if ((_action.isAction(VERB_SWIM_INTO, NOUN_TUNNEL) || _action.isAction(VERB_SWIM_TO, NOUN_SMALL_HOLE))
+ && (!_globals[kHoovicAlive] || _globals[kHoovicSated]) && (_action.isObject(NOUN_TUNNEL)))
+ _game._player._walkOffScreenSceneId = 110;
+
+ _hungryFl = false;
+}
+
+void Scene109::actions() {
+ if (_action._lookFlag) {
+ _vm->_dialogs->show(10912);
+ _action._inProgress = false;
+ return;
+ }
+
+ if ((_action.isAction(VERB_THROW) || _action.isAction(VERB_GIVE)) && (_action.isTarget(NOUN_SMALL_HOLE) || _action.isTarget(NOUN_TUNNEL))) {
+ if (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER)) {
+ _throwingObjectId = _game._objects.getIdFromDesc(_action._activeAction._objectNameId);
+ if (_throwingObjectId >= 0) {
+ if ((_game._objects.isInInventory(_throwingObjectId) && _globals[kHoovicAlive]) || _rexThrowingObject) {
+ switch (_game._trigger) {
+ case 0:
+ _rexThrowingObject = true;
+ _hoovicDifficultFl = false;
+ _game._objects.setRoom(_throwingObjectId, NOWHERE);
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 4, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[0]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+
+ switch (_throwingObjectId) {
+ case OBJ_DEAD_FISH:
+ case OBJ_STUFFED_FISH:
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('H', 1));
+ break;
+
+ case OBJ_BURGER:
+ _hoovicDifficultFl = (_game._difficulty == DIFFICULTY_EASY);
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('H', (_hoovicDifficultFl ? 3 : 1)));
+ break;
+ }
+
+ _vm->_palette->refreshSceneColors();
+ break;
+
+ case 1:
+ _game._player._visible = true;
+ _hoovicTrigger = 4;
+ switch (_throwingObjectId) {
+ case OBJ_BURGER:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, (_hoovicDifficultFl ? 4 : 6), 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 2, 2);
+ if (_hoovicDifficultFl) {
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 30);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 5);
+ } else {
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8);
+ _hoovicTrigger = 3;
+ }
+ break;
+ case OBJ_DEAD_FISH:
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 2);
+ break;
+ case OBJ_STUFFED_FISH:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 2);
+ _hoovicTrigger = 3;
+ break;
+ }
+ break;
+
+ case 2:
+ if (_hoovicDifficultFl)
+ _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 4, 2, 0, 0);
+ else
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 4, 1, 0, 0);
+
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, _hoovicTrigger);
+ _vm->_sound->command(34);
+ break;
+
+ case 3:
+ _scene->loadAnimation(Resources::formatName(109, 'H', 2, EXT_AA, ""), 4);
+ _vm->_sound->command(35);
+ _globals[kHoovicAlive] = false;
+ break;
+
+ case 4:
+ if (!_globals[kHoovicAlive]) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2);
+ int idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(256, 57, 256 + 12, 57 + 31));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST);
+ idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(242, 79, 242 + 24, 79 + 12));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST);
+ idx = _scene->_dynamicHotspots.add(229, 348, -1, Common::Rect(231, 88, 231 + 23, 88 + 7));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST);
+ _scene->changeVariant(1);
+ } else {
+ if (_throwingObjectId == OBJ_DEAD_FISH) {
+ ++_globals[kHoovicFishEaten];
+ int threshold;
+ switch (_game._difficulty) {
+ case DIFFICULTY_HARD:
+ threshold = 1;
+ break;
+ case DIFFICULTY_MEDIUM:
+ threshold = 3;
+ break;
+ default:
+ threshold = 50;
+ break;
+ }
+
+ if (_globals[kHoovicFishEaten] >= threshold) {
+ int randVal = _vm->getRandomNumber(83, 84);
+ _scene->_kernelMessages.add(Common::Point(230, 24), 0xFDFC, 0, 0, 120, _game.getQuote(randVal));
+ _globals[kHoovicFishEaten] = 0;
+ _globals[kHoovicSated] = 1;
+ _scene->changeVariant(1);
+ }
+ }
+ }
+ _scene->freeAnimation();
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _scene->_sprites.remove(_globals._spriteIndexes[8]);
+ _scene->_spriteSlots.clear();
+ _scene->_spriteSlots.fullRefresh();
+ _scene->_sequences.scan();
+ if (_game._player._visible) {
+ _game._player._forceRefresh = true;
+ _game._player.update();
+ }
+
+ _game._player._stepEnabled = true;
+ _rexThrowingObject = false;
+ break;
+
+ case 5: {
+ _game._objects.setRoom(OBJ_BURGER, _scene->_currentSceneId);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 30, 30);
+ int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST);
+ _scene->_sequences.addTimer(65, 6);
+ }
+ break;
+
+ case 6: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 31, 46);
+ int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 7);
+ }
+ break;
+
+ case 7: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST);
+ _vm->_dialogs->show(10915);
+ }
+ break;
+
+ case 8:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, 16);
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ } else if (_game._objects.isInInventory(_throwingObjectId)) {
+ // Nothing.
+ }
+ }
+ }
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_BURGER) && _game._objects.isInRoom(OBJ_BURGER)) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _game._objects.addToInventory(OBJ_BURGER);
+ } else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR))
+ _vm->_dialogs->show(10901);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORAL))
+ _vm->_dialogs->show(10902);
+ else if ((_action.isAction(VERB_TAKE) || _action.isAction(VERB_PULL)) && _action.isObject(NOUN_CORAL))
+ _vm->_dialogs->show(10903);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCKS))
+ _vm->_dialogs->show(10904);
+ else if (_action.isAction(VERB_TAKE, NOUN_ROCKS))
+ _vm->_dialogs->show(10905);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAVE_WALL))
+ _vm->_dialogs->show(10906);
+ else if (_action.isAction(VERB_LOOK, NOUN_TUNNEL)) {
+ if (_globals[kHoovicAlive])
+ _vm->_dialogs->show(10907);
+ else
+ _vm->_dialogs->show(10913);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SMALL_HOLE))
+ _vm->_dialogs->show(10908);
+ else if (_action.isAction(VERB_LOOK, NOUN_OVERHANG_TO_WEST))
+ _vm->_dialogs->show(10911);
+ else if (_action.isAction(VERB_PUT, NOUN_SMALL_HOLE))
+ _vm->_dialogs->show(10910);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEAD_PURPLE_MONSTER))
+ _vm->_dialogs->show(10914);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene110::Scene110(MADSEngine *vm) : Scene1xx(vm) {
+ _crabsFl = false;
+}
+
+void Scene110::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_crabsFl);
+}
+
+void Scene110::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_CRAB);
+}
+
+void Scene110::enter() {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 3));
+
+ _crabsFl = false;
+
+ if (_scene->_priorSceneId == 109) {
+ _game._player._playerPos = Common::Point(59, 71);
+
+ _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+
+ _crabsFl = true;
+
+ int idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE);
+ idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE);
+ idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE);
+ idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(194, 23);
+ _game._player._facing = FACING_SOUTH;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(Resources::formatName(110, 'T', 1,EXT_AA, ""), 70);
+ }
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0x59, 0);
+
+ if (!_game._visitedScenes._sceneRevisited && (_scene->_priorSceneId == 109))
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(109));
+}
+
+void Scene110::step() {
+ if (_game._trigger == 70) {
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ }
+}
+
+void Scene110::preActions() {
+ if (_action.isAction(VERB_SWIM_THROUGH, NOUN_CAVE_ENTRANCE))
+ _game._player._walkOffScreenSceneId = 109;
+
+ if (_crabsFl) {
+ _crabsFl = false;
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[0]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 16, 1, 0, 0);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 16, 1, 0, 0);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 16, 1, 0, 0);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 16, 1, 0, 0);
+
+ int idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE);
+ idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE);
+ idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE);
+ idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE);
+ }
+}
+
+void Scene110::actions() {
+ if (_action.isAction(VERB_SWIM_THROUGH, NOUN_TUNNEL)) {
+ switch (_game._trigger) {
+ case 0:
+ _scene->loadAnimation(Resources::formatName(110, 'T', 0, EXT_AA, ""), 1);
+ _scene->_activeAnimation->setNextFrameTimer(_game._player._ticksAmount + _game._player._priorTimer);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ break;
+ case 1:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _scene->_nextSceneId = 111;
+ break;
+ }
+ } else if ((_action._lookFlag) || _action.isAction(VERB_LOOK, NOUN_CAVE))
+ _vm->_dialogs->show(11001);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAVE_CEILING) || _action.isAction(VERB_LOOK_AT, NOUN_CAVE_CEILING))
+ _vm->_dialogs->show(11002);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCKS))
+ _vm->_dialogs->show(11003);
+ else if (_action.isAction(VERB_TAKE, NOUN_ROCKS))
+ _vm->_dialogs->show(11004);
+ else if (_action.isAction(VERB_LOOK, NOUN_TUNNEL))
+ _vm->_dialogs->show(11005);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE))
+ _vm->_dialogs->show(11006);
+ else if (_action.isAction(VERB_LOOK, NOUN_FUNGOIDS))
+ _vm->_dialogs->show(11007);
+ else if (_action.isAction(VERB_TAKE, NOUN_FUNGOIDS))
+ _vm->_dialogs->show(11008);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene111::Scene111(MADSEngine *vm) : Scene1xx(vm) {
+ _stampedFl = false;
+ _launch1Fl = false;
+ _launched2Fl = false;
+ _rexDivingFl = false;
+}
+
+void Scene111::synchronize(Common::Serializer &s) {
+ Scene1xx::synchronize(s);
+
+ s.syncAsByte(_stampedFl);
+ s.syncAsByte(_launch1Fl);
+ s.syncAsByte(_launched2Fl);
+ s.syncAsByte(_rexDivingFl);
+}
+
+void Scene111::setup() {
+ _scene->addActiveVocab(NOUN_BATS);
+
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene111::enter() {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2));
+
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('B', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('B', 1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('B', 2));
+
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 8, 0, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 9, 73);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 13, 73);
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 71, 71);
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 0, 0, 0);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+
+ int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE);
+ idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE);
+ idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE);
+
+ _launch1Fl = false;
+ _launched2Fl = false;
+ _stampedFl = false;
+
+ if ((_scene->_priorSceneId < 201) && (_scene->_priorSceneId != -2)) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->loadAnimation(Resources::formatName(111, 'A', 0, EXT_AA, ""), 70);
+ _game._player._playerPos = Common::Point(234, 116);
+ _game._player._facing = FACING_EAST;
+
+ _launch1Fl = true;
+ _launched2Fl = true;
+
+ _vm->_sound->command(36);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(300, 130);
+ _game._player._facing = FACING_WEST;
+ }
+
+ _rexDivingFl = false;
+
+ sceneEntrySound();
+}
+
+void Scene111::step() {
+ if (_game._trigger == 70) {
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _launch1Fl = false;
+ _launched2Fl = false;
+ }
+
+ if ((_game._trigger == 71) && !_stampedFl) {
+ _stampedFl = true;
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 18, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ }
+
+ if (_game._trigger == 72) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 20);
+ }
+
+ if (!_launch1Fl && (_vm->getRandomNumber(1, 5000) == 1)) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0);
+ _launch1Fl = true;
+ int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE);
+ }
+
+ if (!_launched2Fl && (_vm->getRandomNumber(1, 30000) == 1)) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 1, 0, 0);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE);
+ _launched2Fl = true;
+ }
+
+ if (_game._trigger == 73)
+ _vm->_sound->command(37);
+
+ if (_rexDivingFl && (_scene->_activeAnimation->getCurrentFrame() >= 9)) {
+ _vm->_sound->command(36);
+ _rexDivingFl = false;
+ }
+}
+
+void Scene111::preActions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_CAVE_ENTRANCE))
+ _game._player._walkOffScreenSceneId = 212;
+}
+
+void Scene111::actions() {
+ if (_action.isAction(VERB_DIVE_INTO, NOUN_POOL) && _game._objects.isInInventory(OBJ_REBREATHER)) {
+ switch (_game._trigger) {
+ case 0:
+ _scene->loadAnimation(Resources::formatName(111, 'A', 1, EXT_AA, ""), 1);
+ _rexDivingFl = true;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ break;
+
+ case 1:
+ _scene->_nextSceneId = 110;
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_CAVE_FLOOR))
+ _vm->_dialogs->show(11101);
+ else if (_action.isAction(VERB_LOOK, NOUN_POOL))
+ _vm->_dialogs->show(11102);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE))
+ _vm->_dialogs->show(11103);
+ else if (_action.isAction(VERB_LOOK, NOUN_STALAGMITES))
+ _vm->_dialogs->show(11104);
+ else if (_action.isAction(VERB_LOOK, NOUN_LARGE_STALAGMITE))
+ _vm->_dialogs->show(11105);
+ else if ((_action.isAction(VERB_PULL) || _action.isAction(VERB_TAKE)) && (_action.isObject(NOUN_STALAGMITES) || _action.isObject(NOUN_LARGE_STALAGMITE)))
+ _vm->_dialogs->show(11106);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene112::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene112::enter() {
+ sceneEntrySound();
+
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 5));
+
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 10, 0, 17, 20);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 0, 0, 0);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 3, 0);
+
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+
+ _scene->_userInterface.emptyConversationList();
+ _scene->_userInterface.setup(kInputConversation);
+
+ _scene->loadAnimation(Resources::formatName(112, 'X', -1, EXT_AA, ""), 70);
+}
+
+void Scene112::step() {
+ if ((_scene->_activeAnimation != nullptr) && (_game._storyMode == STORYMODE_NICE)) {
+ if (_scene->_activeAnimation->getCurrentFrame() >= 54) {
+ _scene->freeAnimation();
+ _game._trigger = 70;
+ }
+ }
+
+ if (_game._trigger == 70) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 3, 0, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ }
+
+ if (_game._trigger == 71) {
+ _scene->_nextSceneId = 101;
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Nebular
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes1.h b/engines/mads/nebular/nebular_scenes1.h
new file mode 100644
index 0000000000..1afa7fccc1
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes1.h
@@ -0,0 +1,264 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_NEBULAR_SCENES1_H
+#define MADS_NEBULAR_SCENES1_H
+
+#include "common/scummsys.h"
+#include "common/serializer.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+class Scene1xx : public NebularScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void sceneEntrySound();
+
+ /**
+ *Sets the AA file to use for the scene
+ */
+ void setAAName();
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix();
+public:
+ Scene1xx(MADSEngine *vm) : NebularScene(vm) {}
+};
+
+class Scene101 : public Scene1xx {
+private:
+ bool _sittingFl;
+ bool _panelOpened;
+
+ int _messageNum;
+ int _posY;
+ int _shieldSpriteIdx;
+ int _chairHotspotId;
+ int _oldSpecial;
+
+ void sayDang();
+
+public:
+ Scene101(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene102 : public Scene1xx {
+private:
+ bool _fridgeOpenedFl;
+ bool _fridgeOpenedDescr;
+ bool _fridgeFirstOpenFl;
+ bool _chairDescrFl;
+ bool _drawerDescrFl;
+ bool _activeMsgFl;
+
+ int _fridgeCommentCount;
+
+ void addRandomMessage();
+
+public:
+ Scene102(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+ virtual void postActions();
+};
+
+class Scene103 : public Scene1xx {
+private:
+ uint32 _updateClock;
+
+public:
+ Scene103(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+ virtual void postActions();
+};
+
+class Scene104 : public Scene1xx {
+private:
+ bool _kargShootingFl;
+ bool _loseFl;
+
+public:
+ Scene104(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene105 : public Scene1xx {
+private:
+ bool _explosionFl;
+
+public:
+ Scene105(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene106 : public Scene1xx {
+private:
+ bool _backToShipFl;
+ bool _shadowFl;
+ bool _firstEmergingFl;
+
+ int _positionY;
+
+public:
+ Scene106(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene107 : public Scene1xx {
+private:
+ bool _shootingFl;
+
+public:
+ Scene107(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene108 : public Scene1xx {
+public:
+ Scene108(MADSEngine *vm) : Scene1xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene109 : public Scene1xx {
+private:
+ bool _rexThrowingObject;
+ bool _hoovicDifficultFl;
+ bool _beforeEatingRex;
+ bool _eatingRex;
+ bool _hungryFl;
+ bool _eatingFirstFish;
+
+ int _throwingObjectId;
+ int _hoovicTrigger;
+
+public:
+ Scene109(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene110 : public Scene1xx {
+private:
+ bool _crabsFl;
+
+public:
+ Scene110(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene111 : public Scene1xx {
+private:
+ bool _stampedFl;
+ bool _launch1Fl;
+ bool _launched2Fl;
+ bool _rexDivingFl;
+
+public:
+ Scene111(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene112 : public Scene1xx {
+public:
+ Scene112(MADSEngine *vm) : Scene1xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions() {};
+};
+
+} // End of namespace Nebular
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES1_H */
diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp
new file mode 100644
index 0000000000..94e30aa4f2
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes2.cpp
@@ -0,0 +1,5380 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes2.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+void Scene2xx::setAAName() {
+ int idx = (_scene->_nextSceneId == 216) ? 4 : 2;
+ _game._aaName = Resources::formatAAName(idx);
+}
+
+void Scene2xx::setPlayerSpritesPrefix() {
+ _vm->_sound->command(5);
+ Common::String oldName = _game._player._spritesPrefix;
+
+ switch(_scene->_nextSceneId) {
+ case 213:
+ case 216:
+ _game._player._spritesPrefix = "";
+ break;
+ default:
+ if (_globals[kSexOfRex] != SEX_MALE) {
+ _game._player._spritesPrefix = "ROX";
+ } else {
+ _game._player._spritesPrefix = "RXM";
+ }
+ break;
+ }
+
+ _game._player._scalingVelocity = (_scene->_nextSceneId <= 212);
+
+ if (oldName != _game._player._spritesPrefix)
+ _game._player._spritesChanged = true;
+
+ if ((_scene->_nextSceneId == 203 || _scene->_nextSceneId == 204) && _globals[kRhotundaStatus])
+ _game._player._loadsFirst = false;
+
+ _vm->_palette->setEntry(16, 10, 63, 63);
+ _vm->_palette->setEntry(17, 10, 45, 45);
+}
+
+void Scene2xx::sceneEntrySound() {
+ if (_vm->_musicFlag) {
+ switch (_scene->_nextSceneId) {
+ case 201:
+ if ((_globals[kTeleporterCommand] == 2) || (_globals[kTeleporterCommand] == 4) || (_globals[kMeteorologistStatus] != 1))
+ _vm->_sound->command(9);
+ else
+ _vm->_sound->command(17);
+ break;
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 208:
+ case 209:
+ case 212:
+ _vm->_sound->command(9);
+ break;
+ case 206:
+ case 211:
+ case 215:
+ _vm->_sound->command(10);
+ break;
+ case 207:
+ case 214:
+ _vm->_sound->command(11);
+ break;
+ case 210:
+ if (_globals[kTwinklesStatus] == 0)
+ _vm->_sound->command(15);
+ else
+ _vm->_sound->command(10);
+ break;
+ case 213:
+ if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL)
+ _vm->_sound->command(1);
+ else
+ _vm->_sound->command(9);
+ break;
+ case 216:
+ _vm->_sound->command(16);
+ break;
+ default:
+ _vm->_sound->command(10);
+ break;
+ }
+ } else
+ _vm->_sound->command(2);
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene201::Scene201(MADSEngine *vm) : Scene2xx(vm) {
+ _pterodactylFlag = false;
+}
+
+void Scene201::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsByte(_pterodactylFlag);
+}
+
+void Scene201::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_SWOOPING_CREATURE);
+ _scene->addActiveVocab(NOUN_BIRDS);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene201::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', -1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', -1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*SC002Z1");
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 1, 0);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 50);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 4, 0, 0, 0);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(185, 46));
+
+ int idx = _scene->_dynamicHotspots.add(NOUN_BIRDS, 209, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(186, 81), FACING_NORTH);
+
+ if ((_scene->_priorSceneId == 202) || (_scene->_priorSceneId == -1)) {
+ _game._player._playerPos = Common::Point(165, 152);
+ } else {
+ _game._player._playerPos = Common::Point(223, 149);
+ _game._player._facing = FACING_SOUTH;
+ }
+
+ if (_globals[kTeleporterCommand]) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ int sepChar = (_globals[kSexOfRex] == SEX_MALE) ? 't' : 'u';
+ // Guess values. What is the default value used by the compiler?
+ int suffixNum = -1;
+ int abortTimers = -1;
+ switch(_globals[kTeleporterCommand]) {
+ case 1:
+ suffixNum = 3;
+ abortTimers = 76;
+ _globals[kTeleporterUnderstood] = true;
+ break;
+ case 2:
+ suffixNum = 1;
+ abortTimers = 77;
+ break;
+ case 3:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ suffixNum = -1;
+ break;
+ case 4:
+ suffixNum = 2;
+ abortTimers = 78;
+ break;
+ }
+ _globals[kTeleporterCommand] = 0;
+ if (suffixNum >= 0)
+ _scene->loadAnimation(formAnimName(sepChar, suffixNum), abortTimers);
+ }
+
+ if ((_scene->_priorSceneId == 202) && (_globals[kMeteorologistStatus] == METEOROLOGIST_PRESENT) && !_scene->_roomChanged) {
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _game.loadQuoteSet(90, 91, 0);
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -1, 12);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 12, 70);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1);
+ _pterodactylFlag = false;
+ _game._player.walk(Common::Point(157, 143), FACING_NORTH);
+ _vm->_palette->setEntry(252, 45, 63, 45);
+ _vm->_palette->setEntry(253, 20, 45, 20);
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 2, 0, 120, _game.getQuote(90));
+ } else
+ _pterodactylFlag = true;
+
+ if (_globals[kTeleporterUnderstood])
+ _scene->_hotspots.activate(NOUN_STRANGE_DEVICE, false);
+
+ sceneEntrySound();
+}
+
+void Scene201::step() {
+ if (_pterodactylFlag && (_vm->getRandomNumber(5000) == 9)) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 1, 6, 0);
+ int idx = _scene->_dynamicHotspots.add(351, 13, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(270, 80), FACING_EAST);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 8);
+ _vm->_sound->command(14);
+ _pterodactylFlag = false;
+ }
+
+ if (_game._trigger == 70) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0);
+ _game._player._visible = false;
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 12, 16);
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 9, 1, 0, 0);
+ _vm->_sound->command(42);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 3, 81);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 73);
+ }
+
+ if (_game._trigger == 81) {
+ _scene->_kernelMessages.reset();
+ }
+
+ if (_game._trigger == 71) {
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 9, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], -2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1);
+ }
+
+ if (_game._trigger == 73) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 17, -2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 74);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1);
+ }
+
+ if (_game._trigger == 74) {
+ _vm->_sound->command(40);
+
+ _scene->_kernelMessages.add(Common::Point(125, 56), 0xFDFC, 32, 82, 180, _game.getQuote(91));
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2);
+ _scene->_sequences.addTimer(180, 75);
+ }
+
+ if (_game._trigger == 75) {
+ _globals[kMeteorologistEverSeen] = 0;
+ _scene->_nextSceneId = 202;
+ }
+
+ if (_game._trigger == 76) {
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ }
+
+ if (_game._trigger == 77) {
+ _globals[kTeleporterCommand] = 1;
+ _scene->_nextSceneId = _globals[kTeleporterDestination];
+ _scene->_reloadSceneFlag = true;
+ }
+
+ if (_game._trigger == 78) {
+ _vm->_sound->command(40);
+ _vm->_dialogs->show(20114);
+ _scene->_reloadSceneFlag = true;
+ }
+}
+
+void Scene201::actions() {
+ if (_action._lookFlag == false) {
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH))
+ _scene->_nextSceneId = 202;
+ else if (_action.isAction(VERB_CLIMB_UP, NOUN_STEPS) || (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) || (_action.isAction(VERB_WALK_INSIDE, NOUN_STRANGE_DEVICE))) {
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ int sepChar = (_globals[kSexOfRex] == SEX_MALE) ? 't' : 'u';
+ _scene->loadAnimation(formAnimName(sepChar, 0), 1);
+ } else if (_game._trigger == 1) {
+ _scene->_nextSceneId = 213;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) {
+ _vm->_dialogs->show(20101);
+ } else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) {
+ _vm->_dialogs->show(20102);
+ } else if (_action.isAction(VERB_LOOK, NOUN_THORNY_BUSH)) {
+ _vm->_dialogs->show(20103);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) {
+ _vm->_dialogs->show(20104);
+ } else if (_action.isAction(VERB_LOOK, NOUN_WATER)) {
+ _vm->_dialogs->show(20105);
+ } else if (_action.isAction(VERB_LOOK, NOUN_ISLAND_IN_DISTANCE)) {
+ _vm->_dialogs->show(20106);
+ } else if (_action.isAction(VERB_LOOK, NOUN_WEATHER_STATION)) {
+ _vm->_dialogs->show(20107);
+ } else if (_action.isAction(VERB_LOOK, NOUN_PATH)) {
+ _vm->_dialogs->show(20108);
+ } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_SOUTH)) {
+ _vm->_dialogs->show(20110);
+ } else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) {
+ if (_globals[kMeteorologistEverSeen])
+ _vm->_dialogs->show(20112);
+ else
+ _vm->_dialogs->show(20109);
+ } else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) {
+ _vm->_dialogs->show(20113);
+ } else
+ return;
+ } else {
+ _vm->_dialogs->show(20111);
+ }
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene202::Scene202(MADSEngine *vm) : Scene2xx(vm) {
+ _activeMsgFl = false;
+ _ladderTopFl = false;
+ _waitingMeteoFl = false;
+ _ladderHotspotId = -1;
+ _meteoClock1 = 0;
+ _meteoClock2 = 0;
+ _toStationFl = false;
+ _toTeleportFl = false;
+ _lastRoute = 0;
+ _stationCounter = 0;
+ _meteoFrame = 0;
+ _startTime = 0;
+ _meteorologistSpecial = false;
+}
+
+void Scene202::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsByte(_activeMsgFl);
+ s.syncAsByte(_ladderTopFl);
+ s.syncAsByte(_waitingMeteoFl);
+ s.syncAsByte(_toStationFl);
+ s.syncAsByte(_toTeleportFl);
+
+ s.syncAsSint32LE(_ladderHotspotId);
+ s.syncAsSint32LE(_lastRoute);
+ s.syncAsSint32LE(_stationCounter);
+ s.syncAsSint32LE(_meteoFrame);
+
+ s.syncAsUint32LE(_meteoClock1);
+ s.syncAsUint32LE(_meteoClock2);
+ s.syncAsUint32LE(_startTime);
+
+ s.syncAsByte(_meteorologistSpecial);
+}
+
+void Scene202::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_LADDER);
+ _scene->addActiveVocab(VERB_CLIMB_DOWN);
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_BONE);
+ _scene->addActiveVocab(NOUN_SKULL);
+ _scene->addActiveVocab(NOUN_BROKEN_LADDER);
+}
+
+void Scene202::enter() {
+ _game._player._beenVisible = true;
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('l', -1));
+ if (_globals[kSexOfRex] != SEX_MALE) {
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXBD_2");
+ } else {
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*RXMBD_2");
+ }
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 2));
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(149, 113));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10);
+ int idx = _scene->_dynamicHotspots.add(NOUN_SKULL, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(153, 97), FACING_SOUTH);
+
+ if (!(_globals[kBone202Status] & 1)) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(130, 108));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ idx = _scene->_dynamicHotspots.add(NOUN_BONE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(132, 97), FACING_SOUTH);
+ }
+
+ if (!(_globals[kBone202Status] & 2)) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(166, 110));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 10);
+ idx = _scene->_dynamicHotspots.add(NOUN_BONE, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(165, 99), FACING_SOUTH);
+ }
+
+ if (_globals[kBone202Status])
+ _scene->changeVariant(_globals[kBone202Status]);
+
+ if (_scene->_priorSceneId == 201) {
+ _game._player._playerPos = Common::Point(190, 91);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(178, 152);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ if (_globals[kLadderBroken]) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 6);
+ _scene->_hotspots.activate(NOUN_LADDER, false);
+ idx = _scene->_dynamicHotspots.add(NOUN_BROKEN_LADDER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(246, 124), FACING_NORTH);
+ }
+
+ _game.loadQuoteSet(0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x61, 0);
+ _activeMsgFl = false;
+
+ if (_scene->_priorSceneId == -2) {
+ if (_waitingMeteoFl) {
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ _game._player._visible = false;
+ }
+ } else {
+ _waitingMeteoFl = false;
+ _ladderTopFl = false;
+ }
+
+ _meteoClock1 = _meteoClock2 = _scene->_frameStartTime;
+
+ if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_BINOCULARS);
+
+ if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _ladderTopFl = (_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER);
+
+ if (_ladderTopFl) {
+ _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 8);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1);
+
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(247, 82));
+ _game._player._playerPos = Common::Point(246, 124);
+ _game._player._facing = FACING_NORTH;
+ _globals[kTeleporterUnderstood] = true;
+ } else {
+ _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1);
+
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123));
+ _game._player._playerPos = Common::Point(171, 122);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ _scene->loadAnimation(formAnimName('M', -1), 71);
+ _scene->_activeAnimation->setCurrentFrame(200);
+ } else {
+ if (_ladderTopFl) {
+ _game._player._visible = false;
+ _scene->_sequences.startCycle(_globals._sequenceIndexes[9], true, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82));
+ _game._player._playerPos = Common::Point(246, 124);
+ _game._player._facing = FACING_NORTH;
+ }
+ }
+
+ _meteorologistSpecial = false;
+}
+
+void Scene202::setRandomKernelMessage() {
+ int vocabId = _vm->getRandomNumber(92, 96);
+ _scene->_kernelMessages.reset();
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 70, 120, _game.getQuote(vocabId));
+ _activeMsgFl = true;
+}
+
+void Scene202::step() {
+ if (!_activeMsgFl && (_game._player._playerPos == Common::Point(77, 105)) && (_game._player._facing == FACING_NORTH) && (_vm->getRandomNumber(999) == 0)) {
+ _scene->_kernelMessages.reset();
+ _activeMsgFl = false;
+ if (_vm->getRandomNumber(4) == 0)
+ setRandomKernelMessage();
+ }
+
+ if (_game._trigger == 70)
+ _activeMsgFl = false;
+
+ if (_game._trigger == 71) {
+ _vm->_sound->command(3);
+ _vm->_sound->command(9);
+
+ _meteoClock1 = _scene->_frameStartTime + 15 * 60;
+
+ if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) {
+ Common::Point msgPos;
+ int msgFlag;
+ if (!_ladderTopFl) {
+ msgPos = Common::Point(0, 0);
+ msgFlag = 2;
+ } else {
+ msgPos = Common::Point(248, 15);
+ msgFlag = 0;
+ }
+ int msgIndex = _scene->_kernelMessages.add(msgPos, 0x1110, msgFlag | 32, 0, 120, _game.getQuote(102));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+
+ if (_globals[kMeteorologistWatch] == METEOROLOGIST_GROUND) {
+ _action._activeAction._verbId = VERB_LOOK;
+ _action._activeAction._objectNameId = NOUN_BINOCULARS;
+ _action._activeAction._indirectObjectId = NOUN_STRANGE_DEVICE;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_PARSER;
+ _scene->_sequences.addTimer(2 * 60, 2);
+ _meteorologistSpecial = true;
+ } else if (_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER) {
+ _scene->_sequences.addTimer(2 * 60, 90);
+ }
+ }
+
+ _globals[kMeteorologistWatch] = METEOROLOGIST_NORMAL;
+ }
+
+ switch (_game._trigger) {
+ case 90:
+ _vm->_sound->command(41);
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 91);
+ break;
+ case 91:
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1);
+ _scene->_sequences.addTimer(60, 92);
+ break;
+ case 92: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 93);
+ _scene->_kernelMessages.reset();
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(0, -65), 0x1110, 32, 0, 60, _game.getQuote(98));
+ _scene->_kernelMessages.setSeqIndex(msgIndex, _globals._sequenceIndexes[11]);
+ }
+ break;
+ case 93: {
+ _globals[kLadderBroken] = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0);
+ _scene->_hotspots.activate(NOUN_LADDER, false);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BROKEN_LADDER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(246, 124), FACING_NORTH);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[11], _globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[11]);
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _ladderTopFl = false;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(99));
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!_scene->_activeAnimation && (_globals[kMeteorologistStatus] != METEOROLOGIST_GONE) && (_meteoClock2 <= _scene->_frameStartTime) && (_meteoClock1 <= _scene->_frameStartTime)) {
+ int randVal = _vm->getRandomNumber(1, 500);
+ int threshold = 1;
+ if (_ladderTopFl)
+ threshold += 25;
+ if (!_globals[kMeteorologistEverSeen])
+ threshold += 25;
+ if (threshold >= randVal) {
+ _vm->_sound->command(17);
+ _scene->loadAnimation(formAnimName('M', -1), 71);
+ _toStationFl = true;
+ _toTeleportFl = false;
+ _globals[kMeteorologistEverSeen] = true;
+ _lastRoute = 0;
+ _stationCounter = 0;
+ _meteoClock2 = _scene->_frameStartTime + 2;
+ }
+ }
+
+ if (!_scene->_activeAnimation)
+ return;
+
+ if (_waitingMeteoFl) {
+ if (_scene->_activeAnimation->getCurrentFrame() >= 200) {
+ if ((_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER) || _globals[kLadderBroken]) {
+ _scene->_nextSceneId = 213;
+ } else {
+ _vm->_dialogs->show(20201);
+ _scene->_reloadSceneFlag = true;
+ }
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() == 160) && (_meteoFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ Common::Point msgPos;
+ int msgFlag;
+ if (!_ladderTopFl) {
+ msgPos = Common::Point(0, 0);
+ msgFlag = 2;
+ } else {
+ msgPos = Common::Point(248, 15);
+ msgFlag = 0;
+ }
+ int msgIndex = _scene->_kernelMessages.add(msgPos, 0x1110, msgFlag | 32, 0, 120, _game.getQuote(101));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+ }
+
+ if (_meteoClock2 + 120 * 60 <= _scene->_frameStartTime) {
+ _toTeleportFl = true;
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == _meteoFrame) {
+ return;
+ }
+
+ _meteoFrame = _scene->_activeAnimation->getCurrentFrame();
+ int randVal = _vm->getRandomNumber(1, 1000);
+ int frameStep = -1;
+
+ switch (_scene->_activeAnimation->getCurrentFrame()) {
+ case 42:
+ case 77:
+ case 96:
+ _stationCounter = 0;
+ frameStep = subStep1(randVal);
+ break;
+ case 51:
+ case 74:
+ _toStationFl = false;
+ frameStep = subStep2(randVal);
+ break;
+ case 27:
+ case 119:
+ case 159:
+ frameStep = subStep3(randVal);
+ break;
+ case 176:
+ frameStep = subStep4(randVal);
+ break;
+ case 59:
+ _lastRoute = 3;
+ ++_stationCounter;
+ if (randVal <= 800)
+ frameStep = 55;
+ break;
+ case 89:
+ _lastRoute = 1;
+ if (randVal <= 700)
+ frameStep = 83;
+ break;
+ case 137:
+ _lastRoute = 2;
+ if (randVal <= 700)
+ frameStep = 126;
+ break;
+ }
+
+ if (frameStep >= 0 && frameStep != _scene->_activeAnimation->getCurrentFrame() + 1) {
+ _scene->_activeAnimation->setCurrentFrame(frameStep);
+ _meteoFrame = frameStep;
+ }
+}
+
+int Scene202::subStep1(int randVal) {
+ if ((randVal <= 100) || _toStationFl)
+ return 42;
+
+ if ((randVal <= 200) || _toTeleportFl)
+ return 96;
+
+ if ((randVal <= 300) && (_lastRoute != 1))
+ return 77;
+
+ return 76;
+}
+
+int Scene202::subStep2(int randVal) {
+ if ((randVal <= 150) && (_stationCounter < 5))
+ return 51;
+
+ if ((randVal <= 300) || _toTeleportFl)
+ return 74;
+
+ if (randVal <= 400)
+ return 64;
+
+ return 44;
+}
+
+int Scene202::subStep3(int randVal) {
+ if ((randVal <= 100) || _toStationFl)
+ return 27;
+
+ if ((randVal <= 200) || _toTeleportFl)
+ return 159;
+
+ if ((randVal <= 300) && (_lastRoute != 2))
+ return 119;
+
+ return 110;
+}
+
+int Scene202::subStep4(int randVal) {
+ if ((randVal <= 100) || _toTeleportFl)
+ return 176;
+
+ if (randVal <= 200)
+ return 19;
+
+ return 166;
+}
+
+void Scene202::preActions() {
+ Player &player = _vm->_game->_player;
+
+ if (player._needToWalk)
+ _scene->_kernelMessages.reset();
+
+ if (_ladderTopFl && (_action.isAction(VERB_CLIMB_DOWN, NOUN_LADDER) || player._needToWalk)) {
+ if (_game._trigger == 0) {
+ _vm->_sound->command(29);
+ player._readyToWalk = false;
+ player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ } else if (_game._trigger == 1) {
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[8]);
+ _scene->_dynamicHotspots.remove(_ladderHotspotId);
+ player._visible = true;
+ player._readyToWalk = true;
+ player._stepEnabled = true;
+ _ladderTopFl = false;
+ }
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS) && (_action._activeAction._indirectObjectId > 0)) {
+ if (!player._readyToWalk || _ladderTopFl)
+ player._needToWalk = false;
+ else
+ player._needToWalk = true;
+
+ if (!_ladderTopFl)
+ player.walk(Common::Point(171, 122), FACING_NORTH);
+ }
+}
+
+void Scene202::actions() {
+ if (_action._lookFlag) {
+ _vm->_dialogs->show(20219);
+ return;
+ }
+
+ if (_action.isAction(VERB_CLIMB_DOWN, NOUN_LADDER)) {
+ _action._inProgress = false;
+ return;
+ } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) {
+ _scene->_nextSceneId = 203;
+ } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_NORTH)) {
+ if (_globals[kMeteorologistStatus] != METEOROLOGIST_GONE) {
+ if (_scene->_activeAnimation)
+ _globals[kMeteorologistStatus] = METEOROLOGIST_PRESENT;
+ else
+ _globals[kMeteorologistStatus] = METEOROLOGIST_ABSENT;
+ }
+ _scene->_nextSceneId = 201;
+ } else if (_action.isAction(VERB_TAKE, NOUN_BONE) && (_action._savedFields._mainObjectSource == 4)) {
+ switch (_game._trigger) {
+ case 0:
+ if (_game._objects.isInInventory(OBJ_BONES)) {
+ _vm->_dialogs->show(20221);
+ } else {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], false, 3, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[7]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+ case 1:
+ if (_game._player._playerPos == Common::Point(132, 97)) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals[kBone202Status] |= BONE_202_LEFT_GONE;
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _globals[kBone202Status] |= BONE_202_RIGHT_GONE;
+ }
+ break;
+ case 2:
+ if (_game._objects.isInInventory(OBJ_BONE)) {
+ _game._objects.removeFromInventory(OBJ_BONE, NOWHERE);
+ _game._objects.addToInventory(OBJ_BONES);
+ _vm->_dialogs->showItem(OBJ_BONES, 20218);
+ } else {
+ _game._objects.addToInventory(OBJ_BONE);
+ _vm->_dialogs->showItem(OBJ_BONE, 20218);
+ }
+ _scene->changeVariant(_globals[kBone202Status]);
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ break;
+ default:
+ break;
+ }
+
+ _action._inProgress = false;
+ } else if (_action.isAction(VERB_CLIMB_UP, NOUN_LADDER) && !_globals[kLadderBroken]) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_sound->command(29);
+ _meteoClock1 = _scene->_frameStartTime;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+
+ _ladderHotspotId = _scene->_dynamicHotspots.add(NOUN_LADDER, 78, -1, Common::Rect(241, 68, 241 + 12, 68 + 54));
+ _scene->_dynamicHotspots.setPosition(_ladderHotspotId, Common::Point(246, 124), FACING_NORTH);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+ case 1: {
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], _globals._sequenceIndexes[9]);
+ _ladderTopFl = true;
+ _game._player._stepEnabled = true;
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(248, 15), 0x1110, 32, 0, 60, _game.getQuote(97));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+ break;
+ default:
+ _action._inProgress = false;
+ return;
+ }
+ } else if ((_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_FIELD_TO_NORTH) || (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_STRANGE_DEVICE))) && (_globals[kSexOfRex] == SEX_MALE)) {
+ if (!_ladderTopFl) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible= false;
+ _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1);
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[10]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+ case 1:
+ _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123));
+ if (_scene->_activeAnimation) {
+ _waitingMeteoFl = true;
+ _globals[kMeteorologistWatch] = METEOROLOGIST_GROUND;
+ } else {
+ _scene->_sequences.addTimer(120, 2);
+ }
+ break;
+ case 2:
+ if (!_scene->_activeAnimation && !_meteorologistSpecial) {
+ _vm->_dialogs->show(20222);
+ }
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _globals._sequenceIndexes[10] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+ case 3:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[10]);
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ break;
+ default:
+ _action._inProgress = false;
+ return;
+ }
+ } else {
+ switch (_game._trigger) {
+ case 0:
+ _toTeleportFl = true;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+ case 1:
+ _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(247, 82));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1);
+ if (_scene->_activeAnimation) {
+ if (_scene->_activeAnimation->getCurrentFrame() > 200) {
+ _scene->_sequences.addTimer(120, 2);
+ } else {
+ _waitingMeteoFl = true;
+ _globals[kMeteorologistWatch] = METEOROLOGIST_GONE;
+ if ((_scene->_activeAnimation->getCurrentFrame() >= 44) && (_scene->_activeAnimation->getCurrentFrame() <= 75)) {
+ _scene->_kernelMessages.reset();
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(248, 15), 0x1110, 32, 0, 60, _game.getQuote(100));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, false);
+ } else {
+ _action._inProgress = false;
+ return;
+ }
+ }
+ } else {
+ _scene->_sequences.addTimer(120, 2);
+ }
+ break;
+ case 2:
+ if (!_scene->_activeAnimation)
+ _vm->_dialogs->show(20222);
+ _meteorologistSpecial = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _globals._sequenceIndexes[9] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+ case 3:
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1);
+ _game._player._stepEnabled = true;
+ break;
+ default:
+ _action._inProgress = false;
+ return;
+ }
+ }
+ } else if (_action.isAction(VERB_WALK_INSIDE, NOUN_HUT)) {
+ setRandomKernelMessage();
+ } else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) {
+ _vm->_dialogs->show(20202);
+ } else if (_action.isAction(VERB_LOOK, NOUN_FIRE_PIT)) {
+ _vm->_dialogs->show(20203);
+ } else if (_action.isAction(VERB_LOOK, NOUN_GRASS)) {
+ _vm->_dialogs->show(20204);
+ } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH)) {
+ if ((_globals[kMeteorologistStatus] == METEOROLOGIST_ABSENT) || (_globals[kMeteorologistStatus] == METEOROLOGIST_GONE))
+ _vm->_dialogs->show(20205);
+ else if (_globals[kMeteorologistStatus] == METEOROLOGIST_PRESENT)
+ _vm->_dialogs->show(20220);
+ } else if (_action.isAction(VERB_LOOK, NOUN_WATCH_TOWER)) {
+ _vm->_dialogs->show(20206);
+ } else if (_action.isAction(VERB_LOOK, NOUN_TALL_GRASS)) {
+ _vm->_dialogs->show(20207);
+ } else if (_action.isAction(VERB_LOOK, NOUN_TREES)) {
+ _vm->_dialogs->show(20208);
+ } else if (_action.isAction(VERB_LOOK, NOUN_TREE)) {
+ _vm->_dialogs->show(20209);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) {
+ _vm->_dialogs->show(20210);
+ } else if (_action.isAction(VERB_LOOK, NOUN_HUT)) {
+ if ((_game._player._playerPos == Common::Point(77, 105)) && (_game._player._facing == FACING_NORTH))
+ _vm->_dialogs->show(20212);
+ else
+ _vm->_dialogs->show(20211);
+ } else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) {
+ _vm->_dialogs->show(20213);
+ } else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_IN_DISTANCE)) {
+ _vm->_dialogs->show(20214);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SKULL)) {
+ _vm->_dialogs->show(20215);
+ } else if (_action.isAction(VERB_TAKE, NOUN_SKULL)) {
+ _vm->_dialogs->show(20216);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BONES) && _action._commandSource == 4) {
+ _vm->_dialogs->show(20217);
+ } else {
+ return;
+ }
+
+ _action._inProgress = false;
+}
+
+/*****************************************************************************/
+
+Scene203::Scene203(MADSEngine *vm) : Scene2xx(vm) {
+ _rhotundaEat2Fl = false;
+ _rhotundaEatFl = false;
+}
+
+void Scene203::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsByte(_rhotundaEat2Fl);
+ s.syncAsByte(_rhotundaEatFl);
+}
+
+void Scene203::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(477);
+}
+
+void Scene203::enter() {
+ if (_scene->_priorSceneId == 202) {
+ _game._player._playerPos = Common::Point(187, 99);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId == 209) {
+ _game._player._playerPos = Common::Point(308, 117);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(155, 152);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ _rhotundaEatFl = false;
+ _rhotundaEat2Fl = false;
+
+ if ((_globals[kRhotundaStatus] == 0) && (!_scene->_roomChanged)) {
+ _rhotundaEatFl = true;
+ _game._player.walk(Common::Point(158, 135), FACING_SOUTH);
+ int idx = _scene->_dynamicHotspots.add(131, 396, 0, Common::Rect(0, 0, 320, 156));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(155, 152), FACING_SOUTH);
+ _scene->_dynamicHotspots.setCursor(idx, CURSOR_GO_DOWN);
+ }
+
+ if (!_rhotundaEatFl) {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('b', -1));
+ if (_vm->getRandomNumber(1, 3) == 2) {
+ _globals._spriteIndexes[15] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 9, 1, 0, 0);
+ int idx = _scene->_dynamicHotspots.add(477, 209, _globals._spriteIndexes[15], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE);
+ _vm->_sound->command(14);
+ }
+ }
+
+ _game.loadQuoteSet(0x67, 0x68, 0x69, 0x6A, 0x5A, 0);
+
+ if (_rhotundaEatFl) {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(_vm->getRandomNumber(103, 106)));
+ }
+
+ sceneEntrySound();
+}
+
+void Scene203::step() {
+ if (!_rhotundaEatFl)
+ return;
+
+ if ((_game._trigger == 0) && _rhotundaEat2Fl)
+ return;
+
+ if ((_game._player._playerPos != Common::Point(158, 136)) || (_game._player._facing != FACING_SOUTH))
+ return;
+
+ _rhotundaEat2Fl = true;
+
+ if (_game._trigger == 0) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _vm->_palette->lock();
+ _scene->_kernelMessages.reset();
+ _scene->resetScene();
+ _vm->_events->setCursor2(CURSOR_WAIT);
+ _scene->loadAnimation(Resources::formatName(203, 'a', -1, EXT_AA, ""), 81);
+ } else if (_game._trigger == 81) {
+ _scene->_nextSceneId = 208;
+ _scene->_reloadSceneFlag = true;
+ }
+}
+
+void Scene203::preActions() {
+ if (_rhotundaEatFl && !_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) {
+ _game._player.walk(Common::Point(158, 136), FACING_SOUTH);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALKTO, NOUN_OPEN_AREA_TO_EAST))
+ _game._player._walkOffScreenSceneId = 209;
+}
+
+void Scene203::actions() {
+ if (_action._savedFields._lookFlag) {
+ _vm->_dialogs->show(20307);
+ } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) {
+ _scene->_nextSceneId = 208;
+ } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_NORTH)) {
+ _scene->_nextSceneId = 202;
+ } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) {
+ _vm->_dialogs->show(20301);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) {
+ _vm->_dialogs->show(20302);
+ } else if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) {
+ _vm->_dialogs->show(20303);
+ } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH)) {
+ _vm->_dialogs->show(20304);
+ } else if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) {
+ _vm->_dialogs->show(20305);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BOULDERS)) {
+ _vm->_dialogs->show(20305);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*****************************************************************************/
+
+void Scene205::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_CHICKEN);
+ _scene->addActiveVocab(NOUN_PIRANHA);
+}
+
+Scene205::Scene205(MADSEngine *vm) : Scene2xx(vm) {
+ _lastFishTime = 0;
+ _chickenTime = 0;
+ _beingKicked = false;
+ _kernelMessage = -1;
+}
+
+void Scene205::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsUint32LE(_lastFishTime);
+ s.syncAsUint32LE(_chickenTime);
+ s.syncAsByte(_beingKicked);
+ s.syncAsSint16LE(_kernelMessage);
+}
+
+void Scene205::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', -1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('p', -1));
+
+ if (_globals[kSexOfRex] == SEX_MALE)
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 1));
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 0, 0, 3);
+ int idx = _scene->_dynamicHotspots.add(73, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(162, 120), FACING_NORTHEAST);
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0);
+ idx = _scene->_dynamicHotspots.add(73, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(162, 120), FACING_NORTHEAST);
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 0, 0, 0);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 11);
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ _lastFishTime = _scene->_frameStartTime;
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0);
+ idx = _scene->_dynamicHotspots.add(269, 13, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(49, 86), FACING_NORTH);
+ }
+
+ if (_game._objects[12]._roomNumber == 205) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 7, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11);
+ } else {
+ _scene->_hotspots.activate(450, false);
+ }
+
+ _beingKicked = false;
+ _game.loadQuoteSet(0x6B, 0x70, 0x71, 0x72, 0x5A, 0x74, 0x75, 0x76, 0x77, 0x78, 0x73, 0x79, 0x7A, 0x7B, 0x7C,
+ 0x7D, 0x7E, 0x7F, 0x80, 0xAC, 0xAD, 0xAE, 0x6C, 0x6D, 0x6E, 0x6F, 0x2, 0);
+ _dialog1.setup(0x2A, 0x5A, 0x78, 0x74, 0x75, 0x76, 0x77, 0);
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _dialog1.set(0x5A, 0x74, 0x75, 0x77, 0);
+
+ _vm->_palette->setEntry(250, 63, 50, 20);
+ _vm->_palette->setEntry(251, 50, 40, 15);
+ _vm->_palette->setEntry(252, 63, 63, 40);
+ _vm->_palette->setEntry(253, 50, 50, 30);
+
+ _chickenTime = _vm->_game->_scene._frameStartTime;
+
+ if (_globals[kSexOfRex] == SEX_FEMALE)
+ _scene->_kernelMessages.initRandomMessages(3,
+ Common::Rect(195, 99, 264, 134), 13, 2, 0xFDFC, 60,
+ 108, 108, 109, 109, 110, 110, 111, 108, 0);
+
+ if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(99, 152);
+
+ if (_globals[kSexOfRex] != SEX_MALE) {
+ _scene->loadAnimation(formAnimName('a', -1));
+ _scene->_activeAnimation->_resetFlag = true;
+ } else {
+ _beingKicked = true;
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0);
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 6, 73);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 11, 74);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ }
+ sceneEntrySound();
+}
+
+void Scene205::step() {
+ if (_globals[kSexOfRex] == SEX_FEMALE) {
+ _scene->_kernelMessages.randomServer();
+
+ if (_vm->_game->_scene._frameStartTime >= _chickenTime) {
+ int chanceMinor = _scene->_kernelMessages.checkRandom() + 1;
+ if (_scene->_kernelMessages.generateRandom(100, chanceMinor))
+ _vm->_sound->command(28);
+
+ _chickenTime = _vm->_game->_scene._frameStartTime + 2;
+ }
+ }
+
+ if (_vm->_game->_scene._frameStartTime - _lastFishTime > 1300) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(
+ _globals._spriteIndexes[6], false, 5, 1, 0, 0);
+ int idx = _scene->_dynamicHotspots.add(269, 13, _globals._sequenceIndexes[6],
+ Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(49, 86), FACING_NORTH);
+ _lastFishTime = _vm->_game->_scene._frameStartTime;
+ }
+
+ if (_game._trigger == 73)
+ _scene->_kernelMessages.add(Common::Point(160, 68), 0xFBFA, 32, 0, 60, _game.getQuote(112));
+
+ if (_game._trigger == 74) {
+ _vm->_sound->command(26);
+ _scene->_kernelMessages.add(Common::Point(106, 90), 0x1110, 32, 0, 60, _game.getQuote(113));
+ }
+
+ if (_game._trigger == 71) {
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 2);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(160, 68), 0xFBFA, 32, 72, 180, _game.getQuote(114));
+ }
+
+ if (_game._trigger == 72)
+ _scene->_nextSceneId = 211;
+}
+
+void Scene205::handleWomanSpeech(int quote) {
+ _kernelMessage = _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 0, 0, 9999999, _game.getQuote(quote));
+}
+
+void Scene205::actions() {
+ if (_game._screenObjects._inputMode == kInputConversation) {
+ if (_kernelMessage >= 0)
+ _scene->_kernelMessages.remove(_kernelMessage);
+ _kernelMessage = -1;
+
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 1, 120, _game.getQuote(_action._activeAction._verbId));
+ } else {
+ if ((_game._trigger > 1) || (_action._activeAction._verbId != 0x76))
+ _game._player._stepEnabled = true;
+
+ switch (_action._activeAction._verbId) {
+ case 0x5A:
+ handleWomanSpeech(0x7A);
+ _dialog1.write(0x78, true);
+ _dialog1.write(0x5A, false);
+ break;
+
+ case 0x74:
+ handleWomanSpeech(0x7C);
+ _dialog1.write(0x74, false);
+ _dialog1.write(0x76, true);
+ break;
+
+ case 0x75:
+ case 0x78:
+ handleWomanSpeech(0x7B);
+ _dialog1.write(_action._activeAction._verbId, false);
+ _vm->_dialogs->show(20501);
+ break;
+
+ case 0x76:
+ if (_game._trigger == 1) {
+ handleWomanSpeech(0x7D);
+ _scene->_sequences.addTimer(120, 2);
+ } else if (_game._trigger == 2) {
+ handleWomanSpeech(0x7E);
+ _dialog1.write(0x76, false);
+ _globals[kChickenPermitted] = true;
+ }
+ break;
+
+ case 0x77:
+ _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 0, 0, 120, _game.getQuote(0x7F));
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ break;
+
+ default:
+ break;
+ }
+
+ if (_action._activeAction._verbId != 0x77)
+ _dialog1.start();
+ }
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(20502);
+ else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_OPPOSITE_BANK))
+ _vm->_dialogs->show(20518);
+ else if (_action.isAction(VERB_TALKTO, NOUN_NATIVE_WOMAN)) {
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 1, 120, _game.getQuote(0x73));
+ } else if (_game._trigger == 1) {
+ _game._player._stepEnabled = true;
+ handleWomanSpeech (0x79);
+ _dialog1.write(0x5A, true);
+ _dialog1.write(0x75, true);
+ _dialog1.start();
+ }
+ } else if (_action.isAction(VERB_GIVE, NOUN_NATIVE_WOMAN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) {
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ int rndVal = _vm->getRandomNumber(0xAC, 0xAE);
+ _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 32, 1, 120, _game.getQuote(rndVal));
+ } else if (_game._trigger == 1)
+ _game._player._stepEnabled = true;
+ } else if (_action.isAction(VERB_WALKTO, NOUN_OPPOSITE_BANK)) {
+ if (_game._trigger == 0) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _vm->_palette->lock();
+ _scene->_kernelMessages.reset();
+ _game._player.removePlayerSprites();
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _vm->_palette->refreshSceneColors();
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], -1);
+ _vm->_sound->command(27);
+ } else if (_game._trigger == 1) {
+ if (_scene->_activeAnimation != nullptr)
+ _scene->_activeAnimation->resetSpriteSetsCount();
+
+ _vm->_dialogs->show(20516);
+ _scene->_reloadSceneFlag = true;
+ }
+ } else {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_SOUTH))
+ _scene->_nextSceneId = 210;
+
+ if (_action.isAction(VERB_WALKTO, NOUN_FIRE_PIT) || _action.isAction(VERB_WALKTO, NOUN_CHICKEN_ON_SPIT)) {
+ if (_game._objects.isInRoom(OBJ_CHICKEN)) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x6B));
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN_ON_SPIT) && _globals[kChickenPermitted] && _game._objects.isInRoom(OBJ_CHICKEN)) {
+ _game._objects.addToInventory(OBJ_CHICKEN);
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _scene->_hotspots.activate(NOUN_CHICKEN_ON_SPIT, false);
+ _vm->_dialogs->showItem(OBJ_CHICKEN, 812);
+ } else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN_ON_SPIT) && (!_globals[kChickenPermitted]))
+ _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 32, 0, 120, _game.getQuote(0x80));
+ else if (_action.isAction(VERB_LOOK, NOUN_NATIVE_WOMAN))
+ _vm->_dialogs->show(20503);
+ else if (_action.isAction(VERB_LOOK, NOUN_HUT))
+ _vm->_dialogs->show(20504);
+ else if (_action.isAction(VERB_LOOK, NOUN_CHICKEN) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(20505);
+ else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(20506);
+ else if (_action.isAction(VERB_LOOK, NOUN_CHICKEN_ON_SPIT))
+ _vm->_dialogs->show(20507);
+ else if (_action.isAction(VERB_LOOK, NOUN_FIRE_PIT))
+ _vm->_dialogs->show(20508);
+ else if (_action.isAction(VERB_TAKE, NOUN_FIRE_PIT))
+ _vm->_dialogs->show(20509);
+ else if (_action.isAction(VERB_LOOK, NOUN_STREAM))
+ _vm->_dialogs->show(20510);
+ else if (_action.isAction(VERB_LOOK, NOUN_OPPOSITE_BANK))
+ _vm->_dialogs->show(20511);
+ else if (_game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))
+ && ( _action.isAction(VERB_GIVE, NOUN_STREAM) || _action.isAction(VERB_THROW, NOUN_STREAM)
+ || _action.isAction(VERB_GIVE, NOUN_PIRANHA) || _action.isAction(VERB_THROW, NOUN_PIRANHA)))
+ _vm->_dialogs->show(20512);
+ else if (_action.isAction(VERB_LOOK, NOUN_PIRANHA))
+ _vm->_dialogs->show(20513);
+ else if (_action.isAction(VERB_LOOK, NOUN_TWINKIFRUIT_BUSH))
+ _vm->_dialogs->show(20514);
+ else if (_action.isAction(VERB_TAKE, NOUN_TWINKIFRUIT_BUSH))
+ _vm->_dialogs->show(20515);
+ else if (_action.isAction(VERB_TAKE, NOUN_NATIVE_WOMAN))
+ _vm->_dialogs->show(20517);
+ else
+ return;
+ }
+
+ _action._inProgress = false;
+}
+
+/*****************************************************************************/
+
+Scene207::Scene207(MADSEngine *vm) : Scene2xx(vm) {
+ _vultureFl = false;
+ _spiderFl = false;
+ _eyeFl = false;
+ _spiderHotspotId = -1;
+ _vultureHotspotId = -1;
+ _spiderTime = 0;
+ _vultureTime = 0;
+}
+
+void Scene207::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsByte(_vultureFl);
+ s.syncAsByte(_spiderFl);
+ s.syncAsByte(_eyeFl);
+
+ s.syncAsSint32LE(_spiderHotspotId);
+ s.syncAsSint32LE(_vultureHotspotId);
+ s.syncAsSint32LE(_spiderTime);
+ s.syncAsSint32LE(_vultureTime);
+}
+
+void Scene207::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_VULTURE);
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_SPIDER);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene207::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('h', 1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('e', 0));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('e', 1));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('g', 1));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('g', 0));
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 7, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 7);
+
+ int var2;
+ if (!_game._visitedScenes._sceneRevisited) {
+ var2 = 1;
+ } else {
+ var2 = _vm->getRandomNumber(4) + 1;
+ }
+
+ if (var2 > 2)
+ _vultureFl = false;
+ else
+ _vultureFl = true;
+
+ _spiderFl = (var2 & 1);
+
+ if (_vultureFl) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 30, 0, 0, 400);
+ _vultureTime = _game._player._priorTimer;
+ _vultureHotspotId = _scene->_dynamicHotspots.add(389, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_vultureHotspotId, Common::Point(254, 94), FACING_WEST);
+ }
+
+ if (_spiderFl) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, -1);
+ _spiderTime = _game._player._priorTimer;
+ _spiderHotspotId = _scene->_dynamicHotspots.add(333, 13, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_spiderHotspotId, Common::Point(59, 132), FACING_SOUTH);
+ }
+
+ _eyeFl = false;
+ if (_scene->_priorSceneId == 211) {
+ _game._player._playerPos = Common::Point(13, 105);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId == 214) {
+ _game._player._playerPos = Common::Point(164, 117);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(305, 131);
+ }
+
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 22);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+}
+
+void Scene207::moveVulture() {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _vm->_sound->command(43);
+ _vultureFl = false;
+ _vultureTime = _game._player._priorTimer;
+ _scene->_dynamicHotspots.remove(_vultureHotspotId);
+}
+
+void Scene207::moveSpider() {
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0);
+ _spiderFl = false;
+ _spiderTime = _game._player._priorTimer;
+ _scene->_dynamicHotspots.remove(_spiderHotspotId);
+}
+
+void Scene207::step() {
+ if (!_vultureFl)
+ moveVulture();
+
+ if (_spiderFl)
+ moveSpider();
+
+ if (_game._trigger == 70) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 23, 34);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6);
+ }
+
+ if (_game._trigger == 71)
+ _eyeFl = false;
+
+ if (_eyeFl)
+ return;
+
+ if ((_game._player._playerPos.x >= 124) && (_game._player._playerPos.x <= 201)) {
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _eyeFl = true;
+ }
+}
+
+void Scene207::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST))
+ _game._player._walkOffScreenSceneId = 211;
+
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_OPEN_FIELD_TO_EAST))
+ _game._player._walkOffScreenSceneId = 208;
+
+ if (_action.isAction(VERB_WALKTO) || _action.isAction(VERB_LOOK)) {
+ if (_action.isObject(NOUN_VULTURE)) {
+ _vultureTime = -9999;
+ } else if (_action.isObject(NOUN_SPIDER)) {
+ _spiderTime = -9999;
+ }
+ }
+}
+
+void Scene207::actions() {
+ if (_action._savedFields._lookFlag)
+ _vm->_dialogs->show(20711);
+ else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY))
+ _scene->_nextSceneId = 214;
+ else {
+ if ((_game._player._playerPos.x > 150) && (_game._player._playerPos.x < 189) &&
+ (_game._player._playerPos.y > 111) && (_game._player._playerPos.y < 130)) {
+ if ((_game._player._playerPos.x <= 162) || (_game._player._playerPos.x >= 181) ||
+ (_game._player._playerPos.y <= 115) || (_game._player._playerPos.y >= 126)) {
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 2, 0, 0);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 2, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6);
+ }
+ } else if (_eyeFl) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[7]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _eyeFl = false;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_DENSE_FOREST))
+ _vm->_dialogs->show(20701);
+ else if (_action.isAction(VERB_LOOK, NOUN_HEDGE))
+ _vm->_dialogs->show(20702);
+ else if (_action.isAction(VERB_LOOK, NOUN_SKULL_AND_CROSSBONES))
+ _vm->_dialogs->show(20703);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAULDRON))
+ _vm->_dialogs->show(20704);
+ else if (_action.isAction(VERB_LOOK, NOUN_WITCHDOCTOR_HUT))
+ _vm->_dialogs->show(20705);
+ else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_WEST))
+ _vm->_dialogs->show(20706);
+ else if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINS))
+ _vm->_dialogs->show(20707);
+ else if (_action.isAction(VERB_LOOK, NOUN_ALOE_PLANT))
+ _vm->_dialogs->show(20708);
+ else if (_action.isAction(VERB_LOOK, NOUN_LAWN))
+ _vm->_dialogs->show(20709);
+ else if (_action.isAction(VERB_LOOK, NOUN_VULTURE))
+ _vm->_dialogs->show(20710);
+ else if (_action.isAction(VERB_TAKE, NOUN_SKULL_AND_CROSSBONES))
+ _vm->_dialogs->show(20712);
+ else if (_action.isAction(VERB_TAKE, NOUN_ALOE_PLANT))
+ _vm->_dialogs->show(20713);
+ else if (_action.isAction(VERB_LOOK, NOUN_SPIDER))
+ _vm->_dialogs->show(20714);
+ else if (_action.isAction(VERB_TAKE, NOUN_SPIDER))
+ _vm->_dialogs->show(20715);
+ else
+ return;
+ }
+
+ _action._inProgress = false;
+}
+
+/*****************************************************************************/
+
+Scene208::Scene208(MADSEngine *vm) : Scene2xx(vm) {
+ _rhotundaTurnFl = false;
+ _boundingFl = false;
+ _rhotundaTime = 0;
+}
+
+void Scene208::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsByte(_rhotundaTurnFl);
+ s.syncAsByte(_boundingFl);
+ s.syncAsSint32LE(_rhotundaTime);
+}
+
+void Scene208::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_HUGE_LEGS);
+ _scene->addActiveVocab(NOUN_LEAF_COVERED_PIT);
+ _scene->addActiveVocab(NOUN_PILE_OF_LEAVES);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene208::updateTrap() {
+ if (_globals[kRhotundaStatus] == 1) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 24);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ int idx = _scene->_dynamicHotspots.add(NOUN_HUGE_LEGS, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(100, 146), FACING_NORTH);
+ _scene->_hotspots.activate(414, false);
+ return;
+ }
+
+ switch (_globals[kLeavesStatus]) {
+ case 0: {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 15);
+ int idx = _scene->_dynamicHotspots.add(NOUN_PILE_OF_LEAVES, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(60, 152), FACING_NORTH);
+ }
+ break;
+ case 2: {
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_hotspots.activate(NOUN_DEEP_PIT, false);
+ int idx = _scene->_dynamicHotspots.add(NOUN_LEAF_COVERED_PIT, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(100, 146), FACING_NORTH);
+ _scene->_dynamicHotspots[idx]._articleNumber = PREP_ON;
+ }
+ break;
+ }
+}
+
+void Scene208::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMBD_8");
+
+ updateTrap();
+
+ _rhotundaTurnFl = false;
+ _boundingFl = false;
+ _scene->_kernelMessages._talkFont = _vm->_font->getFont(FONT_INTERFACE);
+ _scene->_textSpacing = 0;
+
+ if (_scene->_priorSceneId == 207) {
+ _game._player._playerPos = Common::Point(8, 122);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId == 203) {
+ _game._player._playerPos = Common::Point(142, 108);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId == 209) {
+ _game._player._playerPos = Common::Point(307, 123);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(162, 149);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ _game.loadQuoteSet(0x81, 0x46, 0);
+
+ if ((_scene->_priorSceneId == 207) && (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS)) {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(129));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+
+ _vm->_palette->setEntry(16, 0, 0, 63);
+ _vm->_palette->setEntry(17, 0, 0, 45);
+ sceneEntrySound();
+}
+
+void Scene208::step() {
+ if (_boundingFl && (_rhotundaTime <= _scene->_activeAnimation->getCurrentFrame())) {
+ _rhotundaTime = _scene->_activeAnimation->getCurrentFrame();
+
+ if (_rhotundaTime == 125)
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ }
+
+ if (!_rhotundaTurnFl)
+ return;
+
+ if ((_game._player._playerPos != Common::Point(20, 148)) || (_game._player._facing != FACING_EAST))
+ return;
+
+ if ((_game._trigger == 0) && _boundingFl)
+ return;
+
+ _boundingFl = true;
+
+ switch (_game._trigger) {
+ case 0:
+ _scene->loadAnimation(formAnimName('A', -1), 81);
+ _rhotundaTime = 0;
+ break;
+ case 81:
+ _scene->_sequences.remove(_globals._spriteIndexes[15]);
+ _globals[kRhotundaStatus] = 1;
+ updateTrap();
+ _scene->_sequences.addTimer(90, 82);
+ break;
+ case 82:
+ _game._player._stepEnabled = true;
+ break;
+ }
+}
+
+void Scene208::preActions() {
+ Player &player = _vm->_game->_player;
+
+ if (_action.isAction(VERB_LOOK) && player._readyToWalk)
+ player._needToWalk = true;
+
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_GRASSLAND_TO_EAST))
+ player._walkOffScreenSceneId = 209;
+
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_OPEN_AREA_TO_WEST))
+ player._walkOffScreenSceneId = 207;
+}
+
+void Scene208::subAction(int mode) {
+
+ switch (_game._trigger) {
+ case 0: {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+
+ int abortVal;
+ if ((mode == 1) || (mode == 2))
+ abortVal = 1;
+ else
+ abortVal = 2;
+
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, abortVal);
+ }
+ break;
+ case 1: {
+ int oldVal = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 3, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 3, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldVal);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ _vm->_sound->command(20);
+ }
+ break;
+
+ case 2: {
+ switch (mode) {
+ case 1:
+ _game._objects.addToInventory(OBJ_BIG_LEAVES);
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals[kLeavesStatus] = 1;
+ break;
+
+ case 2:
+ _game._objects.setRoom(OBJ_BIG_LEAVES, 1);
+ _globals[kLeavesStatus] = 2;
+ updateTrap();
+ break;
+
+ case 3:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _game._objects.removeFromInventory(OBJ_TWINKIFRUIT, 1);
+ _vm->_sound->command(34);
+ break;
+
+ case 4:
+ _game._objects.removeFromInventory(OBJ_BURGER, 1);
+ _vm->_sound->command(33);
+ break;
+
+ case 5:
+ _game._objects.removeFromInventory(OBJ_DEAD_FISH, 1);
+ _vm->_sound->command(33);
+ break;
+
+ default:
+ break;
+ }
+
+ int oldVal = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldVal);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ }
+ break;
+
+ case 3:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene208::actions() {
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_LOWLANDS_TO_NORTH)) {
+ if (_globals[kRhotundaStatus])
+ _scene->_nextSceneId = 203;
+ else if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, _game.getQuote(70));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ } else if (_game._trigger == 1)
+ _scene->_nextSceneId = 203;
+ } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH))
+ _scene->_nextSceneId = 212;
+ else if (_action.isAction(VERB_TAKE, NOUN_PILE_OF_LEAVES) && (!_globals[kLeavesStatus] || _game._trigger)) {
+ subAction(1);
+ if (_game._player._stepEnabled)
+ _vm->_dialogs->showItem(OBJ_BIG_LEAVES, 0x326, 0);
+ } else if (_action.isAction(VERB_PUT, NOUN_BIG_LEAVES, NOUN_DEEP_PIT) && (_globals[kLeavesStatus] == 1 || _game._trigger))
+ subAction(2);
+ else if (_action.isAction(VERB_PUT, NOUN_TWINKIFRUIT, NOUN_LEAF_COVERED_PIT)) {
+ subAction(3);
+ if (_game._player._stepEnabled) {
+ _game._player._stepEnabled = false;
+ _rhotundaTurnFl = true;
+ _game._player.walk(Common::Point(20, 148), FACING_EAST);
+ }
+ } else if (_action.isAction(VERB_PUT, NOUN_BURGER, NOUN_LEAF_COVERED_PIT)) {
+ subAction(4);
+ if (_game._player._stepEnabled)
+ _vm->_dialogs->show(20812);
+ } else if (_action.isAction(VERB_PUT, NOUN_DEAD_FISH, NOUN_LEAF_COVERED_PIT)) {
+ subAction(5);
+ if (_game._player._stepEnabled)
+ _vm->_dialogs->show(20812);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CUMULOUS_CLOUD))
+ _vm->_dialogs->show(20801);
+ else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_WEST))
+ _vm->_dialogs->show(20802);
+ else if (_action.isAction(VERB_LOOK, NOUN_THORNY_BUSH))
+ _vm->_dialogs->show(20803);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCKS))
+ _vm->_dialogs->show(20804);
+ else if (_action.isAction(VERB_LOOK, NOUN_SMALL_CACTUS))
+ _vm->_dialogs->show(20805);
+ else if (_action.isAction(VERB_TAKE, NOUN_SMALL_CACTUS))
+ _vm->_dialogs->show(20806);
+ else if (_action.isAction(VERB_LOOK, NOUN_GRASSLAND_TO_EAST))
+ _vm->_dialogs->show(20807);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEEP_PIT))
+ _vm->_dialogs->show(20808);
+ else if (_action.isAction(VERB_LOOK, NOUN_PILE_OF_LEAVES))
+ _vm->_dialogs->show(20809);
+ else if (_action.isAction(VERB_LOOK, NOUN_LEAF_COVERED_PIT)) {
+ if (_game._difficulty == DIFFICULTY_EASY)
+ _vm->_dialogs->show(20810);
+ else
+ _vm->_dialogs->show(20811);
+ } else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES))
+ _vm->_dialogs->show(20813);
+ else if (_action.isAction(VERB_TAKE, NOUN_LEAF_COVERED_PIT))
+ _vm->_dialogs->show(20814);
+ else if (_action.isAction(VERB_LOOK, NOUN_HUGE_LEGS))
+ _vm->_dialogs->show(20815);
+ else if (_action.isAction(VERB_TAKE, NOUN_HUGE_LEGS) || _action.isAction(VERB_PULL, NOUN_HUGE_LEGS))
+ _vm->_dialogs->show(20816);
+ else if (_action._savedFields._lookFlag && (_globals[kRhotundaStatus] == 1))
+ _vm->_dialogs->show(20819);
+ else if (_action._savedFields._lookFlag && (_globals[kLeavesStatus] == 2))
+ _vm->_dialogs->show(20818);
+ else if (_action._savedFields._lookFlag)
+ _vm->_dialogs->show(20817);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*****************************************************************************/
+
+Scene209::Scene209(MADSEngine *vm) : Scene2xx(vm) {
+ _dodgeFl = false;
+ _forceDodgeFl = false;
+ _pitchFl = false;
+ _fallFl = false;
+ _forceFallFl = false;
+ _playingAnimFl = false;
+ _shouldFallFl = false;
+ _shouldDodgeFl = false;
+ _monkeyPosition = 0;
+ _counter = 0;
+ _pauseMode = 0;
+ _binocularsDroppedFl = false;
+ _startShootingInTimerFl = false;
+ _dialogAbortVal = 0;
+ _playingDialogFl = false;
+ _shootMissedLastFl = false;
+ _removeMonkeyFl = false;
+ _shootReadyFl = false;
+ _pauseCounterThreshold = 0;
+ _pauseCounter = 0;
+}
+
+void Scene209::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsByte(_dodgeFl);
+ s.syncAsByte(_forceDodgeFl);
+ s.syncAsByte(_shouldDodgeFl);
+ s.syncAsByte(_pitchFl);
+ s.syncAsByte(_fallFl);
+ s.syncAsByte(_forceFallFl);
+ s.syncAsByte(_shouldFallFl);
+ s.syncAsByte(_playingAnimFl);
+ s.syncAsByte(_playingDialogFl);
+
+ s.syncAsSint32LE(_pauseMode);
+ s.syncAsSint32LE(_pauseCounterThreshold);
+ s.syncAsSint32LE(_pauseCounter);
+
+ s.syncAsByte(_removeMonkeyFl);
+
+ s.syncAsSint32LE(_monkeyPosition);
+
+ s.syncAsByte(_shootReadyFl);
+ s.syncAsByte(_startShootingInTimerFl);
+ s.syncAsByte(_shootMissedLastFl);
+ s.syncAsByte(_binocularsDroppedFl);
+
+ s.syncAsSint32LE(_dialogAbortVal);
+ s.syncAsSint32LE(_counter);
+}
+
+void Scene209::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_PLANT_STALK);
+}
+
+void Scene209::handlePause() {
+ switch (_game._trigger) {
+ case 124:
+ if (++_pauseCounter <= _pauseCounterThreshold)
+ _scene->_sequences.addTimer(60, 124);
+ else
+ _pauseMode = 0;
+ break;
+ }
+}
+
+void Scene209::initPauseCounterThreshold() {
+ switch (_game._trigger) {
+ case 226:
+ _scene->_sequences.addTimer(1, 124);
+ _pauseCounterThreshold = _vm->getRandomNumber(7,12);
+ _pauseMode = 2;
+ _pauseCounter = 0;
+ break;
+ }
+}
+
+void Scene209::handlePeek() {
+ switch (_game._trigger) {
+ case 133:
+ _vm->_sound->command(18);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 134);
+ break;
+
+ case 134: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(60, 135);
+ }
+ break;
+
+ case 135:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7);
+ _scene->_sequences.addTimer(10, 136);
+ break;
+
+ case 136:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.addTimer(50, 137);
+ break;
+
+ case 137:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 138);
+ break;
+
+ case 138:
+ _pauseMode = 1;
+ _scene->_hotspots.activate(227, false);
+ _playingAnimFl = false;
+ break;
+ }
+}
+
+void Scene209::handleVerticalMove() {
+ switch (_game._trigger) {
+ case 140:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 8, 0, 1);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 141);
+ break;
+
+ case 141: {
+ _vm->_sound->command(18);
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(60, 142);
+ }
+ break;
+
+ case 142:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 143);
+ break;
+
+ case 143:
+ _pauseMode = 1;
+ _playingAnimFl = false;
+ _scene->_hotspots.activate(227, false);
+ break;
+ }
+}
+
+void Scene209::handleLookStay() {
+ switch (_game._trigger) {
+ case 145:
+ _vm->_sound->command(18);
+ _monkeyPosition = 2;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 146);
+ break;
+
+ case 146: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(15, 147);
+ }
+ break;
+
+ case 147:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7);
+ _scene->_sequences.addTimer(8, 148);
+ break;
+
+ case 148:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+
+ if (!_dodgeFl) {
+ _scene->_sequences.addTimer(90, 149);
+ } else {
+ _scene->_sequences.addTimer(1, 149);
+ _shouldDodgeFl = true;
+ }
+ break;
+
+ case 149:
+ _playingAnimFl = false;
+ break;
+ }
+}
+
+void Scene209::handleLookRight() {
+ switch (_game._trigger) {
+ case 151:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 14);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 152);
+ break;
+
+ case 152: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(60, 153);
+ }
+ break;
+
+ case 153:
+ _playingAnimFl = false;
+ if (_dodgeFl)
+ _shouldDodgeFl = true;
+ break;
+ }
+}
+
+void Scene209::handleBlink() {
+ switch (_game._trigger) {
+ case 155:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.addTimer(50, 156);
+ break;
+
+ case 156:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7);
+ _scene->_sequences.addTimer(10, 157);
+ break;
+
+ case 157:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.addTimer(50, 158);
+ break;
+
+ case 158:
+ _playingAnimFl = false;
+ if (_dodgeFl)
+ _shouldDodgeFl = true;
+ break;
+ }
+}
+
+void Scene209::handleGetBinoculars() {
+ switch (_game._trigger) {
+ case 161:
+ _vm->_sound->command(18);
+ _monkeyPosition = 3;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 24);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 20, 165);
+ if (!_fallFl && !_dodgeFl) {
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 162);
+ } else {
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 163);
+ }
+ break;
+
+ case 162: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 6, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 163);
+ }
+ break;
+
+ case 163: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(8, 164);
+ }
+ break;
+
+ case 164:
+ _playingAnimFl = false;
+ if (_fallFl)
+ _shouldFallFl = true;
+ break;
+
+ case 165:
+ _vm->_sound->command(18);
+ break;
+ }
+}
+
+void Scene209::handleBinocularBlink() {
+ switch (_game._trigger) {
+ case 167: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 168);
+ }
+ break;
+
+ case 168: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(30, 169);
+ }
+ break;
+
+ case 169:
+ _playingAnimFl = false;
+ if (_fallFl)
+ _shouldFallFl = true;
+ break;
+ }
+}
+
+void Scene209::handleBinocularScan() {
+ switch (_game._trigger) {
+ case 171: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 43, 45);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 172);
+ }
+ break;
+
+ case 172: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ int randAction = _vm->getRandomNumber(1,2);
+ switch (randAction) {
+ case 1:
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0);
+ break;
+ case 2:
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 4, 0, 0);
+ break;
+ }
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 173);
+ }
+ break;
+
+ case 173: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 30);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 174);
+ }
+ break;
+
+ case 174: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(60, 175);
+ }
+ break;
+
+ case 175:
+ _playingAnimFl = false;
+ if (_fallFl)
+ _shouldFallFl = true;
+ break;
+ }
+}
+
+void Scene209::handleJumpInTree() {
+ switch (_game._trigger) {
+ case 178: {
+ int oldIdx = 0;
+ _monkeyPosition = 1;
+ if (_removeMonkeyFl)
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ else
+ oldIdx = _globals._sequenceIndexes[3];
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 46, 49);
+ if (!_removeMonkeyFl)
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 179);
+ }
+ break;
+
+ case 179: {
+ _vm->_sound->command(18);
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 53, 61);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 180);
+ }
+ break;
+
+ case 180:
+ _removeMonkeyFl = true;
+ _pauseMode = 1;
+ _playingAnimFl = false;
+ _scene->_hotspots.activate(227, false);
+ break;
+ }
+}
+
+void Scene209::handleTongue() {
+ switch (_game._trigger) {
+ case 182: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 30);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 183);
+ }
+ break;
+
+ case 183: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 31, 33);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 184);
+ }
+ break;
+
+ case 184: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 36, 37);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 185);
+ }
+ break;
+
+ case 185: {
+ _vm->_sound->command(18);
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 20, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 38, 39);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 186);
+ }
+ break;
+
+ case 186: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 40, 41);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 178);
+ _removeMonkeyFl = false;
+ }
+ break;
+ }
+}
+
+void Scene209::handleStandFromPeek() {
+ switch (_game._trigger) {
+ case 189:
+ _monkeyPosition = 4;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 50);
+ _scene->_sequences.addTimer(8, 190);
+ break;
+
+ case 190:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.addTimer(8, 191);
+ break;
+
+ case 191:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 192);
+ break;
+
+ case 192: {
+ _vm->_sound->command(18);
+ int oldIdx = _globals._sequenceIndexes[6];
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx);
+ _scene->_sequences.addTimer(8, 193);
+ }
+ break;
+
+ case 193:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22);
+ _scene->_sequences.addTimer(5, 194);
+ break;
+
+ case 194:
+ _playingAnimFl = false;
+ _counter = 0;
+ break;
+ }
+}
+
+void Scene209::handleStandBlink() {
+ switch (_game._trigger) {
+ case 246:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22);
+ _scene->_sequences.addTimer(10, 247);
+ break;
+
+ case 247:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 23);
+ _scene->_sequences.addTimer(8, 248);
+ break;
+
+ case 248:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22);
+ _scene->_sequences.addTimer(10, 249);
+ break;
+
+ case 249:
+ _playingAnimFl = false;
+ break;
+ }
+}
+
+void Scene209::handleJumpAndHide() {
+ switch (_game._trigger) {
+ case 196:
+ _vm->_sound->command(18);
+ _monkeyPosition = 1;
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 16);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 197);
+ break;
+
+ case 197:
+ _pauseMode = 1;
+ _scene->_hotspots.activate(227, false);
+ _playingAnimFl = false;
+ break;
+ }
+}
+
+void Scene209::handleMonkeyEating() {
+ switch (_game._trigger) {
+ case 199:
+ _vm->_sound->command(18);
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 14);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 200);
+ break;
+
+ case 200: {
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 10, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 15, 16);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 201);
+ }
+ break;
+
+ case 201: {
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 12);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ _scene->_sequences.addTimer(20, 202);
+ }
+ break;
+
+ case 202:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 19);
+ _scene->_sequences.addTimer(20, 203);
+ break;
+
+ case 203:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 17);
+ _scene->_sequences.addTimer(20, 204);
+ break;
+
+ case 204:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 18, 19);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 205);
+ break;
+
+ case 205: {
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 20, 21);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 206);
+ }
+ break;
+
+ case 206: {
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 22, 25);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ if (!_dodgeFl && !_fallFl)
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 207);
+ else
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 209);
+ }
+ break;
+
+ case 207: {
+ _vm->_sound->command(18);
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(180, 25), 0xFDFC, 0, 0, 90, _game.getQuote(130));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 4, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 26, 27);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 208);
+ }
+ break;
+
+ case 208: {
+ _scene->_kernelMessages.add(Common::Point(180, 39), 0xFDFC, 0, 0, 90, _game.getQuote(131));
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 4, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 28, 29);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 209);
+ }
+ break;
+
+ case 209: {
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ _scene->_sequences.addTimer(1, 210);
+ }
+ break;
+
+ case 210:
+ _playingAnimFl = false;
+ break;
+ }
+}
+
+void Scene209::handleMonkeyFall() {
+ switch (_game._trigger) {
+ case 219: {
+ _vm->_sound->command(25);
+ _scene->_sprites.remove(_globals._spriteIndexes[7]);
+ _scene->_sprites.remove(_globals._spriteIndexes[6]);
+ _scene->_sprites.remove(_globals._spriteIndexes[5]);
+ _scene->_sprites.remove(_globals._spriteIndexes[4]);
+
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', 4));
+ _scene->_kernelMessages.add(Common::Point(180, 26), 0xFDFC, 0, 0, 90, _game.getQuote(151));
+ _scene->_sequences.addTimer(40, 100);
+ _scene->_hotspots.activate(227, false);
+ int oldIdx = _globals._sequenceIndexes[3];
+ _monkeyPosition = 1;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 35);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 220);
+ }
+ break;
+
+ case 220: {
+ _vm->_sound->command(18);
+ _scene->_kernelMessages.add(Common::Point(182, 109), 0xFDFC, 0, 0, 90, _game.getQuote(159));
+ _scene->_hotspots.activate(227, false);
+ int oldIdx = _globals._sequenceIndexes[3];
+ _monkeyPosition = 1;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 36, 42);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 221);
+ }
+ break;
+
+ case 221: {
+ _game._objects.setRoom(OBJ_BINOCULARS, 209);
+ _binocularsDroppedFl = true;
+ int oldIdx = _globals._sequenceIndexes[8];
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0);
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], oldIdx);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(201, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], oldIdx);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 43, 72);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 222);
+ int idx = _scene->_dynamicHotspots.add(39, 13, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(200, 133), FACING_NORTH);
+ }
+ break;
+
+ case 222: {
+ _scene->_kernelMessages.add(Common::Point(182, 109), 0xFDFC, 0, 0, 70, _game.getQuote(160));
+ int oldIdx = _globals._sequenceIndexes[8];
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 73, 78);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 223);
+ }
+ break;
+
+ case 223:
+ _scene->loadAnimation(Resources::formatName(209, 'e', -1, EXT_AA, ""), 224);
+ _vm->_sound->command(38);
+ break;
+
+ case 224:
+ _playingAnimFl = false;
+ _fallFl = false;
+ _counter = 0;
+ _pauseMode = 0;
+ _vm->_dialogs->show(20910);
+ _game._player._stepEnabled = true;
+ break;
+ }
+}
+
+void Scene209::handleMonkey1() {
+ switch (_game._trigger) {
+ case 212:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 9, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 13);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 213);
+ break;
+
+ case 213: {
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 22);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 214);
+ }
+ break;
+
+ case 214: {
+ int oldIdx = _globals._sequenceIndexes[7];
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 23, 26);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 215);
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(170, 21), 0xFDFC, 0, 0, 90, _game.getQuote(156));
+ _scene->_kernelMessages.setQuoted(msgIndex, 3, true);
+ }
+ break;
+
+ case 215: {
+ _vm->_sound->command(18);
+ _scene->loadAnimation(Resources::formatName(209, 'a', -1, EXT_AA, ""), 251);
+ int oldIdx = _globals._sequenceIndexes[7];
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 27, 35);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 216);
+ }
+ break;
+
+ case 216: {
+ int oldIdx = _globals._sequenceIndexes[7];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ _scene->_sequences.addTimer(25, 217);
+ }
+ break;
+
+ case 217:
+ _pitchFl = false;
+ _counter = 0;
+ _pauseMode = 0;
+ _scene->_sequences.addTimer(1, 196);
+ break;
+ }
+}
+
+void Scene209::handleMonkey2() {
+ switch (_game._trigger) {
+ case 251:
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(137));
+ _vm->_sound->command(22);
+ _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 11, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[12], Common::Point(111, 133));
+ _scene->_sequences.setScale(_globals._sequenceIndexes[12], 79);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 6);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 252);
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = false;
+ break;
+
+ case 252: {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(132));
+ int oldIdx = _globals._sequenceIndexes[12];
+ _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 7);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[12], Common::Point(111, 133));
+ _scene->_sequences.setScale(_globals._sequenceIndexes[12], 79);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], oldIdx);
+ _scene->_sequences.addTimer(120, 253);
+ }
+ break;
+
+ case 253:
+ _scene->_sequences.remove(_globals._sequenceIndexes[12]);
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+ }
+}
+
+void Scene209::handleDodge() {
+ switch (_game._trigger) {
+ case 241:
+ _scene->_hotspots.activate(227, true);
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7);
+ _scene->_sequences.addTimer(6, 242);
+ break;
+
+ case 242:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5);
+ _scene->_sequences.addTimer(25, 243);
+ _vm->_sound->command(24);
+ break;
+
+ case 243:
+ _vm->_sound->command(18);
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _playingAnimFl = false;
+ _pauseMode = 0;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 90, _game.getQuote(155));
+ if (!_shootMissedLastFl) {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(135));
+ _shootMissedLastFl = true;
+ } else {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(136));
+ }
+ break;
+ }
+}
+
+void Scene209::enter() {
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('m', 1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('m', 3));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('m', 6));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('m', 8));
+
+ _game.loadQuoteSet(0x82, 0x83, 0x84, 0x9C, 0x97, 0x95, 0x99, 0x9E, 0x98, 0x9B, 0xA0, 0x96, 0x9F,
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x91, 0x92, 0x93, 0x94, 0x89, 0x85, 0x8A, 0x86, 0x87, 0x88, 0);
+
+ _vm->_palette->setEntry(252, 63, 44, 30);
+ _vm->_palette->setEntry(253, 63, 20, 22);
+
+ if (_game._objects.isInRoom(OBJ_PLANT_STALK)) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ int idx = _scene->_dynamicHotspots.add(271, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(263, 129), FACING_SOUTH);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 13);
+ }
+
+ if (_scene->_priorSceneId == 208) {
+ _game._player._playerPos = Common::Point(11, 121);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(28, 121);
+ _game._player._facing = FACING_SOUTH;
+ }
+
+ if (_game._objects.isInRoom(OBJ_BINOCULARS)) {
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(201, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ int idx = _scene->_dynamicHotspots.add(39, 13, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(200, 133), FACING_NORTH);
+ }
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_POISON_DARTS);
+ _game._objects.addToInventory(OBJ_BLOWGUN);
+ _globals[kMonkeyStatus] = MONKEY_HAS_BINOCULARS;
+ }
+
+ _pitchFl = false;
+ _fallFl = false;
+ _dodgeFl = false;
+ _playingAnimFl = false;
+ _monkeyPosition = 1;
+ _counter = 0;
+ _pauseMode = 0;
+ _forceFallFl = false;
+ _shouldFallFl = false;
+ _forceDodgeFl = false;
+ _binocularsDroppedFl = false;
+ _shouldDodgeFl = false;
+ _startShootingInTimerFl = false;
+ _dialogAbortVal = 5;
+ _playingDialogFl = false;
+ _shootMissedLastFl = false;
+ _removeMonkeyFl = true;
+ _shootReadyFl = false;
+
+ _scene->_hotspots.activate(227, false);
+
+ sceneEntrySound();
+}
+
+void Scene209::step() {
+ if (!_playingAnimFl && !_pitchFl && !_fallFl && !_dodgeFl && (_pauseMode == 0) && (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS)) {
+ int randAction = _vm->getRandomNumber(1,50);
+ switch (randAction) {
+ case 1:
+ if ((_monkeyPosition == 1) && (_counter < 2)) {
+ _scene->_sequences.addTimer(1, 133);
+ _playingAnimFl = true;
+ _scene->_hotspots.activate(227, true);
+ ++_counter;
+ }
+ break;
+
+ case 2:
+ if ((_monkeyPosition == 1) && (_counter < 2)) {
+ _scene->_sequences.addTimer(1, 140);
+ _scene->_hotspots.activate(227, true);
+ _playingAnimFl = true;
+ ++_counter;
+ }
+ break;
+
+ case 3:
+ if (_monkeyPosition == 1) {
+ _scene->_sequences.addTimer(1, 145);
+ _scene->_hotspots.activate(227, true);
+ _playingAnimFl = true;
+ _counter = 0;
+ }
+ break;
+
+ case 4:
+ if ((_monkeyPosition == 2) && (_counter < 2)) {
+ _scene->_sequences.addTimer(1, 151);
+ _scene->_hotspots.activate(227, true);
+ ++_counter;
+ _playingAnimFl = true;
+ }
+ break;
+
+ case 5:
+ if (_monkeyPosition == 2) {
+ _scene->_sequences.addTimer(1, 161);
+ _scene->_hotspots.activate(227, true);
+ _counter = 0;
+ _playingAnimFl = true;
+ }
+ break;
+
+ case 6:
+ if (_monkeyPosition == 2) {
+ _scene->_sequences.addTimer(1, 189);
+ _scene->_hotspots.activate(227, true);
+ _counter = 0;
+ _playingAnimFl = true;
+ }
+ break;
+ case 7:
+ if (_monkeyPosition == 3) {
+ _scene->_hotspots.activate(227, true);
+ _scene->_sequences.addTimer(1, 167);
+ _playingAnimFl = true;
+ }
+ break;
+
+ case 8:
+ if (_monkeyPosition == 3) {
+ _scene->_sequences.addTimer(1, 178);
+ _playingAnimFl = true;
+ _scene->_hotspots.activate(227, true);
+ _counter = 0;
+ }
+ break;
+
+ case 9:
+ if ((_monkeyPosition == 3) && (_game._player._playerPos.x<120)) {
+ _scene->_sequences.addTimer(1, 182);
+ _scene->_hotspots.activate(227, true);
+ _counter = 0;
+ _playingAnimFl = true;
+ }
+ break;
+
+ case 10:
+ if (_monkeyPosition == 4) {
+ _scene->_sequences.addTimer(1, 196);
+ _scene->_hotspots.activate(227, true);
+ _playingAnimFl = true;
+ _counter = 0;
+ }
+ break;
+
+ case 11:
+ if ((_monkeyPosition == 4) && (_counter < 3)) {
+ _scene->_sequences.addTimer(1, 199);
+ _scene->_hotspots.activate(227, true);
+ ++_counter;
+ _playingAnimFl = true;
+ }
+ break;
+
+ case 30:
+ if (_monkeyPosition == 4) {
+ _scene->_sequences.addTimer(1, 246);
+ _scene->_hotspots.activate(227, true);
+ _counter = 0;
+ _playingAnimFl = true;
+ }
+ break;
+
+ default:
+ if ((randAction >= 12) && (randAction <= 20) && (_monkeyPosition == 2) && (_counter < 5)) {
+ _scene->_sequences.addTimer(1, 155);
+ ++_counter;
+ _playingAnimFl = true;
+ }
+
+ if ((randAction >= 21) && (randAction <= 29) && (_monkeyPosition == 3) && (_counter < 3)) {
+ _scene->_sequences.addTimer(1, 171);
+ _playingAnimFl = true;
+ ++_counter;
+ }
+ break;
+ }
+ }
+
+ if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 1))
+ _scene->_sequences.addTimer(1, 226);
+
+ if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 2))
+ handlePause();
+
+ if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 1))
+ initPauseCounterThreshold();
+
+ handlePeek();
+ handleVerticalMove();
+ handleLookStay();
+ handleLookRight();
+ handleBlink();
+ handleGetBinoculars();
+ handleStandFromPeek();
+ handleDodge();
+ handleBinocularBlink();
+ handleBinocularScan();
+ handleJumpInTree();
+ handleTongue();
+ handleMonkeyFall();
+ handleJumpAndHide();
+ handleMonkeyEating();
+ handleMonkey1();
+ handleStandBlink();
+ handleMonkey2();
+
+ if ((_monkeyPosition == 1) && !_playingAnimFl && _fallFl) {
+ _scene->_sequences.addTimer(1, 145);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 2) && !_playingAnimFl && _fallFl) {
+ _scene->_sequences.addTimer(1, 161);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 4) && !_playingAnimFl && _fallFl) {
+ _scene->_sequences.addTimer(1, 196);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 3) && !_playingAnimFl && _fallFl && _forceFallFl) {
+ _scene->_sequences.addTimer(1, 219);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 1) && !_playingAnimFl && _pitchFl) {
+ _scene->_sequences.addTimer(1, 145);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 2) && !_playingAnimFl && _pitchFl) {
+ _scene->_sequences.addTimer(1, 189);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 4) && !_playingAnimFl && _pitchFl) {
+ _scene->_sequences.addTimer(1, 212);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 3) && !_playingAnimFl && _pitchFl) {
+ _scene->_sequences.addTimer(1, 178);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 1) && !_playingAnimFl && _dodgeFl) {
+ _scene->_sequences.addTimer(1, 145);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 4) && !_playingAnimFl && _dodgeFl) {
+ _scene->_sequences.addTimer(1, 196);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 3) && !_playingAnimFl && _dodgeFl) {
+ _scene->_sequences.addTimer(1, 178);
+ _playingAnimFl = true;
+ }
+
+ if ((_monkeyPosition == 2) && !_playingAnimFl && _dodgeFl && _forceDodgeFl) {
+ _scene->_sequences.addTimer(1, 241);
+ _playingAnimFl = true;
+ }
+
+ if (_dodgeFl || _fallFl) { /* if want to dodge or fall */
+ if (!_playingAnimFl && (_monkeyPosition == 2))
+ _shouldDodgeFl = true;
+
+ if (!_playingAnimFl && (_monkeyPosition == 3))
+ _shouldFallFl = true;
+
+ switch (_game._trigger) {
+ case 228:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 7);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 229);
+ break;
+
+ case 229: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.addTimer(35, 230);
+ }
+ break;
+
+ case 230:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 7);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 231);
+ break;
+
+ case 231: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 8, 10);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 232);
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], -1);
+ _game._player._visible = false;
+ }
+ break;
+
+ case 232: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 10);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.addTimer(2, 233);
+ _scene->_kernelMessages.reset();
+ if (_dodgeFl && (_monkeyPosition != 1) && (_monkeyPosition != 2))
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 34463, _game.getQuote(138));
+ if (_fallFl && (_monkeyPosition != 3))
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 34463, _game.getQuote(138));
+ }
+ break;
+
+ case 233:
+ _shootReadyFl = true;
+ break;
+
+ case 234:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _scene->_kernelMessages.reset();
+ if (_action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_MONKEY)) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 7, 16, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 11, 12);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 12, 239);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 235);
+ } else if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_MONKEY)) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 11, 12);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 235);
+ _vm->_sound->command(23);
+ }
+ break;
+
+ case 235: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 13);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.addTimer(12, 236);
+ _forceFallFl = true;
+ _forceDodgeFl = true;
+ }
+ break;
+
+ case 236:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 14, 16);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 237);
+ break;
+
+ case 237:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(1, 238);
+ break;
+
+ case 238:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ if (_dodgeFl)
+ _game._player._stepEnabled = true;
+
+ _startShootingInTimerFl = false;
+
+ if (_fallFl) {
+ _globals[kMonkeyStatus] = MONKEY_IS_GONE;
+ _game._objects.setRoom(OBJ_POISON_DARTS, NOWHERE);
+ }
+ _dodgeFl = false;
+ _fallFl = false;
+ _forceFallFl = false;
+ _forceDodgeFl = false;
+ _shouldFallFl = false;
+ _shouldDodgeFl = false;
+ break;
+
+ case 239:
+ _vm->_sound->command(23);
+ break;
+ }
+ }
+
+ if (_game._trigger == 100)
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(134));
+
+ if (_shootReadyFl && (_shouldFallFl || _shouldDodgeFl)) {
+ _scene->_sequences.addTimer(4, 234);
+ _shootReadyFl = false;
+ }
+}
+
+void Scene209::preActions() {
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_WEST))
+ _game._player._walkOffScreenSceneId = 208;
+
+ if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) {
+ if ((_action.isAction(VERB_SHOOT) || _action.isAction(VERB_HOSE_DOWN)) && _action.isTarget(NOUN_MONKEY)
+ && _action.isObject(NOUN_BLOWGUN) && _game._objects.isInInventory(OBJ_BLOWGUN) && _game._objects.isInInventory(OBJ_POISON_DARTS)) {
+ _game._player._prepareWalkPos = Common::Point(111, 129);
+ _game._player._prepareWalkFacing = FACING_NORTHEAST;
+ _game._player._needToWalk = true;
+ _game._player._readyToWalk = true;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_MONKEY) || _action.isAction(VERB_TALKTO, NOUN_MONKEY)) {
+ _game._player._prepareWalkPos = Common::Point(111, 129);
+ _game._player._prepareWalkFacing = FACING_NORTHEAST;
+ _game._player._needToWalk = true;
+ _game._player._readyToWalk = true;
+ }
+ }
+}
+
+void Scene209::actions() {
+ if (_action._lookFlag) {
+ _vm->_dialogs->show(20912);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_ROCKY_AREA_TO_NORTH)) {
+ _scene->_nextSceneId = 203;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TALKTO, NOUN_MONKEY) && !_pitchFl && !_playingDialogFl) {
+ _scene->_sequences.addTimer(1, _dialogAbortVal);
+ _playingDialogFl = true;
+ _game._player._stepEnabled = false;
+ _action._inProgress = false;
+ return;
+ }
+
+ switch (_game._trigger) {
+ case 130:
+ _game._player._stepEnabled = true;
+ _playingDialogFl = false;
+ _action._inProgress = false;
+ return;
+
+ case 5:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 6, 180, _game.getQuote(139));
+ _action._inProgress = false;
+ return;
+
+ case 6:
+ _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(151));
+ _scene->_sequences.addTimer(60, 130);
+ _dialogAbortVal = 7;
+ _action._inProgress = false;
+ return;
+
+ case 7:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 8, 180, _game.getQuote(140));
+ _action._inProgress = false;
+ return;
+
+ case 8:
+ _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(149));
+ _scene->_sequences.addTimer(60, 130);
+ _dialogAbortVal = 9;
+ _action._inProgress = false;
+ return;
+
+ case 9:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(141));
+ _scene->_sequences.addTimer(200, 10);
+ _action._inProgress = false;
+ return;
+
+ case 10:
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 11, 180, _game.getQuote(142));
+ _action._inProgress = false;
+ return;
+
+ case 11:
+ _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(152));
+ _scene->_sequences.addTimer(60, 130);
+ _dialogAbortVal = 12;
+ _action._inProgress = false;
+ return;
+
+ case 12:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 130, _game.getQuote(143));
+ _scene->_sequences.addTimer(150, 13);
+ _action._inProgress = false;
+ return;
+
+ case 13:
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 14, 180, _game.getQuote(145));
+ _action._inProgress = false;
+ return;
+
+ case 14:
+ _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(151));
+ _scene->_sequences.addTimer(60, 130);
+ _dialogAbortVal = 15;
+ _action._inProgress = false;
+ return;
+
+ case 15:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 16, 180, _game.getQuote(146));
+ _action._inProgress = false;
+ return;
+
+ case 16:
+ _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 17, 60, _game.getQuote(154));
+ _action._inProgress = false;
+ return;
+
+ case 17:
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 130, 60, _game.getQuote(147));
+ _dialogAbortVal = 18;
+ _action._inProgress = false;
+ return;
+
+ case 18:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(148));
+ _pitchFl = true;
+ _playingDialogFl = false;
+ _dialogAbortVal = 5;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) {
+ if ((_action.isAction(VERB_SHOOT) || _action.isAction(VERB_HOSE_DOWN)) && _action.isTarget(NOUN_MONKEY)
+ && _action.isObject(NOUN_BLOWGUN) && _game._objects.isInInventory(OBJ_BLOWGUN) && _game._objects.isInInventory(OBJ_POISON_DARTS)) {
+ if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_MONKEY) && !_startShootingInTimerFl) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 231);
+ _startShootingInTimerFl = true;
+ _game._player._stepEnabled = false;
+ _dodgeFl = true;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_MONKEY) && !_startShootingInTimerFl) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 228);
+ _game._player._stepEnabled = false;
+ _fallFl = true;
+ _startShootingInTimerFl = true;
+ _action._inProgress = false;
+ return;
+ }
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_MONKEY)) {
+ _pitchFl = true;
+ _game._player._stepEnabled = false;
+ _vm->_dialogs->show(20914);
+ _action._inProgress = false;
+ return;
+ }
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_PLANT_STALK) && (_game._trigger || _game._objects.isInRoom(OBJ_PLANT_STALK))) {
+ switch (_game._trigger) {
+ case 0:
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMBD_2");
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[11]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _game._objects.addToInventory(OBJ_PLANT_STALK);
+ break;
+
+ case 2:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _scene->_sequences.addTimer(4, 3);
+ _vm->_dialogs->showItem(OBJ_PLANT_STALK, 0x328);
+ break;
+
+ case 3:
+ _scene->_sprites.remove(_globals._spriteIndexes[11]);
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_BINOCULARS) && (_game._trigger || _game._objects.isInRoom(OBJ_BINOCULARS))) {
+ switch (_game._trigger) {
+ case 0:
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites("*RXMBD_8");
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 3, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[10]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _game._objects.addToInventory(OBJ_BINOCULARS);
+ break;
+
+ case 2:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _binocularsDroppedFl = false;
+ _scene->_sequences.addTimer(4, 3);
+ break;
+
+ case 3:
+ _vm->_dialogs->showItem (OBJ_BINOCULARS, 0x51AF);
+ _scene->_sprites.remove(_globals._spriteIndexes[10]);
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_SKY)) {
+ _vm->_dialogs->show(20901);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_BAMBOO_LIKE_PLANT)) {
+ _vm->_dialogs->show(20902);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINSIDE)) {
+ _vm->_dialogs->show(20903);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) {
+ _vm->_dialogs->show(20904);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_WEST)) {
+ _vm->_dialogs->show(20905);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_ROCKY_AREA_TO_NORTH)) {
+ _vm->_dialogs->show(20906);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_PLANT_STALK) && (_action._savedFields._mainObjectSource == 4)) {
+ _vm->_dialogs->show(20907);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_GIVE, NOUN_TWINKIFRUIT, NOUN_MONKEY) || _action.isAction(VERB_THROW, NOUN_TWINKIFRUIT, NOUN_MONKEY)) {
+ _vm->_dialogs->show(20909);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_TREES)) {
+ _vm->_dialogs->show(20913);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_THROW, NOUN_MONKEY) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) {
+ if (!_action.isObject(NOUN_POISON_DARTS)) {
+ _vm->_dialogs->show(20915);
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_THROW, NOUN_POISON_DARTS, NOUN_MONKEY)) {
+ _vm->_dialogs->show(20916);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) {
+ if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) {
+ if (_monkeyPosition == 1)
+ _vm->_dialogs->show(20917);
+ else
+ _vm->_dialogs->show(20918);
+ } else {
+ if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY)
+ _vm->_dialogs->show(20917);
+ else
+ _vm->_dialogs->show(20919);
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_MELON_MUSH)) {
+ _vm->_dialogs->show(20920);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_MELON_MUSH)) {
+ _vm->_dialogs->show(20921);
+ _action._inProgress = false;
+ return;
+ }
+}
+
+/*****************************************************************************/
+
+Scene210::Scene210(MADSEngine *vm) : Scene2xx(vm) {
+ _curDialogNode = -1;
+ _nextHandsPlace = 0;
+ _twinkleAnimationType = 0;
+ _twinklesCurrentFrame = 0;
+ _shouldTalk = false;
+ _shouldFaceRex = false;
+ _shouldMoveHead = false;
+ _stopWalking = false;
+ _twinklesTalking = false;
+ _twinklesTalk2 = false;
+ _doorway = 0;
+ _subQuote2 = "";
+}
+
+void Scene210::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsSint32LE(_curDialogNode);
+ s.syncAsSint32LE(_nextHandsPlace);
+ s.syncAsSint32LE(_twinkleAnimationType);
+ s.syncAsSint32LE(_twinklesCurrentFrame);
+
+ s.syncAsByte(_shouldTalk);
+ s.syncAsByte(_shouldFaceRex);
+ s.syncAsByte(_shouldMoveHead);
+ s.syncAsByte(_stopWalking);
+ s.syncAsByte(_twinklesTalking);
+ s.syncAsByte(_twinklesTalk2);
+
+ s.syncAsSint32LE(_doorway);
+
+ s.syncString(_subQuote2);
+}
+
+void Scene210::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_DOORWAY);
+ _scene->addActiveVocab(VERB_WALK_THROUGH);
+}
+
+void Scene210::handleConversations() {
+ if (_game._trigger == 0) {
+ _scene->_kernelMessages.reset();
+ _game._player._stepEnabled = false;
+ Common::String curQuote = _game.getQuote(_action._activeAction._verbId);
+ if (_scene->_kernelMessages._talkFont->getWidth(curQuote, _scene->_textSpacing) > 200) {
+ Common::String subQuote1;
+ _game.splitQuote(curQuote, subQuote1, _subQuote2);
+ _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 240, subQuote1);
+ _scene->_sequences.addTimer(60, 50);
+ } else {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote);
+ }
+ } else if (_game._trigger == 50) {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 240, _subQuote2);
+ _scene->_sequences.addTimer(180, 1);
+ } else {
+ if (_game._trigger == 1)
+ _scene->_kernelMessages.reset();
+
+ switch (_curDialogNode) {
+ case 1:
+ handleConversation1();
+ break;
+
+ case 2:
+ handleConversation2();
+ break;
+
+ case 3:
+ handleConversation3();
+ break;
+
+ case 5:
+ handleConversation5();
+ break;
+
+ case 6:
+ handleConversation6();
+ break;
+
+ case 7:
+ handleConversation7();
+ break;
+
+ case 8:
+ handleConversation8();
+ break;
+ }
+ }
+}
+
+void Scene210::handleConversation1() {
+ switch (_action._activeAction._verbId) {
+ case 180:
+ setDialogNode(2);
+ break;
+
+ case 181:
+ setDialogNode(6);
+ break;
+
+ case 182:
+ setDialogNode(4);
+ break;
+
+ case 183:
+ setDialogNode(9);
+ break;
+
+ case 184:
+ setDialogNode(0);
+ break;
+ }
+}
+
+void Scene210::handleConversation2() {
+ switch (_action._activeAction._verbId) {
+ case 187:
+ setDialogNode(3);
+ break;
+
+ case 188:
+ setDialogNode(4);
+ break;
+
+ case 189:
+ setDialogNode(0);
+ break;
+ }
+}
+
+void Scene210::handleConversation3() {
+ switch (_action._activeAction._verbId) {
+ case 193:
+ setDialogNode(6);
+ break;
+
+ case 194:
+ setDialogNode(5);
+ break;
+
+ case 195:
+ setDialogNode(4);
+ break;
+
+ case 196:
+ setDialogNode(0);
+ break;
+ }
+}
+
+void Scene210::handleConversation5() {
+ switch (_action._activeAction._verbId) {
+ case 204:
+ setDialogNode(6);
+ break;
+
+ case 205:
+ case 206:
+ setDialogNode(4);
+ break;
+
+ case 207:
+ setDialogNode(0);
+ break;
+ }
+}
+
+void Scene210::handleConversation6() {
+ switch (_action._activeAction._verbId) {
+ case 211:
+ setDialogNode(7);
+ break;
+
+ case 212:
+ setDialogNode(4);
+ break;
+
+ case 213:
+ setDialogNode(0);
+ break;
+ }
+}
+
+void Scene210::handleConversation7() {
+ switch (_action._activeAction._verbId) {
+ case 216:
+ case 217:
+ case 219:
+ setDialogNode(4);
+ break;
+
+ case 218:
+ setDialogNode(8);
+ break;
+
+ case 220:
+ setDialogNode(0);
+ break;
+ }
+}
+
+void Scene210::handleConversation8() {
+ switch (_action._activeAction._verbId) {
+ case 223:
+ case 224:
+ setDialogNode(4);
+ break;
+
+ case 225:
+ case 226:
+ setDialogNode(9);
+ break;
+
+ case 227:
+ setDialogNode(0);
+ break;
+ }
+}
+
+void Scene210::setDialogNode(int node) {
+ switch (node) {
+ case 0:
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _shouldFaceRex = false;
+ _shouldTalk = false;
+ _game._player._stepEnabled = true;
+ _curDialogNode = 0;
+ break;
+
+ case 2:
+ switch (_game._trigger) {
+ case 1:
+ _nextHandsPlace = 1;
+ _shouldTalk = true;
+ _game._player._stepEnabled = false;
+ if (_twinklesTalking) {
+ handleTwinklesSpeech(0xB9, -1, 0);
+ _scene->_sequences.addTimer(180, 2);
+ } else {
+ _scene->_sequences.addTimer(6, 1);
+ }
+ break;
+
+ case 2:
+ _nextHandsPlace = 0;
+ handleTwinklesSpeech(186, 0, 0);
+ _scene->_sequences.addTimer(180, 3);
+ break;
+
+ default:
+ _nextHandsPlace = 0;
+ _shouldTalk = false;
+ _game._player._stepEnabled = true;
+ newNode(2);
+ break;
+ }
+ break;
+
+ case 3:
+ switch (_game._trigger) {
+ case 1:
+ _nextHandsPlace = 0;
+ _shouldTalk = true;
+ _game._player._stepEnabled = false;
+ if (_twinklesTalking) {
+ handleTwinklesSpeech(0xBE, -2, 0);
+ _scene->_sequences.addTimer(180, 2);
+ } else {
+ _scene->_sequences.addTimer(6, 1);
+ }
+ break;
+ case 2:
+ _nextHandsPlace = 2;
+ handleTwinklesSpeech(191, -1, 0);
+ _scene->_sequences.addTimer(180, 3);
+ break;
+ case 3:
+ _nextHandsPlace = 0;
+ handleTwinklesSpeech(192, 0, 0);
+ _scene->_sequences.addTimer(180, 4);
+ break;
+ default:
+ _shouldTalk = false;
+ _game._player._stepEnabled = true;
+ newNode(3);
+ break;
+ }
+ break;
+
+ case 4:
+ if (_game._trigger == 1) {
+ _nextHandsPlace = 1;
+ _shouldTalk = true;
+ _game._player._stepEnabled = false;
+
+ int quote;
+ if (_game._storyMode == STORYMODE_NAUGHTY)
+ quote = _vm->getRandomNumber(199, 201);
+ else
+ quote = _vm->getRandomNumber(197, 198);
+
+ if (_twinklesTalking) {
+ handleTwinklesSpeech(quote, 0, 360);
+ _scene->_sequences.addTimer(120, 2);
+ } else {
+ _scene->_sequences.addTimer(6, 1);
+ }
+ } else {
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _shouldFaceRex = false;
+ _shouldTalk = false;
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ case 5:
+ switch (_game._trigger) {
+ case 1:
+ _nextHandsPlace = 2;
+ _shouldTalk = true;
+ _game._player._stepEnabled = false;
+ if (_twinklesTalking) {
+ handleTwinklesSpeech(0xCA, -1, 0);
+ _scene->_sequences.addTimer(180, 2);
+ } else {
+ _scene->_sequences.addTimer(6, 1);
+ }
+ break;
+
+ case 2:
+ _nextHandsPlace = 1;
+ handleTwinklesSpeech(0xCB, 0, 0);
+ _scene->_sequences.addTimer(180, 3);
+ break;
+
+ default:
+ _nextHandsPlace = 2;
+ _shouldTalk = false;
+ _game._player._stepEnabled = true;
+ newNode(5);
+ break;
+ }
+ break;
+
+ case 6:
+ switch (_game._trigger) {
+ case 1:
+ _nextHandsPlace = 1;
+ _shouldTalk = true;
+ _game._player._stepEnabled = false;
+ if (_twinklesTalking) {
+ handleTwinklesSpeech(0xD0, -2, 0);
+ _scene->_sequences.addTimer(180, 2);
+ } else {
+ _scene->_sequences.addTimer(6, 1);
+ }
+ break;
+
+ case 2:
+ handleTwinklesSpeech(0xD1, -1, 0);
+ _scene->_sequences.addTimer(180, 3);
+ break;
+
+ case 3:
+ _nextHandsPlace = 1;
+ handleTwinklesSpeech(0xD2, 0, 0);
+ _scene->_sequences.addTimer(180, 4);
+ break;
+
+ default:
+ _nextHandsPlace = 0;
+ _shouldTalk = false;
+ _game._player._stepEnabled = true;
+ newNode(6);
+ break;
+ }
+ break;
+
+ case 7:
+ switch (_game._trigger) {
+ case 1:
+ _nextHandsPlace = 2;
+ _shouldTalk = true;
+ _game._player._stepEnabled = false;
+ if (_twinklesTalking) {
+ handleTwinklesSpeech(0xD6, -1, 0);
+ _scene->_sequences.addTimer(180, 2);
+ } else {
+ _scene->_sequences.addTimer(6, 1);
+ }
+ break;
+
+ case 2:
+ handleTwinklesSpeech(0xD7, 0, 0);
+ _scene->_sequences.addTimer(180, 3);
+ break;
+
+ default:
+ _shouldTalk = false;
+ _game._player._stepEnabled = true;
+ newNode(7);
+ break;
+ }
+ break;
+
+ case 8:
+ switch (_game._trigger) {
+ case 1:
+ _nextHandsPlace = 2;
+ _shouldTalk = true;
+ _game._player._stepEnabled = false;
+ if (_twinklesTalking) {
+ handleTwinklesSpeech(0xDD, -1, 0);
+ _scene->_sequences.addTimer(180, 2);
+ } else {
+ _scene->_sequences.addTimer(6, 1);
+ }
+ break;
+
+ case 2:
+ handleTwinklesSpeech(0xDE, 0, 0);
+ _scene->_sequences.addTimer(180, 3);
+ break;
+
+ default:
+ _shouldTalk = false;
+ _game._player._stepEnabled = true;
+ newNode(8);
+ break;
+ }
+ break;
+
+
+ case 9:
+ switch (_game._trigger) {
+ case 1:
+ _nextHandsPlace = 0;
+ _shouldTalk = true;
+ _game._player._stepEnabled = false;
+ if (_twinklesTalking) {
+ _scene->_userInterface.emptyConversationList();
+ _scene->_userInterface.setup(kInputConversation);
+ handleTwinklesSpeech(0xE4, -1, 0);
+ _scene->_sequences.addTimer(180, 2);
+ } else {
+ _scene->_sequences.addTimer(6, 1);
+ }
+ break;
+
+ case 2:
+ handleTwinklesSpeech(0xE5, 0, 0);
+ _scene->_sequences.addTimer(180, 3);
+ break;
+
+ case 3:
+ _twinkleAnimationType = 2;
+ _globals[kCurtainOpen] = true;
+ _game._player._visible = false;
+ _vm->_palette->lock();
+ _scene->_kernelMessages.reset();
+ _scene->freeAnimation();
+ _scene->_activeAnimation = nullptr;
+ _scene->resetScene();
+
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _game.loadQuoteSet(0xE6, 0xE9, 0xEA, 0xE7, 0xE8, 0);
+ _scene->loadAnimation(formAnimName('B', -1), 4);
+ break;
+
+ case 4: {
+ _globals._spriteIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5);
+ _scene->_sequences.setDepth(_globals._spriteIndexes[8], 1);
+
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 20), 0x1110, 32, 5, 180, _game.getQuote(231));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+ break;
+
+ case 5: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 40), 0xFDFC, 32, 6, 180, _game.getQuote(233));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+ break;
+
+ case 6: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 60), 0x1110, 32, 7, 180, _game.getQuote(232));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+ break;
+
+ case 7: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 80), 0xFDFC, 32, 8, 180, _game.getQuote(234));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+ break;
+
+ case 8:
+ _globals[kTwinklesStatus] = TWINKLES_GONE;
+ _scene->_nextSceneId = 216;
+ break;
+ }
+ break;
+ }
+}
+
+void Scene210::handleTwinklesSpeech(int quoteId, int shiftX, uint32 delay) {
+ _scene->_kernelMessages.add(Common::Point(10, 70 + (shiftX * 14)), 0xFDFC, 0, 0, (delay == 0) ? 9999999 : delay, _game.getQuote(quoteId));
+}
+
+void Scene210::newNode(int node) {
+ _curDialogNode = node;
+
+ switch (_curDialogNode) {
+ case 1:
+ _conv1.start();
+ break;
+
+ case 2:
+ _conv2.start();
+ break;
+
+ case 3:
+ _conv3.start();
+ break;
+
+ case 5:
+ _conv5.start();
+ break;
+
+ case 6:
+ _conv6.start();
+ break;
+
+ case 7:
+ _conv7.start();
+ break;
+
+ case 8:
+ _conv8.start();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene210::restoreDialogNode(int node, int msgId, int posY) {
+ int curQuoteId = msgId;
+ int curY = 1 - posY;
+ for (int count = 0; count < posY; count++) {
+ handleTwinklesSpeech(curQuoteId, curY, 0);
+ curY++;
+ curQuoteId++;
+ }
+
+ newNode(node);
+}
+
+void Scene210::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1));
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _globals[kCurtainOpen] = 0;
+
+ if (_scene->_priorSceneId == 205)
+ _game._player._playerPos = Common::Point(277, 56);
+ else if (_scene->_priorSceneId == 215) {
+ _game._player._playerPos = Common::Point(168, 128);
+ _game._player._facing = FACING_SOUTH;
+ _globals[kCurtainOpen] = true;
+ } else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(308, 132);
+
+ if (!_globals[kCurtainOpen]) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ } else {
+ int idx = _scene->_dynamicHotspots.add(112, 395, -1, Common::Rect(163, 87, 163 + 19, 87 + 36));
+ _doorway = _scene->_dynamicHotspots.setPosition(idx, Common::Point(168, 127), FACING_NORTH);
+ _scene->_dynamicHotspots.setCursor(_doorway, CURSOR_GO_UP);
+ }
+
+ _game.loadQuoteSet(0x5A, 0x73, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB8, 0xB7,
+ 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
+ 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC,
+ 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0);
+
+ _conv1.setup(0x2E, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0);
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ _conv1.set(0x2E, 0xB4, 0xB5, 0xB6, 0xB8, 0);
+
+ if (_game._widepipeCtr >= 2)
+ _conv1.write(0xB7, true);
+ }
+
+ bool sceneRevisited = _game._visitedScenes._sceneRevisited;
+ _conv2.setup(0x2F, 0xBC, 0xBB, 0xBD, sceneRevisited ? 0 : -1);
+ _conv3.setup(0x30, 0xC3, 0xC2, 0xC1, 0xC4, sceneRevisited ? 0 : -1);
+ _conv5.setup(0x31, 0xCD, 0xCC, 0xCE, 0xCF, sceneRevisited ? 0 : -1);
+ _conv6.setup(0x32, 0xD3, 0xD4, 0xD5, sceneRevisited ? 0 : -1);
+ _conv7.setup(0x33, 0xD8, 0xDA, 0xD9, 0xDB, 0xDC, sceneRevisited ? 0 : -1);
+ _conv8.setup(0x34, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, sceneRevisited ? 0 : -1);
+
+ _twinkleAnimationType = 0;
+ _twinklesCurrentFrame = 0;
+
+ if (_scene->_priorSceneId != -2) {
+ _shouldMoveHead = false;
+ _shouldFaceRex = false;
+ _shouldTalk = false;
+ _nextHandsPlace = 0;
+ _twinklesTalking = false;
+ _curDialogNode = 0;
+ _stopWalking = false;
+ _twinklesTalk2 = (_globals[kTwinklesApproached] > 0);
+ }
+
+ if (_globals[kTwinklesStatus] == 0) {
+ _scene->loadAnimation(formAnimName('A', -1));
+ _twinkleAnimationType = 1;
+ } else
+ _scene->_hotspots.activate(476, false);
+
+ if (_curDialogNode) {
+ int quote = 0;
+ int number = 0;
+
+ switch (_curDialogNode) {
+ case 1:
+ quote = 0xB3;
+ number = 1;
+ break;
+ case 2:
+ quote = 0xB9;
+ number = 2;
+ break;
+ case 3:
+ quote = 0xBE;
+ number = 3;
+ break;
+ case 5:
+ quote = 0xCA;
+ number = 2;
+ break;
+ case 6:
+ quote = 0xD0;
+ number = 3;
+ break;
+ case 7:
+ quote = 0xD6;
+ number = 2;
+ break;
+ case 8:
+ quote = 0xDD;
+ number = 2;
+ break;
+ }
+
+ restoreDialogNode(_curDialogNode, quote, number);
+ if (_scene->_activeAnimation)
+ _scene->_activeAnimation->setCurrentFrame(131);
+ }
+
+ _vm->_palette->setEntry(252, 63, 63, 10);
+ _vm->_palette->setEntry(253, 45, 45, 5);
+
+ sceneEntrySound();
+}
+
+void Scene210::step() {
+ if ((_twinkleAnimationType == 1) && _scene->_activeAnimation) {
+ if (_twinklesCurrentFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _twinklesCurrentFrame = _scene->_activeAnimation->getCurrentFrame();
+ int reset_frame = -1;
+ int random = _vm->getRandomNumber(1, 1000);
+
+ switch (_twinklesCurrentFrame) {
+ case 31:
+ case 58:
+ case 74:
+ case 108:
+ case 190:
+ if (_shouldFaceRex)
+ reset_frame = 108;
+ else if ((random <= 100) || _shouldMoveHead)
+ reset_frame = 74;
+ else if (random <= 300)
+ reset_frame = 58;
+ else if (random <= 500)
+ reset_frame = 31;
+ else
+ reset_frame = 0;
+ break;
+
+ case 80:
+ case 90:
+ _twinklesTalking = false;
+ if (_shouldMoveHead) {
+ reset_frame = 90;
+ } else if (_twinklesCurrentFrame == 90) {
+ if ((random <= 400) || _shouldFaceRex)
+ reset_frame = 99;
+ else
+ reset_frame = 79;
+ }
+ break;
+
+ case 98:
+ if (_shouldMoveHead)
+ reset_frame = 91;
+ break;
+
+ case 99:
+ if ((random <= 400) && !_shouldFaceRex)
+ reset_frame = 79;
+ break;
+
+ case 124:
+ case 136:
+ case 174:
+ case 143:
+ case 152:
+ if (_nextHandsPlace == 3)
+ reset_frame = 174;
+ else if (!_shouldFaceRex)
+ reset_frame = 174;
+ else if (_nextHandsPlace == 1)
+ reset_frame = 136;
+ else if (_nextHandsPlace == 2)
+ reset_frame = 152;
+ else if (_shouldTalk)
+ reset_frame = 124;
+ else
+ reset_frame = (random <= 200) ? 131 : 143;
+ break;
+
+ case 131:
+ if (_shouldTalk) {
+ switch (_nextHandsPlace) {
+ case 1:
+ reset_frame = 136;
+ break;
+ case 2:
+ reset_frame = 152;
+ break;
+ default:
+ reset_frame = 124;
+ break;
+ }
+ }
+ break;
+
+ case 138:
+ case 141:
+ if ((_nextHandsPlace == 0) || !_shouldFaceRex)
+ reset_frame = 141;
+ else if (_nextHandsPlace == 2)
+ reset_frame = 152;
+ else if (!_shouldTalk || (_twinklesCurrentFrame == 141))
+ reset_frame = 137;
+ break;
+
+ case 153:
+ case 169:
+ if ((_nextHandsPlace == 0) || !_shouldFaceRex)
+ reset_frame = 169;
+ else if (_nextHandsPlace == 1)
+ reset_frame = 136;
+ else if (_shouldTalk)
+ reset_frame = 153;
+ else
+ reset_frame = 162;
+ break;
+
+ case 162:
+ if (_shouldTalk) {
+ switch (_nextHandsPlace) {
+ case 0:
+ reset_frame = 124;
+ break;
+ case 1:
+ reset_frame = 136;
+ break;
+ default:
+ reset_frame = 153;
+ break;
+ }
+ }
+ break;
+ }
+
+ if (reset_frame >= 0) {
+ if (reset_frame != _scene->_activeAnimation->getCurrentFrame()) {
+ _scene->_activeAnimation->setCurrentFrame(reset_frame);
+ _twinklesCurrentFrame = reset_frame;
+ }
+
+ if ((reset_frame == 90) || (reset_frame == 91) || (reset_frame == 124) || (reset_frame == 153)
+ || ((reset_frame == 137) && _shouldTalk)) {
+ _twinklesTalking = true;
+ } else {
+ _twinklesTalking = false;
+ }
+ }
+ }
+ }
+
+ if ((_twinkleAnimationType == 2) && _scene->_activeAnimation) {
+ if (_twinklesCurrentFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _twinklesCurrentFrame = _scene->_activeAnimation->getCurrentFrame();
+ int reset_frame = -1;
+
+ if (_twinklesCurrentFrame == 53) {
+ _scene->_kernelMessages.add(Common::Point(151, 61), 0xFDFC, 32, 70, 180, _game.getQuote(230));
+ _shouldTalk = true;
+ } else if ((_twinklesCurrentFrame == 75) && _shouldTalk)
+ reset_frame = 60;
+
+ if ((reset_frame >= 0) && (reset_frame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(reset_frame);
+ _twinklesCurrentFrame = reset_frame;
+ }
+ }
+
+ if (_game._trigger == 70)
+ _shouldTalk = false;
+ }
+
+ if ((_twinkleAnimationType == 1) && (_scene->_rails.getNext() > 0)) {
+ _game._player.walk(Common::Point(214, 150), FACING_NORTHWEST);
+ _scene->_rails.resetNext();
+ _stopWalking = true;
+ }
+}
+
+void Scene210::preActions() {
+ _stopWalking = false;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_EAST))
+ _game._player._walkOffScreenSceneId = 211;
+}
+
+void Scene210::actions() {
+ if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_HUT_TO_NORTH)) {
+ _vm->_dialogs->show(21017);
+ } else if (_game._screenObjects._inputMode == kInputConversation) {
+ handleConversations();
+ } else if (_action.isAction(VERB_TALKTO, NOUN_NATIVE_WOMAN) ||
+ ((_game._player._playerPos == Common::Point(214, 150)) && (_game._player._facing == FACING_NORTHWEST) && (_twinkleAnimationType == 1) && _stopWalking)) {
+ switch (_game._trigger) {
+ case 0: {
+ _game._player._stepEnabled = false;
+ int quote;
+ if (_globals[kTwinklesApproached] == 0)
+ quote = 90;
+ else if (_globals[kTwinklesApproached] == 1)
+ quote = 115;
+ else
+ quote = 171;
+
+ _shouldFaceRex = true;
+ _nextHandsPlace = 0;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.addQuote(quote, 1, 120);
+ }
+ break;
+
+ case 1:
+ _shouldTalk = true;
+ if (!_twinklesTalking) {
+ _scene->_sequences.addTimer(6, 1);
+ } else {
+ if (_globals[kTwinklesApproached] == 0) {
+ handleTwinklesSpeech(0xAF, -1, 0);
+ handleTwinklesSpeech(0xB0, 0, 0);
+ } else if (_globals[kTwinklesApproached] == 1) {
+ handleTwinklesSpeech(0xB1, 0, 0);
+ } else {
+ int quote = _twinklesTalk2 ? 0xB3 : 0xB2;
+ _twinklesTalk2 = true;
+ handleTwinklesSpeech(quote, 0, 0);
+ }
+ _scene->_sequences.addTimer(60, 3);
+ }
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ _shouldMoveHead = false;
+ _shouldTalk = false;
+
+ if (_globals[kTwinklesApproached] < 2)
+ _globals[kTwinklesApproached]++;
+
+ _conv1.start();
+ _curDialogNode = 1;
+ break;
+ }
+ } else if (_action.isAction(VERB_GIVE, NOUN_NATIVE_WOMAN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) {
+ switch (_game._trigger) {
+ case 0: {
+ int quote = _vm->getRandomNumber(172, 174);
+ _shouldMoveHead = true;
+ _game._player._stepEnabled = false;
+ handleTwinklesSpeech(quote, 0, 120);
+ _scene->_sequences.addTimer(120, 1);
+ }
+ break;
+
+ case 1:
+ _game._player._stepEnabled = true;
+ _shouldMoveHead = false;
+ break;
+ }
+ } else if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_NORTH) || _action.isAction(VERB_WALK_TOWARDS, NOUN_HUT_TO_NORTH)) {
+ _scene->_nextSceneId = 205;
+ } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) {
+ _scene->_nextSceneId = 215;
+ } else if ((_action.isAction(VERB_PULL, NOUN_CURTAIN) || _action.isAction(VERB_OPEN, NOUN_CURTAIN)) && !_globals[kCurtainOpen]) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _game._player._stepEnabled = true;
+ _globals[kCurtainOpen] = true;
+ _doorway = _scene->_dynamicHotspots.add(112, 395, -1, Common::Rect(163, 87, 163 + 19, 87 + 36));
+ _scene->_dynamicHotspots.setPosition(_doorway, Common::Point(168, 127), FACING_NORTH);
+ _scene->_dynamicHotspots.setCursor(_doorway, CURSOR_GO_UP);
+ break;
+ }
+ } else if ((_action.isAction(VERB_PULL, NOUN_CURTAIN) || _action.isAction(VERB_CLOSE, NOUN_CURTAIN)) && _globals[kCurtainOpen]) {
+ switch (_game._trigger) {
+ case 0:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _game._player._stepEnabled = false;
+ _game._player._facing = FACING_NORTH;
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 0, 0, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _game._player._stepEnabled = false;
+ break;
+ case 1:
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _scene->_sequences.addTimer(48, 2);
+ break;
+ case 2:
+ _scene->_dynamicHotspots.remove(_doorway);
+ _game._player._stepEnabled = true;
+ _globals[kCurtainOpen] = false;
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_HUT)) {
+ if (_globals[kTwinklesStatus] == TWINKLES_GONE) {
+ if (_game._storyMode == STORYMODE_NAUGHTY)
+ _vm->_dialogs->show(21003);
+ else
+ _vm->_dialogs->show(21002);
+ } else {
+ _vm->_dialogs->show(21001);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_BRA)) {
+ _vm->_dialogs->show(21004);
+ } else if (_action.isAction(VERB_LOOK, NOUN_HOTPANTS)) {
+ _vm->_dialogs->show(21005);
+ } else if (_action.isAction(VERB_TAKE, NOUN_HOTPANTS) || _action.isAction(VERB_TAKE, NOUN_BRA)) {
+ _vm->_dialogs->show(21006);
+ } else if (_action.isAction(VERB_LOOK, NOUN_STREAM)) {
+ _vm->_dialogs->show(21007);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BUSHY_FERN)) {
+ _vm->_dialogs->show(21008);
+ } else if (_action.isAction(VERB_LOOK, NOUN_VILLAGE_PATH)) {
+ _vm->_dialogs->show(21009);
+ } else if (_action.isAction(VERB_LOOK, NOUN_NATIVE_WOMAN)) {
+ _vm->_dialogs->show(21010);
+ } else if (_action.isAction(VERB_SHOOT, NOUN_NATIVE_WOMAN) || _action.isAction(VERB_HOSE_DOWN, NOUN_NATIVE_WOMAN)) {
+ _vm->_dialogs->show(21011);
+ } else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_NORTH)) {
+ _vm->_dialogs->show(21012);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CURTAIN)) {
+ _vm->_dialogs->show(21013);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CLOTHESLINE)) {
+ _vm->_dialogs->show(21014);
+ } else if (_action.isAction(VERB_TAKE, NOUN_CLOTHESLINE)) {
+ _vm->_dialogs->show(21015);
+ } else if (_action.isAction(VERB_LOOK, NOUN_HUT_TO_NORTH)) {
+ _vm->_dialogs->show(21016);
+ } else {
+ // Not handled
+ return;
+ }
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene211::Scene211(MADSEngine *vm) : Scene2xx(vm) {
+ _ambushFl = false;
+ _wakeFl = false;
+ _monkeyFrame = 0;
+ _scrollY = 0;
+ _monkeyTime = 0;
+}
+
+void Scene211::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsByte(_ambushFl);
+ s.syncAsByte(_wakeFl);
+
+ s.syncAsSint32LE(_monkeyFrame);
+ s.syncAsSint32LE(_scrollY);
+ s.syncAsUint32LE(_monkeyTime);
+}
+
+void Scene211::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_SLITHERING_SNAKE);
+}
+
+void Scene211::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC002Z2");
+ _wakeFl = false;
+
+ if (_scene->_priorSceneId == 210)
+ _game._player._playerPos = Common::Point(25, 148);
+ else if (_scene->_priorSceneId == 205) {
+ _game._player._playerPos = Common::Point(49, 133);
+ _game._player._facing = FACING_WEST;
+ _wakeFl = true;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->loadAnimation(formAnimName('A', -1), 100);
+ _scene->_activeAnimation->setCurrentFrame(169);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(310, 31);
+ _game._player._facing = FACING_SOUTHWEST;
+ }
+
+ if (_vm->getRandomNumber(1, 8) == 1) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(202, 126));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8);
+ _scene->_sequences.setMotion(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, -200, 0);
+ _scene->_dynamicHotspots.add(324, 13, _globals._sequenceIndexes[2], Common::Rect(1, 1, 1 + 41, 1 + 10));
+ }
+
+ if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_BINOCULARS);
+
+ _vm->_palette->setEntry(252, 63, 44, 30);
+ _vm->_palette->setEntry(253, 63, 20, 22);
+ _game.loadQuoteSet(0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 1, 0);
+
+ if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY)
+ _scene->_kernelMessages.initRandomMessages(2,
+ Common::Rect(0, 0, 54, 30), 13, 2, 0xFDFC, 60,
+ 151, 152, 153, 154, 0);
+
+ _monkeyTime = _vm->_game->_scene._frameStartTime;
+ _scrollY = 30;
+
+ _ambushFl = false;
+ _monkeyFrame = 0;
+
+ sceneEntrySound();
+}
+
+void Scene211::step() {
+ if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) {
+ _scene->_kernelMessages.randomServer();
+
+ if (!_ambushFl && !_wakeFl && (_vm->_game->_scene._frameStartTime >= _monkeyTime)) {
+ int chanceMinor = _scene->_kernelMessages.checkRandom() * 4 + 1;
+ if (_scene->_kernelMessages.generateRandom(80, chanceMinor))
+ _vm->_sound->command(18);
+
+ _monkeyTime = _vm->_game->_scene._frameStartTime + 2;
+ }
+
+ if ((_game._player._playerPos == Common::Point(52, 132)) && (_game._player._facing == FACING_WEST) && !_game._player._moving &&
+ (_game._trigger || !_ambushFl)) {
+ switch (_game._trigger) {
+ case 0:
+ if (_game._objects.isInInventory(OBJ_BINOCULARS)) {
+ _ambushFl = true;
+ _monkeyFrame = 0;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_kernelMessages.reset();
+ _scene->loadAnimation(formAnimName('A', -1), 90);
+ _vm->_sound->command(19);
+ int count = (int)_game._objects._inventoryList.size();
+ for (int idx = 0; idx < count; idx++) {
+ if ((_game._objects._inventoryList[idx] == OBJ_BINOCULARS) && (_scene->_userInterface._selectedInvIndex != idx))
+ _scene->_userInterface.selectObject(idx);
+ }
+ }
+ break;
+
+ case 90:
+ _vm->_sound->command(10);
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _game._player._playerPos = Common::Point(49, 133);
+ _ambushFl = false;
+ _globals[kMonkeyStatus] = MONKEY_HAS_BINOCULARS;
+ break;
+ }
+ }
+ }
+
+ if (_ambushFl && (_scene->_activeAnimation->getCurrentFrame() > _monkeyFrame)) {
+ _monkeyFrame = _scene->_activeAnimation->getCurrentFrame();
+ switch (_monkeyFrame) {
+ case 2: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(12, 4), 0xFDFC, 0, 0, 60, _game.getQuote(157));
+ _scene->_kernelMessages.setQuoted(msgIndex, 2, true);
+ }
+ break;
+
+ case 12: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(35, 20), 0xFDFC, 0, 0, 60, _game.getQuote(155));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ }
+ break;
+
+ case 42: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(60, 45), 0xFDFC, 0, 0, 60, _game.getQuote(156));
+ _scene->_kernelMessages.setQuoted(msgIndex, 6, true);
+ }
+ break;
+
+ case 73:
+ _scene->_kernelMessages.add(Common::Point(102, 95), 0xFDFC, 32, 0, 75, _game.getQuote(157));
+ break;
+
+ case 90: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(102, 95), 0xFDFC, 32, 0, 60, _game.getQuote(158));
+ _scene->_kernelMessages.setQuoted(msgIndex, 6, true);
+ }
+ break;
+
+ case 97:
+ _scene->_userInterface.selectObject(-1);
+ _game._objects.removeFromInventory(OBJ_BINOCULARS, 1);
+ break;
+
+ case 177: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(161));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ _scrollY += 14;
+ }
+ break;
+
+ case 181: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(162));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ _scrollY += 14;
+ }
+ break;
+
+ case 188: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(163));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ _scrollY += 14;
+ }
+ break;
+
+ case 200: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(164));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ _scrollY += 14;
+ }
+ break;
+ }
+ }
+
+ if (_wakeFl) {
+ if (_game._trigger == 100) {
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _wakeFl = false;
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() > _monkeyFrame) {
+ _monkeyFrame = _scene->_activeAnimation->getCurrentFrame();
+ switch (_scene->_activeAnimation->getCurrentFrame()) {
+ case 177: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(165));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ _scrollY += 14;
+ }
+ break;
+
+ case 181: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(166));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ _scrollY += 14;
+ }
+ break;
+
+ case 188: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(167));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ _scrollY += 14;
+ }
+ break;
+
+ case 200: {
+ int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(168));
+ _scene->_kernelMessages.setQuoted(msgIndex, 4, true);
+ _scrollY += 14;
+ }
+ break;
+ }
+ }
+ }
+}
+
+void Scene211::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_JUNGLE_PATH) && _game._objects.isInInventory(OBJ_BINOCULARS) && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY)
+ && (_scene->_customDest.x <= 52) && (_scene->_customDest.y >= 132))
+ _game._player.walk(Common::Point(52, 132), FACING_WEST);
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST)) {
+ if (_game._objects.isInInventory(OBJ_BINOCULARS) && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY))
+ _game._player.walk(Common::Point(52, 132), FACING_WEST);
+ else
+ _game._player._walkOffScreenSceneId = 210;
+ }
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_NORTHEAST))
+ _game._player._walkOffScreenSceneId = 207;
+}
+
+void Scene211::actions() {
+ if (_action._lookFlag && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY))
+ _vm->_dialogs->show(21111);
+ else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_PALM_TREE))
+ _vm->_dialogs->show(21116);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUSHY_FERN))
+ _vm->_dialogs->show(21101);
+ else if (_action.isAction(VERB_LOOK, NOUN_JUNGLE_PATH))
+ _vm->_dialogs->show(21102);
+ else if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) {
+ if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) {
+ if (_game._storyMode == STORYMODE_NAUGHTY)
+ _vm->_dialogs->show(21103);
+ else
+ _vm->_dialogs->show(21104);
+ } else {
+ _vm->_dialogs->show(21105);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_THICK_UNDERGROWTH)) {
+ if (_game._storyMode == STORYMODE_NAUGHTY)
+ _vm->_dialogs->show(21106);
+ else
+ _vm->_dialogs->show(21107);
+ } else if (_action.isAction(VERB_LOOK, NOUN_JUNGLE))
+ _vm->_dialogs->show(21108);
+ else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_NORTHEAST))
+ _vm->_dialogs->show(21109);
+ else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_WEST))
+ _vm->_dialogs->show(21110);
+ else if (_action.isAction(VERB_LOOK, NOUN_SLITHERING_SNAKE))
+ _vm->_dialogs->show(21113);
+ else if (_action.isAction(VERB_TAKE, NOUN_SLITHERING_SNAKE))
+ _vm->_dialogs->show(21114);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCKS))
+ _vm->_dialogs->show(21115);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene212::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_BOUNCING_REPTILE);
+}
+
+void Scene212::enter() {
+ // CHECKME: Some useless variables have been remove here
+
+ if (_scene->_priorSceneId == 208) {
+ _game._player._playerPos = Common::Point(195, 85);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(67, 117);
+ _game._player._facing = FACING_NORTHEAST;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene212::step() {
+// CHECKME: Could we move the dino?
+}
+
+void Scene212::preActions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_CAVE_ENTRANCE))
+ _game._player._walkOffScreenSceneId = 111;
+}
+
+void Scene212::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(21209);
+ else if (_action.isAction(VERB_WALK_TOWARDS) && (_action.isObject(NOUN_FIELD_TO_NORTH) || _action.isObject(NOUN_MOUNTAINS)))
+ _scene->_nextSceneId = 208;
+ else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_CAVE))
+ _scene->_nextSceneId = 111;
+ else if (_action.isAction(VERB_LOOK, NOUN_GRASS))
+ _vm->_dialogs->show(21201);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCKS))
+ _vm->_dialogs->show(21202);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE))
+ _vm->_dialogs->show(21203);
+ else if (_action.isAction(VERB_LOOK, NOUN_SKY))
+ _vm->_dialogs->show(21204);
+ else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH))
+ _vm->_dialogs->show(21205);
+ else if (_action.isAction(VERB_LOOK, NOUN_TREES))
+ _vm->_dialogs->show(21206);
+ else if (_action.isAction(VERB_LOOK, NOUN_PLANTS))
+ _vm->_dialogs->show(21207);
+ else if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINS))
+ _vm->_dialogs->show(21208);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene213::setup() {
+ _game._player._spritesPrefix = "";
+
+ // The original is calling Scene2xx::setAAName()
+ _game._aaName = Resources::formatAAName(2);
+}
+
+void Scene213::enter() {
+ if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL)
+ _handSpriteId = _scene->_sprites.addSprites("*METHAND");
+ else if (_globals[kSexOfRex] == REX_MALE)
+ _handSpriteId = _scene->_sprites.addSprites("*REXHAND");
+ else
+ _handSpriteId = _scene->_sprites.addSprites("*ROXHAND");
+
+ teleporterEnter();
+
+ // The original is calling Scene2xx::sceneEntrySound()
+ if (_vm->_musicFlag) {
+ if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL)
+ _vm->_sound->command(1);
+ else
+ _vm->_sound->command(9);
+ } else {
+ _vm->_sound->command(2);
+ }
+}
+
+void Scene213::step() {
+ teleporterStep();
+}
+
+void Scene213::actions() {
+ if (teleporterActions()) {
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL))
+ _vm->_dialogs->show(21301);
+ else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD) || _action.isAction (VERB_INSPECT, NOUN_KEYPAD))
+ _vm->_dialogs->show(21302);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY))
+ _vm->_dialogs->show(21303);
+ else if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT))
+ _vm->_dialogs->show(21304);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEVICE))
+ _vm->_dialogs->show(21305);
+ else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY))
+ _vm->_dialogs->show(21306);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene214::Scene214(MADSEngine *vm) : Scene2xx(vm) {
+ _devilTime = 0;
+ _devilRunningFl = false;
+}
+
+void Scene214::synchronize(Common::Serializer &s) {
+ Scene2xx::synchronize(s);
+
+ s.syncAsUint32LE(_devilTime);
+ s.syncAsByte(_devilRunningFl);
+}
+
+void Scene214::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_CAPTIVE_CREATURE);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene214::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('e', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('t', -1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRD_7");
+
+ _devilTime = _game._player._priorTimer;
+ _devilRunningFl = false;
+
+ if (_game._objects.isInRoom(OBJ_POISON_DARTS)) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(103, 86));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 11);
+ } else {
+ _scene->_hotspots.activate(NOUN_POISON_DARTS, false);
+ }
+
+ if (_game._objects.isInRoom(OBJ_BLOWGUN)) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(90, 87));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13);
+ } else {
+ _scene->_hotspots.activate(NOUN_BLOWGUN, false);
+ }
+
+ if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(191, 152);
+
+ sceneEntrySound();
+}
+
+void Scene214::step() {
+ if ((_game._player._priorTimer - _devilTime > 800) && !_devilRunningFl) {
+ _devilRunningFl = true;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 6, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2);
+ _scene->_dynamicHotspots.add(451, 13, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ }
+
+ if (_devilRunningFl) {
+ switch (_game._trigger) {
+ case 71: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 5, 0, 0);
+ _scene->_sequences.updateTimeout(oldIdx, _globals._sequenceIndexes[3]);
+ _scene->_dynamicHotspots.add(451, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, 8);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ }
+ break;
+
+ case 72: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0);
+ _scene->_sequences.updateTimeout(oldIdx, _globals._sequenceIndexes[3]);
+ _scene->_dynamicHotspots.add(451, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 9, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2);
+ _devilTime = _game._player._priorTimer;
+ _devilRunningFl = false;
+ }
+ break;
+ }
+ }
+}
+
+void Scene214::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(21427);
+ else if (_action.isAction(VERB_WALK_OUTSIDE, NOUN_HUT))
+ _scene->_nextSceneId = 207;
+ else if (_action.isAction(VERB_TAKE, NOUN_POISON_DARTS) && (_game._trigger || _game._objects.isInRoom(OBJ_POISON_DARTS))) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], true, 6, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], true, 6, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _game._objects.addToInventory(OBJ_POISON_DARTS);
+ _scene->_hotspots.activate(NOUN_POISON_DARTS, false);
+ break;
+
+ case 2:
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(48, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_POISON_DARTS, 0x53A5);
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_BLOWGUN) && (_game._trigger || _game._objects.isInRoom(OBJ_BLOWGUN))) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _game._objects.addToInventory(OBJ_BLOWGUN);
+ _scene->_hotspots.activate(NOUN_BLOWGUN, false);
+ break;
+
+ case 2:
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(48, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_BLOWGUN, 0x329);
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_WINDOW))
+ _vm->_dialogs->show(21401);
+ else if (_action.isAction(VERB_LOOK, NOUN_EXPERIMENT_CAGE))
+ _vm->_dialogs->show(21402);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAPTIVE_CREATURE))
+ _vm->_dialogs->show(21403);
+ else if (_action.isAction(VERB_LOOK, NOUN_BEAR_RUG))
+ _vm->_dialogs->show(21404);
+ else if (_action.isAction(VERB_LOOK, NOUN_TROPHY))
+ _vm->_dialogs->show(21405);
+ else if (_action.isAction(VERB_LOOK, NOUN_LARGE_BOWL)) {
+ if (_game._storyMode == STORYMODE_NAUGHTY) {
+ _vm->_dialogs->show(21406);
+ } else {
+ _vm->_dialogs->show(21407);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_SPECIMEN_JARS))
+ _vm->_dialogs->show(21408);
+ else if (_action.isAction(VERB_TAKE, NOUN_LARGE_BOWL) || _action.isAction(VERB_TAKE, NOUN_SPECIMEN_JARS))
+ _vm->_dialogs->show(21409);
+ else if (_action.isAction(VERB_LOOK, NOUN_SHRUNKEN_HEADS))
+ _vm->_dialogs->show(21410);
+ else if (_action.isAction(VERB_TAKE, NOUN_SHRUNKEN_HEADS) || _action.isAction(VERB_TAKE, NOUN_LARGE_HEADS))
+ _vm->_dialogs->show(21411);
+ else if (_action.isAction(VERB_LOOK, NOUN_LARGE_HEADS))
+ _vm->_dialogs->show(21428);
+ else if (_action.isAction(VERB_LOOK, NOUN_POISON_DARTS) && (_action._savedFields._mainObjectSource == 4))
+ _vm->_dialogs->show(21412);
+ else if (_action.isAction(VERB_OPEN, NOUN_EXPERIMENT_CAGE))
+ _vm->_dialogs->show(21414);
+ else if (_action.isAction(VERB_TALKTO, NOUN_CAPTIVE_CREATURE))
+ _vm->_dialogs->show(21415);
+ else if (_action.isAction(VERB_GIVE, NOUN_TWINKIFRUIT, NOUN_CAPTIVE_CREATURE))
+ _vm->_dialogs->show(21416);
+ else if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_CAPTIVE_CREATURE) || _action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_CAPTIVE_CREATURE))
+ _vm->_dialogs->show(21417);
+ else if (_action.isAction(VERB_LOOK, NOUN_BIG_HEADS))
+ _vm->_dialogs->show(21418);
+ else if (_action.isAction(VERB_TAKE, NOUN_BIG_HEADS))
+ _vm->_dialogs->show(21419);
+ else if (_action.isAction(VERB_TAKE, NOUN_BEAR_RUG))
+ _vm->_dialogs->show(21420);
+ else if (_action.isAction(VERB_LOOK, NOUN_FLOOR_OF_HUT))
+ _vm->_dialogs->show(21421);
+ else if (_action.isAction(VERB_LOOK, NOUN_BLOWGUN))
+ _vm->_dialogs->show(21422);
+ else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) {
+ if (_game._objects.isInRoom(OBJ_POISON_DARTS) && _game._objects.isInRoom(OBJ_BLOWGUN)) {
+ _vm->_dialogs->show(21423);
+ } else if (_game._objects.isInRoom(OBJ_POISON_DARTS) && !_game._objects.isInRoom(OBJ_BLOWGUN)) {
+ _vm->_dialogs->show(21424);
+ } else if (!_game._objects.isInRoom(OBJ_POISON_DARTS) && _game._objects.isInRoom(OBJ_BLOWGUN)) {
+ _vm->_dialogs->show(21425);
+ } else {
+ _vm->_dialogs->show(21426);
+ }
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene215::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene215::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0));
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle (_globals._spriteIndexes[1], false, 7, 0, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(235, 83));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ if (_globals[kSexOfRex] == REX_MALE)
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9");
+ else
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_9");
+
+ if (_scene->_priorSceneId == 216) {
+ _game._player._playerPos = Common::Point(140, 119);
+ _game._player._facing = FACING_SOUTHWEST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.addTimer(120, 70);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(204, 152);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ _game.loadQuoteSet(0xA9, 0xAA, 0);
+ sceneEntrySound();
+}
+
+void Scene215::step() {
+ if (_game._trigger == 70) {
+ _scene->_sequences.remove (_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ }
+
+ if (_game._trigger == 71) {
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ }
+}
+
+void Scene215::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(21509);
+ else if (_action.isAction(VERB_TAKE, NOUN_TWINKIFRUIT)) {
+ if (!_game._objects.isInInventory(OBJ_TWINKIFRUIT) || _game._trigger) {
+ switch (_game._trigger) {
+ case 0:
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_LOOP, 0, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ } else {
+ _game._objects.addToInventory(OBJ_TWINKIFRUIT);
+ _vm->_dialogs->showItem(OBJ_TWINKIFRUIT, 0x5404);
+ }
+ break;
+
+ case 1:
+ if (!_game._objects.isInInventory(OBJ_TWINKIFRUIT)) {
+ _game._objects.addToInventory(OBJ_TWINKIFRUIT);
+ _vm->_dialogs->showItem(OBJ_TWINKIFRUIT, 0x5404);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ break;
+ }
+ } else {
+ int idx = _vm->getRandomNumber(169, 170);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(idx));
+ }
+ } else if (_action.isAction(VERB_WALK_OUTSIDE, NOUN_HUT))
+ _scene->_nextSceneId = 210;
+ else if (_action.isAction(VERB_LOOK, NOUN_BEAR_RUG))
+ _vm->_dialogs->show(21501);
+ else if (_action.isAction(VERB_LOOK, NOUN_BED))
+ _vm->_dialogs->show(21502);
+ else if (_action.isAction(VERB_LOOK, NOUN_WELCOME_MAT))
+ _vm->_dialogs->show(21503);
+ else if (_action.isAction(VERB_LOOK, NOUN_LOVE_ALTAR))
+ _vm->_dialogs->show(21504);
+ else if (_action.isAction(VERB_LOOK, NOUN_WINDOW))
+ _vm->_dialogs->show(21505);
+ else if (_action.isAction(VERB_LOOK, NOUN_PICTURE))
+ _vm->_dialogs->show(21506);
+ else if (_action.isAction(VERB_LOOK, NOUN_TWINKIFRUIT) && (_action._savedFields._mainObjectSource == 4))
+ _vm->_dialogs->show(21507);
+ else if (_action.isAction(VERB_TAKE, NOUN_BEAR_RUG))
+ _vm->_dialogs->show(21510);
+ else if (_action.isAction(VERB_TAKE, NOUN_LOVE_ALTAR))
+ _vm->_dialogs->show(21511);
+ else if (_action.isAction(VERB_LOOK, NOUN_BAG_OF_TWINKIFRUITS))
+ _vm->_dialogs->show(21512);
+ else if (_action.isAction(VERB_TAKE, NOUN_BAG_OF_TWINKIFRUITS))
+ _vm->_dialogs->show(21513);
+ else if (_action.isAction(VERB_TAKE, NOUN_WELCOME_MAT))
+ _vm->_dialogs->show(21514);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene216::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene216::enter() {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+
+ _scene->_userInterface.emptyConversationList();
+ _scene->_userInterface.setup(kInputConversation);
+ _scene->loadAnimation(formAnimName('A', -1), 60);
+
+ sceneEntrySound();
+}
+
+void Scene216::step() {
+ if (_game._trigger == 60)
+ _scene->_nextSceneId = 215;
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Nebular
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes2.h b/engines/mads/nebular/nebular_scenes2.h
new file mode 100644
index 0000000000..c860db9470
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes2.h
@@ -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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_NEBULAR_SCENES2_H
+#define MADS_NEBULAR_SCENES2_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+class Scene2xx : public NebularScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void setAAName();
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix();
+
+ void sceneEntrySound();
+public:
+ Scene2xx(MADSEngine *vm) : NebularScene(vm) {}
+};
+
+class Scene201 : public Scene2xx {
+private:
+ bool _pterodactylFlag;
+
+public:
+ Scene201(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene202 : public Scene2xx {
+private:
+ bool _activeMsgFl, _ladderTopFl, _waitingMeteoFl, _toStationFl, _toTeleportFl;
+ int _ladderHotspotId, _lastRoute, _stationCounter, _meteoFrame;
+ uint32 _meteoClock1, _meteoClock2, _startTime;
+ bool _meteorologistSpecial;
+
+ int subStep1(int randVal);
+ int subStep2(int randVal);
+ int subStep3(int randVal);
+ int subStep4(int randVal);
+
+public:
+ Scene202(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+
+ void setRandomKernelMessage();
+};
+
+class Scene203 : public Scene2xx {
+private:
+ bool _rhotundaEat2Fl, _rhotundaEatFl;
+
+public:
+ Scene203(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene205 : public Scene2xx {
+private:
+ uint32 _lastFishTime, _chickenTime;
+ bool _beingKicked;
+ int _kernelMessage;
+ Conversation _dialog1;
+
+ void handleWomanSpeech(int quoteId);
+
+public:
+ Scene205(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene207 : public Scene2xx {
+private:
+ bool _vultureFl, _spiderFl, _eyeFl;
+ int _spiderHotspotId, _vultureHotspotId;
+ int32 _spiderTime, _vultureTime;
+
+ void moveVulture();
+ void moveSpider();
+
+public:
+ Scene207(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene208 : public Scene2xx {
+private:
+ bool _rhotundaTurnFl, _boundingFl;
+ int32 _rhotundaTime;
+
+ void updateTrap();
+ void subAction(int mode);
+
+public:
+ Scene208(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene209 : public Scene2xx {
+private:
+ bool _dodgeFl, _forceDodgeFl, _shouldDodgeFl;
+ bool _pitchFl;
+ bool _fallFl, _forceFallFl, _shouldFallFl;
+ bool _playingAnimFl, _playingDialogFl;
+ int _pauseMode, _pauseCounterThreshold, _pauseCounter;
+ bool _removeMonkeyFl;
+ int _monkeyPosition;
+ bool _shootReadyFl, _startShootingInTimerFl, _shootMissedLastFl;
+ bool _binocularsDroppedFl;
+ int _dialogAbortVal;
+ int _counter;
+
+ void handlePause();
+ void initPauseCounterThreshold();
+ void handlePeek();
+ void handleVerticalMove();
+ void handleLookStay();
+ void handleLookRight();
+ void handleBlink();
+ void handleGetBinoculars();
+ void handleStandFromPeek();
+ void handleDodge();
+ void handleBinocularBlink();
+ void handleBinocularScan();
+ void handleJumpInTree();
+ void handleTongue();
+ void handleMonkeyFall();
+ void handleJumpAndHide();
+ void handleMonkeyEating();
+ void handleMonkey1();
+ void handleStandBlink();
+ void handleMonkey2();
+
+public:
+ Scene209(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene210 : public Scene2xx {
+private:
+ int _curDialogNode;
+ int _nextHandsPlace;
+ int _twinkleAnimationType;
+ int _twinklesCurrentFrame;
+ bool _shouldTalk, _shouldFaceRex, _shouldMoveHead;
+ bool _stopWalking;
+ bool _twinklesTalking;
+ bool _twinklesTalk2;
+ int _doorway;
+ Common::String _subQuote2;
+ Conversation _conv1, _conv2, _conv3;
+ Conversation _conv5, _conv6, _conv7, _conv8;
+
+ void handleConversations();
+ void handleConversation1();
+ void handleConversation2();
+ void handleConversation3();
+ void handleConversation5();
+ void handleConversation6();
+ void handleConversation7();
+ void handleConversation8();
+ void setDialogNode(int node);
+ void handleTwinklesSpeech(int quoteId, int shiftX, uint32 delay);
+ void newNode(int node);
+ void restoreDialogNode(int node, int msgId, int posY);
+
+public:
+ Scene210(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene211 : public Scene2xx {
+private:
+ bool _ambushFl, _wakeFl;
+ int _monkeyFrame, _scrollY;
+ uint32 _monkeyTime;
+
+public:
+ Scene211(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene212 : public Scene2xx {
+public:
+ Scene212(MADSEngine *vm) : Scene2xx(vm) {}
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene213 : public SceneTeleporter {
+public:
+ Scene213(MADSEngine *vm) : SceneTeleporter(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene214 : public Scene2xx {
+private:
+ uint32 _devilTime;
+ bool _devilRunningFl;
+
+public:
+ Scene214(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene215 : public Scene2xx {
+public:
+ Scene215(MADSEngine *vm) : Scene2xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene216 : public Scene2xx {
+public:
+ Scene216(MADSEngine *vm) : Scene2xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions() {};
+};
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES2_H */
diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp
new file mode 100644
index 0000000000..bcedf95a27
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes3.cpp
@@ -0,0 +1,5820 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes3.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+void Scene3xx::setAAName() {
+ _game._aaName = Resources::formatAAName(4);
+}
+
+void Scene3xx::setPlayerSpritesPrefix() {
+ _vm->_sound->command(5);
+
+ Common::String oldName = _game._player._spritesPrefix;
+
+ if (_globals[kSexOfRex] == REX_MALE)
+ _game._player._spritesPrefix = "RXM";
+ else
+ _game._player._spritesPrefix = "ROX";
+
+ if ((_scene->_nextSceneId == 313) || (_scene->_nextSceneId == 366)
+ || ((_scene->_nextSceneId >= 301) && (_scene->_nextSceneId <= 303))
+ || ((_scene->_nextSceneId == 304) && (_scene->_currentSceneId == 303))
+ || ((_scene->_nextSceneId == 311) && (_scene->_currentSceneId == 304))
+ || ((_scene->_nextSceneId >= 308) && (_scene->_nextSceneId <= 310))
+ || ((_scene->_nextSceneId >= 319) && (_scene->_nextSceneId <= 322))
+ || ((_scene->_nextSceneId >= 387) && (_scene->_nextSceneId <= 391))) {
+ _game._player._spritesPrefix = "";
+ _game._player._spritesChanged = true;
+ }
+
+ _game._player._scalingVelocity = true;
+ if (oldName != _game._player._spritesPrefix)
+ _game._player._spritesChanged = true;
+
+ _vm->_palette->setEntry(16, 10, 63, 63);
+ _vm->_palette->setEntry(17, 10, 45, 45);
+}
+
+void Scene3xx::sceneEntrySound() {
+ if (!_vm->_musicFlag) {
+ _vm->_sound->command(2);
+ return;
+ }
+
+ switch (_scene->_nextSceneId) {
+ case 301:
+ case 302:
+ case 303:
+ case 304:
+ case 308:
+ case 309:
+ case 310:
+ _vm->_sound->command(11);
+ break;
+
+ case 311:
+ if (_scene->_priorSceneId == 304)
+ _vm->_sound->command(11);
+ else
+ _vm->_sound->command(10);
+ break;
+
+ case 313:
+ case 316:
+ case 320:
+ case 322:
+ case 357:
+ case 358:
+ case 359:
+ case 360:
+ case 361:
+ case 387:
+ case 388:
+ case 389:
+ case 390:
+ case 391:
+ case 399:
+ _vm->_sound->command(10);
+ break;
+
+ case 318:
+ if ((_scene->_priorSceneId == 357) || (_scene->_priorSceneId == 407))
+ _vm->_sound->command(10);
+ else if (_scene->_priorSceneId == 319)
+ _vm->_sound->command(16);
+ else
+ _vm->_sound->command(3);
+
+ _vm->_sound->command(50);
+ break;
+
+ case 319:
+ _vm->_sound->command(16);
+ break;
+
+ case 321:
+ _vm->_sound->command(18);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene3xx::initForceField(ForceField *force, bool flag) {
+ force->_flag = flag;
+ force->_vertical = 0;
+ force->_horizontal = 0;
+ force->_timer = 0;
+
+ for (int count = 0; count < 40; count++)
+ force->_seqId[count] = -1;
+
+ if (force->_flag)
+ _vm->_sound->command(24);
+}
+
+int Scene3xx::computeScale(int low, int high, int id) {
+ int diff = high - (low + 2);
+ int quotient = diff / 20;
+ int remainder = diff % 20;
+ int value = low + 2 + (quotient * id) + (remainder / (id + 1));
+
+ return (value);
+}
+
+void Scene3xx::handleForceField(ForceField *force, int *sprites) {
+ if (_game._trigger >= 150) {
+ int id = _game._trigger - 150;
+ if (id < 40) {
+ if (id < 20)
+ force->_vertical--;
+ else
+ force->_horizontal--;
+
+ force->_seqId[id] = -1;
+ }
+ return;
+ }
+
+ if (!force->_flag || (_scene->_frameStartTime < force->_timer) || (force->_vertical + force->_horizontal >= 5))
+ return;
+
+ if (_vm->getRandomNumber(1, 1000) <= (200 + ((40 - (force->_vertical + force->_horizontal)) << 5))) {
+ int id = -1;
+ for (int i = 0; i < 100; i++) {
+ int randIdx = _vm->getRandomNumber(0, 39);
+ if (force->_seqId[randIdx] < 0) {
+ id = randIdx;
+ break;
+ }
+ }
+
+ if (id < 0) {
+ for (int i = 0; i < 40; i++) {
+ if (force->_seqId[i] < 0) {
+ id = i;
+ break;
+ }
+ }
+ }
+
+ int speedX, speedY;
+ int posX, posY;
+ int randVal = _vm->getRandomNumber(1, 100);
+ int spriteId;
+ bool mirror;
+
+ if (id >= 20) {
+ spriteId = 2;
+ mirror = (randVal <= 50);
+ posX = mirror ? 315 : 5;
+ posY = computeScale(15, 119, id - 20);
+ speedX = 1000 * (mirror ? -1 : 1);
+ speedY = 0;
+ } else if (randVal <= 50) {
+ spriteId = 1;
+ mirror = false;
+ posX = computeScale(21, 258, id);
+ posY = 0;
+ speedX = 0;
+ speedY = 600;
+ } else {
+ spriteId = 0;
+ mirror = false;
+ posX = computeScale(21, 258, id);
+ posY = 155;
+ speedX = 0;
+ speedY = -600;
+ }
+
+ if (id >= 0) {
+ force->_seqId[id] = _scene->_sequences.addSpriteCycle(sprites[spriteId], mirror, 2, 0, 0, 0);
+ _scene->_sequences.setDepth(force->_seqId[id], 8);
+ _scene->_sequences.setPosition(force->_seqId[id], Common::Point(posX, posY));
+ _scene->_sequences.setMotion(force->_seqId[id], 2, speedX, speedY);
+ _scene->_sequences.addSubEntry(force->_seqId[id], SEQUENCE_TRIGGER_EXPIRE, 0, 150 + id);
+ if (spriteId == 2)
+ force->_horizontal++;
+ else
+ force->_vertical++;
+ }
+ }
+
+ force->_timer = _scene->_frameStartTime + 4;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene300s::preActions() {
+ _game._player._needToWalk = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene301::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene301::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0);
+
+ _globals[kMeteorologistStatus] = METEOROLOGIST_GONE;
+ _globals[kTeleporterCommand] = TELEPORTER_NONE;
+
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->loadAnimation(formAnimName('a', -1), 60);
+
+ sceneEntrySound();
+}
+
+void Scene301::step() {
+ if (_game._trigger == 60)
+ _scene->_nextSceneId = 302;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene302::Scene302(MADSEngine *vm) : Scene3xx(vm) {
+ _oldFrame = 0;
+}
+
+void Scene302::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsSint32LE(_oldFrame);
+}
+
+void Scene302::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene302::enter() {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+
+ _scene->loadAnimation(formAnimName('a', -1), 71);
+ sceneEntrySound();
+}
+
+void Scene302::step() {
+ if (_game._trigger == 71)
+ _scene->_nextSceneId = 303;
+
+ if ((_scene->_activeAnimation != nullptr) && (_scene->_activeAnimation->getCurrentFrame() != _oldFrame)) {
+ _oldFrame = _scene->_activeAnimation->getCurrentFrame();
+ if (_oldFrame == 147) {
+ _game._objects.setRoom(OBJ_POISON_DARTS, 1);
+ _game._objects.setRoom(OBJ_BLOWGUN, 1);
+ _game._objects.setRoom(OBJ_REBREATHER, 1);
+ _game._objects.setRoom(OBJ_STUFFED_FISH, 1);
+ _game._objects.setRoom(OBJ_DEAD_FISH, 1);
+ _game._objects.setRoom(OBJ_BURGER, 1);
+
+ int count = (int)_game._objects.size();
+ for (int idx = 0; idx < count; idx++) {
+ if (_game._objects.isInInventory(idx))
+ _game._objects.setRoom(idx, 50);
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene303::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene303::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1));
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 0, 50, 120);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 10, 0, 0, 0);
+
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('a', -1), 60);
+
+ sceneEntrySound();
+}
+
+void Scene303::step() {
+ if (_game._trigger == 60)
+ _scene->_nextSceneId = 304;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene304::Scene304(MADSEngine *vm) : Scene3xx(vm) {
+ _explosionSpriteId = -1;
+}
+
+void Scene304::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsSint32LE(_explosionSpriteId);
+}
+
+void Scene304::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene304::enter() {
+ if (_scene->_priorSceneId == 303) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('a', -1), 60);
+ } else {
+ if (_globals[kSexOfRex] == REX_MALE)
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ else
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2));
+
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 0));
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 150, 0, 3, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2);
+ _vm->_palette->setEntry(252, 45, 63, 45);
+ _vm->_palette->setEntry(253, 20, 45, 20);
+
+ if (_globals[kSexOfRex] == REX_MALE)
+ _game._player._playerPos = Common::Point(111, 117);
+ else
+ _game._player._playerPos = Common::Point(113, 116);
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 11, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -1);
+ _scene->_sequences.addTimer(48, 70);
+ }
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0xEB, 0xEC, 0);
+}
+
+void Scene304::step() {
+ if (_game._trigger == 60)
+ _scene->_nextSceneId = 311;
+
+ if (_game._trigger >= 70) {
+ switch (_game._trigger) {
+ case 70: {
+ _game._player._visible = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ if (_globals[kSexOfRex] == REX_MALE)
+ _explosionSpriteId = _globals._spriteIndexes[1];
+ else
+ _explosionSpriteId = _globals._spriteIndexes[4];
+
+ int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(sprIdx, -1, 4);
+ _scene->_sequences.setDepth(sprIdx, 1);
+ _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 74);
+ }
+ break;
+
+ case 71:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0xEB));
+ _scene->_sequences.addTimer(1, 72);
+ break;
+
+ case 72: {
+ _vm->_sound->command(43);
+ int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(sprIdx, 5, -2);
+ _scene->_sequences.setDepth(sprIdx, 1);
+ _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 73);
+ if (_game._storyMode == STORYMODE_NICE)
+ _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_SPRITE, 8, 78);
+ }
+ break;
+
+ case 73: {
+ int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 0, 0, 0);
+ _scene->_sequences.setAnimRange(sprIdx, -2, -2);
+ _scene->_sequences.setDepth(sprIdx, 1);
+ }
+ break;
+
+ case 74:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 75);
+ break;
+
+ case 75:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 76);
+ break;
+
+ case 76:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 2);
+ _scene->_sequences.addTimer(48, 77);
+ break;
+
+ case 77:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(211, 45), 0xFDFC, 32, 0, 180, _game.getQuote(0xEC));
+ _scene->_sequences.addTimer(120, 78);
+ break;
+
+ case 78:
+ _scene->_nextSceneId = 316;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene307::Scene307(MADSEngine *vm) : Scene3xx(vm) {
+ _afterPeeingFl = false;
+ _duringPeeingFl = false;
+ _grateOpenedFl = false;
+ _activePrisonerFl = false;
+
+ _animationMode = -1;
+ _prisonerMessageId = -1;
+ _fieldCollisionCounter = -1;
+
+ _lastFrameTime = 0;
+ _guardTime = 0;
+ _prisonerTimer = 0;
+
+ _subQuote2 = "";
+
+ _forceField.init();
+}
+
+void Scene307::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ _forceField.synchronize(s);
+
+ s.syncAsByte(_afterPeeingFl);
+ s.syncAsByte(_duringPeeingFl);
+ s.syncAsByte(_grateOpenedFl);
+ s.syncAsByte(_activePrisonerFl);
+
+ s.syncAsSint32LE(_animationMode);
+ s.syncAsSint32LE(_prisonerMessageId);
+ s.syncAsSint32LE(_fieldCollisionCounter);
+
+ s.syncAsUint32LE(_lastFrameTime);
+ s.syncAsUint32LE(_guardTime);
+ s.syncAsUint32LE(_prisonerTimer);
+
+ s.syncString(_subQuote2);
+}
+
+void Scene307::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_AIR_VENT);
+ _scene->addActiveVocab(NOUN_CLIMB_INTO);
+}
+
+void Scene307::handleRexDialog(int quote) {
+ Common::String curQuote = _game.getQuote(_action._activeAction._verbId);
+ if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) {
+ Common::String subQuote1;
+ _game.splitQuote(curQuote, subQuote1, _subQuote2);
+ _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 240, subQuote1);
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 180, _subQuote2);
+ } else
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote);
+}
+
+void Scene307::handlePrisonerEncounter() {
+ switch (_action._activeAction._verbId) {
+ case 275:
+ setDialogNode(5);
+ break;
+
+ case 277:
+ setDialogNode(4);
+ break;
+
+ case 276:
+ setDialogNode(6);
+ break;
+ }
+}
+
+void Scene307::handlePrisonerSpeech(int firstQuoteId, int number, long timeout) {
+ int height = number * 14;
+ int posY;
+
+ if (height < 60)
+ posY = 65 - height;
+ else
+ posY = 78 - (height / 2);
+
+ _scene->_kernelMessages.reset();
+ _activePrisonerFl = true;
+
+ int quoteId = firstQuoteId;
+ for (int count = 0; count < number; count++) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_kernelMessages.add(Common::Point(5, posY), 0xFDFC, 0, 81, timeout, _game.getQuote(quoteId));
+ posY += 14;
+ quoteId++;
+ }
+}
+
+void Scene307::setDialogNode(int node) {
+ switch (node) {
+ case 0:
+ handlePrisonerSpeech(0x153, 2, 120);
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ break;
+
+ case 1:
+ _globals[kMetBuddyBeast] = true;
+ handlePrisonerSpeech(0x10F, 2, 9999999);
+ _dialog1.start();
+ break;
+
+ case 2:
+ _globals[kMetBuddyBeast] = true;
+ handlePrisonerSpeech(0x111, 2, 9999999);
+ _dialog1.start();
+ break;
+
+ case 4:
+ handlePrisonerSpeech(0x116, 1, 120);
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ break;
+
+ case 5:
+ _globals[kKnowsBuddyBeast] = true;
+ handlePrisonerSpeech(0x117, 2, 9999999);
+ _dialog2.start();
+ break;
+
+ case 6:
+ handlePrisonerSpeech(0x123, 1, 120);
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ break;
+
+ case 7:
+ _globals[kKnowsBuddyBeast] = true;
+ handlePrisonerSpeech(0x124, 10, 9999999);
+ _dialog2.write(0x11A, false);
+ _dialog2.write(0x11B, true);
+ _dialog2.write(0x120, true);
+ _dialog2.start();
+ break;
+
+ case 8:
+ handlePrisonerSpeech(0x12E, 6, 9999999);
+ _dialog2.write(0x11A, false);
+ _dialog2.write(0x11B, false);
+ _dialog2.write(0x11C, true);
+ _dialog2.write(0x11D, true);
+ _dialog2.write(0x11F, true);
+ _dialog2.start();
+ break;
+
+ case 9:
+ handlePrisonerSpeech(0x134, 4, 9999999);
+ _dialog2.write(0x11D, false);
+ _dialog2.start();
+ break;
+
+ case 10:
+ handlePrisonerSpeech(0x138, 6, 9999999);
+ _dialog2.write(0x11E, false);
+ _dialog2.start();
+ break;
+
+ case 11:
+ handlePrisonerSpeech(0x13E, 6, 9999999);
+ _dialog2.write(0x11F, false);
+ _dialog2.write(0x121, true);
+ _dialog2.start();
+ break;
+
+ case 12:
+ handlePrisonerSpeech(0x144, 4, 9999999);
+ _dialog2.write(0x11C, false);
+ _dialog2.start();
+ break;
+
+ case 13:
+ handlePrisonerSpeech(0x148, 7, 9999999);
+ _dialog2.write(0x120, false);
+ _dialog2.start();
+ break;
+
+ case 14:
+ handlePrisonerSpeech(0x14F, 3, 9999999);
+ _dialog2.write(0x121, false);
+ _dialog2.start();
+ break;
+
+ case 15:
+ handlePrisonerSpeech(0x152, 1, 120);
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ break;
+
+ case 16:
+ _globals[kKnowsBuddyBeast] = true;
+ handlePrisonerSpeech(0x10C, 1, 9999999);
+ _dialog2.start();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene307::handlePrisonerDialog() {
+ switch (_action._activeAction._verbId) {
+ case 0x11A:
+ setDialogNode(7);
+ break;
+
+ case 0x11B:
+ setDialogNode(8);
+ break;
+
+ case 0x11C:
+ setDialogNode(12);
+ break;
+
+ case 0x11D:
+ setDialogNode(9);
+ break;
+
+ case 0x11E:
+ setDialogNode(10);
+ break;
+
+ case 0x11F:
+ setDialogNode(11);
+ break;
+
+ case 0x120:
+ setDialogNode(13);
+ break;
+
+ case 0x121:
+ setDialogNode(14);
+ break;
+
+ case 0x122:
+ setDialogNode(15);
+ break;
+ }
+}
+
+void Scene307::handleDialog() {
+ if (_game._trigger == 0) {
+ _scene->_kernelMessages.reset();
+ _game._player._stepEnabled = false;
+ handleRexDialog(_action._activeAction._verbId);
+ } else {
+ _game._player._stepEnabled = true;
+
+ if (!_globals[kKnowsBuddyBeast]) {
+ handlePrisonerEncounter();
+ } else {
+ handlePrisonerDialog();
+ }
+ }
+}
+
+void Scene307::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0");
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1");
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2");
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 0));
+
+ initForceField(&_forceField, true);
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15);
+
+ _animationMode = 0;
+ _fieldCollisionCounter = 0;
+
+ _scene->changeVariant(1);
+
+ _game.loadQuoteSet(0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0x10C, 0x104, 0x106, 0x107, 0x108, 0x105,
+ 0x109, 0x10A, 0x10B, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117,
+ 0x118, 0x119, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, 0x122, 0x123, 0x124, 0x125,
+ 0x126, 0x127, 0x128, 0x129, 0x12A, 0x12B, 0x12C, 0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x132, 0x133,
+ 0x134, 0x135, 0x136, 0x137, 0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141,
+ 0x142, 0x143, 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14A, 0x14B, 0x14C, 0x14D, 0x14E, 0x14F,
+ 0x150, 0x151, 0x152, 0x153, 0);
+
+ _dialog1.setup(0x3F, 0x113, 0x114, 0x115, -1);
+ _dialog2.setup(0x40, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, 0x122, 0);
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _dialog2.set(0x11A, 0x122, 0);
+ else if (_scene->_priorSceneId == 318)
+ _dialog2.write(0x11E, true);
+
+
+ if (_scene->_priorSceneId == -2) {
+ if (_grateOpenedFl)
+ _vm->_sound->command(10);
+ else
+ _vm->_sound->command(3);
+ } else {
+ _afterPeeingFl = false;
+ _duringPeeingFl = false;
+ _guardTime = 0;
+ _grateOpenedFl = false;
+ _activePrisonerFl = false;
+ _prisonerTimer = 0;
+ _prisonerMessageId = 0x104;
+
+ if (_scene->_priorSceneId == 308) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _game._player._playerPos = Common::Point(156, 113);
+ _game._player._facing = FACING_NORTH;
+ _animationMode = 1;
+ _vm->_sound->command(11);
+ _scene->loadAnimation(formAnimName('a', -1), 60);
+ } else if (_scene->_priorSceneId == 387) {
+ _game._player._playerPos = Common::Point(129, 108);
+ _game._player._facing = FACING_NORTH;
+ _vm->_sound->command(3);
+ _grateOpenedFl = true;
+ } else {
+ _game._player._playerPos = Common::Point(159, 109);
+ _game._player._facing = FACING_SOUTH;
+ _vm->_sound->command(3);
+ }
+ }
+
+ if (_grateOpenedFl) {
+ _scene->_hotspots.activate(17, false);
+
+ int idx = _scene->_dynamicHotspots.add(17, VERB_CLIMB_INTO, -1, Common::Rect(117, 67, 117 + 19, 67 + 13));
+ int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(129, 104), FACING_NORTH);
+ _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_UP);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15);
+ }
+
+ _vm->_palette->setEntry(252, 63, 30, 20);
+ _vm->_palette->setEntry(253, 45, 15, 12);
+
+ sceneEntrySound();
+
+ if ((_scene->_priorSceneId == 318) || (_scene->_priorSceneId == 387))
+ _scene->_kernelMessages.addQuote(0xF3, 0, 120);
+}
+
+void Scene307::step() {
+ handleForceField(&_forceField, &_globals._spriteIndexes[0]);
+
+ if ((_animationMode == 1) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() == 126) {
+ _forceField._flag = false;
+ _vm->_sound->command(5);
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 194) {
+ _forceField._flag = true;
+ _vm->_sound->command(24);
+ }
+ }
+
+ if ((_animationMode == 2) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() == 54)
+ _forceField._flag = false;
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 150) {
+ _game._player._visible = false;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ }
+ }
+
+ if (_game._trigger == 60) {
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _animationMode = 0;
+ _vm->_sound->command(9);
+ }
+
+ if ((_lastFrameTime != _scene->_frameStartTime) && !_duringPeeingFl) {
+ int32 elapsedTime = _lastFrameTime - _scene->_frameStartTime;
+ if ((elapsedTime > 0) && (elapsedTime <= 4)) {
+ _guardTime += elapsedTime;
+ _prisonerTimer += elapsedTime;
+ } else {
+ _guardTime++;
+ _prisonerTimer++;
+ }
+ _lastFrameTime = _scene->_frameStartTime;
+
+ if ((_guardTime > 3000) && !_duringPeeingFl && (_scene->_activeAnimation == nullptr)
+ && (_game._screenObjects._inputMode != kInputConversation) && _globals[kMetBuddyBeast] && !_activePrisonerFl) {
+ if (!_game._objects.isInInventory(OBJ_SCALPEL) && !_grateOpenedFl) {
+ _game._player._stepEnabled = false;
+ _game._player.walk(Common::Point(151, 119), FACING_SOUTHEAST);
+ _animationMode = 2;
+ _vm->_sound->command(11);
+ _scene->loadAnimation(formAnimName('b', -1), 70);
+ }
+ _guardTime = 0;
+ } else if ((_prisonerTimer > 300) && (_game._screenObjects._inputMode != kInputConversation) && (_scene->_activeAnimation == nullptr) && !_activePrisonerFl) {
+ if (!_globals[kMetBuddyBeast]) {
+ int idx = _scene->_kernelMessages.add(Common::Point(5, 51), 0xFDFC, 0, 81, 120, _game.getQuote(_prisonerMessageId));
+ _scene->_kernelMessages.setQuoted(idx, 4, true);
+ _prisonerMessageId++;
+ if (_prisonerMessageId > 0x10A)
+ _prisonerMessageId = 0x104;
+ } else if (_globals[kKnowsBuddyBeast] && (_dialog2.read(0) > 1) && (_vm->getRandomNumber(1, 3) == 1)) {
+ int idx = _scene->_kernelMessages.add(Common::Point(5, 51), 0xFDFC, 0, 81, 120, _game.getQuote(267));
+ _scene->_kernelMessages.setQuoted(idx, 4, true);
+ }
+ _prisonerTimer = 0;
+ }
+ }
+
+ if (_game._trigger == 70)
+ _scene->_nextSceneId = 318;
+
+ if (_game._trigger == 81) {
+ _prisonerTimer = 0;
+ if (_activePrisonerFl && (_guardTime > 2600))
+ _guardTime = 3000 - _vm->getRandomNumber(1, 800);
+
+ _activePrisonerFl = false;
+ }
+}
+
+void Scene307::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(30715);
+ else if (_game._screenObjects._inputMode == kInputConversation)
+ handleDialog();
+ else if (_action.isAction(VERB_TALKTO, NOUN_CELL_WALL) || _action.isAction(VERB_TALKTO, NOUN_WALL) || _action.isAction(VERB_TALKTO, NOUN_TOILET)) {
+ int node, say;
+ if (_globals[kKnowsBuddyBeast]) {
+ say = 0x10E;
+ node = 16;
+ } else if (_globals[kMetBuddyBeast]) {
+ say = 0x10E;
+ node = 2;
+ } else {
+ say = 0x10D;
+ node = 1;
+ }
+
+ switch (_game._trigger) {
+ case 0:
+ handleRexDialog(say);
+ break;
+
+ case 1:
+ setDialogNode(node);
+ break;
+ }
+ } else if (_action.isAction(VERB_PRY, NOUN_SCALPEL, NOUN_AIR_VENT)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(239));
+ _scene->_sequences.addTimer(120, 1);
+ break;
+
+ case 1:
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXCL_8");
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], -1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2: {
+ int oldIdx = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 12, 6, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 2, 3);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ }
+ break;
+
+ case 3: {
+ int oldIdx = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx);
+ _scene->_sequences.addTimer(48, 4);
+ }
+ break;
+
+ case 4:
+ _vm->_sound->command(26);
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15);
+ _scene->_sequences.addTimer(90, 5);
+ break;
+
+ case 5:
+ _vm->_sound->command(10);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(241));
+ _scene->_sequences.addTimer(120, 6);
+ break;
+
+ case 6: {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _grateOpenedFl = true;
+ _scene->_hotspots.activate(17, false);
+ int idx = _scene->_dynamicHotspots.add(17, NOUN_CLIMB_INTO, -1, Common::Rect(117, 67, 117 + 19, 67 + 13));
+ int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(129, 104), FACING_NORTH);
+ _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_UP);
+ _game._objects.removeFromInventory(OBJ_SCALPEL, NOWHERE);
+ _scene->_kernelMessages.addQuote(0xF2, 7, 120);
+ }
+ break;
+
+ case 7:
+ _scene->_sprites.remove(_globals._spriteIndexes[5]);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) {
+ if (_grateOpenedFl) {
+ switch (_game._trigger) {
+ case 0:
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXCL_8");
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 60, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 3, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], -1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15);
+ break;
+
+ case 2: {
+ int oldIdx = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 4, 10);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ }
+ break;
+
+ case 3:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 3);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 11);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102));
+ _scene->_sequences.addTimer(48, 4);
+ break;
+
+ case 4:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 12, 14);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 5);
+ break;
+
+ case 5:
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 15);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102));
+ _scene->_sequences.addTimer(48, 6);
+ break;
+
+ case 6:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ _scene->_sequences.addTimer(48, 7);
+ break;
+
+ case 7:
+ _scene->_nextSceneId = 313;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action.isAction(VERB_USE, NOUN_TOILET) && (_game._storyMode != STORYMODE_NAUGHTY))
+ _vm->_dialogs->show(30723);
+ else if (_action.isAction(VERB_USE, NOUN_TOILET)) {
+ if (!_afterPeeingFl) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_sound->command(25);
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _duringPeeingFl = true;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 5, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]);
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(48, 3);
+ break;
+
+ case 3: {
+ _scene->_sprites.remove(_globals._spriteIndexes[3]);
+ _scene->_kernelMessages.reset();
+ int idx = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 4, 120, _game.getQuote(237));
+ _scene->_kernelMessages.setQuoted(idx, 4, true);
+ }
+ break;
+
+ case 4:
+ _game._player._stepEnabled = true;
+ _duringPeeingFl = false;
+ _afterPeeingFl = true;
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ _scene->_kernelMessages.reset();
+ int idx = _scene->_kernelMessages.add(Common::Point(85, 39), 0x1110, 0, 0, 180, _game.getQuote(238));
+ _scene->_kernelMessages.setQuoted(idx, 4, true);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) {
+ if (!_grateOpenedFl)
+ _vm->_dialogs->show(30710);
+ else
+ _vm->_dialogs->show(30711);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BED))
+ _vm->_dialogs->show(30712);
+ else if (_action.isAction(VERB_LOOK, NOUN_SINK))
+ _vm->_dialogs->show(30713);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOILET))
+ _vm->_dialogs->show(30714);
+ else if (_action.isAction(VERB_SHARPEN, NOUN_SCALPEL))
+ _vm->_dialogs->show(30716);
+ else if (_action.isAction(VERB_LOOK, NOUN_CELL_WALL))
+ _vm->_dialogs->show(30717);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHT))
+ _vm->_dialogs->show(30718);
+ else if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR)) {
+ switch (_fieldCollisionCounter) {
+ case 0:
+ _vm->_dialogs->show(30719);
+ _fieldCollisionCounter = 1;
+ break;
+
+ case 1:
+ _vm->_dialogs->show(30720);
+ _fieldCollisionCounter = 2;
+ break;
+
+ case 2:
+ _vm->_dialogs->show(30721);
+ _fieldCollisionCounter = 3;
+ break;
+
+ case 3:
+ _vm->_dialogs->show(30722);
+ break;
+ }
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene308::Scene308(MADSEngine *vm) : Scene3xx(vm) {
+ _forceField.init();
+}
+
+void Scene308::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ _forceField.synchronize(s);
+}
+
+
+void Scene308::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene308::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0");
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1");
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2");
+
+ initForceField(&_forceField, true);
+
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+
+ _vm->_palette->setEntry(252, 63, 30, 20);
+ _vm->_palette->setEntry(253, 45, 15, 12);
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_sequences.addTimer(48, 70);
+
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('a', -1), 60);
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0xF4, 0xF5, 0xF6, 0);
+}
+
+void Scene308::step() {
+ handleForceField(&_forceField, &_globals._spriteIndexes[0]);
+
+ if (_game._trigger == 60)
+ _scene->_nextSceneId = 307;
+
+ if (_game._trigger < 70)
+ return;
+
+ switch (_game._trigger) {
+ case 70: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 18, 9, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_kernelMessages.reset();
+ int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(244));
+ _scene->_kernelMessages.setQuoted(idx, 2, true);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ }
+ break;
+
+ case 71: {
+ int seqIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx);
+ _scene->_sequences.addTimer(48, 72);
+ }
+ break;
+
+ case 72:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 20, 5, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_kernelMessages.reset();
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 73);
+ break;
+
+ case 73: {
+ int seqIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx);
+ _scene->_sequences.addTimer(48, 74);
+ }
+ break;
+
+ case 74: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 20, 8, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 6, 7);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_kernelMessages.reset();
+ int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(245));
+ _scene->_kernelMessages.setQuoted(idx, 2, true);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75);
+ }
+ break;
+
+ case 75: {
+ int seqIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 23, 5, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 10);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 76);
+ }
+ break;
+
+ case 76: {
+ int seqIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+ _scene->_kernelMessages.reset();
+ int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(246));
+ _scene->_kernelMessages.setQuoted(idx, 2, true);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene309::Scene309(MADSEngine *vm) : Scene3xx(vm) {
+ for (int i = 0; i < 3; i++) {
+ _characterSpriteIndexes[i] = -1;
+ _messagesIndexes[i] = -1;
+ }
+
+ _lastFrame = -1;
+ _forceField.init();
+}
+
+void Scene309::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ _forceField.synchronize(s);
+
+ for (int i = 0; i < 3; ++i)
+ s.syncAsSint32LE(_characterSpriteIndexes[i]);
+ for (int i = 0; i < 3; ++i)
+ s.syncAsSint32LE(_messagesIndexes[i]);
+ s.syncAsSint32LE(_lastFrame);
+}
+
+void Scene309::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene309::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0");
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1");
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2");
+
+ initForceField(&_forceField, true);
+
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15);
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 3, 70);
+
+ _vm->_palette->setEntry(252, 63, 37, 26);
+ _vm->_palette->setEntry(253, 45, 24, 17);
+ _vm->_palette->setEntry(16, 63, 63, 63);
+ _vm->_palette->setEntry(17, 45, 45, 45);
+ _vm->_palette->setEntry(250, 63, 20, 20);
+ _vm->_palette->setEntry(251, 45, 10, 10);
+
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('a', -1), 60);
+
+ _characterSpriteIndexes[0] = _scene->_activeAnimation->_spriteListIndexes[2];
+ _characterSpriteIndexes[1] = _scene->_activeAnimation->_spriteListIndexes[2];
+ _characterSpriteIndexes[2] = _scene->_activeAnimation->_spriteListIndexes[1];
+
+ _messagesIndexes[0] = -1;
+ _messagesIndexes[1] = -1;
+ _messagesIndexes[2] = -1;
+
+ sceneEntrySound();
+
+ _game.loadQuoteSet(0xF7, 0xF8, 0xF9, 0x15C, 0x15D, 0x15E, 0);
+}
+
+void Scene309::step() {
+ handleForceField(&_forceField, &_globals._spriteIndexes[0]);
+
+ if (_game._trigger == 61) {
+ _messagesIndexes[0] = -1;
+ _messagesIndexes[1] = -1;
+ }
+
+ if (_game._trigger == 62)
+ _messagesIndexes[2] = -1;
+
+ if (_scene->_activeAnimation != nullptr) {
+ if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _lastFrame = _scene->_activeAnimation->getCurrentFrame();
+ if (_lastFrame == 39) {
+ _messagesIndexes[0] = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 32, 61, 210, _game.getQuote(348));
+ _messagesIndexes[1] = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 32, 0, 210, _game.getQuote(349));
+ }
+
+ if (_lastFrame == 97)
+ _messagesIndexes[2] = _scene->_kernelMessages.add(Common::Point(0, 0), 0xFBFA, 32, 62, 180, _game.getQuote(350));
+
+ for (int charIdx = 0; charIdx < 3; charIdx++) {
+ if (_messagesIndexes[charIdx] >= 0) {
+ bool match = false;
+ int j = -1;
+ for (j = _scene->_activeAnimation->_oldFrameEntry; j < _scene->_activeAnimation->_header._frameEntriesCount; j++) {
+ if (_scene->_activeAnimation->_frameEntries[j]._spriteSlot._spritesIndex == _characterSpriteIndexes[charIdx]) {
+ match = true;
+ break;
+ }
+ }
+
+ if (match) {
+ SpriteSlotSubset *curSpriteSlot = &_scene->_activeAnimation->_frameEntries[j]._spriteSlot;
+ _scene->_kernelMessages._entries[_messagesIndexes[charIdx]]._position.x = curSpriteSlot->_position.x;
+ _scene->_kernelMessages._entries[_messagesIndexes[charIdx]]._position.y = curSpriteSlot->_position.y - (50 + (14 * ((charIdx == 0) ? 2 : 1)));
+ }
+ }
+ }
+ }
+ }
+
+ if (_game._trigger >= 70) {
+ switch (_game._trigger) {
+ case 70: {
+ int idx = _scene->_dynamicHotspots.add(689, 690, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(142, 146), FACING_NORTHEAST);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 4, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ }
+ break;
+
+ case 71: {
+ int _oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 7);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx);
+ int idx = _scene->_kernelMessages.add(Common::Point(85, 37), 0xFDFC, 0, 0, 120, _game.getQuote(248));
+ _scene->_kernelMessages.setQuoted(idx, 2, true);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ }
+ break;
+
+ case 72: {
+ int _oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 8, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 73);
+ }
+ break;
+
+ case 73: {
+ int _oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 12, 20);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx);
+ int idx = _scene->_kernelMessages.add(Common::Point(170, 49), 0xFDFC, 0, 0, 120, _game.getQuote(249));
+ _scene->_kernelMessages.setQuoted(idx, 2, true);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74);
+ }
+ break;
+
+ case 74: {
+ int _oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 6, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 21, 23);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75);
+ }
+ break;
+
+ case 75: {
+ int _oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 6, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 24, 25);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 76);
+ }
+ break;
+
+ case 76: {
+ int _oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 28);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 77);
+ }
+ break;
+
+ case 77: {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 90, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 29, 30);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11);
+ int idx = _scene->_kernelMessages.add(Common::Point(15, 46), 0xFDFC, 0, 0, 120, _game.getQuote(247));
+ _scene->_kernelMessages.setQuoted(idx, 2, true);
+ _scene->_sequences.addTimer(120, 78);
+ }
+ break;
+ }
+ }
+
+ if (_game._trigger == 60)
+ _scene->_nextSceneId = 308;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene310::Scene310(MADSEngine *vm) : Scene3xx(vm) {
+ _forceField.init();
+}
+
+void Scene310::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ _forceField.synchronize(s);
+}
+
+void Scene310::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene310::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0");
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1");
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2");
+
+ initForceField(&_forceField, true);
+
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15);
+
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('a', -1), 70);
+
+ sceneEntrySound();
+}
+
+void Scene310::step() {
+ handleForceField(&_forceField, &_globals._spriteIndexes[0]);
+
+ if (_game._trigger == 70)
+ _scene->_nextSceneId = 309;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene311::Scene311(MADSEngine *vm) : Scene3xx(vm) {
+ _checkGuardFl = false;
+}
+
+void Scene311::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsByte(_checkGuardFl);
+}
+
+void Scene311::setup() {
+ if (_scene->_currentSceneId == 391)
+ _globals[kSexOfRex] = REX_MALE;
+
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ if (_scene->_currentSceneId == 304)
+ _game._player._spritesPrefix = "";
+}
+
+void Scene311::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXCL_8");
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCL_2");
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ _checkGuardFl = false;
+ _game.loadQuoteSet(0xFA, 0);
+
+ if (_scene->_priorSceneId == 391) {
+ _globals[kSexOfRex] = REX_MALE;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _game._player._facing = FACING_SOUTH;
+ _game._player._playerPos = Common::Point(166, 101);
+ _scene->_sequences.addTimer(120, 71);
+ } else if (_scene->_priorSceneId == 310)
+ _game._player._playerPos = Common::Point(302, 145);
+ else if (_scene->_priorSceneId == 320) {
+ _game._player._playerPos = Common::Point(129, 113);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('a', -1), 70);
+ }
+
+ sceneEntrySound();
+}
+
+void Scene311::step() {
+ if (_game._trigger == 70)
+ _scene->_nextSceneId = 310;
+
+ if (_game._trigger >= 71) {
+ switch (_game._trigger) {
+ case 71:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 72);
+ break;
+
+ case 72:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 73);
+ break;
+
+ case 73:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 74);
+ break;
+
+ case 74:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75);
+ break;
+
+ case 75: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(15, 76);
+ }
+ break;
+
+ case 76:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 77);
+ break;
+
+ case 77:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 8);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 78);
+ break;
+
+ case 78:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 9);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 79);
+ break;
+
+ case 79:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 10, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ break;
+
+ case 80:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]);
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (_game._player._moving && (_scene->_rails.getNext() > 0)) {
+ int x = _game._player._prepareWalkPos.x;
+ if (x < 75)
+ x = 75;
+ if (x > 207)
+ x = 207;
+
+ _checkGuardFl = true;
+ _game._player.startWalking(Common::Point(x, 122), FACING_SOUTH);
+ _scene->_rails.resetNext();
+ }
+}
+
+void Scene311::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(31119);
+ else if (_checkGuardFl) {
+ _checkGuardFl = false;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.addQuote(0xFA, 120, 0);
+ } else if (_action.isAction(VERB_SIT_AT, NOUN_DESK))
+ _scene->_nextSceneId = 320;
+ else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 50, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 3, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1: {
+ int oldIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], oldIdx);
+ }
+ break;
+
+ case 2: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 4, 10);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ }
+ break;
+
+ case 3: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.addTimer(15, 4);
+ }
+ break;
+
+ case 4:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 12, 14);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 5);
+ break;
+
+ case 5: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 15);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.addTimer(15, 6);
+ }
+ break;
+
+ case 6:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.addTimer(15, 7);
+ break;
+
+ case 7:
+ _scene->_nextSceneId = 313;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_DESK))
+ _vm->_dialogs->show(31110);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(31111);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHTING_FIXTURE) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTING_FIXTURE))
+ _vm->_dialogs->show(31112);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHTS) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTS))
+ _vm->_dialogs->show(31113);
+ else if (_action.isAction(VERB_TAKE, NOUN_LIGHTS))
+ _vm->_dialogs->show(31114);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHT) || _action.isAction(VERB_STARE_AT, NOUN_LIGHT))
+ _vm->_dialogs->show(31115);
+ else if (_action.isAction(VERB_TAKE, NOUN_LIGHT))
+ _vm->_dialogs->show(31116);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(31117);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(31118);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT))
+ _vm->_dialogs->show(31120);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene313::setup() {
+ setPlayerSpritesPrefix();
+ _game._player._spritesPrefix = "RM313A";
+ setAAName();
+}
+
+void Scene313::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+
+ if ((_scene->_priorSceneId == 366) || (_scene->_priorSceneId == 316)) {
+ _game._player._playerPos = Common::Point(30, 80);
+ _game._player._facing = FACING_NORTH;
+ } else if ((_scene->_priorSceneId == 311) || (_scene->_priorSceneId == 361) || (_scene->_priorSceneId == 391)) {
+ _game._player._playerPos = Common::Point(90, 70);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId == 390) {
+ _game._player._playerPos = Common::Point(126, 70);
+ _game._player._facing = FACING_EAST;
+ } else if ((_scene->_priorSceneId == 389) || (_scene->_priorSceneId == 399)) {
+ _game._player._playerPos = Common::Point(163, 70);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId == 388) {
+ _game._player._playerPos = Common::Point(199, 70);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(234, 70);
+ _game._player._facing = FACING_WEST;
+ }
+
+ if (_globals[kAfterHavoc]) {
+ for (uint16 i = 0; i < _scene->_paletteCycles.size(); i++) {
+ int palIdx = _scene->_paletteCycles[i]._firstColorIndex;
+ int size = _scene->_paletteCycles[i]._colorCount * 3;
+ memset(&_vm->_palette->_cyclingPalette[palIdx], 0, size);
+ memset(&_vm->_palette->_mainPalette[palIdx], 0, size);
+ }
+ }
+
+ sceneEntrySound();
+}
+
+void Scene313::actions() {
+ if (_action.isAction(VERB_CRAWL_TO, NOUN_FOURTH_CELL))
+ _scene->_nextSceneId = 387;
+ else if (_action.isAction(VERB_CRAWL_TO, NOUN_THIRD_CELL))
+ _scene->_nextSceneId = 388;
+ else if (_action.isAction(VERB_CRAWL_TO, NOUN_SECOND_CELL)) {
+ if (_globals[kAfterHavoc])
+ _scene->_nextSceneId = 399;
+ else
+ _scene->_nextSceneId = 389;
+ } else if (_action.isAction(VERB_CRAWL_TO, NOUN_FIRST_CELL))
+ _scene->_nextSceneId = 390;
+ else if (_action.isAction(VERB_CRAWL_TO, NOUN_SECURITY_STATION)) {
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _globals[kSexOfRex] = REX_MALE;
+ _vm->_dialogs->show(31301);
+ }
+ _scene->_nextSceneId = 391;
+ } else if (_action.isAction(VERB_CRAWL_TO, NOUN_EQUIPMENT_ROOM)) {
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _globals[kSexOfRex] = REX_MALE;
+ _vm->_dialogs->show(31301);
+ }
+ _scene->_nextSceneId = 366;
+ } else if (!_action.isAction(VERB_CRAWL_DOWN, NOUN_AIR_SHAFT))
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene316::setup() {
+ if (_scene->_currentSceneId == 366)
+ _globals[kSexOfRex] = REX_MALE;
+
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene316::handleRexInGrate() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addTimer(15, 1);
+ break;
+
+ case 1:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 12, 3, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 2, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2: {
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 8);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ }
+ break;
+
+ case 3: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ }
+ break;
+
+ case 4: {
+ int oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 10, 11);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5);
+ }
+ break;
+
+ case 5: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+
+ oldIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 12);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx);
+ _scene->_sequences.addTimer(15, 6);
+ }
+ break;
+
+ case 6:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 13, 14);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 7);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8);
+ break;
+
+ case 7:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 15);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], -1);
+ break;
+
+ case 8: {
+ int oldIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx);
+ _scene->_sequences.addTimer(15, 9);
+ }
+ break;
+
+ case 9:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addTimer(48, 10);
+ break;
+
+ case 10:
+ _scene->_nextSceneId = 313;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene316::handleRoxInGrate() {
+ int temp;
+ int temp1;
+
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addTimer(15, 1);
+ break;
+
+ case 1:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 17, 3, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 2, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12);
+
+ temp = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 4, 8);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ break;
+
+ case 3:
+ temp1 = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp1);
+ break;
+
+ case 4:
+ temp = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 10, 11);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 5);
+ break;
+
+ case 5:
+ temp = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp);
+
+ temp = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 12);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp);
+ _scene->_sequences.addTimer(20, 6);
+ break;
+
+ case 6:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 13, 15);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 7);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8);
+ break;
+
+ case 7:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 16);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], -1);
+ break;
+
+ case 8:
+ temp = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp);
+ _scene->_sequences.addTimer(20, 9);
+ break;
+
+ case 9:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addTimer(48, 10);
+ break;
+
+ case 10:
+ _scene->_nextSceneId = 313;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene316::enter() {
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCL_8");
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXCL_2");
+ } else {
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', 0));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*ROXCL_8");
+ }
+
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('v', 0));
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12);
+
+ if (_scene->_priorSceneId == 366) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _game._player._playerPos = Common::Point(78, 87);
+ _game._player._facing = FACING_SOUTH;
+ _scene->_sequences.addTimer(48, 70);
+ } else if (_scene->_priorSceneId == 321) {
+ _game._player._playerPos = Common::Point(153, 102);
+ _game._player._facing = FACING_SOUTH;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _vm->_sound->command(44);
+ int spriteIdx = (_globals[kSexOfRex] == REX_MALE) ? 1 : 2;
+ _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[spriteIdx], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 60);
+ } else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(291, 126);
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0xFD, 0);
+}
+
+void Scene316::step() {
+ if (_game._trigger == 60) {
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[1]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ }
+
+ if (_game._trigger >= 70) {
+ switch (_game._trigger) {
+ case 70:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 5);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 71: {
+ int synxIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], synxIdx);
+ }
+ break;
+
+ case 72: {
+ int synxIdx = _globals._sequenceIndexes[6];
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 6, 9);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], synxIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 73);
+ }
+ break;
+
+ case 73:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]);
+
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 10, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 75);
+ break;
+
+ case 74: {
+ int synxIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], synxIdx);
+ }
+ break;
+
+ case 75:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]);
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene316::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) {
+ if (_globals[kAfterHavoc])
+ _game._player._walkOffScreenSceneId = 354;
+ else
+ _game._player._walkOffScreenSceneId = 304;
+ }
+}
+
+void Scene316::actions() {
+ if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) {
+ if (_globals[kSexOfRex] == REX_FEMALE)
+ handleRoxInGrate();
+ else
+ handleRexInGrate();
+ } else if (_action.isAction(VERB_WALK_UP, NOUN_RAMP) || _action.isAction(VERB_WALK_ONTO, NOUN_PLATFORM)) {
+ switch (_game._trigger) {
+ case 0:
+ if (_globals[kCityFlooded]) {
+ _vm->_dialogs->show(31623);
+ } else {
+ _vm->_sound->command(45);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, 7);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ } else {
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ }
+ }
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 8, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ _scene->_kernelMessages.reset();
+ if (!_game._visitedScenes.exists(321))
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(253));
+
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2:
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ _scene->_sequences.addTimer(48, 4);
+ break;
+
+ case 3:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -2, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _scene->_sequences.addTimer(48, 4);
+ break;
+
+ case 4:
+ _scene->_nextSceneId = 321;
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM))
+ _vm->_dialogs->show(31610);
+ else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) {
+ if (_game._visitedScenes.exists(321))
+ _vm->_dialogs->show(31612);
+ else
+ _vm->_dialogs->show(31611);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CONTROLS))
+ _vm->_dialogs->show(31613);
+ else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT))
+ _vm->_dialogs->show(31614);
+ else if (_action.isAction(VERB_LOOK, NOUN_PANEL))
+ _vm->_dialogs->show(31615);
+ else if (_action.isAction(VERB_LOOK, NOUN_MONITOR))
+ _vm->_dialogs->show(31616);
+ else if (_action.isAction(VERB_LOOK, NOUN_RAMP))
+ _vm->_dialogs->show(31617);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT))
+ _vm->_dialogs->show(31618);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) {
+ if (!_globals[kAfterHavoc]) {
+ if (_game._difficulty != DIFFICULTY_EASY)
+ _vm->_dialogs->show(31620);
+ else
+ _vm->_dialogs->show(31619);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_FLOOR))
+ _vm->_dialogs->show(31621);
+ else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT))
+ _vm->_dialogs->show(31622);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+
+/*------------------------------------------------------------------------*/
+
+Scene318::Scene318(MADSEngine *vm) : Scene3xx(vm) {
+ _dropTimer = 0;
+
+ _lastFrame = -1;
+ _animMode = -1;
+ _internCounter = -1;
+ _counter = -1;
+
+ _dialogFl = false;
+ _internTalkingFl = false;
+ _internWalkingFl = false;
+ _internVisibleFl = false;
+ _explosionFl = false;
+
+ _lastFrameCounter = 0;
+
+ _subQuote2 = "";
+}
+
+void Scene318::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsUint32LE(_dropTimer);
+
+ s.syncAsSint32LE(_lastFrame);
+ s.syncAsSint32LE(_animMode);
+ s.syncAsSint32LE(_internCounter);
+ s.syncAsSint32LE(_counter);
+
+ s.syncAsByte(_dialogFl);
+ s.syncAsByte(_internTalkingFl);
+ s.syncAsByte(_internWalkingFl);
+ s.syncAsByte(_internVisibleFl);
+ s.syncAsByte(_explosionFl);
+
+ s.syncAsUint32LE(_lastFrameCounter);
+
+ s.syncString(_subQuote2);
+}
+
+void Scene318::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene318::handleDialog() {
+ if (!_game._trigger) {
+ _game._player._stepEnabled = false;
+ handleRexDialogs(_action._activeAction._verbId);
+ } else if (_game._trigger == 2) {
+ int synxIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], synxIdx);
+ _vm->_sound->command(3);
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _game._player._stepEnabled = true;
+ } else {
+ if (_action._activeAction._verbId < 0x19C)
+ _dialog1.write(_action._activeAction._verbId, false);
+
+ switch (_action._activeAction._verbId) {
+ case 0x191:
+ handleInternDialog(0x19E, 2, 9999999);
+ _dialog1.write(0x192, true);
+ break;
+
+ case 0x192:
+ handleInternDialog(0x1A0, 5, 9999999);
+ _dialog1.write(0x193, true);
+ break;
+
+ case 0x193:
+ handleInternDialog(0x1A5, 4, 9999999);
+ _dialog1.write(0x194, true);
+ break;
+
+ case 0x194:
+ handleInternDialog(0x1A9, 6, 9999999);
+ _dialog1.write(0x195, true);
+ _dialog1.write(0x196, true);
+ _dialog1.write(0x19D, false);
+ break;
+
+ case 0x195:
+ handleInternDialog(0x1AF, 7, 9999999);
+ if (!_dialog1.read(0x196))
+ _dialog1.write(0x197, true);
+ break;
+
+ case 0x196:
+ handleInternDialog(0x1B6, 5, 9999999);
+ if (!_dialog1.read(0x195))
+ _dialog1.write(0x197, true);
+ break;
+
+ case 0x197:
+ handleInternDialog(0x1BB, 5, 9999999);
+ break;
+
+ case 0x198:
+ handleInternDialog(0x1C0, 5, 9999999);
+ _dialog1.write(0x19A, true);
+ break;
+
+ case 0x199:
+ handleInternDialog(0x1C5, 3, 9999999);
+ break;
+
+ case 0x19A:
+ handleInternDialog(0x1C8, 5, 9999999);
+ _dialog1.write(0x19B, true);
+ break;
+
+ case 0x19B:
+ handleInternDialog(0x1CD, 3, 9999999);
+ break;
+
+ case 0x19C:
+ case 0x19D:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121));
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+
+ _dialogFl = false;
+ handleInternDialog(0x1D0, 1, 120);
+ if (_dialog1.read(0) || (_action._activeAction._verbId == 0x19D)) {
+ _explosionFl = true;
+ _internCounter = 3420;
+ }
+ break;
+ }
+
+ if (_action._activeAction._verbId < 0x19C) {
+ _dialog1.start();
+ _game._player._stepEnabled = true;
+ }
+
+ }
+}
+
+void Scene318::handleRexDialogs(int quote) {
+ _scene->_kernelMessages.reset();
+
+ Common::String curQuote = _game.getQuote(quote);
+ if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) {
+ Common::String subQuote1;
+ _game.splitQuote(curQuote, subQuote1, _subQuote2);
+ _scene->_kernelMessages.add(Common::Point(138, 59), 0x1110, 32, 0, 240, subQuote1);
+ _scene->_kernelMessages.add(Common::Point(138, 73), 0x1110, 32, 1, 180, _subQuote2);
+ } else
+ _scene->_kernelMessages.add(Common::Point(138, 73), 0x1110, 32, 1, 120, curQuote);
+}
+
+void Scene318::handleInternDialog(int quoteId, int quoteNum, uint32 timeout) {
+ int height = quoteNum * 14;
+ int posY;
+ if (height < 85)
+ posY = 87 - height;
+ else
+ posY = 2;
+
+ int curQuoteId= quoteId;
+
+ int maxWidth = 0;
+ for (int i = 0; i < quoteNum; i++) {
+ maxWidth = MAX(maxWidth, _vm->_font->getWidth(_game.getQuote(curQuoteId), -1));
+ curQuoteId++;
+ }
+
+ int posX = MIN(319 - maxWidth, 178 - (maxWidth >> 1));
+ curQuoteId = quoteId;
+
+ _scene->_kernelMessages.reset();
+ _internTalkingFl = true;
+
+ for (int i = 0; i < quoteNum; i++) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(180, 63);
+ _scene->_kernelMessages.add(Common::Point(posX, posY), 0xFDFC, 0, 0, timeout, _game.getQuote(curQuoteId));
+ posY += 14;
+ curQuoteId++;
+ }
+}
+
+void Scene318::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('k', -1));
+
+ if (_globals[kAfterHavoc]) {
+ _scene->loadAnimation(formAnimName('f', -1));
+ _scene->_activeAnimation->_resetFlag = true;
+ } else if (!_globals[kHasSeenProfPyro]) {
+ _scene->_hotspots.activate(NOUN_PROFESSORS_GURNEY, false);
+ _scene->_hotspots.activate(NOUN_PROFESSOR, false);
+ _scene->_hotspots.activate(NOUN_TAPE_PLAYER, false);
+ }
+
+ if (_game._objects.isInRoom(OBJ_SCALPEL)) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 120);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4);
+ _scene->_dynamicHotspots.add(NOUN_SCALPEL, VERB_TAKE, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ }
+
+ if (_scene->_priorSceneId == 357)
+ _game._player._playerPos = Common::Point(15, 110);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(214, 152);
+
+ _dialog1.setup(0x47, 0x191, 0x192, 0x193, 0x194, 0x195, 0x196, 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19D, 0);
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ _dialog1.set(0x191, 0x198, 0x199, 0x19C, 0);
+ if (_game._widepipeCtr >= 2)
+ _dialog1.write(0x19D, true);
+ }
+
+ if (_scene->_priorSceneId == 307) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('a', -1), 60);
+ _animMode = 1;
+ }
+
+ _lastFrame = 0;
+ _scene->_hotspots.activate(NOUN_INTERN, false);
+
+ if (_scene->_priorSceneId != -2) {
+ _dialogFl = false;
+ _internWalkingFl = false;
+ _counter= 0;
+ _internCounter= 0;
+ _internVisibleFl = true;
+ _explosionFl = false;
+ }
+
+ _game.loadQuoteSet(0x18C, 0x18D, 0x18E, 0x18F, 0x191, 0x192, 0x193, 0x194, 0x195, 0x196,
+ 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19E, 0x19E, 0x1A0, 0x1A1, 0x1A2, 0x1A3,
+ 0x1A4, 0x1A5, 0x1A6, 0x1A7, 0x1A8, 0x1A9, 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1AE, 0x1AF,
+ 0x1B0, 0x1B1, 0x1B2, 0x1B3, 0x1B4, 0x1B5, 0x1B6, 0x1B7, 0x1B8, 0x1B9, 0x1BA, 0x1BB,
+ 0x1BC, 0x1BD, 0x1BE, 0x1BF, 0x1C0, 0x1C1, 0x1C2, 0x1C3, 0x1C4, 0x1C5, 0x1C6, 0x1C7,
+ 0x1C8, 0x1C9, 0x1CA, 0x1CB, 0x1CC, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3,
+ 0x190, 0x19D, 0);
+
+ if ((_scene->_priorSceneId== -2) || (((_scene->_priorSceneId == 318) || (_scene->_priorSceneId == -1)) && (!_globals[kAfterHavoc]))) {
+ if (!_globals[kAfterHavoc]) {
+ _game._player._visible = false;
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', -1));
+ _animMode = 2;
+
+ if (_game._visitedScenes.exists(319) || !_internVisibleFl) {
+ _internVisibleFl = false;
+ _dialogFl = false;
+ } else {
+ _scene->loadAnimation(formAnimName('b', -1), 61);
+ _scene->_hotspots.activate(NOUN_INTERN, true);
+ }
+
+ if (_dialogFl) {
+ _dialog1.start();
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8);
+ } else
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ }
+ }
+
+ if (_scene->_priorSceneId == 319) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _animMode = 4;
+ if (!_globals[kHasSeenProfPyro]) {
+ _scene->loadAnimation(formAnimName('d', -1), 64);
+ _globals[kHasSeenProfPyro] = true;
+ } else {
+ _scene->loadAnimation(formAnimName('e', -1), 64);
+ }
+ }
+
+ _internTalkingFl = false;
+ _vm->_palette->setEntry(252, 63, 63, 10);
+ _vm->_palette->setEntry(253, 45, 45, 05);
+
+ _dropTimer = _vm->_game->_scene._frameStartTime;
+ sceneEntrySound();
+
+ if (_dialogFl)
+ _vm->_sound->command(15);
+}
+
+void Scene318::step() {
+ if ((_scene->_activeAnimation != nullptr) && (_animMode == 2)) {
+ if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _lastFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextFrame = -1;
+
+ switch (_lastFrame) {
+ case 20:
+ case 30:
+ case 40:
+ case 50:
+ case 60:
+ case 70:
+ case 80:
+ case 90:
+ case 100:
+ case 110:
+ case 120:
+ case 130:
+ case 140:
+ case 149:
+ if (_internWalkingFl) {
+ nextFrame = 149;
+ } else if (_internTalkingFl) {
+ nextFrame = 149;
+ } else if (_lastFrame == 149) {
+ nextFrame = 4;
+ }
+ break;
+
+ case 151:
+ if (_internWalkingFl)
+ nextFrame = 183;
+ break;
+
+ case 167:
+ case 184:
+ if (_internWalkingFl) {
+ nextFrame = 184;
+ } else if (!_internTalkingFl) {
+ nextFrame = 0;
+ } else if (_vm->getRandomNumber(1, 100) <= 50) {
+ nextFrame = 151;
+ } else {
+ nextFrame = 167;
+ }
+
+ if (nextFrame == 184) {
+ handleInternDialog(0x1D1, 3, 240);
+ _scene->_hotspots.activate(NOUN_INTERN, false);
+ _internVisibleFl = false;
+ }
+ break;
+ }
+
+ if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextFrame);
+ _lastFrame = nextFrame;
+ }
+ }
+ }
+
+ switch (_game._trigger) {
+ case 60:
+ _vm->_sound->command(3);
+ _animMode = 2;
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ case 61:
+ _counter = 0;
+ break;
+
+ case 62:
+ _scene->_nextSceneId = 319;
+ break;
+
+ case 63:
+ _internTalkingFl = false;
+ break;
+
+ case 64:
+ _vm->_sound->command(3);
+ _scene->_nextSceneId = 307;
+ break;
+ }
+
+ uint32 tmpFrame = _vm->_events->getFrameCounter();
+ long diffFrame = tmpFrame - _lastFrameCounter;
+ _lastFrameCounter = tmpFrame;
+
+ if ((_animMode == 2) && !_internVisibleFl && _game._player._stepEnabled) {
+ if ((diffFrame >= 0) && (diffFrame <= 4))
+ _counter += diffFrame;
+ else
+ _counter++;
+
+ int extraCounter = _game._objects.isInInventory(OBJ_SCALPEL) ? 900 : 0;
+
+ if (_counter + extraCounter >= 1800) {
+ _scene->freeAnimation();
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('c', -1), 62);
+ _animMode = 3;
+ }
+ } else if ((_animMode == 2) && _explosionFl && _internVisibleFl && !_dialogFl
+ && !_internWalkingFl && (_game._screenObjects._inputMode != kInputConversation)) {
+ if ((diffFrame >= 0) && (diffFrame <= 4))
+ _internCounter += diffFrame;
+ else
+ _internCounter++;
+
+ if (_internCounter >= 3600) {
+ _vm->_sound->command(59);
+ _vm->_screen._shakeCountdown = 20;
+ _internWalkingFl = true;
+ }
+ }
+
+ if ((_vm->_game->_scene._frameStartTime - _dropTimer) > 600) {
+ _vm->_sound->command(51);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _dropTimer = _vm->_game->_scene._frameStartTime;
+ }
+}
+
+void Scene318::preActions() {
+ if (_game._player._needToWalk)
+ _game._player._needToWalk = _game._player._visible;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _game._player._walkOffScreenSceneId = 357;
+}
+
+void Scene318::actions() {
+ if (_game._screenObjects._inputMode == kInputConversation) {
+ handleDialog();
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TALKTO, NOUN_INTERN)) {
+ switch (_game._trigger) {
+ case 0: {
+ _dialogFl = true;
+ _vm->_sound->command(15);
+ _game._player._stepEnabled = false;
+ handleRexDialogs(_vm->getRandomNumber(0x18C, 0x18E));
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 80);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121));
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 1:
+ _game._player._stepEnabled = true;
+ handleInternDialog(0x18F, 1, 9999999);
+ _dialog1.start();
+ break;
+
+ case 2: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ }
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_SCALPEL) && (_game._objects.isInRoom(OBJ_SCALPEL) || _game._trigger)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 2, 0, 80);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121));
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ if (_internVisibleFl)
+ handleInternDialog(0x190, 1, 120);
+ else {
+ _game._objects.addToInventory(OBJ_SCALPEL);
+ _vm->_dialogs->showItem(OBJ_SCALPEL, 0x7C5D);
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ }
+ break;
+
+ case 2: {
+ int oldIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx);
+ _scene->_sequences.addTimer(60, 3);
+ }
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_game._player._visible) {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) {
+ _scene->_nextSceneId = 407;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_TAPE_PLAYER)) {
+ if (_game._objects.isInRoom(OBJ_AUDIO_TAPE)) {
+ _vm->_dialogs->showItem(OBJ_AUDIO_TAPE, 0x7C5B);
+ _game._objects.addToInventory(OBJ_AUDIO_TAPE);
+ } else
+ _vm->_dialogs->show(31834);
+
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_TAPE_PLAYER)) {
+ if (_game._objects.isInRoom(OBJ_AUDIO_TAPE))
+ _vm->_dialogs->show(31833);
+ else
+ _vm->_dialogs->show(31834);
+
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALK_INTO, NOUN_DOCTORS_OFFICE)) {
+ _vm->_dialogs->show(31831);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_GURNEY)) {
+ _vm->_dialogs->show(31823);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_INSTRUMENT_TABLE)) {
+ _vm->_dialogs->show(31825);
+ _action._inProgress = false;
+ return;
+ }
+ } else { // Not visible
+ if (_action.isAction(VERB_LOOK, NOUN_GURNEY)) {
+ _vm->_dialogs->show(31822);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_INSTRUMENT_TABLE)) {
+ _vm->_dialogs->show(31824);
+ _action._inProgress = false;
+ return;
+ }
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(31810);
+ else if (_action.isAction(VERB_LOOK, NOUN_FLOOR))
+ _vm->_dialogs->show(31811);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(31812);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(31813);
+ else if (_action.isAction(VERB_LOOK, NOUN_FAUCET))
+ _vm->_dialogs->show(31814);
+ else if (_action.isAction(VERB_LOOK, NOUN_SINK))
+ _vm->_dialogs->show(31815);
+ else if (_action.isAction(VERB_LOOK, NOUN_CONVEYOR_BELT))
+ _vm->_dialogs->show(31816);
+ else if (_action.isAction(VERB_LOOK, NOUN_LARGE_BLADE))
+ _vm->_dialogs->show(31817);
+ else if (_action.isAction(VERB_LOOK, NOUN_MONITOR))
+ _vm->_dialogs->show(31818);
+ else if (_action.isAction(VERB_LOOK, NOUN_CABINETS))
+ _vm->_dialogs->show(31819);
+ else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT))
+ _vm->_dialogs->show(31820);
+ else if (_action.isAction(VERB_LOOK, NOUN_SHELF))
+ _vm->_dialogs->show(31821);
+ else if (_action.isAction(VERB_OPEN, NOUN_CABINETS))
+ _vm->_dialogs->show(31829);
+ else if (_action.isAction(VERB_LOOK, NOUN_INTERN))
+ _vm->_dialogs->show(31830);
+ else if (_action.isAction(VERB_LOOK, NOUN_PROFESSOR))
+ _vm->_dialogs->show(31832);
+ else if (_action.isAction(VERB_LOOK, NOUN_PROFESSORS_GURNEY))
+ _vm->_dialogs->show(31836);
+ else if (_action._lookFlag) {
+ if (_game._player._visible || _game._objects.isInInventory(OBJ_SCALPEL))
+ _vm->_dialogs->show(31828);
+ else if (_internVisibleFl)
+ _vm->_dialogs->show(31826);
+ else
+ _vm->_dialogs->show(31827);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene319::Scene319(MADSEngine *vm) : Scene3xx(vm) {
+ _animMode = -1;
+ _animFrame = -1;
+ _nextAction1 = -1;
+ _nextAction2 = -1;
+ _slacheMode = -1;
+ _slacheTopic = -1;
+ _slachePosY = -1;
+
+ _slacheTalkingFl = false;
+ _slacheReady = false;
+ _slacheInitFl = false;
+
+ _subQuote2 = "";
+}
+
+void Scene319::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsUint32LE(_animMode);
+ s.syncAsUint32LE(_animFrame);
+ s.syncAsUint32LE(_nextAction1);
+ s.syncAsUint32LE(_nextAction2);
+ s.syncAsUint32LE(_slacheMode);
+ s.syncAsUint32LE(_slacheTopic);
+ s.syncAsUint32LE(_slachePosY);
+
+ s.syncAsByte(_slacheTalkingFl);
+ s.syncAsByte(_slacheReady);
+ s.syncAsByte(_slacheInitFl);
+
+ s.syncString(_subQuote2);
+}
+
+void Scene319::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene319::handleRexDialogues(int quote) {
+ _scene->_kernelMessages.reset();
+
+ Common::String curQuote = _game.getQuote(quote);
+ if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) {
+ Common::String subQuote1;
+ _game.splitQuote(curQuote, subQuote1, _subQuote2);
+ _scene->_kernelMessages.add(Common::Point(160, 106), 0x1110, 32, 0, 120, subQuote1);
+ _scene->_kernelMessages.add(Common::Point(160, 120), 0x1110, 32, 1, 120, _subQuote2);
+ } else
+ _scene->_kernelMessages.add(Common::Point(160, 120), 0x1110, 32, 1, 120, curQuote);
+}
+
+void Scene319::handleSlacheDialogs(int quoteId, int counter, uint32 timer) {
+ int curQuote = quoteId;
+ int posY = 5 + (_slachePosY * 14);
+
+ for (int count = 0; count < counter; count++, curQuote++) {
+ _scene->_kernelMessages.add(Common::Point(8, posY), 0xFDFC, 0, 0, timer, _game.getQuote(curQuote));
+ posY += 14;
+ }
+}
+
+void Scene319::enter() {
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('e', 0));
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 3));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('k', -1));
+
+ if (!_game._objects.isInInventory(OBJ_SCALPEL)) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ }
+
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 0, 0, 300);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 67, 0, 0, 377);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 173, 0, 0, 233);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 14);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 14);
+
+ _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+
+ _dialog1.setup(0x43, 0x165, 0x166, 0x167, 0x168, 0x169, 0x16A, 0);
+ _dialog2.setup(0x44, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0);
+ _dialog3.setup(0x45, 0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0);
+
+ if (_scene->_priorSceneId != -2) {
+ _dialog1.set(0x165, 0x166, 0x167, 0x168, 0);
+ _dialog2.set(0x171, 0x172, 0x173, 0x174, 0);
+ _dialog3.set(0x17D, 0x17E, 0x17F, 0x180, 0);
+ }
+
+ _game.loadQuoteSet(0x15F, 0x160, 0x161, 0x162, 0x163, 0x164, 0x16B, 0x16C, 0x16D,
+ 0x16E, 0x16F, 0x170, 0x177, 0x178, 0x178, 0x17A, 0x17B, 0x17C, 0x165, 0x166,
+ 0x167, 0x168, 0x169, 0x16A, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0x17D,
+ 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0x184, 0x185, 0x186, 0x187, 0x188,
+ 0x189, 0x18A, 0x18B, 0);
+
+ _vm->_palette->setEntry(252, 63, 30, 2);
+ _vm->_palette->setEntry(253, 45, 15, 1);
+
+ _slachePosY = 0;
+ _slacheInitFl = false;
+ _slacheTalkingFl = false;
+ _slacheReady = false;
+ _animFrame = 0;
+
+ _scene->loadAnimation(formAnimName('b', 0));
+
+ if (_scene->_priorSceneId != -2) {
+ _animMode = 1;
+ _nextAction1 = 2;
+ _nextAction2 = 2;
+ _slacheMode = 1;
+ _slacheTopic = 1;
+ _slacheInitFl = true;
+
+ if (_globals[kRexHasMetSlache]) {
+ handleSlacheDialogs(VERB_WALK_OUTSIDE, 2, 9999999);
+ _slachePosY = 3;
+ } else {
+ handleSlacheDialogs(0x186, 4, 9999999);
+ _slachePosY = 5;
+ }
+ }
+
+ switch (_slacheTopic) {
+ case 1:
+ handleSlacheDialogs(0x15F, 2, 9999999);
+ _dialog1.start();
+ break;
+
+ case 2:
+ handleSlacheDialogs(0x16B, 2, 9999999);
+ _dialog2.start();
+ break;
+
+ case 3:
+ handleSlacheDialogs(0x177, 2, 9999999);
+ _dialog3.start();
+ break;
+
+ default:
+ break;
+ }
+
+ _slachePosY = 0;
+ sceneEntrySound();
+}
+
+void Scene319::step() {
+ if (_scene->_activeAnimation == nullptr)
+ return;
+
+ if (_animFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _animFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextFrame = -1;
+ if (_animMode == 1) {
+ switch (_animFrame) {
+ case 6:
+ _slacheTalkingFl = true;
+ break;
+
+ case 29:
+ _slacheReady = true;
+ break;
+
+ case 39:
+ if (_slacheInitFl) {
+ _slacheInitFl = false;
+ if (_nextAction1 == 2)
+ nextFrame = 0;
+ } else if (_nextAction1 == 2)
+ _nextAction1 = 1;
+ break;
+
+ case 50:
+ case 60:
+ case 70:
+ case 85:
+ if (_nextAction1 == 2)
+ nextFrame = 0;
+ else if (_nextAction1 == 3) {
+ nextFrame = 85;
+ _slacheTalkingFl = true;
+ } else if (_animFrame == 85) {
+ if (!_game._player._stepEnabled)
+ _slacheTalkingFl = true;
+ nextFrame = 40;
+ }
+ break;
+
+ case 115:
+ _slacheReady = true;
+ break;
+
+ case 129:
+ if (_nextAction1 == 3) {
+ nextFrame = 115;
+ if (!_game._player._stepEnabled)
+ _slacheTalkingFl = true;
+ }
+ break;
+
+ case 145:
+ nextFrame = 40;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((_animFrame > 40) && (_animFrame < 85) && (nextFrame < 0)) {
+ switch (_nextAction1) {
+ case 4:
+ _animFrame = 0;
+ _scene->freeAnimation();
+ _animMode = 2;
+ _scene->loadAnimation(formAnimName('b', 3), 70);
+ break;
+
+ case 5:
+ _animFrame = 0;
+ _scene->freeAnimation();
+ _animMode = 3;
+ _scene->loadAnimation(formAnimName('b', 4), 71);
+ break;
+
+ case 6:
+ _animFrame = 0;
+ _scene->freeAnimation();
+ _animMode = 4;
+ _scene->loadAnimation(formAnimName('b', 5), 72);
+ break;
+
+ default:
+ break;
+ }
+
+ if (!_animFrame) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[0]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+
+ for (int i = 0; i <= 1; i++) {
+ _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 1, 7);
+ }
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 73);
+ }
+ }
+ }
+
+ if (_animMode == 2) {
+ if (_animFrame == 13)
+ _vm->_screen._shakeCountdown = 40;
+
+ if (_animFrame == 16)
+ _vm->_screen._shakeCountdown = 1;
+ }
+
+ if (_animMode == 3) {
+ if (_animFrame == 11)
+ _vm->_screen._shakeCountdown = 60;
+
+ if (_animFrame == 18)
+ _vm->_screen._shakeCountdown = 1;
+ }
+
+ if ((_animMode == 4) && (_animFrame == 16))
+ _vm->_screen._shakeCountdown = 80;
+
+ if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextFrame);
+ _animFrame = nextFrame;
+ }
+ }
+
+ switch (_game._trigger) {
+ case 70:
+ case 71:
+ _animMode = 1;
+ _nextAction1 = _nextAction2;
+ _animFrame = 0;
+ _scene->freeAnimation();
+ _scene->loadAnimation(formAnimName('b', 0));
+ if (_nextAction1 == 3)
+ _scene->_activeAnimation->setCurrentFrame(85);
+ else if (_nextAction1 == 1)
+ _scene->_activeAnimation->setCurrentFrame(40);
+
+ _animFrame = _scene->_activeAnimation->getCurrentFrame();
+ _slacheTalkingFl = true;
+ _vm->_screen._shakeCountdown = 1;
+
+ for (int i = 0; i <= 1; i++) {
+ int oldIdx = _globals._sequenceIndexes[i];
+ _scene->_sequences.remove(_globals._sequenceIndexes[i]);
+ _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 8, 13);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx);
+ }
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 74);
+ break;
+
+ case 72:
+ _vm->_palette->setColorFlags(0xFF, 0, 0);
+ _vm->_palette->setColorValues(0, 0, 0);
+ _vm->_palette->fadeOut(_vm->_palette->_mainPalette, nullptr, 18, 228,
+ 248, 0, 1, 16);
+ _vm->_screen._shakeCountdown = 1;
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ case 73:
+ for (int i = 0; i <= 1; i++) {
+ int oldIdx = _globals._sequenceIndexes[i];
+ _scene->_sequences.remove(_globals._sequenceIndexes[i]);
+ _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 6, 7);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx);
+ }
+ break;
+
+ case 74:
+ for (int i = 0; i <= 1; i++) {
+ int oldIdx = _globals._sequenceIndexes[i];
+ _scene->_sequences.remove(_globals._sequenceIndexes[i]);
+ _globals._sequenceIndexes[i] = _scene->_sequences.startCycle(_globals._spriteIndexes[i], false, 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene319::actions() {
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ handleRexDialogues(_action._activeAction._verbId);
+ } else {
+ if ((_action._activeAction._verbId == 0x165) || (_action._activeAction._verbId == 0x166)) {
+ if (_game._trigger == 1) {
+ _nextAction1 = 3;
+ _slacheTalkingFl = false;
+ _slacheMode = 1;
+ _slacheTopic = 2;
+ }
+
+ if (!_slacheTalkingFl) {
+ _scene->_sequences.addTimer(4, 2);
+ } else {
+ handleSlacheDialogs(0x16B, 2, 9999999);
+ _dialog2.start();
+ _game._player._stepEnabled = true;
+ }
+ }
+
+ if ((_action._activeAction._verbId == 0x171) || (_action._activeAction._verbId == 0x172)) {
+ if (_game._trigger == 1) {
+ _nextAction1 = 2;
+ _slacheTalkingFl = false;
+ _slacheMode = 1;
+ _slacheTopic = 3;
+ }
+
+ if (!_slacheTalkingFl) {
+ _scene->_sequences.addTimer(4, 2);
+ } else {
+ handleSlacheDialogs(0x177, 2, 9999999);
+ _dialog3.start();
+ _game._player._stepEnabled = true;
+ }
+ }
+
+ if ((_action._activeAction._verbId == 0x17D) || (_action._activeAction._verbId == 0x17E)) {
+ if (_game._trigger == 1) {
+ _nextAction1 = 3;
+ _slacheTalkingFl = false;
+ _slacheReady = false;
+ _slacheMode = 1;
+ _slacheTopic = 1;
+ }
+
+ if (!_slacheTalkingFl) {
+ _scene->_sequences.addTimer(4, 2);
+ } else {
+ if (_game._trigger == 2)
+ handleSlacheDialogs(0x184, 2, 180);
+
+ if (!_slacheReady) {
+ _scene->_sequences.addTimer(120, 3);
+ } else {
+ _globals[kRexHasMetSlache] = true;
+ _scene->_nextSceneId = 318;
+ }
+ }
+ }
+
+ if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x174) ||
+ (_action._activeAction._verbId == 0x180) || (_action._activeAction._verbId == 0x169) ||
+ (_action._activeAction._verbId == 0x175) || (_action._activeAction._verbId == 0x181) ||
+ (_action._activeAction._verbId == 0x16A) || (_action._activeAction._verbId == 0x176) ||
+ (_action._activeAction._verbId == 0x182) || (_action._activeAction._verbId == 0x183) ||
+ (_action._activeAction._verbId == 0x167) || (_action._activeAction._verbId == 0x173) ||
+ (_action._activeAction._verbId == 0x17F)) {
+
+ bool addDialogLine = !((_action._activeAction._verbId == 0x167) || (_action._activeAction._verbId == 0x173) ||
+ (_action._activeAction._verbId == 0x17F) || (_action._activeAction._verbId == 0x16A) ||
+ (_action._activeAction._verbId == 0x176) || (_action._activeAction._verbId == 0x182) ||
+ (_action._activeAction._verbId == 0x183));
+
+ int addVerbId = _action._activeAction._verbId + 1;
+ if ((addVerbId == 0x182) && (_game._storyMode != STORYMODE_NAUGHTY))
+ addVerbId = 0x183;
+
+ if (_slacheMode == 1) {
+ if (_game._trigger == 1) {
+ _nextAction2 = _nextAction1;
+ _nextAction1 = 4;
+ }
+
+ if (_nextAction1 != _nextAction2) {
+ _scene->_sequences.addTimer(4, 2);
+ } else {
+ Conversation *curDialog;
+ int nextDocQuote;
+ if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x167)) {
+ curDialog = &_dialog1;
+ nextDocQuote = 0x161;
+ } else if ((_action._activeAction._verbId == 0x174) || (_action._activeAction._verbId == 0x1753)) {
+ nextDocQuote = 0x16D;
+ curDialog = &_dialog2;
+ } else {
+ nextDocQuote = 0x179;
+ curDialog = &_dialog3;
+ }
+
+ handleSlacheDialogs(nextDocQuote, 2, 9999999);
+ if (addDialogLine) {
+ curDialog->write(_action._activeAction._verbId, false);
+ curDialog->write(addVerbId, true);
+ }
+
+ curDialog->start();
+ _game._player._stepEnabled = true;
+ _slacheMode = 2;
+ }
+ } else if (_slacheMode == 2) {
+ if (_game._trigger == 1) {
+ _nextAction2 = _nextAction1;
+ _nextAction1 = 5;
+ }
+
+ if (_nextAction1 != _nextAction2) {
+ _scene->_sequences.addTimer(4, 2);
+ } else {
+ Conversation *curDialog;
+ int nextDocQuote;
+ if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x169) || (_action._activeAction._verbId == 0x167)) {
+ curDialog = &_dialog1;
+ nextDocQuote = 0x163;
+ } else if ((_action._activeAction._verbId == 0x174) || (_action._activeAction._verbId == 0x175) || (_action._activeAction._verbId == 0x173)) {
+ nextDocQuote = 0x16F;
+ curDialog = &_dialog2;
+ } else {
+ nextDocQuote = 0x17B;
+ curDialog = &_dialog3;
+ }
+
+ handleSlacheDialogs(nextDocQuote, 2, 9999999);
+ if (addDialogLine) {
+ curDialog->write(_action._activeAction._verbId, false);
+ curDialog->write(addVerbId, true);
+ }
+
+ curDialog->start();
+ _game._player._stepEnabled = true;
+ _slacheMode = 3;
+ }
+ } else {
+ _nextAction2 = _nextAction1;
+ _nextAction1 = 6;
+ }
+ }
+ }
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene320::Scene320(MADSEngine *vm) : Scene300s(vm) {
+ _blinkFl = false;
+ _flippedFl = false;
+
+ _buttonId = -1;
+ _lastFrame = -1;
+ _leftItemId = -1;
+ _posX = -1;
+ _rightItemId = -1;
+}
+
+void Scene320::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsByte(_blinkFl);
+ s.syncAsByte(_flippedFl);
+
+ s.syncAsSint32LE(_buttonId);
+ s.syncAsSint32LE(_lastFrame);
+ s.syncAsSint32LE(_leftItemId);
+ s.syncAsSint32LE(_posX);
+ s.syncAsSint32LE(_rightItemId);
+}
+
+void Scene320::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene320::setRightView(int view) {
+ if (_rightItemId < 8) _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+
+ int spriteNum;
+ switch (view) {
+ case 0:
+ spriteNum = 16;
+ break;
+
+ case 1:
+ spriteNum = 14;
+ break;
+
+ case 2:
+ spriteNum = 17;
+ break;
+
+ case 3:
+ spriteNum = 15;
+ break;
+
+ default:
+ spriteNum = view + 6;
+ break;
+ }
+
+ if (view != 8) {
+ _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[spriteNum], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 0);
+ }
+
+ _globals[kRightView320] = _rightItemId = view;
+}
+
+void Scene320::setLeftView(int view) {
+ if (_leftItemId < 10)
+ _scene->_sequences.remove(_globals._sequenceIndexes[0]);
+
+ if (view != 10) {
+ _globals._sequenceIndexes[0] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[view], false, 6, 0, 0, 18);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 0);
+ if (!_blinkFl)
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], 2, 2);
+ }
+
+ _leftItemId = view;
+}
+
+void Scene320::handleButtons() {
+ switch(_action._activeAction._objectNameId) {
+ case 0x2DD:
+ _buttonId = 5;
+ break;
+
+ case 0x2DE:
+ _buttonId = 4;
+ break;
+
+ case 0x2E0:
+ _buttonId = 6;
+ break;
+
+ case 0x2E1:
+ _buttonId = 7;
+ break;
+
+ case 0x2E2:
+ _buttonId = 8;
+ break;
+
+ case 0x2E3:
+ _buttonId = 9;
+ break;
+
+ case 0x2E4:
+ _buttonId = 10;
+ break;
+
+ case 0x2E5:
+ _buttonId = 11;
+ break;
+
+ case 0x2E6:
+ _buttonId = 12;
+ break;
+
+ case 0x2E7:
+ _buttonId = 13;
+ break;
+
+ case 0x2E8:
+ _buttonId = 0;
+ break;
+
+ case 0x2E9:
+ _buttonId = 1;
+ break;
+
+ case 0x2EA:
+ _buttonId = 2;
+ break;
+
+ case 0x2EB:
+ _buttonId = 3;
+ break;
+
+ default:
+ break;
+ }
+
+ if (_buttonId <= 3) {
+ _posX = (8 * _buttonId) - 2;
+ _flippedFl = true;
+ } else if (_buttonId <= 5) {
+ _posX = (13 * _buttonId) - 14;
+ _flippedFl = true;
+ } else {
+ _posX = (8 * _buttonId) + 98;
+ _flippedFl = false;
+ }
+}
+
+void Scene320::enter() {
+ _blinkFl = true;
+ _rightItemId = 8;
+ _leftItemId = 10;
+ _lastFrame = 0;
+
+ for (int i = 0; i < 10; i++)
+ _globals._spriteIndexes[i] = _scene->_sprites.addSprites(formAnimName('M', i));
+
+ for (int i = 0; i < 8; i++)
+ _globals._spriteIndexes[10 + i] = _scene->_sprites.addSprites(formAnimName('N', i));
+
+ _globals._spriteIndexes[18] = _scene->_sprites.addSprites("*REXHAND");
+ _game._player._visible = false;
+
+ setRightView(_globals[kRightView320]);
+ setLeftView(0);
+
+ _vm->_palette->setEntry(252, 63, 30, 20);
+ _vm->_palette->setEntry(253, 45, 15, 10);
+
+ sceneEntrySound();
+}
+
+void Scene320::step() {
+ if (_scene->_activeAnimation != nullptr) {
+ if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _lastFrame = _scene->_activeAnimation->getCurrentFrame();
+ switch (_lastFrame) {
+ case 95:
+ _blinkFl = true;
+ setLeftView(9);
+ _vm->_sound->command(41);
+ break;
+
+ case 139:
+ _blinkFl = false;
+ setLeftView(9);
+ break;
+
+ case 191:
+ _scene->_kernelMessages.add(Common::Point(1, 1), 0xFDFC, 0, 0, 60, _game.getQuote(0xFE));
+ break;
+
+ case 417:
+ case 457:
+ _vm->_screen._shakeCountdown = 40;
+ _vm->_sound->command(59);
+ break;
+
+ case 430:
+ _blinkFl = true;
+ setLeftView(4);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (_game._trigger == 70) {
+ _globals[kAfterHavoc] = true;
+ _globals[kTeleporterRoom + 1] = 351;
+ _scene->_nextSceneId = 361;
+ }
+}
+
+void Scene320::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(32011);
+ else if ((_action.isAction(VERB_PRESS) || _action.isAction(VERB_PUSH)) &&
+ (_action.isObject(NOUN_LEFT_1_KEY) || _action.isObject(NOUN_LEFT_2_KEY) || _action.isObject(NOUN_LEFT_3_KEY) || _action.isObject(NOUN_LEFT_4_KEY) ||
+ _action.isObject(NOUN_GREEN_BUTTON) || _action.isObject(NOUN_RED_BUTTON) || _action.isObject(NOUN_RIGHT_1_KEY) || _action.isObject(NOUN_RIGHT_2_KEY) ||
+ _action.isObject(NOUN_RIGHT_3_KEY) || _action.isObject(NOUN_RIGHT_4_KEY) || _action.isObject(NOUN_RIGHT_5_KEY) || _action.isObject(NOUN_RIGHT_6_KEY) ||
+ _action.isObject(NOUN_RIGHT_7_KEY) || _action.isObject(NOUN_RIGHT_8_KEY)
+ )) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ handleButtons();
+ _globals._sequenceIndexes[18] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[18], _flippedFl, 4, 2, 0, 0);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[18], 60);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[18], Common::Point(_posX, 170));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[18], 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[18], SEQUENCE_TRIGGER_LOOP, 0, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[18], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ if (_buttonId >= 6) {
+ _vm->_sound->command(60);
+ setRightView(_buttonId - 6);
+ }
+ if (_buttonId == 4) {
+ _vm->_sound->command(38);
+ if (_leftItemId == 3)
+ setLeftView(0);
+ else
+ setLeftView(3);
+ }
+ if (_buttonId == 5) {
+ _vm->_sound->command(38);
+ if (_leftItemId == 1)
+ setLeftView(2);
+ else
+ setLeftView(1);
+ }
+ if (_buttonId <= 3) {
+ _vm->_sound->command(60);
+ setLeftView(_buttonId + 5);
+ }
+ break;
+
+ case 2:
+ _game._player._stepEnabled = true;
+ if (_buttonId == 5) {
+ if (_leftItemId == 2) {
+ _game._player._stepEnabled = false;
+ setRightView(8);
+ setLeftView(10);
+ _scene->_kernelMessages.reset();
+ _scene->resetScene();
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 2));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('m', 4));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('m', 9));
+ _blinkFl = false;
+ setLeftView(2);
+ _game.loadQuoteSet(0xFE, 0);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->loadAnimation(formAnimName('a', -1), 70);
+ _vm->_sound->command(17);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LEAVE, NOUN_SECURITY_STATION))
+ _scene->_nextSceneId = 311;
+ else if (_action.isAction(VERB_LOOK, NOUN_RIGHT_MONITOR))
+ _vm->_dialogs->show(32001);
+ else if (_action.isAction(VERB_LOOK, NOUN_LEFT_MONITOR))
+ _vm->_dialogs->show(32002);
+ else if (_action.isAction(VERB_LOOK, NOUN_DESK))
+ _vm->_dialogs->show(32003);
+ else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_STATION))
+ _vm->_dialogs->show(32004);
+ else if (_action.isAction(VERB_LOOK, NOUN_MUG))
+ _vm->_dialogs->show(32005);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOUGHNUT))
+ _vm->_dialogs->show(32006);
+ else if (_action.isAction(VERB_LOOK, NOUN_MAGAZINE))
+ _vm->_dialogs->show(32006);
+ else if (_action.isAction(VERB_LOOK, NOUN_PAPER_FOOTBALL))
+ _vm->_dialogs->show(32008);
+ else if (_action.isAction(VERB_LOOK, NOUN_NEWSPAPER))
+ _vm->_dialogs->show(32009);
+ else if (_action.isAction(VERB_LOOK, NOUN_CLIPBOARD))
+ _vm->_dialogs->show(32010);
+ else if (_action.isAction(VERB_TAKE, NOUN_MUG))
+ _vm->_dialogs->show(32012);
+ else if (_action.isAction(VERB_TAKE, NOUN_CLIPBOARD))
+ _vm->_dialogs->show(32013);
+ else if (_action.isAction(VERB_TAKE, NOUN_DOUGHNUT) || _action.isAction(VERB_EAT, NOUN_DOUGHNUT))
+ _vm->_dialogs->show(32014);
+ else if (_action.isAction(VERB_TAKE, NOUN_PAPER_FOOTBALL))
+ _vm->_dialogs->show(32015);
+ else if (_action.isAction(VERB_TAKE, NOUN_MAGAZINE))
+ _vm->_dialogs->show(32016);
+ else if (_action.isAction(VERB_TAKE, NOUN_NEWSPAPER))
+ _vm->_dialogs->show(32017);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene321::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene321::enter() {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+
+ _scene->_userInterface.emptyConversationList();
+ _scene->_userInterface.setup(kInputConversation);
+
+ int suffixNum;
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _globals[kSexOfRex] = REX_MALE;
+ suffixNum = 1;
+ } else {
+ _globals[kSexOfRex] = REX_FEMALE;
+ suffixNum = _game._visitedScenes._sceneRevisited ? 2 : 0;
+ }
+
+ _scene->loadAnimation(formAnimName('g', suffixNum), 60);
+ sceneEntrySound();
+}
+
+void Scene321::step() {
+ if (_scene->_activeAnimation != nullptr) {
+ if ((_scene->_activeAnimation->getCurrentFrame() >= 260) && (_globals[kSexOfRex] == REX_MALE) && (_game._storyMode >= STORYMODE_NICE))
+ _scene->_nextSceneId = 316;
+ }
+
+ if (_game._trigger == 60)
+ _scene->_nextSceneId = 316;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene322::setup() {
+ _game._player._spritesPrefix = "";
+ // The original is calling scene3xx_setAAName()
+ _game._aaName = Resources::formatAAName(4);
+}
+
+void Scene322::enter() {
+ if (_globals[kSexOfRex] == REX_MALE)
+ _handSpriteId = _scene->_sprites.addSprites("*REXHAND");
+ else
+ _handSpriteId = _scene->_sprites.addSprites("*ROXHAND");
+
+ teleporterEnter();
+
+ // The original is using scene3xx_sceneEntrySound()
+ if (!_vm->_musicFlag)
+ _vm->_sound->command(2);
+ else
+ _vm->_sound->command(10);
+}
+
+void Scene322::step() {
+ teleporterStep();
+}
+
+void Scene322::actions() {
+ if (_action._lookFlag) {
+ _vm->_dialogs->show(32214);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (teleporterActions()) {
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT))
+ _vm->_dialogs->show(32210);
+ else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD))
+ _vm->_dialogs->show(32211);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY))
+ _vm->_dialogs->show(32212);
+ else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY))
+ _vm->_dialogs->show(32213);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEVICE))
+ _vm->_dialogs->show(32214);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene351::setup() {
+ if (_scene->_currentSceneId == 391)
+ _globals[kSexOfRex] = REX_MALE;
+
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene351::enter() {
+ _globals[kAfterHavoc] = -1;
+ _globals[kTeleporterRoom + 1] = 351;
+
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_7");
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXRD_7");
+
+ if (_game._objects.isInRoom(OBJ_CREDIT_CHIP)) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 4);
+ } else
+ _scene->_hotspots.activate(NOUN_CREDIT_CHIP, false);
+
+ if (_scene->_priorSceneId == 352)
+ _game._player._playerPos = Common::Point(148, 152);
+ else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(207, 81);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ if (_globals[kTeleporterCommand]) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+
+ char sepChar = 'a';
+ if (_globals[kSexOfRex] != REX_MALE)
+ sepChar = 'b';
+
+ int suffixNum = -1;
+ int trigger = 0;
+
+ switch (_globals[kTeleporterCommand]) {
+ case 1:
+ suffixNum = 0;
+ trigger = 60;
+ _globals[kTeleporterCommand] = true;
+ break;
+
+ case 2:
+ suffixNum = 1;
+ trigger = 61;
+ break;
+
+ case 3:
+ case 4:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _game._player._turnToFacing = FACING_SOUTH;
+ suffixNum = -1;
+ break;
+
+ default:
+ break;
+ }
+
+ _globals[kTeleporterCommand] = 0;
+
+ if (suffixNum >= 0)
+ _scene->loadAnimation(formAnimName(sepChar, suffixNum), trigger);
+ }
+
+ sceneEntrySound();
+}
+
+void Scene351::step() {
+ if (_game._trigger == 60) {
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._turnToFacing = FACING_SOUTH;
+ }
+
+ if (_game._trigger == 61) {
+ _globals[kTeleporterCommand] = 1;
+ _scene->_nextSceneId = _globals[kTeleporterDestination];
+ _scene->_reloadSceneFlag = true;
+ }
+}
+
+void Scene351::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(35121);
+ else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER))
+ _scene->_nextSceneId = 322;
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH))
+ _scene->_nextSceneId = 352;
+ else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP)) {
+ if (_game._trigger || !_game._objects.isInInventory(OBJ_CREDIT_CHIP)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ } else {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 1:
+ _scene->_hotspots.activate(NOUN_CREDIT_CHIP, false);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _game._objects.addToInventory(OBJ_CREDIT_CHIP);
+ break;
+
+ case 2:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 0x32F);
+ break;
+ }
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN))
+ _vm->_dialogs->show(35110);
+ else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR))
+ _vm->_dialogs->show(35111);
+ else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT))
+ _vm->_dialogs->show(35112);
+ else if (_action.isAction(VERB_LOOK, NOUN_GUARD)) {
+ if (_game._objects[0xF]._roomNumber == 351)
+ _vm->_dialogs->show(35114);
+ else
+ _vm->_dialogs->show(35113);
+ } else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT))
+ _vm->_dialogs->show(35115);
+ else if (_action.isAction(VERB_LOOK, NOUN_DESK))
+ _vm->_dialogs->show(35116);
+ else if (_action.isAction(VERB_LOOK, NOUN_MACHINE))
+ _vm->_dialogs->show(35117);
+ else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER))
+ _vm->_dialogs->show(35118);
+ else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL))
+ _vm->_dialogs->show(35119);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(35120);
+ else if (_action.isAction(VERB_LOOK, NOUN_POLE))
+ _vm->_dialogs->show(35122);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene352::Scene352(MADSEngine *vm) : Scene3xx(vm) {
+ _vaultOpenFl = false;
+ _mustPutArmDownFl = false;
+ _leaveRoomFl = false;
+
+ _tapePlayerHotspotIdx = -1;
+ _hotspot1Idx = -1;
+ _hotspot2Idx = -1;
+ _lampHostpotIdx = -1;
+ _commonSequenceIdx = -1;
+ _commonSpriteIndex = -1;
+}
+
+void Scene352::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsByte(_vaultOpenFl);
+ s.syncAsByte(_mustPutArmDownFl);
+ s.syncAsByte(_leaveRoomFl);
+
+ s.syncAsSint32LE(_tapePlayerHotspotIdx);
+ s.syncAsSint32LE(_hotspot1Idx);
+ s.syncAsSint32LE(_hotspot2Idx);
+ s.syncAsSint32LE(_lampHostpotIdx);
+ s.syncAsSint32LE(_commonSequenceIdx);
+ s.syncAsSint32LE(_commonSpriteIndex);
+}
+
+void Scene352::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_YOUR_STUFF);
+ _scene->addActiveVocab(NOUN_OTHER_STUFF);
+ _scene->addActiveVocab(NOUN_LAMP);
+}
+
+void Scene352::putArmDown(bool corridorExit, bool doorwayExit) {
+ switch (_game._trigger) {
+ case 0:
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0xFF));
+ _scene->_sequences.addTimer(48, 1);
+ break;
+
+ case 1:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 5, 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ } else {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ }
+ break;
+
+ case 2: {
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0);
+ int idx = _scene->_dynamicHotspots.add(NOUN_GUARDS_ARM2, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(230, 117), FACING_NORTHWEST);
+ _scene->changeVariant(0);
+ }
+ break;
+
+ case 3:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x100));
+ _game._objects.setRoom(OBJ_GUARDS_ARM, _scene->_currentSceneId);
+ _game._player._visible = true;
+ if (corridorExit)
+ _scene->_sequences.addTimer(48, 6);
+ else if (doorwayExit)
+ _scene->_sequences.addTimer(48, 4);
+ else {
+ _mustPutArmDownFl = false;
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ case 4:
+ _game._player.walk(Common::Point(116, 107), FACING_NORTH);
+ _game._player._stepEnabled = true;
+ _mustPutArmDownFl = false;
+ _scene->_sequences.addTimer(180, 5);
+ _leaveRoomFl = true;
+ break;
+
+ case 5:
+ if (_leaveRoomFl)
+ _scene->_nextSceneId = 351;
+
+ break;
+
+ case 6:
+ _game._player.walk(Common::Point(171, 152), FACING_SOUTH);
+ _game._player._stepEnabled = true;
+ _mustPutArmDownFl = false;
+ _scene->_sequences.addTimer(180, 7);
+ _leaveRoomFl = true;
+ break;
+
+ case 7:
+ if (_leaveRoomFl)
+ _scene->_nextSceneId = 353;
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene352::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*RM302x0");
+ _globals._spriteIndexes[13] = _scene->_sprites.addSprites("*RM302x2");
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RM302x3");
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', -1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', -1));
+
+
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXRC_7");
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXRC_6");
+ _globals._spriteIndexes[15] = _scene->_sprites.addSprites("*ROXRC_9");
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 3));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 2));
+ } else {
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXRD_7");
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXRC_6");
+ _globals._spriteIndexes[14] = _scene->_sprites.addSprites("*RXMRC_9");
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ }
+
+ _leaveRoomFl = false;
+
+ if (_game._objects.isInRoom(OBJ_TAPE_PLAYER)) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 5);
+ int idx = _scene->_dynamicHotspots.add(NOUN_TAPE_PLAYER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _tapePlayerHotspotIdx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(84, 145), FACING_WEST);
+ }
+
+ _vaultOpenFl = false;
+
+ if (_scene->_priorSceneId != -2) {
+ _mustPutArmDownFl = false;
+ if (!_game._visitedScenes._sceneRevisited)
+ _globals[kHaveYourStuff] = false;
+ }
+
+ if (_game._objects.isInRoom(OBJ_GUARDS_ARM)) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0);
+ int idx = _scene->_dynamicHotspots.add(NOUN_GUARDS_ARM2, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(230, 117), FACING_NORTHWEST);
+ } else
+ _mustPutArmDownFl = true;
+
+ if (_scene->_priorSceneId == 353)
+ _game._player._playerPos = Common::Point(171, 155);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(116, 107);
+
+ sceneEntrySound();
+
+ _game.loadQuoteSet(0xFF, 0x100, 0x101, 0x102, 0x103, 0);
+}
+
+void Scene352::preActions() {
+ _leaveRoomFl = false;
+
+ if (_action.isAction(VERB_OPEN, NOUN_VAULT))
+ _game._player.walk(Common::Point(266, 111), FACING_NORTHEAST);
+
+ if (_vaultOpenFl && !_action.isObject(NOUN_VAULT) && !_action.isObject(NOUN_LAMP) && !_action.isObject(NOUN_OTHER_STUFF) && !_action.isObject(NOUN_YOUR_STUFF)) {
+ if (_globals[kHaveYourStuff]) {
+ _commonSpriteIndex = _globals._spriteIndexes[13];
+ _commonSequenceIdx = _globals._sequenceIndexes[13];
+ } else {
+ _commonSpriteIndex = _globals._spriteIndexes[1];
+ _commonSequenceIdx = _globals._sequenceIndexes[1];
+ }
+
+ switch (_game._trigger) {
+ case 0:
+ if (_game._player._needToWalk) {
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_commonSequenceIdx);
+ _vm->_sound->command(20);
+ _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.setDepth(_commonSequenceIdx, 15);
+ }
+ break;
+
+ case 1:
+ if (!_globals[kHaveYourStuff])
+ _scene->_dynamicHotspots.remove(_hotspot2Idx);
+
+ _scene->_dynamicHotspots.remove(_hotspot1Idx);
+ _scene->_dynamicHotspots.remove(_lampHostpotIdx);
+ _vaultOpenFl = false;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (_action.isAction(VERB_PUT, NOUN_GUARDS_ARM2, NOUN_SCANNER)) {
+ if (_globals[kSexOfRex] == REX_MALE)
+ _game._player.walk(Common::Point(269, 111), FACING_NORTHEAST);
+ else
+ _game._player.walk(Common::Point(271, 111), FACING_NORTHEAST);
+ }
+
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY) || _action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) || _action.isAction(VERB_PUT, NOUN_GUARDS_ARM2, NOUN_FLOOR)) {
+ if (_game._objects.isInInventory(OBJ_GUARDS_ARM))
+ _game._player.walk(Common::Point(230, 117), FACING_NORTHWEST);
+ }
+}
+
+void Scene352::actions() {
+ if (_action._lookFlag) {
+ _vm->_dialogs->show(35225);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_OPEN, NOUN_VAULT)) {
+ if (!_vaultOpenFl) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_FEMALE)
+ _commonSpriteIndex = _globals._spriteIndexes[9];
+ else
+ _commonSpriteIndex = _globals._spriteIndexes[8];
+
+ _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 8, 1, 0, 0);
+ _scene->_sequences.updateTimeout(_commonSequenceIdx, -1);
+ _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ _vm->_sound->command(21);
+ _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], FACING_NORTH);
+ int oldIdx = _commonSequenceIdx;
+ _commonSequenceIdx = _scene->_sequences.startCycle(_commonSpriteIndex, false, -2);
+ _scene->_sequences.updateTimeout(_commonSequenceIdx, oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 2:
+ _vm->_sound->command(22);
+ _scene->_sequences.remove(_commonSequenceIdx);
+ _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 3);
+ _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3:
+ _scene->_sequences.updateTimeout(-1, _commonSequenceIdx);
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(60, 4);
+ break;
+
+ case 4:
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x101));
+ _game._player._stepEnabled = true;
+ break;
+ }
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_game._objects.isInInventory(OBJ_GUARDS_ARM)) {
+ _mustPutArmDownFl = true;
+ }
+
+ bool exit_corridor = false;
+ bool exit_doorway = false;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) {
+ exit_corridor = true;
+ }
+
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) {
+ exit_doorway = true;
+ }
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) || _action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY) || _action.isAction(VERB_PUT, NOUN_GUARDS_ARM2, NOUN_FLOOR)) {
+ if (_mustPutArmDownFl)
+ putArmDown(exit_corridor, exit_doorway);
+ else if (exit_corridor)
+ _scene->_nextSceneId = 353;
+ else
+ _scene->_nextSceneId = 351;
+
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_GUARDS_ARM2)) {
+ if (_game._trigger || !_game._objects.isInInventory(OBJ_GUARDS_ARM)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 5, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ } else {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _game._objects.addToInventory(OBJ_GUARDS_ARM);
+ _scene->changeVariant(1);
+ break;
+
+ case 2:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_GUARDS_ARM, 0x899C);
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+ }
+
+ if (_action.isAction(VERB_PUT, NOUN_GUARDS_ARM2, NOUN_SCANNER)) {
+ if (!_vaultOpenFl) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_FEMALE)
+ _commonSpriteIndex = _globals._spriteIndexes[11];
+ else
+ _commonSpriteIndex = _globals._spriteIndexes[10];
+
+ _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 8, 1, 0, 0);
+ _scene->_sequences.updateTimeout(_commonSequenceIdx, -1);
+ _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ _vm->_sound->command(21);
+ _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8);
+ int oldIdx = _commonSequenceIdx;
+ _commonSequenceIdx = _scene->_sequences.startCycle(_commonSpriteIndex, false, -2);
+ _scene->_sequences.updateTimeout(_commonSequenceIdx, oldIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 2:
+ _vm->_sound->command(23);
+ _scene->_sequences.remove(_commonSequenceIdx);
+ _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 4);
+ _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+
+ case 3:
+ _scene->_sequences.updateTimeout(-1, _commonSequenceIdx);
+ _game._player._visible = true;
+ if (_globals[kHaveYourStuff])
+ _commonSpriteIndex = _globals._spriteIndexes[13];
+ else
+ _commonSpriteIndex = _globals._spriteIndexes[1];
+
+ _vm->_sound->command(20);
+ _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_commonSequenceIdx, 15);
+ _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ break;
+
+ case 4:
+ _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 6, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_commonSequenceIdx, -2, -2);
+ _scene->_sequences.setDepth(_commonSequenceIdx, 15);
+ _scene->_sequences.addTimer(60, 5);
+ break;
+
+ case 5: {
+ _vaultOpenFl = true;
+ int idx;
+ if (!_globals[kHaveYourStuff]) {
+ idx = _scene->_dynamicHotspots.add(NOUN_YOUR_STUFF, VERB_WALKTO, -1, Common::Rect(282, 87, 282 + 13, 87 + 7));
+ _hotspot2Idx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(280, 111), FACING_NORTHEAST);
+ _globals._sequenceIndexes[1] = _commonSequenceIdx;
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x102));
+ } else {
+ _globals._sequenceIndexes[13] = _commonSequenceIdx;
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x103));
+ }
+
+ idx = _scene->_dynamicHotspots.add(NOUN_OTHER_STUFF, VERB_WALKTO, -1, Common::Rect(282, 48, 282 + 36, 48 + 27));
+ _hotspot1Idx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(287, 115), FACING_NORTHEAST);
+ idx = _scene->_dynamicHotspots.add(NOUN_LAMP, VERB_WALKTO, -1, Common::Rect(296, 76, 296 + 11, 76 + 17));
+ _lampHostpotIdx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(287, 115), FACING_NORTHEAST);
+ _game._player._stepEnabled = true;
+ }
+ break;
+ }
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_YOUR_STUFF)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._sequenceIndexes[14] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[14], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[14], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[14]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[14], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[14], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ } else {
+ _globals._sequenceIndexes[15] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[15], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[15], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[15]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[15], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[15], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 1:
+ _scene->_dynamicHotspots.remove(_hotspot2Idx);
+ _globals[kHaveYourStuff] = true;
+
+ for (uint16 i = 0; i < _game._objects.size(); i++) {
+ if (_game._objects[i]._roomNumber == 50)
+ _game._objects.addToInventory(i);
+ }
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 15);
+ break;
+
+ case 2:
+ if (_globals[kSexOfRex] == REX_MALE)
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[14]);
+ else
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[15]);
+
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_TAPE_PLAYER) && !_game._objects.isInInventory(OBJ_TAPE_PLAYER)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], true, 6, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ } else {
+ _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], true, 6, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[7]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _scene->_dynamicHotspots.remove(_tapePlayerHotspotIdx);
+ break;
+
+ case 2:
+ _game._objects.addToInventory(OBJ_TAPE_PLAYER);
+ if (_globals[kSexOfRex] == REX_MALE)
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]);
+ else
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[7]);
+
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_TAPE_PLAYER, 35227);
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_SCANNER))
+ _vm->_dialogs->show(35210);
+ else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) {
+ if (_game._storyMode == STORYMODE_NAUGHTY)
+ _vm->_dialogs->show(35211);
+ else
+ _vm->_dialogs->show(35212);
+ } else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY))
+ _vm->_dialogs->show(35213);
+ else if (_action.isAction(VERB_LOOK, NOUN_STATUE))
+ _vm->_dialogs->show(35214);
+ else if (_action.isAction(VERB_LOOK, NOUN_TAPE_PLAYER) && (_action._savedFields._mainObjectSource == 4))
+ _vm->_dialogs->show(35215);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT))
+ _vm->_dialogs->show(35216);
+ else if (_action.isAction(VERB_LOOK, NOUN_GUARDS_ARM2) && (_action._savedFields._mainObjectSource == 4))
+ _vm->_dialogs->show(35217);
+ else if (_action.isAction(VERB_LOOK, NOUN_IRONING_BOARD))
+ _vm->_dialogs->show(35218);
+ else if (_action.isAction(VERB_LOOK, NOUN_CLOCK))
+ _vm->_dialogs->show(35219);
+ else if (_action.isAction(VERB_LOOK, NOUN_GAUGE))
+ _vm->_dialogs->show(35220);
+ else if (_action.isAction(VERB_LOOK, NOUN_VAULT)) {
+ if (!_vaultOpenFl)
+ _vm->_dialogs->show(35221);
+ } else if (_action.isAction(VERB_LOOK, NOUN_YOUR_STUFF))
+ _vm->_dialogs->show(35222);
+ else if (_action.isAction(VERB_LOOK, NOUN_OTHER_STUFF))
+ _vm->_dialogs->show(35223);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(35224);
+ else if (_action.isAction(VERB_TAKE, NOUN_OTHER_STUFF))
+ _vm->_dialogs->show(35226);
+ else if (_action.isAction(VERB_LOOK, NOUN_DESK))
+ _vm->_dialogs->show(35229);
+ else if (_action.isAction(VERB_LOOK, NOUN_GUARD))
+ _vm->_dialogs->show(35230);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY))
+ _vm->_dialogs->show(35231);
+ else if (_action.isAction(VERB_LOOK, NOUN_TABLE))
+ _vm->_dialogs->show(35232);
+ else if (_action.isAction(VERB_LOOK, NOUN_PROJECTOR))
+ _vm->_dialogs->show(35233);
+ else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT))
+ _vm->_dialogs->show(35234);
+ else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_MONITOR))
+ _vm->_dialogs->show(35235);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene353::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene353::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(303, 'B', 0, EXT_SS, ""));
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 5, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ if (_scene->_priorSceneId == 352)
+ _game._player._playerPos = Common::Point(144, 95);
+ else
+ _game._player._playerPos = Common::Point(139, 155);
+
+ sceneEntrySound();
+}
+
+void Scene353::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(35315);
+ else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY))
+ _scene->_nextSceneId = 352;
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH))
+ _scene->_nextSceneId = 354;
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCK_CHUNK))
+ _vm->_dialogs->show(35310);
+ else if (_action.isAction(VERB_LOOK, NOUN_PIPES) || _action.isAction(VERB_LOOK, NOUN_PIPE))
+ _vm->_dialogs->show(35311);
+ else if (_action.isAction(VERB_LOOK, NOUN_BROKEN_BEAM))
+ _vm->_dialogs->show(35312);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY))
+ _vm->_dialogs->show(35313);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(35314);
+ else if (_action.isAction(VERB_LOOK, NOUN_FLOOR))
+ _vm->_dialogs->show(35316);
+ else if (_action.isAction(VERB_LOOK, NOUN_CEILING))
+ _vm->_dialogs->show(35317);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(35318);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene354::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene354::enter() {
+ _globals[kAfterHavoc] = true;
+ _globals[kTeleporterRoom + 1] = 351;
+
+ if (_scene->_priorSceneId == 361)
+ _game._player._playerPos = Common::Point(231, 110);
+ else if (_scene->_priorSceneId == 401) {
+ _game._player._playerPos = Common::Point(106, 152);
+ _game._player._facing = FACING_NORTH;
+ } else if (_scene->_priorSceneId == 316)
+ _game._player._playerPos = Common::Point(71, 107);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(167, 57);
+
+ sceneEntrySound();
+}
+
+void Scene354::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH))
+ _game._player._walkOffScreenSceneId = 401;
+}
+
+void Scene354::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(35414);
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) {
+ _game._player.startWalking(Common::Point(208, 0), FACING_NORTHEAST);
+ _game._player._walkOffScreenSceneId = 353;
+ } else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST))
+ _scene->_nextSceneId = 361;
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _scene->_nextSceneId = 316;
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH))
+ _scene->_nextSceneId = 401;
+ else if (_action.isAction(VERB_LOOK, NOUN_CONTROLS))
+ _vm->_dialogs->show(35410);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGNAL))
+ _vm->_dialogs->show(35411);
+ else if (_action.isAction(VERB_LOOK, NOUN_CATWALK))
+ _vm->_dialogs->show(35412);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_DUCT))
+ _vm->_dialogs->show(35413);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH))
+ _vm->_dialogs->show(35415);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(35416);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(35417);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(35418);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS))
+ _vm->_dialogs->show(35419);
+ else if (_action.isAction(VERB_LOOK, NOUN_GUARD))
+ _vm->_dialogs->show(35420);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene357::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene357::enter() {
+ _globals[kAfterHavoc] = true;
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ if (_scene->_priorSceneId == 318)
+ _game._player._playerPos = Common::Point(298, 142);
+ else if (_scene->_priorSceneId == 313)
+ _game._player._playerPos = Common::Point(127, 101);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(15, 148);
+
+ sceneEntrySound();
+}
+
+void Scene357::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST))
+ _game._player._walkOffScreenSceneId = 318;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _game._player._walkOffScreenSceneId = 358;
+}
+
+void Scene357::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(35715);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT))
+ _vm->_dialogs->show(35710);
+ else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT))
+ _vm->_dialogs->show(35711);
+ else if (_action.isAction(VERB_LOOK, NOUN_BED))
+ _vm->_dialogs->show(35712);
+ else if (_action.isAction(VERB_LOOK, NOUN_SINK))
+ _vm->_dialogs->show(35713);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOILET))
+ _vm->_dialogs->show(35714);
+ else if (_action.isAction(VERB_LOOK, NOUN_CELL_WALL))
+ _vm->_dialogs->show(35716);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHT))
+ _vm->_dialogs->show(35717);
+ else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR))
+ _vm->_dialogs->show(35718);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS))
+ _vm->_dialogs->show(35719);
+ else if (_action.isAction(VERB_TAKE, NOUN_DEBRIS))
+ _vm->_dialogs->show(35720);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(35721);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(35722);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(35723);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene358::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene358::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ if (_scene->_priorSceneId == 357)
+ _game._player._playerPos = Common::Point(305, 142);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(12, 141);
+
+ sceneEntrySound();
+}
+
+void Scene358::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST))
+ _game._player._walkOffScreenSceneId = 357;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _game._player._walkOffScreenSceneId = 359;
+}
+
+void Scene358::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(35815);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(35810);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(35811);
+ else if (_action.isAction(VERB_LOOK, NOUN_BED))
+ _vm->_dialogs->show(35812);
+ else if (_action.isAction(VERB_LOOK, NOUN_SINK))
+ _vm->_dialogs->show(35813);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOILET))
+ _vm->_dialogs->show(35814);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(35816);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT))
+ _vm->_dialogs->show(35817);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene359::Scene359(MADSEngine *vm) : Scene3xx(vm) {
+ _cardHotspotId = -1;
+}
+
+void Scene359::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsSint32LE(_cardHotspotId);
+}
+
+void Scene359::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene359::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', -1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+
+ if (_globals[kSexOfRex] == REX_MALE)
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMBD_2");
+ else
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*ROXBD_2");
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15);
+
+ if (_game._objects.isInRoom(OBJ_SECURITY_CARD)) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0);
+ _cardHotspotId = _scene->_dynamicHotspots.add(NOUN_SECURITY_CARD, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_cardHotspotId, Common::Point(107, 107), FACING_SOUTH);
+ }
+
+ if (_scene->_priorSceneId == 358)
+ _game._player._playerPos = Common::Point(301, 141);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(15, 148);
+
+ sceneEntrySound();
+}
+
+void Scene359::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST))
+ _game._player._walkOffScreenSceneId = 358;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _game._player._walkOffScreenSceneId = 360;
+}
+
+void Scene359::actions() {
+ if (_action._lookFlag) {
+ if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359))
+ _vm->_dialogs->show(35914);
+ else
+ _vm->_dialogs->show(35915);
+ } else if (_action.isAction(VERB_TAKE, NOUN_SECURITY_CARD)) {
+ if (_game._trigger || !_game._objects.isInInventory(OBJ_SECURITY_CARD)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _vm->_dialogs->show(35920);
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 4, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ } else {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], true, 7, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(106, 110));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_cardHotspotId);
+ _vm->_sound->command(57);
+ _game._objects.addToInventory(OBJ_SECURITY_CARD);
+ _vm->_dialogs->showItem(OBJ_SECURITY_CARD, 0x330);
+ _scene->changeVariant(1);
+ break;
+
+ case 2:
+ if (_globals[kSexOfRex] == REX_MALE)
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ else
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]);
+
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_BLOODY_CELL_WALL))
+ _vm->_dialogs->show(35910);
+ else if (_action.isAction(VERB_LOOK, NOUN_BED))
+ _vm->_dialogs->show(35911);
+ else if (_action.isAction(VERB_LOOK, NOUN_SINK))
+ _vm->_dialogs->show(35912);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOILET))
+ _vm->_dialogs->show(35913);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(35916);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(35917);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIMB))
+ _vm->_dialogs->show(35918);
+ else if (_action.isAction(VERB_TAKE, NOUN_LIMB))
+ _vm->_dialogs->show(35919);
+ else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_CARD) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(35921);
+ else if (_action.isAction(VERB_LOOK, NOUN_BLOOD_STAIN)) {
+ if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359))
+ _vm->_dialogs->show(35922);
+ else
+ _vm->_dialogs->show(35923);
+ } else if (_action.isAction(VERB_LOOK, NOUN_WALL_BOARD))
+ _vm->_dialogs->show(35924);
+ else if (_action.isAction(VERB_TAKE, NOUN_WALL_BOARD))
+ _vm->_dialogs->show(35925);
+ else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR))
+ _vm->_dialogs->show(35926);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR))
+ _vm->_dialogs->show(35927);
+ else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) {
+ if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359))
+ _vm->_dialogs->show(35928);
+ else
+ _vm->_dialogs->show(35929);
+ } else if (_action.isAction(VERB_OPEN, NOUN_AIR_VENT) || _action.isAction(VERB_LOOK, NOUN_AIR_VENT))
+ _vm->_dialogs->show(36016);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene360::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene360::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ if (_scene->_priorSceneId == 359)
+ _game._player._playerPos = Common::Point(304, 143);
+ else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(13, 141);
+
+ sceneEntrySound();
+}
+
+void Scene360::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST))
+ _game._player._walkOffScreenSceneId = 359;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _game._player._walkOffScreenSceneId = 361;
+}
+
+void Scene360::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(36015);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(36010);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(36011);
+ else if (_action.isAction(VERB_LOOK, NOUN_BED))
+ _vm->_dialogs->show(36012);
+ else if (_action.isAction(VERB_LOOK, NOUN_SINK))
+ _vm->_dialogs->show(36013);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOILET))
+ _vm->_dialogs->show(36014);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT))
+ _vm->_dialogs->show(36016);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR))
+ _vm->_dialogs->show(36017);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(36018);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene361::setup() {
+ if (_scene->_currentSceneId == 391)
+ _globals[kSexOfRex] = REX_MALE;
+
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene361::handleRexAction() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 50, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 3, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1: {
+ int seqIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 4);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], seqIdx);
+ }
+ break;
+
+ case 2: {
+ int seqIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 4, 10);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ }
+ break;
+
+ case 3: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ int seqIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx);
+ _scene->_sequences.addTimer(15, 4);
+ }
+ break;
+
+ case 4:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ _scene->_sequences.setDone(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 12, 14);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 5);
+ break;
+
+ case 5: {
+ int seqIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 15);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx);
+ _scene->_sequences.addTimer(15, 6);
+ }
+ break;
+
+ case 6:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[2]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.addTimer(48, 7);
+ break;
+
+ case 7:
+ _scene->_nextSceneId = 313;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene361::handleRoxAction() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 18, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 4);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 18, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1: {
+ int tmpIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 4);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], tmpIdx);
+ }
+ break;
+
+ case 2: {
+ int tmpIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 8);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ }
+ break;
+
+ case 3: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ int tmpIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 9, 10);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ }
+ break;
+
+ case 4: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ int tmpIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 11, 15);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5);
+ }
+ break;
+
+ case 5: {
+ int tmpIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 16);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx);
+ _scene->_sequences.addTimer(48, 6);
+ }
+ break;
+
+ case 6:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[4]);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.addTimer(48, 7);
+ break;
+
+ case 7:
+ _scene->_nextSceneId = 313;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene361::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, ""));
+
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXCL_8");
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCL_2");
+ } else
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*ROXCL_8");
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ if (_scene->_priorSceneId == 391) {
+ _globals[kSexOfRex] = REX_MALE;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _game._player._facing = FACING_SOUTH;
+ _game._player._playerPos = Common::Point(166, 101);
+ _scene->_sequences.addTimer(120, 70);
+ } else if (_scene->_priorSceneId == 360)
+ _game._player._playerPos = Common::Point(302, 145);
+ else if (_scene->_priorSceneId == 320) {
+ _game._player._playerPos = Common::Point(129, 113);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(13, 145);
+
+ _game.loadQuoteSet(0xFB, 0xFC, 0);
+
+ if (_scene->_priorSceneId == 320)
+ _scene->_kernelMessages.setQuoted(_scene->_kernelMessages.addQuote(0xFB, 0, 0x78), 4, true);
+
+ sceneEntrySound();
+}
+
+void Scene361::step() {
+ if (_game._trigger >= 70) {
+ switch (_game._trigger) {
+ case 70:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 71);
+ break;
+
+ case 71:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 72);
+ break;
+
+ case 72:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 73);
+ break;
+
+ case 73:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74);
+ break;
+
+ case 74: {
+ int seqIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx);
+ _scene->_sequences.addTimer(15, 75);
+ }
+ break;
+
+ case 75:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 76);
+ break;
+
+ case 76:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 8);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 77);
+ break;
+
+ case 77:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15);
+
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 9);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 78);
+ break;
+
+ case 78:
+ _scene->_sequences.setDone(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 10, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 79);
+ break;
+
+ case 79:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]);
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene361::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST))
+ _game._player._walkOffScreenSceneId = 360;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _game._player._walkOffScreenSceneId = 354;
+}
+
+void Scene361::actions() {
+ if (_action._lookFlag)
+ _vm->_dialogs->show(36119);
+ else if (_action.isAction(VERB_SIT_AT, NOUN_DESK)) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.addQuote(0xFC, 120, 0);
+ } else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) {
+ if (_globals[kSexOfRex] == REX_FEMALE)
+ handleRoxAction();
+ else
+ handleRexAction();
+ } else if (_action.isAction(VERB_LOOK, NOUN_DESK))
+ _vm->_dialogs->show(36110);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(36111);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHTING_FIXTURE) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTING_FIXTURE))
+ _vm->_dialogs->show(36112);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHTS) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTS))
+ _vm->_dialogs->show(36113);
+ else if (_action.isAction(VERB_TAKE, NOUN_LIGHTS))
+ _vm->_dialogs->show(36114);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHT_BULB) || _action.isAction(VERB_STARE_AT, NOUN_LIGHT_BULB))
+ _vm->_dialogs->show(36115);
+ else if (_action.isAction(VERB_TAKE, NOUN_LIGHT_BULB))
+ _vm->_dialogs->show(36116);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(36117);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(36118);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT))
+ _vm->_dialogs->show(36120);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene366::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene366::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ _game._player._visible = false;
+ sceneEntrySound();
+}
+
+void Scene366::actions() {
+ if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT))
+ _scene->_nextSceneId = 302;
+ else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) {
+ if (_game._visitedScenes.exists(316))
+ _vm->_dialogs->show(36612);
+ else
+ _vm->_dialogs->show(36613);
+ _scene->_nextSceneId = 316;
+ } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) {
+ if (_game._visitedScenes.exists(321))
+ _vm->_dialogs->show(36611);
+ else
+ _vm->_dialogs->show(36610);
+ } else {
+ return;
+ }
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene387::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene387::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ _game._player._visible = false;
+
+ sceneEntrySound();
+}
+
+void Scene387::actions() {
+ if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT))
+ _scene->_nextSceneId = 313;
+ else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE))
+ _vm->_dialogs->show(38710);
+ else if (_action.isAction(VERB_OPEN, NOUN_GRATE))
+ _vm->_dialogs->show(38711);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene388::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene388::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+
+ if (_globals[kAfterHavoc])
+ _scene->_hotspots.activate(NOUN_SAUROPOD, false);
+ else {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1);
+ }
+
+ _game._player._visible = false;
+ _vm->_palette->setEntry(252, 63, 30, 20);
+ _vm->_palette->setEntry(253, 45, 15, 12);
+ _game.loadQuoteSet(0x154, 0x155, 0x156, 0x157, 0x158, 0);
+
+ sceneEntrySound();
+}
+
+void Scene388::actions() {
+ if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT))
+ _scene->_nextSceneId = 313;
+ else if (_action.isAction(VERB_TALKTO, NOUN_SAUROPOD)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 1, 120, _game.getQuote(0x154));
+ break;
+
+ case 1:
+ _scene->_kernelMessages.add(Common::Point(82, 38), 0xFDFC, 0, 0, 300, _game.getQuote(0x156));
+ _scene->_kernelMessages.add(Common::Point(82, 52), 0xFDFC, 0, 0, 300, _game.getQuote(0x157));
+ _scene->_kernelMessages.add(Common::Point(82, 66), 0xFDFC, 0, 2, 300, _game.getQuote(0x158));
+ break;
+
+ case 2:
+ _game._player._stepEnabled = true;
+ _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 0, 120, _game.getQuote(0x155));
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) {
+ if (_globals[kAfterHavoc])
+ _vm->_dialogs->show(38811);
+ else
+ _vm->_dialogs->show(38810);
+ } else if (_action.isAction(VERB_OPEN, NOUN_GRATE))
+ _vm->_dialogs->show(38812);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene389::Scene389(MADSEngine *vm) : Scene300s(vm) {
+ _monsterTime = 0;
+ _circularQuoteId = -1;
+}
+
+void Scene389::synchronize(Common::Serializer &s) {
+ Scene3xx::synchronize(s);
+
+ s.syncAsUint32LE(_monsterTime);
+ s.syncAsSint32LE(_circularQuoteId);
+}
+
+void Scene389::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene389::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ _monsterTime = 0;
+ _circularQuoteId = 0x159;
+
+ if (_globals[kAfterHavoc])
+ _scene->_hotspots.activate(NOUN_MONSTER, false);
+ else {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('m', -1));
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0);
+ _scene->_kernelMessages.initRandomMessages(1,
+ Common::Rect(88, 19, 177, 77), 13, 2, 0xFDFC, 60,
+ 247, 248, 249, 0);
+ }
+
+ _vm->_palette->setEntry(252, 63, 37, 26);
+ _vm->_palette->setEntry(253, 45, 24, 17);
+ _game._player._visible = false;
+ _game.loadQuoteSet(0xF7, 0xF8, 0xF9, 0x159, 0x15A, 0x15B, 0);
+
+ sceneEntrySound();
+}
+
+void Scene389::step() {
+ _scene->_kernelMessages.randomServer();
+ if (_scene->_frameStartTime >= _monsterTime) {
+ int chanceMinor = _scene->_kernelMessages.checkRandom() * 4 + 1;
+ _scene->_kernelMessages.generateRandom(20, chanceMinor);
+ _monsterTime = _scene->_frameStartTime + 2;
+ }
+}
+
+void Scene389::actions() {
+ if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT))
+ _scene->_nextSceneId = 313;
+ else if (_action.isAction(VERB_TALKTO, NOUN_MONSTER)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 1, 120, _game.getQuote(_circularQuoteId));
+ _circularQuoteId++;
+ if (_circularQuoteId > 0x15B)
+ _circularQuoteId = 0x159;
+
+ break;
+
+ case 1:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) {
+ if (_globals[kAfterHavoc]) {
+ if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359))
+ _vm->_dialogs->show(38911);
+ else
+ _vm->_dialogs->show(38912);
+ } else
+ _vm->_dialogs->show(38910);
+ } else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) {
+ if (_globals[kAfterHavoc])
+ _vm->_dialogs->show(38914);
+ else
+ _vm->_dialogs->show(38913);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene390::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene390::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ _game._player._visible = false;
+
+ sceneEntrySound();
+}
+
+void Scene390::actions() {
+ if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT))
+ _scene->_nextSceneId = 313;
+ else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE))
+ _vm->_dialogs->show(39010);
+ else if (_action.isAction(VERB_OPEN, NOUN_GRATE))
+ _vm->_dialogs->show(39011);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene391::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene391::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ _game._player._visible = false;
+ sceneEntrySound();
+}
+
+void Scene391::actions() {
+ if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT))
+ _scene->_nextSceneId = 313;
+ else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) {
+ if (_globals[kKickedIn391Grate])
+ _vm->_dialogs->show(39113);
+ else {
+ _vm->_dialogs->show(39112);
+ _globals[kKickedIn391Grate] = true;
+ }
+
+ if (_globals[kAfterHavoc])
+ _scene->_nextSceneId = 361;
+ else
+ _scene->_nextSceneId = 311;
+ } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) {
+ if (_globals[kAfterHavoc])
+ _vm->_dialogs->show(39111);
+ else
+ _vm->_dialogs->show(39110);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene399::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene399::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ _game._player._visible = false;
+ sceneEntrySound();
+}
+
+void Scene399::actions() {
+ if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT))
+ _scene->_nextSceneId = 313;
+ else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) {
+ if (_globals[kAfterHavoc]) {
+ if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359))
+ _vm->_dialogs->show(38911);
+ else
+ _vm->_dialogs->show(38912);
+ } else
+ _vm->_dialogs->show(38910);
+ } else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) {
+ if (_globals[kAfterHavoc])
+ _vm->_dialogs->show(38914);
+ else
+ _vm->_dialogs->show(38913);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Nebular
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes3.h b/engines/mads/nebular/nebular_scenes3.h
new file mode 100644
index 0000000000..9efd38e9a4
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes3.h
@@ -0,0 +1,548 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_NEBULAR_SCENES3_H
+#define MADS_NEBULAR_SCENES3_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+typedef struct {
+ bool _flag;
+ int _vertical;
+ int _horizontal;
+ int _seqId[40];
+ uint32 _timer;
+
+ void init() {
+ _flag = false;
+ _vertical = _horizontal = -1;
+ _timer = 0;
+ for (int i = 0; i < 40; ++i)
+ _seqId[i] = -1;
+ }
+
+ void synchronize(Common::Serializer &s) {
+ s.syncAsByte(_flag);
+ s.syncAsSint32LE(_vertical);
+ s.syncAsSint32LE(_horizontal);
+ for (int i = 0; i < 40; ++i)
+ s.syncAsSint32LE(_seqId[i]);
+ s.syncAsUint32LE(_timer);
+ };
+} ForceField;
+
+class Scene3xx : public NebularScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void setAAName();
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix();
+
+ void sceneEntrySound();
+
+ void initForceField(ForceField *force, bool flag);
+ void handleForceField(ForceField *force, int *sprites);
+ int computeScale(int low, int high, int id);
+
+public:
+ Scene3xx(MADSEngine *vm) : NebularScene(vm) {}
+
+ virtual void actions() {}
+};
+
+class Scene300s : public Scene3xx {
+public:
+ Scene300s(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void preActions();
+};
+
+class Scene301 : public Scene3xx {
+public:
+ Scene301(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+};
+
+class Scene302 : public Scene3xx {
+private:
+ int _oldFrame;
+
+public:
+ Scene302(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+};
+
+class Scene303 : public Scene3xx {
+public:
+ Scene303(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+};
+
+class Scene304 : public Scene3xx {
+private:
+ int _explosionSpriteId;
+
+public:
+ Scene304(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+};
+
+class Scene307 : public Scene3xx {
+private:
+ ForceField _forceField;
+
+ bool _afterPeeingFl;
+ bool _duringPeeingFl;
+ bool _grateOpenedFl;
+ bool _activePrisonerFl;
+
+ int _animationMode;
+ int _prisonerMessageId;
+ int _fieldCollisionCounter;
+
+ uint32 _lastFrameTime;
+ uint32 _guardTime;
+ uint32 _prisonerTimer;
+
+ Common::String _subQuote2;
+
+ Conversation _dialog1, _dialog2;
+
+ void handleDialog();
+ void handleRexDialog(int quote);
+ void handlePrisonerDialog();
+ void handlePrisonerEncounter();
+ void setDialogNode(int node);
+ void handlePrisonerSpeech(int firstQuoteId, int number, long timeout);
+
+public:
+ Scene307(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene308 : public Scene3xx {
+private:
+ ForceField _forceField;
+
+public:
+ Scene308(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+};
+
+class Scene309 : public Scene3xx {
+private:
+ ForceField _forceField;
+ int _characterSpriteIndexes[3];
+ int _messagesIndexes[3];
+ int _lastFrame;
+
+public:
+ Scene309(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+};
+
+class Scene310 : public Scene3xx {
+private:
+ ForceField _forceField;
+
+public:
+ Scene310(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+};
+
+class Scene311 : public Scene3xx {
+private:
+ bool _checkGuardFl;
+
+public:
+ Scene311(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene313 : public Scene3xx {
+public:
+ Scene313(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene316 : public Scene3xx {
+private:
+ void handleRexInGrate();
+ void handleRoxInGrate();
+
+public:
+ Scene316(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene318 : public Scene3xx {
+private:
+ uint32 _dropTimer;
+
+ int _lastFrame;
+ int _animMode;
+ int _internCounter;
+ int _counter;
+
+ bool _dialogFl;
+ bool _internTalkingFl;
+ bool _internWalkingFl;
+ bool _internVisibleFl;
+ bool _explosionFl;
+
+ uint32 _lastFrameCounter;
+
+ Common::String _subQuote2;
+
+ Conversation _dialog1;
+
+ void handleDialog();
+ void handleRexDialogs(int quote);
+ void handleInternDialog(int quoteId, int quoteNum, uint32 timeout);
+
+public:
+ Scene318(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene319 : public Scene3xx {
+private:
+ Conversation _dialog1, _dialog2, _dialog3;
+
+ int _animMode, _animFrame;
+ int _nextAction1, _nextAction2;
+ int _slacheMode;
+ int _slacheTopic;
+ int _slachePosY;
+
+ bool _slacheTalkingFl;
+ bool _slacheReady;
+ bool _slacheInitFl;
+
+ Common::String _subQuote2;
+
+ void handleRexDialogues(int quote);
+ void handleSlacheDialogs(int quoteId, int counter, uint32 timer);
+public:
+ Scene319(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene320 : public Scene300s {
+private:
+ void setRightView(int view);
+ void setLeftView(int view);
+ void handleButtons();
+
+ bool _blinkFl;
+ bool _flippedFl;
+
+ int _buttonId;
+ int _lastFrame;
+ int _leftItemId;
+ int _posX;
+ int _rightItemId;
+
+public:
+ Scene320(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene321 : public Scene3xx {
+public:
+ Scene321(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+};
+
+class Scene322 : public SceneTeleporter {
+public:
+ Scene322(MADSEngine *vm) : SceneTeleporter(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene351 : public Scene3xx {
+public:
+ Scene351(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene352 : public Scene3xx {
+private:
+ bool _vaultOpenFl;
+ bool _mustPutArmDownFl;
+ bool _leaveRoomFl;
+
+ int _tapePlayerHotspotIdx;
+ int _hotspot1Idx;
+ int _hotspot2Idx;
+ int _lampHostpotIdx;
+ int _commonSequenceIdx;
+ int _commonSpriteIndex;
+
+ void putArmDown(bool corridorExit, bool doorwayExit);
+
+public:
+ Scene352(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene353 : public Scene3xx {
+public:
+ Scene353(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene354 : public Scene3xx {
+public:
+ Scene354(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene357 : public Scene3xx {
+public:
+ Scene357(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene358 : public Scene3xx {
+public:
+ Scene358(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene359 : public Scene3xx {
+private:
+ int _cardHotspotId;
+
+public:
+ Scene359(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene360 : public Scene3xx {
+public:
+ Scene360(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene361 : public Scene3xx {
+private:
+ void handleRexAction();
+ void handleRoxAction();
+
+public:
+ Scene361(MADSEngine *vm) : Scene3xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene366 : public Scene300s {
+public:
+ Scene366(MADSEngine *vm) : Scene300s(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene387 : public Scene300s {
+public:
+ Scene387(MADSEngine *vm) : Scene300s(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene388 : public Scene300s {
+public:
+ Scene388(MADSEngine *vm) : Scene300s(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene389 : public Scene300s {
+private:
+ uint32 _monsterTime;
+
+ int _circularQuoteId;
+
+public:
+ Scene389(MADSEngine *vm);
+ virtual void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene390 : public Scene300s {
+public:
+ Scene390(MADSEngine *vm) : Scene300s(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene391 : public Scene300s {
+public:
+ Scene391(MADSEngine *vm) : Scene300s(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene399 : public Scene300s {
+public:
+ Scene399(MADSEngine *vm) : Scene300s(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES3_H */
diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp
new file mode 100644
index 0000000000..56f6fb4466
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes4.cpp
@@ -0,0 +1,4194 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes4.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+void Scene4xx::setAAName() {
+ _game._aaName = Resources::formatAAName(4);
+}
+
+void Scene4xx::setPlayerSpritesPrefix() {
+ _vm->_sound->command(5);
+ Common::String oldName = _game._player._spritesPrefix;
+
+ if ((_scene->_nextSceneId == 403) || (_scene->_nextSceneId == 409))
+ _game._player._spritesPrefix = "";
+ else if (_globals[kSexOfRex] == REX_FEMALE)
+ _game._player._spritesPrefix = "ROX";
+ else
+ _game._player._spritesPrefix = "RXM";
+
+ _game._player._scalingVelocity = true;
+
+ if (oldName != _game._player._spritesPrefix)
+ _game._player._spritesChanged = true;
+
+ _vm->_palette->setEntry(16, 10, 63, 63);
+ _vm->_palette->setEntry(17, 10, 45, 45);
+}
+
+void Scene4xx::sceneEntrySound() {
+ if (!_vm->_musicFlag) {
+ _vm->_sound->command(2);
+ return;
+ }
+
+ switch (_scene->_nextSceneId) {
+ case 401:
+ _vm->_sound->startQueuedCommands();
+ if (_scene->_priorSceneId == 402)
+ _vm->_sound->command(12, 64);
+ else
+ _vm->_sound->command(12, 1);
+ break;
+
+ case 402:
+ _vm->_sound->startQueuedCommands();
+ _vm->_sound->command(12, 127);
+ break;
+
+ case 405:
+ case 407:
+ case 409:
+ case 410:
+ case 413:
+ _vm->_sound->command(10);
+ break;
+
+ case 408:
+ _vm->_sound->command(52);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene401::Scene401(MADSEngine *vm) : Scene4xx(vm), _destPos(0, 0) {
+ _northFl = false;
+ _timer = 0;
+}
+
+void Scene401::synchronize(Common::Serializer &s) {
+ Scene4xx::synchronize(s);
+
+ s.syncAsByte(_northFl);
+ s.syncAsSint16LE(_destPos.x);
+ s.syncAsSint16LE(_destPos.y);
+ s.syncAsUint32LE(_timer);
+}
+
+void Scene401::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene401::enter() {
+ if (_scene->_priorSceneId != -2)
+ _northFl = false;
+
+ _timer = 0;
+
+ if (_scene->_priorSceneId == 402) {
+ _game._player._playerPos = Common::Point(203, 115);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId == 354) {
+ _game._player._playerPos = Common::Point(149, 90);
+ _game._player._facing = FACING_SOUTH;
+ _northFl = true;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(142, 131);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ _game.loadQuoteSet(0x1D4, 0);
+ sceneEntrySound();
+}
+
+void Scene401::step() {
+ if (_game._trigger == 70) {
+ _scene->_nextSceneId = 354;
+ _scene->_reloadSceneFlag = true;
+ }
+
+ if (_game._trigger == 80) {
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _northFl = false;
+ _game._player.walk(Common::Point(149, 110), FACING_SOUTH);
+ }
+
+ if (_scene->_frameStartTime >= _timer) {
+ int dist = 64 - ((_vm->hypotenuse(_game._player._playerPos.x - 219, _game._player._playerPos.y - 115) * 64) / 120);
+
+ if (dist > 64)
+ dist = 64;
+ else if (dist < 1)
+ dist = 1;
+
+ _vm->_sound->command(12, dist);
+ _timer = _scene->_frameStartTime + _game._player._ticksAmount;
+ }
+
+}
+
+void Scene401::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) {
+ _game._player.walk(Common::Point(149, 89), FACING_NORTH);
+ _northFl = false;
+ }
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) && !_northFl)
+ _game._player._walkOffScreenSceneId = 405;
+
+ if (_action.isAction(VERB_TAKE))
+ _game._player._needToWalk = false;
+
+ if (_game._player._needToWalk && _northFl) {
+ if (_globals[kSexOfRex] == REX_MALE)
+ _destPos = Common::Point(148, 94);
+ else
+ _destPos = Common::Point(149, 99);
+
+ _game._player.walk(_destPos, FACING_SOUTH);
+ }
+}
+
+void Scene401::actions() {
+ if ((_game._player._playerPos == _destPos) && _northFl) {
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _vm->_sound->command(21);
+ _scene->loadAnimation(formAnimName('s', 1), 70);
+ _globals[kHasBeenScanned] = true;
+ _vm->_sound->command(22);
+ int idx = _scene->_kernelMessages.add(Common::Point(153, 46), 0x1110, 32, 0, 60, _game.getQuote(0x1D4));
+ _scene->_kernelMessages.setQuoted(idx, 4, true);
+ }
+
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _vm->_sound->command(21);
+ _scene->loadAnimation(formAnimName('s', 2), 80);
+ _vm->_sound->command(23);
+ _globals[kHasBeenScanned] = true;
+ }
+ }
+
+ if (_action.isAction(VERB_WALK_INTO, NOUN_BAR)) {
+ if (!_northFl)
+ _scene->_nextSceneId = 402;
+ } else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH))
+ _scene->_nextSceneId = 354;
+ else if (_action.isAction(VERB_LOOK, NOUN_SCANNER)) {
+ if (_globals[kHasBeenScanned])
+ _vm->_dialogs->show(40111);
+ else
+ _vm->_dialogs->show(40110);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BAR))
+ _vm->_dialogs->show(40112);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGN))
+ _vm->_dialogs->show(40113);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(40114);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH))
+ _vm->_dialogs->show(40115);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(40116);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene402::Scene402(MADSEngine *vm) : Scene4xx(vm) {
+ _lightOn = false;
+ _blowingSmoke = false;
+ _leftWomanMoving = false;
+ _rightWomanMoving = false;
+ _firstTalkToGirlInChair = false;
+ _waitingGinnyMove = false;
+ _ginnyLooking = false;
+ _bigBeatFl = false;
+ _roxOnStool = false;
+ _bartenderSteady = false;
+ _bartenderHandsHips = false;
+ _bartenderLooksLeft = false;
+ _bartenderReady = false;
+ _bartenderTalking = false;
+ _bartenderCalled = false;
+ _conversationFl = false;
+ _activeTeleporter = false;
+ _activeArrows = false;
+ _activeArrow1 = false;
+ _activeArrow2 = false;
+ _activeArrow3 = false;
+ _cutSceneReady = false;
+ _cutSceneNeeded = false;
+ _helgaReady = false;
+ _refuseAlienLiquor = false;
+
+ _drinkTimer = -1;
+ _beatCounter = -1;
+ _bartenderMode = -1;
+ _bartenderDialogNode = -1;
+ _bartenderCurrentQuestion = -1;
+ _helgaTalkMode = -1;
+ _roxMode = -1;
+ _rexMode = -1;
+ _talkTimer = -1;
+}
+
+void Scene402::synchronize(Common::Serializer &s) {
+ Scene4xx::synchronize(s);
+
+ s.syncAsByte(_lightOn);
+ s.syncAsByte(_blowingSmoke);
+ s.syncAsByte(_leftWomanMoving);
+ s.syncAsByte(_rightWomanMoving);
+ s.syncAsByte(_firstTalkToGirlInChair);
+ s.syncAsByte(_waitingGinnyMove);
+ s.syncAsByte(_ginnyLooking);
+ s.syncAsByte(_bigBeatFl);
+ s.syncAsByte(_roxOnStool);
+ s.syncAsByte(_bartenderSteady);
+ s.syncAsByte(_bartenderHandsHips);
+ s.syncAsByte(_bartenderLooksLeft);
+ s.syncAsByte(_bartenderReady);
+ s.syncAsByte(_bartenderTalking);
+ s.syncAsByte(_bartenderCalled);
+ s.syncAsByte(_conversationFl);
+ s.syncAsByte(_activeTeleporter);
+ s.syncAsByte(_activeArrows);
+ s.syncAsByte(_activeArrow1);
+ s.syncAsByte(_activeArrow2);
+ s.syncAsByte(_activeArrow3);
+ s.syncAsByte(_cutSceneReady);
+ s.syncAsByte(_cutSceneNeeded);
+ s.syncAsByte(_helgaReady);
+ s.syncAsByte(_refuseAlienLiquor);
+
+ s.syncAsSint16LE(_drinkTimer);
+ s.syncAsSint16LE(_beatCounter);
+ s.syncAsSint16LE(_bartenderMode);
+ s.syncAsSint16LE(_bartenderDialogNode);
+ s.syncAsSint16LE(_bartenderCurrentQuestion);
+ s.syncAsSint16LE(_helgaTalkMode);
+ s.syncAsSint16LE(_roxMode);
+ s.syncAsSint16LE(_rexMode);
+ s.syncAsSint16LE(_talkTimer);
+}
+
+void Scene402::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_BARTENDER);
+ _scene->addActiveVocab(NOUN_ALIEN_LIQUOR);
+ _scene->addActiveVocab(VERB_DRINK);
+ _scene->addActiveVocab(NOUN_BINOCULARS);
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_CREDIT_CHIP);
+ _scene->addActiveVocab(VERB_TAKE);
+ _scene->addActiveVocab(NOUN_REPAIR_LIST);
+ _scene->addActiveVocab(VERB_LOOK_AT);
+}
+
+void Scene402::setDialogNode(int node) {
+ if (node > 0)
+ _bartenderDialogNode = node;
+
+ _game._player._stepEnabled = true;
+
+ switch (node) {
+ case 0:
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _conversationFl = false;
+ _bartenderDialogNode = 0;
+ break;
+
+ case 1:
+ _dialog1.start();
+ _bartenderDialogNode = 1;
+ break;
+
+ case 2:
+ _dialog2.start();
+ _bartenderDialogNode = 2;
+ break;
+
+ case 3:
+ _dialog3.start();
+ _bartenderDialogNode = 3;
+ break;
+
+ case 4:
+ _dialog4.start();
+ _bartenderDialogNode = 4;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene402::handleConversation1() {
+ switch (_action._activeAction._verbId) {
+ case 0x214: {
+ int quoteId = 0;
+ int quotePosX = 0;
+ switch (_vm->getRandomNumber(1, 3)) {
+ case 1:
+ quoteId = 0x1E4;
+ _bartenderCurrentQuestion = 4;
+ quotePosX = 205;
+ break;
+
+ case 2:
+ quoteId = 0x1E5;
+ _bartenderCurrentQuestion = 5;
+ quotePosX = 203;
+ break;
+
+ case 3:
+ quoteId = 0x1E6;
+ _bartenderCurrentQuestion = 6;
+ quotePosX = 260;
+ break;
+
+ default:
+ break;
+ }
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(quotePosX, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(quoteId));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 120;
+ setDialogNode(2);
+ }
+ break;
+
+ case 0x215:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EC));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 120;
+ _bartenderCurrentQuestion = 1;
+ setDialogNode(3);
+ break;
+
+ case 0x237:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD));
+ setDialogNode(0);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 1120;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene402::handleConversation2() {
+ switch (_action._activeAction._verbId) {
+ case 0x216:
+ _dialog2.write(0x216, false);
+ _dialog2.write(0x21D, true);
+ break;
+
+ case 0x219:
+ _dialog2.write(0x219, false);
+ _dialog2.write(0x220, true);
+ break;
+
+ case 0x21A:
+ _dialog2.write(0x21A, false);
+ _dialog2.write(0x223, true);
+ break;
+
+ case 0x21B:
+ _dialog2.write(0x21B, false);
+ _dialog2.write(0x224, true);
+ break;
+
+ case 0x21D:
+ _dialog2.write(0x21D, false);
+ _dialog2.write(0x227, true);
+ break;
+
+ case 0x220:
+ _dialog2.write(0x220, false);
+ _dialog2.write(0x22A, true);
+ break;
+
+ case 0x223:
+ _dialog2.write(0x223, false);
+ _dialog2.write(0x22D, true);
+ break;
+
+ case 0x224:
+ _dialog2.write(0x224, false);
+ _dialog2.write(0x230, true);
+ break;
+
+ case 0x227:
+ _dialog2.write(0x227, false);
+ break;
+
+ case 0x22A:
+ _dialog2.write(0x22A, false);
+ break;
+
+ case 0x22D:
+ _dialog2.write(0x22D, false);
+ break;
+
+ case 0x230:
+ _dialog2.write(0x230, false);
+ break;
+
+ case 0x21C:
+ setDialogNode(0);
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (_action._activeAction._verbId != 0x21C) {
+ switch (_vm->getRandomNumber(1, 3)) {
+ case 1:
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 180;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E7));
+ _scene->_kernelMessages.add(Common::Point(201, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E8));
+ _bartenderCurrentQuestion = 7;
+ break;
+
+ case 2:
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 180;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(220, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E9));
+ _scene->_kernelMessages.add(Common::Point(190, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EA));
+ _bartenderCurrentQuestion = 8;
+ break;
+
+ case 3:
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 150;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(196, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EB));
+ _bartenderCurrentQuestion = 9;
+ break;
+
+ default:
+ break;
+ }
+ _dialog2.start();
+ } else {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 1120;
+ }
+}
+
+void Scene402::handleConversation3() {
+ switch (_action._activeAction._verbId) {
+ case 0x233:
+ case 0x234:
+ case 0x235:
+ case 0x236:
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 86);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(188, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1ED));
+ _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EE));
+ setDialogNode(4);
+ _bartenderCurrentQuestion = 2;
+ break;
+
+ case 0x237:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 1120;
+ setDialogNode(0);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene402::handleConversation4() {
+ switch (_action._activeAction._verbId) {
+ case 0x238:
+ _scene->_kernelMessages.reset();
+ setDialogNode(0);
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.add(Common::Point(196, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F0));
+ _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F1));
+ _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F2));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 1100;
+ _dialog4.write(0x238, false);
+ _bartenderMode = 22;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(100, 95);
+ _refuseAlienLiquor = true;
+ break;
+
+ case 0x239:
+ _game._player._stepEnabled = false;
+ _roxMode = 21;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 92);
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _conversationFl = false;
+ break;
+
+ case 0x23A:
+ setDialogNode(0);
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.add(Common::Point(193, 27), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F4));
+ _scene->_kernelMessages.add(Common::Point(230, 41), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F5));
+ _dialog4.write(0x23A, false);
+ _globals[kHasSaidTimer] = true;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 1100;
+ _bartenderMode = 22;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(100, 95);
+ _refuseAlienLiquor = true;
+ break;
+
+ case 0x23D:
+ setDialogNode(0);
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.add(Common::Point(153, 27), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F6));
+ _scene->_kernelMessages.add(Common::Point(230, 41), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F7));
+ _dialog4.write(0x23D, false);
+ _globals[kHasSaidBinocs] = true;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 1100;
+ _bartenderMode = 22;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(100, 95);
+ _refuseAlienLiquor = true;
+ break;
+
+ case 0x23E:
+ _scene->_kernelMessages.reset();
+ setDialogNode(0);
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1F8));
+ _bartenderMode = 22;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 1050;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(50, 95);
+ _refuseAlienLiquor = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene402::handleDialogs() {
+ if (_game._trigger == 0) {
+ _scene->_kernelMessages.reset();
+ _game._player._stepEnabled = false;
+ Common::String curQuote = _game.getQuote(_action._activeAction._verbId);
+ if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) {
+ Common::String subQuote1, subQuote2;
+ _game.splitQuote(curQuote, subQuote1, subQuote2);
+ _scene->_kernelMessages.add(Common::Point(230, 42), 0x1110, 32, 0, 140, subQuote1);
+ _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 0, 140, subQuote2);
+ _scene->_sequences.addTimer(160, 120);
+ } else {
+ _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 1, 140, curQuote);
+ _scene->_sequences.addTimer(160, 120);
+ }
+ } else if (_game._trigger == 120) {
+ _game._player._stepEnabled = true;
+ switch (_bartenderDialogNode) {
+ case 1:
+ handleConversation1();
+ break;
+
+ case 2:
+ handleConversation2();
+ break;
+
+ case 3:
+ handleConversation3();
+ break;
+
+ case 4:
+ handleConversation4();
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene402::enter() {
+ _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('n', -1));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 0));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 1));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[15] = _scene->_sprites.addSprites(formAnimName('x', 5));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('x', 4));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('b', 2));
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('b', 3));
+ _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('l', 0));
+ _globals._spriteIndexes[16] = _scene->_sprites.addSprites(formAnimName('h', 0));
+ _globals._spriteIndexes[17] = _scene->_sprites.addSprites(formAnimName('z', 0));
+ _globals._spriteIndexes[18] = _scene->_sprites.addSprites(formAnimName('z', 1));
+ _globals._spriteIndexes[19] = _scene->_sprites.addSprites(formAnimName('z', 2));
+ _globals._spriteIndexes[20] = _scene->_sprites.addSprites(formAnimName('x', 6));
+ _globals._spriteIndexes[21] = _scene->_sprites.addSprites("*ROXRC_9");
+ _globals._spriteIndexes[22] = _scene->_sprites.addSprites("*ROXCL_8");
+
+ if (_scene->_priorSceneId == 401) {
+ _game._player._playerPos = Common::Point(160, 150);
+ _game._player._facing = FACING_NORTH;
+ _roxOnStool = false;
+ _bartenderDialogNode = 1;
+ _conversationFl = false;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(160, 150);
+ _game._player._facing = FACING_NORTH;
+ _game._objects.addToInventory(OBJ_CREDIT_CHIP);
+ _game._objects.addToInventory(OBJ_BINOCULARS);
+ _game._objects.addToInventory(OBJ_TIMER_MODULE);
+ _roxOnStool = false;
+ _bartenderDialogNode = 1;
+ _conversationFl = false;
+ }
+
+ _game.loadQuoteSet(0x1D7, 0x1D8, 0x1D9, 0x1DA, 0x1DB, 0x1DC, 0x1DD, 0x1DE, 0x1DF, 0x1E2, 0x1E3, 0x1E6, 0x1E5, 0x1E7,
+ 0x1E8, 0x1E9, 0x1EA, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, 0x1F5, 0x1F6, 0x1F7, 0x1F8, 0x1F9, 0x1FA, 0x1FB,
+ 0x1FC, 0x1EB, 0x1EC, 0x1ED, 0x1EE, 0x1E4, 0x1FD, 0x1E0, 0x1E1, 0x1FE, 0x1FF, 0x200, 0x201, 0x202, 0x203, 0x204,
+ 0x205, 0x206, 0x207, 0x208, 0x209, 0x20A, 0x20B, 0x20C, 0x20F, 0x20D, 0x20E, 0x210, 0x211, 0x212, 0x213, 0x214,
+ 0x215, 0x237, 0x216, 0x219, 0x21A, 0x21B, 0x21C, 0x21D, 0x220, 0x223, 0x224, 0x227, 0x22A, 0x22D, 0x230, 0x233,
+ 0x234, 0x235, 0x236, 0x238, 0x239, 0x23A, 0x23D, 0x23E, 0x23F, 0);
+
+ _vm->_palette->setEntry(250, 47, 41, 40);
+ _vm->_palette->setEntry(251, 50, 63, 55);
+ _vm->_palette->setEntry(252, 38, 34, 25);
+ _vm->_palette->setEntry(253, 45, 41, 35);
+
+ _dialog1.setup(0x60, 0x214, 0x215, 0x237, 0);
+ _dialog2.setup(0x61, 0x216, 0x219, 0x21A, 0x21B, 0x21D, 0x220, 0x223, 0x224, 0x227, 0x22A, 0x22D, 0x230, 0x21C, 0);
+ _dialog3.setup(0x62, 0x233, 0x234, 0x235, 0x236, 0x237, -1);
+ _dialog4.setup(0x63, 0x238, 0x239, 0x23A, 0x23D, 0x23E, 0);
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ _dialog2.set(0x61, 0x216, 0x219, 0x21A, 0x21B, 0x21C, 0);
+ _dialog4.set(0x63, 0x238, 0x23E, 0);
+ _dialog1.set(0x60, 0x214, 0x215, 0x237, 0);
+ }
+
+ if (_game._objects.isInInventory(OBJ_CREDIT_CHIP))
+ _dialog4.write(0x239, true);
+ else
+ _dialog4.write(0x239, false);
+
+ if (_game._objects.isInInventory(OBJ_BINOCULARS) && !_globals[kHasSaidBinocs])
+ _dialog4.write(0x23D, true);
+ else
+ _dialog4.write(0x23D, false);
+
+ if (_game._objects.isInInventory(OBJ_TIMER_MODULE) && !_globals[kHasSaidTimer])
+ _dialog4.write(0x23A, true);
+ else
+ _dialog4.write(0x23A, false);
+
+ if (_dialog2.read(0) <= 1)
+ _dialog1.write(0x214, false);
+
+ if (_conversationFl) {
+ switch (_bartenderDialogNode) {
+ case 0:
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _bartenderDialogNode = 1;
+ break;
+
+ case 1:
+ _dialog1.start();
+ break;
+
+ case 2:
+ _dialog2.start();
+ break;
+
+ case 3:
+ _dialog3.start();
+ break;
+
+ case 4:
+ _dialog4.start();
+ break;
+
+ default:
+ break;
+ }
+
+ switch (_bartenderCurrentQuestion) {
+ case 1:
+ _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EC));
+ break;
+
+ case 2:
+ _scene->_kernelMessages.add(Common::Point(188, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1ED));
+ _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EE));
+ break;
+
+ case 3:
+ _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EF));
+ break;
+
+ case 4:
+ _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E4));
+ break;
+
+ case 5:
+ _scene->_kernelMessages.add(Common::Point(203, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E5));
+ break;
+
+ case 6:
+ _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E6));
+ break;
+
+ case 7:
+ _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E7));
+ _scene->_kernelMessages.add(Common::Point(201, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E8));
+ break;
+
+ case 8:
+ _scene->_kernelMessages.add(Common::Point(220, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E9));
+ _scene->_kernelMessages.add(Common::Point(190, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EA));
+ break;
+
+ case 9:
+ _scene->_kernelMessages.add(Common::Point(196, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EB));
+ break;
+
+ case 10:
+ _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E2));
+ _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E3));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _firstTalkToGirlInChair = false;
+ _lightOn = false;
+ _blowingSmoke = false;
+ _leftWomanMoving = false;
+ _rightWomanMoving = false;
+ _ginnyLooking = false;
+ _beatCounter = 0;
+ _waitingGinnyMove = false;
+ _bigBeatFl = true;
+ _bartenderHandsHips = false;
+ _bartenderSteady = true;
+ _bartenderLooksLeft = false;
+ _activeTeleporter = false;
+ _activeArrows = false;
+ _activeArrow1 = false;
+ _activeArrow2 = false;
+ _activeArrow3 = false;
+ _cutSceneReady = false;
+ _cutSceneNeeded = false;
+ _helgaReady = true;
+ _bartenderReady = true;
+ _drinkTimer = 0;
+ _bartenderTalking = false;
+ _bartenderCalled = false;
+ _helgaTalkMode = 0;
+ _rexMode = 0;
+ _refuseAlienLiquor = false;
+
+ _scene->loadAnimation(Resources::formatName(402, 'd', 1, EXT_AA, ""));
+ _scene->_activeAnimation->_resetFlag = true;
+
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+
+ if (!_game._objects.isInInventory(OBJ_REPAIR_LIST)) {
+ _globals._sequenceIndexes[14] = _scene->_sequences.startCycle(_globals._spriteIndexes[14], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[14], 7);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[14], Common::Point(210, 80));
+ int idx = _scene->_dynamicHotspots.add(NOUN_REPAIR_LIST, VERB_LOOK_AT, _globals._sequenceIndexes[14], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE);
+ }
+
+ {
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ }
+
+ if (!_game._objects.isInRoom(OBJ_ALIEN_LIQUOR) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP)) {
+ _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80));
+ int idx = _scene->_dynamicHotspots.add(NOUN_CREDIT_CHIP, VERB_TAKE, _globals._sequenceIndexes[15], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE);
+ }
+
+ _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 7);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72));
+
+ if (_globals[kBottleDisplayed]) {
+ _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7);
+ }
+
+ if (_roxOnStool) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5);
+ _game._player._visible = false;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene402::step() {
+ if (_game._trigger == 104) {
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _scene->_sequences.remove(_globals._sequenceIndexes[15]);
+ _game._objects.addToInventory(OBJ_CREDIT_CHIP);
+ _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 40242);
+ _game._player._stepEnabled = true;
+ }
+
+ if ((_vm->getRandomNumber(1, 1500) == 1) && (!_activeTeleporter) && (_game._player._playerPos.x < 150)) {
+ _vm->_sound->command(30);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 13, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 14);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 48);
+ _activeTeleporter = true;
+ _globals[kSomeoneHasExploded] = true;
+ }
+
+ if (_game._trigger == 48)
+ _activeTeleporter = false;
+
+ if (_game._trigger == 100) {
+ _bartenderReady = false;
+ if (_bartenderHandsHips) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _bartenderHandsHips = false;
+ } else if (_bartenderLooksLeft) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _bartenderLooksLeft = false;
+ } else if (_bartenderSteady) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _bartenderSteady = false;
+ }
+
+ if (!_bartenderTalking) {
+ _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 7, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 3, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[10], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _bartenderTalking = true;
+ if (_talkTimer > 1000)
+ _scene->_sequences.addTimer(_talkTimer - 1000, 101);
+ else
+ _scene->_sequences.addTimer(_talkTimer, 101);
+ }
+ }
+
+ if ((_game._trigger == 101) && _bartenderTalking) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ _bartenderSteady = true;
+ _bartenderTalking = false;
+ if (_talkTimer < 1000)
+ _bartenderReady = true;
+ }
+
+ if (_game._trigger == 28)
+ _game._player._stepEnabled = true;
+
+ switch (_game._trigger) {
+ case 92:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 93);
+ break;
+
+ case 93: {
+ int seqIdx = _globals._sequenceIndexes[7];
+ switch (_roxMode) {
+ case 20:
+ _vm->_sound->command(57);
+ _scene->_sequences.remove(_globals._sequenceIndexes[15]);
+ _game._objects.addToInventory(OBJ_CREDIT_CHIP);
+ _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 40242);
+ break;
+
+ case 22:
+ _vm->_sound->command(57);
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _game._objects.addToInventory(OBJ_ALIEN_LIQUOR);
+ _globals[kBottleDisplayed] = false;
+ _vm->_dialogs->showItem(OBJ_ALIEN_LIQUOR, 40241);
+ break;
+
+ case 21:
+ _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80));
+ break;
+
+ default:
+ break;
+ }
+ _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 3);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 94);
+
+ if (_roxMode == 21) {
+ if (_game._objects.isInInventory(OBJ_CREDIT_CHIP))
+ _game._objects.setRoom (OBJ_CREDIT_CHIP, NOWHERE);
+
+ _bartenderMode = 20;
+ _scene->_sequences.addTimer(60, 95);
+ }
+ }
+ break;
+
+ case 94: {
+ int seqIdx = _globals._sequenceIndexes[7];
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx);
+ if (_roxMode == 22) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 0, 120, _game.getQuote(0x23F));
+ _bartenderMode = 21;
+ _globals[kHasPurchased] = true;
+ _scene->_sequences.addTimer(140, 95);
+ } else if (_roxMode == 20)
+ _game._player._stepEnabled = true;
+
+ }
+ break;
+ }
+
+ switch (_game._trigger) {
+ case 95:
+ _bartenderReady = false;
+ _game._player._stepEnabled = false;
+ if (_bartenderHandsHips || _bartenderTalking) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _bartenderHandsHips = false;
+ _bartenderTalking = false;
+ }
+
+ if (_bartenderLooksLeft) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _bartenderLooksLeft = false;
+ }
+
+ if (_bartenderSteady) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _bartenderSteady = false;
+ }
+ _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 96);
+ break;
+
+ case 96: {
+ int seqIdx = _globals._sequenceIndexes[12];
+ _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 6, 7);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 97);
+ }
+ break;
+
+ case 97: {
+ int seqIdx = _globals._sequenceIndexes[12];
+ switch (_bartenderMode) {
+ case 20:
+ _scene->_sequences.remove(_globals._sequenceIndexes[15]);
+ break;
+
+ case 21: {
+ _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80));
+ int idx = _scene->_dynamicHotspots.add(NOUN_CREDIT_CHIP, VERB_TAKE, _globals._sequenceIndexes[15], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE);
+ }
+ break;
+
+ case 22:
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _globals[kBottleDisplayed] = false;
+ break;
+
+ default:
+ break;
+ }
+
+ _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8);
+ _scene->_sequences.addTimer(10, 98);
+ }
+ break;
+
+ case 98:
+ _scene->_sequences.remove(_globals._sequenceIndexes[12]);
+ _globals._sequenceIndexes[12] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 99);
+ break;
+
+ case 99: {
+ int seqIdx = _globals._sequenceIndexes[12];
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ _bartenderSteady = true;
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ if (_bartenderMode == 20) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(210, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1F3));
+ _scene->_sequences.addTimer(5, 100);
+ _talkTimer = 180;
+ _roxMode = 22;
+ _scene->_sequences.addTimer(65, 92);
+ } else if ((_bartenderMode == 21) || (_bartenderMode == 22)) {
+ _game._player._stepEnabled = true;
+ _bartenderReady = true;
+ }
+
+ }
+ break;
+ }
+
+ switch (_game._trigger) {
+ case 86:
+ _bartenderReady = false;
+ _game._player._stepEnabled = false;
+ if ((_bartenderHandsHips) || (_bartenderTalking)) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _bartenderHandsHips = false;
+ _bartenderTalking = false;
+ } else if (_bartenderLooksLeft) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _bartenderLooksLeft = false;
+ } else if (_bartenderSteady) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _bartenderSteady = false;
+ }
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 9);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 87);
+ break;
+
+ case 87: {
+ int seqIdx = _globals._sequenceIndexes[9];
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 9);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], seqIdx);
+ _scene->_sequences.addTimer(10, 89);
+
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 88);
+ }
+ break;
+
+ case 88:
+ _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7);
+ _globals[kBottleDisplayed] = true;
+ break;
+
+ case 89:
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ _scene->_sequences.addTimer(10, 90);
+ break;
+
+ case 90:
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ _scene->_sequences.addTimer(10, 91);
+ break;
+
+ case 91: {
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ _bartenderSteady = true;
+ _game._player._stepEnabled = true;
+ _bartenderReady = true;
+ }
+ break;
+ }
+
+ if (!_waitingGinnyMove && !_ginnyLooking) {
+ _waitingGinnyMove = true;
+ ++ _beatCounter;
+ if (_beatCounter >= 20) {
+ _ginnyLooking = true;
+ _beatCounter = 0;
+ _scene->_sequences.addTimer(60, 54);
+ } else {
+ _scene->_sequences.addTimer(30, 75);
+ }
+ }
+
+ switch (_game._trigger) {
+ case 75:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _bigBeatFl = !_bigBeatFl;
+
+ if (_bigBeatFl) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5);
+ _scene->_sequences.addTimer(8, 130);
+ } else {
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5);
+ _scene->_sequences.addTimer(8, 53);
+ }
+
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+ break;
+
+ case 130:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+ _scene->_sequences.addTimer(8, 131);
+ break;
+
+ case 131:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+ _scene->_sequences.addTimer(8, 53);
+ break;
+
+ case 53:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+ _waitingGinnyMove = false;
+ break;
+ }
+
+ if ((_game._trigger == 54) && _ginnyLooking) {
+ ++_beatCounter;
+ if (_beatCounter >= 10) {
+ _ginnyLooking = false;
+ _waitingGinnyMove = false;
+ _beatCounter = 0;
+ _bigBeatFl = true;
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, _vm->getRandomNumber(1, 4));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+ _scene->_sequences.addTimer(60, 54);
+ }
+ }
+
+ if (_bartenderReady) {
+ if (_vm->getRandomNumber(1, 250) == 1) {
+ if (_bartenderLooksLeft) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _bartenderLooksLeft = false;
+ } else if (_bartenderHandsHips) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _bartenderHandsHips = false;
+ } else if (_bartenderSteady) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _bartenderSteady = false;
+ }
+
+ switch (_vm->getRandomNumber(1, 3)) {
+ case 1: {
+ _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[10], false, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[10], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _bartenderHandsHips = true;
+ }
+ break;
+
+ case 2: {
+ _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[11], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _bartenderLooksLeft = true;
+ }
+ break;
+
+ case 3: {
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _bartenderSteady = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (_game._trigger == 76) {
+ int seqIdx = _globals._sequenceIndexes[6];
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx);
+ if (!_globals[kBeenThruHelgaScene]) {
+ _game._player._stepEnabled = false;
+ _cutSceneNeeded = true;
+ } else {
+ _game._player._stepEnabled = true;
+ }
+ _roxOnStool = true;
+ }
+
+ switch (_game._trigger) {
+ case 77:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 10, 12);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 78);
+ break;
+
+ case 78: {
+ _vm->_sound->command(57);
+ int seqIdx = _globals._sequenceIndexes[7];
+ _game._objects.addToInventory(OBJ_REPAIR_LIST);
+ _scene->_sequences.remove(_globals._sequenceIndexes[14]);
+ _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 10, 12);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 79);
+ }
+ break;
+
+ case 79: {
+ int seqIdx = _globals._sequenceIndexes[7];
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx);
+ _scene->_sequences.addTimer(20, 180);
+ }
+ break;
+
+ case 180:
+ _vm->_dialogs->showItem(OBJ_REPAIR_LIST, 40240);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (_cutSceneNeeded && _cutSceneReady) {
+ _cutSceneNeeded = false;
+ _scene->_sequences.addTimer(20, 55);
+ _helgaReady = false;
+ _bartenderReady = false;
+ }
+
+ if (_vm->getRandomNumber(1, 25) == 1) {
+ if (_lightOn) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[0]);
+ _lightOn = false;
+ } else {
+ _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1);
+ _lightOn = true;
+ }
+ }
+
+ if (!_blowingSmoke && (_vm->getRandomNumber(1, 300) == 1)) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 14);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 14);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 30);
+ _blowingSmoke = true;
+ }
+
+ switch (_game._trigger) {
+ case 30:
+ _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 14);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1],SEQUENCE_TRIGGER_EXPIRE, 0, 31);
+ break;
+
+ case 31:
+ _blowingSmoke = false;
+ break;
+ }
+
+ if (!_leftWomanMoving) {
+ if (_vm->getRandomNumber(1, 1000) == 1) {
+ switch (_vm->getRandomNumber(1, 2)) {
+ case 1:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 33);
+ _leftWomanMoving = true;
+ break;
+
+ case 2:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.addTimer(12, 35);
+ _leftWomanMoving = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ switch (_game._trigger) {
+ case 33: {
+ int seqIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 9);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(60, 250), 34);
+ }
+ break;
+
+ case 34:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 38);
+ break;
+
+ case 35:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 2);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(60, 300), 36);
+ break;
+
+ case 36:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.addTimer(12, 37);
+ break;
+
+ case 37:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _leftWomanMoving = false;
+ break;
+
+ case 38:
+ _leftWomanMoving = false;
+ break;
+
+ default:
+ break;
+ }
+
+ if (!_rightWomanMoving) {
+ if (_vm->getRandomNumber(1, 300) == 1) {
+ switch (_vm->getRandomNumber(1, 4)) {
+ case 1:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32);
+ _rightWomanMoving = true;
+ break;
+
+ case 2:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32);
+ _rightWomanMoving = true;
+ break;
+
+ case 3:
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32);
+ _rightWomanMoving = true;
+ break;
+
+ case 4:
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32);
+ _rightWomanMoving = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (_game._trigger == 32)
+ _rightWomanMoving = false;
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 1) {
+ switch (_vm->getRandomNumber(1, 50)) {
+ case 1:
+ _scene->_activeAnimation->setCurrentFrame(2);
+ break;
+
+ case 2:
+ _scene->_activeAnimation->setCurrentFrame(7);
+ break;
+
+ case 3:
+ _scene->_activeAnimation->setCurrentFrame(11);
+ break;
+
+ default:
+ _scene->_activeAnimation->setCurrentFrame(0);
+ break;
+ }
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() == 4) && (_drinkTimer < 10)) {
+ ++ _drinkTimer;
+ _scene->_activeAnimation->setCurrentFrame(3);
+ }
+
+ if (_drinkTimer == 10) {
+ _drinkTimer = 0;
+ _scene->_activeAnimation->setCurrentFrame(4);
+ _scene->_activeAnimation->_currentFrame = 5;
+ }
+
+
+ switch (_scene->_activeAnimation->getCurrentFrame()) {
+ case 6:
+ case 10:
+ case 14:
+ _scene->_activeAnimation->setCurrentFrame(0);
+ break;
+
+ default:
+ break;
+ }
+
+ switch (_game._trigger) {
+ case 39:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1D8));
+ _scene->_sequences.addTimer(150, 40);
+ break;
+
+ case 40:
+ _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1D9));
+ _scene->_sequences.addTimer(150, 41);
+ break;
+
+ case 41:
+ _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DA));
+ _game._player._stepEnabled = true;
+ break;
+
+ case 42:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DC));
+ _scene->_sequences.addTimer(150, 43);
+ break;
+
+ case 43:
+ _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DD));
+ _game._player._stepEnabled = true;
+ break;
+
+ case 44:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (_game._trigger) {
+ case 55:
+ if (_bartenderHandsHips) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _bartenderHandsHips = false;
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _bartenderSteady = true;
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ } else if (_bartenderLooksLeft) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _bartenderLooksLeft = false;
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH);
+ _bartenderSteady = true;
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ }
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(180, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x1FE));
+ _scene->_sequences.addTimer(120, 56);
+ break;
+
+ case 56:
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 2, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 57);
+ break;
+
+ case 57: {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _scene->_sequences.remove(_globals._sequenceIndexes[20]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 6, 9);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 58);
+ }
+ break;
+
+ case 58: {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 5, 9);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 59);
+ }
+ break;
+
+ case 59: {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 1, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 60);
+ _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 8);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72));
+ }
+ break;
+
+ case 60: {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addTimer(10, 61);
+ }
+ break;
+
+ case 61:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(181, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x1FF));
+ _scene->_kernelMessages.add(Common::Point(171, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x200));
+ _scene->_sequences.addTimer(150, 63);
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 30, 4, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 62);
+ break;
+
+ case 62: {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ }
+ break;
+
+ case 63:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(160, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x201));
+ _scene->_kernelMessages.add(Common::Point(165, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x202));
+ _scene->_sequences.addTimer(150, 64);
+ break;
+
+ case 64:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(210, 27), 0xFDFC, 0, 0, 130, _game.getQuote(0x1E0));
+ _scene->_kernelMessages.add(Common::Point(198, 41), 0xFDFC, 0, 0, 130, _game.getQuote(0x1E1));
+ _scene->_sequences.addTimer(150, 65);
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 1130;
+ break;
+
+ case 65:
+ _vm->_sound->command(30);
+ _globals._sequenceIndexes[16] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[16], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[16], 1, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[16], 9);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[16], SEQUENCE_TRIGGER_EXPIRE, 0, 66);
+ break;
+
+ case 66: {
+ int seqIdx = _globals._sequenceIndexes[16];
+ _globals._sequenceIndexes[16] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[16], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[16], 7, 37);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[16], 9);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[16], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[16], SEQUENCE_TRIGGER_EXPIRE, 0, 68);
+
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 12, 13);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 67);
+ }
+ break;
+
+ case 67: {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 13);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ }
+ break;
+
+ case 68:
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 12, 13);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 69);
+ break;
+
+ case 69: {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(179, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x203));
+ _scene->_kernelMessages.add(Common::Point(167, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x204));
+ _scene->_sequences.addTimer(150, 71);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ }
+ break;
+
+ case 70:
+ _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 12);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 71:
+ _scene->_sequences.addTimer(210, 73);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(168, 33), 0xFBFA, 0, 0, 180, _game.getQuote(0x205));
+ _scene->_kernelMessages.add(Common::Point(151, 47), 0xFBFA, 0, 0, 180, _game.getQuote(0x206));
+ if (!_game._objects.isInInventory(OBJ_REPAIR_LIST))
+ _activeArrows = true;
+ break;
+
+ case 72: {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ }
+ break;
+
+ case 73:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(177, 33), 0xFBFA, 0, 0, 150, _game.getQuote(0x207));
+ _scene->_kernelMessages.add(Common::Point(172, 47), 0xFBFA, 0, 0, 150, _game.getQuote(0x208));
+ _bartenderSteady = true;
+ _game._player._stepEnabled = true;
+ _helgaReady = true;
+ _bartenderReady = true;
+ _globals[kBeenThruHelgaScene] = true;
+ _activeArrows = false;
+ break;
+
+ default:
+ break;
+ }
+
+ if (_helgaReady) {
+ int rndVal = _vm->getRandomNumber(1, 1000);
+ if (rndVal < 6)
+ switch (rndVal) {
+ case 1:
+ _cutSceneReady = false;
+ _helgaReady = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 2, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 82);
+ break;
+
+ case 2:
+ _cutSceneReady = false;
+ _helgaReady = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 11, 13);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26);
+ break;
+
+ case 3:
+ _cutSceneReady = false;
+ _helgaReady = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26);
+ break;
+
+ case 4:
+ _cutSceneReady = false;
+ _helgaReady = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 14, 15);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26);
+ break;
+
+ case 5:
+ _cutSceneReady = false;
+ _helgaReady = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 16, 19);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (_game._trigger == 80) {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 19);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(60, 120), 81);
+ }
+
+ if (_game._trigger == 81) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 16, 19);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26);
+ }
+
+ if (_game._trigger == 26) {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _cutSceneReady = true;
+
+ if (!_cutSceneNeeded)
+ _helgaReady = true;
+ }
+
+ if (_game._trigger == 82) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[20]);
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 6, 9);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 83);
+ }
+
+ if (_game._trigger == 83) {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 5, 9);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 84);
+ }
+
+ if (_game._trigger == 84) {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 1, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 85);
+
+ _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 8);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72));
+ }
+
+ if (_game._trigger == 85) {
+ int seqIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _cutSceneReady = true;
+ if (!_cutSceneNeeded)
+ _helgaReady = true;
+ }
+
+ if (_game._trigger == 102) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 14, 18);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 103);
+ } else if (_game._trigger == 103) {
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _roxOnStool = false;
+ _game._player._facing = FACING_SOUTH;
+ _game._player.selectSeries();
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _game._player._readyToWalk = true;
+ }
+
+ if (_activeArrows) {
+ if (!_activeArrow1) {
+ _globals._sequenceIndexes[17] = _scene->_sequences.startCycle(_globals._spriteIndexes[17], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[17], 1);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 49);
+ _activeArrow1 = true;
+ }
+
+ if (!_activeArrow2) {
+ _globals._sequenceIndexes[18] = _scene->_sequences.startCycle(_globals._spriteIndexes[18], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[18], 1);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 50);
+ _activeArrow2 = true;
+ }
+
+ if (!_activeArrow3) {
+ _globals._sequenceIndexes[19] = _scene->_sequences.startCycle(_globals._spriteIndexes[19], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[19], 1);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 51);
+ _activeArrow3 = true;
+ }
+ }
+
+ if (_game._trigger == 49) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[17]);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 45);
+ }
+
+ if (_game._trigger == 45)
+ _activeArrow1 = false;
+
+ if (_game._trigger == 50) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[18]);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 46);
+ }
+
+ if (_game._trigger == 46)
+ _activeArrow2 = false;
+
+ if (_game._trigger == 51) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[19]);
+ _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 47);
+ }
+
+ if (_game._trigger == 47)
+ _activeArrow3 = false;
+}
+
+void Scene402::preActions() {
+ if (_action.isAction(VERB_SIT_ON, NOUN_BAR_STOOL) && (_game._player._prepareWalkPos.x != 248))
+ _game._player.walk(Common::Point(232, 112), FACING_EAST);
+
+ if (_action.isAction(VERB_WALKTO, NOUN_WOMAN_ON_BALCONY))
+ _game._player._needToWalk = _game._player._readyToWalk;
+
+ if (!_roxOnStool && _action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP))
+ _game._player.walk(Common::Point(246, 108), FACING_NORTH);
+
+ if (_action.isAction(VERB_TAKE))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_roxOnStool)
+ _game._player._needToWalk = true;
+
+ if (_roxOnStool) {
+ if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_BAR_STOOL) || _action.isAction(VERB_TALKTO))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) || _action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) || _action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_ALCOVE))
+ _game._player._needToWalk = _game._player._readyToWalk;
+
+ if (_game._player._needToWalk) {
+ _game._player._facing = FACING_SOUTH;
+ _game._player._readyToWalk = false;
+ _game._player._stepEnabled = false;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 102);
+ }
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && !_roxOnStool && !_game._objects.isInInventory(OBJ_REPAIR_LIST))
+ _game._player.walk(Common::Point(191, 99), FACING_NORTHEAST);
+
+ if (_action.isAction(VERB_TALKTO, NOUN_BARTENDER) && !_roxOnStool)
+ _game._player.walk(Common::Point(228, 83), FACING_SOUTH);
+
+ if (_action.isAction(VERB_TALKTO, NOUN_REPAIR_WOMAN) && !_roxOnStool)
+ _game._player.walk(Common::Point(208, 102), FACING_NORTHEAST);
+}
+
+void Scene402::actions() {
+ if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST) && _roxOnStool) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 77);
+ _game._player._needToWalk = false;
+ } else if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST) && !_roxOnStool) {
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[21] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[21], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[21], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[21]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[21], SEQUENCE_TRIGGER_SPRITE, 2, 165);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[21], SEQUENCE_TRIGGER_EXPIRE, 0, 166);
+ } else if (_game._trigger == 165) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[14]);
+ _game._objects.addToInventory(OBJ_REPAIR_LIST);
+ }
+ } else if (_game._trigger == 166) {
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(20, 167);
+ } else if (_game._trigger == 167) {
+ _vm->_dialogs->showItem(OBJ_REPAIR_LIST, 40240);
+ _game._player._stepEnabled = true;
+ } else if (_game._screenObjects._inputMode == kInputConversation)
+ handleDialogs();
+ else if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH))
+ _scene->_nextSceneId = 401;
+ else if (_action.isAction(VERB_WALK_ONTO, NOUN_DANCE_FLOOR))
+ ; // just... nothing
+ else if (_action.isAction(VERB_TALKTO, NOUN_REPAIR_WOMAN)) {
+ switch (_game._trigger) {
+ case 0: {
+ _game._player._stepEnabled = false;
+ int random = _vm->getRandomNumber(1, 3);
+ if (_helgaTalkMode == 0)
+ random = 1;
+
+ int centerFlag;
+ Common::Point centerPos;
+ if (_roxOnStool) {
+ centerFlag = 0;
+ centerPos = Common::Point(230, 56);
+ } else {
+ centerFlag = 2;
+ centerPos = Common::Point(0, 0);
+ }
+
+ switch (random) {
+ case 1:
+ _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x211));
+ _scene->_sequences.addTimer(110, 25);
+ break;
+
+ case 2:
+ _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x212));
+ _scene->_sequences.addTimer(110, 25);
+ break;
+
+ case 3:
+ _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x213));
+ _scene->_sequences.addTimer(110, 25);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case 25:
+ switch (_helgaTalkMode) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _helgaTalkMode = 1;
+ _scene->_kernelMessages.add(Common::Point(177, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x209));
+ _scene->_kernelMessages.add(Common::Point(182, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x20A));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(130, 28);
+ break;
+
+ case 1:
+ _game._player._stepEnabled = false;
+ _helgaTalkMode = 2;
+ _scene->_kernelMessages.add(Common::Point(157, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x20B));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(100, 28);
+ break;
+
+ case 2:
+ _game._player._stepEnabled = false;
+ _helgaTalkMode = 3;
+ _scene->_kernelMessages.add(Common::Point(172, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x20C));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(100, 28);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+ } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) && !_firstTalkToGirlInChair) {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x1D7));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(150, 39);
+ _game._player._stepEnabled = false;
+ _firstTalkToGirlInChair = true;
+ } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) && _firstTalkToGirlInChair) {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x1DB));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(150, 42);
+ _game._player._stepEnabled = false;
+ } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_ALCOVE) || _action.isAction(VERB_WALKTO, NOUN_WOMAN_IN_ALCOVE)) {
+ _scene->_kernelMessages.add(Common::Point(102, 48), 0xFBFA, 0, 0, 120, _game.getQuote(0x1DE));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(120, 44);
+ _game._player._stepEnabled = false;
+ } else if (_action.isAction(VERB_SIT_ON, NOUN_BAR_STOOL) && (_game._player._targetPos.x == 248)){
+ _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 120, _game.getQuote(0x20D));
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x20E));
+ } else if (_action.isAction(VERB_SIT_ON, NOUN_BAR_STOOL) && !_roxOnStool && (_game._player._targetPos.x != 248)) {
+ _game._player._visible = false;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 76);
+ _game._player._stepEnabled = false;
+ } else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP) && _roxOnStool) {
+ _roxMode = 20;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 92);
+ } else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP) && !_roxOnStool) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[22] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[22], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[22], 1, 2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[22], Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[22], 5);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[22], 88);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[22], SEQUENCE_TRIGGER_EXPIRE, 0, 104);
+ } else if (_action.isAction(VERB_TALKTO, NOUN_BARTENDER)) {
+ switch (_game._trigger) {
+ case 0: {
+ int centerFlag;
+ Common::Point centerPos;
+ if (_roxOnStool) {
+ centerFlag = 0;
+ centerPos = Common::Point(230, 56);
+ } else {
+ centerFlag = 2;
+ centerPos = Common::Point(0, 0);
+ }
+
+ _game._player._stepEnabled = false;
+ int quoteId;
+ if (_bartenderCalled) {
+ quoteId = 0x210;
+ } else {
+ quoteId = 0x20F;
+ _bartenderCalled = true;
+ }
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(quoteId));
+ _scene->_sequences.addTimer(110, 29);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(90, 28);
+ }
+ break;
+
+ case 29:
+ _scene->_kernelMessages.reset();
+ if (!_roxOnStool) {
+ if (_game._objects.isInRoom(OBJ_ALIEN_LIQUOR)) {
+ _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1DF));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 120;
+ } else if (_rexMode == 0) {
+ _scene->_kernelMessages.add(Common::Point(175, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F9));
+ _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FA));
+ _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FB));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 180;
+ _rexMode = 1;
+ } else if (_rexMode == 1) {
+ _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1FC));
+ _game._player._stepEnabled = true;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 120;
+ _rexMode = 3;
+ } else {
+ _game._player._stepEnabled = true;
+ }
+ } else {
+ if (_game._objects.isInRoom(OBJ_ALIEN_LIQUOR)) {
+ if (!_refuseAlienLiquor) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E2));
+ _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E3));
+ _bartenderCurrentQuestion = 10;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 120;
+ _conversationFl = true;
+ _bartenderDialogNode = 1;
+ if (_dialog2.read(0) <= 1)
+ _dialog1.write(0x214, false);
+
+ _dialog1.start();
+ } else {
+ _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EF));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 120;
+ _bartenderCurrentQuestion = 3;
+ _conversationFl = true;
+ _bartenderDialogNode = 1;
+ if (_dialog2.read(0) <= 1)
+ _dialog1.write(0x214, false);
+
+ _dialog1.start();
+ _game._player._stepEnabled = true;
+ }
+ } else {
+ if (_rexMode == 0) {
+ _scene->_kernelMessages.add(Common::Point(175, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F9));
+ _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FA));
+ _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FB));
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 180;
+ _rexMode = 1;
+ } else if (_rexMode == 1) {
+ _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1FC));
+ _game._player._stepEnabled = true;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(1, 100);
+ _talkTimer = 120;
+ _rexMode = 3;
+ } else {
+ _game._player._stepEnabled = true;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_DANCE_FLOOR))
+ _vm->_dialogs->show(40210);
+ else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) {
+ if (_globals[kSomeoneHasExploded])
+ _vm->_dialogs->show(40212);
+ else
+ _vm->_dialogs->show(40211);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BAR))
+ _vm->_dialogs->show(40213);
+ else if (_action.isAction(VERB_LOOK, NOUN_BARTENDER))
+ _vm->_dialogs->show(40214);
+ else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_IN_ALCOVE))
+ _vm->_dialogs->show(40215);
+ else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_ON_BALCONY))
+ _vm->_dialogs->show(40216);
+ else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_IN_CHAIR))
+ _vm->_dialogs->show(40217);
+ else if (_action.isAction(VERB_LOOK, NOUN_REPAIR_WOMAN))
+ _vm->_dialogs->show(40218);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(40219);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(40220);
+ else if (_action.isAction(VERB_LOOK, NOUN_WOMEN))
+ _vm->_dialogs->show(40221);
+ else if (_action.isAction(VERB_PUSH, NOUN_REPAIR_WOMAN) || _action.isAction(VERB_PULL, NOUN_REPAIR_WOMAN))
+ _vm->_dialogs->show(40222);
+ else if (_action.isAction(VERB_TALKTO, NOUN_WOMEN))
+ _vm->_dialogs->show(40223);
+ else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_ON_BALCONY))
+ _vm->_dialogs->show(40224);
+ else if (_action.isAction(VERB_LOOK, NOUN_RAILING))
+ _vm->_dialogs->show(40225);
+ else if (_action.isAction(VERB_LOOK, NOUN_TABLE))
+ _vm->_dialogs->show(40226);
+ else if (_action.isAction(VERB_TAKE, NOUN_TABLE))
+ _vm->_dialogs->show(40227);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGN))
+ _vm->_dialogs->show(40228);
+ else if (_action.isAction(VERB_TAKE, NOUN_SIGN))
+ _vm->_dialogs->show(40229);
+ else if (_action.isAction(VERB_LOOK, NOUN_BAR_STOOL))
+ _vm->_dialogs->show(40230);
+ else if (_action.isAction(VERB_TAKE, NOUN_BAR_STOOL))
+ _vm->_dialogs->show(40231);
+ else if (_action.isAction(VERB_LOOK, NOUN_CACTUS))
+ _vm->_dialogs->show(40232);
+ else if (_action.isAction(VERB_TAKE, NOUN_CACTUS))
+ _vm->_dialogs->show(40233);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISCO_BALL))
+ _vm->_dialogs->show(40234);
+ else if (_action.isAction(VERB_LOOK, NOUN_UPPER_DANCE_FLOOR))
+ _vm->_dialogs->show(40235);
+ else if (_action.isAction(VERB_LOOK, NOUN_TREE))
+ _vm->_dialogs->show(40236);
+ else if (_action.isAction(VERB_LOOK, NOUN_PLANT))
+ _vm->_dialogs->show(40237);
+ else if (_action.isAction(VERB_TAKE, NOUN_PLANT))
+ _vm->_dialogs->show(40238);
+ else if (_action.isAction(VERB_LOOK, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST))
+ _vm->_dialogs->show(40239);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene405::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene405::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXCL_8");
+
+ if (_scene->_priorSceneId == 401) {
+ _game._player._playerPos = Common::Point(23, 123);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId == 406) {
+ _game._player._playerPos = Common::Point(300, 128);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId == 408) {
+ _game._player._playerPos = Common::Point(154, 109);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId == 413) {
+ _game._player._playerPos = Common::Point(284, 109);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(23, 123);
+ _game._player._facing = FACING_EAST;
+ }
+
+ if (_globals[kArmoryDoorOpen])
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ else
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+
+ if (_scene->_roomChanged) {
+ _globals[kArmoryDoorOpen] = false;
+ _game._objects.addToInventory(OBJ_SECURITY_CARD);
+ }
+
+ _game.loadQuoteSet(0x24F, 0);
+ sceneEntrySound();
+}
+
+void Scene405::step() {
+ if (_game._trigger == 80) {
+ _scene->_sequences.addTimer(20, 81);
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ }
+
+ if (_game._trigger == 81) {
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->show(40525);
+ }
+
+ if (_game._trigger == 70) {
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ;
+ _game._player._visible = true;
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _vm->_sound->command(19);
+ }
+
+ if (_game._trigger == 71) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _globals[kArmoryDoorOpen] = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _game._player._stepEnabled = true;
+ }
+
+ if (_game._trigger == 75) {
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ;
+ _game._player._visible = true;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _globals[kArmoryDoorOpen] = true;
+ _game._player._stepEnabled = true;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle (_globals._spriteIndexes[2],
+ false, 1);
+ _vm->_sound->command(19);
+ }
+}
+
+void Scene405::preActions() {
+ if (_action.isAction(VERB_TAKE))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _game._player._walkOffScreenSceneId = 401;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST))
+ _game._player._walkOffScreenSceneId = 406;
+
+ if (_action.isAction(VERB_CLOSE, NOUN_WIDE_DOOR) && _globals[kArmoryDoorOpen])
+ _game._player.walk(Common::Point(212, 113), FACING_NORTH);
+}
+
+void Scene405::actions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR))
+ _scene->_nextSceneId = 413;
+ else if (_action.isAction(VERB_WALK_THROUGH, NOUN_WIDE_DOOR) && _globals[kArmoryDoorOpen])
+ _scene->_nextSceneId = 408;
+ else if (_action.isAction(VERB_WALK_THROUGH, NOUN_WIDE_DOOR) && !_globals[kArmoryDoorOpen])
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0x24F));
+ else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && !_globals[kArmoryDoorOpen]) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75);
+ Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], msgPos);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87);
+ } else if ((_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) || _action.isAction(VERB_CLOSE, NOUN_WIDE_DOOR)) && _globals[kArmoryDoorOpen]) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], _game._player._playerPos);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87);
+ } else if (_action.isAction(VERB_PUT, NOUN_CARD_SLOT)) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], _game._player._playerPos);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CANNON_BALLS))
+ _vm->_dialogs->show(40510);
+ else if (_action.isAction(VERB_TAKE, NOUN_CANNON_BALLS))
+ _vm->_dialogs->show(40511);
+ else if (_action.isAction(VERB_LOOK, NOUN_WATER_FOUNTAIN))
+ _vm->_dialogs->show(40512);
+ else if (_action.isAction(VERB_LOOK, NOUN_BACKBOARD) || _action.isAction(VERB_LOOK, NOUN_HOOP))
+ _vm->_dialogs->show(40513);
+ else if (_action.isAction(VERB_LOOK, NOUN_LIGHT))
+ _vm->_dialogs->show(40514);
+ else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT))
+ _vm->_dialogs->show(40515);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(40516);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(40517);
+ else if (_action.isAction(VERB_LOOK, NOUN_MONITOR))
+ _vm->_dialogs->show(40518);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action._lookFlag)
+ _vm->_dialogs->show(40519);
+ else if (_action.isAction(VERB_LOOK, NOUN_WIDE_DOOR)) {
+ if (_globals[kArmoryDoorOpen])
+ _vm->_dialogs->show(40521);
+ else
+ _vm->_dialogs->show(40520);
+ } else if (_action.isAction(VERB_LOOK, NOUN_DOOR))
+ _vm->_dialogs->show(40522);
+ else if (_action.isAction(VERB_LOOK, NOUN_COACH_LAMP))
+ _vm->_dialogs->show(40523);
+ else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT))
+ _vm->_dialogs->show(40524);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene406::Scene406(MADSEngine *vm) : Scene4xx(vm) {
+ _hitStorageDoor = false;
+}
+
+void Scene406::synchronize(Common::Serializer &s) {
+ Scene4xx::synchronize(s);
+
+ s.syncAsByte(_hitStorageDoor);
+}
+
+void Scene406::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene406::enter() {
+ _game._player._visible = true;
+ if (_scene->_priorSceneId == 405) {
+ _game._player._playerPos = Common::Point(15, 129);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId == 407) {
+ _game._player._playerPos = Common::Point(270, 127);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId == 410) {
+ _game._player._playerPos = Common::Point(30, 108);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId == 411) {
+ _game._player._playerPos = Common::Point(153, 108);
+ _game._player._facing = FACING_SOUTH;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(15, 129);
+ _game._player._facing = FACING_EAST;
+ }
+
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXCL_8");
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1));
+
+ if (_scene->_roomChanged) {
+ _globals[kStorageDoorOpen] = false;
+ _game._objects.addToInventory(OBJ_SECURITY_CARD);
+ }
+
+ if (!_globals[kStorageDoorOpen])
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+
+ if (_scene->_priorSceneId != 411)
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ else {
+ _game._player._stepEnabled = false;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 90);
+ _vm->_sound->command(19);
+ }
+
+ _game.loadQuoteSet(0x24F, 0);
+ _hitStorageDoor = false;
+ sceneEntrySound();
+}
+
+void Scene406::step() {
+ if (_game._trigger == 90) {
+ _game._player._stepEnabled = true;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ }
+
+ if (_game._trigger == 80)
+ _scene->_nextSceneId = 411;
+
+ if (_game._trigger == 100) {
+ _vm->_dialogs->show(40622);
+ _hitStorageDoor = true;
+ }
+
+ if (_game._trigger == 110) {
+ _scene->_sequences.addTimer(20, 111);
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ }
+
+ if (_game._trigger == 111) {
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->show(40613);
+ }
+
+ if (_game._trigger == 70) {
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _vm->_sound->command(19);
+ }
+
+ if (_game._trigger == 71) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _globals[kStorageDoorOpen] = false;
+ _game._player._stepEnabled = true;
+ }
+
+ if (_game._trigger == 75) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0);
+ _globals[kStorageDoorOpen] = true;
+ _game._player._stepEnabled = true;
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _vm->_sound->command(19);
+ }
+}
+
+void Scene406::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST))
+ _game._player._walkOffScreenSceneId = 405;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST))
+ _game._player._walkOffScreenSceneId = 407;
+
+ if (_action.isAction(VERB_TAKE))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_LOOK, NOUN_SIGN) || _action.isAction(VERB_LOOK, NOUN_TRASH))
+ _game._player._needToWalk = true;
+}
+
+void Scene406::actions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && (_game._player._targetPos.x> 100)) {
+ _game._player._stepEnabled = false;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ _vm->_sound->command(19);
+ } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && _globals[kStorageDoorOpen] && (_game._player._targetPos.x < 100))
+ _scene->_nextSceneId = 410;
+ else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && !_globals[kStorageDoorOpen] && (_game._player._targetPos.x < 100)) {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0x24F));
+ if (!_hitStorageDoor) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(80, 100);
+ }
+ } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && !_globals[kStorageDoorOpen]) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 75);
+ Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], msgPos);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87);
+ } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && _globals[kStorageDoorOpen]) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], msgPos);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87);
+ } else if (_action.isAction(VERB_PUT, NOUN_CARD_SLOT)) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 110);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[2], _game._player._playerPos);
+ _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87);
+ } else if (_action.isAction(VERB_LOOK, NOUN_TRASH))
+ _vm->_dialogs->show(40610);
+ else if (_action.isAction(VERB_TAKE, NOUN_TRASH))
+ _vm->_dialogs->show(40611);
+ else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT))
+ _vm->_dialogs->show(40612);
+ else if (_action.isAction(VERB_LOOK, NOUN_FIRE_EXTINGUISHER))
+ _vm->_dialogs->show(40614);
+ else if (_action.isAction(VERB_TAKE, NOUN_FIRE_EXTINGUISHER))
+ _vm->_dialogs->show(40615);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST))
+ _vm->_dialogs->show(40616);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST))
+ _vm->_dialogs->show(40617);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action._lookFlag)
+ _vm->_dialogs->show(40618);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(40619);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) {
+ if (_globals[kStorageDoorOpen])
+ _vm->_dialogs->show(40621);
+ else
+ _vm->_dialogs->show(40620);
+ } else if (_action.isAction(VERB_LOOK, NOUN_MONITOR))
+ _vm->_dialogs->show(40623);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGNPOST))
+ _vm->_dialogs->show(40624);
+ else if (_action.isAction(VERB_TAKE, NOUN_SIGNPOST))
+ _vm->_dialogs->show(40625);
+ else if (_action.isAction(VERB_LOOK, NOUN_BOULDER))
+ _vm->_dialogs->show(40626);
+ else if (_action.isAction(VERB_TAKE, NOUN_BOULDER))
+ _vm->_dialogs->show(40627);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGN))
+ _vm->_dialogs->show(40628);
+ else if (_action.isAction(VERB_TAKE, NOUN_SIGN))
+ _vm->_dialogs->show(40629);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene407::Scene407(MADSEngine *vm) : Scene4xx(vm), _destPos(0, 0) {
+ _fromNorth = false;
+}
+
+void Scene407::synchronize(Common::Serializer &s) {
+ Scene4xx::synchronize(s);
+
+ s.syncAsByte(_fromNorth);
+ s.syncAsSint16LE(_destPos.x);
+ s.syncAsSint16LE(_destPos.y);
+}
+
+void Scene407::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene407::enter() {
+ if (_scene->_priorSceneId != -2)
+ _fromNorth = false;
+
+ if (_scene->_priorSceneId == 318) {
+ _game._player._playerPos = Common::Point(172, 92);
+ _game._player._facing = FACING_SOUTH;
+ _fromNorth = true;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(172, 132);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ _game.loadQuoteSet(0x250, 0);
+ sceneEntrySound();
+}
+
+void Scene407::step() {
+ if (_game._trigger == 70) {
+ _scene->_nextSceneId = 318;
+ _scene->_reloadSceneFlag = true;
+ }
+
+ if (_game._trigger == 80) {
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _fromNorth = false;
+ _game._player.walk(Common::Point(173, 104), FACING_SOUTH);
+ }
+}
+
+void Scene407::preActions() {
+ if (_action.isAction(VERB_TAKE))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_LOOK, NOUN_DOOR))
+ _game._player._needToWalk = true;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) {
+ _game._player.walk(Common::Point(172, 91), FACING_NORTH);
+ _fromNorth = false;
+ }
+
+ if (_game._player._needToWalk && _fromNorth) {
+ if (_globals[kSexOfRex] == REX_MALE)
+ _destPos = Common::Point(171, 95);
+ else
+ _destPos = Common::Point(173, 96);
+
+ _game._player.walk(_destPos, FACING_SOUTH);
+ }
+}
+
+void Scene407::actions() {
+ if ((_game._player._playerPos == _destPos) && _fromNorth) {
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _vm->_sound->command(21);
+ _scene->loadAnimation(formAnimName('s', 1), 70);
+ _globals[kHasBeenScanned] = true;
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(60));
+ _vm->_sound->command(22);
+ }
+
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _vm->_sound->command(21);
+ _scene->loadAnimation(formAnimName('s', 2), 80);
+ _vm->_sound->command(23);
+ _globals[kHasBeenScanned] = true;
+ }
+ }
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) && !_fromNorth)
+ _scene->_nextSceneId = 406;
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH))
+ _scene->_nextSceneId = 318;
+ else if (_action.isAction(VERB_LOOK, NOUN_SCANNER)) {
+ if (_globals[kHasBeenScanned])
+ _vm->_dialogs->show(40711);
+ else
+ _vm->_dialogs->show(40710);
+ } else if (_action.isAction(VERB_LOOK, NOUN_DOOR))
+ _vm->_dialogs->show(40712);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(40713);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH))
+ _vm->_dialogs->show(40714);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(40715);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene408::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_TARGET_MODULE);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene408::enter() {
+ _game._player._playerPos = Common::Point(137, 150);
+ _game._player._facing = FACING_NORTH;
+
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*ROXRC_7");
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', -1));
+
+ if (_game._objects.isInRoom(OBJ_TARGET_MODULE)) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3);
+ int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(283, 128), FACING_NORTHEAST);
+ }
+ sceneEntrySound();
+}
+
+void Scene408::preActions() {
+ if ((_action.isAction(VERB_TAKE) && !_action.isObject(NOUN_TARGET_MODULE)) || _action.isAction(VERB_PULL, NOUN_PIN) || _action.isAction(VERB_OPEN, NOUN_CARTON))
+ _game._player._needToWalk = false;
+
+ if ((_action.isAction(VERB_LOOK, NOUN_TARGET_MODULE) && _game._objects.isInRoom(OBJ_TARGET_MODULE)) || _action.isAction(VERB_LOOK, NOUN_CHEST))
+ _game._player._needToWalk = true;
+}
+
+void Scene408::actions() {
+ if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) {
+ _scene->_nextSceneId = 405;
+ _vm->_sound->command(58);
+ } else if (_action.isAction(VERB_TAKE, NOUN_TARGET_MODULE) && (_game._objects.isInRoom(OBJ_TARGET_MODULE) || _game._trigger)) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_sound->command(57);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], true, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[1]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _game._objects.addToInventory(OBJ_TARGET_MODULE);
+ _vm->_dialogs->showItem(OBJ_TARGET_MODULE, 40847);
+ break;
+
+ case 2:
+ _game._player._priorTimer = _game._player._ticksAmount + _scene->_frameStartTime;
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(20, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_ARMORED_VEHICLE))
+ _vm->_dialogs->show(40810);
+ else if (_action.isAction(VERB_TAKE, NOUN_ARMORED_VEHICLE) || _action.isAction(VERB_TAKE, NOUN_ANVIL) || _action.isAction(VERB_TAKE, NOUN_TWO_TON_WEIGHT))
+ _vm->_dialogs->show(40811);
+ else if (_action.isAction(VERB_LOOK, NOUN_MISSILE))
+ _vm->_dialogs->show(40812);
+ else if (_action.isAction(VERB_TAKE, NOUN_MISSILE))
+ _vm->_dialogs->show(40813);
+ else if (_action.isAction(VERB_LOOK, NOUN_GRENADE))
+ _vm->_dialogs->show(40814);
+ else if (_action.isAction(VERB_TAKE, NOUN_GRENADE))
+ _vm->_dialogs->show(40815);
+ else if (_action.isAction(VERB_TAKE, NOUN_PIN) || _action.isAction(VERB_PULL, NOUN_PIN))
+ _vm->_dialogs->show(40816);
+ else if (_action.isAction(VERB_LOOK, NOUN_BLIMP))
+ _vm->_dialogs->show(40817);
+ else if (_action.isAction(VERB_TAKE, NOUN_BLIMP))
+ _vm->_dialogs->show(40818);
+ else if (_action.isAction(VERB_LOOK, NOUN_AMMUNITION))
+ _vm->_dialogs->show(40819);
+ else if (_action.isAction(VERB_TAKE, NOUN_AMMUNITION))
+ _vm->_dialogs->show(40820);
+ else if (_action.isAction(VERB_LOOK, NOUN_CATAPULT))
+ _vm->_dialogs->show(40821);
+ else if (_action.isAction(VERB_TAKE, NOUN_CATAPULT))
+ _vm->_dialogs->show(40822);
+ else if (_action.isAction(VERB_LOOK, NOUN_CHEST)) {
+ if (_game._objects.isInRoom(OBJ_TARGET_MODULE))
+ _vm->_dialogs->show(40823);
+ else
+ _vm->_dialogs->show(40824);
+ } else if (_action.isAction(VERB_TAKE, NOUN_CHEST))
+ _vm->_dialogs->show(40825);
+ else if (_action.isAction(VERB_LOOK, NOUN_SUIT_OF_ARMOR))
+ _vm->_dialogs->show(40826);
+ else if (_action.isAction(VERB_TAKE, NOUN_SUIT_OF_ARMOR))
+ _vm->_dialogs->show(40827);
+ else if (_action.isAction(VERB_LOOK, NOUN_ESCAPE_HATCH))
+ _vm->_dialogs->show(40828);
+ else if (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH) || _action.isAction(VERB_PULL, NOUN_ESCAPE_HATCH))
+ _vm->_dialogs->show(40829);
+ else if (_action.isAction(VERB_LOOK, NOUN_BARRELS))
+ _vm->_dialogs->show(40830);
+ else if (_action.isAction(VERB_TAKE, NOUN_BARRELS))
+ _vm->_dialogs->show(40831);
+ else if (_action.isAction(VERB_LOOK, NOUN_INFLATABLE_RAFT))
+ _vm->_dialogs->show(40832);
+ else if (_action.isAction(VERB_TAKE, NOUN_INFLATABLE_RAFT))
+ _vm->_dialogs->show(40833);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOMATO))
+ _vm->_dialogs->show(40834);
+ else if (_action.isAction(VERB_TAKE, NOUN_TOMATO))
+ _vm->_dialogs->show(40835);
+ else if (_action.isAction(VERB_LOOK, NOUN_ANVIL))
+ _vm->_dialogs->show(40836);
+ else if (_action.isAction(VERB_LOOK, NOUN_TWO_TON_WEIGHT))
+ _vm->_dialogs->show(40837);
+ else if (_action.isAction(VERB_LOOK, NOUN_POWDER_CONTAINER))
+ _vm->_dialogs->show(40838);
+ else if (_action.isAction(VERB_LOOK, NOUN_POWDER_PUFF))
+ _vm->_dialogs->show(40839);
+ else if (_action.isAction(VERB_TAKE, NOUN_POWDER_PUFF))
+ _vm->_dialogs->show(40840);
+ else if (_action.isAction(VERB_LOOK, NOUN_CARTON))
+ _vm->_dialogs->show(40841);
+ else if (_action.isAction(VERB_TAKE, NOUN_CARTON))
+ _vm->_dialogs->show(40842);
+ else if (_action.isAction(VERB_OPEN, NOUN_CARTON))
+ _vm->_dialogs->show(40843);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(40844);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(40845);
+ else if (_action.isAction(VERB_LOOK, NOUN_TARGET_MODULE) && _game._objects.isInRoom(OBJ_TARGET_MODULE))
+ _vm->_dialogs->show(40846);
+ else if (_action.isAction(VERB_LOOK, NOUN_LOADING_RAMP))
+ _vm->_dialogs->show(40848);
+ else if (_action.isAction(VERB_OPEN, NOUN_CHEST))
+ _vm->_dialogs->show(40849);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene409::setup() {
+ _game._player._spritesPrefix = "";
+
+ // The original is calling Scene4xx::setAAName()
+ _game._aaName = Resources::formatAAName(4);
+}
+
+void Scene409::enter() {
+ _handSpriteId = _scene->_sprites.addSprites("*ROXHAND");
+ teleporterEnter();
+
+ // The original is calling Scene4xx::sceneEntrySound()
+ if (!_vm->_musicFlag)
+ _vm->_sound->command(2);
+ else
+ _vm->_sound->command(10);
+}
+
+void Scene409::step() {
+ teleporterStep();
+}
+
+void Scene409::actions() {
+ if (teleporterActions()) {
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT))
+ _vm->_dialogs->show(40910);
+ else if (_action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT))
+ _vm->_dialogs->show(40910);
+ else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD))
+ _vm->_dialogs->show(40911);
+ else if (_action.isAction(VERB_INSPECT, NOUN_KEYPAD))
+ _vm->_dialogs->show(40911);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY))
+ _vm->_dialogs->show(40912);
+ else if (_action.isAction(VERB_LOOK, NOUN_1_KEY) || _action.isAction(VERB_LOOK, NOUN_2_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_3_KEY) || _action.isAction(VERB_LOOK, NOUN_4_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_5_KEY) || _action.isAction(VERB_LOOK, NOUN_6_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_7_KEY) || _action.isAction(VERB_LOOK, NOUN_8_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_9_KEY) || _action.isAction(VERB_LOOK, NOUN_0_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY))
+ _vm->_dialogs->show(40913);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEVICE))
+ _vm->_dialogs->show(40914);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(40914);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene410::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene410::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('y', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_7");
+
+ if (_game._objects.isInRoom(OBJ_CHARGE_CASES))
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ else
+ _scene->_hotspots.activate(NOUN_CHARGE_CASES, false);
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(155, 150);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ sceneEntrySound();
+
+ _scene->loadAnimation(Resources::formatName(410, 'r', -1, EXT_AA, ""));
+ _scene->_activeAnimation->_resetFlag = true;
+}
+
+void Scene410::step() {
+ if (_scene->_activeAnimation->getCurrentFrame() == 1) {
+ if (_vm->getRandomNumber(1, 30) == 1)
+ _scene->_activeAnimation->setCurrentFrame(2);
+ else
+ _scene->_activeAnimation->setCurrentFrame(0);
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 9) {
+ if (_vm->getRandomNumber(1, 30) == 1)
+ _scene->_activeAnimation->setCurrentFrame(10);
+ else
+ _scene->_activeAnimation->setCurrentFrame(8);
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 5) {
+ if (_vm->getRandomNumber(1, 30) == 1)
+ _scene->_activeAnimation->setCurrentFrame(6);
+ else
+ _scene->_activeAnimation->setCurrentFrame(4);
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 3) {
+ if (_vm->getRandomNumber(1, 2) == 1)
+ _scene->_activeAnimation->setCurrentFrame(4);
+ else // == 2
+ _scene->_activeAnimation->setCurrentFrame(8);
+ }
+}
+
+void Scene410::preActions() {
+ if (_action.isAction(VERB_TAKE) && !_action.isObject(NOUN_CHARGE_CASES))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_LOOK, NOUN_CHARGE_CASES) && _game._objects.isInRoom(OBJ_CHARGE_CASES))
+ _game._player._needToWalk = true;
+
+ if (_action.isAction(VERB_OPEN, NOUN_SACKS) || _action.isAction(VERB_OPEN, NOUN_SACK))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_LOOK, NOUN_CAN))
+ _game._player._needToWalk = true;
+}
+
+void Scene410::actions() {
+ if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH))
+ _scene->_nextSceneId = 406;
+ else if (_action.isAction(VERB_TAKE, NOUN_CHARGE_CASES) && (_game._objects.isInRoom(OBJ_CHARGE_CASES) || _game._trigger)) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_sound->command(57);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 3, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_hotspots.activate(NOUN_CHARGE_CASES, false);
+ _game._objects.addToInventory(OBJ_CHARGE_CASES);
+ _vm->_dialogs->showItem(OBJ_CHARGE_CASES, 41032);
+ break;
+
+ case 2:
+ _game._player._priorTimer = _game._player._ticksAmount + _scene->_frameStartTime;
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(20, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_BARREL))
+ _vm->_dialogs->show(41010);
+ else if (_action.isAction(VERB_TAKE, NOUN_BARREL))
+ _vm->_dialogs->show(41011);
+ else if (_action.isAction(VERB_OPEN, NOUN_BARREL))
+ _vm->_dialogs->show(41012);
+ else if (_action.isAction(VERB_LOOK, NOUN_RUG))
+ _vm->_dialogs->show(41013);
+ else if (_action.isAction(VERB_TAKE, NOUN_RUG))
+ _vm->_dialogs->show(41014);
+ else if (_action.isAction(VERB_LOOK, NOUN_CARTON) || _action.isAction(VERB_OPEN, NOUN_CARTON)) {
+ if (_game._objects.isInRoom(OBJ_CHARGE_CASES))
+ _vm->_dialogs->show(41015);
+ else
+ _vm->_dialogs->show(41016);
+ } else if (_action.isAction(VERB_LOOK, NOUN_FLOUR))
+ _vm->_dialogs->show(41017);
+ else if (_action.isAction(VERB_TAKE, NOUN_FLOUR))
+ _vm->_dialogs->show(41018);
+ else if (_action.isAction(VERB_LOOK, NOUN_SACKS))
+ _vm->_dialogs->show(41019);
+ else if (_action.isAction(VERB_LOOK, NOUN_SACK))
+ _vm->_dialogs->show(41019);
+ else if (_action.isAction(VERB_OPEN, NOUN_SACKS))
+ _vm->_dialogs->show(41020);
+ else if (_action.isAction(VERB_OPEN, NOUN_SACK))
+ _vm->_dialogs->show(41020);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUCKET_OF_TAR))
+ _vm->_dialogs->show(41021);
+ else if (_action.isAction(VERB_TAKE, NOUN_BUCKET_OF_TAR))
+ _vm->_dialogs->show(41022);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAN))
+ _vm->_dialogs->show(41023);
+ else if (_action.isAction(VERB_TAKE, NOUN_CAN))
+ _vm->_dialogs->show(41024);
+ else if (_action.isAction(VERB_LOOK, NOUN_CHARGE_CASES) && _game._objects.isInRoom(OBJ_CHARGE_CASES))
+ _vm->_dialogs->show(41025);
+ else if (_action.isAction(VERB_LOOK, NOUN_FENCE))
+ _vm->_dialogs->show(41027);
+ else if (_action.isAction(VERB_LOOK, NOUN_SHELVES))
+ _vm->_dialogs->show(41028);
+ else if (_action.isAction(VERB_LOOK, NOUN_RAT))
+ _vm->_dialogs->show(41029);
+ else if (_action.isAction(VERB_TAKE, NOUN_RAT))
+ _vm->_dialogs->show(41030);
+ else if (_action.isAction(VERB_THROW, NOUN_RAT))
+ _vm->_dialogs->show(41031);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(41033);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene411::Scene411(MADSEngine *vm) : Scene4xx(vm) {
+ _curAnimationFrame = -1;
+ _newIngredient = -1;
+ _newQuantity = -1;
+ _resetFrame = -1;
+ _badThreshold = -1;
+
+ _killRox = false;
+ _makeMushroomCloud = false;
+}
+
+void Scene411::synchronize(Common::Serializer &s) {
+ Scene4xx::synchronize(s);
+
+ s.syncAsSint32LE(_curAnimationFrame);
+ s.syncAsSint32LE(_newIngredient);
+ s.syncAsSint32LE(_newQuantity);
+ s.syncAsSint32LE(_resetFrame);
+ s.syncAsSint32LE(_badThreshold);
+
+ s.syncAsByte(_killRox);
+ s.syncAsByte(_makeMushroomCloud);
+}
+
+bool Scene411::addIngredient() {
+ bool retVal = false;
+
+ switch (_newIngredient) {
+ case OBJ_LECITHIN:
+ if (_globals[kIngredientList + _globals[kNextIngredient]] == 1)
+ retVal = true;
+
+ _badThreshold = 1;
+ break;
+
+ case OBJ_ALIEN_LIQUOR:
+ if (_globals[kIngredientList + _globals[kNextIngredient]] == 0)
+ retVal = true;
+
+ _badThreshold = 0;
+ break;
+
+ case OBJ_FORMALDEHYDE:
+ if (_globals[kIngredientList + _globals[kNextIngredient]] == 3)
+ retVal = true;
+
+ _badThreshold = 3;
+ break;
+
+ case OBJ_PETROX:
+ if (_globals[kIngredientList + _globals[kNextIngredient]] == 2)
+ retVal = true;
+
+ _badThreshold = 2;
+ break;
+
+ default:
+ break;
+ }
+
+ if (!retVal && (_globals[kNextIngredient] == 0))
+ _globals[kBadFirstIngredient] = _badThreshold;
+
+ if (_globals[kNextIngredient] == 0)
+ retVal = true;
+
+ return(retVal);
+}
+
+bool Scene411::addQuantity() {
+ bool retVal = false;
+
+ if (_globals[kIngredientQuantity + _globals[kNextIngredient]] == _newQuantity)
+ retVal = true;
+
+ if (!retVal && (_globals[kNextIngredient] == 0))
+ _globals[kBadFirstIngredient] = _badThreshold;
+
+ if (_globals[kNextIngredient] == 0)
+ retVal = true;
+
+ return(retVal);
+}
+
+int Scene411::computeQuoteAndQuantity() {
+ int quoteId;
+ int quantity;
+
+ switch (_action._activeAction._verbId) {
+ case 0x252:
+ quoteId = 0x26F;
+ quantity = 0;
+ break;
+
+ case 0x253:
+ quoteId = 0x271;
+ quantity = 0;
+ break;
+
+ case 0x254:
+ quoteId = 0x270;
+ quantity = 0;
+ break;
+
+ case 0x255:
+ quoteId = 0x272;
+ quantity = 0;
+ break;
+
+ case 0x256:
+ quoteId = 0x267;
+ quantity = 2;
+ break;
+
+ case 0x257:
+ quoteId = 0x269;
+ quantity = 2;
+ break;
+
+ case 0x258:
+ quoteId = 0x268;
+ quantity = 2;
+ break;
+
+ case 0x259:
+ quoteId = 0x26A;
+ quantity = 2;
+ break;
+
+ case 0x25A:
+ quoteId = 0x26B;
+ quantity = 3;
+ break;
+
+ case 0x25B:
+ quoteId = 0x26D;
+ quantity = 3;
+ break;
+
+ case 0x25C:
+ quoteId = 0x26C;
+ quantity = 3;
+ break;
+
+ case 0x25D:
+ quoteId = 0x26E;
+ quantity = 3;
+ break;
+
+ case 0x25E:
+ quoteId = 0x263;
+ quantity = 1;
+ break;
+
+ case 0x25F:
+ quoteId = 0x265;
+ quantity = 1;
+ break;
+
+ case 0x260:
+ quoteId = 0x264;
+ quantity = 1;
+ break;
+
+ case 0x261:
+ quoteId = 0x266;
+ quantity = 1;
+ break;
+
+ default:
+ quoteId = 0;
+ quantity = 0;
+ break;
+ }
+
+ _scene->_kernelMessages.add(Common::Point(202, 82), 0x1110, 32, 0, 120, _game.getQuote(quoteId));
+ return quantity;
+}
+
+void Scene411::handleKettleAction() {
+ switch (_globals[kNextIngredient]) {
+ case 1:
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4],
+ false, 15, 0, 0, 0);
+ break;
+
+ case 2:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4],
+ false, 6, 0, 0, 0);
+ break;
+
+ case 3:
+ _makeMushroomCloud = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene411::handleDialog() {
+ if ((_action._activeAction._verbId != 0x262) && (_game._trigger == 0)) {
+ if (_game._objects.isInInventory(_newIngredient)) {
+ switch (_newIngredient) {
+ case OBJ_FORMALDEHYDE:
+ _resetFrame = 17;
+ break;
+
+ case OBJ_PETROX:
+ _resetFrame = 55;
+ break;
+
+ case OBJ_LECITHIN:
+ _resetFrame = 36;
+ break;
+
+ default:
+ _resetFrame = 112;
+ break;
+ }
+
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_activeAnimation->setCurrentFrame(_resetFrame);
+ }
+ _scene->_kernelMessages.reset();
+ _newQuantity = computeQuoteAndQuantity();
+
+ if ((_globals[kNextIngredient] == 1) && (_globals[kBadFirstIngredient] > -1))
+ _killRox = true;
+ else if (addIngredient() && addQuantity()) {
+ handleKettleAction();
+ _globals[kNextIngredient]++;
+ } else
+ _killRox = true;
+
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ } else if (_action._activeAction._verbId == 0x262)
+ _scene->_userInterface.setup(kInputBuildingSentences);
+}
+
+void Scene411::giveToRex(int object) {
+ switch (object) {
+ case 0:
+ _game._objects.addToInventory(OBJ_ALIEN_LIQUOR);
+ break;
+
+ case 1:
+ _game._objects.addToInventory(OBJ_LECITHIN);
+ break;
+
+ case 2:
+ _game._objects.addToInventory(OBJ_PETROX);
+ break;
+
+ case 3:
+ _game._objects.addToInventory(OBJ_FORMALDEHYDE);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene411::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_ALIEN_LIQUOR);
+ _scene->addActiveVocab(NOUN_FORMALDEHYDE);
+ _scene->addActiveVocab(NOUN_PETROX);
+ _scene->addActiveVocab(NOUN_LECITHIN);
+}
+
+void Scene411::enter() {
+ if (_scene->_priorSceneId == 411) {
+ if ((_globals[kNextIngredient] == 1) && (_globals[kBadFirstIngredient] > -1))
+ giveToRex(_globals[kBadFirstIngredient]);
+ else if (_globals[kNextIngredient] > 0) {
+ for (int i = 0; i < _globals[kNextIngredient]; i ++)
+ giveToRex(_globals[kIngredientList + i]);
+ }
+ _globals[kNextIngredient] = 0;
+ _globals[kBadFirstIngredient] = -1;
+ }
+
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', 0));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('f', 1));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('f', 2));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('c', 1));
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('a', 6));
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites("*ROXRC_9");
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 0);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 50, 0, 0, 0);
+
+ _game.loadQuoteSet(0x252, 0x25E, 0x25A, 0x256, 0x253, 0x25F, 0x25B, 0x257, 0x254, 0x260, 0x25C, 0x258, 0x255,
+ 0x261, 0x25D, 0x259, 0x262, 0x267, 0x263, 0x26B, 0x26F, 0x268, 0x264, 0x26C, 0x270, 0x26A, 0x266, 0x26E,
+ 0x272, 0x269, 0x265, 0x26D, 0x271, 0);
+
+ _dialog1.setup(0x5B, 0x252, 0x25E, 0x25A, 0x256, 0x262, -1);
+ _dialog2.setup(0x5C, 0x253, 0x25F, 0x25B, 0x257, 0x262, -1);
+ _dialog3.setup(0x5D, 0x254, 0x260, 0x25C, 0x258, 0x262, -1);
+ _dialog4.setup(0x5E, 0x255, 0x261, 0x25D, 0x259, 0x262, -1);
+
+ if (_globals[kNextIngredient] >= 4 && !_game._objects[OBJ_CHARGE_CASES].getQuality(3)) {
+ _scene->_hotspots.activate(NOUN_KETTLE, false);
+ _scene->_hotspots.activate(NOUN_EXPLOSIVES, true);
+ } else {
+ _scene->_hotspots.activate(NOUN_EXPLOSIVES, false);
+ _scene->_hotspots.activate(NOUN_KETTLE, true);
+ }
+
+ if (_globals[kNextIngredient] >= 4 && _game._objects[OBJ_CHARGE_CASES].getQuality(3)) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6);
+ } else if (!_game._objects[OBJ_CHARGE_CASES].getQuality(3)) {
+ switch (_globals[kNextIngredient]) {
+ case 1:
+ _vm->_sound->command(53);
+ break;
+
+ case 2:
+ _vm->_sound->command(53);
+ _vm->_sound->command(54);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 15, 0, 0, 0);
+ break;
+
+ case 3:
+ _vm->_sound->command(53);
+ _vm->_sound->command(54);
+ _vm->_sound->command(55);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0);
+ break;
+
+ case 4:
+ _vm->_sound->command(53);
+ _vm->_sound->command(54);
+ _vm->_sound->command(55);
+ _vm->_sound->command(56);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0);
+ break;
+
+ default:
+ _vm->_sound->command(10);
+ break;
+ }
+ }
+
+ if (_globals[kNextIngredient] >= 4 && _game._objects[OBJ_CHARGE_CASES].getQuality(3)) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ }
+
+ if (_game._objects.isInRoom(OBJ_FORMALDEHYDE)) {
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_FORMALDEHYDE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(206, 145), FACING_SOUTHEAST);
+ }
+
+ if (_game._objects.isInRoom(OBJ_PETROX)) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_PETROX, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(186, 112), FACING_NORTHEAST);
+ }
+
+ if (_game._objects.isInRoom(OBJ_LECITHIN)) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_LECITHIN, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(220, 121), FACING_NORTHEAST);
+ }
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(60, 146);
+ _game._player._facing = FACING_NORTHEAST;
+ }
+
+ sceneEntrySound();
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_ALIEN_LIQUOR);
+ _game._objects.addToInventory(OBJ_CHARGE_CASES);
+ _game._objects.addToInventory(OBJ_TAPE_PLAYER);
+ _game._objects.addToInventory(OBJ_AUDIO_TAPE);
+ }
+
+ _scene->loadAnimation(formAnimName('a', -1));
+ _scene->_activeAnimation->setCurrentFrame(128);
+
+ _makeMushroomCloud = false;
+ _killRox = false;
+}
+
+void Scene411::step() {
+ if (_scene->_activeAnimation != nullptr) {
+ if (_curAnimationFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _curAnimationFrame = _scene->_activeAnimation->getCurrentFrame();
+ _resetFrame = -1;
+
+ switch (_curAnimationFrame) {
+ case 16:
+ _game._player._stepEnabled = true;
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _resetFrame = 128;
+ break;
+
+ case 35:
+ case 54:
+ case 71:
+ case 127:
+ if (_killRox) {
+ _resetFrame = 72;
+ } else {
+ _resetFrame = 0;
+ _game._objects.removeFromInventory(_newIngredient, NOWHERE);
+ switch (_globals[kNextIngredient]) {
+ case 1:
+ _vm->_sound->command(53);
+ break;
+
+ case 2:
+ _vm->_sound->command(54);
+ break;
+
+ case 3:
+ _vm->_sound->command(55);
+ break;
+
+ case 4:
+ _vm->_sound->command(56);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case 22:
+ case 41:
+ case 59:
+ case 115:
+ if (_makeMushroomCloud) {
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 5, 1, 0, 0);
+ _makeMushroomCloud = false;
+ _scene->_hotspots.activate(NOUN_KETTLE, false);
+ _scene->_hotspots.activate(NOUN_EXPLOSIVES, true);
+ }
+ break;
+
+ case 111:
+ _resetFrame = 111;
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ case 129:
+ _resetFrame = 128;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((_resetFrame >= 0) && (_resetFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(_resetFrame);
+ _curAnimationFrame = _resetFrame;
+ }
+ }
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 86)
+ _vm->_sound->command(59);
+}
+
+void Scene411::preActions() {
+ if (_action.isAction(VERB_LOOK, NOUN_PETROX) && (_game._objects.isInRoom(OBJ_PETROX)))
+ _game._player._needToWalk = true;
+
+ if (_action.isAction(VERB_LOOK, NOUN_LECITHIN) && (_game._objects.isInRoom(OBJ_LECITHIN)))
+ _game._player._needToWalk = true;
+
+ if (_action.isAction(VERB_LOOK, NOUN_FORMALDEHYDE) && (_game._objects.isInRoom(OBJ_FORMALDEHYDE)))
+ _game._player._needToWalk = true;
+
+ if (_action.isAction(VERB_LOOK, NOUN_EXPLOSIVES) || _action.isAction(VERB_LOOK, NOUN_KETTLE) || _action.isAction(VERB_LOOK, NOUN_MISHAP) ||
+ _action.isAction(VERB_LOOK, NOUN_ALCOVE) || _action.isAction(VERB_LOOK, NOUN_SINK) || _action.isAction(VERB_PUT, NOUN_SINK) ||
+ _action.isAction(VERB_LOOK, NOUN_EXPERIMENT) || _action.isAction(VERB_LOOK, NOUN_DRAWING_BOARD))
+ _game._player._needToWalk = true;
+
+ if (_action.isAction(VERB_PULL, NOUN_KNIFE_SWITCH) || _action.isAction(VERB_PUSH, NOUN_KNIFE_SWITCH))
+ _game._player._needToWalk = false;
+}
+
+void Scene411::actions() {
+ if (_game._screenObjects._inputMode == kInputConversation) {
+ handleDialog();
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) {
+ _scene->_nextSceneId = 406;
+ _vm->_sound->command(10);
+ _action._inProgress = false;
+ return;
+ }
+
+ if ((_globals[kNextIngredient] >= 4) && (_action.isAction(VERB_TAKE, NOUN_EXPLOSIVES) || _action.isAction(VERB_PUT, NOUN_CHARGE_CASES, NOUN_EXPLOSIVES))
+ && !_game._objects[OBJ_CHARGE_CASES].getQuality(3)
+ && _game._objects.isInInventory(OBJ_CHARGE_CASES)) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_sound->command(10);
+ _vm->_sound->command(57);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 110);
+ break;
+
+ case 110: {
+ int idx = _globals._sequenceIndexes[10];
+ _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[10], false, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], idx);
+ _scene->_sequences.addTimer(180, 111);
+ }
+ break;
+
+ case 111:
+ _scene->_hotspots.activate(NOUN_KETTLE, true);
+ _scene->_hotspots.activate(NOUN_EXPLOSIVES, false);
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+
+ _globals._sequenceIndexes[10] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[10], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 112);
+ // No break on purpose
+ case 112:
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _game._objects[OBJ_CHARGE_CASES].setQuality(3, 1);
+ _vm->_dialogs->showItem(OBJ_CHARGE_CASES, 41142);
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ } else if (!_game._objects.isInInventory(OBJ_CHARGE_CASES) && _action.isAction(VERB_TAKE, NOUN_EXPLOSIVES)) {
+ _vm->_dialogs->show(41143);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_PETROX) && (_game._objects.isInRoom(OBJ_PETROX) || _game._trigger)) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_sound->command(57);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _game._objects.addToInventory(OBJ_PETROX);
+ _vm->_dialogs->showItem(OBJ_PETROX, 41120);
+ break;
+
+ case 2:
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(20, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_LECITHIN) && (_game._objects.isInRoom(OBJ_LECITHIN) || _game._trigger)) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_sound->command(57);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _game._objects.addToInventory(OBJ_LECITHIN);
+ _vm->_dialogs->showItem(OBJ_LECITHIN, 41124);
+ break;
+
+ case 2:
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(20, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_FORMALDEHYDE) && _game._objects.isInRoom(OBJ_FORMALDEHYDE) && (_game._trigger == 0)) {
+ _vm->_sound->command(57);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 1);
+ _scene->_sequences.addTimer(20, 100);
+ _scene->_sequences.remove(_globals._sequenceIndexes[7]);
+ _game._objects.addToInventory(OBJ_FORMALDEHYDE);
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_game._trigger == 100) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _scene->_sequences.addTimer(20, 10);
+ }
+
+ if (_game._trigger == 10)
+ _vm->_dialogs->showItem(OBJ_FORMALDEHYDE, 41124);
+
+ if (_action.isAction(VERB_PUT) && _action.isTarget(NOUN_KETTLE)) {
+ if (_action.isObject(NOUN_PETROX) ||
+ _action.isObject(NOUN_FORMALDEHYDE) ||
+ _action.isObject(NOUN_LECITHIN) ||
+ _action.isObject(NOUN_ALIEN_LIQUOR)) {
+ _newIngredient = _game._objects.getIdFromDesc(_action._activeAction._objectNameId);
+ switch (_newIngredient) {
+ case OBJ_ALIEN_LIQUOR:
+ _dialog1.start();
+ break;
+
+ case OBJ_FORMALDEHYDE:
+ _dialog3.start();
+ break;
+
+ case OBJ_PETROX:
+ _dialog4.start();
+ break;
+
+ case OBJ_LECITHIN:
+ _dialog2.start();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+
+ if (_action.isAction(VERB_LOOK, NOUN_MONITOR))
+ _vm->_dialogs->show(41110);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_PURIFIER))
+ _vm->_dialogs->show(41111);
+ else if (_action.isAction(VERB_LOOK, NOUN_LAB_EQUIPMENT))
+ _vm->_dialogs->show(41112);
+ else if (_action.isAction(VERB_LOOK, NOUN_KNIFE_SWITCH))
+ _vm->_dialogs->show(41113);
+ else if (_action.isAction(VERB_PUSH, NOUN_KNIFE_SWITCH) || _action.isAction(VERB_PULL, NOUN_KNIFE_SWITCH))
+ _vm->_dialogs->show(41114);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOXIC_WASTE))
+ _vm->_dialogs->show(41115);
+ else if (_action.isAction(VERB_TAKE, NOUN_TOXIC_WASTE))
+ _vm->_dialogs->show(41116);
+ else if (_action.isAction(VERB_LOOK, NOUN_DRAWING_BOARD))
+ _vm->_dialogs->show(41117);
+ else if (_action.isAction(VERB_LOOK, NOUN_EXPERIMENT))
+ _vm->_dialogs->show(41118);
+ else if (_action.isAction(VERB_LOOK, NOUN_PETROX) && _game._objects.isInRoom(OBJ_PETROX))
+ _vm->_dialogs->show(41119);
+ else if (_action.isAction(VERB_LOOK, NOUN_ALCOVE))
+ _vm->_dialogs->show(41121);
+ else if ((_action.isAction(VERB_LOOK, NOUN_FORMALDEHYDE)) && (_game._objects.isInRoom(OBJ_FORMALDEHYDE)))
+ _vm->_dialogs->show(41122);
+ else if ((_action.isAction(VERB_LOOK, NOUN_LECITHIN)) && (_game._objects.isInRoom(OBJ_LECITHIN)))
+ _vm->_dialogs->show(41123);
+ else if (_action.isAction(VERB_LOOK, NOUN_KETTLE)) {
+ if (_globals[kNextIngredient] > 0 && !_game._objects[OBJ_CHARGE_CASES].getQuality(3)) {
+ _vm->_dialogs->show(41126);
+ } else if (_globals[kNextIngredient] == 0 || _game._objects[OBJ_CHARGE_CASES].getQuality(3)) {
+ _vm->_dialogs->show(41125);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_EXPLOSIVES) && _game._objects[OBJ_CHARGE_CASES].getQuality(3) == 0) {
+ _vm->_dialogs->show(41127);
+ } else if (_action.isAction(VERB_TAKE, NOUN_KETTLE))
+ _vm->_dialogs->show(41128);
+ else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL))
+ _vm->_dialogs->show(41129);
+ else if (_action.isAction(VERB_LOOK, NOUN_MISHAP))
+ _vm->_dialogs->show(41130);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(41131);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(41132);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_HORN))
+ _vm->_dialogs->show(41133);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS))
+ _vm->_dialogs->show(41134);
+ else if (_action.isAction(VERB_LOOK, NOUN_HEATER))
+ _vm->_dialogs->show(41135);
+ else if (_action.isAction(VERB_LOOK, NOUN_PIPE))
+ _vm->_dialogs->show(41136);
+ else if (_action.isAction(VERB_LOOK, NOUN_SINK))
+ _vm->_dialogs->show(41137);
+ else if (_action.isAction(VERB_PUT, NOUN_SINK))
+ _vm->_dialogs->show(41138);
+ else if (_action.isAction(VERB_TAKE, NOUN_EXPERIMENT))
+ _vm->_dialogs->show(41139);
+ else if (_action.isAction(VERB_LOOK, NOUN_ELECTRODES))
+ _vm->_dialogs->show(41140);
+ else if (_action.isAction(VERB_TAKE, NOUN_ELECTRODES))
+ _vm->_dialogs->show(41141);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene413::Scene413(MADSEngine *vm) : Scene4xx(vm) {
+ _rexDeath = -1;
+ _canMove = -1;
+}
+
+void Scene413::synchronize(Common::Serializer &s) {
+ Scene4xx::synchronize(s);
+
+ s.syncAsSint32LE(_rexDeath);
+ s.syncAsSint32LE(_canMove);
+}
+
+void Scene413::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene413::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 2));
+ _rexDeath = false;
+
+ if (_scene->_priorSceneId == 405) {
+ _game._player._playerPos = Common::Point(142, 146);
+ _game._player._facing = FACING_NORTH;
+ _game._player._visible = true;
+ } else if (_scene->_priorSceneId != -2) {
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _scene->loadAnimation(Resources::formatName(413, 'd', 1, EXT_AA, ""), 78);
+ _vm->_sound->command(30);
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _rexDeath = true;
+ } else if (!_globals[kTeleporterCommand]) {
+ _game._player._playerPos = Common::Point(136, 117);
+ _game._player.walk(Common::Point(141, 130), FACING_SOUTH);
+ _game._player._facing = FACING_SOUTH;
+ _game._player._visible = true;
+ }
+ }
+
+ if ((_globals[kTeleporterCommand]) && (!_rexDeath)) {
+ switch (_globals[kTeleporterCommand]) {
+ case 1:
+ _vm->_sound->command(30);
+ _game._player._visible = false;
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 19);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 76);
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _vm->_sound->command(30);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 20);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 77);
+ break;
+
+ case 3:
+ case 4:
+ _game._player._playerPos = Common::Point(136, 117);
+ _game._player._facing = FACING_SOUTH;
+ _game._player.walk(Common::Point(141, 130), FACING_SOUTH);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ _globals[kTeleporterCommand] = 0;
+ }
+
+ _canMove = true;
+ sceneEntrySound();
+}
+
+void Scene413::step() {
+ if (_scene->_activeAnimation && _scene->_activeAnimation->getCurrentFrame() == 38)
+ _scene->_activeAnimation->setCurrentFrame(37);
+
+ if (_scene->_activeAnimation && _scene->_activeAnimation->getCurrentFrame() == 21 && _canMove) {
+ _vm->_sound->command(27);
+ _canMove = false;
+ }
+
+ if (_game._trigger == 76) {
+ _game._player._playerPos = Common::Point(136, 117);
+ _game._player.walk(Common::Point(141, 130), FACING_SOUTH);
+ _game._player._facing = FACING_SOUTH;
+ _game._player.selectSeries();
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ }
+
+ if (_game._trigger == 77) {
+ _globals[kTeleporterCommand] = TELEPORTER_BEAM_IN;
+ _scene->_nextSceneId = _globals[kTeleporterDestination];
+ _scene->_reloadSceneFlag = true;
+ }
+
+ if (_game._trigger == 78) {
+ _scene->_reloadSceneFlag = true;
+ _scene->_nextSceneId = _scene->_priorSceneId;
+ _globals[kTeleporterCommand] = TELEPORTER_NONE;
+ }
+}
+
+void Scene413::preActions() {
+ if (_action.isAction(VERB_TAKE) || _action.isAction(VERB_PUT, NOUN_CONVEYOR_BELT))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_LOOK, NOUN_WOODEN_STATUE) || _action.isAction(VERB_LOOK, NOUN_DISPLAY)
+ || _action.isAction(VERB_LOOK, NOUN_PICTURE) || _action.isAction(VERB_LOOK, NOUN_PLANT)) {
+ _game._player._needToWalk = true;
+ }
+}
+
+void Scene413::actions() {
+ if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_nextSceneId = 409;
+ } else if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH))
+ _scene->_nextSceneId = 405;
+ else if (_action.isAction(VERB_LOOK, NOUN_WOODEN_STATUE))
+ _vm->_dialogs->show(41310);
+ else if (_action.isAction(VERB_TAKE, NOUN_WOODEN_STATUE))
+ _vm->_dialogs->show(41311);
+ else if (_action.isAction(VERB_LOOK, NOUN_CONVEYOR_BELT))
+ _vm->_dialogs->show(41312);
+ else if (_action.isAction(VERB_PUT, NOUN_CONVEYOR_BELT))
+ _vm->_dialogs->show(41313);
+ else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER))
+ _vm->_dialogs->show(41314);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY))
+ _vm->_dialogs->show(41315);
+ else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH))
+ _vm->_dialogs->show(41316);
+ else if (_action.isAction(VERB_LOOK, NOUN_PICTURE))
+ _vm->_dialogs->show(41317);
+ else if (_action.isAction(VERB_LOOK, NOUN_PLANT))
+ _vm->_dialogs->show(41318);
+ else if (_action.isAction(VERB_TAKE, NOUN_PLANT))
+ _vm->_dialogs->show(41319);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(41320);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Nebular
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes4.h b/engines/mads/nebular/nebular_scenes4.h
new file mode 100644
index 0000000000..fbd5ce81f0
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes4.h
@@ -0,0 +1,258 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_NEBULAR_SCENES4_H
+#define MADS_NEBULAR_SCENES4_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+class Scene4xx : public NebularScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void setAAName();
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix();
+
+ void sceneEntrySound();
+
+public:
+ Scene4xx(MADSEngine *vm) : NebularScene(vm) {}
+};
+
+class Scene401 : public Scene4xx {
+private:
+ bool _northFl;
+ Common::Point _destPos;
+ uint32 _timer;
+
+public:
+ Scene401(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene402 : public Scene4xx {
+private:
+ bool _lightOn;
+ bool _blowingSmoke;
+ bool _leftWomanMoving;
+ bool _rightWomanMoving;
+ bool _firstTalkToGirlInChair;
+ bool _waitingGinnyMove;
+ bool _ginnyLooking;
+ bool _bigBeatFl;
+ bool _roxOnStool;
+ bool _bartenderSteady;
+ bool _bartenderHandsHips;
+ bool _bartenderLooksLeft;
+ bool _bartenderReady;
+ bool _bartenderTalking;
+ bool _bartenderCalled;
+ bool _conversationFl;
+ bool _activeTeleporter;
+ bool _activeArrows;
+ bool _activeArrow1;
+ bool _activeArrow2;
+ bool _activeArrow3;
+ bool _cutSceneReady;
+ bool _cutSceneNeeded;
+ bool _helgaReady;
+ bool _refuseAlienLiquor;
+
+ int _drinkTimer;
+ int _beatCounter;
+ int _bartenderMode;
+ int _bartenderDialogNode;
+ int _bartenderCurrentQuestion;
+ int _helgaTalkMode;
+ int _roxMode;
+ int _rexMode;
+ int _talkTimer;
+
+ Conversation _dialog1;
+ Conversation _dialog2;
+ Conversation _dialog3;
+ Conversation _dialog4;
+
+ void setDialogNode(int node);
+ void handleConversation1();
+ void handleConversation2();
+ void handleConversation3();
+ void handleConversation4();
+ void handleDialogs();
+
+public:
+ Scene402(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene405 : public Scene4xx {
+public:
+ Scene405(MADSEngine *vm) : Scene4xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene406 : public Scene4xx {
+private:
+ bool _hitStorageDoor;
+
+public:
+ Scene406(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene407 : public Scene4xx {
+private:
+ bool _fromNorth;
+ Common::Point _destPos;
+
+public:
+ Scene407(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene408 : public Scene4xx {
+public:
+ Scene408(MADSEngine *vm) : Scene4xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene409 : public SceneTeleporter {
+public:
+ Scene409(MADSEngine *vm) : SceneTeleporter(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene410 : public Scene4xx {
+public:
+ Scene410(MADSEngine *vm) : Scene4xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene411 : public Scene4xx {
+private:
+ int _curAnimationFrame;
+ int _newIngredient;
+ int _newQuantity;
+ int _resetFrame;
+ int _badThreshold;
+
+ bool _killRox;
+ bool _makeMushroomCloud;
+
+ Conversation _dialog1;
+ Conversation _dialog2;
+ Conversation _dialog3;
+ Conversation _dialog4;
+
+ void giveToRex(int object);
+ void handleDialog();
+ void handleKettleAction();
+
+ int computeQuoteAndQuantity();
+
+ bool addQuantity();
+ bool addIngredient();
+
+public:
+ Scene411(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene413 : public Scene4xx {
+private:
+ int _rexDeath;
+ int _canMove;
+
+public:
+ Scene413(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+} // End of namespace Nebular
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES4_H */
diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp
new file mode 100644
index 0000000000..66d8294fc6
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes5.cpp
@@ -0,0 +1,2870 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes5.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+void Scene5xx::setAAName() {
+ _game._aaName = Resources::formatAAName(5);
+}
+
+void Scene5xx::setPlayerSpritesPrefix() {
+ _vm->_sound->command(5);
+
+ Common::String oldName = _game._player._spritesPrefix;
+
+ if ((_scene->_nextSceneId == 502) || (_scene->_nextSceneId == 504) || (_scene->_nextSceneId == 505) || (_scene->_nextSceneId == 515))
+ _game._player._spritesPrefix = "";
+ else if (_globals[kSexOfRex] == REX_MALE)
+ _game._player._spritesPrefix = "RXM";
+ else if ((_scene->_nextSceneId == 501) || (_scene->_nextSceneId == 503) || (_scene->_nextSceneId == 551))
+ _game._player._spritesPrefix = "ROX";
+
+ _game._player._scalingVelocity = true;
+
+ if ((_scene->_nextSceneId == 512) || (_scene->_nextSceneId == 507))
+ _game._player._scalingVelocity = false;
+
+ if (oldName != _game._player._spritesPrefix)
+ _game._player._spritesChanged = true;
+
+ _vm->_palette->setEntry(16, 10, 63, 63);
+ _vm->_palette->setEntry(17, 10, 45, 45);
+}
+
+void Scene5xx::sceneEntrySound() {
+ if (!_vm->_musicFlag) {
+ _vm->_sound->command(2);
+ return;
+ }
+
+ switch (_scene->_nextSceneId) {
+ case 501:
+ case 502:
+ case 504:
+ case 505:
+ case 506:
+ case 507:
+ case 508:
+ case 511:
+ case 512:
+ case 513:
+ case 515:
+ case 551:
+ if (_scene->_priorSceneId == 503)
+ _vm->_sound->command(38);
+ else
+ _vm->_sound->command(29);
+ break;
+ case 503:
+ _vm->_sound->command(41);
+ break;
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene501::Scene501(MADSEngine *vm) : Scene5xx(vm) {
+ _mainSequenceId = -1;
+ _mainSpriteId = -1;
+ _doorHotspotid = -1;
+
+ _rexPunched = false;
+}
+
+void Scene501::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsSint16LE(_mainSequenceId);
+ s.syncAsSint16LE(_mainSpriteId);
+ s.syncAsSint16LE(_doorHotspotid);
+ s.syncAsByte(_rexPunched);
+}
+
+void Scene501::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_DOOR);
+ _scene->addActiveVocab(VERB_WALK_THROUGH);
+}
+
+void Scene501::handleSlotActions() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ int numTicks, frameIndex;
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _mainSpriteId = _globals._spriteIndexes[4];
+ numTicks = 8;
+ frameIndex = 3;
+ } else {
+ _mainSpriteId = _globals._spriteIndexes[5];
+ numTicks = 10;
+ frameIndex = 2;
+ }
+
+ _mainSequenceId = _scene->_sequences.startReverseCycle(_mainSpriteId, false, numTicks, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_mainSequenceId, 1, frameIndex);
+ _scene->_sequences.setMsgLayout(_mainSequenceId);
+ _vm->_sound->command(10);
+ _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_SPRITE, frameIndex, 1);
+ _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 6, 0, 0);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _mainSequenceId);
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(15, 3);
+ break;
+
+ case 3:
+ _game._player.walk(Common::Point(282, 110), FACING_NORTH);
+ _scene->_sequences.addTimer(60, 4);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene501::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0));
+
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRC_9");
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXCD_7");
+ } else {
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*ROXRC_9");
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXCD_7");
+ }
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_DOOR, VERB_WALK_THROUGH, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _doorHotspotid = _scene->_dynamicHotspots.setPosition(idx,Common::Point(282, 110), FACING_NORTH);
+ _scene->_dynamicHotspots.setCursor(_doorHotspotid, CURSOR_GO_UP);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _rexPunched = true;
+
+ if (_scene->_priorSceneId == 504) {
+ _game._player._stepEnabled = false;
+ _game._player._playerPos = Common::Point(74, 121);
+ _game._player._facing = FACING_NORTHWEST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ if (_globals[kSexOfRex] == REX_MALE)
+ _scene->loadAnimation(formAnimName('G', 2), 70);
+ else
+ _scene->loadAnimation(formAnimName('R', 2), 70);
+ } else if (_scene->_priorSceneId == 503) {
+ _game._player._playerPos = Common::Point(317, 102);
+ _game._player._facing = FACING_SOUTHWEST;
+ _scene->_sequences.addTimer(15, 80);
+ } else if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(299, 131);
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_FAKE_ID);
+ _game._objects.addToInventory(OBJ_SECURITY_CARD);
+ _game._objects.addToInventory(OBJ_ID_CARD);
+ }
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0x275, 0x276, 0x277, 0);
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _scene->_sequences.addTimer(2, 90);
+}
+
+void Scene501::step() {
+ if (_game._trigger == 90)
+ _vm->_dialogs->show(50127);
+
+ if (_game._trigger >= 80) {
+ switch (_game._trigger) {
+ case 80:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 6, 0, 0);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ _vm->_sound->command(11);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 81);
+ break;
+
+ case 81:
+ _scene->_dynamicHotspots.remove(_doorHotspotid);
+ _game._player.walk(Common::Point(276, 110), FACING_SOUTHWEST);
+ _scene->_sequences.addTimer(120, 82);
+ break;
+
+ case 82:
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ _vm->_sound->command(12);
+ _doorHotspotid = _scene->_dynamicHotspots.add(NOUN_DOOR, VERB_WALK_THROUGH, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_globals._sequenceIndexes[3], Common::Point(282, 110), FACING_NORTH);
+ _scene->_dynamicHotspots.setCursor(_doorHotspotid, CURSOR_GO_UP);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 83);
+ break;
+
+ case 83:
+ _game._player._stepEnabled = true;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (_game._trigger >= 70 && _game._trigger <= 73) {
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(15, 71);
+ break;
+
+ case 71:
+ _game._player.walk(Common::Point(92, 130), FACING_SOUTH);
+ _scene->_sequences.addTimer(30, 72);
+ break;
+
+ case 72:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 73);
+ break;
+
+ case 73:
+ _game._player._stepEnabled = true;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene501::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN) && (_action.isObject(NOUN_STREET_TO_EAST) || _action.isObject(NOUN_SIDEWALK_TO_EAST)))
+ _game._player._walkOffScreenSceneId = 551;
+}
+
+void Scene501::actions() {
+ if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx);
+ _scene->_sequences.addTimer(15, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_MALE)
+ _mainSpriteId = _globals._spriteIndexes[6];
+ else
+ _mainSpriteId = _globals._spriteIndexes[7];
+
+ _mainSequenceId = _scene->_sequences.addSpriteCycle(_mainSpriteId, false, 8, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_mainSequenceId);
+ _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _mainSequenceId;
+ _mainSequenceId = _scene->_sequences.startCycle(_mainSpriteId, false, -2);
+ _scene->_sequences.setMsgLayout(_mainSequenceId);
+ _scene->_sequences.updateTimeout(_mainSequenceId, syncIdx);
+ _scene->_sequences.addTimer(30, 4);
+ }
+ break;
+
+ case 4:
+ _scene->_nextSceneId = 504;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT))
+ _vm->_dialogs->show(50113);
+ else if (_action.isAction(VERB_PUT, NOUN_FAKE_ID, NOUN_CARD_SLOT)) {
+ switch (_game._trigger) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ handleSlotActions();
+ break;
+
+ case 4:
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _game._player._visible = false;
+ _vm->_sound->command(13);
+ _scene->loadAnimation(formAnimName('G', 1), 5);
+ } else {
+ _rexPunched = false;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 6, 120, _game.getQuote(0x277));
+ }
+ break;
+
+ case 5:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(30, 6);
+ break;
+
+ case 6:
+ if (_globals[kSexOfRex] == REX_MALE) {
+ if (_rexPunched) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x275));
+ _rexPunched = false;
+ } else {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x276));
+ }
+ }
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PUT, NOUN_ID_CARD, NOUN_CARD_SLOT)) {
+ switch (_game._trigger) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ handleSlotActions();
+ break;
+
+ case 4:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _scene->_dynamicHotspots.remove(_doorHotspotid);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ _vm->_sound->command(11);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 6);
+ break;
+
+ case 6:
+ _game._player.walk(Common::Point(317, 102), FACING_NORTHEAST);
+ _scene->_sequences.addTimer(120, 7);
+ break;
+
+ case 7: {
+ _vm->_sound->command(12);
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _vm->_sound->command(12);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8);
+ }
+ break;
+
+ case 8: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _scene->_nextSceneId = 503;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET))
+ _vm->_dialogs->show(50121);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOOR))
+ _vm->_dialogs->show(50110);
+ else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT))
+ _vm->_dialogs->show(50112);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGN))
+ _vm->_dialogs->show(50114);
+ else if (_action.isAction(VERB_TAKE, NOUN_SIGN))
+ _vm->_dialogs->show(50115);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_EAST))
+ _vm->_dialogs->show(50118);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST)
+ || _action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST))
+ _vm->_dialogs->show(50119);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
+ _vm->_dialogs->show(50120);
+ else if (_action.isAction(VERB_OPEN, NOUN_DOOR))
+ _vm->_dialogs->show(50122);
+ else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT))
+ _vm->_dialogs->show(50123);
+ else if (_action.isAction(VERB_OPEN, NOUN_FIRE_HYDRANT))
+ _vm->_dialogs->show(50124);
+ else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT_OVERHEAD))
+ _vm->_dialogs->show(50125);
+ else if (_action.isAction(VERB_LOOK, NOUN_PIPES) || _action.isAction(VERB_LOOK, NOUN_PIPE))
+ _vm->_dialogs->show(50126);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAR)) {
+ if (!_game._visitedScenes.exists(504))
+ _vm->_dialogs->show(50116);
+ else
+ _vm->_dialogs->show(50117);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene502::setup() {
+ _game._player._spritesPrefix = "";
+ // The original is using Scene5xx_setAAName()
+ _game._aaName = Resources::formatAAName(5);
+}
+
+void Scene502::enter() {
+ if (_globals[kSexOfRex] == REX_MALE)
+ _handSpriteId = _scene->_sprites.addSprites("*REXHAND");
+ else
+ _handSpriteId = _scene->_sprites.addSprites("*ROXHAND");
+
+ teleporterEnter();
+
+ // The original uses scene5xx_sceneEntrySound
+ if (!_vm->_musicFlag)
+ _vm->_sound->command(2);
+ else if (_scene->_priorSceneId == 503)
+ _vm->_sound->command(38);
+ else
+ _vm->_sound->command(29);
+}
+
+void Scene502::step() {
+ teleporterStep();
+}
+
+void Scene502::actions() {
+ if (teleporterActions()) {
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT))
+ _vm->_dialogs->show(50210);
+ else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD))
+ _vm->_dialogs->show(50211);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY))
+ _vm->_dialogs->show(50212);
+ else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY))
+ _vm->_dialogs->show(50213);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) || _action._lookFlag)
+ _vm->_dialogs->show(50214);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene503::Scene503(MADSEngine *vm) : Scene5xx(vm) {
+ _detonatorHotspotId = -1;
+}
+
+void Scene503::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsSint16LE(_detonatorHotspotId);
+}
+
+void Scene503::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_DETONATORS);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene503::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1));
+
+ if (_globals[kSexOfRex] == REX_MALE)
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMBD_2");
+ else
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXBD_2");
+
+ if (_game._objects[OBJ_DETONATORS]._roomNumber == _scene->_currentSceneId) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0);
+ _detonatorHotspotId = _scene->_dynamicHotspots.add(NOUN_DETONATORS, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_detonatorHotspotId, Common::Point(254, 135), FACING_SOUTH);
+ }
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(191, 152);
+ _game._player._facing = FACING_NORTHWEST;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene503::actions() {
+ if (_action.isAction(VERB_WALK, NOUN_OUTSIDE))
+ _scene->_nextSceneId = 501;
+ else if (_action.isAction(VERB_TAKE, NOUN_DETONATORS)) {
+ if ( _game._trigger || !_game._objects.isInInventory(OBJ_DETONATORS)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 3, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ } else {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 1:
+ _vm->_sound->command(9);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_detonatorHotspotId);
+ _game._objects.addToInventory(OBJ_DETONATORS);
+ _vm->_dialogs->showItem(OBJ_DETONATORS, 50326);
+ break;
+
+ case 2:
+ if (_globals[kSexOfRex] == REX_MALE)
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ else
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]);
+
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(50328);
+ else if (_action.isAction(VERB_LOOK, NOUN_MONITORING_EQUIPMENT))
+ _vm->_dialogs->show(50310);
+ else if (_action.isAction(VERB_LOOK, NOUN_PHOTON_RIFLES))
+ _vm->_dialogs->show(50311);
+ else if (_action.isAction(VERB_TAKE, NOUN_PHOTON_RIFLES) || _action.isAction(VERB_TAKE, NOUN_NUCLEAR_SLINGSHOT))
+ _vm->_dialogs->show(50312);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY_CASE))
+ _vm->_dialogs->show(50313);
+ else if (_action.isAction(VERB_LOOK, NOUN_NUCLEAR_SLINGSHOT))
+ _vm->_dialogs->show(50314);
+ else if (_action.isAction(VERB_LOOK, NOUN_WATER_COOLER))
+ _vm->_dialogs->show(50315);
+ else if (_action.isAction(VERB_LOOK, NOUN_STORAGE_BOX))
+ _vm->_dialogs->show(50316);
+ else if (_action.isAction(VERB_OPEN, NOUN_STORAGE_BOX))
+ _vm->_dialogs->show(50317);
+ else if (_action.isAction(VERB_LOOK, NOUN_WARNING_LABEL))
+ _vm->_dialogs->show(50318);
+ else if (_action.isAction(VERB_LOOK, NOUN_DESK))
+ _vm->_dialogs->show(50319);
+ else if (_action.isAction(VERB_LOOK, NOUN_MONITOR))
+ _vm->_dialogs->show(50320);
+ else if (_action.isAction(VERB_LOOK, NOUN_FILE_CABINETS))
+ _vm->_dialogs->show(50322);
+ else if (_action.isAction(VERB_LOOK, NOUN_BOX)) {
+ if (_game._objects.isInRoom(OBJ_DETONATORS))
+ _vm->_dialogs->show(50323);
+ else
+ _vm->_dialogs->show(50324);
+ } else if (_action.isAction(VERB_LOOK, NOUN_DETONATORS) && (_action._savedFields._mainObjectSource == 4))
+ _vm->_dialogs->show(50325);
+ else if (_action.isAction(VERB_LOOK, NOUN_WINDOWS))
+ _vm->_dialogs->show(50327);
+ else if (_action.isAction(VERB_OPEN, NOUN_DISPLAY_CASE))
+ _vm->_dialogs->show(50329);
+ else if (_action.isAction(VERB_THROW, NOUN_DISPLAY_CASE) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId)))
+ _vm->_dialogs->show(50330);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene504::Scene504(MADSEngine *vm) : Scene5xx(vm) {
+ _carAnimationMode = -1;
+ _carFrame = -1;
+}
+
+void Scene504::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsSint16LE(_carAnimationMode);
+ s.syncAsSint16LE(_carFrame);
+}
+
+void Scene504::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+}
+
+void Scene504::enter() {
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2));
+
+ for (int i = 0; i < 4; i++)
+ _globals._spriteIndexes[5 + i] = _scene->_sprites.addSprites(formAnimName('m', i));
+
+ if (_globals[kSexOfRex] == REX_MALE)
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ else {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _scene->changeVariant(1);
+ }
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 0);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0);
+ _carFrame = -1;
+
+ if ((_scene->_priorSceneId == 505) && (_globals[kHoverCarDestination] != _globals[kHoverCarLocation])){
+ _carAnimationMode = 1;
+ _scene->loadAnimation(formAnimName('A', -1));
+ _vm->_sound->command(14);
+ _scene->_sequences.addTimer(1, 70);
+ _game._player._stepEnabled = false;
+ } else {
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 3));
+ _carAnimationMode = 1;
+ _scene->loadAnimation(formAnimName('A', -1));
+ if ((_scene->_priorSceneId != -2) && (_scene->_priorSceneId != 505))
+ _globals[kHoverCarLocation] = _scene->_priorSceneId;
+
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1);
+ }
+
+ if (_globals[kTimebombTimer] > 10500)
+ _globals[kTimebombTimer] = 10500;
+
+ sceneEntrySound();
+}
+
+void Scene504::step() {
+ if ((_carAnimationMode == 1) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) {
+ _carFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextFrame;
+
+ if (_carFrame == 1)
+ nextFrame = 0;
+ else
+ nextFrame = -1;
+
+ if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextFrame);
+ _carFrame = nextFrame;
+ }
+ }
+ }
+
+
+ if (_game._trigger >= 70) {
+ switch (_game._trigger) {
+ case 70:
+ if (_globals[kHoverCarDestination] != -1) {
+ _game._player._stepEnabled = false;
+ _scene->freeAnimation();
+ _carAnimationMode = 2;
+ if (((_globals[kHoverCarLocation] >= 500 && _globals[kHoverCarLocation] <= 599) &&
+ (_globals[kHoverCarDestination] >= 500 && _globals[kHoverCarDestination] <= 599)) ||
+ ((_globals[kHoverCarLocation] >= 600 && _globals[kHoverCarLocation] <= 699) &&
+ (_globals[kHoverCarDestination] >= 600 && _globals[kHoverCarDestination] <= 699))) {
+ _scene->loadAnimation(formAnimName('A', -1), 71);
+ } else if (_globals[kHoverCarLocation] > _globals[kHoverCarDestination])
+ _scene->loadAnimation(formAnimName('C', -1), 71);
+ else
+ _scene->loadAnimation(formAnimName('B', -1), 71);
+ }
+ break;
+
+ case 71:
+ _vm->_sound->command(15);
+ _scene->_nextSceneId = _globals[kHoverCarDestination];
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ((_globals[kTimebombTimer] >= 10800) && (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) && (_game._difficulty != 3)) {
+ _globals[kTimebombStatus] = TIMEBOMB_DEAD;
+ _globals[kTimebombTimer] = 0;
+ _globals[kCheckDaemonTimebomb] = false;
+ _scene->_nextSceneId = 620;
+ }
+}
+
+void Scene504::preActions() {
+ _game._player._needToWalk = false;
+}
+
+void Scene504::actions() {
+ if (_action.isAction(VERB_EXIT_FROM, NOUN_CAR)) {
+ _vm->_sound->command(15);
+ _scene->_nextSceneId = _globals[kHoverCarLocation];
+ } else if (_action.isAction(VERB_ACTIVATE, NOUN_CAR_CONTROLS)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _vm->_sound->command(39);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 13);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _scene->_sequences.remove(_globals._sequenceIndexes[7]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 14);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 13);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 6);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ }
+ break;
+
+ case 2:
+ _scene->_sequences.addTimer(10, 3);
+ break;
+
+ case 3:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _vm->_sound->command(34);
+ _scene->_sequences.addTimer(60, 4);
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 14);
+ } else {
+ _vm->_sound->command(40);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 18, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 14);
+ _scene->_sequences.addTimer(120, 5);
+ }
+ break;
+
+ case 4:
+ _game._player._stepEnabled = true;
+ _globals[kHoverCarDestination] = _globals[kHoverCarLocation];
+ _scene->_nextSceneId = 505;
+ break;
+
+ case 5:
+ _game._player._stepEnabled = true;
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1);
+ _vm->_dialogs->show(50421);
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_INTERIOR_OF_CAR))
+ _vm->_dialogs->show(50412);
+ else if (_action.isAction(VERB_LOOK, NOUN_GLOVE_COMPARTMENT))
+ _vm->_dialogs->show(50410);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAR_CONTROLS) || _action.isAction(VERB_LOOK, NOUN_DASHBOARD))
+ _vm->_dialogs->show(50411);
+ else if (_action.isAction(VERB_LOOK, NOUN_SCENT_PACKET))
+ _vm->_dialogs->show(50413);
+ else if (_action.isAction(VERB_LOOK, NOUN_SODA_CANS))
+ _vm->_dialogs->show(50414);
+ else if (_action.isAction(VERB_LOOK, NOUN_KITTY))
+ _vm->_dialogs->show(50415);
+ else if (_action.isAction(VERB_LOOK, NOUN_WINDSHIELD) || _action.isAction(VERB_LOOK_THROUGH, NOUN_WINDSHIELD))
+ _vm->_dialogs->show(50416);
+ else if (_action.isAction(VERB_LOOK, NOUN_REARVIEW_MIRROR))
+ _vm->_dialogs->show(50417);
+ else if (_action.isAction(VERB_TAKE, NOUN_REARVIEW_MIRROR))
+ _vm->_dialogs->show(50418);
+ else if (_action.isAction(VERB_LOOK, NOUN_MOLDY_SOCK))
+ _vm->_dialogs->show(50419);
+ else if (_action.isAction(VERB_TAKE, NOUN_MOLDY_SOCK))
+ _vm->_dialogs->show(50420);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene505::Scene505(MADSEngine *vm) : Scene5xx(vm) {
+ _frame = -1;
+ _nextButtonId = -1;
+ _homeSelectedId = -1;
+ _selectedId = -1;
+ _activeCars = -1;
+
+ for (int i = 0; i < 9; i++)
+ _carLocations[i] = -1;
+}
+
+void Scene505::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsSint16LE(_frame);
+ s.syncAsSint16LE(_nextButtonId);
+ s.syncAsSint16LE(_homeSelectedId);
+ s.syncAsSint16LE(_selectedId);
+ s.syncAsSint16LE(_activeCars);
+
+ for (int i = 0; i < 9; i++)
+ s.syncAsSint16LE(_carLocations[i]);
+}
+
+void Scene505::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+}
+
+void Scene505::enter() {
+ for (int i = 0; i < 9; i++)
+ _globals._spriteIndexes[i] = _scene->_sprites.addSprites(formAnimName('a', i + 1));
+
+ _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('g', 1));
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('g', 0));
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('t', -1));
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('e', -1));
+
+ if (_scene->_priorSceneId != -2)
+ _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 6, 1, 0, 0);
+
+ _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 120, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 60);
+ _scene->_sequences.addTimer(30, 62);
+
+ _carLocations[0] = 501;
+ _carLocations[1] = 506;
+ _carLocations[2] = 511;
+ _carLocations[3] = 513;
+ _carLocations[4] = 601;
+ _carLocations[5] = 604;
+ _carLocations[6] = 607;
+ _carLocations[7] = 609;
+ _carLocations[8] = 612;
+
+ _activeCars = false;
+
+ for (int i = 0; i < 9; i++) {
+ if (_globals[kHoverCarLocation] == _carLocations[i]) {
+ _homeSelectedId = i;
+ if (_scene->_priorSceneId != -2)
+ _selectedId = i;
+ }
+ }
+
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _frame = -1;
+ _scene->loadAnimation(formAnimName('a', -1));
+ _scene->_activeAnimation->setCurrentFrame(86);
+
+ sceneEntrySound();
+ _vm->_sound->command(16);
+}
+
+void Scene505::step() {
+ if (_frame != _scene->_activeAnimation->getCurrentFrame()) {
+ _frame = _scene->_activeAnimation->getCurrentFrame();
+ int resetFrame = -1;
+
+ switch (_frame) {
+ case 4:
+ case 24:
+ case 33:
+ case 53:
+ case 62:
+ case 82:
+ if (_nextButtonId == 0x38A)
+ resetFrame = 4;
+ else if (_nextButtonId == 0x38B)
+ resetFrame = 33;
+ else if (_nextButtonId == 0x2DE)
+ resetFrame = 62;
+
+ break;
+
+ case 15:
+ case 44:
+ case 73: {
+ int this_button;
+ int old_select;
+ _vm->_sound->command(17);
+ old_select = _selectedId;
+ if (_frame == 15) {
+ this_button = 0x38A;
+ _selectedId = (_selectedId + 1) % 9;
+ } else if (_frame == 44) {
+ this_button = 0x38B;
+ _selectedId--;
+ if (_selectedId < 0)
+ _selectedId = 8;
+ } else {
+ this_button = 0x2DE;
+ if ((_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) && (_carLocations[_selectedId] == 501))
+ _vm->_dialogs->show(431);
+ else if (_selectedId != _homeSelectedId) {
+ _nextButtonId = 0;
+ _activeCars = true;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[0]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 63);
+ _vm->_sound->command(18);
+ }
+ }
+
+ if (_nextButtonId == this_button)
+ _nextButtonId = 0;
+
+ if (old_select != _selectedId) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[11]);
+ _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, _selectedId + 1);
+ if (old_select != _homeSelectedId)
+ _scene->_sequences.remove(_globals._sequenceIndexes[0]);
+
+ if (_selectedId != _homeSelectedId) {
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0 + _selectedId], false, 24, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 1);
+ }
+ }
+ break;
+ }
+
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ if (_nextButtonId == 0x38A)
+ resetFrame = 29 - _frame;
+
+ break;
+
+ case 26:
+ case 55:
+ case 84:
+ if (_nextButtonId != 0)
+ resetFrame = 3;
+
+ break;
+
+ case 27:
+ case 56:
+ case 85:
+ if (_nextButtonId != 0)
+ resetFrame = 2;
+
+ break;
+
+ case 29:
+ case 58:
+ case 87:
+ if (_activeCars)
+ _globals[kHoverCarDestination] = _carLocations[_selectedId];
+
+ if (_nextButtonId == 0x38A)
+ resetFrame = 0;
+ else if (_nextButtonId == 0x38B)
+ resetFrame = 29;
+ else if (_nextButtonId == 0x2DE)
+ resetFrame = 58;
+ else
+ resetFrame = 86;
+ break;
+
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ if (_nextButtonId == 0x38B)
+ resetFrame = 87 - _frame;
+
+ break;
+
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ if (_nextButtonId == 0x2DE)
+ resetFrame = 145 - _frame;
+
+ break;
+
+ default:
+ break;
+ }
+
+ if ((resetFrame >= 0) && (resetFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(resetFrame);
+ _frame = resetFrame;
+ }
+ }
+
+ switch (_game._trigger) {
+ case 60: {
+ _game._player._stepEnabled = true;
+ int syncIdx = _globals._sequenceIndexes[13];
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], syncIdx);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[_homeSelectedId], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, _selectedId + 1);
+
+ if (_selectedId != _homeSelectedId) {
+ _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0 + _selectedId], false, 24, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 1);
+ }
+ break;
+ }
+
+ case 61:
+ _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 8, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], _globals._sequenceIndexes[9]);
+ break;
+
+ case 62:
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 8, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 61);
+ break;
+
+ case 63:
+ _globals[kHoverCarDestination] = _carLocations[_selectedId];
+ _scene->_nextSceneId = 504;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene505::actions() {
+ if (_action.isAction(VERB_PRESS))
+ _nextButtonId = _action._activeAction._objectNameId;
+ else if (_action.isAction(VERB_RETURN_TO, NOUN_INSIDE_OF_CAR))
+ _scene->_nextSceneId = 504;
+ else if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN))
+ _vm->_dialogs->show(50510);
+ else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL))
+ _vm->_dialogs->show(50511);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene506::Scene506(MADSEngine *vm) : Scene5xx(vm), _doorPos(0, 0) {
+ _heroFacing = FACING_DUMMY;
+
+ _doorDepth = -1;
+ _doorSpriteIdx = -1;
+ _doorSequenceIdx = -1;
+ _doorWord = -1;
+
+ _labDoorFl = false;
+ _firstDoorFl = false;
+ _actionFl = false;
+}
+
+void Scene506::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsSint16LE(_doorPos.x);
+ s.syncAsSint16LE(_doorPos.y);
+
+ s.syncAsByte(_heroFacing);
+
+ s.syncAsSint16LE(_doorDepth);
+ s.syncAsSint16LE(_doorSpriteIdx);
+ s.syncAsSint16LE(_doorSequenceIdx);
+ s.syncAsSint16LE(_doorWord);
+
+ s.syncAsByte(_labDoorFl);
+ s.syncAsByte(_firstDoorFl);
+ s.syncAsByte(_actionFl);
+}
+
+void Scene506::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_WALK_INTO);
+ _scene->addActiveVocab(NOUN_SOFTWARE_STORE);
+ _scene->addActiveVocab(NOUN_LABORATORY);
+}
+
+void Scene506::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('q', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('q', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_3");
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_LABORATORY, VERB_WALK_INTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(65, 125), FACING_NORTHWEST);
+ _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ idx = _scene->_dynamicHotspots.add(NOUN_SOFTWARE_STORE, VERB_WALK_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(112, 102), FACING_NORTHWEST);
+ _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13);
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5);
+ _firstDoorFl = true;
+ _actionFl = false;
+
+ if (_scene->_priorSceneId == 508) {
+ _game._player._playerPos = Common::Point(16, 111);
+ _game._player._facing = FACING_SOUTHEAST;
+ _scene->_sequences.addTimer(15, 80);
+ _game._player._stepEnabled = false;
+ } else if (_scene->_priorSceneId == 507) {
+ _game._player._playerPos = Common::Point(80, 102);
+ _game._player._facing = FACING_SOUTHEAST;
+ _scene->_sequences.addTimer(60, 80);
+ _game._player._stepEnabled = false;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(138, 116);
+ _game._player._facing = FACING_NORTHEAST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5);
+ _scene->loadAnimation(formAnimName('R', 1), 70);
+ }
+ sceneEntrySound();
+}
+
+void Scene506::step() {
+ if (_game._trigger >= 80) {
+ if (_firstDoorFl) {
+ _heroFacing = FACING_SOUTHEAST;
+ if (_scene->_priorSceneId == 507) {
+ _doorPos = Common::Point(112, 102);
+ _doorWord = 0x336;
+ } else {
+ _doorPos = Common::Point(65, 125);
+ _doorWord = 0x37D;
+ }
+ }
+ handleDoorSequences();
+ }
+
+ if (_game._trigger >= 70) {
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(6, 71);
+ break;
+
+ case 71:
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 72:
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene506::handleDoorSequences() {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+
+ if (_firstDoorFl) {
+ if (_action.isAction(VERB_WALK_INTO, NOUN_SOFTWARE_STORE) || ((_scene->_priorSceneId == 507) && !_actionFl)) {
+ _doorDepth = 13;
+ _doorSpriteIdx = _globals._spriteIndexes[2];
+ _doorSequenceIdx = _globals._sequenceIndexes[2];
+ _labDoorFl = false;
+ } else {
+ _doorDepth = 10;
+ _doorSpriteIdx = _globals._spriteIndexes[1];
+ _doorSequenceIdx = _globals._sequenceIndexes[1];
+ _labDoorFl = true;
+ }
+ _firstDoorFl = false;
+ }
+
+ switch (_game._trigger) {
+ case 0:
+ case 80:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_doorSequenceIdx);
+ _doorSequenceIdx = _scene->_sequences.addSpriteCycle(_doorSpriteIdx, false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth);
+ _scene->changeVariant(1);
+ _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 81);
+ break;
+
+
+ case 81:
+ _doorSequenceIdx = _scene->_sequences.startCycle(_doorSpriteIdx, false, -2);
+ _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth);
+ _game._player._walkAnywhere = true;
+ _game._player.walk(_doorPos, _heroFacing);
+ _scene->_sequences.addTimer(120, 82);
+ break;
+
+ case 82:
+ _scene->_sequences.remove(_doorSequenceIdx);
+ _doorSequenceIdx = _scene->_sequences.startReverseCycle(_doorSpriteIdx, false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth);
+ if (_actionFl)
+ _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 84);
+ else
+ _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 83);
+
+ break;
+
+ case 83: {
+ _doorSequenceIdx = _scene->_sequences.startCycle(_doorSpriteIdx, false, 1);
+ int idx = _scene->_dynamicHotspots.add(_doorWord, VERB_WALK_INTO, _doorSequenceIdx, Common::Rect(0, 0, 0, 0));
+ int hotspotId = _scene->_dynamicHotspots.setPosition(idx, _doorPos, FACING_NORTHWEST);
+ _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT);
+ _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth);
+ _firstDoorFl = true;
+ if (_labDoorFl) {
+ _globals._spriteIndexes[1] = _doorSpriteIdx;
+ _globals._sequenceIndexes[1] = _doorSequenceIdx;
+ } else {
+ _globals._spriteIndexes[2] = _doorSpriteIdx;
+ _globals._sequenceIndexes[2] = _doorSequenceIdx;
+ }
+ _game._player._stepEnabled = true;
+
+ }
+ break;
+
+ case 84:
+ _actionFl = false;
+ _game._player._stepEnabled = true;
+ if (_labDoorFl)
+ _scene->_nextSceneId = 508;
+ else
+ _scene->_nextSceneId = 507;
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene506::actions() {
+ if (_action.isAction(VERB_WALK_INTO, NOUN_LABORATORY)) {
+ if (_firstDoorFl) {
+ _heroFacing = FACING_NORTHWEST;
+ _doorPos = Common::Point(16, 111);
+ }
+ _actionFl = true;
+ handleDoorSequences();
+ } else if (_action.isAction(VERB_WALK_INTO, NOUN_SOFTWARE_STORE)) {
+ if (_firstDoorFl) {
+ _heroFacing = FACING_NORTHWEST;
+ _doorPos = Common::Point(80, 102);
+ }
+ _actionFl = true;
+ handleDoorSequences();
+ } else if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _scene->_sequences.addTimer(6, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_nextSceneId = 504;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET))
+ _vm->_dialogs->show(50618);
+ else if (_action.isAction(VERB_LOOK, NOUN_RESTAURANT))
+ _vm->_dialogs->show(50610);
+ else if (_action.isAction(VERB_LOOK, NOUN_MOTEL))
+ _vm->_dialogs->show(50611);
+ else if (_action.isAction(VERB_LOOK, NOUN_CYCLE_SHOP))
+ _vm->_dialogs->show(50612);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_BIKE))
+ _vm->_dialogs->show(50613);
+ else if (_action.isAction(VERB_TAKE, NOUN_AIR_BIKE))
+ _vm->_dialogs->show(50614);
+ else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_STORE))
+ _vm->_dialogs->show(50615);
+ else if (_action.isAction(VERB_LOOK, NOUN_LABORATORY))
+ _vm->_dialogs->show(50616);
+ else if (_action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST))
+ _vm->_dialogs->show(50617);
+ else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_STORE_SIGN))
+ _vm->_dialogs->show(50619);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAR))
+ _vm->_dialogs->show(50620);
+ else if (_action.isAction(VERB_LOOK, NOUN_SKY))
+ _vm->_dialogs->show(50621);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene507::Scene507(MADSEngine *vm) : Scene5xx(vm) {
+ _penlightHotspotId = -1;
+}
+
+void Scene507::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsSint16LE(_penlightHotspotId);
+}
+
+void Scene507::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_PENLIGHT);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene507::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('p', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRD_3");
+
+ if ((_game._difficulty != DIFFICULTY_EASY) && (_game._objects[OBJ_PENLIGHT]._roomNumber == _scene->_currentSceneId)) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0);
+ _penlightHotspotId = _scene->_dynamicHotspots.add(NOUN_PENLIGHT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_penlightHotspotId, Common::Point(233, 152), FACING_SOUTHEAST);
+ }
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(121, 147);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ sceneEntrySound();
+}
+void Scene507::actions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_ENTRANCE))
+ _scene->_nextSceneId = 506;
+ else if (_action.isAction(VERB_TAKE, NOUN_PENLIGHT)) {
+ if (_game._trigger || !_game._objects.isInInventory(OBJ_PENLIGHT)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_penlightHotspotId);
+ _vm->_sound->command(27);
+ _game._objects.addToInventory(OBJ_PENLIGHT);
+ _vm->_dialogs->showItem(OBJ_PENLIGHT, 50730);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(50722);
+ else if (_action.isAction(VERB_LOOK, NOUN_SWIRLING_LIGHT))
+ _vm->_dialogs->show(50710);
+ else if (_action.isAction(VERB_TAKE, NOUN_SWIRLING_LIGHT))
+ _vm->_dialogs->show(50711);
+ else if (_action.isAction(VERB_LOOK, NOUN_OLD_SOFTWARE))
+ _vm->_dialogs->show(50712);
+ else if (_action.isAction(VERB_TAKE, NOUN_OLD_SOFTWARE))
+ _vm->_dialogs->show(50713);
+ else if (_action.isAction(VERB_LOOK, NOUN_ADVERTISEMENT))
+ _vm->_dialogs->show(50714);
+ else if (_action.isAction(VERB_LOOK, NOUN_ADVERTISING_POSTER))
+ _vm->_dialogs->show(50715);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) {
+ if (_scene->_customDest.x < 100)
+ _vm->_dialogs->show(50726);
+ else
+ _vm->_dialogs->show(50716);
+ } else if (_action.isAction(VERB_LOOK, NOUN_HOTTEST_SOFTWARE))
+ _vm->_dialogs->show(50717);
+ else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_SHELF))
+ _vm->_dialogs->show(50718);
+ else if (_action.isAction(VERB_LOOK, NOUN_SENSOR))
+ _vm->_dialogs->show(50719);
+ else if (_action.isAction(VERB_LOOK, NOUN_CASH_REGISTER))
+ _vm->_dialogs->show(50720);
+ else if (_action.isAction(VERB_LOOK, NOUN_PAD_OF_PAPER))
+ _vm->_dialogs->show(50721);
+ else if (_action.isAction(VERB_OPEN, NOUN_CASH_REGISTER))
+ _vm->_dialogs->show(50723);
+ else if (_action.isAction(VERB_LOOK, NOUN_BARGAIN_VAT))
+ _vm->_dialogs->show(50724);
+ else if (_action.isAction(VERB_LOOK, NOUN_WINDOW))
+ _vm->_dialogs->show(50725);
+ else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) {
+ if (_game._objects.isInRoom(OBJ_PENLIGHT))
+ _vm->_dialogs->show(50728);
+ else
+ _vm->_dialogs->show(50727);
+ } else if (_action.isAction(VERB_LOOK, NOUN_PENLIGHT) && !_game._objects.isInInventory(OBJ_PENLIGHT)) {
+ if (_game._objects.isInRoom(OBJ_PENLIGHT))
+ _vm->_dialogs->show(50729);
+ } else if (_action.isAction(VERB_LOOK, NOUN_EMERGENCY_LIGHT))
+ _vm->_dialogs->show(50731);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene508::Scene508(MADSEngine *vm) : Scene5xx(vm) {
+ _chosenObject = -1;
+}
+
+void Scene508::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsSint16LE(_chosenObject);
+}
+
+void Scene508::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_SPINACH_PATCH_DOLL);
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_LASER_BEAM);
+}
+
+void Scene508::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('h', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('l', 2));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('t', 0));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXMRC_9");
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('l', 3));
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ _globals[kLaserOn] = false;
+ _chosenObject = 0;
+ }
+
+ if (!_globals[kLaserOn]) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2);
+ int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST);
+ _scene->_hotspots.activate(NOUN_HOLE, false);
+ _scene->_hotspots.activate(NOUN_LASER_BEAM, false);
+ } else {
+ _scene->changeVariant(1);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11);
+ int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6);
+ if (_globals[kLaserHoleIsThere]) {
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2);
+ _scene->_hotspots.activate(NOUN_HOLE, true);
+ _scene->_hotspots.activate(NOUN_LASER_BEAM, true);
+ }
+ _vm->_sound->command(21);
+ }
+ _vm->_sound->command(20);
+
+ if (_scene->_priorSceneId == 515) {
+ _game._player._playerPos = Common::Point(57, 116);
+ _game._player._facing = FACING_NORTHEAST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(289, 139);
+ _game._player._facing = FACING_WEST;
+ }
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0x273, 0);
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_COMPACT_CASE);
+ _game._objects.addToInventory(OBJ_REARVIEW_MIRROR);
+ }
+}
+
+void Scene508::preActions() {
+ if (_action.isAction(VERB_WALK, NOUN_OUTSIDE))
+ _game._player._walkOffScreenSceneId = 506;
+}
+
+void Scene508::handlePedestral() {
+ if (!_globals[kLaserOn])
+ _vm->_dialogs->show(50835);
+
+ if (_globals[kLaserHoleIsThere])
+ _vm->_dialogs->show(50836);
+
+ if (_globals[kLaserOn] && !_globals[kLaserHoleIsThere]) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 1:
+ if (_chosenObject == 2)
+ _game._objects.removeFromInventory(OBJ_COMPACT_CASE, 1);
+ else
+ _game._objects.removeFromInventory(OBJ_REARVIEW_MIRROR, 1);
+
+ _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2:
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2);
+ _scene->_hotspots.activate(NOUN_HOLE, true);
+ _scene->_hotspots.activate(NOUN_LASER_BEAM, true);
+ break;
+
+ case 3:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]);
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(120, 4);
+ break;
+
+ case 4:
+ _vm->_dialogs->show(50834);
+ _globals[kLaserHoleIsThere] = true;
+ _scene->_nextSceneId = 515;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene508::actions() {
+ if (_action.isAction(VERB_PULL, NOUN_LEVER)) {
+ if (!_globals[kLaserOn]) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 2, 120, _game.getQuote(0x273));
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 7);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], -1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3:
+ _vm->_sound->command(19);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[1]);
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(15, 5);
+ break;
+
+ case 4:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6);
+ break;
+
+ case 5:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _scene->loadAnimation(formAnimName('B', 1), 6);
+ break;
+
+ case 6: {
+ _vm->_sound->command(22);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11);
+ int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST);
+ _scene->_kernelMessages.reset();
+ _scene->changeVariant(1);
+ _scene->_sequences.addTimer(30, 7);
+ }
+ break;
+
+ case 7:
+ _globals[kLaserOn] = true;
+ _vm->_dialogs->show(50833);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ _vm->_dialogs->show(50837);
+ }
+ } else if (_action.isAction(VERB_REFLECT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM) || _action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_PEDESTAL) || _action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM)) {
+ _chosenObject = 1;
+ handlePedestral();
+ } else if (_action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_PEDESTAL) || _action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM) || _action.isAction(VERB_REFLECT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM)) {
+ _chosenObject = 2;
+ handlePedestral();
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(50822);
+ else if (_action.isAction(VERB_LOOK, NOUN_TARGET_AREA))
+ _vm->_dialogs->show(50810);
+ else if (_action.isAction(VERB_LOOK, NOUN_SPINACH_PATCH_DOLL))
+ _vm->_dialogs->show(50811);
+ else if (_action.isAction(VERB_TAKE, NOUN_SPINACH_PATCH_DOLL))
+ _vm->_dialogs->show(50812);
+ else if (_action.isAction(VERB_LOOK, NOUN_SAND_BAGS))
+ _vm->_dialogs->show(50816);
+ else if (_action.isAction(VERB_TAKE, NOUN_SAND_BAGS))
+ _vm->_dialogs->show(50817);
+ else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_STATION))
+ _vm->_dialogs->show(50818);
+ else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) {
+ if (_globals[kLaserOn])
+ _vm->_dialogs->show(50820);
+ else
+ _vm->_dialogs->show(50819);
+ } else if (_action.isAction(VERB_LOOK, NOUN_LASER_CANNON)) {
+ if (_globals[kLaserOn])
+ _vm->_dialogs->show(50822);
+ else
+ _vm->_dialogs->show(50821);
+ } else if (_action.isAction(VERB_TAKE, NOUN_LASER_CANNON))
+ _vm->_dialogs->show(50823);
+ else if (_action.isAction(VERB_LOOK, NOUN_LEVER)) {
+ if (_globals[kLaserOn])
+ _vm->_dialogs->show(50825);
+ else
+ _vm->_dialogs->show(50824);
+ } else if (_action.isAction(VERB_PUSH, NOUN_LEVER))
+ _vm->_dialogs->show(50826);
+ else if (_action.isAction(VERB_LOOK, NOUN_LASER_BEAM)) {
+ if (_globals[kLaserHoleIsThere])
+ _vm->_dialogs->show(50828);
+ else
+ _vm->_dialogs->show(50827);
+ } else if (_action.isAction(VERB_TAKE, NOUN_LASER_BEAM))
+ _vm->_dialogs->show(50829);
+ else if (_action.isAction(VERB_LOOK, NOUN_CEILING)) {
+ if (_globals[kLaserHoleIsThere])
+ _vm->_dialogs->show(50831);
+ else
+ _vm->_dialogs->show(50830);
+ } else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(50832);
+ else if (_action.isAction(VERB_LOOK, NOUN_PEDESTAL)) {
+ if (!_globals[kLaserOn])
+ _vm->_dialogs->show(50813);
+ else if (!_globals[kLaserHoleIsThere])
+ _vm->_dialogs->show(50814);
+ else
+ _vm->_dialogs->show(50815);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene511::Scene511(MADSEngine *vm) : Scene5xx(vm) {
+ _handingLine = false;
+ _lineMoving = false;
+
+ _lineAnimationMode = -1;
+ _lineFrame = -1;
+ _lineAnimationPosition = -1;
+}
+
+void Scene511::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsByte(_handingLine);
+ s.syncAsByte(_lineMoving);
+
+ s.syncAsSint16LE(_lineAnimationMode);
+ s.syncAsSint16LE(_lineFrame);
+ s.syncAsSint16LE(_lineAnimationPosition);
+}
+
+void Scene511::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_BOAT);
+ _scene->addActiveVocab(NOUN_FISHING_LINE);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene511::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_6");
+
+ if (_scene->_priorSceneId != -2)
+ _handingLine = false;
+
+ if (_globals[kBoatRaised]) {
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3);
+ _scene->_hotspots.activate(NOUN_BOAT, false);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(75, 124), FACING_NORTH);
+ _scene->_hotspots.activate(NOUN_ROPE, false);
+ } else {
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', 2));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 3));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 1));
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 1, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5);
+
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4);
+
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6],5);
+
+ _scene->_hotspots.activate(NOUN_ROPE, true);
+ _scene->_hotspots.activate(NOUN_BOAT, true);
+ _scene->changeVariant(1);
+ }
+
+ int frame = 0;
+ if (_globals[kLineStatus] == 2)
+ frame = -1;
+ else if (_globals[kLineStatus] == 3)
+ frame = -2;
+
+ if (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3) {
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('b', 4));
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, frame);
+ int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(26, 153), FACING_NORTHEAST);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 3);
+ if (_globals[kBoatRaised])
+ _scene->changeVariant(2);
+ }
+
+ _lineFrame = -1;
+ _lineMoving = false;
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ if (_scene->_priorSceneId == 512) {
+ _game._player._playerPos = Common::Point(60, 112);
+ _game._player._facing = FACING_SOUTHEAST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(55, 152);
+ _game._player._facing = FACING_NORTHWEST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->loadAnimation(formAnimName('R', 1), 70);
+ } else if (_handingLine) {
+ _game._player._visible = false;
+ _lineAnimationMode = 1;
+ _lineAnimationPosition = 1;
+ _scene->loadAnimation(formAnimName('R', -1));
+ _lineFrame = 2;
+ }
+ sceneEntrySound();
+}
+
+void Scene511::step() {
+ if ((_lineAnimationMode == 1) && _scene->_activeAnimation) {
+ if (_lineFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _lineFrame = _scene->_activeAnimation->getCurrentFrame();
+ int resetFrame = -1;
+
+ if ((_lineAnimationPosition == 2) && (_lineFrame == 14))
+ _lineMoving = false;
+
+ if (_lineAnimationPosition == 1) {
+ if (_lineFrame == 3) {
+ _lineMoving = false;
+ resetFrame = 2;
+ }
+
+ if (_handingLine)
+ resetFrame = 2;
+ }
+
+ if ((resetFrame >= 0) && (resetFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(resetFrame);
+ _lineFrame = resetFrame;
+ }
+ }
+ }
+
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(6, 71);
+ break;
+
+ case 71:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 72:
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene511::preActions() {
+ if (!_handingLine)
+ return;
+
+ if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_FISHING_LINE) || _action.isAction(VERB_TALKTO))
+ _game._player._needToWalk = false;
+
+ if ((!_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_BOAT) || !_action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_BOAT)) && _game._player._needToWalk) {
+ if (_game._trigger == 0) {
+ _game._player._readyToWalk = false;
+ _game._player._stepEnabled = false;
+ _scene->freeAnimation ();
+ _lineAnimationMode = 2;
+ _scene->loadAnimation(formAnimName('R',2), 1);
+ } else if (_game._trigger == 1) {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _game._objects.setRoom(OBJ_FISHING_LINE, 1);
+ _handingLine = false;
+ _game._player._stepEnabled = true;
+ _game._player._readyToWalk = true;
+ }
+ }
+}
+
+void Scene511::actions() {
+ if (_action.isAction(VERB_WALK_INTO, NOUN_RESTAURANT))
+ _scene->_nextSceneId = 512;
+ else if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx);
+ _scene->_sequences.addTimer(6, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_nextSceneId = 504;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_FISHING_LINE)) {
+ if (!_globals[kBoatRaised]) {
+ if (_globals[kLineStatus] == 2) {
+ if (_globals[kLineStatus] != 3) {
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _lineAnimationMode = 1;
+ _lineAnimationPosition = 1;
+ _lineMoving = true;
+ _scene->loadAnimation(formAnimName('R', -1));
+ _scene->_sequences.addTimer(1, 1);
+ } else if (_game._trigger == 1) {
+ if (_lineMoving) {
+ _scene->_sequences.addTimer(1, 1);
+ } else {
+ _game._objects.addToInventory(OBJ_FISHING_LINE);
+ _lineMoving = true;
+ _handingLine = true;
+ _game._player._stepEnabled = true;
+ }
+ }
+ } else
+ _vm->_dialogs->show(51129);
+ } else
+ return;
+ } else {
+ _vm->_dialogs->show(51130);
+ }
+ } else if (_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_BOAT) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_BOAT)) {
+ if (_globals[kBoatRaised])
+ _vm->_dialogs->show(51131);
+ else if (_globals[kLineStatus] == 1)
+ _vm->_dialogs->show(51130);
+ else if (!_globals[kBoatRaised] && _handingLine) {
+ if (_globals[kLineStatus] != 3) {
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[7]);
+ _lineMoving = true;
+ _lineAnimationPosition = 2;
+ _scene->_sequences.addTimer(1, 1);
+ } else if (_game._trigger == 1) {
+ if (_lineMoving)
+ _scene->_sequences.addTimer(1, 1);
+ else {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 4);
+ int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(26, 153), FACING_NORTHEAST);
+ _game._objects.removeFromInventory(OBJ_FISHING_LINE, 1);
+ _handingLine = false;
+ _lineMoving = true;
+ _globals[kLineStatus] = 3;
+ _game._player._stepEnabled = true;
+ }
+ }
+ }
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_STREET) || _action._lookFlag) {
+ if (_globals[kLineStatus] == 2)
+ _vm->_dialogs->show(51110);
+ else {
+ if (_globals[kLineStatus] == 3)
+ _vm->_dialogs->show(51111);
+ else
+ _vm->_dialogs->show(51112);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_CAR))
+ _vm->_dialogs->show(51113);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK))
+ _vm->_dialogs->show(51114);
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_EAST) || _action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_EAST))
+ _vm->_dialogs->show(51115);
+ else if (_action.isAction(VERB_LOOK, NOUN_PLEASURE_DOME))
+ _vm->_dialogs->show(51116);
+ else if (_action.isAction(VERB_LOOK, NOUN_TICKET_BOOTH))
+ _vm->_dialogs->show(51117);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOME_ENTRANCE))
+ _vm->_dialogs->show(51118);
+ else if (_action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_DOME_ENTRANCE) || _action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_DOME_ENTRANCE))
+ _vm->_dialogs->show(51119);
+ else if ( (_action.isAction(VERB_PUT) || _action.isAction(VERB_THROW))
+ && (_action.isObject(NOUN_TIMEBOMB) || _action.isObject(NOUN_BOMB) || _action.isObject(NOUN_BOMBS))
+ && _action.isObject(NOUN_DOME_ENTRANCE))
+ _vm->_dialogs->show(51120);
+ else if (_action.isAction(VERB_LOOK, NOUN_RESTAURANT)) {
+ if (_globals[kBoatRaised])
+ _vm->_dialogs->show(51121);
+ else
+ _vm->_dialogs->show(51128);
+ } else if (_action.isAction(VERB_LOOK, NOUN_PORTHOLE))
+ _vm->_dialogs->show(51122);
+ else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_action._mainObjectSource == 4) && (_globals[kLineStatus] == 2))
+ _vm->_dialogs->show(51126);
+ else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_action._mainObjectSource == 4) && (_globals[kLineStatus] == 3))
+ _vm->_dialogs->show(51133);
+ else if (_action.isAction(VERB_LOOK, NOUN_STATUE))
+ _vm->_dialogs->show(51127);
+ else if (_action.isAction(VERB_LOOK, NOUN_BOAT))
+ if (_globals[kBoatRaised])
+ _vm->_dialogs->show(51123);
+ else if (_globals[kLineStatus] != 3)
+ _vm->_dialogs->show(51124);
+ else
+ _vm->_dialogs->show(51125);
+ else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_globals[kLineStatus] == 3))
+ _vm->_dialogs->show(51125);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene512::Scene512(MADSEngine *vm) : Scene5xx(vm) {
+ _fishingRodHotspotId = -1;
+ _keyHotspotId = -1;
+}
+
+void Scene512::synchronize(Common::Serializer &s) {
+ Scene5xx::synchronize(s);
+
+ s.syncAsSint16LE(_fishingRodHotspotId);
+ s.syncAsSint16LE(_keyHotspotId);
+}
+
+void Scene512::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_FISHING_ROD);
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_PADLOCK_KEY);
+ _scene->addActiveVocab(NOUN_REGISTER_DRAWER);
+}
+
+void Scene512::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('r', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9");
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites("*RXMRC_8");
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 3));
+
+ if (_game._objects[OBJ_FISHING_ROD]._roomNumber == _scene->_currentSceneId) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0);
+ _fishingRodHotspotId = _scene->_dynamicHotspots.add(NOUN_FISHING_ROD, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_fishingRodHotspotId, Common::Point(199, 101), FACING_NORTHEAST);
+ }
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _globals[kRegisterOpen] = false;
+
+ _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false);
+ if (_game._difficulty == DIFFICULTY_EASY) {
+ if (_game._objects[OBJ_PADLOCK_KEY]._roomNumber == _scene->_currentSceneId) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 3);
+ _keyHotspotId = _scene->_dynamicHotspots.add(NOUN_PADLOCK_KEY, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_keyHotspotId, Common::Point(218, 152), FACING_NORTHEAST);
+ }
+ if (_globals[kRegisterOpen]) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false);
+ }
+ } else if (_globals[kRegisterOpen]) {
+ if (_game._objects[OBJ_PADLOCK_KEY]._roomNumber == _scene->_currentSceneId) {
+ _scene->_hotspots.activate(NOUN_PADLOCK_KEY, true);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 3);
+ } else {
+ _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ }
+ } else
+ _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false);
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(144, 152);
+ _game._player._facing = FACING_NORTHEAST;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene512::actions() {
+ if (_action.isAction(VERB_WALK, NOUN_OUTSIDE))
+ _scene->_nextSceneId = 511;
+ else if (_action.isAction(VERB_TAKE, NOUN_FISHING_ROD)) {
+ if (_game._trigger || !_game._objects.isInInventory(OBJ_FISHING_ROD)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _vm->_sound->command(9);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_fishingRodHotspotId);
+ _game._objects.addToInventory(OBJ_FISHING_ROD);
+ _vm->_dialogs->showItem(OBJ_FISHING_ROD, 51217);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action.isAction(VERB_OPEN, NOUN_CASH_REGISTER)) {
+ if (!_globals[kRegisterOpen]) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_dialogs->show(51236);
+ _game._player._stepEnabled = false;
+ _game._player._facing = FACING_NORTH;
+ _scene->_sequences.addTimer(15, 1);
+ break;
+
+ case 1:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 9, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[8]);
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(30, 3);
+ break;
+
+ case 3:
+ _game._player._facing = FACING_NORTHEAST;
+ if (!_game._objects.isInRoom(OBJ_PADLOCK_KEY) || (_game._difficulty == DIFFICULTY_EASY)) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ } else {
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5);
+ }
+ _vm->_sound->command(23);
+ break;
+
+ case 4:
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addTimer(60, 6);
+ break;
+
+ case 5:
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 14, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 3);
+ _scene->_hotspots.activate(NOUN_PADLOCK_KEY, true);
+ _scene->_sequences.addTimer(60, 6);
+ break;
+
+ case 6:
+ _globals[kRegisterOpen] = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else
+ _vm->_dialogs->show(51239);
+ } else if (_action.isAction(VERB_CLOSE, NOUN_CASH_REGISTER) && _globals[kRegisterOpen]) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ if (!_game._objects.isInRoom(OBJ_PADLOCK_KEY) || _game._difficulty == DIFFICULTY_EASY) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 3);
+ _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 2:
+ _globals[kRegisterOpen] = false;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_PADLOCK_KEY)) {
+ if (_game._trigger || !_game._objects.isInInventory(OBJ_PADLOCK_KEY)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+
+ int endVal;
+ if (_game._player._playerPos == Common::Point(218, 152))
+ endVal = 3;
+ else
+ endVal = 2;
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, endVal);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, endVal, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ if (_game._player._playerPos == Common::Point(218, 152)) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _scene->_dynamicHotspots.remove(_keyHotspotId);
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3);
+ _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false);
+ }
+ _vm->_sound->command(9);
+ _game._objects.addToInventory(OBJ_PADLOCK_KEY);
+ _vm->_dialogs->showItem(OBJ_PADLOCK_KEY, 51226);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(51225);
+ else if (_action.isAction(VERB_LOOK, NOUN_PADLOCK_KEY) && _game._objects.isInRoom(OBJ_PADLOCK_KEY))
+ _vm->_dialogs->show(51215);
+ else if (_action.isAction(VERB_LOOK, NOUN_FISHING_ROD) && (_scene->_activeAnimation->getCurrentFrame() == 4))
+ _vm->_dialogs->show(51216);
+ else if (_action.isAction(VERB_LOOK, NOUN_SHIPS_WHEEL))
+ _vm->_dialogs->show(51218);
+ else if (_action.isAction(VERB_TAKE, NOUN_SHIPS_WHEEL))
+ _vm->_dialogs->show(51219);
+ else if (_action.isAction(VERB_LOOK, NOUN_PORTHOLE) || _action.isAction(VERB_PEER_THROUGH, NOUN_PORTHOLE))
+ _vm->_dialogs->show(51220);
+ else if (_action.isAction(VERB_LOOK, NOUN_TABLE))
+ _vm->_dialogs->show(51221);
+ else if (_action.isAction(VERB_LOOK, NOUN_STARFISH))
+ _vm->_dialogs->show(51222);
+ else if (_action.isAction(VERB_TAKE, NOUN_STARFISH))
+ _vm->_dialogs->show(51223);
+ else if (_action.isAction(VERB_LOOK, NOUN_OUTSIDE))
+ _vm->_dialogs->show(51224);
+ else if (_action.isAction(VERB_LOOK, NOUN_POSTER))
+ _vm->_dialogs->show(51227);
+ else if (_action.isAction(VERB_TAKE, NOUN_POSTER))
+ _vm->_dialogs->show(51228);
+ else if (_action.isAction(VERB_LOOK, NOUN_TROPHY)) {
+ if (_game._visitedScenes.exists(604))
+ _vm->_dialogs->show(51229);
+ else
+ _vm->_dialogs->show(51230);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CHAIR))
+ _vm->_dialogs->show(51231);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROPE))
+ _vm->_dialogs->show(51232);
+ else if (_action.isAction(VERB_TAKE, NOUN_ROPE))
+ _vm->_dialogs->show(51233);
+ else if (_action.isAction(VERB_LOOK, NOUN_LAMP))
+ _vm->_dialogs->show(51234);
+ else if (_action.isAction(VERB_LOOK, NOUN_COUNTER))
+ _vm->_dialogs->show(51235);
+ else if (_action.isAction(VERB_LOOK, NOUN_ICE_CHESTS))
+ _vm->_dialogs->show(51237);
+ else if (_action.isAction(VERB_OPEN, NOUN_ICE_CHESTS))
+ _vm->_dialogs->show(51238);
+ else if (_action.isAction(VERB_LOOK, NOUN_CASH_REGISTER)) {
+ if (!_globals[kRegisterOpen])
+ _vm->_dialogs->show(51212);
+ else if (_game._objects.isInRoom(OBJ_PADLOCK_KEY))
+ _vm->_dialogs->show(51214);
+ else
+ _vm->_dialogs->show(51213);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene513::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_ELEVATOR_DOOR);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene513::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_9");
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRC_9");
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+
+ if ((_scene->_priorSceneId == 751) || (_scene->_priorSceneId == 701)) {
+ _game._player._playerPos = Common::Point(296, 147);
+ _game._player._facing = FACING_WEST;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.addTimer(15, 80);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(63, 149);
+ _game._player._facing = FACING_NORTHEAST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->loadAnimation(formAnimName('R', 1), 70);
+ }
+
+ sceneEntrySound();
+
+ if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_SECURITY_CARD);
+
+ _game.loadQuoteSet(0x278, 0);
+}
+
+void Scene513::step() {
+ switch (_game._trigger) {
+ case 80:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _vm->_sound->command(24);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81);
+ break;
+
+ case 81:
+ _game._player.walk(Common::Point(265, 152), FACING_WEST);
+ _scene->_sequences.addTimer(120, 82);
+ break;
+
+ case 82:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _vm->_sound->command(25);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 83);
+ break;
+
+ case 83:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(6, 71);
+ break;
+
+ case 71:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 72:
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene513::actions() {
+ if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx);
+ _scene->_sequences.addTimer(6, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _scene->_nextSceneId = 504;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PUT, NOUN_ID_CARD, NOUN_CARD_SLOT) || _action.isAction(VERB_PUT, NOUN_FAKE_ID, NOUN_CARD_SLOT)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]);
+ _game._player._visible = true;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _vm->_sound->command(24);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x278));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 2:
+ _game._player.walk(Common::Point(296, 147), FACING_WEST);
+ _scene->_sequences.addTimer(120, 3);
+ break;
+
+ case 3:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _vm->_sound->command(25);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ break;
+
+ case 4:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _game._player._stepEnabled = true;
+ if (_globals[kCityFlooded])
+ _scene->_nextSceneId = 701;
+ else
+ _scene->_nextSceneId = 751;
+
+ break;
+
+ default:
+ break;
+ }
+ } else if ((_action._lookFlag) || _action.isAction(VERB_LOOK, NOUN_STREET))
+ _vm->_dialogs->show(51318);
+ else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR))
+ _vm->_dialogs->show(51310);
+ else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR_DOOR))
+ _vm->_dialogs->show(51311);
+ else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT))
+ _vm->_dialogs->show(51312);
+ else if (_action.isAction(VERB_LOOK, NOUN_HANDICAP_SIGN))
+ _vm->_dialogs->show(51313);
+ else if (_action.isAction(VERB_LOOK, NOUN_BIKE_RACK))
+ _vm->_dialogs->show(51314);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
+ _vm->_dialogs->show(51315);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGN))
+ _vm->_dialogs->show(51316);
+ else if (_action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST))
+ _vm->_dialogs->show(51317);
+ else if (_action.isAction(VERB_OPEN, NOUN_ELEVATOR_DOOR) || _action.isAction(VERB_OPEN, NOUN_ELEVATOR))
+ _vm->_dialogs->show(51319);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAR))
+ _vm->_dialogs->show(51321);
+ else if (_action.isAction(VERB_LOOK, NOUN_BRICK_WALL))
+ _vm->_dialogs->show(51322);
+ else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT))
+ _vm->_dialogs->show(51320);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene515::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+}
+
+void Scene515::enter() {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.addTimer(30, 70);
+
+ sceneEntrySound();
+}
+
+void Scene515::step() {
+ if (_game._trigger == 70)
+ _scene->loadAnimation(formAnimName('A', -1), 71);
+ else if (_game._trigger == 71)
+ _scene->_nextSceneId = 508;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene551::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene551::enter() {
+ if (_globals[kSexOfRex] == REX_MALE)
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ else
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1));
+
+ if (_scene->_priorSceneId == 501)
+ _game._player._playerPos = Common::Point(18, 130);
+ else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(124, 119);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ if (_globals[kTeleporterCommand]) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+
+ char sepChar;
+ if (_globals[kSexOfRex] == REX_MALE)
+ sepChar = 'e';
+ else
+ sepChar = 'u';
+
+ int suffixNum;
+ int trigger;
+
+ switch (_globals[kTeleporterCommand]) {
+ case 1:
+ suffixNum = 3;
+ trigger = 75;
+ _globals[kTeleporterUnderstood] = true;
+ break;
+
+ case 2:
+ suffixNum = 1;
+ trigger = 80;
+ break;
+
+ case 4:
+ suffixNum = 2;
+ trigger = 90;
+ break;
+
+ default:
+ trigger = 0;
+ suffixNum = 0;
+ }
+
+ _globals[kTeleporterCommand] = 0;
+
+ if (suffixNum > 0)
+ _scene->loadAnimation(formAnimName(sepChar, suffixNum), trigger);
+ else {
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ }
+ }
+
+ sceneEntrySound();
+}
+
+void Scene551::step() {
+ switch (_game._trigger) {
+ case 75:
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ break;
+
+ case 80:
+ _globals[kTeleporterCommand] = 1;
+ _scene->_nextSceneId = _globals[kTeleporterDestination];
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ case 90:
+ if (_globals[kSexOfRex] == REX_MALE) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8);
+ } else {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
+ }
+ _vm->_sound->command(28);
+ _scene->_sequences.addTimer(60, 91);
+ break;
+
+ case 91:
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene551::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN) && (_action.isObject(NOUN_STREET_TO_WEST) || _action.isObject(NOUN_SIDEWALK_TO_WEST)))
+ _game._player._walkOffScreenSceneId = 501;
+}
+
+void Scene551::actions() {
+ if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER))
+ _scene->_nextSceneId = 502;
+ else if ((_action._lookFlag))
+ _vm->_dialogs->show(55117);
+ else if (_action.isAction(VERB_LOOK, NOUN_SKELETON))
+ _vm->_dialogs->show(55110);
+ else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR_SHAFT))
+ _vm->_dialogs->show(55111);
+ else if (_action.isAction(VERB_WALKTO, NOUN_ELEVATOR_SHAFT))
+ _vm->_dialogs->show(55112);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
+ _vm->_dialogs->show(55113);
+ else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER))
+ _vm->_dialogs->show(55114);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_WEST)) {
+ if (_game._visitedScenes.exists(505))
+ _vm->_dialogs->show(55116);
+ else
+ _vm->_dialogs->show(55115);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK))
+ _vm->_dialogs->show(55118);
+ else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT_OVERHEAD))
+ _vm->_dialogs->show(55119);
+ else if (_action.isAction(VERB_LOOK, NOUN_RAILING))
+ _vm->_dialogs->show(55120);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Nebular
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes5.h b/engines/mads/nebular/nebular_scenes5.h
new file mode 100644
index 0000000000..2face26508
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes5.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_NEBULAR_SCENES5_H
+#define MADS_NEBULAR_SCENES5_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+class Scene5xx : public NebularScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void setAAName();
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix();
+
+ void sceneEntrySound();
+
+public:
+ Scene5xx(MADSEngine *vm) : NebularScene(vm) {}
+};
+
+class Scene501 : public Scene5xx{
+private:
+ int _mainSequenceId;
+ int _mainSpriteId;
+ int _doorHotspotid;
+ bool _rexPunched;
+
+ void handleSlotActions();
+
+public:
+ Scene501(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene502 : public SceneTeleporter {
+public:
+ Scene502(MADSEngine *vm) : SceneTeleporter(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene503 : public Scene5xx{
+private:
+ int _detonatorHotspotId;
+
+public:
+ Scene503(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene504 : public Scene5xx{
+private:
+ int _carAnimationMode;
+ int _carFrame;
+
+public:
+ Scene504(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene505 : public Scene5xx{
+private:
+ int _frame;
+ int _nextButtonId;
+ int _homeSelectedId;
+ int _selectedId;
+ int _activeCars;
+
+ int _carLocations[9];
+
+public:
+ Scene505(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene506 : public Scene5xx{
+private:
+ Common::Point _doorPos;
+ Facing _heroFacing;
+
+ int _doorDepth;
+ int _doorSpriteIdx;
+ int _doorSequenceIdx;
+ int _doorWord;
+
+ bool _labDoorFl;
+ bool _firstDoorFl;
+ bool _actionFl;
+
+ void handleDoorSequences();
+
+public:
+ Scene506(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene507 : public Scene5xx{
+private:
+ int _penlightHotspotId;
+
+public:
+ Scene507(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene508 : public Scene5xx{
+private:
+ int _chosenObject;
+
+ void handlePedestral();
+
+public:
+ Scene508(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene511 : public Scene5xx{
+private:
+ bool _handingLine;
+ bool _lineMoving;
+
+ int _lineAnimationMode;
+ int _lineFrame;
+ int _lineAnimationPosition;
+
+public:
+ Scene511(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene512 : public Scene5xx{
+private:
+ int _fishingRodHotspotId;
+ int _keyHotspotId;
+
+public:
+ Scene512(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene513 : public Scene5xx{
+public:
+ Scene513(MADSEngine *vm) : Scene5xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene515 : public Scene5xx{
+public:
+ Scene515(MADSEngine *vm) : Scene5xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions() {};
+};
+
+class Scene551 : public Scene5xx{
+public:
+ Scene551(MADSEngine *vm) : Scene5xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+} // End of namespace Nebular
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES5_H */
diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp
new file mode 100644
index 0000000000..13ee1a3dc1
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes6.cpp
@@ -0,0 +1,4741 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes6.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+void Scene6xx::setAAName() {
+ _game._aaName = Resources::formatAAName(5);
+}
+
+void Scene6xx::setPlayerSpritesPrefix() {
+ _vm->_sound->command(5);
+ Common::String oldName = _game._player._spritesPrefix;
+
+ if ((_scene->_nextSceneId == 605) || (_scene->_nextSceneId == 620))
+ _game._player._spritesPrefix = "";
+ else if (_globals[kSexOfRex] == REX_MALE)
+ _game._player._spritesPrefix = "RXM";
+ else
+ _game._player._spritesPrefix = "ROX";
+
+ if (oldName != _game._player._spritesPrefix)
+ _game._player._spritesChanged = true;
+
+ _game._player._scalingVelocity = true;
+ _vm->_palette->setEntry(16, 10, 63, 63);
+ _vm->_palette->setEntry(17, 10, 45, 45);
+}
+
+void Scene6xx::sceneEntrySound() {
+ if (!_vm->_musicFlag) {
+ _vm->_sound->command(2);
+ return;
+ }
+
+ switch (_scene->_nextSceneId) {
+ case 601:
+ case 602:
+ case 603:
+ case 604:
+ case 605:
+ case 607:
+ case 608:
+ case 609:
+ case 610:
+ case 612:
+ case 620:
+ _vm->_sound->command(29);
+ break;
+ case 611:
+ _vm->_sound->command(24);
+ break;
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene601::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_LASER_BEAM);
+ _scene->addActiveVocab(VERB_LOOK_AT);
+}
+
+void Scene601::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_4");
+
+ if (_globals[kLaserHoleIsThere]) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_LOOK_AT, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ }
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3);
+
+ if (_scene->_priorSceneId == 504) {
+ _game._player._playerPos = Common::Point(73, 148);
+ _game._player._facing = FACING_WEST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3);
+ _scene->loadAnimation(formAnimName('R', 1), 70);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(229, 129);
+ _game._player._facing = FACING_SOUTHWEST;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene601::step() {
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(30, 71);
+ break;
+
+ case 71:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 72:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene601::actions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_ENTRANCE))
+ _scene->_nextSceneId = 602;
+ else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx);
+ _scene->_sequences.addTimer(6, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _scene->_nextSceneId = 504;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) {
+ if (!_globals[kLaserHoleIsThere])
+ _vm->_dialogs->show(60110);
+ else
+ _vm->_dialogs->show(60111);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CAR))
+ _vm->_dialogs->show(60112);
+ else if (_action.isAction(VERB_LOOK, NOUN_PAPERS))
+ _vm->_dialogs->show(60113);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
+ _vm->_dialogs->show(60114);
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET))
+ _vm->_dialogs->show(60115);
+ else if (_action.isAction(VERB_LOOK, NOUN_BALCONY))
+ _vm->_dialogs->show(60116);
+ else if (_action.isAction(VERB_LOOK, NOUN_ENTRANCE))
+ _vm->_dialogs->show(60117);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(60118);
+ else if (_action.isAction(VERB_LOOK, NOUN_CITY))
+ _vm->_dialogs->show(60119);
+ else if (_action.isAction(VERB_LOOK, NOUN_FOUNTAIN))
+ _vm->_dialogs->show(60120);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene602::Scene602(MADSEngine *vm) : Scene6xx(vm) {
+ _lastSpriteIdx = -1;
+ _lastSequenceIdx = -1;
+ _cycleIndex = -1;
+ _safeMode = -1;
+}
+
+void Scene602::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsSint16LE(_lastSpriteIdx);
+ s.syncAsSint16LE(_lastSequenceIdx);
+ s.syncAsSint16LE(_cycleIndex);
+ s.syncAsSint16LE(_safeMode);
+}
+
+void Scene602::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_SAFE);
+ _scene->addActiveVocab(NOUN_LASER_BEAM);
+}
+
+void Scene602::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('l', 0));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9");
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _globals[kSafeStatus] = 0;
+
+ if (_globals[kLaserHoleIsThere]) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 9);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 9);
+ int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(80, 134), FACING_NORTHEAST);
+ _scene->changeVariant(1);
+ } else
+ _scene->_hotspots.activate(NOUN_HOLE, false);
+
+ if (_globals[kSafeStatus] == 0) {
+ _lastSpriteIdx = _globals._spriteIndexes[2];
+ _cycleIndex = -1;
+ } else if (_globals[kSafeStatus] == 1) {
+ _lastSpriteIdx = _globals._spriteIndexes[2];
+ _cycleIndex = -2;
+ } else if (_globals[kSafeStatus] == 3) {
+ _lastSpriteIdx = _globals._spriteIndexes[3];
+ _cycleIndex = -2;
+ } else {
+ _lastSpriteIdx = _globals._spriteIndexes[3];
+ _cycleIndex = -1;
+ }
+
+ _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, _cycleIndex);
+ _scene->_sequences.setDepth(_lastSequenceIdx, 14);
+ int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST);
+
+ if (_game._objects.isInRoom(OBJ_DOOR_KEY)) {
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('k', -1));
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 15);
+ if (_globals[kSafeStatus] == 0 || _globals[kSafeStatus] == 2)
+ _scene->_hotspots.activate(NOUN_DOOR_KEY, false);
+ } else
+ _scene->_hotspots.activate(NOUN_DOOR_KEY, false);
+
+ if (_scene->_priorSceneId == 603) {
+ _game._player._playerPos = Common::Point(228, 126);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(50, 127);
+ _game._player._facing = FACING_EAST;
+ }
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0x2F1, 0x2F2, 0x2F3, 0);
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_NOTE);
+ _game._objects.addToInventory(OBJ_REARVIEW_MIRROR);
+ _game._objects.addToInventory(OBJ_COMPACT_CASE);
+ }
+}
+
+void Scene602::handleSafeActions() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 1:
+ if (_safeMode == 1 || _safeMode == 3) {
+ if (_globals[kSafeStatus] == 0 && _safeMode == 1) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F1));
+ _scene->_sequences.addTimer(120, 4);
+ } else {
+ _scene->_sequences.remove(_lastSequenceIdx);
+ if (_safeMode == 3)
+ _lastSpriteIdx = _globals._spriteIndexes[2];
+ else
+ _lastSpriteIdx = _globals._spriteIndexes[3];
+
+ _lastSequenceIdx = _scene->_sequences.addSpriteCycle(_lastSpriteIdx, false, 12, 1, 0, 0);
+ _scene->_sequences.setDepth(_lastSequenceIdx, 14);
+ if (_game._objects[OBJ_DOOR_KEY]._roomNumber == _scene->_currentSceneId)
+ _scene->_hotspots.activate(NOUN_DOOR_KEY, true);
+
+ _scene->_sequences.addSubEntry(_lastSequenceIdx,
+ SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ } else {
+ _scene->_sequences.remove(_lastSequenceIdx);
+ if (_globals[kSafeStatus] == 1)
+ _lastSpriteIdx = _globals._spriteIndexes[2];
+ else
+ _lastSpriteIdx = _globals._spriteIndexes[3];
+
+ _lastSequenceIdx = _scene->_sequences.startReverseCycle(_lastSpriteIdx, false, 12, 1, 0, 0);
+ _scene->_sequences.setDepth(_lastSequenceIdx, 14);
+ if (_game._objects[OBJ_DOOR_KEY]._roomNumber == _scene->_currentSceneId)
+ _scene->_hotspots.activate(NOUN_DOOR_KEY, false);
+
+ _scene->_sequences.addSubEntry(_lastSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ }
+ break;
+
+ case 2: {
+ int synxIdx = _lastSequenceIdx;
+ _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, _cycleIndex);
+ _scene->_sequences.setDepth(_lastSequenceIdx, 14);
+ _scene->_sequences.updateTimeout(_lastSequenceIdx, synxIdx);
+ int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST);
+ if (_safeMode == 3) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F3));
+ _scene->_sequences.addTimer(120, 4);
+ } else
+ _scene->_sequences.addTimer(60, 4);
+ break;
+ }
+
+ case 3:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]);
+ _game._player._visible = true;
+ break;
+
+ case 4:
+ if (_safeMode == 1) {
+ if (_globals[kSafeStatus] == 2)
+ _globals[kSafeStatus] = 3;
+ } else if (_safeMode == 2) {
+ if (_globals[kSafeStatus] == 3)
+ _globals[kSafeStatus] = 2;
+ else
+ _globals[kSafeStatus] = 0;
+ } else
+ _globals[kSafeStatus] = 1;
+
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene602::actions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_HALLWAY))
+ _scene->_nextSceneId = 601;
+ else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY))
+ _scene->_nextSceneId = 603;
+ else if (_action.isAction(VERB_OPEN, NOUN_SAFE) && ((_globals[kSafeStatus] == 0) || (_globals[kSafeStatus] == 2))) {
+ _safeMode = 1;
+ _cycleIndex = -2;
+ handleSafeActions();
+ } else if (_action.isAction(VERB_CLOSE, NOUN_SAFE) && ((_globals[kSafeStatus] == 1) || (_globals[kSafeStatus] == 3))) {
+ _safeMode = 2;
+ _cycleIndex = -1;
+ handleSafeActions();
+ } else if (_action.isAction(VERB_UNLOCK, NOUN_COMBINATION, NOUN_SAFE)) {
+ if ((_globals[kSafeStatus] == 0) && (_game._difficulty != DIFFICULTY_HARD)) {
+ _safeMode = 3;
+ _cycleIndex = -2;
+ handleSafeActions();
+ }
+ } else if ((_action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM) || _action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM)
+ || _action.isAction(VERB_REFLECT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM) || _action.isAction(VERB_REFLECT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM)) && (_globals[kSafeStatus] == 0)) {
+ switch (_game._trigger) {
+ case 0:
+ _vm->_dialogs->show(60230);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _scene->_sequences.remove(_lastSequenceIdx);
+ _scene->loadAnimation(formAnimName('L', 1), 1);
+ break;
+
+ case 1: {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _lastSpriteIdx = _globals._spriteIndexes[3];
+ _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, -1);
+ _scene->_sequences.setDepth(_lastSequenceIdx, 14);
+ int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 9);
+ idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(80, 134), FACING_NORTHEAST);
+ _scene->_sequences.addTimer(60, 2);
+ }
+ break;
+
+ case 2:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F2));
+ _globals[kSafeStatus] = 2;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_DOOR_KEY) && (_game._trigger || _game._objects.isInRoom(OBJ_DOOR_KEY))) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _scene->_hotspots.activate(NOUN_DOOR_KEY, false);
+ _vm->_sound->command(9);
+ _game._objects.addToInventory(OBJ_DOOR_KEY);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_DOOR_KEY, 835);
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(60210);
+ else if (_action.isAction(VERB_LOOK, NOUN_FLOOR))
+ _vm->_dialogs->show(60211);
+ else if (_action.isAction(VERB_LOOK, NOUN_HALLWAY))
+ _vm->_dialogs->show(60212);
+ else if (_action.isAction(VERB_LOOK, NOUN_TABLE))
+ _vm->_dialogs->show(60213);
+ else if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || _action.isAction(VERB_LOOK, NOUN_LOUNGE_CHAIR))
+ _vm->_dialogs->show(60214);
+ else if (_action.isAction(VERB_LOOK, NOUN_NEON_LIGHTS))
+ _vm->_dialogs->show(60215);
+ else if (_action.isAction(VERB_LOOK, NOUN_FIREPLACE))
+ _vm->_dialogs->show(60216);
+ else if (_action.isAction(VERB_LOOK, NOUN_PICTURE))
+ _vm->_dialogs->show(60217);
+ else if (_action.isAction(VERB_LOOK, NOUN_LAMP))
+ _vm->_dialogs->show(60218);
+ else if (_action.isAction(VERB_LOOK, NOUN_MASKS))
+ _vm->_dialogs->show(60219);
+ else if (_action.isAction(VERB_LOOK, NOUN_GLASS_BLOCK_WALL))
+ _vm->_dialogs->show(60220);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY))
+ _vm->_dialogs->show(60221);
+ else if (_action.isAction(VERB_LOOK, NOUN_SAFE)) {
+ if (_globals[kSafeStatus] == 0)
+ _vm->_dialogs->show(60222);
+ else if (_globals[kSafeStatus] == 1) {
+ if (!_game._objects.isInRoom(OBJ_DOOR_KEY))
+ _vm->_dialogs->show(60223);
+ else
+ _vm->_dialogs->show(60224);
+ } else if (_globals[kSafeStatus] == 2)
+ _vm->_dialogs->show(60234);
+ else if (_game._objects.isInRoom(OBJ_DOOR_KEY))
+ _vm->_dialogs->show(60235);
+ else
+ _vm->_dialogs->show(60236);
+ } else if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_SAFE) || _action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_SAFE))
+ _vm->_dialogs->show(60225);
+ else if (_action.isAction(VERB_PULL, NOUN_SAFE))
+ _vm->_dialogs->show(60226);
+ else if (_action.isAction(VERB_PUT, NOUN_FIREPLACE) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId)))
+ _vm->_dialogs->show(60227);
+ else if (_action.isAction(VERB_LOOK, NOUN_HOLE))
+ _vm->_dialogs->show(60228);
+ else if (_action.isAction(VERB_LOOK, NOUN_LASER_BEAM))
+ _vm->_dialogs->show(60229);
+ else if (_action.isAction(VERB_LOOK, NOUN_FLOWER_BOX))
+ _vm->_dialogs->show(60231);
+ else if (_action.isAction(VERB_THROW, NOUN_BOMB, NOUN_SAFE) || _action.isAction(VERB_THROW, NOUN_BOMBS, NOUN_SAFE))
+ _vm->_dialogs->show(60232);
+ else if (_action.isAction(VERB_PUT, NOUN_TIMEBOMB))
+ _vm->_dialogs->show(60233);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene603::Scene603(MADSEngine *vm) : Scene6xx(vm) {
+ _compactCaseHotspotId = -1;
+ _noteHotspotId = -1;
+}
+
+void Scene603::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsSint16LE(_compactCaseHotspotId);
+ s.syncAsSint16LE(_noteHotspotId);
+}
+
+void Scene603::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_COMPACT_CASE);
+ _scene->addActiveVocab(NOUN_NOTE);
+}
+
+void Scene603::enter() {
+ if (_game._objects[OBJ_COMPACT_CASE]._roomNumber == _scene->_currentSceneId) {
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRD_3");
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _compactCaseHotspotId = _scene->_dynamicHotspots.add(NOUN_COMPACT_CASE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_compactCaseHotspotId, Common::Point(250, 152), FACING_SOUTHEAST);
+ }
+
+ if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId)) {
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9");
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('p', -1));
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 14);
+ _noteHotspotId = _scene->_dynamicHotspots.add(NOUN_NOTE, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_noteHotspotId, Common::Point(242, 118), FACING_NORTHEAST);
+ }
+
+ if (_scene->_priorSceneId != -2)
+ _game._player._playerPos = Common::Point(113, 134);
+
+ sceneEntrySound();
+}
+
+void Scene603::actions() {
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_LIVINGROOM))
+ _scene->_nextSceneId = 602;
+ else if (_action.isAction(VERB_TAKE, NOUN_COMPACT_CASE)) {
+ if ( _game._trigger || !_game._objects.isInInventory(OBJ_COMPACT_CASE)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 5);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 5, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _vm->_sound->command(9);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_compactCaseHotspotId);
+ _game._objects.addToInventory(OBJ_COMPACT_CASE);
+ _vm->_dialogs->showItem(OBJ_COMPACT_CASE, 60330);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_NOTE)) {
+ if ( _game._trigger || !_game._objects.isInInventory(OBJ_NOTE)) {
+ if (_game._trigger == 0) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addTimer(15, 1);
+ } else if (_game._trigger == 1) {
+ _vm->_sound->command(9);
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _scene->_dynamicHotspots.remove(_noteHotspotId);
+ _game._objects.addToInventory(OBJ_NOTE);
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ }
+ } else
+ _vm->_dialogs->show(60323);
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(60310);
+ else if (_action.isAction(VERB_LOOK, NOUN_BED))
+ _vm->_dialogs->show(60311);
+ else if (_action.isAction(VERB_LOOK, NOUN_WIG_STAND))
+ _vm->_dialogs->show(60312);
+ else if (_action.isAction(VERB_TAKE, NOUN_WIG_STAND))
+ _vm->_dialogs->show(60313);
+ else if (_action.isAction(VERB_LOOK, NOUN_REVIEW))
+ _vm->_dialogs->show(60314);
+ else if (_action.isAction(VERB_LOOK, NOUN_SOUVENIR_TICKETS))
+ _vm->_dialogs->show(60315);
+ else if (_action.isAction(VERB_LOOK, NOUN_PHOTOGRAPH))
+ _vm->_dialogs->show(60316);
+ else if (_action.isAction(VERB_LOOK, NOUN_LAMP))
+ _vm->_dialogs->show(60317);
+ else if (_action.isAction(VERB_LOOK, NOUN_DIRECTORS_SLATE) || _action.isAction(VERB_LOOK, NOUN_CROP) || _action.isAction(VERB_LOOK, NOUN_MEGAPHONE))
+ _vm->_dialogs->show(60318);
+ else if (_action.isAction(VERB_LOOK, NOUN_SNAPSHOT))
+ _vm->_dialogs->show(60319);
+ else if (_action.isAction(VERB_TAKE, NOUN_SNAPSHOT))
+ _vm->_dialogs->show(60320);
+ else if (_action.isAction(VERB_LOOK, NOUN_PERFUME))
+ _vm->_dialogs->show(60321);
+ else if (_action.isAction(VERB_TAKE, NOUN_PERFUME))
+ _vm->_dialogs->show(60322);
+ else if (_action.isAction(VERB_LOOK, NOUN_NOTE)) {
+ if (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId)
+ _vm->_dialogs->show(60324);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CORNER_TABLE)) {
+ if (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId)
+ _vm->_dialogs->show(60326);
+ else
+ _vm->_dialogs->show(60325);
+ } else if (_action.isAction(VERB_LOOK, NOUN_VANITY)) {
+ if (_game._objects[OBJ_COMPACT_CASE]._roomNumber == _scene->_currentSceneId)
+ _vm->_dialogs->show(60327);
+ else
+ _vm->_dialogs->show(60328);
+ } else if (_action.isAction(VERB_LOOK, NOUN_COMPACT_CASE) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(60329);
+ // For the next two checks, the second part of the check wasn't surrounded par parenthesis, which was obviously wrong
+ else if (_action.isAction(VERB_LOOK) && (_action.isObject(NOUN_BRA) || _action.isObject(NOUN_BOA) || _action.isObject(NOUN_SLIP)))
+ _vm->_dialogs->show(60331);
+ else if (_action.isAction(VERB_TAKE) && (_action.isObject(NOUN_BRA) || _action.isObject(NOUN_BOA) || _action.isObject(NOUN_SLIP)))
+ _vm->_dialogs->show(60332);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene604::Scene604(MADSEngine *vm) : Scene6xx(vm) {
+ _timebombHotspotId = -1;
+ _bombMode = -1;
+ _monsterFrame = -1;
+
+ _monsterTimer = 0;
+
+ _monsterActive = false;
+ _animationActiveFl = false;
+}
+
+void Scene604::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsSint16LE(_timebombHotspotId);
+ s.syncAsSint16LE(_bombMode);
+ s.syncAsSint16LE(_monsterFrame);
+
+ s.syncAsUint32LE(_monsterTimer);
+
+ s.syncAsByte(_monsterActive);
+ s.syncAsByte(_animationActiveFl);
+}
+
+void Scene604::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_SEA_MONSTER);
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_TIMEBOMB);
+}
+
+void Scene604::enter() {
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_9");
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(Resources::formatName(620, 'b', 0, EXT_SS, ""));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9");
+
+ if (_globals[kTimebombStatus] == 1) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1);
+ _timebombHotspotId = _scene->_dynamicHotspots.add(NOUN_TIMEBOMB, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_timebombHotspotId, Common::Point(166, 118), FACING_NORTHEAST);
+ }
+
+ if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_TIMEBOMB);
+
+ _vm->_palette->setEntry(252, 63, 37, 26);
+ _vm->_palette->setEntry(253, 45, 24, 17);
+ _animationActiveFl = false;
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(72, 149);
+ _game._player._facing = FACING_NORTHEAST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->loadAnimation(formAnimName('R', 1), 70);
+ _animationActiveFl = true;
+ } else {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ }
+
+ _monsterTimer = _scene->_frameStartTime;
+ _monsterActive = false;
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0x2E7, 0x2E8, 0x2E9, 0x2EA, 0x2EB, 0x2EC, 0x2ED, 0x2EE, 0x2EF, 0x2F0, 0);
+}
+
+void Scene604::step() {
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(30, 71);
+ break;
+
+ case 71:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 72:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _game._player._stepEnabled = true;
+ _animationActiveFl = false;
+ break;
+
+ default:
+ break;
+ }
+
+ if (_monsterActive && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _monsterFrame) {
+ _monsterFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextMonsterFrame = -1;
+
+ switch (_monsterFrame) {
+ case 50:
+ case 137:
+ case 174: {
+ int randVal = _vm->getRandomNumber(1, 1000);
+ if ((randVal <= 450) && (_game._player._special)) {
+ if (_game._player._special == 1)
+ nextMonsterFrame = 50;
+ else if (_game._player._special == 2)
+ nextMonsterFrame = 84;
+ else
+ nextMonsterFrame = 137;
+ } else if (randVal <= 150)
+ nextMonsterFrame = 50;
+ else if (randVal <= 300)
+ nextMonsterFrame = 84;
+ else if (randVal <= 450)
+ nextMonsterFrame = 137;
+ else if (randVal < 750)
+ nextMonsterFrame = 13;
+ else
+ nextMonsterFrame = 114;
+
+ }
+ break;
+
+ case 84:
+ nextMonsterFrame = 14;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((nextMonsterFrame >= 0) && (nextMonsterFrame != _monsterFrame)) {
+ _scene->_activeAnimation->setCurrentFrame(nextMonsterFrame);
+ _monsterFrame = nextMonsterFrame;
+ }
+ }
+ }
+
+ if ((!_monsterActive && !_animationActiveFl) && (_scene->_frameStartTime > (_monsterTimer + 4))) {
+ _monsterTimer = _scene->_frameStartTime;
+ if ((_vm->getRandomNumber(1, 1000) < 25) || !_game._visitedScenes._sceneRevisited) {
+ _monsterActive = true;
+ _scene->freeAnimation();
+ _scene->loadAnimation(formAnimName('m', -1));
+ }
+ }
+}
+
+void Scene604::handleBombActions() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 9, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ if (_bombMode == 1)
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1);
+ else
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 2);
+
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1);
+ _timebombHotspotId = _scene->_dynamicHotspots.add(NOUN_TIMEBOMB, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_timebombHotspotId, Common::Point(166, 118), FACING_NORTHEAST);
+ _game._objects.setRoom(OBJ_TIMEBOMB, _scene->_currentSceneId);
+ break;
+
+ case 2:
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _scene->_dynamicHotspots.remove(_timebombHotspotId);
+ _game._objects.addToInventory(OBJ_TIMEBOMB);
+ break;
+
+ case 3:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ if (_bombMode == 1) {
+ _vm->_dialogs->show(60421);
+ _globals[kTimebombStatus] = TIMEBOMB_ACTIVATED;
+ _globals[kTimebombTimer] = 0;
+ } else {
+ _vm->_dialogs->show(60423);
+ _globals[kTimebombStatus] = TIMEBOMB_DEACTIVATED;
+ _globals[kTimebombTimer] = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene604::actions() {
+ if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx);
+ _scene->_sequences.addTimer(6, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_nextSceneId = 504;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if ((_action.isAction(VERB_PUT, NOUN_LEDGE) || _action.isAction(VERB_PUT, NOUN_VIEWPORT) || _action.isAction(VERB_THROW, NOUN_VIEWPORT))
+ && (_action.isObject(NOUN_BOMB) || _action.isObject(NOUN_BOMBS)))
+ _vm->_dialogs->show(60420);
+ else if (_action.isAction(VERB_PUT, NOUN_TIMEBOMB, NOUN_LEDGE) || _action.isAction(VERB_PUT, NOUN_TIMEBOMB, NOUN_VIEWPORT)) {
+ _bombMode = 1;
+ if ((_game._difficulty == DIFFICULTY_HARD) || _globals[kWarnedFloodCity])
+ handleBombActions();
+ else if ((_game._objects.isInInventory(OBJ_POLYCEMENT) && _game._objects.isInInventory(OBJ_CHICKEN))
+ && ((_globals[kLineStatus] == LINE_TIED) || ((_game._difficulty == DIFFICULTY_EASY) && (!_globals[kBoatRaised]))))
+ handleBombActions();
+ else if (_game._difficulty == DIFFICULTY_EASY)
+ _vm->_dialogs->show(60424);
+ else {
+ _vm->_dialogs->show(60425);
+ _globals[kWarnedFloodCity] = true;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_TIMEBOMB)) {
+ if (_game._trigger || !_game._objects.isInInventory(OBJ_TIMEBOMB)) {
+ _bombMode = 2;
+ handleBombActions();
+ }
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(60411);
+ else if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT)) {
+ if (_monsterActive) {
+ _vm->_dialogs->show(60413);
+ } else {
+ _vm->_dialogs->show(60412);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(60414);
+ else if (_action.isAction(VERB_LOOK, NOUN_VENT))
+ _vm->_dialogs->show(60415);
+ else if (_action.isAction(VERB_LOOK, NOUN_INDICATOR))
+ _vm->_dialogs->show(60416);
+ else if (_action.isAction(VERB_LOOK, NOUN_SCULPTURE))
+ _vm->_dialogs->show(60417);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAR))
+ _vm->_dialogs->show(60418);
+ else if (_action.isAction(VERB_LOOK, NOUN_FOUNTAIN))
+ _vm->_dialogs->show(60419);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene605::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+}
+
+void Scene605::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('r', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', -1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('l', -1));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('p', -1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('n', -1));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('f', -1));
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 15, 0, 0, 0);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 0);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 14, 0, 0, 0);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 13, 0, 0, 0);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 17, 0, 0, 0);
+ _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 18, 0, 0, 0);
+
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.addTimer(600, 70);
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ sceneEntrySound();
+ _vm->_sound->command(22);
+}
+
+void Scene605::step() {
+ if (_game._trigger == 70) {
+ _vm->_sound->command(23);
+ if (_globals[kResurrectRoom] >= 700)
+ _vm->_dialogs->show(60598);
+ else
+ _vm->_dialogs->show(60599);
+
+ _scene->_nextSceneId = _globals[kResurrectRoom];
+ }
+}
+
+void Scene605::actions() {
+ return;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene607::Scene607(MADSEngine *vm) : Scene6xx(vm) {
+ _dogTimer = 0;
+ _lastFrameTime = 0;
+
+ _dogLoop = false;
+ _dogEatsRex = false;
+ _dogBarking = false;
+ _shopAvailable = false;
+
+ _animationMode = -1;
+ _animationActive = -1;
+ _counter = -1;
+}
+
+void Scene607::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsUint32LE(_dogTimer);
+ s.syncAsUint32LE(_lastFrameTime);
+
+ s.syncAsByte(_dogLoop);
+ s.syncAsByte(_dogEatsRex);
+ s.syncAsByte(_dogBarking);
+ s.syncAsByte(_shopAvailable);
+
+ s.syncAsSint16LE(_animationMode);
+ s.syncAsSint16LE(_animationActive);
+ s.syncAsSint16LE(_counter);
+}
+
+void Scene607::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_OBNOXIOUS_DOG);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene607::enter() {
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_3");
+
+ if (!_game._visitedScenes._sceneRevisited && (_scene->_priorSceneId != 608))
+ _globals[kDogStatus] = DOG_PRESENT;
+
+ if ((_scene->_priorSceneId == 608) && (_globals[kDogStatus] < DOG_GONE))
+ _globals[kDogStatus] = DOG_GONE;
+
+ _animationActive = 0;
+
+ if ((_globals[kDogStatus] == DOG_PRESENT) && (_game._difficulty != DIFFICULTY_EASY)) {
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 3));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 7));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', 0));
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6);
+ _dogBarking = false;
+ _dogLoop = false;
+ _shopAvailable = false;
+ _dogEatsRex = false;
+ _dogTimer = 0;
+ } else
+ _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, false);
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+
+ if (_scene->_priorSceneId == 608) {
+ _game._player._playerPos = Common::Point(297, 50);
+ _game._player._facing = FACING_SOUTHEAST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(40, 104);
+ _game._player._facing = FACING_SOUTHEAST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->loadAnimation(formAnimName('R', 1), 80);
+ } else if (_globals[kDogStatus] == DOG_LEFT) {
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 3));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 7));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', 0));
+ }
+
+ sceneEntrySound();
+
+ if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_BONES);
+
+ _vm->_palette->setEntry(252, 63, 44, 30);
+ _vm->_palette->setEntry(253, 63, 20, 22);
+ _game.loadQuoteSet(0x2F8, 0x2F7, 0x2F6, 0x2F9, 0x2FA, 0);
+}
+
+void Scene607::step() {
+ if (_globals[kDogStatus] == DOG_LEFT) {
+ int32 diff = _scene->_frameStartTime - _lastFrameTime;
+ if ((diff >= 0) && (diff <= 4))
+ _dogTimer += diff;
+ else
+ _dogTimer++;
+
+ _lastFrameTime = _scene->_frameStartTime;
+ }
+
+ if ((_dogTimer >= 480) && !_dogLoop && !_shopAvailable && (_globals[kDogStatus] == DOG_LEFT) && !_game._player._special) {
+ _vm->_sound->command(14);
+ _dogLoop = true;
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 10, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 91);
+ _dogLoop = false;
+ _dogTimer = 0;
+ }
+
+ if (_game._trigger == 91) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6);
+ _dogBarking = false;
+ _globals[kDogStatus] = DOG_PRESENT;
+ _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, true);
+ }
+
+ if (!_dogEatsRex && (_game._difficulty != DIFFICULTY_EASY) && !_animationActive && (_globals[kDogStatus] == DOG_PRESENT)
+ && !_dogBarking && (_vm->getRandomNumber(1, 50) == 10)) {
+ _dogBarking = true;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 8, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6);
+ _scene->_kernelMessages.reset();
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 100);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ _counter = 0;
+ }
+
+ if ((_game._trigger == 70) && !_dogEatsRex && (_globals[kDogStatus] == DOG_PRESENT) && !_animationActive) {
+ int syncIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx);
+ _scene->_kernelMessages.reset();
+ _dogBarking = false;
+ }
+
+ if (_game._trigger == 100) {
+ _counter++;
+ _vm->_sound->command(12);
+
+ if ((_counter >= 1) && (_counter <= 4)) {
+ Common::Point pos(0, 0);
+ switch (_counter) {
+ case 1:
+ pos = Common::Point(237, 5);
+ break;
+
+ case 2:
+ pos = Common::Point(270, 15);
+ break;
+
+ case 3:
+ pos = Common::Point(237, 25);
+ break;
+
+ case 4:
+ pos = Common::Point(270, 36);
+ break;
+
+ default:
+ break;
+ }
+ _scene->_kernelMessages.add(pos, 0xFDFC, 0, 0, 120, _game.getQuote(0x2F9));
+ }
+ }
+
+ if (_game._player._moving && (_game._difficulty != DIFFICULTY_EASY) && !_shopAvailable && (_globals[kDogStatus] == DOG_PRESENT) && (_scene->_rails.getNext() > 0)) {
+ _game._player.cancelCommand();
+ _game._player.startWalking(Common::Point(268, 72), FACING_NORTHEAST);
+ _scene->_rails.resetNext();
+ }
+
+ if ((_game._player._special > 0) && (_game._difficulty != DIFFICULTY_EASY) && (_globals[kDogStatus] == DOG_PRESENT) && _game._player._stepEnabled)
+ _game._player._stepEnabled = false;
+
+ if ((_game._difficulty != DIFFICULTY_EASY) && (_globals[kDogStatus] == DOG_PRESENT) && (_game._player._playerPos == Common::Point(268, 72))
+ && (_game._trigger || !_dogEatsRex)) {
+ _dogEatsRex = true;
+ switch (_game._trigger) {
+ case 91:
+ case 0:
+ _animationActive = 1;
+ _game._player._visible = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, 7);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FA));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 60);
+ _scene->_sequences.addTimer(10, 64);
+ break;
+
+ case 60: {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 8, 45);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 61);
+ }
+ break;
+
+ case 61: {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 3, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 46, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 62);
+ }
+ break;
+
+ case 62: {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _animationActive = 2;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_sequences.addTimer(60, 63);
+ }
+ break;
+
+ case 63:
+ _vm->_dialogs->show(60729);
+ _animationActive = 0;
+ _dogEatsRex = false;
+ _scene->_reloadSceneFlag = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ case 64:
+ if (_dogEatsRex && (_animationActive == 1)) {
+ _vm->_sound->command(12);
+ _scene->_sequences.addTimer(10, 64);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ switch (_game._trigger) {
+ case 80:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(6, 81);
+ break;
+
+ case 81:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 82);
+ break;
+
+ case 82:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene607::handleThrowingBone() {
+ _animationActive = -1;
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _game._player._visible = false;
+ _scene->loadAnimation(formAnimName('D', _animationMode), 1);
+ break;
+
+ case 1:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+
+ if (_animationMode != 1)
+ _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, false);
+ else {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6);
+ }
+
+ _dogBarking = false;
+ if (_game._objects.isInInventory(OBJ_BONE)) {
+ _game._objects.setRoom(OBJ_BONE, 1);
+ if (_animationMode == 1)
+ _globals[kBone202Status] = 0;
+ } else {
+ _game._objects.setRoom(OBJ_BONES, 1);
+ _game._objects.addToInventory(OBJ_BONE);
+ }
+
+ _scene->_sequences.addTimer(60, 2);
+ break;
+
+ case 2: {
+ int quoteId = 0x2F8;
+ if (_animationMode == 1)
+ quoteId = 0x2F7;
+
+ if (_animationMode == 2) {
+ _globals[kDogStatus] = DOG_LEFT;
+ _dogTimer = 0;
+ }
+
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(quoteId));
+ _scene->_sequences.addTimer(60, 3);
+ }
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ _animationActive = 0;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene607::preActions() {
+ if (_action.isAction(VERB_TALKTO, NOUN_OBNOXIOUS_DOG))
+ _game._player._needToWalk = false;
+
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_SIDE_ENTRANCE) && (_globals[kDogStatus] == DOG_LEFT) && (_game._difficulty != DIFFICULTY_EASY)) {
+ _shopAvailable = true;
+ _dogTimer = 0;
+ }
+
+ if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG))
+ _game._player.walk(Common::Point(193, 100), FACING_NORTHEAST);
+
+ if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_FENCE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FENCE))
+ _game._player.walk(Common::Point(201, 107), FACING_SOUTHEAST);
+}
+
+void Scene607::actions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_SIDE_ENTRANCE))
+ _scene->_nextSceneId = 608;
+ else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx);
+ _scene->_sequences.addTimer(6, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _scene->_nextSceneId = 504;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) {
+ if (_game._difficulty != DIFFICULTY_EASY) {
+ _animationMode = 1;
+ _scene->_kernelMessages.reset();
+ if (_game._trigger == 0)
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F6));
+
+ handleThrowingBone();
+ }
+ } else if ((_action.isAction(VERB_THROW, NOUN_BONES, NOUN_FENCE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FENCE)) && (_game._difficulty != DIFFICULTY_EASY)
+ && ((_globals[kDogStatus] == DOG_PRESENT) || _game._trigger)) {
+ _animationMode = 2;
+ if (_game._trigger == 0) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F6));
+ }
+ handleThrowingBone();
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) {
+ if ((_globals[kDogStatus] == DOG_PRESENT) || (_game._difficulty == DIFFICULTY_EASY))
+ _vm->_dialogs->show(60710);
+ else
+ _vm->_dialogs->show(60711);
+ } else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(60712);
+ else if (_action.isAction(VERB_LOOK, NOUN_FENCE))
+ _vm->_dialogs->show(60713);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAR))
+ _vm->_dialogs->show(60714);
+ else if (_action.isAction(VERB_LOOK, NOUN_MANHOLE))
+ _vm->_dialogs->show(60715);
+ else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT) && (_globals[kDogStatus] == DOG_PRESENT))
+ _vm->_dialogs->show(60716);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIGN))
+ _vm->_dialogs->show(60717);
+ else if (_action.isAction(VERB_LOOK, NOUN_BROKEN_WINDOW))
+ _vm->_dialogs->show(60718);
+ else if (_action.isAction(VERB_LOOK, NOUN_GARAGE_DOOR))
+ _vm->_dialogs->show(60719);
+ else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK))
+ _vm->_dialogs->show(60720);
+ else if (_action.isAction(VERB_LOOK, NOUN_AIR_HOSE))
+ _vm->_dialogs->show(60721);
+ else if (_action.isAction(VERB_LOOK, NOUN_AUTO_SHOP)) {
+ if (_globals[kDogStatus] == DOG_PRESENT)
+ _vm->_dialogs->show(60723);
+ else
+ _vm->_dialogs->show(60722);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SIDE_ENTRANCE)) {
+ if (_globals[kDogStatus] == DOG_PRESENT)
+ _vm->_dialogs->show(60725);
+ else
+ _vm->_dialogs->show(60724);
+ } else if (_action.isAction(VERB_LOOK, NOUN_OBNOXIOUS_DOG))
+ _vm->_dialogs->show(60726);
+ else if (_action.isAction(VERB_TALKTO, NOUN_OBNOXIOUS_DOG))
+ _vm->_dialogs->show(60727);
+ else if (_action.isAction(VERB_LOOK, NOUN_BARRICADE))
+ _vm->_dialogs->show(60728);
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET))
+ _vm->_dialogs->show(60730);
+ else if (_action.isObject(NOUN_GARAGE_DOOR) && (_action.isAction(VERB_OPEN) || _action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL)))
+ _vm->_dialogs->show(60731);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene608::Scene608(MADSEngine *vm) : Scene6xx(vm) {
+ _carMode = -1;
+ _carFrame = -1;
+ _carMoveMode = -1;
+ _dogDeathMode = -1;
+ _carHotspotId = -1;
+ _barkCount = -1;
+ _polycementHotspotId = -1;
+ _animationMode = -1;
+ _nextTrigger = -1;
+ _throwMode = -1;
+
+ _resetPositionsFl = false;
+ _dogActiveFl = false;
+ _dogBarkingFl = false;
+ _dogFirstEncounter = false;
+ _rexBeingEaten = false;
+ _dogHitWindow = false;
+ _checkFl = false;
+ _dogSquashFl = false;
+ _dogSafeFl = false;
+ _buttonPressedonTimeFl = false;
+ _dogUnderCar = false;
+ _dogYelping = false;
+
+ _dogWindowTimer = -1;
+ _dogRunTimer = -1;
+
+ _dogTimer1 = 0;
+ _dogTimer2 = 0;
+}
+
+void Scene608::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsSint16LE(_carMode);
+ s.syncAsSint16LE(_carFrame);
+ s.syncAsSint16LE(_carMoveMode);
+ s.syncAsSint16LE(_dogDeathMode);
+ s.syncAsSint16LE(_carHotspotId);
+ s.syncAsSint16LE(_barkCount);
+ s.syncAsSint16LE(_polycementHotspotId);
+ s.syncAsSint16LE(_animationMode);
+ s.syncAsSint16LE(_nextTrigger);
+ s.syncAsSint16LE(_throwMode);
+
+ s.syncAsByte(_resetPositionsFl);
+ s.syncAsByte(_dogActiveFl);
+ s.syncAsByte(_dogBarkingFl);
+ s.syncAsByte(_dogFirstEncounter);
+ s.syncAsByte(_rexBeingEaten);
+ s.syncAsByte(_dogHitWindow);
+ s.syncAsByte(_checkFl);
+ s.syncAsByte(_dogSquashFl);
+ s.syncAsByte(_dogSafeFl);
+ s.syncAsByte(_buttonPressedonTimeFl);
+ s.syncAsByte(_dogUnderCar);
+ s.syncAsByte(_dogYelping);
+
+ s.syncAsSint32LE(_dogWindowTimer);
+ s.syncAsSint32LE(_dogRunTimer);
+
+ s.syncAsUint32LE(_dogTimer1);
+ s.syncAsUint32LE(_dogTimer2);
+}
+
+void Scene608::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_POLYCEMENT);
+ _scene->addActiveVocab(NOUN_CAR);
+ _scene->addActiveVocab(NOUN_OBNOXIOUS_DOG);
+}
+
+void Scene608::resetDogVariables() {
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_OBNOXIOUS_DOG, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(194, 142), FACING_EAST);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4);
+ _dogBarkingFl = false;
+ _dogFirstEncounter = false;
+}
+
+void Scene608::restoreAnimations() {
+ _scene->freeAnimation();
+ _carMode = 0;
+ _game._player._stepEnabled = true;
+ if (_throwMode == 6)
+ _dogSquashFl = true;
+
+ if (_globals[kCarStatus] == CAR_UP) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[7]);
+ _scene->loadAnimation(formAnimName('A', -1));
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[7]);
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(6);
+ }
+}
+
+void Scene608::setCarAnimations() {
+ _scene->freeAnimation();
+ if (_globals[kCarStatus] == CAR_UP) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(143, 98));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6);
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[7], Common::Point(141, 67));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15);
+ } else {
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(143, 128));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6);
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[7], Common::Point(141, 97));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15);
+ _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[8], Common::Point(144, 126));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 5);
+ }
+}
+
+void Scene608::handleThrowingBone() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ setCarAnimations();
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _animationMode = -1;
+ _game._player._visible = false;
+ _carMode = _throwMode;
+ if (_throwMode == 4)
+ _scene->loadAnimation(formAnimName('X', 2), 1);
+ else if (_throwMode == 5)
+ _scene->loadAnimation(formAnimName('X', 1), 1);
+ else
+ _scene->loadAnimation(formAnimName('X', 3), 1);
+ break;
+
+ case 1:
+ _nextTrigger = 1;
+ _scene->_sequences.addTimer(1, 2);
+ break;
+
+ case 2:
+ if (_nextTrigger != 2)
+ _scene->_sequences.addTimer(1, 2);
+ else {
+ if (_game._objects.isInInventory(OBJ_BONE))
+ _game._objects.setRoom(OBJ_BONE, 1);
+ else {
+ _game._objects.setRoom(OBJ_BONES, 1);
+ _game._objects.addToInventory(OBJ_BONE);
+ }
+ _scene->_sequences.addTimer(60, 3);
+ }
+ break;
+
+ case 3:
+ if (_throwMode != 6) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x304));
+ _scene->_sequences.addTimer(120, 4);
+ } else
+ restoreAnimations();
+ break;
+
+ case 4:
+ restoreAnimations();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene608::enter() {
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRD_7");
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9");
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('c', 2));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('c', 1));
+
+ if (_game._objects.isInRoom(OBJ_POLYCEMENT)) {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_POLYCEMENT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _polycementHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(249, 129), FACING_NORTHEAST);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6);
+ }
+
+ if (_game._objects.isInRoom(OBJ_REARVIEW_MIRROR)) {
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('m', -1));
+ _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_REARVIEW_MIRROR, VERB_WALKTO, _globals._sequenceIndexes[12], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(71, 113), FACING_NORTHEAST);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 15);
+ }
+
+ if (_game._difficulty == DIFFICULTY_HARD) {
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('g', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 2));
+ _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('h', 2));
+ _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('h', 3));
+ _rexBeingEaten = false;
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ _globals[kDogStatus] = DOG_GONE;
+ _dogActiveFl = true;
+ } else
+ _dogActiveFl = (_globals[kDogStatus] != DOG_DEAD);
+ } else {
+ _globals[kDogStatus] = DOG_DEAD;
+ _dogActiveFl = false;
+ }
+
+ _dogSquashFl = false;
+ _buttonPressedonTimeFl = false;
+ _dogWindowTimer = 0;
+ _dogRunTimer = 0;
+ _dogHitWindow = false;
+ _checkFl = false;
+ _dogUnderCar = false;
+ _dogYelping = false;
+
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _globals[kCarStatus] = CAR_UP;
+
+ _animationMode = 0;
+ _carMoveMode = 0;
+ _carFrame = -1;
+
+ if (_globals[kCarStatus] == CAR_UP) {
+ _carMode = 0;
+ _dogDeathMode = 0;
+ _resetPositionsFl = false;
+ int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25));
+ _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST);
+ _scene->loadAnimation(formAnimName('A', -1));
+ } else if (_globals[kCarStatus] == CAR_DOWN) {
+ _carMode = 0;
+ _dogDeathMode = 0;
+ _resetPositionsFl = false;
+ int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25));
+ _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST);
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(6);
+ } else if (_globals[kCarStatus] == CAR_SQUASHES_DOG) {
+ _carMode = 2;
+ _dogDeathMode = 0;
+ _resetPositionsFl = false;
+ int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25));
+ _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST);
+ _scene->loadAnimation(formAnimName('C', -1));
+ } else if (_globals[kCarStatus] == CAR_SQUASHES_DOG_AGAIN) {
+ _carMode = 1;
+ _dogDeathMode = 2;
+ _resetPositionsFl = true;
+ int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25));
+ _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST);
+ _scene->loadAnimation(formAnimName('B', -1));
+ } else {
+ _carMode = 3;
+ _dogDeathMode = 2;
+ _resetPositionsFl = true;
+ int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25));
+ _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST);
+ _scene->loadAnimation(formAnimName('D', -1));
+ }
+
+ _vm->_palette->setEntry(252, 63, 44, 30);
+ _vm->_palette->setEntry(253, 63, 20, 22);
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(46, 132);
+ _game._player._facing = FACING_EAST;
+ if (_game._difficulty == DIFFICULTY_HARD) {
+ if (!_game._visitedScenes._sceneRevisited)
+ _dogFirstEncounter = true;
+ else if (_dogActiveFl)
+ resetDogVariables();
+ }
+ } else if ((_game._difficulty == DIFFICULTY_HARD) && !_dogFirstEncounter && _dogActiveFl) {
+ if (!_dogUnderCar)
+ resetDogVariables();
+ else {
+ _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 10, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 6);
+ }
+ }
+
+ sceneEntrySound();
+
+ if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_BONES);
+
+ _game.loadQuoteSet(0x2FB, 0x2FC, 0x2FE, 0x2FD, 0x2FF, 0x300, 0x301, 0x302, 0x303, 0x304, 0);
+}
+
+void Scene608::step() {
+ if (_dogFirstEncounter) {
+ long diff = _scene->_frameStartTime - _dogTimer1;
+ if ((diff >= 0) && (diff <= 1))
+ _dogWindowTimer += diff;
+ else
+ _dogWindowTimer++;
+
+ _dogTimer1 = _scene->_frameStartTime;
+ }
+
+ if (_dogActiveFl && (_dogWindowTimer >= 2) && !_dogHitWindow) {
+ _dogHitWindow = true;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 11, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1);
+ _vm->_sound->command(14);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ _dogWindowTimer = 0;
+ }
+
+ if (_game._trigger == 70)
+ resetDogVariables();
+
+ if ((_game._difficulty == DIFFICULTY_HARD) && !_animationMode && _dogActiveFl && !_dogFirstEncounter && !_dogUnderCar) {
+ if (!_dogBarkingFl) {
+ if (_vm->getRandomNumber(1, 50) == 10) {
+ _dogBarkingFl = true;
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 5, 8, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4);
+ int idx = _scene->_dynamicHotspots.add(NOUN_OBNOXIOUS_DOG, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(194, 142), FACING_EAST);
+ _barkCount = 0;
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 2, 100);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 60);
+ }
+ } else if (_game._trigger == 60) {
+ int syncIdx = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], syncIdx);
+ _scene->_kernelMessages.reset();
+ _dogBarkingFl = false;
+ }
+ }
+
+ if ((_game._trigger == 100) && _dogBarkingFl) {
+ _vm->_sound->command(12);
+ _barkCount++;
+
+ if ((_barkCount >= 1) && (_barkCount <= 4)) {
+ Common::Point _barkPos(0, 0);
+ switch (_barkCount) {
+ case 1:
+ _barkPos = Common::Point(197, 66);
+ break;
+
+ case 2:
+ _barkPos = Common::Point(230, 76);
+ break;
+
+ case 3:
+ _barkPos = Common::Point(197, 86);
+ break;
+
+ case 4:
+ _barkPos = Common::Point(230, 97);
+ break;
+
+ default:
+ break;
+ }
+ _scene->_kernelMessages.add(_barkPos, 0xFDFC, 0, 0, 120, _game.getQuote(0x2FB));
+ }
+ }
+
+ if (_dogSquashFl && !_dogFirstEncounter && _dogUnderCar && _dogActiveFl) {
+ long diff = _scene->_frameStartTime - _dogTimer2;
+ if ((diff >= 0) && (diff <= 4))
+ _dogRunTimer += diff;
+ else
+ _dogRunTimer++;
+
+ _dogTimer2 = _scene->_frameStartTime;
+ }
+
+ if (_dogRunTimer >= 480 && !_checkFl && !_buttonPressedonTimeFl && !_dogFirstEncounter && _dogUnderCar && _dogActiveFl) {
+ _checkFl = true;
+ _dogSquashFl = false;
+ _dogSafeFl = true;
+ _checkFl = false;
+ _dogRunTimer = 0;
+ } else {
+ _dogSafeFl = false;
+ if (_game._player._moving && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_scene->_rails.getNext() > 0) && _dogUnderCar)
+ _dogSafeFl = true;
+ }
+
+ if (_dogActiveFl && _dogSafeFl && !_buttonPressedonTimeFl) {
+ _dogDeathMode = 0;
+ _globals[kCarStatus] = CAR_UP;
+ _carMode = 0;
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _dogUnderCar = false;
+ _dogYelping = false;
+ _scene->_kernelMessages.reset();
+ _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 92);
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FF));
+ }
+
+ if (_game._trigger == 92) {
+ resetDogVariables();
+ _animationMode = 0;
+ }
+
+ if ((_carMode == 4) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) {
+ _carFrame = _scene->_activeAnimation->getCurrentFrame();
+
+ if (_carFrame == 10) {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ } else if (_carFrame == 56) {
+ resetDogVariables();
+ _animationMode = 0;
+ _nextTrigger = 2;
+ }
+ }
+ }
+
+ if ((_carMode == 5) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) {
+ _carFrame = _scene->_activeAnimation->getCurrentFrame();
+ if (_carFrame == 10) {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ } else if (_carFrame == 52) {
+ resetDogVariables();
+ _animationMode = 0;
+ _nextTrigger = 2;
+ }
+ }
+ }
+
+ if ((_carMode == 6) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) {
+ _carFrame = _scene->_activeAnimation->getCurrentFrame();
+
+ if (_carFrame == 11) {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ } else if (_carFrame == 41) {
+ _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 10, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 6);
+ _dogUnderCar = true;
+ _nextTrigger = 2;
+ }
+ }
+ }
+
+ if (_dogUnderCar) {
+ if (!_dogYelping) {
+ if (_vm->getRandomNumber(1, 50) == 10) {
+ _dogYelping = true;
+ _barkCount = 0;
+ _scene->_sequences.addTimer(12, 110);
+ _scene->_sequences.addTimer(22, 111);
+ _scene->_sequences.addTimer(120, 112);
+ }
+ _scene->_kernelMessages.reset();
+ }
+ } else
+ _dogYelping = false;
+
+ if (_game._trigger == 110) {
+ _vm->_sound->command(12);
+ _scene->_kernelMessages.add(Common::Point(150, 97), 0xFDFC, 0, 0, 60, _game.getQuote(0x303));
+ }
+
+ if (_game._trigger == 111) {
+ _vm->_sound->command(12);
+ _scene->_kernelMessages.add(Common::Point(183, 93), 0xFDFC, 0, 0, 60, _game.getQuote(0x303));
+ }
+
+ if (_game._trigger == 112)
+ _dogYelping = false;
+
+ if ((_carMode == 0) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) {
+ _carFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextFrame = -1;
+
+ if ((_globals[kCarStatus] == CAR_UP) || (_globals[kCarStatus] == CAR_DOWN)) {
+ switch (_carMoveMode) {
+ case 0:
+ if (_globals[kCarStatus] == CAR_UP)
+ nextFrame = 0;
+ else
+ nextFrame = 6;
+ break;
+
+ case 1:
+ if (_scene->_activeAnimation->getCurrentFrame() >= 12) {
+ nextFrame = 0;
+ _carMoveMode = 0;
+ _globals[kCarStatus] = CAR_UP;
+ }
+ break;
+
+ case 2:
+ if (_scene->_activeAnimation->getCurrentFrame() >= 6) {
+ nextFrame = 6;
+ _carMoveMode = 0;
+ _globals[kCarStatus] = CAR_DOWN;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextFrame);
+ _carFrame = nextFrame;
+ }
+ }
+ }
+
+ if ((_carMode == 2) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) {
+ _carFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextFrame = -1;
+
+ if (_carMoveMode == 0)
+ nextFrame = 28;
+ else if (_scene->_activeAnimation->getCurrentFrame() >= 28) {
+ nextFrame = 28;
+ _carMoveMode = 0;
+ }
+
+ if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextFrame);
+ _carFrame = nextFrame;
+ }
+ }
+ }
+
+ if ((_carMode == 3) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) {
+ _carFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextFrame = -1;
+
+ if (_resetPositionsFl) {
+ nextFrame = 0;
+ _carMoveMode = 0;
+ } else if (_carMoveMode == 0)
+ nextFrame = 6;
+ else if (_scene->_activeAnimation->getCurrentFrame() >= 6) {
+ nextFrame = 6;
+ _carMoveMode = 0;
+ }
+
+ if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextFrame);
+ _carFrame = nextFrame;
+ }
+ }
+ }
+
+
+ if ((_carMode == 1) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) {
+ _carFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextFrame = -1;
+
+ if (_resetPositionsFl) {
+ nextFrame = 0;
+ _carMoveMode = 0;
+ } else if (_carMoveMode == 0)
+ nextFrame = 6;
+ else if (_scene->_activeAnimation->getCurrentFrame() >= 6) {
+ nextFrame = 6;
+ _carMoveMode = 0;
+ }
+
+ if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextFrame);
+ _carFrame = nextFrame;
+ }
+ }
+ }
+
+ if (_game._player._moving && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_scene->_rails.getNext() > 0)) {
+ _game._player.cancelCommand();
+ _game._player.startWalking(Common::Point(194, 142), FACING_EAST);
+ _scene->_rails.resetNext();
+ if (_dogUnderCar)
+ _dogSafeFl = true;
+ }
+
+ if (_game._player._special > 0 && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && _game._player._stepEnabled)
+ _game._player._stepEnabled = false;
+
+ if ((_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_game._player._playerPos == Common::Point(194, 142))
+ && (_game._trigger || !_rexBeingEaten)) {
+ _rexBeingEaten = true;
+ switch (_game._trigger) {
+ case 0:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _animationMode = 1;
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ _scene->_sequences.addTimer(10, 85);
+ break;
+
+ case 80:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 3, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], -1);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FC));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 81);
+ break;
+
+ case 81: {
+ int syncIdx = _globals._sequenceIndexes[9];
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 5, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 6, 38);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 82);
+ }
+ break;
+
+ case 82: {
+ int syncIdx = _globals._sequenceIndexes[9];
+ _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], false, 15, 5, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 39, 40);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 83);
+ }
+ break;
+
+ case 83: {
+ _animationMode = 2;
+ int syncIdx = _globals._sequenceIndexes[9];
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx);
+ _scene->_sequences.addTimer(60, 84);
+ }
+ break;
+
+ case 84:
+ _rexBeingEaten = false;
+ _animationMode = 0;
+ _scene->_reloadSceneFlag = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ case 85:
+ if (_rexBeingEaten && (_animationMode == 1)) {
+ _vm->_sound->command(12);
+ _scene->_sequences.addTimer(10, 85);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene608::preActions() {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+
+ if ((_action.isAction(VERB_THROW, NOUN_BONE, NOUN_REAR_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_REAR_OF_GARAGE)
+ || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_FRONT_OF_GARAGE)
+ || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) && _dogActiveFl) {
+ _game._player._stepEnabled = false;
+ _game._player.walk(Common::Point(56, 146), FACING_EAST);
+ }
+
+ if ((_action.isAction(VERB_THROW, NOUN_BONES, NOUN_AREA_BEHIND_CAR) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_AREA_BEHIND_CAR)
+ || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_DANGER_ZONE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_DANGER_ZONE)) && _dogActiveFl) {
+ _game._player._stepEnabled = false;
+ _game._player.walk(Common::Point(75, 136), FACING_EAST);
+ }
+
+ if (_action.isAction(VERB_PUSH, NOUN_DOWN_BUTTON) && _dogUnderCar) {
+ _buttonPressedonTimeFl = true;
+ _dogDeathMode = 1;
+ } else
+ _buttonPressedonTimeFl = false;
+}
+
+void Scene608::actions() {
+ if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY))
+ _scene->_nextSceneId = 607;
+ else if (_action.isAction(VERB_PUSH, NOUN_DOWN_BUTTON)) {
+ _game._player._stepEnabled = true;
+ switch (_game._trigger) {
+ case 0:
+ if ((_globals[kCarStatus] == CAR_UP) || (_globals[kCarStatus] == CAR_SQUASHES_DOG) || (_globals[kCarStatus] == CAR_SQUASHES_DOG_AGAIN)) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ } else
+ _vm->_dialogs->show(60839);
+ break;
+
+ case 1:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]);
+ _game._player._visible = true;
+ if (_dogDeathMode == 0)
+ _carMode = 0;
+ else if (_dogDeathMode == 1) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x300));
+ _globals[kCarStatus] = CAR_SQUASHES_DOG;
+ _carMode = 2;
+ _globals[kDogStatus] = DOG_DEAD;
+ _dogActiveFl = false;
+ _dogUnderCar = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[10]);
+ _scene->freeAnimation();
+ _scene->loadAnimation(formAnimName('C', -1));
+ } else {
+ _resetPositionsFl = false;
+ _carMode = 1;
+ _scene->freeAnimation();
+ _scene->loadAnimation(formAnimName('B', -1));
+ }
+
+ _carMoveMode = 2;
+ _scene->_sequences.addTimer(1, 2);
+ break;
+
+ case 2:
+ if (_carMoveMode != 0)
+ _scene->_sequences.addTimer(1, 2);
+ else {
+ _scene->_dynamicHotspots.remove(_carHotspotId);
+ int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25));
+ _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST);
+ if (_globals[kCarStatus] == CAR_SQUASHES_DOG)
+ _scene->_sequences.addTimer(120, 3);
+ else {
+ if (_dogDeathMode == 0)
+ _globals[kCarStatus] = CAR_DOWN;
+ else {
+ _globals[kCarStatus] = CAR_DOWN_ON_SQUASHED_DOG;
+ _carMode = 3;
+ _dogDeathMode = 2;
+ }
+ _game._player._stepEnabled = true;
+ }
+ }
+ break;
+
+ case 3:
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x302));
+ _globals[kCarStatus] = CAR_DOWN_ON_SQUASHED_DOG;
+ _carMode = 3;
+ _dogDeathMode = 2;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PUSH, NOUN_UP_BUTTON)) {
+ switch (_game._trigger) {
+ case 0:
+ if ((_globals[kCarStatus] == CAR_DOWN) || (_globals[kCarStatus] == CAR_DOWN_ON_SQUASHED_DOG)) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 3);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ } else
+ _vm->_dialogs->show(60840);
+ break;
+
+ case 1:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]);
+ _game._player._visible = true;
+ if (_dogDeathMode == 0)
+ _carMode = 0;
+ else {
+ _carMode = 3;
+ _resetPositionsFl = false;
+ _scene->freeAnimation();
+ _scene->loadAnimation(formAnimName('D', -1));
+ }
+ _carMoveMode = 1;
+ _scene->_sequences.addTimer(1, 2);
+ break;
+
+ case 2: {
+ if (_carMoveMode != 0)
+ _scene->_sequences.addTimer(1, 2);
+ else if (_dogDeathMode == 0)
+ _globals[kCarStatus] = CAR_UP;
+ else if (_dogDeathMode == 2) {
+ _globals[kCarStatus] = CAR_SQUASHES_DOG_AGAIN;
+ _carMode = 3;
+ _dogDeathMode = 2;
+ }
+ _scene->_dynamicHotspots.remove(_carHotspotId);
+ int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25));
+ _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST);
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_REAR_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_REAR_OF_GARAGE)
+ || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) {
+ _game._player._stepEnabled = true;
+ if (_dogActiveFl) {
+ if (_game._trigger == 0) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FE));
+ }
+ _throwMode = 4;
+ handleThrowingBone();
+ } else
+ _vm->_dialogs->show(60841);
+ } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_FRONT_OF_GARAGE)) {
+ _game._player._stepEnabled = true;
+ if (_dogActiveFl) {
+ if (_game._trigger == 0) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FD));
+ }
+ _throwMode = 5;
+ handleThrowingBone();
+ } else
+ _vm->_dialogs->show(60841);
+ } else if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_AREA_BEHIND_CAR) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_AREA_BEHIND_CAR)
+ || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_DANGER_ZONE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_DANGER_ZONE)) {
+ _game._player._stepEnabled = true;
+ if ((_globals[kCarStatus] == CAR_UP) && _dogActiveFl) {
+ if (_dogActiveFl) {
+ if (_game._trigger == 0) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x301));
+ }
+ _throwMode = 6;
+ handleThrowingBone();
+ } else
+ _vm->_dialogs->show(60841);
+ } else
+ _vm->_dialogs->show(60842);
+ } else if (_action.isAction(VERB_TAKE, NOUN_POLYCEMENT) && (_game._trigger || !_game._objects.isInInventory(OBJ_POLYCEMENT))) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _vm->_sound->command(9);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_polycementHotspotId);
+ break;
+
+ case 2:
+ _game._objects.addToInventory(OBJ_POLYCEMENT);
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->showItem(OBJ_POLYCEMENT, 60833);
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_REARVIEW_MIRROR) && (_game._trigger || !_game._objects.isInInventory(OBJ_REARVIEW_MIRROR))) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _vm->_sound->command(9);
+ _scene->_sequences.remove(_globals._sequenceIndexes[12]);
+ _game._objects.addToInventory(OBJ_REARVIEW_MIRROR);
+ _vm->_dialogs->showItem(OBJ_REARVIEW_MIRROR, 60827);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag) {
+ if (_game._difficulty != DIFFICULTY_HARD)
+ _vm->_dialogs->show(60810);
+ else if (_globals[kDogStatus] == DOG_DEAD)
+ _vm->_dialogs->show(60812);
+ else
+ _vm->_dialogs->show(60811);
+ } else if (_action.isAction(VERB_LOOK) && (_action.isObject(NOUN_MUFFLER) || _action.isObject(NOUN_CAR_SEAT) || _action.isObject(NOUN_HUBCAP)
+ || _action.isObject(NOUN_COILS) || _action.isObject(NOUN_QUARTER_PANEL)))
+ _vm->_dialogs->show(60813);
+ else if (_action.isAction(VERB_TAKE) && (_action.isObject(NOUN_MUFFLER) || _action.isObject(NOUN_CAR_SEAT) || _action.isObject(NOUN_HUBCAP)
+ || _action.isObject(NOUN_COILS) || _action.isObject(NOUN_QUARTER_PANEL)))
+ _vm->_dialogs->show(60814);
+ else if (_action.isAction(VERB_LOOK, NOUN_GARAGE_FLOOR) || _action.isAction(VERB_LOOK, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_LOOK, NOUN_REAR_OF_GARAGE)) {
+ if (_dogActiveFl)
+ _vm->_dialogs->show(60815);
+ else
+ _vm->_dialogs->show(60816);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SPARE_RIBS))
+ _vm->_dialogs->show(60817);
+ else if (_action.isAction(VERB_TAKE, NOUN_SPARE_RIBS)) {
+ if (_game._difficulty == DIFFICULTY_HARD)
+ _vm->_dialogs->show(60818);
+ else
+ _vm->_dialogs->show(60819);
+ } else if (_action.isAction(VERB_LOOK, NOUN_UP_BUTTON))
+ _vm->_dialogs->show(60820);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOWN_BUTTON))
+ _vm->_dialogs->show(60821);
+ else if (_action.isAction(VERB_LOOK, NOUN_TRASH_CAN))
+ _vm->_dialogs->show(60822);
+ else if (_action.isAction(VERB_LOOK, NOUN_CALENDAR))
+ _vm->_dialogs->show(60823);
+ else if (_action.isAction(VERB_LOOK, NOUN_STORAGE_BOX)) {
+ if (_game._objects[OBJ_REARVIEW_MIRROR]._roomNumber == _scene->_currentSceneId)
+ _vm->_dialogs->show(60825);
+ else
+ _vm->_dialogs->show(60824);
+ } else if (_action.isAction(VERB_OPEN, NOUN_STORAGE_BOX))
+ _vm->_dialogs->show(60826);
+ else if (_action.isAction(VERB_LOOK, NOUN_REARVIEW_MIRROR) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(60828);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOOL_BOX)) {
+ if (_game._objects[OBJ_POLYCEMENT]._roomNumber == _scene->_currentSceneId)
+ _vm->_dialogs->show(60829);
+ else
+ _vm->_dialogs->show(60830);
+ } else if (_action.isAction(VERB_OPEN, NOUN_TOOL_BOX))
+ _vm->_dialogs->show(60831);
+ else if ((_action.isAction(VERB_LOOK, NOUN_POLYCEMENT)) && (_game._objects.isInRoom(OBJ_POLYCEMENT)))
+ _vm->_dialogs->show(60832);
+ else if (_action.isAction(VERB_LOOK, NOUN_GREASE_CAN) || _action.isAction(VERB_LOOK, NOUN_OIL_CAN))
+ _vm->_dialogs->show(60834);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAR_LIFT))
+ _vm->_dialogs->show(60835);
+ else if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || _action.isAction(VERB_LOOK, NOUN_HAT))
+ _vm->_dialogs->show(60836);
+ else if (_action.isAction(VERB_LOOK, NOUN_DANGER_ZONE))
+ _vm->_dialogs->show(60838);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene609::Scene609(MADSEngine *vm) : Scene6xx(vm) {
+ _videoDoorMode = -1;
+}
+
+void Scene609::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsSint16LE(_videoDoorMode);
+}
+
+void Scene609::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene609::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('h', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_9");
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9");
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _globals[kBeenInVideoStore] = false;
+
+ if (_scene->_priorSceneId == 611) {
+ _game._player._playerPos = Common::Point(264, 69);
+ _game._player._facing = FACING_SOUTHWEST;
+ } else if (_scene->_priorSceneId == 610) {
+ _game._player._playerPos = Common::Point(23, 90);
+ _game._player._facing = FACING_EAST;
+ _scene->_sequences.addTimer(60, 60);
+ _game._player._stepEnabled = false;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(86, 136);
+ _game._player._facing = FACING_NORTHEAST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _scene->loadAnimation(formAnimName('R', 1), 70);
+ }
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_DOOR_KEY);
+ if (_game._difficulty != DIFFICULTY_EASY)
+ _game._objects.addToInventory(OBJ_PENLIGHT);
+ }
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0x305, 0x306, 0x307, 0x308, 0x309, 0);
+}
+
+void Scene609::step() {
+ switch (_game._trigger) {
+ case 60:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 61);
+ break;
+
+ case 61:
+ _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, false);
+ _game._player.walk(Common::Point(101, 100), FACING_EAST);
+ _scene->_sequences.addTimer(180, 62);
+ break;
+
+ case 62:
+ _scene->_sequences.remove( _globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, true);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 63);
+ break;
+
+ case 63:
+ if (!_globals[kHasTalkedToHermit] && (_game._difficulty != DIFFICULTY_HARD)) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(287, 73));
+ _scene->_sequences.setScale(_globals._sequenceIndexes[3], 47);
+ }
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(6, 71);
+ break;
+
+ case 71:
+ if (!_globals[kHasTalkedToHermit]) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(287, 73));
+ _scene->_sequences.setScale(_globals._sequenceIndexes[3], 47);
+ }
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 72:
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene609::enterStore() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ if (_videoDoorMode == 2)
+ _scene->_sequences.addTimer(1, 4);
+ else {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x305));
+ _scene->_sequences.addTimer(120, 1);
+ }
+ break;
+
+ case 1:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x306));
+ _scene->_sequences.addTimer(60, 2);
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 11, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]);
+ _game._player._visible = true;
+ _game._objects.setRoom(OBJ_DOOR_KEY, 1);
+ _scene->_sequences.addTimer(15, 4);
+ break;
+
+ case 4:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], true, 1);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addTimer(15, 5);
+ break;
+
+ case 5:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = true;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 6);
+ break;
+
+ case 6:
+ _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, false);
+ if (_videoDoorMode == 1) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(0x307));
+ }
+ _game._player.walk(Common::Point(23, 90), FACING_WEST);
+ _scene->_sequences.addTimer(180, 7);
+ break;
+
+ case 7:
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 8);
+ break;
+
+ case 8:
+ _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, true);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+ _globals[kBeenInVideoStore] = true;
+ _game._player._stepEnabled = true;
+ _scene->_nextSceneId = 610;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene609::preActions() {
+ if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_VIDEO_STORE_DOOR))
+ _game._player.walk(Common::Point(78, 99), FACING_NORTHWEST);
+}
+
+void Scene609::actions() {
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_ALLEY))
+ _scene->_nextSceneId = 611;
+ else if (_action.isAction(VERB_WALK_THROUGH, NOUN_VIDEO_STORE_DOOR)) {
+ if (!_globals[kBeenInVideoStore]) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x308));
+ _scene->_sequences.addTimer(120, 1);
+ break;
+
+ case 1:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], true, 1);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addTimer(30, 2);
+ break;
+
+ case 2:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(60, 3);
+ break;
+
+ case 3:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x309));
+ _scene->_sequences.addTimer(120, 4);
+ break;
+
+ case 4:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ _videoDoorMode = 2;
+ enterStore();
+ }
+ } else if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_VIDEO_STORE_DOOR)) {
+ _videoDoorMode = 1;
+ enterStore();
+ } else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx);
+ _scene->_sequences.addTimer(6, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_nextSceneId = 504;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(60910);
+ else if (_action.isAction(VERB_LOOK, NOUN_STREET))
+ _vm->_dialogs->show(60911);
+ else if (_action.isAction(VERB_LOOK, NOUN_SPOT_A_POT))
+ _vm->_dialogs->show(60912);
+ else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE))
+ _vm->_dialogs->show(60913);
+ else if (_action.isAction(VERB_LOOK, NOUN_BILLBOARD))
+ _vm->_dialogs->show(60914);
+ else if (_action.isAction(VERB_LOOK, NOUN_STATUE))
+ _vm->_dialogs->show(60915);
+ else if (_action.isAction(VERB_LOOK, NOUN_CAR))
+ _vm->_dialogs->show(60916);
+ else if (_action.isAction(VERB_LOOK, NOUN_NEWSSTAND))
+ _vm->_dialogs->show(60917);
+ else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE_DOOR)) {
+ if (!_globals[kBeenInVideoStore])
+ _vm->_dialogs->show(60918);
+ else
+ _vm->_dialogs->show(60919);
+ } else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET))
+ _vm->_dialogs->show(60730);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene610::Scene610(MADSEngine *vm) : Scene6xx(vm) {
+ _handsetHotspotId = -1;
+ _checkVal = -1;
+
+ _cellCharging = false;
+
+ _cellChargingTimer = -1;
+ _lastFrameTimer = 0;
+}
+
+void Scene610::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsSint16LE(_handsetHotspotId);
+ s.syncAsSint16LE(_checkVal);
+
+ s.syncAsByte(_cellCharging);
+
+ s.syncAsSint32LE(_cellChargingTimer);
+ s.syncAsUint32LE(_lastFrameTimer);
+}
+
+void Scene610::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_PHONE_HANDSET);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene610::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('p', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9");
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 1));
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 60, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 13);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 30, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9);
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _cellCharging = false;
+
+ if (_game._objects[OBJ_PHONE_HANDSET]._roomNumber == _scene->_currentSceneId) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0);
+ _handsetHotspotId = _scene->_dynamicHotspots.add(NOUN_PHONE_HANDSET, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_handsetHotspotId, Common::Point(132, 121), FACING_NORTHWEST);
+ if ((_globals[kHandsetCellStatus] == 2) && (_game._difficulty == DIFFICULTY_HARD) && !_globals[kDurafailRecharged])
+ _globals[kHandsetCellStatus] = 1;
+ }
+
+ if (_scene->_roomChanged && _game._difficulty != DIFFICULTY_EASY)
+ _game._objects.addToInventory(OBJ_PENLIGHT);
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(175, 152);
+ _game._player._facing = FACING_NORTHWEST;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene610::step() {
+ if (_cellCharging) {
+ long diff = _scene->_frameStartTime - _lastFrameTimer;
+ if ((diff >= 0) && (diff <= 60))
+ _cellChargingTimer += diff;
+ else
+ _cellChargingTimer++;
+
+ _lastFrameTimer = _scene->_frameStartTime;
+ }
+
+ // CHECKME: _checkVal is always false, could be removed
+ if ((_cellChargingTimer >= 60) && !_checkVal) {
+ _checkVal = true;
+ _globals[kHandsetCellStatus] = 1;
+ _cellCharging = false;
+ _checkVal = false;
+ _cellChargingTimer = 0;
+ }
+}
+
+void Scene610::actions() {
+ if (_action.isAction(VERB_EXIT_FROM, NOUN_VIDEO_STORE))
+ _scene->_nextSceneId = 609;
+ else if (_action.isAction(VERB_TAKE, NOUN_PHONE_HANDSET)) {
+ if ( _game._trigger || !_game._objects.isInInventory(OBJ_PHONE_HANDSET)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _vm->_sound->command(9);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_handsetHotspotId);
+ _game._objects.addToInventory(OBJ_PHONE_HANDSET);
+ _vm->_dialogs->showItem(OBJ_PHONE_HANDSET, 61017);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action.isAction(VERB_PUT, NOUN_PHONE_HANDSET, NOUN_PHONE_CRADLE)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0);
+ _handsetHotspotId = _scene->_dynamicHotspots.add(NOUN_PHONE_HANDSET, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(_handsetHotspotId, Common::Point(132, 121), FACING_NORTHWEST);
+ _game._objects.setRoom(OBJ_PHONE_HANDSET, _scene->_currentSceneId);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ if ((_globals[kHandsetCellStatus] == 2) && (_game._difficulty == DIFFICULTY_HARD) && !_globals[kDurafailRecharged])
+ _cellCharging = true;
+
+ _vm->_dialogs->show(61032);
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_PIPPY_BILLBOARD))
+ _vm->_dialogs->show(61010);
+ else if (_action.isAction(VERB_LOOK, NOUN_CIVILIZATION_AD))
+ _vm->_dialogs->show(61011);
+ else if (_action.isAction(VERB_LOOK, NOUN_MARX_BROS_POSTER))
+ _vm->_dialogs->show(61012);
+ else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_MONITOR))
+ _vm->_dialogs->show(61013);
+ else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE))
+ _vm->_dialogs->show(61014);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(61015);
+ else if (_action.isAction(VERB_LOOK, NOUN_LOGO))
+ _vm->_dialogs->show(61018);
+ else if (_action.isAction(VERB_LOOK, NOUN_CEMENT)) {
+ if (_game._visitedScenes.exists(601))
+ _vm->_dialogs->show(61020);
+ else
+ _vm->_dialogs->show(61019);
+ } else if (_action.isAction(VERB_LOOK, NOUN_COUNTER))
+ _vm->_dialogs->show(61021);
+ else if (_action.isAction(VERB_LOOK, NOUN_PHONE_ANTENNA))
+ _vm->_dialogs->show(61022);
+ else if (_action.isAction(VERB_LOOK, NOUN_SMELLY_SNEAKER))
+ _vm->_dialogs->show(61023);
+ else if (_action.isAction(VERB_TAKE, NOUN_SMELLY_SNEAKER))
+ _vm->_dialogs->show(61024);
+ else if (_action.isAction(VERB_LOOK, NOUN_SPOTLIGHT))
+ _vm->_dialogs->show(61025);
+ else if (_action.isAction(VERB_LOOK, NOUN_PHONE_HANDSET) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(61026);
+ else if (_action.isAction(VERB_LOOK, NOUN_PHONE_CRADLE))
+ _vm->_dialogs->show(61027);
+ else if (_action.isAction(VERB_LOOK, NOUN_RETURN_SLOT))
+ _vm->_dialogs->show(61028);
+ else if (_action.isAction(VERB_PUT, NOUN_RETURN_SLOT)
+ && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId)))
+ _vm->_dialogs->show(61029);
+ else if ( _action.isObject(NOUN_CLASSIC_VIDEOS) || _action.isObject(NOUN_MORE_CLASSIC_VIDEOS) || _action.isObject(NOUN_DRAMA_VIDEOS)
+ || _action.isObject(NOUN_NEW_RELEASE_VIDEOS) || _action.isObject(NOUN_PORNO_VIDEOS) || _action.isObject(NOUN_EDUCATIONAL_VIDEOS)
+ || _action.isObject(NOUN_INSTRUCTIONAL_VIDEOS) || _action.isObject(NOUN_WORKOUT_VIDEOS) || _action.isObject(NOUN_FOREIGN_VIDEOS)
+ || _action.isObject(NOUN_ADVENTURE_VIDEOS) || _action.isObject(NOUN_COMEDY_VIDEOS)) {
+ if (_action.isAction(VERB_LOOK))
+ _vm->_dialogs->show(61030);
+ else if (_action.isAction(VERB_TAKE))
+ _vm->_dialogs->show(61031);
+ else
+ return;
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene611::Scene611(MADSEngine *vm) : Scene6xx(vm), _defaultDialogPos(0, 0) {
+ _seenRatFl = false;
+ _eyesRunningFl = false;
+ _shouldRemoveEyes = false;
+ _ratPresentFl = false;
+ _duringDialogFl = false;
+ _resetBatterieText = false;
+ _hermitTalkingFl = false;
+ _hermitMovingFl = false;
+ _alreadyTalkingFl = false;
+ _giveBatteriesFl = false;
+ _startTradingFl = false;
+ _check1Fl = false;
+ _stickFingerFl = false;
+
+ _randVal = -1;
+ _ratHotspotId = -1;
+ _hermitDialogNode = -1;
+ _hermitDisplayedQuestion = -1;
+ _nextFrame = -1;
+ _hermitMode = -1;
+
+ _ratTimer = 0;
+}
+
+void Scene611::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsByte(_seenRatFl);
+ s.syncAsByte(_eyesRunningFl);
+ s.syncAsByte(_shouldRemoveEyes);
+ s.syncAsByte(_ratPresentFl);
+ s.syncAsByte(_duringDialogFl);
+ s.syncAsByte(_resetBatterieText);
+ s.syncAsByte(_hermitTalkingFl);
+ s.syncAsByte(_hermitMovingFl);
+ s.syncAsByte(_alreadyTalkingFl);
+ s.syncAsByte(_giveBatteriesFl);
+ s.syncAsByte(_startTradingFl);
+ s.syncAsByte(_check1Fl);
+ s.syncAsByte(_stickFingerFl);
+
+ s.syncAsSint16LE(_randVal);
+ s.syncAsSint16LE(_ratHotspotId);
+ s.syncAsSint16LE(_hermitDialogNode);
+ s.syncAsSint16LE(_hermitDisplayedQuestion);
+ s.syncAsSint16LE(_nextFrame);
+ s.syncAsSint16LE(_hermitMode);
+
+ s.syncAsUint32LE(_ratTimer);
+
+ s.syncAsSint16LE(_defaultDialogPos.x);
+ s.syncAsSint16LE(_defaultDialogPos.y);
+}
+
+void Scene611::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_RAT);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene611::handleRatMoves() {
+ _ratPresentFl = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 11, -2);
+ _ratTimer = _game._player._priorTimer;
+ _scene->_dynamicHotspots.remove(_ratHotspotId);
+}
+
+void Scene611::handleTrading() {
+ if (_game._objects.isInInventory(OBJ_DURAFAIL_CELLS))
+ _game._objects.setRoom(OBJ_DURAFAIL_CELLS, 1);
+
+ if (_game._objects.isInInventory(OBJ_PHONE_CELLS))
+ _game._objects.setRoom(OBJ_PHONE_CELLS, 1);
+
+ _game._objects.addToInventory(OBJ_FAKE_ID);
+}
+
+void Scene611::setDialogNode(int node) {
+ if (node > 0)
+ _hermitDialogNode = node;
+
+ _game._player._stepEnabled = true;
+
+ switch (node) {
+ case 0:
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _duringDialogFl = false;
+ _hermitDialogNode = 0;
+ break;
+
+ case 1:
+ _dialog1.start();
+ _duringDialogFl = true;
+ _hermitDialogNode = 1;
+ break;
+
+ case 2:
+ _dialog2.start();
+ _duringDialogFl = true;
+ _hermitDialogNode = 2;
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool Scene611::check2ChargedBatteries() {
+ if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS))
+ || (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS)))
+ return true;
+
+ return false;
+}
+
+bool Scene611::check4ChargedBatteries() {
+ if (_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS)
+ && _globals[kDurafailRecharged])
+ return true;
+
+ return false;
+}
+
+void Scene611::handleTalking(int delay) {
+ if (_hermitTalkingFl)
+ _alreadyTalkingFl = true;
+
+ _hermitTalkingFl = true;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(delay, 100);
+}
+
+void Scene611::handleSubDialog1() {
+ switch (_action._activeAction._verbId) {
+ case 0x287:
+ _stickFingerFl = true;
+ _nextFrame = 34;
+ _hermitMovingFl = false;
+ _hermitMode = 5;
+ displayHermitQuestions(5);
+ _dialog1.write(0x287, false);
+ if (!_dialog1.read(0x288))
+ _dialog1.write(0x28E, true);
+
+ _dialog2.write(0x29C, true);
+ _dialog2.write(0x29D, true);
+ _dialog2.write(0x29E, true);
+ setDialogNode(2);
+ break;
+
+ case 0x288:
+ handleTalking(500);
+ displayHermitQuestions(6);
+ _dialog1.write(0x288, false);
+ _dialog1.write(0x289, true);
+ if (!_dialog1.read(0x287))
+ _dialog1.write(0x28E, true);
+
+ setDialogNode(1);
+ break;
+
+ case 0x289:
+ handleTalking(500);
+ displayHermitQuestions(10);
+ _dialog1.write(0x289, false);
+ _dialog1.write(0x28A, true);
+ _dialog1.write(0x28B, true);
+ setDialogNode(1);
+ break;
+
+ case 0x28A:
+ handleTalking(500);
+ displayHermitQuestions(11);
+ _dialog1.write(0x28A, false);
+ setDialogNode(1);
+ break;
+
+ case 0x28B:
+ handleTalking(500);
+ displayHermitQuestions(12);
+ _dialog1.write(0x28C, true);
+ _dialog1.write(0x28D, true);
+ _dialog1.write(0x28B, false);
+ setDialogNode(1);
+ break;
+
+ case 0x28C:
+ handleTalking(500);
+ displayHermitQuestions(13);
+ _dialog1.write(0x28C, false);
+ setDialogNode(1);
+ break;
+
+ case 0x28D:
+ handleTalking(500);
+ displayHermitQuestions(14);
+ _dialog1.write(0x290, true);
+ _dialog1.write(0x28D, false);
+ _dialog1.write(0x28F, true);
+ setDialogNode(1);
+ break;
+
+ case 0x28E:
+ handleTalking(500);
+ displayHermitQuestions(15);
+ _dialog1.write(0x295, true);
+ _dialog1.write(0x28E, false);
+ setDialogNode(1);
+ break;
+
+ case 0x290:
+ handleTalking(500);
+ displayHermitQuestions(17);
+ _dialog1.write(0x290, false);
+ if (!_dialog1.read(0x28F))
+ _dialog1.write(0x291, true);
+
+ setDialogNode(1);
+ break;
+
+ case 0x291:
+ handleTalking(500);
+ displayHermitQuestions(18);
+ _dialog1.write(0x291, false);
+ if ((!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) && (!_game._objects.isInInventory(OBJ_PHONE_CELLS))) {
+ _dialog1.write(0x292, true);
+ _dialog1.write(0x293, true);
+ }
+
+ if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) || (_game._objects.isInInventory(OBJ_PHONE_CELLS)))
+ _dialog1.write(0x294, true);
+
+ if (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS))
+ _globals[kExecuted_1_11] = true;
+
+ setDialogNode(1);
+ break;
+
+ case 0x28F:
+ handleTalking(500);
+ displayHermitQuestions(16);
+ _dialog1.write(0x28F, false);
+ if (!_dialog1.read(0x290))
+ _dialog1.write(0x291, true);
+
+ setDialogNode(1);
+ break;
+
+ case 0x295:
+ handleTalking(500);
+ displayHermitQuestions(20);
+ _dialog1.write(0x295, false);
+ setDialogNode(1);
+ break;
+
+ case 0x292:
+ handleTalking(500);
+ displayHermitQuestions(19);
+ _dialog1.write(0x292, false);
+ _dialog1.write(0x293, false);
+ setDialogNode(1);
+ break;
+
+ case 0x293: {
+ handleTalking(200);
+ _scene->_kernelMessages.reset();
+
+ Common::String curQuote = _game.getQuote(0x2D1);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 120, curQuote);
+
+ curQuote = _game.getQuote(0x2D2);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote);
+
+ _dialog1.write(0x293, false);
+ setDialogNode(0);
+ }
+ break;
+
+ case 0x294: {
+ bool hermitPleasedFl = false;
+
+ switch (_game._difficulty) {
+ case DIFFICULTY_EASY:
+ hermitPleasedFl = _game._objects.isInInventory(OBJ_DURAFAIL_CELLS) || _game._objects.isInInventory(OBJ_PHONE_CELLS);
+ break;
+
+ case DIFFICULTY_MEDIUM:
+ hermitPleasedFl = _game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS);
+ break;
+
+ default: // HARD
+ hermitPleasedFl = check4ChargedBatteries();
+ break;
+ }
+
+ if (hermitPleasedFl) {
+ _hermitDisplayedQuestion = 21;
+ if (!_giveBatteriesFl)
+ setDialogNode(0);
+ else
+ _giveBatteriesFl = false;
+ } else if (((_game._difficulty == DIFFICULTY_MEDIUM) || (_game._difficulty == DIFFICULTY_HARD)) && check2ChargedBatteries()) {
+ _hermitDisplayedQuestion = 22;
+ if (!_giveBatteriesFl)
+ setDialogNode(0);
+ else
+ _giveBatteriesFl = false;
+ } else {
+ _hermitDisplayedQuestion = 23;
+ if (!_giveBatteriesFl)
+ setDialogNode(0);
+ else
+ _giveBatteriesFl = false;
+ }
+ _startTradingFl = true;
+ }
+ break;
+
+ case 0x296: {
+ _scene->_kernelMessages.reset();
+
+ Common::String curQuote = _game.getQuote(0x2E6);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote);
+
+ setDialogNode(0);
+ handleTalking(200);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene611::handleSubDialog2() {
+ switch (_action._activeAction._verbId) {
+ case 0x29C:
+ displayHermitQuestions(7);
+ setDialogNode(1);
+ handleTalking(500);
+ break;
+
+ case 0x29D:
+ displayHermitQuestions(8);
+ setDialogNode(1);
+ handleTalking(500);
+ break;
+
+ case 0x29E:
+ displayHermitQuestions(9);
+ setDialogNode(1);
+ handleTalking(500);
+ break;
+
+ case 0x29F: {
+ _scene->_kernelMessages.reset();
+ Common::String curQuote = _game.getQuote(0x2A7);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote);
+ setDialogNode(0);
+ _dialog2.write(0x29F, false);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene611::handleDialog() {
+ if (_game._trigger == 0) {
+ _scene->_kernelMessages.reset();
+ _game._player._stepEnabled = false;
+
+ Common::String curQuote = _game.getQuote(_action._activeAction._verbId);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+
+ if (width > 200) {
+ Common::String subQuote1, subQuote2;
+ _game.splitQuote(curQuote, subQuote1, subQuote2);
+ _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 150, subQuote1);
+
+ if (_action._activeAction._verbId == 0x29D)
+ _scene->_kernelMessages.add(Common::Point(-18, 0), 0x1110, 34, 1, 150, subQuote2);
+ else if (_action._activeAction._verbId == 0x28A)
+ _scene->_kernelMessages.add(Common::Point(-10, 0), 0x1110, 34, 1, 150, subQuote2);
+ else
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 150, subQuote2);
+
+ _scene->_sequences.addTimer(170, 50);
+ } else {
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote);
+ _scene->_sequences.addTimer(140, 50);
+ }
+ } else if (_game._trigger == 50) {
+ if (_hermitDialogNode == 1)
+ handleSubDialog1();
+ else if (_hermitDialogNode == 2)
+ handleSubDialog2();
+ }
+}
+
+void Scene611::displayHermitQuestions(int question) {
+ _scene->_kernelMessages.reset();
+ _hermitDisplayedQuestion = question;
+
+ switch (question) {
+ case 1: {
+ Common::String curQuote = _game.getQuote(0x281);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x282);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 2: {
+ Common::String curQuote = _game.getQuote(0x283);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x284);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 3: {
+ Common::String curQuote = _game.getQuote(0x285);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 4: {
+ Common::String curQuote = _game.getQuote(0x286);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 5: {
+ Common::String curQuote = _game.getQuote(0x297);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y - 14), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x298);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x299);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 6: {
+ Common::String curQuote = _game.getQuote(0x29A);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x29B);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 7: {
+ Common::String curQuote = _game.getQuote(0x2A0);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2A1);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 8: {
+ Common::String curQuote = _game.getQuote(0x2A2);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2A3);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2A4);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 9: {
+ Common::String curQuote = _game.getQuote(0x2A5);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2A6);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 10: {
+ Common::String curQuote = _game.getQuote(0x2A8);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2A9);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2AA);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 11: {
+ Common::String curQuote = _game.getQuote(0x2AB);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2AC);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2AD);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2AE);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 12: {
+ Common::String curQuote = _game.getQuote(0x2AF);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2B0);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2B1);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2B2);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 13: {
+ Common::String curQuote = _game.getQuote(0x2B3);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2B4);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2B5);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2B6);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B7));
+ _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 73), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B8));
+ _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 87), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B9));
+ }
+ break;
+
+ case 14: {
+ Common::String curQuote = _game.getQuote(0x2BA);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2BB);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2BC);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2BD);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 15: {
+ Common::String curQuote = _game.getQuote(0x2BE);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2BF);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2C0);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2C1);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 16: {
+ Common::String curQuote = _game.getQuote(0x2C2);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2C3);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2C4);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2C5);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2C6);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 17: {
+ Common::String curQuote = _game.getQuote(0x2C7);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2C8);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2C0);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2CA);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 18: {
+ Common::String curQuote = _game.getQuote(0x2CB);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2CC);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2CD);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 19: {
+ Common::String curQuote = _game.getQuote(0x2CE);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2CF);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2D0);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 20: {
+ Common::String curQuote = _game.getQuote(0x2E1);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2E2);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2E3);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2E4);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2E5);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 21: {
+ Common::String curQuote = _game.getQuote(0x2D3);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2D4);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2D5);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2D6);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote);
+
+ curQuote = _game.getQuote(0x2D7);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote);
+ }
+ break;
+
+ case 22: {
+ Common::String curQuote = _game.getQuote(0x2D8);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 700, curQuote);
+
+ curQuote = _game.getQuote(0x2D9);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 700, curQuote);
+
+ curQuote = _game.getQuote(0x2DA);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 700, curQuote);
+
+ curQuote = _game.getQuote(0x2DB);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 700, curQuote);
+ }
+ break;
+
+ case 23: {
+ Common::String curQuote = _game.getQuote(0x2DC);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 700, curQuote);
+
+ curQuote = _game.getQuote(0x2DD);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 700, curQuote);
+
+ curQuote = _game.getQuote(0x2DE);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 700, curQuote);
+
+ curQuote = _game.getQuote(0x2DF);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 700, curQuote);
+
+ curQuote = _game.getQuote(0x2E0);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 700, curQuote);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene611::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9");
+
+ _game.loadQuoteSet(0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, 0x282, 0x283, 0x284,
+ 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, 0x291, 0x292,
+ 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0,
+ 0x2A1, 0x2A2, 0x2A3, 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, 0x2AA, 0x2AB, 0x2AC, 0x2AD, 0x2AE,
+ 0x2AF, 0x2B0, 0x2B1, 0x2B2, 0x2B3, 0x2B4, 0x2B5, 0x2B6, 0x2B7, 0x2B8, 0x2B9, 0x2BA, 0x2BB, 0x2BC,
+ 0x2BD, 0x2BE, 0x2BF, 0x2C0, 0x2C1, 0x2C2, 0x2C3, 0x2C4, 0x2C5, 0x2C6, 0x2C7, 0x2C8, 0x2C9, 0x2CA,
+ 0x2CB, 0x2CC, 0x2CD, 0x2CE, 0x2CF, 0x2D0, 0x2D1, 0x2D2, 0x2D3, 0x2D4, 0x2D5, 0x2D6, 0x2D7, 0x2D8,
+ 0x2D9, 0x2DA, 0x2DB, 0x2DC, 0x2DD, 0x2DE, 0x2DF, 0x2E0, 0x2E1, 0x2E2, 0x2E3, 0x2E4, 0x2E5, 0x2E6,
+ 0x323, 0x324, 0);
+
+ _dialog1.setup(0x82, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290,
+ 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0);
+
+ _dialog2.setup(0x83, 0x29C, 0x29D, 0x29E, 0x29F, 0);
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ _dialog1.set(0x82, 0x287, 0x288, 0x296, 0);
+ _dialog2.set(0x83, 0x29F, 0);
+ }
+
+ _vm->_palette->setEntry(252, 51, 51, 47);
+ _vm->_palette->setEntry(253, 37, 37, 37);
+
+ _ratPresentFl = false;
+ _seenRatFl = true;
+ _eyesRunningFl = false;
+ _shouldRemoveEyes = false;
+ _randVal = 0;
+ _defaultDialogPos = Common::Point(264, 43);
+ _giveBatteriesFl = false;
+ _resetBatterieText = false;
+ _alreadyTalkingFl = false;
+ _startTradingFl = false;
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(22, 132);
+ _game._player._facing = FACING_EAST;
+ _duringDialogFl = false;
+ }
+
+ if (!_globals[kHasTalkedToHermit]) {
+ _scene->loadAnimation(Resources::formatName(611, 'h', -1, EXT_AA, ""), 0);
+ _nextFrame = 47;
+ _hermitMode = 1;
+ _hermitTalkingFl = false;
+ _hermitMovingFl = true;
+ _check1Fl = true;
+ _stickFingerFl = false;
+ } else {
+ _hermitMode = 0;
+ _scene->_hotspots.activate(NOUN_HERMIT, false);
+ }
+
+ // CHECKME: The last line of the block looks extremely useless
+ if (_globals[kExecuted_1_11]) {
+ _dialog1.write(0x294, true);
+ _dialog1.write(0x292, false);
+ _globals[kExecuted_1_11] = true;
+ }
+
+ if (_duringDialogFl) {
+ _game._player._playerPos = Common::Point(237, 129);
+ _game._player._facing = FACING_NORTHEAST;
+
+ switch (_hermitDialogNode) {
+ case 0:
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _hermitDialogNode = 1;
+ break;
+
+ case 1:
+ _dialog1.start();
+ break;
+
+ case 2:
+ _dialog2.start();
+ break;
+
+ default:
+ break;
+ }
+ displayHermitQuestions(_hermitDisplayedQuestion);
+ }
+
+ sceneEntrySound();
+}
+
+void Scene611::step() {
+ if (_seenRatFl && (_vm->getRandomNumber(1, 100) == 10)) {
+ _seenRatFl = false;
+ _scene->_sequences.addTimer(1, 80);
+ }
+
+ if (_game._trigger == 80) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 8);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _ratPresentFl = true;
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 81);
+ } else if (_game._trigger == 81) {
+ int syncId = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 20, 0, 0, 0);
+ int idx = _scene->_dynamicHotspots.add(NOUN_RAT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _ratHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(272, 154), FACING_SOUTHEAST);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 9, 10);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncId);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ _ratTimer = _game._player._priorTimer;
+ }
+
+ if (_ratPresentFl && ((_game._player._priorTimer - _ratTimer) > 1200))
+ handleRatMoves();
+
+ if (!_eyesRunningFl) {
+ _randVal = _vm->getRandomNumber(1, 30);
+ _eyesRunningFl = true;
+ _scene->_sequences.addTimer(1, 70);
+ }
+
+ if (_game._trigger == 70) {
+ switch (_randVal) {
+ case 2:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _shouldRemoveEyes = true;
+ _scene->_sequences.addTimer(60, 71);
+ break;
+
+ case 6:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 12, 3, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 4);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ break;
+
+ case 7:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _shouldRemoveEyes = true;
+ _scene->_sequences.addTimer(60, 71);
+ break;
+
+ case 9:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _shouldRemoveEyes = true;
+ _scene->_sequences.addTimer(60, 71);
+ break;
+
+ case 13:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _shouldRemoveEyes = true;
+ _scene->_sequences.addTimer(60, 71);
+ break;
+
+ case 14:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _shouldRemoveEyes = true;
+ _scene->_sequences.addTimer(60, 71);
+ break;
+
+ case 15:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 24, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, 8);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ break;
+
+ case 17:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 20, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 9, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ break;
+
+ case 21:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 9);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _shouldRemoveEyes = true;
+ _scene->_sequences.addTimer(60, 71);
+ break;
+
+ case 25:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 10);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _shouldRemoveEyes = true;
+ _scene->_sequences.addTimer(60, 71);
+ break;
+
+ case 27:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _shouldRemoveEyes = true;
+ _scene->_sequences.addTimer(60, 71);
+ break;
+
+ case 29:
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 20, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ break;
+
+ default:
+ _scene->_sequences.addTimer(1, 71);
+ break;
+ }
+ }
+
+ if (_game._trigger == 71) {
+ if (_shouldRemoveEyes) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _shouldRemoveEyes = false;
+ }
+ _eyesRunningFl = false;
+ _randVal = 0;
+ }
+
+ if (_game._trigger == 100) {
+ if (_alreadyTalkingFl)
+ _alreadyTalkingFl = false;
+ else
+ _hermitMovingFl = true;
+ }
+
+ if (_stickFingerFl && (_scene->_activeAnimation->getCurrentFrame() == 47)) {
+ _stickFingerFl = false;
+ _hermitMovingFl = true;
+ _hermitMode = 1;
+ }
+
+ if (_scene->_activeAnimation != nullptr && (_scene->_activeAnimation->getCurrentFrame() == 240) && _check1Fl) {
+ _check1Fl = false;
+ _scene->_kernelMessages.add(Common::Point(33, 88), 0xFDFC, 0, 0, 90, _game.getQuote(0x27E));
+ _scene->_sequences.addTimer(120, 120);
+ }
+
+ if (_game._trigger == 120) {
+ int msgIdx = _scene->_kernelMessages.add(Common::Point(28, 102), 0xFDFC, 0, 0, 90, _game.getQuote(0x27F));
+ _scene->_kernelMessages.setQuoted(msgIdx, 4, true);
+ _scene->_sequences.addTimer(100, 121);
+ }
+
+ if (_game._trigger == 121) {
+ int msgIdx = _scene->_kernelMessages.add(Common::Point(23, 116), 0xFDFC, 0, 0, 90, _game.getQuote(0x280));
+ _scene->_kernelMessages.setQuoted(msgIdx, 4, true);
+ }
+
+ if (_hermitMode == 1) {
+ if (_startTradingFl) {
+ _hermitMode = 6;
+ _hermitMovingFl = false;
+ _hermitTalkingFl = false;
+ _scene->_sequences.addTimer(1, 110);
+ } else if (_hermitTalkingFl) {
+ _hermitMode = 2;
+ _nextFrame = 18;
+ _hermitMovingFl = false;
+ } else {
+ switch (_vm->getRandomNumber(1, 5)) {
+ case 1:
+ _nextFrame = 46;
+ break;
+
+ case 2:
+ _nextFrame = 47;
+ break;
+
+ case 3:
+ _nextFrame = 48;
+ break;
+
+ case 4:
+ _nextFrame = 49;
+ break;
+
+ case 5:
+ _nextFrame = 50;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (_hermitMode == 2) {
+ if (_startTradingFl) {
+ _hermitMode = 6;
+ _hermitMovingFl = false;
+ _hermitTalkingFl = false;
+ _scene->_sequences.addTimer(1, 110);
+ } else if (_hermitMovingFl) {
+ _hermitMode = 1;
+ _nextFrame = 47;
+ _hermitTalkingFl = false;
+ } else {
+ switch (_vm->getRandomNumber(1, 4)) {
+ case 1:
+ _nextFrame = 18;
+ break;
+
+ case 2:
+ _nextFrame = 20;
+ break;
+
+ case 3:
+ _nextFrame = 22;
+ break;
+
+ case 4:
+ _nextFrame = 24;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (_scene->_activeAnimation != nullptr && _scene->_activeAnimation->getCurrentFrame() == 254)
+ _game._player._stepEnabled = true;
+
+ if (_game._trigger == 110) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 111);
+ }
+
+ if (_game._trigger == 111) {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _nextFrame = 1;
+ }
+
+ if (_game._trigger == 112) {
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = true;
+ }
+
+ if (_hermitMode == 6) {
+ if ((_scene->_activeAnimation->getCurrentFrame() == 9) && _check1Fl) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 112);
+ _check1Fl = false;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() == 17) && !_check1Fl) {
+ _nextFrame = 26;
+ _hermitMode = 4;
+ _check1Fl = true;
+ }
+ }
+
+ if (_hermitMode == 4) {
+ if ((_scene->_activeAnimation->getCurrentFrame() == 33) && _check1Fl) {
+ displayHermitQuestions(_hermitDisplayedQuestion);
+ _nextFrame = 1;
+ _check1Fl = false;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() == 9) && !_check1Fl) {
+ _nextFrame = 8;
+ _scene->_sequences.addTimer(1, 113);
+ _check1Fl = true;
+ }
+ }
+
+ if (_game._trigger == 113) {
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 114);
+ }
+
+ if (_game._trigger == 114) {
+ _resetBatterieText = true;
+ int syncIdx = _globals._sequenceIndexes[3];
+ _nextFrame = 10;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 115);
+ }
+
+ if ((_nextFrame >= 0) && (_nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(_nextFrame);
+ _nextFrame = -1;
+ }
+
+ if (_game._trigger == 115) {
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player._visible = true;
+ if (_hermitDisplayedQuestion == 21) {
+ _game._player._stepEnabled = false;
+ handleTrading();
+ _hermitMode = 0;
+ _startTradingFl = false;
+ _nextFrame = 52;
+ _globals[kHasTalkedToHermit] = true;
+ _scene->_hotspots.activate(NOUN_HERMIT, false);
+ } else {
+ _game._player._stepEnabled = true;
+ _hermitMode = 1;
+ _nextFrame = 47;
+ _hermitTalkingFl = false;
+ _startTradingFl = false;
+ _check1Fl = true;
+ }
+ }
+}
+
+void Scene611::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_ALLEY))
+ _game._player._walkOffScreenSceneId = 609;
+
+ if (_resetBatterieText)
+ _scene->_kernelMessages.reset();
+}
+
+void Scene611::actions() {
+ if (_game._screenObjects._inputMode == kInputConversation)
+ handleDialog();
+ else if ((_action.isAction(VERB_GIVE, NOUN_PHONE_CELLS, NOUN_HERMIT)) || (_action.isAction(VERB_GIVE, NOUN_DURAFAIL_CELLS, NOUN_HERMIT))) {
+ _action._activeAction._verbId = 0x294;
+ _giveBatteriesFl = true;
+ handleSubDialog1();
+ } else if (_action.isAction(VERB_GIVE, NOUN_HERMIT)) {
+ _scene->_kernelMessages.reset();
+
+ Common::String curQuote = _game.getQuote(0x323);
+ int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ int quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 120, curQuote);
+
+ curQuote = _game.getQuote(0x324);
+ width = _vm->_font->getWidth(curQuote, _scene->_textSpacing);
+ quotePosX = _defaultDialogPos.x - (width / 2);
+ _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote);
+ } else if (_game._trigger == 90) {
+ if (_dialog2.read(0x29C) && _dialog2.read(0x29D) && _dialog2.read(0x29E)) {
+ handleTalking(180);
+ if (_vm->getRandomNumber(1, 2) == 1)
+ displayHermitQuestions(1);
+ else
+ displayHermitQuestions(2);
+ } else {
+ handleTalking(180);
+ if (_vm->getRandomNumber(1, 2) == 1)
+ displayHermitQuestions(3);
+ else
+ displayHermitQuestions(4);
+ }
+
+ _duringDialogFl = true;
+ if (_dialog2.read(0x29F)) {
+ _hermitDialogNode = 1;
+ _dialog1.start();
+ _duringDialogFl = true;
+ } else {
+ _hermitDialogNode = 2;
+ _dialog2.write(0x29F, true);
+ _dialog2.start();
+ _duringDialogFl = true;
+ }
+ } else if (_action.isAction(VERB_TALKTO, NOUN_HERMIT)) {
+ if (!_dialog1.read(0x287)) {
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x27A));
+ _scene->_sequences.addTimer(120, 90);
+ } else {
+ int nextQuote = 0;
+ switch (_vm->getRandomNumber(1, 3)) {
+ case 1:
+ nextQuote = 0x27B;
+ break;
+
+ case 2:
+ nextQuote = 0x27C;
+ break;
+
+ case 3:
+ nextQuote = 0x27D;
+ break;
+ }
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(nextQuote));
+ _scene->_sequences.addTimer(120, 90);
+ }
+ } else if ((_action.isAction(VERB_WALKTO) || _action.isAction(VERB_LOOK)) && _action.isObject(NOUN_RAT)) {
+ switch (_game._trigger) {
+ case 0:
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x279));
+ _scene->_sequences.addTimer(60, 1);
+ break;
+
+ case 1:
+ handleRatMoves();
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag) {
+ if (_globals[kHasTalkedToHermit])
+ _vm->_dialogs->show(61111);
+ else
+ _vm->_dialogs->show(61110);
+ } else if (_action.isAction(VERB_LOOK, NOUN_HERMIT))
+ _vm->_dialogs->show(61112);
+ else if (_action.isAction(VERB_LOOK, NOUN_TRASH))
+ _vm->_dialogs->show(61113);
+ else if (_action.isAction(VERB_TAKE, NOUN_TRASH))
+ _vm->_dialogs->show(61114);
+ else if (_action.isAction(VERB_LOOK, NOUN_CARDBOARD_BOX))
+ _vm->_dialogs->show(61115);
+ else if (_action.isAction(VERB_TAKE, NOUN_CARDBOARD_BOX))
+ _vm->_dialogs->show(61116);
+ else if (_action.isAction(VERB_OPEN, NOUN_CARDBOARD_BOX))
+ _vm->_dialogs->show(61117);
+ else if (_action.isAction(VERB_LOOK, NOUN_REFRIGERATOR))
+ _vm->_dialogs->show(61118);
+ else if (_action.isAction(VERB_OPEN, NOUN_REFRIGERATOR))
+ _vm->_dialogs->show(61119);
+ else if (_action.isAction(VERB_TAKE, NOUN_REFRIGERATOR))
+ _vm->_dialogs->show(61120);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
+ _vm->_dialogs->show(61121);
+ else if (_action.isAction(VERB_LOOK, NOUN_GRAFFITI))
+ _vm->_dialogs->show(61122);
+ else if (_action.isAction(VERB_LOOK, NOUN_METAL_PIPE))
+ _vm->_dialogs->show(61123);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene612::Scene612(MADSEngine *vm) : Scene6xx(vm) {
+ _actionMode = -1;
+ _cycleIndex = -1;
+}
+
+void Scene612::synchronize(Common::Serializer &s) {
+ Scene6xx::synchronize(s);
+
+ s.syncAsSint16LE(_actionMode);
+ s.syncAsSint16LE(_cycleIndex);
+}
+
+void Scene612::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_FISHING_LINE);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene612::handleWinchMovement() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 5);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 5, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ // CHECKME: Is the "else" block useful as action is always equal to 1 at this point?
+ // Or is it a missing bit of code we could fix?
+ if (_actionMode == 1) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 7, 0, 0);
+ _vm->_sound->command(19);
+ _game._objects.setRoom(OBJ_PADLOCK_KEY, 1);
+ _globals[kBoatRaised] = false;
+ } else {
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 17, 9, 0, 0);
+ _vm->_sound->command(18);
+ }
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]);
+ _game._player._visible = true;
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, _cycleIndex);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F4));
+ _game._player._stepEnabled = true;
+
+ _vm->_dialogs->show(61217);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene612::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('p', -1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_3");
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXRC_6");
+
+ if ((_globals[kLineStatus] == 2) || (_globals[kLineStatus] == 3)) {
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', -1));
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(34, 117), FACING_SOUTHEAST);
+ }
+
+ if (_globals[kBoatRaised])
+ _cycleIndex = -2;
+ else
+ _cycleIndex = -1;
+
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, _cycleIndex);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1);
+
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(280, 75);
+ _game._player._facing = FACING_SOUTHWEST;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 3);
+ _scene->loadAnimation(formAnimName('R', 1), 70);
+ }
+
+ sceneEntrySound();
+
+ if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_PADLOCK_KEY);
+
+ _game.loadQuoteSet(0x2F5, 0x2F4, 0);
+}
+
+void Scene612::step() {
+ switch (_game._trigger) {
+ case 70:
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _scene->_sequences.addTimer(6, 71);
+ break;
+
+ case 71:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72);
+ break;
+
+ case 72:
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene612::actions() {
+ if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 3);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx);
+ _scene->_sequences.addTimer(6, 2);
+ }
+ break;
+
+ case 2:
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], true, 10, 1, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], true, -2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _scene->_nextSceneId = 504;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_CONTROL_BOX)) {
+ _cycleIndex = -2;
+ _actionMode = 1;
+ handleWinchMovement();
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_EXPRESSWAY))
+ _vm->_dialogs->show(61210);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROPE) || _action.isAction(VERB_LOOK, NOUN_ARMATURE)) {
+ if (_globals[kBoatRaised])
+ _vm->_dialogs->show(61211);
+ else
+ _vm->_dialogs->show(61212);
+ } else if (_action.isAction(VERB_TAKE, NOUN_ROPE))
+ _vm->_dialogs->show(61213);
+ else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_BOX)) {
+ if (_globals[kBoatRaised])
+ _vm->_dialogs->show(61214);
+ else
+ _vm->_dialogs->show(61216);
+ } else if (_action.isAction(VERB_OPEN, NOUN_CONTROL_BOX))
+ _vm->_dialogs->show(61215);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDINGS))
+ _vm->_dialogs->show(61218);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOME))
+ _vm->_dialogs->show(61219);
+ else if (_action.isAction(VERB_LOOK, NOUN_STATUE))
+ _vm->_dialogs->show(61220);
+ else if (_action.isAction(VERB_LOOK, NOUN_MAINTENANCE_BUILDING))
+ _vm->_dialogs->show(61221);
+ else if (_action.isAction(VERB_OPEN, NOUN_MAINTENANCE_BUILDING))
+ _vm->_dialogs->show(61222);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(61223);
+ else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT))
+ _vm->_dialogs->show(61224);
+ else if (_action.isAction(VERB_WALK_DOWN, NOUN_EXPRESSWAY_TO_EAST) || _action.isAction(VERB_WALK_DOWN, NOUN_EXPRESSWAY_TO_WEST))
+ _vm->_dialogs->show(61225);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene620::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+}
+
+void Scene620::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_sequences.addTimer(30, 70);
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ sceneEntrySound();
+}
+
+void Scene620::step() {
+ switch (_game._trigger) {
+ case 70:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->loadAnimation(formAnimName('E', -1), 71);
+ break;
+
+ case 71:
+ if (_scene->_priorSceneId == 751) {
+ _globals[kCityFlooded] = true;
+ _globals[kTeleporterRoom + 5] = 0;
+ _scene->_nextSceneId = 701;
+ } else if (_scene->_priorSceneId == 752) {
+ _globals[kCityFlooded] = true;
+ _globals[kTeleporterRoom + 5] = 0;
+ _scene->_nextSceneId = 702;
+ } else if (_scene->_priorSceneId < 501 || _scene->_priorSceneId > 752) {
+ _globals[kCityFlooded] = true;
+ _globals[kTeleporterRoom + 5] = 0;
+ _scene->_nextSceneId = _scene->_priorSceneId;
+ } else if (_scene->_priorSceneId >= 501 && _scene->_priorSceneId <= 612) {
+ _globals[kResurrectRoom] = _globals[kHoverCarLocation];
+ _game._objects.addToInventory(OBJ_TIMEBOMB);
+ _globals[kTimebombStatus] = 0;
+ _globals[kTimebombTimer] = 0;
+ _scene->_nextSceneId = 605;
+ }
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Nebular
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes6.h b/engines/mads/nebular/nebular_scenes6.h
new file mode 100644
index 0000000000..c5cac56626
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes6.h
@@ -0,0 +1,322 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_NEBULAR_SCENES6_H
+#define MADS_NEBULAR_SCENES6_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+class Scene6xx : public NebularScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void setAAName();
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix();
+
+ void sceneEntrySound();
+
+public:
+ Scene6xx(MADSEngine *vm) : NebularScene(vm) {}
+};
+
+class Scene601 : public Scene6xx{
+public:
+ Scene601(MADSEngine *vm) : Scene6xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene602 : public Scene6xx{
+private:
+ int _lastSpriteIdx;
+ int _lastSequenceIdx;
+ int _cycleIndex;
+ int _safeMode;
+
+ void handleSafeActions();
+
+public:
+ Scene602(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene603 : public Scene6xx{
+private:
+ int _compactCaseHotspotId;
+ int _noteHotspotId;
+
+public:
+ Scene603(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene604 : public Scene6xx{
+private:
+ int _timebombHotspotId;
+ int _bombMode;
+ int _monsterFrame;
+
+ uint32 _monsterTimer;
+
+ bool _monsterActive;
+ bool _animationActiveFl;
+
+ void handleBombActions();
+
+public:
+ Scene604(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene605 : public Scene6xx{
+public:
+ Scene605(MADSEngine *vm) : Scene6xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene607 : public Scene6xx{
+private:
+ uint32 _dogTimer;
+ uint32 _lastFrameTime;
+
+ bool _dogLoop;
+ bool _dogEatsRex;
+ bool _dogBarking;
+ bool _shopAvailable;
+
+ int _animationMode;
+ int _animationActive;
+ int _counter;
+
+ void handleThrowingBone();
+
+public:
+ Scene607(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene608 : public Scene6xx{
+private:
+ int _carMode;
+ int _carFrame;
+ int _carMoveMode;
+ int _dogDeathMode;
+ int _carHotspotId;
+ int _barkCount;
+ int _polycementHotspotId;
+ int _animationMode;
+ int _nextTrigger;
+ int _throwMode;
+
+ bool _resetPositionsFl;
+ bool _dogActiveFl;
+ bool _dogBarkingFl;
+ bool _dogFirstEncounter;
+ bool _rexBeingEaten;
+ bool _dogHitWindow;
+ bool _checkFl;
+ bool _dogSquashFl;
+ bool _dogSafeFl;
+ bool _buttonPressedonTimeFl;
+ bool _dogUnderCar;
+ bool _dogYelping;
+
+ long _dogWindowTimer;
+ long _dogRunTimer;
+
+ uint32 _dogTimer1;
+ uint32 _dogTimer2;
+
+ void resetDogVariables();
+ void restoreAnimations();
+ void setCarAnimations();
+ void handleThrowingBone();
+
+public:
+ Scene608(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene609 : public Scene6xx{
+private:
+ int _videoDoorMode;
+
+ void enterStore();
+
+public:
+ Scene609(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene610 : public Scene6xx{
+private:
+ int _handsetHotspotId;
+ int _checkVal;
+
+ bool _cellCharging;
+
+ long _cellChargingTimer;
+ uint32 _lastFrameTimer;
+
+public:
+ Scene610(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene611 : public Scene6xx{
+private:
+ bool _seenRatFl;
+ bool _eyesRunningFl;
+ bool _shouldRemoveEyes;
+ bool _ratPresentFl;
+ bool _duringDialogFl;
+ bool _resetBatterieText;
+ bool _hermitTalkingFl;
+ bool _hermitMovingFl;
+ bool _alreadyTalkingFl;
+ bool _giveBatteriesFl;
+ bool _startTradingFl;
+ bool _check1Fl;
+ bool _stickFingerFl;
+
+ int _randVal;
+ int _ratHotspotId;
+ int _hermitDialogNode;
+ int _hermitDisplayedQuestion;
+ int _nextFrame;
+ int _hermitMode;
+
+ uint32 _ratTimer;
+
+ Conversation _dialog1;
+ Conversation _dialog2;
+
+ Common::Point _defaultDialogPos;
+
+ void handleTrading();
+ void handleRatMoves();
+ void handleDialog();
+ void handleSubDialog1();
+ void handleSubDialog2();
+ void handleTalking(int delay);
+ void setDialogNode(int node);
+ void displayHermitQuestions(int question);
+
+ bool check2ChargedBatteries();
+ bool check4ChargedBatteries();
+
+public:
+ Scene611(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene612 : public Scene6xx{
+private:
+ int _actionMode;
+ int _cycleIndex;
+
+ void handleWinchMovement();
+
+public:
+ Scene612(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene620 : public Scene6xx{
+public:
+ Scene620(MADSEngine *vm) : Scene6xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions() {};
+};
+} // End of namespace Nebular
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES6_H */
diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp
new file mode 100644
index 0000000000..930bb7c250
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes7.cpp
@@ -0,0 +1,2679 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes7.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+void Scene7xx::setAAName() {
+ _game._aaName = Resources::formatAAName(5);
+}
+
+void Scene7xx::setPlayerSpritesPrefix() {
+ _vm->_sound->command(5);
+
+ Common::String oldName = _game._player._spritesPrefix;
+
+ if ((_scene->_nextSceneId == 703) || (_scene->_nextSceneId == 704) || (_scene->_nextSceneId == 705)
+ || (_scene->_nextSceneId == 707) || (_scene->_nextSceneId == 710) || (_scene->_nextSceneId == 711))
+ _game._player._spritesPrefix = "";
+ else if (_globals[kSexOfRex] == REX_MALE)
+ _game._player._spritesPrefix = "RXM";
+ else
+ _game._player._spritesPrefix = "ROX";
+
+ _game._player._scalingVelocity = true;
+
+ if (oldName != _game._player._spritesPrefix)
+ _game._player._spritesChanged = true;
+
+ _vm->_palette->setEntry(16, 10, 63, 63);
+ _vm->_palette->setEntry(17, 10, 45, 45);
+}
+
+void Scene7xx::sceneEntrySound() {
+ if (!_vm->_musicFlag) {
+ _vm->_sound->command(2);
+ return;
+ }
+
+ switch (_scene->_nextSceneId) {
+ case 701:
+ case 702:
+ case 704:
+ case 705:
+ case 751:
+ _vm->_sound->command(38);
+ break;
+ case 703:
+ if (_globals[kMonsterAlive] == 0)
+ _vm->_sound->command(24);
+ else
+ _vm->_sound->command(27);
+ break;
+ case 706:
+ case 707:
+ case 710:
+ case 711:
+ _vm->_sound->command(25);
+ break;
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene701::Scene701(MADSEngine *vm) : Scene7xx(vm) {
+ _fishingLineId = -1;
+}
+
+void Scene701::synchronize(Common::Serializer &s) {
+ Scene7xx::synchronize(s);
+
+ s.syncAsSint16LE(_fishingLineId);
+}
+
+void Scene701::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_BOAT);
+ _scene->addActiveVocab(VERB_CLIMB_INTO);
+ _scene->addActiveVocab(NOUN_FISHING_LINE);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene701::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 5));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RM202A1");
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 8));
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_BINOCULARS);
+ _game._objects.addToInventory(OBJ_TWINKIFRUIT);
+ _game._objects.addToInventory(OBJ_BOMB);
+ _game._objects.addToInventory(OBJ_CHICKEN);
+ _game._objects.addToInventory(OBJ_BONES);
+
+ _globals[kCityFlooded] = true;
+ _globals[kLineStatus] = LINE_TIED;
+ _globals[kBoatRaised] = false;
+ }
+
+ if (_globals[kBoatStatus] == BOAT_UNFLOODED) {
+ if (_globals[kBoatRaised])
+ _globals[kBoatStatus] = BOAT_GONE;
+ else if (_globals[kLineStatus] == LINE_TIED)
+ _globals[kBoatStatus] = BOAT_TIED_FLOATING;
+ else if (_game._difficulty == DIFFICULTY_HARD)
+ _globals[kBoatStatus] = BOAT_ADRIFT;
+ else
+ _globals[kBoatStatus] = BOAT_TIED;
+ }
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+
+ int boatStatus = (_scene->_priorSceneId == 703) ? BOAT_GONE : _globals[kBoatStatus];
+
+ switch (boatStatus) {
+ case BOAT_TIED_FLOATING:
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 20, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 10);
+ break;
+ case BOAT_ADRIFT:
+ _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 20, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 10);
+ break;
+ case BOAT_TIED:
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+ break;
+ case BOAT_GONE:
+ _scene->_hotspots.activate(NOUN_BOAT, false);
+ break;
+ default:
+ break;
+ }
+
+ if (_globals[kLineStatus] == LINE_DROPPED || _globals[kLineStatus] == LINE_TIED) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _fishingLineId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 129), FACING_NORTHEAST);
+ }
+
+ if (_scene->_priorSceneId == 702) {
+ _game._player._playerPos = Common::Point(309, 138);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId == 710) {
+ _game._player._playerPos = Common::Point(154, 129);
+ _game._player._facing = FACING_NORTH;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129));
+ _scene->_sequences.addTimer(15, 60);
+ } else if (_scene->_priorSceneId == 703) {
+ _game._player._playerPos = Common::Point(231, 127);
+ _game._player._facing = FACING_SOUTH;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(formAnimName('B', 1), 80);
+ _vm->_sound->command(28);
+ } else if (_scene->_priorSceneId != -2 && _scene->_priorSceneId != 620) {
+ _game._player._playerPos = Common::Point(22, 131);
+ _game._player._facing = FACING_EAST;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.addTimer(60, 70);
+ }
+
+ _game.loadQuoteSet(0x310, 0x30F, 0);
+ sceneEntrySound();
+}
+
+void Scene701::step() {
+ switch(_game._trigger) {
+ case 60:
+ _scene->_sequences.remove(_globals._sequenceIndexes[5]);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 61);
+ break;
+
+ case 61:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ case 70:
+ _vm->_sound->command(16);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ break;
+
+ case 71:
+ _game._player.walk(Common::Point(61, 131), FACING_EAST);
+ _scene->_sequences.addTimer(120, 72);
+ break;
+
+ case 72:
+ _vm->_sound->command(17);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 73);
+ break;
+
+ case 73:
+ _game._player._stepEnabled = true;
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_kernelMessages.reset();
+ break;
+
+ case 80: {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_CLIMB_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 129), FACING_NORTH);
+ _globals[kBoatStatus] = BOAT_TIED;
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene701::preActions() {
+ if (_action.isAction(VERB_WALKTO, NOUN_EAST_END_OF_PLATFORM))
+ _game._player._walkOffScreenSceneId = 702;
+
+ if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
+ _game._player.walk(Common::Point(154, 129), FACING_NORTHEAST);
+
+ if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_BUILDING))
+ _game._player.walk(Common::Point(154, 129), FACING_NORTH);
+}
+
+void Scene701::actions() {
+ if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM))
+ return;
+
+ if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_BUILDING) && _game._objects[OBJ_VASE]._roomNumber == 706) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int temp = _globals._sequenceIndexes[5];
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp);
+ _scene->_sequences.addTimer(15, 2);
+ }
+ break;
+
+ case 2:
+ _scene->_nextSceneId = 710;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_STEP_INTO, NOUN_ELEVATOR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _vm->_sound->command(16);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x310, 34, 0, 120, _game.getQuote(0x30D));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _game._player.walk(Common::Point(22, 131), FACING_EAST);
+ _scene->_sequences.addTimer(120, 3);
+ break;
+
+ case 3:
+ _vm->_sound->command(17);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ break;
+
+ case 4:
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _globals[kResurrectRoom] = 701;
+ _scene->_nextSceneId = 605;
+ break;
+
+ default:
+ break;
+ }
+ } else if ((_action.isAction(VERB_PULL, NOUN_BOAT) || _action.isAction(VERB_TAKE, NOUN_BOAT) ||
+ _action.isAction(VERB_PULL, NOUN_FISHING_LINE) || _action.isAction(VERB_TAKE, NOUN_FISHING_LINE)) &&
+ !_game._objects.isInInventory(OBJ_FISHING_LINE)) {
+ if (_globals[kBoatStatus] == BOAT_TIED_FLOATING) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _scene->_dynamicHotspots.remove(_fishingLineId);
+ _scene->_hotspots.activate(NOUN_BOAT, false);
+ _game._player._visible = false;
+ _scene->loadAnimation(formAnimName('E', -1), 1);
+ break;
+
+ case 1: {
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1);
+ _scene->_sequences.setDepth (_globals._sequenceIndexes[2], 9);
+ int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_CLIMB_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(231, 127), FACING_NORTH);
+ _scene->_sequences.addTimer(15, 2);
+ }
+ break;
+
+ case 2:
+ _globals[kBoatStatus] = BOAT_TIED;
+ _globals[kLineStatus] = LINE_NOW_UNTIED;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_globals[kBoatStatus] == BOAT_TIED) {
+ _vm->_dialogs->show(70125);
+ } else if (_globals[kLineStatus] == LINE_DROPPED) {
+ _globals[kLineStatus] = LINE_NOW_UNTIED;
+ _game._objects.addToInventory(OBJ_FISHING_LINE);
+ _vm->_sound->command(15);
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _vm->_dialogs->showItem(OBJ_FISHING_LINE, 70126);
+ } else {
+ _vm->_dialogs->show(70127);
+ }
+ } else if (_action.isAction(VERB_CLIMB_INTO, NOUN_BOAT) && _globals[kBoatStatus] == BOAT_TIED) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _game._player._visible = false;
+ _scene->loadAnimation(formAnimName('B', 0), 1);
+ break;
+
+ case 1:
+ _scene->_nextSceneId = 703;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action._lookFlag) {
+ if (_globals[kBoatStatus] != BOAT_GONE) {
+ if (_globals[kBoatStatus] == BOAT_TIED)
+ _vm->_dialogs->show(70128);
+ else
+ _vm->_dialogs->show(70110);
+ } else
+ _vm->_dialogs->show(70111);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SUBMERGED_CITY))
+ _vm->_dialogs->show(70112);
+ else if (_action.isAction(VERB_LOOK, 0))
+ _vm->_dialogs->show(70113);
+ else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM))
+ _vm->_dialogs->show(70114);
+ else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_PYLON))
+ _vm->_dialogs->show(70115);
+ else if (_action.isAction(VERB_LOOK, NOUN_HOOK)) {
+ if (_globals[kLineStatus] == LINE_NOT_DROPPED || _globals[kLineStatus] == LINE_NOW_UNTIED)
+ _vm->_dialogs->show(70116);
+ else
+ _vm->_dialogs->show(70117);
+ } else if (_action.isAction(VERB_LOOK, NOUN_ROCK))
+ _vm->_dialogs->show(70118);
+ else if (_action.isAction(VERB_TAKE, NOUN_ROCK))
+ _vm->_dialogs->show(70119);
+ else if (_action.isAction(VERB_LOOK, NOUN_EAST_END_OF_PLATFORM))
+ _vm->_dialogs->show(70120);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
+ _vm->_dialogs->show(70121);
+ else if (_action.isAction(VERB_LOOK, NOUN_BOAT)) {
+ if (_globals[kBoatStatus] == BOAT_ADRIFT || _globals[kBoatStatus] == BOAT_TIED_FLOATING)
+ _vm->_dialogs->show(70122);
+ else
+ _vm->_dialogs->show(70123);
+ } else if (_action.isAction(VERB_CAST, NOUN_FISHING_ROD, NOUN_BOAT) && _game._objects.isInInventory(OBJ_FISHING_LINE))
+ _vm->_dialogs->show(70124);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene702::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene702::enter() {
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_8");
+
+ if (_scene->_priorSceneId == 701) {
+ _game._player._playerPos = Common::Point(13, 145);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId != -2 && _scene->_priorSceneId != 620) {
+ _game._player._playerPos = Common::Point(289, 138);
+ _game._player.walk(Common::Point(262, 148), FACING_WEST);
+ _game._player._facing = FACING_WEST;
+ _game._player._visible = true;
+ }
+
+ if (_game._globals[kTeleporterCommand]) {
+ switch(_game._globals[kTeleporterCommand]) {
+ case TELEPORTER_BEAM_OUT:
+ case TELEPORTER_WRONG:
+ case TELEPORTER_STEP_OUT:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+ default:
+ break;
+ }
+
+ _game._globals[kTeleporterCommand] = TELEPORTER_NONE;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene702::preActions() {
+ if (_action.isAction(VERB_WALKTO, NOUN_WEST_END_OF_PLATFORM))
+ _game._player._walkOffScreenSceneId = 701;
+}
+
+void Scene702::actions() {
+ if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM))
+ ; // Only set the action as finished
+ else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_nextSceneId = 711;
+ } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4) && (!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+ case 1:
+ _vm->_sound->command(0xF);
+ if (_game._objects.isInInventory(OBJ_BONE))
+ _game._objects.setRoom(OBJ_BONE, 1);
+ _game._objects.addToInventory(OBJ_BONES);
+ _vm->_dialogs->show(OBJ_BONES, 70218);
+ break;
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[12]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+ default:
+ break;
+ }
+ } else if (_action._lookFlag)
+ _vm->_dialogs->show(70210);
+ else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM))
+ _vm->_dialogs->show(70211);
+ else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_BLOCK))
+ _vm->_dialogs->show(70212);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCK))
+ _vm->_dialogs->show(70213);
+ else if (_action.isAction(VERB_TAKE, NOUN_ROCK))
+ _vm->_dialogs->show(70214);
+ else if (_action.isAction(VERB_LOOK, NOUN_WEST_END_OF_PLATFORM))
+ _vm->_dialogs->show(70215);
+ else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER))
+ _vm->_dialogs->show(70216);
+ else if (_action.isAction(VERB_LOOK, NOUN_BONES) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(70217);
+ else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4)) {
+ if (_game._objects.isInInventory(OBJ_BONES))
+ _vm->_dialogs->show(70219);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SUBMERGED_CITY))
+ _vm->_dialogs->show(70220);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene703::Scene703(MADSEngine *vm) : Scene7xx(vm) {
+ _monsterMode = -1;
+ _boatFrame = -1;
+ _curSequence = -1;
+ _boatDir = -1;
+
+ _useBomb = false;
+ _startMonsterTimer = false;
+ _rexDeathFl = false;
+ _restartTrigger70Fl = false;
+
+ _lastFrameTime = 0;
+ _monsterTime = 0;
+}
+
+void Scene703::synchronize(Common::Serializer &s) {
+ Scene7xx::synchronize(s);
+
+ s.syncAsSint16LE(_monsterMode);
+ s.syncAsSint16LE(_boatFrame);
+ s.syncAsSint16LE(_curSequence);
+ s.syncAsSint16LE(_boatDir);
+
+ s.syncAsByte(_useBomb);
+ s.syncAsByte(_startMonsterTimer);
+ s.syncAsByte(_rexDeathFl);
+ s.syncAsByte(_restartTrigger70Fl);
+
+ s.syncAsUint32LE(_lastFrameTime);
+ s.syncAsUint32LE(_monsterTime);
+}
+
+void Scene703::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+}
+
+void Scene703::handleBottleInterface() {
+ switch (_globals[kBottleStatus]) {
+ case 0:
+ _dialog1.write(0x311, true);
+ _dialog1.write(0x312, true);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 1:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, true);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 2:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, false);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 3:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, false);
+ _dialog1.write(0x313, false);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene703::setBottleSequence() {
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _game._player._stepEnabled = false;
+ if (_boatDir == 2)
+ _curSequence = 6;
+ else
+ _curSequence = 7;
+}
+
+void Scene703::handleFillBottle(int quote) {
+ switch (quote) {
+ case 0x311:
+ _globals[kBottleStatus] = 1;
+ setBottleSequence();
+ break;
+
+ case 0x312:
+ _globals[kBottleStatus] = 2;
+ setBottleSequence();
+ break;
+
+ case 0x313:
+ _globals[kBottleStatus] = 3;
+ setBottleSequence();
+ break;
+
+ case 0x314:
+ _globals[kBottleStatus] = 4;
+ setBottleSequence();
+ break;
+
+ case 0x315:
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene703::enter() {
+ _game._player._visible = false;
+
+ if (!_game._visitedScenes._sceneRevisited) {
+ if (_scene->_priorSceneId == 704)
+ _globals[kMonsterAlive] = false;
+ else
+ _globals[kMonsterAlive] = true;
+ }
+
+ _startMonsterTimer = true;
+ _rexDeathFl = true;
+ _monsterTime = 0;
+ _restartTrigger70Fl = true;
+ _useBomb = false;
+ _boatFrame = -1;
+
+ if (!_globals[kMonsterAlive])
+ _scene->_hotspots.activate(NOUN_SEA_MONSTER, false);
+
+ if (_scene->_priorSceneId == 704) {
+ _game._player._stepEnabled = false;
+ _curSequence = 2;
+ _boatDir = 2;
+ _monsterMode = 0;
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(34);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._stepEnabled = false;
+ _boatDir = 1;
+ if (_globals[kMonsterAlive]) {
+ _monsterMode = 1;
+ _curSequence = 0;
+ _scene->loadAnimation(formAnimName('B', -1));
+ } else {
+ _curSequence = 0;
+ _monsterMode = 0;
+ _scene->loadAnimation(formAnimName('A', -1));
+ }
+ } else if (_globals[kMonsterAlive]) {
+ _curSequence = 0;
+ _boatDir = 1;
+ _monsterMode = 1;
+ _scene->loadAnimation(formAnimName('B', -1));
+ _scene->_activeAnimation->setCurrentFrame(39);
+ } else if (_boatDir == 1) {
+ _curSequence = 0;
+ _monsterMode = 0;
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(9);
+ } else if (_boatDir == 2) {
+ _curSequence = 0;
+ _monsterMode = 0;
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(56);
+ }
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_TWINKIFRUIT);
+ _game._objects.addToInventory(OBJ_BOMB);
+ _game._objects.addToInventory(OBJ_CHICKEN);
+ _game._objects.addToInventory(OBJ_BONES);
+ }
+
+ _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0);
+ _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0);
+ sceneEntrySound();
+ _vm->_sound->command(28);
+}
+
+void Scene703::step() {
+ if (_startMonsterTimer) {
+ long diff = _scene->_frameStartTime - _lastFrameTime;
+ if ((diff >= 0) && (diff <= 12))
+ _monsterTime += diff;
+ else
+ _monsterTime++;
+
+ _lastFrameTime = _scene->_frameStartTime;
+ }
+
+ if ((_monsterTime >= 2400) && !_rexDeathFl && !_useBomb) {
+ _startMonsterTimer = false;
+ _rexDeathFl = true;
+ _game._player._stepEnabled = false;
+ _scene->freeAnimation();
+ _monsterMode = 3;
+ _scene->loadAnimation(formAnimName('D', -1));
+ _rexDeathFl = false;
+ _monsterTime = 0;
+ }
+
+
+ if (_game._trigger == 70)
+ _scene->_reloadSceneFlag = true;
+
+ if ((_monsterMode == 3) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) {
+ _boatFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextBoatFrame = -1;
+
+ if (_boatFrame == 62) {
+ nextBoatFrame = 61;
+ if (_restartTrigger70Fl) {
+ _restartTrigger70Fl = false;
+ _scene->_sequences.addTimer(15, 70);
+ }
+ }
+
+ if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextBoatFrame);
+ _boatFrame = nextBoatFrame;
+ }
+ }
+ }
+
+ if (_game._trigger == 70)
+ _scene->_reloadSceneFlag = true;
+
+ if ((_monsterMode == 0) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) {
+ _boatFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextBoatFrame = -1;
+
+ switch (_boatFrame) {
+ case 11:
+ if (_curSequence == 7) {
+ _curSequence = 0;
+ nextBoatFrame = 100;
+ } else if (_curSequence == 5)
+ nextBoatFrame = 82;
+ else if (_curSequence == 1)
+ nextBoatFrame = 11;
+ else {
+ nextBoatFrame = 9;
+ if (!_game._player._stepEnabled)
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ case 34:
+ if (_curSequence != 2)
+ _scene->_nextSceneId = 704;
+ break;
+
+ case 57:
+ if (_curSequence == 6) {
+ _curSequence = 0;
+ nextBoatFrame = 91;
+ } else if (_curSequence == 4)
+ nextBoatFrame = 73;
+ else if (_curSequence == 3)
+ nextBoatFrame = 57;
+ else {
+ nextBoatFrame = 56;
+ if (!_game._player._stepEnabled)
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ case 73:
+ _scene->_nextSceneId = 701;
+ break;
+
+ case 82:
+ nextBoatFrame = 11;
+ break;
+
+ case 91:
+ nextBoatFrame = 57;
+ break;
+
+ case 100:
+ nextBoatFrame = 56;
+ if (!_game._player._stepEnabled) {
+ _scene->_sequences.addTimer(30, 80);
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ case 110:
+ nextBoatFrame = 9;
+ if (!_game._player._stepEnabled) {
+ _scene->_sequences.addTimer(30, 80);
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextBoatFrame);
+ _boatFrame = nextBoatFrame;
+ }
+ }
+ }
+
+ if (_game._trigger == 80) {
+ switch (_globals[kBottleStatus]) {
+ case 0:
+ _vm->_dialogs->show(432);
+ break;
+
+ case 1:
+ _vm->_dialogs->show(70324);
+ break;
+
+ case 2:
+ _vm->_dialogs->show(70325);
+ break;
+
+ case 3:
+ _vm->_dialogs->show(70326);
+ break;
+
+ case 4:
+ _vm->_dialogs->show(70327);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+ if ((_monsterMode == 1) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) {
+ _boatFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextBoatFrame = -1;
+
+ switch (_boatFrame) {
+ case 39:
+ _game._player._stepEnabled = true;
+ _startMonsterTimer = true;
+ _rexDeathFl = false;
+ break;
+
+ case 40:
+ case 49:
+ case 54:
+ case 67:
+ case 78:
+ case 87:
+ case 96:
+ case 105:
+ case 114:
+ case 123:
+ if (_curSequence == 8)
+ nextBoatFrame = 129;
+
+ break;
+
+ case 129:
+ nextBoatFrame = 39;
+ break;
+
+ case 151:
+ _scene->_nextSceneId = 701;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextBoatFrame);
+ _boatFrame = nextBoatFrame;
+ }
+ }
+ }
+
+ if ((_monsterMode == 2) && (_scene->_activeAnimation != nullptr)) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) {
+ _boatFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextBoatFrame = -1;
+
+ switch (_boatFrame) {
+ case 14:
+ if (!_useBomb) {
+ if (_game._difficulty == DIFFICULTY_HARD)
+ _game._objects.setRoom(OBJ_CHICKEN, 1);
+ else
+ _vm->_dialogs->show(70319);
+ }
+ nextBoatFrame = 80;
+ break;
+
+ case 33:
+ if (_game._objects.isInInventory(OBJ_BONES)) {
+ _game._objects.setRoom(OBJ_BONES, 1);
+ _game._objects.addToInventory(OBJ_BONE);
+ } else
+ _game._objects.setRoom(OBJ_BONE, 1);
+
+ nextBoatFrame = 80;
+ break;
+
+ case 53:
+ _game._objects.setRoom(OBJ_TWINKIFRUIT, 1);
+ nextBoatFrame = 80;
+ _curSequence = 9;
+ break;
+
+ case 80:
+ if (_game._difficulty == DIFFICULTY_HARD) {
+ _game._objects.setRoom(OBJ_BOMB, 1);
+ _vm->_dialogs->show(70318);
+ } else
+ _vm->_dialogs->show(70317);
+
+ _scene->freeAnimation();
+ _monsterMode = 1;
+ _scene->loadAnimation(formAnimName('B', -1));
+ _scene->_activeAnimation->setCurrentFrame(39);
+ _game._player._stepEnabled = true;
+ break;
+
+ case 91:
+ if (!_useBomb) {
+ _scene->freeAnimation();
+ _monsterMode = 1;
+ _scene->loadAnimation(formAnimName('B', -1));
+ _scene->_activeAnimation->setCurrentFrame(39);
+ _game._player._stepEnabled = true;
+ } else
+ _game._objects.setRoom(OBJ_CHICKEN_BOMB, 1);
+
+ break;
+
+ case 126:
+ _scene->_hotspots.activate(NOUN_SEA_MONSTER, false);
+ _globals[kMonsterAlive] = false;
+ _scene->freeAnimation();
+ _monsterMode = 0;
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(9);
+ _game._player._stepEnabled = true;
+ if (_game._storyMode == STORYMODE_NAUGHTY)
+ _vm->_dialogs->show(70321);
+ else
+ _vm->_dialogs->show(70322);
+
+ break;
+
+ default:
+ break;
+ }
+
+ if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextBoatFrame);
+ _boatFrame = nextBoatFrame;
+ }
+ }
+ }
+}
+
+void Scene703::actions() {
+ if (_game._screenObjects._inputMode == kInputConversation)
+ handleFillBottle(_action._activeAction._verbId);
+ else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_DOCK_TO_SOUTH)) {
+ _game._player._stepEnabled = false;
+ if (_globals[kMonsterAlive])
+ _curSequence = 8;
+ else if (_boatDir == 1)
+ _curSequence = 5;
+ else
+ _curSequence = 3;
+ } else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_BUILDING_TO_NORTH)) {
+ _game._player._stepEnabled = false;
+ if (_globals[kMonsterAlive]) {
+ _startMonsterTimer = false;
+ _rexDeathFl = true;
+ _monsterTime = 0;
+ _scene->freeAnimation();
+ _monsterMode = 3;
+ _scene->loadAnimation(formAnimName('D', -1));
+ } else if (_boatDir == 2)
+ _curSequence = 4;
+ else
+ _curSequence = 1;
+ } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_SEA_MONSTER) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_SEA_MONSTER)) {
+ _game._player._stepEnabled = false;
+ _scene->freeAnimation();
+ _monsterMode = 2;
+ _scene->loadAnimation(formAnimName('C', -1));
+ _scene->_activeAnimation->setCurrentFrame(19);
+ } else if (_action.isAction(VERB_THROW, NOUN_CHICKEN, NOUN_SEA_MONSTER)) {
+ _game._player._stepEnabled = false;
+ _scene->freeAnimation();
+ _monsterMode = 2;
+ _scene->loadAnimation(formAnimName('C', -1));
+ } else if (_action.isAction(VERB_THROW, NOUN_TWINKIFRUIT, NOUN_SEA_MONSTER)) {
+ _game._player._stepEnabled = false;
+ _scene->freeAnimation();
+ _monsterMode = 2;
+ _scene->loadAnimation(formAnimName('C', -1));
+ _scene->_activeAnimation->setCurrentFrame(39);
+ } else if (_action.isAction(VERB_THROW, NOUN_BOMB, NOUN_SEA_MONSTER)) {
+ _game._player._stepEnabled = false;
+ _scene->freeAnimation();
+ _monsterMode = 2;
+ _scene->loadAnimation(formAnimName('C', -1));
+ _scene->_activeAnimation->setCurrentFrame(59);
+ } else if (_action.isAction(VERB_THROW, NOUN_CHICKEN_BOMB, NOUN_SEA_MONSTER)) {
+ _useBomb = true;
+ _game._player._stepEnabled = false;
+ _scene->freeAnimation();
+ _monsterMode = 2;
+ _scene->loadAnimation(formAnimName('C', -1));
+ } else if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER)) {
+ if (_globals[kBottleStatus] != 4) {
+ handleBottleInterface();
+ _dialog1.start();
+ } else
+ _vm->_dialogs->show(70323);
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_SEA_MONSTER)) {
+ if (_globals[kMonsterAlive])
+ _vm->_dialogs->show(70310);
+ } else if (_action.isAction(VERB_LOOK, NOUN_WATER)) {
+ if (!_globals[kMonsterAlive])
+ _vm->_dialogs->show(70311);
+ else
+ _vm->_dialogs->show(70312);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_NORTH)) {
+ if (_globals[kMonsterAlive])
+ _vm->_dialogs->show(70313);
+ else if (_game._visitedScenes.exists(710))
+ _vm->_dialogs->show(70314);
+ else
+ _vm->_dialogs->show(70315);
+ } else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM))
+ _vm->_dialogs->show(70316);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene704::Scene704(MADSEngine *vm) : Scene7xx(vm) {
+ _bottleHotspotId = -1;
+ _boatCurrentFrame = -1;
+ _animationMode = -1;
+ _boatDirection = -1;
+
+ _takeBottleFl = false;
+}
+
+void Scene704::synchronize(Common::Serializer &s) {
+ Scene7xx::synchronize(s);
+
+ s.syncAsSint16LE(_bottleHotspotId);
+ s.syncAsSint16LE(_boatCurrentFrame);
+ s.syncAsSint16LE(_animationMode);
+ s.syncAsSint16LE(_boatDirection);
+
+ s.syncAsByte(_takeBottleFl);
+}
+
+void Scene704::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+ _scene->addActiveVocab(NOUN_BOTTLE);
+ _scene->addActiveVocab(VERB_LOOK_AT);
+}
+
+void Scene704::handleBottleInterface() {
+ switch (_globals[kBottleStatus]) {
+ case 0:
+ _dialog1.write(0x311, true);
+ _dialog1.write(0x312, true);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 1:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, true);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 2:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, false);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 3:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, false);
+ _dialog1.write(0x313, false);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene704::setBottleSequence() {
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _game._player._stepEnabled = false;
+ if (_boatDirection == 2)
+ _animationMode = 6;
+ else
+ _animationMode = 7;
+}
+
+void Scene704::handleFillBottle(int quote) {
+ switch (quote) {
+ case 0x311:
+ _globals[kBottleStatus] = 1;
+ setBottleSequence();
+ break;
+
+ case 0x312:
+ _globals[kBottleStatus] = 2;
+ setBottleSequence();
+ break;
+
+ case 0x313:
+ _globals[kBottleStatus] = 3;
+ setBottleSequence();
+ break;
+
+ case 0x314:
+ _globals[kBottleStatus] = 4;
+ setBottleSequence();
+ break;
+
+ case 0x315:
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene704::enter() {
+ if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ if (_scene->_priorSceneId == 705) {
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(123, 125));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ } else {
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(190, 122));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ }
+ int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_LOOK_AT, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _bottleHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE);
+ }
+
+ _game._player._visible = false;
+ _takeBottleFl = false;
+ _boatCurrentFrame = -1;
+
+ if (_scene->_priorSceneId == 705) {
+ _game._player._stepEnabled = false;
+ _animationMode = 2;
+ _boatDirection = 2;
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(36);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._stepEnabled = false;
+ _boatDirection = 1;
+ _scene->loadAnimation(formAnimName('A', -1));
+ } else if (_boatDirection == 1) {
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(8);
+ } else if (_boatDirection == 2) {
+ if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) {
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(123, 125));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ }
+ _scene->loadAnimation(formAnimName('A', -1));
+ _scene->_activeAnimation->setCurrentFrame(57);
+ }
+
+ if (_scene->_roomChanged)
+ _globals[kMonsterAlive] = false;
+
+ _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0);
+ _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0);
+
+ sceneEntrySound();
+ _vm->_sound->command(28);
+}
+
+void Scene704::step() {
+ if (_scene->_activeAnimation != nullptr) {
+ if (_scene->_activeAnimation->getCurrentFrame() != _boatCurrentFrame) {
+ _boatCurrentFrame = _scene->_activeAnimation->getCurrentFrame();
+ int nextFrame = -1;
+
+ switch (_boatCurrentFrame) {
+ case 10:
+ switch (_animationMode) {
+ case 1:
+ nextFrame = 10;
+ break;
+ case 5:
+ nextFrame = 74;
+ break;
+ case 7:
+ _animationMode = 0;
+ nextFrame = 92;
+ break;
+ default:
+ if (!_game._player._stepEnabled)
+ _game._player._stepEnabled = true;
+
+ nextFrame = 8;
+ break;
+ }
+ break;
+
+ case 36:
+ if (_animationMode != 2)
+ _scene->_nextSceneId = 705;
+ break;
+
+ case 59:
+ switch (_animationMode) {
+ case 3:
+ nextFrame = 59;
+ break;
+
+ case 4:
+ nextFrame = 65;
+ break;
+
+ case 6:
+ _animationMode = 0;
+ nextFrame = 83;
+ break;
+
+ default:
+ if (!_game._player._stepEnabled) {
+ _game._player._stepEnabled = true;
+ }
+ nextFrame = 57;
+ break;
+ }
+ break;
+
+ case 65:
+ _scene->_nextSceneId = 703;
+ break;
+
+ case 74:
+ nextFrame = 10;
+ break;
+
+ case 83:
+ nextFrame = 59;
+ break;
+
+ case 90:
+ if (_takeBottleFl) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_bottleHotspotId);
+ _game._objects.addToInventory(OBJ_BOTTLE);
+ _vm->_sound->command(15);
+ _vm->_dialogs->showItem(OBJ_BOTTLE, 70415);
+ }
+ break;
+
+ case 92:
+ nextFrame = 57;
+ if (!_game._player._stepEnabled && !_takeBottleFl) {
+ _scene->_sequences.addTimer(30, 70);
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ case 98:
+ if (_takeBottleFl) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_bottleHotspotId);
+ _game._objects.addToInventory(OBJ_BOTTLE);
+ _vm->_sound->command(15);
+ _vm->_dialogs->showItem(OBJ_BOTTLE, 70415);
+ }
+ break;
+
+ case 101:
+ nextFrame = 8;
+ if (!_game._player._stepEnabled && !_takeBottleFl) {
+ _scene->_sequences.addTimer(30, 70);
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) {
+ _scene->_activeAnimation->setCurrentFrame(nextFrame);
+ _boatCurrentFrame = nextFrame;
+ }
+ }
+ }
+
+ if (_game._trigger == 70) {
+ switch (_globals[kBottleStatus]) {
+ case 0:
+ _vm->_dialogs->show(432);
+ break;
+
+ case 1:
+ _vm->_dialogs->show(70324);
+ break;
+
+ case 2:
+ _vm->_dialogs->show(70325);
+ break;
+
+ case 3:
+ _vm->_dialogs->show(70326);
+ break;
+
+ case 4:
+ _vm->_dialogs->show(70327);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene704::actions() {
+ if (_game._screenObjects._inputMode == kInputConversation)
+ handleFillBottle(_action._activeAction._verbId);
+ else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_OPEN_WATER_TO_SOUTH)) {
+ _game._player._stepEnabled = false;
+ if (_boatDirection == 1)
+ _animationMode = 5;
+ else
+ _animationMode = 3;
+ } else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_BUILDING_TO_NORTH)) {
+ _game._player._stepEnabled = false;
+ if (_boatDirection == 2)
+ _animationMode = 4;
+ else
+ _animationMode = 1;
+ } else if (_action.isAction(VERB_TAKE, NOUN_BOTTLE)) {
+ if (!_game._objects.isInInventory(OBJ_BOTTLE)) {
+ _game._player._stepEnabled = false;
+ _takeBottleFl = true;
+ if (_boatDirection == 2) {
+ _animationMode = 6;
+ } else {
+ _animationMode = 7;
+ }
+ }
+ } else if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER)) {
+ if (_game._objects.isInInventory(OBJ_BOTTLE)) {
+ if (_globals[kBottleStatus] != 4) {
+ _takeBottleFl = false;
+ handleBottleInterface();
+ _dialog1.start();
+ } else
+ _vm->_dialogs->show(70323);
+ }
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_WATER))
+ _vm->_dialogs->show(70410);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_NORTH)) {
+ if (_game._visitedScenes.exists(710))
+ _vm->_dialogs->show(70411);
+ else
+ _vm->_dialogs->show(70412);
+ } else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM))
+ _vm->_dialogs->show(70413);
+ else if (_action.isAction(VERB_LOOK, NOUN_BOTTLE) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(70414);
+ else if (_action.isAction(VERB_LOOK, NOUN_OPEN_WATER_TO_SOUTH))
+ _vm->_dialogs->show(70416);
+ else if (_action.isAction(VERB_LOOK, NOUN_SKY))
+ _vm->_dialogs->show(70417);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene705::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+}
+
+void Scene705::synchronize(Common::Serializer &s) {
+ Scene7xx::synchronize(s);
+}
+
+void Scene705::handleBottleInterface() {
+ switch (_globals[kBottleStatus]) {
+ case 0:
+ _dialog1.write(0x311, true);
+ _dialog1.write(0x312, true);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 1:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, true);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 2:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, false);
+ _dialog1.write(0x313, true);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ case 3:
+ _dialog1.write(0x311, false);
+ _dialog1.write(0x312, false);
+ _dialog1.write(0x313, false);
+ _dialog1.write(0x314, true);
+ _dialog1.write(0x315, true);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene705::setBottleSequence() {
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->loadAnimation(formAnimName('F', -1), 90);
+}
+
+void Scene705::handleFillBottle(int quote) {
+ switch (quote) {
+ case 0x311:
+ _globals[kBottleStatus] = 1;
+ setBottleSequence();
+ break;
+
+ case 0x312:
+ _globals[kBottleStatus] = 2;
+ setBottleSequence();
+ break;
+
+ case 0x313:
+ _globals[kBottleStatus] = 3;
+ setBottleSequence();
+ break;
+
+ case 0x314:
+ _globals[kBottleStatus] = 4;
+ setBottleSequence();
+ break;
+
+ case 0x315:
+ _scene->_userInterface.setup(kInputBuildingSentences);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene705::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0));
+
+ _game._player._visible = false;
+
+ if (_scene->_priorSceneId == 706) {
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._stepEnabled = false;
+ _scene->_sequences.addTimer(1, 80);
+ _vm->_sound->command(28);
+ } else
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+
+ if (_scene->_roomChanged)
+ _game._objects.addToInventory(OBJ_BOTTLE);
+
+ _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0);
+ _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0);
+ sceneEntrySound();
+}
+
+void Scene705::step() {
+ switch (_game._trigger) {
+ case 70:
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ break;
+
+ case 71: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ switch (_game._trigger) {
+ case 80:
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 81);
+ break;
+
+ case 81: {
+ _vm->_sound->command(19);
+ int syncIdx = _globals._sequenceIndexes[1];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ switch (_game._trigger) {
+ case 90:
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.addTimer(30, 91);
+ break;
+
+ case 91:
+ switch (_globals[kBottleStatus]) {
+ case 0:
+ _vm->_dialogs->show(432);
+ break;
+
+ case 1:
+ _vm->_dialogs->show(70324);
+ break;
+
+ case 2:
+ _vm->_dialogs->show(70325);
+ break;
+
+ case 3:
+ _vm->_dialogs->show(70326);
+ break;
+
+ case 4:
+ _vm->_dialogs->show(70327);
+ break;
+
+ default:
+ break;
+ }
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene705::actions() {
+ if (_game._screenObjects._inputMode == kInputConversation)
+ handleFillBottle(_action._activeAction._verbId);
+ else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_OPEN_WATER_TO_SOUTH)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ _vm->_sound->command(18);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx);
+ _scene->_nextSceneId = 704;
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_CLIMB_THROUGH, NOUN_WINDOW)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[3]);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 16);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[3];
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 16);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx);
+ _scene->_nextSceneId = 706;
+ _game._player._stepEnabled = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER)) {
+ if (_globals[kBottleStatus] != 4) {
+ handleBottleInterface();
+ _dialog1.start();
+ } else
+ _vm->_dialogs->show(70323);
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_WATER))
+ _vm->_dialogs->show(70511);
+ else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM))
+ _vm->_dialogs->show(70512);
+ else if (_action.isAction(VERB_LOOK, NOUN_OPEN_WATER_TO_SOUTH))
+ _vm->_dialogs->show(70513);
+ else if (_action.isAction(VERB_LOOK, NOUN_SKY))
+ _vm->_dialogs->show(70514);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
+ _vm->_dialogs->show(70515);
+ else if (_action.isAction(VERB_LOOK, NOUN_WINDOW))
+ _vm->_dialogs->show(70516);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene706::Scene706(MADSEngine *vm) : Scene7xx(vm) {
+ _vaseHotspotId = -1;
+ _vaseMode = -1;
+ _animationMode = -1;
+ _animationFrame = -1;
+
+ _emptyPedestral = false;
+}
+
+void Scene706::synchronize(Common::Serializer &s) {
+ Scene7xx::synchronize(s);
+
+ s.syncAsSint16LE(_vaseHotspotId);
+ s.syncAsSint16LE(_vaseMode);
+ s.syncAsSint16LE(_animationMode);
+ s.syncAsSint16LE(_animationFrame);
+
+ s.syncAsByte(_emptyPedestral);
+}
+
+void Scene706::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_BOTTLE);
+ _scene->addActiveVocab(NOUN_VASE);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene706::handleRexDeath() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->loadAnimation(formAnimName('a', -1), 2);
+ break;
+
+ case 2:
+ if (_animationMode == 1)
+ _vm->_dialogs->show(70625);
+ else if (_globals[kBottleStatus] < 2)
+ _vm->_dialogs->show(70628);
+ else
+ _vm->_dialogs->show(70629);
+
+ _game._objects.setRoom(OBJ_VASE, _scene->_currentSceneId);
+ if (_animationMode == 2)
+ _game._objects.setRoom(OBJ_BOTTLE, 2);
+
+ _animationMode = 0;
+ _scene->_reloadSceneFlag = true;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene706::handleTakeVase() {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 4, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 7, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _vm->_sound->command(9);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _scene->_dynamicHotspots.remove(_vaseHotspotId);
+ _game._objects.addToInventory(OBJ_VASE);
+ if (_vaseMode == 1) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99));
+ int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST);
+ _game._objects.setRoom(OBJ_BOTTLE, _scene->_currentSceneId);
+ }
+ break;
+
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]);
+ _game._player._visible = true;
+ _vm->_dialogs->showItem(OBJ_VASE, 70630);
+ _game._player._stepEnabled = true;
+ break;
+ }
+}
+
+void Scene706::enter() {
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_3");
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', -1));
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _emptyPedestral = false;
+
+ if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId) {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('v', -1));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 4);
+ int idx = _scene->_dynamicHotspots.add(NOUN_VASE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _vaseHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST);
+ } else if (_game._objects.isInRoom(OBJ_BOTTLE)) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99));
+ int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST);
+ }
+
+ _game._player._visible = true;
+
+ if (_scene->_priorSceneId == 707) {
+ _game._player._playerPos = Common::Point(277, 103);
+ _game._player._facing = FACING_SOUTHWEST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(167, 152);
+ _game._player._facing = FACING_NORTH;
+ }
+
+ if (_globals[kTeleporterCommand]) {
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+
+ switch (_globals[kTeleporterCommand]) {
+ case 1:
+ _scene->loadAnimation(formAnimName('E', 1), 75);
+ break;
+
+ case 2:
+ _scene->loadAnimation(formAnimName('E', -1), 80);
+ break;
+
+ default:
+ _game._player.walk(Common::Point(264, 116), FACING_SOUTHWEST);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+ }
+ _globals[kTeleporterCommand] = 0;
+ }
+
+ _animationMode = 0;
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_BOTTLE);
+ _globals[kBottleStatus] = 2;
+ }
+
+ sceneEntrySound();
+}
+
+void Scene706::step() {
+ if (_game._trigger == 75) {
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount;
+ _game._player.walk(Common::Point(264, 116), FACING_SOUTHWEST);
+ }
+
+ if (_game._trigger == 80) {
+ _globals[kTeleporterCommand] = 1;
+ _scene->_nextSceneId = _globals[kTeleporterDestination];
+ _scene->_reloadSceneFlag = true;
+ }
+
+ if (_scene->_activeAnimation != nullptr) {
+ if ((_animationMode != 0) && (_scene->_activeAnimation->getCurrentFrame() != _animationFrame)) {
+ _animationFrame = _scene->_activeAnimation->getCurrentFrame();
+
+ if (_animationFrame == 6) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _game._objects.setRoom(OBJ_VASE, 2);
+
+ if (_animationMode == 2) {
+ _game._objects.setRoom(OBJ_BOTTLE, 1);
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99));
+ int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST);
+ }
+ }
+ }
+ }
+}
+
+void Scene706::preActions() {
+ if (_action.isAction(VERB_LOOK, NOUN_PORTRAIT))
+ _game._player._needToWalk = true;
+}
+
+void Scene706::actions() {
+ if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_nextSceneId = 707;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_EXIT, NOUN_ROOM)) {
+ _scene->_nextSceneId = 705;
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_VASE)) {
+ if (_game._difficulty != DIFFICULTY_EASY) {
+ _animationMode = 1;
+ handleRexDeath();
+ } else if (_game._trigger || !_game._objects.isInInventory(OBJ_VASE)) {
+ handleTakeVase();
+ _emptyPedestral = true;
+ }
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_PEDESTAL)) {
+ if ((_globals[kBottleStatus] == 2 && _game._difficulty == DIFFICULTY_HARD) ||
+ (_globals[kBottleStatus] != 0 && _game._difficulty != DIFFICULTY_HARD)) {
+ if (!_game._objects.isInInventory(OBJ_VASE) || _game._trigger) {
+ _vaseMode = 1;
+ handleTakeVase();
+ _action._inProgress = false;
+ return;
+ }
+ } else if (_game._objects.isInRoom(OBJ_VASE) || _game._trigger) {
+ _animationMode = 2;
+ handleRexDeath();
+ _action._inProgress = false;
+ return;
+ }
+ }
+
+ if (_action.isAction(VERB_PUT, NOUN_PEDESTAL) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) {
+ int objectId = _game._objects.getIdFromDesc(_action._activeAction._objectNameId);
+ if (_game._objects[objectId].hasQuality(10))
+ _vm->_dialogs->show(70626);
+ else
+ _vm->_dialogs->show(70627);
+ } else if (_action.isAction(VERB_TAKE, NOUN_BOTTLE) && _game._objects.isInInventory(OBJ_VASE))
+ _vm->_dialogs->show(70631);
+ else if (_action._lookFlag) {
+ if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId)
+ _vm->_dialogs->show(70610);
+ else
+ _vm->_dialogs->show(70611);
+ } else if (_action.isAction(VERB_LOOK, NOUN_FLOOR))
+ _vm->_dialogs->show(70612);
+ else if (_action.isAction(VERB_LOOK, NOUN_PILLAR))
+ _vm->_dialogs->show(70613);
+ else if (_action.isAction(VERB_LOOK, NOUN_OLD_TEA_CUP))
+ _vm->_dialogs->show(70614);
+ else if (_action.isAction(VERB_TAKE, NOUN_OLD_TEA_CUP))
+ _vm->_dialogs->show(70615);
+ else if (_action.isAction(VERB_LOOK, NOUN_OLD_VASE))
+ _vm->_dialogs->show(70616);
+ else if (_action.isAction(VERB_LOOK, NOUN_PORTRAIT))
+ _vm->_dialogs->show(70617);
+ else if (_action.isAction(VERB_LOOK, NOUN_NAME_PLATE))
+ _vm->_dialogs->show(70618);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(70619);
+ else if (_action.isAction(VERB_LOOK, NOUN_PEDESTAL)) {
+ if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId)
+ _vm->_dialogs->show(70620);
+ else if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId)
+ _vm->_dialogs->show(70622);
+ else
+ _vm->_dialogs->show(70621);
+ } else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER))
+ _vm->_dialogs->show(70623);
+ else if (_action.isAction(VERB_LOOK, NOUN_VASE) && (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId))
+ _vm->_dialogs->show(70624);
+ else if (_action.isAction(VERB_LOOK, NOUN_BOTTLE) && (_action._mainObjectSource == 4))
+ _vm->_dialogs->show(70632);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene707::setup() {
+ _game._player._spritesPrefix = "";
+ // The original calls Scene7xx::setAAName()
+ _game._aaName = Resources::formatAAName(5);
+}
+
+void Scene707::enter() {
+ _handSpriteId = _scene->_sprites.addSprites("*REXHAND");
+ teleporterEnter();
+
+ // The original uses Scene7xx_sceneEntrySound
+ if (!_vm->_musicFlag)
+ _vm->_sound->command(2);
+ else
+ _vm->_sound->command(25);
+}
+
+void Scene707::step() {
+ teleporterStep();
+}
+
+void Scene707::actions() {
+ if (teleporterActions()) {
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT))
+ _vm->_dialogs->show(70710);
+ else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD))
+ _vm->_dialogs->show(70711);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY))
+ _vm->_dialogs->show(70712);
+ else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY))
+ _vm->_dialogs->show(70713);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) || _action._lookFlag)
+ _vm->_dialogs->show(70714);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene710::setup() {
+ _game._player._spritesPrefix = "";
+ setAAName();
+}
+
+void Scene710::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+
+ if (_game._objects[OBJ_VASE]._roomNumber == 706) {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1));
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0);
+ }
+
+ _game._player._visible = false;
+ _scene->_sequences.addTimer(600, 70);
+
+ sceneEntrySound();
+}
+
+void Scene710::step() {
+ if (_game._trigger == 70) {
+ if (_game._globals[kCityFlooded])
+ _scene->_nextSceneId = 701;
+ else
+ _scene->_nextSceneId = 751;
+ }
+}
+
+void Scene710::actions() {
+ if (_action.isAction(VERB_PUT_DOWN, NOUN_BINOCULARS)) {
+ _game._player._stepEnabled = false;
+
+ if (_game._globals[kCityFlooded])
+ _scene->_nextSceneId = 701;
+ else
+ _scene->_nextSceneId = 751;
+
+ _action._inProgress = false;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene711::setup() {
+ // The original was calling Scene7xx::setPlayerSpreitesPrefix()
+ _vm->_sound->command(5);
+ Common::String oldName = _game._player._spritesPrefix;
+ _game._player._spritesPrefix = "";
+ _game._player._scalingVelocity = true;
+
+ if (oldName != _game._player._spritesPrefix)
+ _game._player._spritesChanged = true;
+
+ _vm->_palette->setEntry(16, 10, 63, 63);
+ _vm->_palette->setEntry(17, 10, 45, 45);
+
+ // The original was calling Scene7xx::setAAName()
+ _game._aaName = Resources::formatAAName(5);
+
+ _game._player._spritesPrefix = "";
+}
+
+void Scene711::enter() {
+ if (_globals[kSexOfRex] == REX_FEMALE)
+ _handSpriteId = _scene->_sprites.addSprites("*ROXHAND");
+ else
+ _handSpriteId = _scene->_sprites.addSprites("*REXHAND");
+
+ teleporterEnter();
+
+ // The original was using Scene7xx_SceneEntrySound()
+ if (!_vm->_musicFlag)
+ _vm->_sound->command(2);
+ else
+ _vm->_sound->command(25);
+}
+
+void Scene711::step() {
+ teleporterStep();
+}
+
+void Scene711::actions() {
+ if (teleporterActions())
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene751::Scene751(MADSEngine *vm) : Scene7xx(vm) {
+ _rexHandingLine = false;
+}
+
+void Scene751::synchronize(Common::Serializer &s) {
+ Scene7xx::synchronize(s);
+
+ s.syncAsByte(_rexHandingLine);
+}
+
+void Scene751::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_FISHING_LINE);
+ _scene->addActiveVocab(VERB_WALKTO);
+}
+
+void Scene751::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*RM701X0");
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('f', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RM202A1");
+
+ if (!_game._visitedScenes._sceneRevisited)
+ _rexHandingLine = false;
+
+ if (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST);
+ }
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+
+ if (_scene->_priorSceneId == 752) {
+ _game._player._playerPos = Common::Point(309, 138);
+ _game._player._facing = FACING_WEST;
+ } else if (_scene->_priorSceneId == 710) {
+ _game._player._playerPos = Common::Point(154, 129);
+ _game._player._facing = FACING_NORTH;
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129));
+ _scene->_sequences.addTimer(15, 70);
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(22, 131);
+ _game._player._facing = FACING_EAST;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.addTimer(60, 60);
+ } else if (_rexHandingLine) {
+ _game._player._visible = false;
+ _game._player._playerPos = Common::Point(268, 140);
+ _game._player._facing = FACING_NORTHWEST;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ } else if (_globals[kLineStatus] == 2) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST);
+ }
+
+ if (_scene->_roomChanged) {
+ _game._objects.addToInventory(OBJ_FISHING_LINE);
+ _game._objects.addToInventory(OBJ_BINOCULARS);
+ }
+
+ sceneEntrySound();
+ _game.loadQuoteSet(0x30A, 0x30B, 0x30C, 0x30D, 0x30E, 0);
+
+ if (_globals[kTimebombTimer] > 0)
+ _globals[kTimebombTimer] = 10200;
+}
+
+void Scene751::step() {
+ switch (_game._trigger) {
+ case 70:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ break;
+
+ case 71:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((_globals[kTimebombTimer] >= 10800) && (_globals[kTimebombStatus] == 1)) {
+ _globals[kTimebombStatus] = 3;
+ _globals[kTimebombTimer] = 0;
+ _globals[kCheckDaemonTimebomb] = false;
+ _scene->_nextSceneId = 620;
+ }
+
+ switch (_game._trigger) {
+ case 60:
+ _vm->_sound->command(16);
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 61);
+ break;
+
+ case 61:
+ _game._player.walk(Common::Point(61, 131), FACING_EAST);
+ _scene->_sequences.addTimer(120, 62);
+ break;
+
+ case 62:
+ _vm->_sound->command(17);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 63);
+ break;
+
+ case 63:
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _game._player._stepEnabled = true;
+ _scene->_kernelMessages.reset();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene751::preActions() {
+ if (_action.isAction(VERB_LOOK, NOUN_TALL_BUILDING))
+ _game._player.walk(Common::Point(154, 129), FACING_NORTHEAST);
+
+ if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_TALL_BUILDING))
+ _game._player.walk(Common::Point(154, 129), FACING_NORTH);
+
+ if (_action.isAction(VERB_WALKTO, NOUN_EAST_END_OF_PLATFORM))
+ _game._player._walkOffScreenSceneId = 752;
+
+ if (!_rexHandingLine)
+ return;
+
+ if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_FISHING_LINE) || _action.isAction(VERB_TALKTO))
+ _game._player._needToWalk = false;
+
+ if ((!_action.isAction(VERB_PUT, NOUN_FISHING_LINE, NOUN_HOOK) || !_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_HOOK) || !_action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_HOOK))
+ && (_game._player._needToWalk)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._readyToWalk = false;
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 11, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 7);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _rexHandingLine = false;
+ _game._player._stepEnabled = true;
+ _game._player._readyToWalk = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Scene751::actions() {
+ if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM))
+ ; // Nothing
+ else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_TALL_BUILDING)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129));
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_sequences.addTimer(15, 2);
+ }
+ break;
+
+ case 2:
+ _scene->_nextSceneId = 710;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_STEP_INTO, NOUN_ELEVATOR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _vm->_sound->command(16);
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_kernelMessages.reset();
+ _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x30D));
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1:
+ _game._player.walk(Common::Point(22, 131), FACING_EAST);
+ _scene->_sequences.addTimer(120, 3);
+ break;
+
+ case 3:
+ _vm->_sound->command(17);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4);
+ break;
+
+ case 4:
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10);
+ _scene->_sequences.addTimer(60, 5);
+ break;
+
+ case 5:
+ _game._player._stepEnabled = true;
+ _scene->_nextSceneId = 513;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PUT, NOUN_FISHING_LINE, NOUN_HOOK) || _action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_HOOK) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_HOOK)) {
+ if (_globals[kLineStatus] == 1) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 6);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], -1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1);
+ break;
+
+ case 1: {
+ int syncIdx = _globals._sequenceIndexes[2];
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx);
+ _scene->_sequences.addTimer(30, 2);
+ }
+ break;
+
+ case 2:
+ _rexHandingLine = true;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 8, -2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3);
+ break;
+
+ case 3: {
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]);
+ _game._player._visible = true;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7);
+ int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST);
+ _scene->_kernelMessages.reset();
+ _game._objects.setRoom(OBJ_FISHING_LINE, _scene->_currentSceneId);
+ _rexHandingLine = false;
+ _globals[kLineStatus] = 2;
+ _game._player._stepEnabled = true;
+ _vm->_dialogs->show(75120);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_CITY))
+ _vm->_dialogs->show(75110);
+ else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR))
+ _vm->_dialogs->show(75112);
+ else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM))
+ _vm->_dialogs->show(75113);
+ else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_PYLON))
+ _vm->_dialogs->show(75114);
+ else if ((_action.isAction(VERB_LOOK, NOUN_HOOK) || _action.isAction(VERB_LOOK, NOUN_FISHING_LINE))
+ && (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3))
+ _vm->_dialogs->show(75116);
+ else if (_action.isAction(VERB_LOOK, NOUN_HOOK))
+ _vm->_dialogs->show(75115);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCK))
+ _vm->_dialogs->show(75117);
+ else if (_action.isAction(VERB_TAKE, NOUN_ROCK))
+ _vm->_dialogs->show(75118);
+ else if (_action.isAction(VERB_LOOK, NOUN_EAST_END_OF_PLATFORM))
+ _vm->_dialogs->show(75119);
+ else if (_action.isAction(VERB_TAKE, NOUN_FISHING_LINE) && (_globals[kLineStatus] == 3 || _globals[kLineStatus] == 2))
+ _vm->_dialogs->show(75121);
+ else if (_action.isAction(VERB_LOOK, NOUN_TALL_BUILDING))
+ _vm->_dialogs->show(75122);
+ else if (_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_CEMENT_PYLON) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_CEMENT_PYLON))
+ _vm->_dialogs->show(75123);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene752::Scene752(MADSEngine *vm) : Scene7xx(vm) {
+ _cardId = -1;
+}
+
+void Scene752::synchronize(Common::Serializer &s) {
+ Scene7xx::synchronize(s);
+
+ s.syncAsSint16LE(_cardId);
+}
+
+void Scene752::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+
+ _scene->addActiveVocab(NOUN_ID_CARD);
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(VERB_LOOK_AT);
+ _scene->addActiveVocab(NOUN_LASER_BEAM);
+}
+
+void Scene752::enter() {
+ _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('l', -1));
+ _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_8");
+
+ if (_scene->_priorSceneId == 751) {
+ _game._player._playerPos = Common::Point(13, 145);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(289, 138);
+ _game._player.walk(Common::Point(262, 148), FACING_WEST);
+ _game._player._facing = FACING_WEST;
+ _game._player._visible = true;
+ }
+
+ if (_game._objects[OBJ_ID_CARD]._roomNumber == 752) {
+ _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('i', -1));
+ _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_ID_CARD, VERB_WALKTO, _globals._sequenceIndexes[13], Common::Rect(0, 0, 0, 0));
+ _cardId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 135), FACING_NORTH);
+ }
+
+ if (_game._globals[kLaserHoleIsThere]) {
+ _globals._sequenceIndexes[14] = _scene->_sequences.startCycle(_globals._spriteIndexes[14], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[14], 13);
+ int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_LOOK_AT, _globals._sequenceIndexes[14], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(215, 130), FACING_NORTHWEST);
+ }
+
+ if (_game._globals[kTeleporterCommand]) {
+ switch(_game._globals[kTeleporterCommand]) {
+ case TELEPORTER_BEAM_OUT:
+ case TELEPORTER_WRONG:
+ case TELEPORTER_STEP_OUT:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+ default:
+ break;
+ }
+
+ _game._globals[kTeleporterCommand] = TELEPORTER_NONE;
+ }
+
+ if (_globals._timebombTimer > 0)
+ _globals._timebombTimer = 10800 - 600;
+
+ sceneEntrySound();
+}
+
+void Scene752::step() {
+ if (_globals._timebombTimer >= 10800 && _game._globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) {
+ _globals[kTimebombStatus] = TIMEBOMB_DEAD;
+ _globals._timebombTimer = 0;
+ _globals[kCheckDaemonTimebomb] = false;
+ _scene->_nextSceneId = 620;
+ }
+}
+
+void Scene752::preActions() {
+ if (_action.isAction(VERB_WALKTO, NOUN_WEST_END_OF_PLATFORM)) {
+ _game._player._walkOffScreenSceneId = 751;
+ }
+}
+
+void Scene752::actions() {
+ if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM))
+ ;
+ else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_nextSceneId = 711;
+ } else if (_action.isAction(VERB_TAKE, NOUN_ID_CARD) && (!_game._objects.isInInventory(OBJ_ID_CARD) || _game._trigger)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+ case 1:
+ _vm->_sound->command(15);
+ _scene->_sequences.remove(_globals._sequenceIndexes[13]);
+ _game._objects.addToInventory(OBJ_ID_CARD);
+ _scene->_dynamicHotspots.remove(_cardId);
+ _vm->_dialogs->showItem(OBJ_ID_CARD, 830);
+ break;
+ case 2:
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._savedFields._mainObjectSource == CAT_HOTSPOT) &&
+ (!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+ case 1:
+ _vm->_sound->command(15);
+ if (_game._objects.isInInventory(OBJ_BONE))
+ _game._objects.setRoom(OBJ_BONE, NOWHERE);
+ _game._objects.addToInventory(OBJ_BONES);
+ _vm->_dialogs->showItem(OBJ_BONES, 75221);
+ break;
+ case 2:
+ _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[12]);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+ default:
+ break;
+ }
+ } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_CITY)) {
+ if (_globals[kLaserHoleIsThere])
+ _vm->_dialogs->show(75212);
+ else
+ _vm->_dialogs->show(75210);
+ } else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM))
+ _vm->_dialogs->show(75213);
+ else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_BLOCK))
+ _vm->_dialogs->show(75214);
+ else if (_action.isAction(VERB_LOOK, NOUN_ROCK))
+ _vm->_dialogs->show(75215);
+ else if (_action.isAction(VERB_TAKE, NOUN_ROCK))
+ _vm->_dialogs->show(75216);
+ else if (_action.isAction(VERB_LOOK, NOUN_WEST_END_OF_PLATFORM))
+ _vm->_dialogs->show(75217);
+ else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER))
+ _vm->_dialogs->show(75218);
+ else if ((_action.isAction(VERB_LOOK, NOUN_BONES) || _action.isAction(VERB_LOOK, NOUN_ID_CARD)) && (_action._mainObjectSource == CAT_HOTSPOT)) {
+ if (_game._objects[OBJ_ID_CARD]._roomNumber == 752)
+ _vm->_dialogs->show(75219);
+ else
+ _vm->_dialogs->show(75220);
+ } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._savedFields._mainObjectSource == CAT_HOTSPOT)) {
+ if (_game._objects.isInInventory(OBJ_BONES))
+ _vm->_dialogs->show(75222);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Nebular
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes7.h b/engines/mads/nebular/nebular_scenes7.h
new file mode 100644
index 0000000000..dfb3c0f16e
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes7.h
@@ -0,0 +1,238 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_NEBULAR_SCENES7_H
+#define MADS_NEBULAR_SCENES7_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+class Scene7xx : public NebularScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void setAAName();
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix();
+
+ void sceneEntrySound();
+
+public:
+ Scene7xx(MADSEngine *vm) : NebularScene(vm) {}
+};
+
+class Scene701 : public Scene7xx {
+private:
+ int _fishingLineId;
+
+public:
+ Scene701(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+ virtual void step();
+};
+
+class Scene702 : public Scene7xx {
+public:
+ Scene702(MADSEngine *vm) : Scene7xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene703 : public Scene7xx{
+private:
+ int _monsterMode;
+ int _boatFrame;
+ int _curSequence;
+ int _boatDir;
+
+ bool _useBomb;
+ bool _startMonsterTimer;
+ bool _rexDeathFl;
+ bool _restartTrigger70Fl;
+
+ uint32 _lastFrameTime;
+ uint32 _monsterTime;
+
+ Conversation _dialog1;
+
+ void handleBottleInterface();
+ void setBottleSequence();
+ void handleFillBottle(int quote);
+
+public:
+ Scene703(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene704 : public Scene7xx{
+private:
+ int _bottleHotspotId;
+ int _boatCurrentFrame;
+ int _animationMode;
+ int _boatDirection;
+
+ bool _takeBottleFl;
+
+ Conversation _dialog1;
+
+ void handleFillBottle(int quote);
+ void setBottleSequence();
+ void handleBottleInterface();
+
+public:
+ Scene704(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene705 : public Scene7xx{
+private:
+ Conversation _dialog1;
+
+ void handleFillBottle(int quote);
+ void setBottleSequence();
+ void handleBottleInterface();
+
+public:
+ Scene705(MADSEngine *vm) : Scene7xx(vm) {}
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene706 : public Scene7xx{
+private:
+ int _vaseHotspotId;
+ int _vaseMode;
+ int _animationMode;
+ int _animationFrame;
+
+ bool _emptyPedestral;
+
+ void handleTakeVase();
+ void handleRexDeath();
+
+public:
+ Scene706(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene707 : public SceneTeleporter {
+public:
+ Scene707(MADSEngine *vm) : SceneTeleporter(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene710 : public Scene7xx {
+public:
+ Scene710(MADSEngine *vm) : Scene7xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene711 : public SceneTeleporter {
+public:
+ Scene711(MADSEngine *vm) : SceneTeleporter(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene751 : public Scene7xx{
+private:
+ bool _rexHandingLine;
+
+public:
+ Scene751(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene752 : public Scene7xx {
+private:
+ int _cardId;
+
+public:
+ Scene752(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+} // End of namespace Nebular
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES7_H */
diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp
new file mode 100644
index 0000000000..14f36756de
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes8.cpp
@@ -0,0 +1,1616 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/nebular/nebular_scenes8.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+void Scene8xx::setPlayerSpritesPrefix() {
+ _vm->_sound->command(5);
+ if ((_globals[kFromCockpit] && !_globals[kExitShip]) ||
+ _scene->_nextSceneId == 804 || _scene->_nextSceneId == 805 ||
+ _scene->_nextSceneId == 808 || _scene->_nextSceneId == 810) {
+ _game._player._spritesPrefix = "";
+ } else
+ _game._player._spritesPrefix = _globals[kSexOfRex] == SEX_FEMALE ? "ROX" : "RXM";
+
+ _vm->_palette->setEntry(16, 0x0A, 0x3F, 0x3F);
+ _vm->_palette->setEntry(17, 0x0A, 0x2D, 0x2D);
+}
+
+void Scene8xx::setAAName() {
+ _game._aaName = Resources::formatAAName(5);
+}
+
+void Scene8xx::sceneEntrySound() {
+ if (!_vm->_musicFlag)
+ _vm->_sound->command(2);
+ else {
+ switch (_scene->_nextSceneId) {
+ case 801:
+ case 802:
+ case 803:
+ case 804:
+ case 806:
+ case 807:
+ case 808:
+ _vm->_sound->command(20);
+ break;
+
+ case 805:
+ _vm->_sound->command(23);
+ break;
+
+ case 810:
+ _vm->_sound->command(10);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene801::Scene801(MADSEngine *vm) : Scene8xx(vm) {
+ _walkThroughDoor = false;
+}
+
+void Scene801::synchronize(Common::Serializer &s) {
+ Scene8xx::synchronize(s);
+
+ s.syncAsByte(_walkThroughDoor);
+}
+
+void Scene801::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene801::enter() {
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 3));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('a', -1));
+
+ if (_scene->_priorSceneId != 802) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13);
+ }
+
+ if ((_globals[kCameFromCut]) && (_globals[kCutX] != 0)) {
+ _game._player._playerPos = Common::Point(_globals[kCutX], _globals[kCutY]);
+ _game._player._facing = (Facing)_globals[kCutFacing];
+ _globals[kCutX] = 0;
+ _globals[kCameFromCut] = false;
+ _globals[kReturnFromCut] = false;
+ _globals[kBeamIsUp] = false;
+ _globals[kForceBeamDown] = false;
+ _globals[kDontRepeat] = false;
+ } else if (_scene->_priorSceneId == 808) {
+ _game._player._playerPos = Common::Point(148, 110);
+ _game._player._facing = FACING_NORTH;
+ } else if (_scene->_priorSceneId == 802) {
+ _game._player._playerPos = Common::Point(307, 111);
+ _game._player.walk(Common::Point(270, 118), FACING_WEST);
+ _game._player._visible = true;
+ } else if ((_scene->_priorSceneId != -2) && !_globals[kTeleporterCommand]) {
+ _game._player._playerPos = Common::Point(8, 117);
+ _game._player.walk(Common::Point(41, 115), FACING_EAST);
+ _game._player._visible = true;
+ }
+
+ _globals[kBetweenRooms] = false;
+
+ if (_globals[kTeleporterCommand]) {
+ _game._player._stepEnabled = false;
+ switch (_globals[kTeleporterCommand]) {
+ case 1:
+ _game._player._playerPos = Common::Point(8, 117);
+ _globals[kTeleporterUnderstood] = true;
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 13);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 75);
+ _vm->_sound->command(30);
+ break;
+
+ case 2:
+ _game._player._playerPos = Common::Point(8, 117);
+ _globals[kTeleporterUnderstood] = true;
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 13);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 8090);
+ _vm->_sound->command(30);
+ break;
+
+ case 3:
+ case 4:
+ _game._player._playerPos = Common::Point(8, 117);
+ _game._player.walk(Common::Point(41, 115), FACING_EAST);
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ _globals[kTeleporterCommand] = 0;
+ }
+
+ _walkThroughDoor = false;
+ if (_scene->_priorSceneId == 802) {
+ _game._player._stepEnabled = false;
+ _walkThroughDoor = true;
+ }
+
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 11, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 14);
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 9, 0, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, -2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 14);
+
+ sceneEntrySound();
+}
+
+void Scene801::step() {
+ if (_game._trigger == 75) {
+ if (_globals[kSexOfRex] == REX_FEMALE) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 8);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 140);
+ } else {
+ _game._player._stepEnabled = true;
+ _game._player._visible = true;
+ _game._player._playerPos = Common::Point(8, 117);
+ _game._player.walk(Common::Point(41, 115), FACING_EAST);
+ }
+ }
+
+ if (_game._trigger == 140) {
+ _vm->_sound->command(27);
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 8);
+ _scene->_sequences.addTimer(100, 141);
+ }
+
+ if (_game._trigger == 141) {
+ _scene->_reloadSceneFlag = true;
+ _scene->_nextSceneId = _scene->_priorSceneId;
+ _globals[kTeleporterCommand] = 0;
+ }
+
+ if (_game._trigger == 80) {
+ _globals[kTeleporterCommand] = 1;
+ _scene->_nextSceneId = _globals[kTeleporterDestination];
+ _scene->_reloadSceneFlag = true;
+ }
+
+ if (_walkThroughDoor && (_game._player._playerPos == Common::Point(270, 118))) {
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10);
+ _walkThroughDoor = false;
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 120);
+ }
+
+ if (_game._trigger == 120) {
+ _vm->_sound->command(12);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10);
+ _game._player._stepEnabled = true;
+ }
+
+ if (_game._trigger == 90) {
+ _game._player.walk(Common::Point(307, 111), FACING_EAST);
+ _scene->_sequences.addTimer(80, 130);
+ }
+
+ if (_game._trigger == 130) {
+ _vm->_sound->command(12);
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 110);
+ }
+
+ if (_game._trigger == 110) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10);
+ _scene->_nextSceneId = 802;
+ }
+}
+
+void Scene801::preActions() {
+ if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) {
+ _game._player.walk(Common::Point(148, 110), FACING_NORTH);
+ _game._player._needToWalk = true;
+ _game._player._readyToWalk = true;
+ }
+
+ if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER) && _globals[kBeamIsUp]) {
+ _globals[kCutX] = _game._player._playerPos.x;
+ _globals[kCutY] = _game._player._playerPos.y;
+ _globals[kCutFacing] = _game._player._facing;
+ _globals[kForceBeamDown] = true;
+ _globals[kDontRepeat] = true;
+ _scene->_nextSceneId = 803;
+ }
+}
+
+void Scene801::actions() {
+ if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL))
+ _scene->_nextSceneId = 808;
+ else if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) {
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _scene->_nextSceneId = 807;
+ } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && (_game._player._playerPos == Common::Point(270, 118))) {
+ _game._player._stepEnabled = false;
+ _game._player._facing = FACING_EAST;
+ _game._player.selectSeries();
+ _globals[kBetweenRooms] = true;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 90);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13);
+ _vm->_sound->command(11);
+ } else if (_action.isAction(VERB_LOOK, NOUN_CEILING))
+ _vm->_dialogs->show(80110);
+ else if (_action.isAction(VERB_LOOK, NOUN_MONITOR))
+ _vm->_dialogs->show(80111);
+ else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER))
+ _vm->_dialogs->show(80112);
+ else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT) || _action._lookFlag)
+ _vm->_dialogs->show(80113);
+ else if (_action.isAction(VERB_LOOK, NOUN_SPEAKER))
+ _vm->_dialogs->show(80114);
+ else if (_action.isAction(VERB_LOOK, NOUN_EYE_CHART))
+ _vm->_dialogs->show(80115);
+ else if (_action.isAction(VERB_LOOK, NOUN_WALL))
+ _vm->_dialogs->show(80116);
+ else if (_action.isAction(VERB_LOOK, NOUN_DOOR))
+ _vm->_dialogs->show(80117);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene802::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_SHIELD_MODULATOR);
+ _scene->addActiveVocab(VERB_WALKTO);
+ _scene->addActiveVocab(NOUN_REMOTE);
+}
+
+void Scene802::enter() {
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_8");
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('f', 2));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('f', 0));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('f', 1));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMBD_8");
+ _globals[kBetweenRooms] = false;
+
+ if ((_globals[kCameFromCut]) && (_globals[kCutX] != 0)) {
+ _game._player._playerPos.x = _globals[kCutX];
+ _game._player._playerPos.y = _globals[kCutY];
+ _game._player._facing = (Facing)_globals[kCutFacing];
+ _globals[kCutX] = 0;
+ _globals[kCameFromCut] = false;
+ _globals[kReturnFromCut] = false;
+ _globals[kBeamIsUp] = false;
+ _globals[kForceBeamDown] = false;
+ _globals[kDontRepeat] = false;
+ _globals[kAntigravClock] = _scene->_frameStartTime;
+ } else if (_scene->_priorSceneId == 801) {
+ _game._player._playerPos = Common::Point(15, 129);
+ _game._player._facing = FACING_EAST;
+ } else if (_scene->_priorSceneId == 803) {
+ _game._player._playerPos = Common::Point(303, 119);
+ _game._player._facing = FACING_WEST;
+
+ } else if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(15, 129);
+ _game._player._facing = FACING_EAST;
+ }
+
+ _game._player._visible = true;
+
+
+
+ if (_globals[kHasWatchedAntigrav] && !_globals[kRemoteSequenceRan]) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(200, 70);
+ }
+
+ if ((_globals[kRemoteOnGround]) && (!_game._objects.isInInventory(OBJ_REMOTE))) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_REMOTE, VERB_WALKTO,_globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(107, 99), FACING_NORTH);
+ }
+
+ if (!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled]) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(93, 97), FACING_NORTH);
+ }
+ sceneEntrySound();
+}
+
+void Scene802::step() {
+ if (_game._trigger == 70) {
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 19);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 4, 72);
+ }
+
+ if (_game._trigger == 71) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8);
+ int idx = _scene->_dynamicHotspots.add(NOUN_REMOTE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(107, 99), FACING_NORTH);
+
+ _globals[kRemoteSequenceRan] = true;
+ _globals[kRemoteOnGround] = true;
+ _game._player._stepEnabled = true;
+ }
+
+ if (_game._trigger == 72)
+ _vm->_sound->command(13);
+}
+
+void Scene802::preActions() {
+ if (_action.isAction(VERB_WALK_TOWARDS, NOUN_BUILDING_TO_WEST))
+ _game._player._walkOffScreenSceneId = 801;
+
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_EAST)) {
+ _game._player._walkOffScreenSceneId = 803;
+ _globals[kForceBeamDown] = false;
+ }
+
+ if (_action.isAction(VERB_TAKE, NOUN_SHIP))
+ _game._player._needToWalk = false;
+}
+
+void Scene802::actions() {
+ if (_action.isAction(VERB_TAKE, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _vm->_sound->command(9);
+ break;
+
+ case 2:
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(20, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ _game._objects.addToInventory(OBJ_SHIELD_MODULATOR);
+ _vm->_dialogs->showItem(OBJ_SHIELD_MODULATOR, 80215);
+ break;
+
+ default:
+ break;
+ }
+ } else if ((_action.isAction(VERB_TAKE, NOUN_REMOTE)) && (!_game._objects.isInInventory(OBJ_REMOTE))) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 7, 2, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 4, 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2);
+ break;
+
+ case 1:
+ _scene->_sequences.remove(_globals._sequenceIndexes[4]);
+ _vm->_sound->command(9);
+ _globals[kRemoteOnGround] = false;
+ break;
+
+ case 2:
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _scene->_sequences.addTimer(20, 3);
+ break;
+
+ case 3:
+ _game._player._stepEnabled = true;
+ _game._objects.addToInventory(OBJ_REMOTE);
+ _vm->_dialogs->showItem(OBJ_REMOTE, 80223);
+ break;
+
+ default:
+ break;
+ }
+ } else if (!_globals[kRemoteOnGround] && (_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) || _globals[kShieldModInstalled])
+ && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag))
+ _vm->_dialogs->show(80210);
+ else if (!_globals[kRemoteOnGround]&& !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled]
+ && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag))
+ _vm->_dialogs->show(80211);
+ else if (_globals[kRemoteOnGround] && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled]
+ && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag))
+ _vm->_dialogs->show(80213);
+ else if (_globals[kRemoteOnGround] && (_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) || _globals[kShieldModInstalled])
+ && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag))
+ _vm->_dialogs->show(80212);
+ else if (!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled] && _action.isAction(VERB_LOOK, NOUN_SHIELD_MODULATOR))
+ _vm->_dialogs->show(80214);
+ else if (_globals[kRemoteOnGround] && _action.isAction(VERB_LOOK, NOUN_REMOTE))
+ _vm->_dialogs->show(80216);
+ else if (_action.isAction(VERB_LOOK, NOUN_SHIP)) {
+ if ((!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) && (!_globals[kShieldModInstalled]))
+ _vm->_dialogs->show(80218);
+ else
+ _vm->_dialogs->show(80217);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BUSHES))
+ _vm->_dialogs->show(80219);
+ else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_EAST))
+ _vm->_dialogs->show(80220);
+ else if (_action.isAction(VERB_LOOK, NOUN_SKY))
+ _vm->_dialogs->show(80221);
+ else if (_action.isAction(VERB_TAKE, NOUN_SHIP))
+ _vm->_dialogs->show(80222);
+ else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES))
+ _vm->_dialogs->show(80224);
+ else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_WEST))
+ _vm->_dialogs->show(80225);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene803::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(NOUN_GUTS);
+ _scene->addActiveVocab(VERB_WALKTO);
+
+ if ((!_globals[kFromCockpit] && _globals[kReturnFromCut] && !_globals[kBeamIsUp])
+ || (_globals[kFromCockpit] && !_globals[kExitShip])) {
+ _game._player._spritesPrefix = "";
+ _game._player._spritesChanged = true;
+ }
+}
+
+void Scene803::enter() {
+ _globals[kBetweenRooms] = false;
+ _game._player._visible = false;
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('f', 1));
+ _globals._spriteIndexes[9] = _scene->_sprites.addSprites("*RXMBD_2");
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('d', 1));
+
+ _game.loadQuoteSet(0x31B, 0x31C, 0x31D, 0x31E, 0x31F, 0x320, 0x321, 0x322, 0);
+
+ if (_globals[kHoppyDead]) {
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('e', 1));
+ _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1);
+ int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH);
+ }
+
+ if (!_globals[kBeamIsUp] && !_globals[kReturnFromCut] && (!_globals[kFromCockpit] || _globals[kExitShip])) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ }
+
+ if (!_globals[kFromCockpit]) {
+ if (!_globals[kReturnFromCut]) {
+ if (_scene->_priorSceneId != -2) {
+ _game._player._playerPos = Common::Point(15, 130);
+ _game._player._facing = FACING_EAST;
+ }
+ _game._player._visible = true;
+ } else if (!_globals[kBeamIsUp]){
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 3));
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2));
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15);
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ _vm->_sound->command(14);
+ }
+
+ if (_globals[kBeamIsUp] && !_globals[kReturnFromCut]){
+ if (_globals[kForceBeamDown])
+ _game._player._visible = false;
+ else
+ _game._player._visible = true;
+
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _vm->_sound->command(15);
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 6);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 100);
+ }
+ } else if (!_globals[kExitShip]) {
+ if (!_globals[kBeamIsUp]) {
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 130);
+ _vm->_sound->command(14);
+ } else {
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('c', 1));
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1);
+ _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 140);
+ }
+ } else {
+ _game._player._stepEnabled = false;
+ _game._player._playerPos = Common::Point(197, 96);
+ _game._player._facing = FACING_SOUTHWEST;
+ _game._player._visible = true;
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('d', 1));
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 19);
+ _scene->_sequences.addTimer(1, 150);
+ }
+
+ sceneEntrySound();
+}
+
+void Scene803::step() {
+ if (_game._trigger == 120) {
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 19);
+ _scene->_nextSceneId = 804;
+ }
+
+ if (_game._trigger == 100) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 2);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1);
+ if (!_globals[kHoppyDead]) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 7, 12);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5],SEQUENCE_TRIGGER_EXPIRE, 0, 101);
+ } else {
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2);
+ int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH);
+ _vm->_sound->command(16);
+ _globals[kCameFromCut] = true;
+ _globals[kBeamIsUp] = false;
+ _globals[kReturnFromCut] = false;
+ _globals[kDontRepeat] = false;
+ _globals[kHoppyDead] = true;
+ _globals[kHasWatchedAntigrav] = true;
+
+ if (_globals[kForceBeamDown])
+ _scene->_nextSceneId = _scene->_priorSceneId;
+ else
+ _game._player._stepEnabled = true;
+ }
+ }
+
+ if (_game._trigger == 101) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2);
+ int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH);
+ _vm->_sound->command(16);
+ _globals[kCameFromCut] = true;
+ _globals[kBeamIsUp] = false;
+ _globals[kReturnFromCut] = false;
+ _globals[kDontRepeat] = false;
+ _globals[kHoppyDead] = true;
+ _globals[kHasWatchedAntigrav] = true;
+
+ if (_globals[kForceBeamDown])
+ _scene->_nextSceneId = _scene->_priorSceneId;
+ else
+ _game._player._stepEnabled = true;
+ }
+
+ if (_game._trigger == 80) {
+ if (!_globals[kHoppyDead])
+ _scene->_sequences.addTimer(350, 70);
+
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 3);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90);
+ }
+
+ if (_game._trigger == 70) {
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _vm->_sound->command(31);
+ }
+
+ if (_game._trigger == 71)
+ _scene->_sequences.addTimer(200, 110);
+
+ if (_game._trigger == 90) {
+ int syncIdx = _globals._sequenceIndexes[4];
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 0, 0, 0);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 9);
+ if (_globals[kHoppyDead])
+ _scene->_sequences.addTimer(200, 110);
+ }
+
+ if (_game._trigger == 110)
+ _scene->_nextSceneId = 808;
+
+ if (_game._trigger == 130) {
+ _globals[kBeamIsUp] = true;
+ _scene->_nextSceneId = 804;
+ }
+
+ if (_game._trigger == 140) {
+ if (!_globals[kWindowFixed]) {
+ _scene->_nextSceneId = 810;
+ _globals[kInSpace] = true;
+ } else {
+ if (!_globals[kShieldModInstalled])
+ _game._winStatus = 1;
+ else if (!_globals[kTargetModInstalled])
+ _game._winStatus = 2;
+ else
+ _game._winStatus = 3;
+
+ _vm->quitGame();
+ }
+ }
+
+ if (_game._trigger == 150) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[6]);
+ _vm->_sound->command(18);
+ _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 19);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 151);
+ }
+
+ if (_game._trigger == 151) {
+ _globals[kBeamIsUp] = false;
+ _globals[kFromCockpit] = false;
+ _globals[kExitShip] = false;
+ _game._player._stepEnabled = true;
+ }
+}
+
+void Scene803::preActions() {
+ if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST))
+ _game._player._walkOffScreenSceneId = 802;
+
+ if (_action.isAction(VERB_TAKE, NOUN_SHIP))
+ _game._player._needToWalk = false;
+}
+
+void Scene803::actions() {
+ if (_action.isAction(VERB_TAKE, NOUN_GUTS)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _game._player._visible = false;
+ _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 160);
+ break;
+
+ case 160: {
+ int syncIdx = _globals._sequenceIndexes[9];
+ _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 4);
+ _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]);
+ _scene->_sequences.addTimer(60, 161);
+ }
+ break;
+
+ case 161: {
+ int quoteId = 0x31A + _vm->getRandomNumber(1, 8);
+ _scene->_kernelMessages.add(Common::Point(64, 67), 0x1110, 32, 0, 80, _game.getQuote(quoteId));
+ _scene->_sequences.addTimer(60, 162);
+ }
+ break;
+
+ case 162:
+ _scene->_sequences.remove(_globals._sequenceIndexes[9]);
+ _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 4);
+ _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 163);
+ break;
+
+ case 163:
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
+ _game._player._visible = true;
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_ENTER, NOUN_SHIP)) {
+ _vm->_sound->command(17);
+ _game._player._stepEnabled = false;
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 19);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 120);
+ _globals[kBeamIsUp] = false;
+ } else if (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD))
+ _vm->_dialogs->show(80310);
+ else if (_action._lookFlag)
+ _vm->_dialogs->show(80310);
+ else if (_action.isAction(VERB_LOOK, NOUN_PAD_TO_WEST))
+ _vm->_dialogs->show(80311);
+ else if (_action.isAction(VERB_LOOK, NOUN_GUTS)) {
+ if (_game._storyMode == STORYMODE_NICE)
+ _vm->_dialogs->show(80312);
+ else
+ _vm->_dialogs->show(80313);
+ } else if (_action.isAction(VERB_LOOK, NOUN_BUSHES))
+ _vm->_dialogs->show(80315);
+ else if (_action.isAction(VERB_LOOK, NOUN_SHIP))
+ _vm->_dialogs->show(80317);
+ else if (_action.isAction(VERB_LOOK, NOUN_TOWER))
+ _vm->_dialogs->show(80318);
+ else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES))
+ _vm->_dialogs->show(80319);
+ else if (_action.isAction(VERB_LOOK, NOUN_SKY))
+ _vm->_dialogs->show(80320);
+ else if (_action.isAction(VERB_TAKE, NOUN_SHIP))
+ _vm->_dialogs->show(80321);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene804::Scene804(MADSEngine *vm) : Scene8xx(vm) {
+ _messWithThrottle = false;
+ _movingThrottle = false;
+ _throttleGone = false;
+ _dontPullThrottleAgain = false;
+ _pullThrottleReally = false;
+ _alreadyOrgan = false;
+ _alreadyPop = false;
+
+ _throttleCounter = 0;
+ _resetFrame = -1;
+}
+
+void Scene804::synchronize(Common::Serializer &s) {
+ Scene8xx::synchronize(s);
+
+ s.syncAsByte(_messWithThrottle);
+ s.syncAsByte(_movingThrottle);
+ s.syncAsByte(_throttleGone);
+ s.syncAsByte(_dontPullThrottleAgain);
+ s.syncAsByte(_pullThrottleReally);
+ s.syncAsByte(_alreadyOrgan);
+ s.syncAsByte(_alreadyPop);
+
+ s.syncAsSint16LE(_resetFrame);
+ s.syncAsUint32LE(_throttleCounter);
+}
+
+void Scene804::setup() {
+ Scene8xx::setPlayerSpritesPrefix();
+ Scene8xx::setAAName();
+}
+
+void Scene804::enter() {
+ _messWithThrottle = false;
+ _throttleCounter = 0;
+ _movingThrottle = false;
+ _throttleGone = false;
+ _dontPullThrottleAgain = false;
+ _resetFrame = -1;
+ _pullThrottleReally = false;
+ _alreadyOrgan = false;
+ _alreadyPop = false;
+
+
+ if (_globals[kCopyProtectFailed]) {
+ // Copy protection failed
+ _globals[kInSpace] = true;
+ _globals[kWindowFixed] = 0;
+ }
+
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 0));
+ _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 1));
+ _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 2));
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 3));
+ _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('x', 4));
+ _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('f', 1));
+
+ _game.loadQuoteSet(791, 0);
+
+ if (_globals[kInSpace]) {
+ if (_globals[kWindowFixed]) {
+ _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], 0, 1);
+ _scene->_sequences.addTimer(60, 100);
+ } else {
+ _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1);
+ _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], false, 4, 0, 0, 0);
+ _scene->_sequences.addTimer(160, 70);
+ _game._player._stepEnabled = false;
+ }
+ } else {
+ if (_globals[kBeamIsUp] == 0)
+ _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1);
+
+ if (_globals[kWindowFixed] == 0)
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(133, 139));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8);
+ }
+
+ _scene->loadAnimation(Resources::formatName(804, 'r', 1, EXT_AA, ""));
+
+ Scene8xx::sceneEntrySound();
+
+ if (_globals[kInSpace] && !_globals[kWindowFixed]) {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ _vm->_sound->command(19);
+ }
+}
+
+void Scene804::step() {
+ if (!_messWithThrottle) {
+
+ if ((_throttleGone) && (_movingThrottle) && (_scene->_activeAnimation->getCurrentFrame() == 39)) {
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle
+ (_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(133, 139));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8);
+ _throttleGone = false;
+ }
+
+ if ((_movingThrottle) && (_scene->_activeAnimation->getCurrentFrame() == 42)) {
+ _resetFrame = 0;
+ _movingThrottle = false;
+ }
+
+ if (_game._trigger == 70) {
+ _resetFrame = 42;
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 65)
+ _scene->_sequences.remove(_globals._sequenceIndexes[7]);
+
+ switch (_game._storyMode) {
+ case STORYMODE_NAUGHTY:
+ if (_scene->_activeAnimation->getCurrentFrame() == 81) {
+ _resetFrame = 80;
+ _globals[kInSpace] = false;
+ _globals[kBeamIsUp] = true;
+
+ assert(!_globals[kCopyProtectFailed]);
+ _game._winStatus = 4;
+ _vm->quitGame();
+ }
+ break;
+
+ case STORYMODE_NICE:
+ if (_scene->_activeAnimation->getCurrentFrame() == 68) {
+ _resetFrame = 66;
+ _globals[kInSpace] = false;
+ _globals[kBeamIsUp] = true;
+
+ assert(!_globals[kCopyProtectFailed]);
+ _game._winStatus = 4;
+ _vm->quitGame();
+ }
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 34) {
+ _resetFrame = 36;
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 37) {
+ _resetFrame = 36;
+ if (!_dontPullThrottleAgain) {
+ _dontPullThrottleAgain = true;
+ _scene->_sequences.addTimer(60, 80);
+ }
+ }
+
+ if (_game._trigger == 80) {
+ _scene->_nextSceneId = 803;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() == 7) && (!_globals[kWindowFixed])) {
+ _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1);
+ _scene->_sequences.addTimer(20, 110);
+ _globals[kWindowFixed] = true;
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 10) {
+ _resetFrame = 0;
+ _game._player._stepEnabled = true;
+ _game._objects.setRoom(OBJ_POLYCEMENT, NOWHERE);
+ }
+
+ // FIXME: Original doesn't have resetFrame check. Check why this has been needed
+ if (_resetFrame == -1 && _scene->_activeAnimation->getCurrentFrame() == 1) {
+ int randomVal = _vm->getRandomNumber(29) + 1;
+ switch (randomVal) {
+ case 1:
+ _resetFrame = 25;
+ break;
+ case 2:
+ _resetFrame = 27;
+ break;
+ case 3:
+ _resetFrame = 29;
+ break;
+ default:
+ _resetFrame = 0;
+ break;
+ }
+ }
+
+ switch (_scene->_activeAnimation->getCurrentFrame()) {
+ case 26:
+ case 28:
+ case 31:
+ _resetFrame = 0;
+ break;
+ }
+ } else {
+ if ((_scene->_activeAnimation->getCurrentFrame() == 36) && (!_throttleGone)) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _throttleGone = true;
+ }
+
+ if (_scene->_activeAnimation->getCurrentFrame() == 39) {
+ _movingThrottle = false;
+ switch (_throttleCounter) {
+ case 1:
+ break;
+ case 3:
+ _scene->_sequences.addTimer(130, 120);
+ break;
+ }
+ }
+
+ if (!_movingThrottle) {
+ ++_throttleCounter;
+ _movingThrottle = true;
+ if (_throttleCounter < 4) {
+ _resetFrame = 34;
+ } else {
+ _messWithThrottle = false;
+ _throttleCounter = 0;
+ _game._player._stepEnabled = true;
+ }
+ }
+ }
+
+ if (_game._trigger == 120) {
+ _vm->_dialogs->show(80422);
+ }
+
+ if (_game._trigger == 110) {
+ _vm->_dialogs->show(80426);
+ }
+
+ if (_pullThrottleReally) {
+ _resetFrame = 32;
+ _pullThrottleReally = false;
+ }
+
+ if (_resetFrame >= 0) {
+ if (_resetFrame != _scene->_activeAnimation->getCurrentFrame()) {
+ _scene->_activeAnimation->setCurrentFrame(_resetFrame);
+ _resetFrame = -1;
+ }
+ }
+
+ if (_game._trigger == 90) {
+ _scene->_nextSceneId = 803;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() == 72) && !_alreadyPop) {
+ _vm->_sound->command(21);
+ _alreadyPop = true;
+ }
+
+ if ((_scene->_activeAnimation->getCurrentFrame() == 80) && !_alreadyOrgan) {
+ _vm->_sound->command(22);
+ _alreadyOrgan = true;
+ }
+}
+
+void Scene804::actions() {
+ if (_action.isAction(VERB_LOOK, NOUN_SERVICE_PANEL) ||
+ _action.isAction(VERB_OPEN, NOUN_SERVICE_PANEL)) {
+ _scene->_nextSceneId = 805;
+ } else if ((_action.isAction(VERB_ACTIVATE, NOUN_REMOTE)) && _globals[kTopButtonPushed]) {
+ if (!_globals[kInSpace]) {
+ // Top button pressed on panel in hanger control
+ if (!_globals[kBeamIsUp]) {
+ _globals[kFromCockpit] = true;
+ _globals[kUpBecauseOfRemote] = true;
+ _scene->_nextSceneId = 803;
+ } else {
+ // Player turning off remote
+ _globals[kBeamIsUp] = false;
+ _globals[kUpBecauseOfRemote] = false;
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _vm->_sound->command(15);
+ }
+ }
+ } else if (_action.isAction(VERB_PULL, NOUN_THROTTLE)) {
+ _game._player._stepEnabled = false;
+ if (_globals[kBeamIsUp]) {
+ if (!_game._objects.isInInventory(OBJ_VASE) && _globals[kWindowFixed]) {
+ _vm->_dialogs->show(80423);
+ _game._player._stepEnabled = true;
+ } else {
+ _action._inProgress = false;
+
+ _vm->_dialogs->show(80424);
+ _pullThrottleReally = true;
+ _scene->_kernelMessages.add(Common::Point(78, 75), 0x1110, 0, 0,
+ 120, _game.getQuote(791));
+ }
+ } else {
+ _messWithThrottle = true;
+ }
+ }
+ else if (_action.isAction(VERB_APPLY, NOUN_POLYCEMENT, NOUN_CRACK) ||
+ _action.isAction(VERB_PUT, NOUN_POLYCEMENT, NOUN_CRACK)) {
+ if (!_globals[kWindowFixed]) {
+ _resetFrame = 2;
+ _game._player._stepEnabled = false;
+ }
+ } else if (_action.isAction(VERB_EXIT, NOUN_SHIP)) {
+ _globals[kExitShip] = true;
+ _globals[kFromCockpit] = true;
+ if (_globals[kBeamIsUp]) {
+ _vm->_dialogs->show(80425);
+ _scene->_sequences.remove(_globals._sequenceIndexes[8]);
+ _vm->_sound->command(15);
+ _globals[kBeamIsUp] = false;
+ }
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _scene->_sequences.addTimer(2, 90);
+ } else if (_action._lookFlag) {
+ _vm->_dialogs->show(80410);
+ } else if ((_action.isAction(VERB_LOOK, NOUN_WINDOW)) ||
+ (_action.isAction(VERB_LOOK_OUT, NOUN_WINDOW))) {
+ if (_globals[kBeamIsUp]) {
+ _vm->_dialogs->show(80412);
+ } else {
+ _vm->_dialogs->show(80411);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_CRACK)) {
+ if (_globals[kWindowFixed]) {
+ _vm->_dialogs->show(80414);
+ } else {
+ _vm->_dialogs->show(80413);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_CONTROLS)) {
+ _vm->_dialogs->show(80415);
+ } else if (_action.isAction(VERB_LOOK, NOUN_STATUS_PANEL)) {
+ if (_globals[kBeamIsUp]) {
+ _vm->_dialogs->show(80417);
+ } else {
+ _vm->_dialogs->show(80416);
+ }
+ } else if (_action.isAction(VERB_LOOK, NOUN_TP)) {
+ _vm->_dialogs->show(80418);
+ } else if (_action.isAction(VERB_TAKE, NOUN_TP)) {
+ _vm->_dialogs->show(80419);
+ } else if (_action.isAction(VERB_LOOK, NOUN_INSTRUMENTATION)) {
+ _vm->_dialogs->show(80420);
+ } else if (_action.isAction(VERB_LOOK, NOUN_SEAT)) {
+ _vm->_dialogs->show(80421);
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene805::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+ _scene->addActiveVocab(VERB_REMOVE);
+ _scene->addActiveVocab(NOUN_TARGET_MODULE);
+ _scene->addActiveVocab(NOUN_SHIELD_MODULATOR);
+}
+
+void Scene805::enter() {
+ _game._player._visible = false;
+ _scene->_userInterface.setup(kInputLimitedSentences);
+
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2));
+
+ if (_globals[kShieldModInstalled]) {
+ _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, false);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 25);
+ int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_REMOVE, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY);
+ }
+
+ if (_globals[kTargetModInstalled]) {
+ _scene->_hotspots.activate(OBJ_TARGET_MODULE, false);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 12);
+ int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_REMOVE, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY);
+ }
+
+ sceneEntrySound();
+}
+
+void Scene805::step() {
+ if (_game._trigger == 70) {
+ _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, false);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 25);
+ int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_REMOVE, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY);
+ _globals[kShieldModInstalled] = true;
+ _game._objects.setRoom(OBJ_SHIELD_MODULATOR, NOWHERE);
+ _game._player._stepEnabled = true;
+ _vm->_sound->command(24);
+ }
+
+ if (_game._trigger == 80) {
+ _scene->_hotspots.activate(OBJ_TARGET_MODULE, false);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 12);
+ int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_REMOVE, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0));
+ _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY);
+ _globals[kTargetModInstalled] = true;
+ _game._objects.setRoom(OBJ_TARGET_MODULE, NOWHERE);
+ _game._player._stepEnabled = true;
+ _vm->_sound->command(24);
+ }
+
+ if (_game._trigger == 71) {
+ _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, true);
+ _globals[kShieldModInstalled] = false;
+ _game._objects.addToInventory(OBJ_SHIELD_MODULATOR);
+ _game._player._stepEnabled = true;
+ }
+
+ if (_game._trigger == 81) {
+ _scene->_hotspots.activate(OBJ_TARGET_MODULE, true);
+ _globals[kTargetModInstalled] = false;
+ _game._objects.addToInventory(OBJ_TARGET_MODULE);
+ _game._player._stepEnabled = true;
+ }
+}
+
+void Scene805::preActions() {
+ _game._player._needToWalk = false;
+}
+
+void Scene805::actions() {
+ if (_action.isAction(VERB_EXIT, NOUN_SERVICE_PANEL))
+ _scene->_nextSceneId = 804;
+ else if (_action.isAction(VERB_INSTALL, NOUN_SHIELD_MODULATOR) && _game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, -2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ _game._player._stepEnabled = false;
+ } else if (_action.isAction(VERB_INSTALL, NOUN_TARGET_MODULE) && _game._objects.isInInventory(OBJ_TARGET_MODULE)) {
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ _game._player._stepEnabled = false;
+ } else if (_action.isAction(VERB_REMOVE, NOUN_SHIELD_MODULATOR) && _globals[kShieldModInstalled]) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, -2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ _game._player._stepEnabled = false;
+ } else if (_action.isAction(VERB_REMOVE, NOUN_TARGET_MODULE) && _globals[kTargetModInstalled]) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0);
+ _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81);
+ _game._player._stepEnabled = false;
+ } else if (_action.isAction(VERB_INSTALL, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR))
+ _vm->_dialogs->show(80511);
+ else if (_action.isAction(VERB_INSTALL, NOUN_TARGET_MODULE) && !_game._objects.isInInventory(OBJ_TARGET_MODULE))
+ _vm->_dialogs->show(80510);
+ else if (_action.isAction(VERB_REMOVE, NOUN_LIFE_SUPPORT_MODULE))
+ _vm->_dialogs->show(80512);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Scene807::setup() {
+ _game._player._spritesPrefix = "";
+ // The original was calling Scene8xx::setAAName()
+ _game._aaName = Resources::formatAAName(5);
+}
+
+void Scene807::enter() {
+ if (_globals[kSexOfRex] == REX_FEMALE)
+ _handSpriteId = _scene->_sprites.addSprites("*ROXHAND");
+ else
+ _handSpriteId = _scene->_sprites.addSprites("*REXHAND");
+
+ teleporterEnter();
+
+ // The original uses Scene8xx::SceneEntrySound()
+ if (!_vm->_musicFlag)
+ _vm->_sound->command(2);
+ else
+ _vm->_sound->command(20);
+}
+
+void Scene807::step() {
+ teleporterStep();
+}
+
+void Scene807::actions() {
+ if (teleporterActions()) {
+ _action._inProgress = false;
+ return;
+ }
+
+ if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT))
+ _vm->_dialogs->show(80710);
+ else if (_action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT))
+ _vm->_dialogs->show(80710);
+ else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD) && _action.isAction(VERB_INSPECT, NOUN_KEYPAD))
+ _vm->_dialogs->show(80711);
+ else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY))
+ _vm->_dialogs->show(80712);
+ else if (_action.isAction(VERB_LOOK, NOUN_1_KEY) || _action.isAction(VERB_LOOK, NOUN_2_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_3_KEY) || _action.isAction(VERB_LOOK, NOUN_4_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_5_KEY) || _action.isAction(VERB_LOOK, NOUN_6_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_7_KEY) || _action.isAction(VERB_LOOK, NOUN_8_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_9_KEY) || _action.isAction(VERB_LOOK, NOUN_0_KEY)
+ || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY))
+ _vm->_dialogs->show(80713);
+ else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) && _action._lookFlag)
+ _vm->_dialogs->show(80714);
+ else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene808::Scene808(MADSEngine *vm) : Scene8xx(vm) {
+ _goingTo803 = false;
+}
+
+void Scene808::synchronize(Common::Serializer &s) {
+ Scene8xx::synchronize(s);
+
+ s.syncAsByte(_goingTo803);
+}
+
+void Scene808::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene808::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+
+ _globals._spriteIndexes[4] = _scene->_sprites.addSprites ("*REXHAND");
+ _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0));
+ _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1));
+ _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 2));
+
+ if (_globals[kTopButtonPushed])
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ else
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+
+ _goingTo803 = false;
+
+ if (_globals[kCameFromCut] && _globals[kCutX] != 0) {
+ _globals[kCutX] = 0;
+ _globals[kCameFromCut] = false;
+ _globals[kReturnFromCut] = false;
+ _globals[kBeamIsUp] = false;
+ _globals[kForceBeamDown] = false;
+ _globals[kDontRepeat] = false;
+ } else if ((_scene->_priorSceneId == 803) && _globals[kReturnFromCut]){
+ _globals[kDontRepeat] = false;
+ _globals[kBeamIsUp] = true;
+ _globals[kAntigravClock] = _scene->_frameStartTime;
+ _globals[kAntigravTiming] = _scene->_frameStartTime;
+ _globals[kForceBeamDown] = false;
+ _globals[kReturnFromCut] = false;
+ }
+
+ _globals[kBetweenRooms] = false;
+
+ if (_globals[kBeamIsUp]) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
+ }
+
+ sceneEntrySound();
+}
+
+void Scene808::actions() {
+ if (_action.isAction(VERB_PRESS, NOUN_START_BUTTON_2)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 211));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ break;
+
+ case 70:
+ if (!_globals[kBeamIsUp] && !_globals[kTopButtonPushed]) {
+ _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
+ _goingTo803 = true;
+ _vm->_sound->command(20);
+ _vm->_sound->command(25);
+ }
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 211));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
+ break;
+
+ case 71:
+ _game._player._stepEnabled = true;
+ if (_goingTo803 && !_globals[kTopButtonPushed]) {
+ _goingTo803 = false;
+ _globals[kReturnFromCut] = true;
+ _scene->_nextSceneId = 803;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PRESS, NOUN_TIMER_BUTTON_2)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 186));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90);
+ break;
+ case 90:
+ if (_globals[kTopButtonPushed]) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[1]);
+ _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8);
+ _vm->_sound->command(20);
+ }
+ _globals[kTopButtonPushed] = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 186));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 91);
+ break;
+
+ case 91:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PRESS, NOUN_REMOTE_BUTTON_2)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 163));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ break;
+
+ case 80:
+ if (!_globals[kTopButtonPushed]) {
+ _scene->_sequences.remove(_globals._sequenceIndexes[2]);
+ _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1);
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8);
+ _vm->_sound->command(20);
+ }
+ _globals[kTopButtonPushed] = true;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 163));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 81);
+ break;
+
+ case 81:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PRESS, NOUN_START_BUTTON_1)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(168, 211));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70);
+ break;
+
+ case 70:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PRESS, NOUN_REMOTE_BUTTON_1)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(172, 163));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 80);
+ break;
+
+ case 80:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_PRESS, NOUN_TIMER_BUTTON_1)) {
+ switch (_game._trigger) {
+ case 0:
+ _game._player._stepEnabled = false;
+ _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0);
+ _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(172, 186));
+ _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2);
+ _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90);
+ break;
+
+ case 90:
+ _game._player._stepEnabled = true;
+ break;
+
+ default:
+ break;
+ }
+ } else if (_action.isAction(VERB_EXIT, NOUN_PANEL)) {
+ _scene->_nextSceneId = 801;
+ _globals[kBetweenRooms] = true;
+ } else
+ return;
+
+ _action._inProgress = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+Scene810::Scene810(MADSEngine *vm) : Scene8xx(vm) {
+ _moveAllowed = false;
+}
+
+void Scene810::synchronize(Common::Serializer &s) {
+ Scene8xx::synchronize(s);
+
+ s.syncAsByte(_moveAllowed);
+}
+
+void Scene810::setup() {
+ setPlayerSpritesPrefix();
+ setAAName();
+}
+
+void Scene810::enter() {
+ _scene->_userInterface.setup(kInputLimitedSentences);
+ _game._player._visible = false;
+ _game._player._stepEnabled = false;
+ _scene->loadAnimation(Resources::formatName(810, 'a', -1, EXT_AA, ""));
+ _moveAllowed = true;
+
+ sceneEntrySound();
+}
+
+void Scene810::step() {
+ if ((_scene->_activeAnimation->getCurrentFrame() == 200) && _moveAllowed) {
+ _scene->_sequences.addTimer(100, 70);
+ _moveAllowed = false;
+ }
+
+ if (_game._trigger == 70)
+ _scene->_nextSceneId = 804;
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Nebular
+} // End of namespace MADS
diff --git a/engines/mads/nebular/nebular_scenes8.h b/engines/mads/nebular/nebular_scenes8.h
new file mode 100644
index 0000000000..7f2c34a843
--- /dev/null
+++ b/engines/mads/nebular/nebular_scenes8.h
@@ -0,0 +1,165 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_NEBULAR_SCENES8_H
+#define MADS_NEBULAR_SCENES8_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/nebular/nebular_scenes.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+class Scene8xx : public NebularScene {
+protected:
+ /**
+ * Initial setup code shared by several scenes
+ */
+ void setPlayerSpritesPrefix();
+
+ /**
+ * Initial setup code shared by several scenes
+ */
+ void setAAName();
+
+ /**
+ * Common scene enter code used by multiple scenes
+ */
+ void sceneEntrySound();
+public:
+ Scene8xx(MADSEngine *vm) : NebularScene(vm) {}
+};
+
+class Scene801 : public Scene8xx{
+private:
+ bool _walkThroughDoor;
+
+public:
+ Scene801(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene802 : public Scene8xx{
+public:
+ Scene802(MADSEngine *vm) : Scene8xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene803 : public Scene8xx{
+public:
+ Scene803(MADSEngine *vm) : Scene8xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene804 : public Scene8xx {
+private:
+ bool _messWithThrottle;
+ bool _movingThrottle;
+ bool _throttleGone;
+ bool _dontPullThrottleAgain;
+ bool _pullThrottleReally;
+ bool _alreadyOrgan;
+ bool _alreadyPop;
+ uint32 _throttleCounter;
+ int _resetFrame;
+
+public:
+ Scene804(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene805 : public Scene8xx{
+public:
+ Scene805(MADSEngine *vm) : Scene8xx(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void preActions();
+ virtual void actions();
+};
+
+class Scene807 : public SceneTeleporter {
+public:
+ Scene807(MADSEngine *vm) : SceneTeleporter(vm) {}
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions();
+};
+
+class Scene808 : public Scene8xx{
+private:
+ bool _goingTo803;
+
+public:
+ Scene808(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void actions();
+};
+
+class Scene810 : public Scene8xx{
+private:
+ bool _moveAllowed;
+
+public:
+ Scene810(MADSEngine *vm);
+ void synchronize(Common::Serializer &s);
+
+ virtual void setup();
+ virtual void enter();
+ virtual void step();
+ virtual void actions() {};
+};
+
+} // End of namespace Nebular
+} // End of namespace MADS
+
+#endif /* MADS_NEBULAR_SCENES8_H */
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
new file mode 100644
index 0000000000..c540eb4382
--- /dev/null
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -0,0 +1,3424 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+#include "common/algorithm.h"
+#include "common/debug.h"
+#include "common/memstream.h"
+#include "mads/sound.h"
+#include "mads/nebular/sound_nebular.h"
+
+namespace MADS {
+
+namespace Nebular {
+
+bool AdlibChannel::_channelsEnabled;
+
+AdlibChannel::AdlibChannel() {
+ _activeCount = 0;
+ _field1 = 0;
+ _field2 = 0;
+ _field3 = 0;
+ _field4 = 0;
+ _sampleIndex = 0;
+ _volume = 0;
+ _field7 = 0;
+ _field8 = 0;
+ _field9 = 0;
+ _fieldA = 0;
+ _fieldB = 0;
+ _fieldC = 0;
+ _fieldD = 0;
+ _fieldE = 0;
+ _ptr1 = nullptr;
+ _pSrc = nullptr;
+ _ptr3 = nullptr;
+ _ptr4 = nullptr;
+ _field17 = 0;
+ _field19 = 0;
+ _soundData = nullptr;
+ _field1D = 0;
+ _field1E = 0;
+ _field1F = 0;
+
+ _field20 = 0;
+}
+
+void AdlibChannel::reset() {
+ _activeCount = 0;
+ _field1 = 0;
+ _field2 = 0;
+ _field3 = 0;
+}
+
+void AdlibChannel::enable(int flag) {
+ if (_activeCount) {
+ _fieldE = flag;
+
+ // WORKAROUND: Original set _soundData pointer to flag. Since this seems
+ // just intended to invalidate any prior pointer, I've replaced it with
+ // a simple null pointer
+ _soundData = nullptr;
+ }
+
+ _channelsEnabled = true;
+}
+
+void AdlibChannel::setPtr2(byte *pData) {
+ _pSrc = pData;
+ _field2 = 0xFF;
+ _fieldA = 1;
+ _field9 = 1;
+}
+
+void AdlibChannel::load(byte *pData) {
+ _ptr1 = _pSrc = _ptr3 = pData;
+ _ptr4 = _soundData = pData;
+ _fieldA = 0xFF;
+ _activeCount = 1;
+ _fieldD = 64;
+ _field1 = 0;
+ _field1F = 0;
+ _field2 = _field3 = 0;
+ _volume = _field7 = 0;
+ _field1D = _field1E = 0;
+ _fieldE = 0;
+ _field9 = 0;
+ _fieldB = 0;
+ _field17 = 0;
+ _field19 = 0;
+}
+
+void AdlibChannel::check(byte *nullPtr) {
+ if (_activeCount && _fieldE) {
+ if (!_field1E) {
+ _pSrc = nullPtr;
+ _fieldE = 0;
+ } else {
+ _field2 = 0xFF;
+ _fieldA = 4;
+ if (!_field9)
+ _field9 = 1;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------*/
+
+AdlibSample::AdlibSample(Common::SeekableReadStream &s) {
+ _attackRate = s.readByte();
+ _decayRate = s.readByte();
+ _sustainLevel = s.readByte();
+ _releaseRate = s.readByte();
+ _egTyp = s.readByte() != 0;
+ _ksr = s.readByte() != 0;
+ _totalLevel = s.readByte();
+ _scalingLevel = s.readByte();
+ _waveformSelect = s.readByte();
+ _freqMultiple = s.readByte();
+ _feedback = s.readByte();
+ _ampMod = s.readByte() != 0;
+ _vib = s.readByte();
+ _alg = s.readByte();
+ _fieldE = s.readByte();
+ s.skip(1);
+ _freqMask = s.readUint16LE();
+ _freqBase = s.readUint16LE();
+ _field14 = s.readUint16LE();
+}
+
+/*-----------------------------------------------------------------------*/
+
+ASound::ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, int dataOffset) {
+ // Open up the appropriate sound file
+ if (!_soundFile.open(filename))
+ error("Could not open file - %s", filename.c_str());
+
+ // Initialize fields
+ _commandParam = 0;
+ _activeChannelPtr = nullptr;
+ _samplePtr = nullptr;
+ _frameCounter = 0;
+ _isDisabled = false;
+ _v1 = 0;
+ _v2 = 0;
+ _activeChannelNumber = 0;
+ _freqMask1 = _freqMask2 = 0;
+ _freqBase1 = _freqBase2 = 0;
+ _channelNum1 = _channelNum2 = 0;
+ _v7 = 0;
+ _v8 = 0;
+ _v9 = 0;
+ _v10 = 0;
+ _pollResult = 0;
+ _resultFlag = 0;
+ _nullData[0] = _nullData[1] = 0;
+ Common::fill(&_ports[0], &_ports[256], 0);
+ _stateFlag = false;
+ _activeChannelReg = 0;
+ _v11 = 0;
+ _randomSeed = 1234;
+ _amDep = _vibDep = _splitPoint = true;
+
+ _samplesTillCallback = 0;
+ _samplesTillCallbackRemainder = 0;
+ _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND;
+ _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
+
+ for (int i = 0; i < 11; ++i) {
+ _channelData[i]._field0 = 0;
+ _channelData[i]._freqMask = 0;
+ _channelData[i]._freqBase = 0;
+ _channelData[i]._field6 = 0;
+ }
+
+ AdlibChannel::_channelsEnabled = false;
+
+ // Store passed parameters, and setup OPL
+ _dataOffset = dataOffset;
+ _mixer = mixer;
+ _opl = opl;
+
+ _opl->init(getRate());
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1,
+ Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+
+ // Initialize the Adlib
+ adlibInit();
+
+ // Reset the adlib
+ command0();
+}
+
+ASound::~ASound() {
+ Common::List<CachedDataEntry>::iterator i;
+ for (i = _dataCache.begin(); i != _dataCache.end(); ++i)
+ delete[] (*i)._data;
+
+ _mixer->stopHandle(_soundHandle);
+}
+
+void ASound::adlibInit() {
+ write(4, 0x60);
+ write(4, 0x80);
+ write(2, 0xff);
+ write(4, 0x21);
+ write(4, 0x60);
+ write(4, 0x80);
+}
+
+int ASound::stop() {
+ command0();
+ int result = _pollResult;
+ _pollResult = 0;
+ return result;
+}
+
+int ASound::poll() {
+ // Update any playing sounds
+ update();
+
+ // Return result
+ int result = _pollResult;
+ _pollResult = 0;
+ return result;
+}
+
+void ASound::noise() {
+ int randomVal = getRandomNumber();
+
+ if (_v1) {
+ setFrequency(_channelNum1, ((randomVal ^ 0xFFFF) & _freqMask1) + _freqBase1);
+ }
+
+ if (_v2) {
+ setFrequency(_channelNum2, (randomVal & _freqMask2) + _freqBase2);
+ }
+}
+
+void ASound::write(int reg, int val) {
+ _queue.push(RegisterValue(reg, val));
+}
+
+int ASound::write2(int state, int reg, int val) {
+ // TODO: Original has a state parameter, not used when in Adlib mode?
+ _ports[reg] = val;
+ write(reg, val);
+ return state;
+}
+
+void ASound::flush() {
+ Common::StackLock slock(_driverMutex);
+
+ while (!_queue.empty()) {
+ RegisterValue v = _queue.pop();
+ _opl->writeReg(v._regNum, v._value);
+ }
+}
+
+void ASound::channelOn(int reg, int volume) {
+ write2(8, reg, (_ports[reg] & 0xC0) | (volume & 0x3F));
+}
+
+void ASound::channelOff(int reg) {
+ write2(8, reg, _ports[reg] | 0x3F);
+}
+
+void ASound::resultCheck() {
+ if (_resultFlag != 1) {
+ _resultFlag = 1;
+ _pollResult = 1;
+ }
+}
+
+byte *ASound::loadData(int offset, int size) {
+ // First scan for an existing copy
+ Common::List<CachedDataEntry>::iterator i;
+ for (i = _dataCache.begin(); i != _dataCache.end(); ++i) {
+ CachedDataEntry &e = *i;
+ if (e._offset == offset)
+ return e._data;
+ }
+
+ // No existing entry found, so load up data and store as a new entry
+ CachedDataEntry rec;
+ rec._offset = offset;
+ rec._data = new byte[size];
+ _soundFile.seek(_dataOffset + offset);
+ _soundFile.read(rec._data, size);
+ _dataCache.push_back(rec);
+
+ // Return the data
+ return rec._data;
+}
+
+void ASound::playSound(int offset, int size) {
+ // Load the specified data block
+ playSoundData(loadData(offset, size));
+}
+
+void ASound::playSoundData(byte *pData, int startingChannel) {
+ // Scan for a high level free channel
+ for (int i = startingChannel; i < ADLIB_CHANNEL_COUNT; ++i) {
+ if (!_channels[i]._activeCount) {
+ _channels[i].load(pData);
+ return;
+ }
+ }
+
+ // None found, do a secondary scan for an interruptable channel
+ for (int i = ADLIB_CHANNEL_COUNT - 1; i >= startingChannel; --i) {
+ if (_channels[i]._fieldE == 0xFF) {
+ _channels[i].load(pData);
+ return;
+ }
+ }
+}
+
+bool ASound::isSoundActive(byte *pData) {
+ for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i) {
+ if (_channels[i]._activeCount && _channels[i]._soundData == pData)
+ return true;
+ }
+
+ return false;
+}
+
+void ASound::setFrequency(int channel, int freq) {
+ write2(8, 0xA0 + channel, freq & 0xFF);
+ write2(8, 0xB0 + channel, (freq >> 8) | 0x20);
+}
+
+int ASound::getRandomNumber() {
+ int v = 0x9248 + (int)_randomSeed;
+ _randomSeed = ((v >> 3) | (v << 13)) & 0xFFFF;
+ return _randomSeed;
+}
+
+void ASound::update() {
+ getRandomNumber();
+ if (_isDisabled)
+ return;
+
+ ++_frameCounter;
+ pollChannels();
+ checkChannels();
+
+ if (_v1 == _v2) {
+ if (_resultFlag != -1) {
+ _resultFlag = -1;
+ _pollResult = -1;
+ }
+ } else {
+ if (_v1) {
+ _freqBase1 += _v7;
+ if (!--_v1) {
+ if (!_v2 || _channelNum1 != _channelNum2) {
+ write2(8, 0xA0 + _channelNum1, 0);
+ write2(8, 0xB0 + _channelNum1, 0);
+ }
+ }
+ }
+
+ if (_v2) {
+ _freqBase2 += _v8;
+ if (!--_v2) {
+ if (!_v1 || _channelNum2 != _channelNum1) {
+ write2(8, 0xA0 + _channelNum2, 0);
+ write2(8, 0xB0 + _channelNum2, 0);
+ }
+ }
+ }
+ }
+}
+
+void ASound::pollChannels() {
+ _activeChannelNumber = 0;
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) {
+ _activeChannelPtr = &_channels[i];
+ pollActiveChannel();
+ }
+}
+
+void ASound::checkChannels() {
+ if (AdlibChannel::_channelsEnabled) {
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ _channels[i].check(_nullData);
+ }
+}
+
+void ASound::pollActiveChannel() {
+ AdlibChannel *chan = _activeChannelPtr;
+
+ if (chan->_activeCount) {
+ if (chan->_field8 > 0 && --chan->_field8 == 0)
+ updateOctave();
+
+ bool updateFlag = true;
+ if (--_activeChannelPtr->_activeCount <= 0) {
+ for (;;) {
+ byte *pSrc = chan->_pSrc;
+ if (!chan->_ptr1) {
+ warning("pollActiveChannel(): No data found for sound channel");
+ break;
+ }
+ if (!(*pSrc & 0x80) || (*pSrc <= 0xF0)) {
+ if (updateFlag)
+ updateActiveChannel();
+
+ chan->_field4 = *pSrc++;
+ chan->_activeCount = *pSrc++;
+ chan->_pSrc += 2;
+
+ if (!chan->_field4 || !chan->_activeCount) {
+ updateOctave();
+ } else {
+ chan->_field8 = chan->_activeCount - chan->_field7;
+ updateChannelState();
+ }
+
+ // Break out of processing loop
+ break;
+ } else {
+ updateFlag = false;
+
+ switch ((~*pSrc) & 0xF) {
+ case 0:
+ if (!chan->_field17) {
+ if (*++pSrc == 0) {
+ chan->_pSrc += 2;
+ chan->_ptr3 = chan->_pSrc;
+ chan->_field17 = 0;
+ } else {
+ chan->_field17 = *pSrc;
+ chan->_pSrc = chan->_ptr3;
+ }
+ } else if (--chan->_field17) {
+ chan->_pSrc = chan->_ptr3;
+ } else {
+ chan->_pSrc += 2;
+ chan->_ptr3 = chan->_pSrc;
+ }
+ break;
+
+ case 1:
+ if (!chan->_field19) {
+ if (*++pSrc == 0) {
+ chan->_pSrc += 2;
+ chan->_ptr4 = chan->_pSrc;
+ chan->_ptr3 = chan->_pSrc;
+ chan->_field17 = 0;
+ chan->_field19 = 0;
+ } else {
+ chan->_field19 = *pSrc;
+ chan->_pSrc = chan->_ptr4;
+ chan->_ptr3 = chan->_ptr4;
+ }
+ } else if (--chan->_field19) {
+ chan->_ptr4 = chan->_pSrc;
+ chan->_ptr3 = chan->_pSrc;
+ } else {
+ chan->_pSrc += 2;
+ chan->_ptr4 = chan->_pSrc;
+ chan->_ptr3 = chan->_pSrc;
+ }
+ break;
+
+ case 2:
+ // Loop sound data
+ chan->_field1 = 0;
+ chan->_field2 = chan->_field3 = 0;
+ chan->_volume = chan->_field7 = 0;
+ chan->_field1D = chan->_field1E = 0;
+ chan->_field8 = 0;
+ chan->_field9 = 0;
+ chan->_fieldB = 0;
+ chan->_field17 = 0;
+ chan->_field19 = 0;
+ chan->_fieldD = 0x40;
+ chan->_ptr1 = chan->_soundData;
+ chan->_pSrc = chan->_soundData;
+ chan->_ptr3 = chan->_soundData;
+ chan->_ptr4 = chan->_soundData;
+
+ chan->_pSrc += 2;
+ break;
+
+ case 3:
+ chan->_sampleIndex = *++pSrc;
+ chan->_pSrc += 2;
+ loadSample(chan->_sampleIndex);
+ break;
+
+ case 4:
+ chan->_field7 = *++pSrc;
+ chan->_pSrc += 2;
+ break;
+
+ case 5:
+ chan->_field1 = *++pSrc;
+ chan->_pSrc += 2;
+ break;
+
+ case 6:
+ ++pSrc;
+ if (chan->_fieldE) {
+ chan->_pSrc += 2;
+ } else {
+ chan->_volume = *pSrc >> 1;
+ updateFlag = true;
+ chan->_pSrc += 2;
+ }
+ break;
+
+ case 7:
+ ++pSrc;
+ if (!chan->_fieldE) {
+ chan->_fieldA = *pSrc;
+ chan->_field2 = *++pSrc;
+ chan->_field9 = 1;
+ }
+
+ chan->_pSrc += 3;
+ break;
+
+ case 8:
+ chan->_field1D = *++pSrc;
+ chan->_pSrc += 2;
+ break;
+
+ case 9: {
+ int v1 = *++pSrc;
+ ++pSrc;
+ int v2 = (v1 - 1) & getRandomNumber();
+ int v3 = pSrc[v2];
+ int v4 = pSrc[v1];
+
+ pSrc[v4 + v1 + 1] = v3;
+ chan->_pSrc += v1 + 3;
+ break;
+ }
+
+ case 10:
+ ++pSrc;
+ if (chan->_fieldE) {
+ chan->_pSrc += 2;
+ } else {
+ chan->_field1E = *pSrc >> 1;
+ updateFlag = true;
+ chan->_pSrc += 2;
+ }
+ break;
+
+ case 11:
+ chan->_fieldD = *++pSrc;
+ updateFlag = true;
+ chan->_pSrc += 2;
+ break;
+
+ case 12:
+ chan->_fieldC = *++pSrc;
+ chan->_field3 = *++pSrc;
+ chan->_fieldB = 1;
+ chan->_pSrc += 2;
+ break;
+
+ case 13:
+ ++pSrc;
+ chan->_pSrc += 2;
+ break;
+
+ case 14:
+ chan->_field1F = *++pSrc;
+ chan->_pSrc += 2;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ if (chan->_field1)
+ updateFNumber();
+
+ updateFlag = false;
+ if (chan->_field9 || chan->_fieldB) {
+ if (!--chan->_field9) {
+ chan->_field9 = chan->_fieldA;
+ if (chan->_field2) {
+ int8 newVal = (int8)chan->_field2 + (int8)chan->_field1E;
+ if (newVal < 0) {
+ chan->_field9 = 0;
+ newVal = 0;
+ } else if (newVal > 63) {
+ chan->_field9 = 0;
+ newVal = 63;
+ }
+
+ chan->_field1E = newVal;
+ updateFlag = true;
+ }
+ }
+
+ if (!--chan->_fieldB) {
+ chan->_fieldB = chan->_fieldC;
+ if (chan->_field3) {
+ chan->_fieldD = chan->_field3;
+ updateFlag = true;
+ }
+ }
+
+ if (updateFlag)
+ updateActiveChannel();
+ }
+ }
+
+ ++_activeChannelNumber;
+}
+
+void ASound::updateOctave() {
+ int reg = 0xB0 + _activeChannelNumber;
+ write2(8, reg, _ports[reg] & 0xDF);
+}
+
+static int _vList1[] = {
+ 0x200, 0x21E, 0x23F, 0x261, 0x285, 0x2AB,
+ 0x2D4, 0x2FF, 0x32D, 0x35D, 0x390, 0x3C7
+};
+
+void ASound::updateChannelState() {
+ updateActiveChannel();
+
+ if (_channelData[_activeChannelNumber]._field0) {
+ if (_channelNum1 == _activeChannelNumber)
+ _stateFlag = 0;
+ if (_channelNum2 == _activeChannelNumber)
+ _stateFlag = 1;
+
+ if (!_stateFlag) {
+ _stateFlag = 1;
+ if (_v1)
+ write2(8, 0xB0 + _channelNum1, _ports[0xB0 + _channelNum1] & 0xDF);
+
+ _channelNum1 = _activeChannelNumber;
+ _v1 = _channelData[_channelNum1]._field0;
+ _freqMask1 = _channelData[_channelNum1]._freqMask;
+ _freqBase1 = _channelData[_channelNum1]._freqBase;
+ _v7 = _channelData[_channelNum1]._field6;
+ } else {
+ _stateFlag = 0;
+ if (_v2)
+ write2(8, 0xB0 + _channelNum2, _ports[0xB0 + _channelNum2] & 0xDF);
+
+ _channelNum2 = _activeChannelNumber;
+ _v2 = _channelData[_channelNum2]._field0;
+ _freqMask2 = _channelData[_channelNum2]._freqMask;
+ _freqBase2 = _channelData[_channelNum2]._freqBase;
+ _v8 = _channelData[_channelNum2]._field6;
+ }
+
+ resultCheck();
+ } else {
+ int reg = 0xA0 + _activeChannelNumber;
+ int vTimes = (_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) / 12;
+ int vOffset = (_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) % 12;
+ int val = _vList1[vOffset] + _activeChannelPtr->_field1D;
+ write2(8, reg, val & 0xFF);
+
+ reg += 0x10;
+ write2(8, reg, (_ports[reg] & 0x20) | (vTimes << 2) | (val >> 8));
+
+ write2(8, reg, _ports[reg] | 0x20);
+ }
+}
+
+static const int outputIndexes[] = {
+ 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 13, 16, 14, 17
+};
+static const int outputChannels[] = {
+ 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 0
+};
+static const int volumeList[] = {
+ 0x3F, 0x3F, 0x36, 0x31, 0x2D, 0x2A, 0x28, 0x26, 0x24, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C,
+ 0x1B, 0x1A, 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12,
+ 0x11, 0x11, 0x10, 0x10, 0x0F, 0x0F, 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0C, 0x0B, 0x0B, 0x0A, 0x0A,
+ 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+void ASound::updateActiveChannel() {
+ int reg = 0x40 + outputChannels[outputIndexes[_activeChannelNumber * 2 + 1]];
+ int portVal = _ports[reg] & 0xFFC0;
+ int newVolume = CLIP(_activeChannelPtr->_volume + _activeChannelPtr->_field1E, 0, 63);
+
+ // Note: Original had a whole block not seeming to be used, since the initialisation
+ // sets a variable to 5660h, and doesn't change it, so the branch is never taken
+ int val = CLIP(newVolume - volumeList[_activeChannelPtr->_fieldD], 0, 63);
+ val = (63 - val) | portVal;
+
+ int val2 = CLIP(newVolume - volumeList[-(_activeChannelPtr->_fieldD - 127)], 0, 63);
+ val2 = (63 - val2) | portVal;
+ write2(0, reg, val);
+ write2(2, reg, val2);
+}
+
+void ASound::loadSample(int sampleIndex) {
+ _activeChannelReg = 0xB0 + _activeChannelNumber;
+ write2(8, _activeChannelReg, _ports[_activeChannelReg] & 0xDF);
+
+ _activeChannelReg = _activeChannelNumber;
+ _samplePtr = &_samples[sampleIndex * 2];
+ _v11 = outputChannels[outputIndexes[_activeChannelReg * 2]];
+ processSample();
+
+ AdlibChannelData &cd = _channelData[_activeChannelNumber];
+ cd._field6 = _samplePtr->_field14;
+ cd._freqBase = _samplePtr->_freqBase;
+ cd._freqMask = _samplePtr->_freqMask;
+ cd._field0 = _samplePtr->_fieldE;
+
+ _samplePtr = &_samples[sampleIndex * 2 + 1];
+ _v11 = outputChannels[outputIndexes[_activeChannelReg * 2 + 1]];
+ processSample();
+}
+
+void ASound::processSample() {
+ // Write out vib flags and split point
+ write2(8, 0x40 + _v11, 0x3F);
+ int depthRhythm = (_ports[0xBD] & 0x3F) | (_amDep ? 0x80 : 0) |
+ (_vibDep ? 0x40 : 0);
+ write2(8, 0xBD, depthRhythm);
+ write2(8, 8, _splitPoint ? 0x40 : 0);
+
+ // Write out feedback & Alg
+ int val = (_samplePtr->_feedback << 1) | (1 - _samplePtr->_alg);
+ write2(8, 0xC0 + _activeChannelReg, val);
+
+ // Write out attack/decay rate
+ val = (_samplePtr->_attackRate << 4) | (_samplePtr->_decayRate & 0xF);
+ write2(8, 0x60 + _v11, val);
+
+ // Write out sustain level/release rate
+ val = (_samplePtr->_sustainLevel << 4) | (_samplePtr->_releaseRate & 0xF);
+ write2(8, 0x80 + _v11, val);
+
+ // Write out misc flags
+ val = (_samplePtr->_ampMod ? 0x80 : 0) | (_samplePtr->_vib ? 0x40 : 0)
+ | (_samplePtr->_egTyp ? 0x20 : 0) | (_samplePtr->_ksr ? 0x10 : 0)
+ | (_samplePtr->_freqMultiple & 0xF);
+ write2(8, 0x20 + _v11, val);
+
+ // Write out waveform select
+ write2(8, 0xE0 + _v11, _samplePtr->_waveformSelect & 3);
+
+ // Write out total level & scaling level
+ val = -((_samplePtr->_totalLevel & 0x3F) - 0x3F) | (_samplePtr->_scalingLevel << 6);
+ write2(8, 0x40 + _v11, val);
+}
+
+void ASound::updateFNumber() {
+ int loReg = 0xA0 + _activeChannelNumber;
+ int hiReg = 0xB0 + _activeChannelNumber;
+ int val1 = (_ports[hiReg] & 0x1F) << 8;
+ val1 += _ports[loReg] + _activeChannelPtr->_field1;
+ write2(8, loReg, val1);
+
+ int val2 = (_ports[hiReg] & 0x20) | (val1 >> 8);
+ write2(8, hiReg, val2);
+}
+
+int ASound::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock slock(_driverMutex);
+
+ int32 samplesLeft = numSamples;
+ memset(buffer, 0, sizeof(int16) * numSamples);
+ while (samplesLeft) {
+ if (!_samplesTillCallback) {
+ poll();
+ flush();
+
+ _samplesTillCallback = _samplesPerCallback;
+ _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
+ if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) {
+ _samplesTillCallback++;
+ _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND;
+ }
+ }
+
+ int32 render = MIN<int>(samplesLeft, _samplesTillCallback);
+ samplesLeft -= render;
+ _samplesTillCallback -= render;
+
+ _opl->readBuffer(buffer, render);
+ buffer += render;
+ }
+ return numSamples;
+}
+
+int ASound::command0() {
+ bool isDisabled = _isDisabled;
+ _isDisabled = true;
+
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ _channels[i].reset();
+
+ _v1 = 0;
+ _v2 = 0;
+ _freqMask1 = _freqMask2 = 0;
+ _freqBase1 = _freqBase2 = 0;
+ _v7 = 0;
+ _v8 = 0;
+
+ // Reset Adlib port registers
+ for (int reg = 0x4F; reg >= 0x40; --reg)
+ write2(8, reg, 0x3F);
+ for (int reg = 0xFF; reg >= 0x60; --reg)
+ write2(8, reg, 0);
+ for (int reg = 0x3F; reg > 0; --reg)
+ write2(8, reg, 0);
+ write2(8, 1, 0x20);
+
+ _isDisabled = isDisabled;
+ return 0;
+}
+
+int ASound::command1() {
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ _channels[i].enable(0xFF);
+ return 0;
+}
+
+int ASound::command2() {
+ for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i)
+ _channels[i].setPtr2(_nullData);
+ return 0;
+}
+
+int ASound::command3() {
+ for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i)
+ _channels[i].enable(0xFF);
+ return 0;
+}
+
+int ASound::command4() {
+ for (int i = ADLIB_CHANNEL_MIDWAY; i < ADLIB_CHANNEL_COUNT; ++i)
+ _channels[i].setPtr2(_nullData);
+ return 0;
+}
+
+int ASound::command5() {
+ for (int i = 5; i < ADLIB_CHANNEL_COUNT; ++i)
+ _channels[i].enable(0xFF);
+ return 0;
+}
+
+int ASound::command6() {
+ _v9 = _v1;
+ _v1 = 0;
+ _v10 = _v2;
+ _v2 = 0;
+
+ channelOff(0x43);
+ channelOff(0x44);
+ channelOff(0x45);
+ channelOff(0x4B);
+ channelOff(0x4C);
+ channelOff(0x4D);
+ channelOff(0x53);
+ channelOff(0x54);
+ channelOff(0x55);
+
+ return 0;
+}
+
+int ASound::command7() {
+ channelOn(0x43, _channels[0]._volume);
+ channelOn(0x44, _channels[1]._volume);
+ channelOn(0x45, _channels[2]._volume);
+ channelOn(0x4B, _channels[3]._volume);
+ channelOn(0x4C, _channels[4]._volume);
+ channelOn(0x4D, _channels[5]._volume);
+
+ _v1 = _v9;
+ _v2 = _v10;
+
+ if (_v9 != _v10)
+ resultCheck();
+
+ _isDisabled = 0;
+ return _v10;
+}
+
+int ASound::command8() {
+ int result = 0;
+ for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i)
+ result |= _channels[i]._activeCount;
+
+ return result;
+}
+
+/*-----------------------------------------------------------------------*/
+
+const ASound1::CommandPtr ASound1::_commandList[42] = {
+ &ASound1::command0, &ASound1::command1, &ASound1::command2, &ASound1::command3,
+ &ASound1::command4, &ASound1::command5, &ASound1::command6, &ASound1::command7,
+ &ASound1::command8, &ASound1::command9, &ASound1::command10, &ASound1::command11,
+ &ASound1::command12, &ASound1::command13, &ASound1::command14, &ASound1::command15,
+ &ASound1::command16, &ASound1::command17, &ASound1::command18, &ASound1::command19,
+ &ASound1::command20, &ASound1::command21, &ASound1::command22, &ASound1::command23,
+ &ASound1::command24, &ASound1::command25, &ASound1::command26, &ASound1::command27,
+ &ASound1::command28, &ASound1::command29, &ASound1::command30, &ASound1::command31,
+ &ASound1::command32, &ASound1::command33, &ASound1::command34, &ASound1::command35,
+ &ASound1::command36, &ASound1::command37, &ASound1::command38, &ASound1::command39,
+ &ASound1::command40, &ASound1::command41
+};
+
+ASound1::ASound1(Audio::Mixer *mixer, FM_OPL *opl)
+ : ASound(mixer, opl, "asound.001", 0x1520) {
+ _cmd23Toggle = false;
+
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x12C);
+ for (int i = 0; i < 98; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound1::command(int commandId, int param) {
+ if (commandId > 41)
+ return 0;
+
+ _commandParam = param;
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound1::command9() {
+ playSound(0xC68, 12);
+ return 0;
+}
+
+int ASound1::command10() {
+ byte *pData1 = loadData(0x130E, 48);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x133E, 392));
+ _channels[2].load(loadData(0x14C6, 46));
+ _channels[3].load(loadData(0x14F4, 48));
+ }
+
+ return 0;
+}
+
+int ASound1::command11() {
+ command111213();
+ _channels[0]._field1E = 0;
+ _channels[1]._field1E = 0;
+ return 0;
+}
+
+int ASound1::command12() {
+ command111213();
+ _channels[0]._field1E = 40;
+ _channels[1]._field1E = 0;
+ return 0;
+}
+
+int ASound1::command13() {
+ command111213();
+ _channels[0]._field1E = 40;
+ _channels[1]._field1E = 50;
+ return 0;
+}
+
+int ASound1::command14() {
+ playSound(0x1216, 248);
+ return 0;
+}
+
+int ASound1::command15() {
+ byte *pData1 = loadData(0x1524, 152);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[4].load(pData1);
+ _channels[5].load(loadData(0x15BC, 94));
+ _channels[6].load(loadData(0x161A, 94));
+ _channels[7].load(loadData(0x1678, 42));
+ _channels[8].load(loadData(0x16A2, 42));
+ }
+
+ return 0;
+}
+
+int ASound1::command16() {
+ playSound(0xC74, 14);
+ return 0;
+}
+
+int ASound1::command17() {
+ playSound(0xE9A, 10);
+ return 0;
+}
+
+int ASound1::command18() {
+ command1();
+ playSound(0xCA6, 20);
+ return 0;
+}
+
+int ASound1::command19() {
+ command1();
+ playSound(0xCBA, 74);
+ return 0;
+}
+
+int ASound1::command20() {
+ byte *pData = loadData(0xD18, 28);
+ if (!isSoundActive(pData))
+ playSoundData(pData);
+ return 0;
+}
+
+int ASound1::command21() {
+ playSound(0xD04, 20);
+ return 0;
+}
+
+int ASound1::command22() {
+ byte *pData = loadData(0xD34, 10);
+ pData[6] = (getRandomNumber() & 7) + 85;
+
+ if (!isSoundActive(pData))
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound1::command23() {
+ _cmd23Toggle = !_cmd23Toggle;
+ playSound(_cmd23Toggle ? 0xD3E : 0xD46, 8);
+ return 0;
+}
+
+int ASound1::command24() {
+ playSound(0xD4E, 18);
+ playSound(0xD60, 20);
+ playSound(0xD74, 14);
+ return 0;
+}
+
+int ASound1::command25() {
+ byte *pData = loadData(0xD82, 16);
+ if (!isSoundActive(pData))
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound1::command26() {
+ byte *pData = loadData(0xEEC, 10);
+ pData[5] = (command2627293032() + 0x7F) & 0xFF;
+
+ if (!isSoundActive(pData))
+ _channels[6].load(pData);
+
+ return 0;
+}
+
+int ASound1::command27() {
+ byte *pData = loadData(0xEE2, 10);
+ pData[5] = (command2627293032() + 0x40) & 0xFF;
+
+ if (!isSoundActive(pData))
+ _channels[7].load(pData);
+
+ return 0;
+}
+
+int ASound1::command28() {
+ playSound(0xD92, 28);
+ return 0;
+}
+
+int ASound1::command29() {
+ byte *pData = loadData(0xC82, 36);
+ byte v = (command2627293032() + 0x40) & 0xFF;
+ pData[7] = pData[13] = pData[21] = pData[27] = v;
+
+ if (!isSoundActive(pData))
+ playSoundData(pData, 0);
+
+ return 0;
+}
+
+int ASound1::command30() {
+ byte *pData = loadData(0xEA6, 16);
+ pData[7] = (command2627293032() + 0x40) & 0xFF;
+
+ if (!isSoundActive(pData))
+ playSoundData(pData, 0);
+
+ return 0;
+}
+
+int ASound1::command31() {
+ byte *pData = loadData(0xDAE, 14);
+ if (!isSoundActive(pData))
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound1::command32() {
+ byte *pData = loadData(0xEB4, 46);
+ int v = command2627293032() + 0x40;
+ pData[9] = pData[17] = pData[25] = pData[33] = v & 0xFF;
+ pData[11] = pData[19] = pData[27] = pData[35] = v >> 8;
+
+ if (!isSoundActive(pData))
+ playSoundData(pData, 0);
+
+ return 0;
+}
+
+int ASound1::command33() {
+ playSound(0xDBC, 10);
+ playSound(0xDC6, 10);
+ return 0;
+}
+
+int ASound1::command34() {
+ int v = getRandomNumber() & 0x20;
+ if (!v)
+ v = 0x60;
+
+ byte *pData = loadData(0xDD0, 22);
+ pData[8] = pData[15] = v;
+ playSoundData(pData);
+ return 0;
+}
+
+int ASound1::command35() {
+ playSound(0xDE6, 16);
+ return 0;
+}
+
+int ASound1::command36() {
+ playSound(0xE10, 10);
+ command34();
+
+ return 0;
+}
+
+int ASound1::command37() {
+ playSound(0xE1A, 14);
+ return 0;
+}
+
+int ASound1::command38() {
+ playSound(0xE28, 114);
+ return 0;
+}
+
+int ASound1::command39() {
+ byte *pData1 = loadData(0x16CC, 82);
+ if (!isSoundActive(pData1)) {
+ _channels[5].load(pData1);
+ _channels[6].load(loadData(0x171E, 30));
+ _channels[7].load(loadData(0x173C, 40));
+ _channels[8].load(loadData(0x1764, 64));
+ }
+ return 0;
+}
+
+int ASound1::command40() {
+ playSound(0xDF6, 26);
+ return 0;
+}
+
+int ASound1::command41() {
+ playSound(0xC32, 34);
+ playSound(0xC54, 20);
+ return 0;
+}
+
+void ASound1::command111213() {
+ byte *pData1 = loadData(0xEF6, 408);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x108E, 266));
+ _channels[2].load(loadData(0x1198, 66));
+ _channels[2].load(loadData(0x11DA, 60));
+ }
+}
+
+int ASound1::command2627293032() {
+ return (_commandParam > 0x40) ? _commandParam - 0x40 : _commandParam & 0xff00;
+}
+
+
+/*-----------------------------------------------------------------------*/
+
+const ASound2::CommandPtr ASound2::_commandList[44] = {
+ &ASound2::command0, &ASound2::command1, &ASound2::command2, &ASound2::command3,
+ &ASound2::command4, &ASound2::command5, &ASound2::command6, &ASound2::command7,
+ &ASound2::command8, &ASound2::command9, &ASound2::command10, &ASound2::command11,
+ &ASound2::command12, &ASound2::command13, &ASound2::command14, &ASound2::command15,
+ &ASound2::command16, &ASound2::command17, &ASound2::command18, &ASound2::command19,
+ &ASound2::command20, &ASound2::command21, &ASound2::command22, &ASound2::command23,
+ &ASound2::command24, &ASound2::command25, &ASound2::command26, &ASound2::command27,
+ &ASound2::command28, &ASound2::command29, &ASound2::command30, &ASound2::command31,
+ &ASound2::command32, &ASound2::command33, &ASound2::command34, &ASound2::command35,
+ &ASound2::command36, &ASound2::command37, &ASound2::command38, &ASound2::command39,
+ &ASound2::command40, &ASound2::command41, &ASound2::command42, &ASound2::command43
+};
+
+ASound2::ASound2(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.002", 0x15E0) {
+ _command12Param = 0xFD;
+
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x144);
+ for (int i = 0; i < 164; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound2::command(int commandId, int param) {
+ if (commandId > 43)
+ return 0;
+
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound2::command0() {
+ _command12Param = 0xFD;
+ return ASound::command0();
+}
+
+int ASound2::command9() {
+ byte *pData1 = loadData(0x1094, 376);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[2].load(loadData(0x123E, 130));
+
+ command9Randomize();
+ _channels[1].load(loadData(0x120C, 50));
+ }
+ return 0;
+}
+
+void ASound2::command9Randomize() {
+ // Randomization
+ int v;
+ while (((v = getRandomNumber()) & 0x3F) > 36)
+ ;
+
+ byte *pData = loadData(0x120C, 50);
+ command9Apply(pData, v + 20, -1);
+ command9Apply(pData + 1, 10 - ((v + 1) / 6), 1);
+}
+
+void ASound2::command9Apply(byte *data, int val, int incr) {
+ data += 8;
+ for (int ctr = 0; ctr < 10; ++ctr, data += 4, val += incr) {
+ *data = val;
+ }
+}
+
+int ASound2::command10() {
+ byte *pData1 = loadData(0x12C0, 60);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x12FC, 318));
+ _channels[2].load(loadData(0x143A, 110));
+ }
+
+ return 0;
+}
+
+int ASound2::command11() {
+ byte *pData = loadData(0x14A8, 170);
+ if (!isSoundActive(pData)) {
+ playSoundData(pData);
+ playSoundData(loadData(0x1552, 1802));
+ playSoundData(loadData(0x1C5C, 716));
+ playSoundData(loadData(0x1F28, 106));
+ }
+
+ return 0;
+}
+
+int ASound2::command12() {
+ _command12Param += 26;
+ byte v = _command12Param & 0x7f;
+
+ byte *pData = loadData(0x4A5E, 38);
+ pData[5] = pData[20] = v;
+ playSoundData(pData);
+
+ pData = loadData(0x4A84, 30);
+ pData[5] = pData[18] = v;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound2::command13() {
+ playSoundData(loadData(0x4AA2, 20));
+ playSoundData(loadData(0x4AB6, 20));
+
+ return 0;
+}
+
+int ASound2::command14() {
+ playSound(0x4ACA, 40);
+ playSound(0x4AF2, 42);
+
+ return 0;
+}
+
+int ASound2::command15() {
+ byte *pData1 = loadData(0x1F92, 1074);
+ if (!isSoundActive(pData1)) {
+ command1();
+ playSoundData(pData1);
+ playSound(0x23C4, 1050);
+ playSound(0x27DE, 58);
+ playSound(0x2818, 712);
+ playSound(0x2AE0, 256);
+ }
+
+ return 0;
+}
+
+int ASound2::command16() {
+ byte *pData1 = loadData(0x3960, 280);
+ if (!isSoundActive(pData1)) {
+ command1();
+ playSoundData(pData1);
+ playSound(0x3A78, 266);
+ playSound(0x3B72, 322);
+ playSound(0x3CC4, 488);
+ playSound(0x3EAC, 104);
+ playSound(0x3F14, 104);
+ }
+
+ return 0;
+}
+
+int ASound2::command17() {
+ byte *pData1 = loadData(0x3F7C, 432);
+ if (!isSoundActive(pData1)) {
+ command1();
+ playSoundData(pData1);
+ playSound(0x412C, 422);
+ playSound(0x42D2, 424);
+ playSound(0x447A, 418);
+ }
+
+ return 0;
+}
+
+static const int command18_list[16][2] = {
+ { 0x337C, 28 }, { 0x3398, 26 }, { 0x33B2, 26 }, { 0x33CC, 26 },
+ { 0x33E6, 56 }, { 0x341E, 46 }, { 0x344C, 56 }, { 0x3484, 22 },
+ { 0x349A, 38 }, { 0x34C0, 62 }, { 0x34FE, 26 }, { 0x3518, 26 },
+ { 0x3532, 26 }, { 0x354C, 26 }, { 0x3566, 32 }, { 0x3586, 24 }
+};
+
+int ASound2::command18() {
+ if (_channels[3]._activeCount == 0) {
+ int idx = (getRandomNumber() & 0x1E) >> 1;
+ byte *pData = loadData(command18_list[idx][0], command18_list[idx][1]);
+ _channels[3].load(pData);
+ }
+
+ return 0;
+}
+
+int ASound2::command19() {
+ byte *pData1 = loadData(0x2BE0, 366);
+ if (!isSoundActive(pData1)) {
+ command1();
+ playSoundData(pData1);
+ playSound(0x2D4E, 460);
+ playSound(0x2F1A, 266);
+ playSound(0x3024, 328);
+ playSound(0x316C, 162);
+ playSound(0x320E, 366);
+ }
+
+ return 0;
+}
+
+int ASound2::command20() {
+ playSound(0x4A36, 40);
+
+ return 0;
+}
+
+int ASound2::command21() {
+ playSound(0x49DE, 16);
+ playSound(0x49EE, 16);
+ playSound(0x49FF, 16);
+
+ return 0;
+}
+
+int ASound2::command22() {
+ playSound(0x4A0E, 24);
+ playSound(0x4A26, 16);
+
+ return 0;
+}
+
+int ASound2::command23() {
+ playSound(0x49B6, 16);
+
+ return 0;
+}
+
+int ASound2::command24() {
+ playSound(0x49C6, 24);
+
+ return 0;
+}
+
+int ASound2::command25() {
+ playSound(0x49AC, 10);
+
+ return 0;
+}
+
+int ASound2::command26() {
+ playSound(0x498A, 14);
+ playSound(0x4998, 20);
+
+ return 0;
+}
+
+int ASound2::command27() {
+ playSound(0x4912, 80);
+ playSound(0x4962, 40);
+
+ return 0;
+}
+
+int ASound2::command28() {
+ playSound(0x48E8, 28);
+ playSound(0x4904, 14);
+
+ return 0;
+}
+
+int ASound2::command29() {
+ playSound(0x48B2, 22);
+
+ return 0;
+}
+
+int ASound2::command30() {
+ playSound(0x4870, 22);
+ playSound(0x4886, 22);
+ playSound(0x489C, 22);
+
+ return 0;
+}
+
+int ASound2::command31() {
+ playSound(0x482E, 22);
+ playSound(0x4844, 22);
+ playSound(0x489C, 22);
+
+ return 0;
+}
+
+int ASound2::command32() {
+ playSound(0x46E8, 10);
+
+ return 0;
+}
+
+int ASound2::command33() {
+ playSound(0x46D8, 16);
+
+ return 0;
+}
+
+int ASound2::command34() {
+ playSound(0x46C8, 16);
+
+ return 0;
+}
+
+int ASound2::command35() {
+ playSound(0x46B2, 22);
+
+ return 0;
+}
+
+int ASound2::command36() {
+ playSound(0x4624, 16);
+
+ return 0;
+}
+
+int ASound2::command37() {
+ playSound(0x4674, 20);
+ playSound(0x4688, 32);
+ playSound(0x46A8, 10);
+
+ return 0;
+}
+
+int ASound2::command38() {
+ byte *pData1 = loadData(0x359E, 202);
+ if (!isSoundActive(pData1)) {
+ command1();
+ playSoundData(pData1);
+ playSound(0x3668, 220);
+ playSound(0x3744, 124);
+ playSound(0x37C0, 162);
+ playSound(0x3862, 78);
+ playSound(0x38B0, 176);
+ }
+
+ return 0;
+}
+
+int ASound2::command39() {
+ byte *pData = loadData(0x466A, 10);
+ pData[6] = (getRandomNumber() & 7) + 85;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound2::command40() {
+ playSound(0x4634, 34);
+ playSound(0x4656, 20);
+
+ return 0;
+}
+
+int ASound2::command41() {
+ playSound(0x48C8, 32);
+
+ return 0;
+}
+
+int ASound2::command42() {
+ playSound(0x46F2, 156);
+ playSound(0x478E, 160);
+
+ return 0;
+}
+
+int ASound2::command43() {
+ playSound(0x4B1C, 40);
+ playSound(0x4B44, 41);
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+const ASound3::CommandPtr ASound3::_commandList[61] = {
+ &ASound3::command0, &ASound3::command1, &ASound3::command2, &ASound3::command3,
+ &ASound3::command4, &ASound3::command5, &ASound3::command6, &ASound3::command7,
+ &ASound3::command8, &ASound3::command9, &ASound3::command10, &ASound3::command11,
+ &ASound3::nullCommand, &ASound3::command13, &ASound3::command14, &ASound3::command15,
+ &ASound3::command16, &ASound3::command17, &ASound3::command18, &ASound3::command19,
+ &ASound3::command20, &ASound3::command21, &ASound3::command22, &ASound3::command23,
+ &ASound3::command24, &ASound3::command25, &ASound3::command26, &ASound3::command27,
+ &ASound3::command28, &ASound3::command29, &ASound3::command30, &ASound3::command31,
+ &ASound3::command32, &ASound3::command33, &ASound3::command34, &ASound3::command35,
+ &ASound3::command36, &ASound3::command37, &ASound3::command38, &ASound3::command39,
+ &ASound3::command40, &ASound3::command41, &ASound3::command42, &ASound3::command43,
+ &ASound3::command44, &ASound3::command45, &ASound3::command46, &ASound3::command47,
+ &ASound3::nullCommand, &ASound3::command49, &ASound3::command50, &ASound3::command51,
+ &ASound3::nullCommand, &ASound3::nullCommand, &ASound3::nullCommand, &ASound3::nullCommand,
+ &ASound3::nullCommand, &ASound3::command57, &ASound3::nullCommand, &ASound3::command59,
+ &ASound3::command60
+};
+
+ASound3::ASound3(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.003", 0x15B0) {
+ _command39Flag = false;
+
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x122);
+ for (int i = 0; i < 192; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound3::command(int commandId, int param) {
+ if (commandId > 60)
+ return 0;
+
+ _commandParam = param;
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound3::command9() {
+ AdlibChannel::_channelsEnabled = _commandParam != 0;
+
+ return 0;
+}
+
+int ASound3::command10() {
+ byte *pData1 = loadData(0x13EA, 254);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0X14E8, 452));
+ _channels[2].load(loadData(0x16AC, 396));
+ _channels[3].load(loadData(0x1838, 118));
+ _channels[4].load(loadData(0x18AE, 74));
+ }
+
+ return 0;
+}
+
+int ASound3::command11() {
+ byte *pData1 = loadData(0x2B84, 596);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x2DD8, 562));
+ _channels[2].load(loadData(0x300A, 1694));
+ _channels[3].load(loadData(0x36A8, 1100));
+ _channels[4].load(loadData(0x3AF4, 420));
+ _channels[5].load(loadData(0x3C98, 1516));
+ }
+
+ return 0;
+}
+
+int ASound3::command13() {
+ byte *pData1 = loadData(0x4470, 64);
+ if (!isSoundActive(pData1)) {
+ command1();
+ playSoundData(pData1);
+ playSound(0x44B0, 64);
+ playSound(0x44F0, 64);
+ playSound(0x4530, 64);
+ playSound(0x4570, 64);
+ playSound(0X45b0, 64);
+ }
+
+ return 0;
+}
+
+int ASound3::command14() {
+ byte *pData1 = loadData(0X45F0, 36);
+ if (!isSoundActive(pData1)) {
+ command1();
+ playSoundData(pData1);
+ playSound(0x4614, 36);
+ playSound(0x4638, 36);
+ playSound(0x465C, 32);
+ playSound(0x467C, 76);
+ playSound(0x46C8, 74);
+ }
+
+ return 0;
+}
+
+int ASound3::command15() {
+ _channels[3].load(loadData(0x36A8, 1100));
+ _channels[4].load(loadData(0x3AF4, 420));
+ _channels[5].load(loadData(0x3C98, 1516));
+
+ _channels[3]._field20 = 0xDD;
+ _channels[4]._field20 = 0xDD;
+ _channels[5]._field20 = 0xDD;
+
+ return 0;
+}
+
+int ASound3::command16() {
+ byte *pData1 = loadData(0x4712, 398);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x48A0, 354));
+ _channels[2].load(loadData(0x4A02, 410));
+ _channels[3].load(loadData(0x4B9C, 392));
+ }
+
+ return 0;
+}
+
+int ASound3::command17() {
+ byte *pData1 = loadData(0x18F8, 400);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x1A88, 680));
+ _channels[2].load(loadData(0x1D30, 478));
+ _channels[3].load(loadData(0x1F0E, 1146));
+ _channels[4].load(loadData(0x2388, 1006));
+ _channels[5].load(loadData(0x2776, 1038));
+ }
+
+ return 0;
+}
+
+int ASound3::command18() {
+ byte *pData1 = loadData(0x4284, 142);
+ if (!isSoundActive(pData1)) {
+ command1();
+ playSoundData(pData1);
+ playSound(0x4312, 172);
+ playSound(0x43BE, 88);
+ playSound(0x4416, 90);
+ }
+
+ return 0;
+}
+
+int ASound3::command19() {
+ playSound(0x4F6, 8);
+
+ return 0;
+}
+
+int ASound3::command20() {
+ playSound(0x4F1C, 10);
+
+ return 0;
+}
+
+int ASound3::command21() {
+ playSound(0x4F2E, 8);
+
+ return 0;
+}
+
+int ASound3::command22() {
+ playSound(0x4F36, 16);
+
+ return 0;
+}
+
+int ASound3::command23() {
+ playSound(0x4F50, 10);
+ playSound(0x4F46, 10);
+
+ return 0;
+}
+
+int ASound3::command24() {
+ // WORKAROUND: Original calls isSoundActive without loading data pointer
+ byte *pData = loadData(0x4EFC, 12);
+ if (!isSoundActive(pData)) {
+ int v;
+ while ((v = (getRandomNumber() & 0x3F)) > 45)
+ ;
+
+ pData[6] = v + 19;
+ playSoundData(pData);
+ }
+
+ return 0;
+}
+
+int ASound3::command25() {
+ playSound(0x4EE6, 22);
+
+ return 0;
+}
+
+int ASound3::command26() {
+ playSound(0x4F5A, 8);
+
+ return 0;
+}
+
+int ASound3::command27() {
+ playSound(0x4DA2, 34);
+ playSound(0x4DC4, 20);
+
+ return 0;
+}
+
+int ASound3::command28() {
+ playSound(0x4F72, 10);
+ playSound(0x4F72, 10);
+
+ return 0;
+}
+
+int ASound3::command29() {
+ playSound(0x4F72, 10);
+ playSound(0x4F72, 10);
+
+ return 0;
+}
+
+int ASound3::command30() {
+ playSound(0x4E5A, 22);
+ playSound(0x4E70, 22);
+ playSound(0x4E86, 22);
+
+ return 0;
+}
+
+int ASound3::command31() {
+ playSound(0x4F7C, 40);
+
+ return 0;
+}
+
+int ASound3::command32() {
+ playSound(0x4ED2, 10);
+
+ return 0;
+}
+
+int ASound3::command33() {
+ playSound(0x4EC2, 16);
+
+ return 0;
+}
+
+int ASound3::command34() {
+ playSound(0x4EB2, 16);
+
+ return 0;
+}
+
+int ASound3::command35() {
+ playSound(0x4E9C, 22);
+
+ return 0;
+}
+
+int ASound3::command36() {
+ playSound(0x4D2C, 16);
+
+ return 0;
+}
+
+int ASound3::command37() {
+ playSound(0x4E1E, 20);
+ playSound(0x4E32, 30);
+ playSound(0x4E50, 10);
+
+ return 0;
+}
+
+int ASound3::command38() {
+ playSound(0x4FAC, 10);
+
+ return 0;
+}
+
+int ASound3::command39() {
+ _command39Flag = !_command39Flag;
+ if (_command39Flag) {
+ playSound(0x4FD0, 8);
+ } else {
+ playSound(0x4FD8, 8);
+ }
+
+ return 0;
+}
+
+int ASound3::command40() {
+ _command39Flag = !_command39Flag;
+ if (_command39Flag) {
+ playSound(0x4EE0, 8);
+ } else {
+ playSound(0x4EE8, 8);
+ }
+
+ return 0;
+}
+
+int ASound3::command41() {
+ playSound(0x4F08, 20);
+
+ return 0;
+}
+
+int ASound3::command42() {
+ playSound(0x4DD8, 28);
+ playSound(0x4DF4, 42);
+
+ return 0;
+}
+
+int ASound3::command43() {
+ playSound(0x4FB6, 12);
+ playSound(0x4FC2, 14);
+
+ return 0;
+}
+
+int ASound3::command44() {
+ playSound(0x4FFE, 14);
+
+ return 0;
+}
+
+int ASound3::command45() {
+ playSound(0x500C, 14);
+
+ return 0;
+}
+
+int ASound3::command46() {
+ playSound(0x4D78, 14);
+ playSound(0x4D86, 14);
+ playSound(0x4D94, 14);
+
+ return 0;
+}
+
+int ASound3::command47() {
+ playSound(0x4D62, 8);
+ playSound(0x4D6A, 14);
+
+ return 0;
+}
+
+int ASound3::command49() {
+ playSound(0x4D62, 8);
+ playSound(0x4D6A, 14);
+
+ return 0;
+}
+
+int ASound3::command50() {
+ playSound(0x4D3C, 14);
+ playSound(0x4D4A, 14);
+ playSound(0x4D58, 10);
+
+ return 0;
+}
+
+int ASound3::command51() {
+ playSound(0x4FF0, 14);
+
+ return 0;
+}
+
+int ASound3::command57() {
+ byte *pData = loadData(0x4EDC, 10);
+ pData[6] = (getRandomNumber() & 7) + 85;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound3::command59() {
+ playSound(0x4F62, 16);
+
+ return 0;
+}
+
+int ASound3::command60() {
+ playSound(0x4FA4, 8);
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+const ASound4::CommandPtr ASound4::_commandList[61] = {
+ &ASound4::command0, &ASound4::command1, &ASound4::command2, &ASound4::command3,
+ &ASound4::command4, &ASound4::command5, &ASound4::command6, &ASound4::command7,
+ &ASound4::command8, &ASound4::nullCommand, &ASound4::command10, &ASound4::nullCommand,
+ &ASound4::command12, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand,
+ &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command19,
+ &ASound4::command20, &ASound4::command21, &ASound4::nullCommand, &ASound4::nullCommand,
+ &ASound4::command24, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command27,
+ &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command30, &ASound4::nullCommand,
+ &ASound4::command32, &ASound4::command33, &ASound4::command34, &ASound4::command35,
+ &ASound4::command36, &ASound4::command37, &ASound4::command38, &ASound4::nullCommand,
+ &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command43,
+ &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand,
+ &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand,
+ &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand,
+ &ASound4::nullCommand, &ASound4::command57, &ASound4::nullCommand, &ASound4::command59,
+ &ASound4::command60
+};
+
+ASound4::ASound4(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.004", 0x14F0) {
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x122);
+ for (int i = 0; i < 210; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound4::command(int commandId, int param) {
+ if (commandId > 60)
+ return 0;
+
+ _commandParam = param;
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound4::command10() {
+ byte *pData = loadData(0x22AA, 254);
+ if (!isSoundActive(pData)) {
+ command1();
+ _channels[0].load(pData);
+ _channels[1].load(loadData(0x23A8, 452));
+ _channels[2].load(loadData(0x256C, 396));
+ _channels[3].load(loadData(0x26F8, 118));
+ _channels[4].load(loadData(0x276E, 74));
+ }
+
+ return 0;
+}
+
+int ASound4::command12() {
+ byte *pData = loadData(0x16A8, 550);
+ if (!isSoundActive(pData)) {
+ command1();
+ _channels[0].load(pData);
+ _channels[1].load(loadData(0x18CE, 442));
+ _channels[2].load(loadData(0x1A88, 298));
+ _channels[3].load(loadData(0x1BB2, 354));
+ _channels[4].load(loadData(0x1D14, 572));
+ _channels[4].load(loadData(0x1F50, 560));
+ }
+
+ int v = (_commandParam > 0x40) ? _commandParam - 0x40 : 0;
+ v += 0xB5;
+ for (int channelNum = 0; channelNum < 6; ++channelNum)
+ _channels[channelNum]._field20 = v;
+
+ return 0;
+}
+
+int ASound4::command19() {
+ playSound(0x28EC, 8);
+
+ return 0;
+}
+
+int ASound4::command20() {
+ playSound(0x28E2, 10);
+
+ return 0;
+}
+
+int ASound4::command21() {
+ playSound(0x27C0, 8);
+
+ return 0;
+}
+
+int ASound4::command24() {
+ int v;
+ while ((v = (getRandomNumber() & 0x3F)) > 45)
+ ;
+
+ byte *pData = loadData(0x28D6, 12);
+ pData[6] = v + 19;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound4::command27() {
+ playSound(0x27D8, 34);
+ playSound(0x27FA, 20);
+
+ return 0;
+}
+
+int ASound4::command30() {
+ playSound(0x284A, 22);
+ playSound(0x2860, 22);
+ playSound(0x2876, 22);
+
+ return 0;
+}
+
+int ASound4::command32() {
+ playSound(0x28C2, 10);
+
+ return 0;
+}
+
+int ASound4::command33() {
+ playSound(0x28B2, 16);
+
+ return 0;
+}
+
+int ASound4::command34() {
+ playSound(0x28A2, 16);
+
+ return 0;
+}
+
+int ASound4::command35() {
+ playSound(0x288C, 22);
+
+ return 0;
+}
+
+int ASound4::command36() {
+ playSound(0x27C8, 16);
+
+ return 0;
+}
+
+int ASound4::command37() {
+ playSound(0x280E, 20);
+ playSound(0x2822, 30);
+ playSound(0x2840, 10);
+
+ return 0;
+}
+
+int ASound4::command38() {
+ playSound(0x2904, 10);
+
+ return 0;
+}
+
+int ASound4::command43() {
+ playSound(0x290E, 12);
+ playSound(0x291A, 14);
+
+ return 0;
+}
+
+int ASound4::command52() {
+ byte *pData = loadData(0x23A8, 452);
+ if (_channels[1]._ptr1 == pData) {
+ pData = loadData(0x146E, 570);
+ if (!isSoundActive(pData)) {
+ _channels[0].load(pData);
+ _channels[1]._field20 = 0xD8;
+ _channels[2]._field20 = 0xD8;
+ }
+ }
+
+ return 0;
+}
+
+int ASound4::command53() {
+ method1();
+ _channels[0]._field20 = 0;
+
+ return 0;
+}
+
+int ASound4::command54() {
+ method1();
+ _channels[1]._field20 = 0;
+ _channels[2]._field20 = 0;
+
+ return 0;
+}
+
+int ASound4::command55() {
+ method1();
+ _channels[3]._field20 = 0;
+ _channels[4]._field20 = 0;
+
+ return 0;
+}
+
+int ASound4::command56() {
+ method1();
+ _channels[5]._field20 = 0;
+
+ return 0;
+}
+
+int ASound4::command57() {
+ int v = (getRandomNumber() & 7) + 85;
+ byte *pData = loadData(0x28CC, 10);
+ pData[6] = v;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound4::command58() {
+ byte *pData = loadData(0x146E, 570);
+ if (_channels[1]._ptr1 == pData) {
+ _channels[0].load(loadData(0x22AA, 254));
+ _channels[1]._field20 = 0;
+ _channels[2]._field20 = 0;
+ }
+
+ return 0;
+}
+
+int ASound4::command59() {
+ playSound(0x28F4, 8);
+
+ return 0;
+}
+
+int ASound4::command60() {
+ playSound(0x28FC, 8);
+
+ return 0;
+}
+
+void ASound4::method1() {
+ byte *pData = loadData(0x2180, 58);
+ if (!isSoundActive(pData)) {
+ command1();
+
+ _channels[0].load(pData);
+ _channels[1].load(loadData(0x21BA, 48));
+ _channels[2].load(loadData(0x21EA, 50));
+ _channels[3].load(loadData(0x221C, 40));
+ _channels[4].load(loadData(0x2244, 28));
+ _channels[5].load(loadData(0x2260, 74));
+
+ for (int channel = 0; channel < 6; ++channel)
+ _channels[channel]._field20 = 0xB5;
+ }
+}
+
+
+/*-----------------------------------------------------------------------*/
+
+const ASound5::CommandPtr ASound5::_commandList[42] = {
+ &ASound5::command0, &ASound5::command1, &ASound5::command2, &ASound5::command3,
+ &ASound5::command4, &ASound5::command5, &ASound5::command6, &ASound5::command7,
+ &ASound5::command8, &ASound5::command9, &ASound5::command10, &ASound5::command11,
+ &ASound5::command11, &ASound5::command13, &ASound5::command14, &ASound5::command15,
+ &ASound5::command16, &ASound5::command17, &ASound5::command18, &ASound5::command19,
+ &ASound5::command20, &ASound5::command21, &ASound5::command22, &ASound5::command23,
+ &ASound5::command11, &ASound5::command11, &ASound5::command26, &ASound5::command27,
+ &ASound5::command28, &ASound5::command29, &ASound5::command30, &ASound5::command31,
+ &ASound5::command32, &ASound5::command33, &ASound5::command34, &ASound5::command35,
+ &ASound5::command36, &ASound5::command37, &ASound5::command38, &ASound5::command39,
+ &ASound5::command40, &ASound5::command41
+};
+
+ASound5::ASound5(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.002", 0x15E0) {
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x144);
+ for (int i = 0; i < 164; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound5::command(int commandId, int param) {
+ if (commandId > 41)
+ return 0;
+
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound5::command9() {
+ byte *pData = loadData(0x2114, 10);
+ pData[6] = (getRandomNumber() & 7) + 85;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound5::command10() {
+ playSound(0x211E, 10);
+
+ return 0;
+}
+
+int ASound5::command11() {
+ playSound(0x2016, 10);
+
+ return 0;
+}
+
+int ASound5::command13() {
+ playSound(0x2154, 10);
+
+ return 0;
+}
+
+int ASound5::command14() {
+ playSound(0x21DC, 22);
+
+ return 0;
+}
+
+int ASound5::command15() {
+ byte *pData = loadData(0x21DC, 22);
+ if (_channels[0]._ptr1 == pData) {
+ pData = loadData(0x1F2, 12);
+ _channels[0]._soundData = pData;
+ _channels[0]._field17 = 1;
+ _channels[0]._field19 = 1;
+ }
+
+ return 0;
+}
+
+int ASound5::command16() {
+ playSound(0x214C, 8);
+
+ return 0;
+}
+
+int ASound5::command17() {
+ playSound(0x2142, 10);
+
+ return 0;
+}
+
+int ASound5::command18() {
+ playSound(0x21A2, 22);
+
+ return 0;
+}
+
+int ASound5::command19() {
+ playSound(0x2190, 18);
+
+ return 0;
+}
+
+int ASound5::command20() {
+ playSound(0x2170, 16);
+
+ return 0;
+}
+
+int ASound5::command21() {
+ playSound(0x2180, 16);
+
+ return 0;
+}
+
+int ASound5::command22() {
+ playSound(0x2168, 8);
+
+ return 0;
+}
+
+int ASound5::command23() {
+ playSound(0x215E, 10);
+
+ return 0;
+}
+
+int ASound5::command26() {
+ playSound(0x21B8, 12);
+
+ return 0;
+}
+
+int ASound5::command27() {
+ playSound(0x21C4, 24);
+
+ return 0;
+}
+
+int ASound5::command28() {
+ playSound(0x2020, 34);
+ playSound(0x4904, 20);
+
+ return 0;
+}
+
+int ASound5::command29() {
+ byte *pData = loadData(0x17C, 312);
+ if (!isSoundActive(pData)) {
+ command1();
+ _channels[0].load(pData);
+ _channels[1].load(loadData(0x1864, 304));
+ _channels[2].load(loadData(0x1994, 222));
+ _channels[3].load(loadData(0x1864, 304));
+ _channels[4].load(loadData(0x1994, 222));
+ }
+
+ return 0;
+}
+
+int ASound5::command30() {
+ playSound(0x2092, 22);
+ playSound(0x20A8, 22);
+ playSound(0x20BE, 22);
+
+ return 0;
+}
+
+int ASound5::command31() {
+ playSound(0x2128, 22);
+ playSound(0x2134, 14);
+
+ return 0;
+}
+
+int ASound5::command32() {
+ playSound(0x210A, 10);
+
+ return 0;
+}
+
+int ASound5::command33() {
+ playSound(0x20FA, 16);
+
+ return 0;
+}
+
+int ASound5::command34() {
+ playSound(0x20EA, 16);
+
+ return 0;
+}
+
+int ASound5::command35() {
+ playSound(0x20D4, 22);
+
+ return 0;
+}
+
+int ASound5::command36() {
+ playSound(0x2006, 16);
+
+ return 0;
+}
+
+int ASound5::command37() {
+ playSound(0x2056, 20);
+ playSound(0x206A, 30);
+ playSound(0x2088, 10);
+
+ return 0;
+}
+
+int ASound5::command38() {
+ byte *pData1 = loadData(0x14F2, 570);
+ if (_channels[3]._ptr1 == pData1) {
+ _channels[3].load(loadData(0x1A72, 522));
+ _channels[3].load(loadData(0x1C7C, 874));
+ }
+
+ return 0;
+}
+
+int ASound5::command39() {
+ playSound(0x1FEE, 8);
+
+ return 0;
+}
+
+int ASound5::command40() {
+ playSound(0x1FF6, 16);
+
+ return 0;
+}
+
+int ASound5::command41() {
+ byte *pData1 = loadData(0x14F2, 570);
+ if (!isSoundActive(pData1)) {
+ byte *pData2 = loadData(0x1A72, 522);
+ if (_channels[3]._ptr1 == pData2) {
+ _channels[3].load(pData1);
+ _channels[4].load(loadData(0x1FE6, 8));
+ }
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+const ASound6::CommandPtr ASound6::_commandList[30] = {
+ &ASound6::command0, &ASound6::command1, &ASound6::command2, &ASound6::command3,
+ &ASound6::command4, &ASound6::command5, &ASound6::command6, &ASound6::command7,
+ &ASound6::command8, &ASound6::command9, &ASound6::command10, &ASound6::command11,
+ &ASound6::command11, &ASound6::command13, &ASound6::command14, &ASound6::command15,
+ &ASound6::command16, &ASound6::command17, &ASound6::command18, &ASound6::command19,
+ &ASound6::command20, &ASound6::command21, &ASound6::command22, &ASound6::command23,
+ &ASound6::command11, &ASound6::command11, &ASound6::nullCommand, &ASound6::nullCommand,
+ &ASound6::nullCommand, &ASound6::command29
+};
+
+ASound6::ASound6(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.006", 0x1390) {
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x122);
+ for (int i = 0; i < 200; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound6::command(int commandId, int param) {
+ if (commandId > 29)
+ return 0;
+
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound6::command9() {
+ byte *pData = loadData(0x2194, 10);
+ pData[6] = (getRandomNumber() & 7) + 85;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound6::command10() {
+ playSound(0x2224, 24);
+
+ return 0;
+}
+
+int ASound6::command11() {
+ playSound(0x2202, 34);
+
+ return 0;
+}
+
+int ASound6::command12() {
+ playSound(0x2246, 8);
+
+ return 0;
+}
+
+int ASound6::command13() {
+ playSound(0x2298, 28);
+
+ return 0;
+}
+
+int ASound6::command14() {
+ playSound(0x22B4, 27);
+
+ return 0;
+}
+
+int ASound6::command15() {
+ playSound(0x219E, 12);
+
+ return 0;
+}
+
+int ASound6::command16() {
+ playSound(0x21AA, 22);
+ playSound(0x21C0, 12);
+
+ return 0;
+}
+
+int ASound6::command17() {
+ playSound(0x21CC, 54);
+
+ return 0;
+}
+
+int ASound6::command18() {
+ playSound(0x2270, 16);
+
+ return 0;
+}
+
+int ASound6::command19() {
+ playSound(0x2280, 16);
+
+ return 0;
+}
+
+int ASound6::command20() {
+ playSound(0x223C, 10);
+
+ return 0;
+}
+
+int ASound6::command21() {
+ playSound(0x224E, 34);
+
+ return 0;
+}
+
+int ASound6::command22() {
+ playSound(0x2290, 8);
+
+ return 0;
+}
+
+int ASound6::command23() {
+ playSound(0x215E, 34);
+ playSound(0x2180, 20);
+
+ return 0;
+}
+
+int ASound6::command24() {
+ byte *pData1 = loadData(0x1D54, 540);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x1F70, 52));
+ _channels[2].load(loadData(0x1FA4, 430));
+ }
+
+ return 0;
+}
+
+int ASound6::command25() {
+ playSound(0x2152, 12);
+
+ return 0;
+}
+
+int ASound6::command29() {
+ byte *pData1 = loadData(0x149A, 312);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x15D2, 304));
+ _channels[2].load(loadData(0x1702, 222));
+ _channels[3].load(loadData(0x17E0, 522));
+ _channels[4].load(loadData(0x19EA, 874));
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+const ASound7::CommandPtr ASound7::_commandList[38] = {
+ &ASound7::command0, &ASound7::command1, &ASound7::command2, &ASound7::command3,
+ &ASound7::command4, &ASound7::command5, &ASound7::command6, &ASound7::command7,
+ &ASound7::command8, &ASound7::command9, &ASound7::nullCommand, &ASound7::nullCommand,
+ &ASound7::nullCommand, &ASound7::nullCommand, &ASound7::nullCommand, &ASound7::command15,
+ &ASound7::command16, &ASound7::command16, &ASound7::command18, &ASound7::command19,
+ &ASound7::command20, &ASound7::command21, &ASound7::command22, &ASound7::command23,
+ &ASound7::command24, &ASound7::command25, &ASound7::command26, &ASound7::command27,
+ &ASound7::command28, &ASound7::nullCommand, &ASound7::command30, &ASound7::nullCommand,
+ &ASound7::command32, &ASound7::command33, &ASound7::command34, &ASound7::command35,
+ &ASound7::command36, &ASound7::command37
+};
+
+ASound7::ASound7(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.007", 0x1460) {
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x122);
+ for (int i = 0; i < 214; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound7::command(int commandId, int param) {
+ if (commandId > 37)
+ return 0;
+
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound7::command9() {
+ byte *pData1 = loadData(0x2992, 122);
+ if (!isSoundActive(pData1)) {
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x2A0C, 76));
+ _channels[2].load(loadData(0x2A58, 122));
+ _channels[3].load(loadData(0x2AD2, 38));
+ }
+
+ return 0;
+}
+
+int ASound7::command15() {
+ byte *pData = loadData(0x2B3E, 10);
+ pData[6] = (getRandomNumber() & 7) + 85;
+
+ return 0;
+}
+
+int ASound7::command16() {
+ playSound(0x2CE2, 8);
+
+ return 0;
+}
+
+int ASound7::command18() {
+ playSound(0x2C94, 22);
+
+ return 0;
+}
+
+int ASound7::command19() {
+ byte *pData1 = loadData(0x2C94, 22);
+ byte *pData2 = loadData(0x2CAA, 16);
+ if (_channels[8]._ptr1 == pData1 || _channels[8]._ptr1 == pData2) {
+ _channels[8]._soundData = loadData(0x2CBA, 12);
+ _channels[8]._field17 = 1;
+ _channels[8]._field19 = 1;
+ }
+
+ return 0;
+}
+
+int ASound7::command20() {
+ playSound(0x2CD0, 18);
+
+ return 0;
+}
+
+int ASound7::command21() {
+ playSound(0x2CC6, 10);
+
+ return 0;
+}
+
+int ASound7::command22() {
+ playSound(0x2C08, 140);
+
+ return 0;
+}
+
+int ASound7::command23() {
+ playSound(0x2B08, 34);
+ playSound(0x2B2A, 20);
+
+ return 0;
+}
+
+int ASound7::command24() {
+ byte *pData1 = loadData(0x14C6, 144);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x1556, 146));
+ _channels[2].load(loadData(0x15E8, 138));
+ _channels[3].load(loadData(0x1672, 122));
+ _channels[4].load(loadData(0x16EC, 74));
+ }
+
+ return 0;
+}
+
+int ASound7::command25() {
+ byte *pData1 = loadData(0x1DBE, 182);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x1E74, 182));
+ _channels[2].load(loadData(0x1F2A, 186));
+ _channels[3].load(loadData(0x1FE4, 244));
+ }
+
+ return 0;
+}
+
+int ASound7::command26() {
+ byte *pData1 = loadData(0x20D8, 312);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x2210, 304));
+ _channels[2].load(loadData(0x2340, 222));
+ _channels[3].load(loadData(0x241E, 522));
+ _channels[4].load(loadData(0x2628, 874));
+ }
+
+ return 0;
+}
+
+int ASound7::command27() {
+ byte *pData1 = loadData(0x1736, 158);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x17D4, 288));
+ _channels[2].load(loadData(0x18F4, 290));
+ _channels[3].load(loadData(0x1A16, 396));
+ _channels[4].load(loadData(0x1BA2, 380));
+ _channels[5].load(loadData(0x1D1E, 160));
+ }
+
+ return 0;
+}
+
+int ASound7::command28() {
+ playSound(0x2CAA, 16);
+
+ return 0;
+}
+
+int ASound7::command30() {
+ playSound(0x2B86, 22);
+ playSound(0x2B9C, 22);
+ playSound(0x2BB2, 22);
+
+ return 0;
+}
+
+int ASound7::command32() {
+ playSound(0x2BFE, 10);
+
+ return 0;
+}
+
+int ASound7::command33() {
+ playSound(0x2BEE, 16);
+
+ return 0;
+}
+
+int ASound7::command34() {
+ playSound(0x2BDE, 16);
+
+ return 0;
+}
+
+int ASound7::command35() {
+ playSound(0x2BC8, 22);
+
+ return 0;
+}
+
+int ASound7::command36() {
+ playSound(0x2AF8, 16);
+
+ return 0;
+}
+
+int ASound7::command37() {
+ playSound(0x2B48, 20);
+ playSound(0x2B5C, 32);
+ playSound(0x2B7C, 10);
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+const ASound8::CommandPtr ASound8::_commandList[38] = {
+ &ASound8::command0, &ASound8::command1, &ASound8::command2, &ASound8::command3,
+ &ASound8::command4, &ASound8::command5, &ASound8::command6, &ASound8::command7,
+ &ASound8::command8, &ASound8::command9, &ASound8::command10, &ASound8::command11,
+ &ASound8::command12, &ASound8::command13, &ASound8::command14, &ASound8::command15,
+ &ASound8::command16, &ASound8::command16, &ASound8::command18, &ASound8::command19,
+ &ASound8::command20, &ASound8::command21, &ASound8::command22, &ASound8::command23,
+ &ASound8::command24, &ASound8::command25, &ASound8::command26, &ASound8::command27,
+ &ASound8::command28, &ASound8::command29, &ASound8::command30, &ASound8::command31,
+ &ASound8::command32, &ASound8::command33, &ASound8::command34, &ASound8::command35,
+ &ASound8::command36, &ASound8::command37
+};
+
+ASound8::ASound8(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.008", 0x1490) {
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x122);
+ for (int i = 0; i < 174; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound8::command(int commandId, int param) {
+ if (commandId > 37)
+ return 0;
+
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound8::command9() {
+ byte *pData = loadData(0x15BE, 10);
+ pData[6] = (getRandomNumber() & 7) + 85;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound8::command10() {
+ byte *pData = loadData(0x2B3E, 10);
+ pData[6] = (getRandomNumber() & 7) + 85;
+ playSoundData(pData);
+
+ return 0;
+}
+
+int ASound8::command11() {
+ playSound(0x17CA, 12);
+
+ return 0;
+}
+
+int ASound8::command12() {
+ playSound(0x17D6, 12);
+
+ return 0;
+}
+
+int ASound8::command13() {
+ playSound(0x1694, 10);
+
+ return 0;
+}
+
+int ASound8::command14() {
+ playSound(0x169E, 24);
+
+ return 0;
+}
+
+int ASound8::command15() {
+ byte *pData = loadData(0x169E, 24);
+ if (_channels[8]._ptr1 == pData) {
+ _channels[8]._soundData = loadData(0x16B6, 12);
+ _channels[8]._field17 = 1;
+ _channels[8]._field19 = 1;
+ }
+
+ return 0;
+}
+
+int ASound8::command16() {
+ playSound(0x1686, 14);
+
+ return 0;
+}
+
+int ASound8::command17() {
+ playSound(0x17EC, 12);
+
+ return 0;
+}
+
+int ASound8::command18() {
+ playSound(0x17F8, 12);
+
+ return 0;
+}
+
+int ASound8::command19() {
+ playSound(0x16D8, 8);
+
+ return 0;
+}
+
+int ASound8::command20() {
+ playSound(0x16E0, 8);
+
+ return 0;
+}
+
+int ASound8::command21() {
+ playSound(0x17E2, 10);
+
+ return 0;
+}
+
+int ASound8::command22() {
+ playSound(0x178C, 14);
+ playSound(0x179A, 14);
+ playSound(0x17A8, 14);
+
+ return 0;
+}
+
+int ASound8::command23() {
+ playSound(0x2B08, 34);
+ playSound(0x2B2A, 20);
+
+ return 0;
+}
+
+int ASound8::command24() {
+ playSound(0x17B6, 8);
+
+ return 0;
+}
+
+int ASound8::command25() {
+ playSound(0x17BE, 12);
+
+ return 0;
+}
+
+int ASound8::command26() {
+ playSound(0x16C2, 22);
+
+ return 0;
+}
+
+int ASound8::command27() {
+ playSound(0x1588, 34);
+ playSound(0x15AA, 20);
+
+ return 0;
+}
+
+int ASound8::command28() {
+ byte *pData1 = loadData(0x114E, 376);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[2].load(loadData(0x12F8, 130));
+
+ byte *pData = loadData(0x12C6, 50);
+ method1(pData);
+ _channels[1].load(pData);
+ }
+
+ return 0;
+}
+
+void ASound8::method1(byte *pData) {
+ int v;
+ while ((v = (getRandomNumber() & 0x3F)) > 36)
+ ;
+
+ adjustRange(pData, v + 20, -1);
+ adjustRange(pData + 1, 10 - ((v + 1) / 6), 1);
+}
+
+void ASound8::adjustRange(byte *pData, byte v, int incr) {
+ pData += 8;
+
+ for (int i = 0; i < 10; ++i, pData += 4, v += incr) {
+ *pData = v;
+ }
+}
+
+int ASound8::command29() {
+ byte *pData1 = loadData(0x137A, 60);
+ if (!isSoundActive(pData1)) {
+ command1();
+ _channels[0].load(pData1);
+ _channels[1].load(loadData(0x13B6, 318));
+ _channels[2].load(loadData(0x14F4, 118));
+ }
+
+ return 0;
+}
+
+int ASound8::command30() {
+ playSound(0x1644, 22);
+ playSound(0x165A, 22);
+ playSound(0x1670, 22);
+
+ return 0;
+}
+
+int ASound8::command31() {
+ playSound(0x156A, 14);
+
+ return 0;
+}
+
+int ASound8::command32() {
+ playSound(0x163A, 10);
+
+ return 0;
+}
+
+int ASound8::command33() {
+ playSound(0x162A, 16);
+
+ return 0;
+}
+
+int ASound8::command34() {
+ playSound(0x161A, 16);
+
+ return 0;
+}
+
+int ASound8::command35() {
+ playSound(0x1604, 22);
+
+ return 0;
+}
+
+int ASound8::command36() {
+ playSound(0x1578, 16);
+
+ return 0;
+}
+
+int ASound8::command37() {
+ playSound(0x15C8, 20);
+ playSound(0x15DC, 30);
+ playSound(0X15FA, 10);
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+const ASound9::CommandPtr ASound9::_commandList[52] = {
+ &ASound9::command0, &ASound9::command1, &ASound9::command2, &ASound9::command3,
+ &ASound9::command4, &ASound9::command5, &ASound9::command6, &ASound9::command7,
+ &ASound9::command8, &ASound9::command9, &ASound9::command10, &ASound9::command11,
+ &ASound9::command12, &ASound9::command13, &ASound9::command14, &ASound9::command15,
+ &ASound9::command16, &ASound9::command17, &ASound9::command18, &ASound9::command19,
+ &ASound9::command20, &ASound9::command21, &ASound9::command22, &ASound9::command23,
+ &ASound9::command24, &ASound9::command25, &ASound9::command26, &ASound9::command27,
+ &ASound9::command28, &ASound9::command29, &ASound9::command30, &ASound9::command31,
+ &ASound9::command32, &ASound9::command33, &ASound9::command34, &ASound9::command35,
+ &ASound9::command36, &ASound9::command37, &ASound9::command38, &ASound9::command39,
+ &ASound9::command40, &ASound9::command41, &ASound9::command42, &ASound9::command43,
+ &ASound9::command44_46, &ASound9::command45, &ASound9::command44_46, &ASound9::command47,
+ &ASound9::command48, &ASound9::command49, &ASound9::command50, &ASound9::command51
+};
+
+ASound9::ASound9(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.009", 0x16F0) {
+ _v1 = _v2 = 0;
+ _soundPtr = nullptr;
+
+ // Load sound samples
+ _soundFile.seek(_dataOffset + 0x50);
+ for (int i = 0; i < 94; ++i)
+ _samples.push_back(AdlibSample(_soundFile));
+}
+
+int ASound9::command(int commandId, int param) {
+ if (commandId > 51)
+ return 0;
+
+ _commandParam = param;
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int ASound9::command9() {
+ _v1 = 1848;
+ _v2 = 84;
+ _channels[0].load(loadData(0xAA4, 470));
+ _channels[1].load(loadData(0xE4C, 450));
+ _channels[2].load(loadData(0x1466, 702));
+ _channels[3].load(loadData(0x137E, 232));
+ _channels[4].load(loadData(0x1014, 65));
+ _channels[5].load(loadData(0x11C4, 44));
+ _channels[6].load(loadData(0XC7A, 466));
+ return 0;
+}
+
+int ASound9::command10() {
+ _channels[0].load(loadData(0x1724, 24));
+ _channels[1].load(loadData(0x173C, 24));
+ _channels[2].load(loadData(0x1754, 20));
+ _channels[3].load(loadData(0x1768, 20));
+ _channels[4].load(loadData(0x177C, 20));
+ _channels[5].load(loadData(0x1790, 20));
+ return 0;
+}
+
+int ASound9::command11() {
+ playSound(0x8232, 168);
+ playSound(0x82DA, 170);
+ return 0;
+}
+
+int ASound9::command12() {
+ playSound(0x80DA, 12);
+ playSound(0x80E6, 12);
+ return 0;
+}
+
+int ASound9::command13() {
+ playSound(0x80F2, 38);
+ playSound(0x8118, 42);
+ return 0;
+}
+
+int ASound9::command14() {
+ playSound(0x81F6, 22);
+ return 0;
+}
+
+int ASound9::command15() {
+ playSound(0x818A, 32);
+ playSound(0x81AA, 32);
+ return 0;
+}
+
+int ASound9::command16() {
+ playSound(0x8022, 36);
+ playSound(0x8046, 42);
+ return 0;
+}
+
+int ASound9::command17() {
+ command29();
+ playSound(0x858C, 11);
+ return 0;
+}
+
+int ASound9::command18() {
+ playSound(0x80C2, 24);
+ return 0;
+}
+
+int ASound9::command19() {
+ playSound(0x80A0, 34);
+ return 0;
+}
+
+int ASound9::command20() {
+ int v = (getRandomNumber() & 0x10) | 0x4D;
+ byte *pData = loadData(0x8142, 8);
+ pData[4] = v & 0x7F;
+ playSoundData(pData);
+ return 0;
+}
+
+int ASound9::command21() {
+ playSound(0x815A, 16);
+ return 0;
+}
+
+int ASound9::command22() {
+ playSound(0x816A, 16);
+ return 0;
+}
+
+int ASound9::command23() {
+ playSound(0x814A, 16);
+ return 0;
+}
+
+int ASound9::command24() {
+ playSound(0x7FE2, 34);
+ return 0;
+}
+
+int ASound9::command25() {
+ playSound(0x8004, 30);
+ return 0;
+}
+
+int ASound9::command26() {
+ _channels[6].load(loadData(0x8384, 156));
+ _channels[7].load(loadData(0x8420, 160));
+ return 0;
+}
+
+int ASound9::command27() {
+ playSound(0x84C0, 140);
+ return 0;
+}
+
+int ASound9::command28() {
+ playSound(0x81CA, 10);
+ return 0;
+}
+
+int ASound9::command29() {
+ playSound(0x81D4, 10);
+ return 0;
+}
+
+int ASound9::command30() {
+ playSound(0x817A, 16);
+ return 0;
+}
+
+int ASound9::command31() {
+ playSound(0x820C, 14);
+ playSound(0x821A, 24);
+ return 0;
+}
+
+int ASound9::command32() {
+ playSound(0x8070, 8);
+ return 0;
+}
+
+int ASound9::command33() {
+ playSound(0x8078, 16);
+ playSound(0x8088, 16);
+ return 0;
+}
+
+int ASound9::command34() {
+ // Skipped stuff in original
+ _channels[0].load(loadData(0x17A4, 24));
+ _channels[1].load(loadData(0x1CDE, 62));
+ _channels[2].load(loadData(0x2672, 980));
+ _channels[3].load(loadData(0x3336, 1000));
+ _channels[4].load(loadData(0x469E, 176));
+ _channels[5].load(loadData(0x57F2, 138));
+
+ return 0;
+}
+
+int ASound9::command35() {
+ playSound(0x854C, 64);
+ return 0;
+}
+
+int ASound9::command36() {
+ playSound(0x81DE, 10);
+ playSound(0x81E8, 14);
+ return 0;
+}
+
+int ASound9::command37() {
+ byte *pData = loadData(0x8098, 8);
+ int v = getRandomNumber();
+ if ((v &= 0x40) != 0)
+ v |= 8;
+ else
+ v += 0x4A;
+
+ pData[6] = v;
+ playSoundData(pData);
+ return 0;
+}
+
+int ASound9::command38() {
+ playSound(0x100E, 6);
+ return 0;
+}
+
+int ASound9::command39() {
+ _soundPtr = loadData(0x1055, 128);
+ return 0;
+}
+
+int ASound9::command40() {
+ _soundPtr = loadData(0x118C, 50);
+ return 0;
+}
+
+int ASound9::command41() {
+ _soundPtr = loadData(0x11BE, 6);
+ return 0;
+}
+
+int ASound9::command42() {
+ _soundPtr = loadData(0x11F0, 50);
+ return 0;
+}
+
+int ASound9::command43() {
+ _v1 = _v2 = 80;
+ _channels[0].load(loadData(0x626A, 90));
+ _channels[1].load(loadData(0x67F2, 92));
+ _channels[2].load(loadData(0x6CFE, 232));
+ _channels[3].load(loadData(0x7146, 236));
+
+ return 0;
+}
+
+int ASound9::command44_46() {
+ _soundPtr = loadData(0x10D5, 38);
+ return 0;
+}
+
+int ASound9::command45() {
+ _soundPtr = loadData(0x10FB, 38);
+ return 0;
+}
+
+int ASound9::command47() {
+ _soundPtr = loadData(0x1121, 107);
+ return 0;
+}
+
+int ASound9::command48() {
+ playSound(0x7FD0, 8);
+ playSound(0x7FD8, 10);
+ return 0;
+}
+
+int ASound9::command49() {
+ _channels[0].load(loadData(0x7AD6, 92));
+ _channels[1].load(loadData(0x7B32, 90));
+ _channels[2].load(loadData(0x7B8C, 738));
+ _channels[3].load(loadData(0x7E6E, 28));
+ _channels[4].load(loadData(0x7E8A, 30));
+ _channels[5].load(loadData(0x7EA8, 30));
+ _channels[6].load(loadData(0x7EC6, 195));
+ return 0;
+}
+
+int ASound9::command50() {
+ _soundPtr = loadData(0x1222, 348);
+ return 0;
+}
+
+int ASound9::command51() {
+ // Skipped stuff in original
+ _channels[0].load(loadData(0x17BC, 1282));
+ _channels[1].load(loadData(0x1CFC, 2422));
+ _channels[2].load(loadData(0x2A46, 2288));
+ _channels[3].load(loadData(0x371E, 3964));
+ _channels[4].load(loadData(0x474E, 1863));
+ _channels[5].load(loadData(0x587C, 2538));
+ return 0;
+}
+
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h
new file mode 100644
index 0000000000..abb6516030
--- /dev/null
+++ b/engines/mads/nebular/sound_nebular.h
@@ -0,0 +1,781 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_SOUND_NEBULAR_H
+#define MADS_SOUND_NEBULAR_H
+
+#include "common/scummsys.h"
+#include "common/file.h"
+#include "common/mutex.h"
+#include "common/queue.h"
+#include "audio/audiostream.h"
+#include "audio/fmopl.h"
+#include "audio/mixer.h"
+
+namespace MADS {
+
+class SoundManager;
+
+namespace Nebular {
+
+/**
+ * Represents the data for a channel on the Adlib
+ */
+class AdlibChannel {
+public:
+ int _activeCount;
+ int _field1;
+ int _field2;
+ int _field3;
+ int _field4;
+ int _sampleIndex;
+ int _volume;
+ int _field7;
+ int _field8;
+ int _field9;
+ int _fieldA;
+ uint8 _fieldB;
+ int _fieldC;
+ int _fieldD;
+ int _fieldE;
+ byte *_ptr1;
+ byte *_pSrc;
+ byte *_ptr3;
+ byte *_ptr4;
+ int _field17;
+ int _field19;
+ byte *_soundData;
+ int _field1D;
+ int _field1E;
+ int _field1F;
+
+ // TODO: Only used by asound.003. Figure out usage
+ byte _field20;
+public:
+ static bool _channelsEnabled;
+public:
+ AdlibChannel();
+
+ void reset();
+ void enable(int flag);
+ void setPtr2(byte *pData);
+ void load(byte *pData);
+ void check(byte *nullPtr);
+};
+
+class AdlibChannelData {
+public:
+ int _field0;
+ int _freqMask;
+ int _freqBase;
+ int _field6;
+};
+
+class AdlibSample {
+public:
+ int _attackRate;
+ int _decayRate;
+ int _sustainLevel;
+ int _releaseRate;
+ bool _egTyp;
+ bool _ksr;
+ int _totalLevel;
+ int _scalingLevel;
+ int _waveformSelect;
+ int _freqMultiple;
+ int _feedback;
+ bool _ampMod;
+ int _vib;
+ int _alg;
+ int _fieldE;
+ int _freqMask;
+ int _freqBase;
+ int _field14;
+
+ AdlibSample() {}
+ AdlibSample(Common::SeekableReadStream &s);
+};
+
+struct RegisterValue {
+ uint8 _regNum;
+ uint8 _value;
+
+ RegisterValue(int regNum, int value) {
+ _regNum = regNum; _value = value;
+ }
+};
+
+#define ADLIB_CHANNEL_COUNT 9
+#define ADLIB_CHANNEL_MIDWAY 5
+#define CALLBACKS_PER_SECOND 60
+
+/**
+ * Base class for the sound player resource files
+ */
+class ASound : public Audio::AudioStream {
+private:
+ struct CachedDataEntry {
+ int _offset;
+ byte *_data;
+ };
+ Common::List<CachedDataEntry> _dataCache;
+ uint16 _randomSeed;
+
+ /**
+ * Does the initial Adlib initialisation
+ */
+ void adlibInit();
+
+ /**
+ * Does on-going processing for the Adlib sounds being played
+ */
+ void update();
+
+ /**
+ * Polls each of the channels for updates
+ */
+ void pollChannels();
+
+ /**
+ * Checks the status of the channels
+ */
+ void checkChannels();
+
+ /**
+ * Polls the currently active channel
+ */
+ void pollActiveChannel();
+
+ /**
+ * Updates the octave of the currently active channel
+ */
+ void updateOctave();
+
+ void updateChannelState();
+ void updateActiveChannel();
+
+ /**
+ * Loads up the specified sample
+ */
+ void loadSample(int sampleIndex);
+
+ /**
+ * Writes out the data of the selected sample to the Adlib
+ */
+ void processSample();
+
+ void updateFNumber();
+protected:
+ int _commandParam;
+
+ /**
+ * Queue a byte for an Adlib register
+ */
+ void write(int reg, int val);
+
+ /**
+ * Queue a byte for an Adlib register, and store it in the _ports array
+ */
+ int write2(int state, int reg, int val);
+
+ /**
+ * Flush any pending Adlib register values to the OPL driver
+ */
+ void flush();
+
+ /**
+ * Turn a channel on
+ */
+ void channelOn(int reg, int volume);
+
+ /**
+ * Turn a channel off
+ */
+ void channelOff(int reg);
+
+ /**
+ * Checks for whether a poll result needs to be set
+ */
+ void resultCheck();
+
+ /**
+ * Loads a data block from the sound file, caching the result for any future
+ * calls for the same data
+ */
+ byte *loadData(int offset, int size);
+
+ /**
+ * Play the specified sound
+ * @param offset Offset of sound data within sound player data segment
+ * @param size Size of sound data block
+ */
+ void playSound(int offset, int size);
+
+ /**
+ * Play the specified raw sound data
+ * @param pData Pointer to data block containing sound data
+ * @param startingChannel Channel to start scan from
+ */
+ void playSoundData(byte *pData, int startingChannel = ADLIB_CHANNEL_MIDWAY);
+
+ /**
+ * Checks to see whether the given block of data is already loaded into a channel.
+ */
+ bool isSoundActive(byte *pData);
+
+ /**
+ * Sets the frequency for a given channel.
+ */
+ void setFrequency(int channel, int freq);
+
+ /**
+ * Returns a 16-bit random number
+ */
+ int getRandomNumber();
+
+ virtual int command0();
+ int command1();
+ int command2();
+ int command3();
+ int command4();
+ int command5();
+ int command6();
+ int command7();
+ int command8();
+
+ int nullCommand() { return 0; }
+public:
+ Audio::Mixer *_mixer;
+ FM_OPL *_opl;
+ Audio::SoundHandle _soundHandle;
+ AdlibChannel _channels[ADLIB_CHANNEL_COUNT];
+ AdlibChannel *_activeChannelPtr;
+ AdlibChannelData _channelData[11];
+ Common::Array<AdlibSample> _samples;
+ AdlibSample *_samplePtr;
+ Common::File _soundFile;
+ Common::Queue<RegisterValue> _queue;
+ Common::Mutex _driverMutex;
+ int _dataOffset;
+ int _frameCounter;
+ bool _isDisabled;
+ int _v1;
+ int _v2;
+ int _activeChannelNumber;
+ int _freqMask1;
+ int _freqMask2;
+ int _freqBase1;
+ int _freqBase2;
+ int _channelNum1, _channelNum2;
+ int _v7;
+ int _v8;
+ int _v9;
+ int _v10;
+ int _pollResult;
+ int _resultFlag;
+ byte _nullData[2];
+ int _ports[256];
+ bool _stateFlag;
+ int _activeChannelReg;
+ int _v11;
+ bool _amDep, _vibDep, _splitPoint;
+ int _samplesPerCallback;
+ int _samplesPerCallbackRemainder;
+ int _samplesTillCallback;
+ int _samplesTillCallbackRemainder;
+public:
+ /**
+ * Constructor
+ * @param mixer Mixer
+ * @param opl OPL
+ * @param filename Specifies the adlib sound player file to use
+ * @param dataOffset Offset in the file of the data segment
+ */
+ ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, int dataOffset);
+
+ /**
+ * Destructor
+ */
+ virtual ~ASound();
+
+ /**
+ * Execute a player command. Most commands represent sounds to play, but some
+ * low number commands also provide control operations.
+ * @param commandId Player ommand to execute.
+ * @param param Optional parameter used by a few commands
+ */
+ virtual int command(int commandId, int param) = 0;
+
+ /**
+ * Stop all currently playing sounds
+ */
+ int stop();
+
+ /**
+ * Main poll method to allow sounds to progress
+ */
+ int poll();
+
+ /**
+ * General noise/note output
+ */
+ void noise();
+
+ /**
+ * Return the current frame counter
+ */
+ int getFrameCounter() { return _frameCounter; }
+
+ // AudioStream interface
+ /**
+ * Main buffer read
+ */
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+
+ /**
+ * Mono sound only
+ */
+ virtual bool isStereo() const { return false; }
+
+ /**
+ * Data is continuously pushed, so definitive end
+ */
+ virtual bool endOfData() const { return false; }
+
+ /**
+ * Return sample rate
+ */
+ virtual int getRate() const { return 11025; }
+};
+
+class ASound1 : public ASound {
+private:
+ typedef int (ASound1::*CommandPtr)();
+ static const CommandPtr _commandList[42];
+ bool _cmd23Toggle;
+
+ int command9();
+ int command10();
+ int command11();
+ int command12();
+ int command13();
+ int command14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command26();
+ int command27();
+ int command28();
+ int command29();
+ int command30();
+ int command31();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+ int command38();
+ int command39();
+ int command40();
+ int command41();
+
+ void command111213();
+ int command2627293032();
+public:
+ ASound1(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+class ASound2 : public ASound {
+private:
+ byte _command12Param;
+private:
+ typedef int (ASound2::*CommandPtr)();
+ static const CommandPtr _commandList[44];
+
+ virtual int command0();
+ int command9();
+ int command10();
+ int command11();
+ int command12();
+ int command13();
+ int command14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command26();
+ int command27();
+ int command28();
+ int command29();
+ int command30();
+ int command31();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+ int command38();
+ int command39();
+ int command40();
+ int command41();
+ int command42();
+ int command43();
+
+ void command9Randomize();
+ void command9Apply(byte *data, int val, int incr);
+public:
+ ASound2(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+class ASound3 : public ASound {
+private:
+ bool _command39Flag;
+
+ typedef int (ASound3::*CommandPtr)();
+ static const CommandPtr _commandList[61];
+
+ int command9();
+ int command10();
+ int command11();
+ int command13();
+ int command14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command26();
+ int command27();
+ int command28();
+ int command29();
+ int command30();
+ int command31();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+ int command38();
+ int command39();
+ int command40();
+ int command41();
+ int command42();
+ int command43();
+ int command44();
+ int command45();
+ int command46();
+ int command47();
+ int command49();
+ int command50();
+ int command51();
+ int command57();
+ int command59();
+ int command60();
+
+ void command9Randomize();
+ void command9Apply(byte *data, int val, int incr);
+public:
+ ASound3(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+class ASound4 : public ASound {
+private:
+ typedef int (ASound4::*CommandPtr)();
+ static const CommandPtr _commandList[61];
+
+ int command10();
+ int command12();
+ int command19();
+ int command20();
+ int command21();
+ int command24();
+ int command27();
+ int command30();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+ int command38();
+ int command43();
+ int command52();
+ int command53();
+ int command54();
+ int command55();
+ int command56();
+ int command57();
+ int command58();
+ int command59();
+ int command60();
+
+ void method1();
+public:
+ ASound4(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+class ASound5 : public ASound {
+private:
+ typedef int (ASound5::*CommandPtr)();
+ static const CommandPtr _commandList[42];
+
+ int command9();
+ int command10();
+ int command11();
+ int command12();
+ int command13();
+ int command14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command26();
+ int command27();
+ int command28();
+ int command29();
+ int command30();
+ int command31();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+ int command38();
+ int command39();
+ int command40();
+ int command41();
+ int command42();
+ int command43();
+public:
+ ASound5(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+class ASound6 : public ASound {
+private:
+ typedef int (ASound6::*CommandPtr)();
+ static const CommandPtr _commandList[30];
+
+ int command9();
+ int command10();
+ int command11();
+ int command12();
+ int command13();
+ int command14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command29();
+public:
+ ASound6(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+class ASound7 : public ASound {
+private:
+ typedef int (ASound7::*CommandPtr)();
+ static const CommandPtr _commandList[38];
+
+ int command9();
+ int command15();
+ int command16();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command26();
+ int command27();
+ int command28();
+ int command30();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+public:
+ ASound7(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+class ASound8 : public ASound {
+private:
+ typedef int (ASound8::*CommandPtr)();
+ static const CommandPtr _commandList[38];
+
+ int command9();
+ int command10();
+ int command11();
+ int command12();
+ int command13();
+ int command14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command26();
+ int command27();
+ int command28();
+ int command29();
+ int command30();
+ int command31();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+
+ void method1(byte *pData);
+ void adjustRange(byte *pData, byte v, int incr);
+public:
+ ASound8(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+class ASound9 : public ASound {
+private:
+ int _v1, _v2;
+ byte *_soundPtr;
+
+ typedef int (ASound9::*CommandPtr)();
+ static const CommandPtr _commandList[52];
+
+ int command9();
+ int command10();
+ int command11();
+ int command12();
+ int command13();
+ int command14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command26();
+ int command27();
+ int command28();
+ int command29();
+ int command30();
+ int command31();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+ int command38();
+ int command39();
+ int command40();
+ int command41();
+ int command42();
+ int command43();
+ int command44_46();
+ int command45();
+ int command47();
+ int command48();
+ int command49();
+ int command50();
+ int command51();
+ int command57();
+ int command59();
+ int command60();
+public:
+ ASound9(Audio::Mixer *mixer, FM_OPL *opl);
+
+ virtual int command(int commandId, int param);
+};
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_SOUND_NEBULAR_H */
diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp
new file mode 100644
index 0000000000..c098e23bf9
--- /dev/null
+++ b/engines/mads/palette.cpp
@@ -0,0 +1,838 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "engines/util.h"
+#include "graphics/palette.h"
+#include "mads/mads.h"
+#include "mads/msurface.h"
+#include "mads/staticres.h"
+
+namespace MADS {
+
+#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
+
+void RGB6::load(Common::SeekableReadStream *f) {
+ r = VGA_COLOR_TRANS(f->readByte());
+ g = VGA_COLOR_TRANS(f->readByte());
+ b = VGA_COLOR_TRANS(f->readByte());
+ _palIndex = f->readByte();
+ _u2 = f->readByte();
+ _flags = f->readByte();
+}
+
+/*------------------------------------------------------------------------*/
+
+PaletteUsage::PaletteUsage(MADSEngine *vm) {
+ _vm = vm;
+ _data = nullptr;
+}
+
+void PaletteUsage::load(Common::Array<UsageEntry> *data) {
+ _data = data;
+}
+
+void PaletteUsage::getKeyEntries(Common::Array<RGB6> &palette) {
+ _data->clear();
+
+ for (uint i = 0; i < palette.size(); ++i) {
+ byte *uPtr = &palette[i]._flags;
+ if ((*uPtr & 0x10) && _data->size() < 3) {
+ _data->push_back(UsageEntry(i));
+ }
+ }
+}
+
+static bool sortHelper(const PaletteUsage::UsageEntry &ue1, const PaletteUsage::UsageEntry &ue2) {
+ return ue1._sortValue < ue2._sortValue;
+}
+
+void PaletteUsage::prioritize(Common::Array<RGB6> &palette) {
+ for (uint i = 0; i < _data->size(); ++i) {
+ RGB6 &palEntry = palette[(*_data)[i]._palIndex];
+ (*_data)[i]._sortValue = _vm->_palette->rgbMerge(palEntry);
+ }
+
+ Common::sort(_data->begin(), _data->end(), sortHelper);
+}
+
+static bool rangeSorter(const PaletteUsage::UsageRange &ur1, const PaletteUsage::UsageRange &ur2) {
+ return ur1._v2 < ur2._v2;
+}
+
+int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) {
+ int palLow;
+ int palHigh = (flags & 0x800) ? 0x100 : 0xFC;
+ int palIdx;
+
+ PaletteUsage tempUsage(_vm);
+ Common::Array<UsageEntry> tempUsageData;
+ tempUsage.load(&tempUsageData);
+
+ if (flags & 0x4000) {
+ palLow = 0;
+ palIdx = palHigh;
+ } else {
+ palLow = _vm->_palette->_lowRange;
+ if ((PALETTE_COUNT - _vm->_palette->_highRange) > palHigh) {
+ palIdx = palHigh;
+ } else {
+ palIdx = PALETTE_COUNT - _vm->_palette->_highRange;
+ }
+ }
+
+ int rgbIndex = _vm->_palette->_rgbList.scan();
+ uint32 rgbMask = 1 << rgbIndex;
+ bool noUsageFlag = flags & 0x8000;
+ bool hasUsage = _data != nullptr;
+ bool flag1 = false;
+
+ if (hasUsage) {
+ if (noUsageFlag || _data->size() == 0)
+ hasUsage = false;
+
+ if (noUsageFlag && _data->size() > 0)
+ flag1 = true;
+ }
+
+ if (hasUsage) {
+ tempUsage.getKeyEntries(palette);
+ tempUsage.prioritize(palette);
+ }
+
+ int freeIndex;
+ int palCount = getGamePalFreeIndex(&freeIndex);
+ Common::Array<UsageRange> palRange;
+
+ for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) {
+ byte pal2 = palIndex;
+ byte pal1 = 0;
+
+ if (!(palette[palIndex]._flags & 0x80)) {
+ pal1 = 0x40;
+ }
+ if (palette[palIndex]._flags & 0x60) {
+ pal1 |= 0x20;
+ }
+
+ palRange.push_back(UsageRange(pal1, pal2));
+ }
+
+ Common::sort(palRange.begin(), palRange.end(), rangeSorter);
+
+ int var3A = (flags & 0x4000) ? 0xffff : 0xfffe;
+
+ for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) {
+ bool changed = false;
+ int newPalIndex = 0xFF;
+ int v1 = palRange[palIndex]._v2;
+
+ if (palette[v1]._flags & 8) {
+ changed = true;
+ newPalIndex = 0xFD;
+ }
+
+ if (hasUsage && palette[v1]._flags & 0x10) {
+ for (uint usageIndex = 0; usageIndex < tempUsage._data->size() && !changed; ++usageIndex) {
+ if ((*tempUsage._data)[usageIndex]._palIndex == palIndex) {
+ changed = true;
+ int dataIndex = MIN(usageIndex, _data->size() - 1);
+ newPalIndex = (*_data)[dataIndex]._palIndex;
+ }
+ }
+ }
+
+ if (flag1 && palette[palIndex]._flags & 0x10) {
+ for (uint usageIndex = 0; usageIndex < _data->size() && !changed; ++usageIndex) {
+ if ((*_data)[usageIndex]._palIndex == palIndex) {
+ changed = true;
+ newPalIndex = 0xF0 + usageIndex;
+
+ // Copy data into the high end of the main palette
+ RGB6 &pSrc = palette[palIndex];
+ byte *pDest = &_vm->_palette->_mainPalette[newPalIndex * 3];
+ pDest[0] = pSrc.r;
+ pDest[1] = pSrc.g;
+ pDest[2] = pSrc.b;
+ }
+ }
+ }
+
+ if (!changed && !noUsageFlag) {
+ int var2 = (palette[palIndex]._flags & 0x20) ||
+ (((flags & 0x2000) || (palette[palIndex]._flags & 0x4000)) &&
+ ((flags & 0x1000) || (palCount == 0))) ? 0x7fff : 1;
+ int var36 = (palette[palIndex]._flags & 0x80) ? 0 : 2;
+
+ for (int idx = palLow; idx < palIdx; ++idx) {
+ uint32 v = _vm->_palette->_palFlags[idx];
+ if ((v & var3A) && !(v & var36)) {
+ int var10;
+
+ if (var2 > 1) {
+ var10 = rgbFactor(&_vm->_palette->_mainPalette[idx * 3], palette[palIndex]);
+ }
+ else if (_vm->_palette->_mainPalette[idx * 3] != palette[palIndex].r ||
+ _vm->_palette->_mainPalette[idx * 3 + 1] != palette[palIndex].g ||
+ _vm->_palette->_mainPalette[idx * 3 + 2] != palette[palIndex].b) {
+ var10 = 1;
+ } else {
+ var10 = 0;
+ }
+
+ if (var2 > var10) {
+ changed = true;
+ newPalIndex = idx;
+ var2 = var10;
+ }
+ }
+ }
+ }
+
+ if (!changed && (!(flags & 0x1000) || (!(palette[palIndex]._flags & 0x60) && !(flags & 0x2000)))) {
+ for (int idx = freeIndex; idx < palIdx && !changed; ++idx) {
+ if (!_vm->_palette->_palFlags[idx]) {
+ --palCount;
+ ++freeIndex;
+ changed = true;
+ newPalIndex = idx;
+
+ RGB6 &pSrc = palette[palIndex];
+ byte *pDest = &_vm->_palette->_mainPalette[idx * 3];
+ pDest[0] = pSrc.r;
+ pDest[1] = pSrc.g;
+ pDest[2] = pSrc.b;
+ }
+ }
+ }
+
+ // TODO: Not sure if it's valid or not for changed flag to ever be false.
+ // In at least scene 318, when the doctor knocks you with the blackjack,
+ // the changed flag can be false
+ //assert(changed);
+
+ // CHECKME: When pressing on F1 in the first screen, newPalIndex is set to 0xFF at this point
+ // which is a valid value for the index. Maybe a better check would be "< 256" ?
+ //assert(newPalIndex != -1);
+
+ int var52 = (noUsageFlag && palette[palIndex]._u2) ? 2 : 0;
+
+ _vm->_palette->_palFlags[newPalIndex] |= var52 | rgbMask;
+ palette[palIndex]._palIndex = newPalIndex;
+ }
+
+ _vm->_palette->_rgbList[rgbIndex] = true;
+
+ return rgbIndex;
+}
+
+void PaletteUsage::transform(Common::Array<RGB6> &palette) {
+ if (!empty()) {
+ for (uint i = 0; i < _data->size(); ++i) {
+ int palIndex = (*_data)[i]._palIndex;
+ (*_data)[i]._palIndex = palette[palIndex]._palIndex;
+ }
+ }
+}
+
+void PaletteUsage::updateUsage(Common::Array<int> &usageList, int sceneUsageIndex) {
+ uint32 mask1 = 0xFFFFFFFF;
+ uint32 mask2 = 0;
+
+ for (uint idx = 0; idx < usageList.size(); ++idx) {
+ uint32 bitMask = 1 << usageList[idx];
+ mask1 ^= bitMask;
+ mask2 |= bitMask;
+ _vm->_palette->_rgbList[usageList[idx]] = false;
+ }
+
+ uint32 mask3 = 1 << sceneUsageIndex;
+
+ for (uint idx = 0; idx < PALETTE_COUNT; ++idx) {
+ uint32 mask = mask2 & _vm->_palette->_palFlags[idx];
+ if (mask) {
+ _vm->_palette->_palFlags[idx] = (_vm->_palette->_palFlags[idx] &
+ mask1) | mask3;
+ }
+ }
+
+ _vm->_palette->_rgbList[sceneUsageIndex] = true;
+}
+
+void PaletteUsage::resetPalFlags(int idx) {
+ if (idx >= 0 && idx < 32) {
+ uint32 rgbMask = ~(1 << idx);
+
+ uint32 *flagP = _vm->_palette->_palFlags;
+ for (int i = 0; i < 256; ++i, ++flagP) {
+ *flagP &= rgbMask;
+ if (*flagP == 2)
+ *flagP = 0;
+ }
+
+ _vm->_palette->_rgbList[idx] = false;
+ }
+}
+
+int PaletteUsage::getGamePalFreeIndex(int *palIndex) {
+ *palIndex = -1;
+ int count = 0;
+
+ for (int i = 0; i < PALETTE_COUNT; ++i) {
+ if (!_vm->_palette->_palFlags[i]) {
+ ++count;
+ if (*palIndex < 0)
+ *palIndex = i;
+ }
+ }
+
+ return count;
+}
+
+int PaletteUsage::rgbFactor(byte *palEntry, RGB6 &pal6) {
+ int total = 0;
+ total += (palEntry[0] - pal6.r) * (palEntry[0] - pal6.r);
+ total += (palEntry[1] - pal6.g) * (palEntry[1] - pal6.g);
+ total += (palEntry[2] - pal6.b) * (palEntry[2] - pal6.b);
+
+ return total;
+}
+
+/*------------------------------------------------------------------------*/
+
+void RGBList::clear() {
+ for (int i = 0; i < 32; i++)
+ _data[i] = false;
+}
+
+void RGBList::reset() {
+ for (int i = 2; i < 32; i++)
+ _data[i] = false;
+}
+
+int RGBList::scan() {
+ for (int i = 0; i < 32; ++i) {
+ if (!_data[i])
+ return i;
+ }
+
+ error("RGBList was full");
+}
+
+void RGBList::copy(RGBList &src) {
+ Common::copy(&src._data[0], &src._data[32], &_data[0]);
+}
+
+/*------------------------------------------------------------------------*/
+
+Fader::Fader(MADSEngine *vm)
+ : _vm(vm) {
+ _colorFlags[0] = _colorFlags[1] = _colorFlags[2] = true;
+ _colorFlags[3] = false;
+ _colorValues[0] = _colorValues[1] = 0;
+ _colorValues[2] = _colorValues[3] = 0;
+
+ // TODO: It would be better if the fader routines could be refactored
+ // to work directly with 8-bit RGB values rather than 6-bit RGB values
+ Common::fill(&_rgb64Map[0], &_rgb64Map[PALETTE_COUNT], 0);
+ for (int i = 0; i < 64; ++i)
+ _rgb64Map[VGA_COLOR_TRANS(i)] = i;
+ byte v = 0;
+ for (int i = 0; i < PALETTE_COUNT; ++i) {
+ if (_rgb64Map[i])
+ v = _rgb64Map[i];
+ else
+ _rgb64Map[i] = v;
+ }
+}
+
+
+void Fader::setPalette(const byte *colors, uint start, uint num) {
+ g_system->getPaletteManager()->setPalette(colors, start, num);
+}
+
+void Fader::grabPalette(byte *colors, uint start, uint num) {
+ g_system->getPaletteManager()->grabPalette(colors, start, num);
+}
+
+void Fader::fadeOut(byte palette[PALETTE_SIZE], byte *paletteMap,
+ int baseColor, int numColors, int baseGrey, int numGreys,
+ int tickDelay, int steps) {
+ GreyEntry map[PALETTE_COUNT];
+ int intensity;
+ byte palIndex[PALETTE_COUNT][3];
+ int8 signs[PALETTE_COUNT][3];
+
+ mapToGreyRamp(palette, baseColor, numColors, baseGrey, numGreys, map);
+
+ for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) {
+ int index = palCtr - baseColor;
+ for (int colorCtr = 0; colorCtr < 3; ++colorCtr) {
+ if (_colorFlags[colorCtr]) {
+ int shiftSign = _colorValues[colorCtr];
+ if (shiftSign >= 0) {
+ intensity = map[index]._intensity << shiftSign;
+ } else {
+ intensity = map[index]._intensity >> ABS(shiftSign);
+ }
+ } else {
+ intensity = _colorValues[colorCtr];
+ }
+
+ int diff = intensity - _rgb64Map[palette[palCtr * 3 + colorCtr]];
+ palIndex[palCtr][colorCtr] = (byte)ABS(diff);
+ signs[palCtr][colorCtr] = (diff == 0) ? 0 : (diff < 0 ? -1 : 1);
+ }
+ }
+
+ for (int stepCtr = 0; stepCtr < steps; ++stepCtr) {
+ for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) {
+ int index = palCtr - baseColor;
+ for (int colorCtr = 0; colorCtr < 3; ++colorCtr) {
+ map[index]._accum[colorCtr] += palIndex[palCtr][colorCtr];
+ while (map[index]._accum[colorCtr] >= steps) {
+ map[index]._accum[colorCtr] -= steps;
+
+ byte rgb63 = _rgb64Map[palette[palCtr * 3 + colorCtr]] +
+ signs[palCtr][colorCtr];
+ palette[palCtr * 3 + colorCtr] = VGA_COLOR_TRANS(rgb63);
+ }
+ }
+ }
+
+ setFullPalette(palette);
+
+ _vm->_events->waitForNextFrame();
+ }
+
+ if (paletteMap != nullptr) {
+ for (int palCtr = 0; palCtr < numColors; palCtr++) {
+ paletteMap[palCtr] = map[palCtr]._mapColor;
+ }
+ }
+}
+
+void Fader::fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE],
+ int baseColor, int numColors, int baseGrey, int numGreys,
+ int tickDelay, int steps) {
+ GreyEntry map[PALETTE_COUNT];
+ byte tempPal[PALETTE_SIZE];;
+ int8 signs[PALETTE_COUNT][3];
+ byte palIndex[PALETTE_COUNT][3];
+ int intensity;
+
+ Common::copy(destPalette, destPalette + PALETTE_SIZE, tempPal);
+
+ mapToGreyRamp(tempPal, baseColor, numColors, baseGrey, numGreys, map);
+
+ for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) {
+ int index = palCtr - baseColor;
+ for (int colorCtr = 0; colorCtr < 3; ++colorCtr) {
+ if (_colorFlags[colorCtr]) {
+ int shiftSign = _colorValues[colorCtr];
+ if (shiftSign >= 0) {
+ intensity = map[index]._intensity << shiftSign;
+ }
+ else {
+ intensity = map[index]._intensity >> abs(shiftSign);
+ }
+ }
+ else {
+ intensity = _colorValues[colorCtr];
+ }
+
+ int diff = _rgb64Map[destPalette[palCtr * 3 + colorCtr]] - intensity;
+ palIndex[palCtr][colorCtr] = (byte)ABS(diff);
+ signs[palCtr][colorCtr] = (diff == 0) ? 0 : (diff < 0 ? -1 : 1);
+
+ map[index]._accum[colorCtr] = 0;
+ }
+ }
+
+ for (int stepCtr = 0; stepCtr < steps; ++stepCtr) {
+ for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) {
+ int index = palCtr - baseColor;
+ for (int colorCtr = 0; colorCtr < 3; ++colorCtr) {
+ map[index]._accum[colorCtr] += palIndex[palCtr][colorCtr];
+ while (map[index]._accum[colorCtr] >= steps) {
+ map[index]._accum[colorCtr] -= steps;
+
+ byte rgb63 = _rgb64Map[palette[palCtr * 3 + colorCtr]] +
+ signs[palCtr][colorCtr];
+ palette[palCtr * 3 + colorCtr] = VGA_COLOR_TRANS(rgb63);
+ }
+ }
+ }
+
+ setFullPalette(palette);
+
+ _vm->_events->waitForNextFrame();
+ }
+}
+
+void Fader::mapToGreyRamp(byte palette[PALETTE_SIZE], int baseColor, int numColors,
+ int baseGrey, int numGreys, GreyEntry *map) {
+ byte greyList[PALETTE_COUNT];
+ byte greyMapping[PALETTE_COUNT];
+ byte greyTable[64];
+ byte greyIntensity[64];
+ int intensity, shiftSign;
+
+ getGreyValues(palette, greyList, baseColor, numColors);
+ greyPopularity(greyList, greyTable, numColors);
+
+ for (int idx = 0; idx < numColors; ++idx) {
+ greyMapping[idx] = idx;
+ Common::fill(&map[idx]._accum[0], &map[idx]._accum[3], 0);
+ }
+
+ for (int idx = 0; idx < PALETTE_COUNT; ++idx) {
+ map[idx]._mapColor = (byte)idx;
+ }
+
+ // Sort the mapping lists
+ insertionSort(numColors, greyList, greyMapping);
+
+ // Initialize state variables
+ int greySum = 0;
+ int greyScan = 0;
+ int greyMark = 0;
+ int greyColors = 0;
+ int greyAccum = 0;
+ int firstColor = 0;
+
+ for (int greyCtr = 0; greyCtr < 64; ++greyCtr) {
+ for (int idx = 0; idx < greyTable[greyCtr]; ++idx) {
+ greySum += greyList[greyScan++];
+ ++greyColors;
+
+ greyAccum += numGreys;
+ while (greyAccum >= numColors) {
+ greyAccum -= numColors;
+ if (greyColors > 0) {
+ greyIntensity[greyMark] = (byte)(greySum / greyColors);
+ }
+
+ for (int rescan = firstColor; rescan < greyScan; ++rescan) {
+ map[greyMapping[rescan]]._intensity = greyIntensity[greyMark];
+ map[greyMapping[rescan]]._mapColor = (byte)(greyMark + baseGrey);
+ }
+
+ firstColor = greyScan;
+ greySum = 0;
+ greyColors = 0;
+ ++greyMark;
+ }
+ }
+ }
+
+ // Set the palette range of greyscale values to be used
+ byte *palP = &palette[baseGrey * 3];
+ for (int greys = 0; greys < numGreys; ++greys) {
+ for (int color = 0; color < 3; ++color) {
+ if (_colorFlags[color]) {
+ shiftSign = (byte)_colorValues[color];
+ if (shiftSign >= 0) {
+ intensity = greyIntensity[greys] << shiftSign;
+ } else {
+ intensity = greyIntensity[greys] >> abs(shiftSign);
+ }
+ } else {
+ intensity = _colorValues[color];
+ }
+ *palP++ = VGA_COLOR_TRANS(intensity);
+ }
+ }
+}
+
+void Fader::getGreyValues(const byte palette[PALETTE_SIZE],
+ byte greyList[PALETTE_COUNT], int baseColor, int numColors) {
+ const byte *palP = &palette[baseColor * 3];
+
+ for (int i = 0; i < numColors; ++i, palP += 3) {
+ int v = rgbMerge(palP[0], palP[1], palP[2]);
+ greyList[i] = v >> 7;
+ }
+}
+
+void Fader::greyPopularity(const byte greyList[PALETTE_COUNT],
+ byte greyTable[64], int numColors) {
+ Common::fill(&greyTable[0], &greyTable[64], 0);
+ for (int i = 0; i < numColors; ++i) {
+ int idx = greyList[i];
+ ++greyTable[idx];
+ }
+}
+
+void Fader::insertionSort(int size, byte *id, byte *value) {
+ bool restartFlag;
+ int endIndex = size - 1;
+
+ do {
+ restartFlag = false;
+ if (endIndex <= 0)
+ break;
+
+ for (int arrIndex = 0; arrIndex < endIndex && !restartFlag; ++arrIndex) {
+ byte *idP = id + arrIndex;
+ byte *valueP = value + arrIndex;
+
+ // Check whether the next index is out of order with the one following it
+ if (*idP > *(idP + 1)) {
+ // Found an incorrect ordering
+ restartFlag = true;
+
+ // Save id/value at current index
+ byte savedId = *idP;
+ byte savedValue = *valueP;
+
+ int moveCount = size - arrIndex - 1;
+ if (moveCount > 0) {
+ Common::copy(idP + 1, idP + moveCount + 2, idP);
+ Common::copy(valueP + 1, valueP + moveCount + 2, valueP);
+ }
+
+ // Scan for insert spot
+ int idx = 0;
+ if (endIndex > 0) {
+ bool breakFlag = false;
+ for (; idx <= endIndex && !breakFlag; ++idx) {
+ breakFlag = savedId < id[idx];
+ }
+ }
+
+ // Set up an insert point for entry
+ moveCount = size - idx - 1;
+ if (moveCount > 0) {
+ Common::copy_backward(id + idx, id + idx + moveCount, id + idx + moveCount + 1);
+ Common::copy_backward(value + idx, value + idx + moveCount, value + idx + moveCount + 1);
+ }
+
+ // Set shifted values at the new position
+ id[idx] = savedId;
+ value[idx] = savedValue;
+ }
+ }
+ } while (restartFlag);
+}
+
+int Fader::rgbMerge(RGB6 &palEntry) {
+ return rgbMerge(palEntry.r, palEntry.g, palEntry.b);
+}
+
+int Fader::rgbMerge(byte r, byte g, byte b) {
+ return _rgb64Map[r] * 38 + _rgb64Map[g] * 76 + _rgb64Map[b] * 14;
+}
+
+/*------------------------------------------------------------------------*/
+
+Palette::Palette(MADSEngine *vm) : Fader(vm), _paletteUsage(vm) {
+ _lockFl = false;
+ _lowRange = 0;
+ _highRange = 0;
+ Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0);
+ Common::fill(&_palFlags[0], &_palFlags[PALETTE_COUNT], 0);
+}
+
+void Palette::setEntry(byte palIndex, byte r, byte g, byte b) {
+ _mainPalette[palIndex * 3] = VGA_COLOR_TRANS(r);
+ _mainPalette[palIndex * 3 + 1] = VGA_COLOR_TRANS(g);
+ _mainPalette[palIndex * 3 + 2] = VGA_COLOR_TRANS(b);
+
+ setPalette((const byte *)&_mainPalette[palIndex * 3], palIndex, 1);
+}
+
+uint8 Palette::palIndexFromRgb(byte r, byte g, byte b, byte *paletteData) {
+ byte index = 0;
+ int32 minDist = 0x7fffffff;
+ byte palData[PALETTE_SIZE];
+
+ if (paletteData == NULL) {
+ g_system->getPaletteManager()->grabPalette(palData, 0, PALETTE_COUNT);
+ paletteData = &palData[0];
+ }
+
+ for (int palIndex = 0; palIndex < PALETTE_COUNT; ++palIndex) {
+ int Rdiff = r - paletteData[palIndex * 3];
+ int Gdiff = g - paletteData[palIndex * 3 + 1];
+ int Bdiff = b - paletteData[palIndex * 3 + 2];
+
+ if (Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff < minDist) {
+ minDist = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff;
+ index = (uint8)palIndex;
+ }
+ }
+
+ return (uint8)index;
+}
+
+void Palette::setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2) {
+ int rgbCurrent = rgbValue2;
+ int rgbDiff = -(rgbValue2 - rgbValue1);
+
+ if (count > 0) {
+ byte *pDest = palette + start * 3;
+ int endVal = count - 1;
+ int numLeft = count;
+
+ int rgbCtr = 0;
+ do {
+ pDest[0] = pDest[1] = pDest[2] = rgbCurrent;
+
+ if (numLeft > 1) {
+ rgbCtr += rgbDiff;
+ if (rgbCtr >= endVal) {
+ do {
+ ++rgbCurrent;
+ rgbCtr += 1 - numLeft;
+ } while (rgbCtr >= endVal);
+ }
+ }
+
+ pDest += 3;
+ } while (--numLeft > 0);
+ }
+}
+
+void Palette::setSystemPalette() {
+ byte palData[4 * 3];
+ palData[0 * 3] = palData[0 * 3 + 1] = palData[0 * 3 + 2] = 0;
+ palData[1 * 3] = palData[1 * 3 + 1] = palData[1 * 3 + 2] = 0x54;
+ palData[2 * 3] = palData[2 * 3 + 1] = palData[2 * 3 + 2] = 0xb4;
+ palData[3 * 3] = palData[3 * 3 + 1] = palData[3 * 3 + 2] = 0xff;
+
+ setPalette(palData, 0, 4);
+}
+
+void Palette::resetGamePalette(int lowRange, int highRange) {
+ Common::fill((byte *)&_palFlags[0], (byte *)&_palFlags[PALETTE_COUNT], 0);
+ initVGAPalette(_mainPalette);
+
+ // Reserve the start of the palette for things like on-screen text
+ if (lowRange) {
+ Common::fill(&_palFlags[0], &_palFlags[lowRange], 1);
+ }
+
+ // Reserve the high end of the palette for dialog display
+ if (highRange) {
+ Common::fill(&_palFlags[256 - highRange], &_palFlags[256], 1);
+ }
+
+ _rgbList.clear();
+ _rgbList[0] = _rgbList[1] = true;
+
+ _lockFl = false;
+ _lowRange = lowRange;
+ _highRange = highRange;
+}
+
+void Palette::initPalette() {
+ uint32 palMask = 1;
+
+ if (_vm->_game->_player._spritesLoaded && _vm->_game->_player._numSprites) {
+
+ for (int idx = 0; idx < _vm->_game->_player._numSprites; ++idx) {
+ SpriteAsset *asset = _vm->_game->_scene._sprites[
+ _vm->_game->_player._spritesStart + idx];
+
+ uint32 mask = 1;
+ if (asset->_usageIndex)
+ mask <<= asset->_usageIndex;
+
+ palMask = mask;
+ }
+ }
+
+ for (int idx = 0; idx < PALETTE_COUNT; ++idx)
+ _palFlags[idx] = palMask;
+
+ _lockFl = false;
+ _rgbList.reset();
+}
+
+void Palette::initVGAPalette(byte *palette) {
+ byte *destP = palette;
+ for (int palIndex = 0; palIndex < 16; ++palIndex) {
+ for (int byteCtr = 2; byteCtr >= 0; --byteCtr)
+ *destP++ = ((DEFAULT_VGA_LOW_PALETTE[palIndex] >> (8 * byteCtr)) & 0xff) >> 2;
+ }
+
+ destP = &palette[0xF0 * 3];
+ for (int palIndex = 0; palIndex < 16; ++palIndex) {
+ for (int byteCtr = 2; byteCtr >= 0; --byteCtr)
+ *destP++ = ((DEFAULT_VGA_HIGH_PALETTE[palIndex] >> (8 * byteCtr)) & 0xff) >> 2;
+ }
+}
+
+void Palette::setLowRange() {
+ _mainPalette[0] = _mainPalette[1] = _mainPalette[2] = VGA_COLOR_TRANS(0);
+ _mainPalette[3] = _mainPalette[4] = _mainPalette[5] = VGA_COLOR_TRANS(0x15);
+ _mainPalette[6] = _mainPalette[7] = _mainPalette[8] = VGA_COLOR_TRANS(0x2A);
+ _mainPalette[9] = _mainPalette[10] = _mainPalette[11] = VGA_COLOR_TRANS(0x3F);
+ _vm->_palette->setPalette(_mainPalette, 0, 4);
+}
+
+void Palette::setColorFlags(byte r, byte g, byte b) {
+ _colorFlags[0] = r;
+ _colorFlags[1] = g;
+ _colorFlags[2] = b;
+}
+
+void Palette::setColorValues(byte r, byte g, byte b) {
+ _colorValues[0] = r;
+ _colorValues[1] = g;
+ _colorValues[2] = b;
+}
+
+void Palette::lock() {
+ if (_rgbList[31] && !_lockFl)
+ error("Palette Lock - Unexpected values");
+
+ _lockFl = true;
+ _rgbList[31] = true;
+
+ for (int i = 0; i < 256; i++) {
+ if (_palFlags[i])
+ _palFlags[i] |= 0x80000000;
+ }
+}
+
+void Palette::unlock() {
+ if (!_lockFl)
+ return;
+
+ for (int i = 0; i < 256; i++)
+ _palFlags[i] &= 0x7FFFFFFF;
+
+ _rgbList[31] = false;
+ _lockFl = false;
+}
+
+void Palette::refreshSceneColors() {
+ int val = 18;
+ if (_vm->_game->_scene._cyclingActive)
+ val += _vm->_game->_scene._totalCycleColors;
+
+ setPalette(_mainPalette + (val * 3), val, 256 - val);
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/palette.h b/engines/mads/palette.h
new file mode 100644
index 0000000000..9b8b7146db
--- /dev/null
+++ b/engines/mads/palette.h
@@ -0,0 +1,323 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_PALETTE_H
+#define MADS_PALETTE_H
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+
+namespace MADS {
+
+class MADSEngine;
+
+#define PALETTE_USAGE_COUNT 4
+
+#define PALETTE_RESERVED_LOW_COUNT 18
+#define PALETTE_RESERVED_HIGH_COUNT 10
+
+#define PALETTE_COUNT 256
+#define PALETTE_SIZE (256 * 3)
+
+/**
+ * Palette mapping options
+ */
+enum {
+ PALFLAG_BACKGROUND = 0x8000, // Loading initial background
+ PALFLAG_RESERVED = 0x4000, // Enable mapping reserved colors
+ PALFLAG_ANY_TO_CLOSEST = 0x2000, // Any color can map to closest
+ PALFLAG_ALL_TO_CLOSEST = 0x1000, // Any colors that can map must map
+ PALFLAG_TOP_COLORS = 0x0800, // Allow mapping to high four colors
+ PALFLAG_DEFINE_RESERVED = 0x0400, // Define initial reserved color
+ PALFLAG_MASK = 0xfc00 // Mask for all the palette flags
+};
+
+struct PaletteCycle {
+ byte _colorCount;
+ byte _firstListColor;
+ byte _firstColorIndex;
+ byte _ticks;
+
+ PaletteCycle() { _colorCount = _firstListColor = _firstColorIndex = _ticks = 0; }
+};
+
+struct RGB6 {
+ byte r;
+ byte g;
+ byte b;
+ byte _palIndex;
+ byte _u2;
+ byte _flags;
+
+ /**
+ * Load an entry from a stream
+ */
+ void load(Common::SeekableReadStream *f);
+};
+
+class PaletteUsage {
+public:
+ struct UsageEntry {
+ uint16 _palIndex;
+ int _sortValue;
+
+ UsageEntry(int palIndex) { _palIndex = palIndex; _sortValue = -1; }
+ UsageEntry() { _palIndex = 0; _sortValue = 0; }
+ };
+ struct UsageRange {
+ byte _v1, _v2;
+
+ UsageRange(byte v1, byte v2) { _v1 = v1; _v2 = v2; }
+ };
+private:
+ MADSEngine *_vm;
+ Common::Array<UsageEntry> *_data;
+
+ int getGamePalFreeIndex(int *palIndex);
+
+ int rgbFactor(byte *palEntry, RGB6 &pal6);
+
+ Common::Array<UsageEntry> _nullUsage;
+public:
+ /**
+ * Constructor
+ */
+ PaletteUsage(MADSEngine *vm);
+
+ void load(Common::Array<UsageEntry> *data);
+
+ /**
+ * Returns whether the usage list is empty
+ */
+ bool empty() const { return _data == nullptr; }
+
+ uint16 &operator[](int index) { return (*_data)[index]._palIndex; }
+
+ /**
+ * Assigns the class to an empty usage array
+ */
+ void setEmpty() { _data = &_nullUsage; }
+
+ /**
+ * Gets key entries from the passed palette
+ * @param palette 6-bit per entry read in palette
+ */
+ void getKeyEntries(Common::Array<RGB6> &palette);
+
+ /**
+ * Prioritizes the palette index list based on the intensity of the
+ * RGB values of the palette entries that they refer to
+ */
+ void prioritize(Common::Array<RGB6> &palette);
+
+ int process(Common::Array<RGB6> &palette, uint flags);
+
+ void transform(Common::Array<RGB6> &palette);
+
+ void updateUsage(Common::Array<int> &usageList, int sceneUsageIndex);
+
+ void resetPalFlags(int idx);
+};
+
+class RGBList {
+private:
+ bool _data[32];
+public:
+ RGBList() { clear(); }
+
+ void clear();
+
+ void reset();
+
+ /**
+ * Copies the data from another instance
+ */
+ void copy(RGBList &src);
+
+ /**
+ * Scans for a free slot
+ */
+ int scan();
+
+ bool &operator[](int idx) { return _data[idx]; }
+};
+
+class Fader {
+public:
+ struct GreyEntry {
+ byte _intensity;
+ byte _mapColor;
+ uint16 _accum[3];
+ };
+private:
+ void mapToGreyRamp(byte palette[PALETTE_SIZE], int baseColor, int numColors,
+ int baseGrey, int numGreys, GreyEntry *map);
+
+ void getGreyValues(const byte palette[PALETTE_SIZE], byte greyList[PALETTE_COUNT],
+ int baseColor, int numColors);
+
+ /**
+ * Given a grey value list containing grey shades (0-63), creates a 64 byte
+ * grey table containing the number of grey values for each intensity
+ */
+ void greyPopularity(const byte greyList[PALETTE_COUNT], byte greyTable[64], int numColors);
+
+ /**
+ * Does an insertion sort of a given id/value array pair
+ */
+ void insertionSort(int size, byte *id, byte *value);
+protected:
+ MADSEngine *_vm;
+ byte _rgb64Map[PALETTE_COUNT];
+public:
+ bool _colorFlags[4];
+ int _colorValues[4];
+public:
+ /**
+ * Constructor
+ */
+ Fader(MADSEngine *vm);
+
+ /**
+ * Sets a new palette
+ */
+ void setPalette(const byte *colors, uint start, uint num);
+
+ /**
+ * Returns a subset of the currently loaded palette
+ */
+ void grabPalette(byte *colors, uint start, uint num);
+
+ /**
+ * Gets the entire palette at once
+ */
+ void getFullPalette(byte palette[PALETTE_SIZE]) {
+ grabPalette(&palette[0], 0, PALETTE_COUNT);
+ }
+
+ /**
+ * Sets the entire palette at once
+ */
+ void setFullPalette(byte palette[PALETTE_SIZE]) {
+ setPalette(&palette[0], 0, PALETTE_COUNT);
+ }
+
+ /**
+ * Calculates a merge/hash for a given palette entry
+ */
+ int rgbMerge(byte r, byte g, byte b);
+
+ /**
+ * Calculates a merge/hash for a given palette entry
+ */
+ int rgbMerge(RGB6 &palEntry);
+
+ /**
+ * Fades the given palette out to black or grey
+ */
+ void fadeOut(byte palette[PALETTE_SIZE], byte *paletteMap,
+ int baseColor, int numColors, int baseGrey, int numGreys,
+ int tickDelay, int steps);
+
+ /**
+ * Fade into the given palette
+ */
+ void fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE],
+ int baseColor, int numColors, int baseGrey, int numGreys,
+ int tickDelay, int steps);
+};
+
+class Palette : public Fader {
+private:
+ /**
+ * Initializes the first 16 palette indexes with the equivalent
+ * standard VGA palette
+ */
+ void initVGAPalette(byte *palette);
+public:
+ byte _mainPalette[PALETTE_SIZE];
+ byte _cyclingPalette[PALETTE_SIZE];
+ uint32 _palFlags[PALETTE_COUNT];
+ PaletteUsage _paletteUsage;
+ RGBList _rgbList;
+ bool _lockFl;
+ int _lowRange;
+ int _highRange;
+public:
+ /**
+ * Constructor
+ */
+ Palette(MADSEngine *vm);
+
+ /**
+ * Destructor
+ */
+ virtual ~Palette() {}
+
+ /**
+ * Set a palette entry
+ */
+ void setEntry(byte palIndex, byte r, byte g, byte b);
+
+ /**
+ * Returns the palette index in the palette that most closely matches the
+ * specified RGB pair
+ */
+ uint8 palIndexFromRgb(byte r, byte g, byte b, byte *paletteData = nullptr);
+
+ /**
+ * Sets a small set of system/core colors needed by the game
+ */
+ void setSystemPalette();
+
+ /**
+ * Update a range of an arbitrary palette
+ */
+ static void setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2);
+
+ /**
+ * Resets the game palette
+ */
+ void resetGamePalette(int lowRange, int highRange);
+
+ /**
+ * Initializes the main palette
+ */
+ void initPalette();
+
+ /**
+ * Set the first four palette entries with preset values
+ */
+ void setLowRange();
+
+ void setColorFlags(byte r, byte g, byte b);
+ void setColorValues(byte r, byte g, byte b);
+
+ void lock();
+ void unlock();
+
+ void refreshSceneColors();
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_PALETTE_H */
diff --git a/engines/mads/phantom/game_phantom.cpp b/engines/mads/phantom/game_phantom.cpp
new file mode 100644
index 0000000000..0b2531ef65
--- /dev/null
+++ b/engines/mads/phantom/game_phantom.cpp
@@ -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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "mads/mads.h"
+#include "mads/game.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/phantom/game_phantom.h"
+//#include "mads/nebular/dialogs_nebular.h"
+//#include "mads/nebular/globals_nebular.h"
+#include "mads/phantom/phantom_scenes.h"
+
+namespace MADS {
+
+namespace Phantom {
+
+GamePhantom::GamePhantom(MADSEngine *vm)
+ : Game(vm) {
+ _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+ _storyMode = STORYMODE_NAUGHTY;
+}
+
+void GamePhantom::startGame() {
+ _scene._priorSceneId = 0;
+ _scene._currentSceneId = -1;
+ _scene._nextSceneId = 101;
+
+ initializeGlobals();
+}
+
+void GamePhantom::initializeGlobals() {
+ _globals.reset();
+
+ warning("TODO: sub_316DA()");
+
+ _player._facing = FACING_NORTH;
+ _player._turnToFacing = FACING_NORTH;
+
+ /* Section #1 variables */
+ // TODO
+
+ /* Section #2 variables */
+ // TODO
+
+ /* Section #3 variables */
+ // TODO
+
+ /* Section #4 variables */
+ // TODO
+
+ /* Section #5 variables */
+ // TODO
+
+ /* Section #9 variables */
+ // TODO
+
+ Player::preloadSequences("RAL", 1);
+}
+
+void GamePhantom::setSectionHandler() {
+ delete _sectionHandler;
+
+ switch (_sectionNumber) {
+ case 1:
+ _sectionHandler = new Section1Handler(_vm);
+ break;
+ case 2:
+ _sectionHandler = new Section2Handler(_vm);
+ break;
+ case 3:
+ _sectionHandler = new Section3Handler(_vm);
+ break;
+ case 4:
+ _sectionHandler = new Section4Handler(_vm);
+ break;
+ case 5:
+ _sectionHandler = new Section5Handler(_vm);
+ break;
+ default:
+ break;
+ }
+}
+
+void GamePhantom::checkShowDialog() {
+ // TODO: Copied from Nebular
+ if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[5]) {
+ _player.releasePlayerSprites();
+ _vm->_dialogs->showDialog();
+ _vm->_dialogs->_pendingDialog = DIALOG_NONE;
+ }
+}
+
+void GamePhantom::doObjectAction() {
+ // TODO: Copied from Nebular
+ //Scene &scene = _scene;
+ MADSAction &action = _scene._action;
+ //Dialogs &dialogs = *_vm->_dialogs;
+ //int id;
+
+ action._inProgress = false;
+}
+
+void GamePhantom::unhandledAction() {
+ // TODO
+}
+
+void GamePhantom::step() {
+ if (_player._visible && _player._stepEnabled && !_player._moving &&
+ (_player._facing == _player._turnToFacing)) {
+
+ // TODO
+ }
+
+}
+
+void GamePhantom::synchronize(Common::Serializer &s, bool phase1) {
+ Game::synchronize(s, phase1);
+
+ // TODO: Copied from Nebular
+ if (!phase1) {
+ _globals.synchronize(s);
+ }
+}
+
+} // End of namespace Phantom
+
+} // End of namespace MADS
diff --git a/engines/mads/phantom/game_phantom.h b/engines/mads/phantom/game_phantom.h
new file mode 100644
index 0000000000..99cc2c1230
--- /dev/null
+++ b/engines/mads/phantom/game_phantom.h
@@ -0,0 +1,124 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_GAME_PHANTOM_H
+#define MADS_GAME_PHANTOM_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/globals.h"
+//#include "mads/nebular/globals_nebular.h"
+
+namespace MADS {
+
+namespace Phantom {
+
+// TODO: Adapt for Phantom's difficulty setting
+enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 };
+
+enum InventoryObject {
+ OBJ_NONE = -1,
+ OBJ_KEY = 0,
+ OBJ_LANTERN = 1,
+ OBJ_RED_FRAME = 2,
+ OBJ_SANDBAG = 3,
+ OBJ_YELLOW_FRAME = 4,
+ OBJ_FIRE_AXE = 5,
+ OBJ_SMALL_NOTE = 6,
+ OBJ_ROPE = 7,
+ OBJ_SWORD = 8,
+ OBJ_ENVELOPE = 9,
+ OBJ_TICKET = 10,
+ OBJ_PIECE_OF_PAPER = 11,
+ OBJ_PARCHMENT = 12,
+ OBJ_LETTER = 13,
+ OBJ_NOTICE = 14,
+ OBJ_BOOK = 15,
+ OBJ_CRUMPLED_NOTE = 16,
+ OBJ_BLUE_FRAME = 17,
+ OBJ_LARGE_NOTE = 18,
+ OBJ_GREEN_FRAME = 19,
+ OBJ_MUSIC_SCORE = 20,
+ OBJ_WEDDING_RING = 21,
+ OBJ_CABLE_HOOK = 22,
+ OBJ_ROPE_WITH_HOOK = 23,
+ OBJ_OAR = 24
+};
+
+// HACK: A stub for now, remove from here once it's implemented properly
+class PhantomGlobals : public Globals {
+public:
+ PhantomGlobals() {
+ resize(210); // Rex has 210 globals
+ }
+ virtual ~PhantomGlobals() {}
+};
+
+class GamePhantom : public Game {
+ friend class Game;
+protected:
+ GamePhantom(MADSEngine *vm);
+
+ virtual void startGame();
+
+ virtual void initializeGlobals();
+
+ virtual void setSectionHandler();
+
+ virtual void checkShowDialog();
+public:
+ PhantomGlobals _globals;
+ StoryMode _storyMode;
+
+ virtual Globals &globals() { return _globals; }
+
+ virtual void doObjectAction();
+
+ virtual void unhandledAction();
+
+ virtual void step();
+
+ virtual void synchronize(Common::Serializer &s, bool phase1);
+};
+
+
+class Section1Handler : public SectionHandler {
+public:
+ Section1Handler(MADSEngine *vm) : SectionHandler(vm) {}
+
+ // TODO: Properly implement handler methods
+ virtual void preLoadSection() {}
+ virtual void sectionPtr2() {}
+ virtual void postLoadSection() {}
+};
+
+// TODO: Properly implement handler classes
+typedef Section1Handler Section2Handler;
+typedef Section1Handler Section3Handler;
+typedef Section1Handler Section4Handler;
+typedef Section1Handler Section5Handler;
+
+} // End of namespace Nebular
+
+} // End of namespace MADS
+
+#endif /* MADS_GAME_PHANTOM_H */
diff --git a/engines/mads/phantom/phantom_scenes.cpp b/engines/mads/phantom/phantom_scenes.cpp
new file mode 100644
index 0000000000..7fd7ce642d
--- /dev/null
+++ b/engines/mads/phantom/phantom_scenes.cpp
@@ -0,0 +1,203 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "mads/mads.h"
+#include "mads/compression.h"
+#include "mads/resources.h"
+#include "mads/scene.h"
+#include "mads/phantom/game_phantom.h"
+#include "mads/phantom/phantom_scenes.h"
+
+namespace MADS {
+
+namespace Phantom {
+
+SceneLogic *SceneFactory::createScene(MADSEngine *vm) {
+ Scene &scene = vm->_game->_scene;
+
+ // TODO
+ //scene.addActiveVocab(NOUN_DROP);
+
+ switch (scene._nextSceneId) {
+ // Scene group #1 (theater, stage and dressing rooms)
+ case 101: // seats
+ return new DummyScene(vm); // TODO
+ case 102: // music stands
+ return new DummyScene(vm); // TODO
+ case 103: // below stage
+ return new DummyScene(vm); // TODO
+ case 104: // stage
+ return new DummyScene(vm); // TODO
+ case 105: // ground floor, storage room
+ return new DummyScene(vm); // TODO
+ case 106: // behind stage
+ return new DummyScene(vm); // TODO
+ case 107: // stage right wing
+ return new DummyScene(vm); // TODO
+ case 108: // stage left wing
+ return new DummyScene(vm); // TODO
+ case 109: // upper floor, staircase
+ return new DummyScene(vm); // TODO
+ case 110: // outside dressing rooms 1
+ return new DummyScene(vm); // TODO
+ case 111: // outside dressing rooms 2
+ return new DummyScene(vm); // TODO
+ case 112: // inside dressing room 1
+ return new DummyScene(vm); // TODO
+ case 113: // inside dressing room 2
+ return new DummyScene(vm); // TODO
+ case 114: // lower floor, storage room
+ return new DummyScene(vm); // TODO
+ case 150: // cutscene
+ return new DummyScene(vm); // TODO
+
+ // Scene group #2 (theater entrance, offices, balcony)
+ case 201: // entrance / ticket office
+ return new DummyScene(vm); // TODO
+ case 202: // outside offices / paintings room
+ return new DummyScene(vm); // TODO
+ case 203: // office
+ return new DummyScene(vm); // TODO
+ case 204: // library
+ return new DummyScene(vm); // TODO
+ case 205: // upper floor, outside balcony boxes
+ return new DummyScene(vm); // TODO
+ case 206: // balcony box #1
+ return new DummyScene(vm); // TODO
+ case 207: // balcony box #2
+ return new DummyScene(vm); // TODO
+ case 208: // stage and balcony view
+ return new DummyScene(vm); // TODO
+ case 250: // cutscene
+ return new DummyScene(vm); // TODO
+
+ // Scene group #3 (catwalks, chandelier, lake / catacombs entrance)
+ case 301: // catwalk #1 above stage
+ return new DummyScene(vm); // TODO
+ case 302: // catwalk #2 above stage
+ return new DummyScene(vm); // TODO
+ case 303: // above chandelier
+ return new DummyScene(vm); // TODO
+ case 304: // chandelier
+ return new DummyScene(vm); // TODO
+ case 305: // chandelier fight, phantom closeup
+ return new DummyScene(vm); // TODO
+ case 306: // chandelier #2
+ return new DummyScene(vm); // TODO
+ case 307: // catwalk #3 above stage
+ return new DummyScene(vm); // TODO
+ case 308: // hidden staircase behind balcony box
+ return new DummyScene(vm); // TODO
+ case 309: // lake and archway
+ return new DummyScene(vm); // TODO
+ case 310: // lake
+ return new DummyScene(vm); // TODO
+
+ // Scene group #4 (labyrinth)
+ case 401: // labyrinth room, 3 exits
+ return new DummyScene(vm); // TODO
+ case 403: // labyrinth room (big), 4 exits + 1 bricked door, left
+ return new DummyScene(vm); // TODO
+ case 404: // labyrinth room, 3 exits
+ return new DummyScene(vm); // TODO
+ case 406: // labyrinth room, 2 exits
+ return new DummyScene(vm); // TODO
+ case 407: // catacomb room / lake
+ return new DummyScene(vm); // TODO
+ case 408: // catacomb corridor
+ return new DummyScene(vm); // TODO
+ case 409: // catacomb room, door with switch panel
+ return new DummyScene(vm); // TODO
+ case 410: // skull switch panel
+ return new DummyScene(vm); // TODO
+ case 453: // Labyrinth room (big), 4 exits + 1 bricked door, right
+ return new DummyScene(vm); // TODO
+ case 456: // Labyrinth room, 2 exits
+ return new DummyScene(vm); // TODO
+
+ // Scene group #5 (Phantom's hideout)
+ case 501: // catacombs, outside phantom's hideout, lake and boat
+ return new DummyScene(vm); // TODO
+ case 502: // push panel trap
+ return new DummyScene(vm); // TODO
+ case 504: // Phantom's hideout, church organ
+ return new DummyScene(vm); // TODO
+ case 505: // Phantom's hideout, sarcophagus
+ return new DummyScene(vm); // TODO
+ case 506: // catacomb room with ramp
+ return new DummyScene(vm); // TODO
+
+ default:
+ error("Invalid scene %d called", scene._nextSceneId);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+PhantomScene::PhantomScene(MADSEngine *vm) : SceneLogic(vm),
+ _globals(static_cast<GamePhantom *>(vm->_game)->_globals),
+ _game(*static_cast<GamePhantom *>(vm->_game)),
+ _action(vm->_game->_scene._action) {
+}
+
+Common::String PhantomScene::formAnimName(char sepChar, int suffixNum) {
+ return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum,
+ EXT_NONE, "");
+}
+
+/*------------------------------------------------------------------------*/
+
+void SceneInfoPhantom::loadCodes(MSurface &depthSurface, int variant) {
+ Common::String ext = Common::String::format(".WW%d", variant);
+ File f(Resources::formatName(RESPREFIX_RM, _sceneId, ext));
+ MadsPack codesPack(&f);
+ Common::SeekableReadStream *stream = codesPack.getItemStream(0);
+
+ loadCodes(depthSurface, stream);
+
+ delete stream;
+ f.close();
+}
+
+void SceneInfoPhantom::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
+ byte *destP = depthSurface.getData();
+ byte *walkMap = new byte[stream->size()];
+ stream->read(walkMap, stream->size());
+
+ for (int y = 0; y < 156; ++y) {
+ for (int x = 0; x < 320; ++x) {
+ int offset = x + (y * 320);
+ if ((walkMap[offset / 8] << (offset % 8)) & 0x80)
+ *destP++ = 1; // walkable
+ else
+ *destP++ = 0;
+ }
+ }
+
+ delete[] walkMap;
+}
+
+} // End of namespace Phantom
+
+} // End of namespace MADS
diff --git a/engines/mads/phantom/phantom_scenes.h b/engines/mads/phantom/phantom_scenes.h
new file mode 100644
index 0000000000..cd295a28b6
--- /dev/null
+++ b/engines/mads/phantom/phantom_scenes.h
@@ -0,0 +1,521 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_PHANTOM_SCENES_H
+#define MADS_PHANTOM_SCENES_H
+
+#include "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/scene.h"
+#include "mads/phantom/game_phantom.h"
+//#include "mads/phantom/globals_phantom.h"
+
+
+namespace MADS {
+
+namespace Phantom {
+
+enum Noun {
+ NOUN_GAME = 0x1,
+ NOUN_QSAVE = 0x2,
+ NOUN_LOOK = 0x3,
+ NOUN_TAKE = 0x4,
+ NOUN_PUSH = 0x5,
+ NOUN_OPEN = 0x6,
+ NOUN_PUT = 0x7,
+ NOUN_TALK_TO = 0x8,
+ NOUN_GIVE = 0x9,
+ NOUN_PULL = 0xA,
+ NOUN_CLOSE = 0xB,
+ NOUN_THROW = 0xC,
+ NOUN_WALK_TO = 0xD,
+ NOUN_ = 0xE,
+ NOUN_IN_ONE = 0xF,
+ NOUN_IN_TWO = 0x10,
+ NOUN_ACT_CURTAIN = 0x11,
+ NOUN_AISLE = 0x12,
+ NOUN_APRON = 0x13,
+ NOUN_ATTACK = 0x14,
+ NOUN_BACKSTAGE = 0x15,
+ NOUN_BEAR_PROP = 0x16,
+ NOUN_BLUE_FRAME = 0x17,
+ NOUN_BOOK = 0x18,
+ NOUN_BUST = 0x19,
+ NOUN_CABLE = 0x1A,
+ NOUN_CARPET = 0x1B,
+ NOUN_CARTON = 0x1C,
+ NOUN_CARTONS = 0x1D,
+ NOUN_CEILING = 0x1E,
+ NOUN_CHAIR = 0x1F,
+ NOUN_CIRCULAR_STAIRCASE = 0x20,
+ NOUN_CLIMB_DOWN = 0x21,
+ NOUN_CLIMB_INTO = 0x22,
+ NOUN_CLIMB_THROUGH = 0x23,
+ NOUN_COLUMN_PROP = 0x24,
+ NOUN_CONDUCTORS_STAND = 0x25,
+ NOUN_CORRIDOR = 0x26,
+ NOUN_COUCH = 0x27,
+ NOUN_COUNTERWEIGHT_SYSTEM = 0x28,
+ NOUN_CRATE = 0x29,
+ NOUN_CRATES = 0x2A,
+ NOUN_CRUMPLED_NOTE = 0x2B,
+ NOUN_CYCLORAMA = 0x2C,
+ NOUN_CYLINDER = 0x2D,
+ NOUN_DOOR = 0x2E,
+ NOUN_DRESSING_ROOM_DOOR = 0x2F,
+ NOUN_DRESSING_SCREEN = 0x30,
+ NOUN_DRESSING_TABLE = 0x31,
+ NOUN_ELEPHANT_PROP = 0x32,
+ NOUN_ENVELOPE = 0x33,
+ NOUN_EXIT = 0x34,
+ NOUN_EXIT_DOWN = 0x35,
+ NOUN_EXIT_SIGN = 0x36,
+ NOUN_EXIT_TO = 0x37,
+ NOUN_EXIT_TO_BACKSTAGE = 0x38,
+ NOUN_EXIT_TO_CELLAR = 0x39,
+ NOUN_EXIT_TO_CORRIDOR = 0x3A,
+ NOUN_EXIT_TO_DRESSING_RMS = 0x3B,
+ NOUN_EXIT_TO_LEFT_WING = 0x3C,
+ NOUN_EXIT_TO_PIT = 0x3D,
+ NOUN_EXIT_TO_RIGHT_WING = 0x3E,
+ NOUN_EXIT_TO_STAGE = 0x3F,
+ NOUN_EXIT_TO_STAIRWELL = 0x40,
+ NOUN_EXIT_TO_TRAP_ROOM = 0x41,
+ NOUN_EXIT_UP = 0x42,
+ NOUN_EXPOSED_BRICK = 0x43,
+ NOUN_FAN = 0x44,
+ NOUN_FIRE_AXE = 0x45,
+ NOUN_FL = 0x46,
+ NOUN_FLAT = 0x47,
+ NOUN_FLATS = 0x48,
+ NOUN_FLOOR = 0x49,
+ NOUN_FOLDING_CHAIRS = 0x4A,
+ NOUN_GARBAGE_CAN = 0x4B,
+ NOUN_GRAFFITI = 0x4C,
+ NOUN_GREEN_FRAME = 0x4D,
+ NOUN_HEMP = 0x4E,
+ NOUN_HOLE = 0x4F,
+ NOUN_HOUSE = 0x50,
+ NOUN_IN_ONE2 = 0x51,
+ NOUN_IN_TWO2 = 0x52,
+ NOUN_JUMP_INTO = 0x53,
+ NOUN_JUNK = 0x54,
+ NOUN_KEY = 0x55,
+ NOUN_LAMP = 0x56,
+ NOUN_LANTERN = 0x57,
+ NOUN_LARGE_NOTE = 0x58,
+ NOUN_LASSO = 0x59,
+ NOUN_LEG = 0x5A,
+ NOUN_LETTER = 0x5B,
+ NOUN_LIGHT_FIXTURE = 0x5C,
+ NOUN_LOCK = 0x5D,
+ NOUN_LOCKING_RAIL = 0x5E,
+ NOUN_LOCKRAIL = 0x5F,
+ NOUN_LOOK_AT = 0x60,
+ NOUN_LOOK_THROUGH = 0x61,
+ NOUN_MANNEQUINS = 0x62,
+ NOUN_MIRROR = 0x63,
+ NOUN_MUMMY_PROP = 0x64,
+ NOUN_MURAL = 0x65,
+ NOUN_MUSIC_SCORE = 0x66,
+ NOUN_MUSIC_STAND = 0x67,
+ NOUN_MUSIC_STANDS = 0x68,
+ NOUN_NOTHING = 0x69,
+ NOUN_NOTICE = 0x6A,
+ NOUN_ORCHESTRA_DOOR = 0x6B,
+ NOUN_ORCHESTRA_PIT = 0x6C,
+ NOUN_PAINTING = 0x6D,
+ NOUN_PARCHMENT = 0x6E,
+ NOUN_PIECE_OF_PAPER = 0x6F,
+ NOUN_PIPE = 0x70,
+ NOUN_PIT = 0x71,
+ NOUN_PLANT = 0x72,
+ NOUN_POSTER = 0x73,
+ NOUN_PROMPTERS_BOX = 0x74,
+ NOUN_PROP_TABLE = 0x75,
+ NOUN_PROPS = 0x76,
+ NOUN_PROSCENIUM_ARCH = 0x77,
+ NOUN_PURCHASE_LINES = 0x78,
+ NOUN_RAILING = 0x79,
+ NOUN_READ = 0x7A,
+ NOUN_RED_FRAME = 0x7B,
+ NOUN_REMOVE = 0x7C,
+ NOUN_ROPE = 0x7D,
+ NOUN_RUG = 0x7E,
+ NOUN_SANDBAG = 0x7F,
+ NOUN_SCAFFOLDING = 0x80,
+ NOUN_SEATS = 0x81,
+ NOUN_SIDE_WALL = 0x82,
+ NOUN_SMALL_NOTE = 0x83,
+ NOUN_STAGE = 0x84,
+ NOUN_STAGE_EXIT = 0x85,
+ NOUN_STAGE_LEFT = 0x86,
+ NOUN_STAGE_RIGHT = 0x87,
+ NOUN_STAGEMANAGERS_POST = 0x88,
+ NOUN_STAIR_UNIT = 0x89,
+ NOUN_STAIRCASE = 0x8A,
+ NOUN_STAIRWELL = 0x8B,
+ NOUN_STOOL = 0x8C,
+ NOUN_STRIKE = 0x8D,
+ NOUN_SWORD = 0x8E,
+ NOUN_TABLE = 0x8F,
+ NOUN_THE_HOUSE = 0x90,
+ NOUN_THUNDER_MACHINE = 0x91,
+ NOUN_TICKET = 0x92,
+ NOUN_TRAP_CEILING = 0x93,
+ NOUN_TRAP_DOOR = 0x94,
+ NOUN_TURN_OFF = 0x95,
+ NOUN_TURN_ON = 0x96,
+ NOUN_UNLOCK = 0x97,
+ NOUN_URN = 0x98,
+ NOUN_WALK_ACROSS = 0x99,
+ NOUN_WALK_DOWN = 0x9A,
+ NOUN_WALK_THROUGH = 0x9B,
+ NOUN_WALK_UP = 0x9C,
+ NOUN_WALL = 0x9D,
+ NOUN_WARDROBE = 0x9E,
+ NOUN_WASTE_BASKET = 0x9F,
+ NOUN_WATER_PIPE = 0xA0,
+ NOUN_WEAR = 0xA1,
+ NOUN_WEDDING_RING = 0xA2,
+ NOUN_YELLOW_FRAME = 0xA3,
+ NOUN_PROP = 0xA4,
+ NOUN_CLIMB_UP = 0xA5,
+ NOUN_WALK_ONTO = 0xA6,
+ NOUN_WALK = 0xA7,
+ NOUN_LEFT_DOOR = 0xA8,
+ NOUN_RIGHT_DOOR = 0xA9,
+ NOUN_DOOR_TO_PIT = 0xAA,
+ NOUN_HEADPHONES = 0xAB,
+ NOUN_BOXES = 0xAC,
+ NOUN_MUG = 0xAD,
+ NOUN_DINETTE_SET = 0xAE,
+ NOUN_BOX = 0xAF,
+ NOUN_CASES = 0xB0,
+ NOUN_TRASH_BUCKET = 0xB1,
+ NOUN_CORK_BOARD = 0xB2,
+ NOUN_HEADSET = 0xB3,
+ NOUN_GRAND_FOYER = 0xB4,
+ NOUN_BACK_WALL = 0xB5,
+ NOUN_BALLET_BAR = 0xB6,
+ NOUN_THROW_RUGS = 0xB7,
+ NOUN_COSTUME_RACK = 0xB8,
+ NOUN_COAT_RACK = 0xB9,
+ NOUN_PAINTINGS = 0xBA,
+ NOUN_UMBRELLA = 0xBB,
+ NOUN_SHELF = 0xBC,
+ NOUN_CONTAINER = 0xBD,
+ NOUN_TORN_POSTER = 0xBE,
+ NOUN_REVIEW = 0xBF,
+ NOUN_REVIEWS = 0xC0,
+ NOUN_STAGE_RIGHT_WING = 0xC1,
+ NOUN_STAGE_LEFT_WING = 0xC2,
+ NOUN_PEDESTAL = 0xC3,
+ NOUN_PLANT_PROP = 0xC4,
+ NOUN_STATUE = 0xC5,
+ NOUN_BATTEN = 0xC6,
+ NOUN_BIG_PROP = 0xC7,
+ NOUN_VENTILATION_DUCT = 0xC8,
+ NOUN_CHANDELIER = 0xC9,
+ NOUN_BARRIER = 0xCA,
+ NOUN_PLACARD = 0xCB,
+ NOUN_TICKET_WINDOW = 0xCC,
+ NOUN_ARCHWAY = 0xCD,
+ NOUN_COLUMN = 0xCE,
+ NOUN_RAIL = 0xCF,
+ NOUN_SEAT = 0xD0,
+ NOUN_LOGE_CORRIDOR = 0xD1,
+ NOUN_HOUSE_LIGHT = 0xD2,
+ NOUN_FLOV = 0xD3,
+ NOUN_LEFT_COLUMN = 0xD4,
+ NOUN_RIGHT_COLUMN = 0xD5,
+ NOUN_BOOKCASE = 0xD6,
+ NOUN_DOORWAY = 0xD7,
+ NOUN_COMFY_CHAIR = 0xD8,
+ NOUN_DESK = 0xD9,
+ NOUN_MANAGERS_CHAIR = 0xDA,
+ NOUN_DESK_LAMP = 0xDB,
+ NOUN_WINDOW = 0xDC,
+ NOUN_SHEERS = 0xDD,
+ NOUN_TAPESTRY = 0xDE,
+ NOUN_OVERDOOR_MEDALLION = 0xDF,
+ NOUN_LATTICEWORK = 0xE0,
+ NOUN_DECORATIVE_MOLDING = 0xE1,
+ NOUN_LEFT_DOORWAY = 0xE2,
+ NOUN_LEFT_ARCHWAY = 0xE3,
+ NOUN_RIGHT_DOORWAY = 0xE4,
+ NOUN_RIGHT_ARCHWAY = 0xE5,
+ NOUN_SOFA = 0xE6,
+ NOUN_END_TABLE = 0xE7,
+ NOUN_COFFEE_TABLE = 0xE8,
+ NOUN_DECORATIVE_VASE = 0xE9,
+ NOUN_MARBLE_COLUMN = 0xEA,
+ NOUN_BOX_FIVE = 0xEB,
+ NOUN_ENTER = 0xEC,
+ NOUN_BOX_SIX = 0xED,
+ NOUN_BOX_SEVEN = 0xEE,
+ NOUN_BOX_EIGHT = 0xEF,
+ NOUN_BOX_NINE = 0xF0,
+ NOUN_STEP = 0xF1,
+ NOUN_PANEL = 0xF2,
+ NOUN_WALK_BEHIND = 0xF3,
+ NOUN_MIDDLE_DOORWAY = 0xF4,
+ NOUN_LIGHT = 0xF5,
+ NOUN_CANDLE = 0xF6,
+ NOUN_CASE = 0xF7,
+ NOUN_HANDLE = 0xF8,
+ NOUN_AXE = 0xF9,
+ NOUN_DOOR_CHUNKS = 0xFA,
+ NOUN_FLO = 0xFB,
+ NOUN_BULLETIN_BOARD = 0xFC,
+ NOUN_JULIE = 0xFD,
+ NOUN_GLASS_CASE = 0xFE,
+ NOUN_KEYHOLE = 0xFF,
+ NOUN_MIDDLE_DOOR = 0x100,
+ NOUN_DRESSING_GOWN = 0x101,
+ NOUN_MONSIEUR_BRIE = 0x102,
+ NOUN_CATWALK = 0x103,
+ NOUN_GRID = 0x104,
+ NOUN_GIRDER = 0x105,
+ NOUN_GRIDWORK = 0x106,
+ NOUN_DUCTWORK = 0x107,
+ NOUN_OPENING = 0x108,
+ NOUN_DOME = 0x109,
+ NOUN_ALCOVE = 0x10A,
+ NOUN_CHRISTINE_DAAE = 0x10B,
+ NOUN_CHRISTINE = 0x10C,
+ NOUN_WOMAN = 0x10D,
+ NOUN_PROMPTERS_STAND = 0x10E,
+ NOUN_SUPPORT = 0x10F,
+ NOUN_OTHER_CATWALK = 0x110,
+ NOUN_SLOT = 0x111,
+ NOUN_BEAM_POSITION = 0x112,
+ NOUN_LIGHTING_INSTRUMENT = 0x113,
+ NOUN_TARP = 0x114,
+ NOUN_FACE = 0x115,
+ NOUN_CATWALK_OVER_HOUSE = 0x116,
+ NOUN_STAIRCASE_POST = 0x117,
+ NOUN_JACQUES = 0x118,
+ NOUN_GENTLEMAN = 0x119,
+ NOUN_BODY = 0x11A,
+ NOUN_HOLLOW_COLUMN = 0x11B,
+ NOUN_UPPER_LEVEL = 0x11C,
+ NOUN_MIDDLE_LEVEL = 0x11D,
+ NOUN_LOWER_LEVEL = 0x11E,
+ NOUN_LADDER = 0x11F,
+ NOUN_CLIMB = 0x120,
+ NOUN_CHANDELIER_TRAP = 0x121,
+ NOUN_PIECE_OF_WOOD = 0x122,
+ NOUN_CUT_HEMP = 0x123,
+ NOUN_STONE_WALL = 0x124,
+ NOUN_LAKE = 0x125,
+ NOUN_STONE_COLUMN = 0x126,
+ NOUN_EXIT_THROUGH = 0x127,
+ NOUN_STONE_FLOOR = 0x128,
+ NOUN_STONE_ARCHWAY = 0x129,
+ NOUN_CHARLES = 0x12A,
+ NOUN_SWITCH = 0x12B,
+ NOUN_PROMPTERS_SEAT = 0x12C,
+ NOUN_LEVER = 0x12D,
+ NOUN_MONSIEUR_RICHARD = 0x12E,
+ NOUN_JULIE2 = 0x12F,
+ NOUN_CABLE_HOOK = 0x130,
+ NOUN_ATTACH = 0x131,
+ NOUN_ROPE_WITH_HOOK = 0x132,
+ NOUN_GRAPPLE = 0x133,
+ NOUN_OAR = 0x134,
+ NOUN_ORGAN = 0x135,
+ NOUN_SIT_AT = 0x136,
+ NOUN_ORGAN_BENCH = 0x137,
+ NOUN_SIT_ON = 0x138,
+ NOUN_LARGE_CHAIR = 0x139,
+ NOUN_SIT_IN = 0x13A,
+ NOUN_SARCOPHAGUS = 0x13B,
+ NOUN_SKULL = 0x13C,
+ NOUN_SKULLS = 0x13D,
+ NOUN_TOTEM = 0x13E,
+ NOUN_POLE = 0x13F,
+ NOUN_CURTAIN = 0x140,
+ NOUN_TORCH = 0x141,
+ NOUN_RAMP = 0x142,
+ NOUN_MADAME_GIRY = 0x143,
+ NOUN_PANELS = 0x144,
+ NOUN_MORE_CATACOMBS = 0x145,
+ NOUN_BLOCKED_ARCHWAY = 0x146,
+ NOUN_GRATE = 0x147,
+ NOUN_CATACOMBS = 0x148,
+ NOUN_TICKET_SELLER = 0x149,
+ NOUN_USHER = 0x14A,
+ NOUN_UNLUCKY_ADVENTURER = 0x14B,
+ NOUN_SWITCH_PANEL = 0x14C,
+ NOUN_SKULL_SWITCH = 0x14D,
+ NOUN_TOGGLE = 0x14E,
+ NOUN_CATACOMB_ROOM = 0x14F,
+ NOUN_BOX_TEN = 0x150,
+ NOUN_FOYER = 0x151,
+ NOUN_WALK_DOWN_STAIRCASE = 0x152,
+ NOUN_WALK_DOWN_STAIRS_TO = 0x153,
+ NOUN_HAT_RACK = 0x154,
+ NOUN_VASE = 0x155,
+ NOUN_CLOTHES_DUMMY = 0x156,
+ NOUN_NOTICES = 0x157,
+ NOUN_ARCHWAY_TO_NORTH = 0x158,
+ NOUN_ARCHWAY_TO_WEST = 0x159,
+ NOUN_ARCHWAY_TO_EAST = 0x15A,
+ NOUN_GATE = 0x15B,
+ NOUN_NEST = 0x15C,
+ NOUN_POT = 0x15D,
+ NOUN_PUDDLE = 0x15E,
+ NOUN_WEB = 0x15F,
+ NOUN_PLANK = 0x160,
+ NOUN_BLOCK = 0x161,
+ NOUN_RATS_NEST = 0x162,
+ NOUN_BROKEN_POT = 0x163,
+ NOUN_STONE = 0x164,
+ NOUN_DRAIN = 0x165,
+ NOUN_FATE = 0x166,
+ NOUN_SKULL_SWITCH_1 = 0x167,
+ NOUN_SKULL_SWITCH_2 = 0x168,
+ NOUN_SKULL_SWITCH_3 = 0x169,
+ NOUN_SKULL_SWITCH_4 = 0x16A,
+ NOUN_SKULL_SWITCH_5 = 0x16B,
+ NOUN_SKULL_SWITCH_6 = 0x16C,
+ NOUN_SKULL_SWITCH_7 = 0x16D,
+ NOUN_SKULL_SWITCH_8 = 0x16E,
+ NOUN_SKULL_SWITCH_9 = 0x16F,
+ NOUN_SKULL_SWITCH_10 = 0x170,
+ NOUN_SKULL_SWITCH_11 = 0x171,
+ NOUN_SKULL_SWITCH_12 = 0x172,
+ NOUN_SKULL_SWITCH_13 = 0x173,
+ NOUN_SKULL_SWITCH_14 = 0x174,
+ NOUN_SKULL_SWITCH_15 = 0x175,
+ NOUN_SKULL_SWITCH_16 = 0x176,
+ NOUN_SKULL_SWITCH_17 = 0x177,
+ NOUN_SKULL_SWITCH_18 = 0x178,
+ NOUN_SKULL_SWITCH_19 = 0x179,
+ NOUN_SKULL_SWITCH_20 = 0x17A,
+ NOUN_SKULL_SWITCH_21 = 0x17B,
+ NOUN_SKULL_SWITCH_22 = 0x17C,
+ NOUN_SKULL_SWITCH_23 = 0x17D,
+ NOUN_SKULL_SWITCH_24 = 0x17E,
+ NOUN_SKULL_SWITCH_25 = 0x17F,
+ NOUN_SKULL_SWITCH_26 = 0x180,
+ NOUN_EDGAR_DEGAS = 0x181,
+ NOUN_CHANDELIER_CABLE = 0x182,
+ NOUN_COB_WEB = 0x183,
+ NOUN_SKULL_FACE = 0x184,
+ NOUN_BOAT = 0x185,
+ NOUN_HOOK = 0x186,
+ NOUN_AROUND = 0x187,
+ NOUN_CANE = 0x188,
+ NOUN_MASK = 0x189,
+ NOUN_COVER = 0x18A,
+ NOUN_PADLOCK = 0x18B,
+ NOUN_LID = 0x18C,
+ NOUN_COBWEB = 0x18D,
+ NOUN_PHANTOM = 0x18E,
+ NOUN_PAPER = 0x18F
+};
+
+class SceneFactory {
+public:
+ static SceneLogic *createScene(MADSEngine *vm);
+};
+
+/**
+ * Specialized base class for Dragonsphere game scenes
+ */
+class PhantomScene : public SceneLogic {
+protected:
+ PhantomGlobals &_globals;
+ GamePhantom &_game;
+ MADSAction &_action;
+
+ /**
+ * Forms an animation resource name
+ */
+ Common::String formAnimName(char sepChar, int suffixNum);
+
+ /**
+ * Plays appropriate sound for entering varous rooms
+ */
+ void lowRoomsEntrySound();
+public:
+ /**
+ * Constructor
+ */
+ PhantomScene(MADSEngine *vm);
+
+ void sub7178C();
+};
+
+class SceneInfoPhantom : public SceneInfo {
+ friend class SceneInfo;
+protected:
+ virtual void loadCodes(MSurface &depthSurface, int variant);
+
+ virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream);
+
+ /**
+ * Constructor
+ */
+ SceneInfoPhantom(MADSEngine *vm) : SceneInfo(vm) {}
+};
+
+// TODO: Temporary, remove once implemented properly
+class Scene1xx : public PhantomScene {
+protected:
+ /**
+ * Plays an appropriate sound when entering a scene
+ */
+ void sceneEntrySound() {}
+
+ /**
+ *Sets the AA file to use for the scene
+ */
+ void setAAName() {}
+
+ /**
+ * Updates the prefix used for getting player sprites for the scene
+ */
+ void setPlayerSpritesPrefix() {}
+public:
+ Scene1xx(MADSEngine *vm) : PhantomScene(vm) {}
+};
+
+// TODO: Temporary, remove once implemented properly
+class DummyScene : public PhantomScene {
+public:
+ DummyScene(MADSEngine *vm) : PhantomScene(vm) {
+ warning("Unimplemented scene");
+ }
+
+ virtual void setup() {}
+ virtual void enter() {}
+ virtual void actions() {}
+};
+
+} // End of namespace Phantom
+
+} // End of namespace MADS
+
+#endif /* MADS_PHANTOM_SCENES_H */
diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp
new file mode 100644
index 0000000000..bde313af8d
--- /dev/null
+++ b/engines/mads/player.cpp
@@ -0,0 +1,794 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/player.h"
+
+namespace MADS {
+
+#define PLAYER_SEQ_INDEX -2
+
+const int Player::_directionListIndexes[32] = {
+ 0, 7, 4, 3, 6, 0, 2, 5, 0, 1, 9, 4, 1, 2, 7, 9, 3, 8, 9, 6, 7, 2, 3, 6, 1, 7, 9, 4, 7, 8, 0, 0
+};
+
+Player::Player(MADSEngine *vm)
+ : _vm(vm) {
+ _action = nullptr;
+ _facing = FACING_NORTH;
+ _turnToFacing = FACING_NORTH;
+ _targetFacing = FACING_NORTH;
+ _prepareWalkFacing = FACING_NONE;
+ _mirror = false;
+ _spritesLoaded = false;
+ _spritesStart = 0;
+ _spritesIdx = 0;
+ _numSprites = 0;
+ _stepEnabled = false;
+ _visible = false;
+ _priorVisible = false;
+ _needToWalk = false;
+ _readyToWalk = false;
+ _beenVisible = false;
+ _loadsFirst = false;
+ _loadedFirst = false;
+ _walkAnywhere = false;
+ _special = 0;
+ _ticksAmount = 0;
+ _priorTimer = 0;
+ _trigger = 0;
+ _scalingVelocity = false;
+ _spritesChanged = false;
+ _forceRefresh = false;
+ _highSprites = false;
+ _currentDepth = 0;
+ _currentScale = 0;
+ _frameNumber = 0;
+ _centerOfGravity = 0;
+ _frameCount = 0;
+ _velocity = 0;
+ _upcomingTrigger = 0;
+ _trigger = 0;
+ _frameListIndex = 0;
+ _stopWalkerIndex = 0;
+ _totalDistance = 0;
+ _distAccum = 0;
+ _pixelAccum = 0;
+ _deltaDistance = 0;
+ _xDirection = 0;
+ _yDirection = 0;
+ _moving = false;
+ _walkOffScreen = 0;
+ _walkOffScreenSceneId = -1;
+
+ Common::fill(&_stopWalkerList[0], &_stopWalkerList[12], 0);
+ Common::fill(&_stopWalkerTrigger[0], &_stopWalkerTrigger[12], 0);
+ Common::fill(&_spriteSetsPresent[0], &_spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT], false);
+}
+
+void Player::cancelWalk() {
+ Scene &scene = _vm->_game->_scene;
+ _action = &scene._action;
+ _targetPos = _playerPos;
+ _targetFacing = FACING_NONE;
+ _turnToFacing = _facing;
+ _moving = false;
+ _walkOffScreen = _walkOffScreenSceneId = 0;
+ scene._rails.resetRoute();
+ _walkAnywhere = false;
+
+ _needToWalk = false;
+ _readyToWalk = false;
+}
+
+bool Player::loadSprites(const Common::String &prefix) {
+ Common::String suffixList = "89632741";
+
+ Common::String newPrefix;
+ if (prefix.empty()) {
+ newPrefix = _spritesPrefix;
+ } else {
+ _spritesPrefix = prefix;
+ newPrefix = prefix;
+ }
+
+ _numSprites = 0;
+ if (!_spritesPrefix.empty()) {
+ for (int fileIndex = 0; fileIndex < PLAYER_SPRITES_FILE_COUNT; ++fileIndex) {
+ Common::String setName = Common::String::format("*%s_%c.SS",
+ newPrefix.c_str(), suffixList[fileIndex]);
+ if (fileIndex >= 5)
+ _highSprites = true;
+
+ _spriteSetsPresent[fileIndex] = true;
+
+ int setIndex = -1;
+ if (Common::File::exists(setName)) {
+ setIndex = _vm->_game->_scene._sprites.addSprites(setName, 4);
+ ++_numSprites;
+ } else if (fileIndex < 5) {
+ _highSprites = false;
+ return true;
+ } else {
+ _spriteSetsPresent[fileIndex] = false;
+ }
+
+ if (fileIndex == 0)
+ _spritesStart = setIndex;
+ }
+
+ _spritesLoaded = true;
+ _spritesChanged = false;
+ } else {
+ Common::fill(&_spriteSetsPresent[0], &_spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT], false);
+ _visible = false;
+ }
+
+ _highSprites = false;
+ return false;
+}
+
+void Player::setFinalFacing() {
+ if (_targetFacing != FACING_NONE)
+ _turnToFacing = _targetFacing;
+}
+
+void Player::changeFacing() {
+ int dirIndex = 0, dirIndex2 = 0;
+ int newDir = 0, newDir2 = 0;
+
+ if (_facing != _turnToFacing) {
+ // Find the index for the given direction in the player direction list
+ int tempDir = _facing;
+ do {
+ ++dirIndex;
+ newDir += tempDir;
+ tempDir = _directionListIndexes[tempDir + 10];
+ } while (tempDir != _turnToFacing);
+ }
+
+
+ if (_facing != _turnToFacing) {
+ // Find the index for the given direction in the player direction list
+ int tempDir = _facing;
+ do {
+ ++dirIndex2;
+ newDir2 += tempDir;
+ tempDir = _directionListIndexes[tempDir + 20];
+ } while (tempDir != _turnToFacing);
+ }
+
+ int diff = dirIndex - dirIndex2;
+ if (diff == 0)
+ diff = newDir - newDir2;
+
+ _facing = (diff >= 0) ? (Facing)_directionListIndexes[_facing + 20] :
+ (Facing)_directionListIndexes[_facing + 10];
+ selectSeries();
+
+ if ((_facing == _turnToFacing) && !_moving)
+ updateFrame();
+
+ _priorTimer += 1;
+}
+
+void Player::cancelCommand() {
+ cancelWalk();
+ _action->_inProgress = false;
+}
+
+void Player::selectSeries() {
+ Scene &scene = _vm->_game->_scene;
+
+ clearStopList();
+ _mirror = false;
+
+ _spritesIdx = _directionListIndexes[_facing];
+ if (!_spriteSetsPresent[_spritesIdx]) {
+ // Direction isn't present, so use alternate direction, with entries flipped
+ _spritesIdx -= 4;
+ _mirror = true;
+ }
+
+ // If the user isn't to be present (such as for a cutscene), exit immediately
+ // WORKAROUND: Original didn't do a secondary check for the sprite set being
+ // present, but it's needed to prevent invalid reads during cutscenes
+ if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesIdx])
+ return;
+
+ SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx];
+ assert(spriteSet._charInfo);
+ _velocity = MAX(spriteSet._charInfo->_velocity, 100);
+ setBaseFrameRate();
+
+ _frameCount = spriteSet._charInfo->_totalFrames;
+ if (_frameCount == 0)
+ _frameCount = spriteSet.getCount();
+
+ _centerOfGravity = spriteSet._charInfo->_centerOfGravity;
+
+ if ((_frameNumber <= 0) || (_frameNumber > _frameCount))
+ _frameNumber = 1;
+
+ _forceRefresh = true;
+}
+
+void Player::updateFrame() {
+ // WORKAROUND: Prevent character info being referenced when not present
+ if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesStart + _spritesIdx])
+ return;
+
+ Scene &scene = _vm->_game->_scene;
+ SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx];
+ assert(spriteSet._charInfo);
+
+ if (!spriteSet._charInfo->_numEntries) {
+ _frameNumber = 1;
+ } else {
+ _frameListIndex = _stopWalkerList[_stopWalkerIndex];
+
+ if (!_visible) {
+ _upcomingTrigger = 0;
+ } else {
+ _upcomingTrigger = _stopWalkerTrigger[_stopWalkerIndex];
+
+ if (_stopWalkerIndex > 0)
+ --_stopWalkerIndex;
+ }
+
+ // Set the player frame number
+ int listIndex = ABS(_frameListIndex);
+ _frameNumber = (_frameListIndex >= 0) ? spriteSet._charInfo->_startFrames[listIndex] :
+ spriteSet._charInfo->_stopFrames[listIndex];
+
+ // Set next waiting period in ticks
+ if (listIndex == 0) {
+ setBaseFrameRate();
+ } else {
+ _ticksAmount = spriteSet._charInfo->_ticksList[listIndex];
+ }
+ }
+
+ _forceRefresh = true;
+}
+
+void Player::update() {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_forceRefresh || (_visible != _priorVisible)) {
+ int slotIndex = getSpriteSlot();
+ if (slotIndex >= 0)
+ scene._spriteSlots[slotIndex]._flags = IMG_ERASE;
+
+ int newDepth = 1;
+ int yp = MIN(_playerPos.y, (int16)(MADS_SCENE_HEIGHT - 1));
+
+ for (int idx = 1; idx < 15; ++idx) {
+ if (scene._sceneInfo->_depthList[newDepth] >= yp)
+ newDepth = idx + 1;
+ }
+ _currentDepth = newDepth;
+
+ // Get the scale
+ int newScale = getScale(_playerPos.y);
+ _currentScale = MIN(newScale, 100);
+
+ if (_visible) {
+ // Player sprite needs to be rendered
+ SpriteSlot slot;
+ slot._flags = IMG_UPDATE;
+ slot._seqIndex = PLAYER_SEQ_INDEX;
+ slot._spritesIndex = _spritesStart + _spritesIdx;
+ slot._frameNumber = _mirror ? -_frameNumber : _frameNumber;
+ slot._position.x = _playerPos.x;
+ slot._position.y = _playerPos.y + (_centerOfGravity * newScale) / 100;
+ slot._depth = newDepth;
+ slot._scale = newScale;
+
+ if (slotIndex >= 0) {
+ // Check if the existing player slot has the same details, and can be re-used
+ SpriteSlot &s2 = scene._spriteSlots[slotIndex];
+ bool equal = (s2._seqIndex == slot._seqIndex)
+ && (s2._spritesIndex == slot._spritesIndex)
+ && (s2._frameNumber == slot._frameNumber)
+ && (s2._position == slot._position)
+ && (s2._depth == slot._depth)
+ && (s2._scale == slot._scale);
+
+ if (equal)
+ // Undo the prior expiry of the player sprite
+ s2._flags = IMG_STATIC;
+ else
+ slotIndex = -1;
+ }
+
+ if (slotIndex < 0) {
+ // New slot needed, so allocate one and copy the slot data
+ slotIndex = scene._spriteSlots.add();
+ scene._spriteSlots[slotIndex] = slot;
+ }
+
+ // If changing a scene, check to change the scene when the player
+ // has moved off-screen
+ if (_walkOffScreen) {
+ SpriteAsset *asset = scene._sprites[slot._spritesIndex];
+ MSprite *frame = asset->getFrame(_frameNumber - 1);
+ int xScale = frame->w * newScale / 200;
+ int yScale = frame->h * newScale / 100;
+ int playerX = slot._position.x;
+ int playerY = slot._position.y;
+
+ if ((playerX + xScale) < 0 || (playerX + xScale) >= MADS_SCREEN_WIDTH ||
+ playerY < 0 || (playerY + yScale) >= MADS_SCENE_HEIGHT) {
+ scene._nextSceneId = _walkOffScreen;
+ _walkOffScreen = 0;
+ _walkAnywhere = false;
+ }
+ }
+
+ }
+ }
+
+ _beenVisible |= _visible;
+ _priorVisible = _visible;
+ _forceRefresh = false;
+}
+
+void Player::clearStopList() {
+ _stopWalkerList[0] = 0;
+ _stopWalkerTrigger[0] = 0;
+ _stopWalkerIndex = 0;
+ _upcomingTrigger = 0;
+ _trigger = 0;
+}
+
+void Player::startWalking(const Common::Point &pt, Facing facing) {
+ Scene &scene = _vm->_game->_scene;
+
+ clearStopList();
+ setBaseFrameRate();
+ _moving = true;
+ _targetFacing = facing;
+
+ bool v = scene._depthSurface.getDepthHighBit(pt);
+
+ scene._rails.setupRoute(v, _playerPos, pt);
+}
+
+void Player::walk(const Common::Point &pos, Facing facing) {
+ cancelWalk();
+ _needToWalk = true;
+ _readyToWalk = true;
+ _prepareWalkPos = pos;
+ _prepareWalkFacing = facing;
+}
+
+void Player::nextFrame() {
+ Scene &scene = _vm->_game->_scene;
+
+ uint32 newTime = _priorTimer + _ticksAmount;
+ if (scene._frameStartTime >= newTime) {
+ _priorTimer = scene._frameStartTime;
+ if (_moving) {
+ move();
+ } else {
+ idle();
+ }
+
+ setFrame();
+ update();
+ }
+}
+
+void Player::move() {
+ Scene &scene = _vm->_game->_scene;
+ Rails &rails = scene._rails;
+ bool newFacing = false;
+
+ if (_moving) {
+ while (!_walkOffScreen && _playerPos == _targetPos) {
+ bool isRouteEmpty = rails.empty();
+ if (!isRouteEmpty) {
+ const WalkNode &node = rails.popNode();
+
+ _targetPos = node._walkPos;
+ newFacing = true;
+ } else if (!_walkOffScreenSceneId) {
+ // End of walking path
+ rails.resetRoute();
+ _moving = false;
+ setFinalFacing();
+ newFacing = true;
+ } else {
+ _walkOffScreen = _walkOffScreenSceneId;
+ _walkAnywhere = true;
+ _walkOffScreenSceneId = 0;
+ _stepEnabled = false;
+ newFacing = false;
+ }
+
+ if (!_moving)
+ break;
+ }
+ }
+
+ if (newFacing && _moving)
+ startMovement();
+
+ if (_turnToFacing != _facing)
+ changeFacing();
+ else if (!_moving)
+ updateFrame();
+
+ int velocity = _velocity;
+ if (_scalingVelocity && (_totalDistance > 0)) {
+ int angleRange = 100 - _currentScale;
+ int angleScale = angleRange * (_posDiff.x - 1) / _totalDistance + _currentScale;
+ velocity = MAX(1L, (angleScale * _currentScale * velocity) / 10000L);
+ }
+
+ if (!_moving || (_facing != _turnToFacing))
+ return;
+
+ Common::Point newPos = _playerPos;
+ newFacing = false;
+ _special = 0;
+
+ if (_distAccum < velocity) {
+ do {
+ if (_pixelAccum < _posDiff.x)
+ _pixelAccum += _posDiff.y;
+ if (_pixelAccum >= _posDiff.x) {
+ if ((_posChange.y > 0) || _walkOffScreen)
+ newPos.y += _yDirection;
+ --_posChange.y;
+ _pixelAccum -= _posDiff.x;
+ }
+
+ if (_pixelAccum < _posDiff.x) {
+ if ((_posChange.x > 0) || _walkOffScreen)
+ newPos.x += _xDirection;
+ --_posChange.x;
+ }
+
+ if (!_walkAnywhere && !_walkOffScreen && (_walkOffScreenSceneId == 0)) {
+ newFacing = scene._depthSurface.getDepthHighBit(newPos);
+
+ if (_special == 0)
+ _special = scene.getDepthHighBits(newPos);
+ }
+
+ _distAccum += _deltaDistance;
+
+ } while ((_distAccum < velocity) && !newFacing && ((_posChange.x > 0) || (_posChange.y > 0) || (_walkOffScreen != 0)));
+ }
+
+ _distAccum -= velocity;
+
+ if (newFacing) {
+ cancelCommand();
+ } else {
+ if (!_walkOffScreen) {
+ // If the move is complete, make sure the position is exactly on the given destination
+ if (_posChange.x == 0)
+ newPos.x = _targetPos.x;
+ if (_posChange.y == 0)
+ newPos.y = _targetPos.y;
+ }
+
+ _playerPos = newPos;
+ }
+}
+
+void Player::idle() {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_facing != _turnToFacing) {
+ // The direction has changed, so reset for new direction
+ changeFacing();
+ return;
+ }
+
+ if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesStart + _spritesIdx])
+ return;
+
+ SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx];
+ assert(spriteSet._charInfo);
+ if (spriteSet._charInfo->_numEntries == 0)
+ // No entries, so exit immediately
+ return;
+
+ int frameIndex = ABS(_frameListIndex);
+ int direction = (_frameListIndex < 0) ? -1 : 1;
+
+ if (frameIndex >= spriteSet._charInfo->_numEntries) {
+ // Reset back to the start of the list
+ _frameListIndex = 0;
+ } else {
+ _frameNumber += direction;
+ _forceRefresh = true;
+
+ if (spriteSet._charInfo->_stopFrames[frameIndex] < _frameNumber) {
+ _trigger = _upcomingTrigger;
+ updateFrame();
+ }
+ if (spriteSet._charInfo->_startFrames[frameIndex] < _frameNumber) {
+ _trigger = _upcomingTrigger;
+ updateFrame();
+ }
+ }
+}
+
+void Player::setFrame() {
+ if (_moving) {
+ if (++_frameNumber > _frameCount)
+ _frameNumber = 1;
+ _forceRefresh = true;
+ } else {
+ if (!_forceRefresh)
+ idle();
+ }
+}
+
+int Player::getSpriteSlot() {
+ SpriteSlots &spriteSlots = _vm->_game->_scene._spriteSlots;
+
+ for (uint idx = 0; idx < spriteSlots.size(); ++idx) {
+ if (spriteSlots[idx]._seqIndex == PLAYER_SEQ_INDEX &&
+ spriteSlots[idx]._flags >= IMG_STATIC)
+ return idx;
+ }
+
+ return - 1;
+}
+
+int Player::getScale(int yp) {
+ Scene &scene = _vm->_game->_scene;
+
+ int scale = (scene._bandsRange == 0) ? scene._sceneInfo->_maxScale :
+ (yp - scene._sceneInfo->_yBandsStart) * scene._scaleRange / scene._bandsRange +
+ scene._sceneInfo->_minScale;
+
+ return MIN(scale, 100);
+}
+
+void Player::setBaseFrameRate() {
+ Scene &scene = _vm->_game->_scene;
+
+ SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx];
+ assert(spriteSet._charInfo);
+
+ _ticksAmount = spriteSet._charInfo->_ticksAmount;
+ if (_ticksAmount == 0)
+ _ticksAmount = 6;
+}
+
+void Player::startMovement() {
+ int xDiff = _targetPos.x - _playerPos.x;
+ int yDiff = _targetPos.y - _playerPos.y;
+ int srcScale = getScale(_playerPos.y);
+ int destScale = getScale(_targetPos.y);
+
+ // Sets the X direction
+ if (xDiff > 0)
+ _xDirection = 1;
+ else if (xDiff < 0)
+ _xDirection = -1;
+ else
+ _xDirection = 0;
+
+ // Sets the Y direction
+ if (yDiff > 0)
+ _yDirection = 1;
+ else if (yDiff < 0)
+ _yDirection = -1;
+ else
+ _yDirection = 0;
+
+ xDiff = ABS(xDiff);
+ yDiff = ABS(yDiff);
+ int scaleDiff = ABS(srcScale - destScale);
+
+ int xAmt100 = xDiff * 100;
+ int yAmt100 = yDiff * 100;
+ int xAmt33 = xDiff * 33;
+
+ int scaleAmount = (_scalingVelocity ? scaleDiff * 3 : 0) + 100 * yDiff / 100;
+ int scaleAmount100 = scaleAmount * 100;
+
+ // Figure out direction that will need to be moved in
+ int majorDir;
+ if (xDiff == 0) {
+ majorDir = 1;
+ } else if (yDiff == 0) {
+ majorDir = 3;
+ } else {
+ if ((scaleAmount < xDiff) && ((xAmt33 / scaleAmount) >= 141))
+ majorDir = 3;
+ else if (yDiff <= xDiff)
+ majorDir = 2;
+ else if ((scaleAmount100 / xDiff) >= 141)
+ majorDir = 1;
+ else
+ majorDir = 2;
+ }
+
+ switch (majorDir) {
+ case 1:
+ _turnToFacing = (_yDirection <= 0) ? FACING_NORTH : FACING_SOUTH;
+ break;
+ case 2: {
+ _turnToFacing = (Facing)(((_yDirection <= 0) ? 9 : 3) - ((_xDirection <= 0) ? 2 : 0));
+ break;
+ }
+ case 3:
+ _turnToFacing = (_xDirection <= 0) ? FACING_WEST : FACING_EAST;
+ break;
+ default:
+ break;
+ }
+
+ _totalDistance = (int)sqrt((double)(xAmt100 * xAmt100 + yAmt100 * yAmt100));
+ _posDiff.x = xDiff + 1;
+ _posDiff.y = yDiff + 1;
+ _posChange.x = xDiff;
+ _posChange.y = yDiff;
+
+ int majorChange = MAX(xDiff, yDiff);
+ _deltaDistance = (majorChange == 0) ? 0 : _totalDistance / majorChange;
+
+ if (_playerPos.x > _targetPos.x)
+ _pixelAccum = MAX(_posChange.x, _posChange.y);
+ else
+ _pixelAccum = 0;
+
+ _totalDistance /= 100;
+ _distAccum = -_deltaDistance;
+}
+
+void Player::newWalk() {
+ if (_needToWalk && _readyToWalk) {
+ startWalking(_prepareWalkPos, _prepareWalkFacing);
+ _needToWalk = false;
+ }
+}
+
+void Player::addWalker(int walker, int trigger) {
+ Scene &scene = _vm->_game->_scene;
+ SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx];
+ assert(spriteSet._charInfo);
+
+ if (walker < spriteSet._charInfo->_numEntries && _stopWalkerIndex < 11) {
+ ++_stopWalkerIndex;
+ _stopWalkerList[_stopWalkerIndex] = walker;
+ _stopWalkerTrigger[_stopWalkerIndex] = trigger;
+ }
+}
+
+
+/**
+* Releases any sprites used by the player
+*/
+void Player::releasePlayerSprites() {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_spritesLoaded && _numSprites > 0) {
+ int spriteEnd = _spritesStart + _numSprites - 1;
+ do {
+ scene._sprites.remove(spriteEnd);
+ } while (--spriteEnd >= _spritesStart);
+ }
+
+ _numSprites = 0;
+ _spritesLoaded = false;
+ _spritesChanged = true;
+
+ if (scene._sprites._assetCount > 0) {
+ warning("Player::releasePlayerSprites(): leftover sprites remain, clearing list");
+ scene._sprites.clear();
+ }
+}
+
+void Player::synchronize(Common::Serializer &s) {
+ s.syncAsByte(_moving);
+ s.syncAsSint16LE(_playerPos.x);
+ s.syncAsSint16LE(_playerPos.y);
+ s.syncAsSint16LE(_targetPos.x);
+ s.syncAsSint16LE(_targetPos.y);
+ s.syncAsSint16LE(_xDirection);
+ s.syncAsSint16LE(_yDirection);
+ s.syncAsSint16LE(_posDiff.x);
+ s.syncAsSint16LE(_posDiff.y);
+ s.syncAsSint16LE(_posChange.x);
+ s.syncAsSint16LE(_posChange.y);
+ s.syncAsUint16LE(_targetFacing);
+ s.syncAsSint16LE(_special);
+ s.syncAsByte(_forceRefresh);
+ s.syncAsSint16LE(_ticksAmount);
+ s.syncAsByte(_walkAnywhere);
+ s.syncAsUint16LE(_walkOffScreenSceneId);
+ s.syncAsByte(_walkOffScreen);
+ s.syncAsByte(_needToWalk);
+ s.syncAsByte(_readyToWalk);
+ s.syncAsUint16LE(_prepareWalkFacing);
+ s.syncAsSint16LE(_prepareWalkPos.x);
+ s.syncAsSint16LE(_prepareWalkPos.y);
+ s.syncAsByte(_stepEnabled);
+ s.syncAsByte(_visible);
+ s.syncAsByte(_priorVisible);
+
+ for (int i = 0; i < 8; ++i)
+ s.syncAsByte(_spriteSetsPresent[i]);
+
+ s.syncAsByte(_facing);
+ s.syncAsByte(_turnToFacing);
+ s.syncAsSint16LE(_spritesIdx);
+ s.syncAsSint16LE(_frameNumber);
+ s.syncAsSint16LE(_currentDepth);
+ s.syncAsSint16LE(_currentScale);
+ s.syncAsSint16LE(_frameListIndex);
+
+ for (int i = 0; i < 12; ++i) {
+ s.syncAsSint16LE(_stopWalkerList[i]);
+ s.syncAsSint16LE(_stopWalkerTrigger[i]);
+ }
+
+ s.syncAsSint16LE(_stopWalkerIndex);
+ s.syncAsSint16LE(_upcomingTrigger);
+ s.syncAsSint16LE(_trigger);
+ s.syncAsSint16LE(_scalingVelocity);
+ s.syncAsSint16LE(_pixelAccum);
+ s.syncAsSint16LE(_distAccum);
+ s.syncAsSint16LE(_deltaDistance);
+ s.syncAsSint16LE(_totalDistance);
+ s.syncAsSint16LE(_velocity);
+ s.syncAsUint16LE(_frameCount);
+ s.syncString(_spritesPrefix);
+ s.syncAsUint32LE(_priorTimer);
+ s.syncAsByte(_loadsFirst);
+ s.syncAsByte(_loadedFirst);
+ s.syncAsByte(_spritesLoaded);
+ s.syncAsByte(_spritesChanged);
+ s.syncAsByte(_beenVisible);
+ s.syncAsSint16LE(_centerOfGravity);
+ s.syncAsByte(_mirror);
+}
+
+void Player::removePlayerSprites() {
+ Scene &scene = _vm->_game->_scene;
+ int heroSpriteId = _spritesStart;
+ for (int i = 0; i < 8; i++) {
+ if (_spriteSetsPresent[i]) {
+ scene._sprites.remove(heroSpriteId++);
+ _spriteSetsPresent[i] = false;
+ }
+ }
+
+ if (scene._activeAnimation != nullptr)
+ scene._activeAnimation->resetSpriteSetsCount();
+
+ scene._spriteSlots.fullRefresh();
+ _visible = false;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/player.h b/engines/mads/player.h
new file mode 100644
index 0000000000..671ac9d16e
--- /dev/null
+++ b/engines/mads/player.h
@@ -0,0 +1,228 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_PLAYER_H
+#define MADS_PLAYER_H
+
+#include "common/scummsys.h"
+#include "common/str.h"
+#include "common/serializer.h"
+
+namespace MADS {
+
+class MADSEngine;
+class MADSAction;
+
+#define PLAYER_SPRITES_FILE_COUNT 8
+#define MAX_ROUTE_NODES 22
+
+/**
+ * Player facings
+ */
+enum Facing {
+ FACING_NORTH = 8, FACING_SOUTH = 2, FACING_EAST = 6, FACING_WEST = 4,
+ FACING_NORTHEAST = 9, FACING_SOUTHEAST = 3,
+ FACING_SOUTHWEST = 1, FACING_NORTHWEST = 7,
+ FACING_NONE = 5, FACING_DUMMY = 0
+};
+
+class Player {
+private:
+ static const int _directionListIndexes[32];
+private:
+ MADSEngine *_vm;
+ bool _highSprites;
+ bool _spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT];
+ bool _mirror;
+ int _frameCount;
+ int _frameListIndex;
+ int _distAccum;
+ int _pixelAccum;
+ int _deltaDistance;
+ int _stopWalkerList[12];
+ int _stopWalkerTrigger[12];
+ int _totalDistance;
+
+ void clearStopList();
+
+ /**
+ * If the player is moving, handles figuring out the correct motion
+ */
+ void move();
+
+ /**
+ * Update the player's frame number
+ */
+ void setFrame();
+
+ /**
+ * Get the sprite slot index for the player
+ */
+ int getSpriteSlot();
+
+ /**
+ * Get the scale for the player at the given Y position
+ */
+ int getScale(int yp);
+
+ /**
+ * Sets the frame rate for the current sprite set
+ */
+ void setBaseFrameRate();
+
+ /**
+ * Starts a player moving to a given destination
+ */
+ void startMovement();
+
+ void changeFacing();
+public:
+ MADSAction *_action;
+
+ Facing _facing;
+ Facing _turnToFacing;
+ Facing _prepareWalkFacing;
+ int _xDirection, _yDirection;
+ Facing _targetFacing;
+ bool _spritesLoaded;
+ int _spritesStart;
+ int _spritesIdx;
+ int _numSprites;
+ bool _stepEnabled;
+ bool _spritesChanged;
+ bool _visible;
+ bool _priorVisible;
+ bool _beenVisible;
+ bool _walkAnywhere;
+ int _frameNumber;
+ bool _loadsFirst;
+ bool _loadedFirst;
+ Common::Point _playerPos;
+ Common::Point _targetPos;
+ Common::Point _posChange;
+ Common::Point _posDiff;
+ Common::Point _prepareWalkPos;
+ bool _moving;
+ int _walkOffScreen, _walkOffScreenSceneId;
+ int _special;
+ int _ticksAmount;
+ uint32 _priorTimer;
+ int _velocity;
+ int _upcomingTrigger;
+ int _trigger;
+ bool _scalingVelocity;
+ bool _forceRefresh;
+ bool _needToWalk;
+ bool _readyToWalk;
+ int _stopWalkerIndex;
+ int _centerOfGravity;
+ int _currentDepth;
+ int _currentScale;
+ Common::String _spritesPrefix;
+public:
+ Player(MADSEngine *vm);
+
+ /**
+ * Load sprites for the player
+ */
+ bool loadSprites(const Common::String &prefix);
+
+ /**
+ * Called when the player has reached the given destination, start him
+ * turning to the specified facing
+ */
+ void setFinalFacing();
+
+ /**
+ * Stops the player walking
+ */
+ void cancelWalk();
+
+ /**
+ * Cancels any oustanding player action
+ */
+ void cancelCommand();
+
+ /**
+ * Set up control parameters for the current active series (the
+ * direction which the player is facing in) */
+ void selectSeries();
+
+ /*
+ * Moves to the next frame for the currently active player sprite set
+ */
+ void updateFrame();
+
+ void update();
+
+ /**
+ * Handler method for when the player is not moving
+ */
+ void idle();
+
+ /**
+ * Starts the player walking towards a given point and direction facing
+ * @param pos Destination location
+ * @param facing Direction to face once the destination is reached
+ */
+ void startWalking(const Common::Point &pt, Facing facing);
+
+ /**
+ * Used by the game scripst to make the player walk to a given destination.
+ * The difference from startWalking is that this contains several extra
+ * layers of checking that startWalking bypasses.
+ */
+ void walk(const Common::Point &pos, Facing facing);
+
+ /**
+ * If a new walk sequence is pending, and has been okayed by the preparser,
+ * start the actual walking
+ */
+ void newWalk();
+
+ void nextFrame();
+
+ /**
+ * Add a walker to the current queue
+ */
+ void addWalker(int walker, int trigger);
+
+ /**
+ * Delete any sprites used by the player
+ */
+ void releasePlayerSprites();
+
+ /**
+ * Serialize the data of the player
+ */
+ void synchronize(Common::Serializer &s);
+
+ static void preloadSequences(const Common::String &prefix, int level) {
+ // No implementation in ScummVM
+ }
+
+ void removePlayerSprites();
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_PLAYER_H */
diff --git a/engines/mads/rails.cpp b/engines/mads/rails.cpp
new file mode 100644
index 0000000000..322e6e7cb3
--- /dev/null
+++ b/engines/mads/rails.cpp
@@ -0,0 +1,277 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/rails.h"
+
+namespace MADS {
+
+WalkNode::WalkNode() {
+ _active = false;
+ Common::fill(&_distances[0], &_distances[MAX_ROUTE_NODES], 0);
+}
+
+void WalkNode::load(Common::SeekableReadStream *f) {
+ _walkPos.x = f->readSint16LE();
+ _walkPos.y = f->readSint16LE();
+ for (int i = 0; i < MAX_ROUTE_NODES; ++i)
+ _distances[i] = f->readUint16LE();
+}
+
+/*------------------------------------------------------------------------*/
+
+Rails::Rails() {
+ _depthSurface = nullptr;
+ _routeLength = 0;
+ _depthStyle = 0;
+ _next = 0;
+}
+
+void Rails::load(const WalkNodeList &nodes, DepthSurface *depthSurface, int depthStyle) {
+ // Store the depth surface and depth style to use
+ _depthSurface = depthSurface;
+ _depthStyle = depthStyle;
+
+ // Load the passed node list
+ _nodes.clear();
+
+ for (uint i = 0; i < nodes.size(); ++i)
+ _nodes.push_back(nodes[i]);
+
+ // Add two more empty nodes for the start and end points of any walk sequence
+ _nodes.push_back(WalkNode());
+ _nodes.push_back(WalkNode());
+}
+
+
+void Rails::setupRoute(bool bitFlag, const Common::Point &srcPos, const Common::Point &destPos) {
+ // Reset the nodes in as being inactive
+ for (uint i = 0; i < _nodes.size(); ++i)
+ _nodes[i]._active = false;
+
+ // Set the two extra walk nodes to the start and destination positions
+ setNodePosition(_nodes.size() - 2, srcPos);
+ setNodePosition(_nodes.size() - 1, destPos);
+
+ // Start constructing route node list
+ _routeLength = 0x3FFF;
+ _routeIndexes.clear();
+
+ // Recursively form a route from the destination walk node back to the player's position
+ setupRouteNode(&_tempRoute[0], _nodes.size() - 1, bitFlag ? 0xC000 : 0x8000, 0);
+
+ _next = 0;
+ if (_routeIndexes.size() > 0) {
+ Common::Point currPos = srcPos;
+ for (int routeCtr = size() - 1; (routeCtr >= 0) && !_next; --routeCtr) {
+ int idx = _routeIndexes[routeCtr];
+ const Common::Point &pt = _nodes[idx]._walkPos;
+
+ _next = scanPath(currPos, pt);
+ currPos = pt;
+ }
+ }
+}
+
+void Rails::setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength) {
+ WalkNode &currentNode = _nodes[nodeIndex];
+ currentNode._active = true;
+
+ *routeIndexP++ = nodeIndex;
+
+ // Get the index of the ultimate source position (the player)
+ int subIndex = _nodes.size() - 2;
+
+ int distanceVal = _nodes[nodeIndex]._distances[subIndex];
+ if (distanceVal & flags) {
+ routeLength += distanceVal & 0x3FFF;
+ if (routeLength < _routeLength) {
+ // Found a new shorter route to destination, so set up the route with the found one
+ _routeIndexes.clear();
+ for (int i = 0; routeIndexP != &_tempRoute[i]; ++i)
+ _routeIndexes.push(_tempRoute[i]);
+ _routeLength = routeLength;
+ }
+ } else {
+ for (int idx = _nodes.size() - 2; idx > 0; --idx) {
+ int nodePos = idx - 1;
+ if (!_nodes[nodePos]._active && ((currentNode._distances[nodePos] & flags) != 0))
+ setupRouteNode(routeIndexP, nodePos, 0x8000, routeLength + (distanceVal & 0x3fff));
+ }
+ }
+
+ currentNode._active = false;
+}
+
+
+int Rails::scanPath(const Common::Point &srcPos, const Common::Point &destPos) {
+ // For compressed depth surfaces, always return 0
+ if (_depthStyle == 2)
+ return 0;
+
+ int yDiff = destPos.y - srcPos.y;
+ int yAmount = MADS_SCREEN_WIDTH;
+
+ if (yDiff < 0) {
+ yDiff = -yDiff;
+ yAmount = -yAmount;
+ }
+
+ int xDiff = destPos.x - srcPos.x;
+ int xDirection = 1;
+ int xAmount = 0;
+ if (xDiff < 0) {
+ xDiff = -xDiff;
+ xDirection = -xDirection;
+ xAmount = MIN(yDiff, xDiff);
+ }
+
+ ++xDiff;
+ ++yDiff;
+
+ const byte *srcP = _depthSurface->getBasePtr(srcPos.x, srcPos.y);
+ int index = xAmount;
+
+ // Outer loop
+ for (int xCtr = 0; xCtr < xDiff; ++xCtr, srcP += xDirection) {
+ index += yDiff;
+ int v = (*srcP & 0x7F) >> 4;
+ if (v)
+ return v;
+
+ // Inner loop for handling vertical movement
+ while (index >= xDiff) {
+ index -= xDiff;
+
+ v = (*srcP & 0x7F) >> 4;
+ if (v)
+ return v;
+
+ srcP += yAmount;
+ }
+ }
+
+ return 0;
+}
+
+void Rails::resetRoute() {
+ _routeIndexes.clear();
+ _next = 0;
+}
+
+const WalkNode &Rails::popNode() {
+ assert(!_routeIndexes.empty());
+
+ return _nodes[_routeIndexes.pop()];
+}
+
+void Rails::setNodePosition(int nodeIndex, const Common::Point &pt) {
+ int flags, hypotenuse;
+
+ _nodes[nodeIndex]._walkPos = pt;
+
+ // Recalculate inter-node lengths
+ for (uint idx = 0; idx < _nodes.size(); ++idx) {
+ int entry;
+ if (idx == (uint)nodeIndex) {
+ entry = 0x3FFF;
+ } else {
+ // Process the node
+ flags = getRouteFlags(pt, _nodes[idx]._walkPos);
+
+ int xDiff = ABS(_nodes[idx]._walkPos.x - pt.x);
+ int yDiff = ABS(_nodes[idx]._walkPos.y - pt.y);
+ hypotenuse = (int)sqrt((double)(xDiff * xDiff + yDiff * yDiff));
+
+ if (hypotenuse >= 0x3FFF)
+ // Shouldn't ever be this large
+ hypotenuse = 0x3FFF;
+
+ entry = hypotenuse | flags;
+ }
+
+ _nodes[idx]._distances[nodeIndex] = entry;
+ _nodes[nodeIndex]._distances[idx] = entry;
+ }
+}
+
+int Rails::getRouteFlags(const Common::Point &src, const Common::Point &dest) {
+ int result = 0x8000;
+ bool flag = false;
+
+ int xDiff = ABS(dest.x - src.x);
+ int yDiff = ABS(dest.y - src.y);
+ int xDirection = dest.x >= src.x ? 1 : -1;
+ int yDirection = dest.y >= src.y ? _depthSurface->w : -_depthSurface->w;
+ int minorDiff = 0;
+ if (dest.x < src.x)
+ minorDiff = MIN(xDiff, yDiff);
+ ++xDiff;
+ ++yDiff;
+
+ byte *srcP = _depthSurface->getBasePtr(src.x, src.y);
+
+ int totalCtr = minorDiff;
+ for (int xCtr = 0; xCtr < xDiff; ++xCtr, srcP += xDirection) {
+ totalCtr += yDiff;
+
+ if ((*srcP & 0x80) == 0)
+ flag = false;
+ else if (!flag) {
+ flag = true;
+ result -= 0x4000;
+ if (result == 0)
+ break;
+ }
+
+ while (totalCtr >= xDiff) {
+ totalCtr -= xDiff;
+
+ if ((*srcP & 0x80) == 0)
+ flag = false;
+ else if (!flag) {
+ flag = true;
+ result -= 0x4000;
+ if (result == 0)
+ break;
+ }
+
+ srcP += yDirection;
+ }
+ if (result == 0)
+ break;
+ }
+
+ return result;
+}
+
+void Rails::synchronize(Common::Serializer &s) {
+ s.syncAsSint16LE(_routeLength);
+ s.syncAsSint16LE(_next);
+
+ if (s.isLoading()) {
+ _routeIndexes.clear();
+ }
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/rails.h b/engines/mads/rails.h
new file mode 100644
index 0000000000..e6cab08f85
--- /dev/null
+++ b/engines/mads/rails.h
@@ -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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_RAILS_H
+#define MADS_RAILS_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/serializer.h"
+#include "common/stack.h"
+#include "mads/msurface.h"
+
+namespace MADS {
+
+class WalkNode {
+public:
+ Common::Point _walkPos;
+ uint16 _distances[MAX_ROUTE_NODES];
+ bool _active;
+
+ /**
+ * Constructor
+ */
+ WalkNode();
+
+ /**
+ * Loads the scene node
+ */
+ void load(Common::SeekableReadStream *f);
+};
+typedef Common::Array<WalkNode> WalkNodeList;
+
+/**
+ * This class handles storing the intermediate walk node points for a
+ * given scene, and calculating walking routes between any two positions.
+ */
+class Rails {
+private:
+ WalkNodeList _nodes;
+ DepthSurface *_depthSurface;
+ int _depthStyle;
+ int _routeLength;
+ int _next;
+ int _tempRoute[MAX_ROUTE_NODES];
+ Common::Stack<int> _routeIndexes;
+private:
+ /**
+ * Change the position of a walking node. Doing so causes a recalculation of the
+ * distance between it and every other node, and vice versa
+ */
+ void setNodePosition(int nodeIndex, const Common::Point &pt);
+
+ int getRouteFlags(const Common::Point &src, const Common::Point &dest);
+public:
+ /**
+ * Constructor
+ */
+ Rails();
+
+ /**
+ * Loads the scene data for the list of intermediate walk nodes and the
+ * depth surface to use.
+ * @param nodes Intermediate walk-points
+ * @param depthSurface Depth surface to use
+ */
+ void load(const WalkNodeList &nodes, DepthSurface *depthSurface, int depthStyle);
+
+ /**
+ * Set up a route between two points in a scene
+ */
+ void setupRoute(bool bitFlag, const Common::Point &srcPos, const Common::Point &destPos);
+
+ void setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength);
+
+ /**
+ * Resets any currently running route
+ */
+ void resetRoute();
+
+ /**
+ * Scans along an edge connecting two points within the depths/walk surface, and returns the information of the first
+ * pixel high nibble encountered with a non-zero value
+ */
+ int scanPath(const Common::Point &srcPos, const Common::Point &destPos);
+
+ /*
+ * Return the number of walk nodes in the calculated route
+ */
+ int size() const { return _routeIndexes.size(); }
+
+ /**
+ * Returns true if the current calculated walk route is empty
+ */
+ bool empty() const { return _routeIndexes.empty(); }
+
+ /**
+ * Returns the data for a given walk node
+ */
+ const WalkNode &operator[](int idx) { return _nodes[_routeIndexes[idx]]; }
+
+ const WalkNode &popNode();
+
+ void resetNext() { _next = 0; }
+ int getNext() { return _next; }
+
+ /**
+ * Synchronize the data for the route
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_RAILS_H */
diff --git a/engines/mads/resources.cpp b/engines/mads/resources.cpp
new file mode 100644
index 0000000000..1fb75e6ba2
--- /dev/null
+++ b/engines/mads/resources.cpp
@@ -0,0 +1,417 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/archive.h"
+#include "common/textconsole.h"
+#include "mads/mads.h"
+#include "mads/resources.h"
+
+namespace MADS {
+
+enum ResourceType {RESTYPE_ROOM, RESTYPE_SC, RESTYPE_TEXT, RESTYPE_QUO, RESTYPE_I,
+ RESTYPE_OB, RESTYPE_FONT, RESTYPE_SOUND, RESTYPE_SPEECH, RESTYPE_HAS_EXT, RESTYPE_NO_EXT};
+
+/**
+ * HAG Archives implementation
+ */
+class HagArchive : public Common::Archive {
+private:
+ /**
+ * Details of a single entry in a HAG file index
+ */
+ struct HagEntry {
+ Common::String _resourceName;
+ uint32 _offset;
+ uint32 _size;
+
+ HagEntry() : _offset(0), _size(0) {}
+ HagEntry(Common::String resourceName, uint32 offset, uint32 size)
+ : _resourceName(resourceName), _offset(offset), _size(size) {
+ }
+ };
+
+ class HagIndex {
+ public:
+ Common::List<HagEntry> _entries;
+ Common::String _filename;
+ };
+
+ Common::Array<HagIndex> _index;
+
+ /**
+ * Load the index of all the game's HAG files
+ */
+ void loadIndex(MADSEngine *vm);
+
+ /**
+ * Given a resource name, opens up the correct HAG file and returns whether
+ * an entry with the given name exists.
+ */
+ bool getHeaderEntry(const Common::String &resourceName, HagIndex &hagIndex, HagEntry &hagEntry) const;
+
+ /**
+ * Returns the HAG resource filename that will contain a given resource
+ */
+ Common::String getResourceFilename(const Common::String &resourceName) const;
+
+ /**
+ * Return a resource type given a resource name
+ */
+ ResourceType getResourceType(const Common::String &resourceName) const;
+public:
+ HagArchive(MADSEngine *vm);
+ virtual ~HagArchive();
+
+ // Archive implementation
+ virtual bool hasFile(const Common::String &name) const;
+ virtual int listMembers(Common::ArchiveMemberList &list) const;
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+};
+
+const char *const MADSCONCAT_STRING = "MADSCONCAT";
+
+HagArchive::HagArchive(MADSEngine *vm) {
+ loadIndex(vm);
+}
+
+HagArchive::~HagArchive() {
+}
+
+// Archive implementation
+bool HagArchive::hasFile(const Common::String &name) const {
+ HagIndex hagIndex;
+ HagEntry hagEntry;
+ return getHeaderEntry(name, hagIndex, hagEntry);
+}
+
+int HagArchive::listMembers(Common::ArchiveMemberList &list) const {
+ int members = 0;
+
+ for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) {
+ HagIndex hagIndex = _index[hagCtr];
+ Common::List<HagEntry>::iterator i;
+
+ for (i = hagIndex._entries.begin(); i != hagIndex._entries.end(); ++i) {
+ list.push_back(Common::ArchiveMemberList::value_type(
+ new Common::GenericArchiveMember((*i)._resourceName, this)));
+ ++members;
+ }
+ }
+
+ return members;
+}
+
+const Common::ArchiveMemberPtr HagArchive::getMember(const Common::String &name) const {
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *HagArchive::createReadStreamForMember(const Common::String &name) const {
+ HagIndex hagIndex;
+ HagEntry hagEntry;
+
+ if (getHeaderEntry(name, hagIndex, hagEntry)) {
+ // Entry found. If the correct file is not already open, open it
+ Common::File f;
+ if (!f.open(hagIndex._filename))
+ error("Could not open HAG file");
+
+ // Return a new stream for the specific resource
+ f.seek(hagEntry._offset);
+ return f.readStream(hagEntry._size);
+ }
+
+ return nullptr;
+}
+
+void HagArchive::loadIndex(MADSEngine *vm) {
+ Common::File hagFile;
+
+ for (int sectionIndex = -1; sectionIndex < 11; ++sectionIndex) {
+ if (sectionIndex == 0)
+ continue;
+
+ // Dragonsphere does not have some sections - skip them
+ if (vm->getGameID() == GType_Dragonsphere) {
+ if (sectionIndex == 7 || sectionIndex == 8)
+ continue;
+ }
+
+ // Phantom does not have some sections - skip them
+ if (vm->getGameID() == GType_Phantom) {
+ if (sectionIndex == 6 || sectionIndex == 7 || sectionIndex == 8)
+ continue;
+ }
+
+ Common::String filename = (sectionIndex == -1) ? "GLOBAL.HAG" :
+ Common::String::format("SECTION%d.HAG", sectionIndex);
+ if (sectionIndex == 10) {
+ // Speech
+ if (!Common::File::exists("SPEECH.HAG"))
+ break;
+ else
+ filename = "SPEECH.HAG";
+ }
+ if (!hagFile.open(filename))
+ error("Could not locate HAG file - %s", filename.c_str());
+
+ // Check for header
+ char headerBuffer[16];
+ if ((hagFile.read(headerBuffer, 16) != 16) ||
+ (strncmp(headerBuffer, MADSCONCAT_STRING, 10) != 0))
+ error("Invalid HAG file opened");
+
+ // Scan through the HAG index
+ int numEntries = hagFile.readUint16LE();
+
+ HagIndex hagIndex;
+ hagIndex._filename = filename;
+
+ for (int idx = 0; idx < numEntries; ++idx) {
+ // Read in the details of the next resource
+ char resourceBuffer[14];
+ uint32 offset = hagFile.readUint32LE();
+ uint32 size = hagFile.readUint32LE();
+ hagFile.read(resourceBuffer, 14);
+
+ hagIndex._entries.push_back(HagEntry(resourceBuffer, offset, size));
+ }
+
+ hagFile.close();
+ _index.push_back(hagIndex);
+ }
+}
+
+bool HagArchive::getHeaderEntry(const Common::String &resourceName,
+ HagIndex &hagIndex, HagEntry &hagEntry) const {
+ Common::String resName = resourceName;
+ resName.toUppercase();
+ if (resName[0] == '*')
+ resName.deleteChar(0);
+
+ Common::String hagFilename = getResourceFilename(resName);
+
+ // Find the index for the given file
+ for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) {
+ hagIndex = _index[hagCtr];
+
+ if (hagIndex._filename == hagFilename) {
+ Common::List<HagEntry>::iterator ei;
+ for (ei = hagIndex._entries.begin(); ei != hagIndex._entries.end(); ++ei) {
+ hagEntry = *ei;
+ if (hagEntry._resourceName.compareToIgnoreCase(resName) == 0)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+Common::String HagArchive::getResourceFilename(const Common::String &resourceName) const {
+ ResourceType resType = getResourceType(resourceName);
+ Common::String outputFilename = "GLOBAL.HAG";
+
+ if ((resType == RESTYPE_ROOM) || (resType == RESTYPE_SC)) {
+ int value = atoi(resourceName.c_str() + 2);
+ int hagFileNum = (resType == RESTYPE_ROOM) ? value / 100 : value;
+
+ if (hagFileNum > 0)
+ outputFilename = Common::String::format("SECTION%d.HAG", hagFileNum);
+ }
+
+ if (resType == RESTYPE_SPEECH)
+ outputFilename = "SPEECH.HAG";
+
+ return outputFilename;
+}
+
+ResourceType HagArchive::getResourceType(const Common::String &resourceName) const {
+ if (resourceName.hasPrefix("RM")) {
+ // Room resource
+ return RESTYPE_ROOM;
+ } else if (resourceName.hasPrefix("SC")) {
+ // SC resource
+ return RESTYPE_SC;
+ } else if (resourceName.hasSuffix(".TXT")) {
+ // Text resource
+ return RESTYPE_TEXT;
+ } else if (resourceName.hasSuffix(".QUO")) {
+ // QUO resource
+ return RESTYPE_QUO;
+ } else if (resourceName.hasPrefix("I")) {
+ // I resource
+ return RESTYPE_I;
+ } else if (resourceName.hasPrefix("OB")) {
+ // OB resource
+ return RESTYPE_OB;
+ } else if (resourceName.hasPrefix("FONT")) {
+ // FONT resource
+ return RESTYPE_FONT;
+ } else if (resourceName.hasPrefix("SOUND")) {
+ // SOUND resource
+ return RESTYPE_SOUND;
+ } else if (resourceName.hasPrefix("SPCHC")) {
+ // SPEECH resource
+ return RESTYPE_SPEECH;
+ }
+
+ // Check for a known extension
+ const char *extPos = strchr(resourceName.c_str(), '.');
+ if (extPos) {
+ ++extPos;
+ if (!strcmp(extPos, "FL") || !strcmp(extPos, "LBM") || !strcmp(extPos, "ANM") ||
+ !strcmp(extPos, "AA") || !strcmp(extPos, "SS")) {
+ return RESTYPE_HAS_EXT;
+ }
+ }
+
+ return RESTYPE_NO_EXT;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Resources::init(MADSEngine *vm) {
+ SearchMan.add("HAG", new HagArchive(vm));
+}
+
+Common::String Resources::formatName(RESPREFIX resType, int id, const Common::String &ext) {
+ Common::String result = "*";
+
+ if (resType == 3 && !id) {
+ id = id / 100;
+ }
+
+ if (!ext.empty()) {
+ switch (resType) {
+ case RESPREFIX_GL:
+ result += "GL000";
+ break;
+ case RESPREFIX_SC:
+ result += Common::String::format("SC%.3d", id);
+ break;
+ case RESPREFIX_RM:
+ result += Common::String::format("RM%.3d", id);
+ break;
+ default:
+ break;
+ }
+
+ result += ext;
+ }
+
+ return result;
+}
+
+Common::String Resources::formatName(int prefix, char asciiCh, int id, EXTTYPE extType,
+ const Common::String &suffix) {
+ Common::String result;
+ if (prefix <= 0) {
+ result = "*";
+ } else {
+ result = Common::String::format("%s%.3d",
+ (prefix < 100) ? "*SC" : "*RM", prefix);
+ }
+
+ result += Common::String::format("%c", asciiCh);
+ if (id >= 0)
+ result += Common::String::format("%d", id);
+ if (!suffix.empty())
+ result += suffix;
+
+ switch (extType) {
+ case EXT_SS:
+ result += ".SS";
+ break;
+ case EXT_AA:
+ result += ".AA";
+ break;
+ case EXT_DAT:
+ result += ".DAT";
+ break;
+ case EXT_HH:
+ result += ".HH";
+ break;
+ case EXT_ART:
+ result += ".ART";
+ break;
+ case EXT_INT:
+ result += ".INT";
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+Common::String Resources::formatResource(const Common::String &resName,
+ const Common::String &hagFilename) {
+// int v1 = 0, v2 = 0;
+
+ if (resName.hasPrefix("*")) {
+ // Resource file specified
+ error("TODO: formatResource");
+ } else {
+ // File outside of hag file
+ return resName;
+ }
+}
+
+Common::String Resources::formatAAName(int idx) {
+ return formatName(0, 'I', idx, EXT_AA, "");
+}
+
+/*------------------------------------------------------------------------*/
+
+void File::openFile(const Common::String &filename) {
+ if (!Common::File::open(filename))
+ error("Could not open file - %s", filename.c_str());
+}
+
+/*------------------------------------------------------------------------*/
+
+void SynchronizedList::synchronize(Common::Serializer &s) {
+ int v = 0;
+ int count = size();
+ s.syncAsUint16LE(count);
+
+ if (s.isSaving()) {
+ for (int idx = 0; idx < count; ++idx) {
+ v = (*this)[idx];
+ s.syncAsSint32LE(v);
+ }
+ } else {
+ clear();
+ reserve(count);
+ for (int idx = 0; idx < count; ++idx) {
+ s.syncAsSint32LE(v);
+ push_back(v);
+ }
+ }
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/resources.h b/engines/mads/resources.h
new file mode 100644
index 0000000000..8d9ab1e39f
--- /dev/null
+++ b/engines/mads/resources.h
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_RESOURCES_H
+#define MADS_RESOURCES_H
+
+#include "common/scummsys.h"
+#include "common/file.h"
+#include "common/serializer.h"
+#include "common/str.h"
+
+namespace MADS {
+
+class MADSEngine;
+
+enum RESPREFIX {
+ RESPREFIX_GL = 1, RESPREFIX_SC = 2, RESPREFIX_RM = 3
+};
+
+enum EXTTYPE {
+ EXT_NONE = -1, EXT_SS = 1, EXT_AA = 2, EXT_DAT = 3, EXT_HH = 4,
+ EXT_ART = 5, EXT_INT = 6
+};
+
+class Resources {
+public:
+ /**
+ * Instantiates the resource manager
+ */
+ static void init(MADSEngine *vm);
+
+ static Common::String formatName(RESPREFIX resType, int id, const Common::String &ext);
+ static Common::String formatName(int prefix, char asciiCh, int id,
+ EXTTYPE extType, const Common::String &suffix);
+ static Common::String formatResource(const Common::String &resName, const Common::String &hagFilename);
+ static Common::String formatAAName(int idx);
+};
+
+/**
+ * Derived file class
+ */
+class File : public Common::File {
+public:
+ /**
+ * Constructor
+ */
+ File() : Common::File() {}
+
+ /**
+ * Constructor
+ */
+ File(const Common::String &filename) { openFile(filename); }
+
+ /**
+ * Opens the given file, throwing an error if it can't be opened
+ */
+ void openFile(const Common::String &filename);
+};
+
+class SynchronizedList : public Common::Array<int> {
+public:
+ /**
+ * Synchronize the list
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_RESOURCES_H */
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
new file mode 100644
index 0000000000..ad24dd4f60
--- /dev/null
+++ b/engines/mads/scene.cpp
@@ -0,0 +1,731 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/scene.h"
+#include "mads/compression.h"
+#include "mads/mads.h"
+#include "mads/dragonsphere/dragonsphere_scenes.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/phantom/phantom_scenes.h"
+
+namespace MADS {
+
+Scene::Scene(MADSEngine *vm)
+ : _vm(vm), _action(_vm), _depthSurface(vm),
+ _dirtyAreas(_vm), _dynamicHotspots(vm), _hotspots(vm),
+ _kernelMessages(vm), _sequences(vm), _sprites(vm), _spriteSlots(vm),
+ _textDisplay(vm), _userInterface(vm) {
+ _priorSceneId = 0;
+ _nextSceneId = 0;
+ _currentSceneId = 0;
+ _sceneLogic = nullptr;
+ _sceneInfo = nullptr;
+ _cyclingActive = false;
+ _cyclingThreshold = 0;
+ _cyclingDelay = 0;
+ _totalCycleColors = 0;
+ _depthStyle = 0;
+ _roomChanged = false;
+ _reloadSceneFlag = false;
+ _freeAnimationFlag = false;
+ _animationData = nullptr;
+ _activeAnimation = nullptr;
+ _textSpacing = -1;
+ _frameStartTime = 0;
+ _layer = LAYER_GUI;
+ _lookFlag = false;
+ _bandsRange = 0;
+ _scaleRange = 0;
+ _interfaceY = 0;
+ _spritesCount = 0;
+ _variant = 0;
+
+ _paletteUsageF.push_back(PaletteUsage::UsageEntry(0xF));
+
+ // Set up a scene surface that maps to our physical screen drawing surface
+ restrictScene();
+
+ // Set up the verb list
+ _verbList.push_back(VerbInit(VERB_LOOK, VERB_THAT, PREP_NONE));
+ _verbList.push_back(VerbInit(VERB_TAKE, VERB_THAT, PREP_NONE));
+ _verbList.push_back(VerbInit(VERB_PUSH, VERB_THAT, PREP_NONE));
+ _verbList.push_back(VerbInit(VERB_OPEN, VERB_THAT, PREP_NONE));
+ _verbList.push_back(VerbInit(VERB_PUT, VERB_THIS, PREP_RELATIONAL));
+ _verbList.push_back(VerbInit(VERB_TALKTO, VERB_THAT, PREP_NONE));
+ _verbList.push_back(VerbInit(VERB_GIVE, VERB_THIS, PREP_TO));
+ _verbList.push_back(VerbInit(VERB_PULL, VERB_THAT, PREP_NONE));
+ _verbList.push_back(VerbInit(VERB_CLOSE, VERB_THAT, PREP_NONE));
+ _verbList.push_back(VerbInit(VERB_THROW, VERB_THIS, PREP_AT));
+}
+
+Scene::~Scene() {
+ delete _sceneLogic;
+ delete _sceneInfo;
+ delete _animationData;
+}
+
+void Scene::restrictScene() {
+ _sceneSurface.init(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT, MADS_SCREEN_WIDTH,
+ _vm->_screen.getPixels(), Graphics::PixelFormat::createFormatCLUT8());
+}
+
+void Scene::clearVocab() {
+ _activeVocabs.clear();
+}
+
+void Scene::addActiveVocab(int vocabId) {
+ if (activeVocabIndexOf(vocabId) == -1) {
+ assert(_activeVocabs.size() < 200);
+ _activeVocabs.push_back(vocabId);
+ }
+}
+
+int Scene::activeVocabIndexOf(int vocabId) {
+ for (uint i = 0; i < _activeVocabs.size(); ++i) {
+ if (_activeVocabs[i] == vocabId)
+ return i;
+ }
+
+ return -1;
+}
+
+void Scene::clearSequenceList() {
+ _sequences.clear();
+}
+
+void Scene::clearMessageList() {
+ _kernelMessages.clear();
+ _talkFont = FONT_CONVERSATION;
+ _textSpacing = -1;
+}
+
+void Scene::loadSceneLogic() {
+ delete _sceneLogic;
+
+ switch (_vm->getGameID()) {
+ case GType_RexNebular:
+ _sceneLogic = Nebular::SceneFactory::createScene(_vm);
+ break;
+ case GType_Dragonsphere:
+ _sceneLogic = Dragonsphere::SceneFactory::createScene(_vm);
+ break;
+ case GType_Phantom:
+ _sceneLogic = Phantom::SceneFactory::createScene(_vm);
+ break;
+ default:
+ error("Scene logic: Unknown game");
+ }
+}
+
+void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) {
+ // Store the previously active scene number and set the new one
+ _priorSceneId = _currentSceneId;
+ _currentSceneId = sceneId;
+
+ _variant = 0;
+ if (palFlag)
+ _vm->_palette->resetGamePalette(18, 10);
+
+ _spriteSlots.reset(false);
+ _sequences.clear();
+ _kernelMessages.clear();
+ _vm->_palette->_paletteUsage.load(&_scenePaletteUsage);
+
+ int flags = SCENEFLAG_LOAD_SHADOW;
+ if (_vm->_dithering)
+ flags |= SCENEFLAG_DITHER;
+
+ _sceneInfo = SceneInfo::init(_vm);
+ _sceneInfo->load(_currentSceneId, _variant, Common::String(), flags,
+ _depthSurface, _backgroundSurface);
+
+ // Initialize palette animation for the scene
+ initPaletteAnimation(_sceneInfo->_paletteCycles, false);
+
+ // Copy over nodes
+ _rails.load(_sceneInfo->_nodes, &_depthSurface, _sceneInfo->_depthStyle);
+
+ // Load hotspots
+ loadHotspots();
+
+ // Load vocab
+ loadVocab();
+
+ // Load palette usage
+ _vm->_palette->_paletteUsage.load(&_paletteUsageF);
+
+ // Load interface
+ flags = PALFLAG_RESERVED | ANIMFLAG_LOAD_BACKGROUND;
+ if (_vm->_dithering)
+ flags |= ANIMFLAG_DITHER;
+ if (_vm->_textWindowStill)
+ flags |= ANIMFLAG_LOAD_BACKGROUND_ONLY;
+
+ _animationData = Animation::init(_vm, this);
+ DepthSurface depthSurface(_vm);
+ _animationData->load(_userInterface, depthSurface, prefix, flags, nullptr, nullptr);
+
+ _vm->_palette->_paletteUsage.load(&_scenePaletteUsage);
+
+ _bandsRange = _sceneInfo->_yBandsEnd - _sceneInfo->_yBandsStart;
+ _scaleRange = _sceneInfo->_maxScale - _sceneInfo->_minScale;
+
+ _spriteSlots.reset(false);
+ _interfaceY = MADS_SCENE_HEIGHT;
+ _spritesCount = _sprites.size();
+
+ _userInterface.setup(_vm->_game->_screenObjects._inputMode);
+
+ _vm->_game->_screenObjects._category = CAT_NONE;
+ _vm->_events->showCursor();
+}
+
+void Scene::loadHotspots() {
+ _hotspots.clear();
+
+ Common::File f;
+ if (f.open(Resources::formatName(RESPREFIX_RM, _currentSceneId, ".HH"))) {
+ MadsPack madsPack(&f);
+ bool isV2 = (_vm->getGameID() != GType_RexNebular);
+
+ Common::SeekableReadStream *stream = madsPack.getItemStream(0);
+ int count = stream->readUint16LE();
+ delete stream;
+
+ stream = madsPack.getItemStream(1);
+ for (int i = 0; i < count; ++i)
+ _hotspots.push_back(Hotspot(*stream, isV2));
+
+ delete stream;
+ f.close();
+ }
+}
+
+void Scene::loadVocab() {
+ // Add all the verbs to the active vocab list
+ for (uint i = 0; i < _verbList.size(); ++i)
+ addActiveVocab(_verbList[i]._id);
+
+ // Load the vocabs for any object descriptions and custom actions
+ for (uint objIndex = 0; objIndex < _vm->_game->_objects.size(); ++objIndex) {
+ InventoryObject &io = _vm->_game->_objects[objIndex];
+ addActiveVocab(io._descId);
+
+ for (int vocabIndex = 0; vocabIndex <io._vocabCount; ++vocabIndex) {
+ addActiveVocab(io._vocabList[vocabIndex]._vocabId);
+ }
+ }
+
+ // Load scene hotspot list vocabs and verbs
+ for (uint i = 0; i < _hotspots.size(); ++i) {
+ addActiveVocab(_hotspots[i]._vocabId);
+ if (_hotspots[i]._verbId)
+ addActiveVocab(_hotspots[i]._verbId);
+ }
+
+ loadVocabStrings();
+}
+
+void Scene::loadVocabStrings() {
+ _vocabStrings.clear();
+ File f("*VOCAB.DAT");
+ Common::String msg;
+
+ for (;;) {
+ char c = (char)f.readByte();
+ if (f.eos()) break;
+
+ if (c == '\0') {
+ _vocabStrings.push_back(msg);
+ msg = "";
+ } else {
+ msg += c;
+ }
+ }
+
+ f.close();
+}
+
+uint32 Scene::getVocabStringsCount() const {
+ return _vocabStrings.size();
+}
+
+void Scene::initPaletteAnimation(Common::Array<PaletteCycle> &palCycles, bool animFlag) {
+ // Initialize the animation palette and ticks list
+ _cycleTicks.clear();
+ _paletteCycles.clear();
+
+ for (uint i = 0; i < palCycles.size(); ++i) {
+ _cycleTicks.push_back(_vm->_events->getFrameCounter());
+ _paletteCycles.push_back(palCycles[i]);
+ }
+
+ // Save the initial starting palette
+ Common::copy(&_vm->_palette->_mainPalette[0], &_vm->_palette->_mainPalette[PALETTE_SIZE],
+ &_vm->_palette->_cyclingPalette[0]);
+
+ // Calculate total
+ _totalCycleColors = 0;
+ for (uint i = 0; i < _paletteCycles.size(); ++i)
+ _totalCycleColors += _paletteCycles[i]._colorCount;
+
+ _cyclingThreshold = (_totalCycleColors > 16) ? 3 : 0;
+ _cyclingActive = animFlag;
+}
+
+void Scene::animatePalette() {
+ byte rgb[3];
+
+ if (_cyclingActive) {
+ Scene::_cyclingDelay++;
+ if (_cyclingDelay >= _cyclingThreshold) {
+ uint32 frameCounter = _vm->_events->getFrameCounter();
+ bool changesFlag = false;
+ for (uint16 idx = 0; idx < _paletteCycles.size(); idx++) {
+ if (frameCounter >= (_cycleTicks[idx] + _paletteCycles[idx]._ticks)) {
+ _cycleTicks[idx] = frameCounter;
+ int count = _paletteCycles[idx]._colorCount;
+ int first = _paletteCycles[idx]._firstColorIndex;
+ int listIndex = _paletteCycles[idx]._firstListColor;
+ changesFlag = true;
+
+ if (count > 1) {
+ // Make a copy of the last color
+ byte *pSrc = &_vm->_palette->_cyclingPalette[first * 3];
+ byte *pEnd = pSrc + count * 3;
+ Common::copy(pEnd - 3, pEnd, &rgb[0]);
+
+ // Shift the cycle palette forward one entry
+ Common::copy_backward(pSrc, pEnd - 3, pEnd);
+
+ // Move the saved color to the start of the cycle
+ Common::copy(&rgb[0], &rgb[3], pSrc);
+
+ if (++listIndex >= count)
+ listIndex = 0;
+ }
+
+ _paletteCycles[idx]._firstListColor = listIndex;
+ }
+ }
+
+ if (changesFlag) {
+ int firstColor = _paletteCycles[0]._firstColorIndex;
+ byte *pSrc = &_vm->_palette->_cyclingPalette[firstColor * 3];
+ _vm->_palette->setPalette(pSrc, firstColor, _totalCycleColors);
+ }
+
+ _cyclingDelay = 0;
+ }
+ }
+}
+
+bool Scene::getDepthHighBits(const Common::Point &pt) {
+ if (_sceneInfo->_depthStyle == 2) {
+ return 0;
+ } else {
+ const byte *p = _depthSurface.getBasePtr(pt.x, pt.y);
+ return (*p & 0x70) >> 4;
+ }
+}
+
+void Scene::loop() {
+ while (!_vm->shouldQuit() && !_reloadSceneFlag && (_nextSceneId == _currentSceneId)) {
+ // Handle drawing a game frame
+ doFrame();
+
+ // Wait for the next frame
+ _vm->_events->waitForNextFrame();
+
+ if (_vm->_dialogs->_pendingDialog != DIALOG_NONE && !_vm->_game->_trigger
+ && _vm->_game->_player._stepEnabled)
+ _reloadSceneFlag = true;
+ }
+}
+
+void Scene::doFrame() {
+ Player &player = _vm->_game->_player;
+ bool flag = false;
+
+ if (_action._selectedAction || !player._stepEnabled) {
+ _action.clear();
+ _action._selectedAction = 0;
+ }
+
+ if (!_vm->_game->_trigger && !player._trigger) {
+ // Refresh the dynamic hotspots if they've changed
+ if (_dynamicHotspots._changed)
+ _dynamicHotspots.refresh();
+
+ // Check all on-screen visual objects
+ _vm->_game->_screenObjects.check(player._stepEnabled && !player._needToWalk &&
+ !_vm->_game->_fx);
+ }
+
+ if (_action._selectedAction && player._stepEnabled && !player._needToWalk &&
+ !_vm->_game->_trigger && !player._trigger) {
+ _action.startAction();
+ if (_action._activeAction._verbId == Nebular::VERB_LOOK_AT) {
+ _action._activeAction._verbId = VERB_LOOK;
+ _action._savedFields._command = false;
+ }
+
+ flag = true;
+ }
+
+ if (flag || (_vm->_game->_trigger && _vm->_game->_triggerMode == SEQUENCE_TRIGGER_PREPARE)) {
+ doPreactions();
+ }
+
+ player.newWalk();
+ if (!_vm->_game->_fx)
+ _frameStartTime = _vm->_events->getFrameCounter();
+
+ // Handle parser actions as well as game triggers
+ if ((_action._inProgress && !player._moving && !player._needToWalk &&
+ (player._facing == player._turnToFacing) && !_vm->_game->_trigger) ||
+ (_vm->_game->_trigger && (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PARSER))) {
+ doAction();
+ }
+
+ if (_currentSceneId != _nextSceneId) {
+ _freeAnimationFlag = true;
+ } else {
+ doSceneStep();
+ checkKeyboard();
+
+ if (_currentSceneId != _nextSceneId) {
+ _freeAnimationFlag = true;
+ } else {
+ player.nextFrame();
+
+ // Cursor update code
+ updateCursor();
+
+ if (!_vm->_game->_trigger) {
+ // Handle any active sequences
+ _sequences.tick();
+
+ // Handle any active animation
+ if (_activeAnimation)
+ _activeAnimation->update();
+ }
+
+ // If the debugget flag is set, show the mouse position
+ int mouseTextIndex = 0;
+ if (_vm->_debugger->_showMousePos) {
+ Common::Point pt = _vm->_events->mousePos();
+ Common::String msg = Common::String::format("(%d,%d)", pt.x, pt.y);
+ mouseTextIndex = _kernelMessages.add(Common::Point(5, 5),
+ 0x203, 0, 0, 1, msg);
+ }
+
+ if (!_vm->_game->_trigger) {
+ if (_reloadSceneFlag || _currentSceneId != _nextSceneId)
+ _kernelMessages.reset();
+ _kernelMessages.update();
+ }
+
+ _userInterface._uiSlots.draw(!_vm->_game->_fx, _vm->_game->_fx);
+
+ // Write any text needed by the interface
+ if (_vm->_game->_fx)
+ _userInterface.drawTextElements();
+
+ // Draw any elements
+ drawElements((ScreenTransition)_vm->_game->_fx, _vm->_game->_fx);
+
+ // Handle message updates
+ if (_vm->_game->_fx) {
+ uint32 priorTime = _vm->_game->_priorFrameTimer;
+ uint32 newTime = _vm->_events->getFrameCounter();
+ _sequences.delay(priorTime, newTime);
+ _kernelMessages.delay(priorTime, newTime);
+ }
+
+ if (_vm->_debugger->_showMousePos)
+ // Mouse position display isn't persistent, so remove it
+ _kernelMessages.remove(mouseTextIndex);
+
+ // Original had a debugger check/call here to allow pausing after
+ // drawing each frame. Not implemented under ScummVM
+ }
+ }
+
+ if (_vm->_game->_fx)
+ _cyclingActive = true;
+ _vm->_game->_fx = kTransitionNone;
+
+ // Handle freeing animation if necessary
+ if (_activeAnimation && _activeAnimation->freeFlag())
+ _freeAnimationFlag = true;
+ if (_freeAnimationFlag)
+ freeAnimation();
+}
+
+void Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) {
+ // Draw any sprite backgrounds
+ _spriteSlots.drawBackground();
+
+ // Set up dirty areas for any text display
+ _textDisplay.setDirtyAreas();
+
+ // Merge any identified dirty areas
+ _dirtyAreas.merge(1, DIRTY_AREAS_SIZE);
+
+ // Copy background for the dirty areas to the screen
+ _dirtyAreas.copy(&_backgroundSurface, &_vm->_screen, _posAdjust);
+
+ // Handle dirty areas for foreground objects
+ if (_vm->getGameID() == GType_RexNebular) // TODO: Implement for V2 games
+ _spriteSlots.setDirtyAreas();
+ _textDisplay.setDirtyAreas2();
+ _dirtyAreas.merge(1, DIRTY_AREAS_SIZE);
+
+ // Draw sprites that have changed
+ if (_vm->getGameID() == GType_RexNebular) // TODO: Implement for V2 games
+ _spriteSlots.drawSprites(&_sceneSurface);
+
+ // Draw text elements onto the view
+ _textDisplay.draw(&_vm->_screen);
+
+ if (transitionType) {
+ // Fading in the screen
+ _vm->_screen.transition(transitionType, surfaceFlag);
+ _vm->_sound->startQueuedCommands();
+ } else {
+ // Copy dirty areas to the screen
+ _dirtyAreas.copyToScreen();
+ }
+
+ _spriteSlots.cleanUp();
+ _textDisplay.cleanUp();
+}
+
+void Scene::doPreactions() {
+ if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences ||
+ _vm->_game->_screenObjects._inputMode == kInputLimitedSentences) {
+ _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_PREPARE;
+ _action.checkAction();
+ _sceneLogic->preActions();
+
+ if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PREPARE)
+ _vm->_game->_trigger = 0;
+ }
+}
+
+void Scene::doAction() {
+ bool flag = false;
+
+ _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_PARSER;
+ if ((_action._inProgress || _vm->_game->_trigger) && !_action._savedFields._commandError) {
+ _sceneLogic->actions();
+ flag = !_action._inProgress;
+ }
+
+ if (_vm->_game->_screenObjects._inputMode == kInputConversation) {
+ _action._inProgress = false;
+ } else {
+ if ((_action._inProgress || _vm->_game->_trigger) ||
+ (!flag && _action._savedFields._commandError == flag)) {
+ _vm->_game->_sectionHandler->sectionPtr2();
+ flag = !_action._inProgress;
+ }
+
+ if ((_action._inProgress || _vm->_game->_trigger) &&
+ (!flag || _action._savedFields._commandError == flag)) {
+ _vm->_game->doObjectAction();
+ }
+
+ if (!_action._savedFields._lookFlag) {
+ if (_action._inProgress) {
+ _action._savedFields._commandError = true;
+ _sceneLogic->postActions();
+ }
+
+ if (_action._inProgress) {
+ _action._savedFields._commandError = true;
+ _sceneLogic->unhandledAction();
+ }
+
+ if (_action._inProgress)
+ _vm->_game->unhandledAction();
+ }
+ }
+
+ _action._inProgress = false;
+ if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PARSER)
+ _vm->_game->_trigger = 0;
+}
+
+void Scene::doSceneStep() {
+ _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_DAEMON;
+ _sceneLogic->step();
+ _vm->_game->_sectionHandler->step();
+ _vm->_game->step();
+
+ if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_DAEMON)
+ _vm->_game->_trigger = 0;
+}
+
+void Scene::checkKeyboard() {
+ if (_vm->_events->isKeyPressed()) {
+ Common::Event evt = _vm->_events->_pendingKeys.pop();
+ _vm->_game->handleKeypress(evt);
+ }
+
+ if ((_vm->_events->_mouseStatus & 3) == 3 && _vm->_game->_player._stepEnabled) {
+ _reloadSceneFlag = true;
+ _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU;
+ _action.clear();
+ _action._selectedAction = 0;
+ }
+}
+
+void Scene::loadAnimation(const Common::String &resName, int trigger) {
+ // WORKAROUND: If there's already a previous active animation used by the
+ // scene, then free it before we create the new one
+ if (_activeAnimation)
+ freeAnimation();
+
+ DepthSurface depthSurface(_vm);
+ UserInterface interfaceSurface(_vm);
+
+ _activeAnimation = Animation::init(_vm, this);
+ _activeAnimation->load(interfaceSurface, depthSurface, resName,
+ _vm->_dithering ? ANIMFLAG_DITHER : 0, nullptr, nullptr);
+ _activeAnimation->startAnimation(trigger);
+}
+
+void Scene::updateCursor() {
+ Player &player = _vm->_game->_player;
+
+ CursorType cursorId = CURSOR_ARROW;
+ if (_action._interAwaiting == AWAITING_COMMAND && !_vm->_events->_rightMousePressed &&
+ _vm->_game->_screenObjects._category == CAT_HOTSPOT) {
+ int idx = _vm->_game->_screenObjects._selectedObject -
+ _userInterface._categoryIndexes[CAT_HOTSPOT - 1];
+ assert(idx >= 0);
+
+ if (idx >= (int)_hotspots.size()) {
+ idx -= _hotspots.size();
+ _vm->_events->_newCursorId = _dynamicHotspots[idx]._cursor;
+ } else {
+ idx = _hotspots.size() - idx - 1;
+ _vm->_events->_newCursorId = _hotspots[idx]._cursor;
+ }
+
+ cursorId = _vm->_events->_newCursorId == CURSOR_NONE ?
+ CURSOR_ARROW : _vm->_events->_newCursorId;
+ }
+
+ if (!player._stepEnabled)
+ cursorId = CURSOR_WAIT;
+ if (cursorId >= _vm->_events->_cursorSprites->getCount())
+ cursorId = (CursorType)_vm->_events->_cursorSprites->getCount();
+ _vm->_events->_newCursorId = cursorId;
+
+ if (cursorId != _vm->_events->_cursorId) {
+ _vm->_events->setCursor(cursorId);
+ }
+}
+
+void Scene::freeCurrentScene() {
+ if (_animationData) {
+ delete _animationData;
+ _animationData = nullptr;
+ }
+ if (_activeAnimation) {
+ delete _activeAnimation;
+ _activeAnimation = nullptr;
+ }
+
+ _vm->_palette->_paletteUsage.load(nullptr);
+ _hotspots.clear();
+ _backgroundSurface.free();
+ _depthSurface.free();
+
+ delete _sceneInfo;
+ _sceneInfo = nullptr;
+}
+
+void Scene::removeSprites() {
+ for (int idx = _sprites.size() - 1; idx >= _spritesCount; --idx)
+ _sprites.remove(idx);
+}
+
+void Scene::changeVariant(int variant) {
+ _variant = variant;
+ _sceneInfo->loadCodes(_depthSurface, variant);
+ _spriteSlots.fullRefresh();
+}
+
+void Scene::resetScene() {
+ _vm->_game->clearQuotes();
+ removeSprites();
+ _spriteSlots.fullRefresh(true);
+ _sequences.clear();
+}
+
+void Scene::freeAnimation() {
+ if (_activeAnimation) {
+ Player &player = _vm->_game->_player;
+
+ if (!_freeAnimationFlag) {
+ _spriteSlots.fullRefresh(true);
+ _sequences.scan();
+ }
+
+ // Refresh the player
+ if (player._visible) {
+ player._forceRefresh = true;
+ player.update();
+ }
+
+ // Remove any kernel messages in use by the animation
+ for (uint i = 0; i < _activeAnimation->_messages.size(); ++i) {
+ int msgIndex = _activeAnimation->_messages[i]._kernelMsgIndex;
+ if (msgIndex >= 0)
+ _kernelMessages.remove(msgIndex);
+ }
+
+ // Delete the animation
+ delete _activeAnimation;
+ _activeAnimation = nullptr;
+ }
+
+ _freeAnimationFlag = false;
+}
+
+void Scene::synchronize(Common::Serializer &s) {
+ _action.synchronize(s);
+ _rails.synchronize(s);
+ _userInterface.synchronize(s);
+ s.syncAsByte(_reloadSceneFlag);
+ s.syncAsByte(_roomChanged);
+ s.syncAsUint16LE(_nextSceneId);
+ s.syncAsUint16LE(_priorSceneId);
+ _dynamicHotspots.synchronize(s);
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/scene.h b/engines/mads/scene.h
new file mode 100644
index 0000000000..ee7864cfee
--- /dev/null
+++ b/engines/mads/scene.h
@@ -0,0 +1,253 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_SCENE_H
+#define MADS_SCENE_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "mads/assets.h"
+#include "mads/screen.h"
+#include "mads/hotspots.h"
+#include "mads/messages.h"
+#include "mads/msurface.h"
+#include "mads/scene_data.h"
+#include "mads/animation.h"
+#include "mads/rails.h"
+#include "mads/sequence.h"
+#include "mads/sprites.h"
+#include "mads/user_interface.h"
+
+namespace MADS {
+
+class Scene {
+private:
+ /**
+ * Return the index of a given Vocab in the active vocab list
+ */
+ int activeVocabIndexOf(int vocabId);
+
+ /**
+ * Secondary loading vocab list
+ */
+ void loadVocabStrings();
+
+ /*
+ * Initializes the data for palette animation within the scene
+ */
+ void initPaletteAnimation(Common::Array<PaletteCycle> &palCycles, bool animFlag);
+
+ /**
+ * Handles a single frame within the game scene
+ */
+ void doFrame();
+
+ void doPreactions();
+
+ void doAction();
+
+ /**
+ * Calls all the necessary step handlers for the current frame
+ */
+ void doSceneStep();
+
+ /**
+ * Checks whether there's a pending keypress, and if so handles it.
+ */
+ void checkKeyboard();
+
+ /**
+ * Checks for a highlighted hotspot, and updates the cursor accordingly
+ */
+ void updateCursor();
+protected:
+ MADSEngine *_vm;
+public:
+ SceneLogic *_sceneLogic;
+ MSurface _sceneSurface;
+ int _priorSceneId;
+ int _nextSceneId;
+ int _currentSceneId;
+ Common::Array<VerbInit> _verbList;
+ TextDisplayList _textDisplay;
+ SpriteSlots _spriteSlots;
+ SpriteSets _sprites;
+ DynamicHotspots _dynamicHotspots;
+ Common::Array<int> _activeVocabs;
+ SequenceList _sequences;
+ KernelMessages _kernelMessages;
+ Rails _rails;
+ Common::String _talkFont;
+ int _textSpacing;
+ Hotspots _hotspots;
+ DirtyAreas _dirtyAreas;
+ int _variant;
+ SceneInfo *_sceneInfo;
+ MSurface _backgroundSurface;
+ DepthSurface _depthSurface;
+ UserInterface _userInterface;
+ bool _cyclingActive;
+ int _cyclingThreshold;
+ int _cyclingDelay;
+ int _totalCycleColors;
+ Common::Array<uint32> _cycleTicks;
+ Common::Array<PaletteCycle> _paletteCycles;
+ Common::StringArray _vocabStrings;
+ Animation *_animationData;
+ Animation *_activeAnimation;
+ bool _freeAnimationFlag;
+ int _depthStyle;
+ int _bandsRange;
+ int _scaleRange;
+ int _interfaceY;
+ int _spritesCount;
+ MADSAction _action;
+ bool _roomChanged;
+ bool _reloadSceneFlag;
+ Common::Point _posAdjust;
+ uint32 _frameStartTime;
+ Layer _layer;
+ bool _lookFlag;
+ Common::Point _customDest;
+ Common::Array<PaletteUsage::UsageEntry> _paletteUsageF;
+ Common::Array<PaletteUsage::UsageEntry> _scenePaletteUsage;
+
+ /**
+ * Constructor
+ */
+ Scene(MADSEngine *vm);
+
+ /**
+ * Destructor
+ */
+ ~Scene();
+
+ void restrictScene();
+
+ /**
+ * Clear the vocabulary list
+ */
+ void clearVocab();
+
+ /**
+ * Add a given vocab entry to the active list
+ */
+ void addActiveVocab(int vocabId);
+
+ /**
+ * Get the number of entries in the game's vocabulary
+ */
+ uint32 getVocabStringsCount() const;
+
+ /**
+ * Clear the sequence list
+ */
+ void clearSequenceList();
+
+ /**
+ * Clear the message list
+ */
+ void clearMessageList();
+
+ /**
+ * Loads the scene logic for a given scene
+ */
+ void loadSceneLogic();
+
+ /**
+ * Loads the resources associated with the given scene
+ * @param sceneId Scene to load
+ * @param prefix Prefix to use for retrieving animation data
+ * @param palFlag Flag for whether to reset the high/lo palette areas
+ */
+ void loadScene(int sceneId, const Common::String &prefix, bool palFlag);
+
+ /**
+ * Loads the hotstpots for the scene
+ */
+ void loadHotspots();
+
+ /**
+ * Loads the vocab list
+ */
+ void loadVocab();
+
+ bool getDepthHighBits(const Common::Point &pt);
+
+ /**
+ * Main scene loop
+ */
+ void loop();
+
+ /**
+ * Draw all the elements onto the scene
+ */
+ void drawElements(ScreenTransition transitionType, bool surfaceFlag);
+
+ /**
+ * Handles cycling palette colors for the scene
+ */
+ void animatePalette();
+
+ /**
+ * Load an animation
+ */
+ void loadAnimation(const Common::String &resName, int trigger = 0);
+
+ /**
+ * Returns a vocab entry
+ */
+ Common::String getVocab(int vocabId) { return _vocabStrings[vocabId - 1]; }
+
+ /**
+ * Clear the data for the currently loaded scene
+ */
+ void freeCurrentScene();
+
+ /**
+ * Set the walk surface for a scene to a different variant
+ */
+ void changeVariant(int variant);
+
+ void resetScene();
+
+ /**
+ * Removes all the scene specific sprites fromt the sprites list,
+ * leaving any player sprites list in place at the start of the list.
+ */
+ void removeSprites();
+
+ /**
+ * Frees any currently active animation for the scene
+ */
+ void freeAnimation();
+
+ /**
+ * Synchronize the game
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_SCENE_H */
diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp
new file mode 100644
index 0000000000..174579a624
--- /dev/null
+++ b/engines/mads/scene_data.cpp
@@ -0,0 +1,480 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/scene_data.h"
+#include "mads/mads.h"
+#include "mads/compression.h"
+#include "mads/screen.h"
+#include "mads/resources.h"
+#include "mads/dragonsphere/dragonsphere_scenes.h"
+#include "mads/nebular/nebular_scenes.h"
+#include "mads/phantom/phantom_scenes.h"
+
+namespace MADS {
+
+KernelMessage::KernelMessage() {
+ _flags = 0;
+ _sequenceIndex = 0;
+ _color1 = 0;
+ _color2 = 0;
+ _msgOffset = 0;
+ _numTicks = 0;
+ _frameTimer2 = 0;
+ _frameTimer = 0;
+ _timeout = 0;
+ _trigger = 0;
+ _abortMode = SEQUENCE_TRIGGER_PARSER;
+ _actionDetails._verbId = VERB_NONE;
+ _actionDetails._objectNameId = 0;
+ _actionDetails._indirectObjectId = 0;
+ _textDisplayIndex = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+void ARTHeader::load(Common::SeekableReadStream *f, bool isV2) {
+ if (!isV2) {
+ // Read in dimensions of image
+ _width = f->readUint16LE();
+ _height = f->readUint16LE();
+ }
+
+ // Read in palette information
+ int palCount = f->readUint16LE();
+ for (int i = 0; i < palCount; ++i) {
+ RGB6 rgb;
+ rgb.load(f);
+ _palette.push_back(rgb);
+ }
+ f->skip(6 * (256 - palCount));
+
+ // Read palette animations
+ int cycleCount = f->readUint16LE();
+ for (int i = 0; i < cycleCount; ++i) {
+ PaletteCycle cycle;
+ cycle._colorCount = f->readByte();
+ cycle._firstListColor = f->readByte();
+ cycle._firstColorIndex = f->readByte();
+ cycle._ticks = f->readByte();
+
+ _paletteCycles.push_back(cycle);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+void SceneInfo::SpriteInfo::load(Common::SeekableReadStream *f) {
+ f->skip(3);
+ _spriteSetIndex = f->readByte();
+ f->skip(2);
+ _position.x = f->readSint16LE();
+ _position.y = f->readSint16LE();
+ _depth = f->readByte();
+ _scale = f->readByte();
+}
+
+/*------------------------------------------------------------------------*/
+
+SceneInfo::SceneInfo(MADSEngine *vm) : _vm(vm) {
+ _sceneId = 0;
+ _artFileNum = 0;
+ _depthStyle = 0;
+ _width = 0;
+ _height = 0;
+ _yBandsEnd = 0;
+ _yBandsStart = 0;
+ _maxScale = 0;
+ _minScale = 0;
+ _field4A = 0;
+ _usageIndex = 0;
+ for (int i = 0; i < 15; ++i)
+ _depthList[i] = 0;
+}
+
+SceneInfo *SceneInfo::init(MADSEngine *vm) {
+ switch (vm->getGameID()) {
+ case GType_RexNebular:
+ return new Nebular::SceneInfoNebular(vm);
+ case GType_Dragonsphere:
+ return new Dragonsphere::SceneInfoDragonsphere(vm);
+ case GType_Phantom:
+ return new Phantom::SceneInfoPhantom(vm);
+ default:
+ error("SceneInfo: Unknown game");
+ }
+
+ return nullptr;
+}
+
+void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
+ int flags, DepthSurface &depthSurface, MSurface &bgSurface) {
+ bool sceneFlag = sceneId >= 0;
+
+ // Figure out the resource to use
+ Common::String resourceName;
+ if (sceneFlag) {
+ resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".DAT");
+ } else {
+ resourceName = "*" + Resources::formatResource(resName, resName);
+ }
+
+ // Open the scene info resource for access
+ File infoFile(resourceName);
+ MadsPack infoPack(&infoFile);
+
+ // Read in basic data
+ Common::SeekableReadStream *infoStream = infoPack.getItemStream(0);
+ if (_vm->getGameID() == GType_RexNebular) {
+ _sceneId = infoStream->readUint16LE();
+ } else {
+ infoStream->skip(6); // actual scene ID (string)
+ _sceneId = sceneId;
+ }
+
+ int nodeCount = 20;
+
+ if (_vm->getGameID() == GType_RexNebular) {
+ _artFileNum = infoStream->readUint16LE();
+ _depthStyle = infoStream->readUint16LE();
+ _width = infoStream->readUint16LE();
+ _height = infoStream->readUint16LE();
+
+ infoStream->skip(24);
+
+ nodeCount = infoStream->readUint16LE();
+ _yBandsEnd = infoStream->readUint16LE();
+ _yBandsStart = infoStream->readUint16LE();
+ _maxScale = infoStream->readUint16LE();
+ _minScale = infoStream->readUint16LE();
+ for (int i = 0; i < DEPTH_BANDS_SIZE; ++i)
+ _depthList[i] = infoStream->readUint16LE();
+ _field4A = infoStream->readUint16LE();
+ } else {
+ _artFileNum = sceneId;
+ _depthStyle = 0;
+ _width = 320;
+ _height = 156;
+
+ infoStream->skip(140);
+ }
+
+ // Load the scene's walk nodes
+ for (int i = 0; i < 20; ++i) {
+ WalkNode node;
+ node.load(infoStream);
+
+ if (i < nodeCount)
+ _nodes.push_back(node);
+ }
+
+ int spriteSetsCount = infoStream->readUint16LE();
+ int spriteInfoCount = infoStream->readUint16LE();
+
+ // Load in sprite sets
+ Common::StringArray setNames;
+ for (int i = 0; i < 10; ++i) {
+ char name[64];
+ infoStream->read(name, 64);
+
+ if (i < spriteSetsCount)
+ setNames.push_back(Common::String(name));
+ }
+
+ // Load in sprite draw information
+ Common::Array<SpriteInfo> spriteInfo;
+ // TODO: The following isn't quite right for V2 games
+ if (_vm->getGameID() == GType_RexNebular) {
+ for (int i = 0; i < 50; ++i) {
+ SpriteInfo info;
+ info.load(infoStream);
+
+ if (i < spriteInfoCount)
+ spriteInfo.push_back(info);
+ }
+ }
+ delete infoStream;
+
+ int width = _width;
+ int height = _height;
+
+ if (!bgSurface.getPixels()) {
+ bgSurface.setSize(width, height);
+ }
+
+ if (_depthStyle == 2)
+ width >>= 2;
+ if (!depthSurface.getPixels()) {
+ depthSurface.setSize(width, height);
+ }
+
+ loadCodes(depthSurface, variant);
+ depthSurface._depthStyle = _depthStyle;
+ infoFile.close();
+
+ if (_vm->getGameID() == GType_RexNebular) {
+ loadMadsV1Background(_sceneId, resName, flags, bgSurface);
+ loadPalette(_sceneId, _artFileNum, resName, flags, bgSurface);
+ } else {
+ loadMadsV2Background(_sceneId, resName, flags, bgSurface);
+ loadPalette(_sceneId, _sceneId, resName, flags, bgSurface);
+ }
+
+ Common::Array<SpriteAsset *> spriteSets;
+ Common::Array<int> usageList;
+
+ // TODO: The following isn't quite right for V2 games
+ if (_vm->getGameID() == GType_RexNebular) {
+ for (uint i = 0; i < setNames.size(); ++i) {
+ Common::String setResName;
+ if (sceneFlag || resName.hasPrefix("*"))
+ setResName += "*";
+ setResName += setNames[i];
+
+ SpriteAsset *sprites = new SpriteAsset(_vm, setResName, flags);
+ spriteSets.push_back(sprites);
+ usageList.push_back(sprites->_usageIndex);
+ }
+ }
+
+ _vm->_palette->_paletteUsage.updateUsage(usageList, _usageIndex);
+
+ for (uint i = 0; i < spriteInfo.size(); ++i) {
+ SpriteInfo &si = spriteInfo[i];
+ SpriteAsset *asset = spriteSets[si._spriteSetIndex];
+ assert(asset && _depthStyle != 2);
+
+ MSprite *spr = asset->getFrame(asset->getCount() - 1);
+ bgSurface.copyFrom(spr, si._position, si._depth, &depthSurface,
+ si._scale, spr->getTransparencyIndex());
+ }
+
+ // Free the sprite sets
+ for (int i = (int)spriteSets.size() - 1; i >= 0; --i) {
+ _vm->_palette->_paletteUsage.resetPalFlags(spriteSets[i]->_usageIndex);
+ delete spriteSets[i];
+ }
+}
+
+void SceneInfo::loadPalette(int sceneId, int artFileNum, const Common::String &resName, int flags, MSurface &bgSurface) {
+ bool sceneFlag = sceneId >= 0;
+ Common::String resourceName;
+ bool isV2 = (_vm->getGameID() != GType_RexNebular);
+ Common::String extension = !isV2 ? ".ART" : ".TT";
+ int paletteStream = !isV2 ? 0 : 2;
+
+ // Get the ART resource
+ if (sceneFlag) {
+ resourceName = Resources::formatName(RESPREFIX_RM, artFileNum, extension);
+ } else {
+ resourceName = "*" + Resources::formatResource(resName, resName);
+ }
+
+ // Load in the ART header and palette
+ File artFile(resourceName);
+ MadsPack artResource(&artFile);
+ Common::SeekableReadStream *stream = artResource.getItemStream(paletteStream);
+
+ ARTHeader artHeader;
+ artHeader.load(stream, isV2);
+ delete stream;
+
+ // Copy out the palette animation data
+ for (uint i = 0; i < artHeader._paletteCycles.size(); ++i)
+ _paletteCycles.push_back(artHeader._paletteCycles[i]);
+
+ if (!(flags & 1)) {
+ if (!_vm->_palette->_paletteUsage.empty()) {
+ _vm->_palette->_paletteUsage.getKeyEntries(artHeader._palette);
+ _vm->_palette->_paletteUsage.prioritize(artHeader._palette);
+ }
+
+ _usageIndex = _vm->_palette->_paletteUsage.process(artHeader._palette,
+ (flags & 0xF800) | 0x8000);
+ if (_usageIndex > 0) {
+ _vm->_palette->_paletteUsage.transform(artHeader._palette);
+
+ for (uint i = 0; i < _paletteCycles.size(); ++i) {
+ byte listColor = _paletteCycles[i]._firstListColor;
+ _paletteCycles[i]._firstColorIndex = artHeader._palette[listColor]._palIndex;
+ }
+ }
+ }
+
+ if (!(flags & 1)) {
+ // Translate the background to use the correct palette indexes
+ bgSurface.translate(artHeader._palette);
+ }
+}
+
+void SceneInfo::loadMadsV1Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface) {
+ bool sceneFlag = sceneId >= 0;
+ Common::String resourceName;
+ Common::SeekableReadStream *stream;
+
+ // Get the ART resource
+ if (sceneFlag) {
+ resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".ART");
+ } else {
+ resourceName = "*" + Resources::formatResource(resName, resName);
+ }
+
+ // Load in the ART data
+ File artFile(resourceName);
+ MadsPack artResource(&artFile);
+
+ // Read in the background surface data
+ assert(_width == bgSurface.w && _height == bgSurface.h);
+ stream = artResource.getItemStream(1);
+ stream->read(bgSurface.getPixels(), bgSurface.w * bgSurface.h);
+ delete stream;
+
+ if (flags & SCENEFLAG_TRANSLATE) {
+ // Load in the palette and translate it
+ Common::SeekableReadStream *palStream = artResource.getItemStream(0);
+ Common::Array<RGB6> palette;
+
+ palStream->skip(4); // Skip width and height
+ int numColors = palStream->readUint16LE();
+ assert(numColors <= 252);
+ palette.resize(numColors);
+ for (int i = 0; i < numColors; ++i)
+ palette[i].load(palStream);
+ delete palStream;
+
+ // Translate the surface
+ _vm->_palette->_paletteUsage.process(palette, 0);
+ bgSurface.translate(palette);
+ }
+
+ // Close the ART file
+ artFile.close();
+}
+
+void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface) {
+ Common::String tileMapResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".MM");
+ File tileMapFile(tileMapResourceName);
+ MadsPack tileMapPack(&tileMapFile);
+ Common::SeekableReadStream *mapStream = tileMapPack.getItemStream(0);
+
+ // Get the details of the tiles and map
+ mapStream->readUint32LE();
+ int tileCountX = mapStream->readUint16LE();
+ int tileCountY = mapStream->readUint16LE();
+ int tileWidthMap = mapStream->readUint16LE();
+ int tileHeightMap = mapStream->readUint16LE();
+ int screenWidth = mapStream->readUint16LE();
+ int screenHeight = mapStream->readUint16LE();
+ int tileCountMap = tileCountX * tileCountY;
+ delete mapStream;
+
+ // Obtain tile map information
+ typedef Common::List<Common::SharedPtr<MSurface> > TileSetList;
+ typedef TileSetList::iterator TileSetIterator;
+ TileSetList tileSet;
+ uint16 *tileMap = new uint16[tileCountMap];
+ mapStream = tileMapPack.getItemStream(1);
+ for (int i = 0; i < tileCountMap; ++i)
+ tileMap[i] = mapStream->readUint16LE();
+ delete mapStream;
+ tileMapFile.close();
+
+ // --------------------------------------------------------------------------------
+
+ // Tile data, which needs to be kept compressed, as the tile map offsets refer to
+ // the compressed data. Each tile is then uncompressed separately
+ Common::String tileDataResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".TT");
+ File tileDataFile(tileDataResourceName);
+ MadsPack tileDataPack(&tileDataFile);
+ Common::SeekableReadStream *tileDataUncomp = tileDataPack.getItemStream(0);
+
+ // Validate that the data matches between the tiles and tile map file and is valid
+ int tileCount = tileDataUncomp->readUint16LE();
+ int tileWidth = tileDataUncomp->readUint16LE();
+ int tileHeight = tileDataUncomp->readUint16LE();
+ delete tileDataUncomp;
+ assert(tileCountMap == tileCount);
+ assert(tileWidth == tileWidthMap);
+ assert(tileHeight == tileHeightMap);
+ assert(screenWidth == _width);
+ assert(screenHeight <= _height);
+
+ // --------------------------------------------------------------------------------
+
+ // Get tile data
+
+ tileDataUncomp = tileDataPack.getItemStream(1);
+ FabDecompressor fab;
+ uint32 compressedTileDataSize = 0;
+
+ for (int i = 0; i < tileCount; i++) {
+ tileDataUncomp->seek(i * 4, SEEK_SET);
+ uint32 tileOfs = tileDataUncomp->readUint32LE();
+ MSurface* newTile = new MSurface(tileWidth, tileHeight);
+
+ if (i == tileCount - 1)
+ compressedTileDataSize = tileDataFile.size() - tileOfs;
+ else
+ compressedTileDataSize = tileDataUncomp->readUint32LE() - tileOfs;
+
+ //debugCN(kDebugGraphics, "Tile: %i, compressed size: %i\n", i, compressedTileDataSize);
+
+ newTile->empty();
+
+ byte *compressedTileData = new byte[compressedTileDataSize];
+
+ tileDataFile.seek(tileDataPack.getDataOffset() + tileOfs, SEEK_SET);
+ tileDataFile.read(compressedTileData, compressedTileDataSize);
+
+ fab.decompress(compressedTileData, compressedTileDataSize, (byte*)newTile->getPixels(), tileWidth * tileHeight);
+ tileSet.push_back(TileSetList::value_type(newTile));
+ delete[] compressedTileData;
+ }
+
+ delete tileDataUncomp;
+
+ // --------------------------------------------------------------------------------
+
+ // Loop through the mapping data to place the tiles on the screen
+
+ uint16 *tIndex = &tileMap[0];
+ for (int y = 0; y < tileCountY; y++) {
+ for (int x = 0; x < tileCountX; x++) {
+ int tileIndex = *tIndex++;
+ assert(tileIndex < tileCount);
+ TileSetIterator tile = tileSet.begin();
+ for (int i = 0; i < tileIndex; i++)
+ ++tile;
+ ((*tile).get())->copyTo(&bgSurface, Common::Point(x * tileWidth, y * tileHeight));
+ }
+ }
+ tileSet.clear();
+ tileDataFile.close();
+}
+
+/*------------------------------------------------------------------------*/
+
+SceneLogic::SceneLogic(MADSEngine *vm) : _vm(vm) {
+ _scene = &_vm->_game->_scene;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/scene_data.h b/engines/mads/scene_data.h
new file mode 100644
index 0000000000..41e094b8f5
--- /dev/null
+++ b/engines/mads/scene_data.h
@@ -0,0 +1,225 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_SCENE_DATA_H
+#define MADS_SCENE_DATA_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/serializer.h"
+#include "common/str.h"
+#include "common/str-array.h"
+#include "common/rect.h"
+#include "mads/action.h"
+#include "mads/assets.h"
+#include "mads/events.h"
+#include "mads/game_data.h"
+#include "mads/hotspots.h"
+#include "mads/messages.h"
+#include "mads/rails.h"
+#include "mads/user_interface.h"
+
+namespace MADS {
+
+class MADSEngine;
+class Scene;
+class SpriteSlot;
+
+#define MADS_INTERFACE_HEIGHT 44
+#define MADS_SCENE_HEIGHT 156
+
+#define DEPTH_BANDS_SIZE 15
+
+#define SPRITE_SLOTS_MAX_SIZE 50
+#define TEXT_DISPLAY_MAX_SIZE 40
+#define DIRTY_AREAS_SIZE (SPRITE_SLOTS_MAX_SIZE + TEXT_DISPLAY_MAX_SIZE)
+
+enum {
+ SCENEFLAG_DITHER = 0x01, // Dither to 16 colors
+ SCENEFLAG_LOAD_SHADOW = 0x10, // Load hard shadows
+ SCENEFLAG_TRANSLATE = 0x10000 // Translate palette of loaded background
+};
+
+class VerbInit {
+public:
+ int _id;
+ VerbType _verbType;
+ PrepType _prepType;
+
+ VerbInit() {}
+ VerbInit(int id, VerbType verbType, PrepType prepType)
+ : _id(id), _verbType(verbType), _prepType(prepType) {
+ }
+};
+
+class SceneLogic {
+protected:
+ MADSEngine *_vm;
+ Scene *_scene;
+public:
+ /**
+ * Constructor
+ */
+ SceneLogic(MADSEngine *vm);
+
+ /**
+ * Destructor
+ */
+ virtual ~SceneLogic() {}
+
+ /**
+ * Called to initially setup a scene
+ */
+ virtual void setup() = 0;
+
+ /**
+ * Called as the scene is entered (made active)
+ */
+ virtual void enter() = 0;
+
+ /**
+ * Called one per frame
+ */
+ virtual void step() {}
+
+ /**
+ * Called before an action is started
+ */
+ virtual void preActions() {}
+
+ /**
+ * Handles scene actions
+ */
+ virtual void actions() = 0;
+
+ /**
+ * Post-action handling
+ */
+ virtual void postActions() {}
+
+ /**
+ * Unhandled action handling
+ */
+ virtual void unhandledAction() {}
+
+ /**
+ * Synchronize any local data for the scene
+ */
+ virtual void synchronize(Common::Serializer &s) {}
+};
+
+struct ARTHeader {
+ int _width;
+ int _height;
+ Common::Array<RGB6> _palette;
+ Common::Array<PaletteCycle> _paletteCycles;
+
+ void load(Common::SeekableReadStream *f, bool isV2);
+};
+
+/**
+ * Handles general data for a given scene
+ */
+class SceneInfo {
+ class SpriteInfo {
+ public:
+ int _spriteSetIndex;
+ Common::Point _position;
+ int _depth;
+ int _scale;
+
+ void load(Common::SeekableReadStream *f);
+ };
+protected:
+ MADSEngine *_vm;
+
+ /**
+ * Constructor
+ */
+ SceneInfo(MADSEngine *vm);
+public:
+ int _sceneId;
+ int _artFileNum;
+ int _depthStyle;
+ int _width;
+ int _height;
+
+ int _yBandsEnd;
+ int _yBandsStart;
+ int _maxScale;
+ int _minScale;
+ int _depthList[DEPTH_BANDS_SIZE];
+ int _field4A; // Useless field ?
+
+ int _usageIndex;
+ Common::Array<PaletteCycle> _paletteCycles;
+ WalkNodeList _nodes;
+public:
+ /**
+ * Destructor
+ */
+ virtual ~SceneInfo() {}
+
+ /**
+ * Instantiates the class
+ */
+ static SceneInfo *init(MADSEngine *vm);
+
+ /**
+ * loads the data
+ */
+ void load(int sceneId, int variant, const Common::String &resName, int flags,
+ DepthSurface &depthSurface, MSurface &bgSurface);
+
+ /**
+ * Loads the palette for a scene
+ */
+ void loadPalette(int sceneId, int artFileNum, const Common::String &resName, int flags, MSurface &bgSurface);
+
+ /**
+ * Loads a V1 game background
+ */
+ void loadMadsV1Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface);
+
+ /**
+ * Loads a V2 game background
+ */
+ void loadMadsV2Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface);
+
+ /**
+ * Loads the given surface with depth information of a given scene
+ * @param depthSurface Depth/walk surface
+ * @param variant Variant number to load
+ */
+ virtual void loadCodes(MSurface &depthSurface, int variant) = 0;
+
+ /**
+ * Loads the given surface with depth information of a given scene
+ * @param depthSurface Depth/walk surface
+ * @param stream Stream to load the data from
+ */
+ virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) = 0;
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_SCENE_DATA_H */
diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp
new file mode 100644
index 0000000000..590e63ac9e
--- /dev/null
+++ b/engines/mads/screen.cpp
@@ -0,0 +1,678 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/game.h"
+#include "mads/screen.h"
+#include "mads/palette.h"
+#include "mads/user_interface.h"
+
+namespace MADS {
+
+MADSEngine *DirtyArea::_vm = nullptr;
+
+DirtyArea::DirtyArea() {
+ _active = false;
+ _textActive = false;
+ _mergedArea = nullptr;
+}
+
+void DirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) {
+ if (_bounds.left % 2) {
+ --_bounds.left;
+ ++width;
+ }
+
+ if (_bounds.left < 0)
+ _bounds.left = 0;
+ else if (_bounds.left > maxWidth)
+ _bounds.left = maxWidth;
+ int right = _bounds.left + width;
+ if (right < 0)
+ right = 0;
+ if (right > maxWidth)
+ right = maxWidth;
+
+ _bounds.right = right;
+
+ if (_bounds.top < 0)
+ _bounds.top = 0;
+ else if (_bounds.top > maxHeight)
+ _bounds.top = maxHeight;
+ int bottom = _bounds.top + height;
+ if (bottom < 0)
+ bottom = 0;
+ if (bottom > maxHeight)
+ bottom = maxHeight;
+
+ _bounds.bottom = bottom;
+ _active = true;
+}
+
+
+void DirtyArea::setSpriteSlot(const SpriteSlot *spriteSlot) {
+ int width, height;
+ Scene &scene = _vm->_game->_scene;
+
+ if (spriteSlot->_flags == IMG_REFRESH) {
+ // Special entry to refresh the entire screen
+ _bounds.left = 0;
+ _bounds.top = 0;
+ width = MADS_SCREEN_WIDTH;
+ height = MADS_SCENE_HEIGHT;
+ } else {
+ // Standard sprite slots
+ _bounds.left = spriteSlot->_position.x - scene._posAdjust.x;
+ _bounds.top = spriteSlot->_position.y - scene._posAdjust.y;
+
+ SpriteAsset &spriteSet = *scene._sprites[spriteSlot->_spritesIndex];
+ MSprite *frame = spriteSet.getFrame(ABS(spriteSlot->_frameNumber) - 1);
+
+ if (spriteSlot->_scale == -1) {
+ width = frame->w;
+ height = frame->h;
+ } else {
+ width = frame->w * spriteSlot->_scale / 100;
+ height = frame->h * spriteSlot->_scale / 100;
+
+ _bounds.left -= width / 2;
+ _bounds.top += -(height - 1);
+ }
+ }
+
+ setArea(width, height, MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+}
+
+void DirtyArea::setTextDisplay(const TextDisplay *textDisplay) {
+ _bounds.left = textDisplay->_bounds.left;
+ _bounds.top = textDisplay->_bounds.top;
+
+ setArea(textDisplay->_bounds.width(), textDisplay->_bounds.height(),
+ MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+}
+
+void DirtyArea::setUISlot(const UISlot *slot) {
+ int type = slot->_flags;
+ if (type <= IMG_UPDATE_ONLY)
+ type += -IMG_UPDATE_ONLY;
+ if (type >= 0x40)
+ type &= ~0x40;
+
+ MSurface &intSurface = _vm->_game->_scene._userInterface;
+ switch (type) {
+ case IMG_REFRESH:
+ _bounds.left = 0;
+ _bounds.top = 0;
+ setArea(intSurface.w, intSurface.h, intSurface.w, intSurface.h);
+ break;
+
+ case IMG_OVERPRINT:
+ _bounds.left = slot->_position.x;
+ _bounds.top = slot->_position.y;
+ _bounds.setWidth(slot->_width);
+ _bounds.setHeight(slot->_height);
+ setArea(slot->_width, slot->_height, intSurface.w, intSurface.h);
+ break;
+
+ default: {
+ SpriteAsset *asset = _vm->_game->_scene._sprites[slot->_spritesIndex];
+ MSprite *frame = asset->getFrame(slot->_frameNumber - 1);
+ int w = frame->w;
+ int h = frame->h;
+
+ if (slot->_segmentId == IMG_SPINNING_OBJECT) {
+ _bounds.left = slot->_position.x;
+ _bounds.top = slot->_position.y;
+ } else {
+ _bounds.left = slot->_position.x + w / 2;
+ _bounds.top = slot->_position.y - h + 1;
+ }
+
+ setArea(w, h, intSurface.w, intSurface.h);
+ break;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+DirtyAreas::DirtyAreas(MADSEngine *vm) : _vm(vm) {
+ DirtyArea::_vm = vm;
+
+ for (int i = 0; i < DIRTY_AREAS_SIZE; ++i) {
+ DirtyArea rec;
+ rec._active = false;
+ push_back(rec);
+ }
+}
+
+void DirtyAreas::merge(int startIndex, int count) {
+ if (startIndex >= count)
+ return;
+
+ for (int outerCtr = startIndex - 1, idx = 0; idx < count; ++outerCtr, ++idx) {
+ if (!(*this)[outerCtr]._active)
+ continue;
+
+ for (int innerCtr = outerCtr + 1; innerCtr < count; ++innerCtr) {
+ if (!(*this)[innerCtr]._active || !intersects(outerCtr, innerCtr))
+ continue;
+
+ if ((*this)[outerCtr]._textActive && (*this)[innerCtr]._textActive)
+ mergeAreas(innerCtr, outerCtr);
+ }
+ }
+}
+
+/**
+* Returns true if two dirty areas intersect
+*/
+bool DirtyAreas::intersects(int idx1, int idx2) {
+ return (*this)[idx1]._bounds.intersects((*this)[idx2]._bounds);
+}
+
+void DirtyAreas::mergeAreas(int idx1, int idx2) {
+ DirtyArea &da1 = (*this)[idx1];
+ DirtyArea &da2 = (*this)[idx2];
+
+ da1._bounds.extend(da2._bounds);
+
+ da2._active = false;
+ da2._mergedArea = &da1;
+ da1._textActive = true;
+}
+
+void DirtyAreas::copy(MSurface *srcSurface, MSurface *destSurface, const Common::Point &posAdjust) {
+ for (uint i = 0; i < size(); ++i) {
+ const Common::Rect &srcBounds = (*this)[i]._bounds;
+
+ // Check if this is a sane rectangle before attempting to create it
+ if (srcBounds.left >= srcBounds.right || srcBounds.top >= srcBounds.bottom)
+ continue;
+
+ Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y,
+ srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y);
+ Common::Point destPos(bounds.left, bounds.top);
+
+ if ((*this)[i]._active && bounds.isValidRect()) {
+ srcSurface->copyTo(destSurface, bounds, destPos);
+ }
+ }
+}
+
+void DirtyAreas::copyToScreen() {
+ for (uint i = 0; i < size(); ++i) {
+ const Common::Rect &bounds = (*this)[i]._bounds;
+
+ // Check if this is a sane rectangle before attempting to create it
+ if (bounds.left >= bounds.right || bounds.top >= bounds.bottom)
+ continue;
+
+ if ((*this)[i]._active && (*this)[i]._bounds.isValidRect()) {
+ _vm->_screen.copyRectToScreen(bounds);
+ }
+ }
+}
+
+void DirtyAreas::reset() {
+ for (uint i = 0; i < size(); ++i)
+ (*this)[i]._active = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+ScreenObject::ScreenObject() {
+ _category = CAT_NONE;
+ _descId = 0;
+ _layer = 0;
+ _active = false;
+}
+
+/*------------------------------------------------------------------------*/
+
+ScreenObjects::ScreenObjects(MADSEngine *vm) : _vm(vm) {
+ _objectY = -1;
+ _forceRescan = false;
+ _inputMode = kInputBuildingSentences;
+ _v7FED6 = 0;
+ _v8332A = 0;
+ _category = CAT_NONE;
+ _spotId = 0;
+ _released = false;
+ _uiCount = 0;
+ _selectedObject = -1;
+ _eventFlag = false;
+ _baseTime = 0;
+}
+
+void ScreenObjects::add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId) {
+ //assert(size() < 100);
+
+ ScreenObject so;
+ so._bounds = bounds;
+ so._category = category;
+ so._descId = descId;
+ so._layer = layer;
+ so._active = true;
+
+ push_back(so);
+}
+
+void ScreenObjects::check(bool scanFlag) {
+ Scene &scene = _vm->_game->_scene;
+ UserInterface &userInterface = scene._userInterface;
+
+ if (!_vm->_events->_mouseButtons || _inputMode != kInputBuildingSentences)
+ _vm->_events->_rightMousePressed = false;
+
+ if ((_vm->_events->_mouseMoved || userInterface._scrollbarActive
+ || _v8332A || _forceRescan) && scanFlag) {
+ _category = CAT_NONE;
+ _selectedObject = scanBackwards(_vm->_events->currentPos(), LAYER_GUI);
+ if (_selectedObject > 0) {
+ ScreenObject &scrObject = (*this)[_selectedObject];
+ _category = (ScrCategory)(scrObject._category & 7);
+ _spotId = scrObject._descId;
+ }
+
+ // Handling for easy mouse
+ ScrCategory category = scene._userInterface._category;
+ if (_vm->_easyMouse && _vm->_events->_mouseButtons && category != _category
+ && scene._userInterface._category != CAT_NONE) {
+ _released = true;
+ if (category >= CAT_COMMAND && category <= CAT_TALK_ENTRY) {
+ elementHighlighted();
+ }
+
+ scene._action.checkActionAtMousePos();
+ }
+
+ //_released = _vm->_events->_mouseReleased;
+ if (_vm->_events->_vD2 || (_vm->_easyMouse && !_vm->_events->_mouseStatusCopy))
+ scene._userInterface._category = _category;
+
+ if (!_vm->_events->_mouseButtons || _vm->_easyMouse) {
+ if (userInterface._category >= CAT_COMMAND && userInterface._category <= CAT_TALK_ENTRY) {
+ elementHighlighted();
+ }
+ }
+
+ if (_vm->_events->_mouseButtons || (_vm->_easyMouse && scene._action._interAwaiting > AWAITING_COMMAND
+ && scene._userInterface._category == CAT_INV_LIST) ||
+ (_vm->_easyMouse && scene._userInterface._category == CAT_HOTSPOT)) {
+ scene._action.checkActionAtMousePos();
+ }
+
+ if (_vm->_events->_mouseReleased) {
+ scene._action.leftClick();
+ scene._userInterface._category = CAT_NONE;
+ }
+
+ if (_vm->_events->_mouseButtons || _vm->_easyMouse || userInterface._scrollbarActive)
+ scene._userInterface.updateInventoryScroller();
+
+ if (_vm->_events->_mouseButtons || _vm->_easyMouse)
+ scene._action.set();
+
+ _forceRescan = false;
+ }
+
+ scene._action.refresh();
+
+ uint32 currentTicks = _vm->_events->getFrameCounter();
+ if (currentTicks >= _baseTime) {
+ // Check the user interface slots to see if there's any slots that need to be expired
+ UISlots &uiSlots = userInterface._uiSlots;
+ for (uint idx = 0; idx < uiSlots.size(); ++idx) {
+ UISlot &slot = uiSlots[idx];
+
+ if (slot._flags != IMG_REFRESH && slot._flags > IMG_UPDATE_ONLY
+ && slot._segmentId != IMG_SPINNING_OBJECT)
+ slot._flags = IMG_ERASE;
+ }
+
+ // Any background animation in the user interface
+ userInterface.doBackgroundAnimation();
+
+ // Handle animating the selected inventory item
+ userInterface.inventoryAnim();
+
+ // Set the base time
+ _baseTime = currentTicks + 6;
+ }
+}
+
+int ScreenObjects::scan(const Common::Point &pt, int layer) {
+ for (uint i = 1; i <= size(); ++i) {
+ ScreenObject &sObj = (*this)[i];
+ if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer)
+ return i;
+ }
+
+ // Entry not found
+ return 0;
+}
+
+int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) {
+ for (int i = (int)size(); i >= 1; --i) {
+ ScreenObject &sObj = (*this)[i];
+ if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer)
+ return i;
+ }
+
+ // Entry not found
+ return 0;
+}
+
+void ScreenObjects::elementHighlighted() {
+ Scene &scene = _vm->_game->_scene;
+ UserInterface &userInterface = scene._userInterface;
+ Common::Array<int> &invList = _vm->_game->_objects._inventoryList;
+ MADSAction &action = scene._action;
+ int varA;
+ int topIndex;
+ int *idxP;
+ int var4;
+ int index;
+ int indexEnd = -1;
+ int var8 = 0;
+ int uiCount;
+
+ switch (userInterface._category) {
+ case CAT_COMMAND:
+ index = 10;
+ indexEnd = 9;
+ varA = 5;
+ topIndex = 0;
+ idxP = !_vm->_events->_rightMousePressed ? &userInterface._highlightedCommandIndex :
+ &userInterface._selectedActionIndex;
+
+ if (_vm->_events->_rightMousePressed && userInterface._selectedItemVocabIdx >= 0)
+ userInterface.updateSelection(CAT_INV_VOCAB, -1, &userInterface._selectedItemVocabIdx);
+
+ var4 = _released && !_vm->_events->_rightMousePressed ? 1 : 0;
+ break;
+
+ case CAT_INV_LIST:
+ userInterface.scrollInventory();
+
+ index = MIN((int)invList.size() - userInterface._inventoryTopIndex, 5);
+ indexEnd = invList.size() - 1;
+ varA = 0;
+ topIndex = userInterface._inventoryTopIndex;
+ idxP = &userInterface._highlightedInvIndex;
+ var4 = (!_released || (_vm->_events->_mouseButtons && action._interAwaiting == 1)) ? 0 : 1;
+ break;
+
+ case CAT_INV_VOCAB:
+ if (userInterface._selectedInvIndex >= 0) {
+ InventoryObject &invObject = _vm->_game->_objects.getItem(
+ userInterface._selectedInvIndex);
+ index = invObject._vocabCount;
+ indexEnd = index - 1;
+ } else {
+ index = 0;
+ }
+
+ varA = 0;
+ topIndex = 0;
+ idxP = _vm->_events->_rightMousePressed ? &userInterface._selectedItemVocabIdx : &userInterface._highlightedItemVocabIndex;
+
+ if (_vm->_events->_rightMousePressed && userInterface._selectedActionIndex >= 0)
+ userInterface.updateSelection(CAT_COMMAND, -1, &userInterface._selectedActionIndex);
+
+ var4 = _released && !_vm->_events->_rightMousePressed ? 1 : 0;
+ break;
+
+ case CAT_INV_ANIM:
+ index = 1;
+ indexEnd = invList.size() - 1;
+ varA = 0;
+ topIndex = userInterface._selectedInvIndex;
+ idxP = &var8;
+ var4 = -1;
+ break;
+
+ case CAT_TALK_ENTRY:
+ index = userInterface._talkStrings.size();
+ indexEnd = index - 1;
+ varA = 0;
+ topIndex = 0;
+ idxP = &userInterface._highlightedCommandIndex;
+ var4 = -1;
+ break;
+
+ default:
+ uiCount = size() - _uiCount;
+ index = uiCount + scene._hotspots.size();
+ indexEnd = index - 1;
+ varA = 0;
+ topIndex = 0;
+ idxP = &var8;
+ var4 = -1;
+ break;
+ }
+
+ int newIndex = -1;
+ int catIndex = userInterface._categoryIndexes[userInterface._category - 1];
+ int newX = 0, newY = 0;
+ Common::Point currentPos = _vm->_events->currentPos();
+
+ for (int idx = 0; idx < index && newIndex < 0; ++idx) {
+ int scrObjIndex = (_category == CAT_HOTSPOT) ? catIndex - idx + index - 1 :
+ catIndex + idx;
+
+ ScreenObject &scrObject = (*this)[scrObjIndex];
+ if (!scrObject._active)
+ continue;
+
+ const Common::Rect &bounds = scrObject._bounds;
+ newY = MAX((int)bounds.bottom, newY);
+ newX = MAX((int)bounds.left, newX);
+
+ if (currentPos.y >= bounds.top && currentPos.y < bounds.bottom) {
+ if (var4) {
+ if (currentPos.x >= bounds.left && currentPos.x < bounds.right) {
+ // Cursor is inside hotspot bounds
+ newIndex = scrObjIndex - catIndex;
+ if (_category == CAT_HOTSPOT && newIndex < (int)scene._hotspots.size())
+ newIndex = scene._hotspots.size() - newIndex - 1;
+ }
+ } else if (!varA) {
+ newIndex = idx;
+ } else if (varA <= idx) {
+ if (currentPos.x > bounds.left)
+ newIndex = idx;
+ } else {
+ if (currentPos.x < bounds.right)
+ newIndex = idx;
+ }
+ }
+ }
+
+ if (newIndex == -1 && index > 0 && !var4) {
+ if (_vm->_events->currentPos().y <= newY) {
+ newIndex = 0;
+ if (varA && _vm->_events->currentPos().x >= newX)
+ newIndex = varA;
+ } else {
+ newIndex = index - 1;
+ }
+ }
+
+ if (newIndex >= 0)
+ newIndex = MIN(newIndex + topIndex, indexEnd);
+
+ action._pickedWord = newIndex;
+
+ if (_category == CAT_INV_LIST || _category == CAT_INV_ANIM) {
+ if (action._interAwaiting == 1 && newIndex >= 0 && _released &&
+ (!_vm->_events->_mouseReleased || !_vm->_easyMouse))
+ newIndex = -1;
+ }
+
+ if (_released && !_vm->_events->_rightMousePressed &&
+ (_vm->_events->_mouseReleased || !_vm->_easyMouse))
+ newIndex = -1;
+
+ if (_category != CAT_HOTSPOT && _category != CAT_INV_ANIM)
+ userInterface.updateSelection(_category, newIndex, idxP);
+}
+
+void ScreenObjects::setActive(ScrCategory category, int descId, bool active) {
+ for (uint idx = 1; idx < size(); ++idx) {
+ ScreenObject &sObj = (*this)[idx];
+ if (sObj._category == category && sObj._descId == descId)
+ sObj._active = active;
+ }
+}
+
+void ScreenObjects::synchronize(Common::Serializer &s) {
+ s.syncAsSint16LE(_selectedObject);
+ s.syncAsSint16LE(_category);
+}
+
+/*------------------------------------------------------------------------*/
+
+ScreenSurface::ScreenSurface() {
+ _shakeCountdown = -1;
+ _random = 0x4D2;
+ _surfacePixels = nullptr;
+}
+
+void ScreenSurface::init() {
+ // Set the size for the screen
+ setSize(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
+
+ // Store a copy of the raw pixels pointer for the screen, since the surface
+ // itself may be later changed to only a subset of the screen
+ _surfacePixels = (byte *)getPixels();
+ _freeFlag = false;
+}
+
+ScreenSurface::~ScreenSurface() {
+ delete[] _surfacePixels;
+}
+
+void ScreenSurface::copyRectToScreen(const Common::Rect &bounds) {
+ const byte *buf = getBasePtr(bounds.left, bounds.top);
+
+ Common::Rect destBounds = bounds;
+ destBounds.translate(_clipBounds.left, _clipBounds.top);
+
+ if (bounds.width() != 0 && bounds.height() != 0)
+ g_system->copyRectToScreen(buf, this->pitch, destBounds.left, destBounds.top,
+ destBounds.width(), destBounds.height());
+}
+
+void ScreenSurface::updateScreen() {
+ if (_shakeCountdown >= 0) {
+ _random = _random * 5 + 1;
+ int offset = (_random >> 8) & 3;
+ if (_shakeCountdown-- <= 0)
+ offset = 0;
+
+ // Copy the screen with the left hand hide side of the screen of a given
+ // offset width shown at the very right. The offset changes to give
+ // an effect of shaking the screen
+ offset *= 4;
+ const byte *buf = getBasePtr(offset, 0);
+ g_system->copyRectToScreen(buf, this->pitch, 0, 0,
+ this->pitch - offset, this->h);
+ if (offset > 0)
+ g_system->copyRectToScreen(this->pixels, this->pitch,
+ this->pitch - offset, 0, offset, this->h);
+ }
+
+ g_system->updateScreen();
+}
+
+void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) {
+ Palette &pal = *_vm->_palette;
+ byte palData[PALETTE_SIZE];
+
+ switch (transitionType) {
+ case kTransitionFadeIn:
+ case kTransitionFadeOutIn:
+ Common::fill(&pal._colorValues[0], &pal._colorValues[3], 0);
+ Common::fill(&pal._colorFlags[0], &pal._colorFlags[3], false);
+
+ if (transitionType == kTransitionFadeOutIn) {
+ // Fade out
+ pal.getFullPalette(palData);
+ pal.fadeOut(palData, nullptr, 0, PALETTE_COUNT, 0, 0, 1, 16);
+ }
+
+ // Reset palette to black
+ Common::fill(&palData[0], &palData[PALETTE_SIZE], 0);
+ pal.setFullPalette(palData);
+
+ copyRectToScreen(getBounds());
+ pal.fadeIn(palData, pal._mainPalette, 0, 256, 0, 1, 1, 16);
+ break;
+
+ case kTransitionBoxInBottomLeft:
+ case kTransitionBoxInBottomRight:
+ case kTransitionBoxInTopLeft:
+ case kTransitionBoxInTopRight:
+ warning("TODO: box transition");
+ transition(kTransitionFadeIn, surfaceFlag);
+ break;
+
+ case kTransitionPanLeftToRight:
+ case kTransitionPanRightToLeft:
+ warning("TODO: pan transition");
+ transition(kTransitionFadeIn, surfaceFlag);
+ break;
+
+ case kTransitionCircleIn1:
+ case kTransitionCircleIn2:
+ case kTransitionCircleIn3:
+ case kTransitionCircleIn4:
+ warning("TODO circle transition");
+ transition(kTransitionFadeIn, surfaceFlag);
+ break;
+
+ case kCenterVertTransition:
+ warning("TODO: center vert transition");
+ transition(kTransitionFadeIn, surfaceFlag);
+ break;
+
+ default:
+ // Quick transitions
+ break;
+ }
+}
+
+void ScreenSurface::setClipBounds(const Common::Rect &r) {
+ _clipBounds = r;
+ setPixels(_surfacePixels + pitch * r.top + r.left, r.width(), r.height());
+ this->pitch = MADS_SCREEN_WIDTH;
+}
+
+void ScreenSurface::resetClipBounds() {
+ setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
+}
+
+
+} // End of namespace MADS
diff --git a/engines/mads/screen.h b/engines/mads/screen.h
new file mode 100644
index 0000000000..9d01ca82e3
--- /dev/null
+++ b/engines/mads/screen.h
@@ -0,0 +1,250 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_SCREEN_H
+#define MADS_SCREEN_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "mads/msurface.h"
+#include "mads/action.h"
+
+namespace MADS {
+
+#define MADS_SCREEN_WIDTH 320
+#define MADS_SCREEN_HEIGHT 200
+
+enum Layer {
+ LAYER_GUI = 19
+};
+
+enum ScreenTransition {
+ kTransitionNone = 0,
+ kTransitionFadeIn, kTransitionFadeOutIn,
+ kTransitionBoxInBottomLeft, kTransitionBoxInBottomRight,
+ kTransitionBoxInTopLeft, kTransitionBoxInTopRight,
+ kTransitionPanLeftToRight, kTransitionPanRightToLeft,
+ kTransitionCircleIn1, kTransitionCircleIn2,
+ kTransitionCircleIn3, kTransitionCircleIn4,
+ kVertTransition1, kVertTransition2, kVertTransition3,
+ kVertTransition4, kVertTransition5, kVertTransition6,
+ kVertTransition7, kCenterVertTransition
+};
+
+enum InputMode {
+ kInputBuildingSentences = 0, // Normal sentence building
+ kInputConversation = 1, // Conversation mode
+ kInputLimitedSentences = 2 // Use only scene hotspots
+};
+
+class SpriteSlot;
+class TextDisplay;
+class UISlot;
+
+class DirtyArea {
+private:
+ static MADSEngine *_vm;
+ friend class DirtyAreas;
+public:
+ Common::Rect _bounds;
+ bool _textActive;
+ bool _active;
+ DirtyArea *_mergedArea;
+
+ DirtyArea();
+
+ void setArea(int width, int height, int maxWidth, int maxHeight);
+
+ /**
+ * Set up a dirty area for a sprite slot
+ */
+ void setSpriteSlot(const SpriteSlot *spriteSlot);
+
+ /**
+ * Set up a dirty area for a text display
+ */
+ void setTextDisplay(const TextDisplay *textDisplay);
+
+ /**
+ * Set up a dirty area for a UI slot
+ */
+ void setUISlot(const UISlot *slot);
+};
+
+class DirtyAreas : public Common::Array<DirtyArea> {
+private:
+ MADSEngine *_vm;
+public:
+ DirtyAreas(MADSEngine *vm);
+
+ /**
+ * Merge together any designated dirty areas that overlap
+ * @param startIndex 1-based starting dirty area starting index
+ * @param count Number of entries to process
+ */
+ void merge(int startIndex, int count);
+
+ bool intersects(int idx1, int idx2);
+ void mergeAreas(int idx1, int idx2);
+
+ /**
+ * Copy the data specified by the dirty rect list between surfaces
+ * @param srcSurface Source surface
+ * @param destSurface Dest surface
+ * @param posAdjust Position adjustment
+ */
+ void copy(MSurface *srcSurface, MSurface *destSurface, const Common::Point &posAdjust);
+
+ /**
+ * Use the lsit of dirty areas to copy areas of the screen surface to
+ * the physical screen
+ */
+ void copyToScreen();
+
+ void reset();
+};
+
+
+class ScreenObject {
+public:
+ bool _active;
+ Common::Rect _bounds;
+ ScrCategory _category;
+ int _descId;
+ int _layer;
+
+ ScreenObject();
+};
+
+class ScreenObjects : public Common::Array<ScreenObject> {
+private:
+ MADSEngine *_vm;
+ int _objectY;
+
+ int scanBackwards(const Common::Point &pt, int layer);
+public:
+ InputMode _inputMode;
+ int _v7FED6;
+ int _v8332A;
+ int _forceRescan;
+ int _selectedObject;
+ ScrCategory _category;
+ bool _released;
+ int _uiCount;
+ bool _eventFlag;
+ uint32 _baseTime;
+ int _spotId;
+
+ /*
+ * Constructor
+ */
+ ScreenObjects(MADSEngine *vm);
+
+ /**
+ * Add a new item to the list
+ */
+ void add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId);
+
+ /**
+ * Check objects on the screen
+ */
+ void check(bool scanFlag);
+
+ /**
+ * Scan the registered screen objects
+ */
+ int scan(const Common::Point &pt, int layer);
+
+ /**
+ * Handle an element being highlighted on the screen, and make it active.
+ */
+ void elementHighlighted();
+
+ /**
+ * Retrieve a ScreenObject from the list
+ * @remarks This array is 1-based indexed by the game
+ */
+ ScreenObject &operator[](int idx) {
+ assert(idx > 0);
+ return Common::Array<ScreenObject>::operator[](idx - 1);
+ }
+
+ /**
+ * Sets an item identified by category and Desc Id as active or not
+ * @param category Screen category
+ * @param descId Description for item
+ * @param active Whether to set item as active or not
+ */
+ void setActive(ScrCategory category, int descId, bool active);
+
+ /**
+ * Synchronize the data
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+class ScreenSurface : public MSurface {
+private:
+ uint16 _random;
+ byte *_surfacePixels;
+ Common::Rect _clipBounds;
+public:
+ int _shakeCountdown;
+public:
+ /**
+ * Constructor
+ */
+ ScreenSurface();
+
+ /**
+ * Destructor
+ */
+ ~ScreenSurface();
+
+ /**
+ * Initialize the surface
+ */
+ void init();
+
+ /**
+ * Copys an area of the screen surface to the ScmmVM physical screen buffer
+ * @param bounds Area of screen surface to copy
+ */
+ void copyRectToScreen(const Common::Rect &bounds);
+
+ /**
+ * Updates the screen with the contents of the surface
+ */
+ void updateScreen();
+
+ void transition(ScreenTransition transitionType, bool surfaceFlag);
+
+ void setClipBounds(const Common::Rect &r);
+
+ void resetClipBounds();
+
+ const Common::Rect &getClipBounds() { return _clipBounds; }
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_SCREEN_H */
diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp
new file mode 100644
index 0000000000..07b1451718
--- /dev/null
+++ b/engines/mads/sequence.cpp
@@ -0,0 +1,541 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/assets.h"
+#include "mads/sequence.h"
+#include "mads/scene.h"
+
+namespace MADS {
+
+SequenceEntry::SequenceEntry() {
+ _spritesIndex = 0;
+ _flipped = 0;
+ _frameIndex = 0;
+ _frameStart = 0;
+ _numSprites = 0;
+ _animType = ANIMTYPE_NONE;
+ _frameInc = 0;
+ _depth = 0;
+ _scale = 0;
+ _dynamicHotspotIndex = -1;
+ _triggerCountdown = 0;
+ _doneFlag = 0;
+ _triggerMode = SEQUENCE_TRIGGER_DAEMON;
+ _numTicks = 0;
+ _extraTicks = 0;
+ _timeout = 0;
+ _active = false;
+ _nonFixed = false;
+ _flags = 0;
+ for (int i = 0; i < 5; ++i)
+ _entries._mode[i] = SEQUENCE_TRIGGER_EXPIRE;
+
+ _entries._count = 0;
+ _actionNouns._verbId = VERB_NONE;
+ _actionNouns._objectNameId = -1;
+ _actionNouns._indirectObjectId = -1;
+
+ Common::fill(&_entries._frameIndex[0], &_entries._frameIndex[SEQUENCE_ENTRY_SUBSET_MAX], 0);
+ Common::fill(&_entries._trigger[0], &_entries._trigger[SEQUENCE_ENTRY_SUBSET_MAX], 0);
+}
+
+/*------------------------------------------------------------------------*/
+
+#define SEQUENCE_LIST_SIZE 30
+
+SequenceList::SequenceList(MADSEngine *vm) : _vm(vm) {
+ // IMPORTANT: Preallocate timer slots. Note that sprite slots refer to entries
+ // in this list by index, so we can't just add or delete entries later
+ for (int i = 0; i < SEQUENCE_LIST_SIZE; ++i) {
+ SequenceEntry rec;
+ rec._active = false;
+ rec._dynamicHotspotIndex = -1;
+ _entries.push_back(rec);
+ }
+}
+
+void SequenceList::clear() {
+ for (uint i = 0; i < _entries.size(); ++i) {
+ _entries[i]._active = false;
+ _entries[i]._dynamicHotspotIndex = -1;
+ }
+}
+
+bool SequenceList::addSubEntry(int index, SequenceTrigger mode, int frameIndex, int trigger) {
+ if (_entries[index]._entries._count >= SEQUENCE_ENTRY_SUBSET_MAX)
+ return true;
+
+ int subIndex = _entries[index]._entries._count++;
+ _entries[index]._entries._mode[subIndex] = mode;
+ _entries[index]._entries._frameIndex[subIndex] = frameIndex;
+ _entries[index]._entries._trigger[subIndex] = trigger;
+
+ return false;
+}
+
+int SequenceList::add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, int extraTicks, int numTicks,
+ int msgX, int msgY, bool nonFixed, int scale, int depth, int frameInc, SpriteAnimType animType, int numSprites,
+ int frameStart) {
+ Scene &scene = _vm->_game->_scene;
+
+ // Find a free slot
+ uint seqIndex = 0;
+ while ((seqIndex < _entries.size()) && _entries[seqIndex]._active)
+ ++seqIndex;
+ if (seqIndex == _entries.size())
+ error("TimerList full");
+
+ if (frameStart <= 0)
+ frameStart = 1;
+ if (numSprites == 0)
+ numSprites = scene._sprites[spriteListIndex]->getCount();
+ if (frameStart == numSprites)
+ frameInc = 0;
+
+ // Set the list entry fields
+ _entries[seqIndex]._active = true;
+ _entries[seqIndex]._spritesIndex = spriteListIndex;
+ _entries[seqIndex]._flipped = flipped;
+ _entries[seqIndex]._frameIndex = frameIndex;
+ _entries[seqIndex]._frameStart = frameStart;
+ _entries[seqIndex]._numSprites = numSprites;
+ _entries[seqIndex]._animType = animType;
+ _entries[seqIndex]._frameInc = frameInc;
+ _entries[seqIndex]._depth = depth;
+ _entries[seqIndex]._scale = scale;
+ _entries[seqIndex]._nonFixed = nonFixed;
+ _entries[seqIndex]._position.x = msgX;
+ _entries[seqIndex]._position.y = msgY;
+ _entries[seqIndex]._numTicks = numTicks;
+ _entries[seqIndex]._extraTicks = extraTicks;
+
+ _entries[seqIndex]._timeout = scene._frameStartTime + delayTicks;
+
+ _entries[seqIndex]._triggerCountdown = triggerCountdown;
+ _entries[seqIndex]._doneFlag = false;
+ _entries[seqIndex]._flags = 0;
+ _entries[seqIndex]._dynamicHotspotIndex = -1;
+ _entries[seqIndex]._entries._count = 0;
+ _entries[seqIndex]._triggerMode = _vm->_game->_triggerSetupMode;
+
+ _entries[seqIndex]._actionNouns = _vm->_game->_scene._action._activeAction;
+
+ return seqIndex;
+}
+
+int SequenceList::addTimer(int timeout, int abortVal) {
+ Scene &scene = _vm->_game->_scene;
+ uint seqIndex;
+ for (seqIndex = 0; seqIndex < _entries.size(); ++seqIndex) {
+ if (!_entries[seqIndex]._active)
+ break;
+ }
+ assert(seqIndex < _entries.size());
+
+ SequenceEntry &se = _entries[seqIndex];
+ se._active = true;
+ se._spritesIndex = -1;
+ se._numTicks = timeout;
+ se._extraTicks = 0;
+ se._timeout = scene._frameStartTime + timeout;
+ se._triggerCountdown = true;
+ se._doneFlag = false;
+ se._entries._count = 0;
+ se._triggerMode = _vm->_game->_triggerSetupMode;
+ se._actionNouns = _vm->_game->_scene._action._activeAction;
+ addSubEntry(seqIndex, SEQUENCE_TRIGGER_EXPIRE, 0, abortVal);
+
+ return seqIndex;
+}
+
+void SequenceList::remove(int seqIndex) {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_entries[seqIndex]._active) {
+ if (_entries[seqIndex]._dynamicHotspotIndex >= 0)
+ scene._dynamicHotspots.remove(_entries[seqIndex]._dynamicHotspotIndex);
+ }
+
+ _entries[seqIndex]._active = false;
+ scene._spriteSlots.deleteTimer(seqIndex);
+}
+
+void SequenceList::setSpriteSlot(int seqIndex, SpriteSlot &spriteSlot) {
+ Scene &scene = _vm->_game->_scene;
+ SequenceEntry &timerEntry = _entries[seqIndex];
+ SpriteAsset &spriteSet = *scene._sprites[timerEntry._spritesIndex];
+
+ spriteSlot._flags = spriteSet.isBackground() ? IMG_DELTA : IMG_UPDATE;
+ spriteSlot._seqIndex = seqIndex;
+ spriteSlot._spritesIndex = timerEntry._spritesIndex;
+ spriteSlot._frameNumber = timerEntry._flipped ? -timerEntry._frameIndex : timerEntry._frameIndex;
+ spriteSlot._depth = timerEntry._depth;
+ spriteSlot._scale = timerEntry._scale;
+
+ if (!timerEntry._nonFixed) {
+ spriteSlot._position = timerEntry._position;
+ } else {
+ MSprite *sprite = spriteSet.getFrame(timerEntry._frameIndex - 1);
+ spriteSlot._position = sprite->_offset;
+ }
+}
+
+bool SequenceList::loadSprites(int seqIndex) {
+ Scene &scene = _vm->_game->_scene;
+ SequenceEntry &seqEntry = _entries[seqIndex];
+ int slotIndex;
+ bool result = false;
+ int idx = -1;
+
+ scene._spriteSlots.deleteTimer(seqIndex);
+ if (seqEntry._doneFlag) {
+ remove(seqIndex);
+ return false;
+ }
+
+ if (seqEntry._spritesIndex == -1) {
+ // Doesn't have an associated sprite anymore, so mark as done
+ seqEntry._doneFlag = true;
+ } else if ((slotIndex = scene._spriteSlots.add()) >= 0) {
+ SpriteSlot &spriteSlot = scene._spriteSlots[slotIndex];
+ setSpriteSlot(seqIndex, spriteSlot);
+
+ if ((seqEntry._flags != 0) || (seqEntry._dynamicHotspotIndex >= 0)) {
+ SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex];
+ MSprite *frame = spriteSet.getFrame(seqEntry._frameIndex - 1);
+ int width = frame->getWidth() * seqEntry._scale / 200;
+ int height = frame->getHeight() * seqEntry._scale / 100;
+ Common::Point pt = spriteSlot._position;
+
+ // Handle sprite movement, if present
+ if (seqEntry._flags & 1) {
+ seqEntry._posAccum.x += seqEntry._posDiff.x;
+ if (seqEntry._posAccum.x >= 100) {
+ int v = seqEntry._posAccum.x / 100;
+ seqEntry._position.x += v * seqEntry._posSign.x;
+ seqEntry._posAccum.x -= v * 100;
+ }
+
+ seqEntry._posAccum.y += seqEntry._posDiff.y;
+ if (seqEntry._posAccum.y >= 100) {
+ int v = seqEntry._posAccum.y / 100;
+ seqEntry._position.y += v * seqEntry._posSign.y;
+ seqEntry._posAccum.y -= v * 100;
+ }
+ }
+
+ if (seqEntry._flags & 2) {
+ // Check for object having moved off-scren
+ if ((pt.x + width) < 0 || (pt.x + width) >= MADS_SCREEN_WIDTH ||
+ pt.y < 0 || (pt.y - height) >= MADS_SCENE_HEIGHT) {
+ result = true;
+ seqEntry._doneFlag = true;
+ }
+ }
+
+ if (seqEntry._dynamicHotspotIndex >= 0) {
+ DynamicHotspot &dynHotspot = scene._dynamicHotspots[seqEntry._dynamicHotspotIndex];
+
+ dynHotspot._bounds.left = MAX(pt.x - width, 0);
+ dynHotspot._bounds.top = MAX(pt.y - height, 0);
+ dynHotspot._bounds.right = dynHotspot._bounds.left + width + 1;
+ dynHotspot._bounds.bottom = dynHotspot._bounds.top + height + 1;
+
+ scene._dynamicHotspots._changed = true;
+ }
+ }
+
+ // Frame adjustments
+ if (seqEntry._frameStart != seqEntry._numSprites)
+ seqEntry._frameIndex += seqEntry._frameInc;
+
+ if (seqEntry._frameIndex >= seqEntry._frameStart) {
+ if (seqEntry._frameIndex > seqEntry._numSprites) {
+ result = true;
+ if (seqEntry._animType == ANIMTYPE_CYCLED) {
+ // back to the starting frame (cyclic)
+ seqEntry._frameIndex = seqEntry._frameStart;
+ } else {
+ // Switch into reverse mode
+ seqEntry._frameIndex = seqEntry._numSprites - 1;
+ seqEntry._frameInc = -1;
+ }
+ }
+ } else {
+ // Currently in reverse mode and moved past starting frame
+ result = true;
+
+ if (seqEntry._animType == ANIMTYPE_CYCLED)
+ {
+ // Switch back to forward direction again
+ seqEntry._frameIndex = seqEntry._frameStart + 1;
+ seqEntry._frameInc = 1;
+ } else {
+ // Otherwise reset back to last sprite for further reverse animating
+ seqEntry._frameIndex = seqEntry._numSprites;
+ }
+ }
+
+ if (result && (seqEntry._triggerCountdown != 0)) {
+ if (--seqEntry._triggerCountdown == 0)
+ seqEntry._doneFlag = true;
+ }
+ } else {
+ // Out of sprite display slots, so mark entry as done
+ seqEntry._doneFlag = true;
+ }
+
+ for (int i = 0; i < seqEntry._entries._count; ++i) {
+ switch (seqEntry._entries._mode[i]) {
+ case SEQUENCE_TRIGGER_EXPIRE:
+ case SEQUENCE_TRIGGER_LOOP:
+ if (((seqEntry._entries._mode[i] == SEQUENCE_TRIGGER_EXPIRE) && seqEntry._doneFlag) ||
+ ((seqEntry._entries._mode[i] == SEQUENCE_TRIGGER_LOOP) && result))
+ idx = i;
+ break;
+
+ case SEQUENCE_TRIGGER_SPRITE: {
+ int v = seqEntry._entries._frameIndex[i];
+ if ((v == seqEntry._frameIndex) || (v == 0))
+ idx = i;
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ if (idx >= 0) {
+ _vm->_game->_trigger = seqEntry._entries._trigger[idx];
+ _vm->_game->_triggerMode = seqEntry._triggerMode;
+
+ if (seqEntry._triggerMode != SEQUENCE_TRIGGER_DAEMON)
+ scene._action._activeAction = seqEntry._actionNouns;
+ }
+
+ return result;
+}
+
+/**
+* Handles counting down entries in the timer list for action
+*/
+void SequenceList::tick() {
+ Scene &scene = _vm->_game->_scene;
+ for (uint idx = 0; idx < _entries.size(); ++idx) {
+ if ((_vm->_game->_fx == 0) && (_vm->_game->_trigger != 0))
+ break;
+
+ SequenceEntry &seqEntry = _entries[idx];
+ uint32 currentTimer = scene._frameStartTime;
+
+ if (!seqEntry._active || (currentTimer < seqEntry._timeout))
+ continue;
+
+ // Set the next timeout for the timer entry
+ seqEntry._timeout = currentTimer + seqEntry._numTicks;
+
+ // Action the sprite
+ if (loadSprites(idx)) {
+ seqEntry._timeout += seqEntry._extraTicks;
+ }
+ }
+}
+
+void SequenceList::delay(uint32 priorFrameTime, uint32 currentTime) {
+ for (uint idx = 0; idx < _entries.size(); ++idx) {
+ if (_entries[idx]._active) {
+ _entries[idx]._timeout += currentTime - priorFrameTime;
+ }
+ }
+}
+
+void SequenceList::setAnimRange(int seqIndex, int startVal, int endVal) {
+ Scene &scene = _vm->_game->_scene;
+ SequenceEntry &seqEntry = _entries[seqIndex];
+ SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex];
+ int numSprites = spriteSet.getCount();
+ int tempStart, tempEnd;
+
+ switch (startVal) {
+ case -2:
+ tempStart = numSprites;
+ break;
+ case -1:
+ tempStart = 1;
+ break;
+ default:
+ tempStart = startVal;
+ break;
+ }
+
+ switch (endVal) {
+ case -2:
+ case 0:
+ tempEnd = numSprites;
+ break;
+ case -1:
+ tempEnd = 1;
+ break;
+ default:
+ tempEnd = endVal;
+ break;
+ }
+
+ seqEntry._frameStart = tempStart;
+ seqEntry._numSprites = tempEnd;
+
+ seqEntry._frameIndex = (seqEntry._frameInc >= 0) ? tempStart : tempEnd;
+}
+
+void SequenceList::scan() {
+ Scene &scene = _vm->_game->_scene;
+
+ for (uint i = 0; i < _entries.size(); ++i) {
+ if (_entries[i]._active && (_entries[i]._spritesIndex != -1)) {
+ int idx = scene._spriteSlots.add();
+ setSpriteSlot(i, scene._spriteSlots[idx]);
+ }
+ }
+}
+
+/**
+* Sets the depth of the specified entry in the sequence list
+*/
+void SequenceList::setDepth(int seqIndex, int depth) {
+ _entries[seqIndex]._depth = depth;
+}
+
+void SequenceList::setPosition(int seqIndex, const Common::Point &pt) {
+ _entries[seqIndex]._position = pt;
+ _entries[seqIndex]._nonFixed = false;
+}
+
+int SequenceList::addSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) {
+ Scene &scene = _vm->_game->_scene;
+ MSprite *spriteFrame = scene._sprites[srcSpriteIdx]->getFrame(0);
+ int depth = scene._depthSurface.getDepth(Common::Point(
+ spriteFrame->_offset.x + (spriteFrame->w / 2),
+ spriteFrame->_offset.y + (spriteFrame->h / 2)));
+
+ return add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0,
+ true, 100, depth - 1, 1, ANIMTYPE_CYCLED, 0, 0);
+}
+
+int SequenceList::addReverseSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks,
+ int triggerCountdown, int timeoutTicks, int extraTicks) {
+ Scene &scene = _vm->_game->_scene;
+
+ SpriteAsset *asset = scene._sprites[srcSpriteIdx];
+ MSprite *spriteFrame = asset->getFrame(0);
+ int depth = scene._depthSurface.getDepth(Common::Point(
+ spriteFrame->_offset.x + (spriteFrame->w / 2),
+ spriteFrame->_offset.y + (spriteFrame->h / 2)));
+
+ return add(srcSpriteIdx, flipped, asset->getCount(), triggerCountdown, timeoutTicks, extraTicks,
+ numTicks, 0, 0, true, 100, depth - 1, -1, ANIMTYPE_CYCLED, 0, 0);
+}
+
+
+int SequenceList::startCycle(int srcSpriteIndex, bool flipped, int cycleIndex) {
+ int result = addSpriteCycle(srcSpriteIndex, flipped, INDEFINITE_TIMEOUT, 0, 0, 0);
+ if (result >= 0)
+ setAnimRange(result, cycleIndex, cycleIndex);
+
+ return result;
+}
+
+int SequenceList::startReverseCycle(int srcSpriteIndex, bool flipped, int numTicks,
+ int triggerCountdown, int timeoutTicks, int extraTicks) {
+ SpriteAsset *sprites = _vm->_game->_scene._sprites[srcSpriteIndex];
+ MSprite *frame = sprites->getFrame(0);
+ int depth = _vm->_game->_scene._depthSurface.getDepth(Common::Point(
+ frame->_offset.x + frame->w / 2, frame->_offset.y + frame->h / 2));
+
+ return add(srcSpriteIndex, flipped, sprites->getCount(), triggerCountdown, timeoutTicks,
+ extraTicks, numTicks, 0, 0, true, 100, depth - 1, -1, ANIMTYPE_REVERSIBLE, 0, 0);
+}
+
+void SequenceList::updateTimeout(int spriteIdx, int seqIndex) {
+ Player &player = _vm->_game->_player;
+ int timeout;
+
+ if (spriteIdx >= 0)
+ timeout = _entries[spriteIdx]._timeout;
+ else
+ timeout = player._priorTimer + player._ticksAmount;
+
+ if (seqIndex >= 0)
+ _entries[seqIndex]._timeout = timeout;
+ else
+ player._priorTimer = timeout - player._ticksAmount;
+
+}
+
+void SequenceList::setScale(int spriteIdx, int scale) {
+ _entries[spriteIdx]._scale = scale;
+}
+
+void SequenceList::setMsgLayout(int seqIndex) {
+ Player &player = _vm->_game->_player;
+ int yp = player._playerPos.y + (player._centerOfGravity * player._currentScale) / 100;
+ setPosition(seqIndex, Common::Point(player._playerPos.x, yp));
+ setDepth(seqIndex, player._currentDepth);
+ setScale(seqIndex, player._currentScale);
+ updateTimeout(-1, seqIndex);
+}
+
+void SequenceList::setDone(int seqIndex) {
+ _entries[seqIndex]._doneFlag = true;
+ _entries[seqIndex]._timeout = _vm->_game->_player._priorTimer;
+}
+
+void SequenceList::setMotion(int seqIndex, int flags, int deltaX, int deltaY) {
+ SequenceEntry &se = _entries[seqIndex];
+ se._flags = flags | 1;
+
+ // Set the direction sign for movement
+ if (deltaX > 0) {
+ se._posSign.x = 1;
+ } else if (deltaX < 0) {
+ se._posSign.x = -1;
+ } else {
+ se._posSign.x = 0;
+ }
+
+ if (deltaY > 0) {
+ se._posSign.y = 1;
+ }
+ else if (deltaY < 0) {
+ se._posSign.y = -1;
+ } else {
+ se._posSign.y = 0;
+ }
+
+ se._posDiff.x = ABS(deltaX);
+ se._posDiff.y = ABS(deltaY);
+ se._posAccum.x = se._posAccum.y = 0;
+}
+
+} // End of namespace
diff --git a/engines/mads/sequence.h b/engines/mads/sequence.h
new file mode 100644
index 0000000000..ee587ff02d
--- /dev/null
+++ b/engines/mads/sequence.h
@@ -0,0 +1,131 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_SEQUENCE_H
+#define MADS_SEQUENCE_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "mads/action.h"
+
+namespace MADS {
+
+class SpriteSlot;
+
+enum SequenceTrigger {
+ SEQUENCE_TRIGGER_EXPIRE = 0, // Trigger when the sequence finishes
+ SEQUENCE_TRIGGER_LOOP = 1, // Trigger when the sequence loops
+ SEQUENCE_TRIGGER_SPRITE = 2 // Trigger when sequence reaches specific sprite
+};
+
+enum SpriteAnimType { ANIMTYPE_NONE = 0, ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2 };
+
+#define SEQUENCE_ENTRY_SUBSET_MAX 5
+
+struct SequenceSubEntries {
+ int _count;
+ SequenceTrigger _mode[SEQUENCE_ENTRY_SUBSET_MAX];
+ int _frameIndex[SEQUENCE_ENTRY_SUBSET_MAX];
+ int _trigger[SEQUENCE_ENTRY_SUBSET_MAX];
+};
+
+struct SequenceEntry {
+ bool _active;
+ int8 _spritesIndex;
+ bool _flipped;
+
+ int _frameIndex;
+ int _frameStart;
+ int _numSprites;
+
+ SpriteAnimType _animType;
+ int _frameInc;
+
+ int _depth;
+ int _scale;
+ int _dynamicHotspotIndex;
+
+ bool _nonFixed;
+ uint32 _flags;
+
+ Common::Point _position;
+ Common::Point _posDiff;
+ Common::Point _posSign;
+ Common::Point _posAccum;
+ int _triggerCountdown;
+ bool _doneFlag;
+ SequenceSubEntries _entries;
+ TriggerMode _triggerMode;
+
+ ActionDetails _actionNouns;
+ int _numTicks;
+ int _extraTicks;
+ uint32 _timeout;
+
+ SequenceEntry();
+};
+
+class MADSEngine;
+
+class SequenceList {
+private:
+ MADSEngine *_vm;
+ Common::Array<SequenceEntry> _entries;
+public:
+ SequenceList(MADSEngine *vm);
+
+ SequenceEntry &operator[](int index) { return _entries[index]; }
+ void clear();
+ bool addSubEntry(int index, SequenceTrigger mode, int frameIndex, int trigger);
+ int add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks,
+ int extraTicks, int numTicks, int msgX, int msgY, bool nonFixed, int scale, int depth,
+ int frameInc, SpriteAnimType animType, int numSprites, int frameStart);
+
+ int addTimer(int timeout, int abortVal);
+ void remove(int seqIndex);
+ void setSpriteSlot(int seqIndex, SpriteSlot &spriteSlot);
+ bool loadSprites(int seqIndex);
+ void tick();
+ void delay(uint32 priorFrameTime, uint32 currentTime);
+ void setAnimRange(int seqIndex, int startVal, int endVal);
+ void scan();
+ void setDepth(int seqIndex, int depth);
+ void setPosition(int seqIndex, const Common::Point &pt);
+ int addSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks,
+ int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0);
+ int addReverseSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks,
+ int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0);
+
+ int startCycle(int srcSpriteIdx, bool flipped, int cycleIndex);
+ int startReverseCycle(int srcSpriteIndex, bool flipped, int numTicks,
+ int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0);
+ void updateTimeout(int spriteIdx, int seqIndex);
+ void setScale(int spriteIdx, int scale);
+ void setMsgLayout(int seqIndex);
+ void setDone(int seqIndex);
+ void setMotion(int seqIndex, int flags, int deltaX, int deltaY);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_SEQUENCE_H */
diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp
new file mode 100644
index 0000000000..12109895b5
--- /dev/null
+++ b/engines/mads/sound.cpp
@@ -0,0 +1,144 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+#include "common/memstream.h"
+#include "mads/sound.h"
+#include "mads/mads.h"
+#include "mads/nebular/sound_nebular.h"
+
+namespace MADS {
+
+SoundManager::SoundManager(MADSEngine *vm, Audio::Mixer *mixer, FM_OPL *opl) {
+ _vm = vm;
+ _mixer = mixer;
+ _opl = opl;
+ _driver = nullptr;
+ _pollSoundEnabled = false;
+ _soundPollFlag = false;
+ _newSoundsPaused = false;
+}
+
+SoundManager::~SoundManager() {
+ delete _driver;
+}
+
+void SoundManager::init(int sectionNumber) {
+ assert(sectionNumber > 0 && sectionNumber < 10);
+
+ switch (_vm->getGameID()) {
+ case GType_RexNebular:
+ switch (sectionNumber) {
+ case 1:
+ _driver = new Nebular::ASound1(_mixer, _opl);
+ break;
+ case 2:
+ _driver = new Nebular::ASound2(_mixer, _opl);
+ break;
+ case 3:
+ _driver = new Nebular::ASound3(_mixer, _opl);
+ break;
+ case 4:
+ _driver = new Nebular::ASound4(_mixer, _opl);
+ break;
+ case 5:
+ _driver = new Nebular::ASound5(_mixer, _opl);
+ break;
+ case 6:
+ _driver = new Nebular::ASound6(_mixer, _opl);
+ break;
+ case 7:
+ _driver = new Nebular::ASound7(_mixer, _opl);
+ break;
+ case 8:
+ _driver = new Nebular::ASound8(_mixer, _opl);
+ break;
+ case 9:
+ _driver = new Nebular::ASound9(_mixer, _opl);
+ break;
+ default:
+ _driver = nullptr;
+ break;
+ }
+ break;
+
+ default:
+ warning("SoundManager: Unknown game");
+ _driver = nullptr;
+ break;
+ }
+}
+
+void SoundManager::closeDriver() {
+ if (_driver) {
+ command(0);
+ setEnabled(false);
+ stop();
+
+ removeDriver();
+ }
+}
+
+void SoundManager::removeDriver() {
+ delete _driver;
+ _driver = nullptr;
+}
+
+void SoundManager::setEnabled(bool flag) {
+ _pollSoundEnabled = flag;
+ _soundPollFlag = false;
+}
+
+void SoundManager::pauseNewCommands() {
+ _newSoundsPaused = true;
+}
+
+void SoundManager::startQueuedCommands() {
+ _newSoundsPaused = false;
+
+ while (!_queuedCommands.empty()) {
+ int commandId = _queuedCommands.pop();
+ command(commandId);
+ }
+}
+
+void SoundManager::command(int commandId, int param) {
+ if (_newSoundsPaused) {
+ if (_queuedCommands.size() < 8)
+ _queuedCommands.push(commandId);
+ } else if (_driver) {
+ _driver->command(commandId, param);
+ }
+}
+
+void SoundManager::stop() {
+ if (_driver)
+ _driver->stop();
+}
+
+void SoundManager::noise() {
+ if (_driver)
+ _driver->noise();
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/sound.h b/engines/mads/sound.h
new file mode 100644
index 0000000000..b2af7e2346
--- /dev/null
+++ b/engines/mads/sound.h
@@ -0,0 +1,104 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_SOUND_H
+#define MADS_SOUND_H
+
+#include "common/scummsys.h"
+#include "common/queue.h"
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "mads/nebular/sound_nebular.h"
+
+namespace MADS {
+
+class MADSEngine;
+
+class SoundManager {
+private:
+ MADSEngine *_vm;
+ Audio::Mixer *_mixer;
+ FM_OPL *_opl;
+ Nebular::ASound *_driver;
+ bool _pollSoundEnabled;
+ bool _soundPollFlag;
+ bool _newSoundsPaused;
+ Common::Queue<int> _queuedCommands;
+public:
+ SoundManager(MADSEngine *vm, Audio::Mixer *mixer, FM_OPL *opl);
+ ~SoundManager();
+
+ /**
+ * Initializes the sound driver for a given game section
+ */
+ void init(int sectionNumber);
+
+ /**
+ * Stop any currently active sound and remove the driver
+ */
+ void closeDriver();
+
+ /**
+ * Remove the driver
+ */
+ void removeDriver();
+
+ /**
+ * Sets the enabled status of the sound
+ * @flag True if sound should be enabled
+ */
+ void setEnabled(bool flag);
+
+ /**
+ * Temporarily pause the playback of any new sound commands
+ */
+ void pauseNewCommands();
+
+ /**
+ * Stop queueing sound commands, and execute any previously queued ones
+ */
+ void startQueuedCommands();
+
+ //@{
+ /**
+ * Executes a command on the sound driver
+ * @param commandid Command Id to execute
+ * @param param Optional paramater specific to a few commands
+ */
+ void command(int commandId, int param = 0);
+
+ /**
+ * Stops any currently playing sound
+ */
+ void stop();
+
+ /**
+ * Noise
+ * Some sort of random noise generation?
+ */
+ void noise();
+ //@}
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_SOUND_H */
diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp
new file mode 100644
index 0000000000..cd358077b5
--- /dev/null
+++ b/engines/mads/sprites.cpp
@@ -0,0 +1,417 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "engines/util.h"
+#include "graphics/palette.h"
+#include "mads/mads.h"
+#include "mads/screen.h"
+#include "mads/msurface.h"
+#include "mads/sprites.h"
+
+namespace MADS {
+
+enum {
+ kEndOfLine = 0,
+ kEndOfSprite = 1,
+ kMarker = 2
+};
+
+#define TRANSPARENT_COLOR_INDEX 0xFF
+
+class DepthEntry {
+public:
+ int depth;
+ int index;
+
+ DepthEntry(int depthAmt, int indexVal) { depth = depthAmt; index = indexVal; }
+};
+
+bool sortHelper(const DepthEntry &entry1, const DepthEntry &entry2) {
+ return entry1.depth < entry2.depth;
+}
+
+typedef Common::List<DepthEntry> DepthList;
+
+/*------------------------------------------------------------------------*/
+
+MSprite::MSprite() : MSurface() {
+ _transparencyIndex = TRANSPARENT_COLOR_INDEX;
+}
+
+MSprite::MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette,
+ const Common::Rect &bounds)
+ : MSurface(bounds.width(), bounds.height()),
+ _offset(Common::Point(bounds.left, bounds.top)), _transparencyIndex(TRANSPARENT_COLOR_INDEX) {
+ // Load the sprite data
+ loadSprite(source, palette);
+}
+
+MSprite::~MSprite() {
+}
+
+void MSprite::loadSprite(Common::SeekableReadStream *source,
+ const Common::Array<RGB6> &palette) {
+ byte *outp, *lineStart;
+ bool newLine = false;
+
+ outp = getData();
+ lineStart = getData();
+ int spriteSize = this->w * this->h;
+ byte transIndex = getTransparencyIndex();
+ Common::fill(outp, outp + spriteSize, transIndex);
+
+ for (;;) {
+ byte cmd1, cmd2, count, pixel;
+
+ if (newLine) {
+ outp = lineStart + getWidth();
+ lineStart = outp;
+ newLine = false;
+ }
+
+ cmd1 = source->readByte();
+
+ if (cmd1 == 0xFC)
+ break;
+ else if (cmd1 == 0xFF)
+ newLine = true;
+ else if (cmd1 == 0xFD) {
+ while (!newLine) {
+ count = source->readByte();
+ if (count == 0xFF) {
+ newLine = true;
+ } else {
+ pixel = source->readByte();
+ while (count--)
+ *outp++ = (pixel == 0xFD) ? getTransparencyIndex() : pixel;
+ }
+ }
+ } else {
+ while (!newLine) {
+ cmd2 = source->readByte();
+ if (cmd2 == 0xFF) {
+ newLine = true;
+ } else if (cmd2 == 0xFE) {
+ count = source->readByte();
+ pixel = source->readByte();
+ while (count--)
+ *outp++ = (pixel == 0xFD) ? getTransparencyIndex() : pixel;
+ } else {
+ *outp++ = (cmd2 == 0xFD) ? getTransparencyIndex() : cmd2;
+ }
+ }
+ }
+ }
+
+ // Do a final iteration over the sprite to convert it's pixels to
+ // the final positions in the main palette
+ spriteSize = this->w * this->h;
+ for (outp = getData(); spriteSize > 0; --spriteSize, ++outp) {
+ if (*outp != transIndex)
+ *outp = palette[*outp]._palIndex;
+ }
+}
+
+byte MSprite::getTransparencyIndex() const {
+ return _transparencyIndex;
+}
+
+/*------------------------------------------------------------------------*/
+
+MADSEngine *SpriteSlot::_vm = nullptr;
+
+SpriteSlot::SpriteSlot() {
+ _flags = IMG_STATIC;
+ _seqIndex = 0;
+ _spritesIndex = 0;
+ _frameNumber = 0;
+ _depth = 0;
+ _scale = 0;
+}
+
+SpriteSlot::SpriteSlot(SpriteFlags type, int seqIndex) {
+ _flags = type;
+ _seqIndex = seqIndex;
+ _spritesIndex = 0;
+ _frameNumber = 0;
+ _depth = 0;
+ _scale = 0;
+}
+
+bool SpriteSlot::operator==(const SpriteSlotSubset &other) const {
+ return (_spritesIndex == other._spritesIndex) && (_frameNumber == other._frameNumber) &&
+ (_position == other._position) && (_depth == other._depth) &&
+ (_scale == other._scale);
+}
+
+void SpriteSlot::copy(const SpriteSlotSubset &other) {
+ _spritesIndex = other._spritesIndex;
+ _frameNumber = other._frameNumber;
+ _position = other._position;
+ _depth = other._depth;
+ _scale = other._scale;
+}
+
+/*------------------------------------------------------------------------*/
+
+SpriteSlots::SpriteSlots(MADSEngine *vm) : _vm(vm) {
+ SpriteSlot::_vm = vm;
+}
+
+void SpriteSlots::reset(bool flag) {
+ _vm->_game->_scene._textDisplay.reset();
+
+ if (flag)
+ _vm->_game->_scene._sprites.clear();
+
+ Common::Array<SpriteSlot>::clear();
+ push_back(SpriteSlot(IMG_REFRESH, -1));
+}
+
+void SpriteSlots::deleteEntry(int index) {
+ remove_at(index);
+}
+
+void SpriteSlots::setDirtyAreas() {
+ Scene &scene = _vm->_game->_scene;
+
+ for (uint i = 0; i < size(); ++i) {
+ if ((*this)[i]._flags >= IMG_STATIC) {
+ scene._dirtyAreas[i].setSpriteSlot(&(*this)[i]);
+
+ scene._dirtyAreas[i]._textActive = ((*this)[i]._flags <= IMG_STATIC) ? 0 : 1;
+ (*this)[i]._flags = IMG_STATIC;
+ }
+ }
+}
+
+void SpriteSlots::fullRefresh(bool clearAll) {
+ if (clearAll)
+ Common::Array<SpriteSlot>::clear();
+
+ push_back(SpriteSlot(IMG_REFRESH, -1));
+}
+
+void SpriteSlots::deleteTimer(int seqIndex) {
+ for (uint idx = 0; idx < size(); ++idx) {
+ SpriteSlot &slot = (*this)[idx];
+ if (slot._seqIndex == seqIndex) {
+ slot._flags = IMG_ERASE;
+ return;
+ }
+ }
+}
+
+int SpriteSlots::add() {
+ SpriteSlot ss;
+ push_back(ss);
+ return size() - 1;
+}
+
+void SpriteSlots::drawBackground() {
+ Scene &scene = _vm->_game->_scene;
+
+ // Initial draw loop for any active sprites in the background
+ for (uint i = 0; i < size(); ++i) {
+ SpriteSlot &spriteSlot = (*this)[i];
+ DirtyArea &dirtyArea = scene._dirtyAreas[i];
+
+ if (spriteSlot._flags >= IMG_STATIC) {
+ // Foreground sprite, so we can ignore it
+ dirtyArea._active = false;
+ } else {
+ dirtyArea._active = true;
+ dirtyArea.setSpriteSlot(&spriteSlot);
+
+ if (spriteSlot._flags == IMG_DELTA) {
+ // Background object, so need to draw it
+ assert(spriteSlot._frameNumber > 0);
+ SpriteAsset *asset = scene._sprites[spriteSlot._spritesIndex];
+ MSprite *frame = asset->getFrame(spriteSlot._frameNumber - 1);
+
+ Common::Point pt = spriteSlot._position;
+ if (spriteSlot._scale != -1) {
+ // Adjust the drawing position
+ pt.x -= frame->w / 2;
+ pt.y -= frame->h - 1;
+ }
+
+ if (spriteSlot._depth <= 1) {
+ frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex());
+ } else if (scene._depthStyle == 0) {
+ scene._backgroundSurface.copyFrom(frame, pt, spriteSlot._depth, &scene._depthSurface,
+ -1, false, frame->getTransparencyIndex());
+ } else {
+ error("Unsupported depth style");
+ }
+ }
+ }
+ }
+
+ // Mark any remaning sprite slot dirty areas as inactive
+ for (uint i = size(); i < SPRITE_SLOTS_MAX_SIZE; ++i)
+ scene._dirtyAreas[i]._active = false;
+
+ // Flag any active text display
+ for (uint i = 0; i < scene._textDisplay.size(); ++i) {
+ TextDisplay &textDisplay = scene._textDisplay[i];
+ DirtyArea &dirtyArea = scene._dirtyAreas[i + SPRITE_SLOTS_MAX_SIZE];
+
+ if (textDisplay._expire >= 0 || !textDisplay._active) {
+ dirtyArea._active = false;
+ } else {
+ dirtyArea._active = true;
+ dirtyArea.setTextDisplay(&textDisplay);
+ }
+ }
+}
+
+void SpriteSlots::drawSprites(MSurface *s) {
+ DepthList depthList;
+ Scene &scene = _vm->_game->_scene;
+
+ // Get a list of sprite object depths for active objects
+ for (uint i = 0; i < size(); ++i) {
+ SpriteSlot &spriteSlot = (*this)[i];
+ if (spriteSlot._flags >= IMG_STATIC) {
+ DepthEntry rec(16 - spriteSlot._depth, i);
+ depthList.push_back(rec);
+ }
+ }
+
+ // Sort the list in order of the depth
+ Common::sort(depthList.begin(), depthList.end(), sortHelper);
+
+ // Loop through each of the objects
+ DepthList::iterator i;
+ for (i = depthList.begin(); i != depthList.end(); ++i) {
+ DepthEntry &de = *i;
+ SpriteSlot &slot = (*this)[de.index];
+ assert(slot._spritesIndex < (int)scene._sprites.size());
+ SpriteAsset &spriteSet = *scene._sprites[slot._spritesIndex];
+
+ // Get the sprite frame
+ int frameNumber = ABS(slot._frameNumber);
+ bool flipped = slot._frameNumber < 0;
+
+ assert(frameNumber > 0);
+ MSprite *sprite = spriteSet.getFrame(frameNumber - 1);
+
+ if ((slot._scale < 100) && (slot._scale != -1)) {
+ // Scaled drawing
+ s->copyFrom(sprite, slot._position, slot._depth, &scene._depthSurface,
+ slot._scale, flipped, sprite->getTransparencyIndex());
+ } else {
+ int xp, yp;
+
+ if (slot._scale == -1) {
+ xp = slot._position.x - scene._posAdjust.x;
+ yp = slot._position.y - scene._posAdjust.y;
+ } else {
+ xp = slot._position.x - (sprite->w / 2) - scene._posAdjust.x;
+ yp = slot._position.y - sprite->h - scene._posAdjust.y + 1;
+ }
+
+ if (slot._depth > 1) {
+ // Draw the frame with depth processing
+ s->copyFrom(sprite, Common::Point(xp, yp), slot._depth, &scene._depthSurface,
+ -1, flipped, sprite->getTransparencyIndex());
+ } else {
+ MSurface *spr = sprite;
+ if (flipped) {
+ // Create a flipped copy of the sprite temporarily
+ spr = sprite->flipHorizontal();
+ }
+
+ // No depth, so simply draw the image
+ spr->copyTo(s, Common::Point(xp, yp), sprite->getTransparencyIndex());
+
+ // Free sprite if it was a flipped one
+ if (flipped)
+ delete spr;
+ }
+ }
+ }
+}
+
+void SpriteSlots::cleanUp() {
+ for (int i = (int)size() - 1; i >= 0; --i) {
+ if ((*this)[i]._flags < IMG_STATIC)
+ remove_at(i);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+SpriteSets::~SpriteSets() {
+ clear();
+}
+
+int SpriteSets::add(SpriteAsset *asset, int idx) {
+ if (idx)
+ idx = idx + 49;
+ else
+ idx = size();
+
+ if (idx >= (int)size())
+ resize(idx + 1);
+
+ if ((*this)[idx]) {
+ delete (*this)[idx];
+ } else {
+ ++_assetCount;
+ }
+
+ (*this)[idx] = asset;
+ return idx;
+}
+
+int SpriteSets::addSprites(const Common::String &resName, int flags) {
+ return add(new SpriteAsset(_vm, resName, flags));
+}
+
+void SpriteSets::clear() {
+ for (uint i = 0; i < size(); ++i)
+ delete (*this)[i];
+
+ _assetCount = 0;
+ Common::Array<SpriteAsset *>::clear();
+}
+
+void SpriteSets::remove(int idx) {
+ if (idx >= 0) {
+ if (idx < ((int)size() - 1)) {
+ delete (*this)[idx];
+ (*this)[idx] = nullptr;
+ } else {
+ while (size() > 0 && (*this)[size() - 1] == nullptr) {
+ remove_at(size() - 1);
+ }
+ }
+
+ if (_assetCount > 0)
+ --_assetCount;
+ }
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/sprites.h b/engines/mads/sprites.h
new file mode 100644
index 0000000000..6ea3c9e52e
--- /dev/null
+++ b/engines/mads/sprites.h
@@ -0,0 +1,240 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_SPRITES_H
+#define MADS_SPRITES_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "mads/assets.h"
+#include "mads/msurface.h"
+
+namespace MADS {
+
+enum SpriteFlags {
+ IMG_STATIC = 0, // Item should remain fixed on the screen
+ IMG_UPDATE = 1, // Item needs to be redrawn
+ IMG_ERASE = -1, // Erase image and remove it
+ IMG_REFRESH = -2, // Full refresh
+ IMG_OVERPRINT = -3, // Interface overprint
+ IMG_DELTA = -4, // Delta change
+ IMG_FULL_UPDATE = -5, // Interface refresh
+ IMG_UPDATE_ONLY = -20 // Update the active screen area only
+};
+
+class MADSEngine;
+
+struct BGR8 {
+ uint8 b, g, r;
+};
+
+typedef struct {
+ int32 x; // x position relative to GrBuff(0, 0)
+ int32 y; // y position relative to GrBuff(0, 0)
+ int32 scale_x; // x scale factor (can be negative for reverse draw)
+ int32 scale_y; // y scale factor (can't be negative)
+ uint8* depth_map; // depth code array for destination (doesn't care if srcDepth is 0)
+ BGR8* Pal; // palette for shadow draw (doesn't care if SHADOW bit is not set in Src.encoding)
+ uint8* ICT; // Inverse Color Table (doesn't care if SHADOW bit is not set in Src.encoding)
+ uint8 depth; // depth code for source (0 if no depth processing)
+} DrawRequestX;
+
+typedef struct {
+ uint32 Pack;
+ uint32 Stream;
+ long hot_x;
+ long hot_y;
+ uint32 Width;
+ uint32 Height;
+ uint32 Comp;
+ uint32 Reserved[8];
+ uint8* data;
+} RendCell;
+
+#define SS_HEADER_NUM_FIELDS 14
+struct SpriteSeriesHeader {
+ uint32 header;
+ uint32 size;
+ uint32 packing;
+ uint32 frameRate;
+ uint32 pixSpeed;
+ uint32 maxWidth;
+ uint32 maxHeight;
+ uint32 reserved3;
+ uint32 reserved4;
+ uint32 reserved5;
+ uint32 reserved6;
+ uint32 reserved7;
+ uint32 reserved8;
+ uint32 count;
+};
+
+#define SF_HEADER_NUM_FIELDS 15
+struct SpriteFrameHeader {
+ uint32 pack;
+ uint32 stream;
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+ uint32 comp;
+ uint32 reserved1;
+ uint32 reserved2;
+ uint32 reserved3;
+ uint32 reserved4;
+ uint32 reserved5;
+ uint32 reserved6;
+ uint32 reserved7;
+ uint32 reserved8;
+};
+
+class MSprite : public MSurface {
+private:
+ void loadSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette);
+public:
+ MSprite();
+ MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette,
+ const Common::Rect &bounds);
+ virtual ~MSprite();
+
+ Common::Point _offset;
+ int _transparencyIndex;
+
+ byte getTransparencyIndex() const;
+};
+
+class SpriteSlotSubset {
+public:
+ int _spritesIndex;
+ int _frameNumber;
+ Common::Point _position;
+ int _depth;
+ int _scale;
+};
+
+class SpriteSlot : public SpriteSlotSubset {
+private:
+ static MADSEngine *_vm;
+ friend class SpriteSlots;
+public:
+ SpriteFlags _flags;
+ int _seqIndex;
+public:
+ SpriteSlot();
+ SpriteSlot(SpriteFlags type, int seqIndex);
+
+ void setup(int dirtyAreaIndex);
+ bool operator==(const SpriteSlotSubset &other) const;
+ void copy(const SpriteSlotSubset &other);
+};
+
+class SpriteSlots : public Common::Array<SpriteSlot> {
+private:
+ MADSEngine *_vm;
+public:
+ SpriteSlots(MADSEngine *vm);
+
+ /**
+ * Clears any pending slot data and schedules a full screen refresh.
+ * @param flag Also reset sprite list
+ */
+ void reset(bool flag = true);
+
+ /**
+ * Delete a sprite entry
+ * @param index Specifies the index in the array
+ */
+ void deleteEntry(int index);
+
+ /**
+ * Setup dirty areas for the sprite slots
+ */
+ void setDirtyAreas();
+
+ /**
+ * Adds a full screen refresh to the sprite slots
+ */
+ void fullRefresh(bool clearAll = false);
+
+ /**
+ * Delete a timer entry with the given Id
+ */
+ void deleteTimer(int seqIndex);
+
+ /**
+ * Add a new slot entry and return it's index
+ */
+ int add();
+
+ /**
+ * Draw any sprites into the background of the scene
+ */
+ void drawBackground();
+
+ /**
+ * Draw any sprites into the foreground of the scene
+ */
+ void drawSprites(MSurface *s);
+
+ void cleanUp();
+};
+
+class SpriteSets : public Common::Array<SpriteAsset *> {
+private:
+ MADSEngine *_vm;
+public:
+ int _assetCount;
+
+ /**
+ * Constructor
+ */
+ SpriteSets(MADSEngine *vm) : _vm(vm), _assetCount(0) {}
+
+ /**
+ * Destructor
+ */
+ ~SpriteSets();
+
+ /**
+ * Clears the current list, freeing any laoded assets
+ */
+ void clear();
+
+ /**
+ * Add a sprite asset to the list
+ */
+ int add(SpriteAsset *asset, int idx = 0);
+
+ /**
+ * Adds a sprite asset to the list by name
+ */
+ int addSprites(const Common::String &resName, int flags = 0);
+
+ /**
+ * Remove an asset from the list
+ */
+ void remove(int idx);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_SPRITES_H */
diff --git a/engines/mads/staticres.cpp b/engines/mads/staticres.cpp
new file mode 100644
index 0000000000..189e5f72e7
--- /dev/null
+++ b/engines/mads/staticres.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/staticres.h"
+
+namespace MADS {
+
+const char *const kArticleList[9] = {
+ nullptr, "with", "to", "at", "from", "on", "in", "under", "behind"
+};
+
+const char *const kCheatingEnabledDesc[3] = {
+ "CHEATING ENABLED",
+ "(For your convenience).",
+ nullptr
+};
+
+const char *const kLookAroundStr = "Look around";
+const char *const kToStr = "to ";
+const char *const kUseStr = "Use ";
+const char *const kWalkToStr = "Walk to ";
+const char *const kFenceStr = "fence";
+const char *const kOverStr = "over";
+
+const char *const kGameReleaseInfoStr = "ScummVM rev: 8.43 14-Sept-92";
+const char *const kGameReleaseTitleStr = "GAME RELASE VERSION INFO";
+
+const uint32 DEFAULT_VGA_LOW_PALETTE[16] = {
+ 0x000000, 0x0000a8, 0x00a800, 0x00a8a8, 0xa80000, 0xa800a8, 0xa85400, 0xa8a8a8,
+ 0x545454, 0x5454fc, 0x54fc54, 0x54fcfc, 0xfc5454, 0xfc54fc, 0xfcfc54, 0xfcfcfc
+};
+
+const uint32 DEFAULT_VGA_HIGH_PALETTE[16] = {
+ 0x2c402c, 0x2c4030, 0x2c4034, 0x2c403c, 0x2c4040, 0x2c3c40, 0x2c3440, 0x2c3040,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
+};
+
+} // End of namespace MADS
diff --git a/engines/mads/staticres.h b/engines/mads/staticres.h
new file mode 100644
index 0000000000..560fd12e67
--- /dev/null
+++ b/engines/mads/staticres.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MADS_STATICRES_H
+#define MADS_STATICRES_H
+
+namespace MADS {
+
+extern const char *const kArticleList[9];
+
+extern const char *const kCheatingEnabledDesc[3];
+
+extern const char *const kLookAroundStr;
+extern const char *const kToStr;
+extern const char *const kUseStr;
+extern const char *const kWalkToStr;
+extern const char *const kFenceStr;
+extern const char *const kOverStr;
+
+extern const char *const kGameReleaseInfoStr;
+extern const char *const kGameReleaseTitleStr;
+
+extern const uint32 DEFAULT_VGA_LOW_PALETTE[16];
+extern const uint32 DEFAULT_VGA_HIGH_PALETTE[16];
+
+} // End of namespace MADS
+
+#endif /* MADS_STATICRES_H */
diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp
new file mode 100644
index 0000000000..1f8d5037bc
--- /dev/null
+++ b/engines/mads/user_interface.cpp
@@ -0,0 +1,1096 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mads/mads.h"
+#include "mads/compression.h"
+#include "mads/user_interface.h"
+#include "mads/nebular/game_nebular.h"
+
+namespace MADS {
+
+UISlot::UISlot() {
+ _flags = IMG_STATIC;
+ _segmentId = 0;
+ _spritesIndex = 0;
+ _frameNumber = 0;
+ _width = _height = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+void UISlots::fullRefresh() {
+ UISlot slot;
+ slot._flags = IMG_REFRESH;
+ slot._segmentId = -1;
+
+ push_back(slot);
+}
+
+void UISlots::add(const Common::Rect &bounds) {
+ assert(size() < 50);
+
+ UISlot ie;
+ ie._flags = IMG_OVERPRINT;
+ ie._segmentId = IMG_TEXT_UPDATE;
+ ie._position = Common::Point(bounds.left, bounds.top);
+ ie._width = bounds.width();
+ ie._height = bounds.height();
+
+ push_back(ie);
+}
+
+void UISlots::add(const AnimFrameEntry &frameEntry) {
+ assert(size() < 50);
+
+ UISlot ie;
+ ie._flags = IMG_UPDATE;
+ ie._segmentId = frameEntry._seqIndex;
+ ie._spritesIndex = frameEntry._spriteSlot._spritesIndex;
+ ie._frameNumber = frameEntry._spriteSlot._frameNumber;
+ ie._position = frameEntry._spriteSlot._position;
+
+ push_back(ie);
+}
+
+void UISlots::draw(bool updateFlag, bool delFlag) {
+ Scene &scene = _vm->_game->_scene;
+ UserInterface &userInterface = scene._userInterface;
+ DirtyArea *dirtyAreaPtr = nullptr;
+
+ // Loop through setting up the dirty areas
+ for (uint idx = 0; idx < size(); ++idx) {
+ DirtyArea &dirtyArea = userInterface._dirtyAreas[idx];
+ UISlot &slot = (*this)[idx];
+
+ if (slot._flags >= IMG_STATIC) {
+ dirtyArea._active = false;
+ } else {
+ dirtyArea.setUISlot(&slot);
+ dirtyArea._textActive = true;
+ if (slot._segmentId == IMG_SPINNING_OBJECT && slot._flags == IMG_FULL_UPDATE) {
+ dirtyArea._active = false;
+ dirtyAreaPtr = &dirtyArea;
+ }
+ }
+ }
+
+ userInterface._dirtyAreas.merge(1, userInterface._uiSlots.size());
+ if (dirtyAreaPtr)
+ dirtyAreaPtr->_active = true;
+
+ // Copy parts of the user interface background that need to be erased
+ for (uint idx = 0; idx < size(); ++idx) {
+ DirtyArea &dirtyArea = userInterface._dirtyAreas[idx];
+ UISlot &slot = (*this)[idx];
+
+ if (dirtyArea._active && dirtyArea._bounds.width() > 0
+ && dirtyArea._bounds.height() > 0 && slot._flags > -20) {
+
+ if (slot._flags >= IMG_ERASE) {
+ // Merge area
+ userInterface.mergeFrom(&userInterface._surface, dirtyArea._bounds,
+ Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top));
+ } else {
+ // Copy area
+ userInterface._surface.copyTo(&userInterface, dirtyArea._bounds,
+ Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top));
+ }
+ }
+ }
+
+ for (uint idx = 0; idx < size(); ++idx) {
+ DirtyArea &dirtyArea = userInterface._dirtyAreas[idx];
+ UISlot &slot = (*this)[idx];
+
+ int slotType = slot._flags;
+ if (slotType >= IMG_STATIC) {
+ dirtyArea.setUISlot(&slot);
+ if (!updateFlag)
+ slotType &= ~0x40;
+
+ dirtyArea._textActive = slotType > 0;
+ slot._flags &= 0x40;
+ }
+ }
+
+ userInterface._dirtyAreas.merge(1, userInterface._uiSlots.size());
+
+ for (uint idx = 0; idx < size(); ++idx) {
+ DirtyArea *dirtyArea = &userInterface._dirtyAreas[idx];
+ UISlot &slot = (*this)[idx];
+
+ if (slot._flags >= IMG_STATIC && !(slot._flags & 0x40)) {
+ if (!dirtyArea->_active) {
+ do {
+ dirtyArea = dirtyArea->_mergedArea;
+ } while (!dirtyArea->_active);
+ }
+
+ if (dirtyArea->_textActive) {
+ SpriteAsset *asset = scene._sprites[slot._spritesIndex];
+
+ // Get the frame details
+ int frameNumber = ABS(slot._frameNumber);
+ bool flipped = slot._frameNumber < 0;
+
+ if (slot._segmentId == IMG_SPINNING_OBJECT) {
+ MSprite *sprite = asset->getFrame(frameNumber - 1);
+ sprite->copyTo(&userInterface, slot._position,
+ sprite->getTransparencyIndex());
+ } else {
+ MSprite *sprite = asset->getFrame(frameNumber - 1);
+
+ if (flipped) {
+ MSurface *spr = sprite->flipHorizontal();
+ userInterface.mergeFrom(spr, spr->getBounds(), slot._position,
+ sprite->getTransparencyIndex());
+ delete spr;
+ } else {
+ userInterface.mergeFrom(sprite, sprite->getBounds(), slot._position,
+ sprite->getTransparencyIndex());
+ }
+ }
+ }
+ }
+ }
+
+ // Mark areas of the screen surface for updating
+ if (updateFlag) {
+ for (uint idx = 0; idx < size(); ++idx) {
+ DirtyArea &dirtyArea = userInterface._dirtyAreas[idx];
+
+ if (dirtyArea._active && dirtyArea._textActive &&
+ dirtyArea._bounds.width() > 0 && dirtyArea._bounds.height() > 0) {
+ // Flag area of screen as needing update
+ Common::Rect r = dirtyArea._bounds;
+ r.translate(0, scene._interfaceY);
+ _vm->_screen.copyRectToScreen(r);
+ }
+ }
+ }
+
+ // Post-processing to remove slots no longer needed
+ for (int idx = (int)size() - 1; idx >= 0; --idx) {
+ UISlot &slot = (*this)[idx];
+
+ if (slot._flags < IMG_STATIC) {
+ if (delFlag || updateFlag)
+ remove_at(idx);
+ else if (slot._flags > -20)
+ slot._flags -= 20;
+ } else {
+ if (updateFlag)
+ slot._flags &= ~0x40;
+ else
+ slot._flags |= 0x40;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+MADSEngine *Conversation::_vm;
+
+void Conversation::init(MADSEngine *vm) {
+ _vm = vm;
+}
+
+void Conversation::setup(int globalId, ...) {
+ va_list va;
+ va_start(va, globalId);
+
+ // Load the list of conversation quotes
+ _quotes.clear();
+ int quoteId = va_arg(va, int);
+ while (quoteId > 0) {
+ _quotes.push_back(quoteId);
+ quoteId = va_arg(va, int);
+ }
+ va_end(va);
+
+ if (quoteId < 0) {
+ // For an ending value of -1, also initial the bitflags for the global
+ // associated with the conversation entry, which enables all the quote Ids
+ _vm->_game->globals()[globalId] = (int16)0xffff;
+ }
+
+ _globalId = globalId;
+}
+
+void Conversation::set(int quoteId, ...) {
+ _vm->_game->globals()[_globalId] = 0;
+
+ va_list va;
+ va_start(va, quoteId);
+
+ // Loop through handling each quote
+ while (quoteId > 0) {
+ for (uint idx = 0; idx < _quotes.size(); ++idx) {
+ if (_quotes[idx] == quoteId) {
+ // Found index, so set that bit in the global keeping track of conversation state
+ _vm->_game->globals()[_globalId] |= 1 << idx;
+ break;
+ }
+ }
+
+ quoteId = va_arg(va, int);
+ }
+ va_end(va);
+}
+
+int Conversation::read(int quoteId) {
+ uint16 flags = _vm->_game->globals()[_globalId];
+ int count = 0;
+
+ for (uint idx = 0; idx < _quotes.size(); ++idx) {
+ if (flags & (1 << idx))
+ ++count;
+
+ if (_quotes[idx] == quoteId)
+ return flags & (1 << idx);
+ }
+
+ // Could not find it, simply return number of active quotes
+ return count;
+}
+
+void Conversation::write(int quoteId, bool flag) {
+ for (uint idx = 0; idx < _quotes.size(); ++idx) {
+ if (_quotes[idx] == quoteId) {
+ // Found index, so set or clear the flag
+ if (flag) {
+ // Set bit
+ _vm->_game->globals()[_globalId] |= 1 << idx;
+ } else {
+ // Clear bit
+ _vm->_game->globals()[_globalId] &= ~(1 << idx);
+ }
+ return;
+ }
+ }
+}
+
+void Conversation::start() {
+ UserInterface &userInterface = _vm->_game->_scene._userInterface;
+ userInterface.emptyConversationList();
+
+ // Loop through each of the quotes loaded into the conversation
+ for (uint idx = 0; idx < _quotes.size(); ++idx) {
+ // Check whether the given quote is enabled or not
+ if (_vm->_game->globals()[_globalId] & (1 << idx)) {
+ // Quote enabled, so add it to the list of talk selections
+ Common::String msg = _vm->_game->getQuote(_quotes[idx]);
+ userInterface.addConversationMessage(_quotes[idx], msg);
+ }
+ }
+
+ userInterface.setup(kInputConversation);
+}
+
+/*------------------------------------------------------------------------*/
+
+UserInterface::UserInterface(MADSEngine *vm) : _vm(vm), _dirtyAreas(vm),
+ _uiSlots(vm) {
+ _invSpritesIndex = -1;
+ _invFrameNumber = 1;
+ _scrollMilli = 0;
+ _scrollFlag = false;
+ _category = CAT_NONE;
+ _inventoryTopIndex = 0;
+ _selectedInvIndex = -1;
+ _selectedActionIndex = 0;
+ _selectedItemVocabIdx = -1;
+ _scrollbarActive = SCROLLBAR_NONE;
+ _scrollbarOldActive = SCROLLBAR_NONE;
+ _scrollbarStrokeType = SCROLLBAR_NONE;
+ _scrollbarQuickly = false;
+ _scrollbarMilliTime = 0;
+ _scrollbarElevator = _scrollbarOldElevator = 0;
+ _highlightedCommandIndex = -1;
+ _highlightedInvIndex = -1;
+ _highlightedItemVocabIndex = -1;
+ _dirtyAreas.resize(50);
+ _inventoryChanged = false;
+ _noSegmentsActive = 0;
+ _someSegmentsActive = 0;
+ _rectP = nullptr;
+
+ Common::fill(&_categoryIndexes[0], &_categoryIndexes[7], 0);
+
+ // Map the user interface to the bottom of the game's screen surface
+ byte *pData = _vm->_screen.getBasePtr(0, MADS_SCENE_HEIGHT);
+ setPixels(pData, MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
+
+ _surface.setSize(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
+}
+
+void UserInterface::load(const Common::String &resName) {
+ File f(resName);
+ MadsPack madsPack(&f);
+
+ // Load in the palette
+ Common::SeekableReadStream *palStream = madsPack.getItemStream(0);
+
+ uint32 *gamePalP = &_vm->_palette->_palFlags[0];
+ byte *palP = &_vm->_palette->_mainPalette[0];
+
+ for (int i = 0; i < 16; ++i, gamePalP++, palP += 3) {
+ RGB6 rgb;
+ rgb.load(palStream);
+ palP[0] = rgb.r;
+ palP[1] = rgb.g;
+ palP[2] = rgb.b;
+ *gamePalP |= 1;
+ }
+ delete palStream;
+
+ // Read in the surface data
+ Common::SeekableReadStream *pixelsStream = madsPack.getItemStream(1);
+ pixelsStream->read(_surface.getData(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT);
+ delete pixelsStream;
+}
+
+void UserInterface::setup(InputMode inputMode) {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_vm->_game->_screenObjects._inputMode != inputMode) {
+ Common::String resName = _vm->_game->_aaName;
+
+ // Strip off any extension
+ const char *p = strchr(resName.c_str(), '.');
+ if (p) {
+ resName = Common::String(resName.c_str(), p);
+ }
+
+ // Add on suffix if necessary
+ if (inputMode != kInputBuildingSentences)
+ resName += "A";
+
+ resName += ".INT";
+
+ load(resName);
+ _surface.copyTo(this);
+ }
+ _vm->_game->_screenObjects._inputMode = inputMode;
+
+ scene._userInterface._uiSlots.clear();
+ scene._userInterface._uiSlots.fullRefresh();
+ _vm->_game->_screenObjects._baseTime = _vm->_events->getFrameCounter();
+ _highlightedCommandIndex = -1;
+ _highlightedItemVocabIndex = -1;
+ _highlightedInvIndex = -1;
+
+ if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE)
+ scene._userInterface._uiSlots.draw(false, false);
+
+ scene._action.clear();
+ drawTextElements();
+ loadElements();
+ scene._dynamicHotspots.refresh();
+}
+
+void UserInterface::drawTextElements() {
+ if (_vm->_game->_screenObjects._inputMode) {
+ drawConversationList();
+ } else {
+ // Draw the actions
+ drawActions();
+ drawInventoryList();
+ drawItemVocabList();
+ }
+}
+
+void UserInterface::mergeFrom(MSurface *src, const Common::Rect &srcBounds,
+ const Common::Point &destPos, int transparencyIndex) {
+ // Validation of the rectangle and position
+ int destX = destPos.x, destY = destPos.y;
+ if ((destX >= w) || (destY >= h))
+ return;
+
+ Common::Rect copyRect = srcBounds;
+ if (destX < 0) {
+ copyRect.left += -destX;
+ destX = 0;
+ } else if (destX + copyRect.width() > w) {
+ copyRect.right -= destX + copyRect.width() - w;
+ }
+ if (destY < 0) {
+ copyRect.top += -destY;
+ destY = 0;
+ } else if (destY + copyRect.height() > h) {
+ copyRect.bottom -= destY + copyRect.height() - h;
+ }
+
+ if (!copyRect.isValidRect())
+ return;
+
+ // Copy the specified area
+
+ byte *data = src->getData();
+ byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
+ byte *destPtr = (byte *)this->pixels + (destY * getWidth()) + destX;
+
+ for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
+ // Process each line of the area
+ for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) {
+ // Check for the range used for the user interface background,
+ // which are the only pixels that can be replaced
+ if ((destPtr[xCtr] >= 8 && destPtr[xCtr] <= 15) && (int)srcPtr[xCtr] != transparencyIndex)
+ destPtr[xCtr] = srcPtr[xCtr];
+ }
+
+ srcPtr += src->getWidth();
+ destPtr += getWidth();
+ }
+}
+
+void UserInterface::drawActions() {
+ for (int idx = 0; idx < 10; ++idx) {
+ writeVocab(CAT_COMMAND, idx);
+ }
+}
+
+void UserInterface::drawInventoryList() {
+ int endIndex = MIN((int)_vm->_game->_objects._inventoryList.size(), _inventoryTopIndex + 5);
+ for (int idx = _inventoryTopIndex; idx < endIndex; ++idx) {
+ writeVocab(CAT_INV_LIST, idx);
+ }
+}
+
+void UserInterface::drawItemVocabList() {
+ if (_selectedInvIndex >= 0) {
+ InventoryObject &io = _vm->_game->_objects[
+ _vm->_game->_objects._inventoryList[_selectedInvIndex]];
+ for (int idx = 0; idx < io._vocabCount; ++idx) {
+ writeVocab(CAT_INV_VOCAB, idx);
+ }
+ }
+}
+
+void UserInterface::drawScroller() {
+ if (_scrollbarActive)
+ writeVocab(CAT_INV_SCROLLER, _scrollbarActive);
+ writeVocab(CAT_INV_SCROLLER, 4);
+}
+
+void UserInterface::updateInventoryScroller() {
+ ScreenObjects &screenObjects = _vm->_game->_screenObjects;
+ Common::Array<int> &inventoryList = _vm->_game->_objects._inventoryList;
+
+ if (screenObjects._inputMode != kInputBuildingSentences)
+ return;
+
+ _scrollbarActive = SCROLLBAR_NONE;
+
+ if ((screenObjects._category == CAT_INV_SCROLLER) || (screenObjects._category != CAT_INV_SCROLLER
+ && _scrollbarOldActive == SCROLLBAR_ELEVATOR && _vm->_events->_mouseStatusCopy)) {
+ if (_vm->_events->_mouseStatusCopy || _vm->_easyMouse) {
+ if ((_vm->_events->_mouseClicked || (_vm->_easyMouse && !_vm->_events->_mouseStatusCopy))
+ && (screenObjects._category == CAT_INV_SCROLLER))
+ _scrollbarStrokeType = (ScrollbarActive)screenObjects._spotId;
+
+ if (screenObjects._spotId == _scrollbarStrokeType || _scrollbarOldActive == SCROLLBAR_ELEVATOR) {
+ _scrollbarActive = _scrollbarStrokeType;
+ uint32 currentMilli = g_system->getMillis();
+ uint32 timeInc = _scrollbarQuickly ? 100 : 380;
+
+ if (_vm->_events->_mouseStatus && (_scrollbarMilliTime + timeInc) <= currentMilli) {
+ _scrollbarQuickly = _vm->_events->_vD2 < 1;
+ _scrollbarMilliTime = currentMilli;
+
+ switch (_scrollbarStrokeType) {
+ case SCROLLBAR_UP:
+ // Scroll up
+ if (_inventoryTopIndex > 0 && inventoryList.size() > 0) {
+ --_inventoryTopIndex;
+ _inventoryChanged = true;
+ }
+ break;
+
+ case SCROLLBAR_DOWN:
+ // Scroll down
+ if (_inventoryTopIndex < ((int)inventoryList.size() - 1) && inventoryList.size() > 1) {
+ ++_inventoryTopIndex;
+ _inventoryChanged = true;
+ }
+ break;
+
+ case SCROLLBAR_ELEVATOR: {
+ // Inventory slider
+ int newIndex = CLIP((int)_vm->_events->currentPos().y - 170, 0, 17)
+ * inventoryList.size() / 10;
+ if (newIndex >= (int)inventoryList.size())
+ newIndex = inventoryList.size() - 1;
+
+ if (inventoryList.size() > 0) {
+ _inventoryChanged = newIndex != _inventoryTopIndex;
+ _inventoryTopIndex = newIndex;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (_inventoryChanged) {
+ int dummy;
+ updateSelection(CAT_INV_LIST, 0, &dummy);
+ }
+ }
+ }
+ }
+ }
+
+ if (_scrollbarActive != _scrollbarOldActive || _scrollbarElevator != _scrollbarOldElevator)
+ scrollbarChanged();
+
+ _scrollbarOldActive = _scrollbarActive;
+ _scrollbarOldElevator = _scrollbarElevator;
+}
+
+void UserInterface::scrollbarChanged() {
+ Common::Rect r(73, 4, 73 + 9, 4 + 38);
+ _uiSlots.add(r);
+ _uiSlots.draw(false, false);
+ drawScroller();
+ updateRect(r);
+}
+
+void UserInterface::writeVocab(ScrCategory category, int id) {
+ Common::Rect bounds;
+ if (!getBounds(category, id, bounds))
+ return;
+
+ Scene &scene = _vm->_game->_scene;
+ Font *font = nullptr;
+
+ int vocabId;
+ Common::String vocabStr;
+ switch (category) {
+ case CAT_COMMAND:
+ font = _vm->_font->getFont(FONT_INTERFACE);
+ vocabId = scene._verbList[id]._id;
+ if (id == _highlightedCommandIndex) {
+ _vm->_font->setColorMode(SELMODE_HIGHLIGHTED);
+ } else {
+ _vm->_font->setColorMode(id == _selectedActionIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED);
+ }
+ vocabStr = scene.getVocab(vocabId);
+ vocabStr.setChar(toupper(vocabStr[0]), 0);
+ font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top));
+ break;
+
+ case CAT_INV_LIST:
+ font = _vm->_font->getFont(FONT_INTERFACE);
+ vocabId = _vm->_game->_objects.getItem(id)._descId;
+ if (id == _highlightedInvIndex) {
+ _vm->_font->setColorMode(SELMODE_HIGHLIGHTED);
+ } else {
+ _vm->_font->setColorMode(id == _selectedInvIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED);
+ }
+
+ vocabStr = scene.getVocab(vocabId);
+ vocabStr.setChar(toupper(vocabStr[0]), 0);
+ font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top));
+ break;
+
+ case CAT_TALK_ENTRY:
+ font = _vm->_font->getFont(FONT_INTERFACE);
+ font->setColorMode(id == _highlightedCommandIndex ? SELMODE_HIGHLIGHTED : SELMODE_UNSELECTED);
+ font->writeString(this, _talkStrings[id], Common::Point(bounds.left, bounds.top));
+ break;
+
+ case CAT_INV_SCROLLER:
+ font = _vm->_font->getFont(FONT_MISC);
+
+ switch (id) {
+ case 1:
+ vocabStr = "a";
+ break;
+ case 2:
+ vocabStr = "b";
+ break;
+ case 3:
+ vocabStr = "d";
+ break;
+ case 4:
+ vocabStr = "c";
+ break;
+ default:
+ break;
+ }
+
+ font->setColorMode((id == 4) || (_scrollbarActive == SCROLLBAR_ELEVATOR) ?
+ SELMODE_HIGHLIGHTED : SELMODE_UNSELECTED);
+ font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top));
+ break;
+ default:
+ // Item specific verbs
+ font = _vm->_font->getFont(FONT_INTERFACE);
+ vocabId = _vm->_game->_objects.getItem(_selectedInvIndex)._vocabList[id]._vocabId;
+ if (id == _highlightedItemVocabIndex) {
+ _vm->_font->setColorMode(SELMODE_HIGHLIGHTED);
+ } else {
+ _vm->_font->setColorMode(id == _selectedInvIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED);
+ vocabStr = scene.getVocab(vocabId);
+ vocabStr.setChar(toupper(vocabStr[0]), 0);
+ font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top));
+ break;
+ }
+ break;
+ }
+}
+
+void UserInterface::loadElements() {
+ Scene &scene = _vm->_game->_scene;
+ Common::Rect bounds;
+ _vm->_game->_screenObjects.clear();
+
+ if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences) {
+ // Set up screen objects for the inventory scroller
+ for (int idx = 1; idx <= 3; ++idx) {
+ getBounds(CAT_INV_SCROLLER, idx, bounds);
+ moveRect(bounds);
+
+ _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_SCROLLER, idx);
+ }
+
+ // Set up actions
+ _categoryIndexes[CAT_COMMAND - 1] = _vm->_game->_screenObjects.size() + 1;
+ for (int idx = 0; idx < 10; ++idx) {
+ getBounds(CAT_COMMAND, idx, bounds);
+ moveRect(bounds);
+
+ _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_COMMAND, idx);
+ }
+
+ // Set up inventory list
+ _categoryIndexes[CAT_INV_LIST - 1] = _vm->_game->_screenObjects.size() + 1;
+ for (int idx = 0; idx < 5; ++idx) {
+ getBounds(CAT_INV_LIST, _inventoryTopIndex + idx, bounds);
+ moveRect(bounds);
+
+ _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_LIST, idx);
+ }
+
+ // Set up the inventory vocab list
+ _categoryIndexes[CAT_INV_VOCAB - 1] = _vm->_game->_screenObjects.size() + 1;
+ for (int idx = 0; idx < 5; ++idx) {
+ getBounds(CAT_INV_VOCAB, idx, bounds);
+ moveRect(bounds);
+
+ _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_VOCAB, idx);
+ }
+
+ // Set up the inventory item picture
+ _categoryIndexes[CAT_INV_ANIM - 1] = _vm->_game->_screenObjects.size() + 1;
+ _vm->_game->_screenObjects.add(Common::Rect(160, 159, 231, 194), LAYER_GUI,
+ CAT_INV_ANIM, 0);
+ }
+
+ if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences ||
+ _vm->_game->_screenObjects._inputMode == kInputLimitedSentences) {
+ _categoryIndexes[CAT_HOTSPOT - 1] = _vm->_game->_screenObjects.size() + 1;
+ for (int hotspotIdx = scene._hotspots.size() - 1; hotspotIdx >= 0; --hotspotIdx) {
+ Hotspot &hs = scene._hotspots[hotspotIdx];
+ _vm->_game->_screenObjects.add(hs._bounds, LAYER_GUI, CAT_HOTSPOT, hotspotIdx);
+ }
+ }
+
+ if (_vm->_game->_screenObjects._inputMode == kInputConversation) {
+ // setup areas for talk entries
+ _categoryIndexes[CAT_TALK_ENTRY - 1] = _vm->_game->_screenObjects.size() + 1;
+ for (int idx = 0; idx < 5; ++idx) {
+ getBounds(CAT_TALK_ENTRY, idx, bounds);
+ moveRect(bounds);
+
+ _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_TALK_ENTRY, idx);
+ }
+ }
+
+ // Store the number of UI elements loaded for easy nuking/refreshing hotspots added later
+ _vm->_game->_screenObjects._uiCount = _vm->_game->_screenObjects.size();
+}
+
+bool UserInterface::getBounds(ScrCategory category, int v, Common::Rect &bounds) {
+ int heightMultiplier, widthMultiplier;
+ int leftStart, yOffset, widthAmt;
+
+ switch (category) {
+ case CAT_COMMAND:
+ heightMultiplier = v % 5;
+ widthMultiplier = v / 5;
+ leftStart = 2;
+ yOffset = 3;
+ widthAmt = 32;
+ break;
+
+ case CAT_INV_LIST:
+ if (v < _inventoryTopIndex || v >= (_inventoryTopIndex + 5))
+ return false;
+
+ heightMultiplier = v - _inventoryTopIndex;
+ widthMultiplier = 0;
+ leftStart = 90;
+ yOffset = 3;
+ widthAmt = 69;
+ break;
+
+ case CAT_TALK_ENTRY:
+ heightMultiplier = v;
+ widthMultiplier = 0;
+ leftStart = 2;
+ yOffset = 3;
+ widthAmt = 310;
+ break;
+
+ case CAT_INV_SCROLLER:
+ heightMultiplier = 0;
+ widthMultiplier = 0;
+ yOffset = 0;
+ widthAmt = 9;
+ leftStart = (v != 73) ? 73 : 75;
+ break;
+
+ default:
+ heightMultiplier = v;
+ widthMultiplier = 0;
+ leftStart = 240;
+ yOffset = 3;
+ widthAmt = 80;
+ break;
+ }
+
+ bounds.left = (widthMultiplier > 0) ? widthMultiplier * widthAmt + leftStart : leftStart;
+ bounds.setWidth(widthAmt);
+ bounds.top = heightMultiplier * 8 + yOffset;
+ bounds.setHeight(8);
+
+ if (category == CAT_INV_SCROLLER) {
+ switch (v) {
+ case SCROLLBAR_UP:
+ // Arrow up
+ bounds.top = 4;
+ bounds.setHeight(7);
+ break;
+ case SCROLLBAR_DOWN:
+ // Arrow down
+ bounds.top = 35;
+ bounds.setHeight(7);
+ break;
+ case SCROLLBAR_ELEVATOR:
+ // Scroller
+ bounds.top = 12;
+ bounds.setHeight(22);
+ break;
+ case SCROLLBAR_THUMB:
+ // Thumb
+ bounds.top = _scrollbarElevator + 14;
+ bounds.setHeight(1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+void UserInterface::moveRect(Common::Rect &bounds) {
+ bounds.translate(0, MADS_SCENE_HEIGHT);
+}
+
+void UserInterface::drawConversationList() {
+ for (uint idx = 0; idx < _talkStrings.size(); ++idx) {
+ writeVocab(CAT_TALK_ENTRY, idx);
+ }
+}
+
+void UserInterface::emptyConversationList() {
+ _talkStrings.clear();
+ _talkIds.clear();
+}
+
+void UserInterface::addConversationMessage(int vocabId, const Common::String &msg) {
+ assert(_talkStrings.size() < 5);
+
+ _talkStrings.push_back(msg);
+ _talkIds.push_back(vocabId);
+}
+
+void UserInterface::loadInventoryAnim(int objectId) {
+ Scene &scene = _vm->_game->_scene;
+ noInventoryAnim();
+
+ if (_vm->_invObjectsAnimated) {
+ Common::String resName = Common::String::format("*OB%.3dI", objectId);
+ SpriteAsset *asset = new SpriteAsset(_vm, resName, ASSET_SPINNING_OBJECT);
+ _invSpritesIndex = scene._sprites.add(asset, 1);
+ if (_invSpritesIndex >= 0) {
+ _invFrameNumber = 1;
+ }
+ }
+}
+
+void UserInterface::noInventoryAnim() {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_invSpritesIndex >= 0) {
+ scene._sprites.remove(_invSpritesIndex);
+ _vm->_game->_screenObjects._baseTime = _vm->_events->getFrameCounter();
+ _invSpritesIndex = -1;
+ }
+
+ if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences)
+ refresh();
+}
+
+void UserInterface::refresh() {
+ _uiSlots.clear();
+ _uiSlots.fullRefresh();
+ _uiSlots.draw(false, false);
+
+ drawTextElements();
+}
+
+void UserInterface::inventoryAnim() {
+ Scene &scene = _vm->_game->_scene;
+ if (_vm->_game->_screenObjects._inputMode == kInputConversation ||
+ _vm->_game->_screenObjects._inputMode == kInputLimitedSentences ||
+ _invSpritesIndex < 0)
+ return;
+
+ // Move to the next frame number in the sequence, resetting if at the end
+ SpriteAsset *asset = scene._sprites[_invSpritesIndex];
+ if (++_invFrameNumber > asset->getCount())
+ _invFrameNumber = 1;
+
+ // Loop through the slots list for inventory animation entry
+ for (uint i = 0; i < _uiSlots.size(); ++i) {
+ if (_uiSlots[i]._segmentId == IMG_SPINNING_OBJECT)
+ _uiSlots[i]._flags = IMG_FULL_UPDATE;
+ }
+
+ // Add a new slot entry for the inventory animation
+ UISlot slot;
+ slot._flags = IMG_UPDATE;
+ slot._segmentId = IMG_SPINNING_OBJECT;
+ slot._frameNumber = _invFrameNumber;
+ slot._spritesIndex = _invSpritesIndex;
+ slot._position = Common::Point(160, 3);
+
+ _uiSlots.push_back(slot);
+}
+
+void UserInterface::doBackgroundAnimation() {
+ Scene &scene = _vm->_game->_scene;
+ Common::Array<AnimUIEntry> &uiEntries = scene._animationData->_uiEntries;
+ Common::Array<AnimFrameEntry> &frameEntries = scene._animationData->_frameEntries;
+
+ _noSegmentsActive = !_someSegmentsActive;
+ _someSegmentsActive = false;
+
+ for (int idx = 0; idx < (int)uiEntries.size(); ++idx) {
+ AnimUIEntry &uiEntry = uiEntries[idx];
+
+ if (uiEntry._counter < 0) {
+ if (uiEntry._counter == -1) {
+ int probabilityRandom = _vm->getRandomNumber(1, 30000);
+ int probability = uiEntry._probability;
+ if (uiEntry._probability > 30000) {
+ if (_noSegmentsActive) {
+ probability -= 30000;
+ } else {
+ probability = -1;
+ }
+ }
+ if (probabilityRandom <= probability) {
+ uiEntry._counter = uiEntry._firstImage;
+ _someSegmentsActive = true;
+ }
+ } else {
+ uiEntry._counter = uiEntry._firstImage;
+ _someSegmentsActive = true;
+ }
+ } else {
+ for (int idx2 = 0; idx2 < ANIM_SPAWN_COUNT; idx2++) {
+ if (uiEntry._spawnFrame[idx2] == (uiEntry._counter - uiEntry._firstImage)) {
+ int tempIndex = uiEntry._spawn[idx2];
+ if (idx >= tempIndex) {
+ uiEntries[tempIndex]._counter = uiEntries[tempIndex]._firstImage;
+ } else {
+ uiEntries[tempIndex]._counter = -2;
+ }
+ _someSegmentsActive = true;
+ }
+ }
+
+ ++uiEntry._counter;
+ if (uiEntry._counter > uiEntry._lastImage) {
+ uiEntry._counter = -1;
+ } else {
+ _someSegmentsActive = true;
+ }
+ }
+ }
+
+ for (uint idx = 0; idx < uiEntries.size(); ++idx) {
+ int imgScan = uiEntries[idx]._counter;
+ if (imgScan >= 0) {
+ _uiSlots.add(frameEntries[imgScan]);
+ }
+ }
+}
+
+void UserInterface::categoryChanged() {
+ _highlightedInvIndex = -1;
+ _vm->_events->initVars();
+ _category = CAT_NONE;
+}
+
+void UserInterface::selectObject(int invIndex) {
+ if (_selectedInvIndex != invIndex || _inventoryChanged) {
+ int oldVocabCount = _selectedInvIndex < 0 ? 0 : _vm->_game->_objects.getItem(_selectedInvIndex)._vocabCount;
+ int newVocabCount = invIndex < 0 ? 0 : _vm->_game->_objects.getItem(invIndex)._vocabCount;
+ int maxVocab = MAX(oldVocabCount, newVocabCount);
+
+ updateSelection(CAT_INV_LIST, invIndex, &_selectedInvIndex);
+ _highlightedItemVocabIndex = -1;
+ _selectedItemVocabIdx = -1;
+
+ if (maxVocab) {
+ assert(_uiSlots.size() < 50);
+ int vocabHeight = maxVocab * 8;
+
+ Common::Rect bounds(240, 3, 240 + 80, 3 + vocabHeight);
+ _uiSlots.add(bounds);
+ _uiSlots.draw(false, false);
+ drawItemVocabList();
+ updateRect(bounds);
+ }
+ }
+
+ if (invIndex == -1) {
+ noInventoryAnim();
+ } else {
+ loadInventoryAnim(_vm->_game->_objects._inventoryList[invIndex]);
+ _vm->_palette->setPalette(&_vm->_palette->_mainPalette[7 * 3], 7, 1);
+ _vm->_palette->setPalette(&_vm->_palette->_mainPalette[246 * 3], 246, 2);
+ }
+}
+
+void UserInterface::updateSelection(ScrCategory category, int newIndex, int *idx) {
+ Game &game = *_vm->_game;
+ Common::Array<int> &invList = game._objects._inventoryList;
+ Common::Rect bounds;
+
+ if (category == CAT_INV_LIST && _inventoryChanged) {
+ *idx = newIndex;
+ bounds = Common::Rect(90, 3, 90 + 69, 3 + 40);
+ _uiSlots.add(bounds);
+ _uiSlots.draw(false, false);
+ drawInventoryList();
+ updateRect(bounds);
+ _inventoryChanged = false;
+
+ if (invList.size() < 2) {
+ _scrollbarElevator = 0;
+ } else {
+ int v = _inventoryTopIndex * 18 / (invList.size() - 1);
+ _scrollbarElevator = MIN(v, 17);
+ }
+ } else {
+ int oldIndex = *idx;
+ *idx = newIndex;
+
+ if (oldIndex >= 0) {
+ writeVocab(category, oldIndex);
+
+ if (getBounds(category, oldIndex, bounds))
+ updateRect(bounds);
+ }
+
+ if (newIndex >= 0) {
+ writeVocab(category, newIndex);
+
+ if (getBounds(category, newIndex, bounds))
+ updateRect(bounds);
+ }
+ }
+}
+
+void UserInterface::updateRect(const Common::Rect &bounds) {
+ Common::Rect r = bounds;
+ r.translate(0, MADS_SCENE_HEIGHT);
+ _vm->_screen.copyRectToScreen(r);
+}
+
+void UserInterface::scrollerChanged() {
+ warning("TODO: scrollerChanged");
+}
+
+void UserInterface::scrollInventory() {
+ Common::Array<int> &invList = _vm->_game->_objects._inventoryList;
+
+ if (_vm->_events->_mouseButtons) {
+ int yp = _vm->_events->currentPos().y;
+ if (yp < MADS_SCENE_HEIGHT || yp == (MADS_SCREEN_HEIGHT - 1)) {
+ uint32 timeDiff = _scrollFlag ? 100 : 380;
+ uint32 currentMilli = g_system->getMillis();
+ _vm->_game->_screenObjects._v8332A = -1;
+
+ if (currentMilli >= (_scrollMilli + timeDiff)) {
+ _scrollMilli = currentMilli;
+ _scrollFlag = true;
+
+ if (yp == (MADS_SCREEN_HEIGHT - 1)) {
+ if (_inventoryTopIndex < ((int)invList.size() - 1)) {
+ ++_inventoryTopIndex;
+ _inventoryChanged = true;
+ }
+ } else {
+ if (_inventoryTopIndex > 0) {
+ --_inventoryTopIndex;
+ _inventoryChanged = true;
+ }
+ }
+ }
+ }
+ }
+
+ _vm->_game->_screenObjects._v8332A = 0;
+}
+
+void UserInterface::synchronize(Common::Serializer &s) {
+ InventoryObjects &invObjects = _vm->_game->_objects;
+
+ if (s.isLoading()) {
+ _selectedInvIndex = invObjects._inventoryList.empty() ? -1 : 0;
+ }
+
+ for (int i = 0; i < 8; ++i)
+ s.syncAsSint16LE(_categoryIndexes[i]);
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h
new file mode 100644
index 0000000000..89044c9bf1
--- /dev/null
+++ b/engines/mads/user_interface.h
@@ -0,0 +1,306 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 MADS_USER_INTERFACE_H
+#define MADS_USER_INTERFACE_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+#include "common/str.h"
+#include "mads/msurface.h"
+#include "mads/screen.h"
+
+namespace MADS {
+
+enum { IMG_SPINNING_OBJECT = 200, IMG_TEXT_UPDATE = 201 };
+
+enum ScrollbarActive {
+ SCROLLBAR_NONE = 0, // No state
+ SCROLLBAR_UP = 1, // Up butotn
+ SCROLLBAR_DOWN = 2, // Down button
+ SCROLLBAR_ELEVATOR = 3, // Elevator bar
+ SCROLLBAR_THUMB = 4 // Scrollbar thumb
+};
+
+class AnimFrameEntry;
+class MADSEngine;
+
+class UISlot {
+public:
+ int _flags;
+ int _segmentId;
+ int _spritesIndex;
+ int _frameNumber;
+ Common::Point _position;
+
+ // Only used for IMG_OVERPRINT
+ int _width;
+ int _height;
+
+ UISlot();
+};
+
+/**
+ * Sprite list for the user interface
+ */
+class UISlots : public Common::Array<UISlot> {
+private:
+ MADSEngine *_vm;
+public:
+ /**
+ * Constructor
+ */
+ UISlots(MADSEngine *vm) : _vm(vm) {}
+
+ /**
+ * Add an overprint (text) entry to the list
+ */
+ void add(const Common::Rect &bounds);
+
+ /**
+ * Loads the data from an aimation frame entry
+ */
+ void add(const AnimFrameEntry &frameEntry);
+
+ /**
+ * Adds a special entry for full refresh of the user interface
+ */
+ void fullRefresh();
+
+ /**
+ * Draw all the sprites in the list on the user interface.
+ * @param updateFlag Flag drawn areas to be updated on physical screen
+ * @param delFlag Controls how used slots are deleted after drawing
+ */
+ void draw(bool updateFlag, bool delFlag);
+};
+
+class Conversation {
+private:
+ static MADSEngine *_vm;
+public:
+ static void init(MADSEngine *vm);
+public:
+ int _globalId;
+ Common::Array<int> _quotes;
+
+ /**
+ * Set up a conversation sequence
+ */
+ void setup(int globalId, ...);
+
+ /**
+ * Activates the passed set of quotes in the given conversation node
+ */
+ void set(int quoteId, ...);
+
+ /**
+ * Returns the bit for a given quote to indicate whether it's active or not or,
+ * if 0 is passed, returns the number of currently active quotes
+ */
+ int read(int quoteId);
+
+ /**
+ * Activates or deactivates the specified quote in the given conversation node
+ */
+ void write(int quoteId, bool flag);
+
+ /**
+ * Starts the conversation
+ */
+ void start();
+};
+
+class UserInterface : public MSurface {
+ friend class UISlots;
+private:
+ MADSEngine *_vm;
+ int _invSpritesIndex;
+ int _invFrameNumber;
+ uint32 _scrollMilli;
+ bool _scrollFlag;
+ int _noSegmentsActive;
+ int _someSegmentsActive;
+ ScrollbarActive _scrollbarStrokeType;
+
+ /**
+ * Loads the elements of the user interface
+ */
+ void loadElements();
+
+ /**
+ * Returns the area within the user interface a given element falls
+ */
+ bool getBounds(ScrCategory category, int invIndex, Common::Rect &bounds);
+
+ /**
+ * Reposition a bounding rectangle to physical co-ordinates
+ */
+ void moveRect(Common::Rect &bounds);
+
+ /**
+ * Draw options during a conversation.
+ */
+ void drawConversationList();
+
+ /**
+ * Draw the action list
+ */
+ void drawActions();
+
+ /**
+ * Draw the inventory list
+ */
+ void drawInventoryList();
+
+ /**
+ * Draw the inventory item vocab list
+ */
+ void drawItemVocabList();
+
+ /**
+ * Draw the inventory scroller
+ */
+ void drawScroller();
+
+ /**
+ * Called when the inventory scrollbar has changed
+ */
+ void scrollbarChanged();
+
+ /**
+ * Draw a UI textual element
+ */
+ void writeVocab(ScrCategory category, int id);
+
+ void refresh();
+
+ void updateRect(const Common::Rect &bounds);
+public:
+ MSurface _surface;
+ UISlots _uiSlots;
+ DirtyAreas _dirtyAreas;
+ ScrCategory _category;
+ Common::Rect *_rectP;
+ int _inventoryTopIndex;
+ int _selectedInvIndex;
+ int _selectedActionIndex;
+ int _selectedItemVocabIdx;
+ ScrollbarActive _scrollbarActive, _scrollbarOldActive;
+ int _highlightedCommandIndex;
+ int _highlightedInvIndex;
+ int _highlightedItemVocabIndex;
+ bool _inventoryChanged;
+ int _categoryIndexes[8];
+ Common::StringArray _talkStrings;
+ Common::Array<int> _talkIds;
+ bool _scrollbarQuickly;
+ uint32 _scrollbarMilliTime;
+ int _scrollbarElevator, _scrollbarOldElevator;
+public:
+ /**
+ * Constructor
+ */
+ UserInterface(MADSEngine *vm);
+
+ /**
+ * Loads an interface from a specified resource
+ */
+ virtual void load(const Common::String &resName);
+
+ /**
+ * Set up the interface
+ */
+ void setup(InputMode inputMode);
+
+ void drawTextElements();
+
+ /**
+ * Merges a sub-section of another surface into the user interface without
+ * destroying any on-screen text
+ * @param src Source surface
+ * @param srcBounds Area to copy/merge from
+ * @param destPos Destination position to draw in current surface
+ * @param transparencyIndex Transparency color
+ */
+ void mergeFrom(MSurface *src, const Common::Rect &srcBounds, const Common::Point &destPos,
+ int transparencyIndex = -1);
+
+ /**
+ * Loads the animation sprite data for a given inventory object
+ */
+ void loadInventoryAnim(int objectId);
+
+ /**
+ * Resets the inventory animation when no inventory item is selected
+ */
+ void noInventoryAnim();
+
+ /**
+ * Handles any animation that occurs in the background of the user interface
+ */
+ void doBackgroundAnimation();
+
+ /**
+ * Handles queuing a new frame of an inventory animation for drawing
+ */
+ void inventoryAnim();
+
+ void categoryChanged();
+
+ /**
+ * Select an item from the inventory list
+ * @param invIndex Index in the inventory list of the item to select
+ */
+ void selectObject(int invIndex);
+
+ void updateSelection(ScrCategory category, int newIndex, int *idx);
+
+ void scrollerChanged();
+
+ void scrollInventory();
+
+ /**
+ * Checks for the mouse being on the user interface inventory scroller,
+ * and update the scroller highlight and selected inventory object as necessary
+ */
+ void updateInventoryScroller();
+
+ /**
+ * Empties the current conversation talk list
+ */
+ void emptyConversationList();
+
+ /**
+ * Add a msesage to the list of conversation items to select from
+ */
+ void addConversationMessage(int vocabId, const Common::String &msg);
+
+ /**
+ * Synchronize the data
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_USER_INTERFACE_H */
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 2e83eb3328..d49f3e8637 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -49,20 +49,20 @@ namespace Mohawk {
#ifdef ENABLE_MYST
MystConsole::MystConsole(MohawkEngine_Myst *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("changeCard", WRAP_METHOD(MystConsole, Cmd_ChangeCard));
- DCmd_Register("curCard", WRAP_METHOD(MystConsole, Cmd_CurCard));
- DCmd_Register("var", WRAP_METHOD(MystConsole, Cmd_Var));
- DCmd_Register("curStack", WRAP_METHOD(MystConsole, Cmd_CurStack));
- DCmd_Register("changeStack", WRAP_METHOD(MystConsole, Cmd_ChangeStack));
- DCmd_Register("drawImage", WRAP_METHOD(MystConsole, Cmd_DrawImage));
- DCmd_Register("drawRect", WRAP_METHOD(MystConsole, Cmd_DrawRect));
- DCmd_Register("setResourceEnable", WRAP_METHOD(MystConsole, Cmd_SetResourceEnable));
- DCmd_Register("playSound", WRAP_METHOD(MystConsole, Cmd_PlaySound));
- DCmd_Register("stopSound", WRAP_METHOD(MystConsole, Cmd_StopSound));
- DCmd_Register("playMovie", WRAP_METHOD(MystConsole, Cmd_PlayMovie));
- DCmd_Register("disableInitOpcodes", WRAP_METHOD(MystConsole, Cmd_DisableInitOpcodes));
- DCmd_Register("cache", WRAP_METHOD(MystConsole, Cmd_Cache));
- DCmd_Register("resources", WRAP_METHOD(MystConsole, Cmd_Resources));
+ registerCmd("changeCard", WRAP_METHOD(MystConsole, Cmd_ChangeCard));
+ registerCmd("curCard", WRAP_METHOD(MystConsole, Cmd_CurCard));
+ registerCmd("var", WRAP_METHOD(MystConsole, Cmd_Var));
+ registerCmd("curStack", WRAP_METHOD(MystConsole, Cmd_CurStack));
+ registerCmd("changeStack", WRAP_METHOD(MystConsole, Cmd_ChangeStack));
+ registerCmd("drawImage", WRAP_METHOD(MystConsole, Cmd_DrawImage));
+ registerCmd("drawRect", WRAP_METHOD(MystConsole, Cmd_DrawRect));
+ registerCmd("setResourceEnable", WRAP_METHOD(MystConsole, Cmd_SetResourceEnable));
+ registerCmd("playSound", WRAP_METHOD(MystConsole, Cmd_PlaySound));
+ registerCmd("stopSound", WRAP_METHOD(MystConsole, Cmd_StopSound));
+ registerCmd("playMovie", WRAP_METHOD(MystConsole, Cmd_PlayMovie));
+ registerCmd("disableInitOpcodes", WRAP_METHOD(MystConsole, Cmd_DisableInitOpcodes));
+ registerCmd("cache", WRAP_METHOD(MystConsole, Cmd_Cache));
+ registerCmd("resources", WRAP_METHOD(MystConsole, Cmd_Resources));
}
MystConsole::~MystConsole() {
@@ -70,7 +70,7 @@ MystConsole::~MystConsole() {
bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: changeCard <card>\n");
+ debugPrintf("Usage: changeCard <card>\n");
return true;
}
@@ -81,20 +81,20 @@ bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) {
}
bool MystConsole::Cmd_CurCard(int argc, const char **argv) {
- DebugPrintf("Current Card: %d\n", _vm->getCurCard());
+ debugPrintf("Current Card: %d\n", _vm->getCurCard());
return true;
}
bool MystConsole::Cmd_Var(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: var <var> (<value>)\n");
+ debugPrintf("Usage: var <var> (<value>)\n");
return true;
}
if (argc > 2)
_vm->_scriptParser->setVarValue((uint16)atoi(argv[1]), (uint16)atoi(argv[2]));
- DebugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_scriptParser->getVar((uint16)atoi(argv[1])));
+ debugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_scriptParser->getVar((uint16)atoi(argv[1])));
return true;
}
@@ -130,19 +130,19 @@ static const uint16 default_start_card[12] = {
};
bool MystConsole::Cmd_CurStack(int argc, const char **argv) {
- DebugPrintf("Current Stack: %s\n", mystStackNames[_vm->getCurStack()]);
+ debugPrintf("Current Stack: %s\n", mystStackNames[_vm->getCurStack()]);
return true;
}
bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) {
if (argc != 2 && argc != 3) {
- DebugPrintf("Usage: changeStack <stack> [<card>]\n\n");
- DebugPrintf("Stacks:\n=======\n");
+ debugPrintf("Usage: changeStack <stack> [<card>]\n\n");
+ debugPrintf("Stacks:\n=======\n");
for (byte i = 0; i < ARRAYSIZE(mystStackNames); i++)
- DebugPrintf(" %s\n", mystStackNames[i]);
+ debugPrintf(" %s\n", mystStackNames[i]);
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
@@ -156,7 +156,7 @@ bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) {
}
if (!stackNum) {
- DebugPrintf("\'%s\' is not a stack name!\n", argv[1]);
+ debugPrintf("\'%s\' is not a stack name!\n", argv[1]);
return true;
}
@@ -177,7 +177,7 @@ bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) {
bool MystConsole::Cmd_DrawImage(int argc, const char **argv) {
if (argc != 2 && argc != 6) {
- DebugPrintf("Usage: drawImage <image> [<left> <top> <right> <bottom>]\n");
+ debugPrintf("Usage: drawImage <image> [<left> <top> <right> <bottom>]\n");
return true;
}
@@ -195,8 +195,8 @@ bool MystConsole::Cmd_DrawImage(int argc, const char **argv) {
bool MystConsole::Cmd_DrawRect(int argc, const char **argv) {
if (argc != 5 && argc != 2) {
- DebugPrintf("Usage: drawRect <left> <top> <right> <bottom>\n");
- DebugPrintf("Usage: drawRect <resource id>\n");
+ debugPrintf("Usage: drawRect <left> <top> <right> <bottom>\n");
+ debugPrintf("Usage: drawRect <resource id>\n");
return true;
}
@@ -213,7 +213,7 @@ bool MystConsole::Cmd_DrawRect(int argc, const char **argv) {
bool MystConsole::Cmd_SetResourceEnable(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("Usage: setResourceEnable <resource id> <bool>\n");
+ debugPrintf("Usage: setResourceEnable <resource id> <bool>\n");
return true;
}
@@ -223,7 +223,7 @@ bool MystConsole::Cmd_SetResourceEnable(int argc, const char **argv) {
bool MystConsole::Cmd_PlaySound(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: playSound <value>\n");
+ debugPrintf("Usage: playSound <value>\n");
return true;
}
@@ -234,7 +234,7 @@ bool MystConsole::Cmd_PlaySound(int argc, const char **argv) {
}
bool MystConsole::Cmd_StopSound(int argc, const char **argv) {
- DebugPrintf("Stopping Sound\n");
+ debugPrintf("Stopping Sound\n");
_vm->_sound->stopSound();
@@ -243,8 +243,8 @@ bool MystConsole::Cmd_StopSound(int argc, const char **argv) {
bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: playMovie <name> [<stack>] [<left> <top>]\n");
- DebugPrintf("NOTE: The movie will play *once* in the background.\n");
+ debugPrintf("Usage: playMovie <name> [<stack>] [<left> <top>]\n");
+ debugPrintf("NOTE: The movie will play *once* in the background.\n");
return true;
}
@@ -258,7 +258,7 @@ bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) {
}
if (!stackNum) {
- DebugPrintf("\'%s\' is not a stack name!\n", argv[2]);
+ debugPrintf("\'%s\' is not a stack name!\n", argv[2]);
return true;
}
}
@@ -277,7 +277,7 @@ bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) {
bool MystConsole::Cmd_DisableInitOpcodes(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: disableInitOpcodes\n");
+ debugPrintf("Usage: disableInitOpcodes\n");
return true;
}
@@ -289,7 +289,7 @@ bool MystConsole::Cmd_DisableInitOpcodes(int argc, const char **argv) {
bool MystConsole::Cmd_Cache(int argc, const char **argv) {
if (argc > 2) {
- DebugPrintf("Usage: cache on/off - Omit parameter to get current state\n");
+ debugPrintf("Usage: cache on/off - Omit parameter to get current state\n");
return true;
}
@@ -304,15 +304,15 @@ bool MystConsole::Cmd_Cache(int argc, const char **argv) {
_vm->setCacheState(state);
}
- DebugPrintf("Cache: %s\n", state ? "Enabled" : "Disabled");
+ debugPrintf("Cache: %s\n", state ? "Enabled" : "Disabled");
return true;
}
bool MystConsole::Cmd_Resources(int argc, const char **argv) {
- DebugPrintf("Resources in card %d:\n", _vm->getCurCard());
+ debugPrintf("Resources in card %d:\n", _vm->getCurCard());
for (uint i = 0; i < _vm->_resources.size(); i++) {
- DebugPrintf("#%2d %s\n", i, _vm->_resources[i]->describe().c_str());
+ debugPrintf("#%2d %s\n", i, _vm->_resources[i]->describe().c_str());
}
return true;
@@ -323,21 +323,21 @@ bool MystConsole::Cmd_Resources(int argc, const char **argv) {
#ifdef ENABLE_RIVEN
RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("changeCard", WRAP_METHOD(RivenConsole, Cmd_ChangeCard));
- DCmd_Register("curCard", WRAP_METHOD(RivenConsole, Cmd_CurCard));
- DCmd_Register("var", WRAP_METHOD(RivenConsole, Cmd_Var));
- DCmd_Register("playSound", WRAP_METHOD(RivenConsole, Cmd_PlaySound));
- DCmd_Register("playSLST", WRAP_METHOD(RivenConsole, Cmd_PlaySLST));
- DCmd_Register("stopSound", WRAP_METHOD(RivenConsole, Cmd_StopSound));
- DCmd_Register("curStack", WRAP_METHOD(RivenConsole, Cmd_CurStack));
- DCmd_Register("changeStack", WRAP_METHOD(RivenConsole, Cmd_ChangeStack));
- DCmd_Register("hotspots", WRAP_METHOD(RivenConsole, Cmd_Hotspots));
- DCmd_Register("zipMode", WRAP_METHOD(RivenConsole, Cmd_ZipMode));
- DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript));
- DCmd_Register("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards));
- DCmd_Register("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP));
- DCmd_Register("combos", WRAP_METHOD(RivenConsole, Cmd_Combos));
- DCmd_Register("sliderState", WRAP_METHOD(RivenConsole, Cmd_SliderState));
+ registerCmd("changeCard", WRAP_METHOD(RivenConsole, Cmd_ChangeCard));
+ registerCmd("curCard", WRAP_METHOD(RivenConsole, Cmd_CurCard));
+ registerCmd("var", WRAP_METHOD(RivenConsole, Cmd_Var));
+ registerCmd("playSound", WRAP_METHOD(RivenConsole, Cmd_PlaySound));
+ registerCmd("playSLST", WRAP_METHOD(RivenConsole, Cmd_PlaySLST));
+ registerCmd("stopSound", WRAP_METHOD(RivenConsole, Cmd_StopSound));
+ registerCmd("curStack", WRAP_METHOD(RivenConsole, Cmd_CurStack));
+ registerCmd("changeStack", WRAP_METHOD(RivenConsole, Cmd_ChangeStack));
+ registerCmd("hotspots", WRAP_METHOD(RivenConsole, Cmd_Hotspots));
+ registerCmd("zipMode", WRAP_METHOD(RivenConsole, Cmd_ZipMode));
+ registerCmd("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript));
+ registerCmd("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards));
+ registerCmd("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP));
+ registerCmd("combos", WRAP_METHOD(RivenConsole, Cmd_Combos));
+ registerCmd("sliderState", WRAP_METHOD(RivenConsole, Cmd_SliderState));
}
RivenConsole::~RivenConsole() {
@@ -346,7 +346,7 @@ RivenConsole::~RivenConsole() {
bool RivenConsole::Cmd_ChangeCard(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: changeCard <card>\n");
+ debugPrintf("Usage: changeCard <card>\n");
return true;
}
@@ -358,19 +358,19 @@ bool RivenConsole::Cmd_ChangeCard(int argc, const char **argv) {
}
bool RivenConsole::Cmd_CurCard(int argc, const char **argv) {
- DebugPrintf("Current Card: %d\n", _vm->getCurCard());
+ debugPrintf("Current Card: %d\n", _vm->getCurCard());
return true;
}
bool RivenConsole::Cmd_Var(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: var <var name> (<value>)\n");
+ debugPrintf("Usage: var <var name> (<value>)\n");
return true;
}
if (!_vm->_vars.contains(argv[1])) {
- DebugPrintf("Unknown variable '%s'\n", argv[1]);
+ debugPrintf("Unknown variable '%s'\n", argv[1]);
return true;
}
@@ -379,13 +379,13 @@ bool RivenConsole::Cmd_Var(int argc, const char **argv) {
if (argc > 2)
var = (uint32)atoi(argv[2]);
- DebugPrintf("%s = %d\n", argv[1], var);
+ debugPrintf("%s = %d\n", argv[1], var);
return true;
}
bool RivenConsole::Cmd_PlaySound(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: playSound <value>\n");
+ debugPrintf("Usage: playSound <value>\n");
return true;
}
@@ -397,7 +397,7 @@ bool RivenConsole::Cmd_PlaySound(int argc, const char **argv) {
bool RivenConsole::Cmd_PlaySLST(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: playSLST <slst index> <card, default = current>\n");
+ debugPrintf("Usage: playSLST <slst index> <card, default = current>\n");
return true;
}
@@ -412,7 +412,7 @@ bool RivenConsole::Cmd_PlaySLST(int argc, const char **argv) {
}
bool RivenConsole::Cmd_StopSound(int argc, const char **argv) {
- DebugPrintf("Stopping Sound\n");
+ debugPrintf("Stopping Sound\n");
_vm->_sound->stopSound();
_vm->_sound->stopAllSLST();
@@ -420,58 +420,57 @@ bool RivenConsole::Cmd_StopSound(int argc, const char **argv) {
}
bool RivenConsole::Cmd_CurStack(int argc, const char **argv) {
- DebugPrintf("Current Stack: %s\n", _vm->getStackName(_vm->getCurStack()).c_str());
+ debugPrintf("Current Stack: %s\n", _vm->getStackName(_vm->getCurStack()).c_str());
return true;
}
bool RivenConsole::Cmd_ChangeStack(int argc, const char **argv) {
- byte i;
-
if (argc < 3) {
- DebugPrintf("Usage: changeStack <stack> <card>\n\n");
- DebugPrintf("Stacks:\n=======\n");
+ debugPrintf("Usage: changeStack <stack> <card>\n\n");
+ debugPrintf("Stacks:\n=======\n");
- for (i = 0; i <= tspit; i++)
- DebugPrintf(" %s\n", _vm->getStackName(i).c_str());
+ for (uint i = kStackFirst; i <= kStackLast; i++)
+ debugPrintf(" %s\n", _vm->getStackName(i).c_str());
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
- byte stackNum = 0;
+ uint stack = kStackUnknown;
- for (i = 1; i <= tspit + 1; i++)
- if (!scumm_stricmp(argv[1], _vm->getStackName(i - 1).c_str())) {
- stackNum = i;
+ for (uint i = kStackFirst; i <= kStackLast; i++) {
+ if (!scumm_stricmp(argv[1], _vm->getStackName(i).c_str())) {
+ stack = i;
break;
}
+ }
- if (!stackNum) {
- DebugPrintf("\'%s\' is not a stack name!\n", argv[1]);
+ if (stack == kStackUnknown) {
+ debugPrintf("\'%s\' is not a stack name!\n", argv[1]);
return true;
}
- _vm->changeToStack(stackNum - 1);
+ _vm->changeToStack(stack);
_vm->changeToCard((uint16)atoi(argv[2]));
return false;
}
bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) {
- DebugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard(), _vm->getHotspotCount());
+ debugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard(), _vm->getHotspotCount());
for (uint16 i = 0; i < _vm->getHotspotCount(); i++) {
- DebugPrintf("Hotspot %d, index %d, BLST ID %d (", i, _vm->_hotspots[i].index, _vm->_hotspots[i].blstID);
+ debugPrintf("Hotspot %d, index %d, BLST ID %d (", i, _vm->_hotspots[i].index, _vm->_hotspots[i].blstID);
if (_vm->_hotspots[i].enabled)
- DebugPrintf("enabled");
+ debugPrintf("enabled");
else
- DebugPrintf("disabled");
+ debugPrintf("disabled");
- DebugPrintf(") - (%d, %d, %d, %d)\n", _vm->_hotspots[i].rect.left, _vm->_hotspots[i].rect.top, _vm->_hotspots[i].rect.right, _vm->_hotspots[i].rect.bottom);
- DebugPrintf(" Name = %s\n", _vm->getHotspotName(i).c_str());
+ debugPrintf(") - (%d, %d, %d, %d)\n", _vm->_hotspots[i].rect.left, _vm->_hotspots[i].rect.top, _vm->_hotspots[i].rect.right, _vm->_hotspots[i].rect.bottom);
+ debugPrintf(" Name = %s\n", _vm->getHotspotName(i).c_str());
}
return true;
@@ -481,34 +480,33 @@ bool RivenConsole::Cmd_ZipMode(int argc, const char **argv) {
uint32 &zipModeActive = _vm->_vars["azip"];
zipModeActive = !zipModeActive;
- DebugPrintf("Zip Mode is ");
- DebugPrintf(zipModeActive ? "Enabled" : "Disabled");
- DebugPrintf("\n");
+ debugPrintf("Zip Mode is ");
+ debugPrintf(zipModeActive ? "Enabled" : "Disabled");
+ debugPrintf("\n");
return true;
}
bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
if (argc < 4) {
- DebugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n");
+ debugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n");
return true;
}
uint16 oldStack = _vm->getCurStack();
+ uint newStack = kStackUnknown;
- byte newStack = 0;
-
- for (byte i = 1; i <= tspit + 1; i++)
- if (!scumm_stricmp(argv[1], _vm->getStackName(i - 1).c_str())) {
+ for (uint i = kStackFirst; i <= kStackLast; i++) {
+ if (!scumm_stricmp(argv[1], _vm->getStackName(i).c_str())) {
newStack = i;
break;
}
+ }
- if (!newStack) {
- DebugPrintf("\'%s\' is not a stack name!\n", argv[1]);
+ if (newStack == kStackUnknown) {
+ debugPrintf("\'%s\' is not a stack name!\n", argv[1]);
return true;
}
- newStack--;
_vm->changeToStack(newStack);
// Load in Variable Names
@@ -594,7 +592,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
delete hsptStream;
} else {
- DebugPrintf("%s doesn't have any scripts!\n", argv[2]);
+ debugPrintf("%s doesn't have any scripts!\n", argv[2]);
}
// See above for why this is printed via debugN
@@ -602,18 +600,18 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
_vm->changeToStack(oldStack);
- DebugPrintf("Script dump complete.\n");
+ debugPrintf("Script dump complete.\n");
return true;
}
bool RivenConsole::Cmd_ListZipCards(int argc, const char **argv) {
if (_vm->_zipModeData.size() == 0) {
- DebugPrintf("No zip card data.\n");
+ debugPrintf("No zip card data.\n");
} else {
- DebugPrintf("Listing zip cards:\n");
+ debugPrintf("Listing zip cards:\n");
for (uint32 i = 0; i < _vm->_zipModeData.size(); i++)
- DebugPrintf("ID = %d, Name = %s\n", _vm->_zipModeData[i].id, _vm->_zipModeData[i].name.c_str());
+ debugPrintf("ID = %d, Name = %s\n", _vm->_zipModeData[i].id, _vm->_zipModeData[i].name.c_str());
}
return true;
@@ -621,7 +619,7 @@ bool RivenConsole::Cmd_ListZipCards(int argc, const char **argv) {
bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) {
uint32 rmapCode = _vm->getCurCardRMAP();
- DebugPrintf("RMAP for %s %d = %08x\n", _vm->getStackName(_vm->getCurStack()).c_str(), _vm->getCurCard(), rmapCode);
+ debugPrintf("RMAP for %s %d = %08x\n", _vm->getStackName(_vm->getCurStack()).c_str(), _vm->getCurCard(), rmapCode);
return true;
}
@@ -635,20 +633,20 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
uint32 prisonCombo = _vm->_vars["pcorrectorder"];
uint32 domeCombo = _vm->_vars["adomecombo"];
- DebugPrintf("Telescope Combo:\n ");
+ debugPrintf("Telescope Combo:\n ");
for (int i = 0; i < 5; i++)
- DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i));
+ debugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i));
- DebugPrintf("\nPrison Combo:\n ");
+ debugPrintf("\nPrison Combo:\n ");
for (int i = 0; i < 5; i++)
- DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i));
+ debugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i));
- DebugPrintf("\nDome Combo:\n ");
+ debugPrintf("\nDome Combo:\n ");
for (int i = 1; i <= 25; i++)
if (domeCombo & (1 << (25 - i)))
- DebugPrintf("%d ", i);
+ debugPrintf("%d ", i);
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
@@ -656,17 +654,17 @@ bool RivenConsole::Cmd_SliderState(int argc, const char **argv) {
if (argc > 1)
_vm->_externalScriptHandler->setDomeSliderState((uint32)atoi(argv[1]));
- DebugPrintf("Dome Slider State = %08x\n", _vm->_externalScriptHandler->getDomeSliderState());
+ debugPrintf("Dome Slider State = %08x\n", _vm->_externalScriptHandler->getDomeSliderState());
return true;
}
#endif // ENABLE_RIVEN
LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound));
- DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound));
- DCmd_Register("drawImage", WRAP_METHOD(LivingBooksConsole, Cmd_DrawImage));
- DCmd_Register("changePage", WRAP_METHOD(LivingBooksConsole, Cmd_ChangePage));
+ registerCmd("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound));
+ registerCmd("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound));
+ registerCmd("drawImage", WRAP_METHOD(LivingBooksConsole, Cmd_DrawImage));
+ registerCmd("changePage", WRAP_METHOD(LivingBooksConsole, Cmd_ChangePage));
}
LivingBooksConsole::~LivingBooksConsole() {
@@ -674,7 +672,7 @@ LivingBooksConsole::~LivingBooksConsole() {
bool LivingBooksConsole::Cmd_PlaySound(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: playSound <value>\n");
+ debugPrintf("Usage: playSound <value>\n");
return true;
}
@@ -684,7 +682,7 @@ bool LivingBooksConsole::Cmd_PlaySound(int argc, const char **argv) {
}
bool LivingBooksConsole::Cmd_StopSound(int argc, const char **argv) {
- DebugPrintf("Stopping Sound\n");
+ debugPrintf("Stopping Sound\n");
_vm->_sound->stopSound();
return true;
@@ -692,7 +690,7 @@ bool LivingBooksConsole::Cmd_StopSound(int argc, const char **argv) {
bool LivingBooksConsole::Cmd_DrawImage(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: drawImage <value>\n");
+ debugPrintf("Usage: drawImage <value>\n");
return true;
}
@@ -703,13 +701,13 @@ bool LivingBooksConsole::Cmd_DrawImage(int argc, const char **argv) {
bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) {
if (argc < 2 || argc > 3) {
- DebugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n");
+ debugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n");
return true;
}
int page, subpage = 0;
if (sscanf(argv[1], "%d.%d", &page, &subpage) == 0) {
- DebugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n");
+ debugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n");
return true;
}
LBMode mode = argc == 2 ? _vm->getCurMode() : (LBMode)atoi(argv[2]);
@@ -720,21 +718,21 @@ bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) {
if (_vm->loadPage(mode, page, subpage))
return false;
}
- DebugPrintf("no such page %d.%d\n", page, subpage);
+ debugPrintf("no such page %d.%d\n", page, subpage);
return true;
}
#ifdef ENABLE_CSTIME
CSTimeConsole::CSTimeConsole(MohawkEngine_CSTime *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("playSound", WRAP_METHOD(CSTimeConsole, Cmd_PlaySound));
- DCmd_Register("stopSound", WRAP_METHOD(CSTimeConsole, Cmd_StopSound));
- DCmd_Register("drawImage", WRAP_METHOD(CSTimeConsole, Cmd_DrawImage));
- DCmd_Register("drawSubimage", WRAP_METHOD(CSTimeConsole, Cmd_DrawSubimage));
- DCmd_Register("changeCase", WRAP_METHOD(CSTimeConsole, Cmd_ChangeCase));
- DCmd_Register("changeScene", WRAP_METHOD(CSTimeConsole, Cmd_ChangeScene));
- DCmd_Register("caseVariable", WRAP_METHOD(CSTimeConsole, Cmd_CaseVariable));
- DCmd_Register("invItem", WRAP_METHOD(CSTimeConsole, Cmd_InvItem));
+ registerCmd("playSound", WRAP_METHOD(CSTimeConsole, Cmd_PlaySound));
+ registerCmd("stopSound", WRAP_METHOD(CSTimeConsole, Cmd_StopSound));
+ registerCmd("drawImage", WRAP_METHOD(CSTimeConsole, Cmd_DrawImage));
+ registerCmd("drawSubimage", WRAP_METHOD(CSTimeConsole, Cmd_DrawSubimage));
+ registerCmd("changeCase", WRAP_METHOD(CSTimeConsole, Cmd_ChangeCase));
+ registerCmd("changeScene", WRAP_METHOD(CSTimeConsole, Cmd_ChangeScene));
+ registerCmd("caseVariable", WRAP_METHOD(CSTimeConsole, Cmd_CaseVariable));
+ registerCmd("invItem", WRAP_METHOD(CSTimeConsole, Cmd_InvItem));
}
CSTimeConsole::~CSTimeConsole() {
@@ -742,7 +740,7 @@ CSTimeConsole::~CSTimeConsole() {
bool CSTimeConsole::Cmd_PlaySound(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: playSound <value>\n");
+ debugPrintf("Usage: playSound <value>\n");
return true;
}
@@ -752,7 +750,7 @@ bool CSTimeConsole::Cmd_PlaySound(int argc, const char **argv) {
}
bool CSTimeConsole::Cmd_StopSound(int argc, const char **argv) {
- DebugPrintf("Stopping Sound\n");
+ debugPrintf("Stopping Sound\n");
_vm->_sound->stopSound();
return true;
@@ -760,7 +758,7 @@ bool CSTimeConsole::Cmd_StopSound(int argc, const char **argv) {
bool CSTimeConsole::Cmd_DrawImage(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: drawImage <value>\n");
+ debugPrintf("Usage: drawImage <value>\n");
return true;
}
@@ -771,7 +769,7 @@ bool CSTimeConsole::Cmd_DrawImage(int argc, const char **argv) {
bool CSTimeConsole::Cmd_DrawSubimage(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("Usage: drawSubimage <value> <subimage>\n");
+ debugPrintf("Usage: drawSubimage <value> <subimage>\n");
return true;
}
@@ -782,7 +780,7 @@ bool CSTimeConsole::Cmd_DrawSubimage(int argc, const char **argv) {
bool CSTimeConsole::Cmd_ChangeCase(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: changeCase <value>\n");
+ debugPrintf("Usage: changeCase <value>\n");
return true;
}
@@ -792,7 +790,7 @@ bool CSTimeConsole::Cmd_ChangeCase(int argc, const char **argv) {
bool CSTimeConsole::Cmd_ChangeScene(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: changeScene <value>\n");
+ debugPrintf("Usage: changeScene <value>\n");
return true;
}
@@ -802,12 +800,12 @@ bool CSTimeConsole::Cmd_ChangeScene(int argc, const char **argv) {
bool CSTimeConsole::Cmd_CaseVariable(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: caseVariable <id> [<value>]\n");
+ debugPrintf("Usage: caseVariable <id> [<value>]\n");
return true;
}
if (argc == 2) {
- DebugPrintf("case variable %d has value %d\n", atoi(argv[1]), _vm->_caseVariable[atoi(argv[1])]);
+ debugPrintf("case variable %d has value %d\n", atoi(argv[1]), _vm->_caseVariable[atoi(argv[1])]);
} else {
_vm->_caseVariable[atoi(argv[1])] = atoi(argv[2]);
}
@@ -816,7 +814,7 @@ bool CSTimeConsole::Cmd_CaseVariable(int argc, const char **argv) {
bool CSTimeConsole::Cmd_InvItem(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("Usage: invItem <id> <0 or 1>\n");
+ debugPrintf("Usage: invItem <id> <0 or 1>\n");
return true;
}
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index 8a9c0f70fa..7632cde294 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -294,7 +294,7 @@ static const MohawkGameDescription gameDescriptions[] = {
},
// Riven: The Sequel to Myst
- // Version 1.? (5CD)
+ // Version 1.? (5CD) - Spanish
// From jvprat
{
{
@@ -312,6 +312,24 @@ static const MohawkGameDescription gameDescriptions[] = {
},
// Riven: The Sequel to Myst
+ // Version 1.0 (5CD) - Italian
+ // From dodomorandi on bug #6629
+ {
+ {
+ "riven",
+ "",
+ AD_ENTRY1("a_Data.MHK", "0e21e89df7788f32056b6521abf2e81a"),
+ Common::IT_ITA,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NOASPECT)
+ },
+ GType_RIVEN,
+ 0,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
// Version 1.? (DVD, From "Myst 10th Anniversary Edition")
// From Clone2727
{
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index 3181b78ae1..b5d1285435 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -353,7 +353,7 @@ void Mechanical::o_elevatorRotationMove(uint16 op, uint16 var, uint16 argc, uint
int16 step = ((rect.bottom - mouse.y) * lever->getNumFrames()) / rect.height();
step = CLIP<int16>(step, 0, maxStep);
- _elevatorRotationSpeed = step * 0.1;
+ _elevatorRotationSpeed = step * 0.1f;
// Draw current frame
lever->drawFrame(step);
@@ -386,9 +386,9 @@ void Mechanical::o_elevatorRotationStop(uint16 op, uint16 var, uint16 argc, uint
// Decrease speed
while (speed > 2) {
- speed -= 0.5;
+ speed -= 0.5f;
- _elevatorRotationGearPosition += speed * 0.1;
+ _elevatorRotationGearPosition += speed * 0.1f;
if (_elevatorRotationGearPosition > 12)
break;
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index 710c36ac8d..d8dbeef641 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -42,6 +42,7 @@ Stoneship::Stoneship(MohawkEngine_Myst *vm) :
_tunnelRunning = false;
+ _state.lightState = 0;
_state.generatorDepletionTime = 0;
_state.generatorDuration = 0;
_cabinMystBookPresent = 0;
diff --git a/engines/mohawk/myst_state.cpp b/engines/mohawk/myst_state.cpp
index d07aa9d5ec..3e54017df8 100644
--- a/engines/mohawk/myst_state.cpp
+++ b/engines/mohawk/myst_state.cpp
@@ -100,6 +100,9 @@ bool MystGameState::load(const Common::String &filename) {
syncGameState(s, size == 664);
delete loadFile;
+ // Set Channelwood elevator state to down, because we start on the lower level
+ _channelwood.elevatorState = 0;
+
// Switch us back to the intro stack, to the linking book
_vm->changeToStack(kIntroStack, 5, 0, 0);
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index e1059bebaa..a7fe12b9e1 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -55,7 +55,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
_activatedSLST = false;
_ignoreNextMouseUp = false;
_extrasFile = 0;
- _curStack = aspit;
+ _curStack = kStackUnknown;
_hotspots = 0;
removeTimer();
@@ -161,7 +161,7 @@ Common::Error MohawkEngine_Riven::run() {
// Let's begin, shall we?
if (getFeatures() & GF_DEMO) {
// Start the demo off with the videos
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(6);
} else if (ConfMan.hasKey("save_slot")) {
// Load game from launcher/command line if requested
@@ -172,12 +172,12 @@ Common::Error MohawkEngine_Riven::run() {
// Attempt to load the game. On failure, just send us to the main menu.
if (_saveLoad->loadGame(savedGamesList[gameToLoad]).getCode() != Common::kNoError) {
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(1);
}
} else {
// Otherwise, start us off at aspit's card 1 (the main menu)
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(1);
}
@@ -255,16 +255,16 @@ void MohawkEngine_Riven::handleEvents() {
case Common::KEYCODE_r:
// Return to the main menu in the demo on ctrl+r
if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) {
- if (_curStack != aspit)
- changeToStack(aspit);
+ if (_curStack != kStackAspit)
+ changeToStack(kStackAspit);
changeToCard(1);
}
break;
case Common::KEYCODE_p:
// Play the intro videos in the demo on ctrl+p
if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) {
- if (_curStack != aspit)
- changeToStack(aspit);
+ if (_curStack != kStackAspit)
+ changeToStack(kStackAspit);
changeToCard(6);
}
break;
@@ -343,20 +343,22 @@ struct RivenSpecialChange {
uint32 startCardRMAP;
byte targetStack;
uint32 targetCardRMAP;
-} rivenSpecialChange[] = {
- { aspit, 0x1f04, ospit, 0x44ad }, // Trap Book
- { bspit, 0x1c0e7, ospit, 0x2e76 }, // Dome Linking Book
- { gspit, 0x111b1, ospit, 0x2e76 }, // Dome Linking Book
- { jspit, 0x28a18, rspit, 0xf94 }, // Tay Linking Book
- { jspit, 0x26228, ospit, 0x2e76 }, // Dome Linking Book
- { ospit, 0x5f0d, pspit, 0x3bf0 }, // Return from 233rd Age
- { ospit, 0x470a, jspit, 0x1508e }, // Return from 233rd Age
- { ospit, 0x5c52, gspit, 0x10bea }, // Return from 233rd Age
- { ospit, 0x5d68, bspit, 0x1adfd }, // Return from 233rd Age
- { ospit, 0x5e49, tspit, 0xe87 }, // Return from 233rd Age
- { pspit, 0x4108, ospit, 0x2e76 }, // Dome Linking Book
- { rspit, 0x32d8, jspit, 0x1c474 }, // Return from Tay
- { tspit, 0x21b69, ospit, 0x2e76 } // Dome Linking Book
+};
+
+static const RivenSpecialChange rivenSpecialChange[] = {
+ { kStackAspit, 0x1f04, kStackOspit, 0x44ad }, // Trap Book
+ { kStackBspit, 0x1c0e7, kStackOspit, 0x2e76 }, // Dome Linking Book
+ { kStackGspit, 0x111b1, kStackOspit, 0x2e76 }, // Dome Linking Book
+ { kStackJspit, 0x28a18, kStackRspit, 0xf94 }, // Tay Linking Book
+ { kStackJspit, 0x26228, kStackOspit, 0x2e76 }, // Dome Linking Book
+ { kStackOspit, 0x5f0d, kStackPspit, 0x3bf0 }, // Return from 233rd Age
+ { kStackOspit, 0x470a, kStackJspit, 0x1508e }, // Return from 233rd Age
+ { kStackOspit, 0x5c52, kStackGspit, 0x10bea }, // Return from 233rd Age
+ { kStackOspit, 0x5d68, kStackBspit, 0x1adfd }, // Return from 233rd Age
+ { kStackOspit, 0x5e49, kStackTspit, 0xe87 }, // Return from 233rd Age
+ { kStackPspit, 0x4108, kStackOspit, 0x2e76 }, // Dome Linking Book
+ { kStackRspit, 0x32d8, kStackJspit, 0x1c474 }, // Return from Tay
+ { kStackTspit, 0x21b69, kStackOspit, 0x2e76 } // Dome Linking Book
};
void MohawkEngine_Riven::changeToCard(uint16 dest) {
@@ -556,16 +558,16 @@ void MohawkEngine_Riven::checkInventoryClick() {
// In the demo, check if we've clicked the exit button
if (getFeatures() & GF_DEMO) {
if (g_demoExitRect->contains(mousePos)) {
- if (_curStack == aspit && _curCard == 1) {
+ if (_curStack == kStackAspit && _curCard == 1) {
// From the main menu, go to the "quit" screen
changeToCard(12);
- } else if (_curStack == aspit && _curCard == 12) {
+ } else if (_curStack == kStackAspit && _curCard == 12) {
// From the "quit" screen, just quit
_gameOver = true;
} else {
// Otherwise, return to the main menu
- if (_curStack != aspit)
- changeToStack(aspit);
+ if (_curStack != kStackAspit)
+ changeToStack(kStackAspit);
changeToCard(1);
}
}
@@ -573,7 +575,7 @@ void MohawkEngine_Riven::checkInventoryClick() {
}
// No inventory shown on aspit
- if (_curStack == aspit)
+ if (_curStack == kStackAspit)
return;
// Set the return stack/card id's.
@@ -589,31 +591,31 @@ void MohawkEngine_Riven::checkInventoryClick() {
if (!hasCathBook) {
if (g_atrusJournalRect1->contains(mousePos)) {
_gfx->hideInventory();
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(5);
}
} else if (!hasTrapBook) {
if (g_atrusJournalRect2->contains(mousePos)) {
_gfx->hideInventory();
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(5);
} else if (g_cathJournalRect2->contains(mousePos)) {
_gfx->hideInventory();
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(6);
}
} else {
if (g_atrusJournalRect3->contains(mousePos)) {
_gfx->hideInventory();
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(5);
} else if (g_cathJournalRect3->contains(mousePos)) {
_gfx->hideInventory();
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(6);
} else if (g_trapBookRect3->contains(mousePos)) {
_gfx->hideInventory();
- changeToStack(aspit);
+ changeToStack(kStackAspit);
changeToCard(7);
}
}
@@ -735,16 +737,20 @@ Common::Error MohawkEngine_Riven::saveGameState(int slot, const Common::String &
Common::String MohawkEngine_Riven::getStackName(uint16 stack) const {
static const char *rivenStackNames[] = {
- "aspit",
- "bspit",
- "gspit",
- "jspit",
+ "<unknown>",
"ospit",
"pspit",
"rspit",
- "tspit"
+ "tspit",
+ "bspit",
+ "gspit",
+ "jspit",
+ "aspit"
};
+ // Sanity check.
+ assert(stack < ARRAYSIZE(rivenStackNames));
+
return rivenStackNames[stack];
}
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index c22b9f7f87..9c23d07c52 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -44,18 +44,20 @@ class RivenConsole;
class RivenSaveLoad;
class RivenOptionsDialog;
-#define RIVEN_STACKS 8
-
// Riven Stack Types
enum {
- aspit = 0, // Main Menu, Books, Setup
- bspit = 1, // Book-Making Island
- gspit = 2, // Garden Island
- jspit = 3, // Jungle Island
- ospit = 4, // 233rd Age (Gehn's Office)
- pspit = 5, // Prison Island
- rspit = 6, // Rebel Age (Tay)
- tspit = 7 // Temple Island
+ kStackUnknown = 0, // Default value for ReturnStackID
+ kStackOspit = 1, // 233rd Age (Gehn's Office)
+ kStackPspit = 2, // Prison Island
+ kStackRspit = 3, // Temple Island
+ kStackTspit = 4, // Rebel Age (Tay)
+ kStackBspit = 5, // Book-Making Island
+ kStackGspit = 6, // Garden Island
+ kStackJspit = 7, // Jungle Island
+ kStackAspit = 8, // Main Menu, Books, Setup
+
+ kStackFirst = kStackOspit,
+ kStackLast = kStackAspit
};
// NAME Resource ID's
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 10dcfd9fa7..3d0bccc47f 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -405,7 +405,7 @@ void RivenExternal::drawDomeSliders(uint16 startHotspot) {
// On pspit, the rect is different by two pixels
// (alternatively, we could just use hotspot 3 here, but only on pspit is there a hotspot for this)
- if (_vm->getCurStack() == pspit)
+ if (_vm->getCurStack() == kStackPspit)
dstAreaRect.translate(-2, 0);
// Find out bitmap id
@@ -2016,8 +2016,8 @@ void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) {
// WORKAROUND: The special change stuff only handles one destination and it would
// be messy to modify the way that currently works. If we use the trap book on Tay,
// we should be using the Tay end game sequences.
- if (_vm->_vars["returnstackid"] == rspit) {
- _vm->changeToStack(rspit);
+ if (_vm->_vars["returnstackid"] == kStackRspit) {
+ _vm->changeToStack(kStackRspit);
_vm->changeToCard(2);
return;
}
diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp
index 615b2fdadb..b44fbb828e 100644
--- a/engines/mohawk/riven_graphics.cpp
+++ b/engines/mohawk/riven_graphics.cpp
@@ -289,7 +289,7 @@ void RivenGraphics::showInventory() {
drawInventoryImage(101, g_demoExitRect);
} else {
// We don't want to show the inventory on setup screens or in other journals.
- if (_vm->getCurStack() == aspit)
+ if (_vm->getCurStack() == kStackAspit)
return;
// There are three books and three vars. We have three different
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index d97d0e174b..6af66f7a2d 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -38,56 +38,6 @@ Common::StringArray RivenSaveLoad::generateSaveGameList() {
return _saveFileMan->listSavefiles("*.rvn");
}
-// Note: The stack numbers we use do not match up to what the original executable,
-// so, match them ;)
-static uint16 mapOldStackIDToNew(uint16 oldID) {
- switch (oldID) {
- case 1:
- return ospit;
- case 2:
- return pspit;
- case 3:
- return rspit;
- case 4:
- return tspit;
- case 5:
- return bspit;
- case 6:
- return gspit;
- case 7:
- return jspit;
- case 8:
- return aspit;
- }
-
- error("Unknown old stack ID %d", oldID);
- return 0;
-}
-
-static uint16 mapNewStackIDToOld(uint16 newID) {
- switch (newID) {
- case aspit:
- return 8;
- case bspit:
- return 5;
- case gspit:
- return 6;
- case jspit:
- return 7;
- case ospit:
- return 1;
- case pspit:
- return 2;
- case rspit:
- return 3;
- case tspit:
- return 4;
- }
-
- error("Unknown new stack ID %d", newID);
- return 0;
-}
-
Common::Error RivenSaveLoad::loadGame(Common::String filename) {
if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo
return Common::kNoError;
@@ -141,9 +91,6 @@ Common::Error RivenSaveLoad::loadGame(Common::String filename) {
names->readUint16BE(); // Skip unknown values
uint32 curNamesPos = names->pos();
- uint16 stackID = 0;
- uint16 cardID = 0;
-
for (uint32 i = 0; i < namesCount && !names->eos(); i++) {
names->seek(curNamesPos);
names->seek(stringOffsets[i], SEEK_CUR);
@@ -165,25 +112,18 @@ Common::Error RivenSaveLoad::loadGame(Common::String filename) {
uint32 &var = _vm->_vars[name];
name.toLowercase();
- // Handle any special variables here
// WORKAROUND: time variables are reset here for one main reason:
// The save does not store any start point for the time, so we don't know the real time.
// Because of this, in many cases, the original would just give a 'free' Ytram upon saving
// since the time would be used in a new (improper) time frame.
- if (name.equalsIgnoreCase("CurrentStackID")) // Remap to our definitions, store for later
- stackID = mapOldStackIDToNew(rawVariables[i]);
- else if (name.equalsIgnoreCase("CurrentCardID")) // Store for later
- cardID = rawVariables[i];
- else if (name.equalsIgnoreCase("ReturnStackID") && var != 0) // if 0, the game did not use the variable yet
- var = mapOldStackIDToNew(rawVariables[i]);
- else if (name.contains("time")) // WORKAROUND: See above
+ if (name.contains("time"))
var = 0;
- else // Otherwise, just store it
+ else
var = rawVariables[i];
}
- _vm->changeToStack(stackID);
- _vm->changeToCard(cardID);
+ _vm->changeToStack(_vm->_vars["CurrentStackID"]);
+ _vm->changeToCard(_vm->_vars["CurrentCardID"]);
delete names;
delete[] stringOffsets;
@@ -224,14 +164,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() {
for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) {
stream->writeUint32BE(0); // Unknown
stream->writeUint32BE(0); // Unknown
-
- // Remap returnstackid here because we don't actually want to change
- // our internal returnstackid.
- uint32 variable = it->_value;
- if (it->_key == "returnstackid")
- variable = mapNewStackIDToOld(variable);
-
- stream->writeUint32BE(variable);
+ stream->writeUint32BE(it->_value);
}
return stream;
@@ -290,7 +223,7 @@ Common::Error RivenSaveLoad::saveGame(Common::String filename) {
filename += ".rvn";
// Convert class variables to variable numbers
- _vm->_vars["currentstackid"] = mapNewStackIDToOld(_vm->getCurStack());
+ _vm->_vars["currentstackid"] = _vm->getCurStack();
_vm->_vars["currentcardid"] = _vm->getCurCard();
Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 06b6afdf30..29ee5cd50b 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -403,7 +403,7 @@ void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) {
// would cause all ambient sounds not to play. An alternative
// fix would be to stop all scripts on a stack change, but this
// does fine for now.
- if (_vm->getCurStack() == tspit && (_vm->getCurCardRMAP() == 0x6e9a || _vm->getCurCardRMAP() == 0xfeeb))
+ if (_vm->getCurStack() == kStackTspit && (_vm->getCurCardRMAP() == 0x6e9a || _vm->getCurCardRMAP() == 0xfeeb))
return;
// The argument is a bitflag for the setting.
@@ -586,7 +586,7 @@ void RivenScript::activatePLST(uint16 op, uint16 argc, uint16 *argv) {
void RivenScript::activateSLST(uint16 op, uint16 argc, uint16 *argv) {
// WORKAROUND: Disable the SLST that is played during Riven's intro.
// Riven X does this too (spoke this over with Jeff)
- if (_vm->getCurStack() == tspit && _vm->getCurCardRMAP() == 0x6e9a && argv[0] == 2)
+ if (_vm->getCurStack() == kStackTspit && _vm->getCurCardRMAP() == 0x6e9a && argv[0] == 2)
return;
_vm->_sound->playSLST(argv[0], _vm->getCurCard());
diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp
index 1cd748d8d6..f09aba7f90 100644
--- a/engines/mohawk/riven_vars.cpp
+++ b/engines/mohawk/riven_vars.cpp
@@ -31,240 +31,240 @@ namespace Mohawk {
static const char *variableNames[] = {
// aspit
- "aatrusbook",
- "aatruspage",
- "acathbook",
- "acathpage",
- "acathstate",
- "adoit",
- "adomecombo",
- "agehn",
- "ainventory",
- "aova",
- "apower",
- "araw",
- "atemp",
- "atrap",
- "atrapbook",
- "auservolume",
- "azip",
+ "aAtrusBook",
+ "aAtrusPage",
+ "aCathBook",
+ "aCathPage",
+ "aCathState",
+ "aDoIt",
+ "aDomeCombo",
+ "aGehn",
+ "aInventory",
+ "aOva",
+ "aPower",
+ "aRaw",
+ "aTemp",
+ "aTrap",
+ "aTrapBook",
+ "aUserVolume",
+ "aZip",
// bspit
- "bbacklock",
- "bbait",
- "bbigbridge",
- "bbirds",
- "bblrarm",
- "bblrdoor",
- "bblrgrt",
- "bblrsw",
- "bblrvalve",
- "bblrwtr",
- "bbook",
- "bbrlever",
- "bcavedoor",
+ "bBackLock",
+ "bBait",
+ "bBigBridge",
+ "bBirds",
+ "bBlrArm",
+ "bBlrDoor",
+ "bBlrGrt",
+ "bBlrSw",
+ "bBlrValve",
+ "bBlrWtr",
+ "bBook",
+ "bBrLever",
+ "bCaveDoor",
"bcombo",
- "bcpipegr",
- "bcratergg",
- "bdome",
- "bdrwr",
- "bfans",
- "bfmdoor",
- "bidvlv",
- "blab",
- "blabbackdr",
- "blabbook",
- "blabeye",
- "blabfrontdr",
- "blabpage",
- "blever",
- "bfrontlock",
- "bheat",
- "bmagcar",
- "bpipdr",
- "bprs",
- "bstove",
- "btrap",
- "bvalve",
- "bvise",
- "bytram",
- "bytramtime",
- "bytrap",
- "bytrapped",
+ "bCPipeGr",
+ "bCraterGg",
+ "bDome",
+ "bDrwr",
+ "bFans",
+ "bFMDoor",
+ "bIdVlv",
+ "bLab",
+ "bLabBackDr",
+ "bLabBook",
+ "bLabEye",
+ "bLabFrontDr",
+ "bLabPage",
+ "bLever",
+ "bFrontLock",
+ "bHeat",
+ "bMagCar",
+ "bPipDr",
+ "bPrs",
+ "bStove",
+ "bTrap",
+ "bValve",
+ "bVise",
+ "bYtram",
+ "bYtramTime",
+ "bYtrap",
+ "bYtrapped",
// gspit
- "gbook",
- "gcathtime",
- "gcathstate",
- "gcombo",
- "gdome",
- "gemagcar",
- "gimagecurr",
+ "gBook",
+ "gCathTime",
+ "gCathState",
+ "gCombo",
+ "gDome",
+ "gEmagCar",
+ "gImageCurr",
"gimagemax",
- "gimagerot",
- "glkbtns",
- "glkbridge",
- "glkelev",
- "glview",
- "glviewmpos",
- "glviewpos",
- "gnmagrot",
- "gnmagcar",
- "gpinup",
- "gpinpos",
- "gpinsmpos",
- "grview",
- "grviewmpos",
- "grviewpos",
- "gscribe",
- "gscribetime",
- "gsubelev",
- "gsubdr",
- "gupmoov",
- "gwhark",
- "gwharktime",
+ "gImageRot",
+ "gLkBtns",
+ "gLkBridge",
+ "gLkElev",
+ "gLView",
+ "gLViewMPos",
+ "gLViewPos",
+ "gNmagRot",
+ "gNmagCar",
+ "gPinUp",
+ "gPinPos",
+ "gPinsMPos",
+ "gRView",
+ "gRViewMPos",
+ "gRViewPos",
+ "gScribe",
+ "gScribeTime",
+ "gSubElev",
+ "gSubDr",
+ "gUpMoov",
+ "gWhark",
+ "gWharkTime",
// jspit
- "jwmagcar",
- "jbeetle",
- "jbeetlepool",
- "jbook",
- "jbridge1",
- "jbridge2",
- "jbridge3",
- "jbridge4",
- "jbridge5",
- "jccb",
- "jcombo",
- "jcrg",
- "jdome",
- "jdrain",
- "jgallows",
- "jgate",
- "jgirl",
- "jiconcorrectorder",
- "jiconorder",
- "jicons",
- "jladder",
- "jleftpos",
- "jpeek",
- "jplaybeetle",
- "jprebel",
- "jprisondr",
- "jprisonsecdr",
- "jrbook",
- "jrightpos",
- "jsouthpathdr",
- "jschooldr",
- "jsub",
- "jsubdir",
- "jsubhatch",
- "jsubsw",
- "jsunners",
- "jsunnertime",
- "jthronedr",
- "jtunneldr",
- "jtunnellamps",
- "jvillagepeople",
- "jwarning",
- "jwharkpos",
- "jwharkram",
- "jwmouth",
- "jwmagcar",
- "jymagcar",
+ "jWMagCar",
+ "jBeetle",
+ "jBeetlePool",
+ "jBook",
+ "jBridge1",
+ "jBridge2",
+ "jBridge3",
+ "jBridge4",
+ "jBridge5",
+ "jCCB",
+ "jCombo",
+ "jCrg",
+ "jDome",
+ "jDrain",
+ "jGallows",
+ "jGate",
+ "jGirl",
+ "jIconCorrectOrder",
+ "jIconOrder",
+ "jIcons",
+ "jLadder",
+ "jLeftPos",
+ "jPeek",
+ "jPlayBeetle",
+ "jPRebel",
+ "jPrisonDr",
+ "jPrisonSecDr",
+ "jrBook",
+ "jRightPos",
+ "jSouthPathDr",
+ "jSchoolDr",
+ "jSub",
+ "jSubDir",
+ "jSubHatch",
+ "jSubSw",
+ "jSunners",
+ "jSunnerTime",
+ "jThroneDr",
+ "jTunnelDr",
+ "jTunnelLamps",
+ "jVillagePeople",
+ "jWarning",
+ "jWharkPos",
+ "jWharkRam",
+ "jWMouth",
+ "jWMagCar",
+ "jYMagCar",
// ospit
"oambient",
- "obutton",
+ "oButton",
"ocage",
- "odeskbook",
- "ogehnpage",
- "omusicplayer",
- "ostanddrawer",
- "ostove",
+ "oDeskBook",
+ "oGehnPage",
+ "oMusicPlayer",
+ "oStandDrawer",
+ "oStove",
// pspit
- "pbook",
- "pcage",
- "pcathcheck",
- "pcathstate",
- "pcathtime",
- "pcombo",
- "pcorrectorder",
+ "pBook",
+ "pCage",
+ "pCathCheck",
+ "pCathState",
+ "pCathTime",
+ "pCombo",
+ "pCorrectOrder",
"pdome",
- "pelevcombo",
- "pleftpos",
- "prightpos",
- "ptemp",
- "pwharkpos",
+ "pElevCombo",
+ "pLeftPos",
+ "pRightPos",
+ "pTemp",
+ "pWharkPos",
// rspit
- "rrebel",
- "rrebelview",
- "rrichard",
- "rvillagetime",
+ "rRebel",
+ "rRebelView",
+ "rRichard",
+ "rVillageTime",
// tspit
- "tbars",
- "tbeetle",
- "tblue",
- "tbook",
- "tbookvalve",
- "tcage",
- "tcombo",
- "tcorrectorder",
- "tcovercombo",
- "tdl",
- "tdome",
- "tdomeelev",
- "tdomeelevbtn",
- "tgatebrhandle",
- "tgatebridge",
- "tgatestate",
- "tgreen",
- "tgridoor",
- "tgrodoor",
- "tgrmdoor",
- "tguard",
- "timagedoor",
- "tmagcar",
- "torange",
- "tred",
- "tsecdoor",
- "tsubbridge",
- "ttelecover",
- "ttelehandle",
- "ttelepin",
- "ttelescope",
- "ttelevalve",
- "ttemple",
- "ttempledoor",
- "ttunneldoor",
- "tviewer",
- "tviolet",
- "twabrvalve",
- "twaffle",
- "tyellow",
+ "tBars",
+ "tBeetle",
+ "tBlue",
+ "tBook",
+ "tBookValve",
+ "tCage",
+ "tCombo",
+ "tCorrectOrder",
+ "tCoverCombo",
+ "tDL",
+ "tDome",
+ "tDomeElev",
+ "tDomeElevBtn",
+ "tGateBrHandle",
+ "tGateBridge",
+ "tGateState",
+ "tGreen",
+ "tGRIDoor",
+ "tGRODoor",
+ "tGRMDoor",
+ "tGuard",
+ "tImageDoor",
+ "tMagCar",
+ "tOrange",
+ "tRed",
+ "tSecDoor",
+ "tSubBridge",
+ "tTeleCover",
+ "tTeleHandle",
+ "tTelePin",
+ "tTelescope",
+ "tTeleValve",
+ "tTemple",
+ "tTempleDoor",
+ "tTunnelDoor",
+ "tViewer",
+ "tViolet",
+ "tWaBrValve",
+ "tWaffle",
+ "tYellow",
// Miscellaneous
"elevbtn1",
"elevbtn2",
"elevbtn3",
- "domecheck",
- "transitionsenabled",
- "transitionmode",
- "waterenabled",
- "rivenambients",
- "stackvarsinitialized",
- "doingsetupscreens",
+ "domeCheck",
+ "transitionsEnabled",
+ "transitionMode",
+ "waterEnabled",
+ "RivenAmbients",
+ "stackVarsInitialized",
+ "DoingSetupScreens",
"all_book",
- "playerhasbook",
- "returnstackid",
- "returncardid",
- "newpos",
- "themarble",
- "currentstackid",
- "currentcardid"
+ "playerHasBook",
+ "returnStackID",
+ "returnCardID",
+ "NewPos",
+ "theMarble",
+ "CurrentStackID",
+ "CurrentCardID"
};
uint32 &MohawkEngine_Riven::getStackVar(uint32 index) {
diff --git a/engines/mortevielle/debugger.cpp b/engines/mortevielle/debugger.cpp
index c8f75918ab..b2c99b894a 100644
--- a/engines/mortevielle/debugger.cpp
+++ b/engines/mortevielle/debugger.cpp
@@ -27,9 +27,9 @@ namespace Mortevielle {
Debugger::Debugger(MortevielleEngine *vm) : GUI::Debugger() {
_vm = vm;
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("show_questions", WRAP_METHOD(Debugger, Cmd_showAllQuestions));
- DCmd_Register("reset_parano", WRAP_METHOD(Debugger, Cmd_resetParano));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("show_questions", WRAP_METHOD(Debugger, Cmd_showAllQuestions));
+ registerCmd("reset_parano", WRAP_METHOD(Debugger, Cmd_resetParano));
}
bool Debugger::Cmd_showAllQuestions(int argc, const char **argv) {
diff --git a/engines/mortevielle/detection_tables.h b/engines/mortevielle/detection_tables.h
index 3e1e5aaefe..0aa27b89eb 100644
--- a/engines/mortevielle/detection_tables.h
+++ b/engines/mortevielle/detection_tables.h
@@ -57,21 +57,21 @@ static const MortevielleGameDescription MortevielleGameDescriptions[] = {
},
// German, improved translation
- {
- {
- "mortevielle",
- "Improved Translation",
- {
- {"menual.mor", 0, "792aea282b07a1d74c4a4abeabc90c19", 144},
- {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
- AD_LISTEND
- },
- Common::DE_DEU,
- Common::kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO0()
- }, Common::DE_DEU, kUseEngineDataFile
- },
+// {
+// {
+// "mortevielle",
+// "Improved Translation",
+// {
+// {"menual.mor", 0, "792aea282b07a1d74c4a4abeabc90c19", 144},
+// {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+// AD_LISTEND
+// },
+// Common::DE_DEU,
+// Common::kPlatformDOS,
+// ADGF_NO_FLAGS,
+// GUIO0()
+// }, Common::DE_DEU, kUseEngineDataFile
+// },
// DOS English version doesn't exist. Technically, they are French or German versions,
// using English strings stored mort.dat
diff --git a/engines/neverhood/console.cpp b/engines/neverhood/console.cpp
index a4d1366880..91ab3e767a 100644
--- a/engines/neverhood/console.cpp
+++ b/engines/neverhood/console.cpp
@@ -34,13 +34,13 @@
namespace Neverhood {
Console::Console(NeverhoodEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("cheat", WRAP_METHOD(Console, Cmd_Cheat));
- DCmd_Register("checkresource", WRAP_METHOD(Console, Cmd_CheckResource));
- DCmd_Register("dumpresource", WRAP_METHOD(Console, Cmd_DumpResource));
- DCmd_Register("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars));
- DCmd_Register("playsound", WRAP_METHOD(Console, Cmd_PlaySound));
- DCmd_Register("scene", WRAP_METHOD(Console, Cmd_Scene));
- DCmd_Register("surfaces", WRAP_METHOD(Console, Cmd_Surfaces));
+ registerCmd("cheat", WRAP_METHOD(Console, Cmd_Cheat));
+ registerCmd("checkresource", WRAP_METHOD(Console, Cmd_CheckResource));
+ registerCmd("dumpresource", WRAP_METHOD(Console, Cmd_DumpResource));
+ registerCmd("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars));
+ registerCmd("playsound", WRAP_METHOD(Console, Cmd_PlaySound));
+ registerCmd("scene", WRAP_METHOD(Console, Cmd_Scene));
+ registerCmd("surfaces", WRAP_METHOD(Console, Cmd_Surfaces));
}
Console::~Console() {
@@ -55,33 +55,33 @@ bool Console::Cmd_Scene(int argc, const char **argv) {
const char *sceneTypes[] = { "normal", "smacker", "navigation" };
- DebugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]);
+ debugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]);
if (sceneType == kSceneTypeNormal) {
Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
// Normal scenes have a background and a cursor file hash
- DebugPrintf("Background hash: 0x%x, cursor hash: 0x%x\n", scene->getBackgroundFileHash(), scene->getCursorFileHash());
+ debugPrintf("Background hash: 0x%x, cursor hash: 0x%x\n", scene->getBackgroundFileHash(), scene->getCursorFileHash());
} else if (sceneType == kSceneTypeSmacker) {
SmackerScene *scene = (SmackerScene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
// Smacker scenes have a file hash, or a list of hashes
// TODO: Only the first file hash is shown - any additional hashes, found in
// scenes with a list of hashes (two scenes in module 1100 and the making of
// video) aren't shown yet
- DebugPrintf("File hash: 0x%x\n", scene->getSmackerFileHash());
+ debugPrintf("File hash: 0x%x\n", scene->getSmackerFileHash());
} else if (sceneType == kSceneTypeNavigation) {
NavigationScene *scene = (NavigationScene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
// Navigation scenes have a navigation list and its index
NavigationList *navigationList = _vm->_staticData->getNavigationList(scene->getNavigationListId());
int navigationIndex = scene->getGlobalVar(V_NAVIGATION_INDEX);
NavigationItem curNavigation = (*navigationList)[navigationIndex];
- DebugPrintf("Navigation list ID: 0x%x, index: %d\n", scene->getNavigationListId(), navigationIndex);
- DebugPrintf("File hash: 0x%x, cursor hash: 0x%x, Smacker hashes: [left: 0x%x, middle: 0x%x, right: 0x%x\n",
+ debugPrintf("Navigation list ID: 0x%x, index: %d\n", scene->getNavigationListId(), navigationIndex);
+ debugPrintf("File hash: 0x%x, cursor hash: 0x%x, Smacker hashes: [left: 0x%x, middle: 0x%x, right: 0x%x\n",
curNavigation.fileHash, curNavigation.mouseCursorFileHash,
curNavigation.leftSmackerFileHash, curNavigation.middleSmackerFileHash, curNavigation.rightSmackerFileHash);
}
- DebugPrintf("Use %s <module> <scene> to change scenes\n", argv[0]);
- DebugPrintf("Modules are incremental by 100, from 1000 to 3000\n");
+ debugPrintf("Use %s <module> <scene> to change scenes\n", argv[0]);
+ debugPrintf("Modules are incremental by 100, from 1000 to 3000\n");
} else {
int newModule = atoi(argv[1]);
int newScene = atoi(argv[2]);
@@ -102,17 +102,17 @@ bool Console::Cmd_Surfaces(int argc, const char **argv) {
bool Console::Cmd_Cheat(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Cheats for various puzzles in the game\n");
- DebugPrintf("Use %s <cheatname> to use a cheat.\n", argv[0]);
- DebugPrintf("Cheats:\n-------\n");
- DebugPrintf(" buttons - enables all 3 buttons on the door in the purple building, module 3000, scene 9\n");
- DebugPrintf(" cannon - sets the correct cannon combination in module 3000, scene 8\n");
- DebugPrintf(" dice - shows the correct dice combination in the teddy bear puzzle, module 1100, scene 6\n");
- DebugPrintf(" memory - solves the memory puzzle, module 1400, scene 4\n");
- DebugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n");
- DebugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n");
- DebugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n");
- DebugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n");
+ debugPrintf("Cheats for various puzzles in the game\n");
+ debugPrintf("Use %s <cheatname> to use a cheat.\n", argv[0]);
+ debugPrintf("Cheats:\n-------\n");
+ debugPrintf(" buttons - enables all 3 buttons on the door in the purple building, module 3000, scene 9\n");
+ debugPrintf(" cannon - sets the correct cannon combination in module 3000, scene 8\n");
+ debugPrintf(" dice - shows the correct dice combination in the teddy bear puzzle, module 1100, scene 6\n");
+ debugPrintf(" memory - solves the memory puzzle, module 1400, scene 4\n");
+ debugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n");
+ debugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n");
+ debugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n");
+ debugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n");
return true;
}
@@ -127,7 +127,7 @@ bool Console::Cmd_Cheat(int argc, const char **argv) {
scene->setSubVar(VA_LOCKS_DISABLED, 0x40119852, 1); // kScene3010ButtonNameHashes[1]
scene->setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1); // kScene3010ButtonNameHashes[2]
- DebugPrintf("All 3 door buttons have been enabled\n");
+ debugPrintf("All 3 door buttons have been enabled\n");
} else if (cheatName == "cannon") {
Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
@@ -137,10 +137,10 @@ bool Console::Cmd_Cheat(int argc, const char **argv) {
for (int i = 3; i < 6; i++)
scene->setSubVar(VA_CURR_CANNON_SYMBOLS, i, scene->getSubVar(VA_GOOD_CANNON_SYMBOLS_2, i - 3));
- DebugPrintf("Puzzle solved\n");
+ debugPrintf("Puzzle solved\n");
} else if (cheatName == "dice") {
Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
- DebugPrintf("Good: (%d %d %d), current: (%d %d %d)\n",
+ debugPrintf("Good: (%d %d %d), current: (%d %d %d)\n",
scene->getSubVar(VA_GOOD_DICE_NUMBERS, 0), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 1), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 2),
scene->getSubVar(VA_CURR_DICE_NUMBERS, 0), scene->getSubVar(VA_CURR_DICE_NUMBERS, 1), scene->getSubVar(VA_CURR_DICE_NUMBERS, 2)
);
@@ -162,15 +162,15 @@ bool Console::Cmd_Cheat(int argc, const char **argv) {
}
}
- DebugPrintf("Puzzle solved\n");
+ debugPrintf("Puzzle solved\n");
} else if (cheatName == "music") {
Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
- DebugPrintf("Good music index: %d, current radio music index: %d\n", scene->getGlobalVar(V_CURR_RADIO_MUSIC_INDEX), scene->getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX));
+ debugPrintf("Good music index: %d, current radio music index: %d\n", scene->getGlobalVar(V_CURR_RADIO_MUSIC_INDEX), scene->getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX));
} else if (cheatName == "radio") {
Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
scene->setGlobalVar(V_RADIO_ENABLED, 1);
- DebugPrintf("The radio has been enabled\n");
+ debugPrintf("The radio has been enabled\n");
} else if (cheatName == "symbols") {
if (moduleNum == 1600 && sceneNum == 8) {
Scene1609 *scene = ((Scene1609 *)((Module1600 *)_vm->_gameModule->_childObject)->_childObject);
@@ -183,14 +183,14 @@ bool Console::Cmd_Cheat(int argc, const char **argv) {
scene->_symbolPosition = 11;
scene->_countdown1 = 36;
- DebugPrintf("Puzzle solved\n");
+ debugPrintf("Puzzle solved\n");
} else {
- DebugPrintf("Only available in module 1600, scene 8\n");
+ debugPrintf("Only available in module 1600, scene 8\n");
}
} else if (cheatName == "tubes") {
Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
- DebugPrintf("Tube set 1: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2));
- DebugPrintf("Tube set 2: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2));
+ debugPrintf("Tube set 1: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2));
+ debugPrintf("Tube set 2: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2));
}
return true;
@@ -204,7 +204,7 @@ bool Console::Cmd_Dumpvars(int argc, const char **argv) {
bool Console::Cmd_PlaySound(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: %s <sound hash>\n", argv[0]);
+ debugPrintf("Usage: %s <sound hash>\n", argv[0]);
} else {
uint32 soundHash = strtol(argv[1], NULL, 0);
AudioResourceManSoundItem *soundItem = new AudioResourceManSoundItem(_vm, soundHash);
@@ -223,17 +223,17 @@ bool Console::Cmd_CheckResource(int argc, const char **argv) {
const char *resourceNames[] = { "unknown", "unknown", "bitmap", "palette", "animation", "data", "text", "sound", "music", "unknown", "video" };
if (argc < 2) {
- DebugPrintf("Gets information about a resource\n");
- DebugPrintf("Usage: %s <resource hash>\n", argv[0]);
+ debugPrintf("Gets information about a resource\n");
+ debugPrintf("Usage: %s <resource hash>\n", argv[0]);
} else {
uint32 resourceHash = strtol(argv[1], NULL, 0);
ResourceHandle handle;
_vm->_res->queryResource(resourceHash, handle);
if (!handle.isValid()) {
- DebugPrintf("Invalid resource hash\n");
+ debugPrintf("Invalid resource hash\n");
} else {
- DebugPrintf("Resource type: %d (%s). Size: %d bytes\n", handle.type(), resourceNames[handle.type()], handle.size());
+ debugPrintf("Resource type: %d (%s). Size: %d bytes\n", handle.type(), resourceNames[handle.type()], handle.size());
}
}
@@ -242,8 +242,8 @@ bool Console::Cmd_CheckResource(int argc, const char **argv) {
bool Console::Cmd_DumpResource(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("Dumps a resource to disk\n");
- DebugPrintf("Usage: %s <resource hash> <output file>\n", argv[0]);
+ debugPrintf("Dumps a resource to disk\n");
+ debugPrintf("Usage: %s <resource hash> <output file>\n", argv[0]);
} else {
uint32 resourceHash = strtol(argv[1], NULL, 0);
const char *outFileName = argv[2];
@@ -251,7 +251,7 @@ bool Console::Cmd_DumpResource(int argc, const char **argv) {
_vm->_res->queryResource(resourceHash, handle);
if (!handle.isValid()) {
- DebugPrintf("Invalid resource hash\n");
+ debugPrintf("Invalid resource hash\n");
} else {
_vm->_res->loadResource(handle, _vm->applyResourceFixes());
Common::DumpFile outFile;
diff --git a/engines/neverhood/gamevars.cpp b/engines/neverhood/gamevars.cpp
index 72b688c194..dcbe5583de 100644
--- a/engines/neverhood/gamevars.cpp
+++ b/engines/neverhood/gamevars.cpp
@@ -127,7 +127,7 @@ int16 GameVars::getSubVarIndex(int16 varIndex, uint32 subNameHash) {
void GameVars::dumpVars(Console *con) {
for (Common::Array<GameVar>::iterator it = _vars.begin(); it != _vars.end(); ++it) {
GameVar gameVar = *it;
- con->DebugPrintf("hash: %08X, var: %08X, first index: %3d, next index: %3d\n", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex);
+ con->debugPrintf("hash: %08X, var: %08X, first index: %3d, next index: %3d\n", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex);
}
}
diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp
index 3d1724ed8a..89792d2659 100644
--- a/engines/neverhood/graphics.cpp
+++ b/engines/neverhood/graphics.cpp
@@ -47,6 +47,7 @@ BaseSurface::BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 h
}
BaseSurface::~BaseSurface() {
+ _surface->free();
delete _surface;
}
@@ -113,7 +114,15 @@ void BaseSurface::drawMouseCursorResource(MouseCursorResource &mouseCursorResour
}
void BaseSurface::copyFrom(Graphics::Surface *sourceSurface, int16 x, int16 y, NDrawRect &sourceRect) {
- // Copy a rectangle from sourceSurface, no clipping is performed, 0 is the transparent color
+ // Copy a rectangle from sourceSurface, 0 is the transparent color
+ // Clipping is performed against the right/bottom border since x, y will always be >= 0
+
+ if (x + sourceRect.width > _surface->w)
+ sourceRect.width = _surface->w - x - 1;
+
+ if (y + sourceRect.height > _surface->h)
+ sourceRect.height = _surface->h - y - 1;
+
byte *source = (byte*)sourceSurface->getBasePtr(sourceRect.x, sourceRect.y);
byte *dest = (byte*)_surface->getBasePtr(x, y);
int height = sourceRect.height;
diff --git a/engines/neverhood/modules/module1000.cpp b/engines/neverhood/modules/module1000.cpp
index b19ba05b32..5e4d67d2bc 100644
--- a/engines/neverhood/modules/module1000.cpp
+++ b/engines/neverhood/modules/module1000.cpp
@@ -693,22 +693,18 @@ uint32 Scene1005::getTextIndex1() {
uint32 Scene1005::getKloggsTextIndex() {
uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX1);
if (textIndex + 1 > 10) {
- setGlobalVar(V_TEXT_COUNTING_INDEX1, 0);
textIndex = 0;
- } else {
- setGlobalVar(V_TEXT_COUNTING_INDEX1, textIndex + 1);
}
+ setGlobalVar(V_TEXT_COUNTING_INDEX1, textIndex + 1);
return textIndex + 40;
}
uint32 Scene1005::getTextIndex3() {
uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX2);
- if (textIndex + 1 >= 10) {
- setGlobalVar(V_TEXT_COUNTING_INDEX2, 0);
+ if (textIndex + 1 > 10) {
textIndex = 0;
- } else {
- setGlobalVar(V_TEXT_COUNTING_INDEX2, textIndex + 1);
}
+ setGlobalVar(V_TEXT_COUNTING_INDEX2, textIndex + 1);
return textIndex + 30;
}
diff --git a/engines/neverhood/modules/module1400.cpp b/engines/neverhood/modules/module1400.cpp
index 551b6874ff..465ad5909a 100644
--- a/engines/neverhood/modules/module1400.cpp
+++ b/engines/neverhood/modules/module1400.cpp
@@ -709,13 +709,14 @@ Scene1405::Scene1405(NeverhoodEngine *vm, Module *parentModule)
void Scene1405::update() {
Scene::update();
+ // Check if the player chose a wrong tile, in which case the whole grid gets reset
if (_countdown != 0 && (--_countdown == 0)) {
_tilesLeft = 48;
- _tiles[_firstTileIndex]->hide();
- _tiles[_secondTileIndex]->hide();
+ _tiles[_firstTileIndex]->hide(true);
+ _tiles[_secondTileIndex]->hide(false);
for (uint32 i = 0; i < 48; i++) {
if (getSubVar(VA_IS_TILE_MATCH, i)) {
- _tiles[i]->hide();
+ _tiles[i]->hide(false);
setSubVar(VA_IS_TILE_MATCH, i, 0);
}
}
diff --git a/engines/neverhood/modules/module1400_sprites.cpp b/engines/neverhood/modules/module1400_sprites.cpp
index 30a5c340c9..99a2a314a7 100644
--- a/engines/neverhood/modules/module1400_sprites.cpp
+++ b/engines/neverhood/modules/module1400_sprites.cpp
@@ -873,10 +873,11 @@ void AsScene1405Tile::show() {
}
}
-void AsScene1405Tile::hide() {
+void AsScene1405Tile::hide(bool playClickSound) {
if (_isShowing) {
_isShowing = false;
- playSound(0);
+ if (playClickSound)
+ playSound(0);
setVisible(false);
}
}
diff --git a/engines/neverhood/modules/module1400_sprites.h b/engines/neverhood/modules/module1400_sprites.h
index fe0db66d27..e709193aab 100644
--- a/engines/neverhood/modules/module1400_sprites.h
+++ b/engines/neverhood/modules/module1400_sprites.h
@@ -155,7 +155,7 @@ class AsScene1405Tile : public AnimatedSprite {
public:
AsScene1405Tile(NeverhoodEngine *vm, Scene1405 *parentScene, uint32 tileIndex);
void show();
- void hide();
+ void hide(bool playClickSound);
protected:
Scene1405 *_parentScene;
bool _isShowing;
diff --git a/engines/neverhood/modules/module1600_sprites.cpp b/engines/neverhood/modules/module1600_sprites.cpp
index 09e3d0afe1..6a4de86517 100644
--- a/engines/neverhood/modules/module1600_sprites.cpp
+++ b/engines/neverhood/modules/module1600_sprites.cpp
@@ -30,6 +30,8 @@ AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
createSurface(200, 556, 328);
_x = x;
_y = y;
+ _destX = x;
+ _destY = y;
_inMainArea = false;
_exitDirection = 0;
@@ -48,6 +50,7 @@ AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
_soundCounter = 0;
_pathPoints = NULL;
_currMoveDirection = 0;
+ _newMoveDirection = 0;
startAnimation(0xD4220027, 0, -1);
setDoDeltaX(getGlobalVar(V_CAR_DELTA_X));
diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp
index 2a112435fc..a510c02558 100644
--- a/engines/neverhood/modules/module2700.cpp
+++ b/engines/neverhood/modules/module2700.cpp
@@ -461,6 +461,7 @@ void Module2700::updateScene() {
_vm->_soundMan->deleteMusic(_musicFileHash);
_vm->_soundMan->startMusic(0x04020210, 0, 2);
_vm->_soundMan->deleteSoundGroup(0x42212411);
+ _radioMusicInitialized = false;
createScene(20, 3);
break;
case 22:
diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp
index 58056b65a9..1a8e74da38 100644
--- a/engines/neverhood/scene.cpp
+++ b/engines/neverhood/scene.cpp
@@ -148,7 +148,7 @@ void Scene::printSurfaces(Console *con) {
NDrawRect drawRect = _surfaces[index]->getDrawRect();
NRect clipRect = _surfaces[index]->getClipRect();
int priority = _surfaces[index]->getPriority();
- con->DebugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n",
+ con->debugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n",
index, _surfaces[index]->getName().c_str(), priority,
drawRect.x, drawRect.y, drawRect.x2(), drawRect.y2(),
clipRect.x1, clipRect.y1, clipRect.x2, clipRect.y2);
diff --git a/engines/neverhood/sprite.cpp b/engines/neverhood/sprite.cpp
index a566b8ee3b..3611ce1ba2 100644
--- a/engines/neverhood/sprite.cpp
+++ b/engines/neverhood/sprite.cpp
@@ -31,8 +31,20 @@ Sprite::Sprite(NeverhoodEngine *vm, int objectPriority)
: Entity(vm, objectPriority), _x(0), _y(0), _spriteUpdateCb(NULL), _filterXCb(NULL), _filterYCb(NULL),
_dataResource(vm), _doDeltaX(false), _doDeltaY(false), _needRefresh(false), _flags(0), _surface(NULL) {
- SetMessageHandler(&Sprite::handleMessage);
+ _drawOffset.x = 0;
+ _drawOffset.y = 0;
+ _drawOffset.width = 0;
+ _drawOffset.height = 0;
+ _collisionBounds.x1 = 0;
+ _collisionBounds.y1 = 0;
+ _collisionBounds.x2 = 0;
+ _collisionBounds.y2 = 0;
+ _collisionBoundsOffset.x = 0;
+ _collisionBoundsOffset.y = 0;
+ _collisionBoundsOffset.width = 0;
+ _collisionBoundsOffset.height = 0;
+ SetMessageHandler(&Sprite::handleMessage);
}
Sprite::~Sprite() {
diff --git a/engines/neverhood/staticdata.cpp b/engines/neverhood/staticdata.cpp
index 552ea92604..03af44b2a5 100644
--- a/engines/neverhood/staticdata.cpp
+++ b/engines/neverhood/staticdata.cpp
@@ -28,6 +28,18 @@ StaticData::StaticData() {
}
StaticData::~StaticData() {
+ for (Common::HashMap<uint32, HitRectList*>::iterator i = _hitRectLists.begin(); i != _hitRectLists.end(); ++i)
+ delete i->_value;
+ for (Common::HashMap<uint32, RectList*>::iterator i = _rectLists.begin(); i != _rectLists.end(); ++i)
+ delete i->_value;
+ for (Common::HashMap<uint32, MessageList*>::iterator i = _messageLists.begin(); i != _messageLists.end(); ++i)
+ delete i->_value;
+ for (Common::HashMap<uint32, NavigationList*>::iterator i = _navigationLists.begin(); i != _navigationLists.end(); ++i)
+ delete i->_value;
+ for (Common::HashMap<uint32, HallOfRecordsInfo*>::iterator i = _hallOfRecordsInfoItems.begin(); i != _hallOfRecordsInfoItems.end(); ++i)
+ delete i->_value;
+ for (Common::HashMap<uint32, TrackInfo*>::iterator i = _trackInfoItems.begin(); i != _trackInfoItems.end(); ++i)
+ delete i->_value;
}
void StaticData::load(const char *filename) {
@@ -69,6 +81,11 @@ void StaticData::load(const char *filename) {
messageList->push_back(messageItem);
}
+ if(_messageLists.contains(id)) {
+ warning("Duplicate id %d in _messageLists - freeing older entry", id);
+ delete _messageLists[id];
+ }
+
_messageLists[id] = messageList;
}
@@ -98,6 +115,12 @@ void StaticData::load(const char *filename) {
}
rectList->push_back(rectItem);
}
+
+ if(_rectLists.contains(id)) {
+ warning("Duplicate id %d in _rectLists - freeing older entry", id);
+ delete _rectLists[id];
+ }
+
_rectLists[id] = rectList;
}
@@ -117,6 +140,12 @@ void StaticData::load(const char *filename) {
hitRect.type = fd.readUint16LE();
hitRectList->push_back(hitRect);
}
+
+ if(_hitRectLists.contains(id)) {
+ warning("Duplicate id %d in _hitRectLists - freeing older entry", id);
+ delete _hitRectLists[id];
+ }
+
_hitRectLists[id] = hitRectList;
}
@@ -138,6 +167,12 @@ void StaticData::load(const char *filename) {
navigationItem.mouseCursorFileHash = fd.readUint32LE();
navigationList->push_back(navigationItem);
}
+
+ if(_navigationLists.contains(id)) {
+ warning("Duplicate id %d in _navigationLists - freeing older entry", id);
+ delete _navigationLists[id];
+ }
+
_navigationLists[id] = navigationList;
}
@@ -153,6 +188,12 @@ void StaticData::load(const char *filename) {
hallOfRecordsInfo->bgFilename3 = fd.readUint32LE();
hallOfRecordsInfo->xPosIndex = fd.readByte();
hallOfRecordsInfo->count = fd.readByte();
+
+ if(_hallOfRecordsInfoItems.contains(id)) {
+ warning("Duplicate id %d in _hallOfRecordsInfoItems - freeing older entry", id);
+ delete _hallOfRecordsInfoItems[id];
+ }
+
_hallOfRecordsInfoItems[id] = hallOfRecordsInfo;
}
@@ -172,6 +213,12 @@ void StaticData::load(const char *filename) {
trackInfo->mouseCursorFilename = fd.readUint32LE();
trackInfo->which1 = fd.readUint16LE();
trackInfo->which2 = fd.readUint16LE();
+
+ if(_trackInfoItems.contains(id)) {
+ warning("Duplicate id %d in _trackInfoItems - freeing older entry", id);
+ delete _trackInfoItems[id];
+ }
+
_trackInfoItems[id] = trackInfo;
}
diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp
index 1fea73a326..a7087c64d7 100644
--- a/engines/parallaction/debug.cpp
+++ b/engines/parallaction/debug.cpp
@@ -33,18 +33,18 @@ Debugger::Debugger(Parallaction *vm)
: GUI::Debugger() {
_vm = vm;
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("location", WRAP_METHOD(Debugger, Cmd_Location));
- DCmd_Register("give", WRAP_METHOD(Debugger, Cmd_Give));
- DCmd_Register("zones", WRAP_METHOD(Debugger, Cmd_Zones));
- DCmd_Register("animations", WRAP_METHOD(Debugger, Cmd_Animations));
- DCmd_Register("globalflags",WRAP_METHOD(Debugger, Cmd_GlobalFlags));
- DCmd_Register("toggleglobalflag",WRAP_METHOD(Debugger, Cmd_ToggleGlobalFlag));
- DCmd_Register("localflags", WRAP_METHOD(Debugger, Cmd_LocalFlags));
- DCmd_Register("locations", WRAP_METHOD(Debugger, Cmd_Locations));
- DCmd_Register("gfxobjects", WRAP_METHOD(Debugger, Cmd_GfxObjects));
- DCmd_Register("programs", WRAP_METHOD(Debugger, Cmd_Programs));
- DCmd_Register("showmouse", WRAP_METHOD(Debugger, Cmd_ShowMouse));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("location", WRAP_METHOD(Debugger, Cmd_Location));
+ registerCmd("give", WRAP_METHOD(Debugger, Cmd_Give));
+ registerCmd("zones", WRAP_METHOD(Debugger, Cmd_Zones));
+ registerCmd("animations", WRAP_METHOD(Debugger, Cmd_Animations));
+ registerCmd("globalflags",WRAP_METHOD(Debugger, Cmd_GlobalFlags));
+ registerCmd("toggleglobalflag",WRAP_METHOD(Debugger, Cmd_ToggleGlobalFlag));
+ registerCmd("localflags", WRAP_METHOD(Debugger, Cmd_LocalFlags));
+ registerCmd("locations", WRAP_METHOD(Debugger, Cmd_Locations));
+ registerCmd("gfxobjects", WRAP_METHOD(Debugger, Cmd_GfxObjects));
+ registerCmd("programs", WRAP_METHOD(Debugger, Cmd_Programs));
+ registerCmd("showmouse", WRAP_METHOD(Debugger, Cmd_ShowMouse));
}
@@ -81,7 +81,7 @@ bool Debugger::Cmd_Location(int argc, const char **argv) {
break;
case 1:
- DebugPrintf("location <location name> [character name]\n");
+ debugPrintf("location <location name> [character name]\n");
}
@@ -90,13 +90,13 @@ bool Debugger::Cmd_Location(int argc, const char **argv) {
bool Debugger::Cmd_Locations(int argc, const char **argv) {
- DebugPrintf("+------------------------------+---------+\n"
+ debugPrintf("+------------------------------+---------+\n"
"| location name | flags |\n"
"+------------------------------+---------+\n");
for (uint i = 0; i < _vm->_numLocations; i++) {
- DebugPrintf("|%-30s| %08x|\n", _vm->_locationNames[i], _vm->_localFlags[i]);
+ debugPrintf("|%-30s| %08x|\n", _vm->_locationNames[i], _vm->_localFlags[i]);
}
- DebugPrintf("+------------------------------+---------+\n");
+ debugPrintf("+------------------------------+---------+\n");
return true;
}
@@ -105,14 +105,14 @@ bool Debugger::Cmd_GlobalFlags(int argc, const char **argv) {
uint32 flags = g_globalFlags;
- DebugPrintf("+------------------------------+---------+\n"
+ debugPrintf("+------------------------------+---------+\n"
"| flag name | value |\n"
"+------------------------------+---------+\n");
for (uint i = 0; i < _vm->_globalFlagsNames->count(); i++) {
const char *value = ((flags & (1 << i)) == 0) ? "OFF" : "ON";
- DebugPrintf("|%-30s| %-6s|\n", _vm->_globalFlagsNames->item(i), value);
+ debugPrintf("|%-30s| %-6s|\n", _vm->_globalFlagsNames->item(i), value);
}
- DebugPrintf("+------------------------------+---------+\n");
+ debugPrintf("+------------------------------+---------+\n");
return true;
}
@@ -125,7 +125,7 @@ bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) {
case 2:
i = _vm->_globalFlagsNames->lookup(argv[1]);
if (i == Table::notFound) {
- DebugPrintf("invalid flag '%s'\n", argv[1]);
+ debugPrintf("invalid flag '%s'\n", argv[1]);
} else {
i--;
if ((g_globalFlags & (1 << i)) == 0)
@@ -136,7 +136,7 @@ bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) {
break;
default:
- DebugPrintf("toggleglobalflag <flag name>\n");
+ debugPrintf("toggleglobalflag <flag name>\n");
}
@@ -147,14 +147,14 @@ bool Debugger::Cmd_LocalFlags(int argc, const char **argv) {
uint32 flags = _vm->getLocationFlags();
- DebugPrintf("+------------------------------+---------+\n"
+ debugPrintf("+------------------------------+---------+\n"
"| flag name | value |\n"
"+------------------------------+---------+\n");
for (uint i = 0; i < _vm->_localFlagNames->count(); i++) {
const char *value = ((flags & (1 << i)) == 0) ? "OFF" : "ON";
- DebugPrintf("|%-30s| %-6s|\n", _vm->_localFlagNames->item(i), value);
+ debugPrintf("|%-30s| %-6s|\n", _vm->_localFlagNames->item(i), value);
}
- DebugPrintf("+------------------------------+---------+\n");
+ debugPrintf("+------------------------------+---------+\n");
return true;
}
@@ -162,13 +162,13 @@ bool Debugger::Cmd_LocalFlags(int argc, const char **argv) {
bool Debugger::Cmd_Give(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("give <item name>\n");
+ debugPrintf("give <item name>\n");
} else {
int index = _vm->_objectsNames->lookup(argv[1]);
if (index != Table::notFound)
_vm->addInventoryItem(index + 4);
else
- DebugPrintf("invalid item name '%s'\n", argv[1]);
+ debugPrintf("invalid item name '%s'\n", argv[1]);
}
return true;
@@ -181,15 +181,15 @@ bool Debugger::Cmd_Zones(int argc, const char **argv) {
ZoneList::iterator e = _vm->_location._zones.end();
Common::Rect r;
- DebugPrintf("+--------------------+---+---+---+---+--------+--------+\n"
+ debugPrintf("+--------------------+---+---+---+---+--------+--------+\n"
"| name | l | t | r | b | type | flag |\n"
"+--------------------+---+---+---+---+--------+--------+\n");
for ( ; b != e; ++b) {
ZonePtr z = *b;
z->getRect(r);
- DebugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", z->_name, r.left, r.top, r.right, r.bottom, z->_type, z->_flags );
+ debugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", z->_name, r.left, r.top, r.right, r.bottom, z->_type, z->_flags );
}
- DebugPrintf("+--------------------+---+---+---+---+--------+--------+\n");
+ debugPrintf("+--------------------+---+---+---+---+--------+--------+\n");
return true;
@@ -260,15 +260,15 @@ bool Debugger::Cmd_Animations(int argc, const char **argv) {
AnimationList::iterator e = _vm->_location._animations.end();
Common::String flags;
- DebugPrintf("+--------------------+----+----+----+---+--------+----------------------------------------+\n"
+ debugPrintf("+--------------------+----+----+----+---+--------+----------------------------------------+\n"
"| name | x | y | z | f | type | flags | \n"
"+--------------------+----+----+----+---+--------+----------------------------------------+\n");
for ( ; b != e; ++b) {
AnimationPtr a = *b;
flags = decodeZoneFlags(a->_flags);
- DebugPrintf("|%-20s|%4i|%4i|%4i|%3i|%8x|%-40s|\n", a->_name, a->getX(), a->getY(), a->getZ(), a->getF(), a->_type, flags.c_str() );
+ debugPrintf("|%-20s|%4i|%4i|%4i|%3i|%8x|%-40s|\n", a->_name, a->getX(), a->getY(), a->getZ(), a->getF(), a->_type, flags.c_str() );
}
- DebugPrintf("+--------------------+---+---+---+---+--------+----------------------------------------+\n");
+ debugPrintf("+--------------------+---+---+---+---+--------+----------------------------------------+\n");
return true;
@@ -278,7 +278,7 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) {
const char *objType[] = { "DOOR", "GET", "ANIM" };
- DebugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n"
+ debugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n"
"| name | x | y | w | h | z | layer | f | type |\n"
"+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n");
@@ -289,11 +289,11 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) {
for ( ; b != e; ++b) {
GfxObj *obj = *b;
obj->getRect(obj->frame, r);
- DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%5i|%7i|%5i|%8s|\n", obj->getName(), r.left, r.top, r.width(), r.height(),
+ debugPrintf("|%-20s|%5i|%5i|%5i|%5i|%5i|%7i|%5i|%8s|\n", obj->getName(), r.left, r.top, r.width(), r.height(),
obj->z, obj->layer, obj->frame, objType[obj->type]);
}
- DebugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n");
+ debugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n");
return true;
}
@@ -307,14 +307,14 @@ bool Debugger::Cmd_Programs(int argc, const char** argv) {
int i = 1;
- DebugPrintf("+---+--------------------+--------+----------+\n"
+ debugPrintf("+---+--------------------+--------+----------+\n"
"| # | bound animation | size | status |\n"
"+---+--------------------+--------+----------+\n");
for ( ; b != e; b++, i++) {
ProgramPtr p = *b;
- DebugPrintf("|%3i|%-20s|%8i|%-10s|\n", i, p->_anim->_name, p->_instructions.size(), status[p->_status] );
+ debugPrintf("|%3i|%-20s|%8i|%-10s|\n", i, p->_anim->_name, p->_instructions.size(), status[p->_status] );
}
- DebugPrintf("+---+--------------------+--------+----------+\n");
+ debugPrintf("+---+--------------------+--------+----------+\n");
return true;
}
diff --git a/engines/parallaction/debug.h b/engines/parallaction/debug.h
index 887d08e945..551d746edf 100644
--- a/engines/parallaction/debug.h
+++ b/engines/parallaction/debug.h
@@ -22,7 +22,6 @@ private:
Parallaction *_vm;
MouseTriState _mouseState;
- bool Cmd_DebugLevel(int argc, const char **argv);
bool Cmd_Location(int argc, const char **argv);
bool Cmd_Give(int argc, const char **argv);
bool Cmd_Zones(int argc, const char **argv);
diff --git a/engines/pegasus/console.cpp b/engines/pegasus/console.cpp
index 64bd0ba5f2..e5a0cfec98 100644
--- a/engines/pegasus/console.cpp
+++ b/engines/pegasus/console.cpp
@@ -28,11 +28,11 @@
namespace Pegasus {
PegasusConsole::PegasusConsole(PegasusEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("die", WRAP_METHOD(PegasusConsole, Cmd_Die));
+ registerCmd("die", WRAP_METHOD(PegasusConsole, Cmd_Die));
// These functions are non-demo specific
if (!_vm->isDemo())
- DCmd_Register("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump));
+ registerCmd("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump));
}
PegasusConsole::~PegasusConsole() {
@@ -40,7 +40,7 @@ PegasusConsole::~PegasusConsole() {
bool PegasusConsole::Cmd_Die(int argc, const char **argv) {
if (argc == 1) {
- DebugPrintf("Usage: die <death reason>\n");
+ debugPrintf("Usage: die <death reason>\n");
return true;
}
@@ -54,7 +54,7 @@ bool PegasusConsole::Cmd_Die(int argc, const char **argv) {
if (invalidReason) {
- DebugPrintf("Invalid death reason %d\n", reason);
+ debugPrintf("Invalid death reason %d\n", reason);
return true;
}
@@ -65,14 +65,14 @@ bool PegasusConsole::Cmd_Die(int argc, const char **argv) {
bool PegasusConsole::Cmd_Jump(int argc, const char **argv) {
if (!g_interface) {
// TODO
- DebugPrintf("Cannot jump without interface set up\n");
+ 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");
+ debugPrintf("Usage: jump <neighborhood> <room> <direction>\n");
return true;
}
@@ -82,14 +82,14 @@ bool PegasusConsole::Cmd_Jump(int argc, const char **argv) {
if ((neighborhood < kCaldoriaID || neighborhood > kNoradDeltaID || neighborhood == kFinalTSAID) &&
neighborhood != kNoradSubChaseID) {
- DebugPrintf("Invalid neighborhood %d", neighborhood);
+ 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);
+ debugPrintf("Invalid direction %d", direction);
return true;
}
diff --git a/engines/pegasus/energymonitor.cpp b/engines/pegasus/energymonitor.cpp
index 40e54afb89..d3cc208e41 100644
--- a/engines/pegasus/energymonitor.cpp
+++ b/engines/pegasus/energymonitor.cpp
@@ -68,7 +68,9 @@ void Blinker::timeChanged(const TimeValue time) {
}
}
-static const NotificationFlags kEnergyExpiredFlag = 1;
+enum {
+ kEnergyExpiredFlag = 1
+};
EnergyMonitor *g_energyMonitor = 0;
diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp
index 283d55421f..e1b7e25cd5 100644
--- a/engines/pegasus/input.cpp
+++ b/engines/pegasus/input.cpp
@@ -57,9 +57,10 @@ InputDeviceManager::InputDeviceManager() {
_keyMap[Common::KEYCODE_p] = false;
_keyMap[Common::KEYCODE_TILDE] = false;
_keyMap[Common::KEYCODE_BACKQUOTE] = false;
- _keyMap[Common::KEYCODE_NUMLOCK] = false;
+ _keyMap[Common::KEYCODE_KP7] = false;
_keyMap[Common::KEYCODE_BACKSPACE] = false;
_keyMap[Common::KEYCODE_KP_MULTIPLY] = false;
+ _keyMap[Common::KEYCODE_KP9] = false;
_keyMap[Common::KEYCODE_LALT] = false;
_keyMap[Common::KEYCODE_RALT] = false;
_keyMap[Common::KEYCODE_e] = false;
@@ -113,10 +114,19 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) {
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])
+ // The original also used clear (aka "num lock" on Mac keyboards) here, but it doesn't
+ // work right on most systems. Either SDL or the OS treats num lock specially and the
+ // events don't come as expected. In many cases, the key down event is sent many times
+ // causing the drawer to open and close constantly until pressed again. It only causes
+ // more grief than anything else.
+
+ // The original doesn't use KP7 for inventory, but we're using it as an alternative for
+ // num lock. KP9 is used for the biochip drawer to balance things out.
+
+ if (_keyMap[Common::KEYCODE_TILDE] || _keyMap[Common::KEYCODE_BACKQUOTE] || _keyMap[Common::KEYCODE_KP7])
currentBits |= (kRawButtonDown << kLeftFireButtonShift);
- if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY])
+ if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY] || _keyMap[Common::KEYCODE_KP9])
currentBits |= (kRawButtonDown << kRightFireButtonShift);
// Update mouse button state
diff --git a/engines/pegasus/interaction.cpp b/engines/pegasus/interaction.cpp
new file mode 100644
index 0000000000..143bdebaba
--- /dev/null
+++ b/engines/pegasus/interaction.cpp
@@ -0,0 +1,38 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the 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/interaction.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+GameInteraction::GameInteraction(const InteractionID id, Neighborhood *nextHandler) : IDObject(id), InputHandler(nextHandler) {
+ _isInteracting = false;
+ _savedHandler = 0;
+ _owner = nextHandler;
+}
+
+} // End of namespace Pegasus
+
diff --git a/engines/pegasus/interaction.h b/engines/pegasus/interaction.h
index 293ee6be83..ca168b4cb7 100644
--- a/engines/pegasus/interaction.h
+++ b/engines/pegasus/interaction.h
@@ -37,11 +37,7 @@ 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;
- }
+ GameInteraction(const InteractionID id, Neighborhood *nextHandler);
// If the interaction is open (_isInteracting == true), it's too late to do anything
// about it here.
diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp
index e55c006f86..4bbda8fd93 100644
--- a/engines/pegasus/menu.cpp
+++ b/engines/pegasus/menu.cpp
@@ -227,6 +227,7 @@ MainMenu::MainMenu() : GameMenu(kMainMenuID), _menuBackground(0), _overviewButto
_menuLoop.attachFader(&_menuFader);
_menuLoop.initFromAIFFFile("Sounds/Main Menu.aiff");
+ _menuFader.setMasterVolume(((PegasusEngine *)g_engine)->getAmbienceLevel());
updateDisplay();
}
@@ -736,6 +737,7 @@ DeathMenu::DeathMenu(const DeathReason deathReason) : GameMenu(kDeathMenuID), _d
_largeSelect.startDisplaying();
} else {
_triumphSound.initFromQuickTime("Sounds/Caldoria/Galactic Triumph");
+ _triumphSound.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel());
_triumphSound.playSound();
}
diff --git a/engines/pegasus/module.mk b/engines/pegasus/module.mk
index cb44a04171..6d69d6ea58 100644
--- a/engines/pegasus/module.mk
+++ b/engines/pegasus/module.mk
@@ -12,6 +12,7 @@ MODULE_OBJS = \
graphics.o \
hotspot.o \
input.o \
+ interaction.o \
interface.o \
menu.o \
movie.o \
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
index 7977c17f12..ed52851338 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
@@ -42,109 +42,119 @@
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;
+enum {
+ kVidPhoneAngle = 30,
+ kReplicatorAngle = 50,
+ kDrawersAngle = -30,
+ kCaldoria53Angle = 45,
+ kCaldoria55Angle = -45
+};
-static const TimeValue kSinclairInterruptionTime1 = 2955;
-static const TimeValue kSinclairInterruptionTime2 = 6835;
-static const TimeValue kSinclairInterruptionTime3 = 9835;
-static const TimeValue kSinclairInterruptionTime4 = 12555;
+enum {
+ kSinclairInterruptionTime1 = 2955,
+ kSinclairInterruptionTime2 = 6835,
+ kSinclairInterruptionTime3 = 9835,
+ kSinclairInterruptionTime4 = 12555
+};
-static const InputBits kPullbackInterruptFilter = kFilterAllInput;
-static const InputBits kRecalibrationInterruptFilter = kFilterAllInput;
+enum {
+ kPullbackInterruptFilter = kFilterAllInput,
+ kRecalibrationInterruptFilter = kFilterAllInput
+};
-static const TimeValue kCaldoriaReplicatorIntroIn = 4933;
-static const TimeValue kCaldoriaReplicatorIntroOut = 6557;
+enum {
+ kCaldoriaReplicatorIntroIn = 4933,
+ kCaldoriaReplicatorIntroOut = 6557,
-static const TimeValue kCaldoriaReplicatorWrongChoiceIn = 6557;
-static const TimeValue kCaldoriaReplicatorWrongChoiceOut = 8586;
+ kCaldoriaReplicatorWrongChoiceIn = 6557,
+ kCaldoriaReplicatorWrongChoiceOut = 8586,
-static const TimeValue kCaldoriaReplicatorOJChoiceIn = 8586;
-static const TimeValue kCaldoriaReplicatorOJChoiceOut = 11687;
+ kCaldoriaReplicatorOJChoiceIn = 8586,
+ kCaldoriaReplicatorOJChoiceOut = 11687,
-static const TimeValue kCaldoriaMessagesIntroIn = 11687;
-static const TimeValue kCaldoriaMessagesIntroOut = 13641;
+ kCaldoriaMessagesIntroIn = 11687,
+ kCaldoriaMessagesIntroOut = 13641,
-static const TimeValue kCaldoriaFirstMessageIn = 13641;
-static const TimeValue kCaldoriaFirstMessageOut = 14203;
+ kCaldoriaFirstMessageIn = 13641,
+ kCaldoriaFirstMessageOut = 14203,
-static const TimeValue kCaldoriaSecondMessageIn = 14203;
-static const TimeValue kCaldoriaSecondMessageOut = 14750;
+ kCaldoriaSecondMessageIn = 14203,
+ kCaldoriaSecondMessageOut = 14750,
-static const TimeValue kCaldoriaDoorCloseIn = 14750;
-static const TimeValue kCaldoriaDoorCloseOut = 15472;
+ kCaldoriaDoorCloseIn = 14750,
+ kCaldoriaDoorCloseOut = 15472,
-static const TimeValue kCaldoriaElevatorCloseIn = 15472;
-static const TimeValue kCaldoriaElevatorCloseOut = 16336;
+ kCaldoriaElevatorCloseIn = 15472,
+ kCaldoriaElevatorCloseOut = 16336,
-static const TimeValue kCaldoriaShowerCloseIn = 16336;
-static const TimeValue kCaldoriaShowerCloseOut = 17101;
+ kCaldoriaShowerCloseIn = 16336,
+ kCaldoriaShowerCloseOut = 17101,
-static const TimeValue kCaldoriaGTDoorCloseIn = 17101;
-static const TimeValue kCaldoriaGTDoorCloseOut = 18523;
+ kCaldoriaGTDoorCloseIn = 17101,
+ kCaldoriaGTDoorCloseOut = 18523,
-static const TimeValue kCaldoriaNobodyHomeIn = 18523;
-static const TimeValue kCaldoriaNobodyHomeOut = 21469;
+ kCaldoriaNobodyHomeIn = 18523,
+ kCaldoriaNobodyHomeOut = 21469,
-static const TimeValue kCaldoriaNoOtherFloorIn = 21469;
-static const TimeValue kCaldoriaNoOtherFloorOut = 28013;
+ kCaldoriaNoOtherFloorIn = 21469,
+ kCaldoriaNoOtherFloorOut = 28013,
-static const TimeValue kCaldoria4DInstructionsIn = 28013;
-static const TimeValue kCaldoria4DInstructionsOut = 29730;
+ kCaldoria4DInstructionsIn = 28013,
+ kCaldoria4DInstructionsOut = 29730,
-static const TimeValue kCaldoriaDrinkOJIn = 33910;
-static const TimeValue kCaldoriaDrinkOJOut = 35846;
+ kCaldoriaDrinkOJIn = 33910,
+ kCaldoriaDrinkOJOut = 35846,
-static const TimeValue kCaldoriaNoOtherDestinationIn = 35846;
-static const TimeValue kCaldoriaNoOtherDestinationOut = 37877;
+ kCaldoriaNoOtherDestinationIn = 35846,
+ kCaldoriaNoOtherDestinationOut = 37877,
-static const TimeValue kCaldoriaUhghIn = 37877;
-static const TimeValue kCaldoriaUhghOut = 38025;
+ kCaldoriaUhghIn = 37877,
+ kCaldoriaUhghOut = 38025,
-static const TimeValue kCaldoriaSinclairShootsOSIn = 38025;
-static const TimeValue kCaldoriaSinclairShootsOSOut = 40649;
+ kCaldoriaSinclairShootsOSIn = 38025,
+ kCaldoriaSinclairShootsOSOut = 40649,
-static const TimeValue kCaldoriaScreamingAfterIn = 40649;
-static const TimeValue kCaldoriaScreamingAfterOut = 47661;
+ kCaldoriaScreamingAfterIn = 40649,
+ kCaldoriaScreamingAfterOut = 47661
+};
-static const TimeValue k4FloorTime = 0;
+enum {
+ k4FloorTime = 0,
-static const TimeValue k4To1Start = 40;
-static const TimeValue k4To1Stop = 7720;
+ k4To1Start = 40,
+ k4To1Stop = 7720,
-static const TimeValue k4To5Start = 7720;
-static const TimeValue k4To5Stop = 10280;
+ k4To5Start = 7720,
+ k4To5Stop = 10280,
-static const TimeValue k4To2Time = 10280;
+ k4To2Time = 10280,
-static const TimeValue k4To3Time = 10320;
+ k4To3Time = 10320,
-static const TimeValue k1FloorTime = 10360;
+ k1FloorTime = 10360,
-static const TimeValue k1To4Start = 10400;
-static const TimeValue k1To4Stop = 18080;
+ k1To4Start = 10400,
+ k1To4Stop = 18080,
-static const TimeValue k1To5Start = 18080;
-static const TimeValue k1To5Stop = 28320;
+ k1To5Start = 18080,
+ k1To5Stop = 28320,
-static const TimeValue k1To2Time = 28320;
+ k1To2Time = 28320,
-static const TimeValue k1To3Time = 28360;
+ k1To3Time = 28360,
-static const TimeValue k5FloorTime = 28400;
+ k5FloorTime = 28400,
-static const TimeValue k5To1Start = 28440;
-static const TimeValue k5To1Stop = 38680;
+ k5To1Start = 28440,
+ k5To1Stop = 38680,
-static const TimeValue k5To4Start = 38680;
-static const TimeValue k5To4Stop = 41240;
+ k5To4Start = 38680,
+ k5To4Stop = 41240,
-static const TimeValue k5To2Time = 41240;
+ k5To2Time = 41240,
-static const TimeValue k5To3Time = 41280;
+ k5To3Time = 41280
+};
// FuseFunction functions...
@@ -196,6 +206,8 @@ void Caldoria::start() {
if (!pullbackMovie->loadFile("Images/Caldoria/Pullback.movie"))
error("Could not load pullback movie");
+ pullbackMovie->setVolume(MIN<uint>(_vm->getSoundFXLevel(), 0xFF));
+
// Draw the first frame so we can fade to it
const Graphics::Surface *frame = pullbackMovie->decodeNextFrame();
assert(frame);
@@ -907,7 +919,7 @@ void Caldoria::arriveAtCaldoria49() {
setCurrentAlternate(kAltCaldoriaNormal);
// Need to force the loop to play.
- if (GameState.getCurrentDirection() == kNorth) {
+ if (GameState.getCurrentDirection() == kNorth && !GameState.getCaldoriaSinclairShot()) {
GameState.setCaldoriaFuseTimeLimit(kSinclairShootsTimeLimit);
startExtraSequence(kCa49NorthVoiceAnalysis, kExtraCompletedFlag, kFilterNoInput);
}
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp b/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
index 0494753661..688fb7860d 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
@@ -30,34 +30,36 @@
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;
+enum {
+ kSwitchableSlop = 3 * kCaldoriaFrameDuration,
+ // Two seconds - some slop
+ kSwitchableDuration = kCaldoriaMovieScale * 2 - kSwitchableSlop,
+ // Twelve frames + some slop
+ kNonswitchableDuration = kCaldoriaFrameDuration * 12 + kSwitchableSlop,
-static const TimeValue kSwitchable1Start = 0;
-static const TimeValue kSwitchable1Stop = kSwitchable1Start + kSwitchableDuration;
+ kSwitchable1Start = 0,
+ kSwitchable1Stop = kSwitchable1Start + kSwitchableDuration,
-static const TimeValue kSwitchable2Start = kSwitchable1Stop + kNonswitchableDuration;
-static const TimeValue kSwitchable2Stop = kSwitchable2Start + kSwitchableDuration;
+ kSwitchable2Start = kSwitchable1Stop + kNonswitchableDuration,
+ kSwitchable2Stop = kSwitchable2Start + kSwitchableDuration,
-static const TimeValue kSwitchable3Start = kSwitchable2Stop + kNonswitchableDuration;
-static const TimeValue kSwitchable3Stop = kSwitchable3Start + kSwitchableDuration;
+ kSwitchable3Start = kSwitchable2Stop + kNonswitchableDuration,
+ kSwitchable3Stop = kSwitchable3Start + kSwitchableDuration,
-static const NotificationFlags kVidPhoneDoneFlag = 1;
+ kVidPhoneDoneFlag = 1,
-static const TimeValue kRockMusicLoopIn = 0;
-static const TimeValue kRockMusicLoopOut = 2088;
+ kRockMusicLoopIn = 0,
+ kRockMusicLoopOut = 2088,
-static const TimeValue kOrchestralMusicLoopIn = 2088;
-static const TimeValue kOrchestralMusicLoopOut = 4985;
+ kOrchestralMusicLoopIn = 2088,
+ kOrchestralMusicLoopOut = 4985,
-static const TimeValue kRhythmsMusicLoopIn = 4985;
-static const TimeValue kRhythmsMusicLoopOut = 6824;
+ kRhythmsMusicLoopIn = 4985,
+ kRhythmsMusicLoopOut = 6824,
-static const TimeValue kAcousticMusicLoopIn = 6824;
-static const TimeValue kAcousticMusicLoopOut = 9387;
+ kAcousticMusicLoopIn = 6824,
+ kAcousticMusicLoopOut = 9387
+};
enum {
k4DVideoMenu,
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
index abf34d3863..c964e3458b 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
@@ -1167,6 +1167,18 @@ CaldoriaBomb::~CaldoriaBomb() {
delete[] _bombLevel[i];
}
+void CaldoriaBomb::setSoundFXLevel(const uint16) {
+ // The transition sounds between levels are ambience, so overwrite what
+ // Neighborhood::setSoundFXLevel does and keep using the ambience volume level
+ if (_timer.isRunning())
+ _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel());
+}
+
+void CaldoriaBomb::setAmbienceLevel(const uint16 level) {
+ if (_timer.isRunning())
+ _owner->_navMovie.setVolume(level);
+}
+
void CaldoriaBomb::openInteraction() {
_grid.moveElementTo(kCaldoriaBombGridLeft, kCaldoriaBombGridTop);
_grid.setDisplayOrder(kCaldoriaBombGridOrder);
@@ -1234,6 +1246,7 @@ void CaldoriaBomb::receiveNotification(Notification *notification, const Notific
_timer.start();
_currentLevel = 0;
_lastVertex = -1;
+ _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel());
startBombAmbient("Sounds/Caldoria/BmbLoop1.22K.AIFF");
break;
case kCaldoria56BombStage2:
@@ -1258,6 +1271,7 @@ void CaldoriaBomb::receiveNotification(Notification *notification, const Notific
_grid.hide();
_timer.stop();
_timer.hide();
+ _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
_owner->loadLoopSound1("");
_owner->playDeathExtra(kCaldoria56BombExplodes, kDeathNuclearExplosion);
}
@@ -1411,6 +1425,7 @@ void CaldoriaBomb::handleInput(const Input &input, const Hotspot *hotspot) {
_timer.stop();
_grid.hide();
_timer.hide();
+ _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
_owner->startExtraSequence(kCaldoria56BombStage7, kExtraCompletedFlag, kFilterNoInput);
break;
}
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h
index 5bb39b4122..ba6d1e8998 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h
+++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h
@@ -122,6 +122,9 @@ public:
CaldoriaBomb(Neighborhood *, NotificationManager *);
virtual ~CaldoriaBomb();
+ void setSoundFXLevel(const uint16);
+ void setAmbienceLevel(const uint16);
+
long getNumHints();
Common::String getHintMovie(uint);
void doSolve();
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp b/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp
index a3ce97d438..2ae990d775 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp
@@ -24,6 +24,7 @@
*/
#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
#include "pegasus/neighborhood/neighborhood.h"
#include "pegasus/neighborhood/caldoria/caldoria.h"
#include "pegasus/neighborhood/caldoria/caldoriamessages.h"
@@ -45,6 +46,10 @@ void CaldoriaMessages::openInteraction() {
_messageNumber = 1;
}
+void CaldoriaMessages::setSoundFXLevel(const uint16 fxLevel) {
+ _messageMovie.setVolume(fxLevel);
+}
+
void CaldoriaMessages::initInteraction() {
GameInteraction::_owner->startExtraSequence(kCaBedroomVidPhone, kExtraCompletedFlag, kFilterNoInput);
}
@@ -101,6 +106,7 @@ void CaldoriaMessages::play1Message(uint messageNumber) {
GameState.setCaldoriaSeenMessages(true);
}
+ _messageMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
_messageMovie.moveElementTo(kCaldoriaMessageLeft, kCaldoriaMessageTop);
_messageMovie.setDisplayOrder(kCaldoriaMessagesOrder);
_messageMovie.startDisplaying();
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamessages.h b/engines/pegasus/neighborhood/caldoria/caldoriamessages.h
index 955fe10ce9..b2fc7c3bf9 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoriamessages.h
+++ b/engines/pegasus/neighborhood/caldoria/caldoriamessages.h
@@ -41,6 +41,8 @@ public:
CaldoriaMessages(Neighborhood *, const NotificationID, NotificationManager *);
virtual ~CaldoriaMessages() {}
+ void setSoundFXLevel(const uint16);
+
protected:
void openInteraction();
void initInteraction();
diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp
index f7493dbe75..df5a75541c 100644
--- a/engines/pegasus/neighborhood/mars/mars.cpp
+++ b/engines/pegasus/neighborhood/mars/mars.cpp
@@ -2402,6 +2402,8 @@ void Mars::doCanyonChase() {
if (!video->loadFile("Images/Mars/M44ESA.movie"))
error("Could not load interface->shuttle transition video");
+ video->setVolume(MIN<uint>(_vm->getSoundFXLevel(), 0xFF));
+
video->start();
while (!_vm->shouldQuit() && !video->endOfVideo()) {
@@ -2612,6 +2614,7 @@ void Mars::startUpFromFinishedSpaceChase() {
kShuttleJunkTop, false);
initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false);
+ _explosions.setVolume(_vm->getSoundFXLevel());
_explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes);
_energyBeam.initShuttleWeapon();
@@ -2650,6 +2653,7 @@ void Mars::startUpFromFinishedSpaceChase() {
initOneMovie(&_canyonChaseMovie, "Images/Mars/M98EAS.movie", kShuttleTractorBeamMovieOrder,
kShuttleWindowLeft, kShuttleWindowTop, true);
+ _canyonChaseMovie.setVolume(_vm->getSoundFXLevel());
_canyonChaseMovie.setTime(_canyonChaseMovie.getDuration());
_canyonChaseMovie.redrawMovieWorld();
}
@@ -2725,6 +2729,7 @@ void Mars::startUpFromSpaceChase() {
kShuttleJunkTop, false);
initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false);
+ _explosions.setVolume(_vm->getSoundFXLevel());
_explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes);
_energyBeam.initShuttleWeapon();
@@ -2788,6 +2793,10 @@ void Mars::startUpFromSpaceChase() {
void Mars::setSoundFXLevel(const uint16 level) {
Neighborhood::setSoundFXLevel(level);
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kMars48, kEast) &&
+ !GameState.getMarsAvoidedReactorRobot())
+ _loop2Fader.setMasterVolume(level);
+
if (_canyonChaseMovie.isMovieValid())
_canyonChaseMovie.setVolume(level);
@@ -2842,6 +2851,7 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) {
initOneMovie(&_junk, "Images/Mars/Junk.movie", kShuttleJunkOrder, kShuttleJunkLeft, kShuttleJunkTop, false);
initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false);
+ _explosions.setVolume(_vm->getSoundFXLevel());
_explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes);
_energyBeam.initShuttleWeapon();
@@ -3175,6 +3185,7 @@ void Mars::spaceChaseClick(const Input &input, const HotSpotID id) {
// Shameless reuse of a variable :P
initOneMovie(&_canyonChaseMovie, "Images/Mars/M98EAS.movie", kShuttleTractorBeamMovieOrder,
kShuttleWindowLeft, kShuttleWindowTop, true);
+ _canyonChaseMovie.setVolume(_vm->getSoundFXLevel());
_canyonChaseMovie.redrawMovieWorld();
playMovieSegment(&_canyonChaseMovie, 0, _canyonChaseMovie.getDuration());
diff --git a/engines/pegasus/neighborhood/mars/shuttlehud.cpp b/engines/pegasus/neighborhood/mars/shuttlehud.cpp
index 11e826278b..2d894f7b95 100644
--- a/engines/pegasus/neighborhood/mars/shuttlehud.cpp
+++ b/engines/pegasus/neighborhood/mars/shuttlehud.cpp
@@ -30,26 +30,28 @@
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;
+enum {
+ kHUDTargetGridLeft = kShuttleWindowLeft + 16,
+ kHUDTargetGridTop = kShuttleWindowTop + 8,
+ kHUDTargetGridWidth = 328,
+ kHUDTargetGridHeight = 206,
+
+ kHUDRS232Left = kHUDTargetGridLeft + 264,
+ kHUDRS232Top = kHUDTargetGridTop + 2,
+
+ kHUDLockLeft = kShuttleWindowLeft + 101,
+ kHUDLockTop = kShuttleWindowTop + 49,
+ kHUDLockWidth = 145,
+ kHUDLockHeight = 124,
+
+ kTractorLockWidth = 50,
+ kTractorLockHeight = 30,
+
+ kTractorLockLeft = kShuttleWindowMidH - kTractorLockWidth / 2,
+ kTractorLockTop = kShuttleWindowMidV - kTractorLockHeight / 2,
+ kTractorLockRight = kTractorLockLeft + kTractorLockWidth,
+ kTractorLockBottom = kTractorLockTop + kTractorLockHeight
+};
static const uint16 s_RS232Data[] = {
0xF0E1, 0xCE70,
diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp
index 320fbdabaa..c9be349694 100644
--- a/engines/pegasus/neighborhood/neighborhood.cpp
+++ b/engines/pegasus/neighborhood/neighborhood.cpp
@@ -1495,7 +1495,15 @@ void Neighborhood::loadLoopSound2(const Common::String &soundName, uint16 volume
if (!_loop2SoundString.empty()) {
_soundLoop2.initFromAIFFFile(_loop2SoundString);
_soundLoop2.loopSound();
- _loop2Fader.setMasterVolume(_vm->getAmbienceLevel());
+ // HACK: Some ambient loops are actually sound effects, like Ares waiting at
+ // the reactor and Poseidon at the launch console. Detect these and use the
+ // SFX volume instead of ambience.
+ if (soundName == "Sounds/Mars/Robot Loop.aiff" ||
+ soundName == "Sounds/Norad/Breathing Typing.22K.AIFF" ||
+ soundName == "Sounds/Norad/N54NAS.32K.AIFF")
+ _loop2Fader.setMasterVolume(_vm->getSoundFXLevel());
+ else
+ _loop2Fader.setMasterVolume(_vm->getAmbienceLevel());
_loop2Fader.setFaderValue(0);
faderMove.makeTwoKnotFaderSpec(fadeScale, 0, 0, fadeIn, volume);
_loop2Fader.startFaderSync(faderMove);
@@ -1580,6 +1588,7 @@ void Neighborhood::closeCroppedMovie() {
void Neighborhood::playCroppedMovieOnce(const Common::String &movieName, CoordType left, CoordType top, const InputBits interruptionFilter) {
openCroppedMovie(movieName, left, top);
+ _croppedMovie.setVolume(_vm->getSoundFXLevel());
_croppedMovie.redrawMovieWorld();
_croppedMovie.start();
diff --git a/engines/pegasus/neighborhood/neighborhood.h b/engines/pegasus/neighborhood/neighborhood.h
index 3c1c5eac92..f7f2b038c6 100644
--- a/engines/pegasus/neighborhood/neighborhood.h
+++ b/engines/pegasus/neighborhood/neighborhood.h
@@ -91,6 +91,7 @@ struct QueueRequest {
bool operator==(const QueueRequest &arg1, const QueueRequest &arg2);
bool operator!=(const QueueRequest &arg1, const QueueRequest &arg2);
+class CaldoriaBomb;
class GameInteraction;
class Item;
class Neighborhood;
@@ -109,6 +110,7 @@ protected:
typedef Common::Queue<QueueRequest> NeighborhoodActionQueue;
class Neighborhood : public IDObject, public NotificationReceiver, public InputHandler, public Idler {
+friend class CaldoriaBomb;
friend class StriderCallBack;
public:
diff --git a/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp b/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp
index e2a0267231..1478a74744 100644
--- a/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp
+++ b/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp
@@ -45,7 +45,9 @@ 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;
+enum {
+ kPanPixelsPerFrame = 8
+};
// Interesting times are in seconds.
static const TimeValue s_ECRInterestingTimes[] = {
diff --git a/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp b/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
index 3491f161c7..e85a3e699f 100644
--- a/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
+++ b/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
@@ -65,64 +65,66 @@ 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;
+enum {
+ kFSPowerUpStartStart = 0,
+ kFSPowerUpStartStop = 600,
+ kFSSplashStart = 600,
+ kFSSplashStop = 7800,
+ kFSSplashIntakeStart = 7800,
+ kFSSplashIntakeStop = 18600,
+
+ kFSMainMenu = 18600,
+ kFSIntakeHiliteStart = 19200,
+ kFSIntakeHiliteStop = 19800,
+ kFSDispenseHiliteStart = 19800,
+ kFSDispenseHiliteStop = 20400,
+
+ kFSDispenseMenu = 20400,
+
+ kFSArHiliteStart = 21000,
+ kFSArHiliteStop = 21600,
+ kFSArAttach = 21600,
+ kFSArFilledStart = 22200,
+ kFSArFilledStop = 25200,
+ kFSArIncompatibleStart = 25200,
+ kFSArIncompatibleStop = 30000,
+
+ kFSCO2HiliteStart = 30000,
+ kFSCO2HiliteStop = 30600,
+ kFSCO2Attach = 30600,
+ kFSCO2FilledStart = 31200,
+ kFSCO2FilledStop = 34200,
+ kFSCO2IncompatibleStart = 34200,
+ kFSCO2IncompatibleStop = 39000,
+
+ kFSHeHiliteStart = 39000,
+ kFSHeHiliteStop = 39600,
+ kFSHeAttach = 39600,
+ kFSHeFilledStart = 40200,
+ kFSHeFilledStop = 43200,
+ kFSHeIncompatibleStart = 43200,
+ kFSHeIncompatibleStop = 48000,
+
+ kFSOHiliteStart = 48000,
+ kFSOHiliteStop = 48600,
+ kFSOAttach = 48600,
+ kFSOFilledStart = 49200,
+ kFSOFilledStop = 52200,
+ kFSOIncompatibleStart = 52200,
+ kFSOIncompatibleStop = 57000,
+
+ kFSNHiliteStart = 57000,
+ kFSNHiliteStop = 57600,
+ kFSNAttach = 57600,
+ kFSNFilledStart = 58200,
+ kFSNFilledStop = 61200,
+ kFSNIncompatibleStart = 61200,
+ kFSNIncompatibleStop = 66000,
+
+ kFSIntakeMenu = 66000,
+ kFSIntakeInProgressStart = 66600,
+ kFSIntakeInProgressStop = 69600
+};
NoradAlphaFillingStation::NoradAlphaFillingStation(Neighborhood *owner) : GameInteraction(kNoradFillingStationInteractionID, owner),
_rightSideMovie(kN01RightSideID), _rightSideNotification(kNoradFillingStationNotificationID, ((PegasusEngine *)g_engine)) {
diff --git a/engines/pegasus/neighborhood/norad/delta/globegame.cpp b/engines/pegasus/neighborhood/norad/delta/globegame.cpp
index 0b95e9bc2b..9ea3036024 100644
--- a/engines/pegasus/neighborhood/norad/delta/globegame.cpp
+++ b/engines/pegasus/neighborhood/norad/delta/globegame.cpp
@@ -394,20 +394,22 @@ 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 {
+ kSplash1End = 4,
+ kSplash2End = 5,
+ kSplash3Start = 8,
+ kSplash3Stop = 9,
+ kSplash4Start = 9,
+ kSplash4Stop = 10,
+ kNewLaunchSiloTime = 10,
+ kSiloDeactivatedTime = 11,
+ kMissileLaunchedTime = 12,
+ kMaxDeactivatedStart = 13,
+ kMaxDeactivatedStop = 23,
+
+ kGamePlaying = 1,
+ kGameOver = 2
+};
enum {
kGameIntro,
@@ -453,8 +455,13 @@ GlobeGame::GlobeGame(Neighborhood *handler) : GameInteraction(kNoradGlobeGameInt
_neighborhoodNotification = handler->getNeighborhoodNotification();
}
+void GlobeGame::setSoundFXLevel(const uint16 fxLevel) {
+ _monitorMovie.setVolume(fxLevel);
+}
+
void GlobeGame::openInteraction() {
_monitorMovie.initFromMovieFile("Images/Norad Delta/N79 Left Monitor");
+ _monitorMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
_monitorMovie.moveElementTo(kGlobeMonitorLeft, kGlobeMonitorTop);
_monitorMovie.setDisplayOrder(kGlobeMonitorLayer);
_monitorMovie.startDisplaying();
diff --git a/engines/pegasus/neighborhood/norad/delta/globegame.h b/engines/pegasus/neighborhood/norad/delta/globegame.h
index 73ed48866f..93235a1784 100644
--- a/engines/pegasus/neighborhood/norad/delta/globegame.h
+++ b/engines/pegasus/neighborhood/norad/delta/globegame.h
@@ -98,6 +98,8 @@ public:
GlobeGame(Neighborhood *);
virtual ~GlobeGame() {}
+ void setSoundFXLevel(const uint16);
+
void handleInput(const Input &, const Hotspot *);
void clickInHotspot(const Input &, const Hotspot *);
void activateHotspots();
diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
index 1eea2f0156..ee047d72b2 100644
--- a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
+++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
@@ -514,6 +514,17 @@ void NoradDelta::openDoor() {
}
}
+void NoradDelta::cantMoveThatWay(CanOpenDoorReason reason) {
+ // WORKAROUND: The door outside the launch console room isn't treated as a door,
+ // so play the correct sound.
+ if (reason == kCantMoveBlocked && GameState.getCurrentRoomAndView() == MakeRoomView(kNorad67, kNorth)) {
+ cantOpenDoor(kCantOpenLocked);
+ return;
+ }
+
+ Neighborhood::cantMoveThatWay(reason);
+}
+
void NoradDelta::activateHotspots() {
Norad::activateHotspots();
@@ -863,6 +874,13 @@ void NoradDelta::doSolve() {
}
}
+void NoradDelta::setSoundFXLevel(const uint16 level) {
+ Neighborhood::setSoundFXLevel(level);
+
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad54North, kNorth))
+ _loop2Fader.setMasterVolume(level);
+}
+
Common::String NoradDelta::getSoundSpotsName() {
return "Sounds/Norad/Norad Delta Spots";
}
diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.h b/engines/pegasus/neighborhood/norad/delta/noraddelta.h
index 11065f2c9d..591fd691a2 100644
--- a/engines/pegasus/neighborhood/norad/delta/noraddelta.h
+++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.h
@@ -68,6 +68,8 @@ public:
bool canSolve();
void doSolve();
+ void setSoundFXLevel(const uint16);
+
void doorOpened();
protected:
@@ -90,6 +92,7 @@ protected:
void arriveAtNorad79West();
TimeValue getViewTime(const RoomID, const DirectionConstant);
void openDoor();
+ void cantMoveThatWay(CanMoveForwardReason);
void activateHotspots();
void clickInHotspot(const Input &, const Hotspot *);
void receiveNotification(Notification *, const NotificationFlags);
diff --git a/engines/pegasus/neighborhood/norad/subcontrolroom.cpp b/engines/pegasus/neighborhood/norad/subcontrolroom.cpp
index d48481e925..1b14c529d8 100644
--- a/engines/pegasus/neighborhood/norad/subcontrolroom.cpp
+++ b/engines/pegasus/neighborhood/norad/subcontrolroom.cpp
@@ -34,110 +34,113 @@ 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;
+enum {
+ kAlphaClawSplashStart = 0,
+ kAlphaClawSplashStop = 4000,
+
+ kDeltaClawSplashStart = 4000,
+ kDeltaClawSplashStop = 8000,
+
+ kClawAtATime = 8000,
+ kClawAtAPinchedTime = 8600,
+ kClawAtATurnedTime = 9200,
+ kClawAtAWithRobotPinchedTime = 9800,
+
+ kClawAtBTime = 10400,
+ kClawAtBPinchedTime = 11000,
+ kClawAtBTurnedTime = 11600,
+ kClawAtBWithRobotTime = 12200,
+ kClawAtBWithRobotPinchedTime = 12800,
+
+ kClawAtCTime = 13400,
+ kClawAtCPinchedTime = 14000,
+ kClawAtCTurnedTime = 14600,
+
+ kClawAtDTime = 15200,
+ kClawAtDPinchedTime = 15800,
+ kClawAtDTurnedTime = 16400,
+
+ kAToBStart = 17000,
+ kAToBStop = 18680,
+ kAPinchStart = 18680,
+ kAPinchStop = 20200,
+ kACCWStart = 20200,
+ kACCWStop = 21600,
+ kACWStart = 21600,
+ kACWStop = 23000,
+
+ kBToAStart = 23000,
+ kBToAStop = 24680,
+ kBToCStart = 24680,
+ kBToCStop = 26520,
+ kBToDStart = 26520,
+ kBToDStop = 28320,
+ kBPinchStart = 28320,
+ kBPinchStop = 29680,
+ kBCCWStart = 29680,
+ kBCCWStop = 31200,
+ kBCWStart = 31200,
+ kBCWStop = 32720,
+
+ kCToBStart = 32720,
+ kCToBStop = 34560,
+ kCPinchStart = 34560,
+ kCPinchStop = 36400,
+ kCCCWStart = 36400,
+ kCCCWStop = 37840,
+ kCCWStart = 37840,
+ kCCWStop = 39280,
+
+ kDToBStart = 39280,
+ kDToBStop = 41080,
+ kDPinchStart = 41080,
+ kDPinchStop = 42600,
+ kDCCWStart = 42600,
+ kDCCWStop = 44000,
+ kDCWStart = 44000,
+ kDCWStop = 45400,
+
+ kRobotApproachStart = 45400,
+ kRobotApproachStop = 56800,
+
+ kCToBWithRobotStart = 56800,
+ kCToBWithRobotStop = 58600,
+
+ kBPinchWithRobotStart = 58600,
+ kBPinchWithRobotStop = 60400,
+ kBToAWithRobotStart = 60400,
+ kBToAWithRobotStop = 62240
+};
// As usual, times here are in seconds.
// Left monitor times.
+enum {
+ kAlphaSplashStart = 0,
+ kAlphaSplashStop = 2,
-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;
+ kMainMenuTime = 2,
+ kLaunchPrepRolloverTime = 3,
+ kLaunchPrepHighlightStart = 4,
+ kLaunchPrepHighlightStop = 5,
+ kClawControlRolloverTime = 5,
+ kClawControlHighlightStart = 6,
+ kClawControlHighlightStop = 7,
-static const TimeValue kAlphaLaunchPrepStart = 7;
-static const TimeValue kAlphaLaunchPrepStop = 17;
+ kAlphaLaunchPrepStart = 7,
+ kAlphaLaunchPrepStop = 17,
-static const TimeValue kClawMenuStart = 17;
-static const TimeValue kClawMenuStop = 18;
+ kClawMenuStart = 17,
+ kClawMenuStop = 18,
-static const TimeValue kClawMenuTime = 18;
+ kClawMenuTime = 18,
-static const TimeValue kDeltaSplashStart = 19;
-static const TimeValue kDeltaSplashStop = 21;
+ kDeltaSplashStart = 19,
+ kDeltaSplashStop = 21,
-static const TimeValue kDeltaLaunchPrepStart = 21;
-static const TimeValue kDeltaLaunchPrepStop = 30;
+ kDeltaLaunchPrepStart = 21,
+ kDeltaLaunchPrepStop = 30
+};
// Right monitor times.
diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
index 92b79c038e..f7996fabf5 100644
--- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp
+++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
@@ -41,41 +41,45 @@ 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;
+enum {
+ kTBPCloseBoxPICTID = 800,
+ kTBPRewindPICTID = 801,
+ kUnresolvedPICTID = 802,
+ kResolvedPICTID = 803,
+ kJumpMenuPICTID = 804,
+ kJumpMenuHilitedPICTID = 805,
+ kExitPICTID = 806,
+ kExitHilitedPICTID = 807,
+ kLeftRipPICTID = 808,
+ kComparisonCloseBoxPICTID = 809,
+ kComparisonLeftRewindPICTID = 810,
+ kComparisonRightRewindPICTID = 811,
+ kComparisonHiliteNoradPICTID = 812,
+ kComparisonHiliteMarsPICTID = 813,
+ kComparisonHiliteCaldoriaPICTID = 814,
+ kComparisonHiliteWSCPICTID = 815,
+ kComparisonChancesNoradPICTID = 816,
+ kComparisonChancesMarsPICTID = 817,
+ kComparisonChancesCaldoriaPICTID = 818,
+ kComparisonChancesWSCPICTID = 819,
+ kRedirectionCCRolloverPICTID = 820,
+ kRedirectionRRRolloverPICTID = 821,
+ kRedirectionFDRolloverPICTID = 822,
+ kRedirectionCCDoorPICTID = 823,
+ kRedirectionRRDoorPICTID = 824,
+ kRedirectionFDDoorPICTID = 825,
+ kRedirectionSecuredPICTID = 826,
+ kRedirectionNewTargetPICTID = 827,
+ kRedirectionClosePICTID = 828
+};
static const int16 kCompassShift = 15;
-static const TimeScale kFullTSAMovieScale = 600;
-static const TimeScale kFullTSAFramesPerSecond = 15;
-static const TimeScale kFullTSAFrameDuration = 40;
+enum {
+ kFullTSAMovieScale = 600,
+ kFullTSAFramesPerSecond = 15,
+ kFullTSAFrameDuration = 40
+};
// Alternate IDs.
static const AlternateID kAltTSANormal = 0;
@@ -84,416 +88,425 @@ 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;
+enum {
+ kTSA01 = 1,
+ kTSA02 = 2,
+ kTSA03 = 3,
+ kTSA04 = 4,
+ kTSA05 = 5,
+ kTSA0A = 6,
+ kTSA06 = 7,
+ kTSA07 = 8,
+ kTSA08 = 9,
+ kTSA09 = 10,
+ kTSA10 = 11,
+ kTSA11 = 12,
+ kTSA12 = 13,
+ kTSA13 = 14,
+ kTSA14 = 15,
+ kTSA15 = 16,
+ kTSA16 = 17,
+ kTSA17 = 18,
+ kTSA18 = 19,
+ kTSA19 = 20,
+ kTSA0B = 21,
+ kTSA21Cyan = 22,
+ kTSA22Cyan = 23,
+ kTSA23Cyan = 24,
+ kTSA24Cyan = 25,
+ kTSA25Cyan = 26,
+ kTSA21Red = 27,
+ kTSA23Red = 29,
+ kTSA24Red = 30,
+ kTSA25Red = 31,
+ kTSA26 = 32,
+ kTSA27 = 33,
+ kTSA28 = 34,
+ kTSA29 = 35,
+ kTSA30 = 36,
+ kTSA31 = 37,
+ kTSA32 = 38,
+ kTSA33 = 39,
+ kTSA34 = 40,
+ kTSA35 = 41,
+ 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;
+enum {
+ kActivateTSAReadyForCard = 1,
+ kActivateTSAReadyToTransport = 2,
+ kActivateTSARobotsAwake = 3,
+ kActivateTSA0BZoomedOut = 4,
+ kActivateTSA0BZoomedIn = 5,
+ kActivateTSA0BComparisonVideo = 6,
+ kActivationLogReaderOpen = 7,
+ kActivateTSA0BTBPVideo = 8,
+ kActivationDoesntHaveKey = 9,
+ kActivationKeyVaultOpen = 10,
+ kActivationDoesntHaveChips = 11,
+ kActivationChipVaultOpen = 12,
+ kActivationJumpToPrehistoric = 13,
+ kActivationJumpToNorad = 14,
+ kActivationJumpToMars = 15,
+ kActivationJumpToWSC = 16,
+ kActivationReadyToExit = 17,
+ kActivationReadyForJumpMenu = 18,
+ 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;
+enum {
+ kTSAGTCardDropSpotID = 5000,
+ kTSAGTTokyoSpotID = 5001,
+ kTSAGTCaldoriaSpotID = 5002,
+ kTSAGTBeachSpotID = 5003,
+ kTSAGTOtherSpotID = 5004,
+ kTSA02DoorSpotID = 5005,
+ kTSA03EastJimenezSpotID = 5006,
+ kTSA03WestCrenshawSpotID = 5007,
+ kTSA04EastMatsumotoSpotID = 5008,
+ kTSA04WestCastilleSpotID = 5009,
+ kTSA05EastSinclairSpotID = 5010,
+ kTSA05WestWhiteSpotID = 5011,
+ kTSA0AEastSpotID = 5012,
+ kTSA0AWastSpotID = 5013,
+ kTSA0BEastMonitorSpotID = 5014,
+ kTSA0BEastMonitorOutSpotID = 5015,
+ kTSA0BEastCompareNoradSpotID = 5016,
+ kTSA0BEastCompareMarsSpotID = 5017,
+ kTSA0BEastCompareCaldoriaSpotID = 5018,
+ kTSA0BEastCompareWSCSpotID = 5019,
+ kTSA0BEastLeftRewindSpotID = 5020,
+ kTSA0BEastLeftPlaySpotID = 5021,
+ kTSA0BEastRightRewindSpotID = 5022,
+ kTSA0BEastRightPlaySpotID = 5023,
+ kTSA0BEastCloseVideoSpotID = 5024,
+ kTSA0BNorthMonitorSpotID = 5025,
+ kTSA0BNorthMonitorOutSpotID = 5026,
+ kTSA0BNorthHistLogSpotID = 5027,
+ kTSA0BNorthRobotsToCommandCenterSpotID = 5028,
+ kTSA0BNorthRobotsToReadyRoomSpotID = 5029,
+ kTSA0BNorthRobotsToFrontDoorSpotID = 5030,
+ kTSA0BWestMonitorSpotID = 5031,
+ kTSA0BWestMonitorOutSpotID = 5032,
+ kTSA0BWestTheorySpotID = 5033,
+ kTSA0BWestBackgroundSpotID = 5034,
+ kTSA0BWestProcedureSpotID = 5035,
+ kTSA0BWestCloseVideoSpotID = 5036,
+ kTSA0BWestPlayVideoSpotID = 5037,
+ kTSA0BWestRewindVideoSpotID = 5038,
+ kTSA22EastMonitorSpotID = 5039,
+ kTSA22EastKeySpotID = 5040,
+ kTSA23WestMonitorSpotID = 5041,
+ kTSA23WestChipsSpotID = 5042,
+ kTSA34NorthDoorSpotID = 5043,
+ kTSA37NorthJumpToPrehistoricSpotID = 5044,
+ kTSA37NorthJumpToNoradSpotID = 5045,
+ kTSA37NorthCancelNoradSpotID = 5046,
+ kTSA37NorthJumpToMarsSpotID = 5047,
+ kTSA37NorthCancelMarsSpotID = 5048,
+ kTSA37NorthJumpToWSCSpotID = 5049,
+ kTSA37NorthCancelWSCSpotID = 5050,
+ kTSA37NorthExitSpotID = 5051,
+ kTSA37NorthJumpMenuSpotID = 5052,
+ kTSA37NorthNoradMenuSpotID = 5053,
+ kTSA37NorthMarsMenuSpotID = 5054,
+ 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;
+enum {
+ kTSATransporterArrowLoop = 0,
+ kTSAArriveFromCaldoria = 1,
+ kTSAGTOtherChoice = 2,
+ kTSAGTCardSwipe = 3,
+ kTSAGTSelectCaldoria = 4,
+ kTSAGTGoToCaldoria = 5,
+ kTSAGTSelectBeach = 6,
+ kTSAGTGoToBeach = 7,
+ kTSAGTArriveAtBeach = 8,
+ kTSAGTSelectTokyo = 9,
+ kTSAGTGoToTokyo = 10,
+ kTSAGTArriveAtTokyo = 11,
+ kTSA02NorthZoomIn = 12,
+ kTSA02NorthTenSecondDoor = 13,
+ kTSA02NorthZoomOut = 14,
+ kTSA02NorthDoorWithAgent3 = 15,
+ kTSA03JimenezZoomIn = 16,
+ kTSA03JimenezSpeech = 17,
+ kTSA03JimenezZoomOut = 18,
+ kTSA03CrenshawZoomIn = 19,
+ kTSA03CrenshawSpeech = 20,
+ kTSA03CrenshawZoomOut = 21,
+ kTSA03SouthRobotDeath = 22,
+ kTSA04NorthRobotGreeting = 23,
+ kTSA04MatsumotoZoomIn = 24,
+ kTSA04MatsumotoSpeech = 25,
+ kTSA04MatsumotoZoomOut = 26,
+ kTSA04CastilleZoomIn = 27,
+ kTSA04CastilleSpeech = 28,
+ kTSA04CastilleZoomOut = 29,
+ kTSA05SinclairZoomIn = 30,
+ kTSA05SinclairSpeech = 31,
+ kTSA05SinclairZoomOut = 32,
+ kTSA05WhiteZoomIn = 33,
+ kTSA05WhiteSpeech = 34,
+ kTSA05WhiteZoomOut = 35,
+ kTSA0AEastRobot = 36,
+ kTSA0AWestRobot = 37,
+ kTSA16NorthRobotDeath = 38,
+ kTSA0BEastZoomIn = 39,
+ kTSA0BEastZoomedView = 40,
+ kTSA0BEastZoomOut = 41,
+ kTSA0BEastTurnLeft = 42,
+ kTSA0BComparisonStartup = 43,
+ kTSA0BComparisonView0000 = 44,
+ kTSA0BComparisonView0002 = 45,
+ kTSA0BComparisonView0020 = 46,
+ kTSA0BComparisonView0022 = 47,
+ kTSA0BComparisonView0200 = 48,
+ kTSA0BComparisonView0202 = 49,
+ kTSA0BComparisonView0220 = 50,
+ kTSA0BComparisonView0222 = 51,
+ kTSA0BComparisonView2000 = 52,
+ kTSA0BComparisonView2002 = 53,
+ kTSA0BComparisonView2020 = 54,
+ kTSA0BComparisonView2022 = 55,
+ kTSA0BComparisonView2200 = 56,
+ kTSA0BComparisonView2202 = 57,
+ kTSA0BComparisonView2220 = 58,
+ kTSA0BComparisonView2222 = 59,
+ kTSA0BNoradComparisonView = 60,
+ kTSA0BNoradUnaltered = 61,
+ kTSA0BNoradAltered = 62,
+ kTSA0BMarsComparisonView = 63,
+ kTSA0BMarsUnaltered = 64,
+ kTSA0BMarsAltered = 65,
+ kTSA0BWSCComparisonView = 66,
+ kTSA0BWSCUnaltered = 67,
+ kTSA0BWSCAltered = 68,
+ kTSA0BCaldoriaComparisonView = 69,
+ kTSA0BCaldoriaUnaltered = 70,
+ kTSA0BCaldoriaAltered = 71,
+ kTSA0BNorthZoomIn = 72,
+ kTSA0BNorthZoomedView = 73,
+ kTSA0BNorthZoomOut = 74,
+ kTSA0BNorthTurnLeft = 75,
+ kTSA0BNorthTurnRight = 76,
+ kTSA0BNorthHistLogOpen = 77,
+ kTSA0BNorthHistLogClose = 78,
+ kTSA0BNorthHistLogCloseWithLog = 79,
+ kTSA0BNorthCantChangeHistory = 80,
+ kTSA0BNorthYoureBusted = 81,
+ kTSA0BNorthFinallyHappened = 82,
+ kTSA0BShowRip1 = 83,
+ kTSA0BNorthRipView1 = 84,
+ kTSA0BShowRip2 = 85,
+ kTSA0BShowGuardRobots = 86,
+ kTSA0BAIInterruption = 87,
+ kTSA0BRobotsToCommandCenter = 88,
+ kTSA0BNorthRobotsAtCCView = 89,
+ kTSA0BNorthRobotsAtRRView = 90,
+ kTSA0BNorthRobotsAtFDView = 91,
+ kTSA0BRobotsFromCommandCenterToReadyRoom = 92,
+ kTSA0BRobotsFromReadyRoomToCommandCenter = 93,
+ kTSA0BRobotsFromCommandCenterToFrontDoor = 94,
+ kTSA0BRobotsFromFrontDoorToCommandCenter = 95,
+ kTSA0BRobotsFromFrontDoorToReadyRoom = 96,
+ kTSA0BRobotsFromReadyRoomToFrontDoor = 97,
+ kTSA0BWestZoomIn = 98,
+ kTSA0BWestZoomedView = 99,
+ kTSA0BWestZoomOut = 100,
+ kTSA0BWestTurnRight = 101,
+ kTSA0BTBPTheoryHighlight = 102,
+ kTSA0BTBPBackgroundHighlight = 103,
+ kTSA0BTBPProcedureHighlight = 104,
+ kTSA0BTBPTheory = 105,
+ kTSA0BTBPBackground = 106,
+ kTSA0BTBPProcedure = 107,
+ kTSA0BRipAlarmScreen = 108,
+ kTSA22RedEastZoomInSequence = 109,
+ kTSA22RedEastVaultViewWithKey = 110,
+ kTSA22RedEastVaultViewNoKey = 111,
+ kTSA23RedWestVaultZoomInSequence = 112,
+ kTSA23RedWestVaultViewWithChips = 113,
+ kTSA23RedWestVaultViewNoChips = 114,
+ kTSA25NorthDeniedNoKey = 115,
+ kTSA25NorthDeniedNoChip = 116,
+ kTSA25NorthPutOnSuit = 117,
+ kTSA25NorthAlreadyHaveSuit = 118,
+ kTSA25NorthDescending1 = 119,
+ kTSA25NorthDescending2 = 120,
+ kTSA37HorseToAI1 = 121,
+ kTSA37PegasusAI1 = 122,
+ kTSA37AI1ToCommissioner1 = 123,
+ kTSA37Commissioner1 = 124,
+ kTSA37Commissioner1ToZoom = 125,
+ kTSA37ZoomToPrehistoric = 126,
+ kTSA37PrehistoricToAI2 = 127,
+ kTSA37PegasusAI2 = 128,
+ kTSA37AI2ToPrehistoric = 129,
+ kTSA37PrehistoricToDepart = 130,
+ kTSA37PegasusDepart = 131,
+ kTSA37TimeJumpToPegasus = 132,
+ kTSA37RecallToDownload = 133,
+ kTSA37DownloadToColonel1 = 134,
+ kTSA37Colonel1 = 135,
+ kTSA37Colonel1ToReviewRequired = 136,
+ kTSA37ReviewRequiredToExit = 137,
+ kTSA37ExitHilited = 138,
+ kTSA37ExitToHorse = 139,
+ kTSA37HorseToColonel2 = 140,
+ kTSA37Colonel2 = 141,
+ kTSA37PegasusAI3 = 142,
+ kTSA37AI3ToHorse = 143,
+ kTSA37HorseToZoom = 144,
+ kTSA37ZoomToMainMenu = 145,
+ kTSA37MainMenuToAI4 = 146,
+ kTSA37PegasusAI4 = 147,
+ kTSA37AI4ToMainMenu = 148,
+ kTSA37JumpMenu000 = 149,
+ kTSA37JumpMenu001 = 150,
+ kTSA37JumpMenu010 = 151,
+ kTSA37JumpMenu011 = 152,
+ kTSA37JumpMenu100 = 153,
+ kTSA37JumpMenu101 = 154,
+ kTSA37JumpMenu110 = 155,
+ kTSA37JumpMenu111 = 156,
+ kTSA37JumpToWSCMenu = 157,
+ kTSA37CancelWSC = 158,
+ kTSA37JumpToWSC = 159,
+ kTSA37WSCToAI5 = 160,
+ kTSA37PegasusAI5 = 161,
+ kTSA37AI5ToWSC = 162,
+ kTSA37WSCToDepart = 163,
+ kTSA37JumpToMarsMenu = 164,
+ kTSA37CancelMars = 165,
+ kTSA37JumpToMars = 166,
+ kTSA37MarsToAI6 = 167,
+ kTSA37PegasusAI6 = 168,
+ kTSA37AI6ToMars = 169,
+ kTSA37MarsToDepart = 170,
+ kTSA37JumpToNoradMenu = 171,
+ kTSA37CancelNorad = 172,
+ kTSA37JumpToNorad = 173,
+ kTSA37NoradToAI7 = 174,
+ kTSA37PegasusAI7 = 175,
+ kTSA37AI7ToNorad = 176,
+ kTSA37NoradToDepart = 177,
+ kTSA37EnvironmentalScan = 178,
+ kTSA37DownloadToMainMenu = 179,
+ kTSA37DownloadToOpMemReview = 180,
+ kTSA37OpMemReviewToMainMenu = 181,
+ kTSA37OpMemReviewToAllClear = 182,
+ kTSA37AllClearToCongratulations = 183,
+ kTSA37Congratulations = 184,
+ kTSA37CongratulationsToExit = 185
+};
const DisplayOrder kRipTimerOrder = kMonitorLayer;
+enum {
+ kUnresolvedLeft = kNavAreaLeft + 14,
+ kUnresolvedTop = kNavAreaTop + 236,
-const CoordType kUnresolvedLeft = kNavAreaLeft + 14;
-const CoordType kUnresolvedTop = kNavAreaTop + 236;
-
-const CoordType kResolvedLeft = kNavAreaLeft + 36;
-const CoordType kResolvedTop = kNavAreaTop + 236;
+ kResolvedLeft = kNavAreaLeft + 36,
+ kResolvedTop = kNavAreaTop + 236,
-const CoordType kJumpMenuLeft = kNavAreaLeft + 360;
-const CoordType kJumpMenuTop = kNavAreaTop + 202;
+ kJumpMenuLeft = kNavAreaLeft + 360,
+ kJumpMenuTop = kNavAreaTop + 202,
-const CoordType kJumpMenuHilitedLeft = kNavAreaLeft + 354;
-const CoordType kJumpMenuHilitedTop = kNavAreaTop + 196;
+ kJumpMenuHilitedLeft = kNavAreaLeft + 354,
+ kJumpMenuHilitedTop = kNavAreaTop + 196,
-const CoordType kExitLeft = kNavAreaLeft + 360;
-const CoordType kExitTop = kNavAreaTop + 216;
+ kExitLeft = kNavAreaLeft + 360,
+ kExitTop = kNavAreaTop + 216,
-const CoordType kExitHilitedLeft = kNavAreaLeft + 354;
-const CoordType kExitHilitedTop = kNavAreaTop + 210;
+ kExitHilitedLeft = kNavAreaLeft + 354,
+ kExitHilitedTop = kNavAreaTop + 210,
-const CoordType kRipTimerLeft = kNavAreaLeft + 95;
-const CoordType kRipTimerTop = kNavAreaTop + 87;
+ kRipTimerLeft = kNavAreaLeft + 95,
+ kRipTimerTop = kNavAreaTop + 87,
-const CoordType kTBPCloseLeft = kNavAreaLeft + 30;
-const CoordType kTBPCloseTop = kNavAreaTop + 16;
+ kTBPCloseLeft = kNavAreaLeft + 30,
+ kTBPCloseTop = kNavAreaTop + 16,
-const CoordType kTBPRewindLeft = kNavAreaLeft + 86;
-const CoordType kTBPRewindTop = kNavAreaTop + 218;
+ kTBPRewindLeft = kNavAreaLeft + 86,
+ kTBPRewindTop = kNavAreaTop + 218,
-const CoordType kComparisonCloseLeft = kNavAreaLeft + 50;
-const CoordType kComparisonCloseTop = kNavAreaTop + 14;
+ kComparisonCloseLeft = kNavAreaLeft + 50,
+ kComparisonCloseTop = kNavAreaTop + 14,
-const CoordType kComparisonLeftRewindLeft = kNavAreaLeft + 96;
-const CoordType kComparisonLeftRewindTop = kNavAreaTop + 190;
+ kComparisonLeftRewindLeft = kNavAreaLeft + 96,
+ kComparisonLeftRewindTop = kNavAreaTop + 190,
-const CoordType kComparisonRightRewindLeft = kNavAreaLeft + 282;
-const CoordType kComparisonRightRewindTop = kNavAreaTop + 190;
+ kComparisonRightRewindLeft = kNavAreaLeft + 282,
+ kComparisonRightRewindTop = kNavAreaTop + 190,
-const CoordType kComparisonHiliteSpriteLeft = kNavAreaLeft + 45;
-const CoordType kComparisonHiliteSpriteTop = kNavAreaTop + 65;
+ kComparisonHiliteSpriteLeft = kNavAreaLeft + 45,
+ kComparisonHiliteSpriteTop = kNavAreaTop + 65,
-const CoordType kComparisonHiliteNoradLeft = kNavAreaLeft + 45;
-const CoordType kComparisonHiliteNoradTop = kNavAreaTop + 65;
+ kComparisonHiliteNoradLeft = kNavAreaLeft + 45,
+ kComparisonHiliteNoradTop = kNavAreaTop + 65,
-const CoordType kComparisonHiliteMarsLeft = kNavAreaLeft + 45 + 4;
-const CoordType kComparisonHiliteMarsTop = kNavAreaTop + 65 + 23;
+ kComparisonHiliteMarsLeft = kNavAreaLeft + 45 + 4,
+ kComparisonHiliteMarsTop = kNavAreaTop + 65 + 23,
-const CoordType kComparisonHiliteCaldoriaLeft = kNavAreaLeft + 45 + 7;
-const CoordType kComparisonHiliteCaldoriaTop = kNavAreaTop + 65 + 46;
+ kComparisonHiliteCaldoriaLeft = kNavAreaLeft + 45 + 7,
+ kComparisonHiliteCaldoriaTop = kNavAreaTop + 65 + 46,
-const CoordType kComparisonHiliteWSCLeft = kNavAreaLeft + 45 + 11;
-const CoordType kComparisonHiliteWSCTop = kNavAreaTop + 65 + 68;
+ kComparisonHiliteWSCLeft = kNavAreaLeft + 45 + 11,
+ kComparisonHiliteWSCTop = kNavAreaTop + 65 + 68,
-const CoordType kComparisonChancesSpriteLeft = kNavAreaLeft + 148;
-const CoordType kComparisonChancesSpriteTop = kNavAreaTop + 162;
+ kComparisonChancesSpriteLeft = kNavAreaLeft + 148,
+ kComparisonChancesSpriteTop = kNavAreaTop + 162,
-const CoordType kComparisonChancesNoradLeft = kNavAreaLeft + 148;
-const CoordType kComparisonChancesNoradTop = kNavAreaTop + 162;
+ kComparisonChancesNoradLeft = kNavAreaLeft + 148,
+ kComparisonChancesNoradTop = kNavAreaTop + 162,
-const CoordType kComparisonChancesMarsLeft = kNavAreaLeft + 148;
-const CoordType kComparisonChancesMarsTop = kNavAreaTop + 162;
+ kComparisonChancesMarsLeft = kNavAreaLeft + 148,
+ kComparisonChancesMarsTop = kNavAreaTop + 162,
-const CoordType kComparisonChancesCaldoriaLeft = kNavAreaLeft + 148;
-const CoordType kComparisonChancesCaldoriaTop = kNavAreaTop + 162 + 1;
+ kComparisonChancesCaldoriaLeft = kNavAreaLeft + 148,
+ kComparisonChancesCaldoriaTop = kNavAreaTop + 162 + 1,
-const CoordType kComparisonChancesWSCLeft = kNavAreaLeft + 148;
-const CoordType kComparisonChancesWSCTop = kNavAreaTop + 162;
+ kComparisonChancesWSCLeft = kNavAreaLeft + 148,
+ kComparisonChancesWSCTop = kNavAreaTop + 162,
-const CoordType kRedirectionSprite1Left = kNavAreaLeft + 58;
-const CoordType kRedirectionSprite1Top = kNavAreaTop + 16;
+ kRedirectionSprite1Left = kNavAreaLeft + 58,
+ kRedirectionSprite1Top = kNavAreaTop + 16,
-const CoordType kRedirectionSprite2Left = kNavAreaLeft + 36;
-const CoordType kRedirectionSprite2Top = kNavAreaTop + 166;
+ kRedirectionSprite2Left = kNavAreaLeft + 36,
+ kRedirectionSprite2Top = kNavAreaTop + 166,
-const CoordType kRedirectionCCRolloverLeft = kNavAreaLeft + 58;
-const CoordType kRedirectionCCRolloverTop = kNavAreaTop + 16;
+ kRedirectionCCRolloverLeft = kNavAreaLeft + 58,
+ kRedirectionCCRolloverTop = kNavAreaTop + 16,
-const CoordType kRedirectionRRRolloverLeft = kNavAreaLeft + 430;
-const CoordType kRedirectionRRRolloverTop = kNavAreaTop + 30;
+ kRedirectionRRRolloverLeft = kNavAreaLeft + 430,
+ kRedirectionRRRolloverTop = kNavAreaTop + 30,
-const CoordType kRedirectionFDRolloverLeft = kNavAreaLeft + 278;
-const CoordType kRedirectionFDRolloverTop = kNavAreaTop + 160;
+ kRedirectionFDRolloverLeft = kNavAreaLeft + 278,
+ kRedirectionFDRolloverTop = kNavAreaTop + 160,
-const CoordType kRedirectionCCDoorLeft = kNavAreaLeft + 174;
-const CoordType kRedirectionCCDoorTop = kNavAreaTop + 36;
+ kRedirectionCCDoorLeft = kNavAreaLeft + 174,
+ kRedirectionCCDoorTop = kNavAreaTop + 36,
-const CoordType kRedirectionRRDoorLeft = kNavAreaLeft + 418;
-const CoordType kRedirectionRRDoorTop = kNavAreaTop + 32;
+ kRedirectionRRDoorLeft = kNavAreaLeft + 418,
+ kRedirectionRRDoorTop = kNavAreaTop + 32,
-const CoordType kRedirectionFDDoorLeft = kNavAreaLeft + 298;
-const CoordType kRedirectionFDDoorTop = kNavAreaTop + 240;
+ kRedirectionFDDoorLeft = kNavAreaLeft + 298,
+ kRedirectionFDDoorTop = kNavAreaTop + 240,
-const CoordType kRedirectionSecuredLeft = kNavAreaLeft + 36;
-const CoordType kRedirectionSecuredTop = kNavAreaTop + 166;
+ kRedirectionSecuredLeft = kNavAreaLeft + 36,
+ kRedirectionSecuredTop = kNavAreaTop + 166,
-const CoordType kRedirectionNewTargetLeft = kNavAreaLeft + 36;
-const CoordType kRedirectionNewTargetTop = kNavAreaTop + 166;
+ kRedirectionNewTargetLeft = kNavAreaLeft + 36,
+ kRedirectionNewTargetTop = kNavAreaTop + 166,
-const CoordType kRedirectionCloseLeft = kNavAreaLeft + 56;
-const CoordType kRedirectionCloseTop = kNavAreaTop + 220;
+ kRedirectionCloseLeft = kNavAreaLeft + 56,
+ kRedirectionCloseTop = kNavAreaTop + 220
+};
static const TimeValue kTSABumpIntoWallIn = 0;
static const TimeValue kTSABumpIntoWallOut = 148;
@@ -516,10 +529,12 @@ 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;
+enum {
+ kPegasusUnresolved = false,
+ kPegasusResolved = true,
+ kPegasusCantExit = false,
+ kPegasusCanExit = true
+};
// Monitor modes
enum {
@@ -582,15 +597,17 @@ static const ExtraID s_historicalLogViews[16] = {
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;
+enum {
+ kRedirectionCCRolloverSprite = 0,
+ kRedirectionRRRolloverSprite = 1,
+ kRedirectionFDRolloverSprite = 2,
+ kRedirectionCCDoorSprite = 3,
+ kRedirectionRRDoorSprite = 4,
+ kRedirectionFDDoorSprite = 5,
+ kRedirectionCloseSprite = 6,
+ kRedirectionSecuredSprite = 0,
+ kRedirectionNewTargetSprite = 1
+};
void RipTimer::initImage() {
_middle = -1;
diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
index c808325b0f..0c29e06f41 100644
--- a/engines/pegasus/neighborhood/tsa/tinytsa.cpp
+++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
@@ -38,71 +38,81 @@ namespace Pegasus {
static const int16 kCompassShift = 30;
-static const TimeScale kTinyTSAMovieScale = 600;
-static const TimeScale kTinyTSAFramesPerSecond = 15;
-static const TimeScale kTinyTSAFrameDuration = 40;
+enum {
+ kTinyTSAMovieScale = 600,
+ kTinyTSAFramesPerSecond = 15,
+ kTinyTSAFrameDuration = 40
+};
// Alternate IDs.
-static const AlternateID kAltTinyTSANormal = 0;
+enum {
+ 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;
+enum {
+ kActivationTinyTSAJumpToNorad = 1,
+ kActivationTinyTSAJumpToMars = 2,
+ kActivationTinyTSAJumpToWSC = 3,
+ kActivationTinyTSAReadyForJumpMenu = 4,
+ 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;
+enum {
+ kTinyTSA37NorthJumpToNoradSpotID = 5000,
+ kTinyTSA37NorthCancelNoradSpotID = 5001,
+ kTinyTSA37NorthJumpToMarsSpotID = 5002,
+ kTinyTSA37NorthCancelMarsSpotID = 5003,
+ kTinyTSA37NorthJumpToWSCSpotID = 5004,
+ kTinyTSA37NorthCancelWSCSpotID = 5005,
+ kTinyTSA37NorthJumpMenuSpotID = 5006,
+ kTinyTSA37NorthNoradMenuSpotID = 5007,
+ kTinyTSA37NorthMarsMenuSpotID = 5008,
+ 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;
+enum {
+ kTinyTSA37PegasusDepart = 0,
+ kTinyTSA37TimeJumpToPegasus = 1,
+ kTinyTSA37RecallToDownload = 2,
+ kTinyTSA37ExitHilited = 3,
+ kTinyTSA37ExitToHorse = 4,
+ kTinyTSA37JumpMenu000 = 5,
+ kTinyTSA37JumpMenu001 = 6,
+ kTinyTSA37JumpMenu010 = 7,
+ kTinyTSA37JumpMenu011 = 8,
+ kTinyTSA37JumpMenu100 = 9,
+ kTinyTSA37JumpMenu101 = 10,
+ kTinyTSA37JumpMenu110 = 11,
+ kTinyTSA37JumpMenu111 = 12,
+ kTinyTSA37JumpToWSCMenu = 13,
+ kTinyTSA37CancelWSC = 14,
+ kTinyTSA37JumpToWSC = 15,
+ kTinyTSA37WSCToAI5 = 16,
+ kTinyTSA37PegasusAI5 = 17,
+ kTinyTSA37AI5ToWSC = 18,
+ kTinyTSA37WSCToDepart = 19,
+ kTinyTSA37JumpToMarsMenu = 20,
+ kTinyTSA37CancelMars = 21,
+ kTinyTSA37JumpToMars = 22,
+ kTinyTSA37MarsToAI6 = 23,
+ kTinyTSA37PegasusAI6 = 24,
+ kTinyTSA37AI6ToMars = 25,
+ kTinyTSA37MarsToDepart = 26,
+ kTinyTSA37JumpToNoradMenu = 27,
+ kTinyTSA37CancelNorad = 28,
+ kTinyTSA37JumpToNorad = 29,
+ kTinyTSA37NoradToAI7 = 30,
+ kTinyTSA37PegasusAI7 = 31,
+ kTinyTSA37AI7ToNorad = 32,
+ kTinyTSA37NoradToDepart = 33,
+ kTinyTSA37EnvironmentalScan = 34,
+ kTinyTSA37DownloadToMainMenu = 35,
+ kTinyTSA37DownloadToOpMemReview = 36,
+ kTinyTSA37OpMemReviewToMainMenu = 37
+};
TinyTSA::TinyTSA(InputHandler *nextHandler, PegasusEngine *owner) : Neighborhood(nextHandler, owner, "Tiny TSA", kTinyTSAID) {
}
diff --git a/engines/pegasus/neighborhood/wsc/wsc.cpp b/engines/pegasus/neighborhood/wsc/wsc.cpp
index f009b35cdc..5e35d8ccc1 100644
--- a/engines/pegasus/neighborhood/wsc/wsc.cpp
+++ b/engines/pegasus/neighborhood/wsc/wsc.cpp
@@ -87,81 +87,85 @@ 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;
+enum {
+ kWSCMolecule1In = 0,
+ kWSCMolecule1Out = 937,
-static const TimeValue kWSCMolecule2In = 937;
-static const TimeValue kWSCMolecule2Out = 1864;
+ kWSCMolecule2In = 937,
+ kWSCMolecule2Out = 1864,
-static const TimeValue kWSCMolecule3In = 1864;
-static const TimeValue kWSCMolecule3Out = 2790;
+ kWSCMolecule3In = 1864,
+ kWSCMolecule3Out = 2790,
-static const TimeValue kWSCClick1In = 2790;
-static const TimeValue kWSCClick1Out = 2890;
+ kWSCClick1In = 2790,
+ kWSCClick1Out = 2890,
-static const TimeValue kWSCClick2In = 2890;
-static const TimeValue kWSCClick2Out = 3059;
+ kWSCClick2In = 2890,
+ kWSCClick2Out = 3059,
-static const TimeValue kWSCClick3In = 3059;
-static const TimeValue kWSCClick3Out = 3156;
+ kWSCClick3In = 3059,
+ kWSCClick3Out = 3156,
-static const TimeValue kWSCFlashlightClickIn = 3156;
-static const TimeValue kWSCFlashlightClickOut = 3211;
+ kWSCFlashlightClickIn = 3156,
+ kWSCFlashlightClickOut = 3211,
-static const TimeValue kWSCBumpIntoWallIn = 3211;
-static const TimeValue kWSCBumpIntoWallOut = 3514;
+ kWSCBumpIntoWallIn = 3211,
+ kWSCBumpIntoWallOut = 3514,
-static const TimeValue kWSCCantTransportIn = 3514;
-static const TimeValue kWSCCantTransportOut = 7791;
+ kWSCCantTransportIn = 3514,
+ kWSCCantTransportOut = 7791,
-static const TimeValue kHernandezNotHomeIn = 7791;
-static const TimeValue kHernandezNotHomeOut = 10199;
+ kHernandezNotHomeIn = 7791,
+ kHernandezNotHomeOut = 10199,
-static const TimeValue kWashingtonNotHomeIn = 10199;
-static const TimeValue kWashingtonNotHomeOut = 12649;
+ kWashingtonNotHomeIn = 10199,
+ kWashingtonNotHomeOut = 12649,
-static const TimeValue kSullivanNotHomeIn = 12649;
-static const TimeValue kSullivanNotHomeOut = 15031;
+ kSullivanNotHomeIn = 12649,
+ kSullivanNotHomeOut = 15031,
-static const TimeValue kNakamuraNotHomeIn = 15031;
-static const TimeValue kNakamuraNotHomeOut = 17545;
+ kNakamuraNotHomeIn = 15031,
+ kNakamuraNotHomeOut = 17545,
-static const TimeValue kGrailisNotHomeIn = 17545;
-static const TimeValue kGrailisNotHomeOut = 19937;
+ kGrailisNotHomeIn = 17545,
+ kGrailisNotHomeOut = 19937,
-static const TimeValue kTheriaultNotHomeIn = 19937;
-static const TimeValue kTheriaultNotHomeOut = 22395;
+ kTheriaultNotHomeIn = 19937,
+ kTheriaultNotHomeOut = 22395,
-static const TimeValue kGlennerNotHomeIn = 22395;
-static const TimeValue kGlennerNotHomeOut = 24770;
+ kGlennerNotHomeIn = 22395,
+ kGlennerNotHomeOut = 24770,
-static const TimeValue kSinclairNotHomeIn = 24770;
-static const TimeValue kSinclairNotHomeOut = 27328;
+ kSinclairNotHomeIn = 24770,
+ kSinclairNotHomeOut = 27328,
-static const TimeValue kWSCLabClosedIn = 27328;
-static const TimeValue kWSCLabClosedOut = 28904;
+ kWSCLabClosedIn = 27328,
+ kWSCLabClosedOut = 28904,
-static const TimeValue kSlidingDoorCloseIn = 28904;
-static const TimeValue kSlidingDoorCloseOut = 29295;
+ kSlidingDoorCloseIn = 28904,
+ kSlidingDoorCloseOut = 29295,
-static const TimeValue kSlimyDoorCloseIn = 29295;
-static const TimeValue kSlimyDoorCloseOut = 29788;
+ kSlimyDoorCloseIn = 29295,
+ kSlimyDoorCloseOut = 29788,
-static const TimeValue kPaging1In = 29788;
-static const TimeValue kPaging1Out = 32501;
+ kPaging1In = 29788,
+ kPaging1Out = 32501,
-static const TimeValue kPaging2In = 32501;
-static const TimeValue kPaging2Out = 34892;
+ kPaging2In = 32501,
+ kPaging2Out = 34892,
-static const TimeValue kCheckInIn = 34892;
-static const TimeValue kCheckInOut = 37789;
+ kCheckInIn = 34892,
+ kCheckInOut = 37789,
-static const TimeValue kDrinkAntidoteIn = 37789;
-static const TimeValue kDrinkAntidoteOut = 39725;
+ kDrinkAntidoteIn = 37789,
+ kDrinkAntidoteOut = 39725
+};
-static const TimeScale kWSCMovieScale = 600;
-static const TimeScale kWSCFramesPerSecond = 15;
-static const TimeScale kWSCFrameDuration = 40;
+enum {
+ kWSCMovieScale = 600,
+ kWSCFramesPerSecond = 15,
+ kWSCFrameDuration = 40
+};
// Alternate IDs.
static const AlternateID kAltWSCNormal = 0;
@@ -170,304 +174,312 @@ 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;
+enum {
+ kWSC02 = 1,
+ kWSC03 = 4,
+ kWSC04 = 5,
+ kWSC06 = 6,
+ kWSC07 = 7,
+ kWSC08 = 8,
+ kWSC09 = 9,
+ kWSC10 = 10,
+ kWSC11 = 11,
+ kWSC13 = 12,
+ kWSC14 = 13,
+ kWSC15 = 14,
+ kWSC16 = 15,
+ kWSC17 = 16,
+ kWSC18 = 17,
+ kWSC19 = 18,
+ kWSC20 = 19,
+ kWSC21 = 20,
+ kWSC22 = 21,
+ kWSC23 = 22,
+ kWSC24 = 23,
+ kWSC25 = 24,
+ kWSC26 = 25,
+ kWSC27 = 26,
+ kWSC28 = 27,
+ kWSC29 = 28,
+ kWSC31 = 29,
+ kWSC32 = 30,
+ kWSC33 = 31,
+ kWSC34 = 32,
+ kWSC35 = 33,
+ kWSC36 = 34,
+ kWSC37 = 35,
+ kWSC38 = 36,
+ kWSC39 = 37,
+ kWSC40 = 38,
+ kWSC41 = 39,
+ kWSC42 = 40,
+ kWSC43 = 41,
+ kWSC44 = 42,
+ kWSC45 = 43,
+ kWSC46 = 44,
+ kWSC47 = 45,
+ kWSC48 = 46,
+ kWSC49 = 47,
+ kWSC50 = 48,
+ kWSC52 = 49,
+ kWSC53 = 50,
+ kWSC54 = 51,
+ kWSC55 = 52,
+ kWSC56 = 53,
+ kWSC57 = 54,
+ kWSC58 = 55,
+ kWSC60 = 56,
+ kWSC60East = 57,
+ kWSC60North = 58,
+ kWSC61 = 59,
+ kWSC61South = 60,
+ kWSC61West = 61,
+ kWSC63 = 63,
+ kWSC64 = 64,
+ kWSC65 = 65,
+ kWSC65Screen = 66,
+ kWSC66 = 67,
+ kWSC67 = 68,
+ kWSC68 = 69,
+ kWSC69 = 70,
+ kWSC70 = 71,
+ kWSC71 = 72,
+ kWSC72 = 73,
+ kWSC73 = 74,
+ kWSC74 = 75,
+ kWSC75 = 76,
+ kWSC0Z = 77,
+ kWSC76 = 78,
+ kWSC77 = 79,
+ kWSC78 = 80,
+ kWSC79 = 81,
+ kWSC80 = 82,
+ kWSC81 = 83,
+ kWSC82 = 84,
+ kWSC83 = 85,
+ kWSC84 = 86,
+ kWSC85 = 87,
+ kWSC86 = 88,
+ kWSC87 = 89,
+ kWSC88 = 90,
+ kWSC89 = 91,
+ kWSC90 = 92,
+ kWSC91 = 93,
+ kWSC92 = 94,
+ kWSC93 = 95,
+ kWSC94 = 96,
+ kWSC95 = 97,
+ kWSC96 = 98,
+ kWSC97 = 99,
+ kWSC98 = 100,
+ 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;
+enum {
+ kActivationZoomedInToAnalyzer = 1,
+ kActivationShotByRobot = 2,
+ kActivationWarnedAboutPoison = 3,
+ kActivationMorphScreenOff = 4,
+ kActivationReadyForMorph = 5,
+ kActivationMorphLooping = 6,
+ kActivationMorphInterrupted = 7,
+ kActivationW03NorthOff = 8,
+ kActivationW03NorthReadyForInstructions = 9,
+ kActivationW03NorthSawInstructions = 10,
+ kActivationW03NorthInGame = 11,
+ kActivationReadyForSynthesis = 12,
+ kActivationSynthesizerLooping = 13,
+ kActivationReadyForMap = 14,
+ kActivationSinclairOfficeLocked = 15,
+ kActivationW58SouthDoorLocked = 16,
+ kActivationW61SouthOff = 17,
+ kActivationW61SouthOn = 18,
+ kActivationW61MessagesOff = 19,
+ kActivationW61MessagesOn = 20,
+ kActivationWSCRobotHeadOpen = 21,
+ kActivationRobotTurning = 22,
+ kActivationRobotDead = 23,
+ 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;
+enum {
+ kWSCDropDartSpotID = 5000,
+ kWSCTurnOnAnalyzerSpotID = 5001,
+ kWSCAnalyzerScreenSpotID = 5002,
+ kWSCSpinRobotSpotID = 5003,
+ kWSC01YesSpotID = 5004,
+ kWSC01NoSpotID = 5005,
+ kWSC01AcknowledgeWarningSpotID = 5006,
+ kWSC02SouthMorphSpotID = 5007,
+ kWSC02SouthMessagesSpotID = 5008,
+ kWSC02SouthMorphOutSpotID = 5009,
+ kWSC02ActivateMorphScreenSpotID = 5010,
+ kWSC02SouthStartMorphSpotID = 5011,
+ kWSC02SouthInterruptMorphSpotID = 5012,
+ kWSC02SouthMorphFinishedSpotID = 5013,
+ kWSC02SouthTakeArgonSpotID = 5014,
+ kWSC02SouthMessagesOutSpotID = 5015,
+ kWSC02SouthTakeNitrogenSpotID = 5016,
+ kWSC02SouthPlayMessagesSpotID = 5017,
+ kWSC03NorthActivateScreenSpotID = 5018,
+ kWSC03NorthBuildMoleculeSpotID = 5019,
+ kWSC03NorthProceedSpotID = 5020,
+ kWSC03NorthMolecule1SpotID = 5021,
+ kWSC03NorthMolecule2SpotID = 5022,
+ kWSC03NorthMolecule3SpotID = 5023,
+ kWSC03NorthMolecule4SpotID = 5024,
+ kWSC03NorthMolecule5SpotID = 5025,
+ kWSC03NorthMolecule6SpotID = 5026,
+ kWSC03SouthActivateSynthesizerSpotID = 5027,
+ kWSC03SouthPickUpAntidoteSpotID = 5028,
+ kWSC07SouthMapSpotID = 5029,
+ kW42EastUnlockDoorSpotID = 5030,
+ kW56NorthMapSpotID = 5031,
+ kW58SouthPryDoorSpotID = 5032,
+ kWSC60EastSpotID = 5033,
+ kWSC60NorthSpotID = 5034,
+ kWSC60EastOutSpotID = 5035,
+ kWSC60NorthOutSpotID = 5036,
+ kWSC61EastSpotID = 5037,
+ kWSC61SouthSpotID = 5038,
+ kW61SouthMachineGunSpotID = 5039,
+ kW61SouthDropMachineGunSpotID = 5040,
+ kWSC61WestSpotID = 5041,
+ kWSC61SouthOutSpotID = 5042,
+ kW61SouthActivateSpotID = 5043,
+ kW61SmartAlloysSpotID = 5044,
+ kW61MorphingSpotID = 5045,
+ kW61TimeBendingSpotID = 5046,
+ kWSC61WestOutSpotID = 5047,
+ kW61TurnOnMessagesSpotID = 5048,
+ kW61WhiteMessageSpotID = 5049,
+ kW61WalchekMessageSpotID = 5050,
+ kWSC65SouthScreenSpotID = 5051,
+ kWSC65SouthScreenOutSpotID = 5052,
+ kW98RetinalChipSpotID = 5053,
+ kW98MapChipSpotID = 5054,
+ kW98OpticalChipSpotID = 5055,
+ kW98DropArgonSpotID = 5056,
+ kW98GrabCableSpotID = 5057,
+ kW98OpenRobotSpotID = 5058,
+ 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;
+enum {
+ kWSCArrivalFromTSA = 0,
+ kWSCShotByRobot = 1,
+ kWSCDartScan1 = 2,
+ kWSCDartScan2 = 3,
+ kWSCDartScanNo = 4,
+ kWSCDartScan3 = 5,
+ kWSCAnalyzerPowerUp = 6,
+ kWSCAnalyzerPowerUpWithDart = 7,
+ kWSCDropDartIntoAnalyzer = 8,
+ kWSCAnalyzeDart = 9,
+ kWSCZoomOutFromAnalyzer = 10,
+ kWSCSpinRobot = 11,
+ kWSC02MorphZoomNoArgon = 12,
+ kWSC02MessagesZoomNoNitrogen = 13,
+ kWSC02ZoomOutNoArgon = 14,
+ kWSC02TurnOnMorphScreen = 15,
+ kWSC02DropToMorphExperiment = 16,
+ kWSC02MorphLoop = 17,
+ kWSC02MorphInterruption = 18,
+ kWSC02MorphFinished = 19,
+ kWSC02TurnOffMorphScreen = 20,
+ kWSC02SouthViewNoArgon = 21,
+ kMessagesMovedToOffice = 22,
+ kMessagesOff = 23,
+ kMessagesZoomOutNoNitrogen = 24,
+ kMessagesMovedToOfficeNoNitrogen = 25,
+ kMessagesOffNoNitrogen = 26,
+ kMessagesViewNoNitrogen = 27,
+ kMessagesViewMachineOnNoNitrogen = 28,
+ kW03NorthActivate = 29,
+ kW03NorthGetData = 30,
+ kW03NorthInstructions = 31,
+ kW03NorthPrepMolecule1 = 32,
+ kW03NorthPrepMolecule2 = 33,
+ kW03NorthPrepMolecule3 = 34,
+ kW03NorthFinishSynthesis = 35,
+ kW03SouthCreateAntidote = 36,
+ kW03SouthAntidoteLoop = 37,
+ kW03SouthDeactivate = 38,
+ kW03SouthViewNoAntidote = 39,
+ kWSC07SouthMap = 40,
+ kW17WestPeopleCrossing = 41,
+ kW17WestPeopleCrossingView = 42,
+ kW21SouthPeopleCrossing = 43,
+ kW24SouthPeopleCrossing = 44,
+ kW34EastPeopleCrossing = 45,
+ kW36WestPeopleCrossing = 46,
+ kW38NorthPeopleCrossing = 47,
+ kW46SouthPeopleCrossing = 48,
+ kW49NorthPeopleCrossing = 49,
+ kW49NorthPeopleCrossingView = 50,
+ kWSC56SouthMap = 51,
+ kNerdAtTheDoor1 = 52,
+ kNerdAtTheDoor2 = 53,
+ kW61SouthZoomInNoGun = 54,
+ kW61Brochure = 55,
+ kW61SouthScreenOnWithGun = 56,
+ kW61SouthScreenOffWithGun = 57,
+ kW61SouthSmartAlloysWithGun = 58,
+ kW61SouthMorphingWithGun = 59,
+ kW61SouthTimeBendingWithGun = 60,
+ kW61SouthZoomOutNoGun = 61,
+ kW61SouthScreenOnNoGun = 62,
+ kW61SouthScreenOffNoGun = 63,
+ kW61SouthSmartAlloysNoGun = 64,
+ kW61SouthMorphingNoGun = 65,
+ kW61SouthTimeBendingNoGun = 66,
+ kW61MessagesOn = 67,
+ kW61MessagesOff = 68,
+ kW61WhiteMessage = 69,
+ kW61WalchekMessage = 70,
+ kW61WalchekEasterEgg1 = 71,
+ kW62SouthPlasmaRobotAppears = 72,
+ kW62ZoomToRobot = 73,
+ kW62ZoomOutFromRobot = 74,
+ kW62PlasmaDodgeSurvive = 75,
+ kW62PlasmaDodgeDie = 76,
+ kW65SouthSinclairLecture = 77,
+ kW73WestPeopleCrossing = 78,
+ kW73WestPeopleCrossingView = 79,
+ kW0ZSpottedByWomen = 80,
+ kW95RobotShoots = 81,
+ kW98MorphsToRobot = 82,
+ kW98RobotShoots = 83,
+ kW98RobotShocked = 84,
+ kW98RobotGassed = 85,
+ kW98RobotHeadOpensDark = 86,
+ kW98RobotHead000Dark = 87,
+ kW98RobotHead001Dark = 88,
+ kW98RobotHead010Dark = 89,
+ kW98RobotHead011Dark = 90,
+ kW98RobotHead100Dark = 91,
+ kW98RobotHead101Dark = 92,
+ kW98RobotHead110Dark = 93,
+ kW98RobotHead111Dark = 94,
+ kW98RobotHeadClosesDark = 95,
+ kW98WestViewWithGunDark = 96,
+ kW98WestViewNoGunDark = 97,
+ kW98RobotHeadOpensLight = 98,
+ kW98RobotHead000Light = 99,
+ kW98RobotHead001Light = 100,
+ kW98RobotHead010Light = 101,
+ kW98RobotHead011Light = 102,
+ kW98RobotHead100Light = 103,
+ kW98RobotHead101Light = 104,
+ kW98RobotHead110Light = 105,
+ kW98RobotHead111Light = 106,
+ kW98RobotHeadClosesLight = 107,
+ kW98WestViewWithGunLight = 108,
+ kW98WestViewNoGunLight = 109
+};
static const CoordType kMoleculesMovieLeft = kNavAreaLeft + 112;
static const CoordType kMoleculesMovieTop = kNavAreaTop + 40;
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index a0ec12a7c4..0c8ea2e4ee 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -307,6 +307,7 @@ void PegasusEngine::runIntro() {
Video::VideoDecoder *video = new Video::QuickTimeDecoder();
if (video->loadFile(_introDirectory + "/BandaiLogo.movie")) {
+ video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF));
video->start();
while (!shouldQuit() && !video->endOfVideo() && !skipped) {
@@ -338,6 +339,8 @@ void PegasusEngine::runIntro() {
if (!video->loadFile(_introDirectory + "/Big Movie.movie"))
error("Could not load intro movie");
+ video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF));
+
video->seek(Audio::Timestamp(0, 10 * 600, 600));
video->start();
@@ -794,6 +797,8 @@ void PegasusEngine::introTimerExpired() {
if (!video->loadFile(_introDirectory + "/LilMovie.movie"))
error("Failed to load little movie");
+ video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF));
+
bool saveAllowed = swapSaveAllowed(false);
bool openAllowed = swapLoadAllowed(false);
@@ -941,6 +946,8 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) {
if (!video->loadFile(_introDirectory + "/Closing.movie"))
error("Could not load closing movie");
+ video->setVolume(MIN<uint>(getSoundFXLevel(), 0xFF));
+
uint16 x = (640 - video->getWidth() * 2) / 2;
uint16 y = (480 - video->getHeight() * 2) / 2;
@@ -2507,7 +2514,7 @@ void PegasusEngine::initKeymap() {
{ Common::KEYCODE_t, "TMA", _("Toggle Center Data Display") },
{ Common::KEYCODE_i, "TIN", _("Display/Hide Info Screen") },
{ Common::KEYCODE_ESCAPE, "PM", _("Display/Hide Pause Menu") },
- { Common::KEYCODE_e, "WTF", _("???") } // easter egg key (without being completely upfront about it)
+ { Common::KEYCODE_e, "WTF", "???" } // easter egg key (without being completely upfront about it)
};
for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
diff --git a/engines/queen/POTFILES b/engines/queen/POTFILES
index 1baf9c24de..28624662ca 100644
--- a/engines/queen/POTFILES
+++ b/engines/queen/POTFILES
@@ -1 +1 @@
-engines/queen/queen.cpp
+engines/queen/detection.cpp
diff --git a/engines/queen/debug.cpp b/engines/queen/debug.cpp
index 3706806ac2..125ddf30c6 100644
--- a/engines/queen/debug.cpp
+++ b/engines/queen/debug.cpp
@@ -36,15 +36,15 @@ namespace Queen {
Debugger::Debugger(QueenEngine *vm)
: _vm(vm), _flags(0) {
- DCmd_Register("areas", WRAP_METHOD(Debugger, Cmd_Areas));
- DCmd_Register("asm", WRAP_METHOD(Debugger, Cmd_Asm));
- DCmd_Register("bob", WRAP_METHOD(Debugger, Cmd_Bob));
- DCmd_Register("bobs", WRAP_METHOD(Debugger, Cmd_PrintBobs));
- DCmd_Register("gs", WRAP_METHOD(Debugger, Cmd_GameState));
- DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info));
- DCmd_Register("items", WRAP_METHOD(Debugger, Cmd_Items));
- DCmd_Register("room", WRAP_METHOD(Debugger, Cmd_Room));
- DCmd_Register("song", WRAP_METHOD(Debugger, Cmd_Song));
+ registerCmd("areas", WRAP_METHOD(Debugger, Cmd_Areas));
+ registerCmd("asm", WRAP_METHOD(Debugger, Cmd_Asm));
+ registerCmd("bob", WRAP_METHOD(Debugger, Cmd_Bob));
+ registerCmd("bobs", WRAP_METHOD(Debugger, Cmd_PrintBobs));
+ registerCmd("gs", WRAP_METHOD(Debugger, Cmd_GameState));
+ registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info));
+ registerCmd("items", WRAP_METHOD(Debugger, Cmd_Items));
+ registerCmd("room", WRAP_METHOD(Debugger, Cmd_Room));
+ registerCmd("song", WRAP_METHOD(Debugger, Cmd_Song));
}
Debugger::~Debugger() {} // we need this here for __SYMBIAN32__
@@ -73,14 +73,14 @@ bool Debugger::Cmd_Asm(int argc, const char **argv) {
_vm->logic()->executeSpecialMove(sm);
return false;
} else {
- DebugPrintf("Usage: %s smnum\n", argv[0]);
+ debugPrintf("Usage: %s smnum\n", argv[0]);
}
return true;
}
bool Debugger::Cmd_Areas(int argc, const char **argv) {
_flags ^= DF_DRAW_AREAS;
- DebugPrintf("Room areas display %s\n", (_flags & DF_DRAW_AREAS) != 0 ? "on" : "off");
+ debugPrintf("Room areas display %s\n", (_flags & DF_DRAW_AREAS) != 0 ? "on" : "off");
return true;
}
@@ -88,36 +88,36 @@ bool Debugger::Cmd_Bob(int argc, const char **argv) {
if (argc >= 3 && isNumeric(argv[1])) {
int bobNum = atoi(argv[1]);
if (bobNum >= Graphics::MAX_BOBS_NUMBER) {
- DebugPrintf("Bob %d is out of range (range: 0 - %d)\n", bobNum, Graphics::MAX_BOBS_NUMBER);
+ debugPrintf("Bob %d is out of range (range: 0 - %d)\n", bobNum, Graphics::MAX_BOBS_NUMBER);
} else {
int param = 0;
if (argc > 3 && isNumeric(argv[3])) {
param = atoi(argv[3]);
} else {
- DebugPrintf("Invalid parameter for bob command '%s'\n", argv[2]);
+ debugPrintf("Invalid parameter for bob command '%s'\n", argv[2]);
}
BobSlot *bob = _vm->graphics()->bob(bobNum);
if (!strcmp(argv[2], "toggle")) {
bob->active = !bob->active;
- DebugPrintf("bob[%d].active = %d\n", bobNum, bob->active);
+ debugPrintf("bob[%d].active = %d\n", bobNum, bob->active);
} else if (!strcmp(argv[2], "x")) {
bob->x = param;
- DebugPrintf("bob[%d].x = %d\n", bobNum, bob->x);
+ debugPrintf("bob[%d].x = %d\n", bobNum, bob->x);
} else if (!strcmp(argv[2], "y")) {
bob->y = param;
- DebugPrintf("bob[%d].y = %d\n", bobNum, bob->y);
+ debugPrintf("bob[%d].y = %d\n", bobNum, bob->y);
} else if (!strcmp(argv[2], "frame")) {
bob->frameNum = param;
- DebugPrintf("bob[%d].frameNum = %d\n", bobNum, bob->frameNum);
+ debugPrintf("bob[%d].frameNum = %d\n", bobNum, bob->frameNum);
} else if (!strcmp(argv[2], "speed")) {
bob->speed = param;
- DebugPrintf("bob[%d].speed = %d\n", bobNum, bob->speed);
+ debugPrintf("bob[%d].speed = %d\n", bobNum, bob->speed);
} else {
- DebugPrintf("Unknown bob command '%s'\n", argv[2]);
+ debugPrintf("Unknown bob command '%s'\n", argv[2]);
}
}
} else {
- DebugPrintf("Usage: %s bobnum command parameter\n", argv[0]);
+ debugPrintf("Usage: %s bobnum command parameter\n", argv[0]);
}
return true;
}
@@ -126,26 +126,26 @@ bool Debugger::Cmd_GameState(int argc, const char **argv) {
uint16 slot;
if ((argc == 2 || argc == 3) && isNumeric(argv[1])) {
slot = atoi(argv[1]);
- DebugPrintf("GAMESTATE[%d] ", slot);
- DebugPrintf("%s %d\n", (argc == 2) ? "is" : "was", _vm->logic()->gameState(slot));
+ debugPrintf("GAMESTATE[%d] ", slot);
+ debugPrintf("%s %d\n", (argc == 2) ? "is" : "was", _vm->logic()->gameState(slot));
if (argc == 3) {
if (isNumeric(argv[1])) {
_vm->logic()->gameState(slot, atoi(argv[2]));
- DebugPrintf("now %d\n", _vm->logic()->gameState(slot));
+ debugPrintf("now %d\n", _vm->logic()->gameState(slot));
} else {
- DebugPrintf("Usage: %s slotnum <value>\n", argv[0]);
+ debugPrintf("Usage: %s slotnum <value>\n", argv[0]);
}
}
} else {
- DebugPrintf("Usage: %s slotnum <value>\n", argv[0]);
+ debugPrintf("Usage: %s slotnum <value>\n", argv[0]);
}
return true;
}
bool Debugger::Cmd_Info(int argc, const char **argv) {
- DebugPrintf("Version: %s\n", _vm->resource()->getJASVersion());
- DebugPrintf("Audio compression: %d\n", _vm->resource()->getCompression());
+ debugPrintf("Version: %s\n", _vm->resource()->getJASVersion());
+ debugPrintf("Audio compression: %d\n", _vm->resource()->getCompression());
return true;
}
@@ -156,24 +156,24 @@ bool Debugger::Cmd_Items(int argc, const char **argv) {
item->name = ABS(item->name);
++item;
}
- DebugPrintf("Enabled all inventory items\n");
+ debugPrintf("Enabled all inventory items\n");
return true;
}
bool Debugger::Cmd_PrintBobs(int argc, const char**argv) {
int i;
BobSlot *bob = _vm->graphics()->bob(0);
- DebugPrintf("+------------------------------------+\n");
- DebugPrintf("|# | x| y|f|scl|frm|a|m|spd| ex| ey|\n");
- DebugPrintf("+--+---+---+-+---+---+-+-+---+---+---+\n");
+ debugPrintf("+------------------------------------+\n");
+ debugPrintf("|# | x| y|f|scl|frm|a|m|spd| ex| ey|\n");
+ debugPrintf("+--+---+---+-+---+---+-+-+---+---+---+\n");
for (i = 0; i < Graphics::MAX_BOBS_NUMBER; ++i, ++bob) {
if (bob->active) {
- DebugPrintf("|%2d|%3d|%3d|%1d|%3d|%3d|%1d|%1d|%3d|%3d|%3d|\n",
+ debugPrintf("|%2d|%3d|%3d|%1d|%3d|%3d|%1d|%1d|%3d|%3d|%3d|\n",
i, bob->x, bob->y, bob->xflip, bob->scale, bob->frameNum,
bob->animating, bob->moving, bob->speed, bob->endx, bob->endy);
}
}
- DebugPrintf("+--------------------------------+\n");
+ debugPrintf("+--------------------------------+\n");
return true;
}
@@ -185,7 +185,7 @@ bool Debugger::Cmd_Room(int argc, const char **argv) {
_vm->logic()->entryObj(_vm->logic()->roomData(roomNum) + 1);
return false;
} else {
- DebugPrintf("Current room: %d (%s), use '%s <roomnum>' to switch\n",
+ debugPrintf("Current room: %d (%s), use '%s <roomnum>' to switch\n",
_vm->logic()->currentRoom(),
_vm->logic()->roomName(_vm->logic()->currentRoom()),
argv[0]);
@@ -197,9 +197,9 @@ bool Debugger::Cmd_Song(int argc, const char **argv) {
if (argc == 2 && isNumeric(argv[1])) {
int16 songNum = atoi(argv[1]);
_vm->sound()->playSong(songNum);
- DebugPrintf("Playing song %d\n", songNum);
+ debugPrintf("Playing song %d\n", songNum);
} else {
- DebugPrintf("Usage: %s songnum\n", argv[0]);
+ debugPrintf("Usage: %s songnum\n", argv[0]);
}
return true;
}
diff --git a/engines/saga/actor_walk.cpp b/engines/saga/actor_walk.cpp
index a5345261c5..04741da2cd 100644
--- a/engines/saga/actor_walk.cpp
+++ b/engines/saga/actor_walk.cpp
@@ -1378,7 +1378,7 @@ void Actor::cmdActorWalkTo(int argc, const char **argv) {
location.fromScreenPoint(movePoint);
if (!validActorId(actorId)) {
- _vm->_console->DebugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId);
+ _vm->_console->debugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId);
return;
}
diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index 9e0bcf52ad..25119c6407 100644
--- a/engines/saga/animation.cpp
+++ b/engines/saga/animation.cpp
@@ -914,14 +914,14 @@ void Anim::animInfo() {
animCount = getAnimationCount();
- _vm->_console->DebugPrintf("There are %d animations loaded:\n", animCount);
+ _vm->_console->debugPrintf("There are %d animations loaded:\n", animCount);
for (i = 0; i < MAX_ANIMATIONS; i++) {
if (_animations[i] == NULL) {
continue;
}
- _vm->_console->DebugPrintf("%02d: Frames: %u Flags: %u\n", i, _animations[i]->maxFrame, _animations[i]->flags);
+ _vm->_console->debugPrintf("%02d: Frames: %u Flags: %u\n", i, _animations[i]->maxFrame, _animations[i]->flags);
}
}
@@ -929,10 +929,10 @@ void Anim::animInfo() {
void Anim::cutawayInfo() {
uint16 i;
- _vm->_console->DebugPrintf("There are %d cutaways loaded:\n", _cutawayList.size());
+ _vm->_console->debugPrintf("There are %d cutaways loaded:\n", _cutawayList.size());
for (i = 0; i < _cutawayList.size(); i++) {
- _vm->_console->DebugPrintf("%02d: Bg res: %u Anim res: %u Cycles: %u Framerate: %u\n", i,
+ _vm->_console->debugPrintf("%02d: Bg res: %u Anim res: %u Cycles: %u Framerate: %u\n", i,
_cutawayList[i].backgroundResourceId, _cutawayList[i].animResourceId,
_cutawayList[i].cycles, _cutawayList[i].frameRate);
}
diff --git a/engines/saga/console.cpp b/engines/saga/console.cpp
index eab615b33f..8ad7fd5aaa 100644
--- a/engines/saga/console.cpp
+++ b/engines/saga/console.cpp
@@ -25,8 +25,10 @@
#include "saga/saga.h"
#include "saga/actor.h"
#include "saga/animation.h"
+#include "saga/music.h"
#include "saga/scene.h"
#include "saga/script.h"
+#include "saga/sndres.h"
#include "saga/console.h"
@@ -35,15 +37,20 @@ namespace Saga {
Console::Console(SagaEngine *vm) : GUI::Debugger() {
_vm = vm;
- DCmd_Register("continue", WRAP_METHOD(Console, Cmd_Exit));
+ registerCmd("continue", WRAP_METHOD(Console, cmdExit));
// Actor commands
- DCmd_Register("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo));
+ registerCmd("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo));
// Animation commands
- DCmd_Register("anim_info", WRAP_METHOD(Console, cmdAnimInfo));
- DCmd_Register("cutaway_info", WRAP_METHOD(Console, cmdCutawayInfo));
- DCmd_Register("play_cutaway", WRAP_METHOD(Console, cmdPlayCutaway));
+ registerCmd("anim_info", WRAP_METHOD(Console, cmdAnimInfo));
+ registerCmd("cutaway_info", WRAP_METHOD(Console, cmdCutawayInfo));
+ registerCmd("play_cutaway", WRAP_METHOD(Console, cmdPlayCutaway));
+
+ // Sound commands
+ registerCmd("play_music", WRAP_METHOD(Console, cmdPlayMusic));
+ registerCmd("play_sound", WRAP_METHOD(Console, cmdPlaySound));
+ registerCmd("play_voice", WRAP_METHOD(Console, cmdPlayVoice));
// Game stuff
@@ -60,28 +67,28 @@ Console::Console(SagaEngine *vm) : GUI::Debugger() {
#endif
// Scene commands
- DCmd_Register("current_scene", WRAP_METHOD(Console, cmdCurrentScene));
- DCmd_Register("current_chapter", WRAP_METHOD(Console, cmdCurrentChapter));
- DCmd_Register("scene_change", WRAP_METHOD(Console, cmdSceneChange));
- DCmd_Register("chapter_change", WRAP_METHOD(Console, cmdChapterChange));
+ registerCmd("current_scene", WRAP_METHOD(Console, cmdCurrentScene));
+ registerCmd("current_chapter", WRAP_METHOD(Console, cmdCurrentChapter));
+ registerCmd("scene_change", WRAP_METHOD(Console, cmdSceneChange));
+ registerCmd("chapter_change", WRAP_METHOD(Console, cmdChapterChange));
- DCmd_Register("action_map_info", WRAP_METHOD(Console, cmdActionMapInfo));
- DCmd_Register("object_map_info", WRAP_METHOD(Console, cmdObjectMapInfo));
+ registerCmd("action_map_info", WRAP_METHOD(Console, cmdActionMapInfo));
+ registerCmd("object_map_info", WRAP_METHOD(Console, cmdObjectMapInfo));
// Script commands
- DCmd_Register("wake_up_threads", WRAP_METHOD(Console, cmdWakeUpThreads));
+ registerCmd("wake_up_threads", WRAP_METHOD(Console, cmdWakeUpThreads));
// Panel commands
- DCmd_Register("current_panel_mode", WRAP_METHOD(Console, cmdCurrentPanelMode));
- DCmd_Register("set_panel_mode", WRAP_METHOD(Console, cmdSetPanelMode));
+ registerCmd("current_panel_mode", WRAP_METHOD(Console, cmdCurrentPanelMode));
+ registerCmd("set_panel_mode", WRAP_METHOD(Console, cmdSetPanelMode));
// Font commands
- DCmd_Register("set_font_mapping", WRAP_METHOD(Console, cmdSetFontMapping));
+ registerCmd("set_font_mapping", WRAP_METHOD(Console, cmdSetFontMapping));
// Global flags commands
- DCmd_Register("global_flags_info", WRAP_METHOD(Console, cmdGlobalFlagsInfo));
- DCmd_Register("set_global_flag", WRAP_METHOD(Console, cmdSetGlobalFlag));
- DCmd_Register("clear_global_flag", WRAP_METHOD(Console, cmdClearGlobalFlag));
+ registerCmd("global_flags_info", WRAP_METHOD(Console, cmdGlobalFlagsInfo));
+ registerCmd("set_global_flag", WRAP_METHOD(Console, cmdSetGlobalFlag));
+ registerCmd("clear_global_flag", WRAP_METHOD(Console, cmdClearGlobalFlag));
}
Console::~Console() {
@@ -89,7 +96,7 @@ Console::~Console() {
bool Console::cmdActorWalkTo(int argc, const char **argv) {
if (argc != 4)
- DebugPrintf("Usage: %s <Actor id> <lx> <ly>\n", argv[0]);
+ debugPrintf("Usage: %s <Actor id> <lx> <ly>\n", argv[0]);
else
_vm->_actor->cmdActorWalkTo(argc, argv);
return true;
@@ -110,27 +117,66 @@ bool Console::cmdCutawayInfo(int argc, const char **argv) {
bool Console::cmdPlayCutaway(int argc, const char **argv) {
#ifdef ENABLE_IHNM
if (argc != 2)
- DebugPrintf("Usage: %s <Cutaway number>\n", argv[0]);
+ debugPrintf("Usage: %s <Cutaway number>\n", argv[0]);
else
_vm->_anim->playCutaway(atoi(argv[1]), false);
#endif
return true;
}
+bool Console::cmdPlayMusic(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Usage: %s <Music number>\n", argv[0]);
+ } else {
+ if (_vm->getGameId() == GID_ITE)
+ _vm->_music->play(atoi(argv[1]) + 9);
+ else
+ _vm->_music->play(atoi(argv[1]));
+ }
+ return true;
+}
+
+bool Console::cmdPlaySound(int argc, const char **argv) {
+ if (argc != 2)
+ debugPrintf("Usage: %s <Sound number>\n", argv[0]);
+ else
+ _vm->_sndRes->playSound(atoi(argv[1]), 255, false);
+ return true;
+}
+
+bool Console::cmdPlayVoice(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Usage: %s <Voice number> <Voice bank>\n", argv[0]);
+ } else {
+ int voiceBank = 0;
+
+ if (argc == 3) {
+ voiceBank = _vm->_sndRes->getVoiceBank();
+ _vm->_sndRes->setVoiceBank(atoi(argv[2]));
+ }
+
+ _vm->_sndRes->playVoice(atoi(argv[1]));
+
+ if (argc == 3)
+ _vm->_sndRes->setVoiceBank(voiceBank);
+ }
+ return true;
+}
+
bool Console::cmdCurrentScene(int argc, const char **argv) {
- DebugPrintf("Current Scene is: %i, scene resource id: %i\n",
+ debugPrintf("Current Scene is: %i, scene resource id: %i\n",
_vm->_scene->currentSceneNumber(), _vm->_scene->currentSceneResourceId());
return true;
}
bool Console::cmdCurrentChapter(int argc, const char **argv) {
- DebugPrintf("Current Chapter is: %i\n", _vm->_scene->currentChapterNumber());
+ debugPrintf("Current Chapter is: %i\n", _vm->_scene->currentChapterNumber());
return true;
}
bool Console::cmdSceneChange(int argc, const char **argv) {
if (argc != 2)
- DebugPrintf("Usage: %s <Scene number>\n", argv[0]);
+ debugPrintf("Usage: %s <Scene number>\n", argv[0]);
else
_vm->_scene->cmdSceneChange(argc, argv);
return true;
@@ -138,7 +184,7 @@ bool Console::cmdSceneChange(int argc, const char **argv) {
bool Console::cmdChapterChange(int argc, const char **argv) {
if (argc != 3)
- DebugPrintf("Usage: %s <Chapter number> <Scene number>\n", argv[0]);
+ debugPrintf("Usage: %s <Chapter number> <Scene number>\n", argv[0]);
else {
_vm->_scene->setChapterNumber(atoi(argv[2]));
_vm->_scene->cmdSceneChange(argc, argv);
@@ -158,9 +204,9 @@ bool Console::cmdObjectMapInfo(int argc, const char **argv) {
bool Console::cmdWakeUpThreads(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: %s <wait type>\n", argv[0]);
- DebugPrintf("e.g.: 1 for kWaitTypeDelay, 2 for kWaitTypeSpeech, 10 for kWaitTypeWaitFrames");
- DebugPrintf("Refer to saga/script.h for additional types");
+ debugPrintf("Usage: %s <wait type>\n", argv[0]);
+ debugPrintf("e.g.: 1 for kWaitTypeDelay, 2 for kWaitTypeSpeech, 10 for kWaitTypeWaitFrames");
+ debugPrintf("Refer to saga/script.h for additional types");
} else {
_vm->_script->wakeUpThreads(atoi(argv[1]));
}
@@ -168,13 +214,13 @@ bool Console::cmdWakeUpThreads(int argc, const char **argv) {
}
bool Console::cmdCurrentPanelMode(int argc, const char **argv) {
- DebugPrintf("Current Panel Mode is: %i\n", _vm->_interface->getMode());
+ debugPrintf("Current Panel Mode is: %i\n", _vm->_interface->getMode());
return true;
}
bool Console::cmdSetPanelMode(int argc, const char **argv) {
if (argc != 2)
- DebugPrintf("Usage: %s <Panel mode number>\n", argv[0]);
+ debugPrintf("Usage: %s <Panel mode number>\n", argv[0]);
else
_vm->_interface->setMode(atoi(argv[1]));
return true;
@@ -182,8 +228,8 @@ bool Console::cmdSetPanelMode(int argc, const char **argv) {
bool Console::cmdSetFontMapping(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Sets font mapping\nUsage: %s <Font mapping flag>\n", argv[0]);
- DebugPrintf("Mapping flags:\n0 - default game behavior\n1 - force font mapping\n2 - ignore font mapping\n");
+ debugPrintf("Sets font mapping\nUsage: %s <Font mapping flag>\n", argv[0]);
+ debugPrintf("Mapping flags:\n0 - default game behavior\n1 - force font mapping\n2 - ignore font mapping\n");
} else {
_vm->_font->setFontMapping(atoi(argv[1]));
}
@@ -191,7 +237,7 @@ bool Console::cmdSetFontMapping(int argc, const char **argv) {
}
bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) {
- DebugPrintf("Global flags status for IHNM:\n");
+ debugPrintf("Global flags status for IHNM:\n");
// Global flags in IHNM:
// 00: Tested when Gorrister's chapter ends. 0: Gorrister failed, 1: Gorrister won
@@ -232,9 +278,9 @@ bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) {
for (i = 0; i < 32; i += 8) {
for (k = i; k < i + 8; k ++) {
flagStatus = _vm->_globalFlags & (1 << k) ? 1 : 0;
- _vm->_console->DebugPrintf("%02d: %u |", k, flagStatus);
+ _vm->_console->debugPrintf("%02d: %u |", k, flagStatus);
}
- _vm->_console->DebugPrintf("\n");
+ _vm->_console->debugPrintf("\n");
}
return true;
@@ -242,13 +288,13 @@ bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) {
bool Console::cmdSetGlobalFlag(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]);
+ debugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]);
} else {
int flagNumber = atoi(argv[1]);
if (flagNumber >= 0 && flagNumber <= 31) {
_vm->_globalFlags |= (1 << flagNumber);
} else {
- DebugPrintf("Valid flag numbers are 0 - 31\n");
+ debugPrintf("Valid flag numbers are 0 - 31\n");
}
}
return true;
@@ -256,13 +302,13 @@ bool Console::cmdSetGlobalFlag(int argc, const char **argv) {
bool Console::cmdClearGlobalFlag(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]);
+ debugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]);
} else {
int flagNumber = atoi(argv[1]);
if (flagNumber >= 0 && flagNumber <= 31) {
_vm->_globalFlags &= ~(1 << flagNumber);
} else {
- DebugPrintf("Valid flag numbers are 0 - 31\n");
+ debugPrintf("Valid flag numbers are 0 - 31\n");
}
}
return true;
diff --git a/engines/saga/console.h b/engines/saga/console.h
index 625e6f57ad..cec964301c 100644
--- a/engines/saga/console.h
+++ b/engines/saga/console.h
@@ -41,6 +41,10 @@ private:
bool cmdCutawayInfo(int argc, const char **argv);
bool cmdPlayCutaway(int argc, const char **argv);
+ bool cmdPlayMusic(int argc, const char **argv);
+ bool cmdPlaySound(int argc, const char **argv);
+ bool cmdPlayVoice(int argc, const char **argv);
+
bool cmdCurrentScene(int argc, const char **argv);
bool cmdCurrentChapter(int argc, const char **argv);
bool cmdSceneChange(int argc, const char **argv);
diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index 72187a1a13..2f72e7a13c 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -595,6 +595,30 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEPatch_Files,
},
+ // Inherit the earth - Chinese Disk version
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", 8901704},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", 281071},
+ { NULL, 0, NULL, 0}
+ },
+ Common::ZH_CNA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ GID_ITE,
+ GF_ITE_FLOPPY,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITE_GameFonts),
+ ITE_GameFonts,
+ ITEPatch_Files,
+ },
+
// ITE Amiga versions /////////////////////////////////////////////////////////////////////////////////////
// TODO: Add the Amiga versions here (not supported yet)
diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp
index 013b019c9f..b7c3fa4d6e 100644
--- a/engines/saga/events.cpp
+++ b/engines/saga/events.cpp
@@ -583,6 +583,18 @@ EventColumns *Events::chain(EventColumns *eventColumns, const Event &event) {
return eventColumns;
}
+EventColumns *Events::chainMusic(EventColumns *eventColumns, long musicId, bool loop, long time) {
+ Event event;
+
+ event.type = kEvTOneshot;
+ event.code = kMusicEvent;
+ event.param = musicId;
+ event.param2 = loop ? MUSIC_NORMAL : MUSIC_LOOP;
+ event.op = kEventPlay;
+ event.time = time;
+ return chain(eventColumns, event);
+}
+
void Events::initializeEvent(Event &event) {
switch (event.type) {
case kEvTOneshot:
diff --git a/engines/saga/events.h b/engines/saga/events.h
index 6c423abb8c..84a62f5a3a 100644
--- a/engines/saga/events.h
+++ b/engines/saga/events.h
@@ -172,9 +172,18 @@ class Events {
return chain(NULL, event);
}
+ // Schedules a music event in the event list; returns a pointer to the scheduled
+ // event columns suitable for chaining if desired.
+ EventColumns *queueMusic(long musicId, bool loop = false, long time = 0) {
+ return chainMusic(NULL, musicId, loop, time);
+ }
+
// Places a 'event' on the end of an event columns given by 'eventColumns'
EventColumns *chain(EventColumns *eventColumns, const Event &event);
+ // Places a music 'event' on the end of an event columns given by 'eventColumns'
+ EventColumns *chainMusic(EventColumns *eventColumns, long musicId, bool loop = false, long time = 0);
+
private:
int handleContinuous(Event *event);
int handleOneShot(Event *event);
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 680b2274f5..44581f26fc 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -710,6 +710,11 @@ bool Interface::processAscii(Common::KeyState keystate) {
}
void Interface::setStatusText(const char *text, int statusColor) {
+ if (_vm->getGameId() == GID_FTA2 || _vm->getGameId() == GID_DINO) {
+ warning("setStatusText not implemented for SAGA2");
+ return;
+ }
+
if (_vm->getGameId() == GID_IHNM) {
// Don't show the status text for the IHNM chapter selection screens (chapter 8), or
// scene 0 (IHNM demo introduction)
diff --git a/engines/saga/introproc_ite.cpp b/engines/saga/introproc_ite.cpp
index 91b1d3db95..0c1a2ce233 100644
--- a/engines/saga/introproc_ite.cpp
+++ b/engines/saga/introproc_ite.cpp
@@ -28,6 +28,7 @@
#include "saga/animation.h"
#include "saga/events.h"
#include "saga/font.h"
+#include "saga/itedata.h"
#include "saga/sndres.h"
#include "saga/palanim.h"
#include "saga/music.h"
@@ -37,10 +38,15 @@
namespace Saga {
-using Common::UNK_LANG;
-using Common::EN_ANY;
-using Common::DE_DEU;
-using Common::IT_ITA;
+#define INTRO_FRAMETIME 90
+#define INTRO_CAPTION_Y 170
+#define INTRO_DE_CAPTION_Y 160
+#define INTRO_IT_CAPTION_Y 160
+#define INTRO_VOICE_PAD 50
+#define INTRO_VOICE_LETTERLEN 90
+
+#define DISSOLVE_DURATION 3000
+#define LOGO_DISSOLVE_DURATION 1000
// Intro scenes
#define RID_ITE_INTRO_ANIM_SCENE 1538
@@ -54,8 +60,8 @@ using Common::IT_ITA;
#define RID_ITE_FAIRETENT_SCENE 1567
// ITE intro music
-#define MUSIC_1 9
-#define MUSIC_2 10
+#define MUSIC_INTRO 9
+#define MUSIC_TITLE_THEME 10
LoadSceneParams ITE_IntroList[] = {
{RID_ITE_INTRO_ANIM_SCENE, kLoadByResourceId, Scene::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
@@ -98,11 +104,11 @@ int Scene::ITEStartProc() {
return SUCCESS;
}
-EventColumns *Scene::ITEQueueDialogue(EventColumns *eventColumns, int n_dialogues, const IntroDialogue dialogue[]) {
+EventColumns *Scene::queueIntroDialogue(EventColumns *eventColumns, int n_dialogues, const IntroDialogue dialogue[]) {
TextListEntry textEntry;
TextListEntry *entry;
Event event;
- int voice_len;
+ int voiceLength;
int i;
// Queue narrator dialogue list
@@ -132,7 +138,7 @@ EventColumns *Scene::ITEQueueDialogue(EventColumns *eventColumns, int n_dialogue
event.code = kTextEvent;
event.op = kEventDisplay;
event.data = entry;
- event.time = (i == 0) ? 0 : VOICE_PAD;
+ event.time = (i == 0) ? 0 : INTRO_VOICE_PAD;
eventColumns = _vm->_events->chain(eventColumns, event);
}
@@ -146,9 +152,10 @@ EventColumns *Scene::ITEQueueDialogue(EventColumns *eventColumns, int n_dialogue
_vm->_events->chain(eventColumns, event);
}
- voice_len = _vm->_sndRes->getVoiceLength(dialogue[i].i_voice_rn);
- if (voice_len < 0) {
- voice_len = strlen(dialogue[i].i_str) * VOICE_LETTERLEN;
+ voiceLength = _vm->_sndRes->getVoiceLength(dialogue[i].i_voice_rn);
+ if (voiceLength < 0) {
+ // Set a default length if no speech file is present
+ voiceLength = strlen(dialogue[i].i_str) * INTRO_VOICE_LETTERLEN;
}
// Remove text
@@ -156,31 +163,17 @@ EventColumns *Scene::ITEQueueDialogue(EventColumns *eventColumns, int n_dialogue
event.code = kTextEvent;
event.op = kEventRemove;
event.data = entry;
- event.time = voice_len;
+ event.time = voiceLength;
_vm->_events->chain(eventColumns, event);
}
return eventColumns;
}
-enum {
- kCHeader,
- kCText
-};
-
-enum {
- kITEPC = (1 << 0),
- kITEPCCD = (1 << 1),
- kITEMac = (1 << 2),
- kITEWyrmKeep = (1 << 3),
- kITEAny = 0xffff,
- kITENotWyrmKeep = kITEAny & ~kITEWyrmKeep
-};
-
// Queue a page of credits text. The original interpreter did word-wrapping
// automatically. We currently don't.
-EventColumns *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]) {
+EventColumns *Scene::queueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]) {
int game;
Common::Language lang;
bool hasWyrmkeepCredits = (Common::File::exists("credit3n.dlt") || // PC
@@ -192,13 +185,13 @@ EventColumns *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits
lang = _vm->getLanguage();
if (hasWyrmkeepCredits)
- game = kITEWyrmKeep;
+ game = kITECreditsWyrmKeep;
else if (_vm->getPlatform() == Common::kPlatformMacintosh)
- game = kITEMac;
+ game = kITECreditsMac;
else if (_vm->getFeatures() & GF_EXTRA_ITE_CREDITS)
- game = kITEPCCD;
+ game = kITECreditsPCCD;
else
- game = kITEPC;
+ game = kITECreditsPC;
int line_spacing = 0;
int paragraph_spacing;
@@ -209,7 +202,7 @@ EventColumns *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits
int credits_height = 0;
for (i = 0; i < n_credits; i++) {
- if (credits[i].lang != lang && credits[i].lang != UNK_LANG) {
+ if (credits[i].lang != lang && credits[i].lang != Common::UNK_LANG) {
continue;
}
@@ -218,12 +211,12 @@ EventColumns *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits
}
switch (credits[i].type) {
- case kCHeader:
+ case kITECreditsHeader:
font = kKnownFontSmall;
line_spacing = 4;
n_paragraphs++;
break;
- case kCText:
+ case kITECreditsText:
font = kKnownFontMedium;
line_spacing = 2;
break;
@@ -250,7 +243,7 @@ EventColumns *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits
textEntry.point.x = 160;
for (i = 0; i < n_credits; i++) {
- if (credits[i].lang != lang && credits[i].lang != UNK_LANG) {
+ if (credits[i].lang != lang && credits[i].lang != Common::UNK_LANG) {
continue;
}
@@ -259,12 +252,12 @@ EventColumns *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits
}
switch (credits[i].type) {
- case kCHeader:
+ case kITECreditsHeader:
font = kKnownFontSmall;
line_spacing = 4;
y += paragraph_spacing;
break;
- case kCText:
+ case kITECreditsText:
font = kKnownFontMedium;
line_spacing = 2;
break;
@@ -328,7 +321,7 @@ int Scene::ITEIntroAnimProc(int param) {
debug(3, "Intro animation procedure started.");
debug(3, "Linking animation resources...");
- _vm->_anim->setFrameTime(0, ITE_INTRO_FRAMETIME);
+ _vm->_anim->setFrameTime(0, INTRO_FRAMETIME);
// Link this scene's animation resources for continuous
// playback
@@ -355,13 +348,7 @@ int Scene::ITEIntroAnimProc(int param) {
_vm->_events->chain(eventColumns, event);
// Queue intro music playback
- event.type = kEvTOneshot;
- event.code = kMusicEvent;
- event.param = MUSIC_1;
- event.param2 = MUSIC_LOOP;
- event.op = kEventPlay;
- event.time = 0;
- _vm->_events->chain(eventColumns, event);
+ _vm->_events->chainMusic(eventColumns, MUSIC_INTRO, true);
}
break;
case SCENE_END:
@@ -374,14 +361,11 @@ int Scene::ITEIntroAnimProc(int param) {
return 0;
}
-int Scene::SC_ITEIntroCave1Proc(int param, void *refCon) {
- return ((Scene *)refCon)->ITEIntroCave1Proc(param);
-}
-
-// Handles first introductory cave painting scene
-int Scene::ITEIntroCave1Proc(int param) {
+int Scene::ITEIntroCaveCommonProc(int param, int caveScene) {
Event event;
- EventColumns *eventColumns;
+ EventColumns *eventColumns = NULL;
+ const IntroDialogue *dialogue;
+
int lang = 0;
if (_vm->getLanguage() == Common::DE_DEU)
@@ -389,202 +373,62 @@ int Scene::ITEIntroCave1Proc(int param) {
else if (_vm->getLanguage() == Common::IT_ITA)
lang = 2;
- static const IntroDialogue dialogue[][4] = {
- { { // English
- 0, // cave voice 0
- "We see the sky, we see the land, we see the water, "
- "and we wonder: Are we the only ones?"
- },
- {
- 1, // cave voice 1
- "Long before we came to exist, the humans ruled the "
- "Earth."
- },
- {
- 2, // cave voice 2
- "They made marvelous things, and moved whole "
- "mountains."
- },
- {
- 3, // cave voice 3
- "They knew the Secret of Flight, the Secret of "
- "Happiness, and other secrets beyond our imagining."
- } },
- // -----------------------------------------------------
- { { // German
- 0, // cave voice 0
- "Um uns sind der Himmel, das Land und die Seen; und "
- "wir fragen uns - sind wir die einzigen?"
- },
- {
- 1, // cave voice 1
- "Lange vor unserer Zeit herrschten die Menschen "
- "\201ber die Erde."
- },
- {
- 2, // cave voice 2
- "Sie taten wundersame Dinge und versetzten ganze "
- "Berge."
- },
- {
- 3, // cave voice 3
- "Sie kannten das Geheimnis des Fluges, das Geheimnis "
- "der Fr\224hlichkeit und andere Geheimnisse, die "
- "unsere Vorstellungskraft \201bersteigen."
- } },
- // -----------------------------------------------------
- { { // Italian fan translation
- 0, // cave voice 0
- "Guardiamo il cielo, guardiamo la terra, guardiamo "
- "l'acqua, e ci chiediamo: Siamo forse soli?"
- },
- {
- 1, // cave voice 1
- "Molto tempo prima che noi esistessimo, gli Umani "
- "dominavano la terra."
- },
- {
- 2, // cave voice 2
- "Fecero cose meravigliose, e mossero intere "
- "montagne."
- },
- {
- 3, // cave voice 3
- "Conoscevano il Segreto del Volo, il Segreto della "
- "Felicit\205, ed altri segreti oltre ogni nostra "
- "immaginazione."
- } }
- };
-
- int n_dialogues = ARRAYSIZE(dialogue[lang]);
-
- switch (param) {
- case SCENE_BEGIN:
- // Begin palette cycling animation for candles
- event.type = kEvTOneshot;
- event.code = kPalAnimEvent;
- event.op = kEventCycleStart;
- event.time = 0;
- eventColumns = _vm->_events->queue(event);
-
- // Queue narrator dialogue list
- ITEQueueDialogue(eventColumns, n_dialogues, dialogue[lang]);
-
- // End scene after last dialogue over
- event.type = kEvTOneshot;
- event.code = kSceneEvent;
- event.op = kEventEnd;
- event.time = VOICE_PAD;
- _vm->_events->chain(eventColumns, event);
-
+ int n_dialogues = 0;
+
+ switch (caveScene) {
+ case 1:
+ n_dialogues = ARRAYSIZE(introDialogueCave1[lang]);
+ dialogue = introDialogueCave1[lang];
break;
- case SCENE_END:
+ case 2:
+ n_dialogues = ARRAYSIZE(introDialogueCave2[lang]);
+ dialogue = introDialogueCave2[lang];
break;
-
- default:
- warning("Illegal scene procedure parameter");
+ case 3:
+ n_dialogues = ARRAYSIZE(introDialogueCave3[lang]);
+ dialogue = introDialogueCave3[lang];
break;
+ case 4:
+ n_dialogues = ARRAYSIZE(introDialogueCave4[lang]);
+ dialogue = introDialogueCave4[lang];
+ break;
+ default:
+ error("Invalid cave scene");
}
- return 0;
-}
-
-int Scene::SC_ITEIntroCave2Proc(int param, void *refCon) {
- return ((Scene *)refCon)->ITEIntroCave2Proc(param);
-}
-
-// Handles second introductory cave painting scene
-int Scene::ITEIntroCave2Proc(int param) {
- Event event;
- EventColumns *eventColumns;
- int lang = 0;
-
- if (_vm->getLanguage() == Common::DE_DEU)
- lang = 1;
- else if (_vm->getLanguage() == Common::IT_ITA)
- lang = 2;
-
- static const IntroDialogue dialogue[][3] = {
- { { // English
- 4, // cave voice 4
- "The humans also knew the Secret of Life, and they "
- "used it to give us the Four Great Gifts:"
- },
- {
- 5, // cave voice 5
- "Thinking minds, feeling hearts, speaking mouths, and "
- "reaching hands."
- },
- {
- 6, // cave voice 6
- "We are their children."
- } },
- // -----------------------------------------------------
- { { // German
- 4, // cave voice 4
- "Au$erdem kannten die Menschen das Geheimnis des "
- "Lebens. Und sie nutzten es, um uns die vier gro$en "
- "Geschenke zu geben -"
- },
- {
- 5, // cave voice 5
- "den denkenden Geist, das f\201hlende Herz, den "
- "sprechenden Mund und die greifende Hand."
- },
- {
- 6, // cave voice 6
- "Wir sind ihre Kinder."
- } },
- // -----------------------------------------------------
- { { // Italian fan translation
- 4, // cave voice 4
- "Gli Umani conoscevano anche il Segreto della Vita, "
- "e lo usarono per darci i Quattro Grandi Doni:"
-
- },
- {
- 5, // cave voice 5
- "Il pensiero, le emozioni, la parola e la manualit\205."
-
- },
- {
- 6, // cave voice 6
- "Siamo i loro figli."
- } }
- };
-
- int n_dialogues = ARRAYSIZE(dialogue[lang]);
-
switch (param) {
case SCENE_BEGIN:
- // Start 'dissolve' transition to new scene background
- event.type = kEvTContinuous;
- event.code = kTransitionEvent;
- event.op = kEventDissolve;
- event.time = 0;
- event.duration = DISSOLVE_DURATION;
- eventColumns = _vm->_events->queue(event);
+ if (caveScene > 1) {
+ // Start 'dissolve' transition to new scene background
+ event.type = kEvTContinuous;
+ event.code = kTransitionEvent;
+ event.op = kEventDissolve;
+ event.time = 0;
+ event.duration = DISSOLVE_DURATION;
+ eventColumns = _vm->_events->queue(event);
+ }
// Begin palette cycling animation for candles
event.type = kEvTOneshot;
event.code = kPalAnimEvent;
event.op = kEventCycleStart;
event.time = 0;
- _vm->_events->chain(eventColumns, event);
+ eventColumns = _vm->_events->chain(eventColumns, event);
// Queue narrator dialogue list
- ITEQueueDialogue(eventColumns, n_dialogues, dialogue[lang]);
+ queueIntroDialogue(eventColumns, n_dialogues, dialogue);
// End scene after last dialogue over
event.type = kEvTOneshot;
event.code = kSceneEvent;
event.op = kEventEnd;
- event.time = VOICE_PAD;
+ event.time = INTRO_VOICE_PAD;
_vm->_events->chain(eventColumns, event);
break;
case SCENE_END:
break;
+
default:
warning("Illegal scene procedure parameter");
break;
@@ -593,227 +437,24 @@ int Scene::ITEIntroCave2Proc(int param) {
return 0;
}
-int Scene::SC_ITEIntroCave3Proc(int param, void *refCon) {
- return ((Scene *)refCon)->ITEIntroCave3Proc(param);
+// Handles first introductory cave painting scene
+int Scene::SC_ITEIntroCave1Proc(int param, void *refCon) {
+ return ((Scene *)refCon)->ITEIntroCaveCommonProc(param, 1);
}
-// Handles third introductory cave painting scene
-int Scene::ITEIntroCave3Proc(int param) {
- Event event;
- EventColumns *eventColumns;
- int lang = 0;
-
- if (_vm->getLanguage() == Common::DE_DEU)
- lang = 1;
- else if (_vm->getLanguage() == Common::IT_ITA)
- lang = 2;
-
- static const IntroDialogue dialogue[][3] = {
- { { // English
- 7, // cave voice 7
- "They taught us how to use our hands, and how to "
- "speak."
- },
- {
- 8, // cave voice 8
- "They showed us the joy of using our minds."
- },
- {
- 9, // cave voice 9
- "They loved us, and when we were ready, they surely "
- "would have given us the Secret of Happiness."
- } },
- // -----------------------------------------------------
- { { // German
- 7, // cave voice 7
- "Sie lehrten uns zu sprechen und unsere H\204nde zu "
- "benutzen."
- },
- {
- 8, // cave voice 8
- "Sie zeigten uns die Freude am Denken."
- },
- {
- 9, // cave voice 9
- "Sie liebten uns, und w\204ren wir bereit gewesen, "
- "h\204tten sie uns sicherlich das Geheimnis der "
- "Fr\224hlichkeit offenbart."
- } },
- // -----------------------------------------------------
- { { // Italian fan translation
- 7, // cave voice 7
- "Ci insegnarono come usare le mani e come parlare. "
-
- },
- {
- 8, // cave voice 8
- "Ci mostrarono le gioie che l'uso della mente "
- "pu\225 dare. "
- },
- {
- 9, // cave voice 9
- "Ci amarono, ed una volta pronti, ci avrebbero "
- "sicuramente svelato il Segreto della Felicit\205."
-
- } }
- };
-
- int n_dialogues = ARRAYSIZE(dialogue[lang]);
-
- switch (param) {
- case SCENE_BEGIN:
- // Start 'dissolve' transition to new scene background
- event.type = kEvTContinuous;
- event.code = kTransitionEvent;
- event.op = kEventDissolve;
- event.time = 0;
- event.duration = DISSOLVE_DURATION;
- eventColumns = _vm->_events->queue(event);
-
- // Begin palette cycling animation for candles
- event.type = kEvTOneshot;
- event.code = kPalAnimEvent;
- event.op = kEventCycleStart;
- event.time = 0;
- _vm->_events->chain(eventColumns, event);
-
- // Queue narrator dialogue list
- ITEQueueDialogue(eventColumns, n_dialogues, dialogue[lang]);
-
- // End scene after last dialogue over
- event.type = kEvTOneshot;
- event.code = kSceneEvent;
- event.op = kEventEnd;
- event.time = VOICE_PAD;
- _vm->_events->chain(eventColumns, event);
-
- break;
- case SCENE_END:
- break;
- default:
- warning("Illegal scene procedure parameter");
- break;
- }
-
- return 0;
+// Handles second introductory cave painting scene
+int Scene::SC_ITEIntroCave2Proc(int param, void *refCon) {
+ return ((Scene *)refCon)->ITEIntroCaveCommonProc(param, 2);
}
-int Scene::SC_ITEIntroCave4Proc(int param, void *refCon) {
- return ((Scene *)refCon)->ITEIntroCave4Proc(param);
+// Handles third introductory cave painting scene
+int Scene::SC_ITEIntroCave3Proc(int param, void *refCon) {
+ return ((Scene *)refCon)->ITEIntroCaveCommonProc(param, 3);
}
// Handles fourth introductory cave painting scene
-int Scene::ITEIntroCave4Proc(int param) {
- Event event;
- EventColumns *eventColumns;
- int lang = 0;
-
- if (_vm->getLanguage() == Common::DE_DEU)
- lang = 1;
- else if (_vm->getLanguage() == Common::IT_ITA)
- lang = 2;
-
- static const IntroDialogue dialogue[][4] = {
- { { // English
- 10, // cave voice 10
- "And now we see the sky, the land, and the water that "
- "we are heirs to, and we wonder: why did they leave?"
- },
- {
- 11, // cave voice 11
- "Do they live still, in the stars? In the oceans "
- "depths? In the wind?"
- },
- {
- 12, // cave voice 12
- "We wonder, was their fate good or evil?"
- },
- {
- 13, // cave voice 13
- "And will we also share the same fate one day?"
- } },
- // -----------------------------------------------------
- { { // German
- 10, // cave voice 10
- "Und nun sehen wir den Himmel, das Land und die "
- "Seen - unser Erbe. Und wir fragen uns - warum "
- "verschwanden sie?"
- },
- {
- 11, // cave voice 11
- "Leben sie noch in den Sternen? In den Tiefen des "
- "Ozeans? Im Wind?"
- },
- {
- 12, // cave voice 12
- "Wir fragen uns - war ihr Schicksal gut oder b\224se?"
- },
- {
- 13, // cave voice 13
- "Und wird uns eines Tages das gleiche Schicksal "
- "ereilen?"
- } },
- // -----------------------------------------------------
- { { // Italian fan translation
- 10, // cave voice 10
- "Ed ora che guardiamo il cielo, la terra e l'acqua "
- "che abbiamo ereditato, pensiamo: Perch\202 partirono?"
-
- },
- {
- 11, // cave voice 11
- "Vivono ancora, nelle stelle? Nelle profondit\205 "
- "dell'oceano? Nel vento?"
- },
- {
- 12, // cave voice 12
- "Ci domandiamo, il loro destino fu felice o nefasto?"
- },
- {
- 13, // cave voice 13
- "E un giorno, condivideremo anche noi lo stesso "
- "destino?"
- } }
- };
-
- int n_dialogues = ARRAYSIZE(dialogue[lang]);
-
- switch (param) {
- case SCENE_BEGIN:
- // Start 'dissolve' transition to new scene background
- event.type = kEvTContinuous;
- event.code = kTransitionEvent;
- event.op = kEventDissolve;
- event.time = 0;
- event.duration = DISSOLVE_DURATION;
- eventColumns = _vm->_events->queue(event);
-
- // Begin palette cycling animation for candles
- event.type = kEvTOneshot;
- event.code = kPalAnimEvent;
- event.op = kEventCycleStart;
- event.time = 0;
- _vm->_events->chain(eventColumns, event);
-
- // Queue narrator dialogue list
- ITEQueueDialogue(eventColumns, n_dialogues, dialogue[lang]);
-
- // End scene after last dialogue over
- event.type = kEvTOneshot;
- event.code = kSceneEvent;
- event.op = kEventEnd;
- event.time = VOICE_PAD;
- _vm->_events->chain(eventColumns, event);
-
- break;
- case SCENE_END:
- break;
- default:
- warning("Illegal scene procedure parameter");
- break;
- }
-
- return 0;
+int Scene::SC_ITEIntroCave4Proc(int param, void *refCon) {
+ return ((Scene *)refCon)->ITEIntroCaveCommonProc(param, 4);
}
int Scene::SC_ITEIntroValleyProc(int param, void *refCon) {
@@ -825,23 +466,7 @@ int Scene::ITEIntroValleyProc(int param) {
Event event;
EventColumns *eventColumns;
- static const IntroCredit credits[] = {
- {EN_ANY, kITEAny, kCHeader, "Producer"},
- {DE_DEU, kITEAny, kCHeader, "Produzent"},
- {IT_ITA, kITEAny, kCHeader, "Produttore"},
- {UNK_LANG, kITEAny, kCText, "Walter Hochbrueckner"},
- {EN_ANY, kITEAny, kCHeader, "Executive Producer"},
- {DE_DEU, kITEAny, kCHeader, "Ausf\201hrender Produzent"},
- {IT_ITA, kITEAny, kCHeader, "Produttore Esecutivo"},
- {UNK_LANG, kITEAny, kCText, "Robert McNally"},
- {UNK_LANG, kITEWyrmKeep, kCHeader, "2nd Executive Producer"},
- {EN_ANY, kITENotWyrmKeep, kCHeader, "Publisher"},
- {DE_DEU, kITENotWyrmKeep, kCHeader, "Herausgeber"},
- {IT_ITA, kITENotWyrmKeep, kCHeader, "Editore"},
- {UNK_LANG, kITEAny, kCText, "Jon Van Caneghem"}
- };
-
- int n_credits = ARRAYSIZE(credits);
+ int n_credits = ARRAYSIZE(creditsValley);
switch (param) {
case SCENE_BEGIN:
@@ -858,13 +483,7 @@ int Scene::ITEIntroValleyProc(int param) {
// Begin ITE title theme music
_vm->_music->stop();
- event.type = kEvTOneshot;
- event.code = kMusicEvent;
- event.param = MUSIC_2;
- event.param2 = MUSIC_NORMAL;
- event.op = kEventPlay;
- event.time = 0;
- _vm->_events->chain(eventColumns, event);
+ _vm->_events->chainMusic(eventColumns, MUSIC_TITLE_THEME);
// Pause animation before logo
event.type = kEvTOneshot;
@@ -899,7 +518,7 @@ int Scene::ITEIntroValleyProc(int param) {
_vm->_events->chain(eventColumns, event);
// Queue game credits list
- eventColumns = ITEQueueCredits(9000, CREDIT_DURATION1, n_credits, credits);
+ eventColumns = queueCredits(9000, CREDIT_DURATION1, n_credits, creditsValley);
// End scene after credit display
event.type = kEvTOneshot;
@@ -928,47 +547,8 @@ int Scene::ITEIntroTreeHouseProc(int param) {
Event event;
EventColumns *eventColumns;
- static const IntroCredit credits1[] = {
- {EN_ANY, kITEAny, kCHeader, "Game Design"},
- {DE_DEU, kITEAny, kCHeader, "Spielentwurf"},
- {IT_ITA, kITEAny, kCHeader, "Progetto"},
- {UNK_LANG, kITEAny, kCText, "Talin, Joe Pearce, Robert McNally"},
- {EN_ANY, kITEAny, kCText, "and Carolly Hauksdottir"},
- {DE_DEU, kITEAny, kCText, "und Carolly Hauksdottir"},
- {IT_ITA, kITEAny, kCText, "e Carolly Hauksdottir"},
- {EN_ANY, kITEAny, kCHeader, "Screenplay and Dialog"},
- {EN_ANY, kITEAny, kCText, "Robert Leh, Len Wein, and Bill Rotsler"},
- {DE_DEU, kITEAny, kCHeader, "Geschichte und Dialoge"},
- {DE_DEU, kITEAny, kCText, "Robert Leh, Len Wein und Bill Rotsler"},
- {IT_ITA, kITEAny, kCHeader, "Sceneggiatura e Dialoghi"},
- {IT_ITA, kITEAny, kCText, "Robert Leh, Len Wein e Bill Rotsler"}
- };
-
- int n_credits1 = ARRAYSIZE(credits1);
-
- static const IntroCredit credits2[] = {
- {UNK_LANG, kITEWyrmKeep, kCHeader, "Art Direction"},
- {UNK_LANG, kITEWyrmKeep, kCText, "Allison Hershey"},
- {EN_ANY, kITEAny, kCHeader, "Art"},
- {DE_DEU, kITEAny, kCHeader, "Grafiken"},
- {IT_ITA, kITEAny, kCHeader, "Grafica"},
- {UNK_LANG, kITEWyrmKeep, kCText, "Ed Lacabanne, Glenn Price, April Lee,"},
- {UNK_LANG, kITENotWyrmKeep, kCText, "Edward Lacabanne, Glenn Price, April Lee,"},
- {UNK_LANG, kITEWyrmKeep, kCText, "Lisa Sample, Brian Dowrick, Reed Waller,"},
- {EN_ANY, kITEWyrmKeep, kCText, "Allison Hershey and Talin"},
- {DE_DEU, kITEWyrmKeep, kCText, "Allison Hershey und Talin"},
- {IT_ITA, kITEWyrmKeep, kCText, "Allison Hershey e Talin"},
- {EN_ANY, kITENotWyrmKeep, kCText, "Lisa Iennaco, Brian Dowrick, Reed"},
- {EN_ANY, kITENotWyrmKeep, kCText, "Waller, Allison Hershey and Talin"},
- {DE_DEU, kITEAny, kCText, "Waller, Allison Hershey und Talin"},
- {IT_ITA, kITEAny, kCText, "Waller, Allison Hershey e Talin"},
- {EN_ANY, kITENotWyrmKeep, kCHeader, "Art Direction"},
- {DE_DEU, kITENotWyrmKeep, kCHeader, "Grafische Leitung"},
- {IT_ITA, kITENotWyrmKeep, kCHeader, "Direzione Grafica"},
- {UNK_LANG, kITENotWyrmKeep, kCText, "Allison Hershey"}
- };
-
- int n_credits2 = ARRAYSIZE(credits2);
+ int n_credits1 = ARRAYSIZE(creditsTreeHouse1);
+ int n_credits2 = ARRAYSIZE(creditsTreeHouse2);
switch (param) {
case SCENE_BEGIN:
@@ -993,8 +573,8 @@ int Scene::ITEIntroTreeHouseProc(int param) {
}
// Queue game credits list
- ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1);
- eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, credits2);
+ queueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, creditsTreeHouse1);
+ eventColumns = queueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, creditsTreeHouse2);
// End scene after credit display
event.type = kEvTOneshot;
@@ -1023,34 +603,8 @@ int Scene::ITEIntroFairePathProc(int param) {
Event event;
EventColumns *eventColumns;
- static const IntroCredit credits1[] = {
- {EN_ANY, kITEAny, kCHeader, "Programming"},
- {DE_DEU, kITEAny, kCHeader, "Programmiert von"},
- {IT_ITA, kITEAny, kCHeader, "Programmazione"},
- {UNK_LANG, kITEAny, kCText, "Talin, Walter Hochbrueckner,"},
- {EN_ANY, kITEAny, kCText, "Joe Burks and Robert Wiggins"},
- {DE_DEU, kITEAny, kCText, "Joe Burks und Robert Wiggins"},
- {IT_ITA, kITEAny, kCText, "Joe Burks e Robert Wiggins"},
- {EN_ANY, kITEPCCD | kITEWyrmKeep, kCHeader, "Additional Programming"},
- {EN_ANY, kITEPCCD | kITEWyrmKeep, kCText, "John Bolton"},
- {UNK_LANG, kITEMac, kCHeader, "Macintosh Version"},
- {UNK_LANG, kITEMac, kCText, "Michael McNally and Robert McNally"},
- {EN_ANY, kITEAny, kCHeader, "Music and Sound"},
- {DE_DEU, kITEAny, kCHeader, "Musik und Sound"},
- {IT_ITA, kITEAny, kCHeader, "Musica e Sonoro"},
- {UNK_LANG, kITEAny, kCText, "Matt Nathan"}
- };
-
- int n_credits1 = ARRAYSIZE(credits1);
-
- static const IntroCredit credits2[] = {
- {EN_ANY, kITEAny, kCHeader, "Directed by"},
- {DE_DEU, kITEAny, kCHeader, "Regie"},
- {IT_ITA, kITEAny, kCHeader, "Regia"},
- {UNK_LANG, kITEAny, kCText, "Talin"}
- };
-
- int n_credits2 = ARRAYSIZE(credits2);
+ int n_credits1 = ARRAYSIZE(creditsFairePath1);
+ int n_credits2 = ARRAYSIZE(creditsFairePath2);
switch (param) {
case SCENE_BEGIN:
@@ -1073,8 +627,8 @@ int Scene::ITEIntroFairePathProc(int param) {
_vm->_events->chain(eventColumns, event);
// Queue game credits list
- ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1);
- eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, credits2);
+ queueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, creditsFairePath1);
+ eventColumns = queueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, creditsFairePath2);
// End scene after credit display
event.type = kEvTOneshot;
diff --git a/engines/saga/introproc_saga2.cpp b/engines/saga/introproc_saga2.cpp
index 710236b0c4..0b773b03f0 100644
--- a/engines/saga/introproc_saga2.cpp
+++ b/engines/saga/introproc_saga2.cpp
@@ -43,9 +43,6 @@ int Scene::DinoStartProc() {
playMovie("testvid.smk");
- // HACK: Forcibly quit here
- _vm->quitGame();
-
return SUCCESS;
}
@@ -55,9 +52,6 @@ int Scene::FTA2StartProc() {
playMovie("trimark.smk");
playMovie("intro.smk");
- // HACK: Forcibly quit here
- _vm->quitGame();
-
return SUCCESS;
}
diff --git a/engines/saga/itedata.cpp b/engines/saga/itedata.cpp
index 87b71c2cb7..da70733f4e 100644
--- a/engines/saga/itedata.cpp
+++ b/engines/saga/itedata.cpp
@@ -444,111 +444,437 @@ const RawPoint pieceOrigins[PUZZLE_PIECES] = {
};
const char *pieceNames[][PUZZLE_PIECES] = {
- { "screwdriver", "pliers", "c-clamp", "wood clamp", "level",
- "twine", "wood plane", "claw hammer", "tape measure", "hatchet",
- "shears", "ruler", "saw", "mallet", "paint brush"
+ {
+ "screwdriver", "pliers", "c-clamp", "wood clamp", "level",
+ "twine", "wood plane", "claw hammer", "tape measure", "hatchet",
+ "shears", "ruler", "saw", "mallet", "paint brush"
},
- { "Schraubendreher", "Zange", "Schraubzwinge", "Holzzwinge", "Wasserwaage",
- "Bindfaden", "Hobel", "Schusterhammer", "Bandma$", "Beil",
- "Schere", "Winkel", "S\204ge", "Hammer", "Pinsel"
+ {
+ "Schraubendreher", "Zange", "Schraubzwinge", "Holzzwinge", "Wasserwaage",
+ "Bindfaden", "Hobel", "Schusterhammer", "Bandma$", "Beil",
+ "Schere", "Winkel", "S\204ge", "Hammer", "Pinsel"
},
- { "cacciavite", "pinze", "morsa", "morsa da legno", "livella",
- "spago", "pialla", "martello", "metro a nastro", "accetta",
- "cesoie", "righello", "sega", "mazza", "pennello"
+ {
+ "cacciavite", "pinze", "morsa", "morsa da legno", "livella",
+ "spago", "pialla", "martello", "metro a nastro", "accetta",
+ "cesoie", "righello", "sega", "mazza", "pennello"
}
};
const char *hintStr[][4] = {
- { "Check which pieces could fit in each corner first.",
- "Check which corner has the least number of pieces that can fit and start from there.",
- "Check each new corner and any new side for pieces that fit.",
- "I don't see anything out of place."
- },
- { "\232berpr\201fe zun\204chst, welche die Eckteile sein k\224nnten.",
- "Schau, in welche Ecke die wenigsten Teile passen, und fang dort an.",
- "Untersuche jede Ecke und jede Seite auf Teile, die dort passen k\224nnen.",
- "Ich sehe nichts an der falschen Stelle."
- },
- { "Controlla prima quali pezzi si inseriscono meglio in ogni angolo.",
- "Controlla quale angolo ha il minor numero di pezzi che combaciano, e parti da quello.",
- "Controlla ogni nuovo angolo e lato per ogni pezzo che combacia.",
- "Non vedo nulla fuori posto."
+ {
+ "Check which pieces could fit in each corner first.",
+ "Check which corner has the least number of pieces that can fit and start from there.",
+ "Check each new corner and any new side for pieces that fit.",
+ "I don't see anything out of place."
+ },
+ {
+ "\232berpr\201fe zun\204chst, welche die Eckteile sein k\224nnten.",
+ "Schau, in welche Ecke die wenigsten Teile passen, und fang dort an.",
+ "Untersuche jede Ecke und jede Seite auf Teile, die dort passen k\224nnen.",
+ "Ich sehe nichts an der falschen Stelle."
+ },
+ {
+ "Controlla prima quali pezzi si inseriscono meglio in ogni angolo.",
+ "Controlla quale angolo ha il minor numero di pezzi che combaciano, e parti da quello.",
+ "Controlla ogni nuovo angolo e lato per ogni pezzo che combacia.",
+ "Non vedo nulla fuori posto."
}
};
const char *solicitStr[][NUM_SOLICIT_REPLIES] = {
- { "Hey, Fox! Would you like a hint?",
- "Would you like some help?",
- "Umm...Umm...",
- "Psst! want a hint?",
- "I would have done this differently, you know."
- },
- { "Hey, Fuchs! Brauchst Du \047nen Tip?",
- "M\224chtest Du etwas Hilfe?"
- "\231hm...\216hm..."
- "Psst! \047n Tip vielleicht?"
- "Ja, wei$t Du... ich h\204tte das anders gemacht."
- },
- { "Hey, Volpe! Serve un suggerimento?",
- "Hai bisogno di aiuto?",
- "Umm...Umm...",
- "Psst! Serve un aiutino?",
- "Io, sai, l'avrei fatto diversamente."
+ {
+ "Hey, Fox! Would you like a hint?",
+ "Would you like some help?",
+ "Umm...Umm...",
+ "Psst! want a hint?",
+ "I would have done this differently, you know."
+ },
+ {
+ "Hey, Fuchs! Brauchst Du \047nen Tip?",
+ "M\224chtest Du etwas Hilfe?"
+ "\231hm...\216hm..."
+ "Psst! \047n Tip vielleicht?"
+ "Ja, wei$t Du... ich h\204tte das anders gemacht."
+ },
+ {
+ "Hey, Volpe! Serve un suggerimento?",
+ "Hai bisogno di aiuto?",
+ "Umm...Umm...",
+ "Psst! Serve un aiutino?",
+ "Io, sai, l'avrei fatto diversamente."
}
};
const char *sakkaStr[][NUM_SAKKA] = {
- { "Hey, you're not supposed to help the applicants!",
- "Guys! This is supposed to be a test!",
- "C'mon fellows, that's not in the rules!"
+ {
+ "Hey, you're not supposed to help the applicants!",
+ "Guys! This is supposed to be a test!",
+ "C'mon fellows, that's not in the rules!"
},
- { "Hey, Du darfst dem Pr\201fling nicht helfen!",
- "Hallo?! Dies soll eine Pr\201fung sein!",
- "Also, Jungs. Schummeln steht nicht in den Regeln!"
+ {
+ "Hey, Du darfst dem Pr\201fling nicht helfen!",
+ "Hallo?! Dies soll eine Pr\201fung sein!",
+ "Also, Jungs. Schummeln steht nicht in den Regeln!"
},
- { "Hey, non si dovrebbero aiutare i candidati!",
- "Ragazzi! Questo dovrebbe essere un test!",
- "Forza ragazzi, non si pu\225!"
+ {
+ "Hey, non si dovrebbero aiutare i candidati!",
+ "Ragazzi! Questo dovrebbe essere un test!",
+ "Forza ragazzi, non si pu\225!"
}
};
const char *whineStr[][NUM_WHINES] = {
- { "Aww, c'mon Sakka!",
- "One hint won't hurt, will it?",
- "Sigh...",
- "I think that clipboard has gone to your head, Sakka!",
- "Well, I don't recall any specific rule against hinting."
- },
- { "Och, sei nicht so, Sakka!"
- "EIN Tip wird schon nicht schaden, oder?",
- "Seufz..."
- "Ich glaube, Du hast ein Brett vor dem Kopf, Sakka!",
- "Hm, ich kann mich an keine Regel erinnern, die Tips verbietet."
- },
- { "Ooo, suvvia Sakka!",
- "Un indizio non guaster\205, no?",
- "Sigh...",
- "Credo che questa faccenda ti abbia dato alla testa, Sakka!",
- "Beh, non ricordo regole specifiche contro i suggerimenti."
+ {
+ "Aww, c'mon Sakka!",
+ "One hint won't hurt, will it?",
+ "Sigh...",
+ "I think that clipboard has gone to your head, Sakka!",
+ "Well, I don't recall any specific rule against hinting."
+ },
+ {
+ "Och, sei nicht so, Sakka!"
+ "EIN Tip wird schon nicht schaden, oder?",
+ "Seufz..."
+ "Ich glaube, Du hast ein Brett vor dem Kopf, Sakka!",
+ "Hm, ich kann mich an keine Regel erinnern, die Tips verbietet."
+ },
+ {
+ "Ooo, suvvia Sakka!",
+ "Un indizio non guaster\205, no?",
+ "Sigh...",
+ "Credo che questa faccenda ti abbia dato alla testa, Sakka!",
+ "Beh, non ricordo regole specifiche contro i suggerimenti."
}
};
const char *optionsStr[][4] = {
- { "\"I'll do this puzzle later.\"",
- "\"Yes, I'd like a hint please.\"",
- "\"No, thank you, I'd like to try and solve it myself.\"",
- "I think the %s is in the wrong place."
- },
- { "\"Ich l\224se das Puzzle sp\204ter.\"",
- "\"Ja, ich m\224chte einen Tip, bitte.\"",
- "\"Nein danke, ich m\224chte das alleine l\224sen.\"",
- "Pssst... %s... falsche Stelle..."
- },
- { "\"Far\225 questo puzzle pi\227 tardi.\"",
- "\"Si, grazie. Ne avrei bisogno.\"",
- "\"No, grazie, voglio provare a risolverlo da solo.\"",
- "Penso che la tessera %s sia nel posto sbagliato."
+ {
+ "\"I'll do this puzzle later.\"",
+ "\"Yes, I'd like a hint please.\"",
+ "\"No, thank you, I'd like to try and solve it myself.\"",
+ "I think the %s is in the wrong place."
+ },
+ {
+ "\"Ich l\224se das Puzzle sp\204ter.\"",
+ "\"Ja, ich m\224chte einen Tip, bitte.\"",
+ "\"Nein danke, ich m\224chte das alleine l\224sen.\"",
+ "Pssst... %s... falsche Stelle..."
+ },
+ {
+ "\"Far\225 questo puzzle pi\227 tardi.\"",
+ "\"Si, grazie. Ne avrei bisogno.\"",
+ "\"No, grazie, voglio provare a risolverlo da solo.\"",
+ "Penso che la tessera %s sia nel posto sbagliato."
}
};
+const IntroDialogue introDialogueCave1[][4] = {
+ { { // English
+ 0, // cave voice 0
+ "We see the sky, we see the land, we see the water, "
+ "and we wonder: Are we the only ones?"
+ },
+ {
+ 1, // cave voice 1
+ "Long before we came to exist, the humans ruled the "
+ "Earth."
+ },
+ {
+ 2, // cave voice 2
+ "They made marvelous things, and moved whole "
+ "mountains."
+ },
+ {
+ 3, // cave voice 3
+ "They knew the Secret of Flight, the Secret of "
+ "Happiness, and other secrets beyond our imagining."
+ } },
+ // -----------------------------------------------------
+ { { // German
+ 0, // cave voice 0
+ "Um uns sind der Himmel, das Land und die Seen; und "
+ "wir fragen uns - sind wir die einzigen?"
+ },
+ {
+ 1, // cave voice 1
+ "Lange vor unserer Zeit herrschten die Menschen "
+ "\201ber die Erde."
+ },
+ {
+ 2, // cave voice 2
+ "Sie taten wundersame Dinge und versetzten ganze "
+ "Berge."
+ },
+ {
+ 3, // cave voice 3
+ "Sie kannten das Geheimnis des Fluges, das Geheimnis "
+ "der Fr\224hlichkeit und andere Geheimnisse, die "
+ "unsere Vorstellungskraft \201bersteigen."
+ } },
+ // -----------------------------------------------------
+ { { // Italian fan translation
+ 0, // cave voice 0
+ "Guardiamo il cielo, guardiamo la terra, guardiamo "
+ "l'acqua, e ci chiediamo: Siamo forse soli?"
+ },
+ {
+ 1, // cave voice 1
+ "Molto tempo prima che noi esistessimo, gli Umani "
+ "dominavano la terra."
+ },
+ {
+ 2, // cave voice 2
+ "Fecero cose meravigliose, e mossero intere "
+ "montagne."
+ },
+ {
+ 3, // cave voice 3
+ "Conoscevano il Segreto del Volo, il Segreto della "
+ "Felicit\205, ed altri segreti oltre ogni nostra "
+ "immaginazione."
+ } }
+};
+
+const IntroDialogue introDialogueCave2[][3] = {
+ { { // English
+ 4, // cave voice 4
+ "The humans also knew the Secret of Life, and they "
+ "used it to give us the Four Great Gifts:"
+ },
+ {
+ 5, // cave voice 5
+ "Thinking minds, feeling hearts, speaking mouths, and "
+ "reaching hands."
+ },
+ {
+ 6, // cave voice 6
+ "We are their children."
+ } },
+ // -----------------------------------------------------
+ { { // German
+ 4, // cave voice 4
+ "Au$erdem kannten die Menschen das Geheimnis des "
+ "Lebens. Und sie nutzten es, um uns die vier gro$en "
+ "Geschenke zu geben -"
+ },
+ {
+ 5, // cave voice 5
+ "den denkenden Geist, das f\201hlende Herz, den "
+ "sprechenden Mund und die greifende Hand."
+ },
+ {
+ 6, // cave voice 6
+ "Wir sind ihre Kinder."
+ } },
+ // -----------------------------------------------------
+ { { // Italian fan translation
+ 4, // cave voice 4
+ "Gli Umani conoscevano anche il Segreto della Vita, "
+ "e lo usarono per darci i Quattro Grandi Doni:"
+
+ },
+ {
+ 5, // cave voice 5
+ "Il pensiero, le emozioni, la parola e la manualit\205."
+
+ },
+ {
+ 6, // cave voice 6
+ "Siamo i loro figli."
+ } }
+};
+
+const IntroDialogue introDialogueCave3[][3] = {
+ { { // English
+ 7, // cave voice 7
+ "They taught us how to use our hands, and how to "
+ "speak."
+ },
+ {
+ 8, // cave voice 8
+ "They showed us the joy of using our minds."
+ },
+ {
+ 9, // cave voice 9
+ "They loved us, and when we were ready, they surely "
+ "would have given us the Secret of Happiness."
+ } },
+ // -----------------------------------------------------
+ { { // German
+ 7, // cave voice 7
+ "Sie lehrten uns zu sprechen und unsere H\204nde zu "
+ "benutzen."
+ },
+ {
+ 8, // cave voice 8
+ "Sie zeigten uns die Freude am Denken."
+ },
+ {
+ 9, // cave voice 9
+ "Sie liebten uns, und w\204ren wir bereit gewesen, "
+ "h\204tten sie uns sicherlich das Geheimnis der "
+ "Fr\224hlichkeit offenbart."
+ } },
+ // -----------------------------------------------------
+ { { // Italian fan translation
+ 7, // cave voice 7
+ "Ci insegnarono come usare le mani e come parlare. "
+
+ },
+ {
+ 8, // cave voice 8
+ "Ci mostrarono le gioie che l'uso della mente "
+ "pu\225 dare. "
+ },
+ {
+ 9, // cave voice 9
+ "Ci amarono, ed una volta pronti, ci avrebbero "
+ "sicuramente svelato il Segreto della Felicit\205."
+
+ } }
+};
+
+const IntroDialogue introDialogueCave4[][4] = {
+ { { // English
+ 10, // cave voice 10
+ "And now we see the sky, the land, and the water that "
+ "we are heirs to, and we wonder: why did they leave?"
+ },
+ {
+ 11, // cave voice 11
+ "Do they live still, in the stars? In the oceans "
+ "depths? In the wind?"
+ },
+ {
+ 12, // cave voice 12
+ "We wonder, was their fate good or evil?"
+ },
+ {
+ 13, // cave voice 13
+ "And will we also share the same fate one day?"
+ } },
+ // -----------------------------------------------------
+ { { // German
+ 10, // cave voice 10
+ "Und nun sehen wir den Himmel, das Land und die "
+ "Seen - unser Erbe. Und wir fragen uns - warum "
+ "verschwanden sie?"
+ },
+ {
+ 11, // cave voice 11
+ "Leben sie noch in den Sternen? In den Tiefen des "
+ "Ozeans? Im Wind?"
+ },
+ {
+ 12, // cave voice 12
+ "Wir fragen uns - war ihr Schicksal gut oder b\224se?"
+ },
+ {
+ 13, // cave voice 13
+ "Und wird uns eines Tages das gleiche Schicksal "
+ "ereilen?"
+ } },
+ // -----------------------------------------------------
+ { { // Italian fan translation
+ 10, // cave voice 10
+ "Ed ora che guardiamo il cielo, la terra e l'acqua "
+ "che abbiamo ereditato, pensiamo: Perch\202 partirono?"
+
+ },
+ {
+ 11, // cave voice 11
+ "Vivono ancora, nelle stelle? Nelle profondit\205 "
+ "dell'oceano? Nel vento?"
+ },
+ {
+ 12, // cave voice 12
+ "Ci domandiamo, il loro destino fu felice o nefasto?"
+ },
+ {
+ 13, // cave voice 13
+ "E un giorno, condivideremo anche noi lo stesso "
+ "destino?"
+ } }
+};
+
+const IntroCredit creditsValley[] = {
+ {Common::EN_ANY, kITECreditsAny, kITECreditsHeader, "Producer"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsHeader, "Produzent"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsHeader, "Produttore"},
+ {Common::UNK_LANG, kITECreditsAny, kITECreditsText, "Walter Hochbrueckner"},
+ {Common::EN_ANY, kITECreditsAny, kITECreditsHeader, "Executive Producer"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsHeader, "Ausf\201hrender Produzent"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsHeader, "Produttore Esecutivo"},
+ {Common::UNK_LANG, kITECreditsAny, kITECreditsText, "Robert McNally"},
+ {Common::UNK_LANG, kITECreditsWyrmKeep, kITECreditsHeader, "2nd Executive Producer"},
+ {Common::EN_ANY, kITECreditsNotWyrmKeep, kITECreditsHeader, "Publisher"},
+ {Common::DE_DEU, kITECreditsNotWyrmKeep, kITECreditsHeader, "Herausgeber"},
+ {Common::IT_ITA, kITECreditsNotWyrmKeep, kITECreditsHeader, "Editore"},
+ {Common::UNK_LANG, kITECreditsAny, kITECreditsText, "Jon Van Caneghem"}
+};
+
+const IntroCredit creditsTreeHouse1[] = {
+ {Common::EN_ANY, kITECreditsAny, kITECreditsHeader, "Game Design"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsHeader, "Spielentwurf"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsHeader, "Progetto"},
+ {Common::UNK_LANG, kITECreditsAny, kITECreditsText, "Talin, Joe Pearce, Robert McNally"},
+ {Common::EN_ANY, kITECreditsAny, kITECreditsText, "and Carolly Hauksdottir"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsText, "und Carolly Hauksdottir"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsText, "e Carolly Hauksdottir"},
+ {Common::EN_ANY, kITECreditsAny, kITECreditsHeader, "Screenplay and Dialog"},
+ {Common::EN_ANY, kITECreditsAny, kITECreditsText, "Robert Leh, Len Wein, and Bill Rotsler"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsHeader, "Geschichte und Dialoge"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsText, "Robert Leh, Len Wein und Bill Rotsler"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsHeader, "Sceneggiatura e Dialoghi"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsText, "Robert Leh, Len Wein e Bill Rotsler"}
+};
+
+const IntroCredit creditsTreeHouse2[] = {
+ {Common::UNK_LANG, kITECreditsWyrmKeep, kITECreditsHeader, "Art Direction"},
+ {Common::UNK_LANG, kITECreditsWyrmKeep, kITECreditsText, "Allison Hershey"},
+ {Common::EN_ANY, kITECreditsAny, kITECreditsHeader, "Art"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsHeader, "Grafiken"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsHeader, "Grafica"},
+ {Common::UNK_LANG, kITECreditsWyrmKeep, kITECreditsText, "Ed Lacabanne, Glenn Price, April Lee,"},
+ {Common::UNK_LANG, kITECreditsNotWyrmKeep, kITECreditsText, "Edward Lacabanne, Glenn Price, April Lee,"},
+ {Common::UNK_LANG, kITECreditsWyrmKeep, kITECreditsText, "Lisa Sample, Brian Dowrick, Reed Waller,"},
+ {Common::EN_ANY, kITECreditsWyrmKeep, kITECreditsText, "Allison Hershey and Talin"},
+ {Common::DE_DEU, kITECreditsWyrmKeep, kITECreditsText, "Allison Hershey und Talin"},
+ {Common::IT_ITA, kITECreditsWyrmKeep, kITECreditsText, "Allison Hershey e Talin"},
+ {Common::EN_ANY, kITECreditsNotWyrmKeep, kITECreditsText, "Lisa Iennaco, Brian Dowrick, Reed"},
+ {Common::EN_ANY, kITECreditsNotWyrmKeep, kITECreditsText, "Waller, Allison Hershey and Talin"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsText, "Waller, Allison Hershey und Talin"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsText, "Waller, Allison Hershey e Talin"},
+ {Common::EN_ANY, kITECreditsNotWyrmKeep, kITECreditsHeader, "Art Direction"},
+ {Common::DE_DEU, kITECreditsNotWyrmKeep, kITECreditsHeader, "Grafische Leitung"},
+ {Common::IT_ITA, kITECreditsNotWyrmKeep, kITECreditsHeader, "Direzione Grafica"},
+ {Common::UNK_LANG, kITECreditsNotWyrmKeep, kITECreditsText, "Allison Hershey"}
+};
+
+const IntroCredit creditsFairePath1[] = {
+ {Common::EN_ANY, kITECreditsAny, kITECreditsHeader, "Programming"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsHeader, "Programmiert von"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsHeader, "Programmazione"},
+ {Common::UNK_LANG, kITECreditsAny, kITECreditsText, "Talin, Walter Hochbrueckner,"},
+ {Common::EN_ANY, kITECreditsAny, kITECreditsText, "Joe Burks and Robert Wiggins"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsText, "Joe Burks und Robert Wiggins"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsText, "Joe Burks e Robert Wiggins"},
+ {Common::EN_ANY, kITECreditsPCCD | kITECreditsWyrmKeep, kITECreditsHeader, "Additional Programming"},
+ {Common::EN_ANY, kITECreditsPCCD | kITECreditsWyrmKeep, kITECreditsText, "John Bolton"},
+ {Common::UNK_LANG, kITECreditsMac, kITECreditsHeader, "Macintosh Version"},
+ {Common::UNK_LANG, kITECreditsMac, kITECreditsText, "Michael McNally and Robert McNally"},
+ {Common::EN_ANY, kITECreditsAny, kITECreditsHeader, "Music and Sound"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsHeader, "Musik und Sound"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsHeader, "Musica e Sonoro"},
+ {Common::UNK_LANG, kITECreditsAny, kITECreditsText, "Matt Nathan"}
+};
+
+const IntroCredit creditsFairePath2[] = {
+ {Common::EN_ANY, kITECreditsAny, kITECreditsHeader, "Directed by"},
+ {Common::DE_DEU, kITECreditsAny, kITECreditsHeader, "Regie"},
+ {Common::IT_ITA, kITECreditsAny, kITECreditsHeader, "Regia"},
+ {Common::UNK_LANG, kITECreditsAny, kITECreditsText, "Talin"}
+};
+
} // End of namespace Saga
diff --git a/engines/saga/itedata.h b/engines/saga/itedata.h
index d27b84781f..f9416652bf 100644
--- a/engines/saga/itedata.h
+++ b/engines/saga/itedata.h
@@ -79,6 +79,32 @@ struct IteFxTable {
byte vol;
};
+struct IntroDialogue {
+ uint32 i_voice_rn;
+ const char *i_str;
+};
+
+struct IntroCredit {
+ Common::Language lang;
+ int game;
+ int type;
+ const char *string;
+};
+
+enum {
+ kITECreditsHeader,
+ kITECreditsText
+};
+
+enum {
+ kITECreditsPC = (1 << 0),
+ kITECreditsPCCD = (1 << 1),
+ kITECreditsMac = (1 << 2),
+ kITECreditsWyrmKeep = (1 << 3),
+ kITECreditsAny = 0xffff,
+ kITECreditsNotWyrmKeep = kITECreditsAny & ~kITECreditsWyrmKeep
+};
+
#define ITE_OBJECTCOUNT 39
#define ITE_SFXCOUNT 63
@@ -106,6 +132,17 @@ extern const char *hintStr[][4];
extern const char portraitList[];
extern const char *optionsStr[][4];
+extern const IntroDialogue introDialogueCave1[][4];
+extern const IntroDialogue introDialogueCave2[][3];
+extern const IntroDialogue introDialogueCave3[][3];
+extern const IntroDialogue introDialogueCave4[][4];
+
+extern const IntroCredit creditsValley[13];
+extern const IntroCredit creditsTreeHouse1[13];
+extern const IntroCredit creditsTreeHouse2[19];
+extern const IntroCredit creditsFairePath1[15];
+extern const IntroCredit creditsFairePath2[4];
+
} // End of namespace Saga
#endif
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index e444900967..d20882ca26 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -147,7 +147,7 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
if (!_musicContext) {
if (_vm->getGameId() == GID_ITE) {
_musicContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
- } else {
+ } else if (_vm->getGameId() == GID_IHNM) {
// I've listened to music from both the FM and the GM
// file, and I've tentatively reached the conclusion
// that they are both General MIDI. My guess is that
@@ -173,6 +173,8 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
// Note that the IHNM demo has only got one music file
// (music.rsc). It is assumed that it contains FM music
_musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM);
+ } else if (_vm->getGameId() == GID_DINO || _vm->getGameId() == GID_FTA2) {
+ _musicContext = _vm->_resource->getContext(GAME_SOUNDFILE);
}
}
@@ -255,19 +257,18 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
_mixer->stopHandle(_musicHandle);
_player->stop();
- int realTrackNumber;
+ int realTrackNumber = 0;
if (_vm->getGameId() == GID_ITE) {
- if (flags == MUSIC_DEFAULT) {
- if (resourceId == 13 || resourceId == 19) {
- flags = MUSIC_NORMAL;
- } else {
- flags = MUSIC_LOOP;
- }
- }
+ if (flags == MUSIC_NORMAL && (resourceId == 13 || resourceId == 19))
+ flags = MUSIC_LOOP;
realTrackNumber = resourceId - 8;
- } else {
+ } else if (_vm->getGameId() == GID_IHNM) {
+ realTrackNumber = resourceId + 1;
+ } else if (_vm->getGameId() == GID_DINO || _vm->getGameId() == GID_FTA2) {
realTrackNumber = resourceId + 1;
+ uint32 musicTrackTag = MKTAG('X','M','I', (byte)(resourceId + 1));
+ resourceId = _musicContext->getEntryNum(musicTrackTag);
}
// Try to open standalone digital track
@@ -359,9 +360,6 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
return;
}
- if (flags == MUSIC_DEFAULT)
- flags = MUSIC_NORMAL;
-
// Load MIDI/XMI resource data
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
// Load the external music file for Mac IHNM
diff --git a/engines/saga/music.h b/engines/saga/music.h
index ba44c3ca71..2106fb6fa6 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -37,8 +37,7 @@ namespace Saga {
enum MusicFlags {
MUSIC_NORMAL = 0,
- MUSIC_LOOP = 0x0001,
- MUSIC_DEFAULT = 0xffff
+ MUSIC_LOOP = 0x0001
};
class MusicDriver : public Audio::MidiPlayer {
@@ -72,7 +71,7 @@ public:
bool isPlaying();
bool hasDigitalMusic() { return _digitalMusic; }
- void play(uint32 resourceId, MusicFlags flags = MUSIC_DEFAULT);
+ void play(uint32 resourceId, MusicFlags flags = MUSIC_NORMAL);
void pause();
void resume();
void stop();
diff --git a/engines/saga/objectmap.cpp b/engines/saga/objectmap.cpp
index f27c888a61..ad5167209c 100644
--- a/engines/saga/objectmap.cpp
+++ b/engines/saga/objectmap.cpp
@@ -231,7 +231,7 @@ int ObjectMap::hitTest(const Point& testPoint) {
}
void ObjectMap::cmdInfo() {
- _vm->_console->DebugPrintf("%d zone(s) loaded.\n\n", _hitZoneList.size());
+ _vm->_console->debugPrintf("%d zone(s) loaded.\n\n", _hitZoneList.size());
}
} // End of namespace Saga
diff --git a/engines/saga/resource.cpp b/engines/saga/resource.cpp
index cdf674dc66..1fb9ac1c04 100644
--- a/engines/saga/resource.cpp
+++ b/engines/saga/resource.cpp
@@ -304,21 +304,13 @@ void Resource::clearContexts() {
}
void Resource::loadResource(ResourceContext *context, uint32 resourceId, ByteArray &resourceBuffer) {
- Common::File *file;
- uint32 resourceOffset;
- ResourceData *resourceData;
-
-
- resourceData = context->getResourceData(resourceId);
-
- file = context->getFile(resourceData);
-
- resourceOffset = resourceData->offset;
+ ResourceData *resourceData = context->getResourceData(resourceId);
+ Common::File *file = context->getFile(resourceData);
+ uint32 resourceOffset = resourceData->offset;
debug(8, "loadResource %d 0x%X:0x%X", resourceId, resourceOffset, uint(resourceData->size));
resourceBuffer.resize(resourceData->size);
-
file->seek((long)resourceOffset, SEEK_SET);
if (file->read(resourceBuffer.getBuffer(), resourceBuffer.size()) != resourceBuffer.size()) {
diff --git a/engines/saga/resource.h b/engines/saga/resource.h
index 252e92c967..2a1aaf3103 100644
--- a/engines/saga/resource.h
+++ b/engines/saga/resource.h
@@ -60,12 +60,13 @@ struct PatchData {
struct ResourceData {
uint32 id; // SAGA2
+ uint32 category; // SAGA2
size_t offset;
size_t size;
PatchData *patchData;
ResourceData() :
- id(0), offset(0), size(0), patchData(NULL) {
+ id(0), category(0), offset(0), size(0), patchData(NULL) {
}
~ResourceData() {
@@ -130,10 +131,15 @@ public:
// SAGA 2
int32 getEntryNum(uint32 id) {
int32 num = 0;
+ uint32 miloCategory = MKTAG('M', 'I', 'L', 'O');
+
for (ResourceDataArray::const_iterator i = _table.begin(); i != _table.end(); ++i) {
- if (i->id == id) {
+ //uint32 c = i->category;
+ //debug("%c%c%c%c, offset: %d, size: %d", (c >> 24), (c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF, i->offset, i->size);
+ // Ignore low quality music resources (MILO)
+ if (i->id == id && i->category != miloCategory)
return num;
- }
+
num++;
}
return -1;
@@ -282,6 +288,10 @@ protected:
return loadResV2(contextSize);
}
bool loadResV2(uint32 contextSize);
+
+ void readCategory(ResourceData &element);
+ void readEntry(ResourceData &element);
+ uint32 getCategory(uint32 resourceOffset);
};
class Resource_HRS : public Resource {
diff --git a/engines/saga/resource_hrs.cpp b/engines/saga/resource_hrs.cpp
index 09da9cf0bb..ba58830269 100644
--- a/engines/saga/resource_hrs.cpp
+++ b/engines/saga/resource_hrs.cpp
@@ -39,13 +39,35 @@
namespace Saga {
-void readElement(Common::File &file, Saga::ResourceData &element) {
- element.id = file.readUint32BE();
- element.offset = file.readUint32LE();
- element.size = file.readUint32LE();
+void ResourceContext_HRS::readCategory(ResourceData &element) {
+ element.id = _file.readUint32BE();
+ element.offset = _file.readUint32LE();
+ element.size = _file.readUint32LE();
+ element.category = 0;
+ debug(3, "Category: id %u, offset %u, size %u", element.id, (uint)element.offset, (uint)element.size);
+}
+
+void ResourceContext_HRS::readEntry(ResourceData &element) {
+ element.id = _file.readUint32BE();
+ element.offset = _file.readUint32LE();
+ element.size = _file.readUint32LE();
+ element.category = getCategory(_file.pos());
debug(3, "Entry: id %u, offset %u, size %u", element.id, (uint)element.offset, (uint)element.size);
}
+uint32 ResourceContext_HRS::getCategory(uint32 resourceOffset) {
+ for (int i = _categories.size() - 1; i >= 0; --i) {
+ if (resourceOffset >= _categories[i].offset)
+ return _categories[i].id;
+ }
+
+ error("Unknown category for offset %d", resourceOffset);
+}
+
+static bool categorySortHelper(const ResourceData &r1, const ResourceData &r2) {
+ return r1.offset < r2.offset;
+}
+
bool ResourceContext_HRS::loadResV2(uint32 contextSize) {
ResourceData origin;
uint32 firstEntryOffset;
@@ -56,7 +78,7 @@ bool ResourceContext_HRS::loadResV2(uint32 contextSize) {
debug(3, "Context %s =====", _fileName);
_file.seek(0, SEEK_SET);
- readElement(_file, origin);
+ readCategory(origin);
// Check if the file is valid
if (origin.id != MKTAG('H','R','E','S')) { // header
@@ -74,18 +96,23 @@ bool ResourceContext_HRS::loadResV2(uint32 contextSize) {
// Read categories
count = origin.size / resourceSize;
- debug(3, "Categories: %d =====", count);
+ debug(3, "File: %s, categories: %d =====", _file.getName(), count);
for (i = 0; i < count; i++) {
- readElement(_file, _categories[i]);
+ readCategory(_categories[i]);
+ //uint32 id = _categories[i].id;
+ //debug("%i: %c%c%c%c, offset: %d, size: %d", i, (id >> 24), (id >> 16) & 0xFF, (id >> 8) & 0xFF, id & 0xFF, _categories[i].offset, _categories[i].size);
}
+ Common::sort(_categories.begin(), _categories.end(), categorySortHelper);
+
_file.seek(firstEntryOffset, SEEK_SET);
// Read table entries
count = tableSize / resourceSize;
- debug(3, "Entries: %d =====", count);
+ debug(3, "File: %s, entries: %d =====", _file.getName(), count);
for (i = 0; i < count; i++) {
- readElement(_file, _table[i]);
+ readEntry(_table[i]);
+ //debug("%i: offset: %d, size: %d", i, _table[i].offset, _table[i].size);
}
return true;
}
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index b15d161ba3..3d38b3ea52 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -341,7 +341,6 @@ Common::Error SagaEngine::run() {
syncSoundSettings();
} else {
_framesEsc = 0;
- //_sndRes->playVoice(0); // SAGA 2 sound test
_scene->startScene();
}
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 7f77cbab38..f19645dd99 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -789,13 +789,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) {
if (_vm->getGameId() == GID_ITE) {
if (_sceneDescription.musicResourceId >= 0) {
- event.type = kEvTOneshot;
- event.code = kMusicEvent;
- event.param = _sceneDescription.musicResourceId;
- event.param2 = MUSIC_DEFAULT;
- event.op = kEventPlay;
- event.time = 0;
- _vm->_events->queue(event);
+ _vm->_events->queueMusic(_sceneDescription.musicResourceId);
} else {
event.type = kEvTOneshot;
event.code = kMusicEvent;
@@ -1220,7 +1214,7 @@ void Scene::cmdSceneChange(int argc, const char **argv) {
scene_num = atoi(argv[1]);
if ((scene_num < 1) || (uint(scene_num) >= _sceneLUT.size())) {
- _vm->_console->DebugPrintf("Invalid scene number.\n");
+ _vm->_console->debugPrintf("Invalid scene number.\n");
return;
}
diff --git a/engines/saga/scene.h b/engines/saga/scene.h
index 0a3b98b33f..6a9571d282 100644
--- a/engines/saga/scene.h
+++ b/engines/saga/scene.h
@@ -182,34 +182,8 @@ typedef Common::List<LoadSceneParams> SceneQueueList;
#define IHNM_TITLE_TIME_GM 28750
#define IHNM_TITLE_TIME_FM 19500
-///// ITE-specific stuff
-#define ITE_INTRO_FRAMETIME 90
-
-#define INTRO_CAPTION_Y 170
-#define INTRO_DE_CAPTION_Y 160
-#define INTRO_IT_CAPTION_Y 160
-#define VOICE_PAD 50
-#define VOICE_LETTERLEN 90
-
-#define PALETTE_FADE_DURATION 1000
-#define DISSOLVE_DURATION 3000
-#define LOGO_DISSOLVE_DURATION 1000
-
#define CREDIT_DURATION1 4000
-struct IntroDialogue {
- uint32 i_voice_rn;
- const char *i_str;
-};
-
-struct IntroCredit {
- Common::Language lang;
- int game;
- int type;
- const char *string;
-};
-
-
class Scene {
public:
Scene(SagaEngine *vm);
@@ -431,13 +405,10 @@ class Scene {
static int SC_ITEIntroFaireTentProc(int param, void *refCon);
private:
- EventColumns *ITEQueueDialogue(EventColumns *eventColumns, int n_dialogues, const IntroDialogue dialogue[]);
- EventColumns *ITEQueueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]);
+ EventColumns *queueIntroDialogue(EventColumns *eventColumns, int n_dialogues, const IntroDialogue dialogue[]);
+ EventColumns *queueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]);
int ITEIntroAnimProc(int param);
- int ITEIntroCave1Proc(int param);
- int ITEIntroCave2Proc(int param);
- int ITEIntroCave3Proc(int param);
- int ITEIntroCave4Proc(int param);
+ int ITEIntroCaveCommonProc(int param, int caveScene);
int ITEIntroValleyProc(int param);
int ITEIntroTreeHouseProc(int param);
int ITEIntroFairePathProc(int param);
diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp
index 91e39c54b6..cb963e23ac 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -139,7 +139,7 @@ void Script::setupITEScriptFuncList() {
void Script::sfPutString(SCRIPTFUNC_PARAMS) {
const char *str = thread->_strings->getString(thread->pop());
- _vm->_console->DebugPrintf("sfPutString: %s\n",str);
+ _vm->_console->debugPrintf("sfPutString: %s\n",str);
debug(0, "sfPutString: %s", str);
}
diff --git a/engines/saga/sfuncs_ihnm.cpp b/engines/saga/sfuncs_ihnm.cpp
index 6957360942..e3e3c1ca11 100644
--- a/engines/saga/sfuncs_ihnm.cpp
+++ b/engines/saga/sfuncs_ihnm.cpp
@@ -421,14 +421,7 @@ void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) {
warning("sfQueueMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTable.size() - 1);
} else {
_vm->_music->setVolume(_vm->_musicVolume, 1);
- event.type = kEvTOneshot;
- event.code = kMusicEvent;
- event.param = _vm->_music->_songTable[param1];
- event.param2 = param2 ? MUSIC_LOOP : MUSIC_NORMAL;
- event.op = kEventPlay;
- event.time = _vm->ticksToMSec(1000);
-
- _vm->_events->queue(event);
+ _vm->_events->queueMusic(_vm->_music->_songTable[param1], param2, _vm->ticksToMSec(1000));
if (!_vm->_scene->haveChapterPointsChanged()) {
_vm->_scene->setCurrentMusicTrack(param1);
diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp
index 426430c892..1e1c397212 100644
--- a/engines/saga/shorten.cpp
+++ b/engines/saga/shorten.cpp
@@ -29,6 +29,8 @@
// Based on etree's Shorten tool, version 3.6.1
// http://etree.org/shnutils/shorten/
+// and
+// https://github.com/soiaf/Java-Shorten-decoder
// FIXME: This doesn't work yet correctly
@@ -154,6 +156,7 @@ uint32 ShortenGolombReader::getUint32(uint32 numBits) {
byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, byte &flags) {
int32 *buffer[2], *offset[2]; // up to 2 channels
+ int32 *oldValues[2];
byte *unpackedBuffer = 0;
byte *pBuf = unpackedBuffer;
int prevSize = 0;
@@ -190,15 +193,18 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
switch (type) {
case kTypeS8:
+ mean = 0;
break;
case kTypeU8:
flags |= Audio::FLAG_UNSIGNED;
+ mean = 0x80;
break;
case kTypeS16LH:
flags |= Audio::FLAG_LITTLE_ENDIAN;
// fallthrough
case kTypeS16HL:
flags |= Audio::FLAG_16BITS;
+ mean = 0;
break;
case kTypeU16LH:
flags |= Audio::FLAG_LITTLE_ENDIAN;
@@ -206,6 +212,7 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
case kTypeU16HL:
flags |= Audio::FLAG_16BITS;
flags |= Audio::FLAG_UNSIGNED;
+ mean = 0x8000;
break;
case kTypeWAV:
// TODO: Perhaps implement this if we find WAV Shorten encoded files
@@ -264,8 +271,10 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
for (i = 0; i < channels; i++) {
buffer[i] = (int32 *)malloc((blockSize + wrap) * 4);
offset[i] = (int32 *)malloc((MAX<uint32>(1, mean)) * 4);
+ oldValues[i] = (int32 *)malloc(64 * 4);
memset(buffer[i], 0, (blockSize + wrap) * 4);
memset(offset[i], 0, (MAX<uint32>(1, mean)) * 4);
+ memset(oldValues[i], 0, 64 * 4);
}
if (maxLPC > 0)
@@ -329,9 +338,6 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
channelOffset = (channelOffset >> (bitShift - 1)) >> 1;
}
- // FIXME: The original code in this bit tries to modify memory outside of the array (negative indices)
- // in cases kCmdDiff1, kCmdDiff2 and kCmdDiff3
- // I've removed those invalid writes, since they happen all the time (even when curChannel is 0)
switch (cmd) {
case kCmdZero:
for (i = 0; i < blockSize; i++)
@@ -342,22 +348,34 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
buffer[curChannel][i] = gReader->getSRice(energy) + channelOffset;
break;
case kCmdDiff1:
- gReader->getSRice(energy); // i = 0 (to fix invalid table/memory access)
- for (i = 1; i < blockSize; i++)
- buffer[curChannel][i] = gReader->getSRice(energy) + buffer[curChannel][i - 1];
+ for (i = 0; i < blockSize; i++) {
+ if (i == 0)
+ buffer[curChannel][i] = gReader->getSRice(energy) + oldValues[curChannel][0];
+ else
+ buffer[curChannel][i] = gReader->getSRice(energy) + buffer[curChannel][i - 1];
+ }
break;
case kCmdDiff2:
- gReader->getSRice(energy); // i = 0 (to fix invalid table/memory access)
- gReader->getSRice(energy); // i = 1 (to fix invalid table/memory access)
- for (i = 2; i < blockSize; i++)
- buffer[curChannel][i] = gReader->getSRice(energy) + 2 * buffer[curChannel][i - 1] - buffer[curChannel][i - 2];
+ for (i = 0; i < blockSize; i++) {
+ if (i == 0)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 2 * oldValues[curChannel][0] - oldValues[curChannel][1];
+ else if (i == 1)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 2 * buffer[curChannel][0] - oldValues[curChannel][0];
+ else
+ buffer[curChannel][i] = gReader->getSRice(energy) + 2 * buffer[curChannel][i - 1] - buffer[curChannel][i - 2];
+ }
break;
case kCmdDiff3:
- gReader->getSRice(energy); // i = 0 (to fix invalid table/memory access)
- gReader->getSRice(energy); // i = 1 (to fix invalid table/memory access)
- gReader->getSRice(energy); // i = 2 (to fix invalid table/memory access)
- for (i = 3; i < blockSize; i++)
- buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (buffer[curChannel][i - 1] - buffer[curChannel][i - 2]) + buffer[curChannel][i - 3];
+ for (i = 0; i < blockSize; i++) {
+ if (i == 0)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (oldValues[curChannel][0] - oldValues[curChannel][1]) + oldValues[curChannel][2];
+ else if (i == 1)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (buffer[curChannel][0] - oldValues[curChannel][0]) + oldValues[curChannel][1];
+ else if (i == 2)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (buffer[curChannel][1] - buffer[curChannel][0]) + oldValues[curChannel][0];
+ else
+ buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (buffer[curChannel][i - 1] - buffer[curChannel][i - 2]) + buffer[curChannel][i - 3];
+ }
break;
case kCmdQLPC:
lpcNum = gReader->getURice(2);
@@ -417,10 +435,12 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
// Do the wrap
- // FIXME: removed for now, as this corrupts the heap, because it
- // accesses negative array indices
- //for (int32 k = -wrap; k < 0; k++)
- // buffer[curChannel][k] = buffer[curChannel][k + blockSize];
+ for (i = 0; i < 64; ++i)
+ oldValues[curChannel][i] = 0;
+
+ uint arrayTerminator = MIN<int>(64, blockSize);
+ for (i = 0; i < arrayTerminator; ++i)
+ oldValues[curChannel][i] = buffer[curChannel][blockSize - (i + 1)];
// Fix bitshift
if (bitShift > 0) {
@@ -495,6 +515,7 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
for (i = 0; i < channels; i++) {
free(buffer[i]);
free(offset[i]);
+ free(oldValues[i]);
}
if (maxLPC > 0)
@@ -516,6 +537,7 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
for (i = 0; i < channels; i++) {
free(buffer[i]);
free(offset[i]);
+ free(oldValues[i]);
}
if (maxLPC > 0)
diff --git a/engines/saga/sndres.h b/engines/saga/sndres.h
index 554eed4a27..5115873d76 100644
--- a/engines/saga/sndres.h
+++ b/engines/saga/sndres.h
@@ -45,6 +45,7 @@ public:
void playVoice(uint32 resourceId);
int getVoiceLength(uint32 resourceId);
void setVoiceBank(int serial);
+ int getVoiceBank() { return _voiceSerial; }
Common::Array<FxTable> _fxTable;
diff --git a/engines/savestate.h b/engines/savestate.h
index 970e01485d..54eff0f8cb 100644
--- a/engines/savestate.h
+++ b/engines/savestate.h
@@ -140,7 +140,7 @@ public:
* Sets the time the game was played before the save state was created.
*
* @param hours How many hours the user played the game so far.
- * @param min How many minutes the user played the game so far.
+ * @param minutes How many minutes the user played the game so far.
*/
void setPlayTime(int hours, int minutes);
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 1bc0dd067c..565e9752c3 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -79,148 +79,151 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
assert(_engine->_gamestate);
// Variables
- DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0);
- DVar_Register("gc_interval", &engine->_gamestate->scriptGCInterval, DVAR_INT, 0);
- DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0);
- DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0);
- DVar_Register("script_abort_flag", &_engine->_gamestate->abortScriptProcessing, DVAR_INT, 0);
+ registerVar("sleeptime_factor", &g_debug_sleeptime_factor);
+ registerVar("gc_interval", &engine->_gamestate->scriptGCInterval);
+ registerVar("simulated_key", &g_debug_simulated_key);
+ registerVar("track_mouse_clicks", &g_debug_track_mouse_clicks);
+ // FIXME: This actually passes an enum type instead of an integer but no
+ // precaution is taken to assure that all assigned values are in the range
+ // of the enum type. We should handle this more carefully...
+ registerVar("script_abort_flag", (int *)&_engine->_gamestate->abortScriptProcessing);
// General
- DCmd_Register("help", WRAP_METHOD(Console, cmdHelp));
+ registerCmd("help", WRAP_METHOD(Console, cmdHelp));
// Kernel
-// DCmd_Register("classes", WRAP_METHOD(Console, cmdClasses)); // TODO
- DCmd_Register("opcodes", WRAP_METHOD(Console, cmdOpcodes));
- DCmd_Register("selector", WRAP_METHOD(Console, cmdSelector));
- DCmd_Register("selectors", WRAP_METHOD(Console, cmdSelectors));
- DCmd_Register("functions", WRAP_METHOD(Console, cmdKernelFunctions));
- DCmd_Register("class_table", WRAP_METHOD(Console, cmdClassTable));
+// registerCmd("classes", WRAP_METHOD(Console, cmdClasses)); // TODO
+ registerCmd("opcodes", WRAP_METHOD(Console, cmdOpcodes));
+ registerCmd("selector", WRAP_METHOD(Console, cmdSelector));
+ registerCmd("selectors", WRAP_METHOD(Console, cmdSelectors));
+ registerCmd("functions", WRAP_METHOD(Console, cmdKernelFunctions));
+ registerCmd("class_table", WRAP_METHOD(Console, cmdClassTable));
// Parser
- DCmd_Register("suffixes", WRAP_METHOD(Console, cmdSuffixes));
- DCmd_Register("parse_grammar", WRAP_METHOD(Console, cmdParseGrammar));
- DCmd_Register("parser_nodes", WRAP_METHOD(Console, cmdParserNodes));
- DCmd_Register("parser_words", WRAP_METHOD(Console, cmdParserWords));
- DCmd_Register("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments));
- DCmd_Register("parse", WRAP_METHOD(Console, cmdParse));
- DCmd_Register("set_parse_nodes", WRAP_METHOD(Console, cmdSetParseNodes));
- DCmd_Register("said", WRAP_METHOD(Console, cmdSaid));
+ registerCmd("suffixes", WRAP_METHOD(Console, cmdSuffixes));
+ registerCmd("parse_grammar", WRAP_METHOD(Console, cmdParseGrammar));
+ registerCmd("parser_nodes", WRAP_METHOD(Console, cmdParserNodes));
+ registerCmd("parser_words", WRAP_METHOD(Console, cmdParserWords));
+ registerCmd("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments));
+ registerCmd("parse", WRAP_METHOD(Console, cmdParse));
+ registerCmd("set_parse_nodes", WRAP_METHOD(Console, cmdSetParseNodes));
+ registerCmd("said", WRAP_METHOD(Console, cmdSaid));
// Resources
- DCmd_Register("diskdump", WRAP_METHOD(Console, cmdDiskDump));
- DCmd_Register("hexdump", WRAP_METHOD(Console, cmdHexDump));
- DCmd_Register("resource_id", WRAP_METHOD(Console, cmdResourceId));
- DCmd_Register("resource_info", WRAP_METHOD(Console, cmdResourceInfo));
- DCmd_Register("resource_types", WRAP_METHOD(Console, cmdResourceTypes));
- DCmd_Register("list", WRAP_METHOD(Console, cmdList));
- DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep));
- DCmd_Register("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts));
+ registerCmd("diskdump", WRAP_METHOD(Console, cmdDiskDump));
+ registerCmd("hexdump", WRAP_METHOD(Console, cmdHexDump));
+ registerCmd("resource_id", WRAP_METHOD(Console, cmdResourceId));
+ registerCmd("resource_info", WRAP_METHOD(Console, cmdResourceInfo));
+ registerCmd("resource_types", WRAP_METHOD(Console, cmdResourceTypes));
+ registerCmd("list", WRAP_METHOD(Console, cmdList));
+ registerCmd("hexgrep", WRAP_METHOD(Console, cmdHexgrep));
+ registerCmd("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts));
// Game
- DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame));
- DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame));
- DCmd_Register("restart_game", WRAP_METHOD(Console, cmdRestartGame));
- DCmd_Register("version", WRAP_METHOD(Console, cmdGetVersion));
- DCmd_Register("room", WRAP_METHOD(Console, cmdRoomNumber));
- DCmd_Register("quit", WRAP_METHOD(Console, cmdQuit));
- DCmd_Register("list_saves", WRAP_METHOD(Console, cmdListSaves));
+ registerCmd("save_game", WRAP_METHOD(Console, cmdSaveGame));
+ registerCmd("restore_game", WRAP_METHOD(Console, cmdRestoreGame));
+ registerCmd("restart_game", WRAP_METHOD(Console, cmdRestartGame));
+ registerCmd("version", WRAP_METHOD(Console, cmdGetVersion));
+ registerCmd("room", WRAP_METHOD(Console, cmdRoomNumber));
+ registerCmd("quit", WRAP_METHOD(Console, cmdQuit));
+ registerCmd("list_saves", WRAP_METHOD(Console, cmdListSaves));
// Graphics
- DCmd_Register("show_map", WRAP_METHOD(Console, cmdShowMap));
- DCmd_Register("set_palette", WRAP_METHOD(Console, cmdSetPalette));
- DCmd_Register("draw_pic", WRAP_METHOD(Console, cmdDrawPic));
- DCmd_Register("draw_cel", WRAP_METHOD(Console, cmdDrawCel));
- DCmd_Register("undither", WRAP_METHOD(Console, cmdUndither));
- DCmd_Register("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize));
- DCmd_Register("play_video", WRAP_METHOD(Console, cmdPlayVideo));
- DCmd_Register("animate_list", WRAP_METHOD(Console, cmdAnimateList));
- DCmd_Register("al", WRAP_METHOD(Console, cmdAnimateList)); // alias
- DCmd_Register("window_list", WRAP_METHOD(Console, cmdWindowList));
- DCmd_Register("wl", WRAP_METHOD(Console, cmdWindowList)); // alias
- DCmd_Register("plane_list", WRAP_METHOD(Console, cmdPlaneList));
- DCmd_Register("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias
- DCmd_Register("plane_items", WRAP_METHOD(Console, cmdPlaneItemList));
- DCmd_Register("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias
- DCmd_Register("saved_bits", WRAP_METHOD(Console, cmdSavedBits));
- DCmd_Register("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits));
+ registerCmd("show_map", WRAP_METHOD(Console, cmdShowMap));
+ registerCmd("set_palette", WRAP_METHOD(Console, cmdSetPalette));
+ registerCmd("draw_pic", WRAP_METHOD(Console, cmdDrawPic));
+ registerCmd("draw_cel", WRAP_METHOD(Console, cmdDrawCel));
+ registerCmd("undither", WRAP_METHOD(Console, cmdUndither));
+ registerCmd("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize));
+ registerCmd("play_video", WRAP_METHOD(Console, cmdPlayVideo));
+ registerCmd("animate_list", WRAP_METHOD(Console, cmdAnimateList));
+ registerCmd("al", WRAP_METHOD(Console, cmdAnimateList)); // alias
+ registerCmd("window_list", WRAP_METHOD(Console, cmdWindowList));
+ registerCmd("wl", WRAP_METHOD(Console, cmdWindowList)); // alias
+ registerCmd("plane_list", WRAP_METHOD(Console, cmdPlaneList));
+ registerCmd("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias
+ registerCmd("plane_items", WRAP_METHOD(Console, cmdPlaneItemList));
+ registerCmd("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias
+ registerCmd("saved_bits", WRAP_METHOD(Console, cmdSavedBits));
+ registerCmd("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits));
// Segments
- DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable));
- DCmd_Register("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias
- DCmd_Register("segment_info", WRAP_METHOD(Console, cmdSegmentInfo));
- DCmd_Register("seginfo", WRAP_METHOD(Console, cmdSegmentInfo)); // alias
- DCmd_Register("segment_kill", WRAP_METHOD(Console, cmdKillSegment));
- DCmd_Register("segkill", WRAP_METHOD(Console, cmdKillSegment)); // alias
+ registerCmd("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable));
+ registerCmd("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias
+ registerCmd("segment_info", WRAP_METHOD(Console, cmdSegmentInfo));
+ registerCmd("seginfo", WRAP_METHOD(Console, cmdSegmentInfo)); // alias
+ registerCmd("segment_kill", WRAP_METHOD(Console, cmdKillSegment));
+ registerCmd("segkill", WRAP_METHOD(Console, cmdKillSegment)); // alias
// Garbage collection
- DCmd_Register("gc", WRAP_METHOD(Console, cmdGCInvoke));
- DCmd_Register("gc_objects", WRAP_METHOD(Console, cmdGCObjects));
- DCmd_Register("gc_reachable", WRAP_METHOD(Console, cmdGCShowReachable));
- DCmd_Register("gc_freeable", WRAP_METHOD(Console, cmdGCShowFreeable));
- DCmd_Register("gc_normalize", WRAP_METHOD(Console, cmdGCNormalize));
+ registerCmd("gc", WRAP_METHOD(Console, cmdGCInvoke));
+ registerCmd("gc_objects", WRAP_METHOD(Console, cmdGCObjects));
+ registerCmd("gc_reachable", WRAP_METHOD(Console, cmdGCShowReachable));
+ registerCmd("gc_freeable", WRAP_METHOD(Console, cmdGCShowFreeable));
+ registerCmd("gc_normalize", WRAP_METHOD(Console, cmdGCNormalize));
// Music/SFX
- DCmd_Register("songlib", WRAP_METHOD(Console, cmdSongLib));
- DCmd_Register("songinfo", WRAP_METHOD(Console, cmdSongInfo));
- DCmd_Register("is_sample", WRAP_METHOD(Console, cmdIsSample));
- DCmd_Register("startsound", WRAP_METHOD(Console, cmdStartSound));
- DCmd_Register("togglesound", WRAP_METHOD(Console, cmdToggleSound));
- DCmd_Register("stopallsounds", WRAP_METHOD(Console, cmdStopAllSounds));
- DCmd_Register("sfx01_header", WRAP_METHOD(Console, cmdSfx01Header));
- DCmd_Register("sfx01_track", WRAP_METHOD(Console, cmdSfx01Track));
- DCmd_Register("show_instruments", WRAP_METHOD(Console, cmdShowInstruments));
- DCmd_Register("map_instrument", WRAP_METHOD(Console, cmdMapInstrument));
+ registerCmd("songlib", WRAP_METHOD(Console, cmdSongLib));
+ registerCmd("songinfo", WRAP_METHOD(Console, cmdSongInfo));
+ registerCmd("is_sample", WRAP_METHOD(Console, cmdIsSample));
+ registerCmd("startsound", WRAP_METHOD(Console, cmdStartSound));
+ registerCmd("togglesound", WRAP_METHOD(Console, cmdToggleSound));
+ registerCmd("stopallsounds", WRAP_METHOD(Console, cmdStopAllSounds));
+ registerCmd("sfx01_header", WRAP_METHOD(Console, cmdSfx01Header));
+ registerCmd("sfx01_track", WRAP_METHOD(Console, cmdSfx01Track));
+ registerCmd("show_instruments", WRAP_METHOD(Console, cmdShowInstruments));
+ registerCmd("map_instrument", WRAP_METHOD(Console, cmdMapInstrument));
// Script
- DCmd_Register("addresses", WRAP_METHOD(Console, cmdAddresses));
- DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters));
- DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript));
- DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace));
- DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias
- DCmd_Register("trace", WRAP_METHOD(Console, cmdTrace));
- DCmd_Register("t", WRAP_METHOD(Console, cmdTrace)); // alias
- DCmd_Register("s", WRAP_METHOD(Console, cmdTrace)); // alias
- DCmd_Register("stepover", WRAP_METHOD(Console, cmdStepOver));
- DCmd_Register("p", WRAP_METHOD(Console, cmdStepOver)); // alias
- DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet));
- DCmd_Register("pret", WRAP_METHOD(Console, cmdStepRet)); // alias
- DCmd_Register("step_event", WRAP_METHOD(Console, cmdStepEvent));
- DCmd_Register("se", WRAP_METHOD(Console, cmdStepEvent)); // alias
- DCmd_Register("step_global", WRAP_METHOD(Console, cmdStepGlobal));
- DCmd_Register("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias
- DCmd_Register("step_callk", WRAP_METHOD(Console, cmdStepCallk));
- DCmd_Register("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias
- DCmd_Register("disasm", WRAP_METHOD(Console, cmdDisassemble));
- DCmd_Register("disasm_addr", WRAP_METHOD(Console, cmdDisassembleAddress));
- DCmd_Register("find_callk", WRAP_METHOD(Console, cmdFindKernelFunctionCall));
- DCmd_Register("send", WRAP_METHOD(Console, cmdSend));
- DCmd_Register("go", WRAP_METHOD(Console, cmdGo));
- DCmd_Register("logkernel", WRAP_METHOD(Console, cmdLogKernel));
+ registerCmd("addresses", WRAP_METHOD(Console, cmdAddresses));
+ registerCmd("registers", WRAP_METHOD(Console, cmdRegisters));
+ registerCmd("dissect_script", WRAP_METHOD(Console, cmdDissectScript));
+ registerCmd("backtrace", WRAP_METHOD(Console, cmdBacktrace));
+ registerCmd("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias
+ registerCmd("trace", WRAP_METHOD(Console, cmdTrace));
+ registerCmd("t", WRAP_METHOD(Console, cmdTrace)); // alias
+ registerCmd("s", WRAP_METHOD(Console, cmdTrace)); // alias
+ registerCmd("stepover", WRAP_METHOD(Console, cmdStepOver));
+ registerCmd("p", WRAP_METHOD(Console, cmdStepOver)); // alias
+ registerCmd("step_ret", WRAP_METHOD(Console, cmdStepRet));
+ registerCmd("pret", WRAP_METHOD(Console, cmdStepRet)); // alias
+ registerCmd("step_event", WRAP_METHOD(Console, cmdStepEvent));
+ registerCmd("se", WRAP_METHOD(Console, cmdStepEvent)); // alias
+ registerCmd("step_global", WRAP_METHOD(Console, cmdStepGlobal));
+ registerCmd("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias
+ registerCmd("step_callk", WRAP_METHOD(Console, cmdStepCallk));
+ registerCmd("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias
+ registerCmd("disasm", WRAP_METHOD(Console, cmdDisassemble));
+ registerCmd("disasm_addr", WRAP_METHOD(Console, cmdDisassembleAddress));
+ registerCmd("find_callk", WRAP_METHOD(Console, cmdFindKernelFunctionCall));
+ registerCmd("send", WRAP_METHOD(Console, cmdSend));
+ registerCmd("go", WRAP_METHOD(Console, cmdGo));
+ registerCmd("logkernel", WRAP_METHOD(Console, cmdLogKernel));
// Breakpoints
- DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList));
- DCmd_Register("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias
- DCmd_Register("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias
- DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete));
- DCmd_Register("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
- DCmd_Register("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
- DCmd_Register("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod));
- DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias
- DCmd_Register("bp_read", WRAP_METHOD(Console, cmdBreakpointRead));
- DCmd_Register("bpr", WRAP_METHOD(Console, cmdBreakpointRead)); // alias
- DCmd_Register("bp_write", WRAP_METHOD(Console, cmdBreakpointWrite));
- DCmd_Register("bpw", WRAP_METHOD(Console, cmdBreakpointWrite)); // alias
- DCmd_Register("bp_kernel", WRAP_METHOD(Console, cmdBreakpointKernel));
- DCmd_Register("bpk", WRAP_METHOD(Console, cmdBreakpointKernel)); // alias
- DCmd_Register("bp_function", WRAP_METHOD(Console, cmdBreakpointFunction));
- DCmd_Register("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias
+ registerCmd("bp_list", WRAP_METHOD(Console, cmdBreakpointList));
+ registerCmd("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias
+ registerCmd("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias
+ registerCmd("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete));
+ registerCmd("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
+ registerCmd("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
+ registerCmd("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod));
+ registerCmd("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias
+ registerCmd("bp_read", WRAP_METHOD(Console, cmdBreakpointRead));
+ registerCmd("bpr", WRAP_METHOD(Console, cmdBreakpointRead)); // alias
+ registerCmd("bp_write", WRAP_METHOD(Console, cmdBreakpointWrite));
+ registerCmd("bpw", WRAP_METHOD(Console, cmdBreakpointWrite)); // alias
+ registerCmd("bp_kernel", WRAP_METHOD(Console, cmdBreakpointKernel));
+ registerCmd("bpk", WRAP_METHOD(Console, cmdBreakpointKernel)); // alias
+ registerCmd("bp_function", WRAP_METHOD(Console, cmdBreakpointFunction));
+ registerCmd("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias
// VM
- DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps));
- DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist));
- DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias
- DCmd_Register("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias
- DCmd_Register("vm_vars", WRAP_METHOD(Console, cmdVMVars));
- DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias
- DCmd_Register("vv", WRAP_METHOD(Console, cmdVMVars)); // alias
- DCmd_Register("stack", WRAP_METHOD(Console, cmdStack));
- DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType));
- DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode));
- DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference));
- DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias
- DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject));
- DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias
- DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject));
- DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject));
+ registerCmd("script_steps", WRAP_METHOD(Console, cmdScriptSteps));
+ registerCmd("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist));
+ registerCmd("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias
+ registerCmd("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias
+ registerCmd("vm_vars", WRAP_METHOD(Console, cmdVMVars));
+ registerCmd("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias
+ registerCmd("vv", WRAP_METHOD(Console, cmdVMVars)); // alias
+ registerCmd("stack", WRAP_METHOD(Console, cmdStack));
+ registerCmd("value_type", WRAP_METHOD(Console, cmdValueType));
+ registerCmd("view_listnode", WRAP_METHOD(Console, cmdViewListNode));
+ registerCmd("view_reference", WRAP_METHOD(Console, cmdViewReference));
+ registerCmd("vr", WRAP_METHOD(Console, cmdViewReference)); // alias
+ registerCmd("view_object", WRAP_METHOD(Console, cmdViewObject));
+ registerCmd("vo", WRAP_METHOD(Console, cmdViewObject)); // alias
+ registerCmd("active_object", WRAP_METHOD(Console, cmdViewActiveObject));
+ registerCmd("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject));
_debugState.seeking = kDebugSeekNothing;
_debugState.seekLevel = 0;
@@ -307,137 +310,137 @@ void Console::postEnter() {
}
bool Console::cmdHelp(int argc, const char **argv) {
- DebugPrintf("\n");
- DebugPrintf("Variables\n");
- DebugPrintf("---------\n");
- DebugPrintf("sleeptime_factor: Factor to multiply with wait times in kWait()\n");
- DebugPrintf("gc_interval: Number of kernel calls in between garbage collections\n");
- DebugPrintf("simulated_key: Add a key with the specified scan code to the event list\n");
- DebugPrintf("track_mouse_clicks: Toggles mouse click tracking to the console\n");
- DebugPrintf("weak_validations: Turns some validation errors into warnings\n");
- DebugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n");
- DebugPrintf("\n");
- DebugPrintf("Debug flags\n");
- DebugPrintf("-----------\n");
- DebugPrintf("debugflag_list - Lists the available debug flags and their status\n");
- DebugPrintf("debugflag_enable - Enables a debug flag\n");
- DebugPrintf("debugflag_disable - Disables a debug flag\n");
- DebugPrintf("\n");
- DebugPrintf("Commands\n");
- DebugPrintf("--------\n");
- DebugPrintf("Kernel:\n");
- DebugPrintf(" opcodes - Lists the opcode names\n");
- DebugPrintf(" selectors - Lists the selector names\n");
- DebugPrintf(" selector - Attempts to find the requested selector by name\n");
- DebugPrintf(" functions - Lists the kernel functions\n");
- DebugPrintf(" class_table - Shows the available classes\n");
- DebugPrintf("\n");
- DebugPrintf("Parser:\n");
- DebugPrintf(" suffixes - Lists the vocabulary suffixes\n");
- DebugPrintf(" parse_grammar - Shows the parse grammar, in strict GNF\n");
- DebugPrintf(" parser_nodes - Shows the specified number of nodes from the parse node tree\n");
- DebugPrintf(" parser_words - Shows the words from the parse node tree\n");
- DebugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n");
- DebugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n");
- DebugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n");
- DebugPrintf(" said - Match a string against a said spec\n");
- DebugPrintf("\n");
- DebugPrintf("Resources:\n");
- DebugPrintf(" diskdump - Dumps the specified resource to disk as a patch file\n");
- DebugPrintf(" hexdump - Dumps the specified resource to standard output\n");
- DebugPrintf(" resource_id - Identifies a resource number by splitting it up in resource type and resource number\n");
- DebugPrintf(" resource_info - Shows info about a resource\n");
- DebugPrintf(" resource_types - Shows the valid resource types\n");
- DebugPrintf(" list - Lists all the resources of a given type\n");
- DebugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n");
- DebugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n");
- DebugPrintf("\n");
- DebugPrintf("Game:\n");
- DebugPrintf(" save_game - Saves the current game state to the hard disk\n");
- DebugPrintf(" restore_game - Restores a saved game from the hard disk\n");
- DebugPrintf(" list_saves - List all saved games including filenames\n");
- DebugPrintf(" restart_game - Restarts the game\n");
- DebugPrintf(" version - Shows the resource and interpreter versions\n");
- DebugPrintf(" room - Gets or sets the current room number\n");
- DebugPrintf(" quit - Quits the game\n");
- DebugPrintf("\n");
- DebugPrintf("Graphics:\n");
- DebugPrintf(" show_map - Switches to visual, priority, control or display screen\n");
- DebugPrintf(" set_palette - Sets a palette resource\n");
- DebugPrintf(" draw_pic - Draws a pic resource\n");
- DebugPrintf(" draw_cel - Draws a cel from a view resource\n");
- DebugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n");
- DebugPrintf(" undither - Enable/disable undithering\n");
- DebugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n");
- DebugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n");
- DebugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n");
- DebugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n");
- DebugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n");
- DebugPrintf(" saved_bits - List saved bits on the hunk\n");
- DebugPrintf(" show_saved_bits - Display saved bits\n");
- DebugPrintf("\n");
- DebugPrintf("Segments:\n");
- DebugPrintf(" segment_table / segtable - Lists all segments\n");
- DebugPrintf(" segment_info / seginfo - Provides information on the specified segment\n");
- DebugPrintf(" segment_kill / segkill - Deletes the specified segment\n");
- DebugPrintf("\n");
- DebugPrintf("Garbage collection:\n");
- DebugPrintf(" gc - Invokes the garbage collector\n");
- DebugPrintf(" gc_objects - Lists all reachable objects, normalized\n");
- DebugPrintf(" gc_reachable - Lists all addresses directly reachable from a given memory object\n");
- DebugPrintf(" gc_freeable - Lists all addresses freeable in a given segment\n");
- DebugPrintf(" gc_normalize - Prints the \"normal\" address of a given address\n");
- DebugPrintf("\n");
- DebugPrintf("Music/SFX:\n");
- DebugPrintf(" songlib - Shows the song library\n");
- DebugPrintf(" songinfo - Shows information about a specified song in the song library\n");
- DebugPrintf(" togglesound - Starts/stops a sound in the song library\n");
- DebugPrintf(" stopallsounds - Stops all sounds in the playlist\n");
- DebugPrintf(" startsound - Starts the specified sound resource, replacing the first song in the song library\n");
- DebugPrintf(" is_sample - Shows information on a given sound resource, if it's a PCM sample\n");
- DebugPrintf(" sfx01_header - Dumps the header of a SCI01 song\n");
- DebugPrintf(" sfx01_track - Dumps a track of a SCI01 song\n");
- DebugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n");
- DebugPrintf(" map_instrument - Dynamically maps an MT-32 instrument to a GM instrument\n");
- DebugPrintf("\n");
- DebugPrintf("Script:\n");
- DebugPrintf(" addresses - Provides information on how to pass addresses\n");
- DebugPrintf(" registers - Shows the current register values\n");
- DebugPrintf(" dissect_script - Examines a script\n");
- DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n");
- DebugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n");
- DebugPrintf(" stepover / p - Executes one operation, skips over call/send\n");
- DebugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n");
- DebugPrintf(" step_event / se - Steps forward until a SCI event is received.\n");
- DebugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n");
- DebugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n");
- DebugPrintf(" disasm - Disassembles a method by name\n");
- DebugPrintf(" disasm_addr - Disassembles one or more commands\n");
- DebugPrintf(" send - Sends a message to an object\n");
- DebugPrintf(" go - Executes the script\n");
- DebugPrintf(" logkernel - Logs kernel calls\n");
- DebugPrintf("\n");
- DebugPrintf("Breakpoints:\n");
- DebugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n");
- DebugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n");
- DebugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n");
- DebugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n");
- DebugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n");
- DebugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n");
- DebugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n");
- DebugPrintf("\n");
- DebugPrintf("VM:\n");
- DebugPrintf(" script_steps - Shows the number of executed SCI operations\n");
- DebugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n");
- DebugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n");
- DebugPrintf(" stack - Lists the specified number of stack elements\n");
- DebugPrintf(" value_type - Determines the type of a value\n");
- DebugPrintf(" view_listnode - Examines the list node at the given address\n");
- DebugPrintf(" view_reference / vr - Examines an arbitrary reference\n");
- DebugPrintf(" view_object / vo - Examines the object at the given address\n");
- DebugPrintf(" active_object - Shows information on the currently active object or class\n");
- DebugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n");
- DebugPrintf("\n");
+ debugPrintf("\n");
+ debugPrintf("Variables\n");
+ debugPrintf("---------\n");
+ debugPrintf("sleeptime_factor: Factor to multiply with wait times in kWait()\n");
+ debugPrintf("gc_interval: Number of kernel calls in between garbage collections\n");
+ debugPrintf("simulated_key: Add a key with the specified scan code to the event list\n");
+ debugPrintf("track_mouse_clicks: Toggles mouse click tracking to the console\n");
+ debugPrintf("weak_validations: Turns some validation errors into warnings\n");
+ debugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n");
+ debugPrintf("\n");
+ debugPrintf("Debug flags\n");
+ debugPrintf("-----------\n");
+ debugPrintf("debugflag_list - Lists the available debug flags and their status\n");
+ debugPrintf("debugflag_enable - Enables a debug flag\n");
+ debugPrintf("debugflag_disable - Disables a debug flag\n");
+ debugPrintf("\n");
+ debugPrintf("Commands\n");
+ debugPrintf("--------\n");
+ debugPrintf("Kernel:\n");
+ debugPrintf(" opcodes - Lists the opcode names\n");
+ debugPrintf(" selectors - Lists the selector names\n");
+ debugPrintf(" selector - Attempts to find the requested selector by name\n");
+ debugPrintf(" functions - Lists the kernel functions\n");
+ debugPrintf(" class_table - Shows the available classes\n");
+ debugPrintf("\n");
+ debugPrintf("Parser:\n");
+ debugPrintf(" suffixes - Lists the vocabulary suffixes\n");
+ debugPrintf(" parse_grammar - Shows the parse grammar, in strict GNF\n");
+ debugPrintf(" parser_nodes - Shows the specified number of nodes from the parse node tree\n");
+ debugPrintf(" parser_words - Shows the words from the parse node tree\n");
+ debugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n");
+ debugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n");
+ debugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n");
+ debugPrintf(" said - Match a string against a said spec\n");
+ debugPrintf("\n");
+ debugPrintf("Resources:\n");
+ debugPrintf(" diskdump - Dumps the specified resource to disk as a patch file\n");
+ debugPrintf(" hexdump - Dumps the specified resource to standard output\n");
+ debugPrintf(" resource_id - Identifies a resource number by splitting it up in resource type and resource number\n");
+ debugPrintf(" resource_info - Shows info about a resource\n");
+ debugPrintf(" resource_types - Shows the valid resource types\n");
+ debugPrintf(" list - Lists all the resources of a given type\n");
+ debugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n");
+ debugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n");
+ debugPrintf("\n");
+ debugPrintf("Game:\n");
+ debugPrintf(" save_game - Saves the current game state to the hard disk\n");
+ debugPrintf(" restore_game - Restores a saved game from the hard disk\n");
+ debugPrintf(" list_saves - List all saved games including filenames\n");
+ debugPrintf(" restart_game - Restarts the game\n");
+ debugPrintf(" version - Shows the resource and interpreter versions\n");
+ debugPrintf(" room - Gets or sets the current room number\n");
+ debugPrintf(" quit - Quits the game\n");
+ debugPrintf("\n");
+ debugPrintf("Graphics:\n");
+ debugPrintf(" show_map - Switches to visual, priority, control or display screen\n");
+ debugPrintf(" set_palette - Sets a palette resource\n");
+ debugPrintf(" draw_pic - Draws a pic resource\n");
+ debugPrintf(" draw_cel - Draws a cel from a view resource\n");
+ debugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n");
+ debugPrintf(" undither - Enable/disable undithering\n");
+ debugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n");
+ debugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n");
+ debugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n");
+ debugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n");
+ debugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n");
+ debugPrintf(" saved_bits - List saved bits on the hunk\n");
+ debugPrintf(" show_saved_bits - Display saved bits\n");
+ debugPrintf("\n");
+ debugPrintf("Segments:\n");
+ debugPrintf(" segment_table / segtable - Lists all segments\n");
+ debugPrintf(" segment_info / seginfo - Provides information on the specified segment\n");
+ debugPrintf(" segment_kill / segkill - Deletes the specified segment\n");
+ debugPrintf("\n");
+ debugPrintf("Garbage collection:\n");
+ debugPrintf(" gc - Invokes the garbage collector\n");
+ debugPrintf(" gc_objects - Lists all reachable objects, normalized\n");
+ debugPrintf(" gc_reachable - Lists all addresses directly reachable from a given memory object\n");
+ debugPrintf(" gc_freeable - Lists all addresses freeable in a given segment\n");
+ debugPrintf(" gc_normalize - Prints the \"normal\" address of a given address\n");
+ debugPrintf("\n");
+ debugPrintf("Music/SFX:\n");
+ debugPrintf(" songlib - Shows the song library\n");
+ debugPrintf(" songinfo - Shows information about a specified song in the song library\n");
+ debugPrintf(" togglesound - Starts/stops a sound in the song library\n");
+ debugPrintf(" stopallsounds - Stops all sounds in the playlist\n");
+ debugPrintf(" startsound - Starts the specified sound resource, replacing the first song in the song library\n");
+ debugPrintf(" is_sample - Shows information on a given sound resource, if it's a PCM sample\n");
+ debugPrintf(" sfx01_header - Dumps the header of a SCI01 song\n");
+ debugPrintf(" sfx01_track - Dumps a track of a SCI01 song\n");
+ debugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n");
+ debugPrintf(" map_instrument - Dynamically maps an MT-32 instrument to a GM instrument\n");
+ debugPrintf("\n");
+ debugPrintf("Script:\n");
+ debugPrintf(" addresses - Provides information on how to pass addresses\n");
+ debugPrintf(" registers - Shows the current register values\n");
+ debugPrintf(" dissect_script - Examines a script\n");
+ debugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n");
+ debugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n");
+ debugPrintf(" stepover / p - Executes one operation, skips over call/send\n");
+ debugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n");
+ debugPrintf(" step_event / se - Steps forward until a SCI event is received.\n");
+ debugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n");
+ debugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n");
+ debugPrintf(" disasm - Disassembles a method by name\n");
+ debugPrintf(" disasm_addr - Disassembles one or more commands\n");
+ debugPrintf(" send - Sends a message to an object\n");
+ debugPrintf(" go - Executes the script\n");
+ debugPrintf(" logkernel - Logs kernel calls\n");
+ debugPrintf("\n");
+ debugPrintf("Breakpoints:\n");
+ debugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n");
+ debugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n");
+ debugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n");
+ debugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n");
+ debugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n");
+ debugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n");
+ debugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n");
+ debugPrintf("\n");
+ debugPrintf("VM:\n");
+ debugPrintf(" script_steps - Shows the number of executed SCI operations\n");
+ debugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n");
+ debugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n");
+ debugPrintf(" stack - Lists the specified number of stack elements\n");
+ debugPrintf(" value_type - Determines the type of a value\n");
+ debugPrintf(" view_listnode - Examines the list node at the given address\n");
+ debugPrintf(" view_reference / vr - Examines an arbitrary reference\n");
+ debugPrintf(" view_object / vo - Examines the object at the given address\n");
+ debugPrintf(" active_object - Shows information on the currently active object or class\n");
+ debugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n");
+ debugPrintf("\n");
return true;
}
@@ -464,30 +467,30 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
versionFile.close();
}
- DebugPrintf("Game ID: %s\n", _engine->getGameIdStr());
- DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion()));
- DebugPrintf("\n");
- DebugPrintf("Detected features:\n");
- DebugPrintf("------------------\n");
- DebugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType()));
- DebugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType()));
- DebugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType()));
- DebugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore");
- DebugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType()));
+ debugPrintf("Game ID: %s\n", _engine->getGameIdStr());
+ debugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion()));
+ debugPrintf("\n");
+ debugPrintf("Detected features:\n");
+ debugPrintf("------------------\n");
+ debugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType()));
+ debugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType()));
+ debugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType()));
+ debugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore");
+ debugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType()));
#ifdef ENABLE_SCI32
if (getSciVersion() >= SCI_VERSION_2)
- DebugPrintf("kString type: %s\n", (_engine->_features->detectSci2StringFunctionType() == kSci2StringFunctionOld) ? "SCI2 (old)" : "SCI2.1 (new)");
+ debugPrintf("kString type: %s\n", (_engine->_features->detectSci2StringFunctionType() == kSci2StringFunctionOld) ? "SCI2 (old)" : "SCI2.1 (new)");
if (getSciVersion() == SCI_VERSION_2_1)
- DebugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)");
+ debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)");
#endif
- DebugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]);
- DebugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no");
- DebugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc());
- DebugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc());
- DebugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no");
- DebugPrintf("Has CantBeHere selector: %s\n", g_sci->getKernel()->_selectorCache.cantBeHere != -1 ? "yes" : "no");
- DebugPrintf("Game version (VERSION file): %s\n", gameVersion.c_str());
- DebugPrintf("\n");
+ debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]);
+ debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no");
+ debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc());
+ debugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc());
+ debugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no");
+ debugPrintf("Has CantBeHere selector: %s\n", g_sci->getKernel()->_selectorCache.cantBeHere != -1 ? "yes" : "no");
+ debugPrintf("Game version (VERSION file): %s\n", gameVersion.c_str());
+ debugPrintf("\n");
return true;
}
@@ -498,13 +501,13 @@ bool Console::cmdOpcodes(int argc, const char **argv) {
// If the resource couldn't be loaded, leave
if (!r) {
- DebugPrintf("unable to load vocab.998");
+ debugPrintf("unable to load vocab.998");
return true;
}
int count = READ_LE_UINT16(r->data);
- DebugPrintf("Opcode names in numeric order [index: type name]:\n");
+ debugPrintf("Opcode names in numeric order [index: type name]:\n");
for (int i = 0; i < count; i++) {
int offset = READ_LE_UINT16(r->data + 2 + i * 2);
@@ -512,49 +515,49 @@ bool Console::cmdOpcodes(int argc, const char **argv) {
int type = READ_LE_UINT16(r->data + offset + 2);
// QFG3 has empty opcodes
Common::String name = len > 0 ? Common::String((const char *)r->data + offset + 4, len) : "Dummy";
- DebugPrintf("%03x: %03x %20s | ", i, type, name.c_str());
+ debugPrintf("%03x: %03x %20s | ", i, type, name.c_str());
if ((i % 3) == 2)
- DebugPrintf("\n");
+ debugPrintf("\n");
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
bool Console::cmdSelector(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Attempts to find the requested selector by name.\n");
- DebugPrintf("Usage: %s <selector name>\n", argv[0]);
+ debugPrintf("Attempts to find the requested selector by name.\n");
+ debugPrintf("Usage: %s <selector name>\n", argv[0]);
return true;
}
Common::String name = argv[1];
int seeker = _engine->getKernel()->findSelector(name.c_str());
if (seeker >= 0) {
- DebugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker);
+ debugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker);
return true;
}
- DebugPrintf("Selector %s wasn't found\n", name.c_str());
+ debugPrintf("Selector %s wasn't found\n", name.c_str());
return true;
}
bool Console::cmdSelectors(int argc, const char **argv) {
- DebugPrintf("Selector names in numeric order:\n");
+ debugPrintf("Selector names in numeric order:\n");
Common::String selectorName;
for (uint seeker = 0; seeker < _engine->getKernel()->getSelectorNamesSize(); seeker++) {
selectorName = _engine->getKernel()->getSelectorName(seeker);
if (selectorName != "BAD SELECTOR")
- DebugPrintf("%03x: %20s | ", seeker, selectorName.c_str());
+ debugPrintf("%03x: %20s | ", seeker, selectorName.c_str());
else
continue;
if ((seeker % 3) == 2)
- DebugPrintf("\n");
+ debugPrintf("\n");
}
- DebugPrintf("\n");
+ debugPrintf("\n");
#if 0
// For debug/development
@@ -584,14 +587,14 @@ bool Console::cmdSelectors(int argc, const char **argv) {
}
bool Console::cmdKernelFunctions(int argc, const char **argv) {
- DebugPrintf("Kernel function names in numeric order:\n");
+ debugPrintf("Kernel function names in numeric order:\n");
for (uint seeker = 0; seeker < _engine->getKernel()->getKernelNamesSize(); seeker++) {
- DebugPrintf("%03x: %20s | ", seeker, _engine->getKernel()->getKernelName(seeker).c_str());
+ debugPrintf("%03x: %20s | ", seeker, _engine->getKernel()->getKernelName(seeker).c_str());
if ((seeker % 3) == 2)
- DebugPrintf("\n");
+ debugPrintf("\n");
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
@@ -610,9 +613,9 @@ bool Console::cmdParserWords(int argc, const char **argv) {
bool Console::cmdSetParseNodes(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Sets the contents of all parse nodes.\n");
- DebugPrintf("Usage: %s <parse node1> <parse node2> ... <parse noden>\n", argv[0]);
- DebugPrintf("Tokens should be separated by blanks and enclosed in parentheses\n");
+ debugPrintf("Sets the contents of all parse nodes.\n");
+ debugPrintf("Usage: %s <parse node1> <parse node2> ... <parse noden>\n", argv[0]);
+ debugPrintf("Tokens should be separated by blanks and enclosed in parentheses\n");
return true;
}
@@ -643,46 +646,62 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) {
bool Console::cmdRegisters(int argc, const char **argv) {
EngineState *s = _engine->_gamestate;
- DebugPrintf("Current register values:\n");
- DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->r_rest);
+ debugPrintf("Current register values:\n");
+ debugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->r_rest);
if (!s->_executionStack.empty()) {
- DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n",
+ debugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n",
PRINT_REG(s->xs->addr.pc), PRINT_REG(s->xs->objp),
(unsigned)(s->xs->fp - s->stack_base), (unsigned)(s->xs->sp - s->stack_base));
} else
- DebugPrintf("<no execution stack: pc,obj,fp omitted>\n");
+ debugPrintf("<no execution stack: pc,obj,fp omitted>\n");
return true;
}
bool Console::cmdDiskDump(int argc, const char **argv) {
+ int resNumFrom = 0;
+ int resNumTo = 0;
+ int resNumCur = 0;
+
if (argc != 3) {
- DebugPrintf("Dumps the specified resource to disk as a patch file\n");
- DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]);
+ debugPrintf("Dumps the specified resource to disk as a patch file\n");
+ debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]);
+ debugPrintf(" <resource number> may be '*' to dump all resources of given type\n");
cmdResourceTypes(argc, argv);
return true;
}
+
+ if (strcmp(argv[2], "*") == 0) {
+ resNumFrom = 0;
+ resNumTo = 65535;
+ } else {
+ resNumFrom = atoi(argv[2]);
+ resNumTo = resNumFrom;
+ }
- int resNum = atoi(argv[2]);
ResourceType res = parseResourceType(argv[1]);
if (res == kResourceTypeInvalid)
- DebugPrintf("Resource type '%s' is not valid\n", argv[1]);
+ debugPrintf("Resource type '%s' is not valid\n", argv[1]);
else {
- Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0);
- if (resource) {
- char outFileName[50];
- sprintf(outFileName, "%s.%03d", getResourceTypeName(res), resNum);
- Common::DumpFile *outFile = new Common::DumpFile();
- outFile->open(outFileName);
- resource->writeToStream(outFile);
- outFile->finalize();
- outFile->close();
- delete outFile;
- DebugPrintf("Resource %s.%03d (located in %s) has been dumped to disk\n", argv[1], resNum, resource->getResourceLocation().c_str());
- } else {
- DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum);
+ for (resNumCur = resNumFrom; resNumCur <= resNumTo; resNumCur++) {
+ Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNumCur), 0);
+ if (resource) {
+ char outFileName[50];
+ sprintf(outFileName, "%s.%03d", getResourceTypeName(res), resNumCur);
+ Common::DumpFile *outFile = new Common::DumpFile();
+ outFile->open(outFileName);
+ resource->writeToStream(outFile);
+ outFile->finalize();
+ outFile->close();
+ delete outFile;
+ debugPrintf("Resource %s.%03d (located in %s) has been dumped to disk\n", argv[1], resNumCur, resource->getResourceLocation().c_str());
+ } else {
+ if (resNumFrom == resNumTo) {
+ debugPrintf("Resource %s.%03d not found\n", argv[1], resNumCur);
+ }
+ }
}
}
@@ -691,8 +710,8 @@ bool Console::cmdDiskDump(int argc, const char **argv) {
bool Console::cmdHexDump(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Dumps the specified resource to standard output\n");
- DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]);
+ debugPrintf("Dumps the specified resource to standard output\n");
+ debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]);
cmdResourceTypes(argc, argv);
return true;
}
@@ -701,14 +720,14 @@ bool Console::cmdHexDump(int argc, const char **argv) {
ResourceType res = parseResourceType(argv[1]);
if (res == kResourceTypeInvalid)
- DebugPrintf("Resource type '%s' is not valid\n", argv[1]);
+ debugPrintf("Resource type '%s' is not valid\n", argv[1]);
else {
Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0);
if (resource) {
Common::hexdump(resource->data, resource->size, 16, 0);
- DebugPrintf("Resource %s.%03d has been dumped to standard output\n", argv[1], resNum);
+ debugPrintf("Resource %s.%03d has been dumped to standard output\n", argv[1], resNum);
} else {
- DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum);
+ debugPrintf("Resource %s.%03d not found\n", argv[1], resNum);
}
}
@@ -717,21 +736,21 @@ bool Console::cmdHexDump(int argc, const char **argv) {
bool Console::cmdResourceId(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Identifies a resource number by splitting it up in resource type and resource number\n");
- DebugPrintf("Usage: %s <resource number>\n", argv[0]);
+ debugPrintf("Identifies a resource number by splitting it up in resource type and resource number\n");
+ debugPrintf("Usage: %s <resource number>\n", argv[0]);
return true;
}
int id = atoi(argv[1]);
- DebugPrintf("%s.%d (0x%x)\n", getResourceTypeName((ResourceType)(id >> 11)), id & 0x7ff, id & 0x7ff);
+ debugPrintf("%s.%d (0x%x)\n", getResourceTypeName((ResourceType)(id >> 11)), id & 0x7ff, id & 0x7ff);
return true;
}
bool Console::cmdDissectScript(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Examines a script\n");
- DebugPrintf("Usage: %s <script number>\n", argv[0]);
+ debugPrintf("Examines a script\n");
+ debugPrintf("Usage: %s <script number>\n", argv[0]);
return true;
}
@@ -745,13 +764,13 @@ bool Console::cmdRoomNumber(int argc, const char **argv) {
// The same functionality is provided by "vmvars g 13" (but this one is more straighforward)
if (argc != 2) {
- DebugPrintf("Current room number is %d\n", _engine->_gamestate->currentRoomNumber());
- DebugPrintf("Calling this command with the room number (in decimal or hexadecimal) changes the room\n");
+ debugPrintf("Current room number is %d\n", _engine->_gamestate->currentRoomNumber());
+ debugPrintf("Calling this command with the room number (in decimal or hexadecimal) changes the room\n");
} else {
Common::String roomNumberStr = argv[1];
int roomNumber = strtol(roomNumberStr.c_str(), NULL, roomNumberStr.hasSuffix("h") ? 16 : 10);
_engine->_gamestate->setRoomNumber(roomNumber);
- DebugPrintf("Room number changed to %d (%x in hex)\n", roomNumber, roomNumber);
+ debugPrintf("Room number changed to %d (%x in hex)\n", roomNumber, roomNumber);
}
return true;
@@ -759,8 +778,8 @@ bool Console::cmdRoomNumber(int argc, const char **argv) {
bool Console::cmdResourceInfo(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Shows information about a resource\n");
- DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]);
+ debugPrintf("Shows information about a resource\n");
+ debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]);
return true;
}
@@ -768,14 +787,14 @@ bool Console::cmdResourceInfo(int argc, const char **argv) {
ResourceType res = parseResourceType(argv[1]);
if (res == kResourceTypeInvalid)
- DebugPrintf("Resource type '%s' is not valid\n", argv[1]);
+ debugPrintf("Resource type '%s' is not valid\n", argv[1]);
else {
Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0);
if (resource) {
- DebugPrintf("Resource size: %d\n", resource->size);
- DebugPrintf("Resource location: %s\n", resource->getResourceLocation().c_str());
+ debugPrintf("Resource size: %d\n", resource->size);
+ debugPrintf("Resource location: %s\n", resource->getResourceLocation().c_str());
} else {
- DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum);
+ debugPrintf("Resource %s.%03d not found\n", argv[1], resNum);
}
}
@@ -783,10 +802,10 @@ bool Console::cmdResourceInfo(int argc, const char **argv) {
}
bool Console::cmdResourceTypes(int argc, const char **argv) {
- DebugPrintf("The %d valid resource types are:\n", kResourceTypeInvalid);
+ debugPrintf("The %d valid resource types are:\n", kResourceTypeInvalid);
for (int i = 0; i < kResourceTypeInvalid; i++) {
- DebugPrintf("%s", getResourceTypeName((ResourceType) i));
- DebugPrintf((i < kResourceTypeInvalid - 1) ? ", " : "\n");
+ debugPrintf("%s", getResourceTypeName((ResourceType) i));
+ debugPrintf((i < kResourceTypeInvalid - 1) ? ", " : "\n");
}
return true;
@@ -794,10 +813,10 @@ bool Console::cmdResourceTypes(int argc, const char **argv) {
bool Console::cmdHexgrep(int argc, const char **argv) {
if (argc < 4) {
- DebugPrintf("Searches some resources for a particular sequence of bytes, represented as decimal or hexadecimal numbers.\n");
- DebugPrintf("Usage: %s <resource type> <resource number> <search string>\n", argv[0]);
- DebugPrintf("<resource number> can be a specific resource number, or \"all\" for all of the resources of the specified type\n");
- DebugPrintf("EXAMPLES:\n hexgrep script all 0xe8 0x03 0xc8 0x00\n hexgrep pic 0x42 0xfe\n");
+ debugPrintf("Searches some resources for a particular sequence of bytes, represented as decimal or hexadecimal numbers.\n");
+ debugPrintf("Usage: %s <resource type> <resource number> <search string>\n", argv[0]);
+ debugPrintf("<resource number> can be a specific resource number, or \"all\" for all of the resources of the specified type\n");
+ debugPrintf("EXAMPLES:\n hexgrep script all 0xe8 0x03 0xc8 0x00\n hexgrep pic 0x42 0xfe\n");
cmdResourceTypes(argc, argv);
return true;
}
@@ -807,7 +826,7 @@ bool Console::cmdHexgrep(int argc, const char **argv) {
Resource *script = NULL;
if (restype == kResourceTypeInvalid) {
- DebugPrintf("Resource type '%s' is not valid\n", argv[1]);
+ debugPrintf("Resource type '%s' is not valid\n", argv[1]);
return true;
}
@@ -845,10 +864,10 @@ bool Console::cmdHexgrep(int argc, const char **argv) {
seeker = seekerold + 1;
if (!output_script_name) {
- DebugPrintf("\nIn %s.%03d:\n", getResourceTypeName((ResourceType)restype), resNumber);
+ debugPrintf("\nIn %s.%03d:\n", getResourceTypeName((ResourceType)restype), resNumber);
output_script_name = 1;
}
- DebugPrintf(" 0x%04x\n", seekerold);
+ debugPrintf(" 0x%04x\n", seekerold);
}
} else
comppos = 0;
@@ -863,38 +882,38 @@ bool Console::cmdHexgrep(int argc, const char **argv) {
bool Console::cmdVerifyScripts(int argc, const char **argv) {
if (getSciVersion() < SCI_VERSION_1_1) {
- DebugPrintf("This script check is only meant for SCI1.1-SCI3 games\n");
+ debugPrintf("This script check is only meant for SCI1.1-SCI3 games\n");
return true;
}
Common::List<ResourceId> resources = _engine->getResMan()->listResources(kResourceTypeScript);
Common::sort(resources.begin(), resources.end());
- DebugPrintf("%d SCI1.1-SCI3 scripts found, performing sanity checks...\n", resources.size());
+ debugPrintf("%d SCI1.1-SCI3 scripts found, performing sanity checks...\n", resources.size());
Resource *script, *heap;
Common::List<ResourceId>::iterator itr;
for (itr = resources.begin(); itr != resources.end(); ++itr) {
script = _engine->getResMan()->findResource(*itr, false);
if (!script)
- DebugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber());
+ debugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber());
if (getSciVersion() <= SCI_VERSION_2_1) {
heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false);
if (!heap)
- DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber());
+ debugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber());
if (script && heap && (script->size + heap->size > 65535))
- DebugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n",
+ debugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n",
itr->getNumber(), script->size + heap->size);
} else { // SCI3
if (script && script->size > 65535)
- DebugPrintf("Error: script %d is larger than 64KB (%d bytes)\n",
+ debugPrintf("Error: script %d is larger than 64KB (%d bytes)\n",
itr->getNumber(), script->size);
}
}
- DebugPrintf("SCI1.1-SCI2.1 script check finished\n");
+ debugPrintf("SCI1.1-SCI2.1 script check finished\n");
return true;
}
@@ -931,9 +950,9 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
instrumentsSongs[i][j] = false;
if (songNumber == -1) {
- DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources.size());
- DebugPrintf("Instruments:\n");
- DebugPrintf("============\n");
+ debugPrintf("%d sounds found, checking their instrument mappings...\n", resources.size());
+ debugPrintf("Instruments:\n");
+ debugPrintf("============\n");
}
Common::List<ResourceId>::iterator itr;
@@ -956,7 +975,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
bool endOfTrack = false;
bool firstOneShown = false;
- DebugPrintf("Song %d: ", itr->getNumber());
+ debugPrintf("Song %d: ", itr->getNumber());
do {
while (*channelData == 0xF8)
@@ -984,9 +1003,9 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
if (!firstOneShown)
firstOneShown = true;
else
- DebugPrintf(",");
+ debugPrintf(",");
- DebugPrintf(" %d", instrument);
+ debugPrintf(" %d", instrument);
instruments[instrument]++;
instrumentsSongs[instrument][itr->getNumber()] = true;
} else {
@@ -1024,44 +1043,44 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
}
} while (!endOfTrack);
- DebugPrintf("\n");
+ debugPrintf("\n");
}
delete parser;
delete player;
- DebugPrintf("\n");
+ debugPrintf("\n");
if (songNumber == -1) {
- DebugPrintf("Used instruments: ");
+ debugPrintf("Used instruments: ");
for (int i = 0; i < 128; i++) {
if (instruments[i] > 0)
- DebugPrintf("%d, ", i);
+ debugPrintf("%d, ", i);
}
- DebugPrintf("\n\n");
+ debugPrintf("\n\n");
}
- DebugPrintf("Instruments not mapped in the MT32->GM map: ");
+ debugPrintf("Instruments not mapped in the MT32->GM map: ");
for (int i = 0; i < 128; i++) {
if (instruments[i] > 0 && getGmInstrument(Mt32MemoryTimbreMaps[i]) == MIDI_UNMAPPED)
- DebugPrintf("%d, ", i);
+ debugPrintf("%d, ", i);
}
- DebugPrintf("\n\n");
+ debugPrintf("\n\n");
if (songNumber == -1) {
- DebugPrintf("Used instruments in songs:\n");
+ debugPrintf("Used instruments in songs:\n");
for (int i = 0; i < 128; i++) {
if (instruments[i] > 0) {
- DebugPrintf("Instrument %d: ", i);
+ debugPrintf("Instrument %d: ", i);
for (int j = 0; j < 1000; j++) {
if (instrumentsSongs[i][j])
- DebugPrintf("%d, ", j);
+ debugPrintf("%d, ", j);
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
}
- DebugPrintf("\n\n");
+ debugPrintf("\n\n");
}
return true;
@@ -1069,13 +1088,13 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
bool Console::cmdMapInstrument(int argc, const char **argv) {
if (argc != 4) {
- DebugPrintf("Maps an MT-32 custom instrument to a GM instrument on the fly\n\n");
- DebugPrintf("Usage %s <MT-32 instrument name> <GM instrument> <GM rhythm key>\n", argv[0]);
- DebugPrintf("Each MT-32 instrument is always 10 characters and is mapped to either a GM instrument, or a GM rhythm key\n");
- DebugPrintf("A value of 255 (0xff) signifies an unmapped instrument\n");
- DebugPrintf("Please replace the spaces in the instrument name with underscores (\"_\"). They'll be converted to spaces afterwards\n\n");
- DebugPrintf("Example: %s test_0__XX 1 255\n", argv[0]);
- DebugPrintf("The above example will map the MT-32 instrument \"test 0 XX\" to GM instrument 1\n\n");
+ debugPrintf("Maps an MT-32 custom instrument to a GM instrument on the fly\n\n");
+ debugPrintf("Usage %s <MT-32 instrument name> <GM instrument> <GM rhythm key>\n", argv[0]);
+ debugPrintf("Each MT-32 instrument is always 10 characters and is mapped to either a GM instrument, or a GM rhythm key\n");
+ debugPrintf("A value of 255 (0xff) signifies an unmapped instrument\n");
+ debugPrintf("Please replace the spaces in the instrument name with underscores (\"_\"). They'll be converted to spaces afterwards\n\n");
+ debugPrintf("Example: %s test_0__XX 1 255\n", argv[0]);
+ debugPrintf("The above example will map the MT-32 instrument \"test 0 XX\" to GM instrument 1\n\n");
} else {
if (Mt32dynamicMappings != NULL) {
Mt32ToGmMap newMapping;
@@ -1093,11 +1112,11 @@ bool Console::cmdMapInstrument(int argc, const char **argv) {
}
}
- DebugPrintf("Current dynamic mappings:\n");
+ debugPrintf("Current dynamic mappings:\n");
if (Mt32dynamicMappings != NULL) {
const Mt32ToGmMapList::iterator end = Mt32dynamicMappings->end();
for (Mt32ToGmMapList::iterator it = Mt32dynamicMappings->begin(); it != end; ++it) {
- DebugPrintf("\"%s\" -> %d / %d\n", (*it).name, (*it).gmInstr, (*it).gmRhythmKey);
+ debugPrintf("\"%s\" -> %d / %d\n", (*it).name, (*it).gmInstr, (*it).gmRhythmKey);
}
}
@@ -1106,7 +1125,7 @@ bool Console::cmdMapInstrument(int argc, const char **argv) {
bool Console::cmdList(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Lists all the resources of a given type\n");
+ debugPrintf("Lists all the resources of a given type\n");
cmdResourceTypes(argc, argv);
return true;
}
@@ -1114,13 +1133,13 @@ bool Console::cmdList(int argc, const char **argv) {
ResourceType res = parseResourceType(argv[1]);
if (res == kResourceTypeInvalid)
- DebugPrintf("Unknown resource type: '%s'\n", argv[1]);
+ debugPrintf("Unknown resource type: '%s'\n", argv[1]);
else {
int number = -1;
if ((res == kResourceTypeAudio36) || (res == kResourceTypeSync36)) {
if (argc != 3) {
- DebugPrintf("Please specify map number (-1: all maps)\n");
+ debugPrintf("Please specify map number (-1: all maps)\n");
return true;
}
number = atoi(argv[2]);
@@ -1133,18 +1152,18 @@ bool Console::cmdList(int argc, const char **argv) {
Common::List<ResourceId>::iterator itr;
for (itr = resources.begin(); itr != resources.end(); ++itr) {
if (number == -1) {
- DebugPrintf("%8i", itr->getNumber());
+ debugPrintf("%8i", itr->getNumber());
if (++cnt % 10 == 0)
- DebugPrintf("\n");
+ debugPrintf("\n");
} else if (number == (int)itr->getNumber()) {
const uint32 tuple = itr->getTuple();
- DebugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff,
+ debugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff,
(tuple >> 8) & 0xff, tuple & 0xff);
if (++cnt % 4 == 0)
- DebugPrintf("\n");
+ debugPrintf("\n");
}
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
return true;
@@ -1152,8 +1171,8 @@ bool Console::cmdList(int argc, const char **argv) {
bool Console::cmdSaveGame(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Saves the current game state to the hard disk\n");
- DebugPrintf("Usage: %s <filename>\n", argv[0]);
+ debugPrintf("Saves the current game state to the hard disk\n");
+ debugPrintf("Usage: %s <filename>\n", argv[0]);
return true;
}
@@ -1163,19 +1182,19 @@ bool Console::cmdSaveGame(int argc, const char **argv) {
result++;
if (result)
- DebugPrintf("Note: Game state has %d open file handles.\n", result);
+ debugPrintf("Note: Game state has %d open file handles.\n", result);
Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
Common::OutSaveFile *out = saveFileMan->openForSaving(argv[1]);
const char *version = "";
if (!out) {
- DebugPrintf("Error opening savegame \"%s\" for writing\n", argv[1]);
+ debugPrintf("Error opening savegame \"%s\" for writing\n", argv[1]);
return true;
}
// TODO: enable custom descriptions? force filename into a specific format?
if (!gamestate_save(_engine->_gamestate, out, "debugging", version)) {
- DebugPrintf("Saving the game state to '%s' failed\n", argv[1]);
+ debugPrintf("Saving the game state to '%s' failed\n", argv[1]);
} else {
out->finalize();
if (out->err()) {
@@ -1189,8 +1208,8 @@ bool Console::cmdSaveGame(int argc, const char **argv) {
bool Console::cmdRestoreGame(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Restores a saved game from the hard disk\n");
- DebugPrintf("Usage: %s <filename>\n", argv[0]);
+ debugPrintf("Restores a saved game from the hard disk\n");
+ debugPrintf("Usage: %s <filename>\n", argv[0]);
return true;
}
@@ -1203,17 +1222,17 @@ bool Console::cmdRestoreGame(int argc, const char **argv) {
}
if (_engine->_gamestate->r_acc == make_reg(0, 1)) {
- DebugPrintf("Restoring gamestate '%s' failed.\n", argv[1]);
+ debugPrintf("Restoring gamestate '%s' failed.\n", argv[1]);
return true;
}
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdRestartGame(int argc, const char **argv) {
_engine->_gamestate->abortScriptProcessing = kAbortRestartGame;
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
// The scripts get IDs ranging from 100->199, because the scripts require us to assign unique ids THAT EVEN STAY BETWEEN
@@ -1231,25 +1250,25 @@ bool Console::cmdListSaves(int argc, const char **argv) {
for (uint i = 0; i < saves.size(); i++) {
Common::String filename = g_sci->getSavegameName(saves[i].id);
- DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name);
+ debugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name);
}
return true;
}
bool Console::cmdClassTable(int argc, const char **argv) {
- DebugPrintf("Available classes (parse a parameter to filter the table by a specific class):\n");
+ debugPrintf("Available classes (parse a parameter to filter the table by a specific class):\n");
for (uint i = 0; i < _engine->_gamestate->_segMan->classTableSize(); i++) {
Class temp = _engine->_gamestate->_segMan->_classTable[i];
if (temp.reg.getSegment()) {
const char *className = _engine->_gamestate->_segMan->getObjectName(temp.reg);
if (argc == 1 || (argc == 2 && !strcmp(className, argv[1]))) {
- DebugPrintf(" Class 0x%x (%s) at %04x:%04x (script %d)\n", i,
+ debugPrintf(" Class 0x%x (%s) at %04x:%04x (script %d)\n", i,
className,
PRINT_REG(temp.reg),
temp.script);
- } else DebugPrintf(" Class 0x%x (not loaded; can't get name) (script %d)\n", i, temp.script);
+ } else debugPrintf(" Class 0x%x (not loaded; can't get name) (script %d)\n", i, temp.script);
}
}
@@ -1257,52 +1276,52 @@ bool Console::cmdClassTable(int argc, const char **argv) {
}
bool Console::cmdSentenceFragments(int argc, const char **argv) {
- DebugPrintf("Sentence fragments (used to build Parse trees)\n");
+ debugPrintf("Sentence fragments (used to build Parse trees)\n");
for (uint i = 0; i < _engine->getVocabulary()->getParserBranchesSize(); i++) {
int j = 0;
const parse_tree_branch_t &branch = _engine->getVocabulary()->getParseTreeBranch(i);
- DebugPrintf("R%02d: [%x] ->", i, branch.id);
+ debugPrintf("R%02d: [%x] ->", i, branch.id);
while ((j < 10) && branch.data[j]) {
int dat = branch.data[j++];
switch (dat) {
case VOCAB_TREE_NODE_COMPARE_TYPE:
dat = branch.data[j++];
- DebugPrintf(" C(%x)", dat);
+ debugPrintf(" C(%x)", dat);
break;
case VOCAB_TREE_NODE_COMPARE_GROUP:
dat = branch.data[j++];
- DebugPrintf(" WG(%x)", dat);
+ debugPrintf(" WG(%x)", dat);
break;
case VOCAB_TREE_NODE_FORCE_STORAGE:
dat = branch.data[j++];
- DebugPrintf(" FORCE(%x)", dat);
+ debugPrintf(" FORCE(%x)", dat);
break;
default:
if (dat > VOCAB_TREE_NODE_LAST_WORD_STORAGE) {
int dat2 = branch.data[j++];
- DebugPrintf(" %x[%x]", dat, dat2);
+ debugPrintf(" %x[%x]", dat, dat2);
} else
- DebugPrintf(" ?%x?", dat);
+ debugPrintf(" ?%x?", dat);
}
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
- DebugPrintf("%d rules.\n", _engine->getVocabulary()->getParserBranchesSize());
+ debugPrintf("%d rules.\n", _engine->getVocabulary()->getParserBranchesSize());
return true;
}
bool Console::cmdParse(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Parses a sequence of words with a GNF rule set and prints the resulting parse tree\n");
- DebugPrintf("Usage: %s <word1> <word2> ... <wordn>\n", argv[0]);
+ debugPrintf("Parses a sequence of words with a GNF rule set and prints the resulting parse tree\n");
+ debugPrintf("Usage: %s <word1> <word2> ... <wordn>\n", argv[0]);
return true;
}
@@ -1316,7 +1335,7 @@ bool Console::cmdParse(int argc, const char **argv) {
strcat(string, argv[i]);
}
- DebugPrintf("Parsing '%s'\n", string);
+ debugPrintf("Parsing '%s'\n", string);
ResultWordListList words;
bool res = _engine->getVocabulary()->tokenizeString(words, string, &error);
@@ -1325,26 +1344,26 @@ bool Console::cmdParse(int argc, const char **argv) {
_engine->getVocabulary()->synonymizeTokens(words);
- DebugPrintf("Parsed to the following blocks:\n");
+ debugPrintf("Parsed to the following blocks:\n");
for (ResultWordListList::const_iterator i = words.begin(); i != words.end(); ++i) {
- DebugPrintf(" ");
+ debugPrintf(" ");
for (ResultWordList::const_iterator j = i->begin(); j != i->end(); ++j) {
- DebugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group);
+ debugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group);
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
if (_engine->getVocabulary()->parseGNF(words, true))
syntax_fail = 1; // Building a tree failed
if (syntax_fail)
- DebugPrintf("Building a tree failed.\n");
+ debugPrintf("Building a tree failed.\n");
else
_engine->getVocabulary()->dumpParseTree();
} else {
- DebugPrintf("Unknown word: '%s'\n", error);
+ debugPrintf("Unknown word: '%s'\n", error);
free(error);
}
@@ -1353,10 +1372,10 @@ bool Console::cmdParse(int argc, const char **argv) {
bool Console::cmdSaid(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Matches a string against a said spec\n");
- DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]);
- DebugPrintf("<string> is a sequence of actual words.\n");
- DebugPrintf("<said spec> is a sequence of hex tokens.\n");
+ debugPrintf("Matches a string against a said spec\n");
+ debugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]);
+ debugPrintf("<string> is a sequence of actual words.\n");
+ debugPrintf("<said spec> is a sequence of hex tokens.\n");
return true;
}
@@ -1373,10 +1392,10 @@ bool Console::cmdSaid(int argc, const char **argv) {
}
if (p >= argc-1) {
- DebugPrintf("Matches a string against a said spec\n");
- DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]);
- DebugPrintf("<string> is a sequence of actual words.\n");
- DebugPrintf("<said spec> is a sequence of hex tokens.\n");
+ debugPrintf("Matches a string against a said spec\n");
+ debugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]);
+ debugPrintf("<string> is a sequence of actual words.\n");
+ debugPrintf("<said spec> is a sequence of hex tokens.\n");
return true;
}
@@ -1440,14 +1459,14 @@ bool Console::cmdSaid(int argc, const char **argv) {
_engine->getVocabulary()->synonymizeTokens(words);
- DebugPrintf("Parsed to the following blocks:\n");
+ debugPrintf("Parsed to the following blocks:\n");
for (ResultWordListList::const_iterator i = words.begin(); i != words.end(); ++i) {
- DebugPrintf(" ");
+ debugPrintf(" ");
for (ResultWordList::const_iterator j = i->begin(); j != i->end(); ++j) {
- DebugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group);
+ debugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group);
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
@@ -1456,17 +1475,17 @@ bool Console::cmdSaid(int argc, const char **argv) {
syntax_fail = 1; // Building a tree failed
if (syntax_fail)
- DebugPrintf("Building a tree failed.\n");
+ debugPrintf("Building a tree failed.\n");
else {
_engine->getVocabulary()->dumpParseTree();
_engine->getVocabulary()->parserIsValid = true;
int ret = said((byte *)spec, true);
- DebugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match"));
+ debugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match"));
}
} else {
- DebugPrintf("Unknown word: '%s'\n", error);
+ debugPrintf("Unknown word: '%s'\n", error);
free(error);
}
@@ -1476,9 +1495,9 @@ bool Console::cmdSaid(int argc, const char **argv) {
bool Console::cmdParserNodes(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Shows the specified number of nodes from the parse node tree\n");
- DebugPrintf("Usage: %s <nr>\n", argv[0]);
- DebugPrintf("where <nr> is the number of nodes to show from the parse node tree\n");
+ debugPrintf("Shows the specified number of nodes from the parse node tree\n");
+ debugPrintf("Usage: %s <nr>\n", argv[0]);
+ debugPrintf("where <nr> is the number of nodes to show from the parse node tree\n");
return true;
}
@@ -1491,9 +1510,9 @@ bool Console::cmdParserNodes(int argc, const char **argv) {
bool Console::cmdSetPalette(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Sets a palette resource\n");
- DebugPrintf("Usage: %s <resourceId>\n", argv[0]);
- DebugPrintf("where <resourceId> is the number of the palette resource to set\n");
+ debugPrintf("Sets a palette resource\n");
+ debugPrintf("Usage: %s <resourceId>\n", argv[0]);
+ debugPrintf("where <resourceId> is the number of the palette resource to set\n");
return true;
}
@@ -1505,9 +1524,9 @@ bool Console::cmdSetPalette(int argc, const char **argv) {
bool Console::cmdDrawPic(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Draws a pic resource\n");
- DebugPrintf("Usage: %s <resourceId>\n", argv[0]);
- DebugPrintf("where <resourceId> is the number of the pic resource to draw\n");
+ debugPrintf("Draws a pic resource\n");
+ debugPrintf("Usage: %s <resourceId>\n", argv[0]);
+ debugPrintf("where <resourceId> is the number of the pic resource to draw\n");
return true;
}
@@ -1532,9 +1551,9 @@ bool Console::cmdDrawPic(int argc, const char **argv) {
bool Console::cmdDrawCel(int argc, const char **argv) {
if (argc < 4) {
- DebugPrintf("Draws a cel from a view resource\n");
- DebugPrintf("Usage: %s <resourceId> <loopNr> <celNr> \n", argv[0]);
- DebugPrintf("where <resourceId> is the number of the view resource to draw\n");
+ debugPrintf("Draws a cel from a view resource\n");
+ debugPrintf("Usage: %s <resourceId> <loopNr> <celNr> \n", argv[0]);
+ debugPrintf("where <resourceId> is the number of the view resource to draw\n");
return true;
}
@@ -1555,24 +1574,24 @@ bool Console::cmdDrawCel(int argc, const char **argv) {
bool Console::cmdUndither(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Enable/disable undithering.\n");
- DebugPrintf("Usage: %s <0/1>\n", argv[0]);
+ debugPrintf("Enable/disable undithering.\n");
+ debugPrintf("Usage: %s <0/1>\n", argv[0]);
return true;
}
bool flag = atoi(argv[1]) ? true : false;
_engine->_gfxScreen->enableUndithering(flag);
if (flag)
- DebugPrintf("undithering ENABLED\n");
+ debugPrintf("undithering ENABLED\n");
else
- DebugPrintf("undithering DISABLED\n");
+ debugPrintf("undithering DISABLED\n");
return true;
}
bool Console::cmdPicVisualize(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Enable/disable picture visualization (EGA only)\n");
- DebugPrintf("Usage: %s <0/1>\n", argv[0]);
+ debugPrintf("Enable/disable picture visualization (EGA only)\n");
+ debugPrintf("Usage: %s <0/1>\n", argv[0]);
return true;
}
@@ -1581,21 +1600,21 @@ bool Console::cmdPicVisualize(int argc, const char **argv) {
if (_engine->_resMan->getViewType() == kViewEga) {
_engine->_gfxPaint16->debugSetEGAdrawingVisualize(state);
if (state)
- DebugPrintf("picture visualization ENABLED\n");
+ debugPrintf("picture visualization ENABLED\n");
else
- DebugPrintf("picture visualization DISABLED\n");
+ debugPrintf("picture visualization DISABLED\n");
} else {
- DebugPrintf("picture visualization only available for EGA games\n");
+ debugPrintf("picture visualization only available for EGA games\n");
}
return true;
}
bool Console::cmdPlayVideo(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Plays a SEQ, AVI, VMD, RBT or DUK video.\n");
- DebugPrintf("Usage: %s <video file name> <delay>\n", argv[0]);
- DebugPrintf("The video file name should include the extension\n");
- DebugPrintf("Delay is only used in SEQ videos and is measured in ticks (default: 10)\n");
+ debugPrintf("Plays a SEQ, AVI, VMD, RBT or DUK video.\n");
+ debugPrintf("Usage: %s <video file name> <delay>\n", argv[0]);
+ debugPrintf("The video file name should include the extension\n");
+ debugPrintf("Delay is only used in SEQ videos and is measured in ticks (default: 10)\n");
return true;
}
@@ -1606,29 +1625,29 @@ bool Console::cmdPlayVideo(int argc, const char **argv) {
filename.hasSuffix(".rbt") || filename.hasSuffix(".duk")) {
_videoFile = filename;
_videoFrameDelay = (argc == 2) ? 10 : atoi(argv[2]);
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
} else {
- DebugPrintf("Unknown video file type\n");
+ debugPrintf("Unknown video file type\n");
return true;
}
}
bool Console::cmdAnimateList(int argc, const char **argv) {
if (_engine->_gfxAnimate) {
- DebugPrintf("Animate list:\n");
+ debugPrintf("Animate list:\n");
_engine->_gfxAnimate->printAnimateList(this);
} else {
- DebugPrintf("This SCI version does not have an animate list\n");
+ debugPrintf("This SCI version does not have an animate list\n");
}
return true;
}
bool Console::cmdWindowList(int argc, const char **argv) {
if (_engine->_gfxPorts) {
- DebugPrintf("Window list:\n");
+ debugPrintf("Window list:\n");
_engine->_gfxPorts->printWindowList(this);
} else {
- DebugPrintf("This SCI version does not have a list of ports\n");
+ debugPrintf("This SCI version does not have a list of ports\n");
}
return true;
}
@@ -1636,41 +1655,41 @@ bool Console::cmdWindowList(int argc, const char **argv) {
bool Console::cmdPlaneList(int argc, const char **argv) {
#ifdef ENABLE_SCI32
if (_engine->_gfxFrameout) {
- DebugPrintf("Plane list:\n");
+ debugPrintf("Plane list:\n");
_engine->_gfxFrameout->printPlaneList(this);
} else {
- DebugPrintf("This SCI version does not have a list of planes\n");
+ debugPrintf("This SCI version does not have a list of planes\n");
}
#else
- DebugPrintf("SCI32 isn't included in this compiled executable\n");
+ debugPrintf("SCI32 isn't included in this compiled executable\n");
#endif
return true;
}
bool Console::cmdPlaneItemList(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Shows the list of items for a plane\n");
- DebugPrintf("Usage: %s <plane address>\n", argv[0]);
+ debugPrintf("Shows the list of items for a plane\n");
+ debugPrintf("Usage: %s <plane address>\n", argv[0]);
return true;
}
reg_t planeObject = NULL_REG;
if (parse_reg_t(_engine->_gamestate, argv[1], &planeObject, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
#ifdef ENABLE_SCI32
if (_engine->_gfxFrameout) {
- DebugPrintf("Plane item list:\n");
+ debugPrintf("Plane item list:\n");
_engine->_gfxFrameout->printPlaneItemList(this, planeObject);
} else {
- DebugPrintf("This SCI version does not have a list of plane items\n");
+ debugPrintf("This SCI version does not have a list of plane items\n");
}
#else
- DebugPrintf("SCI32 isn't included in this compiled executable\n");
+ debugPrintf("SCI32 isn't included in this compiled executable\n");
#endif
return true;
}
@@ -1680,7 +1699,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) {
SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK);
HunkTable* hunks = (HunkTable *)segman->getSegmentObj(id);
if (!hunks) {
- DebugPrintf("No hunk segment found.\n");
+ debugPrintf("No hunk segment found.\n");
return true;
}
@@ -1693,7 +1712,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) {
byte* memoryPtr = (byte *)h.mem;
if (memoryPtr) {
- DebugPrintf("%04x:%04x:", PRINT_REG(entries[i]));
+ debugPrintf("%04x:%04x:", PRINT_REG(entries[i]));
Common::Rect rect;
byte mask;
@@ -1702,17 +1721,17 @@ bool Console::cmdSavedBits(int argc, const char **argv) {
memcpy((void *)&rect, memoryPtr, sizeof(rect));
memcpy((void *)&mask, memoryPtr + sizeof(rect), sizeof(mask));
- DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left,
+ debugPrintf(" %d,%d - %d,%d", rect.top, rect.left,
rect.bottom, rect.right);
if (mask & GFX_SCREEN_MASK_VISUAL)
- DebugPrintf(" visual");
+ debugPrintf(" visual");
if (mask & GFX_SCREEN_MASK_PRIORITY)
- DebugPrintf(" priority");
+ debugPrintf(" priority");
if (mask & GFX_SCREEN_MASK_CONTROL)
- DebugPrintf(" control");
+ debugPrintf(" control");
if (mask & GFX_SCREEN_MASK_DISPLAY)
- DebugPrintf(" display");
- DebugPrintf("\n");
+ debugPrintf(" display");
+ debugPrintf("\n");
}
}
}
@@ -1723,22 +1742,22 @@ bool Console::cmdSavedBits(int argc, const char **argv) {
bool Console::cmdShowSavedBits(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Display saved bits.\n");
- DebugPrintf("Usage: %s <address>\n", argv[0]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Display saved bits.\n");
+ debugPrintf("Usage: %s <address>\n", argv[0]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
reg_t memoryHandle = NULL_REG;
if (parse_reg_t(_engine->_gamestate, argv[1], &memoryHandle, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
if (memoryHandle.isNull()) {
- DebugPrintf("Invalid address.\n");
+ debugPrintf("Invalid address.\n");
return true;
}
@@ -1746,26 +1765,26 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) {
SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK);
HunkTable* hunks = (HunkTable *)segman->getSegmentObj(id);
if (!hunks) {
- DebugPrintf("No hunk segment found.\n");
+ debugPrintf("No hunk segment found.\n");
return true;
}
if (memoryHandle.getSegment() != id || !hunks->isValidOffset(memoryHandle.getOffset())) {
- DebugPrintf("Invalid address.\n");
+ debugPrintf("Invalid address.\n");
return true;
}
const Hunk& h = hunks->_table[memoryHandle.getOffset()];
if (strcmp(h.type, "SaveBits()") != 0) {
- DebugPrintf("Invalid address.\n");
+ debugPrintf("Invalid address.\n");
return true;
}
byte *memoryPtr = segman->getHunkPointer(memoryHandle);
if (!memoryPtr) {
- DebugPrintf("Invalid or freed bits.\n");
+ debugPrintf("Invalid or freed bits.\n");
return true;
}
@@ -1783,17 +1802,17 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) {
Common::Point bl(rect.left, rect.bottom-1);
Common::Point br(rect.right-1, rect.bottom-1);
- DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left,
+ debugPrintf(" %d,%d - %d,%d", rect.top, rect.left,
rect.bottom, rect.right);
if (mask & GFX_SCREEN_MASK_VISUAL)
- DebugPrintf(" visual");
+ debugPrintf(" visual");
if (mask & GFX_SCREEN_MASK_PRIORITY)
- DebugPrintf(" priority");
+ debugPrintf(" priority");
if (mask & GFX_SCREEN_MASK_CONTROL)
- DebugPrintf(" control");
+ debugPrintf(" control");
if (mask & GFX_SCREEN_MASK_DISPLAY)
- DebugPrintf(" display");
- DebugPrintf("\n");
+ debugPrintf(" display");
+ debugPrintf("\n");
if (!_engine->_gfxPaint16 || !_engine->_gfxScreen)
return true;
@@ -1843,7 +1862,7 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) {
bool Console::cmdParseGrammar(int argc, const char **argv) {
- DebugPrintf("Parse grammar, in strict GNF:\n");
+ debugPrintf("Parse grammar, in strict GNF:\n");
_engine->getVocabulary()->buildGNF(true);
@@ -1851,71 +1870,71 @@ bool Console::cmdParseGrammar(int argc, const char **argv) {
}
bool Console::cmdPrintSegmentTable(int argc, const char **argv) {
- DebugPrintf("Segment table:\n");
+ debugPrintf("Segment table:\n");
for (uint i = 0; i < _engine->_gamestate->_segMan->_heap.size(); i++) {
SegmentObj *mobj = _engine->_gamestate->_segMan->_heap[i];
if (mobj && mobj->getType()) {
- DebugPrintf(" [%04x] ", i);
+ debugPrintf(" [%04x] ", i);
switch (mobj->getType()) {
case SEG_TYPE_SCRIPT:
- DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers());
+ debugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers());
break;
case SEG_TYPE_CLONES:
- DebugPrintf("C clones (%d allocd)", (*(CloneTable *)mobj).entries_used);
+ debugPrintf("C clones (%d allocd)", (*(CloneTable *)mobj).entries_used);
break;
case SEG_TYPE_LOCALS:
- DebugPrintf("V locals %03d", (*(LocalVariables *)mobj).script_id);
+ debugPrintf("V locals %03d", (*(LocalVariables *)mobj).script_id);
break;
case SEG_TYPE_STACK:
- DebugPrintf("D data stack (%d)", (*(DataStack *)mobj)._capacity);
+ debugPrintf("D data stack (%d)", (*(DataStack *)mobj)._capacity);
break;
case SEG_TYPE_LISTS:
- DebugPrintf("L lists (%d)", (*(ListTable *)mobj).entries_used);
+ debugPrintf("L lists (%d)", (*(ListTable *)mobj).entries_used);
break;
case SEG_TYPE_NODES:
- DebugPrintf("N nodes (%d)", (*(NodeTable *)mobj).entries_used);
+ debugPrintf("N nodes (%d)", (*(NodeTable *)mobj).entries_used);
break;
case SEG_TYPE_HUNK:
- DebugPrintf("H hunk (%d)", (*(HunkTable *)mobj).entries_used);
+ debugPrintf("H hunk (%d)", (*(HunkTable *)mobj).entries_used);
break;
case SEG_TYPE_DYNMEM:
- DebugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size);
+ debugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size);
break;
#ifdef ENABLE_SCI32
case SEG_TYPE_ARRAY:
- DebugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used);
+ debugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used);
break;
case SEG_TYPE_STRING:
- DebugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used);
+ debugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used);
break;
#endif
default:
- DebugPrintf("I Invalid (type = %x)", mobj->getType());
+ debugPrintf("I Invalid (type = %x)", mobj->getType());
break;
}
- DebugPrintf(" \n");
+ debugPrintf(" \n");
}
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
bool Console::segmentInfo(int nr) {
- DebugPrintf("[%04x] ", nr);
+ debugPrintf("[%04x] ", nr);
if ((nr < 0) || ((uint)nr >= _engine->_gamestate->_segMan->_heap.size()) || !_engine->_gamestate->_segMan->_heap[nr])
return false;
@@ -1926,30 +1945,30 @@ bool Console::segmentInfo(int nr) {
case SEG_TYPE_SCRIPT: {
Script *scr = (Script *)mobj;
- DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize());
+ debugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize());
if (scr->getExportTable())
- DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf())));
+ debugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf())));
else
- DebugPrintf(" Exports: none\n");
+ debugPrintf(" Exports: none\n");
- DebugPrintf(" Synonyms: %4d\n", scr->getSynonymsNr());
+ debugPrintf(" Synonyms: %4d\n", scr->getSynonymsNr());
if (scr->getLocalsCount() > 0)
- DebugPrintf(" Locals : %4d in segment 0x%x\n", scr->getLocalsCount(), scr->getLocalsSegment());
+ debugPrintf(" Locals : %4d in segment 0x%x\n", scr->getLocalsCount(), scr->getLocalsSegment());
else
- DebugPrintf(" Locals : none\n");
+ debugPrintf(" Locals : none\n");
ObjMap objects = scr->getObjectMap();
- DebugPrintf(" Objects: %4d\n", objects.size());
+ debugPrintf(" Objects: %4d\n", objects.size());
ObjMap::iterator it;
const ObjMap::iterator end = objects.end();
for (it = objects.begin(); it != end; ++it) {
- DebugPrintf(" ");
+ debugPrintf(" ");
// Object header
const Object *obj = _engine->_gamestate->_segMan->getObject(it->_value.getPos());
if (obj)
- DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value.getPos()),
+ debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value.getPos()),
_engine->_gamestate->_segMan->getObjectName(it->_value.getPos()),
obj->getVarCount(), obj->getMethodCount());
}
@@ -1958,31 +1977,31 @@ bool Console::segmentInfo(int nr) {
case SEG_TYPE_LOCALS: {
LocalVariables *locals = (LocalVariables *)mobj;
- DebugPrintf("locals for script.%03d\n", locals->script_id);
- DebugPrintf(" %d (0x%x) locals\n", locals->_locals.size(), locals->_locals.size());
+ debugPrintf("locals for script.%03d\n", locals->script_id);
+ debugPrintf(" %d (0x%x) locals\n", locals->_locals.size(), locals->_locals.size());
}
break;
case SEG_TYPE_STACK: {
DataStack *stack = (DataStack *)mobj;
- DebugPrintf("stack\n");
- DebugPrintf(" %d (0x%x) entries\n", stack->_capacity, stack->_capacity);
+ debugPrintf("stack\n");
+ debugPrintf(" %d (0x%x) entries\n", stack->_capacity, stack->_capacity);
}
break;
case SEG_TYPE_CLONES: {
CloneTable *ct = (CloneTable *)mobj;
- DebugPrintf("clones\n");
+ debugPrintf("clones\n");
for (uint i = 0; i < ct->_table.size(); i++)
if (ct->isValidEntry(i)) {
reg_t objpos = make_reg(nr, i);
- DebugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos));
+ debugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos));
// Object header
const Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos());
if (obj)
- DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()),
+ debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()),
_engine->_gamestate->_segMan->getObjectName(ct->_table[i].getPos()),
obj->getVarCount(), obj->getMethodCount());
}
@@ -1992,34 +2011,34 @@ bool Console::segmentInfo(int nr) {
case SEG_TYPE_LISTS: {
ListTable *lt = (ListTable *)mobj;
- DebugPrintf("lists\n");
+ debugPrintf("lists\n");
for (uint i = 0; i < lt->_table.size(); i++)
if (lt->isValidEntry(i)) {
- DebugPrintf(" [%04x]: ", i);
+ debugPrintf(" [%04x]: ", i);
printList(&(lt->_table[i]));
}
}
break;
case SEG_TYPE_NODES: {
- DebugPrintf("nodes (total %d)\n", (*(NodeTable *)mobj).entries_used);
+ debugPrintf("nodes (total %d)\n", (*(NodeTable *)mobj).entries_used);
break;
}
case SEG_TYPE_HUNK: {
HunkTable *ht = (HunkTable *)mobj;
- DebugPrintf("hunk (total %d)\n", ht->entries_used);
+ debugPrintf("hunk (total %d)\n", ht->entries_used);
for (uint i = 0; i < ht->_table.size(); i++)
if (ht->isValidEntry(i)) {
- DebugPrintf(" [%04x] %d bytes at %p, type=%s\n",
+ debugPrintf(" [%04x] %d bytes at %p, type=%s\n",
i, ht->_table[i].size, ht->_table[i].mem, ht->_table[i].type);
}
}
break;
case SEG_TYPE_DYNMEM: {
- DebugPrintf("dynmem (%s): %d bytes\n",
+ debugPrintf("dynmem (%s): %d bytes\n",
(*(DynMem *)mobj)._description.c_str(), (*(DynMem *)mobj)._size);
Common::hexdump((*(DynMem *)mobj)._buf, (*(DynMem *)mobj)._size, 16, 0);
@@ -2028,28 +2047,28 @@ bool Console::segmentInfo(int nr) {
#ifdef ENABLE_SCI32
case SEG_TYPE_STRING:
- DebugPrintf("SCI32 strings\n");
+ debugPrintf("SCI32 strings\n");
break;
case SEG_TYPE_ARRAY:
- DebugPrintf("SCI32 arrays\n");
+ debugPrintf("SCI32 arrays\n");
break;
#endif
default :
- DebugPrintf("Invalid type %d\n", mobj->getType());
+ debugPrintf("Invalid type %d\n", mobj->getType());
break;
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
bool Console::cmdSegmentInfo(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Provides information on the specified segment(s)\n");
- DebugPrintf("Usage: %s <segment number>\n", argv[0]);
- DebugPrintf("<segment number> can be a number, which shows the information of the segment with\n");
- DebugPrintf("the specified number, or \"all\" to show information on all active segments\n");
+ debugPrintf("Provides information on the specified segment(s)\n");
+ debugPrintf("Usage: %s <segment number>\n", argv[0]);
+ debugPrintf("<segment number> can be a number, which shows the information of the segment with\n");
+ debugPrintf("the specified number, or \"all\" to show information on all active segments\n");
return true;
}
@@ -2061,7 +2080,7 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) {
if (!parseInteger(argv[1], segmentNr))
return true;
if (!segmentInfo(segmentNr))
- DebugPrintf("Segment %04xh does not exist\n", segmentNr);
+ debugPrintf("Segment %04xh does not exist\n", segmentNr);
}
return true;
@@ -2070,8 +2089,8 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) {
bool Console::cmdKillSegment(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Deletes the specified segment\n");
- DebugPrintf("Usage: %s <segment number>\n", argv[0]);
+ debugPrintf("Deletes the specified segment\n");
+ debugPrintf("Usage: %s <segment number>\n", argv[0]);
return true;
}
int segmentNumber;
@@ -2084,13 +2103,13 @@ bool Console::cmdKillSegment(int argc, const char **argv) {
bool Console::cmdShowMap(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Switches to one of the following screen maps\n");
- DebugPrintf("Usage: %s <screen map>\n", argv[0]);
- DebugPrintf("Screen maps:\n");
- DebugPrintf("- 0: visual map\n");
- DebugPrintf("- 1: priority map\n");
- DebugPrintf("- 2: control map\n");
- DebugPrintf("- 3: display screen\n");
+ debugPrintf("Switches to one of the following screen maps\n");
+ debugPrintf("Usage: %s <screen map>\n", argv[0]);
+ debugPrintf("Screen maps:\n");
+ debugPrintf("- 0: visual map\n");
+ debugPrintf("- 1: priority map\n");
+ debugPrintf("- 2: control map\n");
+ debugPrintf("- 3: display screen\n");
return true;
}
@@ -2105,14 +2124,14 @@ bool Console::cmdShowMap(int argc, const char **argv) {
break;
default:
- DebugPrintf("Map %d is not available.\n", map);
+ debugPrintf("Map %d is not available.\n", map);
return true;
}
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdSongLib(int argc, const char **argv) {
- DebugPrintf("Song library:\n");
+ debugPrintf("Song library:\n");
g_sci->_soundCmd->printPlayList(this);
return true;
@@ -2120,16 +2139,16 @@ bool Console::cmdSongLib(int argc, const char **argv) {
bool Console::cmdSongInfo(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Shows information about a given song in the playlist\n");
- DebugPrintf("Usage: %s <song object>\n", argv[0]);
+ debugPrintf("Shows information about a given song in the playlist\n");
+ debugPrintf("Usage: %s <song object>\n", argv[0]);
return true;
}
reg_t addr;
if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -2140,38 +2159,38 @@ bool Console::cmdSongInfo(int argc, const char **argv) {
bool Console::cmdStartSound(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Adds the requested sound resource to the playlist, and starts playing it\n");
- DebugPrintf("Usage: %s <sound resource id>\n", argv[0]);
+ debugPrintf("Adds the requested sound resource to the playlist, and starts playing it\n");
+ debugPrintf("Usage: %s <sound resource id>\n", argv[0]);
return true;
}
int16 number = atoi(argv[1]);
if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) {
- DebugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n");
+ debugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n");
return true;
}
g_sci->_soundCmd->startNewSound(number);
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdToggleSound(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Plays or stops the specified sound in the playlist\n");
- DebugPrintf("Usage: %s <address> <state>\n", argv[0]);
- DebugPrintf("Where:\n");
- DebugPrintf("- <address> is the address of the sound to play or stop.\n");
- DebugPrintf("- <state> is the new state (play or stop).\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Plays or stops the specified sound in the playlist\n");
+ debugPrintf("Usage: %s <address> <state>\n", argv[0]);
+ debugPrintf("Where:\n");
+ debugPrintf("- <address> is the address of the sound to play or stop.\n");
+ debugPrintf("- <state> is the new state (play or stop).\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
reg_t id;
if (parse_reg_t(_engine->_gamestate, argv[1], &id, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -2183,7 +2202,7 @@ bool Console::cmdToggleSound(int argc, const char **argv) {
else if (newState == "stop")
g_sci->_soundCmd->processStopSound(id, false);
else
- DebugPrintf("New state can either be 'play' or 'stop'");
+ debugPrintf("New state can either be 'play' or 'stop'");
return true;
}
@@ -2191,40 +2210,40 @@ bool Console::cmdToggleSound(int argc, const char **argv) {
bool Console::cmdStopAllSounds(int argc, const char **argv) {
g_sci->_soundCmd->stopAllSounds();
- DebugPrintf("All sounds have been stopped\n");
+ debugPrintf("All sounds have been stopped\n");
return true;
}
bool Console::cmdIsSample(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Tests whether a given sound resource is a PCM sample, \n");
- DebugPrintf("and displays information on it if it is.\n");
- DebugPrintf("Usage: %s <sample id>\n", argv[0]);
+ debugPrintf("Tests whether a given sound resource is a PCM sample, \n");
+ debugPrintf("and displays information on it if it is.\n");
+ debugPrintf("Usage: %s <sample id>\n", argv[0]);
return true;
}
int16 number = atoi(argv[1]);
if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) {
- DebugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n");
+ debugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n");
return true;
}
SoundResource *soundRes = new SoundResource(number, _engine->getResMan(), _engine->_features->detectDoSoundType());
if (!soundRes) {
- DebugPrintf("Not a sound resource!\n");
+ debugPrintf("Not a sound resource!\n");
return true;
}
SoundResource::Track *track = soundRes->getDigitalTrack();
if (!track || track->digitalChannelNr == -1) {
- DebugPrintf("Valid song, but not a sample.\n");
+ debugPrintf("Valid song, but not a sample.\n");
delete soundRes;
return true;
}
- DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n",
+ debugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n",
track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr);
delete soundRes;
@@ -2232,7 +2251,7 @@ bool Console::cmdIsSample(int argc, const char **argv) {
}
bool Console::cmdGCInvoke(int argc, const char **argv) {
- DebugPrintf("Performing garbage collection...\n");
+ debugPrintf("Performing garbage collection...\n");
run_gc(_engine->_gamestate);
return true;
}
@@ -2240,9 +2259,9 @@ bool Console::cmdGCInvoke(int argc, const char **argv) {
bool Console::cmdGCObjects(int argc, const char **argv) {
AddrSet *use_map = findAllActiveReferences(_engine->_gamestate);
- DebugPrintf("Reachable object references (normalised):\n");
+ debugPrintf("Reachable object references (normalised):\n");
for (AddrSet::iterator i = use_map->begin(); i != use_map->end(); ++i) {
- DebugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key));
+ debugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key));
}
delete use_map;
@@ -2252,93 +2271,93 @@ bool Console::cmdGCObjects(int argc, const char **argv) {
bool Console::cmdGCShowReachable(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n");
- DebugPrintf("Usage: %s <address>\n", argv[0]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n");
+ debugPrintf("Usage: %s <address>\n", argv[0]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
reg_t addr;
if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment());
if (!mobj) {
- DebugPrintf("Unknown segment : %x\n", addr.getSegment());
+ debugPrintf("Unknown segment : %x\n", addr.getSegment());
return 1;
}
- DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr));
+ debugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr));
const Common::Array<reg_t> tmp = mobj->listAllOutgoingReferences(addr);
for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
if (it->getSegment())
- g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it));
+ g_sci->getSciDebugger()->debugPrintf(" %04x:%04x\n", PRINT_REG(*it));
return true;
}
bool Console::cmdGCShowFreeable(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Prints all addresses freeable in the segment associated with the\n");
- DebugPrintf("given address (offset is ignored).\n");
- DebugPrintf("Usage: %s <address>\n", argv[0]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Prints all addresses freeable in the segment associated with the\n");
+ debugPrintf("given address (offset is ignored).\n");
+ debugPrintf("Usage: %s <address>\n", argv[0]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
reg_t addr;
if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment());
if (!mobj) {
- DebugPrintf("Unknown segment : %x\n", addr.getSegment());
+ debugPrintf("Unknown segment : %x\n", addr.getSegment());
return true;
}
- DebugPrintf("Freeable in segment %04x:\n", addr.getSegment());
+ debugPrintf("Freeable in segment %04x:\n", addr.getSegment());
const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(addr.getSegment());
for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
if (it->getSegment())
- g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it));
+ g_sci->getSciDebugger()->debugPrintf(" %04x:%04x\n", PRINT_REG(*it));
return true;
}
bool Console::cmdGCNormalize(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Prints the \"normal\" address of a given address,\n");
- DebugPrintf("i.e. the address we would free in order to free\n");
- DebugPrintf("the object associated with the original address.\n");
- DebugPrintf("Usage: %s <address>\n", argv[0]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Prints the \"normal\" address of a given address,\n");
+ debugPrintf("i.e. the address we would free in order to free\n");
+ debugPrintf("the object associated with the original address.\n");
+ debugPrintf("Usage: %s <address>\n", argv[0]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
reg_t addr;
if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment());
if (!mobj) {
- DebugPrintf("Unknown segment : %x\n", addr.getSegment());
+ debugPrintf("Unknown segment : %x\n", addr.getSegment());
return true;
}
addr = mobj->findCanonicAddress(_engine->_gamestate->_segMan, addr);
- DebugPrintf(" %04x:%04x\n", PRINT_REG(addr));
+ debugPrintf(" %04x:%04x\n", PRINT_REG(addr));
return true;
}
@@ -2347,12 +2366,12 @@ bool Console::cmdVMVarlist(int argc, const char **argv) {
EngineState *s = _engine->_gamestate;
const char *varnames[] = {"global", "local", "temp", "param"};
- DebugPrintf("Addresses of variables in the VM:\n");
+ debugPrintf("Addresses of variables in the VM:\n");
for (int i = 0; i < 4; i++) {
- DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i])));
- DebugPrintf(" total %d", s->variablesMax[i]);
- DebugPrintf("\n");
+ debugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i])));
+ debugPrintf(" total %d", s->variablesMax[i]);
+ debugPrintf("\n");
}
return true;
@@ -2360,12 +2379,12 @@ bool Console::cmdVMVarlist(int argc, const char **argv) {
bool Console::cmdVMVars(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Displays or changes variables in the VM\n");
- DebugPrintf("Usage: %s <type> <varnum> [<value>]\n", argv[0]);
- DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n");
- DebugPrintf("Second parameter is the var number (not specified on acc)\n");
- DebugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Displays or changes variables in the VM\n");
+ debugPrintf("Usage: %s <type> <varnum> [<value>]\n", argv[0]);
+ debugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n");
+ debugPrintf("Second parameter is the var number (not specified on acc)\n");
+ debugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -2379,7 +2398,7 @@ bool Console::cmdVMVars(int argc, const char **argv) {
const char *setValue = NULL;
if (!varType_pre) {
- DebugPrintf("Invalid variable type '%c'\n", *argv[1]);
+ debugPrintf("Invalid variable type '%c'\n", *argv[1]);
return true;
}
@@ -2392,11 +2411,11 @@ bool Console::cmdVMVars(int argc, const char **argv) {
case 3: {
// for global, local, temp and param, we need an index
if (argc < 3) {
- DebugPrintf("Variable number must be specified for requested type\n");
+ debugPrintf("Variable number must be specified for requested type\n");
return true;
}
if (argc > 4) {
- DebugPrintf("Too many arguments\n");
+ debugPrintf("Too many arguments\n");
return true;
}
@@ -2404,12 +2423,12 @@ bool Console::cmdVMVars(int argc, const char **argv) {
return true;
if (varIndex < 0) {
- DebugPrintf("Variable number may not be negative\n");
+ debugPrintf("Variable number may not be negative\n");
return true;
}
if (s->variablesMax[varType] <= varIndex) {
- DebugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]);
+ debugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]);
return true;
}
curValue = &s->variables[varType][varIndex];
@@ -2421,7 +2440,7 @@ bool Console::cmdVMVars(int argc, const char **argv) {
case 4:
// acc
if (argc > 3) {
- DebugPrintf("Too many arguments\n");
+ debugPrintf("Too many arguments\n");
return true;
}
curValue = &s->r_acc;
@@ -2435,16 +2454,16 @@ bool Console::cmdVMVars(int argc, const char **argv) {
if (!setValue) {
if (varType == 4)
- DebugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue));
+ debugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue));
else
- DebugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue));
+ debugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue));
printBasicVarInfo(*curValue);
- DebugPrintf("\n");
+ debugPrintf("\n");
} else {
if (parse_reg_t(s, setValue, curValue, true)) {
- DebugPrintf("Invalid value/address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
- DebugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n");
+ debugPrintf("Invalid value/address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n");
return true;
}
}
@@ -2453,13 +2472,13 @@ bool Console::cmdVMVars(int argc, const char **argv) {
bool Console::cmdStack(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Lists the specified number of stack elements.\n");
- DebugPrintf("Usage: %s <elements>\n", argv[0]);
+ debugPrintf("Lists the specified number of stack elements.\n");
+ debugPrintf("Usage: %s <elements>\n", argv[0]);
return true;
}
if (_engine->_gamestate->_executionStack.empty()) {
- DebugPrintf("No exec stack!");
+ debugPrintf("No exec stack!");
return true;
}
@@ -2468,9 +2487,9 @@ bool Console::cmdStack(int argc, const char **argv) {
for (int i = nr; i > 0; i--) {
if ((xs.sp - xs.fp - i) == 0)
- DebugPrintf("-- temp variables --\n");
+ debugPrintf("-- temp variables --\n");
if (xs.sp - i >= _engine->_gamestate->stack_base)
- DebugPrintf("ST:%04x = %04x:%04x\n", (unsigned)(xs.sp - i - _engine->_gamestate->stack_base), PRINT_REG(xs.sp[-i]));
+ debugPrintf("ST:%04x = %04x:%04x\n", (unsigned)(xs.sp - i - _engine->_gamestate->stack_base), PRINT_REG(xs.sp[-i]));
}
return true;
@@ -2478,19 +2497,19 @@ bool Console::cmdStack(int argc, const char **argv) {
bool Console::cmdValueType(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Determines the type of a value.\n");
- DebugPrintf("The type can be one of the following:\n");
- DebugPrintf("Invalid, list, object, reference or arithmetic\n");
- DebugPrintf("Usage: %s <address>\n", argv[0]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Determines the type of a value.\n");
+ debugPrintf("The type can be one of the following:\n");
+ debugPrintf("Invalid, list, object, reference or arithmetic\n");
+ debugPrintf("Usage: %s <address>\n", argv[0]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
reg_t val;
if (parse_reg_t(_engine->_gamestate, argv[1], &val, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -2498,22 +2517,22 @@ bool Console::cmdValueType(int argc, const char **argv) {
switch (t) {
case SIG_TYPE_LIST:
- DebugPrintf("List");
+ debugPrintf("List");
break;
case SIG_TYPE_OBJECT:
- DebugPrintf("Object");
+ debugPrintf("Object");
break;
case SIG_TYPE_REFERENCE:
- DebugPrintf("Reference");
+ debugPrintf("Reference");
break;
case SIG_TYPE_INTEGER:
- DebugPrintf("Integer");
+ debugPrintf("Integer");
break;
case SIG_TYPE_INTEGER | SIG_TYPE_NULL:
- DebugPrintf("Null");
+ debugPrintf("Null");
break;
default:
- DebugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t);
+ debugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t);
}
return true;
@@ -2521,17 +2540,17 @@ bool Console::cmdValueType(int argc, const char **argv) {
bool Console::cmdViewListNode(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Examines the list node at the given address.\n");
- DebugPrintf("Usage: %s <address>\n", argv[0]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Examines the list node at the given address.\n");
+ debugPrintf("Usage: %s <address>\n", argv[0]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
reg_t addr;
if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -2541,11 +2560,11 @@ bool Console::cmdViewListNode(int argc, const char **argv) {
bool Console::cmdViewReference(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Examines an arbitrary reference.\n");
- DebugPrintf("Usage: %s <start address> [<end address>]\n", argv[0]);
- DebugPrintf("Where <start address> is the starting address to examine\n");
- DebugPrintf("<end address>, if provided, is the address where examining ends at\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Examines an arbitrary reference.\n");
+ debugPrintf("Usage: %s <start address> [<end address>]\n", argv[0]);
+ debugPrintf("Where <start address> is the starting address to examine\n");
+ debugPrintf("<end address>, if provided, is the address where examining ends at\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -2553,15 +2572,15 @@ bool Console::cmdViewReference(int argc, const char **argv) {
reg_t reg_end = NULL_REG;
if (parse_reg_t(_engine->_gamestate, argv[1], &reg, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
if (argc > 2) {
if (parse_reg_t(_engine->_gamestate, argv[2], &reg_end, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
}
@@ -2570,15 +2589,15 @@ bool Console::cmdViewReference(int argc, const char **argv) {
int filter;
int found = 0;
- DebugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask);
+ debugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask);
if (reg.getSegment() == 0 && reg.getOffset() == 0) {
- DebugPrintf("Null.\n");
+ debugPrintf("Null.\n");
return true;
}
if (reg_end.getSegment() != reg.getSegment() && reg_end != NULL_REG) {
- DebugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n");
+ debugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n");
reg_end = NULL_REG;
}
@@ -2586,7 +2605,7 @@ bool Console::cmdViewReference(int argc, const char **argv) {
int type = type_mask & filter;
if (found && type) {
- DebugPrintf("--- Alternatively, it could be a ");
+ debugPrintf("--- Alternatively, it could be a ");
}
@@ -2596,33 +2615,33 @@ bool Console::cmdViewReference(int argc, const char **argv) {
case SIG_TYPE_LIST: {
List *list = _engine->_gamestate->_segMan->lookupList(reg);
- DebugPrintf("list\n");
+ debugPrintf("list\n");
if (list)
printList(list);
else
- DebugPrintf("Invalid list.\n");
+ debugPrintf("Invalid list.\n");
}
break;
case SIG_TYPE_NODE:
- DebugPrintf("list node\n");
+ debugPrintf("list node\n");
printNode(reg);
break;
case SIG_TYPE_OBJECT:
- DebugPrintf("object\n");
+ debugPrintf("object\n");
printObject(reg);
break;
case SIG_TYPE_REFERENCE: {
switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) {
#ifdef ENABLE_SCI32
case SEG_TYPE_STRING: {
- DebugPrintf("SCI32 string\n");
+ debugPrintf("SCI32 string\n");
const SciString *str = _engine->_gamestate->_segMan->lookupString(reg);
Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0);
break;
}
case SEG_TYPE_ARRAY: {
- DebugPrintf("SCI32 array:\n");
+ debugPrintf("SCI32 array:\n");
const SciArray<reg_t> *array = _engine->_gamestate->_segMan->lookupArray(reg);
hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true);
break;
@@ -2632,10 +2651,10 @@ bool Console::cmdViewReference(int argc, const char **argv) {
const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg);
uint16 size = block.maxSize;
- DebugPrintf("raw data\n");
+ debugPrintf("raw data\n");
if (reg_end.getSegment() != 0 && (size < reg_end.getOffset() - reg.getOffset())) {
- DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size);
+ debugPrintf("Block end out of bounds (size %d). Resetting.\n", size);
reg_end = NULL_REG;
}
@@ -2643,7 +2662,7 @@ bool Console::cmdViewReference(int argc, const char **argv) {
size = reg_end.getOffset() - reg.getOffset();
if (reg_end.getSegment() != 0)
- DebugPrintf("Block size less than or equal to %d\n", size);
+ debugPrintf("Block size less than or equal to %d\n", size);
if (block.isRaw)
Common::hexdump(block.raw, size, 16, 0);
@@ -2654,14 +2673,14 @@ bool Console::cmdViewReference(int argc, const char **argv) {
break;
}
case SIG_TYPE_INTEGER:
- DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset());
+ debugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset());
break;
default:
- DebugPrintf("unknown type %d.\n", type);
+ debugPrintf("unknown type %d.\n", type);
}
if (type) {
- DebugPrintf("\n");
+ debugPrintf("\n");
found = 1;
}
}
@@ -2671,47 +2690,47 @@ bool Console::cmdViewReference(int argc, const char **argv) {
bool Console::cmdViewObject(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Examines the object at the given address.\n");
- DebugPrintf("Usage: %s <address>\n", argv[0]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Examines the object at the given address.\n");
+ debugPrintf("Usage: %s <address>\n", argv[0]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
reg_t addr;
if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
- DebugPrintf("Information on the object at the given address:\n");
+ debugPrintf("Information on the object at the given address:\n");
printObject(addr);
return true;
}
bool Console::cmdViewActiveObject(int argc, const char **argv) {
- DebugPrintf("Information on the currently active object or class:\n");
+ debugPrintf("Information on the currently active object or class:\n");
printObject(_engine->_gamestate->xs->objp);
return true;
}
bool Console::cmdViewAccumulatorObject(int argc, const char **argv) {
- DebugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n");
+ debugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n");
printObject(_engine->_gamestate->r_acc);
return true;
}
bool Console::cmdScriptSteps(int argc, const char **argv) {
- DebugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter);
+ debugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter);
return true;
}
bool Console::cmdBacktrace(int argc, const char **argv) {
- DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase);
+ debugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase);
Common::List<ExecStack>::const_iterator iter;
uint i = 0;
@@ -2724,22 +2743,22 @@ bool Console::cmdBacktrace(int argc, const char **argv) {
switch (call.type) {
case EXEC_STACK_TYPE_CALL: // Normal function
if (call.type == EXEC_STACK_TYPE_CALL)
- DebugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.getSegment()]).getScriptNumber());
+ debugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.getSegment()]).getScriptNumber());
if (call.debugSelector != -1) {
- DebugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str());
+ debugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str());
} else if (call.debugExportId != -1) {
- DebugPrintf("export %d (", call.debugExportId);
+ debugPrintf("export %d (", call.debugExportId);
} else if (call.debugLocalCallOffset != -1) {
- DebugPrintf("call %x (", call.debugLocalCallOffset);
+ debugPrintf("call %x (", call.debugLocalCallOffset);
}
break;
case EXEC_STACK_TYPE_KERNEL: // Kernel function
- DebugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str());
+ debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str());
break;
case EXEC_STACK_TYPE_VARSELECTOR:
- DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read",
+ debugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read",
objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str());
break;
}
@@ -2750,32 +2769,32 @@ bool Console::cmdBacktrace(int argc, const char **argv) {
totalparamc = 16;
for (paramc = 1; paramc <= totalparamc; paramc++) {
- DebugPrintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc]));
+ debugPrintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc]));
if (paramc < call.argc)
- DebugPrintf(", ");
+ debugPrintf(", ");
}
if (call.argc > 16)
- DebugPrintf("...");
+ debugPrintf("...");
- DebugPrintf(")\n ");
+ debugPrintf(")\n ");
if (call.debugOrigin != -1)
- DebugPrintf("by %x ", call.debugOrigin);
- DebugPrintf("obj@%04x:%04x", PRINT_REG(call.objp));
+ debugPrintf("by %x ", call.debugOrigin);
+ debugPrintf("obj@%04x:%04x", PRINT_REG(call.objp));
if (call.type == EXEC_STACK_TYPE_CALL) {
- DebugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc));
+ debugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc));
if (call.sp == CALL_SP_CARRY)
- DebugPrintf(" sp,fp:carry");
+ debugPrintf(" sp,fp:carry");
else {
- DebugPrintf(" sp=ST:%04x", (unsigned)(call.sp - _engine->_gamestate->stack_base));
- DebugPrintf(" fp=ST:%04x", (unsigned)(call.fp - _engine->_gamestate->stack_base));
+ debugPrintf(" sp=ST:%04x", (unsigned)(call.sp - _engine->_gamestate->stack_base));
+ debugPrintf(" fp=ST:%04x", (unsigned)(call.fp - _engine->_gamestate->stack_base));
}
} else
- DebugPrintf(" pc:none");
+ debugPrintf(" pc:none");
- DebugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base));
- DebugPrintf("\n");
+ debugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base));
+ debugPrintf("\n");
}
return true;
@@ -2786,7 +2805,7 @@ bool Console::cmdTrace(int argc, const char **argv) {
_debugState.runningStep = atoi(argv[1]) - 1;
_debugState.debugging = true;
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdStepOver(int argc, const char **argv) {
@@ -2794,14 +2813,14 @@ bool Console::cmdStepOver(int argc, const char **argv) {
_debugState.seekLevel = _engine->_gamestate->_executionStack.size();
_debugState.debugging = true;
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdStepEvent(int argc, const char **argv) {
_debugState.stopOnEvent = true;
_debugState.debugging = true;
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdStepRet(int argc, const char **argv) {
@@ -2809,13 +2828,13 @@ bool Console::cmdStepRet(int argc, const char **argv) {
_debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1;
_debugState.debugging = true;
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdStepGlobal(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Steps until the global variable with the specified index is modified.\n");
- DebugPrintf("Usage: %s <global variable index>\n", argv[0]);
+ debugPrintf("Steps until the global variable with the specified index is modified.\n");
+ debugPrintf("Usage: %s <global variable index>\n", argv[0]);
return true;
}
@@ -2823,7 +2842,7 @@ bool Console::cmdStepGlobal(int argc, const char **argv) {
_debugState.seekSpecial = atoi(argv[1]);
_debugState.debugging = true;
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdStepCallk(int argc, const char **argv) {
@@ -2844,7 +2863,7 @@ bool Console::cmdStepCallk(int argc, const char **argv) {
}
if (callk_index == -1) {
- DebugPrintf("Unknown kernel function '%s'\n", argv[1]);
+ debugPrintf("Unknown kernel function '%s'\n", argv[1]);
return true;
}
}
@@ -2856,16 +2875,16 @@ bool Console::cmdStepCallk(int argc, const char **argv) {
}
_debugState.debugging = true;
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdDisassemble(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("Disassembles a method by name.\n");
- DebugPrintf("Usage: %s <object> <method> <options>\n", argv[0]);
- DebugPrintf("Valid options are:\n");
- DebugPrintf(" bwt : Print byte/word tag\n");
- DebugPrintf(" bc : Print bytecode\n");
+ debugPrintf("Disassembles a method by name.\n");
+ debugPrintf("Usage: %s <object> <method> <options>\n", argv[0]);
+ debugPrintf("Valid options are:\n");
+ debugPrintf(" bwt : Print byte/word tag\n");
+ debugPrintf(" bc : Print bytecode\n");
return true;
}
@@ -2874,8 +2893,8 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
bool printBWTag = false;
if (parse_reg_t(_engine->_gamestate, argv[1], &objAddr, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -2884,17 +2903,17 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
reg_t addr = NULL_REG;
if (!obj) {
- DebugPrintf("Not an object.\n");
+ debugPrintf("Not an object.\n");
return true;
}
if (selectorId < 0) {
- DebugPrintf("Not a valid selector name.\n");
+ debugPrintf("Not a valid selector name.\n");
return true;
}
if (lookupSelector(_engine->_gamestate->_segMan, objAddr, selectorId, NULL, &addr) != kSelectorMethod) {
- DebugPrintf("Not a method.\n");
+ debugPrintf("Not a method.\n");
return true;
}
@@ -2924,12 +2943,12 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
bool Console::cmdDisassembleAddress(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Disassembles one or more commands.\n");
- DebugPrintf("Usage: %s [startaddr] <options>\n", argv[0]);
- DebugPrintf("Valid options are:\n");
- DebugPrintf(" bwt : Print byte/word tag\n");
- DebugPrintf(" c<x> : Disassemble <x> bytes\n");
- DebugPrintf(" bc : Print bytecode\n");
+ debugPrintf("Disassembles one or more commands.\n");
+ debugPrintf("Usage: %s [startaddr] <options>\n", argv[0]);
+ debugPrintf("Valid options are:\n");
+ debugPrintf(" bwt : Print byte/word tag\n");
+ debugPrintf(" c<x> : Disassemble <x> bytes\n");
+ debugPrintf(" bc : Print bytecode\n");
return true;
}
@@ -2940,8 +2959,8 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) {
uint16 size;
if (parse_reg_t(_engine->_gamestate, argv[1], &vpc, false)) {
- DebugPrintf("Invalid address passed.\n");
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -2956,7 +2975,7 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) {
else if (toupper(argv[i][0]) == 'C')
opCount = atoi(argv[i] + 1);
else {
- DebugPrintf("Invalid option '%s'\n", argv[i]);
+ debugPrintf("Invalid option '%s'\n", argv[i]);
return true;
}
}
@@ -2974,7 +2993,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
Common::sort(resources.begin(), resources.end());
if (showFoundScripts)
- DebugPrintf("%d scripts found, dissassembling...\n", resources.size());
+ debugPrintf("%d scripts found, dissassembling...\n", resources.size());
int scriptSegment;
Script *script;
@@ -3023,7 +3042,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
uint16 argc2 = opparams[1];
if (kFuncNum == kernelFuncNum) {
- DebugPrintf("Called from script %d, object %s, method %s(%d) with %d bytes for arguments\n",
+ debugPrintf("Called from script %d, object %s, method %s(%d) with %d bytes for arguments\n",
itr->getNumber(), objName,
_engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), i, argc2);
}
@@ -3055,19 +3074,19 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Finds the scripts and methods that call a specific kernel function.\n");
- DebugPrintf("Usage: %s <kernel function>\n", argv[0]);
- DebugPrintf("Example: %s Display\n", argv[0]);
- DebugPrintf("Special usage:\n");
- DebugPrintf("%s Dummy - find all calls to actual dummy functions "
+ debugPrintf("Finds the scripts and methods that call a specific kernel function.\n");
+ debugPrintf("Usage: %s <kernel function>\n", argv[0]);
+ debugPrintf("Example: %s Display\n", argv[0]);
+ debugPrintf("Special usage:\n");
+ debugPrintf("%s Dummy - find all calls to actual dummy functions "
"(mapped to kDummy, and dummy in the kernel table). "
"There shouldn't be calls to these (apart from a known "
"one in Shivers)\n", argv[0]);
- DebugPrintf("%s Unused - find all calls to unused functions (mapped to "
+ debugPrintf("%s Unused - find all calls to unused functions (mapped to "
"kDummy - i.e. mapped in SSCI but dummy in ScummVM, thus "
"they'll error out when called). Only debug scripts should "
"be calling these\n", argv[0]);
- DebugPrintf("%s Unmapped - find all calls to currently unmapped or "
+ debugPrintf("%s Unmapped - find all calls to currently unmapped or "
"unimplemented functions (mapped to kStub/kStubNull)\n", argv[0]);
return true;
}
@@ -3080,7 +3099,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
int kernelFuncNum = kernel->findKernelFuncPos(argv[1]);
if (kernelFuncNum < 0) {
- DebugPrintf("Invalid kernel function requested\n");
+ debugPrintf("Invalid kernel function requested\n");
return true;
}
@@ -3090,7 +3109,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
// in the kernel table)
for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) {
if (kernel->_kernelFuncs[i].function == &kDummy && kernel->getKernelName(i) == "Dummy") {
- DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
+ debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
printKernelCallsFound(i, false);
}
}
@@ -3100,7 +3119,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
// called)
for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) {
if (kernel->_kernelFuncs[i].function == &kDummy && kernel->getKernelName(i) != "Dummy") {
- DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
+ debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
printKernelCallsFound(i, false);
}
}
@@ -3109,7 +3128,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) {
if (kernel->_kernelFuncs[i].function == &kStub ||
kernel->_kernelFuncs[i].function == &kStubNull) {
- DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
+ debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
printKernelCallsFound(i, false);
}
}
@@ -3120,17 +3139,17 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
bool Console::cmdSend(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("Sends a message to an object.\n");
- DebugPrintf("Usage: %s <object> <selector name> <param1> <param2> ... <paramn>\n", argv[0]);
- DebugPrintf("Example: %s ?fooScript cue\n", argv[0]);
+ debugPrintf("Sends a message to an object.\n");
+ debugPrintf("Usage: %s <object> <selector name> <param1> <param2> ... <paramn>\n", argv[0]);
+ debugPrintf("Example: %s ?fooScript cue\n", argv[0]);
return true;
}
reg_t object;
if (parse_reg_t(_engine->_gamestate, argv[1], &object, false)) {
- DebugPrintf("Invalid address \"%s\" passed.\n", argv[1]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address \"%s\" passed.\n", argv[1]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
@@ -3138,20 +3157,20 @@ bool Console::cmdSend(int argc, const char **argv) {
int selectorId = _engine->getKernel()->findSelector(selectorName);
if (selectorId < 0) {
- DebugPrintf("Unknown selector: \"%s\"\n", selectorName);
+ debugPrintf("Unknown selector: \"%s\"\n", selectorName);
return true;
}
const Object *o = _engine->_gamestate->_segMan->getObject(object);
if (o == NULL) {
- DebugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object));
+ debugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object));
return true;
}
SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, NULL, NULL);
if (selector_type == kSelectorNone) {
- DebugPrintf("Object does not support selector: \"%s\"\n", selectorName);
+ debugPrintf("Object does not support selector: \"%s\"\n", selectorName);
return true;
}
@@ -3165,8 +3184,8 @@ bool Console::cmdSend(int argc, const char **argv) {
stackframe[1] = make_reg(0, send_argc);
for (int i = 0; i < send_argc; i++) {
if (parse_reg_t(_engine->_gamestate, argv[3+i], &stackframe[2+i], false)) {
- DebugPrintf("Invalid address \"%s\" passed.\n", argv[3+i]);
- DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ debugPrintf("Invalid address \"%s\" passed.\n", argv[3+i]);
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true;
}
}
@@ -3184,7 +3203,7 @@ bool Console::cmdSend(int argc, const char **argv) {
if (old_xstack != xstack) {
_engine->_gamestate->_executionStackPosChanged = true;
- DebugPrintf("Message scheduled for execution\n");
+ debugPrintf("Message scheduled for execution\n");
// We call run_engine explictly so we can restore the value of r_acc
// after execution.
@@ -3194,7 +3213,7 @@ bool Console::cmdSend(int argc, const char **argv) {
if (restore_acc) {
// varselector read or message executed
- DebugPrintf("Message completed. Value returned: %04x:%04x\n", PRINT_REG(_engine->_gamestate->r_acc));
+ debugPrintf("Message completed. Value returned: %04x:%04x\n", PRINT_REG(_engine->_gamestate->r_acc));
_engine->_gamestate->r_acc = old_acc;
}
@@ -3205,14 +3224,14 @@ bool Console::cmdGo(int argc, const char **argv) {
// CHECKME: is this necessary?
_debugState.seeking = kDebugSeekNothing;
- return Cmd_Exit(argc, argv);
+ return cmdExit(argc, argv);
}
bool Console::cmdLogKernel(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("Logs calls to specified kernel function.\n");
- DebugPrintf("Usage: %s <kernel function/*> <on/off>\n", argv[0]);
- DebugPrintf("Example: %s StrCpy on\n", argv[0]);
+ debugPrintf("Logs calls to specified kernel function.\n");
+ debugPrintf("Usage: %s <kernel function/*> <on/off>\n", argv[0]);
+ debugPrintf("Example: %s StrCpy on\n", argv[0]);
return true;
}
@@ -3222,14 +3241,14 @@ bool Console::cmdLogKernel(int argc, const char **argv) {
else if (strcmp(argv[2], "off") == 0)
logging = false;
else {
- DebugPrintf("2nd parameter must be either on or off\n");
+ debugPrintf("2nd parameter must be either on or off\n");
return true;
}
if (g_sci->getKernel()->debugSetFunction(argv[1], logging, -1))
- DebugPrintf("Logging %s for k%s\n", logging ? "enabled" : "disabled", argv[1]);
+ debugPrintf("Logging %s for k%s\n", logging ? "enabled" : "disabled", argv[1]);
else
- DebugPrintf("Unknown kernel function %s\n", argv[1]);
+ debugPrintf("Unknown kernel function %s\n", argv[1]);
return true;
}
@@ -3237,25 +3256,25 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
int i = 0;
int bpdata;
- DebugPrintf("Breakpoint list:\n");
+ debugPrintf("Breakpoint list:\n");
Common::List<Breakpoint>::const_iterator bp = _debugState._breakpoints.begin();
Common::List<Breakpoint>::const_iterator end = _debugState._breakpoints.end();
for (; bp != end; ++bp) {
- DebugPrintf(" #%i: ", i);
+ debugPrintf(" #%i: ", i);
switch (bp->type) {
case BREAK_SELECTOREXEC:
- DebugPrintf("Execute %s\n", bp->name.c_str());
+ debugPrintf("Execute %s\n", bp->name.c_str());
break;
case BREAK_SELECTORREAD:
- DebugPrintf("Read %s\n", bp->name.c_str());
+ debugPrintf("Read %s\n", bp->name.c_str());
break;
case BREAK_SELECTORWRITE:
- DebugPrintf("Write %s\n", bp->name.c_str());
+ debugPrintf("Write %s\n", bp->name.c_str());
break;
case BREAK_EXPORT:
bpdata = bp->address;
- DebugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF);
+ debugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF);
break;
}
@@ -3263,16 +3282,16 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
}
if (!i)
- DebugPrintf(" No breakpoints defined.\n");
+ debugPrintf(" No breakpoints defined.\n");
return true;
}
bool Console::cmdBreakpointDelete(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Deletes a breakpoint with the specified index.\n");
- DebugPrintf("Usage: %s <breakpoint index>\n", argv[0]);
- DebugPrintf("<index> * will remove all breakpoints\n");
+ debugPrintf("Deletes a breakpoint with the specified index.\n");
+ debugPrintf("Usage: %s <breakpoint index>\n", argv[0]);
+ debugPrintf("<index> * will remove all breakpoints\n");
return true;
}
@@ -3292,7 +3311,7 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) {
}
if (bp == end) {
- DebugPrintf("Invalid breakpoint index %i\n", idx);
+ debugPrintf("Invalid breakpoint index %i\n", idx);
return true;
}
@@ -3312,11 +3331,11 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) {
bool Console::cmdBreakpointMethod(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Sets a breakpoint on execution of a specified method/selector.\n");
- DebugPrintf("Usage: %s <name>\n", argv[0]);
- DebugPrintf("Example: %s ego::doit\n", argv[0]);
- DebugPrintf("May also be used to set a breakpoint that applies whenever an object\n");
- DebugPrintf("of a specific type is touched: %s foo::\n", argv[0]);
+ debugPrintf("Sets a breakpoint on execution of a specified method/selector.\n");
+ debugPrintf("Usage: %s <name>\n", argv[0]);
+ debugPrintf("Example: %s ego::doit\n", argv[0]);
+ debugPrintf("May also be used to set a breakpoint that applies whenever an object\n");
+ debugPrintf("of a specific type is touched: %s foo::\n", argv[0]);
return true;
}
@@ -3334,9 +3353,9 @@ bool Console::cmdBreakpointMethod(int argc, const char **argv) {
bool Console::cmdBreakpointRead(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Sets a breakpoint on reading of a specified selector.\n");
- DebugPrintf("Usage: %s <name>\n", argv[0]);
- DebugPrintf("Example: %s ego::view\n", argv[0]);
+ debugPrintf("Sets a breakpoint on reading of a specified selector.\n");
+ debugPrintf("Usage: %s <name>\n", argv[0]);
+ debugPrintf("Example: %s ego::view\n", argv[0]);
return true;
}
@@ -3351,9 +3370,9 @@ bool Console::cmdBreakpointRead(int argc, const char **argv) {
bool Console::cmdBreakpointWrite(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Sets a breakpoint on writing of a specified selector.\n");
- DebugPrintf("Usage: %s <name>\n", argv[0]);
- DebugPrintf("Example: %s ego::view\n", argv[0]);
+ debugPrintf("Sets a breakpoint on writing of a specified selector.\n");
+ debugPrintf("Usage: %s <name>\n", argv[0]);
+ debugPrintf("Example: %s ego::view\n", argv[0]);
return true;
}
@@ -3368,9 +3387,9 @@ bool Console::cmdBreakpointWrite(int argc, const char **argv) {
bool Console::cmdBreakpointKernel(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("Sets a breakpoint on execution of a kernel function.\n");
- DebugPrintf("Usage: %s <name> <on/off>\n", argv[0]);
- DebugPrintf("Example: %s DrawPic on\n", argv[0]);
+ debugPrintf("Sets a breakpoint on execution of a kernel function.\n");
+ debugPrintf("Usage: %s <name> <on/off>\n", argv[0]);
+ debugPrintf("Example: %s DrawPic on\n", argv[0]);
return true;
}
@@ -3380,22 +3399,22 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) {
else if (strcmp(argv[2], "off") == 0)
breakpoint = false;
else {
- DebugPrintf("2nd parameter must be either on or off\n");
+ debugPrintf("2nd parameter must be either on or off\n");
return true;
}
if (g_sci->getKernel()->debugSetFunction(argv[1], -1, breakpoint))
- DebugPrintf("Breakpoint %s for k%s\n", (breakpoint ? "enabled" : "disabled"), argv[1]);
+ debugPrintf("Breakpoint %s for k%s\n", (breakpoint ? "enabled" : "disabled"), argv[1]);
else
- DebugPrintf("Unknown kernel function %s\n", argv[1]);
+ debugPrintf("Unknown kernel function %s\n", argv[1]);
return true;
}
bool Console::cmdBreakpointFunction(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Sets a breakpoint on the execution of the specified exported function.\n");
- DebugPrintf("Usage: %s <script number> <export number\n", argv[0]);
+ debugPrintf("Sets a breakpoint on the execution of the specified exported function.\n");
+ debugPrintf("Usage: %s <script number> <export number\n", argv[0]);
return true;
}
@@ -3415,21 +3434,21 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) {
bool Console::cmdSfx01Header(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Dumps the header of a SCI01 song\n");
- DebugPrintf("Usage: %s <track>\n", argv[0]);
+ debugPrintf("Dumps the header of a SCI01 song\n");
+ debugPrintf("Usage: %s <track>\n", argv[0]);
return true;
}
Resource *song = _engine->getResMan()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0);
if (!song) {
- DebugPrintf("Doesn't exist\n");
+ debugPrintf("Doesn't exist\n");
return true;
}
uint32 offset = 0;
- DebugPrintf("SCI01 song track mappings:\n");
+ debugPrintf("SCI01 song track mappings:\n");
if (*song->data == 0xf0) // SCI1 priority spec
offset = 8;
@@ -3439,7 +3458,7 @@ bool Console::cmdSfx01Header(int argc, const char **argv) {
while (song->data[offset] != 0xff) {
byte device_id = song->data[offset];
- DebugPrintf("* Device %02x:\n", device_id);
+ debugPrintf("* Device %02x:\n", device_id);
offset++;
if (offset + 1 >= song->size)
@@ -3461,12 +3480,12 @@ bool Console::cmdSfx01Header(int argc, const char **argv) {
track_offset += 2;
end = READ_LE_UINT16(song->data + offset + 2);
- DebugPrintf(" - %04x -- %04x", track_offset, track_offset + end);
+ debugPrintf(" - %04x -- %04x", track_offset, track_offset + end);
if (track_offset == 0xfe)
- DebugPrintf(" (PCM data)\n");
+ debugPrintf(" (PCM data)\n");
else
- DebugPrintf(" (channel %d, special %d, %d playing notes, %d foo)\n",
+ debugPrintf(" (channel %d, special %d, %d playing notes, %d foo)\n",
header1 & 0xf, header1 >> 4, header2 & 0xf, header2 >> 4);
offset += 4;
}
@@ -3580,8 +3599,8 @@ static void midi_hexdump(byte *data, int size, int notational_offset) {
bool Console::cmdSfx01Track(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Dumps a track of a SCI01 song\n");
- DebugPrintf("Usage: %s <track> <offset>\n", argv[0]);
+ debugPrintf("Dumps a track of a SCI01 song\n");
+ debugPrintf("Usage: %s <track> <offset>\n", argv[0]);
return true;
}
@@ -3590,7 +3609,7 @@ bool Console::cmdSfx01Track(int argc, const char **argv) {
int offset = atoi(argv[2]);
if (!song) {
- DebugPrintf("Doesn't exist\n");
+ debugPrintf("Doesn't exist\n");
return true;
}
@@ -3614,29 +3633,29 @@ bool Console::cmdQuit(int argc, const char **argv) {
_debugState.runningStep = 0;
} else {
- DebugPrintf("%s [game] - exit gracefully\n", argv[0]);
- DebugPrintf("%s now - exit ungracefully\n", argv[0]);
+ debugPrintf("%s [game] - exit gracefully\n", argv[0]);
+ debugPrintf("%s now - exit ungracefully\n", argv[0]);
return true;
}
- return Cmd_Exit(0, 0);
+ return cmdExit(0, 0);
}
bool Console::cmdAddresses(int argc, const char **argv) {
- DebugPrintf("Address parameters may be passed in one of three forms:\n");
- DebugPrintf(" - ssss:oooo -- where 'ssss' denotes a segment and 'oooo' an offset.\n");
- DebugPrintf(" Example: \"a:c5\" would address something in segment 0xa at offset 0xc5.\n");
- DebugPrintf(" - &scr:oooo -- where 'scr' is a script number and oooo an offset within that script; will\n");
- DebugPrintf(" fail if the script is not currently loaded\n");
- DebugPrintf(" - $REG -- where 'REG' is one of 'PC', 'ACC', 'PREV' or 'OBJ': References the address\n");
- DebugPrintf(" indicated by the register of this name.\n");
- DebugPrintf(" - $REG+n (or -n) -- Like $REG, but modifies the offset part by a specific amount (which\n");
- DebugPrintf(" is specified in hexadecimal).\n");
- DebugPrintf(" - ?obj -- Looks up an object with the specified name, uses its address. This will abort if\n");
- DebugPrintf(" the object name is ambiguous; in that case, a list of addresses and indices is provided.\n");
- DebugPrintf(" ?obj.idx may be used to disambiguate 'obj' by the index 'idx'.\n");
- DebugPrintf(" Underscores are used as substitute characters for spaces in object names.\n");
- DebugPrintf(" For example, an object named \"Glass Jar\" can be accessed as \"Glass_Jar\".\n");
+ debugPrintf("Address parameters may be passed in one of three forms:\n");
+ debugPrintf(" - ssss:oooo -- where 'ssss' denotes a segment and 'oooo' an offset.\n");
+ debugPrintf(" Example: \"a:c5\" would address something in segment 0xa at offset 0xc5.\n");
+ debugPrintf(" - &scr:oooo -- where 'scr' is a script number and oooo an offset within that script; will\n");
+ debugPrintf(" fail if the script is not currently loaded\n");
+ debugPrintf(" - $REG -- where 'REG' is one of 'PC', 'ACC', 'PREV' or 'OBJ': References the address\n");
+ debugPrintf(" indicated by the register of this name.\n");
+ debugPrintf(" - $REG+n (or -n) -- Like $REG, but modifies the offset part by a specific amount (which\n");
+ debugPrintf(" is specified in hexadecimal).\n");
+ debugPrintf(" - ?obj -- Looks up an object with the specified name, uses its address. This will abort if\n");
+ debugPrintf(" the object name is ambiguous; in that case, a list of addresses and indices is provided.\n");
+ debugPrintf(" ?obj.idx may be used to disambiguate 'obj' by the index 'idx'.\n");
+ debugPrintf(" Underscores are used as substitute characters for spaces in object names.\n");
+ debugPrintf(" For example, an object named \"Glass Jar\" can be accessed as \"Glass_Jar\".\n");
return true;
}
@@ -3887,14 +3906,14 @@ bool Console::parseInteger(const char *argument, int &result) {
// hexadecimal number
result = strtol(argument, &endPtr, 16);
if ((*endPtr != 0) && (*endPtr != 'h')) {
- DebugPrintf("Invalid hexadecimal number '%s'\n", argument);
+ debugPrintf("Invalid hexadecimal number '%s'\n", argument);
return false;
}
} else {
// decimal number
result = strtol(argument, &endPtr, 10);
if (*endPtr != 0) {
- DebugPrintf("Invalid decimal number '%s'\n", argument);
+ debugPrintf("Invalid decimal number '%s'\n", argument);
return false;
}
}
@@ -3912,57 +3931,57 @@ void Console::printBasicVarInfo(reg_t variable) {
case SIG_TYPE_INTEGER: {
uint16 content = variable.toUint16();
if (content >= 10)
- DebugPrintf(" (%dd)", content);
+ debugPrintf(" (%dd)", content);
break;
}
case SIG_TYPE_OBJECT:
- DebugPrintf(" (object '%s')", segMan->getObjectName(variable));
+ debugPrintf(" (object '%s')", segMan->getObjectName(variable));
break;
case SIG_TYPE_REFERENCE:
- DebugPrintf(" (reference)");
+ debugPrintf(" (reference)");
break;
case SIG_TYPE_NODE:
- DebugPrintf(" (node)");
+ debugPrintf(" (node)");
break;
case SIG_TYPE_LIST:
- DebugPrintf(" (list)");
+ debugPrintf(" (list)");
break;
case SIG_TYPE_UNINITIALIZED:
- DebugPrintf(" (uninitialized)");
+ debugPrintf(" (uninitialized)");
break;
case SIG_TYPE_ERROR:
- DebugPrintf(" (error)");
+ debugPrintf(" (error)");
break;
default:
- DebugPrintf(" (??\?)");
+ debugPrintf(" (??\?)");
}
if (regType & SIG_IS_INVALID)
- DebugPrintf(" IS INVALID!");
+ debugPrintf(" IS INVALID!");
}
void Console::printList(List *list) {
reg_t pos = list->first;
reg_t my_prev = NULL_REG;
- DebugPrintf("\t<\n");
+ debugPrintf("\t<\n");
while (!pos.isNull()) {
Node *node;
NodeTable *nt = (NodeTable *)_engine->_gamestate->_segMan->getSegment(pos.getSegment(), SEG_TYPE_NODES);
if (!nt || !nt->isValidEntry(pos.getOffset())) {
- DebugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n",
+ debugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n",
PRINT_REG(pos));
return;
}
node = &(nt->_table[pos.getOffset()]);
- DebugPrintf("\t%04x:%04x : %04x:%04x -> %04x:%04x\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value));
+ debugPrintf("\t%04x:%04x : %04x:%04x -> %04x:%04x\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value));
if (my_prev != node->pred)
- DebugPrintf(" WARNING: current node gives %04x:%04x as predecessor!\n",
+ debugPrintf(" WARNING: current node gives %04x:%04x as predecessor!\n",
PRINT_REG(node->pred));
my_prev = pos;
@@ -3970,9 +3989,9 @@ void Console::printList(List *list) {
}
if (my_prev != list->last)
- DebugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n",
+ debugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n",
PRINT_REG(list->last), PRINT_REG(my_prev));
- DebugPrintf("\t>\n");
+ debugPrintf("\t>\n");
}
int Console::printNode(reg_t addr) {
@@ -3983,32 +4002,32 @@ int Console::printNode(reg_t addr) {
List *list;
if (!lt->isValidEntry(addr.getOffset())) {
- DebugPrintf("Address does not contain a list\n");
+ debugPrintf("Address does not contain a list\n");
return 1;
}
list = &(lt->_table[addr.getOffset()]);
- DebugPrintf("%04x:%04x : first x last = (%04x:%04x, %04x:%04x)\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last));
+ debugPrintf("%04x:%04x : first x last = (%04x:%04x, %04x:%04x)\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last));
} else {
NodeTable *nt;
Node *node;
mobj = _engine->_gamestate->_segMan->getSegment(addr.getSegment(), SEG_TYPE_NODES);
if (!mobj) {
- DebugPrintf("Segment #%04x is not a list or node segment\n", addr.getSegment());
+ debugPrintf("Segment #%04x is not a list or node segment\n", addr.getSegment());
return 1;
}
nt = (NodeTable *)mobj;
if (!nt->isValidEntry(addr.getOffset())) {
- DebugPrintf("Address does not contain a node\n");
+ debugPrintf("Address does not contain a node\n");
return 1;
}
node = &(nt->_table[addr.getOffset()]);
- DebugPrintf("%04x:%04x : prev x next = (%04x:%04x, %04x:%04x); maps %04x:%04x -> %04x:%04x\n",
+ debugPrintf("%04x:%04x : prev x next = (%04x:%04x, %04x:%04x); maps %04x:%04x -> %04x:%04x\n",
PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(node->succ), PRINT_REG(node->key), PRINT_REG(node->value));
}
@@ -4022,44 +4041,44 @@ int Console::printObject(reg_t pos) {
uint i;
if (!obj) {
- DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos));
+ debugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos));
return 1;
}
// Object header
- DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos),
+ debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos),
obj->getVarCount(), obj->getMethodCount());
if (!obj->isClass() && getSciVersion() != SCI_VERSION_3)
var_container = s->_segMan->getObject(obj->getSuperClassSelector());
- DebugPrintf(" -- member variables:\n");
+ debugPrintf(" -- member variables:\n");
for (i = 0; (uint)i < obj->getVarCount(); i++) {
- DebugPrintf(" ");
+ debugPrintf(" ");
if (var_container && i < var_container->getVarCount()) {
uint16 varSelector = var_container->getVarSelector(i);
- DebugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str());
+ debugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str());
} else
- DebugPrintf("p#%x = ", i);
+ debugPrintf("p#%x = ", i);
reg_t val = obj->getVariable(i);
- DebugPrintf("%04x:%04x", PRINT_REG(val));
+ debugPrintf("%04x:%04x", PRINT_REG(val));
if (!val.getSegment())
- DebugPrintf(" (%d)", val.getOffset());
+ debugPrintf(" (%d)", val.getOffset());
const Object *ref = s->_segMan->getObject(val);
if (ref)
- DebugPrintf(" (%s)", s->_segMan->getObjectName(val));
+ debugPrintf(" (%s)", s->_segMan->getObjectName(val));
- DebugPrintf("\n");
+ debugPrintf("\n");
}
- DebugPrintf(" -- methods:\n");
+ debugPrintf(" -- methods:\n");
for (i = 0; i < obj->getMethodCount(); i++) {
reg_t fptr = obj->getFunction(i);
- DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr));
+ debugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr));
}
if (s->_segMan->_heap[pos.getSegment()]->getType() == SEG_TYPE_SCRIPT)
- DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.getSegment())->getScriptNumber());
+ debugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.getSegment())->getScriptNumber());
return 0;
}
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index e97db04a8f..91b3c45c6e 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -469,6 +469,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Eco Quest - English DOS Floppy (reported by misterhands in bug #6599)
+ // Game v1.10, interpreter 2.000.286, INT #6.12.92
+ {"ecoquest", "Floppy", {
+ {"resource.map", 0, "acb10c12bf15ffa7d0fac36124b20c8e", 4890},
+ {"resource.000", 0, "89cf7c8eed99afd0a9f4188170b81ebe", 3428654},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Eco Quest - English DOS Floppy
// SCI interpreter version 1.000.510
{"ecoquest", "Floppy", {
@@ -861,7 +869,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 342149},
{"resource.003", 0, "e0dd44069a62a463fd124974b915f10d", 328925},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 1 - English DOS (supplied by wibble92 in bug report #2644547)
// SCI interpreter version 0.000.530
@@ -888,6 +896,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Hoyle 1 - English DOS v1.000.115 (supplied by misterhands in bug report #6597)
+ // Executable scanning reports "0.000.668"
+ {"hoyle1", "", {
+ {"resource.map", 0, "3ddf55fdbe14eb0e89a27a2cfc1338bd", 4386},
+ {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 519525},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
#if 0 // TODO: unknown if these files are corrupt
// Hoyle 1 - English Amiga (from www.back2roots.org)
// SCI interpreter version 0.000.519 - FIXME: some have 0.000.530, others x.yyy.zzz
@@ -916,6 +932,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Hoyle 2 - English DOS (supplied by misterhands in bug report #6598)
+ // Game v1.000.016, interpreter 0.000.668, INT #12.5.90
+ {"hoyle2", "", {
+ {"resource.map", 0, "d8758a4eb6f34f6b3130bf25a496d123", 1356},
+ {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 217880},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Hoyle 2 - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.002.032"
// SCI interpreter version 0.000.685
@@ -923,15 +947,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "62ed48d20c580e5a98f102f7cd93706a", 1356},
{"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 222704},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Hoyle 2 - English Macintosh
// Executable scanning reports "x.yyy.zzz"
{"hoyle2", "", {
{"resource.map", 0, "1af1d3aa3cf564f93477c9f87e53f495", 1728},
{"resource.001", 0, "b73b8131669d69d41a326415e4519138", 482882},
- {NULL, 0, NULL, 0}},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#if 0 // TODO: unknown if these files are corrupt
// Hoyle 3 - English Amiga (from www.back2roots.org)
@@ -1744,7 +1768,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
- // Laura Bow 2 - English DOS Floppy
+ // Laura Bow 2 - English DOS Floppy v1.0
// Executable scanning reports "2.000.274"
// SCI interpreter version 1.001.069 (just a guess)
{"laurabow2", "", {
@@ -1753,6 +1777,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Laura Bow 2 v1.1 - English DOS Floppy (supplied by misterhands in bug report #6543)
+ // Executable scanning reports "2.000.274"
+ {"laurabow2", "", {
+ {"resource.map", 0, "3b6dfbcda210bbc3f23fd1927113bf98", 6483},
+ {"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766},
+ {"resource.msg", 0, "d1755fc4f41b5210febc9410503c6a29", 278354},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Laura Bow 2 - English DOS CD (from "The Roberta Williams Antology"/1996)
// Executable scanning reports "1.001.072", VERSION file reports "1.1" (from jvprat)
// SCI interpreter version 1.001.069 (just a guess)
@@ -2425,6 +2458,17 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Mixed-Up Fairy Tales - English DOS Floppy EGA (from misterhands, bug report #6596)
+ // Version 1.0, interpreter 1.000.158, INT# 11.23.91
+ {"fairytales", "EGA", {
+ {"resource.map", 0, "de9e151517013af15e0baf7bd8cbfe0b", 3243},
+ {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 840595},
+ {"resource.001", 0, "6ef4acdab49bdcaccf649640ddb12e9a", 115071},
+ {"resource.002", 0, "020d8c9da753a30899dd10c4463682db", 762020},
+ {"resource.003", 0, "9e0dea6b2bfd6cf0007cceb866bcbfb3", 670688},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Mixed-Up Fairy Tales v1.000 - English DOS (supplied by markcoolio in bug report #2723791)
// Executable scanning reports "1.000.145"
{"fairytales", "", {
@@ -2563,6 +2607,25 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Phantasmagoria - French DOS
+ // Supplied by Kervala in bug #6574
+ {"phantasmagoria", "", {
+ {"resmap.001", 0, "4da82dd336d4b9cd8c16f3cc11f0c615", 11524},
+ {"ressci.001", 0, "3aae6559aa1df273bc542d5ac6330d75", 69963685},
+ {"resmap.002", 0, "4f40f43f2b60bf765864433069752bb9", 12064},
+ {"ressci.002", 0, "3aae6559aa1df273bc542d5ac6330d75", 78362841},
+ {"resmap.003", 0, "6a392a86f14b6ddb4422978ee71e54ac", 12340},
+ {"ressci.003", 0, "3aae6559aa1df273bc542d5ac6330d75", 80431189},
+ {"resmap.004", 0, "df2e9462c41202de5f3843908c95a715", 12562},
+ {"ressci.004", 0, "3aae6559aa1df273bc542d5ac6330d75", 82542844},
+ {"resmap.005", 0, "43efd3fe834286c70a2c8b4cd747c1e2", 12616},
+ {"ressci.005", 0, "3aae6559aa1df273bc542d5ac6330d75", 83790486},
+ {"resmap.006", 0, "b3065e54a00190752a06dacd201b5058", 12538},
+ {"ressci.006", 0, "3aae6559aa1df273bc542d5ac6330d75", 85415107},
+ {"resmap.007", 0, "5633960bc106c39ca91d2d8fce18fd2d", 7984},
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Phantasmagoria - English DOS Demo
// Executable scanning reports "2.100.002"
{"phantasmagoria", "Demo", {
@@ -3580,7 +3643,18 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "9107c2aa5398e28b5c5406df13491f85", 596768},
{"resource.003", 0, "9107c2aa5398e28b5c5406df13491f85", 693573},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // Space Quest 3 v1.1 (game says 0.016) - English Mac (supplied by misterhands in bug report #6484)
+ // Executable scanning reports "0.024"
+ {"sq3", "", {
+ {"resource.map", 0, "d1574928fc6187f5958d431ac9d8022e", 5844},
+ {"resource.001", 0, "0d8dfe42683b46f3131823233a91ce6a", 771942},
+ {"resource.002", 0, "0d8dfe42683b46f3131823233a91ce6a", 794127},
+ {"resource.003", 0, "0d8dfe42683b46f3131823233a91ce6a", 776554},
+ {"resource.004", 0, "0d8dfe42683b46f3131823233a91ce6a", 787066},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Space Quest 4 - English Amiga
// Executable scanning reports "1.004.024"
@@ -4020,12 +4094,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
#endif // ENABLE_SCI32
// SCI Fanmade Games
+ FANMADE("120 Degrees Below Zero", "57f6135bd073802215c9b97f32d6aea3", 504, "03adf530a34557dfc20f848c9572f4d0", 320749),
FANMADE("Al Pond: Island Quest 2", "4cba6a5a4c8f66f21935ed78b0511a92", 870, "876587dc9a5ec569287a3dc4b29139d8", 613769),
FANMADE("Al Pond 2: Island Quest", "9625372e710d1a95d2027b48f9e325af", 1506, "a0f9aa65b9bf3d8703adff5a621f243c", 889843),
FANMADE("Al Pond 2: Island Quest (Updated)", "64be277cdcc6aafce7d9f26e88ad31a8", 1500, "571547228a212d63315f0c114cf48d54", 885241),
FANMADE("Another DG Game: I Want My C64 Back", "4a8ca7ca2abd18899ef856f47665e2e9", 588, "12ff558d20c72e42cc6adb408f34d6d8", 150513),
FANMADE_L("Another DG Game: I Want My C64 Back", "13dc1d9ebc57daf8895412eee5e39fea", 576, "e2ad60b3a280171429db5c85f158f84a", 141697, Common::FR_FRA),
FANMADE("Aquarius: An Aquatic Experience", "2e23bc3b82f22a454be202ea593fb478", 480, "01555c8de683d25405bda270aa1ff014", 272372),
+ FANMADE("Betrayed Alliance", "b1f43f496a83cb8503f290a838b26242", 4062, "e637255aae6191ee92b9e843ad276288", 2367197),
FANMADE("Bluntman and Chronic (Politically Correct Version)", "c3ef9fa6c7c5fb840078bf28d87c7f8b", 1362, "441636a9f6f86710844868fded868ee7", 596688),
FANMADE("Cascade Quest", "c94efc10d18c040b6e22a1dc6d3adfe1", 3468, "8ada33dfa945f81531e5508240b573de", 1432195),
FANMADE("Circus Quest", "35871f6b4e1df56af4113c0203a0b223", 630, "7d6f97d7935d8733f488d4cb74315e5b", 279627),
@@ -4033,26 +4109,40 @@ static const struct ADGameDescription SciGameDescriptions[] = {
FANMADE("Curt's Quest 1.1", "54084c29346683296e45ef32d7ae74f3", 1128, "c851182cdf6fc6a81b840f4d4875f1a0", 302000),
FANMADE("Demo Quest", "c89a0c9e0a4e4af0ecedb300a3b31dbf", 384, "a32f3495ba24764cba091119cc3f1e13", 160098),
FANMADE("Dr. Jummybummy's Space Adventure 2", "6ae6cb7de423f51736d9487b4ca0c6da", 810, "26e5b563f578e104d79689f36568b7cf", 394670),
+ FANMADE("Edy Oliver into the Cave of Whistling Skulls Demo", "eba0a0e86768ee3f14e78fecbc5af011", 2388, "4f6eab79a0f7980960eed101ab8122ad", 2601551),
+ FANMADE("Footsteps Sound Demo", "d9dabee6e1550b1fdb793f442f227738", 372, "06561df40dea49c6e84184e0ba6f19cb", 114212),
FANMADE_L("Grostesteing: Plus Mechant que Jamais", "ec9a97ccb134f69249f6ea8b16c13d8e", 1500, "b869f5f11bfe2ab5f67f4f0c618f2ce1", 464657, Common::FR_FRA), // FIXME: Accent
FANMADE("Humanoid Demo", "97d8331293a6d57e8bad58c1efc89a63", 624, "fb354b9abe64011b12159e45d724633f", 452320),
+ FANMADE("Island of Secrets Demo 0.3", "61279176c3e4530fec9b578877aecda7", 504, "7f4ed7a81b86bea22c62bc98e6d9ec39", 197790),
FANMADE("Jim’s Quest 1: The Phantom Thesis", "0af50be1d3f0cb77a09137709a76ef4f", 960, "9c042c136548b20d9183495668e03526", 496446),
+ FANMADE("King's Quest II SCI Pre-Alpha Version", "cdea1c081022e7697a1afffb1d2f9f6a", 2646, "fb2ce39002c3e05f3d83533638dea105", 2310356),
FANMADE("Knight's Quest Demo 1.0", "5e816edf993956752ed06fccfeeae6d9", 1260, "959321f88a22905fa1f8c6d897874744", 703836),
FANMADE("LockerGnome Quest", "3eeff9130206cad0c4e1551e2b9dd2c5", 420, "ae05ca90806fd90cc43f147c82d3547c", 158906),
+ FANMADE("LockerGnome Quest Redux", "55b0081dbdd77a07807c76cec3606970", 492, "75c9c5e8a475a7b5f1a6cb18edad67f2", 168069),
FANMADE("New Year's Mystery", "e4dcab1b1d3cb4a2c070a07a9c9589e0", 708, "e00ca5e44fd4e98d8174b467b31b0f21", 295425),
FANMADE("New Year's Mystery (Updated)", "efd1beb5120293725065c95959144f81", 714, "b3bd3c2372ed6efa28adb12403c4c31a", 305027),
FANMADE("Ocean Battle", "c2304a0568e0eb84f8e9a0915f01170a", 408, "46c520c1ac9b63528854d0f58c7e1b74", 142234),
FANMADE("Osama", "db8f1710453cfbecf4214b2946970043", 390, "7afd75d4620dedf97a84ae8f0a7523cf", 123827),
FANMADE("Quest for the Cheat", "a359d4cf27f98264b42b55c017671214", 882, "8a943029f73c4bc85d454b7f473455ba", 455209),
+ FANMADE("Robust Parse Demo 1.2", "c956d40b6eb42292ec328c510acb11d8", 540, "26f092bab5ec4490737d8463fd3ebbd5", 229044),
FANMADE("SCI Capture the Flag", "4cd679a51d93b8b27c6b38d81be24b8b", 432, "98ae1f6ed7b4c21f88addbf643dd1d2f", 147878),
FANMADE("SCI Companion Template", "ad54d4f504086cd597aa2348d0aa3b09", 354, "6798b7b601ce8154c1d1bc0f0edcdd18", 113061),
+ FANMADE("SCI Logging Demo", "615c30c1445ea9349847e8868312a674", 558, "2df6858526177612ef9473e7af5b31c6", 171012),
+#if 0
+ // Disabled as this requires network access to the Google Translate API, which is not available as OSystem has no network API.
+ FANMADE("SCI Narration Demo", "731f4f2b726a13c153380af08da16591", 360, "38c80558fb942e8568f011d4a1a4af59", 109789),
+#endif
FANMADE("SCI Programming April 2010 Competition Template", "36e5c4011dd7c92e1ae4c6fede7d698d", 456, "20c87fbb7f73e2a3eb2c5dfab4d76b5a", 142221),
FANMADE("SCI Studio Template 3.0", "ca0dc8d586e0a8670b7621cde090b532", 354, "58a48ee692a86c0575e6bd0b00a92b9a", 113097),
FANMADE("SCI Quest", "9067e1f1e54436d2dbfce855524bc84a", 552, "ffa7d355cd9223f245289108a696bcd2", 149634),
FANMADE("SCI-Man", "3ab85bd39a86c11f85781764f9db09bb", 468, "bb8f9992f504a242bf0860e3588e150b", 131810),
- FANMADE("The Black Cauldron", "5e1ff2833c7f33ebcfa456ba836e2067", 2592, "2f8e6264d2db91bb54982ab8aa18b3b4", 1881839),
+ FANMADE("Text Views Demo", "ad0485a96470566517f184ff5dd049f8", 372, "727b946b37588ed334737732c55007c4", 115788),
+ FANMADE("The Black Cauldron Demo", "5e1ff2833c7f33ebcfa456ba836e2067", 2592, "2f8e6264d2db91bb54982ab8aa18b3b4", 1881839),
+ FANMADE("The Black Cauldron Final", "cbb4705f0cd73760996e5b27aae54f6a", 2484, "fc3bcaa7783b91bb78faefa345c6b3d9", 1677293),
FANMADE("The Farm Nightmare", "fb6cbfddaa7c055e2c3d8cf4c683a7db", 906, "50655e8b8925f717e698e08f006f40be", 338303),
FANMADE("The Gem Scenario", "ef5f61f4d2c6d31122d3e2baf89ad976", 642, "2f16be390dd90c3d7ca1c8a594ac0bfa", 244794),
FANMADE("The Legend of the Lost Jewel", "ba1bca315e3818c5626eda51bcfbcccf", 636, "9b0736d69924af0cff32a0f78db96855", 300398),
+ FANMADE("Winter Wonderland", "c1ffaf8327462effd4ad21eeed9eea59", 504, "5d48666dc62f90d852a1d0de6e69195f", 305076),
// FIXME: The vga demo does not have a resource.000/001 file.
//FANMADE_V("SCI VGA Demo", "00b1abd87bad356b90fcdfcb6132c26f", 8, "", 0, 0),
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 31e7ca4931..be062dba64 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -344,9 +344,9 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) {
if (kFuncNum == 8) { // kDrawPic (SCI0 - SCI11)
// If kDrawPic is called with 6 parameters from the overlay
// selector, the game is using old graphics functions.
- // Otherwise, if it's called with 8 parameters, it's using new
- // graphics functions.
- _gfxFunctionsType = (argc == 8) ? SCI_VERSION_0_LATE : SCI_VERSION_0_EARLY;
+ // Otherwise, if it's called with 8 parameters (e.g. SQ3) or 4 parameters
+ // (e.g. Hoyle 1/2), it's using new graphics functions.
+ _gfxFunctionsType = (argc == 6) ? SCI_VERSION_0_EARLY : SCI_VERSION_0_LATE;
return true;
}
}
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 8a9c1426b6..0c2fd4e3ea 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -331,7 +331,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(CoordPri), SIG_EVERYWHERE, "i(i)", NULL, NULL },
{ MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL },
- { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL },
+ { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, kDeleteKey_workarounds },
{ MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, kDeviceInfo_workarounds }, // subop
{ MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir!]*)", NULL, kDisplay_workarounds },
// ^ we allow invalid references here, because kDisplay gets called with those in e.g. pq3 during intro
@@ -468,7 +468,8 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL },
{ "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL },
- { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, kUnLoad_workarounds },
+ { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ir!]", NULL, kUnLoad_workarounds },
+ // ^ We allow invalid references here (e.g. bug #6600), since they will be invalidated anyway by the call itself
{ MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL },
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index 59f741a254..cb81da2279 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -126,7 +126,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// track left buttton clicks, if requested
if (curEvent.type == SCI_EVENT_MOUSE_PRESS && curEvent.data == 1 && g_debug_track_mouse_clicks) {
- g_sci->getSciDebugger()->DebugPrintf("Mouse clicked at %d, %d\n",
+ g_sci->getSciDebugger()->debugPrintf("Mouse clicked at %d, %d\n",
mousePos.x, mousePos.y);
}
@@ -163,20 +163,20 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// A SCI event occurred, and we have been asked to stop, so open the debug console
Console *con = g_sci->getSciDebugger();
- con->DebugPrintf("SCI event occurred: ");
+ con->debugPrintf("SCI event occurred: ");
switch (curEvent.type) {
case SCI_EVENT_QUIT:
- con->DebugPrintf("quit event\n");
+ con->debugPrintf("quit event\n");
break;
case SCI_EVENT_KEYBOARD:
- con->DebugPrintf("keyboard event\n");
+ con->debugPrintf("keyboard event\n");
break;
case SCI_EVENT_MOUSE_RELEASE:
case SCI_EVENT_MOUSE_PRESS:
- con->DebugPrintf("mouse click event\n");
+ con->debugPrintf("mouse click event\n");
break;
default:
- con->DebugPrintf("unknown or no event (event type %d)\n", curEvent.type);
+ con->debugPrintf("unknown or no event (event type %d)\n", curEvent.type);
}
con->attach();
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 65acdbcdf5..61fb717567 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -896,12 +896,25 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
gamestate_restore(s, in);
delete in;
- if (g_sci->getGameId() == GID_MOTHERGOOSE256) {
+ switch (g_sci->getGameId()) {
+ case GID_MOTHERGOOSE:
+ // WORKAROUND: Mother Goose SCI0
+ // Script 200 / rm200::newRoom will set global C5h directly right after creating a child to the
+ // current number of children plus 1.
+ // We can't trust that global, that's why we set the actual savedgame id right here directly after
+ // restoring a saved game.
+ // If we didn't, the game would always save to a new slot
+ s->variables[VAR_GLOBAL][0xC5].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
+ break;
+ case GID_MOTHERGOOSE256:
// WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for
// saving a previously restored game.
// We set the current savedgame-id directly and remove the script
// code concerning this via script patch.
s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
+ break;
+ default:
+ break;
}
} else {
s->r_acc = TRUE_REG;
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index e3a354e222..448e641b63 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -244,7 +244,8 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelTime, "GetTime(24h) returns %d", retval);
break;
case KGETTIME_DATE :
- retval = loc_time.tm_mday | ((loc_time.tm_mon + 1) << 5) | (((loc_time.tm_year + 1900) & 0x7f) << 9);
+ // Year since 1980 (0 = 1980, 1 = 1981, etc.)
+ retval = loc_time.tm_mday | ((loc_time.tm_mon + 1) << 5) | (((loc_time.tm_year - 80) & 0x7f) << 9);
debugC(kDebugLevelTime, "GetTime(date) returns %d", retval);
break;
default:
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 940bd38adb..67d814b86f 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -1921,7 +1921,7 @@ static int intersectDir(const Vertex *v1, const Vertex *v2) {
// Direction of edge in degrees from pos. x-axis, between -180 and 180
static int edgeDir(const Vertex *v) {
Common::Point p = v->_next->v - v->v;
- int deg = (int)Common::rad2deg(atan2((double)p.y, (double)p.x));
+ int deg = (int)Common::rad2deg((float)atan2((double)p.y, (double)p.x));
if (deg < -180) deg += 360;
if (deg > 180) deg -= 360;
return deg;
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index b4d245197b..8bbbd713a6 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -1218,7 +1218,7 @@ static const uint16 kq6CDPatchAudioTextSupportGirlInTheTower[] = {
// Adds another button state for the text/audio button. We currently use the "speech" view for "dual" mode.
// View 947, loop 9, cel 0+1 -> "text"
// View 947, loop 8, cel 0+1 -> "speech"
-// View 947, loop 12, cel 0+1 -> "dual" (TODO: inject our own 2 views for the new "dual" mode)
+// View 947, loop 12, cel 0+1 -> "dual" (this view is injected by us into the game)
// Applies to at least: PC-CD
// Patched method: iconTextSwitch::show, iconTextSwitch::doit
static const uint16 kq6CDSignatureAudioTextMenuSupport[] = {
@@ -1595,6 +1595,86 @@ static const uint16 laurabow2CDPatchFixProblematicIconBar[] = {
PATCH_END
};
+// Opening/Closing the east door in the pterodactyl room doesn't
+// check, if it's locked and will open/close the door internally
+// even when it is.
+//
+// It will get wired shut later in the game by Laura Bow and will be
+// "locked" because of this. We patch in a check for the locked
+// state. We also add code, that will set the "locked" state
+// in case our eastDoor-wired-global is set. This makes the locked
+// state effectively persistent.
+//
+// Applies to at least: English PC-CD, English PC-Floppy
+// Responsible method (CD): eastDoor::doVerb
+// Responsible method (Floppy): eastDoor::<noname300>
+// Fixes bug: #6458 (partly, see additional patch below)
+static const uint16 laurabow2CDSignatureFixWiredEastDoor[] = {
+ 0x30, SIG_UINT16(0x0022), // bnt [skip hand action]
+ 0x67, SIG_ADDTOOFFSET(+1), // pTos CD: doorState, Floppy: state
+ 0x35, 0x00, // ldi 00
+ 0x1a, // eq?
+ 0x31, 0x08, // bnt [close door code]
+ 0x78, // push1
+ SIG_MAGICDWORD,
+ 0x39, 0x63, // pushi 63h
+ 0x45, 0x04, 0x02, // callb export000_4, 02 (sets door-bitflag)
+ 0x33, 0x06, // jmp [super-code]
+ 0x78, // push1
+ 0x39, 0x63, // pushi 63h
+ 0x45, 0x03, 0x02, // callb export000_3, 02 (resets door-bitflag)
+ 0x38, SIG_ADDTOOFFSET(+2), // pushi CD: 011dh, Floppy: 012ch
+ 0x78, // push1
+ 0x8f, 0x01, // lsp param[01]
+ 0x59, 0x02, // rest 02
+ 0x57, SIG_ADDTOOFFSET(+1), 0x06, // super CD: LbDoor, Floppy: Door, 06
+ 0x33, 0x0b, // jmp [ret]
+ SIG_END
+};
+
+static const uint16 laurabow2CDPatchFixWiredEastDoor[] = {
+ 0x31, 0x23, // bnt [skip hand action] (saves 1 byte)
+ 0x81, 97, // lag 97d (get our eastDoor-wired-global)
+ 0x31, 0x04, // bnt [skip setting locked property]
+ 0x35, 0x01, // ldi 01
+ 0x65, 0x6a, // aTop locked (set eastDoor::locked to 1)
+ 0x63, 0x6a, // pToa locked (get eastDoor::locked)
+ 0x2f, 0x17, // bt [skip hand action]
+ 0x63, PATCH_GETORIGINALBYTE(+4), // pToa CD: doorState, Floppy: state
+ 0x78, // push1
+ 0x39, 0x63, // pushi 63h
+ 0x2f, 0x05, // bt [close door code]
+ 0x45, 0x04, 0x02, // callb export000_4, 02 (sets door-bitflag)
+ 0x33, 0x0b, // jmp [super-code]
+ 0x45, 0x03, 0x02, // callb export000_3, 02 (resets door-bitflag)
+ 0x33, 0x06, // jmp [super-code]
+ PATCH_END
+};
+
+// We patch in code, so that our eastDoor-wired-global will get set to 1.
+// This way the wired-state won't get lost when exiting room 430.
+//
+// Applies to at least: English PC-CD, English PC-Floppy
+// Responsible method (CD): sWireItShut::changeState
+// Responsible method (Floppy): sWireItShut::<noname144>
+// Fixes bug: #6458 (partly, see additional patch above)
+static const uint16 laurabow2SignatureRememberWiredEastDoor[] = {
+ SIG_MAGICDWORD,
+ 0x33, 0x27, // jmp [ret]
+ 0x3c, // dup
+ 0x35, 0x06, // ldi 06
+ 0x1a, // eq?
+ 0x31, 0x21, // bnt [skip step]
+ SIG_END
+};
+
+static const uint16 laurabow2PatchRememberWiredEastDoor[] = {
+ PATCH_ADDTOOFFSET(+2), // skip jmp [ret]
+ 0x34, PATCH_UINT16(0x0001), // ldi 0001
+ 0xa1, PATCH_UINT16(97), // sag 97d (set our eastDoor-wired-global)
+ PATCH_END
+};
+
// Laura Bow 2 CD resets the audio mode to speech on init/restart
// We already sync the settings from ScummVM (see SciEngine::syncIngameAudioOptions())
// and this script code would make it impossible to see the intro using "dual" mode w/o using debugger command
@@ -1617,7 +1697,7 @@ static const uint16 laurabow2CDPatchAudioTextSupportModeReset[] = {
// That way it's possible to use a new "dual" mode view in the game menu
// View 995, loop 13, cel 0 -> "text"
// View 995, loop 13, cel 1 -> "speech"
-// View 995, loop 13, cel 2 -> "dual" (TODO: inject our own view for the new "dual" mode)
+// View 995, loop 13, cel 2 -> "dual" (this view is injected by us into the game)
// Patched method: gcWin::open
static const uint16 laurabow2CDSignatureAudioTextMenuSupport1[] = {
SIG_MAGICDWORD,
@@ -1636,7 +1716,6 @@ static const uint16 laurabow2CDPatchAudioTextMenuSupport1[] = {
};
// Adds another button state for the text/audio button. We currently use the "speech" view for "dual" mode.
-// TODO: inject our own 2 views for the new "dual" mode
// Patched method: iconMode::doit
static const uint16 laurabow2CDSignatureAudioTextMenuSupport2[] = {
SIG_MAGICDWORD,
@@ -1684,6 +1763,8 @@ static const uint16 laurabow2CDPatchAudioTextMenuSupport2[] = {
static const SciScriptPatcherEntry laurabow2Signatures[] = {
{ true, 560, "CD: painting closing immediately", 1, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing },
{ true, 0, "CD: fix problematic icon bar", 1, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar },
+ { true, 430, "CD/Floppy: make wired east door persistent", 1, laurabow2SignatureRememberWiredEastDoor, laurabow2PatchRememberWiredEastDoor },
+ { true, 430, "CD/Floppy: fix wired east door", 1, laurabow2CDSignatureFixWiredEastDoor, laurabow2CDPatchFixWiredEastDoor },
// King's Quest 6 and Laura Bow 2 share basic patches for audio + text support
{ false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 },
{ false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 },
@@ -2373,11 +2454,91 @@ static const uint16 sq1vgaPatchEgoShowsCard[] = {
PATCH_END
};
+// The spider droid on planet Korona has a fixed movement speed,
+// which is way faster than the default movement speed of ego.
+// This means that the player would have to turn up movement speed,
+// otherwise it will be impossible to escape it.
+// We fix this issue by making the droid move a bit slower than ego
+// does (relative to movement speed setting).
+//
+// Applies to at least: English PC floppy
+// Responsible method: spider::doit
+static const uint16 sq1vgaSignatureSpiderDroidTiming[] = {
+ SIG_MAGICDWORD,
+ 0x63, 0x4e, // pToa script
+ 0x30, SIG_UINT16(0x0005), // bnt [further method code]
+ 0x35, 0x00, // ldi 00
+ 0x32, SIG_UINT16(0x0062), // jmp [super-call]
+ 0x38, SIG_UINT16(0x0088), // pushi 0088h (script)
+ 0x76, // push0
+ 0x81, 0x02, // lag global[2] (current room)
+ 0x4a, 0x04, // send 04 (get [current room].script)
+ 0x30, SIG_UINT16(0x0005), // bnt [further method code]
+ 0x35, 0x00, // ldi 00
+ 0x32, SIG_UINT16(0x0052), // jmp [super-call]
+ 0x89, 0xa6, // lsg global[a6]
+ 0x35, 0x01, // ldi 01
+ 0x1a, // eq?
+ 0x30, SIG_UINT16(0x0012), // bnt [2nd code], in case global A6 <> 1
+ 0x81, 0xb5, // lag global[b5]
+ 0x30, SIG_UINT16(0x000d), // bnt [2nd code], in case global B5 == 0
+ 0x38, SIG_UINT16(0x008c), // pushi 008c
+ 0x78, // push1
+ 0x72, SIG_UINT16(0x1cb6), // lofsa 1CB6 (moveToPath)
+ 0x36, // push
+ 0x54, 0x06, // self 06
+ 0x32, SIG_UINT16(0x0038), // jmp [super-call]
+ 0x81, 0xb5, // lag global[B5]
+ 0x18, // not
+ 0x30, SIG_UINT16(0x0032), // bnt [super-call], in case global B5 <> 0
+ SIG_END
+}; // 58 bytes)
+
+static const uint16 sq1vgaPatchSpiderDroidTiming[] = {
+ 0x63, 0x4e, // pToa script
+ 0x2f, 0x68, // bt [super-call]
+ 0x38, PATCH_UINT16(0x0088), // pushi 0088 (script)
+ 0x76, // push0
+ 0x81, 0x02, // lag global[2] (current room)
+ 0x4a, 0x04, // send 04
+ 0x2f, 0x5e, // bt [super-call]
+ // --> 12 bytes saved
+ // new code
+ 0x38, PATCH_UINT16(0x0176), // pushi 0176 (egoMoveSpeed)
+ 0x76, // push0
+ 0x81, 0x01, // lag global[1]
+ 0x4a, 0x04, // send 04 - sq1::egoMoveSpeed
+ 0x36, // push
+ 0x36, // push
+ 0x35, 0x03, // ldi 03
+ 0x0c, // shr
+ 0x02, // add --> egoMoveSpeed + (egoMoveSpeed >> 3)
+ 0x39, 0x01, // push 01 (waste 1 byte)
+ 0x02, // add --> egoMoveSpeed++
+ 0x65, 0x4c, // aTop cycleSpeed
+ 0x65, 0x5e, // aTop moveSpeed
+ // new code end
+ 0x89, 0xb5, // lsg global[B5]
+ 0x31, 0x13, // bnt [2nd code chunk]
+ 0x89, 0xa6, // lsg global[A6]
+ 0x35, 0x01, // ldi 01
+ 0x1a, // eq?
+ 0x31, 0x3e, // bnt [super-call]
+ 0x38, PATCH_UINT16(0x008c), // pushi 008c
+ 0x78, // push1
+ 0x72, PATCH_UINT16(0x1cb6), // lofsa moveToPath
+ 0x36, // push
+ 0x54, 0x06, // self 06 - spider::setScript(movePath)
+ 0x33, 0x32, // jmp [super-call]
+ // --> 9 bytes saved
+ PATCH_END
+};
// script, description, signature patch
static const SciScriptPatcherEntry sq1vgaSignatures[] = {
{ true, 45, "Ulence Flats: timepod graphic glitch", 1, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch },
{ true, 58, "Sarien armory droid zapping ego first time", 1, sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard },
+ { true, 704, "spider droid timing issue", 1, sq1vgaSignatureSpiderDroidTiming, sq1vgaPatchSpiderDroidTiming },
SCI_SIGNATUREENTRY_TERMINATOR
};
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 44910058ef..f0157a6569 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -604,7 +604,7 @@ bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t sen
Common::List<Breakpoint>::const_iterator bpIter;
for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) {
if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) {
- _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj));
+ _console->debugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj));
_debugState.debugging = true;
_debugState.breakpointWasHit = true;
return true;
@@ -620,7 +620,7 @@ bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
Common::List<Breakpoint>::const_iterator bp;
for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
if (bp->type == BREAK_EXPORT && bp->address == bpaddress) {
- _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct);
+ _console->debugPrintf("Break on script %d, export %d\n", script, pubfunct);
_debugState.debugging = true;
_debugState.breakpointWasHit = true;
return true;
@@ -666,12 +666,12 @@ void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr arg
reg_t selectorValue = *varp.getPointer(segMan);
if (!argc && (activeBreakpointTypes & BREAK_SELECTORREAD)) {
if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector))
- con->DebugPrintf("Read from selector (%s:%s): %04x:%04x\n",
+ con->debugPrintf("Read from selector (%s:%s): %04x:%04x\n",
objectName, selectorName,
PRINT_REG(selectorValue));
} else if (argc && (activeBreakpointTypes & BREAK_SELECTORWRITE)) {
if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector))
- con->DebugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n",
+ con->debugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n",
objectName, selectorName,
PRINT_REG(selectorValue), PRINT_REG(argp[1]));
}
@@ -690,13 +690,13 @@ void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr arg
if (true) {
if (true) {
#endif
- con->DebugPrintf("%s::%s(", objectName, selectorName);
+ con->debugPrintf("%s::%s(", objectName, selectorName);
for (int i = 0; i < argc; i++) {
- con->DebugPrintf("%04x:%04x", PRINT_REG(argp[i+1]));
+ con->debugPrintf("%04x:%04x", PRINT_REG(argp[i+1]));
if (i + 1 < argc)
- con->DebugPrintf(", ");
+ con->debugPrintf(", ");
}
- con->DebugPrintf(") at %04x:%04x\n", PRINT_REG(funcp));
+ con->debugPrintf(") at %04x:%04x\n", PRINT_REG(funcp));
}
}
break;
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 3738fd3dcb..58c2b8d3e3 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -371,7 +371,7 @@ void SegManager::freeHunkEntry(reg_t addr) {
HunkTable *ht = (HunkTable *)getSegment(addr.getSegment(), SEG_TYPE_HUNK);
if (!ht) {
- warning("Attempt to free Hunk from address %04x:%04x: Invalid segment type", PRINT_REG(addr));
+ warning("Attempt to free Hunk from address %04x:%04x: Invalid segment type %d", PRINT_REG(addr), getSegmentType(addr.getSegment()));
return;
}
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 6ef98e3b2a..ea4dc2fe71 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -44,7 +44,8 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = {
{ GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue.
{ GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria
{ GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object
- { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer bug #5152
+ { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152
+ { GID_QFG3, 780, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692
{ GID_QFG4, 710,64941, 0, "RandCycle", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -90,9 +91,11 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_HOYLE4, 700, -1, 1, "BridgeDefense", "think", -1, -1, { WORKAROUND_FAKE, 0 } }, // sometimes while playing bridge, temp var 3, 17 and others, objects LeadReturn_Trump, ThirdSeat_Trump and others
{ GID_HOYLE4, 700, 730, 1, "BridgeDefense", "beatTheirBest", -1, 3, { WORKAROUND_FAKE, 0 } }, // rarely while playing bridge
{ GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #5663 and #5794
+ { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when saving the game (may also occur in other situations) - bug #6601
{ GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts
{ GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665
{ GID_HOYLE4, 500, 17, 1, "Character", "say", -1, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662
+ { GID_HOYLE4, -1, 937, 0, "IconBar", "dispatchEvent", -1, 408, { WORKAROUND_FAKE, 0 } }, // pressing ENTER on scoreboard while mouse is not on OK button, may not happen all the time - bug #6603
{ GID_ISLANDBRAIN, 100, 937, 0, "IconBar", "dispatchEvent", -1, 58, { WORKAROUND_FAKE, 0 } }, // when using ENTER at the startup menu - bug #5241
{ GID_ISLANDBRAIN, 140, 140, 0, "piece", "init", -1, 3, { WORKAROUND_FAKE, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0
{ GID_ISLANDBRAIN, 200, 268, 0, "anElement", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // elements puzzle, gets used before super TextIcon
@@ -222,6 +225,14 @@ const SciWorkaroundEntry kCelWide_workarounds[] = {
};
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kDeleteKey_workarounds[] = {
+ { GID_HOYLE4, 300, 999, 0, "handleEventList", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // restarting hearts, while tray is shown - bug #6604
+ { GID_HOYLE4, 500, 999, 0, "handleEventList", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // restarting cribbage, while tray is shown - bug #6604
+ { GID_HOYLE4, 975, 999, 0, "handleEventList", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // going back to gamelist from hearts/cribbage, while tray is shown - bug #6604
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kDeviceInfo_workarounds[] = {
{ GID_FANMADE, -1, 994, 1, "Game", "save", 0xd1c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest)
{ GID_FANMADE, -1, 994, 1, "Game", "save", 0xe55, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest)
diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h
index 2e73dddbe3..9cad618481 100644
--- a/engines/sci/engine/workarounds.h
+++ b/engines/sci/engine/workarounds.h
@@ -76,6 +76,7 @@ extern const SciWorkaroundEntry kDirLoop_workarounds[];
extern const SciWorkaroundEntry kDisposeScript_workarounds[];
extern const SciWorkaroundEntry kDoSoundFade_workarounds[];
extern const SciWorkaroundEntry kFindKey_workarounds[];
+extern const SciWorkaroundEntry kDeleteKey_workarounds[];
extern const SciWorkaroundEntry kGetAngle_workarounds[];
extern const SciWorkaroundEntry kGraphDrawLine_workarounds[];
extern const SciWorkaroundEntry kGraphSaveBox_workarounds[];
diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp
index 73cd7240d3..7957ed6a55 100644
--- a/engines/sci/graphics/animate.cpp
+++ b/engines/sci/graphics/animate.cpp
@@ -726,7 +726,7 @@ void GfxAnimate::printAnimateList(Console *con) {
Script *scr = _s->_segMan->getScriptIfLoaded(it->object.getSegment());
int16 scriptNo = scr ? scr->getScriptNumber() : -1;
- con->DebugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, "
+ con->debugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, "
"at %d, %d, scale %d, %d / %d (z: %d, prio: %d, shown: %d, signal: %d)\n",
PRINT_REG(it->object), _s->_segMan->getObjectName(it->object),
scriptNo, it->viewId, it->loopNo, it->celNo, it->paletteNo,
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index ffed7b596e..91b5b25e99 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -782,9 +782,13 @@ void GfxFrameout::kernelFrameout() {
// TODO: For some reason, the top left nsRect coordinates get
// swapped in the GK1 inventory screen, investigate why.
+ // This is also needed for GK1 rooms 710 and 720 (catacombs, inner and
+ // outer circle), for handling the tiles and talking to Wolfgang.
// HACK: Fix the coordinates by explicitly setting them here.
Common::Rect objNSRect = g_sci->_gfxCompare->getNSRect(itemEntry->object);
- if (objNSRect.top == nsRect.left && objNSRect.left == nsRect.top && nsRect.top != 0 && nsRect.left != 0) {
+ uint16 roomNumber = g_sci->getEngineState()->currentRoomNumber();
+ if (objNSRect.top == nsRect.left && objNSRect.left == nsRect.top && nsRect.top != 0 && nsRect.left != 0 ||
+ (g_sci->getGameId() == GID_GK1 && (roomNumber == 710 || roomNumber == 720))) {
g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
}
}
@@ -852,21 +856,21 @@ void GfxFrameout::printPlaneList(Console *con) {
Common::Rect r = p.upscaledPlaneRect;
Common::Rect cr = p.upscaledPlaneClipRect;
- con->DebugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n",
+ con->debugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n",
PRINT_REG(p.object), curPlaneName.c_str(),
(int16)p.priority, (int16)p.lastPriority,
p.planeOffsetX, p.planeOffsetY, p.pictureId,
p.planePictureMirrored, p.planeBack);
- con->DebugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n",
+ con->debugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n",
r.left, r.top, r.right, r.bottom,
cr.left, cr.top, cr.right, cr.bottom);
if (p.pictureId != 0xffff && p.pictureId != 0xfffe) {
- con->DebugPrintf("Pictures:\n");
+ con->debugPrintf("Pictures:\n");
for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
if (pictureIt->object == p.object) {
- con->DebugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY);
+ con->debugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY);
}
}
}
@@ -883,7 +887,7 @@ void GfxFrameout::printPlaneItemList(Console *con, reg_t planeObject) {
Common::Rect icr = e->celRect;
GuiResourceId picId = e->picture ? e->picture->getResourceId() : 0;
- con->DebugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, "
+ con->debugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, "
"signal %d, scale signal %d, scaleX %d, scaleY %d, rect (%d, %d, %d, %d), "
"pic %d, picX %d, picY %d, visible %d\n",
e->givenOrderNr, PRINT_REG(e->object), curItemName.c_str(),
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp
index f94c65c76b..7d106b5b02 100644
--- a/engines/sci/graphics/paint32.cpp
+++ b/engines/sci/graphics/paint32.cpp
@@ -43,8 +43,12 @@ GfxPaint32::~GfxPaint32() {
void GfxPaint32::fillRect(Common::Rect rect, byte color) {
int16 y, x;
- for (y = rect.top; y < rect.bottom; y++) {
- for (x = rect.left; x < rect.right; x++) {
+ Common::Rect clipRect = rect;
+
+ clipRect.clip(_screen->getWidth(), _screen->getHeight());
+
+ for (y = clipRect.top; y < clipRect.bottom; y++) {
+ for (x = clipRect.left; x < clipRect.right; x++) {
_screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL, color, 0, 0);
}
}
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index bd0b5f4081..56c63a7b12 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -748,7 +748,7 @@ void GfxPorts::printWindowList(Console *con) {
for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) {
if ((*it)->isWindow()) {
Window *wnd = ((Window *)*it);
- con->DebugPrintf("%d: '%s' at %d, %d, (%d, %d, %d, %d), drawn: %d, style: %d\n",
+ con->debugPrintf("%d: '%s' at %d, %d, (%d, %d, %d, %d), drawn: %d, style: %d\n",
wnd->id, wnd->title.c_str(), wnd->left, wnd->top,
wnd->rect.left, wnd->rect.top, wnd->rect.right, wnd->rect.bottom,
wnd->bDrawn, wnd->wndStyle);
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 15717239d8..c5c94d7991 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -50,6 +50,11 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_upscaledHires = GFX_SCREEN_UPSCALED_640x480;
#endif
}
+
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
+ if (getSciVersion() <= SCI_VERSION_01)
+ _upscaledHires = GFX_SCREEN_UPSCALED_480x300;
+ }
#ifdef ENABLE_SCI32
// GK1 Mac uses a 640x480 resolution too
@@ -84,28 +89,48 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_pixels = _pitch * _height;
switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_480x300:
+ // Space Quest 3, Hoyle 1+2 on MAC use this one
+ // TODO: Sierra's upscaling worked differently. We need to figure out the exact algo
+ _displayWidth = 480;
+ _displayHeight = 300;
+ for (int i = 0; i <= _height; i++)
+ _upscaledHeightMapping[i] = (i * 3) >> 1;
+ for (int i = 0; i <= _width; i++)
+ _upscaledWidthMapping[i] = (i * 3) >> 1;
+ break;
case GFX_SCREEN_UPSCALED_640x400:
+ // Police Quest 2 and Quest For Glory on PC9801 (Japanese)
_displayWidth = 640;
_displayHeight = 400;
for (int i = 0; i <= _height; i++)
- _upscaledMapping[i] = i * 2;
+ _upscaledHeightMapping[i] = i * 2;
+ for (int i = 0; i <= _width; i++)
+ _upscaledWidthMapping[i] = i * 2;
break;
case GFX_SCREEN_UPSCALED_640x440:
+ // used by King's Quest 6 on Windows
_displayWidth = 640;
_displayHeight = 440;
for (int i = 0; i <= _height; i++)
- _upscaledMapping[i] = (i * 11) / 5;
+ _upscaledHeightMapping[i] = (i * 11) / 5;
+ for (int i = 0; i <= _width; i++)
+ _upscaledWidthMapping[i] = i * 2;
break;
case GFX_SCREEN_UPSCALED_640x480:
+ // Gabriel Knight 1 (VESA, Mac)
_displayWidth = 640;
_displayHeight = 480;
for (int i = 0; i <= _height; i++)
- _upscaledMapping[i] = (i * 12) / 5;
+ _upscaledHeightMapping[i] = (i * 12) / 5;
+ for (int i = 0; i <= _width; i++)
+ _upscaledWidthMapping[i] = i * 2;
break;
default:
_displayWidth = _pitch;
_displayHeight = _height;
- memset(&_upscaledMapping, 0, sizeof(_upscaledMapping) );
+ memset(&_upscaledHeightMapping, 0, sizeof(_upscaledHeightMapping) );
+ memset(&_upscaledWidthMapping, 0, sizeof(_upscaledWidthMapping) );
break;
}
@@ -185,8 +210,9 @@ void GfxScreen::copyRectToScreen(const Common::Rect &rect) {
if (!_upscaledHires) {
g_system->copyRectToScreen(_activeScreen + rect.top * _displayWidth + rect.left, _displayWidth, rect.left, rect.top, rect.width(), rect.height());
} else {
- int rectHeight = _upscaledMapping[rect.bottom] - _upscaledMapping[rect.top];
- g_system->copyRectToScreen(_activeScreen + _upscaledMapping[rect.top] * _displayWidth + rect.left * 2, _displayWidth, rect.left * 2, _upscaledMapping[rect.top], rect.width() * 2, rectHeight);
+ int rectHeight = _upscaledHeightMapping[rect.bottom] - _upscaledHeightMapping[rect.top];
+ int rectWidth = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left];
+ g_system->copyRectToScreen(_activeScreen + _upscaledHeightMapping[rect.top] * _displayWidth + _upscaledWidthMapping[rect.left], _displayWidth, _upscaledWidthMapping[rect.left], _upscaledHeightMapping[rect.top], rectWidth, rectHeight);
}
}
@@ -204,8 +230,10 @@ void GfxScreen::copyRectToScreen(const Common::Rect &rect, int16 x, int16 y) {
if (!_upscaledHires) {
g_system->copyRectToScreen(_activeScreen + rect.top * _displayWidth + rect.left, _displayWidth, x, y, rect.width(), rect.height());
} else {
- int rectHeight = _upscaledMapping[rect.bottom] - _upscaledMapping[rect.top];
- g_system->copyRectToScreen(_activeScreen + _upscaledMapping[rect.top] * _displayWidth + rect.left * 2, _displayWidth, x * 2, _upscaledMapping[y], rect.width() * 2, rectHeight);
+ int rectHeight = _upscaledHeightMapping[rect.bottom] - _upscaledHeightMapping[rect.top];
+ int rectWidth = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left];
+
+ g_system->copyRectToScreen(_activeScreen + _upscaledHeightMapping[rect.top] * _displayWidth + _upscaledWidthMapping[rect.left], _displayWidth, _upscaledWidthMapping[x], _upscaledHeightMapping[y], rectWidth, rectHeight);
}
}
@@ -228,14 +256,7 @@ void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority,
if (!_upscaledHires) {
_displayScreen[offset] = color;
} else {
- int displayOffset = _upscaledMapping[y] * _displayWidth + x * 2;
- int heightOffsetBreak = (_upscaledMapping[y + 1] - _upscaledMapping[y]) * _displayWidth;
- int heightOffset = 0;
- do {
- _displayScreen[displayOffset + heightOffset] = color;
- _displayScreen[displayOffset + heightOffset + 1] = color;
- heightOffset += _displayWidth;
- } while (heightOffset != heightOffsetBreak);
+ putScaledPixelOnDisplay(x, y, color);
}
}
if (drawMask & GFX_SCREEN_MASK_PRIORITY)
@@ -250,22 +271,21 @@ void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority,
* Sierra SCI didn't do this
*/
void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) {
+ int actualY = startingY + y;
if (_fontIsUpscaled) {
// Do not scale ourselves, but put it on the display directly
- putPixelOnDisplay(x, y + startingY, color);
+ putPixelOnDisplay(x, actualY, color);
} else {
- int offset = (startingY + y) * _pitch + x;
+ int offset = actualY * _pitch + x;
_visualScreen[offset] = color;
- if (!_upscaledHires) {
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_DISABLED:
_displayScreen[offset] = color;
- } else {
- int displayOffset = (_upscaledMapping[startingY] + y * 2) * _displayWidth + x * 2;
- _displayScreen[displayOffset] = color;
- _displayScreen[displayOffset + 1] = color;
- displayOffset += _displayWidth;
- _displayScreen[displayOffset] = color;
- _displayScreen[displayOffset + 1] = color;
+ break;
+ default:
+ putScaledPixelOnDisplay(x, actualY, color);
+ break;
}
}
}
@@ -280,6 +300,21 @@ void GfxScreen::putPixelOnDisplay(int x, int y, byte color) {
_displayScreen[offset] = color;
}
+void GfxScreen::putScaledPixelOnDisplay(int x, int y, byte color) {
+ int displayOffset = _upscaledHeightMapping[y] * _displayWidth + _upscaledWidthMapping[x];
+ int heightOffsetBreak = (_upscaledHeightMapping[y + 1] - _upscaledHeightMapping[y]) * _displayWidth;
+ int heightOffset = 0;
+ int widthOffsetBreak = _upscaledWidthMapping[x + 1] - _upscaledWidthMapping[x];
+ do {
+ int widthOffset = 0;
+ do {
+ _displayScreen[displayOffset + heightOffset + widthOffset] = color;
+ widthOffset++;
+ } while (widthOffset != widthOffsetBreak);
+ heightOffset += _displayWidth;
+ } while (heightOffset != heightOffsetBreak);
+}
+
/**
* Sierra's Bresenham line drawing.
* WARNING: Do not replace this with Graphics::drawLine(), as this causes issues
@@ -409,8 +444,9 @@ int GfxScreen::bitsGetDataSize(Common::Rect rect, byte mask) {
if (!_upscaledHires) {
byteCount += pixels; // _displayScreen
} else {
- int rectHeight = _upscaledMapping[rect.bottom] - _upscaledMapping[rect.top];
- byteCount += rectHeight * rect.width() * 2; // _displayScreen (upscaled hires)
+ int rectHeight = _upscaledHeightMapping[rect.bottom] - _upscaledHeightMapping[rect.top];
+ int rectWidth = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left];
+ byteCount += rectHeight * rect.width() * rectWidth; // _displayScreen (upscaled hires)
}
}
if (mask & GFX_SCREEN_MASK_PRIORITY) {
@@ -463,16 +499,17 @@ void GfxScreen::bitsSaveScreen(Common::Rect rect, byte *screen, uint16 screenWid
void GfxScreen::bitsSaveDisplayScreen(Common::Rect rect, byte *&memoryPtr) {
byte *screen = _displayScreen;
- int width = rect.width();
+ int width;
int y;
if (!_upscaledHires) {
+ width = rect.width();
screen += (rect.top * _displayWidth) + rect.left;
} else {
- screen += (_upscaledMapping[rect.top] * _displayWidth) + rect.left * 2;
- width *= 2;
- rect.top = _upscaledMapping[rect.top];
- rect.bottom = _upscaledMapping[rect.bottom];
+ screen += (_upscaledHeightMapping[rect.top] * _displayWidth) + _upscaledWidthMapping[rect.left];
+ width = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left];
+ rect.top = _upscaledHeightMapping[rect.top];
+ rect.bottom = _upscaledHeightMapping[rect.bottom];
}
for (y = rect.top; y < rect.bottom; y++) {
@@ -528,16 +565,17 @@ void GfxScreen::bitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *scr
void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) {
byte *screen = _displayScreen;
- int width = rect.width();
+ int width;
int y;
if (!_upscaledHires) {
screen += (rect.top * _displayWidth) + rect.left;
+ width = rect.width();
} else {
- screen += (_upscaledMapping[rect.top] * _displayWidth) + rect.left * 2;
- width *= 2;
- rect.top = _upscaledMapping[rect.top];
- rect.bottom = _upscaledMapping[rect.bottom];
+ screen += (_upscaledHeightMapping[rect.top] * _displayWidth) + _upscaledWidthMapping[rect.left];
+ width = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left];
+ rect.top = _upscaledHeightMapping[rect.top];
+ rect.bottom = _upscaledHeightMapping[rect.bottom];
}
for (y = rect.top; y < rect.bottom; y++) {
@@ -550,7 +588,7 @@ void GfxScreen::setVerticalShakePos(uint16 shakePos) {
if (!_upscaledHires)
g_system->setShakePos(shakePos);
else
- g_system->setShakePos(shakePos * 2);
+ g_system->setShakePos(_upscaledHeightMapping[shakePos]);
}
void GfxScreen::kernelShakeScreen(uint16 shakeCount, uint16 directions) {
@@ -583,20 +621,18 @@ void GfxScreen::dither(bool addToFlag) {
if (color & 0xF0) {
color ^= color << 4;
color = ((x^y) & 1) ? color >> 4 : color & 0x0F;
- *displayPtr = color;
- if (_upscaledHires) {
- *(displayPtr + 1) = color;
- *(displayPtr + _displayWidth) = color;
- *(displayPtr + _displayWidth + 1) = color;
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_DISABLED:
+ *displayPtr = color;
+ break;
+ default:
+ putScaledPixelOnDisplay(x, y, color);
+ break;
}
*visualPtr = color;
}
visualPtr++; displayPtr++;
- if (_upscaledHires)
- displayPtr++;
}
- if (_upscaledHires)
- displayPtr += _displayWidth;
}
} else {
if (!addToFlag)
@@ -616,21 +652,19 @@ void GfxScreen::dither(bool addToFlag) {
} else {
ditheredColor = color << 4;
}
- *displayPtr = ditheredColor;
- if (_upscaledHires) {
- *(displayPtr + 1) = ditheredColor;
- *(displayPtr + _displayWidth) = ditheredColor;
- *(displayPtr + _displayWidth + 1) = ditheredColor;
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_DISABLED:
+ *displayPtr = ditheredColor;
+ break;
+ default:
+ putScaledPixelOnDisplay(x, y, ditheredColor);
+ break;
}
color = ((x^y) & 1) ? color >> 4 : color & 0x0F;
*visualPtr = color;
}
visualPtr++; displayPtr++;
- if (_upscaledHires)
- displayPtr++;
}
- if (_upscaledHires)
- displayPtr += _displayWidth;
}
}
}
@@ -722,8 +756,8 @@ static const UpScaledAdjust s_upscaledAdjustTable[] = {
};
void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewNativeRes) {
- x *= 2;
- y = _upscaledMapping[y];
+ x = _upscaledWidthMapping[x];
+ y = _upscaledHeightMapping[y];
for (int i = 0; i < ARRAYSIZE(s_upscaledAdjustTable); i++) {
if (s_upscaledAdjustTable[i].gameHiresMode == _upscaledHires &&
@@ -744,6 +778,10 @@ void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativ
}
switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_480x300:
+ x = (x << 1) / 3;
+ y = (y << 1) / 3;
+ break;
case GFX_SCREEN_UPSCALED_640x400:
x /= 2;
y /= 2;
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index c334638703..e266a4ed16 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -32,12 +32,14 @@
namespace Sci {
#define SCI_SCREEN_UPSCALEDMAXHEIGHT 200
+#define SCI_SCREEN_UPSCALEDMAXWIDTH 320
enum GfxScreenUpscaledMode {
GFX_SCREEN_UPSCALED_DISABLED = 0,
- GFX_SCREEN_UPSCALED_640x400 = 1,
- GFX_SCREEN_UPSCALED_640x440 = 2,
- GFX_SCREEN_UPSCALED_640x480 = 3
+ GFX_SCREEN_UPSCALED_480x300 = 1,
+ GFX_SCREEN_UPSCALED_640x400 = 2,
+ GFX_SCREEN_UPSCALED_640x440 = 3,
+ GFX_SCREEN_UPSCALED_640x480 = 4
};
enum GfxScreenMasks {
@@ -83,6 +85,7 @@ public:
void putPixel(int x, int y, byte drawMask, byte color, byte prio, byte control);
void putFontPixel(int startingY, int x, int y, byte color);
void putPixelOnDisplay(int x, int y, byte color);
+ void putScaledPixelOnDisplay(int x, int y, byte color);
void drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte prio, byte control);
void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) {
drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control);
@@ -184,10 +187,11 @@ private:
GfxScreenUpscaledMode _upscaledHires;
/**
- * This here holds a translation for vertical coordinates between native
+ * This here holds a translation for vertical+horizontal coordinates between native
* (visual) and actual (display) screen.
*/
- int _upscaledMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1];
+ int _upscaledHeightMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1];
+ int _upscaledWidthMapping[SCI_SCREEN_UPSCALEDMAXWIDTH + 1];
/**
* This defines whether or not the font we're drawing is already scaled
diff --git a/engines/sci/parser/grammar.cpp b/engines/sci/parser/grammar.cpp
index ee0125b7c9..05764ba0a8 100644
--- a/engines/sci/parser/grammar.cpp
+++ b/engines/sci/parser/grammar.cpp
@@ -397,7 +397,7 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) {
ntrules_nr = _vocab_rule_list_length(ntlist);
if (verbose)
- con->DebugPrintf("Starting with %d rules\n", ntrules_nr);
+ con->debugPrintf("Starting with %d rules\n", ntrules_nr);
new_tlist = tlist;
tlist = NULL;
@@ -425,17 +425,17 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) {
termrules = _vocab_rule_list_length(new_new_tlist);
if (verbose)
- con->DebugPrintf("After iteration #%d: %d new term rules\n", ++iterations, termrules);
+ con->debugPrintf("After iteration #%d: %d new term rules\n", ++iterations, termrules);
} while (termrules && (iterations < 30));
freeRuleList(ntlist);
if (verbose) {
- con->DebugPrintf("\nGNF rules:\n");
+ con->debugPrintf("\nGNF rules:\n");
tlist->print();
- con->DebugPrintf("%d allocd rules\n", _allocd_rules);
- con->DebugPrintf("Freeing rule list...\n");
+ con->debugPrintf("%d allocd rules\n", _allocd_rules);
+ con->debugPrintf("Freeing rule list...\n");
freeRuleList(tlist);
return NULL;
}
@@ -548,7 +548,7 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) {
ParseRuleList *seeker, *subseeker;
if (verbose)
- con->DebugPrintf("Adding word %d...\n", word);
+ con->debugPrintf("Adding word %d...\n", word);
seeker = work;
while (seeker) {
@@ -562,7 +562,7 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) {
if (reduced_rules == NULL) {
freeRuleList(work);
if (verbose)
- con->DebugPrintf("No results.\n");
+ con->debugPrintf("No results.\n");
return 1;
}
@@ -592,10 +592,10 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) {
work = new_work;
if (verbose)
- con->DebugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work));
+ con->debugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work));
if (work == NULL) {
if (verbose)
- con->DebugPrintf("No results.\n");
+ con->debugPrintf("No results.\n");
return 1;
}
}
@@ -603,9 +603,9 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) {
results = work;
if (verbose) {
- con->DebugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id);
+ con->debugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id);
results->print();
- con->DebugPrintf("\n");
+ con->debugPrintf("\n");
}
// now use the first result
diff --git a/engines/sci/parser/said.cpp b/engines/sci/parser/said.cpp
index 693bbec744..27ebc58704 100644
--- a/engines/sci/parser/said.cpp
+++ b/engines/sci/parser/said.cpp
@@ -186,8 +186,7 @@ static bool parseList(ParseTreeNode* parentNode);
static bool parseListEntry(ParseTreeNode* parentNode);
static bool parseWord(ParseTreeNode* parentNode);
-static bool parseWord(ParseTreeNode* parentNode)
-{
+static bool parseWord(ParseTreeNode* parentNode) {
int token = said_tokens[said_token];
if (token & 0x8000)
return false;
@@ -201,8 +200,7 @@ static bool parseWord(ParseTreeNode* parentNode)
return true;
}
-static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty)
-{
+static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -259,8 +257,7 @@ static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty)
return false;
}
-static bool parsePart3(ParseTreeNode* parentNode, bool& nonempty)
-{
+static bool parsePart3(ParseTreeNode* parentNode, bool& nonempty) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -318,8 +315,7 @@ static bool parsePart3(ParseTreeNode* parentNode, bool& nonempty)
}
-static bool parseSlash(ParseTreeNode* parentNode)
-{
+static bool parseSlash(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -343,8 +339,7 @@ static bool parseSlash(ParseTreeNode* parentNode)
}
-static bool parseRef(ParseTreeNode* parentNode)
-{
+static bool parseRef(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -411,8 +406,7 @@ static bool parseRef(ParseTreeNode* parentNode)
return false;
}
-static bool parseComma(ParseTreeNode* parentNode)
-{
+static bool parseComma(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -435,8 +429,7 @@ static bool parseComma(ParseTreeNode* parentNode)
return false;
}
-static bool parseListEntry(ParseTreeNode* parentNode)
-{
+static bool parseListEntry(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -494,8 +487,7 @@ static bool parseListEntry(ParseTreeNode* parentNode)
return false;
}
-static bool parseList(ParseTreeNode* parentNode)
-{
+static bool parseList(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -524,8 +516,7 @@ static bool parseList(ParseTreeNode* parentNode)
return false;
}
-static bool parseExpr(ParseTreeNode* parentNode)
-{
+static bool parseExpr(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -546,7 +537,6 @@ static bool parseExpr(ParseTreeNode* parentNode)
said_attach_subtree(newParent, 0x141, 0x14F, newNode);
newParent = newParent->right;
-
}
found = parseRef(newParent);
@@ -561,8 +551,7 @@ static bool parseExpr(ParseTreeNode* parentNode)
return false;
}
-static bool parseSpec(ParseTreeNode* parentNode)
-{
+static bool parseSpec(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -748,9 +737,7 @@ static void node_print_desc(ParseTreeNode *) { }
-
-static int matchTrees(ParseTreeNode* parseT, ParseTreeNode* saidT)
-{
+static int matchTrees(ParseTreeNode* parseT, ParseTreeNode* saidT) {
outputDepth++;
scidprintf("%*smatchTrees on ", outputDepth, "");
node_print_desc(parseT);
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index 7c560dfaef..3344b79e26 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -530,18 +530,19 @@ bool Vocabulary::tokenizeString(ResultWordListList &retval, const char *sentence
*error = NULL;
do {
-
c = sentence[pos_in_sentence++];
+
if (Common::isAlnum(c) || (c == '-' && wordLen) || (c >= 0x80)) {
currentWord[wordLen] = lowerCaseMap[c];
++wordLen;
- }
- // Continue on this word */
- // Words may contain a '-', but may not
- // start with one.
- else {
- if (wordLen) { // Finished a word?
+ } else if (c == '\'' && wordLen && (sentence[pos_in_sentence] == 's' || sentence[pos_in_sentence] == 'S')) {
+ // Skip apostrophe-s at the end of the word, if it exists
+ pos_in_sentence++; // skip the 's'
+ } else {
+ // Continue on this word. Words may contain a '-', but may not start with
+ // one.
+ if (wordLen) { // Finished a word?
ResultWordList lookup_result;
// Look it up
@@ -577,7 +578,7 @@ void Vocabulary::printSuffixes() const {
strncpy(alt_buf, suf->alt_suffix, suf->alt_suffix_length);
alt_buf[suf->alt_suffix_length] = 0;
- con->DebugPrintf("%4d: (%03x) -%12s => -%12s (%03x)\n", i, suf->class_mask, word_buf, alt_buf, suf->result_class);
+ con->debugPrintf("%4d: (%03x) -%12s => -%12s (%03x)\n", i, suf->class_mask, word_buf, alt_buf, suf->result_class);
++i;
}
}
@@ -588,14 +589,14 @@ void Vocabulary::printParserWords() const {
int n = 0;
for (WordMap::iterator i = _parserWords.begin(); i != _parserWords.end(); ++i) {
for (ResultWordList::iterator j = i->_value.begin(); j != i->_value.end(); ++j) {
- con->DebugPrintf("%4d: %03x [%03x] %20s |", n, j->_class, j->_group, i->_key.c_str());
+ con->debugPrintf("%4d: %03x [%03x] %20s |", n, j->_class, j->_group, i->_key.c_str());
if (n % 3 == 0)
- con->DebugPrintf("\n");
+ con->debugPrintf("\n");
n++;
}
}
- con->DebugPrintf("\n");
+ con->debugPrintf("\n");
}
void _vocab_recursive_ptree_dump(ParseTreeNode *tree, int blanks) {
@@ -665,15 +666,15 @@ void Vocabulary::printParserNodes(int num) {
Console *con = g_sci->getSciDebugger();
for (int i = 0; i < num; i++) {
- con->DebugPrintf(" Node %03x: ", i);
+ con->debugPrintf(" Node %03x: ", i);
if (_parserNodes[i].type == kParseTreeLeafNode)
- con->DebugPrintf("Leaf: %04x\n", _parserNodes[i].value);
+ con->debugPrintf("Leaf: %04x\n", _parserNodes[i].value);
else {
// FIXME: Do we really want to print the *addresses*
// of the left & right child?
// Note that one or both may be zero pointers, so we can't just
// print their values.
- con->DebugPrintf("Branch: ->%p, ->%p\n",
+ con->debugPrintf("Branch: ->%p, ->%p\n",
(const void *)_parserNodes[i].left,
(const void *)_parserNodes[i].right);
}
@@ -694,11 +695,11 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c
return *pos;
}
if (type == kParseEndOfInput) {
- con->DebugPrintf("Unbalanced parentheses\n");
+ con->debugPrintf("Unbalanced parentheses\n");
return -1;
}
if (type == kParseClosingParenthesis) {
- con->DebugPrintf("Syntax error at token %d\n", *i);
+ con->debugPrintf("Syntax error at token %d\n", *i);
return -1;
}
@@ -735,7 +736,7 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c
const char *token = argv[(*i)++];
if (strcmp(token, ")"))
- con->DebugPrintf("Expected ')' at token %d\n", *i);
+ con->debugPrintf("Expected ')' at token %d\n", *i);
return oldPos;
}
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 4c7cd9b84a..66778f0914 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -710,7 +710,6 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
// 0x20 is set on rhythm channels to prevent remapping
// CHECKME: Which SCI versions need that set manually?
- channel->flags = (*channel->data) >> 4;
if (channel->number == 9)
channel->flags |= 2;
// Note: flag 1: channel start offset is 0 instead of 10
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index cf5192e1e6..fc723f18cf 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -511,6 +511,7 @@ void SciEngine::patchGameSaveRestore() {
case GID_HOYLE1: // gets confused, although the game doesnt support saving/restoring at all
case GID_HOYLE2: // gets confused, see hoyle1
case GID_JONES: // gets confused, when we patch us in, the game is only able to save to 1 slot, so hooking is not required
+ case GID_MOTHERGOOSE: // mother goose EGA saves/restores directly and has no save/restore dialogs
case GID_MOTHERGOOSE256: // mother goose saves/restores directly and has no save/restore dialogs
case GID_PHANTASMAGORIA: // has custom save/load code
case GID_SHIVERS: // has custom save/load code
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index 31c9d90de8..80a72b9a6f 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -398,8 +398,7 @@ void MidiPlayer_Midi::playSwitch(bool play) {
}
}
-bool MidiPlayer_Midi::isMt32GmPatch(const byte *data, int size)
-{
+bool MidiPlayer_Midi::isMt32GmPatch(const byte *data, int size) {
if (size < 1155)
return false;
if (size > 16889)
@@ -957,7 +956,7 @@ int MidiPlayer_Midi::open(ResourceManager *resMan) {
if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
warning("The automatic mapping for General MIDI hasn't been worked on for "
"SCI1 games. Music might sound wrong or broken. Please choose another "
- "music driver for this game (e.g. Adlib or MT-32) if you are "
+ "music driver for this game (e.g. AdLib or MT-32) if you are "
"experiencing issues with music");
// Modify velocity map to make low velocity notes a little louder
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index 97675a140e..362cca699d 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -142,6 +142,8 @@ void SciMusic::init() {
_driverLastChannel = _pMidiDrv->getLastChannel();
if (getSciVersion() <= SCI_VERSION_0_LATE)
_globalReverb = _pMidiDrv->getReverb(); // Init global reverb for SCI0
+
+ _currentlyPlayingSample = NULL;
}
void SciMusic::miditimerCallback(void *p) {
@@ -432,6 +434,17 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
if (pSnd->pStreamAud) {
if (!_pMixer->isSoundHandleActive(pSnd->hCurrentAud)) {
+ if ((_currentlyPlayingSample) && (_pMixer->isSoundHandleActive(_currentlyPlayingSample->hCurrentAud))) {
+ // Another sample is already playing, we have to stop that one
+ // SSCI is only able to play 1 sample at a time
+ // In Space Quest 5 room 250 the player is able to open the air-hatch and kill himself.
+ // In that situation the scripts are playing 2 samples at the same time and the first sample
+ // is not supposed to play.
+ // TODO: SSCI actually calls kDoAudio(play) internally, which stops other samples from being played
+ // but such a change isn't trivial, because we also handle Sound resources in here, that contain samples
+ _pMixer->stopHandle(_currentlyPlayingSample->hCurrentAud);
+ warning("kDoSound: sample already playing, old resource %d, new resource %d", _currentlyPlayingSample->resourceId, pSnd->resourceId);
+ }
// Sierra SCI ignores volume set when playing samples via kDoSound
// At least freddy pharkas/CD has a script bug that sets volume to 0
// when playing the "score" sample
@@ -449,6 +462,8 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
pSnd->pStreamAud, -1, _pMixer->kMaxChannelVolume, 0,
DisposeAfterUse::NO);
}
+ // Remember the sample, that is now playing
+ _currentlyPlayingSample = pSnd;
}
} else {
if (pSnd->pMidiParser) {
@@ -495,8 +510,11 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
pSnd->status = kSoundStopped;
if (_soundVersion <= SCI_VERSION_0_LATE)
pSnd->isQueued = false;
- if (pSnd->pStreamAud)
+ if (pSnd->pStreamAud) {
+ if (_currentlyPlayingSample == pSnd)
+ _currentlyPlayingSample = NULL;
_pMixer->stopHandle(pSnd->hCurrentAud);
+ }
if (pSnd->pMidiParser) {
Common::StackLock lock(_mutex);
@@ -556,6 +574,10 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
_mutex.unlock();
if (pSnd->pStreamAud) {
+ if (_currentlyPlayingSample == pSnd) {
+ // Forget about this sound, in case it was currently playing
+ _currentlyPlayingSample = NULL;
+ }
_pMixer->stopHandle(pSnd->hCurrentAud);
delete pSnd->pStreamAud;
pSnd->pStreamAud = NULL;
@@ -666,7 +688,7 @@ void SciMusic::printPlayList(Console *con) {
for (uint32 i = 0; i < _playList.size(); i++) {
MusicEntry *song = _playList[i];
- con->DebugPrintf("%d: %04x:%04x (%s), resource id: %d, status: %s, %s type\n",
+ con->debugPrintf("%d: %04x:%04x (%s), resource id: %d, status: %s, %s type\n",
i, PRINT_REG(song->soundObj),
g_sci->getEngineState()->_segMan->getObjectName(song->soundObj),
song->resourceId, musicStatus[song->status],
@@ -683,26 +705,26 @@ void SciMusic::printSongInfo(reg_t obj, Console *con) {
for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
MusicEntry *song = *i;
if (song->soundObj == obj) {
- con->DebugPrintf("Resource id: %d, status: %s\n", song->resourceId, musicStatus[song->status]);
- con->DebugPrintf("dataInc: %d, hold: %d, loop: %d\n", song->dataInc, song->hold, song->loop);
- con->DebugPrintf("signal: %d, priority: %d\n", song->signal, song->priority);
- con->DebugPrintf("ticker: %d, volume: %d\n", song->ticker, song->volume);
+ con->debugPrintf("Resource id: %d, status: %s\n", song->resourceId, musicStatus[song->status]);
+ con->debugPrintf("dataInc: %d, hold: %d, loop: %d\n", song->dataInc, song->hold, song->loop);
+ con->debugPrintf("signal: %d, priority: %d\n", song->signal, song->priority);
+ con->debugPrintf("ticker: %d, volume: %d\n", song->ticker, song->volume);
if (song->pMidiParser) {
- con->DebugPrintf("Type: MIDI\n");
+ con->debugPrintf("Type: MIDI\n");
if (song->soundRes) {
SoundResource::Track *track = song->soundRes->getTrackByType(_pMidiDrv->getPlayId());
- con->DebugPrintf("Channels: %d\n", track->channelCount);
+ con->debugPrintf("Channels: %d\n", track->channelCount);
}
} else if (song->pStreamAud || song->pLoopStream) {
- con->DebugPrintf("Type: digital audio (%s), sound active: %s\n",
+ con->debugPrintf("Type: digital audio (%s), sound active: %s\n",
song->pStreamAud ? "non looping" : "looping",
_pMixer->isSoundHandleActive(song->hCurrentAud) ? "yes" : "no");
if (song->soundRes) {
- con->DebugPrintf("Sound resource information:\n");
+ con->debugPrintf("Sound resource information:\n");
SoundResource::Track *track = song->soundRes->getTrackByType(_pMidiDrv->getPlayId());
if (track && track->digitalChannelNr != -1) {
- con->DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n",
+ con->debugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n",
track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr);
}
}
@@ -712,7 +734,7 @@ void SciMusic::printSongInfo(reg_t obj, Console *con) {
}
}
- con->DebugPrintf("Song object not found in playlist");
+ con->debugPrintf("Song object not found in playlist");
}
MusicEntry::MusicEntry() {
@@ -1169,8 +1191,14 @@ ChannelRemapping *SciMusic::determineChannelMap() {
int neededVoices = channel._voices;
// do we have enough free voices?
- // We only care for essential channels
- if (map->_freeVoices < neededVoices && prio > 0) {
+ if (map->_freeVoices < neededVoices) {
+ // We only care for essential channels
+ if (prio > 0) {
+#ifdef DEBUG_REMAP
+ debug(" not enough voices; need %d, have %d. Skipping this channel.", neededVoices, map->_freeVoices);
+#endif
+ continue;
+ }
do {
int j = map->lowestPrio();
if (j == -1) {
diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h
index bfc542d2a5..6149bb799e 100644
--- a/engines/sci/sound/music.h
+++ b/engines/sci/sound/music.h
@@ -264,6 +264,8 @@ private:
int _driverFirstChannel;
int _driverLastChannel;
+
+ MusicEntry *_currentlyPlayingSample;
};
} // End of namespace Sci
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 2bd7f50de5..73e0a23a6a 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -61,7 +61,7 @@ reg_t SoundCommandParser::kDoSoundInit(int argc, reg_t *argv, reg_t acc) {
}
int SoundCommandParser::getSoundResourceId(reg_t obj) {
- int resourceId = obj.getSegment() ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1;
+ int resourceId = obj.getSegment() ? (int)readSelectorValue(_segMan, obj, SELECTOR(number)) : -1;
// Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did.
if (g_sci && g_sci->_features->useAltWinGMSound()) {
// Check if the alternate MIDI song actually exists...
diff --git a/engines/scumm/POTFILES b/engines/scumm/POTFILES
index 6034320259..6d10537d3c 100644
--- a/engines/scumm/POTFILES
+++ b/engines/scumm/POTFILES
@@ -1,3 +1,6 @@
engines/scumm/dialogs.cpp
engines/scumm/help.cpp
engines/scumm/scumm.cpp
+engines/scumm/players/player_v3m.cpp
+engines/scumm/players/player_v5m.cpp
+
diff --git a/engines/scumm/cdda.cpp b/engines/scumm/cdda.cpp
new file mode 100644
index 0000000000..adb414ecce
--- /dev/null
+++ b/engines/scumm/cdda.cpp
@@ -0,0 +1,120 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/cdda.h"
+#include "common/stream.h"
+#include "audio/audiostream.h"
+
+namespace Scumm {
+
+
+#pragma mark -
+#pragma mark --- CDDA stream ---
+#pragma mark -
+
+#define START_OF_CDDA_DATA 800
+#define BLOCK_SIZE 1177
+
+class CDDAStream : public Audio::SeekableAudioStream {
+private:
+ Common::SeekableReadStream *_stream;
+ DisposeAfterUse::Flag _disposeAfterUse;
+ byte _shiftLeft;
+ byte _shiftRight;
+ uint32 _pos;
+ Audio::Timestamp _length;
+
+public:
+ CDDAStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse);
+ virtual ~CDDAStream();
+
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const { return true; }
+ int getRate() const { return 44100; }
+ bool endOfData() const { return _stream->eos(); }
+ bool seek(const Audio::Timestamp &where);
+ Audio::Timestamp getLength() const { return _length; }
+};
+
+CDDAStream::CDDAStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) :
+ _stream(stream), _disposeAfterUse(disposeAfterUse), _pos(START_OF_CDDA_DATA) {
+ _stream->seek(START_OF_CDDA_DATA, SEEK_SET);
+ // The total size of CDDA.SOU is 289,808,802 bytes or (289808802 - 800) / 1177 = 246226 blocks
+ // We also deduct the shift values to return the correct length
+ uint32 blocks = (_stream->size() - START_OF_CDDA_DATA) / BLOCK_SIZE;
+ _length = Audio::Timestamp(0, (_stream->size() - START_OF_CDDA_DATA - blocks) / (isStereo() ? 2 : 1), getRate());
+}
+
+CDDAStream::~CDDAStream() {
+ if (_disposeAfterUse == DisposeAfterUse::YES)
+ delete _stream;
+}
+
+bool CDDAStream::seek(const Audio::Timestamp &where) {
+ const uint32 seekSample = convertTimeToStreamPos(where, getRate(), isStereo()).totalNumberOfFrames();
+ uint32 blocks = seekSample / 1176;
+
+ // Before seeking, read the shift values from the beginning of that block
+ _stream->seek(START_OF_CDDA_DATA + blocks * BLOCK_SIZE, SEEK_SET);
+ byte shiftVal = _stream->readByte();
+ _shiftLeft = shiftVal >> 4;
+ _shiftRight = shiftVal & 0x0F;
+
+ _pos = START_OF_CDDA_DATA + blocks + seekSample;
+ return _stream->seek(_pos, SEEK_SET);
+}
+
+int CDDAStream::readBuffer(int16 *buffer, const int numSamples) {
+ int samples;
+
+ for (samples = 0 ; samples < numSamples && !_stream->eos() ; ) {
+ if (!((_pos - START_OF_CDDA_DATA) % BLOCK_SIZE)) {
+ byte shiftVal = _stream->readByte();
+ _shiftLeft = shiftVal >> 4;
+ _shiftRight = shiftVal & 0x0F;
+ _pos++;
+ }
+ buffer[samples++] = _stream->readSByte() << _shiftLeft;
+ buffer[samples++] = _stream->readSByte() << _shiftRight;
+ _pos += 2;
+ }
+ return samples;
+}
+
+#pragma mark -
+#pragma mark --- CDDA factory functions ---
+#pragma mark -
+
+Audio::SeekableAudioStream *makeCDDAStream(
+ Common::SeekableReadStream *stream,
+ DisposeAfterUse::Flag disposeAfterUse) {
+ Audio::SeekableAudioStream *s = new CDDAStream(stream, disposeAfterUse);
+ if (s && s->endOfData()) {
+ delete s;
+ return 0;
+ } else {
+ return s;
+ }
+ return 0;
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/cdda.h b/engines/scumm/cdda.h
new file mode 100644
index 0000000000..c1e6e82c9e
--- /dev/null
+++ b/engines/scumm/cdda.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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/**
+ * @file
+ * CD audio decoder used in the Steam versions of Loom
+ */
+
+#ifndef SCUMM_CDDA_H
+#define SCUMM_CDDA_H
+
+#include "common/types.h"
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Audio {
+class SeekableAudioStream;
+}
+
+namespace Scumm {
+
+/**
+ * Create a new SeekableAudioStream from the CDDA data in the given stream.
+ * Allows for seeking (which is why we require a SeekableReadStream).
+ *
+ * @param stream The SeekableReadStream from which to read the CDDA data
+ * @param disposeAfterUse Whether to delete the stream after use
+ * @return a new SeekableAudioStream, or NULL, if an error occurred
+ */
+Audio::SeekableAudioStream *makeCDDAStream(
+ Common::SeekableReadStream *stream,
+ DisposeAfterUse::Flag disposeAfterUse);
+
+} // End of namespace Audio
+
+#endif // #ifndef SCUMM_CDDA_H
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 185ebbce6e..e546c805b5 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -253,7 +253,7 @@ CharsetRenderer::~CharsetRenderer() {
CharsetRendererCommon::CharsetRendererCommon(ScummEngine *vm)
: CharsetRenderer(vm), _bytesPerPixel(0), _fontHeight(0), _numChars(0) {
- _shadowMode = false;
+ _enableShadow = false;
_shadowColor = 0;
}
@@ -392,6 +392,10 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) {
} else if (chr & 0x80) {
pos++;
width += _vm->_2byteWidth;
+ // Original keeps glyph width and character dimensions separately
+ if (_vm->_language == Common::KO_KOR || _vm->_language == Common::ZH_TWN) {
+ width++;
+ }
continue;
}
}
@@ -478,6 +482,12 @@ void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
} else if (chr & 0x80) {
pos++;
curw += _vm->_2byteWidth;
+ // Original keeps glyph width and character dimensions separately
+ if (_vm->_language == Common::KO_KOR || _vm->_language == Common::ZH_TWN) {
+ curw++;
+ }
+ } else {
+ curw += getCharWidth(chr);
}
} else {
curw += getCharWidth(chr);
@@ -507,12 +517,17 @@ int CharsetRendererV3::getCharWidth(uint16 chr) {
return spacing;
}
-void CharsetRendererV3::enableShadow(bool enable) {
+void CharsetRendererPC::enableShadow(bool enable) {
_shadowColor = 0;
- _shadowMode = enable;
+ _enableShadow = enable;
+
+ if (_vm->_game.version >= 7 && _vm->_language == Common::KO_KOR)
+ _shadowType = kHorizontalShadowType;
+ else
+ _shadowType = kNormalShadowType;
}
-void CharsetRendererV3::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
+void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
byte *dst = (byte *)dest.getBasePtr(x, y);
byte bits = 0;
@@ -525,8 +540,12 @@ void CharsetRendererV3::drawBits1(Graphics::Surface &dest, int x, int y, const b
if ((x % 8) == 0)
bits = *src++;
if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
- if (_shadowMode)
- dst[1] = dst2[0] = dst2[1] = _shadowColor;
+ if (_enableShadow) {
+ if (_shadowType == kNormalShadowType)
+ dst[1] = dst2[0] = dst2[1] = _shadowColor;
+ else if (_shadowType == kHorizontalShadowType)
+ dst[1] = _shadowColor;
+ }
dst[0] = col;
}
dst += dest.format.bytesPerPixel;
@@ -615,7 +634,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (_left + origWidth > _right + 1)
return;
- if (_shadowMode) {
+ if (_enableShadow) {
width++;
height++;
}
@@ -658,7 +677,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_shadowMode)
+ if (_enableShadow)
_str.right++;
}
@@ -776,11 +795,15 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
printCharIntern(is2byte, _charPtr, _origWidth, _origHeight, _width, _height, vs, ignoreCharsetMask);
+ // Original keeps glyph width and character dimensions separately
+ if ((_vm->_language == Common::ZH_TWN || _vm->_language == Common::KO_KOR) && is2byte)
+ _origWidth++;
+
_left += _origWidth;
if (_str.right < _left) {
_str.right = _left;
- if (_vm->_game.platform != Common::kPlatformFMTowns && _shadowMode)
+ if (_vm->_game.platform != Common::kPlatformFMTowns && _enableShadow)
_str.right++;
}
@@ -844,7 +867,10 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
drawTop = _top - _vm->_screenTop;
}
- drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight);
+ if (is2byte && _vm->_game.platform != Common::kPlatformFMTowns)
+ drawBits1(dstSurface, _left, drawTop, charPtr, drawTop, origWidth, origHeight);
+ else
+ drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight);
if (_blitAlso && vs->hasTwoBuffers) {
// FIXME: Revisiting this code, I think the _blitAlso mode is likely broken
@@ -884,6 +910,24 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
}
bool CharsetRendererClassic::prepareDraw(uint16 chr) {
+ bool is2byte = (chr >= 256 && _vm->_useCJKMode);
+ if (is2byte) {
+ if (_vm->_language == Common::KO_KOR)
+ enableShadow(true);
+
+ _charPtr = _vm->get2byteCharPtr(chr);
+ _width = _origWidth = _vm->_2byteWidth;
+ _height = _origHeight = _vm->_2byteHeight;
+ _offsX = _offsY = 0;
+
+ if (_enableShadow) {
+ _width++;
+ _height++;
+ }
+
+ return true;
+ }
+
uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
assert(charOffs < 0x14000);
if (!charOffs)
@@ -908,8 +952,14 @@ bool CharsetRendererClassic::prepareDraw(uint16 chr) {
void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int y) {
if (!prepareDraw(chr))
return;
+
byte *dst = (byte *)s.getBasePtr(x, y);
- drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height);
+
+ bool is2byte = (_vm->_useCJKMode && chr >= 256);
+ if (is2byte)
+ drawBits1(s, x, y, _charPtr, y, _width, _height);
+ else
+ drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height);
}
void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) {
@@ -982,7 +1032,7 @@ int CharsetRendererTownsV3::getFontHeight() {
void CharsetRendererTownsV3::enableShadow(bool enable) {
_shadowColor = 8;
- _shadowMode = enable;
+ _enableShadow = enable;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_shadowColor = 0x88;
@@ -1027,13 +1077,13 @@ void CharsetRendererTownsV3::drawBits1(Graphics::Surface &dest, int x, int y, co
bits = *src++;
if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
if (dest.format.bytesPerPixel == 2) {
- if (_shadowMode) {
+ if (_enableShadow) {
WRITE_UINT16(dst + 2, _vm->_16BitPalette[_shadowColor]);
WRITE_UINT16(dst + dest.pitch, _vm->_16BitPalette[_shadowColor]);
}
WRITE_UINT16(dst, _vm->_16BitPalette[_color]);
} else {
- if (_shadowMode) {
+ if (_enableShadow) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (scale2x) {
dst[2] = dst[3] = dst2[2] = dst2[3] = _shadowColor;
@@ -1124,11 +1174,11 @@ void CharsetRendererPCE::drawBits1(Graphics::Surface &dest, int x, int y, const
bits = *src++;
if ((bits & revBitMask(bitCount % 8)) && y + drawTop >= 0) {
if (dest.format.bytesPerPixel == 2) {
- if (_shadowMode)
+ if (_enableShadow)
WRITE_UINT16(dst + dest.pitch + 2, _vm->_16BitPalette[_shadowColor]);
WRITE_UINT16(dst, _vm->_16BitPalette[_color]);
} else {
- if (_shadowMode)
+ if (_enableShadow)
*(dst + dest.pitch + 1) = _shadowColor;
*dst = _color;
}
@@ -1227,7 +1277,8 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
int width = _current->getCharWidth(chr);
int height = _current->getCharHeight(chr);
- if (chr >= 256 && _vm->_useCJKMode)
+ bool is2byte = chr >= 256 && _vm->_useCJKMode;
+ if (is2byte)
width = _vm->_2byteWidth;
shadow.right = _left + width;
@@ -1259,8 +1310,8 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
_str.left = _left;
// Original keeps glyph width and character dimensions separately
- if (_vm->_language == Common::ZH_TWN && width == 16)
- width = 17;
+ if ((_vm->_language == Common::ZH_TWN || _vm->_language == Common::KO_KOR) && is2byte)
+ width++;
_left += width;
@@ -1327,7 +1378,7 @@ void CharsetRendererNES::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_shadowMode)
+ if (_enableShadow)
_str.right++;
}
@@ -1483,7 +1534,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) {
_origHeight = _height = _vm->_2byteHeight;
_charPtr = _vm->get2byteCharPtr(chr);
_offsX = _offsY = 0;
- if (_shadowMode) {
+ if (_enableShadow) {
_width++;
_height++;
}
@@ -1495,7 +1546,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) {
}
void CharsetRendererTownsClassic::setupShadowMode() {
- _shadowMode = true;
+ _enableShadow = true;
_shadowColor = _vm->_townsCharsetColorMap[0];
assert(_vm->_cjkFont);
diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h
index 5a9977b7d6..b4b3d88ccd 100644
--- a/engines/scumm/charset.h
+++ b/engines/scumm/charset.h
@@ -100,7 +100,7 @@ protected:
int _numChars;
byte _shadowColor;
- bool _shadowMode;
+ bool _enableShadow;
public:
CharsetRendererCommon(ScummEngine *vm);
@@ -110,7 +110,24 @@ public:
virtual int getFontHeight();
};
-class CharsetRendererClassic : public CharsetRendererCommon {
+class CharsetRendererPC : public CharsetRendererCommon {
+ enum ShadowType {
+ kNoShadowType,
+ kNormalShadowType,
+ kHorizontalShadowType
+ };
+
+ ShadowType _shadowType;
+
+protected:
+ virtual void enableShadow(bool enable);
+ virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height);
+
+public:
+ CharsetRendererPC(ScummEngine *vm) : CharsetRendererCommon(vm), _shadowType(kNoShadowType) { }
+};
+
+class CharsetRendererClassic : public CharsetRendererPC {
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);
@@ -124,7 +141,7 @@ protected:
VirtScreenNumber _drawScreen;
public:
- CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
+ CharsetRendererClassic(ScummEngine *vm) : CharsetRendererPC(vm) {}
void printChar(int chr, bool ignoreCharsetMask);
void drawChar(int chr, Graphics::Surface &s, int x, int y);
@@ -170,10 +187,8 @@ public:
int getCharWidth(uint16 chr) { return 8; }
};
-class CharsetRendererV3 : public CharsetRendererCommon {
+class CharsetRendererV3 : public CharsetRendererPC {
protected:
- virtual void enableShadow(bool enable);
- virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height);
virtual int getDrawWidthIntern(uint16 chr);
virtual int getDrawHeightIntern(uint16 chr);
virtual void setDrawCharIntern(uint16 chr) {}
@@ -181,7 +196,7 @@ protected:
const byte *_widthTable;
public:
- CharsetRendererV3(ScummEngine *vm) : CharsetRendererCommon(vm) {}
+ CharsetRendererV3(ScummEngine *vm) : CharsetRendererPC(vm) {}
void printChar(int chr, bool ignoreCharsetMask);
void drawChar(int chr, Graphics::Surface &s, int x, int y);
diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp
index a792d63149..2b718b2cfe 100644
--- a/engines/scumm/debugger.cpp
+++ b/engines/scumm/debugger.cpp
@@ -58,52 +58,63 @@ ScummDebugger::ScummDebugger(ScummEngine *s)
_vm = s;
// Register variables
- DVar_Register("scumm_speed", &_vm->_fastMode, DVAR_BYTE, 0);
- DVar_Register("scumm_room", &_vm->_currentRoom, DVAR_BYTE, 0);
- DVar_Register("scumm_roomresource", &_vm->_roomResource, DVAR_INT, 0);
- DVar_Register("scumm_vars", &_vm->_scummVars, DVAR_INTARRAY, _vm->_numVariables);
+ registerVar("scumm_speed", &_vm->_fastMode);
+ registerVar("scumm_room", &_vm->_currentRoom);
+ registerVar("scumm_roomresource", &_vm->_roomResource);
+ registerVar("scumm_vars", &_vm->_scummVars, _vm->_numVariables);
// Register commands
- DCmd_Register("continue", WRAP_METHOD(ScummDebugger, Cmd_Exit));
- DCmd_Register("restart", WRAP_METHOD(ScummDebugger, Cmd_Restart));
-
- DCmd_Register("actor", WRAP_METHOD(ScummDebugger, Cmd_Actor));
- DCmd_Register("actors", WRAP_METHOD(ScummDebugger, Cmd_PrintActor));
- DCmd_Register("box", WRAP_METHOD(ScummDebugger, Cmd_PrintBox));
- DCmd_Register("matrix", WRAP_METHOD(ScummDebugger, Cmd_PrintBoxMatrix));
- DCmd_Register("camera", WRAP_METHOD(ScummDebugger, Cmd_Camera));
- DCmd_Register("room", WRAP_METHOD(ScummDebugger, Cmd_Room));
- DCmd_Register("objects", WRAP_METHOD(ScummDebugger, Cmd_PrintObjects));
- DCmd_Register("object", WRAP_METHOD(ScummDebugger, Cmd_Object));
- DCmd_Register("script", WRAP_METHOD(ScummDebugger, Cmd_Script));
- DCmd_Register("scr", WRAP_METHOD(ScummDebugger, Cmd_Script));
- DCmd_Register("scripts", WRAP_METHOD(ScummDebugger, Cmd_PrintScript));
- DCmd_Register("importres", WRAP_METHOD(ScummDebugger, Cmd_ImportRes));
+ registerCmd("continue", WRAP_METHOD(ScummDebugger, cmdExit));
+ registerCmd("restart", WRAP_METHOD(ScummDebugger, Cmd_Restart));
+
+ registerCmd("actor", WRAP_METHOD(ScummDebugger, Cmd_Actor));
+ registerCmd("actors", WRAP_METHOD(ScummDebugger, Cmd_PrintActor));
+ registerCmd("box", WRAP_METHOD(ScummDebugger, Cmd_PrintBox));
+ registerCmd("matrix", WRAP_METHOD(ScummDebugger, Cmd_PrintBoxMatrix));
+ registerCmd("camera", WRAP_METHOD(ScummDebugger, Cmd_Camera));
+ registerCmd("room", WRAP_METHOD(ScummDebugger, Cmd_Room));
+ registerCmd("objects", WRAP_METHOD(ScummDebugger, Cmd_PrintObjects));
+ registerCmd("object", WRAP_METHOD(ScummDebugger, Cmd_Object));
+ registerCmd("script", WRAP_METHOD(ScummDebugger, Cmd_Script));
+ registerCmd("scr", WRAP_METHOD(ScummDebugger, Cmd_Script));
+ registerCmd("scripts", WRAP_METHOD(ScummDebugger, Cmd_PrintScript));
+ registerCmd("importres", WRAP_METHOD(ScummDebugger, Cmd_ImportRes));
if (_vm->_game.id == GID_LOOM)
- DCmd_Register("drafts", WRAP_METHOD(ScummDebugger, Cmd_PrintDraft));
+ registerCmd("drafts", WRAP_METHOD(ScummDebugger, Cmd_PrintDraft));
if (_vm->_game.id == GID_MONKEY && _vm->_game.platform == Common::kPlatformSegaCD)
- DCmd_Register("passcode", WRAP_METHOD(ScummDebugger, Cmd_Passcode));
+ registerCmd("passcode", WRAP_METHOD(ScummDebugger, Cmd_Passcode));
- DCmd_Register("loadgame", WRAP_METHOD(ScummDebugger, Cmd_LoadGame));
- DCmd_Register("savegame", WRAP_METHOD(ScummDebugger, Cmd_SaveGame));
+ registerCmd("loadgame", WRAP_METHOD(ScummDebugger, Cmd_LoadGame));
+ registerCmd("savegame", WRAP_METHOD(ScummDebugger, Cmd_SaveGame));
- DCmd_Register("level", WRAP_METHOD(ScummDebugger, Cmd_DebugLevel));
- DCmd_Register("debug", WRAP_METHOD(ScummDebugger, Cmd_Debug));
+ registerCmd("debug", WRAP_METHOD(ScummDebugger, Cmd_Debug));
- DCmd_Register("show", WRAP_METHOD(ScummDebugger, Cmd_Show));
- DCmd_Register("hide", WRAP_METHOD(ScummDebugger, Cmd_Hide));
+ registerCmd("show", WRAP_METHOD(ScummDebugger, Cmd_Show));
+ registerCmd("hide", WRAP_METHOD(ScummDebugger, Cmd_Hide));
- DCmd_Register("imuse", WRAP_METHOD(ScummDebugger, Cmd_IMuse));
+ registerCmd("imuse", WRAP_METHOD(ScummDebugger, Cmd_IMuse));
- DCmd_Register("resetcursors", WRAP_METHOD(ScummDebugger, Cmd_ResetCursors));
+ registerCmd("resetcursors", WRAP_METHOD(ScummDebugger, Cmd_ResetCursors));
}
ScummDebugger::~ScummDebugger() {
// we need this destructor, even if it is empty, for __SYMBIAN32__
}
+void ScummDebugger::preEnter() {
+}
+
+void ScummDebugger::postEnter() {
+ // Runtime debug level change is dealt with by the base class "debuglevel" command
+ // but need to ensure that the _debugMode parameter is updated in sync.
+ _vm->_debugMode = (gDebugLevel >= 0);
+ // Boot params often need debugging switched on to work
+ if (_vm->_bootParam)
+ _vm->_debugMode = true;
+}
+
///////////////////////////////////////////////////
// Now the fun stuff:
@@ -117,51 +128,51 @@ bool ScummDebugger::Cmd_Restart(int argc, const char **argv) {
bool ScummDebugger::Cmd_IMuse(int argc, const char **argv) {
if (!_vm->_imuse && !_vm->_musicEngine) {
- DebugPrintf("No iMuse engine is active.\n");
+ debugPrintf("No iMuse engine is active.\n");
return true;
}
if (argc > 1) {
if (!strcmp(argv[1], "panic")) {
_vm->_musicEngine->stopAllSounds();
- DebugPrintf("AAAIIIEEEEEE!\n");
- DebugPrintf("Shutting down all music tracks\n");
+ debugPrintf("AAAIIIEEEEEE!\n");
+ debugPrintf("Shutting down all music tracks\n");
return true;
} else if (!strcmp(argv[1], "play")) {
if (argc > 2 && (!strcmp(argv[2], "random") || atoi(argv[2]) != 0)) {
int sound = atoi(argv[2]);
if (!strcmp(argv[2], "random")) {
- DebugPrintf("Selecting from %d songs...\n", _vm->_numSounds);
+ debugPrintf("Selecting from %d songs...\n", _vm->_numSounds);
sound = _vm->_rnd.getRandomNumber(_vm->_numSounds);
}
_vm->ensureResourceLoaded(rtSound, sound);
_vm->_musicEngine->startSound(sound);
- DebugPrintf("Attempted to start music %d.\n", sound);
+ debugPrintf("Attempted to start music %d.\n", sound);
} else {
- DebugPrintf("Specify a music resource # from 1-255.\n");
+ debugPrintf("Specify a music resource # from 1-255.\n");
}
return true;
} else if (!strcmp(argv[1], "stop")) {
if (argc > 2 && (!strcmp(argv[2], "all") || atoi(argv[2]) != 0)) {
if (!strcmp(argv[2], "all")) {
_vm->_musicEngine->stopAllSounds();
- DebugPrintf("Shutting down all music tracks.\n");
+ debugPrintf("Shutting down all music tracks.\n");
} else {
_vm->_musicEngine->stopSound(atoi(argv[2]));
- DebugPrintf("Attempted to stop music %d.\n", atoi(argv[2]));
+ debugPrintf("Attempted to stop music %d.\n", atoi(argv[2]));
}
} else {
- DebugPrintf("Specify a music resource # or \"all\".\n");
+ debugPrintf("Specify a music resource # or \"all\".\n");
}
return true;
}
}
- DebugPrintf("Available iMuse commands:\n");
- DebugPrintf(" panic - Stop all music tracks\n");
- DebugPrintf(" play # - Play a music resource\n");
- DebugPrintf(" stop # - Stop a music resource\n");
+ debugPrintf("Available iMuse commands:\n");
+ debugPrintf(" panic - Stop all music tracks\n");
+ debugPrintf(" play # - Play a music resource\n");
+ debugPrintf(" stop # - Stop a music resource\n");
return true;
}
@@ -174,7 +185,7 @@ bool ScummDebugger::Cmd_Room(int argc, const char **argv) {
_vm->_fullRedraw = true;
return false;
} else {
- DebugPrintf("Current room: %d [%d] - use 'room <roomnum>' to switch\n", _vm->_currentRoom, _vm->_roomResource);
+ debugPrintf("Current room: %d [%d] - use 'room <roomnum>' to switch\n", _vm->_currentRoom, _vm->_roomResource);
return true;
}
}
@@ -189,7 +200,7 @@ bool ScummDebugger::Cmd_LoadGame(int argc, const char **argv) {
return false;
}
- DebugPrintf("Syntax: loadgame <slotnum>\n");
+ debugPrintf("Syntax: loadgame <slotnum>\n");
return true;
}
@@ -199,7 +210,7 @@ bool ScummDebugger::Cmd_SaveGame(int argc, const char **argv) {
_vm->requestSave(slot, argv[2]);
} else
- DebugPrintf("Syntax: savegame <slotnum> <name>\n");
+ debugPrintf("Syntax: savegame <slotnum> <name>\n");
return true;
}
@@ -207,18 +218,18 @@ bool ScummDebugger::Cmd_SaveGame(int argc, const char **argv) {
bool ScummDebugger::Cmd_Show(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Syntax: show <parameter>\n");
+ debugPrintf("Syntax: show <parameter>\n");
return true;
}
if (!strcmp(argv[1], "hex")) {
_vm->_hexdumpScripts = true;
- DebugPrintf("Script hex dumping on\n");
+ debugPrintf("Script hex dumping on\n");
} else if (!strncmp(argv[1], "sta", 3)) {
_vm->_showStack = 1;
- DebugPrintf("Stack tracing on\n");
+ debugPrintf("Stack tracing on\n");
} else {
- DebugPrintf("Unknown show parameter '%s'\nParameters are 'hex' for hex dumping and 'sta' for stack tracing\n", argv[1]);
+ debugPrintf("Unknown show parameter '%s'\nParameters are 'hex' for hex dumping and 'sta' for stack tracing\n", argv[1]);
}
return true;
}
@@ -226,18 +237,18 @@ bool ScummDebugger::Cmd_Show(int argc, const char **argv) {
bool ScummDebugger::Cmd_Hide(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Syntax: hide <parameter>\n");
+ debugPrintf("Syntax: hide <parameter>\n");
return true;
}
if (!strcmp(argv[1], "hex")) {
_vm->_hexdumpScripts = false;
- DebugPrintf("Script hex dumping off\n");
+ debugPrintf("Script hex dumping off\n");
} else if (!strncmp(argv[1], "sta", 3)) {
_vm->_showStack = 0;
- DebugPrintf("Stack tracing off\n");
+ debugPrintf("Stack tracing off\n");
} else {
- DebugPrintf("Unknown hide parameter '%s'\nParameters are 'hex' to turn off hex dumping and 'sta' to turn off stack tracing\n", argv[1]);
+ debugPrintf("Unknown hide parameter '%s'\nParameters are 'hex' to turn off hex dumping and 'sta' to turn off stack tracing\n", argv[1]);
}
return true;
}
@@ -246,7 +257,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) {
int scriptnum;
if (argc < 2) {
- DebugPrintf("Syntax: script <scriptnum> <command>\n");
+ debugPrintf("Syntax: script <scriptnum> <command>\n");
return true;
}
@@ -254,7 +265,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) {
// FIXME: what is the max range on these?
// if (scriptnum >= _vm->_numScripts) {
- // DebugPrintf("Script number %d is out of range (range: 1 - %d)\n", scriptnum, _vm->_numScripts);
+ // debugPrintf("Script number %d is out of range (range: 1 - %d)\n", scriptnum, _vm->_numScripts);
// return true;
//}
@@ -264,7 +275,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) {
_vm->runScript(scriptnum, 0, 0, 0);
return false;
} else {
- DebugPrintf("Unknown script command '%s'\nUse <kill/stop | run/start> as command\n", argv[2]);
+ debugPrintf("Unknown script command '%s'\nUse <kill/stop | run/start> as command\n", argv[2]);
}
return true;
@@ -276,7 +287,7 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) {
int resnum;
if (argc != 4) {
- DebugPrintf("Syntax: importres <restype> <filename> <resnum>\n");
+ debugPrintf("Syntax: importres <restype> <filename> <resnum>\n");
return true;
}
@@ -286,7 +297,7 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) {
if (!strncmp(argv[1], "scr", 3)) {
file.open(argv[2]);
if (file.isOpen() == false) {
- DebugPrintf("Could not open file %s\n", argv[2]);
+ debugPrintf("Could not open file %s\n", argv[2]);
return true;
}
if (_vm->_game.features & GF_SMALL_HEADER) {
@@ -307,25 +318,25 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) {
file.read(_vm->_res->createResource(rtScript, resnum, size), size);
} else
- DebugPrintf("Unknown importres type '%s'\n", argv[1]);
+ debugPrintf("Unknown importres type '%s'\n", argv[1]);
return true;
}
bool ScummDebugger::Cmd_PrintScript(int argc, const char **argv) {
int i;
ScriptSlot *ss = _vm->vm.slot;
- DebugPrintf("+-----------------------------------+\n");
- DebugPrintf("|# | num|offst|sta|typ|fr|rec|fc|cut|\n");
- DebugPrintf("+--+----+-----+---+---+--+---+--+---+\n");
+ debugPrintf("+-----------------------------------+\n");
+ debugPrintf("|# | num|offst|sta|typ|fr|rec|fc|cut|\n");
+ debugPrintf("+--+----+-----+---+---+--+---+--+---+\n");
for (i = 0; i < NUM_SCRIPT_SLOT; i++, ss++) {
if (ss->number) {
- DebugPrintf("|%2d|%4d|%05x|%3d|%3d|%2d|%3d|%2d|%3d|\n",
+ debugPrintf("|%2d|%4d|%05x|%3d|%3d|%2d|%3d|%2d|%3d|\n",
i, ss->number, ss->offs, ss->status, ss->where,
ss->freezeResistant, ss->recursive,
ss->freezeCount, ss->cutsceneOverride);
}
}
- DebugPrintf("+-----------------------------------+\n");
+ debugPrintf("+-----------------------------------+\n");
return true;
}
@@ -336,13 +347,13 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) {
int value = 0, value2 = 0;
if (argc < 3) {
- DebugPrintf("Syntax: actor <actornum> <command> <parameter>\n");
+ debugPrintf("Syntax: actor <actornum> <command> <parameter>\n");
return true;
}
actnum = atoi(argv[1]);
if (actnum >= _vm->_numActors) {
- DebugPrintf("Actor %d is out of range (range: 1 - %d)\n", actnum, _vm->_numActors);
+ debugPrintf("Actor %d is out of range (range: 1 - %d)\n", actnum, _vm->_numActors);
return true;
}
@@ -354,43 +365,43 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) {
if (!strcmp(argv[2], "animvar")) {
a->setAnimVar(value, value2);
- DebugPrintf("Actor[%d].animVar[%d] = %d\n", actnum, value, a->getAnimVar(value));
+ debugPrintf("Actor[%d].animVar[%d] = %d\n", actnum, value, a->getAnimVar(value));
} else if (!strcmp(argv[2], "anim")) {
a->animateActor(value);
- DebugPrintf("Actor[%d].animateActor(%d)\n", actnum, value);
+ debugPrintf("Actor[%d].animateActor(%d)\n", actnum, value);
} else if (!strcmp(argv[2], "ignoreboxes")) {
a->_ignoreBoxes = (value > 0);
- DebugPrintf("Actor[%d].ignoreBoxes = %d\n", actnum, a->_ignoreBoxes);
+ debugPrintf("Actor[%d].ignoreBoxes = %d\n", actnum, a->_ignoreBoxes);
} else if (!strcmp(argv[2], "x")) {
a->putActor(value, a->getRealPos().y);
- DebugPrintf("Actor[%d].x = %d\n", actnum, a->getRealPos().x);
+ debugPrintf("Actor[%d].x = %d\n", actnum, a->getRealPos().x);
_vm->_fullRedraw = true;
} else if (!strcmp(argv[2], "y")) {
a->putActor(a->getRealPos().x, value);
- DebugPrintf("Actor[%d].y = %d\n", actnum, a->getRealPos().y);
+ debugPrintf("Actor[%d].y = %d\n", actnum, a->getRealPos().y);
_vm->_fullRedraw = true;
} else if (!strcmp(argv[2], "_elevation")) {
a->setElevation(value);
- DebugPrintf("Actor[%d]._elevation = %d\n", actnum, a->getElevation());
+ debugPrintf("Actor[%d]._elevation = %d\n", actnum, a->getElevation());
_vm->_fullRedraw = true;
} else if (!strcmp(argv[2], "costume")) {
if (value >= (int)_vm->_res->_types[rtCostume].size())
- DebugPrintf("Costume not changed as %d exceeds max of %d\n", value, _vm->_res->_types[rtCostume].size());
+ debugPrintf("Costume not changed as %d exceeds max of %d\n", value, _vm->_res->_types[rtCostume].size());
else {
a->setActorCostume(value);
_vm->_fullRedraw = true;
- DebugPrintf("Actor[%d].costume = %d\n", actnum, a->_costume);
+ 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) {
a->_heCondMask = value;
}
- DebugPrintf("Actor[%d]._heCondMask = 0x%X\n", actnum, a->_heCondMask);
+ debugPrintf("Actor[%d]._heCondMask = 0x%X\n", actnum, a->_heCondMask);
} else {
- DebugPrintf("Unknown actor command '%s'\nUse <ignoreboxes |costume> as command\n", argv[2]);
+ debugPrintf("Unknown actor command '%s'\nUse <ignoreboxes |costume> as command\n", argv[2]);
}
return true;
@@ -400,40 +411,40 @@ bool ScummDebugger::Cmd_PrintActor(int argc, const char **argv) {
int i;
Actor *a;
- DebugPrintf("+---------------------------------------------------------------+\n");
- DebugPrintf("|# | x | y | w | h |elev|cos|box|mov| zp|frm|scl|dir| cls |\n");
- DebugPrintf("+--+----+----+---+---+----+---+---+---+---+---+---+---+---------+\n");
+ debugPrintf("+---------------------------------------------------------------+\n");
+ debugPrintf("|# | x | y | w | h |elev|cos|box|mov| zp|frm|scl|dir| cls |\n");
+ debugPrintf("+--+----+----+---+---+----+---+---+---+---+---+---+---+---------+\n");
for (i = 1; i < _vm->_numActors; i++) {
a = _vm->_actors[i];
if (a->_visible)
- DebugPrintf("|%2d|%4d|%4d|%3d|%3d|%4d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|$%08x|\n",
+ debugPrintf("|%2d|%4d|%4d|%3d|%3d|%4d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|$%08x|\n",
a->_number, a->getRealPos().x, a->getRealPos().y, a->_width, a->_bottom - a->_top,
a->getElevation(),
a->_costume, a->_walkbox, a->_moving, a->_forceClip, a->_frame,
a->_scalex, a->getFacing(), _vm->_classData[a->_number]);
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
bool ScummDebugger::Cmd_PrintObjects(int argc, const char **argv) {
int i;
ObjectData *o;
- DebugPrintf("Objects in current room\n");
- DebugPrintf("+---------------------------------+------------+\n");
- DebugPrintf("|num | x | y |width|height|state|fl| cls |\n");
- DebugPrintf("+----+----+----+-----+------+-----+--+---------+\n");
+ debugPrintf("Objects in current room\n");
+ debugPrintf("+---------------------------------+------------+\n");
+ debugPrintf("|num | x | y |width|height|state|fl| cls |\n");
+ debugPrintf("+----+----+----+-----+------+-----+--+---------+\n");
for (i = 1; i < _vm->_numLocalObjects; i++) {
o = &(_vm->_objs[i]);
if (o->obj_nr == 0)
continue;
int classData = (_vm->_game.version != 0 ? _vm->_classData[o->obj_nr] : 0);
- DebugPrintf("|%4d|%4d|%4d|%5d|%6d|%5d|%2d|$%08x|\n",
+ debugPrintf("|%4d|%4d|%4d|%5d|%6d|%5d|%2d|$%08x|\n",
o->obj_nr, o->x_pos, o->y_pos, o->width, o->height, o->state,
o->fl_object_index, classData);
}
- DebugPrintf("\n");
+ debugPrintf("\n");
return true;
}
@@ -443,13 +454,13 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) {
int obj;
if (argc < 3) {
- DebugPrintf("Syntax: object <objectnum> <command> <parameter>\n");
+ debugPrintf("Syntax: object <objectnum> <command> <parameter>\n");
return true;
}
obj = atoi(argv[1]);
if (_vm->_game.version != 0 && obj >= _vm->_numGlobalObjects) {
- DebugPrintf("Object %d is out of range (range: 1 - %d)\n", obj, _vm->_numGlobalObjects);
+ debugPrintf("Object %d is out of range (range: 1 - %d)\n", obj, _vm->_numGlobalObjects);
return true;
}
@@ -479,12 +490,12 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) {
//is BgNeedsRedraw enough?
_vm->_bgNeedsRedraw = true;
} else {
- DebugPrintf("State of object %d: %d\n", obj, _vm->getState(obj));
+ debugPrintf("State of object %d: %d\n", obj, _vm->getState(obj));
}
} else if (!strcmp(argv[2], "name")) {
- DebugPrintf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj));
+ debugPrintf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj));
} else {
- DebugPrintf("Unknown object command '%s'\nUse <pickup | state | name> as command\n", argv[2]);
+ debugPrintf("Unknown object command '%s'\nUse <pickup | state | name> as command\n", argv[2]);
}
return true;
@@ -495,9 +506,9 @@ bool ScummDebugger::Cmd_Debug(int argc, const char **argv) {
// No parameters given: Print out a list of all channels and their status
if (argc <= 1) {
- DebugPrintf("Available debug channels:\n");
+ debugPrintf("Available debug channels:\n");
for (Common::DebugManager::DebugChannelList::const_iterator i = lvls.begin(); i != lvls.end(); ++i) {
- DebugPrintf("%c%s - %s (%s)\n", i->enabled ? '+' : ' ',
+ debugPrintf("%c%s - %s (%s)\n", i->enabled ? '+' : ' ',
i->name.c_str(), i->description.c_str(),
i->enabled ? "enabled" : "disabled");
}
@@ -513,39 +524,18 @@ bool ScummDebugger::Cmd_Debug(int argc, const char **argv) {
}
if (result) {
- DebugPrintf("%s %s\n", (argv[1][0] == '+') ? "Enabled" : "Disabled", argv[1] + 1);
+ debugPrintf("%s %s\n", (argv[1][0] == '+') ? "Enabled" : "Disabled", argv[1] + 1);
} else {
- DebugPrintf("Usage: debug [+CHANNEL|-CHANNEL]\n");
- DebugPrintf("Enables or disables the given debug channel.\n");
- DebugPrintf("When used without parameters, lists all available debug channels and their status.\n");
- }
-
- return true;
-}
-
-bool ScummDebugger::Cmd_DebugLevel(int argc, const char **argv) {
- if (argc == 1) {
- if (_vm->_debugMode == false)
- DebugPrintf("Debugging is not enabled at this time\n");
- else
- DebugPrintf("Debugging is currently set at level %d\n", gDebugLevel);
- } else { // set level
- gDebugLevel = atoi(argv[1]);
- if (gDebugLevel >= 0) {
- _vm->_debugMode = true;
- DebugPrintf("Debug level set to level %d\n", gDebugLevel);
- } else if (gDebugLevel < 0) {
- _vm->_debugMode = false;
- DebugPrintf("Debugging is now disabled\n");
- } else
- DebugPrintf("Not a valid debug level\n");
+ debugPrintf("Usage: debug [+CHANNEL|-CHANNEL]\n");
+ debugPrintf("Enables or disables the given debug channel.\n");
+ debugPrintf("When used without parameters, lists all available debug channels and their status.\n");
}
return true;
}
bool ScummDebugger::Cmd_Camera(int argc, const char **argv) {
- DebugPrintf("Camera: cur (%d,%d) - dest (%d,%d) - accel (%d,%d) -- last (%d,%d)\n",
+ debugPrintf("Camera: cur (%d,%d) - dest (%d,%d) - accel (%d,%d) -- last (%d,%d)\n",
_vm->camera._cur.x, _vm->camera._cur.y, _vm->camera._dest.x, _vm->camera._dest.y,
_vm->camera._accel.x, _vm->camera._accel.y, _vm->camera._last.x, _vm->camera._last.y);
@@ -560,7 +550,7 @@ bool ScummDebugger::Cmd_PrintBox(int argc, const char **argv) {
printBox(atoi(argv[i]));
} else {
num = _vm->getNumBoxes();
- DebugPrintf("\nWalk boxes:\n");
+ debugPrintf("\nWalk boxes:\n");
for (i = 0; i < num; i++)
printBox(i);
}
@@ -572,29 +562,29 @@ bool ScummDebugger::Cmd_PrintBoxMatrix(int argc, const char **argv) {
int num = _vm->getNumBoxes();
int i, j;
- DebugPrintf("Walk matrix:\n");
+ debugPrintf("Walk matrix:\n");
if (_vm->_game.version <= 2)
boxm += num;
for (i = 0; i < num; i++) {
- DebugPrintf("%d: ", i);
+ debugPrintf("%d: ", i);
if (_vm->_game.version <= 2) {
for (j = 0; j < num; j++)
- DebugPrintf("[%d] ", *boxm++);
+ debugPrintf("[%d] ", *boxm++);
} else {
while (*boxm != 0xFF) {
- DebugPrintf("[%d-%d=>%d] ", boxm[0], boxm[1], boxm[2]);
+ debugPrintf("[%d-%d=>%d] ", boxm[0], boxm[1], boxm[2]);
boxm += 3;
}
boxm++;
}
- DebugPrintf("\n");
+ debugPrintf("\n");
}
return true;
}
void ScummDebugger::printBox(int box) {
if (box < 0 || box >= _vm->getNumBoxes()) {
- DebugPrintf("%d is not a valid box!\n", box);
+ debugPrintf("%d is not a valid box!\n", box);
return;
}
BoxCoords coords;
@@ -605,7 +595,7 @@ void ScummDebugger::printBox(int box) {
coords = _vm->getBoxCoordinates(box);
// Print out coords, flags, zbuffer mask
- DebugPrintf("%d: [%d x %d] [%d x %d] [%d x %d] [%d x %d], flags=0x%02x, mask=%d, scale=%d\n",
+ debugPrintf("%d: [%d x %d] [%d x %d] [%d x %d] [%d x %d], flags=0x%02x, mask=%d, scale=%d\n",
box,
coords.ul.x, coords.ul.y, coords.ll.x, coords.ll.y,
coords.ur.x, coords.ur.y, coords.lr.x, coords.lr.y,
@@ -746,7 +736,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
int i, base, draft;
if (_vm->_game.id != GID_LOOM) {
- DebugPrintf("Command only works with Loom/LoomCD\n");
+ debugPrintf("Command only works with Loom/LoomCD\n");
return true;
}
@@ -797,7 +787,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
// the distaff, but I don't know if that's a safe
// thing to do.
- DebugPrintf("Learned all drafts and notes.\n");
+ debugPrintf("Learned all drafts and notes.\n");
return true;
}
}
@@ -806,7 +796,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
for (i = 0; i < 16; i++) {
draft = _vm->_scummVars[base + i * 2];
- DebugPrintf("%d %-13s %c%c%c%c %c%c\n",
+ debugPrintf("%d %-13s %c%c%c%c %c%c\n",
base + 2 * i,
names[i],
notes[draft & 0x0007],
@@ -830,7 +820,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) {
_vm->runScript(61, 0, 0, args);
if (_vm->_bootParam != _vm->_scummVars[411]){
- DebugPrintf("Invalid Passcode\n");
+ debugPrintf("Invalid Passcode\n");
return true;
}
@@ -838,7 +828,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) {
detach();
} else {
- DebugPrintf("Current Passcode is %d \nUse 'passcode <SEGA CD Passcode>'\n",_vm->_scummVars[411]);
+ debugPrintf("Current Passcode is %d \nUse 'passcode <SEGA CD Passcode>'\n",_vm->_scummVars[411]);
return true;
}
return false;
diff --git a/engines/scumm/debugger.h b/engines/scumm/debugger.h
index 43bf9d6fd4..657f6be286 100644
--- a/engines/scumm/debugger.h
+++ b/engines/scumm/debugger.h
@@ -37,6 +37,9 @@ public:
private:
ScummEngine *_vm;
+ virtual void preEnter();
+ virtual void postEnter();
+
// Commands
bool Cmd_Room(int argc, const char **argv);
bool Cmd_LoadGame(int argc, const char **argv);
@@ -58,7 +61,6 @@ private:
bool Cmd_Passcode(int argc, const char **argv);
bool Cmd_Debug(int argc, const char **argv);
- bool Cmd_DebugLevel(int argc, const char **argv);
bool Cmd_Show(int argc, const char **argv);
bool Cmd_Hide(int argc, const char **argv);
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index b7a25808a5..a7922b232e 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -79,10 +79,12 @@ Common::String ScummEngine::generateFilename(const int room) const {
} else {
switch (_filenamePattern.genMethod) {
case kGenDiskNum:
+ case kGenDiskNumSteam:
result = Common::String::format(_filenamePattern.pattern, diskNumber);
break;
case kGenRoomNum:
+ case kGenRoomNumSteam:
result = Common::String::format(_filenamePattern.pattern, room);
break;
@@ -209,7 +211,32 @@ Common::String ScummEngine_v70he::generateFilename(const int room) const {
return result;
}
-static Common::String generateFilenameForDetection(const char *pattern, FilenameGenMethod genMethod) {
+// The following table includes all the index files, which are embedded in the
+// main game executables in Steam versions.
+static const SteamIndexFile steamIndexFiles[] = {
+ { GID_INDY3, Common::kPlatformWindows, "%02d.LFL", "00.LFL", "Indiana Jones and the Last Crusade.exe", 162056, 6295 },
+ { GID_INDY3, Common::kPlatformMacintosh, "%02d.LFL", "00.LFL", "The Last Crusade", 150368, 6295 },
+ { GID_INDY4, Common::kPlatformWindows, "atlantis.%03d", "ATLANTIS.000", "Indiana Jones and the Fate of Atlantis.exe", 224336, 12035 },
+ { GID_INDY4, Common::kPlatformMacintosh, "atlantis.%03d", "ATLANTIS.000", "The Fate of Atlantis", 260224, 12035 },
+ { GID_LOOM, Common::kPlatformWindows, "%03d.LFL", "000.LFL", "Loom.exe", 187248, 8307 },
+ { GID_LOOM, Common::kPlatformMacintosh, "%03d.LFL", "000.LFL", "Loom", 170464, 8307 },
+#ifdef ENABLE_SCUMM_7_8
+ { GID_DIG, Common::kPlatformWindows, "dig.la%d", "DIG.LA0", "The Dig.exe", 340632, 16304 },
+ { GID_DIG, Common::kPlatformMacintosh, "dig.la%d", "DIG.LA0", "The Dig", 339744, 16304 },
+#endif
+ { 0, Common::kPlatformUnknown, nullptr, nullptr, nullptr, 0, 0 }
+};
+
+const SteamIndexFile *lookUpSteamIndexFile(Common::String pattern, Common::Platform platform) {
+ for (const SteamIndexFile *indexFile = steamIndexFiles; indexFile->len; ++indexFile) {
+ if (platform == indexFile->platform && pattern.equalsIgnoreCase(indexFile->pattern))
+ return indexFile;
+ }
+
+ return nullptr;
+}
+
+static Common::String generateFilenameForDetection(const char *pattern, FilenameGenMethod genMethod, Common::Platform platform) {
Common::String result;
switch (genMethod) {
@@ -217,6 +244,16 @@ static Common::String generateFilenameForDetection(const char *pattern, Filename
case kGenRoomNum:
result = Common::String::format(pattern, 0);
break;
+
+ case kGenDiskNumSteam:
+ case kGenRoomNumSteam: {
+ const SteamIndexFile *indexFile = lookUpSteamIndexFile(pattern, platform);
+ if (!indexFile) {
+ error("Unable to find Steam executable from detection pattern");
+ } else {
+ result = indexFile->executableName;
+ }
+ } break;
case kGenHEPC:
case kGenHEIOS:
@@ -467,12 +504,6 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF
dr.extra = "V1 Demo";
}
- // HACK: If 'Demo' occurs in the extra string, set the GF_DEMO flag,
- // required by some game demos (e.g. Dig, FT and COMI).
- if (dr.extra && strstr(dr.extra, "Demo")) {
- dr.game.features |= GF_DEMO;
- }
-
// HACK: Try to detect languages for translated games
if (dr.language == UNK_LANG) {
dr.language = detectLanguage(fslist, dr.game.id);
@@ -528,7 +559,8 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul
DetectorResult dr;
// Dive one level down since mac indy3/loom has its files split into directories. See Bug #1438631
- composeFileHashMap(fileMD5Map, fslist, 2, directoryGlobs);
+ // Dive two levels down for Mac Steam games
+ composeFileHashMap(fileMD5Map, fslist, 3, directoryGlobs);
// Iterate over all filename patterns.
for (const GameFilenamePattern *gfp = gameFilenamesTable; gfp->gameid; ++gfp) {
@@ -540,7 +572,7 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul
// Generate the detectname corresponding to the gfp. If the file doesn't
// exist in the directory we are looking at, we can skip to the next
// one immediately.
- Common::String file(generateFilenameForDetection(gfp->pattern, gfp->genMethod));
+ Common::String file(generateFilenameForDetection(gfp->pattern, gfp->genMethod, gfp->platform));
if (!fileMD5Map.contains(file))
continue;
@@ -1025,7 +1057,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
Common::FSNode dir(ConfMan.get("path"));
if (!dir.isDirectory())
return Common::kPathNotDirectory;
- if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly))
+ if (!dir.getChildren(fslist, Common::FSNode::kListAll))
return Common::kNoGameDataFoundError;
// Invoke the detector, but fixed to the specified gameid.
@@ -1081,7 +1113,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
md5Warning += Common::String::format(" SCUMM gameid '%s', file '%s', MD5 '%s'\n\n",
res.game.gameid,
- generateFilenameForDetection(res.fp.pattern, res.fp.genMethod).c_str(),
+ generateFilenameForDetection(res.fp.pattern, res.fp.genMethod, Common::kPlatformUnknown).c_str(),
res.md5.c_str());
g_system->logMessage(LogMessageType::kWarning, md5Warning.c_str());
diff --git a/engines/scumm/detection.h b/engines/scumm/detection.h
index f714812a9c..0587c3fab1 100644
--- a/engines/scumm/detection.h
+++ b/engines/scumm/detection.h
@@ -95,7 +95,9 @@ struct GameSettings {
enum FilenameGenMethod {
kGenDiskNum,
+ kGenDiskNumSteam,
kGenRoomNum,
+ kGenRoomNumSteam,
kGenHEMac,
kGenHEMacNoParens,
kGenHEPC,
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index c876af1256..791963e237 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -52,6 +52,8 @@ namespace Scumm {
*/
static const char *const directoryGlobs[] = {
"rooms *", // Mac version of indy3/loom
+ "Contents", // Mac Steam versions
+ "MacOS", // Mac Steam versions
0
};
@@ -221,6 +223,7 @@ static const GameSettings gameVariantsTable[] = {
{"indy3", "EGA", "ega", GID_INDY3, 3, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, 0, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"indy3", "No AdLib", "ega", GID_INDY3, 3, 0, MDT_PCSPK | MDT_PCJR, 0, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformDOS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
+ {"indy3", "Steam", "steam", GID_INDY3, 3, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO4(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_MIDITOWNS, GUIO_NOASPECT)},
{"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO1(GUIO_NOSPEECH)},
@@ -230,6 +233,7 @@ static const GameSettings gameVariantsTable[] = {
#endif
{"loom", "FM-TOWNS", 0, GID_LOOM, 3, 0, MDT_TOWNS, GF_AUDIOTRACKS | GF_OLD256, Common::kPlatformFMTowns, GUIO4(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_MIDITOWNS, GUIO_NOASPECT)},
{"loom", "VGA", "vga", GID_LOOM, 4, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformDOS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
+ {"loom", "Steam", "steam", GID_LOOM, 4, 0, MDT_NONE, GF_AUDIOTRACKS, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, GF_16COLOR, Common::kPlatformDOS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
@@ -245,6 +249,7 @@ static const GameSettings gameVariantsTable[] = {
{"monkey2", "FM-TOWNS", 0, GID_MONKEY2, 5, 0, MDT_PCSPK | MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO5(GUIO_NOSPEECH, GUIO_MIDITOWNS, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_NOASPECT)},
{"atlantis", "", 0, GID_INDY4, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()},
+ {"atlantis", "Steam", "steam", GID_INDY4, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()},
{"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO1(GUIO_NOSPEECH)},
{"atlantis", "FM-TOWNS", 0, GID_INDY4, 5, 0, MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO4(GUIO_MIDITOWNS, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_NOASPECT)},
@@ -255,12 +260,16 @@ static const GameSettings gameVariantsTable[] = {
{"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO1(GUIO_NOSPEECH)},
#ifdef ENABLE_SCUMM_7_8
- {"ft", 0, 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
+ {"ft", "", 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
+ {"ft", "Demo", 0, GID_FT, 7, 0, MDT_NONE, GF_DEMO, UNK, GUIO1(GUIO_NOMIDI)},
- {"dig", 0, 0, GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
+ {"dig", "", 0, GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
+ {"dig", "Demo", 0, GID_DIG, 7, 0, MDT_NONE, GF_DEMO, UNK, GUIO1(GUIO_NOMIDI)},
+ {"dig", "Steam", "steam", GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
- {"comi", 0, 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
-#endif
+ {"comi", "", 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"comi", "Demo", 0, GID_CMI, 8, 0, MDT_NONE, GF_DEMO, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
+ #endif
// Humongous Entertainment Scumm Version 6
{"activity", "", 0, GID_HEGAME, 6, 62, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO1(GUIO_NOLAUNCHLOAD)},
@@ -383,7 +392,7 @@ static const GameSettings gameVariantsTable[] = {
{"freddicove", "HE 100", 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
// Restructured the Scumm engine
- {"pjgames", 0, 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"pjgames", 0, 0, GID_PJGAMES, 6, 100, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
// Added the use of bink videos
{"Soccer2004", 0, 0, GID_SOCCER2004, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)},
@@ -422,10 +431,10 @@ static const GameSettings gameVariantsTable[] = {
using Common::UNK_LANG;
// The following describes how Fingolfin thinks this table might be used one day;
-// this is work in progress, so read this with a salt of grain...
+// this is work in progress, so read this with a grain of salt...
//
// The following table maps gameids to possible filename variants for that game.
-// This information is used by the detector to determin possible "detect files".
+// This information is used by the detector to determine possible "detect files".
// It is also later used by the engine creation code to verify the game to be
// launched is present. Finally, the correct GameFilenamePattern entry is passed on
// to the engine which uses it to locate the files for the game.
@@ -451,6 +460,8 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "zak", "zak1.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, "V1" }, // ... and zak2.d64
{ "indy3", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
+ { "indy3", "%02d.LFL", kGenRoomNumSteam, UNK_LANG, Common::kPlatformWindows, "Steam" },
+ { "indy3", "%02d.LFL", kGenRoomNumSteam, UNK_LANG, Common::kPlatformMacintosh, "Steam" },
{ "indyloom", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
{ "indyzak", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
@@ -458,6 +469,8 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "loom", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
{ "loom", "%03d.LFL", kGenRoomNum, UNK_LANG, UNK, "VGA" }, // Loom CD
+ { "loom", "%03d.LFL", kGenRoomNumSteam, UNK_LANG, Common::kPlatformWindows, "Steam" },
+ { "loom", "%03d.LFL", kGenRoomNumSteam, UNK_LANG, Common::kPlatformMacintosh, "Steam" },
{ "pass", "%03d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
@@ -471,6 +484,8 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "monkey2", "mi2demo.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
{ "atlantis", "atlantis.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "atlantis", "atlantis.%03d", kGenDiskNumSteam, UNK_LANG, Common::kPlatformWindows, "Steam" },
+ { "atlantis", "atlantis.%03d", kGenDiskNumSteam, UNK_LANG, Common::kPlatformMacintosh, "Steam" },
{ "atlantis", "fate.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
{ "atlantis", "playfate.%03d", kGenDiskNum, UNK_LANG, UNK, 0 },
{ "atlantis", "indy4.%03d", kGenDiskNum, Common::JA_JPN, Common::kPlatformFMTowns, "FM-TOWNS" },
@@ -494,6 +509,8 @@ static const GameFilenamePattern gameFilenamesTable[] = {
#ifdef ENABLE_SCUMM_7_8
{ "dig", "dig.la%d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "dig", "dig.la%d", kGenDiskNumSteam, UNK_LANG, Common::kPlatformWindows, "Steam" },
+ { "dig", "dig.la%d", kGenDiskNumSteam, UNK_LANG, Common::kPlatformMacintosh, "Steam" },
{ "dig", "thedig.la%d", kGenDiskNum, UNK_LANG, UNK, "Demo" }, // Used by an alternate version of the demo
{ "dig", "The Dig Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "dig", "The Dig Demo Data", kGenUnchanged, UNK_LANG, Common::kPlatformMacintosh, "Demo" },
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 8321daa583..52120949cc 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -428,7 +428,9 @@ const Common::String InfoDialog::queryResString(int stringno) {
if (stringno == 0)
return String();
- if (_vm->_game.version == 8)
+ if (_vm->_game.heversion >= 80)
+ return _(string_map_table_v6[stringno - 1].string);
+ else if (_vm->_game.version == 8)
result = (const byte *)string_map_table_v8[stringno - 1].string;
else if (_vm->_game.version == 7)
result = _vm->getStringAddressVar(string_map_table_v7[stringno - 1].num);
diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp
index 9c161ff1cc..475ffa3238 100644
--- a/engines/scumm/file.cpp
+++ b/engines/scumm/file.cpp
@@ -185,6 +185,30 @@ uint32 ScummFile::read(void *dataPtr, uint32 dataSize) {
}
#pragma mark -
+#pragma mark --- ScummSteamFile ---
+#pragma mark -
+
+bool ScummSteamFile::open(const Common::String &filename) {
+ if (filename.equalsIgnoreCase(_indexFile.indexFileName)) {
+ return openWithSubRange(_indexFile.executableName, _indexFile.start, _indexFile.len);
+ } else {
+ // Regular non-bundled file
+ return ScummFile::open(filename);
+ }
+}
+
+bool ScummSteamFile::openWithSubRange(const Common::String &filename, int32 subFileStart, int32 subFileLen) {
+ if (ScummFile::open(filename)) {
+ _subFileStart = subFileStart;
+ _subFileLen = subFileLen;
+ seek(0, SEEK_SET);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#pragma mark -
#pragma mark --- ScummDiskImage ---
#pragma mark -
diff --git a/engines/scumm/file.h b/engines/scumm/file.h
index d6dbc06ddc..e7c1eb6d71 100644
--- a/engines/scumm/file.h
+++ b/engines/scumm/file.h
@@ -53,7 +53,7 @@ public:
};
class ScummFile : public BaseScummFile {
-private:
+protected:
int32 _subFileStart;
int32 _subFileLen;
bool _myEos; // Have we read past the end of the subfile?
@@ -64,7 +64,7 @@ private:
public:
ScummFile();
- bool open(const Common::String &filename);
+ virtual bool open(const Common::String &filename);
bool openSubFile(const Common::String &filename);
void clearErr() { _myEos = false; BaseScummFile::clearErr(); }
@@ -120,6 +120,29 @@ public:
uint32 read(void *dataPtr, uint32 dataSize);
};
+struct SteamIndexFile {
+ byte id;
+ Common::Platform platform;
+ const char *pattern;
+ const char *indexFileName;
+ const char *executableName;
+ int32 start;
+ int32 len;
+};
+
+const SteamIndexFile *lookUpSteamIndexFile(Common::String pattern, Common::Platform platform);
+
+class ScummSteamFile : public ScummFile {
+private:
+ const SteamIndexFile &_indexFile;
+
+ bool openWithSubRange(const Common::String &filename, int32 subFileStart, int32 subFileLen);
+public:
+ ScummSteamFile(const SteamIndexFile &indexFile) : ScummFile(), _indexFile(indexFile) {}
+
+ bool open(const Common::String &filename);
+};
+
} // End of namespace Scumm
#endif
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
index 218f2ec59c..245a986531 100644
--- a/engines/scumm/he/sprite_he.cpp
+++ b/engines/scumm/he/sprite_he.cpp
@@ -264,6 +264,13 @@ int Sprite::getSpriteFlagRemapPalette(int spriteId) {
int Sprite::getSpriteFlagAutoAnim(int spriteId) {
assertRange(1, spriteId, _varNumSprites, "sprite");
+ // WORKAROUND: Two scripts (room 2 script 2070/2071) compare against
+ // a return value of one, but the original game returned the flag value
+ // (0x200000) for true. These scripts bugs caused problems (infinite loop
+ // and beans not appearing) in the Jumping Beans mini games under ScummVM.
+ if (_vm->_game.id == GID_PJGAMES)
+ return 0;
+
return ((_spriteTable[spriteId].flags & kSFAutoAnim) != 0) ? 1 : 0;
}
@@ -793,6 +800,11 @@ void Sprite::resetSprite(int spriteId) {
_spriteTable[spriteId].field_84 = 0;
_spriteTable[spriteId].imgFlags = 0;
_spriteTable[spriteId].field_90 = 0;
+
+ if (_vm->_game.heversion >= 100) {
+ _spriteTable[spriteId].flags &= ~kSFMarkDirty;
+ _spriteTable[spriteId].flags |= kSFAutoAnim | kSFBlitDirectly;
+ }
}
void Sprite::setSpriteImage(int spriteId, int imageNum) {
@@ -820,6 +832,8 @@ void Sprite::setSpriteImage(int spriteId, int imageNum) {
} else {
if (_vm->VAR(139))
_spriteTable[spriteId].flags &= ~kSFActive;
+ else if (_vm->_game.heversion >= 100 && origResId == 0)
+ _spriteTable[spriteId].flags = 0;
else if (_spriteTable[spriteId].flags & kSFImageless)
_spriteTable[spriteId].flags = 0;
else
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 5e2566dc32..824dfec144 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -435,8 +435,9 @@ void ScummEngine_v6::processKeyboard(Common::KeyState lastKeyHit) {
break;
}
- if (VAR_VOICE_MODE != 0xFF)
- VAR(VAR_VOICE_MODE) = _voiceMode;
+ // We need to sync the current sound settings here to make sure that
+ // we actually update the mute state of speech properly.
+ syncSoundSettings();
return;
}
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index d43db1e5f1..416a8f7ef9 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
bomp.o \
boxes.o \
camera.o \
+ cdda.o \
charset.o \
charset-fontdata.o \
costume.o \
diff --git a/engines/scumm/music.h b/engines/scumm/music.h
index c5762ed24a..e170647560 100644
--- a/engines/scumm/music.h
+++ b/engines/scumm/music.h
@@ -24,10 +24,11 @@
#define SCUMM_MUSIC_H
#include "common/scummsys.h"
-#include "engines/scumm/saveload.h"
namespace Scumm {
+class Serializer;
+
/**
* Pure virtual base class for the various music/sound engines used in Scumm
* games. In particular, the iMuse code provides a subclass of this. There are
diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp
index 1d5761ef48..d8672c473c 100644
--- a/engines/scumm/nut_renderer.cpp
+++ b/engines/scumm/nut_renderer.cpp
@@ -395,10 +395,6 @@ void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byt
}
void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color) {
- // FIXME: This gets passed a const destination Surface. Intuitively this
- // should never get written to. But sadly it does... For now we simply
- // cast the const qualifier away.
- byte *dst = (byte *)const_cast<void *>(s.getBasePtr(x, y));
const int width = _vm->_2byteWidth;
const int height = MIN(_vm->_2byteHeight, s.h - y);
const byte *src = _vm->get2byteCharPtr(c);
@@ -408,17 +404,50 @@ void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byt
return;
}
- for (int ty = 0; ty < height; ty++) {
- for (int tx = 0; tx < width; tx++) {
- if ((tx & 7) == 0)
- bits = *src++;
- if (x + tx < 0 || x + tx >= s.w || y + ty < 0)
- continue;
- if (bits & revBitMask(tx % 8)) {
- dst[tx] = color;
+ enum ShadowMode {
+ kNone,
+ kKoreanV8ShadowMode
+ };
+
+ ShadowMode shadowMode = kNone;
+
+ if (_vm->_language == Common::KO_KOR && _vm->_game.version == 8) {
+ shadowMode = kKoreanV8ShadowMode;
+ }
+
+ int shadowOffsetXTable[4] = {-1, 0, 1, 0};
+ int shadowOffsetYTable[4] = {0, 1, 0, 0};
+ int shadowOffsetColorTable[4] = {0, 0, 0, color};
+
+ int shadowIdx = 3;
+ if (shadowMode == kKoreanV8ShadowMode)
+ shadowIdx = 0;
+
+ const byte *origSrc = src;
+
+ for (; shadowIdx < 4; shadowIdx++) {
+ int offX = x + shadowOffsetXTable[shadowIdx];
+ int offY = y + shadowOffsetYTable[shadowIdx];
+ byte drawColor = shadowOffsetColorTable[shadowIdx];
+
+ // FIXME: This gets passed a const destination Surface. Intuitively this
+ // should never get written to. But sadly it does... For now we simply
+ // cast the const qualifier away.
+ byte *dst = (byte *)const_cast<void *>(s.getBasePtr(offX, offY));
+ src = origSrc;
+
+ for (int ty = 0; ty < height; ty++) {
+ for (int tx = 0; tx < width; tx++) {
+ if ((tx & 7) == 0)
+ bits = *src++;
+ if (offX + tx < 0 || offX + tx >= s.w || offY + ty < 0)
+ continue;
+ if (bits & revBitMask(tx % 8)) {
+ dst[tx] = drawColor;
+ }
}
+ dst += s.pitch;
}
- dst += s.pitch;
}
}
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index 7919075d0b..db836467ef 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -1013,7 +1013,6 @@ void ScummEngine::resetRoomObject(ObjectData *od, const byte *room, const byte *
od->actordir = (byte)READ_LE_UINT16(&imhd->v7.actordir);
} else if (_game.version == 6) {
- assert(imhd);
od->obj_nr = READ_LE_UINT16(&(cdhd->v6.obj_id));
od->width = READ_LE_UINT16(&cdhd->v6.w);
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 7b525116cf..adcda68e10 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -24,6 +24,7 @@
#include "scumm/imuse/imuse.h"
#include "scumm/scumm.h"
#include "scumm/resource.h"
+#include "scumm/saveload.h"
#include "audio/fmopl.h"
@@ -62,9 +63,21 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
_sfxTimer = 4;
_rndSeed = 1;
- memset(_channels, 0, sizeof(_channels));
- memset(_sfxResource, 0, sizeof(_sfxResource));
- memset(_sfxPriority, 0, sizeof(_sfxPriority));
+ memset(_sfx, 0, sizeof(_sfx));
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ _sfx[i].resource = -1;
+ for (int j = 0; j < ARRAYSIZE(_sfx[i].channels); ++j) {
+ _sfx[i].channels[j].hardwareChannel = -1;
+ }
+ }
+
+ memset(_hwChannels, 0, sizeof(_hwChannels));
+ _numHWChannels = ARRAYSIZE(_hwChannels);
+
+ memset(_voiceChannels, 0, sizeof(_voiceChannels));
+
+ _musicVolume = _sfxVolume = 255;
+ _isSeeking = false;
}
Player_AD::~Player_AD() {
@@ -86,79 +99,69 @@ void Player_AD::setMusicVolume(int vol) {
void Player_AD::startSound(int sound) {
Common::StackLock lock(_mutex);
+ // Setup the sound volume
+ setupVolume();
+
// Query the sound resource
const byte *res = _vm->getResourceAddress(rtSound, sound);
if (res[2] == 0x80) {
// Stop the current sounds
- stopAllSounds();
+ stopMusic();
// Lock the new music resource
_soundPlaying = sound;
_vm->_res->lock(rtSound, _soundPlaying);
// Start the new music resource
- _resource = res;
+ _musicData = res;
startMusic();
} else {
- // Only try to start a sfx when no music is playing.
- if (_soundPlaying == -1) {
- const byte priority = res[0];
- const byte channel = res[1];
-
- // Check for out of bounds access
- if (channel >= 3) {
- warning("AdLib sfx resource %d uses channel %d", sound, channel);
- return;
- }
-
- // Check whether the channel is free or the priority of the new
- // sfx resource is above the old one.
- if (_channels[channel * 3 + 0].state
- || _channels[channel * 3 + 1].state
- || _channels[channel * 3 + 2].state) {
- if (_sfxPriority[channel] > priority) {
- return;
- }
- }
+ const byte priority = res[0];
+ // The original specified the channel to use in the sound
+ // resource. However, since we play as much as possible we sill
+ // ignore it and simply use the priority value to determine
+ // whether the sfx can be played or not.
+ //const byte channel = res[1];
+
+ // Try to allocate a sfx slot for playback.
+ SfxSlot *sfx = allocateSfxSlot(priority);
+ if (!sfx) {
+ ::debugC(3, DEBUG_SOUND, "AdLib: No free sfx slot for sound %d", sound);
+ return;
+ }
+ // Try to start sfx playback
+ sfx->resource = sound;
+ sfx->priority = priority;
+ if (startSfx(sfx, res)) {
// Lock the new resource
- _sfxResource[channel] = sound;
- _sfxPriority[channel] = priority;
_vm->_res->lock(rtSound, sound);
+ } else {
+ // When starting the sfx failed we need to reset the slot.
+ sfx->resource = -1;
- // Start the actual sfx resource
- _resource = res;
- startSfx();
+ for (int i = 0; i < ARRAYSIZE(sfx->channels); ++i) {
+ sfx->channels[i].state = kChannelStateOff;
+
+ if (sfx->channels[i].hardwareChannel != -1) {
+ freeHWChannel(sfx->channels[i].hardwareChannel);
+ sfx->channels[i].hardwareChannel = -1;
+ }
+ }
}
}
-
- // Setup the sound volume
- setupVolume();
}
void Player_AD::stopSound(int sound) {
Common::StackLock lock(_mutex);
if (sound == _soundPlaying) {
- stopAllSounds();
+ stopMusic();
} else {
- for (int i = 0; i < 3; ++i) {
- if (_sfxResource[i] == sound) {
- if (_channels[i * 3 + 0].state
- || _channels[i * 3 + 1].state
- || _channels[i * 3 + 2].state) {
- // Unlock the sound resource
- _vm->_res->unlock(rtSound, sound);
-
- // Stop the actual sfx playback
- _channels[i * 3 + 0].state = 0;
- _channels[i * 3 + 1].state = 0;
- _channels[i * 3 + 2].state = 0;
- clearChannel(i * 3 + 0);
- clearChannel(i * 3 + 1);
- clearChannel(i * 3 + 2);
- }
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ if (_sfx[i].resource == sound) {
+ stopSfx(&_sfx[i]);
}
}
}
@@ -167,29 +170,13 @@ void Player_AD::stopSound(int sound) {
void Player_AD::stopAllSounds() {
Common::StackLock lock(_mutex);
- // Unlock the music resource if present
- if (_soundPlaying != -1) {
- _vm->_res->unlock(rtSound, _soundPlaying);
- _soundPlaying = -1;
- }
+ // Stop the music
+ stopMusic();
- // Stop the music playback
- _curOffset = 0;
-
- // Unloack all used sfx resources
- for (int i = 0; i < 3; ++i) {
- if (_channels[i * 3 + 0].state || _channels[i * 3 + 1].state || _channels[i * 3 + 2].state) {
- _vm->_res->unlock(rtSound, _sfxResource[i]);
- }
- }
-
- // Reset all the sfx channels
- for (int i = 0; i < 9; ++i) {
- _channels[i].state = 0;
- clearChannel(i);
+ // Stop all the sfx playback
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ stopSfx(&_sfx[i]);
}
-
- writeReg(0xBD, 0x00);
}
int Player_AD::getMusicTimer() {
@@ -210,8 +197,51 @@ void Player_AD::saveLoadWithSerializer(Serializer *ser) {
return;
}
- // TODO: Be nicer than the original and save the data to continue the
- // currently played sound resources on load?
+ if (ser->getVersion() >= VER(96)) {
+ int32 res[4] = {
+ _soundPlaying, _sfx[0].resource, _sfx[1].resource, _sfx[2].resource
+ };
+
+ // The first thing we save is a list of sound resources being played
+ // at the moment.
+ ser->saveLoadArrayOf(res, 4, sizeof(res[0]), sleInt32);
+
+ // If we are loading start the music again at this point.
+ if (ser->isLoading()) {
+ if (res[0] != -1) {
+ startSound(res[0]);
+ }
+ }
+
+ uint32 musicOffset = _curOffset;
+
+ static const SaveLoadEntry musicData[] = {
+ MKLINE(Player_AD, _engineMusicTimer, sleInt32, VER(96)),
+ MKLINE(Player_AD, _musicTimer, sleUint32, VER(96)),
+ MKLINE(Player_AD, _internalMusicTimer, sleUint32, VER(96)),
+ MKLINE(Player_AD, _curOffset, sleUint32, VER(96)),
+ MKLINE(Player_AD, _nextEventTimer, sleUint32, VER(96)),
+ MKEND()
+ };
+
+ ser->saveLoadEntries(this, musicData);
+
+ // We seek back to the old music position.
+ if (ser->isLoading()) {
+ SWAP(musicOffset, _curOffset);
+ musicSeekTo(musicOffset);
+ }
+
+ // Finally start up the SFX. This makes sure that they are not
+ // accidently stopped while seeking to the old music position.
+ if (ser->isLoading()) {
+ for (int i = 1; i < ARRAYSIZE(res); ++i) {
+ if (res[i] != -1) {
+ startSound(res[i]);
+ }
+ }
+ }
+ }
}
int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
@@ -221,14 +251,12 @@ int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
while (len > 0) {
if (!_samplesTillCallback) {
- // Run the update callback for music or sfx depending on which is
- // active.
if (_curOffset) {
updateMusic();
- } else {
- updateSfx();
}
+ updateSfx();
+
_samplesTillCallback = _samplesPerCallback;
_samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
if (_samplesTillCallbackRemainder >= AD_CALLBACK_FREQUENCY) {
@@ -250,29 +278,143 @@ int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
void Player_AD::setupVolume() {
// Setup the correct volume
- int soundVolumeMusic = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume);
- int soundVolumeSfx = CLIP<int>(ConfMan.getInt("sfx_volume"), 0, Audio::Mixer::kMaxChannelVolume);
+ _musicVolume = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume);
+ _sfxVolume = CLIP<int>(ConfMan.getInt("sfx_volume"), 0, Audio::Mixer::kMaxChannelVolume);
+
if (ConfMan.hasKey("mute")) {
if (ConfMan.getBool("mute")) {
- soundVolumeMusic = 0;
- soundVolumeSfx = 0;
+ _musicVolume = 0;
+ _sfxVolume = 0;
}
}
- // In case a music is being played set the music volume. Set the sfx
- // volume otherwise. This is safe because in the latter case either
- // sfx are playing or there is no sound being played at all.
- if (_soundPlaying != -1) {
- _mixer->setChannelVolume(_soundHandle, soundVolumeMusic);
- } else {
- _mixer->setChannelVolume(_soundHandle, soundVolumeSfx);
+ // Update current output levels
+ for (int i = 0; i < ARRAYSIZE(_operatorOffsetTable); ++i) {
+ const uint reg = 0x40 + _operatorOffsetTable[i];
+ writeReg(reg, readReg(reg));
+ }
+
+ // Reset note on status
+ for (int i = 0; i < ARRAYSIZE(_hwChannels); ++i) {
+ const uint reg = 0xB0 + i;
+ writeReg(reg, readReg(reg));
}
}
+int Player_AD::allocateHWChannel(int priority, SfxSlot *owner) {
+ // We always reaLlocate the channel with the lowest priority in case none
+ // is free.
+ int channel = -1;
+ int minPrio = priority;
+
+ for (int i = 0; i < _numHWChannels; ++i) {
+ if (!_hwChannels[i].allocated) {
+ channel = i;
+ break;
+ }
+
+ // We don't allow SFX to reallocate their own channels. Otherwise we
+ // would call stopSfx in the midst of startSfx and that can lead to
+ // horrible states...
+ // We also prevent the music from reallocating its own channels like
+ // in the original.
+ if (_hwChannels[i].priority <= minPrio && _hwChannels[i].sfxOwner != owner) {
+ minPrio = _hwChannels[i].priority;
+ channel = i;
+ }
+ }
+
+ if (channel != -1) {
+ // In case the HW channel belongs to a SFX we will completely
+ // stop playback of that SFX.
+ // TODO: Maybe be more fine grained in the future and allow
+ // detachment of individual channels of a SFX?
+ if (_hwChannels[channel].allocated && _hwChannels[channel].sfxOwner) {
+ stopSfx(_hwChannels[channel].sfxOwner);
+ }
+
+ _hwChannels[channel].allocated = true;
+ _hwChannels[channel].priority = priority;
+ _hwChannels[channel].sfxOwner = owner;
+ }
+
+ return channel;
+}
+
+void Player_AD::freeHWChannel(int channel) {
+ assert(_hwChannels[channel].allocated);
+ _hwChannels[channel].allocated = false;
+ _hwChannels[channel].sfxOwner = nullptr;
+}
+
+void Player_AD::limitHWChannels(int newCount) {
+ for (int i = newCount; i < ARRAYSIZE(_hwChannels); ++i) {
+ if (_hwChannels[i].allocated) {
+ freeHWChannel(i);
+ }
+ }
+ _numHWChannels = newCount;
+}
+
+const int Player_AD::_operatorOffsetToChannel[22] = {
+ 0, 1, 2, 0, 1, 2, -1, -1,
+ 3, 4, 5, 3, 4, 5, -1, -1,
+ 6, 7, 8, 6, 7, 8
+};
+
void Player_AD::writeReg(int r, int v) {
if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) {
_registerBackUpTable[r] = v;
}
+
+ // Handle volume scaling depending on the sound type.
+ if (r >= 0x40 && r <= 0x55) {
+ const int operatorOffset = r - 0x40;
+ const int channel = _operatorOffsetToChannel[operatorOffset];
+ if (channel != -1) {
+ const bool twoOPOutput = (readReg(0xC0 + channel) & 0x01) != 0;
+
+ int scale = Audio::Mixer::kMaxChannelVolume;
+ // We only scale the volume of operator 2 unless both operators
+ // are set to directly produce sound.
+ if (twoOPOutput || operatorOffset == _operatorOffsetTable[channel * 2 + 1]) {
+ if (_hwChannels[channel].sfxOwner) {
+ scale = _sfxVolume;
+ } else {
+ scale = _musicVolume;
+ }
+ }
+
+ int vol = 0x3F - (v & 0x3F);
+ vol = vol * scale / Audio::Mixer::kMaxChannelVolume;
+ v &= 0xC0;
+ v |= (0x3F - vol);
+ }
+ }
+
+ // Since AdLib's lowest volume level does not imply that the sound is
+ // completely silent we ignore key on in such a case.
+ // We also ignore key on for music whenever we do seeking.
+ if (r >= 0xB0 && r <= 0xB8) {
+ const int channel = r - 0xB0;
+ bool mute = false;
+ if (_hwChannels[channel].sfxOwner) {
+ if (!_sfxVolume) {
+ mute = true;
+ }
+ } else {
+ if (!_musicVolume) {
+ mute = true;
+ } else {
+ mute = _isSeeking;
+ }
+ }
+
+ if (mute) {
+ v &= ~0x20;
+ }
+ }
+
_opl2->writeReg(r, v);
}
@@ -311,26 +453,23 @@ const int Player_AD::_operatorOffsetTable[18] = {
void Player_AD::startMusic() {
memset(_instrumentOffset, 0, sizeof(_instrumentOffset));
- memset(_channelLastEvent, 0, sizeof(_channelLastEvent));
- memset(_channelFrequency, 0, sizeof(_channelFrequency));
- memset(_channelB0Reg, 0, sizeof(_channelB0Reg));
- _voiceChannels = 0;
- uint instruments = _resource[10];
+ bool hasRhythmData = false;
+ uint instruments = _musicData[10];
for (uint i = 0; i < instruments; ++i) {
- const int instrIndex = _resource[11 + i] - 1;
+ const int instrIndex = _musicData[11 + i] - 1;
if (0 <= instrIndex && instrIndex < 16) {
_instrumentOffset[instrIndex] = i * 16 + 16 + 3;
- _voiceChannels |= _resource[_instrumentOffset[instrIndex] + 13];
+ hasRhythmData |= (_musicData[_instrumentOffset[instrIndex] + 13] != 0);
}
}
- if (_voiceChannels) {
+ if (hasRhythmData) {
_mdvdrState = 0x20;
- _voiceChannels = 6;
+ limitHWChannels(6);
} else {
_mdvdrState = 0;
- _voiceChannels = 9;
+ limitHWChannels(9);
}
_curOffset = 0x93;
@@ -344,9 +483,33 @@ void Player_AD::startMusic() {
const bool isLoom = (_vm->_game.id == GID_LOOM);
_timerLimit = isLoom ? 473 : 256;
- _musicTicks = _resource[3] * (isLoom ? 2 : 1);
- _loopFlag = (_resource[4] == 0);
- _musicLoopStart = READ_LE_UINT16(_resource + 5);
+ _musicTicks = _musicData[3] * (isLoom ? 2 : 1);
+ _loopFlag = (_musicData[4] == 0);
+ _musicLoopStart = _curOffset + READ_LE_UINT16(_musicData + 5);
+}
+
+void Player_AD::stopMusic() {
+ if (_soundPlaying == -1) {
+ return;
+ }
+
+ // Unlock the music resource if present
+ _vm->_res->unlock(rtSound, _soundPlaying);
+ _soundPlaying = -1;
+
+ // Stop the music playback
+ _curOffset = 0;
+
+ // Stop all music voice channels
+ for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
+ if (_voiceChannels[i].lastEvent) {
+ noteOff(i);
+ }
+ }
+
+ // Reset rhythm state
+ writeReg(0xBD, 0x00);
+ limitHWChannels(9);
}
void Player_AD::updateMusic() {
@@ -368,129 +531,142 @@ void Player_AD::updateMusic() {
}
while (true) {
- uint command = _resource[_curOffset++];
- if (command == 0xFF) {
- // META EVENT
- // Get the command number.
- command = _resource[_curOffset++];
- if (command == 47) {
- // End of track
- if (_loopFlag) {
- // In case the track is looping jump to the start.
- _curOffset = _musicLoopStart;
- _nextEventTimer = 0;
- } else {
- // Otherwise completely stop playback.
- stopAllSounds();
- }
+ if (parseCommand()) {
+ // We received an EOT command. In case there's no music playing
+ // we know there was no looping enabled. Thus, we stop further
+ // handling. Otherwise we will just continue parsing. It is
+ // important to note that we need to parse a command directly
+ // at the new position, i.e. there is no time value we need to
+ // parse.
+ if (_soundPlaying == -1) {
return;
- } else if (command == 88) {
- // This is proposedly a debug information insertion. The CMS
- // player code handles this differently, but is still using
- // the same resources...
- _curOffset += 5;
- } else if (command == 81) {
- // Change tempo. This is used exclusively in Loom.
- const uint timing = _resource[_curOffset + 2] | (_resource[_curOffset + 1] << 8);
- _musicTicks = 0x73000 / timing;
- command = _resource[_curOffset++];
- _curOffset += command;
} else {
- // In case an unknown meta event occurs just skip over the
- // data by using the length supplied.
- command = _resource[_curOffset++];
- _curOffset += command;
+ continue;
}
- } else {
- if (command >= 0x90) {
- // NOTE ON
- // Extract the channel number and save it in command.
- command -= 0x90;
-
- const uint instrOffset = _instrumentOffset[command];
- if (instrOffset) {
- if (_resource[instrOffset + 13] != 0) {
- setupRhythm(_resource[instrOffset + 13], instrOffset);
- } else {
- int channel = findFreeChannel();
- if (channel != -1) {
- noteOff(channel);
- setupChannel(channel, instrOffset);
- _channelLastEvent[channel] = command + 0x90;
- _channelFrequency[channel] = _resource[_curOffset];
- setupFrequency(channel, _resource[_curOffset]);
- }
- }
- }
- } else {
- // NOTE OFF
- const uint note = _resource[_curOffset];
- command += 0x10;
-
- // Find the output channel which plays the note.
- uint channel = 0xFF;
- for (uint i = 0; i < _voiceChannels; ++i) {
- if (_channelFrequency[i] == note && _channelLastEvent[i] == command) {
- channel = i;
- break;
- }
- }
-
- if (channel != 0xFF) {
- // In case a output channel playing the note was found,
- // stop it.
- noteOff(channel);
- } else {
- // In case there is no such note this will disable the
- // rhythm instrument played on the channel.
- command -= 0x90;
- const uint instrOffset = _instrumentOffset[command];
- if (instrOffset && _resource[instrOffset + 13] != 0) {
- const uint rhythmInstr = _resource[instrOffset + 13];
- if (rhythmInstr < 6) {
- _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF;
- writeReg(0xBD, _mdvdrState);
- }
- }
- }
- }
-
- _curOffset += 2;
}
// In case there is a delay till the next event stop handling.
- if (_resource[_curOffset] != 0) {
+ if (_musicData[_curOffset] != 0) {
break;
}
++_curOffset;
}
- _nextEventTimer = _resource[_curOffset++];
- if (_nextEventTimer & 0x80) {
- _nextEventTimer -= 0x80;
- _nextEventTimer <<= 7;
- _nextEventTimer |= _resource[_curOffset++];
- }
-
+ _nextEventTimer = parseVLQ();
_nextEventTimer >>= (_vm->_game.id == GID_LOOM) ? 2 : 1;
if (!_nextEventTimer) {
_nextEventTimer = 1;
}
}
-void Player_AD::noteOff(uint channel) {
- _channelLastEvent[channel] = 0;
- writeReg(0xB0 + channel, _channelB0Reg[channel] & 0xDF);
-}
+bool Player_AD::parseCommand() {
+ uint command = _musicData[_curOffset++];
+ if (command == 0xFF) {
+ // META EVENT
+ // Get the command number.
+ command = _musicData[_curOffset++];
+ if (command == 47) {
+ // End of track
+ if (_loopFlag) {
+ // In case the track is looping jump to the start.
+ _curOffset = _musicLoopStart;
+ _nextEventTimer = 0;
+ } else {
+ // Otherwise completely stop playback.
+ stopMusic();
+ }
+ return true;
+ } else if (command == 88) {
+ // This is proposedly a debug information insertion. The CMS
+ // player code handles this differently, but is still using
+ // the same resources...
+ _curOffset += 5;
+ } else if (command == 81) {
+ // Change tempo. This is used exclusively in Loom.
+ const uint timing = _musicData[_curOffset + 2] | (_musicData[_curOffset + 1] << 8);
+ _musicTicks = 0x73000 / timing;
+ command = _musicData[_curOffset++];
+ _curOffset += command;
+ } else {
+ // In case an unknown meta event occurs just skip over the
+ // data by using the length supplied.
+ command = _musicData[_curOffset++];
+ _curOffset += command;
+ }
+ } else {
+ if (command >= 0x90) {
+ // NOTE ON
+ // Extract the channel number and save it in command.
+ command -= 0x90;
+
+ const uint instrOffset = _instrumentOffset[command];
+ if (instrOffset) {
+ if (_musicData[instrOffset + 13] != 0) {
+ setupRhythm(_musicData[instrOffset + 13], instrOffset);
+ } else {
+ // Priority 256 makes sure we always prefer music
+ // channels over SFX channels.
+ int channel = allocateHWChannel(256);
+ if (channel != -1) {
+ setupChannel(channel, _musicData + instrOffset);
+ _voiceChannels[channel].lastEvent = command + 0x90;
+ _voiceChannels[channel].frequency = _musicData[_curOffset];
+ setupFrequency(channel, _musicData[_curOffset]);
+ }
+ }
+ }
+ } else {
+ // NOTE OFF
+ const uint note = _musicData[_curOffset];
+ command += 0x10;
+
+ // Find the output channel which plays the note.
+ uint channel = 0xFF;
+ for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
+ if (_voiceChannels[i].frequency == note && _voiceChannels[i].lastEvent == command) {
+ channel = i;
+ break;
+ }
+ }
-int Player_AD::findFreeChannel() {
- for (uint i = 0; i < _voiceChannels; ++i) {
- if (!_channelLastEvent[i]) {
- return i;
+ if (channel != 0xFF) {
+ // In case a output channel playing the note was found,
+ // stop it.
+ noteOff(channel);
+ } else {
+ // In case there is no such note this will disable the
+ // rhythm instrument played on the channel.
+ command -= 0x90;
+ const uint instrOffset = _instrumentOffset[command];
+ if (instrOffset && _musicData[instrOffset + 13] != 0) {
+ const uint rhythmInstr = _musicData[instrOffset + 13];
+ if (rhythmInstr < 6) {
+ _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF;
+ writeReg(0xBD, _mdvdrState);
+ }
+ }
+ }
}
+
+ _curOffset += 2;
+ }
+
+ return false;
+}
+
+uint Player_AD::parseVLQ() {
+ uint vlq = _musicData[_curOffset++];
+ if (vlq & 0x80) {
+ vlq -= 0x80;
+ vlq <<= 7;
+ vlq |= _musicData[_curOffset++];
}
+ return vlq;
+}
- return -1;
+void Player_AD::noteOff(uint channel) {
+ writeReg(0xB0 + channel, _voiceChannels[channel].b0Reg & 0xDF);
+ freeVoiceChannel(channel);
}
void Player_AD::setupFrequency(uint channel, int8 frequency) {
@@ -510,28 +686,67 @@ void Player_AD::setupFrequency(uint channel, int8 frequency) {
octave |= noteFrequency >> 8;
octave |= 0x20;
writeReg(0xA0 + channel, noteFrequency & 0xFF);
- _channelB0Reg[channel] = octave;
+ _voiceChannels[channel].b0Reg = octave;
writeReg(0xB0 + channel, octave);
}
void Player_AD::setupRhythm(uint rhythmInstr, uint instrOffset) {
if (rhythmInstr == 1) {
- setupChannel(6, instrOffset);
- writeReg(0xA6, _resource[instrOffset++]);
- writeReg(0xB6, _resource[instrOffset] & 0xDF);
+ setupChannel(6, _musicData + instrOffset);
+ writeReg(0xA6, _musicData[instrOffset++]);
+ writeReg(0xB6, _musicData[instrOffset] & 0xDF);
_mdvdrState |= 0x10;
writeReg(0xBD, _mdvdrState);
} else if (rhythmInstr < 6) {
- const byte *secondOperatorOffset = _resource + instrOffset + 8;
+ const byte *secondOperatorOffset = _musicData + instrOffset + 8;
setupOperator(_rhythmOperatorTable[rhythmInstr], secondOperatorOffset);
- writeReg(0xA0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++]);
- writeReg(0xB0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++] & 0xDF);
- writeReg(0xC0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset]);
+ writeReg(0xA0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset++]);
+ writeReg(0xB0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset++] & 0xDF);
+ writeReg(0xC0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset]);
_mdvdrState |= _mdvdrTable[rhythmInstr];
writeReg(0xBD, _mdvdrState);
}
}
+void Player_AD::freeVoiceChannel(uint channel) {
+ VoiceChannel &vChannel = _voiceChannels[channel];
+ assert(vChannel.lastEvent);
+
+ freeHWChannel(channel);
+ vChannel.lastEvent = 0;
+ vChannel.b0Reg = 0;
+ vChannel.frequency = 0;
+}
+
+void Player_AD::musicSeekTo(const uint position) {
+ // This method is actually dangerous to use and should only be used for
+ // loading save games because it does not set up anything like the engine
+ // music timer or similar.
+ _isSeeking = true;
+
+ // Seek until the given position.
+ while (_curOffset != position) {
+ if (parseCommand()) {
+ // We encountered an EOT command. This should not happen unless
+ // we try to seek to an illegal position. In this case just abort
+ // seeking.
+ ::debugC(3, DEBUG_SOUND, "AD illegal seek to %u", position);
+ break;
+ }
+ parseVLQ();
+ }
+
+ _isSeeking = false;
+
+ // Turn on all notes.
+ for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
+ if (_voiceChannels[i].lastEvent != 0) {
+ const int reg = 0xB0 + i;
+ writeReg(reg, readReg(reg));
+ }
+ }
+}
+
const uint Player_AD::_noteFrequencies[12] = {
0x200, 0x21E, 0x23F, 0x261,
0x285, 0x2AB, 0x2D4, 0x300,
@@ -552,29 +767,50 @@ const uint Player_AD::_rhythmChannelTable[6] = {
// SFX
-void Player_AD::startSfx() {
- writeReg(0xBD, 0x00);
+Player_AD::SfxSlot *Player_AD::allocateSfxSlot(int priority) {
+ // We always reaLlocate the slot with the lowest priority in case none is
+ // free.
+ SfxSlot *sfx = nullptr;
+ int minPrio = priority;
+
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ if (_sfx[i].resource == -1) {
+ return &_sfx[i];
+ } else if (_sfx[i].priority <= minPrio) {
+ minPrio = _sfx[i].priority;
+ sfx = &_sfx[i];
+ }
+ }
+
+ // In case we reallocate a slot stop the old one.
+ if (sfx) {
+ stopSfx(sfx);
+ }
- // The second byte of the resource defines the logical channel where
- // the sound effect should be played.
- const int startChannel = _resource[1] * 3;
+ return sfx;
+}
- // Clear the channel.
- _channels[startChannel + 0].state = 0;
- _channels[startChannel + 1].state = 0;
- _channels[startChannel + 2].state = 0;
+bool Player_AD::startSfx(SfxSlot *sfx, const byte *resource) {
+ writeReg(0xBD, 0x00);
- clearChannel(startChannel + 0);
- clearChannel(startChannel + 1);
- clearChannel(startChannel + 2);
+ // Clear the channels.
+ sfx->channels[0].state = kChannelStateOff;
+ sfx->channels[1].state = kChannelStateOff;
+ sfx->channels[2].state = kChannelStateOff;
// Set up the first channel to pick up playback.
- _channels[startChannel].currentOffset = _channels[startChannel].startOffset = _resource + 2;
- _channels[startChannel].state = 1;
+ // Try to allocate a hardware channel.
+ sfx->channels[0].hardwareChannel = allocateHWChannel(sfx->priority, sfx);
+ if (sfx->channels[0].hardwareChannel == -1) {
+ ::debugC(3, DEBUG_SOUND, "AD No hardware channel available");
+ return false;
+ }
+ sfx->channels[0].currentOffset = sfx->channels[0].startOffset = resource + 2;
+ sfx->channels[0].state = kChannelStateParse;
// Scan for the start of the other channels and set them up if required.
- int curChannel = startChannel + 1;
- const byte *bufferPosition = _resource + 2;
+ int curChannel = 1;
+ const byte *bufferPosition = resource + 2;
uint8 command = 0;
while ((command = *bufferPosition) != 0xFF) {
switch (command) {
@@ -596,13 +832,46 @@ void Player_AD::startSfx() {
default:
// START OF CHANNEL
bufferPosition += 1;
- _channels[curChannel].currentOffset = bufferPosition;
- _channels[curChannel].startOffset = bufferPosition;
- _channels[curChannel].state = 1;
+ if (curChannel >= 3) {
+ error("AD SFX resource %d uses more than 3 channels", sfx->resource);
+ }
+ sfx->channels[curChannel].hardwareChannel = allocateHWChannel(sfx->priority, sfx);
+ if (sfx->channels[curChannel].hardwareChannel == -1) {
+ ::debugC(3, DEBUG_SOUND, "AD No hardware channel available");
+ return false;
+ }
+ sfx->channels[curChannel].currentOffset = bufferPosition;
+ sfx->channels[curChannel].startOffset = bufferPosition;
+ sfx->channels[curChannel].state = kChannelStateParse;
++curChannel;
break;
}
}
+
+ return true;
+}
+
+void Player_AD::stopSfx(SfxSlot *sfx) {
+ if (sfx->resource == -1) {
+ return;
+ }
+
+ // 1. step: Clear all the channels.
+ for (int i = 0; i < ARRAYSIZE(sfx->channels); ++i) {
+ if (sfx->channels[i].state) {
+ clearChannel(sfx->channels[i]);
+ sfx->channels[i].state = kChannelStateOff;
+ }
+
+ if (sfx->channels[i].hardwareChannel != -1) {
+ freeHWChannel(sfx->channels[i].hardwareChannel);
+ sfx->channels[i].hardwareChannel = -1;
+ }
+ }
+
+ // 2. step: Unlock the resource.
+ _vm->_res->unlock(rtSound, sfx->resource);
+ sfx->resource = -1;
}
void Player_AD::updateSfx() {
@@ -611,64 +880,75 @@ void Player_AD::updateSfx() {
}
_sfxTimer = 4;
- for (int i = 0; i <= 9; ++i) {
- if (!_channels[i].state) {
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ if (_sfx[i].resource == -1) {
continue;
}
- updateChannel(i);
+ bool hasActiveChannel = false;
+ for (int j = 0; j < ARRAYSIZE(_sfx[i].channels); ++j) {
+ if (_sfx[i].channels[j].state) {
+ hasActiveChannel = true;
+ updateChannel(&_sfx[i].channels[j]);
+ }
+ }
+
+ // In case no channel is active we will stop the sfx.
+ if (!hasActiveChannel) {
+ stopSfx(&_sfx[i]);
+ }
}
}
-void Player_AD::clearChannel(int channel) {
- writeReg(0xA0 + channel, 0x00);
- writeReg(0xB0 + channel, 0x00);
+void Player_AD::clearChannel(const Channel &channel) {
+ writeReg(0xA0 + channel.hardwareChannel, 0x00);
+ writeReg(0xB0 + channel.hardwareChannel, 0x00);
}
-void Player_AD::updateChannel(int channel) {
- if (_channels[channel].state == 1) {
+void Player_AD::updateChannel(Channel *channel) {
+ if (channel->state == kChannelStateParse) {
parseSlot(channel);
} else {
updateSlot(channel);
}
}
-void Player_AD::parseSlot(int channel) {
+void Player_AD::parseSlot(Channel *channel) {
while (true) {
- const byte *curOffset = _channels[channel].currentOffset;
+ const byte *curOffset = channel->currentOffset;
switch (*curOffset) {
case 1:
// INSTRUMENT DEFINITION
++curOffset;
- _channels[channel].instrumentData[0] = *(curOffset + 0);
- _channels[channel].instrumentData[1] = *(curOffset + 2);
- _channels[channel].instrumentData[2] = *(curOffset + 9);
- _channels[channel].instrumentData[3] = *(curOffset + 8);
- _channels[channel].instrumentData[4] = *(curOffset + 4);
- _channels[channel].instrumentData[5] = *(curOffset + 3);
- _channels[channel].instrumentData[6] = 0;
+ channel->instrumentData[0] = *(curOffset + 0);
+ channel->instrumentData[1] = *(curOffset + 2);
+ channel->instrumentData[2] = *(curOffset + 9);
+ channel->instrumentData[3] = *(curOffset + 8);
+ channel->instrumentData[4] = *(curOffset + 4);
+ channel->instrumentData[5] = *(curOffset + 3);
+ channel->instrumentData[6] = 0;
- setupChannel(channel, curOffset);
+ setupChannel(channel->hardwareChannel, curOffset);
- writeReg(0xA0 + channel, *(curOffset + 0));
- writeReg(0xB0 + channel, *(curOffset + 1) & 0xDF);
+ writeReg(0xA0 + channel->hardwareChannel, *(curOffset + 0));
+ writeReg(0xB0 + channel->hardwareChannel, *(curOffset + 1) & 0xDF);
- _channels[channel].currentOffset += 15;
+ channel->currentOffset += 15;
break;
case 2:
// NOTE DEFINITION
++curOffset;
- _channels[channel].state = 2;
- noteOffOn(channel);
- parseNote(channel, 0, curOffset);
- parseNote(channel, 1, curOffset);
+ channel->state = kChannelStatePlay;
+ noteOffOn(channel->hardwareChannel);
+ parseNote(&channel->notes[0], *channel, curOffset + 0);
+ parseNote(&channel->notes[1], *channel, curOffset + 5);
return;
case 0x80:
// LOOP
- _channels[channel].currentOffset = _channels[channel].startOffset;
+ channel->currentOffset = channel->startOffset;
break;
default:
@@ -676,120 +956,106 @@ void Player_AD::parseSlot(int channel) {
// When we encounter a start of another channel while playback
// it means that the current channel is finished. Thus, we will
// stop it.
- clearChannel(channel);
- _channels[channel].state = 0;
-
- // If no channel of the sound effect is playing anymore, unlock
- // the resource.
- channel /= 3;
- if (!_channels[channel + 0].state
- && !_channels[channel + 1].state
- && !_channels[channel + 2].state) {
- _vm->_res->unlock(rtSound, _sfxResource[channel]);
- }
+ clearChannel(*channel);
+ channel->state = kChannelStateOff;
return;
}
}
}
-void Player_AD::updateSlot(int channel) {
- const byte *curOffset = _channels[channel].currentOffset + 1;
+void Player_AD::updateSlot(Channel *channel) {
+ const byte *curOffset = channel->currentOffset + 1;
for (int num = 0; num <= 1; ++num, curOffset += 5) {
if (!(*curOffset & 0x80)) {
continue;
}
- const int note = channel * 2 + num;
+ Note *const note = &channel->notes[num];
bool updateNote = false;
- if (_notes[note].state == 2) {
- if (!--_notes[note].sustainTimer) {
+ if (note->state == kNoteStateSustain) {
+ if (!--note->sustainTimer) {
updateNote = true;
}
} else {
- updateNote = processNoteEnvelope(note, _notes[note].instrumentValue);
+ updateNote = processNoteEnvelope(note);
- if (_notes[note].bias) {
- writeRegisterSpecial(note, _notes[note].bias - _notes[note].instrumentValue, *curOffset & 0x07);
+ if (note->bias) {
+ writeRegisterSpecial(channel->hardwareChannel, note->bias - note->instrumentValue, *curOffset & 0x07);
} else {
- writeRegisterSpecial(note, _notes[note].instrumentValue, *curOffset & 0x07);
+ writeRegisterSpecial(channel->hardwareChannel, note->instrumentValue, *curOffset & 0x07);
}
}
if (updateNote) {
- if (processNote(note, curOffset)) {
+ if (processNote(note, *channel, curOffset)) {
if (!(*curOffset & 0x08)) {
- _channels[channel].currentOffset += 11;
- _channels[channel].state = 1;
+ channel->currentOffset += 11;
+ channel->state = kChannelStateParse;
continue;
} else if (*curOffset & 0x10) {
- noteOffOn(channel);
+ noteOffOn(channel->hardwareChannel);
}
- _notes[note].state = -1;
- processNote(note, curOffset);
+ note->state = kNoteStatePreInit;
+ processNote(note, *channel, curOffset);
}
}
- if ((*curOffset & 0x20) && !--_notes[note].playTime) {
- _channels[channel].currentOffset += 11;
- _channels[channel].state = 1;
+ if ((*curOffset & 0x20) && !--note->playTime) {
+ channel->currentOffset += 11;
+ channel->state = kChannelStateParse;
}
}
}
-void Player_AD::parseNote(int channel, int num, const byte *offset) {
- if (num) {
- offset += 5;
- }
-
+void Player_AD::parseNote(Note *note, const Channel &channel, const byte *offset) {
if (*offset & 0x80) {
- const int note = channel * 2 + num;
- _notes[note].state = -1;
- processNote(note, offset);
- _notes[note].playTime = 0;
+ note->state = kNoteStatePreInit;
+ processNote(note, channel, offset);
+ note->playTime = 0;
if (*offset & 0x20) {
- _notes[note].playTime = (*(offset + 4) >> 4) * 118;
- _notes[note].playTime += (*(offset + 4) & 0x0F) * 8;
+ note->playTime = (*(offset + 4) >> 4) * 118;
+ note->playTime += (*(offset + 4) & 0x0F) * 8;
}
}
}
-bool Player_AD::processNote(int note, const byte *offset) {
- if (++_notes[note].state == 4) {
+bool Player_AD::processNote(Note *note, const Channel &channel, const byte *offset) {
+ if (++note->state == kNoteStateOff) {
return true;
}
const int instrumentDataOffset = *offset & 0x07;
- _notes[note].bias = _noteBiasTable[instrumentDataOffset];
+ note->bias = _noteBiasTable[instrumentDataOffset];
uint8 instrumentDataValue = 0;
- if (_notes[note].state == 0) {
- instrumentDataValue = _channels[note / 2].instrumentData[instrumentDataOffset];
+ if (note->state == kNoteStateAttack) {
+ instrumentDataValue = channel.instrumentData[instrumentDataOffset];
}
- uint8 noteInstrumentValue = readRegisterSpecial(note, instrumentDataValue, instrumentDataOffset);
- if (_notes[note].bias) {
- noteInstrumentValue = _notes[note].bias - noteInstrumentValue;
+ uint8 noteInstrumentValue = readRegisterSpecial(channel.hardwareChannel, instrumentDataValue, instrumentDataOffset);
+ if (note->bias) {
+ noteInstrumentValue = note->bias - noteInstrumentValue;
}
- _notes[note].instrumentValue = noteInstrumentValue;
+ note->instrumentValue = noteInstrumentValue;
- if (_notes[note].state == 2) {
- _notes[note].sustainTimer = _numStepsTable[*(offset + 3) >> 4];
+ if (note->state == kNoteStateSustain) {
+ note->sustainTimer = _numStepsTable[*(offset + 3) >> 4];
if (*offset & 0x40) {
- _notes[note].sustainTimer = (((getRnd() << 8) * _notes[note].sustainTimer) >> 16) + 1;
+ note->sustainTimer = (((getRnd() << 8) * note->sustainTimer) >> 16) + 1;
}
} else {
int timer1, timer2;
- if (_notes[note].state == 3) {
+ if (note->state == kNoteStateRelease) {
timer1 = *(offset + 3) & 0x0F;
timer2 = 0;
} else {
- timer1 = *(offset + _notes[note].state + 1) >> 4;
- timer2 = *(offset + _notes[note].state + 1) & 0x0F;
+ timer1 = *(offset + note->state + 1) >> 4;
+ timer2 = *(offset + note->state + 1) & 0x0F;
}
int adjustValue = ((_noteAdjustTable[timer2] * _noteAdjustScaleTable[instrumentDataOffset]) >> 16) - noteInstrumentValue;
@@ -805,19 +1071,16 @@ void Player_AD::noteOffOn(int channel) {
writeReg(0xB0 | channel, regValue | 0x20);
}
-void Player_AD::writeRegisterSpecial(int note, uint8 value, int offset) {
+void Player_AD::writeRegisterSpecial(int channel, uint8 value, int offset) {
if (offset == 6) {
return;
}
- // Division by 2 extracts the channel number out of the note.
- note /= 2;
-
uint8 regNum;
if (_useOperatorTable[offset]) {
- regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2];
+ regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + channel * 2];
} else {
- regNum = _channelOffsetTable[note];
+ regNum = _channelOffsetTable[channel];
}
regNum += _baseRegisterTable[offset];
@@ -828,19 +1091,16 @@ void Player_AD::writeRegisterSpecial(int note, uint8 value, int offset) {
writeReg(regNum, regValue);
}
-uint8 Player_AD::readRegisterSpecial(int note, uint8 defaultValue, int offset) {
+uint8 Player_AD::readRegisterSpecial(int channel, uint8 defaultValue, int offset) {
if (offset == 6) {
return 0;
}
- // Division by 2 extracts the channel number out of the note.
- note /= 2;
-
uint8 regNum;
if (_useOperatorTable[offset]) {
- regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2];
+ regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + channel * 2];
} else {
- regNum = _channelOffsetTable[note];
+ regNum = _channelOffsetTable[channel];
}
regNum += _baseRegisterTable[offset];
@@ -858,39 +1118,39 @@ uint8 Player_AD::readRegisterSpecial(int note, uint8 defaultValue, int offset) {
return regValue;
}
-void Player_AD::setupNoteEnvelopeState(int note, int steps, int adjust) {
- _notes[note].preIncrease = 0;
+void Player_AD::setupNoteEnvelopeState(Note *note, int steps, int adjust) {
+ note->preIncrease = 0;
if (ABS(adjust) > steps) {
- _notes[note].preIncrease = 1;
- _notes[note].adjust = adjust / steps;
- _notes[note].envelope.stepIncrease = ABS(adjust % steps);
+ note->preIncrease = 1;
+ note->adjust = adjust / steps;
+ note->envelope.stepIncrease = ABS(adjust % steps);
} else {
- _notes[note].adjust = adjust;
- _notes[note].envelope.stepIncrease = ABS(adjust);
+ note->adjust = adjust;
+ note->envelope.stepIncrease = ABS(adjust);
}
- _notes[note].envelope.step = steps;
- _notes[note].envelope.stepCounter = 0;
- _notes[note].envelope.timer = steps;
+ note->envelope.step = steps;
+ note->envelope.stepCounter = 0;
+ note->envelope.timer = steps;
}
-bool Player_AD::processNoteEnvelope(int note, int &instrumentValue) {
- if (_notes[note].preIncrease) {
- instrumentValue += _notes[note].adjust;
+bool Player_AD::processNoteEnvelope(Note *note) {
+ if (note->preIncrease) {
+ note->instrumentValue += note->adjust;
}
- _notes[note].envelope.stepCounter += _notes[note].envelope.stepIncrease;
- if (_notes[note].envelope.stepCounter >= _notes[note].envelope.step) {
- _notes[note].envelope.stepCounter -= _notes[note].envelope.step;
+ note->envelope.stepCounter += note->envelope.stepIncrease;
+ if (note->envelope.stepCounter >= note->envelope.step) {
+ note->envelope.stepCounter -= note->envelope.step;
- if (_notes[note].adjust < 0) {
- --instrumentValue;
+ if (note->adjust < 0) {
+ --note->instrumentValue;
} else {
- ++instrumentValue;
+ ++note->instrumentValue;
}
}
- if (--_notes[note].envelope.timer) {
+ if (--note->envelope.timer) {
return false;
} else {
return true;
@@ -927,7 +1187,7 @@ const uint Player_AD::_noteAdjustTable[16] = {
0, 4369, 8738, 13107,
17476, 21845, 26214, 30583,
34952, 39321, 43690, 48059,
- 52428, 46797, 61166, 65535
+ 52428, 56797, 61166, 65535
};
const bool Player_AD::_useOperatorTable[7] = {
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index fbb65fbe24..63a8503f47 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -68,7 +68,10 @@ private:
Audio::Mixer *const _mixer;
const int _rate;
Audio::SoundHandle _soundHandle;
+
void setupVolume();
+ int _musicVolume;
+ int _sfxVolume;
OPL::OPL *_opl2;
@@ -78,7 +81,21 @@ private:
int _samplesTillCallbackRemainder;
int _soundPlaying;
- int _engineMusicTimer;
+ int32 _engineMusicTimer;
+
+ struct SfxSlot;
+
+ struct HardwareChannel {
+ bool allocated;
+ int priority;
+ SfxSlot *sfxOwner;
+ } _hwChannels[9];
+ int _numHWChannels;
+ static const int _operatorOffsetToChannel[22];
+
+ int allocateHWChannel(int priority, SfxSlot *owner = nullptr);
+ void freeHWChannel(int channel);
+ void limitHWChannels(int newCount);
// AdLib register utilities
uint8 _registerBackUpTable[256];
@@ -86,40 +103,43 @@ private:
uint8 readReg(int r) const;
// Instrument setup
- void setupChannel(const uint channel, uint instrOffset) {
- setupChannel(channel, _resource + instrOffset);
- }
void setupChannel(const uint channel, const byte *instrOffset);
void setupOperator(const uint opr, const byte *&instrOffset);
static const int _operatorOffsetTable[18];
- // Sound data
- const byte *_resource;
-
// Music handling
void startMusic();
+ void stopMusic();
void updateMusic();
+ bool parseCommand();
+ uint parseVLQ();
void noteOff(uint channel);
- int findFreeChannel();
void setupFrequency(uint channel, int8 frequency);
void setupRhythm(uint rhythmInstr, uint instrOffset);
+ const byte *_musicData;
uint _timerLimit;
uint _musicTicks;
- uint _musicTimer;
- uint _internalMusicTimer;
+ uint32 _musicTimer;
+ uint32 _internalMusicTimer;
bool _loopFlag;
uint _musicLoopStart;
uint _instrumentOffset[16];
- uint _channelLastEvent[9];
- uint _channelFrequency[9];
- uint _channelB0Reg[9];
+
+ struct VoiceChannel {
+ uint lastEvent;
+ uint frequency;
+ uint b0Reg;
+ } _voiceChannels[9];
+ void freeVoiceChannel(uint channel);
+
+ void musicSeekTo(const uint position);
+ bool _isSeeking;
uint _mdvdrState;
- uint _voiceChannels;
-
- uint _curOffset;
- uint _nextEventTimer;
+
+ uint32 _curOffset;
+ uint32 _nextEventTimer;
static const uint _noteFrequencies[12];
static const uint _mdvdrTable[6];
@@ -127,34 +147,14 @@ private:
static const uint _rhythmChannelTable[6];
// SFX handling
- void startSfx();
- void updateSfx();
- void clearChannel(int channel);
- void updateChannel(int channel);
- void parseSlot(int channel);
- void updateSlot(int channel);
- void parseNote(int channel, int num, const byte *offset);
- bool processNote(int note, const byte *offset);
- void noteOffOn(int channel);
- void writeRegisterSpecial(int note, uint8 value, int offset);
- uint8 readRegisterSpecial(int note, uint8 defaultValue, int offset);
- void setupNoteEnvelopeState(int note, int steps, int adjust);
- bool processNoteEnvelope(int note, int &instrumentValue);
-
- int _sfxTimer;
-
- int _sfxResource[3];
- int _sfxPriority[3];
-
- struct Channel {
- int state;
- const byte *currentOffset;
- const byte *startOffset;
- uint8 instrumentData[7];
- } _channels[11];
-
- uint8 _rndSeed;
- uint8 getRnd();
+ enum {
+ kNoteStatePreInit = -1,
+ kNoteStateAttack = 0,
+ kNoteStateDecay = 1,
+ kNoteStateSustain = 2,
+ kNoteStateRelease = 3,
+ kNoteStateOff = 4
+ };
struct Note {
int state;
@@ -164,14 +164,60 @@ private:
int bias;
int preIncrease;
int adjust;
-
+
struct Envelope {
int stepIncrease;
int step;
int stepCounter;
int timer;
} envelope;
- } _notes[22];
+ };
+
+ enum {
+ kChannelStateOff = 0,
+ kChannelStateParse = 1,
+ kChannelStatePlay = 2
+ };
+
+ struct Channel {
+ int state;
+ const byte *currentOffset;
+ const byte *startOffset;
+ uint8 instrumentData[7];
+
+ Note notes[2];
+
+ int hardwareChannel;
+ };
+
+ struct SfxSlot {
+ int resource;
+ int priority;
+
+ Channel channels[3];
+ } _sfx[3];
+
+ SfxSlot *allocateSfxSlot(int priority);
+ bool startSfx(SfxSlot *sfx, const byte *resource);
+ void stopSfx(SfxSlot *sfx);
+
+ void updateSfx();
+ void clearChannel(const Channel &channel);
+ void updateChannel(Channel *channel);
+ void parseSlot(Channel *channel);
+ void updateSlot(Channel *channel);
+ void parseNote(Note *note, const Channel &channel, const byte *offset);
+ bool processNote(Note *note, const Channel &channel, const byte *offset);
+ void noteOffOn(int channel);
+ void writeRegisterSpecial(int channel, uint8 value, int offset);
+ uint8 readRegisterSpecial(int channel, uint8 defaultValue, int offset);
+ void setupNoteEnvelopeState(Note *note, int steps, int adjust);
+ bool processNoteEnvelope(Note *note);
+
+ int _sfxTimer;
+
+ uint8 _rndSeed;
+ uint8 getRnd();
static const uint _noteBiasTable[7];
static const uint _numStepsTable[16];
diff --git a/engines/scumm/players/player_mac.cpp b/engines/scumm/players/player_mac.cpp
index fe15698494..634fd2de2b 100644
--- a/engines/scumm/players/player_mac.cpp
+++ b/engines/scumm/players/player_mac.cpp
@@ -21,7 +21,6 @@
*/
#include "common/macresman.h"
-#include "common/translation.h"
#include "engines/engine.h"
#include "gui/message.h"
#include "scumm/players/player_mac.h"
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 0aaff4c094..7eadb042fb 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -1453,7 +1453,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
// forever, then resume playing it. This helps a lot when the audio CD
// is used to provide ambient music (see bug #788195).
if (s->isLoading() && info.playing && info.numLoops < 0)
- _system->getAudioCDManager()->play(info.track, info.numLoops, info.start, info.duration);
+ _sound->playCDTrackInternal(info.track, info.numLoops, info.start, info.duration);
}
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index bd8ae3ff59..01ed21ece5 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 95
+#define CURRENT_VER 96
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index 2c672ccc89..2fe5333bfc 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -972,6 +972,18 @@ void ScummEngine::runEntryScript() {
runScript(VAR(VAR_ENTRY_SCRIPT2), 0, 0, 0);
}
+void ScummEngine::runQuitScript() {
+ if (VAR_QUIT_SCRIPT != 0xFF && VAR(VAR_QUIT_SCRIPT)) {
+ int args[NUM_SCRIPT_LOCAL];
+
+ memset(args, 0, sizeof(args));
+ args[0] = 2;
+ args[1] = 1003;
+
+ runScript(VAR(VAR_QUIT_SCRIPT), 0, 0, args);
+ }
+}
+
void ScummEngine::killScriptsAndResources() {
ScriptSlot *ss;
int i;
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 2cda9898af..91afa859a9 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -544,7 +544,7 @@ void ScummEngine_v5::o5_setClass() {
} else if (cls == 0) {
// Class '0' means: clean all class data
_classData[obj] = 0;
- if ((_game.features & GF_SMALL_HEADER) && obj <= _numActors) {
+ if ((_game.features & GF_SMALL_HEADER) && objIsActor(obj)) {
Actor *a = derefActor(obj, "o5_setClass");
a->_ignoreBoxes = false;
a->_forceClip = 0;
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index ae80f306af..0eeff57ff7 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Fri Sep 27 05:44:12 2013
+ This file was generated by the md5table tool on Wed Jun 25 10:34:07 2014
DO NOT EDIT MANUALLY!
*/
@@ -17,6 +17,7 @@ static const MD5Table md5table[] = {
{ "008e76ec3ae58d0add637ea7aa299a2c", "freddi3", "", "", -1, Common::FR_FRA, Common::kPlatformMacintosh },
{ "02cae0e7ff8504f73618391873d5781a", "freddi3", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformWindows },
{ "0305e850382b812fec6e5998ef88a966", "pajama", "", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
+ { "0354ee0d14cde1264ec762261c04c14a", "loom", "Steam", "Steam", 585728, Common::EN_ANY, Common::kPlatformWindows },
{ "035deab53b47bc43abc763560d0f8d4b", "atlantis", "Floppy", "Demo", -1, Common::EN_ANY, Common::kPlatformDOS },
{ "037385a953789190298494d92b89b3d0", "catalog", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "03d3b18ee3fd68114e2a687c871e38d5", "freddi4", "HE 99", "Mini Game", -1, Common::EN_USA, Common::kPlatformWindows },
@@ -194,6 +195,7 @@ static const MD5Table md5table[] = {
{ "45152f7cf2ba8f43cf8a8ea2e740ae09", "monkey", "VGA", "VGA", 8357, Common::ES_ESP, Common::kPlatformDOS },
{ "4521138d15d1fd7649c31fb981746231", "pajama2", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "4522564b3c31aaf218b6a96826a549fd", "maze", "HE 99", "", -1, Common::EN_USA, Common::kPlatformWindows },
+ { "45adb5065e77559196dc0477e0f91fb9", "freddi3", "HE 99", "", -1, Common::EN_GRB, Common::kPlatformWindows },
{ "46b53fd430adcfbed791b48a0d4b079f", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatformDOS },
{ "470c45b636139bb40716daa1c7edaad0", "loom", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformDOS },
{ "477dbafbd66a53c98416dc01aef019ad", "monkey", "EGA", "EGA", -1, Common::IT_ITA, Common::kPlatformDOS },
@@ -298,6 +300,7 @@ static const MD5Table md5table[] = {
{ "69ffe29185b8d71f09f6199f8b2a87cb", "lost", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "6a30a07f353a75cdc602db27d73e1b42", "puttputt", "HE 70", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "6a60d395b78b205c93a956100b1bf5ae", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
+ { "6a8133b63d46f6663fbcbb49d5a2edb1", "atlantis", "Steam", "Steam", 520548, Common::EN_ANY, Common::kPlatformMacintosh },
{ "6af2419fe3db5c2fdb091ae4e5833770", "puttrace", "HE 98.5", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "6b19d0e25cbf720d05822379b8b90ed9", "PuttTime", "HE 90", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "6b257bb2827dd894b8109a50a1a18b5a", "freddicove", "HE 100", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
@@ -356,6 +359,7 @@ static const MD5Table md5table[] = {
{ "7edd665bbede7ea8b7233f8e650be6f8", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "7f45ddd6dbfbf8f80c0c0efea4c295bc", "maniac", "V1", "V1", 1972, Common::EN_ANY, Common::kPlatformDOS },
{ "7f945525abcd48015adf1632637a44a1", "pajama", "", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown },
+ { "7fbcff27c323499beaedd605e1ebd47d", "indy3", "Steam", "Steam", 561152, Common::EN_ANY, Common::kPlatformWindows },
{ "7fc6cdb46b4c9d384c52327f4bca6416", "football", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "810a9da887aefa597b0cf3c77d262897", "BluesABCTime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "822807c3cd3b43a925cab2767ca6b453", "BluesTreasureHunt", "", "Disc 1", -1, Common::EN_ANY, Common::kPlatformUnknown },
@@ -438,6 +442,7 @@ static const MD5Table md5table[] = {
{ "a095616d2d23ccf43b8e257711202cba", "football2002", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "a095e33061606d231ff37dca4c64c8ac", "pajama", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "a0a7dea72003933b8b3f8b99b9f7ddeb", "loom", "No AdLib", "EGA", -1, Common::EN_ANY, Common::kPlatformAtariST },
+ { "a15d6e1e2c52bbd0ff7fa6b63ab7f796", "indy3", "Steam", "Steam", 680340, Common::EN_ANY, Common::kPlatformMacintosh },
{ "a194f15f51ee62badab74b9e7da97693", "baseball2001", "", "Demo", 20507, Common::EN_ANY, Common::kPlatformUnknown },
{ "a197a87ae77f3b3333f09a7a2c448fe2", "freddi", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "a22af0ad0e3126d19d22707b0267a37d", "balloon", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformWindows },
@@ -466,6 +471,7 @@ static const MD5Table md5table[] = {
{ "aa8a0cb65f3afbbe2c14c3f9f92775a3", "monkey", "CD", "CD", 8955, Common::FR_FRA, Common::kPlatformDOS },
{ "aaa587701cde7e74692c68c1024b85eb", "puttrace", "HE 99", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "aaa7f36a253f277dd29dd1c051b0e4b9", "indy3", "No AdLib", "EGA", -1, Common::DE_DEU, Common::kPlatformAtariST },
+ { "aad201302286c1cfee92321cd406e427", "dig", "Steam", "Steam", 811008, Common::EN_ANY, Common::kPlatformWindows },
{ "ab0693e9324cfcf498fdcbb12acf8bb4", "puttcircus", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "ac1642b6edfb8521ca03760126f1c250", "tentacle", "", "Demo", -1, Common::DE_DEU, Common::kPlatformDOS },
{ "ac62d50e39492ee3738b4e83a5ac780f", "freddi2", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformWindows },
@@ -479,6 +485,7 @@ static const MD5Table md5table[] = {
{ "b250d0f9cc83f80ced56fe11a4fb057c", "maniac", "V2", "V2", 1988, Common::EN_ANY, Common::kPlatformDOS },
{ "b289a2a8cbedbf45786e0b4ad2f510f1", "samnmax", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformDOS },
{ "b47be81e39a9710f6f595f7b527b60f8", "puttrace", "HE 99", "", -1, Common::EN_GRB, Common::kPlatformWindows },
+ { "b4a677bf27c010a747975705108ff1e6", "loom", "Steam", "Steam", 393572, Common::EN_ANY, Common::kPlatformMacintosh },
{ "b5298a5c15ffbe8b381d51ea4e26d35c", "freddi4", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "b597e0403cc0002f69170e6caba7edd9", "indy3", "EGA", "EGA Demo", 5361, Common::EN_ANY, Common::kPlatformDOS },
{ "b628506f7def772e40de0aa5440fb8e1", "activity", "HE 70", "", -1, Common::EN_ANY, Common::kPlatformWindows },
@@ -568,6 +575,7 @@ static const MD5Table md5table[] = {
{ "d7b247c26bf1f01f8f7daf142be84de3", "balloon", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "d8323015ecb8b10bf53474f6e6b0ae33", "dig", "", "", 16304, Common::UNK_LANG, Common::kPlatformUnknown },
{ "d917f311a448e3cc7239c31bddb00dd2", "samnmax", "", "CD", 9080, Common::EN_ANY, Common::kPlatformUnknown },
+ { "d93cc8be628ed5d3b3a29188fc7105d3", "dig", "Steam", "Steam", 1061296, Common::EN_ANY, Common::kPlatformMacintosh },
{ "d9d0dd93d16ab4dec55cabc2b86bbd17", "samnmax", "", "Demo", 6478, Common::EN_ANY, Common::kPlatformDOS },
{ "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "FM-TOWNS", "", 11135, Common::EN_ANY, Common::kPlatformFMTowns },
{ "da6269b18fcb08189c0aa9c95533cce2", "monkey", "CD", "CD", 8955, Common::IT_ITA, Common::kPlatformDOS },
@@ -628,6 +636,7 @@ static const MD5Table md5table[] = {
{ "f237bf8a5ef9af78b2a6a4f3901da341", "pajama", "", "Demo", 18354, Common::EN_ANY, Common::kPlatformUnknown },
{ "f27b1ba0eadaf2a6617b2b58192d1dbf", "samnmax", "Floppy", "Floppy", -1, Common::DE_DEU, Common::kPlatformDOS },
{ "f2ec78e50bdc63b70044e9758be10914", "spyfox", "HE 98.5", "Demo", -1, Common::NL_NLD, Common::kPlatformMacintosh },
+ { "f3c5d9bf3f091bd1f18dc1013fba5396", "atlantis", "Steam", "Steam", 638976, Common::EN_ANY, Common::kPlatformWindows },
{ "f3d55aea441e260e9e9c7d2a187097e0", "puttzoo", "", "Demo", 14337, Common::EN_ANY, Common::kPlatformWindows },
{ "f40a7f495f59188ca57a9d1d50301bb6", "puttputt", "HE 60", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "f5228b0cc1c19e6ea8268ba2eeb61f60", "freddi", "HE 73", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 54f22ecad3..475b146a7b 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -205,7 +205,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_lastInputScriptTime = 0;
_bootParam = 0;
_dumpScripts = false;
- _debugMode = 0;
+ _debugMode = false;
_objectOwnerTable = NULL;
_objectRoomTable = NULL;
_objectStateTable = NULL;
@@ -467,6 +467,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
VAR_NUM_SCRIPT_CYCLES = 0xFF;
VAR_SCRIPT_CYCLE = 0xFF;
+ VAR_QUIT_SCRIPT = 0xFF;
+
VAR_NUM_GLOBAL_OBJS = 0xFF;
// Use g_scumm from error() ONLY
@@ -1026,6 +1028,35 @@ Common::Error ScummEngine::init() {
}
#endif
+ // Extra directories needed for the Steam versions
+ if (_filenamePattern.genMethod == kGenDiskNumSteam || _filenamePattern.genMethod == kGenRoomNumSteam) {
+ if (_game.platform == Common::kPlatformWindows) {
+ switch (_game.id) {
+ case GID_INDY3 :
+ SearchMan.addSubDirectoryMatching(gameDataDir, "indy3");
+ break;
+ case GID_INDY4 :
+ SearchMan.addSubDirectoryMatching(gameDataDir, "atlantis");
+ break;
+ case GID_LOOM :
+ SearchMan.addSubDirectoryMatching(gameDataDir, "loom");
+ break;
+#ifdef ENABLE_SCUMM_7_8
+ case GID_DIG :
+ SearchMan.addSubDirectoryMatching(gameDataDir, "dig");
+ SearchMan.addSubDirectoryMatching(gameDataDir, "dig/video");
+ break;
+#endif
+ default:
+ break;
+ }
+ } else {
+ SearchMan.addSubDirectoryMatching(gameDataDir, "Contents");
+ SearchMan.addSubDirectoryMatching(gameDataDir, "Contents/MacOS");
+ SearchMan.addSubDirectoryMatching(gameDataDir, "Contents/Resources");
+ SearchMan.addSubDirectoryMatching(gameDataDir, "Contents/Resources/video");
+ }
+ }
// The kGenUnchanged method is only used for 'container files', i.e. files
// that contain the real game files bundled together in an archive format.
@@ -1126,15 +1157,30 @@ Common::Error ScummEngine::init() {
error("Couldn't find known subfile inside container file '%s'", _containerFile.c_str());
_fileHandle->close();
-
} else {
error("kGenUnchanged used with unsupported platform");
}
} else {
- // Regular access, no container file involved
- _fileHandle = new ScummFile();
+ if (_filenamePattern.genMethod == kGenDiskNumSteam || _filenamePattern.genMethod == kGenRoomNumSteam) {
+ // Steam game versions have the index file embedded in the main executable
+ const SteamIndexFile *indexFile = lookUpSteamIndexFile(_filenamePattern.pattern, _game.platform);
+ if (!indexFile || indexFile->id != _game.id) {
+ error("Couldn't find index file description for Steam version");
+ } else {
+ _fileHandle = new ScummSteamFile(*indexFile);
+ }
+ } else {
+ // Regular access, no container file involved
+ _fileHandle = new ScummFile();
+ }
}
+ // Steam Win and Mac versions share the same DOS data files. We show Windows or Mac
+ // for the platform the detector, but internally we force the platform to DOS, so that
+ // the code for handling the original DOS data files is used.
+ if (_filenamePattern.genMethod == kGenDiskNumSteam || _filenamePattern.genMethod == kGenRoomNumSteam)
+ _game.platform = Common::kPlatformDOS;
+
// Load CJK font, if present
// Load it earlier so _useCJKMode variable could be set
loadCJKFont();
@@ -1218,7 +1264,7 @@ Common::Error ScummEngine::init() {
void ScummEngine::setupScumm() {
// On some systems it's not safe to run CD audio games from the CD.
- if (_game.features & GF_AUDIOTRACKS) {
+ if (_game.features & GF_AUDIOTRACKS && !Common::File::exists("CDDA.SOU")) {
checkCD();
int cd_num = ConfMan.getInt("cdrom");
@@ -2029,6 +2075,7 @@ Common::Error ScummEngine::go() {
if (shouldQuit()) {
// TODO: Maybe perform an autosave on exit?
+ runQuitScript();
}
}
@@ -2281,7 +2328,7 @@ void ScummEngine::scummLoop_updateScummVars() {
VAR(VAR_MOUSE_Y) = _mouse.y;
if (VAR_DEBUGMODE != 0xFF) {
// This is NOT for the Mac version of Indy3/Loom
- VAR(VAR_DEBUGMODE) = _debugMode;
+ VAR(VAR_DEBUGMODE) = (_debugMode ? 1 : 0);
}
} else if (_game.version >= 1) {
// We use shifts below instead of dividing by V12_X_MULTIPLIER resp.
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index b4afa09bb2..af118a89a1 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -256,6 +256,7 @@ enum ScummGameId {
GID_BASEBALL2003,
GID_BASKETBALL,
GID_MOONBASE,
+ GID_PJGAMES,
GID_HECUP // CUP demos
};
@@ -586,7 +587,7 @@ protected:
bool _dumpScripts;
bool _hexdumpScripts;
bool _showStack;
- uint16 _debugMode;
+ bool _debugMode;
// Save/Load class - some of this may be GUI
byte _saveLoadFlag, _saveLoadSlot;
@@ -670,6 +671,7 @@ protected:
virtual void checkAndRunSentenceScript();
void runExitScript();
void runEntryScript();
+ void runQuitScript();
void runAllScripts();
void freezeScripts(int scr);
void unfreezeScripts();
@@ -1360,6 +1362,8 @@ public:
byte VAR_SCRIPT_CYCLE; // Used in runScript()/runObjectScript()
byte VAR_NUM_SCRIPT_CYCLES; // Used in runAllScripts()
+
+ byte VAR_QUIT_SCRIPT; // Used in confirmExitDialog()
// Exists both in V7 and in V72HE:
byte VAR_NUM_GLOBAL_OBJS;
diff --git a/engines/scumm/smush/smush_font.cpp b/engines/scumm/smush/smush_font.cpp
index 4c04901b42..e2f75a6862 100644
--- a/engines/scumm/smush/smush_font.cpp
+++ b/engines/scumm/smush/smush_font.cpp
@@ -115,9 +115,7 @@ int SmushFont::drawChar(byte *buffer, int dst_width, int x, int y, byte chr) {
int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) {
int w = _vm->_2byteWidth;
int h = _vm->_2byteHeight;
-
- byte *src = _vm->get2byteCharPtr(idx);
- byte *dst = buffer + dst_width * (y + (_vm->_game.id == GID_CMI ? 7 : (_vm->_game.id == GID_DIG ? 2 : 0))) + x;
+ const byte *src = _vm->get2byteCharPtr(idx);
byte bits = 0;
char color = (_color != -1) ? _color : 1;
@@ -128,18 +126,60 @@ int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) {
if (_vm->_game.id == GID_FT)
color = 1;
- for (int j = 0; j < h; j++) {
- for (int i = 0; i < w; i++) {
- if ((i % 8) == 0)
- bits = *src++;
- if (bits & revBitMask(i % 8)) {
- dst[i + 1] = 0;
- dst[dst_width + i] = 0;
- dst[dst_width + i + 1] = 0;
- dst[i] = color;
+ enum ShadowMode {
+ kNone,
+ kNormalShadowMode,
+ kKoreanV7ShadowMode,
+ kKoreanV8ShadowMode
+ };
+
+ ShadowMode shadowMode = kNone;
+
+ if (_vm->_language == Common::KO_KOR) {
+ if (_vm->_game.version == 8)
+ shadowMode = kKoreanV8ShadowMode;
+ else
+ shadowMode = kKoreanV7ShadowMode;
+ }
+
+ int shadowOffsetXTable[4] = {-1, 0, 1, 0};
+ int shadowOffsetYTable[4] = {0, 1, 0, 0};
+ int shadowOffsetColorTable[4] = {0, 0, 0, color};
+
+ int shadowIdx = 3;
+ if (shadowMode == kKoreanV8ShadowMode)
+ shadowIdx = 0;
+ else if (shadowMode == kKoreanV7ShadowMode)
+ shadowIdx = 2;
+
+ const byte *origSrc = src;
+
+ for (; shadowIdx < 4; shadowIdx++) {
+ int offX = x + shadowOffsetXTable[shadowIdx];
+ int offY = y + shadowOffsetYTable[shadowIdx];
+ byte drawColor = shadowOffsetColorTable[shadowIdx];
+
+ src = origSrc;
+
+ byte *dst = buffer + dst_width * (offY + (_vm->_game.id == GID_CMI ? 7 : (_vm->_game.id == GID_DIG ? 2 : 0))) + offX;
+
+ for (int j = 0; j < h; j++) {
+ for (int i = 0; i < w; i++) {
+ if (offX + i < 0)
+ continue;
+ if ((i % 8) == 0)
+ bits = *src++;
+ if (bits & revBitMask(i % 8)) {
+ if (shadowMode == kNormalShadowMode) {
+ dst[i + 1] = 0;
+ dst[dst_width + i] = 0;
+ dst[dst_width + i + 1] = 0;
+ }
+ dst[i] = drawColor;
+ }
}
+ dst += dst_width;
}
- dst += dst_width;
}
return w + 1;
}
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 01bdefc7c0..cb428d1c15 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -27,6 +27,7 @@
#include "common/substream.h"
#include "scumm/actor.h"
+#include "scumm/cdda.h"
#include "scumm/file.h"
#include "scumm/imuse/imuse.h"
#include "scumm/imuse_digi/dimuse.h"
@@ -36,8 +37,6 @@
#include "scumm/sound.h"
#include "scumm/util.h"
-#include "backends/audiocd/audiocd.h"
-
#include "audio/decoders/adpcm.h"
#include "audio/decoders/flac.h"
#include "audio/mididrv.h"
@@ -89,11 +88,21 @@ Sound::Sound(ScummEngine *parent, Audio::Mixer *mixer)
memset(_mouthSyncTimes, 0, sizeof(_mouthSyncTimes));
_musicType = MDT_NONE;
+
+ _loomSteamCD.playing = false;
+ _loomSteamCD.track = 0;
+ _loomSteamCD.start = 0;
+ _loomSteamCD.duration = 0;
+ _loomSteamCD.numLoops = 0;
+ _loomSteamCD.volume = Audio::Mixer::kMaxChannelVolume;
+ _loomSteamCD.balance = 0;
+
+ _isLoomSteam = _vm->_game.id == GID_LOOM && Common::File::exists("CDDA.SOU");
}
Sound::~Sound() {
stopCDTimer();
- g_system->getAudioCDManager()->stop();
+ stopCD();
free(_offsetTable);
}
@@ -649,7 +658,11 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
_vm->_imuseDigital->startVoice(kTalkSoundID, input);
#endif
} else {
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, handle, input, id);
+ if (mode == 1) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, handle, input, id);
+ } else {
+ _mixer->playStream(Audio::Mixer::kSpeechSoundType, handle, input, id);
+ }
}
}
}
@@ -838,9 +851,6 @@ void Sound::soundKludge(int *list, int num) {
}
void Sound::talkSound(uint32 a, uint32 b, int mode, int channel) {
- if (_vm->_game.version >= 5 && ConfMan.getBool("speech_mute"))
- return;
-
if (mode == 1) {
_talk_sound_a1 = a;
_talk_sound_b1 = b;
@@ -1033,7 +1043,7 @@ void Sound::playCDTrack(int track, int numLoops, int startFrame, int duration) {
// Play it
if (!_soundsPaused)
- g_system->getAudioCDManager()->play(track, numLoops, startFrame, duration);
+ playCDTrackInternal(track, numLoops, startFrame, duration);
// Start the timer after starting the track. Starting an MP3 track is
// almost instantaneous, but a CD player may take some time. Hopefully
@@ -1041,16 +1051,59 @@ void Sound::playCDTrack(int track, int numLoops, int startFrame, int duration) {
startCDTimer();
}
+void Sound::playCDTrackInternal(int track, int numLoops, int startFrame, int duration) {
+ _loomSteamCD.track = track;
+ _loomSteamCD.numLoops = numLoops;
+ _loomSteamCD.start = startFrame;
+ _loomSteamCD.duration = duration;
+
+ if (!_isLoomSteam) {
+ g_system->getAudioCDManager()->play(track, numLoops, startFrame, duration);
+ } else {
+ // Stop any currently playing track
+ _mixer->stopHandle(_loomSteamCDAudioHandle);
+
+ Common::File *cddaFile = new Common::File();
+ if (cddaFile->open("CDDA.SOU")) {
+ Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75);
+ Audio::Timestamp end = Audio::Timestamp(0, startFrame + duration, 75);
+ Audio::SeekableAudioStream *stream = makeCDDAStream(cddaFile, DisposeAfterUse::YES);
+
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_loomSteamCDAudioHandle,
+ Audio::makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops));
+ } else {
+ delete cddaFile;
+ }
+ }
+}
+
void Sound::stopCD() {
- g_system->getAudioCDManager()->stop();
+ if (!_isLoomSteam)
+ g_system->getAudioCDManager()->stop();
+ else
+ _mixer->stopHandle(_loomSteamCDAudioHandle);
}
int Sound::pollCD() const {
- return g_system->getAudioCDManager()->isPlaying();
+ if (!_isLoomSteam)
+ return g_system->getAudioCDManager()->isPlaying();
+ else
+ return _mixer->isSoundHandleActive(_loomSteamCDAudioHandle);
}
void Sound::updateCD() {
- g_system->getAudioCDManager()->updateCD();
+ if (!_isLoomSteam)
+ g_system->getAudioCDManager()->updateCD();
+}
+
+AudioCDManager::Status Sound::getCDStatus() {
+ if (!_isLoomSteam)
+ return g_system->getAudioCDManager()->getStatus();
+ else {
+ AudioCDManager::Status info = _loomSteamCD;
+ info.playing = _mixer->isSoundHandleActive(_loomSteamCDAudioHandle);
+ return info;
+ }
}
void Sound::saveLoadWithSerializer(Serializer *ser) {
diff --git a/engines/scumm/sound.h b/engines/scumm/sound.h
index a96d2b8ed5..a479ad5731 100644
--- a/engines/scumm/sound.h
+++ b/engines/scumm/sound.h
@@ -27,6 +27,7 @@
#include "audio/audiostream.h"
#include "audio/mididrv.h"
#include "audio/mixer.h"
+#include "backends/audiocd/audiocd.h"
#include "scumm/saveload.h"
namespace Audio {
@@ -86,6 +87,10 @@ protected:
int16 _currentCDSound;
int16 _currentMusic;
+ Audio::SoundHandle _loomSteamCDAudioHandle;
+ bool _isLoomSteam;
+ AudioCDManager::Status _loomSteamCD;
+
public:
Audio::SoundHandle _talkChannelHandle; // Handle of mixer channel actor is talking on
@@ -119,9 +124,11 @@ public:
void stopCDTimer();
void playCDTrack(int track, int numLoops, int startFrame, int duration);
+ void playCDTrackInternal(int track, int numLoops, int startFrame, int duration);
void stopCD();
int pollCD() const;
void updateCD();
+ AudioCDManager::Status getCDStatus();
int getCurrentCDSound() const { return _currentCDSound; }
// Used by the save/load system:
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index 73028c8513..a903ac5804 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -320,6 +320,7 @@ void ScummEngine_v90he::setupScummVars() {
ScummEngine_v80he::setupScummVars();
VAR_TIMER = 97;
+ VAR_QUIT_SCRIPT = 102;
VAR_SCRIPT_CYCLE = 103;
VAR_NUM_SCRIPT_CYCLES = 104;
@@ -805,7 +806,7 @@ void ScummEngine::resetScummVars() {
}
if (VAR_DEBUGMODE != 0xFF) {
- VAR(VAR_DEBUGMODE) = _debugMode;
+ VAR(VAR_DEBUGMODE) = (_debugMode ? 1 : 0);
if (_game.heversion >= 80 && _debugMode)
VAR(85) = 1;
}
diff --git a/engines/sky/debug.cpp b/engines/sky/debug.cpp
index 63da42eec2..d663bd206d 100644
--- a/engines/sky/debug.cpp
+++ b/engines/sky/debug.cpp
@@ -1087,14 +1087,14 @@ void Debug::mcode(uint32 mcode, uint32 a, uint32 b, uint32 c) {
Debugger::Debugger(Logic *logic, Mouse *mouse, Screen *screen, SkyCompact *skyCompact)
: GUI::Debugger(), _logic(logic), _mouse(mouse), _screen(screen), _skyCompact(skyCompact), _showGrid(false) {
- DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info));
- DCmd_Register("showgrid", WRAP_METHOD(Debugger, Cmd_ShowGrid));
- DCmd_Register("reloadgrid", WRAP_METHOD(Debugger, Cmd_ReloadGrid));
- DCmd_Register("compact", WRAP_METHOD(Debugger, Cmd_ShowCompact));
- DCmd_Register("logiccmd", WRAP_METHOD(Debugger, Cmd_LogicCommand));
- DCmd_Register("scriptvar", WRAP_METHOD(Debugger, Cmd_ScriptVar));
- DCmd_Register("section", WRAP_METHOD(Debugger, Cmd_Section));
- DCmd_Register("logiclist", WRAP_METHOD(Debugger, Cmd_LogicList));
+ registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info));
+ registerCmd("showgrid", WRAP_METHOD(Debugger, Cmd_ShowGrid));
+ registerCmd("reloadgrid", WRAP_METHOD(Debugger, Cmd_ReloadGrid));
+ registerCmd("compact", WRAP_METHOD(Debugger, Cmd_ShowCompact));
+ registerCmd("logiccmd", WRAP_METHOD(Debugger, Cmd_LogicCommand));
+ registerCmd("scriptvar", WRAP_METHOD(Debugger, Cmd_ScriptVar));
+ registerCmd("section", WRAP_METHOD(Debugger, Cmd_Section));
+ registerCmd("logiclist", WRAP_METHOD(Debugger, Cmd_LogicList));
}
Debugger::~Debugger() {} // we need this here for __SYMBIAN32__
@@ -1119,14 +1119,14 @@ static bool isNumeric(const char *arg) {
bool Debugger::Cmd_ShowGrid(int argc, const char **argv) {
_showGrid = !_showGrid;
- DebugPrintf("Show grid: %s\n", _showGrid ? "On" : "Off");
+ debugPrintf("Show grid: %s\n", _showGrid ? "On" : "Off");
if (!_showGrid) _screen->forceRefresh();
return true;
}
bool Debugger::Cmd_ReloadGrid(int argc, const char **argv) {
_logic->_skyGrid->loadGrids();
- DebugPrintf("Grid reloaded\n");
+ debugPrintf("Grid reloaded\n");
return true;
}
@@ -1143,35 +1143,35 @@ void Debugger::dumpCompact(uint16 cptId) {
Compact *cpt = _skyCompact->fetchCptInfo(cptId, &size, &type, name);
if (type == COMPACT) {
- DebugPrintf("Compact %s: id = %04X, section %d, id %d\n", name, cptId, cptId >> 12, cptId & 0xFFF);
- DebugPrintf("logic : %04X: %s\n", cpt->logic, (cpt->logic <= 16) ? logicTypes[cpt->logic] : "unknown");
- DebugPrintf("status : %04X\n", cpt->status);
- DebugPrintf(" : background : %s\n", noYes[(cpt->status & ST_BACKGROUND) >> 0]);
- DebugPrintf(" : foreground : %s\n", noYes[(cpt->status & ST_FOREGROUND) >> 1]);
- DebugPrintf(" : sort list : %s\n", noYes[(cpt->status & ST_SORT) >> 2]);
- DebugPrintf(" : recreate : %s\n", noYes[(cpt->status & ST_RECREATE) >> 3]);
- DebugPrintf(" : mouse : %s\n", noYes[(cpt->status & ST_MOUSE) >> 4]);
- DebugPrintf(" : collision : %s\n", noYes[(cpt->status & ST_COLLISION) >> 5]);
- DebugPrintf(" : logic : %s\n", noYes[(cpt->status & ST_LOGIC) >> 6]);
- DebugPrintf(" : on grid : %s\n", noYes[(cpt->status & ST_GRID_PLOT) >> 7]);
- DebugPrintf(" : ar priority : %s\n", noYes[(cpt->status & ST_AR_PRIORITY) >> 8]);
- DebugPrintf("sync : %04X\n", cpt->sync);
- DebugPrintf("screen : %d\n", cpt->screen);
+ debugPrintf("Compact %s: id = %04X, section %d, id %d\n", name, cptId, cptId >> 12, cptId & 0xFFF);
+ debugPrintf("logic : %04X: %s\n", cpt->logic, (cpt->logic <= 16) ? logicTypes[cpt->logic] : "unknown");
+ debugPrintf("status : %04X\n", cpt->status);
+ debugPrintf(" : background : %s\n", noYes[(cpt->status & ST_BACKGROUND) >> 0]);
+ debugPrintf(" : foreground : %s\n", noYes[(cpt->status & ST_FOREGROUND) >> 1]);
+ debugPrintf(" : sort list : %s\n", noYes[(cpt->status & ST_SORT) >> 2]);
+ debugPrintf(" : recreate : %s\n", noYes[(cpt->status & ST_RECREATE) >> 3]);
+ debugPrintf(" : mouse : %s\n", noYes[(cpt->status & ST_MOUSE) >> 4]);
+ debugPrintf(" : collision : %s\n", noYes[(cpt->status & ST_COLLISION) >> 5]);
+ debugPrintf(" : logic : %s\n", noYes[(cpt->status & ST_LOGIC) >> 6]);
+ debugPrintf(" : on grid : %s\n", noYes[(cpt->status & ST_GRID_PLOT) >> 7]);
+ debugPrintf(" : ar priority : %s\n", noYes[(cpt->status & ST_AR_PRIORITY) >> 8]);
+ debugPrintf("sync : %04X\n", cpt->sync);
+ debugPrintf("screen : %d\n", cpt->screen);
_skyCompact->fetchCptInfo(cpt->place, NULL, NULL, name);
- DebugPrintf("place : %04X: %s\n", cpt->place, name);
+ debugPrintf("place : %04X: %s\n", cpt->place, name);
_skyCompact->fetchCptInfo(cpt->getToTableId, NULL, NULL, name);
- DebugPrintf("get to tab : %04X: %s\n", cpt->getToTableId, name);
- DebugPrintf("x/y : %d/%d\n", cpt->xcood, cpt->ycood);
+ debugPrintf("get to tab : %04X: %s\n", cpt->getToTableId, name);
+ debugPrintf("x/y : %d/%d\n", cpt->xcood, cpt->ycood);
} else {
- DebugPrintf("Can't dump binary data\n");
+ debugPrintf("Can't dump binary data\n");
}
}
bool Debugger::Cmd_ShowCompact(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Example: \"%s foster\" dumps compact \"foster\"\n", argv[0]);
- DebugPrintf("Example: \"%s list 1\" lists all compacts from section 1\n", argv[0]);
- DebugPrintf("Example: \"%s list 1 all\" lists all entities from section 1\n", argv[0]);
+ debugPrintf("Example: \"%s foster\" dumps compact \"foster\"\n", argv[0]);
+ debugPrintf("Example: \"%s list 1\" lists all compacts from section 1\n", argv[0]);
+ debugPrintf("Example: \"%s list 1 all\" lists all entities from section 1\n", argv[0]);
return true;
}
@@ -1181,7 +1181,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) {
if (argc >= 3) {
sectionNumber = atoi(argv[2]);
if (sectionNumber >= _skyCompact->giveNumDataLists()) {
- DebugPrintf("Section number %d does not exist\n", sectionNumber);
+ debugPrintf("Section number %d does not exist\n", sectionNumber);
return true;
}
if ((argc == 4) && (scumm_stricmp(argv[3], "all") == 0))
@@ -1189,14 +1189,14 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) {
}
for (int sec = 0; sec < _skyCompact->giveNumDataLists(); sec++) {
if ((sectionNumber == -1) || (sectionNumber == sec)) {
- DebugPrintf("Compacts in section %d:\n", sec);
+ debugPrintf("Compacts in section %d:\n", sec);
if (showAll) {
char line[256];
char *linePos = line;
for (int cpt = 0; cpt < _skyCompact->giveDataListLen(sec); cpt++) {
if (cpt != 0) {
if ((cpt % 3) == 0) {
- DebugPrintf("%s\n", line);
+ debugPrintf("%s\n", line);
linePos = line;
} else
linePos += sprintf(linePos, ", ");
@@ -1208,7 +1208,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) {
linePos += sprintf(linePos, "%04X: %10s %22s", cptId, _skyCompact->nameForType(type), name);
}
if (linePos != line)
- DebugPrintf("%s\n", line);
+ debugPrintf("%s\n", line);
} else {
for (int cpt = 0; cpt < _skyCompact->giveDataListLen(sec); cpt++) {
uint16 cptId = (uint16)((sec << 12) | cpt);
@@ -1216,7 +1216,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) {
char name[256];
_skyCompact->fetchCptInfo(cptId, &size, &type, name);
if (type == COMPACT)
- DebugPrintf("%04X: %s\n", cptId, name);
+ debugPrintf("%04X: %s\n", cptId, name);
}
}
}
@@ -1224,7 +1224,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) {
} else {
uint16 cptId = _skyCompact->findCptId(argv[1]);
if (cptId == 0)
- DebugPrintf("Unknown compact: '%s'\n", argv[1]);
+ debugPrintf("Unknown compact: '%s'\n", argv[1]);
else
dumpCompact(cptId);
}
@@ -1233,7 +1233,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) {
bool Debugger::Cmd_LogicCommand(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Example: %s fn_printf 42\n", argv[0]);
+ debugPrintf("Example: %s fn_printf 42\n", argv[0]);
return true;
}
@@ -1241,7 +1241,7 @@ bool Debugger::Cmd_LogicCommand(int argc, const char **argv) {
if (0 == strcmp(argv[1], "list")) {
for (int i = 0; i < numMCodes; ++i) {
- DebugPrintf("%s\n", mcodes[i]);
+ debugPrintf("%s\n", mcodes[i]);
}
return true;
}
@@ -1264,21 +1264,21 @@ bool Debugger::Cmd_LogicCommand(int argc, const char **argv) {
}
}
- DebugPrintf("Unknown function: '%s'\n", argv[1]);
+ debugPrintf("Unknown function: '%s'\n", argv[1]);
return true;
}
bool Debugger::Cmd_Info(int argc, const char **argv) {
- DebugPrintf("Beneath a Steel Sky version: 0.0%d\n", SkyEngine::_systemVars.gameVersion);
- DebugPrintf("Speech: %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_SPEECH) ? "on" : "off");
- DebugPrintf("Text : %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_TEXT) ? "on" : "off");
+ debugPrintf("Beneath a Steel Sky version: 0.0%d\n", SkyEngine::_systemVars.gameVersion);
+ debugPrintf("Speech: %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_SPEECH) ? "on" : "off");
+ debugPrintf("Text : %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_TEXT) ? "on" : "off");
return true;
}
bool Debugger::Cmd_ScriptVar(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Example: %s lamb_friend <value>\n", argv[0]);
+ debugPrintf("Example: %s lamb_friend <value>\n", argv[0]);
return true;
}
@@ -1286,7 +1286,7 @@ bool Debugger::Cmd_ScriptVar(int argc, const char **argv) {
if (0 == strcmp(argv[1], "list")) {
for (int i = 0; i < numScriptVars; ++i) {
- DebugPrintf("%s\n", scriptVars[i]);
+ debugPrintf("%s\n", scriptVars[i]);
}
return true;
}
@@ -1296,13 +1296,13 @@ bool Debugger::Cmd_ScriptVar(int argc, const char **argv) {
if (argc == 3) {
Logic::_scriptVariables[i] = atoi(argv[2]);
}
- DebugPrintf("%s = %d\n", argv[1], Logic::_scriptVariables[i]);
+ debugPrintf("%s = %d\n", argv[1], Logic::_scriptVariables[i]);
return true;
}
}
- DebugPrintf("Unknown ScriptVar: '%s'\n", argv[1]);
+ debugPrintf("Unknown ScriptVar: '%s'\n", argv[1]);
return true;
}
@@ -1317,30 +1317,30 @@ bool Debugger::Cmd_Section(int argc, const char **argv) {
_logic->fnAssignBase(ID_FOSTER, baseId[section], 0);
_skyCompact->fetchCpt(ID_FOSTER)->megaSet = 0;
} else {
- DebugPrintf("Section %d is out of range (range: %d - %d)\n", section, 0, 6);
+ debugPrintf("Section %d is out of range (range: %d - %d)\n", section, 0, 6);
}
} else {
- DebugPrintf("Example: %s 4\n", argv[0]);
+ debugPrintf("Example: %s 4\n", argv[0]);
}
return true;
}
bool Debugger::Cmd_LogicList(int argc, const char **argv) {
if (argc != 1)
- DebugPrintf("%s does not expect any parameters\n", argv[0]);
+ debugPrintf("%s does not expect any parameters\n", argv[0]);
char cptName[256];
uint16 numElems, type;
uint16 *logicList = (uint16 *)_skyCompact->fetchCptInfo(Logic::_scriptVariables[LOGIC_LIST_NO], &numElems, &type, cptName);
- DebugPrintf("Current LogicList: %04X (%s)\n", Logic::_scriptVariables[LOGIC_LIST_NO], cptName);
+ debugPrintf("Current LogicList: %04X (%s)\n", Logic::_scriptVariables[LOGIC_LIST_NO], cptName);
while (*logicList != 0) {
if (*logicList == 0xFFFF) {
uint16 newList = logicList[1];
logicList = (uint16 *)_skyCompact->fetchCptInfo(newList, &numElems, &type, cptName);
- DebugPrintf("New List: %04X (%s)\n", newList, cptName);
+ debugPrintf("New List: %04X (%s)\n", newList, cptName);
} else {
_skyCompact->fetchCptInfo(*logicList, &numElems, &type, cptName);
- DebugPrintf(" Cpt %04X (%s) (%s)\n", *logicList, cptName, _skyCompact->nameForType(type));
+ debugPrintf(" Cpt %04X (%s) (%s)\n", *logicList, cptName, _skyCompact->nameForType(type));
logicList++;
}
}
diff --git a/engines/sword1/POTFILES b/engines/sword1/POTFILES
index 849bef9060..b60d55ff22 100644
--- a/engines/sword1/POTFILES
+++ b/engines/sword1/POTFILES
@@ -1,4 +1,4 @@
engines/sword1/animation.cpp
engines/sword1/control.cpp
engines/sword1/logic.cpp
-engines/sword1/sword1.cpp
+
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 0257a805ff..ac358e774b 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -542,7 +542,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
Video::VideoDecoder *dxaDecoder = new Video::DXADecoder();
return new MoviePlayer(vm, textMan, resMan, system, dxaDecoder, kVideoDecoderDXA);
#else
- GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK"));
+ GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib"), _("OK"));
dialog.runModal();
return 0;
#endif
@@ -558,7 +558,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
Video::VideoDecoder *aviDecoder = new Video::AVIDecoder(12);
return new MoviePlayer(vm, textMan, resMan, system, aviDecoder, kVideoDecoderMP2);
#else
- GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2"), _("OK"));
+ GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"), _("OK"));
dialog.runModal();
return 0;
#endif
diff --git a/engines/sword1/console.cpp b/engines/sword1/console.cpp
index 3eb3b93a19..7fabc62192 100644
--- a/engines/sword1/console.cpp
+++ b/engines/sword1/console.cpp
@@ -22,14 +22,37 @@
#include "sword1/console.h"
#include "sword1/sword1.h"
+#include "sword1/sound.h"
+#include "common/config-manager.h"
+#include "common/str.h"
namespace Sword1 {
SwordConsole::SwordConsole(SwordEngine *vm) : GUI::Debugger(), _vm(vm) {
assert(_vm);
+ if (scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1mac") == 0 || scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1macdemo") == 0)
+ registerCmd("speechEndianness", WRAP_METHOD(SwordConsole, Cmd_SpeechEndianness));
}
SwordConsole::~SwordConsole() {
}
+
+bool SwordConsole::Cmd_SpeechEndianness(int argc, const char **argv) {
+ if (argc == 1) {
+ debugPrintf("Using %s speech\n", _vm->_sound->_bigEndianSpeech ? "be" : "le");
+ return true;
+ }
+ if (argc == 2) {
+ if (scumm_stricmp(argv[1], "le") == 0) {
+ _vm->_sound->_bigEndianSpeech = false;
+ return false;
+ } else if (scumm_stricmp(argv[1], "be") == 0) {
+ _vm->_sound->_bigEndianSpeech = true;
+ return false;
+ }
+ }
+ debugPrintf("Usage: %s [le | be]\n", argv[0]);
+ return true;
+}
} // End of namespace Sword
diff --git a/engines/sword1/console.h b/engines/sword1/console.h
index a2bb51f9a4..88ee756151 100644
--- a/engines/sword1/console.h
+++ b/engines/sword1/console.h
@@ -36,6 +36,7 @@ public:
private:
SwordEngine *_vm;
+ bool Cmd_SpeechEndianness(int argc, const char **argv);
};
} // End of namespace Sword1
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 0b4d3829d6..9140bddb65 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -116,7 +116,7 @@ void Sound::checkSpeechFileEndianness() {
return;
// I picked the sample to use randomly (I just made sure it is long enough so that there is
- // a fair change of the heuristic to have a stable result and work for every language).
+ // a fair chance of the heuristic to have a stable result and work for every language).
int roomNo = _currentCowFile == 1 ? 1 : 129;
int localNo = _currentCowFile == 1 ? 2 : 933;
// Get the speech data and apply the heuristic
@@ -125,32 +125,45 @@ void Sound::checkSpeechFileEndianness() {
uint32 index = _cowHeader[locIndex + (localNo * 2) - 1];
if (sampleSize) {
uint32 size;
- double be_diff_sum = 0., le_diff_sum = 0.;
+ // Compute average of difference between two consecutive samples for both BE and LE
_bigEndianSpeech = false;
int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
- // Compute average of difference between two consecutive samples for both BE and LE
- if (data) {
- if (size > 4000)
- size = 2000;
- else
- size /= 2;
- int16 prev_be_value = (int16)SWAP_BYTES_16(*((uint16 *)(data)));
- for (uint32 i = 1; i < size; ++i) {
- le_diff_sum += fabs((double)(data[i] - data[i - 1]));
- int16 be_value = (int16)SWAP_BYTES_16(*((uint16 *)(data + i)));
- be_diff_sum += fabs((double)(be_value - prev_be_value));
- prev_be_value = be_value;
- }
- delete[] data;
- }
+ uint32 maxSamples = size > 2000 ? 2000 : size;
+ double le_diff = endiannessHeuristicValue(data, size, maxSamples);
+ delete[] data;
+ _bigEndianSpeech = true;
+ data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
+ double be_diff = endiannessHeuristicValue(data, size, maxSamples);
+ delete [] data;
// Set the big endian flag
- _bigEndianSpeech = (be_diff_sum < le_diff_sum);
+ _bigEndianSpeech = (be_diff < le_diff);
if (_bigEndianSpeech)
debug(6, "Mac version: using big endian speech file");
else
debug(6, "Mac version: using little endian speech file");
- debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE, computed on %d samples)", be_diff_sum / (size - 1), le_diff_sum / (size - 1), size);
+ debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE (%d samples)", be_diff, le_diff, maxSamples);
+ }
+}
+
+double Sound::endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples) {
+ if (!data)
+ return 50000.; // the heuristic value for the wrong endianess is about 21000 (1/3rd of the 16 bits range)
+
+ double diff_sum = 0.;
+ uint32 cpt = 0;
+ int16 prev_value = (int16)FROM_LE_16(*((uint16 *)(data)));
+ for (uint32 i = 1; i < dataSize && cpt < maxSamples; ++i) {
+ int16 value = (int16)FROM_LE_16(*((uint16 *)(data + i)));
+ if (value != prev_value) {
+ diff_sum += fabs((double)(value - prev_value));
+ ++cpt;
+ prev_value = value;
+ }
}
+ if (cpt == 0)
+ return 50000.;
+ maxSamples = cpt;
+ return diff_sum / cpt;
}
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 666598dba0..e65e797934 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -79,6 +79,7 @@ enum CowMode {
};
class Sound {
+ friend class SwordConsole;
public:
Sound(Audio::Mixer *mixer, ResMan *pResMan);
~Sound();
@@ -101,6 +102,7 @@ public:
void engine();
void checkSpeechFileEndianness();
+ double endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples);
private:
uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR;
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 08ea02f32d..1e9b7f70f4 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -774,6 +774,8 @@ void SwordEngine::reinitRes() {
_logic->newScreen(Logic::_scriptVars[NEW_SCREEN]);
_sound->newScreen(Logic::_scriptVars[NEW_SCREEN]);
Logic::_scriptVars[SCREEN] = Logic::_scriptVars[NEW_SCREEN];
+ _logic->engine();
+ _logic->updateScreenParams();
_screen->fullRefresh();
_screen->draw();
}
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index c58e97e353..eb24ef70fa 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -79,6 +79,7 @@ struct SystemVars {
};
class SwordEngine : public Engine {
+ friend class SwordConsole;
public:
SwordEngine(OSystem *syst);
virtual ~SwordEngine();
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 92fa9d0e44..e93f27f76c 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -442,7 +442,7 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system
Video::DXADecoder *dxaDecoder = new Video::DXADecoder();
return new MoviePlayer(vm, system, dxaDecoder, kVideoDecoderDXA);
#else
- GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK"));
+ GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib"), _("OK"));
dialog.runModal();
return NULL;
#endif
diff --git a/engines/sword2/console.cpp b/engines/sword2/console.cpp
index 4838bd15f6..0aa78f552b 100644
--- a/engines/sword2/console.cpp
+++ b/engines/sword2/console.cpp
@@ -82,55 +82,55 @@ Debugger::Debugger(Sword2Engine *vm)
// Register commands
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("q", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("mem", WRAP_METHOD(Debugger, Cmd_Mem));
- DCmd_Register("tony", WRAP_METHOD(Debugger, Cmd_Tony));
- DCmd_Register("res", WRAP_METHOD(Debugger, Cmd_Res));
- DCmd_Register("reslist", WRAP_METHOD(Debugger, Cmd_ResList));
- DCmd_Register("starts", WRAP_METHOD(Debugger, Cmd_Starts));
- DCmd_Register("start", WRAP_METHOD(Debugger, Cmd_Start));
- DCmd_Register("s", WRAP_METHOD(Debugger, Cmd_Start));
- DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info));
- DCmd_Register("walkgrid", WRAP_METHOD(Debugger, Cmd_WalkGrid));
- DCmd_Register("mouse", WRAP_METHOD(Debugger, Cmd_Mouse));
- DCmd_Register("player", WRAP_METHOD(Debugger, Cmd_Player));
- DCmd_Register("reslook", WRAP_METHOD(Debugger, Cmd_ResLook));
- DCmd_Register("cur", WRAP_METHOD(Debugger, Cmd_CurrentInfo));
- DCmd_Register("runlist", WRAP_METHOD(Debugger, Cmd_RunList));
- DCmd_Register("kill", WRAP_METHOD(Debugger, Cmd_Kill));
- DCmd_Register("nuke", WRAP_METHOD(Debugger, Cmd_Nuke));
- DCmd_Register("var", WRAP_METHOD(Debugger, Cmd_Var));
- DCmd_Register("rect", WRAP_METHOD(Debugger, Cmd_Rect));
- DCmd_Register("clear", WRAP_METHOD(Debugger, Cmd_Clear));
- DCmd_Register("debugon", WRAP_METHOD(Debugger, Cmd_DebugOn));
- DCmd_Register("debugoff", WRAP_METHOD(Debugger, Cmd_DebugOff));
- DCmd_Register("saverest", WRAP_METHOD(Debugger, Cmd_SaveRest));
- DCmd_Register("timeon", WRAP_METHOD(Debugger, Cmd_TimeOn));
- DCmd_Register("timeoff", WRAP_METHOD(Debugger, Cmd_TimeOff));
- DCmd_Register("text", WRAP_METHOD(Debugger, Cmd_Text));
- DCmd_Register("showvar", WRAP_METHOD(Debugger, Cmd_ShowVar));
- DCmd_Register("hidevar", WRAP_METHOD(Debugger, Cmd_HideVar));
- DCmd_Register("version", WRAP_METHOD(Debugger, Cmd_Version));
- DCmd_Register("animtest", WRAP_METHOD(Debugger, Cmd_AnimTest));
- DCmd_Register("texttest", WRAP_METHOD(Debugger, Cmd_TextTest));
- DCmd_Register("linetest", WRAP_METHOD(Debugger, Cmd_LineTest));
- DCmd_Register("events", WRAP_METHOD(Debugger, Cmd_Events));
- DCmd_Register("sfx", WRAP_METHOD(Debugger, Cmd_Sfx));
- DCmd_Register("english", WRAP_METHOD(Debugger, Cmd_English));
- DCmd_Register("finnish", WRAP_METHOD(Debugger, Cmd_Finnish));
- DCmd_Register("polish", WRAP_METHOD(Debugger, Cmd_Polish));
- DCmd_Register("fxq", WRAP_METHOD(Debugger, Cmd_FxQueue));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("q", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("mem", WRAP_METHOD(Debugger, Cmd_Mem));
+ registerCmd("tony", WRAP_METHOD(Debugger, Cmd_Tony));
+ registerCmd("res", WRAP_METHOD(Debugger, Cmd_Res));
+ registerCmd("reslist", WRAP_METHOD(Debugger, Cmd_ResList));
+ registerCmd("starts", WRAP_METHOD(Debugger, Cmd_Starts));
+ registerCmd("start", WRAP_METHOD(Debugger, Cmd_Start));
+ registerCmd("s", WRAP_METHOD(Debugger, Cmd_Start));
+ registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info));
+ registerCmd("walkgrid", WRAP_METHOD(Debugger, Cmd_WalkGrid));
+ registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse));
+ registerCmd("player", WRAP_METHOD(Debugger, Cmd_Player));
+ registerCmd("reslook", WRAP_METHOD(Debugger, Cmd_ResLook));
+ registerCmd("cur", WRAP_METHOD(Debugger, Cmd_CurrentInfo));
+ registerCmd("runlist", WRAP_METHOD(Debugger, Cmd_RunList));
+ registerCmd("kill", WRAP_METHOD(Debugger, Cmd_Kill));
+ registerCmd("nuke", WRAP_METHOD(Debugger, Cmd_Nuke));
+ registerCmd("var", WRAP_METHOD(Debugger, Cmd_Var));
+ registerCmd("rect", WRAP_METHOD(Debugger, Cmd_Rect));
+ registerCmd("clear", WRAP_METHOD(Debugger, Cmd_Clear));
+ registerCmd("debugon", WRAP_METHOD(Debugger, Cmd_DebugOn));
+ registerCmd("debugoff", WRAP_METHOD(Debugger, Cmd_DebugOff));
+ registerCmd("saverest", WRAP_METHOD(Debugger, Cmd_SaveRest));
+ registerCmd("timeon", WRAP_METHOD(Debugger, Cmd_TimeOn));
+ registerCmd("timeoff", WRAP_METHOD(Debugger, Cmd_TimeOff));
+ registerCmd("text", WRAP_METHOD(Debugger, Cmd_Text));
+ registerCmd("showvar", WRAP_METHOD(Debugger, Cmd_ShowVar));
+ registerCmd("hidevar", WRAP_METHOD(Debugger, Cmd_HideVar));
+ registerCmd("version", WRAP_METHOD(Debugger, Cmd_Version));
+ registerCmd("animtest", WRAP_METHOD(Debugger, Cmd_AnimTest));
+ registerCmd("texttest", WRAP_METHOD(Debugger, Cmd_TextTest));
+ registerCmd("linetest", WRAP_METHOD(Debugger, Cmd_LineTest));
+ registerCmd("events", WRAP_METHOD(Debugger, Cmd_Events));
+ registerCmd("sfx", WRAP_METHOD(Debugger, Cmd_Sfx));
+ registerCmd("english", WRAP_METHOD(Debugger, Cmd_English));
+ registerCmd("finnish", WRAP_METHOD(Debugger, Cmd_Finnish));
+ registerCmd("polish", WRAP_METHOD(Debugger, Cmd_Polish));
+ registerCmd("fxq", WRAP_METHOD(Debugger, Cmd_FxQueue));
}
void Debugger::varGet(int var) {
- DebugPrintf("%d\n", _vm->_logic->readVar(var));
+ debugPrintf("%d\n", _vm->_logic->readVar(var));
}
void Debugger::varSet(int var, int val) {
- DebugPrintf("was %d, ", _vm->_logic->readVar(var));
+ debugPrintf("was %d, ", _vm->_logic->readVar(var));
_vm->_logic->writeVar(var, val);
- DebugPrintf("now %d\n", _vm->_logic->readVar(var));
+ debugPrintf("now %d\n", _vm->_logic->readVar(var));
}
void Debugger::preEnter() {
@@ -184,8 +184,8 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) {
qsort(blocks, numBlocks, sizeof(MemBlock *), compare_blocks);
- DebugPrintf(" size id res type name\n");
- DebugPrintf("---------------------------------------------------------------------------\n");
+ debugPrintf(" size id res type name\n");
+ debugPrintf("---------------------------------------------------------------------------\n");
for (i = 0; i < numBlocks; i++) {
const char *type;
@@ -235,21 +235,21 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) {
break;
}
- DebugPrintf("%9d %-3d %-4d %-20s %s\n",
+ debugPrintf("%9d %-3d %-4d %-20s %s\n",
blocks[i]->size, blocks[i]->id, blocks[i]->uid,
type, _vm->_resman->fetchName(blocks[i]->ptr));
}
free(blocks);
- DebugPrintf("---------------------------------------------------------------------------\n");
- DebugPrintf("%9d\n", _vm->_memory->getTotAlloc());
+ debugPrintf("---------------------------------------------------------------------------\n");
+ debugPrintf("%9d\n", _vm->_memory->getTotAlloc());
return true;
}
bool Debugger::Cmd_Tony(int argc, const char **argv) {
- DebugPrintf("What about him?\n");
+ debugPrintf("What about him?\n");
return true;
}
@@ -257,7 +257,7 @@ bool Debugger::Cmd_Res(int argc, const char **argv) {
uint32 numClusters = _vm->_resman->getNumClusters();
if (!numClusters) {
- DebugPrintf("Argh! No resources!\n");
+ debugPrintf("Argh! No resources!\n");
return true;
}
@@ -266,10 +266,10 @@ bool Debugger::Cmd_Res(int argc, const char **argv) {
for (uint i = 0; i < numClusters; i++) {
const char *locStr[3] = { "HDD", "CD1", "CD2" };
- DebugPrintf("%-20s %s\n", resFiles[i].fileName, locStr[resFiles[i].cd]);
+ debugPrintf("%-20s %s\n", resFiles[i].fileName, locStr[resFiles[i].cd]);
}
- DebugPrintf("%d resources\n", _vm->_resman->getNumResFiles());
+ debugPrintf("%d resources\n", _vm->_resman->getNumResFiles());
return true;
}
@@ -285,7 +285,7 @@ bool Debugger::Cmd_ResList(int argc, const char **argv) {
for (uint i = 0; i < numResFiles; i++) {
if (resList[i].ptr && resList[i].refCount >= minCount) {
- DebugPrintf("%-4d: %-35s refCount: %-3d\n", i, _vm->_resman->fetchName(resList[i].ptr), resList[i].refCount);
+ debugPrintf("%-4d: %-35s refCount: %-3d\n", i, _vm->_resman->fetchName(resList[i].ptr), resList[i].refCount);
}
}
@@ -296,21 +296,21 @@ bool Debugger::Cmd_Starts(int argc, const char **argv) {
uint32 numStarts = _vm->getNumStarts();
if (!numStarts) {
- DebugPrintf("Sorry - no startup positions registered?\n");
+ debugPrintf("Sorry - no startup positions registered?\n");
uint32 numScreenManagers = _vm->getNumScreenManagers();
if (!numScreenManagers)
- DebugPrintf("There is a problem with startup.inf\n");
+ debugPrintf("There is a problem with startup.inf\n");
else
- DebugPrintf(" (%d screen managers found in startup.inf)\n", numScreenManagers);
+ debugPrintf(" (%d screen managers found in startup.inf)\n", numScreenManagers);
return true;
}
StartUp *startList = _vm->getStartList();
for (uint i = 0; i < numStarts; i++)
- DebugPrintf("%d (%s)\n", i, startList[i].description);
+ debugPrintf("%d (%s)\n", i, startList[i].description);
return true;
}
@@ -319,25 +319,25 @@ bool Debugger::Cmd_Start(int argc, const char **argv) {
uint8 pal[3] = { 255, 255, 255 };
if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
+ debugPrintf("Usage: %s number\n", argv[0]);
return true;
}
uint32 numStarts = _vm->getNumStarts();
if (!numStarts) {
- DebugPrintf("Sorry - there are no startups!\n");
+ debugPrintf("Sorry - there are no startups!\n");
return true;
}
int start = atoi(argv[1]);
if (start < 0 || start >= (int)numStarts) {
- DebugPrintf("Not a legal start position\n");
+ debugPrintf("Not a legal start position\n");
return true;
}
- DebugPrintf("Running start %d\n", start);
+ debugPrintf("Running start %d\n", start);
_vm->runStart(start);
_vm->_screen->setPalette(187, 1, pal, RDPAL_INSTANT);
@@ -348,9 +348,9 @@ bool Debugger::Cmd_Info(int argc, const char **argv) {
_displayDebugText = !_displayDebugText;
if (_displayDebugText)
- DebugPrintf("Info text on\n");
+ debugPrintf("Info text on\n");
else
- DebugPrintf("Info Text off\n");
+ debugPrintf("Info Text off\n");
return true;
}
@@ -359,9 +359,9 @@ bool Debugger::Cmd_WalkGrid(int argc, const char **argv) {
_displayWalkGrid = !_displayWalkGrid;
if (_displayWalkGrid)
- DebugPrintf("Walk-grid display on\n");
+ debugPrintf("Walk-grid display on\n");
else
- DebugPrintf("Walk-grid display off\n");
+ debugPrintf("Walk-grid display off\n");
return true;
}
@@ -370,9 +370,9 @@ bool Debugger::Cmd_Mouse(int argc, const char **argv) {
_displayMouseMarker = !_displayMouseMarker;
if (_displayMouseMarker)
- DebugPrintf("Mouse marker on\n");
+ debugPrintf("Mouse marker on\n");
else
- DebugPrintf("Mouse marker off\n");
+ debugPrintf("Mouse marker off\n");
return true;
}
@@ -381,16 +381,16 @@ bool Debugger::Cmd_Player(int argc, const char **argv) {
_displayPlayerMarker = !_displayPlayerMarker;
if (_displayPlayerMarker)
- DebugPrintf("Player feet marker on\n");
+ debugPrintf("Player feet marker on\n");
else
- DebugPrintf("Player feet marker off\n");
+ debugPrintf("Player feet marker off\n");
return true;
}
bool Debugger::Cmd_ResLook(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
+ debugPrintf("Usage: %s number\n", argv[0]);
return true;
}
@@ -398,13 +398,13 @@ bool Debugger::Cmd_ResLook(int argc, const char **argv) {
uint32 numResFiles = _vm->_resman->getNumResFiles();
if (res < 0 || res >= (int)numResFiles) {
- DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n",
+ debugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n",
res, numResFiles, numResFiles - 1);
return true;
}
if (!_vm->_resman->checkValid(res)) {
- DebugPrintf("%d is a null & void resource number\n", res);
+ debugPrintf("%d is a null & void resource number\n", res);
return true;
}
@@ -413,40 +413,40 @@ bool Debugger::Cmd_ResLook(int argc, const char **argv) {
switch (type) {
case ANIMATION_FILE:
- DebugPrintf("<anim> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<anim> %s\n", _vm->_resman->fetchName(res));
break;
case SCREEN_FILE:
- DebugPrintf("<layer> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<layer> %s\n", _vm->_resman->fetchName(res));
break;
case GAME_OBJECT:
- DebugPrintf("<game object> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<game object> %s\n", _vm->_resman->fetchName(res));
break;
case WALK_GRID_FILE:
- DebugPrintf("<walk grid> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<walk grid> %s\n", _vm->_resman->fetchName(res));
break;
case GLOBAL_VAR_FILE:
- DebugPrintf("<global variables> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<global variables> %s\n", _vm->_resman->fetchName(res));
break;
case PARALLAX_FILE_null:
- DebugPrintf("<parallax file NOT USED!> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<parallax file NOT USED!> %s\n", _vm->_resman->fetchName(res));
break;
case RUN_LIST:
- DebugPrintf("<run list> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<run list> %s\n", _vm->_resman->fetchName(res));
break;
case TEXT_FILE:
- DebugPrintf("<text file> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<text file> %s\n", _vm->_resman->fetchName(res));
break;
case SCREEN_MANAGER:
- DebugPrintf("<screen manager> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<screen manager> %s\n", _vm->_resman->fetchName(res));
break;
case MOUSE_FILE:
- DebugPrintf("<mouse pointer> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<mouse pointer> %s\n", _vm->_resman->fetchName(res));
break;
case ICON_FILE:
- DebugPrintf("<menu icon> %s\n", _vm->_resman->fetchName(res));
+ debugPrintf("<menu icon> %s\n", _vm->_resman->fetchName(res));
break;
default:
- DebugPrintf("unrecognized fileType %d\n", type);
+ debugPrintf("unrecognized fileType %d\n", type);
break;
}
@@ -458,13 +458,13 @@ bool Debugger::Cmd_CurrentInfo(int argc, const char **argv) {
ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
if (screenInfo->background_layer_id) {
- DebugPrintf("background layer id %d\n", screenInfo->background_layer_id);
- DebugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep);
- DebugPrintf("%d normal layers\n", screenInfo->number_of_layers);
+ debugPrintf("background layer id %d\n", screenInfo->background_layer_id);
+ debugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep);
+ debugPrintf("%d normal layers\n", screenInfo->number_of_layers);
Cmd_RunList(argc, argv);
} else
- DebugPrintf("No screen\n");
+ debugPrintf("No screen\n");
return true;
}
@@ -476,26 +476,26 @@ bool Debugger::Cmd_RunList(int argc, const char **argv) {
readS.seek(ResHeader::size());
- DebugPrintf("Runlist number %d\n", runList);
+ debugPrintf("Runlist number %d\n", runList);
while (1) {
uint32 res = readS.readUint32LE();
if (!res)
break;
- DebugPrintf("%d %s\n", res, _vm->_resman->fetchName(res));
+ debugPrintf("%d %s\n", res, _vm->_resman->fetchName(res));
}
_vm->_resman->closeResource(runList);
} else
- DebugPrintf("No run list set\n");
+ debugPrintf("No run list set\n");
return true;
}
bool Debugger::Cmd_Kill(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
+ debugPrintf("Usage: %s number\n", argv[0]);
return true;
}
@@ -503,7 +503,7 @@ bool Debugger::Cmd_Kill(int argc, const char **argv) {
uint32 numResFiles = _vm->_resman->getNumResFiles();
if (res < 0 || res >= (int)numResFiles) {
- DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n",
+ debugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n",
res, numResFiles, numResFiles - 1);
return true;
}
@@ -511,22 +511,22 @@ bool Debugger::Cmd_Kill(int argc, const char **argv) {
Resource *resList = _vm->_resman->getResList();
if (!resList[res].ptr) {
- DebugPrintf("Resource %d is not in memory\n", res);
+ debugPrintf("Resource %d is not in memory\n", res);
return true;
}
if (resList[res].refCount) {
- DebugPrintf("Resource %d is open - cannot remove\n", res);
+ debugPrintf("Resource %d is open - cannot remove\n", res);
return true;
}
_vm->_resman->remove(res);
- DebugPrintf("Trashed %d\n", res);
+ debugPrintf("Trashed %d\n", res);
return true;
}
bool Debugger::Cmd_Nuke(int argc, const char **argv) {
- DebugPrintf("Killing all resources except variable file and player object\n");
+ debugPrintf("Killing all resources except variable file and player object\n");
_vm->_resman->killAll(true);
return true;
}
@@ -540,7 +540,7 @@ bool Debugger::Cmd_Var(int argc, const char **argv) {
varSet(atoi(argv[1]), atoi(argv[2]));
break;
default:
- DebugPrintf("Usage: %s number value\n", argv[0]);
+ debugPrintf("Usage: %s number value\n", argv[0]);
break;
}
@@ -554,10 +554,10 @@ bool Debugger::Cmd_Rect(int argc, const char **argv) {
if (_definingRectangles) {
_vm->setInputEventFilter(filter & ~(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP));
- DebugPrintf("Mouse rectangles enabled\n");
+ debugPrintf("Mouse rectangles enabled\n");
} else {
_vm->setInputEventFilter(filter | RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP);
- DebugPrintf("Mouse rectangles disabled\n");
+ debugPrintf("Mouse rectangles disabled\n");
}
_draggingRectangle = 0;
@@ -575,7 +575,7 @@ bool Debugger::Cmd_DebugOn(int argc, const char **argv) {
_displayMouseMarker = true;
_displayPlayerMarker = true;
_displayTextNumbers = true;
- DebugPrintf("Enabled all on-screen debug info\n");
+ debugPrintf("Enabled all on-screen debug info\n");
return true;
}
@@ -585,7 +585,7 @@ bool Debugger::Cmd_DebugOff(int argc, const char **argv) {
_displayMouseMarker = false;
_displayPlayerMarker = false;
_displayTextNumbers = false;
- DebugPrintf("Disabled all on-screen debug info\n");
+ debugPrintf("Disabled all on-screen debug info\n");
return true;
}
@@ -593,9 +593,9 @@ bool Debugger::Cmd_SaveRest(int argc, const char **argv) {
_testingSnR = !_testingSnR;
if (_testingSnR)
- DebugPrintf("Enabled S&R logic_script stability checking\n");
+ debugPrintf("Enabled S&R logic_script stability checking\n");
else
- DebugPrintf("Disabled S&R logic_script stability checking\n");
+ debugPrintf("Disabled S&R logic_script stability checking\n");
return true;
}
@@ -606,13 +606,13 @@ bool Debugger::Cmd_TimeOn(int argc, const char **argv) {
else if (_startTime == 0)
_startTime = _vm->_system->getMillis();
_displayTime = true;
- DebugPrintf("Timer display on\n");
+ debugPrintf("Timer display on\n");
return true;
}
bool Debugger::Cmd_TimeOff(int argc, const char **argv) {
_displayTime = false;
- DebugPrintf("Timer display off\n");
+ debugPrintf("Timer display off\n");
return true;
}
@@ -620,9 +620,9 @@ bool Debugger::Cmd_Text(int argc, const char **argv) {
_displayTextNumbers = !_displayTextNumbers;
if (_displayTextNumbers)
- DebugPrintf("Text numbers on\n");
+ debugPrintf("Text numbers on\n");
else
- DebugPrintf("Text numbers off\n");
+ debugPrintf("Text numbers off\n");
return true;
}
@@ -632,7 +632,7 @@ bool Debugger::Cmd_ShowVar(int argc, const char **argv) {
int32 varNo;
if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
+ debugPrintf("Usage: %s number\n", argv[0]);
return true;
}
@@ -649,11 +649,11 @@ bool Debugger::Cmd_ShowVar(int argc, const char **argv) {
if (_showVar[showVarNo] == 0) {
// empty slot - add it to the list at this slot
_showVar[showVarNo] = varNo;
- DebugPrintf("var(%d) added to the watch-list\n", varNo);
+ debugPrintf("var(%d) added to the watch-list\n", varNo);
} else
- DebugPrintf("var(%d) already in the watch-list!\n", varNo);
+ debugPrintf("var(%d) already in the watch-list!\n", varNo);
} else
- DebugPrintf("Sorry - no more allowed - hide one or extend the system watch-list\n");
+ debugPrintf("Sorry - no more allowed - hide one or extend the system watch-list\n");
return true;
}
@@ -663,7 +663,7 @@ bool Debugger::Cmd_HideVar(int argc, const char **argv) {
int32 varNo;
if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
+ debugPrintf("Usage: %s number\n", argv[0]);
return true;
}
@@ -676,9 +676,9 @@ bool Debugger::Cmd_HideVar(int argc, const char **argv) {
if (showVarNo < MAX_SHOWVARS) {
// We've found 'varNo' in the list - clear this slot
_showVar[showVarNo] = 0;
- DebugPrintf("var(%d) removed from watch-list\n", varNo);
+ debugPrintf("var(%d) removed from watch-list\n", varNo);
} else
- DebugPrintf("Sorry - can't find var(%d) in the list\n", varNo);
+ debugPrintf("Sorry - can't find var(%d) in the list\n", varNo);
return true;
}
@@ -687,13 +687,13 @@ bool Debugger::Cmd_Version(int argc, const char **argv) {
// This function used to print more information, but nothing we
// particularly care about.
- DebugPrintf("\"Broken Sword II\" (c) Revolution Software 1997.\n");
+ debugPrintf("\"Broken Sword II\" (c) Revolution Software 1997.\n");
return true;
}
bool Debugger::Cmd_AnimTest(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: %s value\n", argv[0]);
+ debugPrintf("Usage: %s value\n", argv[0]);
return true;
}
@@ -703,13 +703,13 @@ bool Debugger::Cmd_AnimTest(int argc, const char **argv) {
// Same as typing "VAR 912 <value>" at the console
varSet(912, atoi(argv[1]));
- DebugPrintf("Setting flag 'system_testing_anims'\n");
+ debugPrintf("Setting flag 'system_testing_anims'\n");
return true;
}
bool Debugger::Cmd_TextTest(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: %s value\n", argv[0]);
+ debugPrintf("Usage: %s value\n", argv[0]);
return true;
}
@@ -721,14 +721,14 @@ bool Debugger::Cmd_TextTest(int argc, const char **argv) {
_displayTextNumbers = true;
- DebugPrintf("Setting flag 'system_testing_text'\n");
- DebugPrintf("Text numbers on\n");
+ debugPrintf("Setting flag 'system_testing_text'\n");
+ debugPrintf("Text numbers on\n");
return true;
}
bool Debugger::Cmd_LineTest(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Usage: %s value1 value2\n", argv[0]);
+ debugPrintf("Usage: %s value1 value2\n", argv[0]);
return true;
}
@@ -743,24 +743,24 @@ bool Debugger::Cmd_LineTest(int argc, const char **argv) {
_displayTextNumbers = true;
- DebugPrintf("Setting flag 'system_testing_text'\n");
- DebugPrintf("Setting flag 'system_test_line_no'\n");
- DebugPrintf("Text numbers on\n");
+ debugPrintf("Setting flag 'system_testing_text'\n");
+ debugPrintf("Setting flag 'system_test_line_no'\n");
+ debugPrintf("Text numbers on\n");
return true;
}
bool Debugger::Cmd_Events(int argc, const char **argv) {
EventUnit *eventList = _vm->_logic->getEventList();
- DebugPrintf("EVENT LIST:\n");
+ debugPrintf("EVENT LIST:\n");
for (uint32 i = 0; i < MAX_events; i++) {
if (eventList[i].id) {
uint32 target = eventList[i].id;
uint32 script = eventList[i].interact_id;
- DebugPrintf("slot %2d: id = %s (%d)\n", i, _vm->_resman->fetchName(target), target);
- DebugPrintf(" script = %s (%d) pos %d\n", _vm->_resman->fetchName(script / 65536), script / 65536, script % 65536);
+ debugPrintf("slot %2d: id = %s (%d)\n", i, _vm->_resman->fetchName(target), target);
+ debugPrintf(" script = %s (%d) pos %d\n", _vm->_resman->fetchName(script / 65536), script / 65536, script % 65536);
}
}
@@ -771,28 +771,28 @@ bool Debugger::Cmd_Sfx(int argc, const char **argv) {
_vm->_wantSfxDebug = !_vm->_wantSfxDebug;
if (_vm->_wantSfxDebug)
- DebugPrintf("SFX logging activated\n");
+ debugPrintf("SFX logging activated\n");
else
- DebugPrintf("SFX logging deactivated\n");
+ debugPrintf("SFX logging deactivated\n");
return true;
}
bool Debugger::Cmd_English(int argc, const char **argv) {
_vm->initializeFontResourceFlags(DEFAULT_TEXT);
- DebugPrintf("Default fonts selected\n");
+ debugPrintf("Default fonts selected\n");
return true;
}
bool Debugger::Cmd_Finnish(int argc, const char **argv) {
_vm->initializeFontResourceFlags(FINNISH_TEXT);
- DebugPrintf("Finnish fonts selected\n");
+ debugPrintf("Finnish fonts selected\n");
return true;
}
bool Debugger::Cmd_Polish(int argc, const char **argv) {
_vm->initializeFontResourceFlags(POLISH_TEXT);
- DebugPrintf("Polish fonts selected\n");
+ debugPrintf("Polish fonts selected\n");
return true;
}
diff --git a/engines/sword2/resman.cpp b/engines/sword2/resman.cpp
index a0561641d7..44027fd281 100644
--- a/engines/sword2/resman.cpp
+++ b/engines/sword2/resman.cpp
@@ -38,7 +38,7 @@
#include "sword2/screen.h"
#include "sword2/sound.h"
-#define Debug_Printf _vm->_debugger->DebugPrintf
+#define Debug_Printf _vm->_debugger->debugPrintf
namespace Sword2 {
diff --git a/engines/sword2/sound.cpp b/engines/sword2/sound.cpp
index aea33e99e3..1e1687b1e6 100644
--- a/engines/sword2/sound.cpp
+++ b/engines/sword2/sound.cpp
@@ -49,7 +49,7 @@
#include "audio/decoders/wave.h"
#include "audio/decoders/xa.h"
-#define Debug_Printf _vm->_debugger->DebugPrintf
+#define Debug_Printf _vm->_debugger->debugPrintf
namespace Sword2 {
diff --git a/engines/sword25/gfx/animation.cpp b/engines/sword25/gfx/animation.cpp
index eeb78857ea..e2662fb2b3 100644
--- a/engines/sword25/gfx/animation.cpp
+++ b/engines/sword25/gfx/animation.cpp
@@ -189,14 +189,14 @@ bool Animation::doRender(RectangleList *updateRects) {
bool result;
if (isScalingAllowed() && (_width != pBitmapResource->getWidth() || _height != pBitmapResource->getHeight())) {
result = pBitmapResource->blit(_absoluteX, _absoluteY,
- (animationDescriptionPtr->getFrame(_currentFrame).flipV ? BitmapResource::FLIP_V : 0) |
- (animationDescriptionPtr->getFrame(_currentFrame).flipH ? BitmapResource::FLIP_H : 0),
+ (animationDescriptionPtr->getFrame(_currentFrame).flipV ? Graphics::FLIP_V : 0) |
+ (animationDescriptionPtr->getFrame(_currentFrame).flipH ? Graphics::FLIP_H : 0),
0, _modulationColor, _width, _height,
updateRects);
} else {
result = pBitmapResource->blit(_absoluteX, _absoluteY,
- (animationDescriptionPtr->getFrame(_currentFrame).flipV ? BitmapResource::FLIP_V : 0) |
- (animationDescriptionPtr->getFrame(_currentFrame).flipH ? BitmapResource::FLIP_H : 0),
+ (animationDescriptionPtr->getFrame(_currentFrame).flipV ? Graphics::FLIP_V : 0) |
+ (animationDescriptionPtr->getFrame(_currentFrame).flipH ? Graphics::FLIP_H : 0),
0, _modulationColor, -1, -1,
updateRects);
}
diff --git a/engines/sword25/gfx/bitmapresource.h b/engines/sword25/gfx/bitmapresource.h
index 7a4daedd84..2ae891f5cd 100644
--- a/engines/sword25/gfx/bitmapresource.h
+++ b/engines/sword25/gfx/bitmapresource.h
@@ -40,22 +40,6 @@ namespace Sword25 {
class BitmapResource : public Resource {
public:
- /**
- @brief Die möglichen Flippingparameter für die Blit-Methode.
- */
- enum FLIP_FLAGS {
- /// Das Bild wird nicht gespiegelt.
- FLIP_NONE = 0,
- /// Das Bild wird an der horizontalen Achse gespiegelt.
- FLIP_H = 1,
- /// Das Bild wird an der vertikalen Achse gespiegelt.
- FLIP_V = 2,
- /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt.
- FLIP_HV = FLIP_H | FLIP_V,
- /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt.
- FLIP_VH = FLIP_H | FLIP_V
- };
-
BitmapResource(const Common::String &filename, Image *pImage) :
_pImage(pImage), Resource(filename, Resource::TYPE_BITMAP) {}
virtual ~BitmapResource() { delete _pImage; }
@@ -120,7 +104,7 @@ public:
- IsColorModulationAllowed()
*/
bool blit(int posX = 0, int posY = 0,
- int flipping = FLIP_NONE,
+ int flipping = Graphics::FLIP_NONE,
Common::Rect *pSrcPartRect = NULL,
uint color = BS_ARGB(255, 255, 255, 255),
int width = -1, int height = -1,
diff --git a/engines/sword25/gfx/dynamicbitmap.cpp b/engines/sword25/gfx/dynamicbitmap.cpp
index ce9c056d08..a335f87fa5 100644
--- a/engines/sword25/gfx/dynamicbitmap.cpp
+++ b/engines/sword25/gfx/dynamicbitmap.cpp
@@ -86,8 +86,8 @@ bool DynamicBitmap::doRender(RectangleList *updateRects) {
// a bit slow when drawing videos, but it's not the main
// bottleneck.
result = _image->blit(_absoluteX, _absoluteY,
- (_flipV ? BitmapResource::FLIP_V : 0) |
- (_flipH ? BitmapResource::FLIP_H : 0),
+ (_flipV ? Graphics::FLIP_V : 0) |
+ (_flipH ? Graphics::FLIP_H : 0),
0, _modulationColor, -1, -1,
updateRects);
#else
@@ -105,8 +105,8 @@ bool DynamicBitmap::doRender(RectangleList *updateRects) {
return true;
} else {
result = _image->blit(_absoluteX, _absoluteY,
- (_flipV ? BitmapResource::FLIP_V : 0) |
- (_flipH ? BitmapResource::FLIP_H : 0),
+ (_flipV ? Graphics::FLIP_V : 0) |
+ (_flipH ? Graphics::FLIP_H : 0),
0, _modulationColor, _width, _height,
updateRects);
}
diff --git a/engines/sword25/gfx/graphicengine.cpp b/engines/sword25/gfx/graphicengine.cpp
index 2a870c021d..f887c3cd51 100644
--- a/engines/sword25/gfx/graphicengine.cpp
+++ b/engines/sword25/gfx/graphicengine.cpp
@@ -183,7 +183,7 @@ bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) {
if (rect.width() > 0 && rect.height() > 0) {
if (ca == 0xff) {
- _backSurface.fillRect(rect, color);
+ _backSurface.fillRect(rect, BS_ARGB(cr, cg, cb, ca));
} else {
byte *outo = (byte *)_backSurface.getBasePtr(rect.left, rect.top);
byte *out;
@@ -192,23 +192,23 @@ bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) {
out = outo;
for (int j = rect.left; j < rect.right; j++) {
#if defined(SCUMM_LITTLE_ENDIAN)
+ *out = 255;
+ out++;
*out += (byte)(((cb - *out) * ca) >> 8);
out++;
*out += (byte)(((cg - *out) * ca) >> 8);
out++;
*out += (byte)(((cr - *out) * ca) >> 8);
out++;
- *out = 255;
- out++;
#else
- *out = 255;
- out++;
*out += (byte)(((cr - *out) * ca) >> 8);
out++;
*out += (byte)(((cg - *out) * ca) >> 8);
out++;
*out += (byte)(((cb - *out) * ca) >> 8);
out++;
+ *out = 255;
+ out++;
#endif
}
diff --git a/engines/sword25/gfx/image/image.h b/engines/sword25/gfx/image/image.h
index 8fbf802501..f8cb0dfec0 100644
--- a/engines/sword25/gfx/image/image.h
+++ b/engines/sword25/gfx/image/image.h
@@ -43,6 +43,7 @@
#include "sword25/kernel/common.h"
#include "common/rect.h"
#include "sword25/gfx/graphicengine.h"
+#include "graphics/transparent_surface.h"
namespace Sword25 {
@@ -52,23 +53,6 @@ class Image {
public:
virtual ~Image() {}
- // Enums
- /**
- @brief The possible flipping parameters for the blit methode.
- */
- enum FLIP_FLAGS {
- /// The image will not be flipped.
- FLIP_NONE = 0,
- /// The image will be flipped at the horizontal axis.
- FLIP_H = 1,
- /// The image will be flipped at the vertical axis.
- FLIP_V = 2,
- /// The image will be flipped at the horizontal and vertical axis.
- FLIP_HV = FLIP_H | FLIP_V,
- /// The image will be flipped at the horizontal and vertical axis.
- FLIP_VH = FLIP_H | FLIP_V
- };
-
//@{
/** @name Accessor methods */
@@ -100,7 +84,7 @@ public:
@param PosY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.<br>
The default value is 0.
@param Flipping how the the image should be flipped.<br>
- The default value is BS_Image::FLIP_NONE (no flipping)
+ The default value is Graphics::FLIP_NONE (no flipping)
@param pSrcPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.<br>
This referes to the unflipped and unscaled image.<br>
The default value is NULL.
@@ -128,7 +112,7 @@ public:
- IsSetContentAllowed()
*/
virtual bool blit(int posX = 0, int posY = 0,
- int flipping = FLIP_NONE,
+ int flipping = Graphics::FLIP_NONE,
Common::Rect *pPartRect = NULL,
uint color = BS_ARGB(255, 255, 255, 255),
int width = -1, int height = -1,
diff --git a/engines/sword25/gfx/image/imgloader.cpp b/engines/sword25/gfx/image/imgloader.cpp
index b4b3030de8..f299cee9d1 100644
--- a/engines/sword25/gfx/image/imgloader.cpp
+++ b/engines/sword25/gfx/image/imgloader.cpp
@@ -45,7 +45,7 @@ bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, byte *&un
error("Error while reading PNG image");
const Graphics::Surface *sourceSurface = png.getSurface();
- Graphics::Surface *pngSurface = sourceSurface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), png.getPalette());
+ Graphics::Surface *pngSurface = sourceSurface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), png.getPalette());
width = pngSurface->w;
height = pngSurface->h;
@@ -70,7 +70,7 @@ bool ImgLoader::decodeThumbnailImage(const byte *pFileData, uint fileSize, byte
uint32 totalSize = pitch * height;
pUncompressedData = new byte[totalSize];
uint32 *dst = (uint32 *)pUncompressedData; // treat as uint32, for pixelformat output
- const Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ const Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
byte r, g, b;
for (uint32 i = 0; i < totalSize / 4; i++) {
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index 107b4cd402..8c6369a790 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -100,9 +100,6 @@ static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSiz
}
RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
- _data(0),
- _width(0),
- _height(0),
_isTransparent(true) {
result = false;
@@ -130,10 +127,18 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
// Uncompress the image
int pitch;
+ byte *dst;
+ int w, h;
if (isPNG)
- result = ImgLoader::decodePNGImage(pFileData, fileSize, _data, _width, _height, pitch);
+ result = ImgLoader::decodePNGImage(pFileData, fileSize, dst, w, h, pitch);
else
- result = ImgLoader::decodeThumbnailImage(pFileData, fileSize, _data, _width, _height, pitch);
+ result = ImgLoader::decodeThumbnailImage(pFileData, fileSize, dst, w, h, pitch);
+
+ _surface.w = w;
+ _surface.h = h;
+ _surface.pitch = w * 4;
+ _surface.setPixels(dst);
+ _surface.format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
if (!result) {
error("Could not decode image.");
@@ -157,12 +162,9 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
// -----------------------------------------------------------------------------
RenderedImage::RenderedImage(uint width, uint height, bool &result) :
- _width(width),
- _height(height),
_isTransparent(true) {
- _data = new byte[width * height * 4];
- Common::fill(_data, &_data[width * height * 4], 0);
+ _surface.create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
_backSurface = Kernel::getInstance()->getGfx()->getSurface();
@@ -172,9 +174,11 @@ RenderedImage::RenderedImage(uint width, uint height, bool &result) :
return;
}
-RenderedImage::RenderedImage() : _width(0), _height(0), _data(0), _isTransparent(true) {
+RenderedImage::RenderedImage() : _isTransparent(true) {
_backSurface = Kernel::getInstance()->getGfx()->getSurface();
+ _surface.format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+
_doCleanup = false;
return;
@@ -183,8 +187,6 @@ RenderedImage::RenderedImage() : _width(0), _height(0), _data(0), _isTransparent
// -----------------------------------------------------------------------------
RenderedImage::~RenderedImage() {
- if (_doCleanup)
- delete[] _data;
}
// -----------------------------------------------------------------------------
@@ -198,17 +200,17 @@ bool RenderedImage::fill(const Common::Rect *pFillRect, uint color) {
bool RenderedImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) {
// Check if PixelData contains enough pixel to create an image with image size equals width * height
- if (size < static_cast<uint>(_width * _height * 4)) {
- error("PixelData vector is too small to define a 32 bit %dx%d image.", _width, _height);
+ if (size < static_cast<uint>(_surface.w * _surface.h * 4)) {
+ error("PixelData vector is too small to define a 32 bit %dx%d image.", _surface.w, _surface.h);
return false;
}
const byte *in = &pixeldata[offset];
- byte *out = _data;
+ byte *out = (byte *)_surface.getPixels();
- for (int i = 0; i < _height; i++) {
- memcpy(out, in, _width * 4);
- out += _width * 4;
+ for (int i = 0; i < _surface.h; i++) {
+ memcpy(out, in, _surface.w * 4);
+ out += _surface.w * 4;
in += stride;
}
@@ -216,9 +218,10 @@ bool RenderedImage::setContent(const byte *pixeldata, uint size, uint offset, ui
}
void RenderedImage::replaceContent(byte *pixeldata, int width, int height) {
- _width = width;
- _height = height;
- _data = pixeldata;
+ _surface.w = width;
+ _surface.h = height;
+ _surface.pitch = width * 4;
+ _surface.setPixels(pixeldata);
}
// -----------------------------------------------------------------------------
@@ -230,251 +233,26 @@ uint RenderedImage::getPixel(int x, int y) {
// -----------------------------------------------------------------------------
bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, RectangleList *updateRects) {
- int ca = (color >> 24) & 0xff;
-
- // Check if we need to draw anything at all
- if (ca == 0)
- return true;
-
- int cr = (color >> 16) & 0xff;
- int cg = (color >> 8) & 0xff;
- int cb = (color >> 0) & 0xff;
-
- // Create an encapsulating surface for the data
- Graphics::Surface srcImage;
- // TODO: Is the data really in the screen format?
- srcImage.init(_width, _height, _width * 4, _data, g_system->getScreenFormat());
-
- if (pPartRect) {
- srcImage.setPixels(&_data[pPartRect->top * srcImage.pitch + pPartRect->left * 4]);
- srcImage.w = pPartRect->right - pPartRect->left;
- srcImage.h = pPartRect->bottom - pPartRect->top;
-
- debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping,
- pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height);
- } else {
-
- debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0,
- srcImage.w, srcImage.h, color, width, height);
- }
-
- if (width == -1)
- width = srcImage.w;
- if (height == -1)
- height = srcImage.h;
-
-#ifdef SCALING_TESTING
- // Hardcode scaling to 66% to test scaling
- width = width * 2 / 3;
- height = height * 2 / 3;
-#endif
-
- Graphics::Surface *img;
- Graphics::Surface *imgScaled = NULL;
- byte *savedPixels = NULL;
- if ((width != srcImage.w) || (height != srcImage.h)) {
- // Scale the image
- img = imgScaled = scale(srcImage, width, height);
- savedPixels = (byte *)img->getPixels();
- } else {
- img = &srcImage;
- }
-
- for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) {
- const Common::Rect &clipRect = *it;
-
- int skipLeft = 0, skipTop = 0;
- int drawX = posX, drawY = posY;
- int drawWidth = img->w;
- int drawHeight = img->h;
-
- // Handle clipping
- if (drawX < clipRect.left) {
- skipLeft = clipRect.left - drawX;
- drawWidth -= skipLeft;
- drawX = clipRect.left;
- }
-
- if (drawY < clipRect.top) {
- skipTop = clipRect.top - drawY;
- drawHeight -= skipTop;
- drawY = clipRect.top;
- }
-
- if (drawX + drawWidth >= clipRect.right)
- drawWidth = clipRect.right - drawX;
-
- if (drawY + drawHeight >= clipRect.bottom)
- drawHeight = clipRect.bottom - drawY;
-
- if ((drawWidth > 0) && (drawHeight > 0)) {
- int xp = 0, yp = 0;
-
- int inStep = 4;
- int inoStep = img->pitch;
- if (flipping & Image::FLIP_V) {
- inStep = -inStep;
- xp = img->w - 1 - skipLeft;
- } else {
- xp = skipLeft;
- }
-
- if (flipping & Image::FLIP_H) {
- inoStep = -inoStep;
- yp = img->h - 1 - skipTop;
- } else {
- yp = skipTop;
- }
-
- byte *ino = (byte *)img->getBasePtr(xp, yp);
- byte *outo = (byte *)_backSurface->getBasePtr(drawX, drawY);
-
-#if defined(SCUMM_LITTLE_ENDIAN)
- // Simple memcpy if the source bitmap doesn't have transparent pixels and the drawing transparency is 255
- // NOTE Only possible with LE-machines at the moment, maybe it would be feasible to convert the bitmap pixels at loading time?
- if (!_isTransparent && ca == 255) {
- for (int i = 0; i < drawHeight; i++) {
- memcpy(outo, ino, drawWidth * 4);
- outo += _backSurface->pitch;
- ino += inoStep;
- }
- } else
-#endif
- {
- byte *in, *out;
- for (int i = 0; i < drawHeight; i++) {
- out = outo;
- in = ino;
- for (int j = 0; j < drawWidth; j++) {
- uint32 pix = *(uint32 *)in;
- int a = (pix >> 24) & 0xff;
- in += inStep;
-
- if (ca != 255) {
- a = a * ca >> 8;
- }
-
- if (a == 0) {
- // Full transparency
- out += 4;
- continue;
- }
-
- int b = (pix >> 0) & 0xff;
- int g = (pix >> 8) & 0xff;
- int r = (pix >> 16) & 0xff;
-
- if (a == 255) {
-#if defined(SCUMM_LITTLE_ENDIAN)
- if (cb != 255)
- b = (b * cb) >> 8;
- if (cg != 255)
- g = (g * cg) >> 8;
- if (cr != 255)
- r = (r * cr) >> 8;
- *(uint32 *)out = (255 << 24) | (r << 16) | (g << 8) | b;
- out += 4;
-#else
- *out++ = a;
- if (cr != 255)
- *out++ = (r * cr) >> 8;
- else
- *out++ = r;
- if (cg != 255)
- *out++ = (g * cg) >> 8;
- else
- *out++ = g;
- if (cb != 255)
- *out++ = (b * cb) >> 8;
- else
- *out++ = b;
-#endif
- } else {
-#if defined(SCUMM_LITTLE_ENDIAN)
- pix = *(uint32 *)out;
- int outb = ((pix >> 0) & 0xff) * (255 - a);
- int outg = ((pix >> 8) & 0xff) * (255 - a);
- int outr = ((pix >> 16) & 0xff) * (255 - a);
- if (cb == 0)
- outb = outb >> 8;
- else if (cb != 255)
- outb = ((outb << 8) + b * a * cb) >> 16;
- else
- outb = (outb + b * a) >> 8;
- if (cg == 0)
- outg = outg >> 8;
- else if (cg != 255)
- outg = ((outg << 8) + g * a * cg) >> 16;
- else
- outg = (outg + g * a) >> 8;
- if (cr == 0)
- outr = outr >> 8;
- else if (cr != 255)
- outr = ((outr << 8) + r * a * cr) >> 16;
- else
- outr = (outr + r * a) >> 8;
- *(uint32 *)out = (255 << 24) | (outr << 16) | (outg << 8) | outb;
- out += 4;
-#else
- *out = 255;
- out++;
- if (cr == 0)
- *out = (*out * (255-a)) >> 8;
- else if (cr != 255)
- *out = (((*out * (255-a)) << 8) + r * a * cr) >> 16;
- else
- *out = ((*out * (255-a)) + r * a) >> 8;
- out++;
- if (cg == 0)
- *out = (*out * (255-a)) >> 8;
- else if (cg != 255)
- *out = (((*out * (255-a)) << 8) + g * a * cg) >> 16;
- else
- *out = ((*out * (255-a)) + g * a) >> 8;
- out++;
- if (cb == 0)
- *out = (*out * (255-a)) >> 8;
- else if (cb != 255)
- *out = (((*out * (255-a)) << 8) + b * a * cb) >> 16;
- else
- *out = ((*out * (255-a)) + b * a) >> 8;
- out++;
-#endif
- }
- }
- outo += _backSurface->pitch;
- ino += inoStep;
- }
- }
-
- }
-
- }
-
- if (imgScaled) {
- imgScaled->setPixels(savedPixels);
- imgScaled->free();
- delete imgScaled;
- }
+ _surface.blit(*_backSurface, posX, posY, (((flipping & 1) ? Graphics::FLIP_V : 0) | ((flipping & 2) ? Graphics::FLIP_H : 0)), pPartRect, color, width, height);
return true;
}
void RenderedImage::copyDirectly(int posX, int posY) {
- byte *data = _data;
- int w = _width;
- int h = _height;
+ byte *data = (byte *)_surface.getPixels();
+ int w = _surface.w;
+ int h = _surface.h;
// Handle off-screen clipping
if (posY < 0) {
- h = MAX(0, (int)_height - -posY);
- data = (byte *)_data + _width * -posY;
+ h = MAX(0, (int)_surface.h - -posY);
+ data = (byte *)_surface.getPixels() + _surface.w * -posY;
posY = 0;
}
if (posX < 0) {
- w = MAX(0, (int)_width - -posX);
- data = (byte *)_data + (-posX * 4);
+ w = MAX(0, (int)_surface.h - -posX);
+ data = (byte *)_surface.getPixels() + (-posX * 4);
posX = 0;
}
@@ -487,9 +265,9 @@ void RenderedImage::copyDirectly(int posX, int posY) {
void RenderedImage::checkForTransparency() {
// Check if the source bitmap has any transparent pixels at all
_isTransparent = false;
- byte *data = _data;
- for (int i = 0; i < _height; i++) {
- for (int j = 0; j < _width; j++) {
+ byte *data = (byte *)_surface.getPixels();
+ for (int i = 0; i < _surface.h; i++) {
+ for (int j = 0; j < _surface.w; j++) {
_isTransparent = data[3] != 0xff;
if (_isTransparent)
return;
diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h
index 3cc9725b12..5b65a27355 100644
--- a/engines/sword25/gfx/image/renderedimage.h
+++ b/engines/sword25/gfx/image/renderedimage.h
@@ -39,6 +39,7 @@
#include "sword25/kernel/common.h"
#include "sword25/gfx/image/image.h"
#include "sword25/gfx/graphicengine.h"
+#include "graphics/transparent_surface.h"
namespace Sword25 {
@@ -60,10 +61,10 @@ public:
virtual ~RenderedImage();
virtual int getWidth() const {
- return _width;
+ return _surface.w;
}
virtual int getHeight() const {
- return _height;
+ return _surface.h;
}
virtual GraphicEngine::COLOR_FORMATS getColorFormat() const {
return GraphicEngine::CF_ARGB32;
@@ -72,7 +73,7 @@ public:
void copyDirectly(int posX, int posY);
virtual bool blit(int posX = 0, int posY = 0,
- int flipping = Image::FLIP_NONE,
+ int flipping = Graphics::FLIP_NONE,
Common::Rect *pPartRect = NULL,
uint color = BS_ARGB(255, 255, 255, 255),
int width = -1, int height = -1,
@@ -108,9 +109,7 @@ public:
virtual bool isSolid() const { return !_isTransparent; }
private:
- byte *_data;
- int _width;
- int _height;
+ Graphics::TransparentSurface _surface;
bool _doCleanup;
bool _isTransparent;
diff --git a/engines/sword25/gfx/image/swimage.h b/engines/sword25/gfx/image/swimage.h
index b31c2318ec..60978eb6cc 100644
--- a/engines/sword25/gfx/image/swimage.h
+++ b/engines/sword25/gfx/image/swimage.h
@@ -55,7 +55,7 @@ public:
}
virtual bool blit(int posX = 0, int posY = 0,
- int flipping = Image::FLIP_NONE,
+ int flipping = Graphics::FLIP_NONE,
Common::Rect *pPartRect = NULL,
uint color = BS_ARGB(255, 255, 255, 255),
int width = -1, int height = -1,
diff --git a/engines/sword25/gfx/image/vectorimage.h b/engines/sword25/gfx/image/vectorimage.h
index a99d532e75..057064fc6a 100644
--- a/engines/sword25/gfx/image/vectorimage.h
+++ b/engines/sword25/gfx/image/vectorimage.h
@@ -209,7 +209,7 @@ public:
}
virtual bool setContent(const byte *pixeldata, uint size, uint offset, uint stride);
virtual bool blit(int posX = 0, int posY = 0,
- int flipping = FLIP_NONE,
+ int flipping = Graphics::FLIP_NONE,
Common::Rect *pPartRect = NULL,
uint color = BS_ARGB(255, 255, 255, 255),
int width = -1, int height = -1,
diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp
index c7a79fd3c4..c69cb497c1 100644
--- a/engines/sword25/gfx/image/vectorimagerenderer.cpp
+++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp
@@ -52,7 +52,7 @@ void art_rgb_fill_run1(byte *buf, byte r, byte g, byte b, int n) {
memset(buf, g, n + n + n + n);
} else {
uint32 *alt = (uint32 *)buf;
- uint32 color = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(0xff, r, g, b);
+ uint32 color = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(r, g, b, 0xff);
for (i = 0; i < n; i++)
*alt++ = color;
@@ -66,22 +66,22 @@ void art_rgb_run_alpha1(byte *buf, byte r, byte g, byte b, int alpha, int n) {
for (i = 0; i < n; i++) {
#if defined(SCUMM_LITTLE_ENDIAN)
v = *buf;
+ *buf++ = MIN(v + alpha, 0xff);
+ v = *buf;
*buf++ = v + (((b - v) * alpha + 0x80) >> 8);
v = *buf;
*buf++ = v + (((g - v) * alpha + 0x80) >> 8);
v = *buf;
*buf++ = v + (((r - v) * alpha + 0x80) >> 8);
- v = *buf;
- *buf++ = MIN(v + alpha, 0xff);
#else
v = *buf;
- *buf++ = MIN(v + alpha, 0xff);
- v = *buf;
*buf++ = v + (((r - v) * alpha + 0x80) >> 8);
v = *buf;
*buf++ = v + (((g - v) * alpha + 0x80) >> 8);
v = *buf;
*buf++ = v + (((b - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ *buf++ = MIN(v + alpha, 0xff);
#endif
}
}
diff --git a/engines/sword25/gfx/staticbitmap.cpp b/engines/sword25/gfx/staticbitmap.cpp
index 14e2012d80..1a6c812508 100644
--- a/engines/sword25/gfx/staticbitmap.cpp
+++ b/engines/sword25/gfx/staticbitmap.cpp
@@ -98,14 +98,14 @@ bool StaticBitmap::doRender(RectangleList *updateRects) {
bool result;
if (_scaleFactorX == 1.0f && _scaleFactorY == 1.0f) {
result = bitmapResourcePtr->blit(_absoluteX, _absoluteY,
- (_flipV ? BitmapResource::FLIP_V : 0) |
- (_flipH ? BitmapResource::FLIP_H : 0),
+ (_flipV ? Graphics::FLIP_V : 0) |
+ (_flipH ? Graphics::FLIP_H : 0),
0, _modulationColor, -1, -1,
updateRects);
} else {
result = bitmapResourcePtr->blit(_absoluteX, _absoluteY,
- (_flipV ? BitmapResource::FLIP_V : 0) |
- (_flipH ? BitmapResource::FLIP_H : 0),
+ (_flipV ? Graphics::FLIP_V : 0) |
+ (_flipH ? Graphics::FLIP_H : 0),
0, _modulationColor, _width, _height,
updateRects);
}
diff --git a/engines/sword25/gfx/text.cpp b/engines/sword25/gfx/text.cpp
index b0a9e4ed3f..904435fcb0 100644
--- a/engines/sword25/gfx/text.cpp
+++ b/engines/sword25/gfx/text.cpp
@@ -99,7 +99,7 @@ void Text::setText(const Common::String &text) {
}
void Text::setColor(uint32 modulationColor) {
- uint32 newModulationColor = (modulationColor & 0x00ffffff) | (_modulationColor & 0xff000000);
+ uint32 newModulationColor = (modulationColor & 0xffffff00) | (_modulationColor & 0x000000ff);
if (newModulationColor != _modulationColor) {
_modulationColor = newModulationColor;
forceRefresh();
@@ -108,7 +108,7 @@ void Text::setColor(uint32 modulationColor) {
void Text::setAlpha(int alpha) {
assert(alpha >= 0 && alpha < 256);
- uint32 newModulationColor = (_modulationColor & 0x00ffffff) | alpha << 24;
+ uint32 newModulationColor = (_modulationColor & 0xffffff00) | alpha;
if (newModulationColor != _modulationColor) {
_modulationColor = newModulationColor;
forceRefresh();
@@ -173,7 +173,7 @@ bool Text::doRender(RectangleList *updateRects) {
Common::Rect renderRect(curX, curY, curX + curRect.width(), curY + curRect.height());
renderRect.translate(curRect.left - curX, curRect.top - curY);
- result = charMapPtr->blit(curX, curY, Image::FLIP_NONE, &renderRect, _modulationColor, -1, -1, updateRects);
+ result = charMapPtr->blit(curX, curY, Graphics::FLIP_NONE, &renderRect, _modulationColor, -1, -1, updateRects);
if (!result)
break;
diff --git a/engines/sword25/kernel/persistenceservice.cpp b/engines/sword25/kernel/persistenceservice.cpp
index fb83b7f941..7d68081593 100644
--- a/engines/sword25/kernel/persistenceservice.cpp
+++ b/engines/sword25/kernel/persistenceservice.cpp
@@ -52,7 +52,7 @@ static const uint SLOT_COUNT = 18;
static const uint FILE_COPY_BUFFER_SIZE = 1024 * 10;
static const char *VERSIONIDOLD = "SCUMMVM1";
static const char *VERSIONID = "SCUMMVM2";
-static const int VERSIONNUM = 2;
+static const int VERSIONNUM = 3;
#define MAX_SAVEGAME_SIZE 100
diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp
index 4029b4e808..dcb29cb380 100644
--- a/engines/sword25/sfx/soundengine.cpp
+++ b/engines/sword25/sfx/soundengine.cpp
@@ -114,7 +114,7 @@ float SoundEngine::getVolume(SOUND_TYPES type) {
error("Unknown SOUND_TYPE");
}
- return (float)val / 255.0;
+ return (float)val / 255.0f;
}
void SoundEngine::pauseAll() {
@@ -302,7 +302,7 @@ float SoundEngine::getSoundVolume(uint handle) {
SndHandle* sndHandle = findHandle(handle);
if (sndHandle == NULL)
return 0.f;
- return (float)_mixer->getChannelVolume(sndHandle->handle) / 255.0;
+ return (float)_mixer->getChannelVolume(sndHandle->handle) / 255.0f;
}
float SoundEngine::getSoundPanning(uint handle) {
@@ -311,7 +311,7 @@ float SoundEngine::getSoundPanning(uint handle) {
SndHandle* sndHandle = findHandle(handle);
if (sndHandle == NULL)
return 0.f;
- return (float)_mixer->getChannelBalance(sndHandle->handle) / 127.0;
+ return (float)_mixer->getChannelBalance(sndHandle->handle) / 127.0f;
}
Resource *SoundEngine::loadResource(const Common::String &fileName) {
diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp
index 259deb2ea8..bb0aab3ad4 100644
--- a/engines/sword25/sword25.cpp
+++ b/engines/sword25/sword25.cpp
@@ -97,7 +97,7 @@ Common::Error Sword25Engine::run() {
Common::Error Sword25Engine::appStart() {
// Initialize the graphics mode to ARGB8888
- Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
initGraphics(800, 600, true, &format);
if (format != g_system->getScreenFormat())
return Common::kUnsupportedColorMode;
diff --git a/engines/sword25/util/lua/loslib.cpp b/engines/sword25/util/lua/loslib.cpp
index 25bfa2d1b5..055dfdf19e 100644
--- a/engines/sword25/util/lua/loslib.cpp
+++ b/engines/sword25/util/lua/loslib.cpp
@@ -113,6 +113,9 @@ static int getfield (lua_State *L, const char *key, int d) {
static int os_date (lua_State *L) {
+ #ifdef __PLAYSTATION2__ // missing: gmtime & strftime
+ lua_pushnil(L);
+ #else
const char *s = luaL_optstring(L, 1, "%c");
// FIXME: Rewrite the code below to use OSystem::getTimeAndDate
// Alternatively, remove it, if sword25 does not use it.
@@ -160,6 +163,7 @@ static int os_date (lua_State *L) {
}
luaL_pushresult(&b);
}
+ #endif
return 1;
}
@@ -167,6 +171,9 @@ static int os_date (lua_State *L) {
static int os_time (lua_State *L) {
// FIXME: Rewrite the code below to use OSystem::getTimeAndDate.
// Alternatively, remove it, if sword25 does not use it.
+ #ifdef __PLAYSTATION2__ // missing: mktime
+ lua_pushnil(L);
+ #else
time_t t;
if (lua_isnoneornil(L, 1)) /* called without args? */
t = time(NULL); /* get current time */
@@ -187,6 +194,7 @@ static int os_time (lua_State *L) {
lua_pushnil(L);
else
lua_pushnumber(L, (lua_Number)t);
+ #endif
return 1;
}
@@ -195,8 +203,10 @@ static int os_difftime (lua_State *L) {
// FIXME: difftime is not portable, unfortunately.
// So we either have to replace this code, or just remove it,
// depending on whether sword25 actually uses it.
+ #ifndef __PLAYSTATION2__ // missing: difftime
lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
(time_t)(luaL_optnumber(L, 2, 0))));
+ #endif
return 1;
}
diff --git a/engines/sword25/util/pluto/pluto.cpp b/engines/sword25/util/pluto/pluto.cpp
index fb477c1687..78b0a815e8 100644
--- a/engines/sword25/util/pluto/pluto.cpp
+++ b/engines/sword25/util/pluto/pluto.cpp
@@ -835,7 +835,15 @@ static void persistthread(PersistInfo *pi)
#endif
write_size(pi, &stackbase);
write_size(pi, &stacktop);
+
+ // ptrdiff_t changes sizes based on 32/64 bit
+ // Hard cast to 64 bit size if SIZE64 is defined
+#ifdef SIZES64
+ uint64 ptrIndex = static_cast<uint64>(L2->errfunc);
+ pi_write(pi, &ptrIndex, sizeof(uint64), pi->ud);
+#else
pi_write(pi, &L2->errfunc, sizeof(ptrdiff_t), pi->ud);
+#endif
//write_size(pi, (size_t *)&L2->errfunc);
}
@@ -944,12 +952,6 @@ static void persist(PersistInfo *pi)
if(!lua_isnil(pi->L, -1)) {
/* perms reftbl ... obj ref */
int zero = 0;
- // FIXME: Casting a pointer to an integer data type is a bad idea we
- // should really get rid of this by fixing the design of this code.
- // For now casting to size_t should silence most (all?) compilers,
- // since size_t is supposedly the same size as a pointer on most
- // (modern) architectures.
- int ref = (int)(size_t)lua_touserdata(pi->L, -1);
pi_write(pi, &zero, sizeof(int), pi->ud);
if (humanReadable) {
snprintf(hrBuf, hrBufSize, "persist_seenobject\n");
@@ -958,7 +960,8 @@ static void persist(PersistInfo *pi)
#ifdef TOTEXT
printf("persist_seenobject\n");
#endif
- pi_write(pi, &ref, sizeof(int), pi->ud);
+ int *ref = (int *)lua_touserdata(pi->L, -1);
+ pi_write(pi, ref, sizeof(int), pi->ud);
if (humanReadable) {
snprintf(hrBuf, hrBufSize, "persist_touserdata_ref %d\n", ref);
hrOut(pi);
@@ -1011,7 +1014,8 @@ static void persist(PersistInfo *pi)
}
lua_pushvalue(pi->L, -1);
/* perms reftbl ... obj obj */
- lua_pushlightuserdata(pi->L, (void *)(++(pi->counter)));
+ int *ref = (int *)lua_newuserdata(pi->L, sizeof(int));
+ *ref = ++(pi->counter);
/* perms reftbl ... obj obj ref */
lua_rawset(pi->L, 2);
/* perms reftbl ... obj */
@@ -1737,7 +1741,16 @@ static void unpersistthread(int ref, UnpersistInfo *upi)
verify(LIF(Z,read)(&upi->zio, &L2->status, sizeof(lu_byte)) == 0);
read_size(&upi->zio, &stackbase);
read_size(&upi->zio, &stacktop);
+
+#ifdef SIZES64
+ uint64 value;
+ verify(LIF(Z,read)(&upi->zio, &value, sizeof(uint64)) == 0);
+
+ L2->errfunc = static_cast<ptrdiff_t>(value);
+#else
verify(LIF(Z,read)(&upi->zio, &L2->errfunc, sizeof(ptrdiff_t)) == 0);
+#endif
+
//read_size(&upi->zio, (size_t *)&L2->errfunc);
L2->base = L2->stack + stackbase;
L2->top = L2->stack + stacktop;
diff --git a/engines/teenagent/actor.cpp b/engines/teenagent/actor.cpp
index a4df43a5fe..5c796c13ab 100644
--- a/engines/teenagent/actor.cpp
+++ b/engines/teenagent/actor.cpp
@@ -134,10 +134,6 @@ Common::Rect Actor::render(Graphics::Surface *surface, const Common::Point &posi
default:
return Common::Rect();
}
- if (s == NULL) {
- warning("no surface, skipping");
- return Common::Rect();
- }
Common::Rect dirty;
Common::Rect clip(0, 0, s->w, s->h);
diff --git a/engines/teenagent/console.cpp b/engines/teenagent/console.cpp
index 13d5c687ce..2304829782 100644
--- a/engines/teenagent/console.cpp
+++ b/engines/teenagent/console.cpp
@@ -26,24 +26,24 @@
namespace TeenAgent {
Console::Console(TeenAgentEngine *engine) : _engine(engine) {
- DCmd_Register("enable_object", WRAP_METHOD(Console, enableObject));
- DCmd_Register("disable_object", WRAP_METHOD(Console, enableObject));
- DCmd_Register("set_ons", WRAP_METHOD(Console, setOns));
- DCmd_Register("set_music", WRAP_METHOD(Console, setMusic));
- DCmd_Register("animation", WRAP_METHOD(Console, playAnimation));
- DCmd_Register("actor_animation", WRAP_METHOD(Console, playActorAnimation));
- DCmd_Register("call", WRAP_METHOD(Console, call));
+ registerCmd("enable_object", WRAP_METHOD(Console, enableObject));
+ registerCmd("disable_object", WRAP_METHOD(Console, enableObject));
+ registerCmd("set_ons", WRAP_METHOD(Console, setOns));
+ registerCmd("set_music", WRAP_METHOD(Console, setMusic));
+ registerCmd("animation", WRAP_METHOD(Console, playAnimation));
+ registerCmd("actor_animation", WRAP_METHOD(Console, playActorAnimation));
+ registerCmd("call", WRAP_METHOD(Console, call));
}
bool Console::enableObject(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("usage: %s object_id [scene_id]\n", argv[0]);
+ debugPrintf("usage: %s object_id [scene_id]\n", argv[0]);
return true;
}
int id = atoi(argv[1]);
if (id < 0) {
- DebugPrintf("object id %d is invalid\n", id);
+ debugPrintf("object id %d is invalid\n", id);
return true;
}
@@ -51,7 +51,7 @@ bool Console::enableObject(int argc, const char **argv) {
if (argc > 2) {
scene_id = atoi(argv[2]);
if (scene_id < 0) {
- DebugPrintf("scene id %d is invalid\n", scene_id);
+ debugPrintf("scene id %d is invalid\n", scene_id);
return true;
}
}
@@ -66,20 +66,20 @@ bool Console::enableObject(int argc, const char **argv) {
bool Console::setOns(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("usage: %s index(0-3) value [scene_id]\n", argv[0]);
+ debugPrintf("usage: %s index(0-3) value [scene_id]\n", argv[0]);
return true;
}
int index = atoi(argv[1]);
if (index < 0 || index > 3) {
- DebugPrintf("index %d is invalid\n", index);
+ debugPrintf("index %d is invalid\n", index);
return true;
}
int value = 0;
value = atoi(argv[2]);
if (value < 0) {
- DebugPrintf("invalid value\n");
+ debugPrintf("invalid value\n");
return true;
}
@@ -87,7 +87,7 @@ bool Console::setOns(int argc, const char **argv) {
if (argc > 3) {
scene_id = atoi(argv[3]);
if (scene_id < 0) {
- DebugPrintf("scene id %d is invalid\n", scene_id);
+ debugPrintf("scene id %d is invalid\n", scene_id);
return true;
}
}
@@ -98,13 +98,13 @@ bool Console::setOns(int argc, const char **argv) {
bool Console::setMusic(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("usage: %s index(1-11)\n", argv[0]);
+ debugPrintf("usage: %s index(1-11)\n", argv[0]);
return true;
}
int index = atoi(argv[1]);
if (index <= 0 || index > 11) {
- DebugPrintf("invalid value\n");
+ debugPrintf("invalid value\n");
return true;
}
@@ -114,14 +114,14 @@ bool Console::setMusic(int argc, const char **argv) {
bool Console::playAnimation(int argc, const char **argv) {
if (argc < 3) {
- DebugPrintf("usage: %s id slot(0-3)\n", argv[0]);
+ debugPrintf("usage: %s id slot(0-3)\n", argv[0]);
return true;
}
int id = atoi(argv[1]);
int slot = atoi(argv[2]);
if (id < 0 || slot < 0 || slot > 3) {
- DebugPrintf("invalid slot or animation id\n");
+ debugPrintf("invalid slot or animation id\n");
return true;
}
@@ -131,13 +131,13 @@ bool Console::playAnimation(int argc, const char **argv) {
bool Console::playActorAnimation(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("usage: %s id\n", argv[0]);
+ debugPrintf("usage: %s id\n", argv[0]);
return true;
}
int id = atoi(argv[1]);
if (id < 0) {
- DebugPrintf("invalid animation id\n");
+ debugPrintf("invalid animation id\n");
return true;
}
@@ -147,18 +147,18 @@ bool Console::playActorAnimation(int argc, const char **argv) {
bool Console::call(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("usage: %s 0xHEXADDR\n", argv[0]);
+ debugPrintf("usage: %s 0xHEXADDR\n", argv[0]);
return true;
}
uint addr;
if (sscanf(argv[1], "0x%x", &addr) != 1) {
- DebugPrintf("invalid address\n");
+ debugPrintf("invalid address\n");
return true;
}
if (!_engine->processCallback(addr))
- DebugPrintf("calling callback %04x failed\n", addr);
+ debugPrintf("calling callback %04x failed\n", addr);
return true;
}
diff --git a/engines/testbed/sound.cpp b/engines/testbed/sound.cpp
index aebd981826..998afbf7db 100644
--- a/engines/testbed/sound.cpp
+++ b/engines/testbed/sound.cpp
@@ -235,7 +235,7 @@ TestExitStatus SoundSubsystem::sampleRates() {
Common::Point pt(0, 100);
mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, s1);
- Testsuite::writeOnScreen(Common::String::format("Playing at smaple rate: %d", s1->getRate()), pt);
+ Testsuite::writeOnScreen(Common::String::format("Playing at sample rate: %d", s1->getRate()), pt);
g_system->delayMillis(1000);
mixer->stopHandle(handle);
g_system->delayMillis(1000);
diff --git a/engines/tinsel/debugger.cpp b/engines/tinsel/debugger.cpp
index 45e3a05903..1dbb19d383 100644
--- a/engines/tinsel/debugger.cpp
+++ b/engines/tinsel/debugger.cpp
@@ -62,11 +62,11 @@ int strToInt(const char *s) {
//----------------- CONSOLE CLASS ---------------------
Console::Console() : GUI::Debugger() {
- DCmd_Register("item", WRAP_METHOD(Console, cmd_item));
- DCmd_Register("scene", WRAP_METHOD(Console, cmd_scene));
- DCmd_Register("music", WRAP_METHOD(Console, cmd_music));
- DCmd_Register("sound", WRAP_METHOD(Console, cmd_sound));
- DCmd_Register("string", WRAP_METHOD(Console, cmd_string));
+ registerCmd("item", WRAP_METHOD(Console, cmd_item));
+ registerCmd("scene", WRAP_METHOD(Console, cmd_scene));
+ registerCmd("music", WRAP_METHOD(Console, cmd_music));
+ registerCmd("sound", WRAP_METHOD(Console, cmd_sound));
+ registerCmd("string", WRAP_METHOD(Console, cmd_string));
}
Console::~Console() {
@@ -74,8 +74,8 @@ Console::~Console() {
bool Console::cmd_item(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("%s item_number\n", argv[0]);
- DebugPrintf("Sets the currently active 'held' item\n");
+ debugPrintf("%s item_number\n", argv[0]);
+ debugPrintf("Sets the currently active 'held' item\n");
return true;
}
@@ -86,14 +86,14 @@ bool Console::cmd_item(int argc, const char **argv) {
bool Console::cmd_scene(int argc, const char **argv) {
if (argc < 1 || argc > 3) {
- DebugPrintf("%s [scene_number [entry number]]\n", argv[0]);
- DebugPrintf("If no parameters are given, prints the current scene.\n");
- DebugPrintf("Otherwise changes to the specified scene number. Entry number defaults to 1 if none provided\n");
+ debugPrintf("%s [scene_number [entry number]]\n", argv[0]);
+ debugPrintf("If no parameters are given, prints the current scene.\n");
+ debugPrintf("Otherwise changes to the specified scene number. Entry number defaults to 1 if none provided\n");
return true;
}
if (argc == 1) {
- DebugPrintf("Current scene is %d\n", GetSceneHandle() >> SCNHANDLE_SHIFT);
+ debugPrintf("Current scene is %d\n", GetSceneHandle() >> SCNHANDLE_SHIFT);
return true;
}
@@ -106,15 +106,15 @@ bool Console::cmd_scene(int argc, const char **argv) {
bool Console::cmd_music(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("%s track_number or %s -offset\n", argv[0], argv[0]);
- DebugPrintf("Plays the MIDI track number provided, or the offset inside midi.dat\n");
- DebugPrintf("A positive number signifies a track number, whereas a negative signifies an offset\n");
+ debugPrintf("%s track_number or %s -offset\n", argv[0], argv[0]);
+ debugPrintf("Plays the MIDI track number provided, or the offset inside midi.dat\n");
+ debugPrintf("A positive number signifies a track number, whereas a negative signifies an offset\n");
return true;
}
int param = strToInt(argv[1]);
if (param == 0) {
- DebugPrintf("Track number/offset can't be 0!\n");
+ debugPrintf("Track number/offset can't be 0!\n");
} else if (param > 0) {
// Track provided
PlayMidiSequence(GetTrackOffset(param - 1), false);
@@ -128,8 +128,8 @@ bool Console::cmd_music(int argc, const char **argv) {
bool Console::cmd_sound(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("%s id\n", argv[0]);
- DebugPrintf("Plays the sound with the given ID\n");
+ debugPrintf("%s id\n", argv[0]);
+ debugPrintf("Plays the sound with the given ID\n");
return true;
}
@@ -140,7 +140,7 @@ bool Console::cmd_sound(int argc, const char **argv) {
else
_vm->_sound->playSample(id, 0, false, 0, 0, PRIORITY_TALK, Audio::Mixer::kSpeechSoundType);
} else {
- DebugPrintf("Sample %d does not exist!\n", id);
+ debugPrintf("Sample %d does not exist!\n", id);
}
return true;
@@ -148,15 +148,15 @@ bool Console::cmd_sound(int argc, const char **argv) {
bool Console::cmd_string(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("%s id\n", argv[0]);
- DebugPrintf("Prints the string with the given ID\n");
+ debugPrintf("%s id\n", argv[0]);
+ debugPrintf("Prints the string with the given ID\n");
return true;
}
char tmp[TBUFSZ];
int id = strToInt(argv[1]);
LoadStringRes(id, tmp, TBUFSZ);
- DebugPrintf("%s\n", tmp);
+ debugPrintf("%s\n", tmp);
return true;
}
diff --git a/engines/toltecs/console.cpp b/engines/toltecs/console.cpp
index f84a8e3c44..5a0c66c7b0 100644
--- a/engines/toltecs/console.cpp
+++ b/engines/toltecs/console.cpp
@@ -31,8 +31,8 @@
namespace Toltecs {
Console::Console(ToltecsEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room));
- DCmd_Register("dump", WRAP_METHOD(Console, Cmd_Dump));
+ registerCmd("room", WRAP_METHOD(Console, Cmd_Room));
+ registerCmd("dump", WRAP_METHOD(Console, Cmd_Dump));
}
Console::~Console() {
@@ -40,10 +40,10 @@ Console::~Console() {
bool Console::Cmd_Room(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Current room number is %d\n", _vm->_sceneResIndex);
+ debugPrintf("Current room number is %d\n", _vm->_sceneResIndex);
#if 0
- DebugPrintf("Calling this command with the room number changes the room\n");
- DebugPrintf("WARNING: It's a bad idea to warp to rooms with this, as the room object scripts are not loaded\n");
+ debugPrintf("Calling this command with the room number changes the room\n");
+ debugPrintf("WARNING: It's a bad idea to warp to rooms with this, as the room object scripts are not loaded\n");
#endif
return true;
#if 0
@@ -65,13 +65,13 @@ bool Console::Cmd_Room(int argc, const char **argv) {
bool Console::Cmd_Dump(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: dump <resource number>\n");
+ debugPrintf("Usage: dump <resource number>\n");
return true;
}
int resNum = atoi(argv[1]);
_vm->_arc->dump(resNum);
- DebugPrintf("Resource %d has been dumped to disk\n", resNum);
+ debugPrintf("Resource %d has been dumped to disk\n", resNum);
return true;
}
diff --git a/engines/toltecs/detection.cpp b/engines/toltecs/detection.cpp
index b6c7ad3d2b..e8f08bcc61 100644
--- a/engines/toltecs/detection.cpp
+++ b/engines/toltecs/detection.cpp
@@ -86,6 +86,20 @@ static const ToltecsGameDescription gameDescriptions[] = {
},
{
+ // 3 Skulls of the Toltecs PIRATE CD-RIP version (no audio)
+ // == DO NOT RE-ADD ==
+ {
+ "toltecs",
+ 0,
+ AD_ENTRY1s("WESTERN", "56d0da91ec3db8ac869594357584e851", 104804435),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_PIRATED,
+ GUIO1(GUIO_NONE)
+ },
+ },
+
+ {
// 3 Skulls of the Toltecs Russian version
{
"toltecs",
diff --git a/engines/tony/debugger.cpp b/engines/tony/debugger.cpp
index 22c218a19c..e192c53d2b 100644
--- a/engines/tony/debugger.cpp
+++ b/engines/tony/debugger.cpp
@@ -28,9 +28,9 @@
namespace Tony {
Debugger::Debugger() : GUI::Debugger() {
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("scene", WRAP_METHOD(Debugger, Cmd_Scene));
- DCmd_Register("dirty_rects", WRAP_METHOD(Debugger, Cmd_DirtyRects));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("scene", WRAP_METHOD(Debugger, Cmd_Scene));
+ registerCmd("dirty_rects", WRAP_METHOD(Debugger, Cmd_DirtyRects));
}
static int strToInt(const char *s) {
@@ -82,13 +82,13 @@ void DebugChangeScene(CORO_PARAM, const void *param) {
*/
bool Debugger::Cmd_Scene(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: %s <scene number> [<x> <y>]\n", argv[0]);
+ debugPrintf("Usage: %s <scene number> [<x> <y>]\n", argv[0]);
return true;
}
int sceneNumber = strToInt(argv[1]);
if (sceneNumber >= g_vm->_theBoxes.getLocBoxesCount()) {
- DebugPrintf("Invalid scene\n");
+ debugPrintf("Invalid scene\n");
return true;
}
@@ -118,7 +118,7 @@ bool Debugger::Cmd_Scene(int argc, const char **argv) {
*/
bool Debugger::Cmd_DirtyRects(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage; %s [on | off]\n", argv[0]);
+ debugPrintf("Usage; %s [on | off]\n", argv[0]);
return true;
} else {
g_vm->_window.showDirtyRects(strcmp(argv[1], "on") == 0);
diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h
index ce4651f0ab..28dcaac752 100644
--- a/engines/tony/detection_tables.h
+++ b/engines/tony/detection_tables.h
@@ -217,7 +217,7 @@ static const TonyGameDescription gameDescriptions[] = {
// Tony Tough German "Shoe Box", reported in bug #3582420
{
"tony",
- 0,
+ 0,
{
{"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071},
{"roasted.mpc", 0, "bc3471f098e591dc509dcad401a8d8a5", 389554},
@@ -230,6 +230,23 @@ static const TonyGameDescription gameDescriptions[] = {
},
},
+ {
+ // Tony Tough Russian, reported in bug #6589
+ {
+ "tony",
+ 0,
+ {
+ {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071},
+ {"roasted.mpc", 0, "377d6e24adeedc6c5c09c31b92231218", 391536},
+ AD_LISTEND
+ },
+ Common::RU_RUS,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ },
+
{ AD_TABLE_END_MARKER }
};
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index cab31795f7..51e8dee19f 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -1059,12 +1059,14 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) {
_specialAnim->loadAnimation(animName);
_animSpecialId = animId;
-
- _animationInstance->setAnimation(_specialAnim);
- _animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1);
- _animationInstance->reset();
- _animationInstance->stopAnimation();
- _animationInstance->setLooping(false);
+
+ if (_animationInstance) {
+ _animationInstance->setAnimation(_specialAnim);
+ _animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1);
+ _animationInstance->reset();
+ _animationInstance->stopAnimation();
+ _animationInstance->setLooping(false);
+ }
}
int32 Character::getAnimFlag() {
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 14e7d104d2..2f5051c157 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -2037,23 +2037,19 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
}
}
- int32 myId = 0;
char *myLine;
- if (dialogid < 1000) {
+ if (dialogid < 1000)
myLine = _roomTexts->getText(dialogid);
- myId = dialogid;
- } else {
+ else
myLine = _genericTexts->getText(dialogid - 1000);
- myId = dialogid - 1000;
- }
if (!myLine)
return 0;
bool oldMouseHidden = _gameState->_mouseHidden;
- if (blocking) {
+ if (blocking)
_gameState->_mouseHidden = true;
- }
+
// get what is before the string
int a = READ_LE_UINT16(myLine - 2);
@@ -2090,10 +2086,8 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
while ((waitChar->getAnimFlag() & 0x10) == 0x10 && !_shouldQuit)
doFrame();
}
- } else {
- if (_audioManager->voiceStillPlaying())
- _audioManager->stopCurrentVoice();
- }
+ } else if (_audioManager->voiceStillPlaying())
+ _audioManager->stopCurrentVoice();
for (int32 i = 0; i < numParticipants - 1; i++) {
// listener
@@ -2133,10 +2127,10 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
getTextPosition(talkerId, &_currentTextLineX, &_currentTextLineY);
if (dialogid < 1000) {
- myId = _roomTexts->getId(dialogid);
+ int myId = _roomTexts->getId(dialogid);
_audioManager->playVoice(myId, false);
} else {
- myId = _genericTexts->getId(dialogid - 1000);
+ int myId = _genericTexts->getId(dialogid - 1000);
_audioManager->playVoice(myId, true);
}
diff --git a/engines/touche/console.cpp b/engines/touche/console.cpp
index c4272038dc..472863c817 100644
--- a/engines/touche/console.cpp
+++ b/engines/touche/console.cpp
@@ -26,8 +26,8 @@
namespace Touche {
ToucheConsole::ToucheConsole(ToucheEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("startMusic", WRAP_METHOD(ToucheConsole, Cmd_StartMusic));
- DCmd_Register("stopMusic", WRAP_METHOD(ToucheConsole, Cmd_StopMusic));
+ registerCmd("startMusic", WRAP_METHOD(ToucheConsole, Cmd_StartMusic));
+ registerCmd("stopMusic", WRAP_METHOD(ToucheConsole, Cmd_StopMusic));
}
ToucheConsole::~ToucheConsole() {
@@ -35,7 +35,7 @@ ToucheConsole::~ToucheConsole() {
bool ToucheConsole::Cmd_StartMusic(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: startMusic <num>\n");
+ debugPrintf("Usage: startMusic <num>\n");
return true;
}
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index 97a14e5bc1..1d0e136d69 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -24,7 +24,6 @@
#include "engines/advancedDetector.h"
#include "common/savefile.h"
#include "common/system.h"
-#include "common/translation.h"
#include "base/plugins.h"
diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp
index 19c10af8de..b94776eee5 100644
--- a/engines/touche/menu.cpp
+++ b/engines/touche/menu.cpp
@@ -31,96 +31,6 @@
namespace Touche {
-enum ActionId {
- kActionNone,
-
- // settings menu
- kActionLoadMenu,
- kActionSaveMenu,
- kActionRestartGame,
- kActionPlayGame,
- kActionQuitGame,
- kActionTextOnly,
- kActionVoiceOnly,
- kActionTextAndVoice,
- kActionLowerVolume,
- kActionUpperVolume,
-
- // saveLoad menu
- kActionGameState1,
- kActionGameState2,
- kActionGameState3,
- kActionGameState4,
- kActionGameState5,
- kActionGameState6,
- kActionGameState7,
- kActionGameState8,
- kActionGameState9,
- kActionGameState10,
- kActionScrollUpSaves,
- kActionScrollDownSaves,
- kActionPerformSaveLoad,
- kActionCancelSaveLoad
-};
-
-enum MenuMode {
- kMenuSettingsMode = 0,
- kMenuLoadStateMode,
- kMenuSaveStateMode
-};
-
-enum ButtonFlags {
- kButtonBorder = 1 << 0,
- kButtonText = 1 << 1,
- kButtonArrow = 1 << 2
-};
-
-struct Button {
- int x, y;
- int w, h;
- ActionId action;
- int data;
- uint8 flags;
-};
-
-struct MenuData {
- MenuMode mode;
- Button *buttonsTable;
- uint buttonsCount;
- bool quit;
- bool exit;
- char saveLoadDescriptionsTable[kMaxSaveStates][33];
-
- void removeLastCharFromDescription(int slot) {
- char *description = saveLoadDescriptionsTable[slot];
- int descriptionLen = strlen(description);
- if (descriptionLen > 0) {
- --descriptionLen;
- description[descriptionLen] = 0;
- }
- }
-
- void addCharToDescription(int slot, char chr) {
- char *description = saveLoadDescriptionsTable[slot];
- int descriptionLen = strlen(description);
- if (descriptionLen < 32 && Common::isPrint(chr)) {
- description[descriptionLen] = chr;
- description[descriptionLen + 1] = 0;
- }
- }
-
- const Button *findButtonUnderCursor(int cursorX, int cursorY) const {
- for (uint i = 0; i < buttonsCount; ++i) {
- const Button *button = &buttonsTable[i];
- if (cursorX >= button->x && cursorX < button->x + button->w &&
- cursorY >= button->y && cursorY < button->y + button->h) {
- return button;
- }
- }
- return 0;
- }
-};
-
static void drawArrow(uint8 *dst, int dstPitch, int x, int y, int delta, uint8 color) {
static const int8 arrowCoordsTable[7][4] = {
{ 5, 0, 9, 0 },
@@ -140,25 +50,24 @@ static void drawArrow(uint8 *dst, int dstPitch, int x, int y, int delta, uint8 c
}
}
-void ToucheEngine::drawButton(void *button) {
- Button *b = (Button *)button;
- if (b->flags & kButtonBorder) {
- Graphics::drawRect(_offscreenBuffer, kScreenWidth, b->x, b->y, b->w, b->h, 0xF7, 0xF9);
+void ToucheEngine::drawButton(Button *button) {
+ if (button->flags & kButtonBorder) {
+ Graphics::drawRect(_offscreenBuffer, kScreenWidth, button->x, button->y, button->w, button->h, 0xF7, 0xF9);
}
- if (b->flags & kButtonText) {
- if (b->data != 0) {
- const char *str = getString(b->data);
- const int w = getStringWidth(b->data);
+ if (button->flags & kButtonText) {
+ if (button->data != 0) {
+ const char *str = getString(button->data);
+ const int w = getStringWidth(button->data);
const int h = kTextHeight;
- const int x = b->x + (b->w - w) / 2;
- const int y = b->y + (b->h - h) / 2;
+ const int x = button->x + (button->w - w) / 2;
+ const int y = button->y + (button->h - h) / 2;
Graphics::drawString16(_offscreenBuffer, kScreenWidth, 0xFF, x, y, str);
}
}
- if (b->flags & kButtonArrow) {
+ if (button->flags & kButtonArrow) {
int dx = 0;
int dy = 0;
- switch (b->data) {
+ switch (button->data) {
case 2000: // up arrow
dx = 1;
dy = 2;
@@ -168,8 +77,8 @@ void ToucheEngine::drawButton(void *button) {
dy = -2;
break;
}
- const int x = b->x + b->w / 2;
- const int y = b->y + b->h / 2;
+ const int x = button->x + button->w / 2;
+ const int y = button->y + button->h / 2;
drawArrow(_offscreenBuffer, kScreenWidth, x, y + dy + 1, dx, 0xD2);
drawArrow(_offscreenBuffer, kScreenWidth, x, y + dy, dx, 0xFF);
}
@@ -253,49 +162,47 @@ static void setupMenu(MenuMode mode, MenuData *menuData) {
}
}
-void ToucheEngine::redrawMenu(void *menu) {
- MenuData *menuData = (MenuData *)menu;
+void ToucheEngine::redrawMenu(MenuData *menu) {
Graphics::fillRect(_offscreenBuffer, kScreenWidth, 90, 102, 460, 196, 0xF8);
Graphics::drawRect(_offscreenBuffer, kScreenWidth, 90, 102, 460, 196, 0xF7, 0xF9);
Graphics::drawRect(_offscreenBuffer, kScreenWidth, 106, 118, 340, 164, 0xF9, 0xF7);
- switch (menuData->mode) {
+ switch (menu->mode) {
case kMenuSettingsMode:
drawVolumeSlideBar(_offscreenBuffer, kScreenWidth, getMusicVolume());
- menuData->buttonsTable[5].data = 0;
- menuData->buttonsTable[6].data = 0;
- menuData->buttonsTable[7].data = 0;
- menuData->buttonsTable[5 + _talkTextMode].data = -86;
+ menu->buttonsTable[5].data = 0;
+ menu->buttonsTable[6].data = 0;
+ menu->buttonsTable[7].data = 0;
+ menu->buttonsTable[5 + _talkTextMode].data = -86;
break;
case kMenuLoadStateMode:
case kMenuSaveStateMode:
- drawSaveGameStateDescriptions(_offscreenBuffer, kScreenWidth, menuData, _saveLoadCurrentPage, _saveLoadCurrentSlot);
+ drawSaveGameStateDescriptions(_offscreenBuffer, kScreenWidth, menu, _saveLoadCurrentPage, _saveLoadCurrentSlot);
break;
}
- for (uint i = 0; i < menuData->buttonsCount; ++i) {
- drawButton(&menuData->buttonsTable[i]);
+ for (uint i = 0; i < menu->buttonsCount; ++i) {
+ drawButton(&menu->buttonsTable[i]);
}
}
-void ToucheEngine::handleMenuAction(void *menu, int actionId) {
- MenuData *menuData = (MenuData *)menu;
+void ToucheEngine::handleMenuAction(MenuData *menu, int actionId) {
switch (actionId) {
case kActionLoadMenu:
- menuData->mode = kMenuLoadStateMode;
+ menu->mode = kMenuLoadStateMode;
break;
case kActionSaveMenu:
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
- menuData->mode = kMenuSaveStateMode;
+ menu->mode = kMenuSaveStateMode;
break;
case kActionRestartGame:
restart();
- menuData->quit = true;
+ menu->quit = true;
break;
case kActionPlayGame:
- menuData->quit = true;
+ menu->quit = true;
break;
case kActionQuitGame:
quitGame();
- menuData->quit = true;
+ menu->quit = true;
break;
case kActionTextOnly:
_talkTextMode = kTalkModeTextOnly;
@@ -327,23 +234,23 @@ void ToucheEngine::handleMenuAction(void *menu, int actionId) {
_saveLoadCurrentSlot = _saveLoadCurrentPage * 10 + (_saveLoadCurrentSlot % 10);
break;
case kActionPerformSaveLoad:
- if (menuData->mode == kMenuLoadStateMode) {
+ if (menu->mode == kMenuLoadStateMode) {
if (loadGameState(_saveLoadCurrentSlot).getCode() == Common::kNoError) {
- menuData->quit = true;
+ menu->quit = true;
}
- } else if (menuData->mode == kMenuSaveStateMode) {
+ } else if (menu->mode == kMenuSaveStateMode) {
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
- const char *description = menuData->saveLoadDescriptionsTable[_saveLoadCurrentSlot];
+ const char *description = menu->saveLoadDescriptionsTable[_saveLoadCurrentSlot];
if (strlen(description) > 0) {
if (saveGameState(_saveLoadCurrentSlot, description).getCode() == Common::kNoError) {
- menuData->quit = true;
+ menu->quit = true;
}
}
}
break;
case kActionCancelSaveLoad:
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
- menuData->mode = kMenuSettingsMode;
+ menu->mode = kMenuSettingsMode;
break;
default:
if (actionId >= kActionGameState1 && actionId <= kActionGameState10) {
diff --git a/engines/touche/resource.cpp b/engines/touche/resource.cpp
index 16a95d307f..467d2bed90 100644
--- a/engines/touche/resource.cpp
+++ b/engines/touche/resource.cpp
@@ -150,38 +150,38 @@ void ToucheEngine::res_allocateTables() {
void ToucheEngine::res_deallocateTables() {
free(_textData);
- _textData = 0;
+ _textData = nullptr;
free(_backdropBuffer);
- _backdropBuffer = 0;
+ _backdropBuffer = nullptr;
free(_menuKitData);
- _menuKitData = 0;
+ _menuKitData = nullptr;
free(_convKitData);
- _convKitData = 0;
+ _convKitData = nullptr;
for (int i = 0; i < NUM_SEQUENCES; ++i) {
free(_sequenceDataTable[i]);
- _sequenceDataTable[i] = 0;
+ _sequenceDataTable[i] = nullptr;
}
free(_programData);
- _programData = 0;
+ _programData = nullptr;
free(_mouseData);
- _mouseData = 0;
+ _mouseData = nullptr;
free(_iconData);
- _iconData = 0;
+ _iconData = nullptr;
for (int i = 0; i < NUM_SPRITES; ++i) {
free(_spritesTable[i].ptr);
- _spritesTable[i].ptr = 0;
+ _spritesTable[i].ptr = nullptr;
}
free(_offscreenBuffer);
- _offscreenBuffer = 0;
+ _offscreenBuffer = nullptr;
}
uint32 ToucheEngine::res_getDataOffset(ResourceType type, int num, uint32 *size) {
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index 09697d0e4a..ff4f41f44d 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -46,32 +46,32 @@
namespace Touche {
ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
- : Engine(system), _midiPlayer(0), _language(language), _rnd("touche") {
+ : Engine(system), _midiPlayer(nullptr), _language(language), _rnd("touche") {
_saveLoadCurrentPage = 0;
_saveLoadCurrentSlot = 0;
_hideInventoryTexts = false;
_numOpcodes = 0;
_compressedSpeechData = 0;
- _textData = 0;
- _backdropBuffer = 0;
- _menuKitData = 0;
- _convKitData = 0;
+ _textData = nullptr;
+ _backdropBuffer = nullptr;
+ _menuKitData = nullptr;
+ _convKitData = nullptr;
for (int i = 0; i < NUM_SEQUENCES; i++)
- _sequenceDataTable[i] = 0;
+ _sequenceDataTable[i] = nullptr;
- _programData = 0;
+ _programData = nullptr;
_programDataSize = 0;
- _mouseData = 0;
- _iconData = 0;
+ _mouseData = nullptr;
+ _iconData = nullptr;
_currentBitmapWidth = 0;
_currentBitmapHeight = 0;
_currentImageWidth = 0;
_currentImageHeight = 0;
_roomWidth = 0;
- _programTextDataPtr = 0;
- _offscreenBuffer = 0;
+ _programTextDataPtr = nullptr;
+ _offscreenBuffer = nullptr;
_screenRect = Common::Rect(kScreenWidth, kScreenHeight);
_roomAreaRect = Common::Rect(kScreenWidth, kRoomHeight);
@@ -124,11 +124,11 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
_script.opcodeNum = 0;
_script.dataOffset = 0;
_script.keyCharNum = 0;
- _script.dataPtr = 0;
- _script.stackDataPtr = 0;
- _script.stackDataBasePtr = 0;
+ _script.dataPtr = nullptr;
+ _script.stackDataPtr = nullptr;
+ _script.stackDataBasePtr = nullptr;
_script.quitFlag = 0;
- _opcodesTable = 0;
+ _opcodesTable = nullptr;
for (uint i = 0; i < NUM_SPRITES; i++)
memset(&_spritesTable[i], 0, sizeof(SpriteData));
@@ -138,10 +138,10 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
_talkListEnd = 0;
_talkListCurrent = 0;
- _talkTextRectDefined = 0;
- _talkTextDisplayed = 0;
- _talkTextInitialized = 0;
- _skipTalkText = 0;
+ _talkTextRectDefined = false;
+ _talkTextDisplayed = false;
+ _talkTextInitialized = false;
+ _skipTalkText = false;
_talkTextSpeed = 0;
_keyCharTalkCounter = 0;
_talkTableLastTalkingKeyChar = 0;
@@ -151,14 +151,14 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
for (uint i = 0; i < NUM_TALK_ENTRIES; i++)
memset(&_talkTable[i], 0, sizeof(TalkEntry));
- _conversationChoicesUpdated = 0;
+ _conversationChoicesUpdated = false;
_conversationReplyNum = 0;
- _conversationEnded = 0;
+ _conversationEnded = false;
_conversationNum = 0;
_scrollConversationChoiceOffset = 0;
_currentConversation = 0;
- _disableConversationScript = 0;
- _conversationAreaCleared = 0;
+ _disableConversationScript = false;
+ _conversationAreaCleared = false;
for (uint i = 0; i < NUM_CONVERSATION_CHOICES; i++)
memset(&_conversationChoicesTable[i], 0, sizeof(ConversationChoice));
@@ -167,6 +167,26 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
_sortedKeyCharsTable[i] = 0;
_currentKeyCharNum = 0;
+ _inp_leftMouseButtonPressed = false;
+ _inp_rightMouseButtonPressed = false;
+ _disabledInputCounter = 0;
+ _gameState = kGameStateNone;
+ _displayQuitDialog = false;
+ _newMusicNum = 0;
+ _currentMusicNum = 0;
+ _newSoundNum = 0;
+ _newSoundDelay = 0;
+ _newSoundPriority = 0;
+ for (int i = 0; i < 3; ++i) {
+ _inventoryStateTable[i].displayOffset = 0;
+ _inventoryStateTable[i].lastItem = 0;
+ _inventoryStateTable[i].itemsPerLine = 0;
+ _inventoryStateTable[i].itemsList = nullptr;
+ }
+ _inventoryVar1 = nullptr;
+ _inventoryVar2 = nullptr;
+ _currentCursorObject = 0;
+ _talkTextMode = 0;
}
ToucheEngine::~ToucheEngine() {
@@ -3094,12 +3114,12 @@ void ToucheEngine::buildWalkPath(int dstPosX, int dstPosY, int keyChar) {
for (uint i = 0; i < _programWalkTable.size(); ++i) {
const ProgramWalkData *pwd = &_programWalkTable[i];
if ((pwd->point1 & 0x4000) == 0) {
- int distance = 32000;
ProgramPointData *pts1 = &_programPointsTable[pwd->point1];
ProgramPointData *pts2 = &_programPointsTable[pwd->point2];
if (pts1->order != 0) {
int dx = pts2->x - pts1->x;
int dy = pts2->y - pts1->y;
+ int distance = 32000;
if (dx == 0) {
if (dstPosY > MIN(pts2->y, pts1->y) && dstPosY < MAX(pts2->y, pts1->y)) {
int d = ABS(dstPosX - pts1->x);
diff --git a/engines/touche/touche.h b/engines/touche/touche.h
index 3da33f593b..20bf723553 100644
--- a/engines/touche/touche.h
+++ b/engines/touche/touche.h
@@ -346,16 +346,108 @@ enum StringType {
kStringTypeConversation
};
-void readGameStateDescription(Common::ReadStream *f, char *description, int len);
-Common::String generateGameStateFileName(const char *target, int slot, bool prefixOnly = false);
-int getGameStateFileSlot(const char *filename);
-
enum GameState {
kGameStateGameLoop,
kGameStateOptionsDialog,
- kGameStateQuitDialog
+ kGameStateQuitDialog,
+ kGameStateNone
+};
+
+enum ActionId {
+ kActionNone,
+
+ // settings menu
+ kActionLoadMenu,
+ kActionSaveMenu,
+ kActionRestartGame,
+ kActionPlayGame,
+ kActionQuitGame,
+ kActionTextOnly,
+ kActionVoiceOnly,
+ kActionTextAndVoice,
+ kActionLowerVolume,
+ kActionUpperVolume,
+
+ // saveLoad menu
+ kActionGameState1,
+ kActionGameState2,
+ kActionGameState3,
+ kActionGameState4,
+ kActionGameState5,
+ kActionGameState6,
+ kActionGameState7,
+ kActionGameState8,
+ kActionGameState9,
+ kActionGameState10,
+ kActionScrollUpSaves,
+ kActionScrollDownSaves,
+ kActionPerformSaveLoad,
+ kActionCancelSaveLoad
+};
+
+enum MenuMode {
+ kMenuSettingsMode = 0,
+ kMenuLoadStateMode,
+ kMenuSaveStateMode
+};
+
+enum ButtonFlags {
+ kButtonBorder = 1 << 0,
+ kButtonText = 1 << 1,
+ kButtonArrow = 1 << 2
};
+struct Button {
+ int x, y;
+ int w, h;
+ ActionId action;
+ int data;
+ uint8 flags;
+};
+
+struct MenuData {
+ MenuMode mode;
+ Button *buttonsTable;
+ uint buttonsCount;
+ bool quit;
+ bool exit;
+ char saveLoadDescriptionsTable[kMaxSaveStates][33];
+
+ void removeLastCharFromDescription(int slot) {
+ char *description = saveLoadDescriptionsTable[slot];
+ int descriptionLen = strlen(description);
+ if (descriptionLen > 0) {
+ --descriptionLen;
+ description[descriptionLen] = 0;
+ }
+ }
+
+ void addCharToDescription(int slot, char chr) {
+ char *description = saveLoadDescriptionsTable[slot];
+ int descriptionLen = strlen(description);
+ if (descriptionLen < 32 && Common::isPrint(chr)) {
+ description[descriptionLen] = chr;
+ description[descriptionLen + 1] = 0;
+ }
+ }
+
+ const Button *findButtonUnderCursor(int cursorX, int cursorY) const {
+ for (uint i = 0; i < buttonsCount; ++i) {
+ const Button *button = &buttonsTable[i];
+ if (cursorX >= button->x && cursorX < button->x + button->w &&
+ cursorY >= button->y && cursorY < button->y + button->h) {
+ return button;
+ }
+ }
+ return 0;
+ }
+};
+
+
+void readGameStateDescription(Common::ReadStream *f, char *description, int len);
+Common::String generateGameStateFileName(const char *target, int slot, bool prefixOnly = false);
+int getGameStateFileSlot(const char *filename);
+
class MidiPlayer;
class ToucheEngine: public Engine {
@@ -631,9 +723,9 @@ protected:
void res_loadSpeechSegment(int num);
void res_stopSpeech();
- void drawButton(void *button);
- void redrawMenu(void *menu);
- void handleMenuAction(void *menu, int actionId);
+ void drawButton(Button *button);
+ void redrawMenu(MenuData *menu);
+ void handleMenuAction(MenuData *menu, int actionId);
void handleOptions(int forceDisplay);
void drawActionsPanel(int dstX, int dstY, int deltaX, int deltaY);
void drawConversationPanelBorder(int dstY, int srcX, int srcY);
diff --git a/engines/tsage/POTFILES b/engines/tsage/POTFILES
new file mode 100644
index 0000000000..de18cbd072
--- /dev/null
+++ b/engines/tsage/POTFILES
@@ -0,0 +1,3 @@
+engines/tsage/dialogs.cpp
+engines/tsage/scenes.cpp
+
diff --git a/engines/tsage/blue_force/blueforce_dialogs.cpp b/engines/tsage/blue_force/blueforce_dialogs.cpp
index 2f337ac549..5be27c9ae7 100644
--- a/engines/tsage/blue_force/blueforce_dialogs.cpp
+++ b/engines/tsage/blue_force/blueforce_dialogs.cpp
@@ -20,8 +20,6 @@
*
*/
-#include "common/translation.h"
-
#include "gui/dialog.h"
#include "gui/widget.h"
diff --git a/engines/tsage/debugger.cpp b/engines/tsage/debugger.cpp
index 5a520b0e89..a38796717a 100644
--- a/engines/tsage/debugger.cpp
+++ b/engines/tsage/debugger.cpp
@@ -30,19 +30,19 @@
namespace TsAGE {
Debugger::Debugger() : GUI::Debugger() {
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("scene", WRAP_METHOD(Debugger, Cmd_Scene));
- DCmd_Register("walk_regions", WRAP_METHOD(Debugger, Cmd_WalkRegions));
- DCmd_Register("priority_regions", WRAP_METHOD(Debugger, Cmd_PriorityRegions));
- DCmd_Register("scene_regions", WRAP_METHOD(Debugger, Cmd_SceneRegions));
- DCmd_Register("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag));
- DCmd_Register("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag));
- DCmd_Register("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag));
- DCmd_Register("listobjects", WRAP_METHOD(Debugger, Cmd_ListObjects));
- DCmd_Register("moveobject", WRAP_METHOD(Debugger, Cmd_MoveObject));
- DCmd_Register("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots));
- DCmd_Register("sound", WRAP_METHOD(Debugger, Cmd_Sound));
- DCmd_Register("setdebug", WRAP_METHOD(Debugger, Cmd_SetDebug));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("scene", WRAP_METHOD(Debugger, Cmd_Scene));
+ registerCmd("walk_regions", WRAP_METHOD(Debugger, Cmd_WalkRegions));
+ registerCmd("priority_regions", WRAP_METHOD(Debugger, Cmd_PriorityRegions));
+ registerCmd("scene_regions", WRAP_METHOD(Debugger, Cmd_SceneRegions));
+ registerCmd("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag));
+ registerCmd("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag));
+ registerCmd("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag));
+ registerCmd("listobjects", WRAP_METHOD(Debugger, Cmd_ListObjects));
+ registerCmd("moveobject", WRAP_METHOD(Debugger, Cmd_MoveObject));
+ registerCmd("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots));
+ registerCmd("sound", WRAP_METHOD(Debugger, Cmd_Sound));
+ registerCmd("setdebug", WRAP_METHOD(Debugger, Cmd_SetOutpostAlphaDebug));
}
static int strToInt(const char *s) {
@@ -66,7 +66,7 @@ static int strToInt(const char *s) {
*/
bool Debugger::Cmd_Scene(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: %s <scene number> [prior scene #]\n", argv[0]);
+ debugPrintf("Usage: %s <scene number> [prior scene #]\n", argv[0]);
return true;
}
@@ -82,7 +82,7 @@ bool Debugger::Cmd_Scene(int argc, const char **argv) {
*/
bool Debugger::Cmd_WalkRegions(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
@@ -120,8 +120,8 @@ bool Debugger::Cmd_WalkRegions(int argc, const char **argv) {
// Mark the scene as requiring a full redraw
g_globals->_paneRefreshFlag[0] = 2;
- DebugPrintf("Total regions = %d\n", g_globals->_walkRegions._regionList.size());
- DebugPrintf("%s\n", regionsDesc.c_str());
+ debugPrintf("Total regions = %d\n", g_globals->_walkRegions._regionList.size());
+ debugPrintf("%s\n", regionsDesc.c_str());
return false;
}
@@ -172,8 +172,8 @@ bool Debugger::Cmd_PriorityRegions(int argc, const char **argv) {
// Mark the scene as requiring a full redraw
g_globals->_paneRefreshFlag[0] = 2;
- DebugPrintf("Total regions = %d\n", count);
- DebugPrintf("%s", regionsDesc.c_str());
+ debugPrintf("Total regions = %d\n", count);
+ debugPrintf("%s", regionsDesc.c_str());
return true;
}
@@ -225,8 +225,8 @@ bool Debugger::Cmd_SceneRegions(int argc, const char **argv) {
// Mark the scene as requiring a full redraw
g_globals->_paneRefreshFlag[0] = 2;
- DebugPrintf("Total regions = %d\n", count);
- DebugPrintf("%s", regionsDesc.c_str());
+ debugPrintf("Total regions = %d\n", count);
+ debugPrintf("%s", regionsDesc.c_str());
return true;
}
@@ -237,7 +237,7 @@ bool Debugger::Cmd_SceneRegions(int argc, const char **argv) {
bool Debugger::Cmd_SetFlag(int argc, const char **argv) {
// Check for a flag to set
if (argc != 2) {
- DebugPrintf("Usage: %s <flag number>\n", argv[0]);
+ debugPrintf("Usage: %s <flag number>\n", argv[0]);
return true;
}
@@ -252,12 +252,12 @@ bool Debugger::Cmd_SetFlag(int argc, const char **argv) {
bool Debugger::Cmd_GetFlag(int argc, const char **argv) {
// Check for an flag to display
if (argc != 2) {
- DebugPrintf("Usage: %s <flag number>\n", argv[0]);
+ debugPrintf("Usage: %s <flag number>\n", argv[0]);
return true;
}
int flagNum = strToInt(argv[1]);
- DebugPrintf("Value: %d\n", g_globals->getFlag(flagNum));
+ debugPrintf("Value: %d\n", g_globals->getFlag(flagNum));
return true;
}
@@ -267,7 +267,7 @@ bool Debugger::Cmd_GetFlag(int argc, const char **argv) {
bool Debugger::Cmd_ClearFlag(int argc, const char **argv) {
// Check for a flag to clear
if (argc != 2) {
- DebugPrintf("Usage: %s <flag number>\n", argv[0]);
+ debugPrintf("Usage: %s <flag number>\n", argv[0]);
return true;
}
@@ -332,7 +332,7 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) {
*/
bool Debugger::Cmd_Sound(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Usage: %s <sound number>\n", argv[0]);
+ debugPrintf("Usage: %s <sound number>\n", argv[0]);
return true;
}
@@ -344,8 +344,8 @@ bool Debugger::Cmd_Sound(int argc, const char **argv) {
/**
* Activate internal debugger, when available
*/
-bool Debugger::Cmd_SetDebug(int argc, const char **argv) {
- DebugPrintf("Not available in this game\n");
+bool Debugger::Cmd_SetOutpostAlphaDebug(int argc, const char **argv) {
+ debugPrintf("Not available in this game\n");
return true;
}
@@ -353,12 +353,12 @@ bool Debugger::Cmd_SetDebug(int argc, const char **argv) {
* This command lists the objects available, and their ID
*/
bool DemoDebugger::Cmd_ListObjects(int argc, const char **argv) {
- DebugPrintf("Not available in Demo\n");
+ debugPrintf("Not available in Demo\n");
return true;
}
bool DemoDebugger::Cmd_MoveObject(int argc, const char **argv) {
- DebugPrintf("Not available in Demo\n");
+ debugPrintf("Not available in Demo\n");
return true;
}
@@ -367,44 +367,44 @@ bool DemoDebugger::Cmd_MoveObject(int argc, const char **argv) {
*/
bool RingworldDebugger::Cmd_ListObjects(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
- DebugPrintf("Available objects for this game are:\n");
- DebugPrintf("0 - Stunner\n");
- DebugPrintf("1 - Scanner\n");
- DebugPrintf("2 - Stasis Box\n");
- DebugPrintf("3 - Info Disk\n");
- DebugPrintf("4 - Stasis Negator\n");
- DebugPrintf("5 - Key Device\n");
- DebugPrintf("6 - Medkit\n");
- DebugPrintf("7 - Ladder\n");
- DebugPrintf("8 - Rope\n");
- DebugPrintf("9 - Key\n");
- DebugPrintf("10 - Translator\n");
- DebugPrintf("11 - Ale\n");
- DebugPrintf("12 - Paper\n");
- DebugPrintf("13 - Waldos\n");
- DebugPrintf("14 - Stasis Box 2\n");
- DebugPrintf("15 - Ring\n");
- DebugPrintf("16 - Cloak\n");
- DebugPrintf("17 - Tunic\n");
- DebugPrintf("18 - Candle\n");
- DebugPrintf("19 - Straw\n");
- DebugPrintf("20 - Scimitar\n");
- DebugPrintf("21 - Sword\n");
- DebugPrintf("22 - Helmet\n");
- DebugPrintf("23 - Items\n");
- DebugPrintf("24 - Concentrator\n");
- DebugPrintf("25 - Nullifier\n");
- DebugPrintf("26 - Peg\n");
- DebugPrintf("27 - Vial\n");
- DebugPrintf("28 - Jacket\n");
- DebugPrintf("29 - Tunic 2\n");
- DebugPrintf("30 - Bone\n");
- DebugPrintf("31 - Empty Jar\n");
- DebugPrintf("32 - Jar\n");
+ debugPrintf("Available objects for this game are:\n");
+ debugPrintf("0 - Stunner\n");
+ debugPrintf("1 - Scanner\n");
+ debugPrintf("2 - Stasis Box\n");
+ debugPrintf("3 - Info Disk\n");
+ debugPrintf("4 - Stasis Negator\n");
+ debugPrintf("5 - Key Device\n");
+ debugPrintf("6 - Medkit\n");
+ debugPrintf("7 - Ladder\n");
+ debugPrintf("8 - Rope\n");
+ debugPrintf("9 - Key\n");
+ debugPrintf("10 - Translator\n");
+ debugPrintf("11 - Ale\n");
+ debugPrintf("12 - Paper\n");
+ debugPrintf("13 - Waldos\n");
+ debugPrintf("14 - Stasis Box 2\n");
+ debugPrintf("15 - Ring\n");
+ debugPrintf("16 - Cloak\n");
+ debugPrintf("17 - Tunic\n");
+ debugPrintf("18 - Candle\n");
+ debugPrintf("19 - Straw\n");
+ debugPrintf("20 - Scimitar\n");
+ debugPrintf("21 - Sword\n");
+ debugPrintf("22 - Helmet\n");
+ debugPrintf("23 - Items\n");
+ debugPrintf("24 - Concentrator\n");
+ debugPrintf("25 - Nullifier\n");
+ debugPrintf("26 - Peg\n");
+ debugPrintf("27 - Vial\n");
+ debugPrintf("28 - Jacket\n");
+ debugPrintf("29 - Tunic 2\n");
+ debugPrintf("30 - Bone\n");
+ debugPrintf("31 - Empty Jar\n");
+ debugPrintf("32 - Jar\n");
return true;
}
@@ -414,8 +414,8 @@ bool RingworldDebugger::Cmd_ListObjects(int argc, const char **argv) {
bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) {
// Check for a flag to clear
if ((argc < 2) || (argc > 3)){
- DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]);
- DebugPrintf("If no scene is specified, the object will be added to inventory\n");
+ debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]);
+ debugPrintf("If no scene is specified, the object will be added to inventory\n");
return true;
}
@@ -525,7 +525,7 @@ bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) {
RING_INVENTORY._jar._sceneNumber = sceneNum;
break;
default:
- DebugPrintf("Invalid object Id %s\n", argv[1]);
+ debugPrintf("Invalid object Id %s\n", argv[1]);
break;
}
@@ -537,83 +537,83 @@ bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) {
*/
bool BlueForceDebugger::Cmd_ListObjects(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
- DebugPrintf("Available objects for this game are:\n");
- DebugPrintf("1 - INV_COLT45\n");
- DebugPrintf("2 - INV_AMMO_CLIP\n");
- DebugPrintf("3 - INV_SPARE_CLIP\n");
- DebugPrintf("4 - INV_HANDCUFFS\n");
- DebugPrintf("5 - INV_GREENS_GUN\n");
- DebugPrintf("6 - INV_TICKET_BOOK\n");
- DebugPrintf("7 - INV_MIRANDA_CARD\n");
- DebugPrintf("8 - INV_FOREST_RAP\n");
- DebugPrintf("9 - INV_GREEN_ID\n");
- DebugPrintf("10 - INV_BASEBALL_CARD\n");
- DebugPrintf("11 - INV_BOOKING_GREEN\n");
- DebugPrintf("12 - INV_FLARE\n");
- DebugPrintf("13 - INV_COBB_RAP\n");
- DebugPrintf("14 - INV_22_BULLET\n");
- DebugPrintf("15 - INV_AUTO_RIFLE\n");
- DebugPrintf("16 - INV_WIG\n");
- DebugPrintf("17 - INV_FRANKIE_ID\n");
- DebugPrintf("18 - INV_TYRONE_ID\n");
- DebugPrintf("19 - INV_22_SNUB\n");
- DebugPrintf("20 - INV_BOOKING_FRANKIE\n");
- DebugPrintf("21 - INV_BOOKING_GANG\n");
- DebugPrintf("22 - INV_FBI_TELETYPE\n");
- DebugPrintf("23 - INV_DA_NOTE\n");
- DebugPrintf("24 - INV_PRINT_OUT\n");
- DebugPrintf("25 - INV_WAREHOUSE_KEYS\n");
- DebugPrintf("26 - INV_CENTER_PUNCH\n");
- DebugPrintf("27 - INV_TRANQ_GUN\n");
- DebugPrintf("28 - INV_HOOK\n");
- DebugPrintf("29 - INV_RAGS\n");
- DebugPrintf("30 - INV_JAR\n");
- DebugPrintf("31 - INV_SCREWDRIVER\n");
- DebugPrintf("32 - INV_D_FLOPPY\n");
- DebugPrintf("33 - INV_BLANK_DISK\n");
- DebugPrintf("34 - INV_STICK\n");
- DebugPrintf("35 - INV_CRATE1\n");
- DebugPrintf("36 - INV_CRATE2\n");
- DebugPrintf("37 - INV_SHOEBOX\n");
- DebugPrintf("38 - INV_BADGE\n");
- DebugPrintf("39 - INV_RENTAL_COUPON\n");
- DebugPrintf("40 - INV_NICKEL\n");
- DebugPrintf("41 - INV_LYLE_CARD\n");
- DebugPrintf("42 - INV_CARTER_NOTE\n");
- DebugPrintf("43 - INV_MUG_SHOT\n");
- DebugPrintf("44 - INV_CLIPPING\n");
- DebugPrintf("45 - INV_MICROFILM \n");
- DebugPrintf("46 - INV_WAVE_KEYS\n");
- DebugPrintf("47 - INV_RENTAL_KEYS\n");
- DebugPrintf("48 - INV_NAPKIN\n");
- DebugPrintf("49 - INV_DMV_PRINTOUT\n");
- DebugPrintf("50 - INV_FISHING_NET\n");
- DebugPrintf("51 - INV_ID\n");
- DebugPrintf("52 - INV_9MM_BULLETS\n");
- DebugPrintf("53 - INV_SCHEDULE\n");
- DebugPrintf("54 - INV_GRENADES\n");
- DebugPrintf("55 - INV_YELLOW_CORD\n");
- DebugPrintf("56 - INV_HALF_YELLOW_CORD\n");
- DebugPrintf("57 - INV_BLACK_CORD\n");
- DebugPrintf("58 - INV_HALF_BLACK_CORD\n");
- DebugPrintf("59 - INV_WARRANT\n");
- DebugPrintf("60 - INV_JACKET\n");
- DebugPrintf("61 - INV_GREENS_KNIFE\n");
- DebugPrintf("62 - INV_DOG_WHISTLE\n");
- DebugPrintf("63 - INV_AMMO_BELT\n");
- DebugPrintf("64 - INV_CARAVAN_KEY\n");
+ debugPrintf("Available objects for this game are:\n");
+ debugPrintf("1 - INV_COLT45\n");
+ debugPrintf("2 - INV_AMMO_CLIP\n");
+ debugPrintf("3 - INV_SPARE_CLIP\n");
+ debugPrintf("4 - INV_HANDCUFFS\n");
+ debugPrintf("5 - INV_GREENS_GUN\n");
+ debugPrintf("6 - INV_TICKET_BOOK\n");
+ debugPrintf("7 - INV_MIRANDA_CARD\n");
+ debugPrintf("8 - INV_FOREST_RAP\n");
+ debugPrintf("9 - INV_GREEN_ID\n");
+ debugPrintf("10 - INV_BASEBALL_CARD\n");
+ debugPrintf("11 - INV_BOOKING_GREEN\n");
+ debugPrintf("12 - INV_FLARE\n");
+ debugPrintf("13 - INV_COBB_RAP\n");
+ debugPrintf("14 - INV_22_BULLET\n");
+ debugPrintf("15 - INV_AUTO_RIFLE\n");
+ debugPrintf("16 - INV_WIG\n");
+ debugPrintf("17 - INV_FRANKIE_ID\n");
+ debugPrintf("18 - INV_TYRONE_ID\n");
+ debugPrintf("19 - INV_22_SNUB\n");
+ debugPrintf("20 - INV_BOOKING_FRANKIE\n");
+ debugPrintf("21 - INV_BOOKING_GANG\n");
+ debugPrintf("22 - INV_FBI_TELETYPE\n");
+ debugPrintf("23 - INV_DA_NOTE\n");
+ debugPrintf("24 - INV_PRINT_OUT\n");
+ debugPrintf("25 - INV_WAREHOUSE_KEYS\n");
+ debugPrintf("26 - INV_CENTER_PUNCH\n");
+ debugPrintf("27 - INV_TRANQ_GUN\n");
+ debugPrintf("28 - INV_HOOK\n");
+ debugPrintf("29 - INV_RAGS\n");
+ debugPrintf("30 - INV_JAR\n");
+ debugPrintf("31 - INV_SCREWDRIVER\n");
+ debugPrintf("32 - INV_D_FLOPPY\n");
+ debugPrintf("33 - INV_BLANK_DISK\n");
+ debugPrintf("34 - INV_STICK\n");
+ debugPrintf("35 - INV_CRATE1\n");
+ debugPrintf("36 - INV_CRATE2\n");
+ debugPrintf("37 - INV_SHOEBOX\n");
+ debugPrintf("38 - INV_BADGE\n");
+ debugPrintf("39 - INV_RENTAL_COUPON\n");
+ debugPrintf("40 - INV_NICKEL\n");
+ debugPrintf("41 - INV_LYLE_CARD\n");
+ debugPrintf("42 - INV_CARTER_NOTE\n");
+ debugPrintf("43 - INV_MUG_SHOT\n");
+ debugPrintf("44 - INV_CLIPPING\n");
+ debugPrintf("45 - INV_MICROFILM \n");
+ debugPrintf("46 - INV_WAVE_KEYS\n");
+ debugPrintf("47 - INV_RENTAL_KEYS\n");
+ debugPrintf("48 - INV_NAPKIN\n");
+ debugPrintf("49 - INV_DMV_PRINTOUT\n");
+ debugPrintf("50 - INV_FISHING_NET\n");
+ debugPrintf("51 - INV_ID\n");
+ debugPrintf("52 - INV_9MM_BULLETS\n");
+ debugPrintf("53 - INV_SCHEDULE\n");
+ debugPrintf("54 - INV_GRENADES\n");
+ debugPrintf("55 - INV_YELLOW_CORD\n");
+ debugPrintf("56 - INV_HALF_YELLOW_CORD\n");
+ debugPrintf("57 - INV_BLACK_CORD\n");
+ debugPrintf("58 - INV_HALF_BLACK_CORD\n");
+ debugPrintf("59 - INV_WARRANT\n");
+ debugPrintf("60 - INV_JACKET\n");
+ debugPrintf("61 - INV_GREENS_KNIFE\n");
+ debugPrintf("62 - INV_DOG_WHISTLE\n");
+ debugPrintf("63 - INV_AMMO_BELT\n");
+ debugPrintf("64 - INV_CARAVAN_KEY\n");
return true;
}
bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) {
// Check for a flag to clear
if ((argc < 2) || (argc > 3)){
- DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]);
- DebugPrintf("If no scene is specified, the object will be added to inventory\n");
+ debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]);
+ debugPrintf("If no scene is specified, the object will be added to inventory\n");
return true;
}
@@ -625,7 +625,7 @@ bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) {
if ((objNum > 0) && (objNum < 65))
BF_INVENTORY.setObjectScene(objNum, sceneNum);
else
- DebugPrintf("Invalid object Id %s\n", argv[1]);
+ debugPrintf("Invalid object Id %s\n", argv[1]);
return true;
}
@@ -635,63 +635,63 @@ bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) {
*/
bool Ringworld2Debugger::Cmd_ListObjects(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
- DebugPrintf("Available objects for this game are:\n");
- DebugPrintf("1 - Scene %d - R2_OPTO_DISK\n", BF_INVENTORY.getObjectScene(1));
- DebugPrintf("2 - Scene %d - R2_READER\n", BF_INVENTORY.getObjectScene(2));
- DebugPrintf("3 - Scene %d - R2_NEGATOR_GUN\n", BF_INVENTORY.getObjectScene(3));
- DebugPrintf("4 - Scene %d - R2_STEPPING_DISKS\n", BF_INVENTORY.getObjectScene(4));
- DebugPrintf("5 - Scene %d - R2_ATTRACTOR_UNIT\n", BF_INVENTORY.getObjectScene(5));
- DebugPrintf("6 - Scene %d - R2_SENSOR_PROBE\n", BF_INVENTORY.getObjectScene(6));
- DebugPrintf("7 - Scene %d - R2_SONIC_STUNNER\n", BF_INVENTORY.getObjectScene(7));
- DebugPrintf("8 - Scene %d - R2_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(8));
- DebugPrintf("9 - Scene %d - R2_COM_SCANNER\n", BF_INVENTORY.getObjectScene(9));
- DebugPrintf("10 - Scene %d - R2_SPENT_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(10));
- DebugPrintf("11 - Scene %d - R2_CHARGED_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(11));
- DebugPrintf("12 - Scene %d - R2_AEROSOL\n", BF_INVENTORY.getObjectScene(12));
- DebugPrintf("13 - Scene %d - R2_REMOTE_CONTROL\n", BF_INVENTORY.getObjectScene(13));
- DebugPrintf("14 - Scene %d - R2_OPTICAL_FIBER\n", BF_INVENTORY.getObjectScene(14));
- DebugPrintf("15 - Scene %d - R2_CLAMP\n", BF_INVENTORY.getObjectScene(15));
- DebugPrintf("16 - Scene %d - R2_ATTRACTOR_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(16));
- DebugPrintf("17 - Scene %d - R2_FUEL_CELL\n", BF_INVENTORY.getObjectScene(17));
- DebugPrintf("18 - Scene %d - R2_GYROSCOPE\n", BF_INVENTORY.getObjectScene(18));
- DebugPrintf("19 - Scene %d - R2_AIRBAG\n", BF_INVENTORY.getObjectScene(19));
- DebugPrintf("20 - Scene %d - R2_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(20));
- DebugPrintf("21 - Scene %d - R2_RESERVE_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(21));
- DebugPrintf("22 - Scene %d - R2_GUIDANCE_MODULE\n", BF_INVENTORY.getObjectScene(22));
- DebugPrintf("23 - Scene %d - R2_THRUSTER_VALVE\n", BF_INVENTORY.getObjectScene(23));
- DebugPrintf("24 - Scene %d - R2_BALLOON_BACKPACK\n", BF_INVENTORY.getObjectScene(24));
- DebugPrintf("25 - Scene %d - R2_RADAR_MECHANISM\n", BF_INVENTORY.getObjectScene(25));
- DebugPrintf("26 - Scene %d - R2_JOYSTICK\n", BF_INVENTORY.getObjectScene(26));
- DebugPrintf("27 - Scene %d - R2_IGNITOR\n", BF_INVENTORY.getObjectScene(27));
- DebugPrintf("28 - Scene %d - R2_DIAGNOSTICS_DISPLAY\n", BF_INVENTORY.getObjectScene(28));
- DebugPrintf("29 - Scene %d - R2_GLASS_DOME\n", BF_INVENTORY.getObjectScene(29));
- DebugPrintf("30 - Scene %d - R2_WICK_LAMP\n", BF_INVENTORY.getObjectScene(30));
- DebugPrintf("31 - Scene %d - R2_SCRITH_KEY\n", BF_INVENTORY.getObjectScene(31));
- DebugPrintf("32 - Scene %d - R2_TANNER_MASK\n", BF_INVENTORY.getObjectScene(32));
- DebugPrintf("33 - Scene %d - R2_PURE_GRAIN_ALCOHOL\n", BF_INVENTORY.getObjectScene(33));
- DebugPrintf("34 - Scene %d - R2_SAPPHIRE_BLUE\n", BF_INVENTORY.getObjectScene(34));
- DebugPrintf("35 - Scene %d - R2_ANCIENT_SCROLLS\n", BF_INVENTORY.getObjectScene(35));
- DebugPrintf("36 - Scene %d - R2_FLUTE\n", BF_INVENTORY.getObjectScene(36));
- DebugPrintf("37 - Scene %d - R2_GUNPOWDER\n", BF_INVENTORY.getObjectScene(37));
- DebugPrintf("38 - Scene %d - R2_NONAME\n", BF_INVENTORY.getObjectScene(38));
- DebugPrintf("39 - Scene %d - R2_COM_SCANNER_2\n", BF_INVENTORY.getObjectScene(39));
- DebugPrintf("40 - Scene %d - R2_SUPERCONDUCTOR_WIRE\n", BF_INVENTORY.getObjectScene(40));
- DebugPrintf("41 - Scene %d - R2_PILLOW\n", BF_INVENTORY.getObjectScene(41));
- DebugPrintf("42 - Scene %d - R2_FOOD_TRAY\n", BF_INVENTORY.getObjectScene(42));
- DebugPrintf("43 - Scene %d - R2_LASER_HACKSAW\n", BF_INVENTORY.getObjectScene(43));
- DebugPrintf("44 - Scene %d - R2_PHOTON_STUNNER\n", BF_INVENTORY.getObjectScene(44));
- DebugPrintf("45 - Scene %d - R2_BATTERY\n", BF_INVENTORY.getObjectScene(45));
- DebugPrintf("46 - Scene %d - R2_SOAKED_FACEMASK\n", BF_INVENTORY.getObjectScene(46));
- DebugPrintf("47 - Scene %d - R2_LIGHT_BULB\n", BF_INVENTORY.getObjectScene(47));
- DebugPrintf("48 - Scene %d - R2_ALCOHOL_LAMP\n", BF_INVENTORY.getObjectScene(48));
- DebugPrintf("49 - Scene %d - R2_ALCOHOL_LAMP_2\n", BF_INVENTORY.getObjectScene(49));
- DebugPrintf("50 - Scene %d - R2_ALCOHOL_LAMP_3\n", BF_INVENTORY.getObjectScene(50));
- DebugPrintf("51 - Scene %d - R2_BROKEN_DISPLAY\n", BF_INVENTORY.getObjectScene(51));
- DebugPrintf("52 - Scene %d - R2_TOOLBOX\n", BF_INVENTORY.getObjectScene(52));
+ debugPrintf("Available objects for this game are:\n");
+ debugPrintf("1 - Scene %d - R2_OPTO_DISK\n", BF_INVENTORY.getObjectScene(1));
+ debugPrintf("2 - Scene %d - R2_READER\n", BF_INVENTORY.getObjectScene(2));
+ debugPrintf("3 - Scene %d - R2_NEGATOR_GUN\n", BF_INVENTORY.getObjectScene(3));
+ debugPrintf("4 - Scene %d - R2_STEPPING_DISKS\n", BF_INVENTORY.getObjectScene(4));
+ debugPrintf("5 - Scene %d - R2_ATTRACTOR_UNIT\n", BF_INVENTORY.getObjectScene(5));
+ debugPrintf("6 - Scene %d - R2_SENSOR_PROBE\n", BF_INVENTORY.getObjectScene(6));
+ debugPrintf("7 - Scene %d - R2_SONIC_STUNNER\n", BF_INVENTORY.getObjectScene(7));
+ debugPrintf("8 - Scene %d - R2_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(8));
+ debugPrintf("9 - Scene %d - R2_COM_SCANNER\n", BF_INVENTORY.getObjectScene(9));
+ debugPrintf("10 - Scene %d - R2_SPENT_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(10));
+ debugPrintf("11 - Scene %d - R2_CHARGED_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(11));
+ debugPrintf("12 - Scene %d - R2_AEROSOL\n", BF_INVENTORY.getObjectScene(12));
+ debugPrintf("13 - Scene %d - R2_REMOTE_CONTROL\n", BF_INVENTORY.getObjectScene(13));
+ debugPrintf("14 - Scene %d - R2_OPTICAL_FIBER\n", BF_INVENTORY.getObjectScene(14));
+ debugPrintf("15 - Scene %d - R2_CLAMP\n", BF_INVENTORY.getObjectScene(15));
+ debugPrintf("16 - Scene %d - R2_ATTRACTOR_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(16));
+ debugPrintf("17 - Scene %d - R2_FUEL_CELL\n", BF_INVENTORY.getObjectScene(17));
+ debugPrintf("18 - Scene %d - R2_GYROSCOPE\n", BF_INVENTORY.getObjectScene(18));
+ debugPrintf("19 - Scene %d - R2_AIRBAG\n", BF_INVENTORY.getObjectScene(19));
+ debugPrintf("20 - Scene %d - R2_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(20));
+ debugPrintf("21 - Scene %d - R2_RESERVE_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(21));
+ debugPrintf("22 - Scene %d - R2_GUIDANCE_MODULE\n", BF_INVENTORY.getObjectScene(22));
+ debugPrintf("23 - Scene %d - R2_THRUSTER_VALVE\n", BF_INVENTORY.getObjectScene(23));
+ debugPrintf("24 - Scene %d - R2_BALLOON_BACKPACK\n", BF_INVENTORY.getObjectScene(24));
+ debugPrintf("25 - Scene %d - R2_RADAR_MECHANISM\n", BF_INVENTORY.getObjectScene(25));
+ debugPrintf("26 - Scene %d - R2_JOYSTICK\n", BF_INVENTORY.getObjectScene(26));
+ debugPrintf("27 - Scene %d - R2_IGNITOR\n", BF_INVENTORY.getObjectScene(27));
+ debugPrintf("28 - Scene %d - R2_DIAGNOSTICS_DISPLAY\n", BF_INVENTORY.getObjectScene(28));
+ debugPrintf("29 - Scene %d - R2_GLASS_DOME\n", BF_INVENTORY.getObjectScene(29));
+ debugPrintf("30 - Scene %d - R2_WICK_LAMP\n", BF_INVENTORY.getObjectScene(30));
+ debugPrintf("31 - Scene %d - R2_SCRITH_KEY\n", BF_INVENTORY.getObjectScene(31));
+ debugPrintf("32 - Scene %d - R2_TANNER_MASK\n", BF_INVENTORY.getObjectScene(32));
+ debugPrintf("33 - Scene %d - R2_PURE_GRAIN_ALCOHOL\n", BF_INVENTORY.getObjectScene(33));
+ debugPrintf("34 - Scene %d - R2_SAPPHIRE_BLUE\n", BF_INVENTORY.getObjectScene(34));
+ debugPrintf("35 - Scene %d - R2_ANCIENT_SCROLLS\n", BF_INVENTORY.getObjectScene(35));
+ debugPrintf("36 - Scene %d - R2_FLUTE\n", BF_INVENTORY.getObjectScene(36));
+ debugPrintf("37 - Scene %d - R2_GUNPOWDER\n", BF_INVENTORY.getObjectScene(37));
+ debugPrintf("38 - Scene %d - R2_NONAME\n", BF_INVENTORY.getObjectScene(38));
+ debugPrintf("39 - Scene %d - R2_COM_SCANNER_2\n", BF_INVENTORY.getObjectScene(39));
+ debugPrintf("40 - Scene %d - R2_SUPERCONDUCTOR_WIRE\n", BF_INVENTORY.getObjectScene(40));
+ debugPrintf("41 - Scene %d - R2_PILLOW\n", BF_INVENTORY.getObjectScene(41));
+ debugPrintf("42 - Scene %d - R2_FOOD_TRAY\n", BF_INVENTORY.getObjectScene(42));
+ debugPrintf("43 - Scene %d - R2_LASER_HACKSAW\n", BF_INVENTORY.getObjectScene(43));
+ debugPrintf("44 - Scene %d - R2_PHOTON_STUNNER\n", BF_INVENTORY.getObjectScene(44));
+ debugPrintf("45 - Scene %d - R2_BATTERY\n", BF_INVENTORY.getObjectScene(45));
+ debugPrintf("46 - Scene %d - R2_SOAKED_FACEMASK\n", BF_INVENTORY.getObjectScene(46));
+ debugPrintf("47 - Scene %d - R2_LIGHT_BULB\n", BF_INVENTORY.getObjectScene(47));
+ debugPrintf("48 - Scene %d - R2_ALCOHOL_LAMP\n", BF_INVENTORY.getObjectScene(48));
+ debugPrintf("49 - Scene %d - R2_ALCOHOL_LAMP_2\n", BF_INVENTORY.getObjectScene(49));
+ debugPrintf("50 - Scene %d - R2_ALCOHOL_LAMP_3\n", BF_INVENTORY.getObjectScene(50));
+ debugPrintf("51 - Scene %d - R2_BROKEN_DISPLAY\n", BF_INVENTORY.getObjectScene(51));
+ debugPrintf("52 - Scene %d - R2_TOOLBOX\n", BF_INVENTORY.getObjectScene(52));
return true;
}
@@ -699,8 +699,8 @@ bool Ringworld2Debugger::Cmd_ListObjects(int argc, const char **argv) {
bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) {
// Check for a flag to clear
if ((argc < 2) || (argc > 3)){
- DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]);
- DebugPrintf("If no scene is specified, the object will be added to inventory\n");
+ debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]);
+ debugPrintf("If no scene is specified, the object will be added to inventory\n");
return true;
}
@@ -712,7 +712,7 @@ bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) {
if ((objNum > 0) && (objNum < 53))
R2_INVENTORY.setObjectScene(objNum, sceneNum);
else
- DebugPrintf("Invalid object Id %s\n", argv[1]);
+ debugPrintf("Invalid object Id %s\n", argv[1]);
return true;
}
@@ -720,9 +720,9 @@ bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) {
/**
* Activate internal debugger, when available
*/
-bool Ringworld2Debugger::Cmd_SetDebug(int argc, const char **argv) {
+bool Ringworld2Debugger::Cmd_SetOutpostAlphaDebug(int argc, const char **argv) {
if (argc != 1) {
- DebugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Usage: %s\n", argv[0]);
return true;
}
diff --git a/engines/tsage/debugger.h b/engines/tsage/debugger.h
index 610f45de64..b0f4c665dd 100644
--- a/engines/tsage/debugger.h
+++ b/engines/tsage/debugger.h
@@ -45,7 +45,7 @@ protected:
bool Cmd_Sound(int argc, const char **argv);
virtual bool Cmd_ListObjects(int argc, const char **argv) = 0;
virtual bool Cmd_MoveObject(int argc, const char **argv) = 0;
- virtual bool Cmd_SetDebug(int argc, const char **argv);
+ virtual bool Cmd_SetOutpostAlphaDebug(int argc, const char **argv);
};
class DemoDebugger : public Debugger {
@@ -70,7 +70,7 @@ class Ringworld2Debugger : public Debugger {
protected:
virtual bool Cmd_ListObjects(int argc, const char **argv);
virtual bool Cmd_MoveObject(int argc, const char **argv);
- virtual bool Cmd_SetDebug(int argc, const char **argv);
+ virtual bool Cmd_SetOutpostAlphaDebug(int argc, const char **argv);
};
} // End of namespace TsAGE
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index fa5d1a3b6a..ce24c76290 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -1229,6 +1229,8 @@ GfxButton *GfxDialog::execute(GfxButton *defaultButton) {
selectedButton = defaultButton;
breakFlag = true;
break;
+ } else if (event.eventType == EVENT_KEYPRESS && handleKeypress(event, selectedButton)) {
+ breakFlag = true;
}
}
}
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
index cdb4826528..d65d0bcf8b 100644
--- a/engines/tsage/graphics.h
+++ b/engines/tsage/graphics.h
@@ -343,6 +343,8 @@ public:
virtual void draw();
static void setPalette();
+
+ virtual bool handleKeypress(Event &evt, GfxButton *&btn) { return false; }
};
GfxSurface *surfaceGetArea(GfxSurface &src, const Rect &bounds);
diff --git a/engines/tsage/ringworld/ringworld_dialogs.cpp b/engines/tsage/ringworld/ringworld_dialogs.cpp
index 226a943f08..1dd3bc158b 100644
--- a/engines/tsage/ringworld/ringworld_dialogs.cpp
+++ b/engines/tsage/ringworld/ringworld_dialogs.cpp
@@ -20,8 +20,6 @@
*
*/
-#include "common/translation.h"
-
#include "gui/dialog.h"
#include "gui/widget.h"
diff --git a/engines/tsage/ringworld/ringworld_scenes10.cpp b/engines/tsage/ringworld/ringworld_scenes10.cpp
index c4874c0f59..99c953217c 100644
--- a/engines/tsage/ringworld/ringworld_scenes10.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes10.cpp
@@ -1004,7 +1004,7 @@ void Scene9450::postInit(SceneObjectList *OwnerList) {
_hotspot8.setDetails(110, 0, 199, 117, 9450, 7, 8);
_hotspot9.setDetails(101, 104, 130, 174, 9450, 9, 10);
_hotspot10.setDetails(110, 246, 149, 319, 9450, 11, 12);
- _hotspot11.setDetails(16, 34, 74, 62, 6450, 13, 14);
+ _hotspot11.setDetails(16, 34, 74, 62, 9450, 13, 14);
_hotspot12.setDetails(19, 108, 72, 134, 9450, 15, 16);
_hotspot13.setDetails(18, 215, 71, 237, 9450, 17, 18);
_hotspot14.setDetails(15, 288, 76, 314, 9450, 19, 20);
diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
index dfbb281cfb..99f88a1687 100644
--- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp
+++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
@@ -365,7 +365,7 @@ void HelpDialog::show() {
HelpDialog *dlg = new HelpDialog();
dlg->draw();
- // Show the character selection dialog
+ // Show the help dialog
GfxButton *btn = dlg->execute(&dlg->_btnResume);
// If a function button was selected, take care of it
@@ -458,6 +458,36 @@ HelpDialog::HelpDialog() {
setCenter(160, 100);
}
+bool HelpDialog::handleKeypress(Event &event, GfxButton *&btn) {
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_F2:
+ btn = &_btnList[0];
+ break;
+ case Common::KEYCODE_F3:
+ btn = &_btnList[1];
+ break;
+ case Common::KEYCODE_F4:
+ btn = &_btnList[2];
+ break;
+ case Common::KEYCODE_F5:
+ btn = &_btnList[3];
+ break;
+ case Common::KEYCODE_F7:
+ btn = &_btnList[4];
+ break;
+ case Common::KEYCODE_F8:
+ btn = &_btnList[5];
+ break;
+ case Common::KEYCODE_F10:
+ btn = &_btnList[6];
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.h b/engines/tsage/ringworld2/ringworld2_dialogs.h
index 8ef35c9024..3d1e1ad48c 100644
--- a/engines/tsage/ringworld2/ringworld2_dialogs.h
+++ b/engines/tsage/ringworld2/ringworld2_dialogs.h
@@ -83,6 +83,8 @@ public:
virtual ~HelpDialog() {}
static void show();
+
+ virtual bool handleKeypress(Event &event, GfxButton *&btn);
};
} // End of namespace Ringworld2
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index c5c6de980c..99913d87b0 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -355,6 +355,11 @@ SceneExt::SceneExt(): Scene() {
// to make inter-scene debugging easier, I'm explicitly resetting the _animationCtr
// on scene start, since scene objects aren't drawn while it's non-zero
R2_GLOBALS._animationCtr = 0;
+
+ // WORKAROUND: We had a case where at some point the number of modal dialogs
+ // open became incorrect. So reset it on scene changes to fix the problem if
+ // it ever happens
+ R2_GLOBALS._insetUp = 0;
}
void SceneExt::synchronize(Serializer &s) {
@@ -1215,12 +1220,6 @@ void Ringworld2Game::processEvent(Event &event) {
R2_GLOBALS._events.setCursorFromFlag();
break;
- case Common::KEYCODE_F5:
- // F5 - Save
- saveGame();
- R2_GLOBALS._events.setCursorFromFlag();
- break;
-
case Common::KEYCODE_F7:
// F7 - Restore
restoreGame();
diff --git a/engines/tsage/ringworld2/ringworld2_logic.h b/engines/tsage/ringworld2/ringworld2_logic.h
index 31d801fa55..d95f279e27 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.h
+++ b/engines/tsage/ringworld2/ringworld2_logic.h
@@ -320,7 +320,7 @@ public:
int pixelToCellXY(Common::Point &pt);
virtual Common::String getClassName() { return "MazeUI"; }
- void synchronize(Serializer &s);
+ virtual void synchronize(Serializer &s);
virtual void reposition();
virtual void draw();
};
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
index 110c3ff510..591ed30cfd 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
@@ -1919,7 +1919,7 @@ void Scene1200::process(Event &event) {
return;
}
} else if (event.eventType == EVENT_KEYPRESS) {
- if (_field414 == 0) {
+ if (_field414) {
event.handled = false;
return;
}
@@ -2210,7 +2210,11 @@ Scene1337::Card::Card() {
}
void Scene1337::Card::synchronize(Serializer &s) {
- warning("STUBBED: Card::synchronize()");
+ _card.synchronize(s);
+
+ s.syncAsSint16LE(_cardId);
+ s.syncAsSint16LE(_stationPos.x);
+ s.syncAsSint16LE(_stationPos.y);
}
bool Scene1337::Card::isIn(Common::Point pt) {
@@ -2232,7 +2236,26 @@ Scene1337::GameBoardSide::GameBoardSide() {
}
void Scene1337::GameBoardSide::synchronize(Serializer &s) {
- warning("STUBBED: GameBoardSide::synchronize()");
+ SceneHotspot::synchronize(s);
+
+ for (int i = 0; i < 4; i++)
+ _handCard[i].synchronize(s);
+
+ for (int i = 0; i < 8; i++)
+ _outpostStation[i].synchronize(s);
+
+ _delayCard.synchronize(s);
+ _emptyStationPos.synchronize(s);
+
+ s.syncAsSint16LE(_card1Pos.x);
+ s.syncAsSint16LE(_card1Pos.y);
+ s.syncAsSint16LE(_card2Pos.x);
+ s.syncAsSint16LE(_card2Pos.y);
+ s.syncAsSint16LE(_card3Pos.x);
+ s.syncAsSint16LE(_card3Pos.y);
+ s.syncAsSint16LE(_card4Pos.x);
+ s.syncAsSint16LE(_card4Pos.y);
+ s.syncAsSint16LE(_frameNum);
}
Scene1337::Scene1337() {
@@ -2245,8 +2268,8 @@ Scene1337::Scene1337() {
_shuffleEndedFl = false;
_currentPlayerNumb = 0;
- _actionIdx1 = 0;
- _actionIdx2 = 0;
+ _actionPlayerIdx = 0;
+ _actionVictimIdx = 0;
_showPlayerTurn = false;
_displayHelpFl = false;
_winnerId = -1;
@@ -2264,7 +2287,50 @@ Scene1337::Scene1337() {
}
void Scene1337::synchronize(Serializer &s) {
- warning("STUBBED: Scene1337::synchronize()");
+ _actionCard1->synchronize(s);
+ _actionCard2->synchronize(s);
+ _actionCard3->synchronize(s);
+ _animatedCard.synchronize(s);
+ _shuffleAnimation.synchronize(s);
+ _discardedPlatformCard.synchronize(s);
+ _selectedCard.synchronize(s);
+ _discardPile.synchronize(s);
+ _stockCard.synchronize(s);
+ _aSound1.synchronize(s);
+ _aSound2.synchronize(s);
+ _helpIcon.synchronize(s);
+ _stockPile.synchronize(s);
+ _actionItem.synchronize(s);
+ _currentPlayerArrow.synchronize(s);
+
+ for (int i = 0; i < 4; i++)
+ _gameBoardSide[i].synchronize(s);
+
+ for (int i = 0; i < 8; i++) {
+ _upperDisplayCard[i].synchronize(s);
+ _lowerDisplayCard[i].synchronize(s);
+ }
+
+ // TODO s.syncPointer(_delayedFunction);
+ s.syncAsByte(_autoplay);
+ s.syncAsByte(_shuffleEndedFl);
+ s.syncAsByte(_showPlayerTurn);
+ s.syncAsByte(_displayHelpFl);
+ s.syncAsByte(_instructionsDisplayedFl);
+ s.syncAsSint16LE(_currentDiscardIndex);
+ s.syncAsSint16LE(_cardsAvailableNumb);
+ s.syncAsSint16LE(_currentPlayerNumb);
+ s.syncAsSint16LE(_actionPlayerIdx);
+ s.syncAsSint16LE(_actionVictimIdx);
+ s.syncAsSint16LE(_winnerId);
+ s.syncAsSint16LE(_instructionsWaitCount);
+ s.syncAsSint16LE(_cursorCurRes);
+ s.syncAsSint16LE(_cursorCurStrip);
+ s.syncAsSint16LE(_cursorCurFrame);
+
+ for (int i = 0; i < 100; i++)
+ s.syncAsSint16LE(_availableCardsPile[i]);
+
}
void Scene1337::Action1337::waitFrames(int32 frameCount) {
@@ -2458,7 +2524,7 @@ void Scene1337::Action1::signal() {
scene->_gameBoardSide[0]._outpostStation[1]._card.remove();
scene->_stockPile.setup(1332, 5, 1);
- scene->_stockPile.setPosition(Common::Point(165, 95));
+ scene->_stockPile.setPosition(Common::Point(162, 95));
scene->_stockPile.setPriority(110);
scene->_stockPile._effect = EFFECT_SHADED;
scene->_stockPile.show();
@@ -3412,7 +3478,7 @@ void Scene1337::Action4::signal() {
scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]);
scene->_animatedCard._card.hide();
- if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId == 0)
+ if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._cardId == 0)
&& (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
if (scene->_cardsAvailableNumb < 0)
scene->shuffleCards();
@@ -3666,6 +3732,7 @@ void Scene1337::Action7::signal() {
}
}
+// Remove a delay card
void Scene1337::Action8::signal() {
Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
@@ -3775,7 +3842,7 @@ void Scene1337::Action10::signal() {
bool found = false;
int indexFound = -1;
- switch (scene->_actionIdx1) {
+ switch (scene->_actionPlayerIdx) {
case 0:
for (indexFound = 0; indexFound < 3; indexFound++) {
if (scene->_gameBoardSide[0]._handCard[indexFound]._cardId == 29) {
@@ -3815,13 +3882,13 @@ void Scene1337::Action10::signal() {
bool found2 = false;
if (found) {
- switch (scene->_actionIdx1) {
+ switch (scene->_actionPlayerIdx) {
case 0:
- scene->subC51A0(&scene->_gameBoardSide[0]._handCard[indexFound], scene->_actionCard3);
+ scene->playInterceptorCard(&scene->_gameBoardSide[0]._handCard[indexFound], scene->_actionCard3);
found2 = true;
break;
case 1:
- scene->subC51A0(&scene->_gameBoardSide[1]._handCard[indexFound], scene->_actionCard3);
+ scene->playInterceptorCard(&scene->_gameBoardSide[1]._handCard[indexFound], scene->_actionCard3);
found2 = true;
break;
case 2:
@@ -3829,12 +3896,12 @@ void Scene1337::Action10::signal() {
if (MessageDialog::show(USE_INTERCEPTOR, NO_MSG, YES_MSG) == 0)
scene->subC4CEC();
else {
- scene->subC51A0(&scene->_gameBoardSide[2]._handCard[indexFound], scene->_actionCard3);
+ scene->playInterceptorCard(&scene->_gameBoardSide[2]._handCard[indexFound], scene->_actionCard3);
found2 = true;
}
break;
case 3:
- scene->subC51A0(&scene->_gameBoardSide[3]._handCard[indexFound], scene->_actionCard3);
+ scene->playInterceptorCard(&scene->_gameBoardSide[3]._handCard[indexFound], scene->_actionCard3);
found2 = true;
break;
default:
@@ -3845,7 +3912,7 @@ void Scene1337::Action10::signal() {
if (!found2)
break;
- if (scene->_actionIdx1 == 2) {
+ if (scene->_actionPlayerIdx == 2) {
int j = 0;
for (int i = 0; i <= 7; i++) {
if (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0)
@@ -3909,7 +3976,7 @@ void Scene1337::Action10::signal() {
}
}
-// Use trick (card #25 - thieft ?) and pick a card from the opponent
+// Use Thief card (#25) and pick a card from the opponent
void Scene1337::Action11::signal() {
Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
@@ -3922,7 +3989,7 @@ void Scene1337::Action11::signal() {
scene->_actionCard2->_card.fixPriority(170);
scene->_actionCard2->_cardId = 25;
- if (scene->_actionIdx1 == 2) {
+ if (scene->_actionPlayerIdx == 2) {
scene->_animatedCard._card.setPosition(scene->_actionCard2->_stationPos, 0);
scene->setCursorData(5, 1, 4);
} else {
@@ -3946,7 +4013,7 @@ void Scene1337::Action11::signal() {
int i = -1;
- switch (scene->_actionIdx2) {
+ switch (scene->_actionVictimIdx) {
case 0:
for (i = 0; i <= 3; i++) {
if (scene->_gameBoardSide[0]._handCard[i]._cardId == 27) {
@@ -3955,12 +4022,12 @@ void Scene1337::Action11::signal() {
}
}
- if ((found) && (scene->getFreeHandCard(scene->_actionIdx1) != -1)) {
+ if ((found) && (scene->getFreeHandCard(scene->_actionPlayerIdx) != -1)) {
scene->_actionCard1 = &scene->_gameBoardSide[0]._handCard[i];
scene->_actionCard2 = &scene->_gameBoardSide[0]._emptyStationPos;
- if (scene->_actionIdx1 != 0) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx1);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx1]._handCard[tmpVal];
+ if (scene->_actionPlayerIdx != 0) {
+ int tmpVal = scene->getFreeHandCard(scene->_actionPlayerIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionPlayerIdx]._handCard[tmpVal];
}
scene->_actionItem.setAction(&scene->_action12);
noAction = false;
@@ -3974,12 +4041,12 @@ void Scene1337::Action11::signal() {
}
}
- if ((found) && (scene->getFreeHandCard(scene->_actionIdx1) != -1)) {
+ if ((found) && (scene->getFreeHandCard(scene->_actionPlayerIdx) != -1)) {
scene->_actionCard1 = &scene->_gameBoardSide[1]._handCard[i];
scene->_actionCard2 = &scene->_gameBoardSide[1]._emptyStationPos;
- if (scene->_actionIdx1 != 1) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx1);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx1]._handCard[tmpVal];
+ if (scene->_actionPlayerIdx != 1) {
+ int tmpVal = scene->getFreeHandCard(scene->_actionPlayerIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionPlayerIdx]._handCard[tmpVal];
}
scene->_actionItem.setAction(&scene->_action12);
noAction = false;
@@ -3993,7 +4060,7 @@ void Scene1337::Action11::signal() {
}
}
- if ((found) && (scene->getFreeHandCard(scene->_actionIdx1) != -1)) {
+ if ((found) && (scene->getFreeHandCard(scene->_actionPlayerIdx) != -1)) {
scene->subC4CD2();
if (MessageDialog::show(USE_DOUBLE_AGENT, NO_MSG, YES_MSG) == 0)
scene->subC4CEC();
@@ -4001,9 +4068,9 @@ void Scene1337::Action11::signal() {
scene->subC4CEC();
scene->_actionCard1 = &scene->_gameBoardSide[2]._handCard[i];
scene->_actionCard2 = &scene->_gameBoardSide[2]._emptyStationPos;
- if (scene->_actionIdx1 != 2) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx1);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx1]._handCard[tmpVal];
+ if (scene->_actionPlayerIdx != 2) {
+ int tmpVal = scene->getFreeHandCard(scene->_actionPlayerIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionPlayerIdx]._handCard[tmpVal];
}
scene->_actionItem.setAction(&scene->_action12);
noAction = false;
@@ -4018,12 +4085,12 @@ void Scene1337::Action11::signal() {
}
}
- if ((found) && (scene->getFreeHandCard(scene->_actionIdx1) != -1)) {
+ if ((found) && (scene->getFreeHandCard(scene->_actionPlayerIdx) != -1)) {
scene->_actionCard1 = &scene->_gameBoardSide[3]._handCard[i];
scene->_actionCard2 = &scene->_gameBoardSide[3]._emptyStationPos;
- if (scene->_actionIdx1 != 3) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx1);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx1]._handCard[tmpVal];
+ if (scene->_actionPlayerIdx != 3) {
+ int tmpVal = scene->getFreeHandCard(scene->_actionPlayerIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionPlayerIdx]._handCard[tmpVal];
}
scene->_actionItem.setAction(&scene->_action12);
noAction = false;
@@ -4036,11 +4103,11 @@ void Scene1337::Action11::signal() {
if (!noAction)
return;
- if (scene->_actionIdx1 == 2) {
+ if (scene->_actionPlayerIdx == 2) {
int count = 0;
- if (scene->_actionIdx2 != 2) {
+ if (scene->_actionVictimIdx != 2) {
for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[scene->_actionIdx2]._handCard[i]._cardId == 0)
+ if (scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[i]._cardId != 0)
++count;
}
}
@@ -4050,7 +4117,7 @@ void Scene1337::Action11::signal() {
found = false;
while (!found) {
- switch (scene->_actionIdx2) {
+ switch (scene->_actionVictimIdx) {
case 0:
scene->actionDisplay(1330, 131, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -4075,10 +4142,10 @@ void Scene1337::Action11::signal() {
found = false;
- if (scene->_actionIdx2 != 2) {
+ if (scene->_actionVictimIdx != 2) {
for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[scene->_actionIdx2]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[scene->_actionIdx2]._handCard[i]._cardId != 0)) {
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx2]._handCard[i];
+ if (scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[i]._cardId != 0)) {
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[i];
found = true;
break;
}
@@ -4087,9 +4154,9 @@ void Scene1337::Action11::signal() {
} // while
scene->_displayHelpFl = true;
scene->subC4CEC();
- } else if (scene->_actionIdx2 != 2) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx2);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx2]._handCard[tmpVal];
+ } else if (scene->_actionVictimIdx != 2) {
+ int tmpVal = scene->getFreeHandCard(scene->_actionVictimIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[tmpVal];
}
}
@@ -4113,7 +4180,7 @@ void Scene1337::Action11::signal() {
break;
case 2:
scene->_animatedCard._card.hide();
- switch (scene->_actionIdx1) {
+ switch (scene->_actionPlayerIdx) {
case 0:
scene->_actionCard1->_card.setFrame2(2);
scene->_actionCard1->_card.show();
@@ -4165,10 +4232,10 @@ void Scene1337::Action12::signal() {
scene->_animatedCard._card.hide();
scene->setAnimationInfo(scene->_actionCard2);
scene->_aSound1.play(58);
- if (scene->_actionIdx2 == 2) {
+ if (scene->_actionVictimIdx == 2) {
int count = 0;
int i = -1;
- switch (scene->_actionIdx1) {
+ switch (scene->_actionPlayerIdx) {
case 0:
for (i = 0; i <= 3; i++) {
if (scene->_gameBoardSide[0]._handCard[i]._cardId != 0)
@@ -4198,7 +4265,7 @@ void Scene1337::Action12::signal() {
bool found = false;
while (!found) {
- switch (scene->_actionIdx1) {
+ switch (scene->_actionPlayerIdx) {
case 0:
scene->actionDisplay(1330, 131, 159, 10, 1, 200, 0, 7, 0, 154, 154);
break;
@@ -4221,7 +4288,7 @@ void Scene1337::Action12::signal() {
scene->_selectedCard._stationPos = event.mousePos;
- if (scene->_actionIdx1 == 0) {
+ if (scene->_actionPlayerIdx == 0) {
for (i = 0; i <= 3; i++) {
if (scene->_gameBoardSide[0]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[0]._handCard[i]._cardId != 0)) {
found = true;
@@ -4231,7 +4298,7 @@ void Scene1337::Action12::signal() {
}
}
- if (scene->_actionIdx1 == 3) {
+ if (scene->_actionPlayerIdx == 3) {
for (i = 0; i <= 3; i++) {
if (scene->_gameBoardSide[3]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[3]._handCard[i]._cardId != 0)) {
found = true;
@@ -4241,7 +4308,7 @@ void Scene1337::Action12::signal() {
}
}
- if (scene->_actionIdx1 == 1) {
+ if (scene->_actionPlayerIdx == 1) {
for (i = 0; i <= 3; i++) {
if (scene->_gameBoardSide[1]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[1]._handCard[i]._cardId != 0)) {
found = true;
@@ -4252,8 +4319,8 @@ void Scene1337::Action12::signal() {
}
}
scene->subC4CEC();
- } else if (scene->_actionIdx1 != 1) {
- switch (scene->_actionIdx1) {
+ } else if (scene->_actionPlayerIdx != 1) {
+ switch (scene->_actionPlayerIdx) {
case 0:
scene->_actionCard3 = &scene->_gameBoardSide[0]._handCard[scene->getFreeHandCard(0)];
break;
@@ -4288,7 +4355,7 @@ void Scene1337::Action12::signal() {
break;
case 3:
scene->_animatedCard._card.hide();
- switch (scene->_actionIdx2) {
+ switch (scene->_actionVictimIdx) {
case 0:
scene->_actionCard1->_card.setFrame2(2);
scene->_actionCard1->_card.show();
@@ -4313,6 +4380,7 @@ void Scene1337::Action12::signal() {
}
}
+// Handle the animations of the interceptor card
void Scene1337::Action13::signal() {
Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
@@ -4877,8 +4945,8 @@ void Scene1337::handlePlayer01Discard(int playerId) {
}
void Scene1337::playThieftCard(int playerId, Card *card, int victimId) {
- _actionIdx1 = playerId;
- _actionIdx2 = victimId;
+ _actionPlayerIdx = playerId;
+ _actionVictimIdx = victimId;
int randIndx;
@@ -4931,6 +4999,9 @@ int Scene1337::getPreventionCardId(int cardId) {
}
bool Scene1337::isAttackPossible(int victimId, int cardId) {
+ if (victimId < 0 || victimId >= ARRAYSIZE(_gameBoardSide))
+ error("Scene1337::isAttackPossible() victimId:%d out of range 0 to %d", victimId, ARRAYSIZE(_gameBoardSide)-1);
+
for (int i = 0; i <= 7; i++) {
if (_gameBoardSide[victimId]._outpostStation[i]._cardId != 0) {
if (getPreventionCardId(cardId) == _gameBoardSide[victimId]._outpostStation[i]._cardId)
@@ -5024,7 +5095,12 @@ void Scene1337::playAntiDelayCard(Card *card, Card *dest) {
_actionItem.setAction(&_action8);
- handleNextTurn();
+ // WORKAROUND: Restore the default cursor and for a call to signal.
+ // This works around the cursor caching we got rid of, and avoid
+ // the game ends in an eternal loop when a player reacts to another player
+ // attack.
+ setCursorData(5, 1, 4);
+ signal();
}
@@ -5041,7 +5117,7 @@ void Scene1337::playCounterTrickCard(Card *card, int playerId) {
_actionCard1 = card;
_actionCard2 = getStationCard(playerId);
_actionCard3 = &_gameBoardSide[playerId]._emptyStationPos;
- _actionIdx1 = playerId;
+ _actionPlayerIdx = playerId;
_actionItem.setAction(&_action10);
handleNextTurn();
}
@@ -5066,7 +5142,8 @@ void Scene1337::subC4CEC() {
}
}
-void Scene1337::subC51A0(Card *subObj1, Card *subObj2) {
+// Play Interceptor card
+void Scene1337::playInterceptorCard(Card *subObj1, Card *subObj2) {
_actionCard1 = subObj1;
_actionCard2 = subObj2;
@@ -5935,10 +6012,10 @@ void Scene1337::handlePlayer1() {
}
int card13Id = findCard13InHand(1);
- int tmpVal2 = getPlayerWithOutpost(1);
+ int victimId = getPlayerWithOutpost(1);
- if ((card13Id != -1) && (tmpVal2 != -1)) {
- playCounterTrickCard(&_gameBoardSide[1]._handCard[card13Id], tmpVal2);
+ if ((card13Id != -1) && (victimId != -1)) {
+ playCounterTrickCard(&_gameBoardSide[1]._handCard[card13Id], victimId);
return;
}
@@ -5951,7 +6028,7 @@ void Scene1337::handlePlayer1() {
if ( (_gameBoardSide[rndVal]._handCard[0]._cardId != 0)
|| (_gameBoardSide[rndVal]._handCard[1]._cardId != 0)
|| (_gameBoardSide[rndVal]._handCard[2]._cardId != 0)
- || (_gameBoardSide[rndVal]._handCard[3]._cardId == 0)) {
+ || (_gameBoardSide[rndVal]._handCard[3]._cardId != 0)) {
playerIdFound = rndVal;
break;
}
@@ -5969,22 +6046,20 @@ void Scene1337::handlePlayer1() {
}
}
- int count = -1;
- int i;
- for (i = 0; i <= 3; i++) {
+ for (int i = 0; i <= 3; i++) {
int tmpVal = isDelayCard(_gameBoardSide[1]._handCard[i]._cardId);
if (tmpVal != -1) {
+ victimId = -1;
int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
for (int j = 0; j <= 3; j++) {
- //CHECKME: tmpVal or rndVal?
- if (tmpVal != 1) {
- if ((_gameBoardSide[tmpVal]._delayCard._cardId == 0) && isAttackPossible(tmpVal, _gameBoardSide[1]._handCard[i]._cardId))
- count = tmpVal;
+ if (rndVal != 1) {
+ if ((_gameBoardSide[rndVal]._delayCard._cardId == 0) && isAttackPossible(rndVal, _gameBoardSide[1]._handCard[i]._cardId))
+ victimId = rndVal;
}
- if (count != -1) {
- playDelayCard(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[count]._delayCard);
+ if (victimId != -1) {
+ playDelayCard(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[victimId]._delayCard);
return;
} else {
rndVal--;
@@ -5995,18 +6070,17 @@ void Scene1337::handlePlayer1() {
}
}
- int j;
- for (j = 0; j <= 3; j++) {
+ for (int j = 0; j <= 3; j++) {
if (getStationCardId(_gameBoardSide[1]._handCard[j]._cardId) != -1) {
- count = -1;
+ victimId = -1;
int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
for (int l = 0; l <= 3; l++) {
if (rndVal != 1) {
if ((_gameBoardSide[rndVal]._delayCard._cardId == 0) && (_gameBoardSide[1]._handCard[j]._cardId == 1))
- count = rndVal;
+ victimId = rndVal;
}
- if (count != -1) {
- playDelayCard(&_gameBoardSide[1]._handCard[j], &_gameBoardSide[count]._delayCard);
+ if (victimId != -1) {
+ playDelayCard(&_gameBoardSide[1]._handCard[j], &_gameBoardSide[victimId]._delayCard);
return;
} else {
rndVal--;
@@ -6052,7 +6126,6 @@ void Scene1337::handlePlayer3() {
}
int randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
-
if (_gameBoardSide[3]._handCard[randIndx]._cardId == 1) {
for (int i = 0; i <= 7; i++) {
if ((_gameBoardSide[3]._outpostStation[i]._cardId == 0) && !isStopConstructionCard(_gameBoardSide[3]._delayCard._cardId)) {
@@ -6206,7 +6279,6 @@ void Scene1337::handlePlayer2() {
//warning("_selectedCard._field0 = handcard->_field0;");
_selectedCard._card._updateStartFrame = handcard->_card._updateStartFrame;
_selectedCard._card._walkStartFrame = handcard->_card._walkStartFrame;
- // _field2E is named _field3C in R2R
_selectedCard._card._oldPosition = handcard->_card._oldPosition;
_selectedCard._card._percent = handcard->_card._percent;
_selectedCard._card._priority = handcard->_card._priority;
@@ -6222,7 +6294,6 @@ void Scene1337::handlePlayer2() {
_selectedCard._card._animateMode = handcard->_card._animateMode;
_selectedCard._card._frame = handcard->_card._frame;
_selectedCard._card._endFrame = handcard->_card._endFrame;
- // _field68 is named _field76 in R2R
_selectedCard._card._loopCount = handcard->_card._loopCount;
_selectedCard._card._frameChange = handcard->_card._frameChange;
_selectedCard._card._numFrames = handcard->_card._numFrames;
@@ -6639,7 +6710,7 @@ void Scene1337::setCursorData(int resNum, int rlbNum, int frameNum) {
// FIXME: Use another cursor when possible
R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
} else {
- // TODO: The original was using some ressource caching, which was useless and complex
+ // TODO: The original was using some resource caching, which was useless and complex
// and which has been removed. This cursor behavior clearly made intensive use of this caching...
// We now have to find a way to cache these cursor pointers and avoid loading them multiple times per seconds
uint size;
@@ -6658,7 +6729,9 @@ void Scene1337::setCursorData(int resNum, int rlbNum, int frameNum) {
void Scene1337::subD18F5() {
if (R2_GLOBALS._v57709 == 0)
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ // The original restores a copy of the default cursor (the hand), which isn't possible with our implementation
+ // We reload that cursor instead.
+ setCursorData(5, 1, 4);
++R2_GLOBALS._v57709;
}
@@ -6666,7 +6739,7 @@ void Scene1337::subD18F5() {
void Scene1337::subD1917() {
if (R2_GLOBALS._v57709 != 0) {
R2_GLOBALS._v57709--;
- if (R2_GLOBALS._v57709 != 0) {
+ if (R2_GLOBALS._v57709 == 0) {
// The original was using an intermediate function to call setCursorData.
// It has been removed to improve readability
setCursorData(5, _cursorCurStrip, _cursorCurFrame);
@@ -6682,7 +6755,7 @@ void Scene1337::subD1940(bool flag) {
}
void Scene1337::subD1975(int arg1, int arg2) {
- warning("STUBBED lvl2 Scene1337::subD1975()");
+ // No implementation required in ScummVM: Mouse handling with tons of caching
}
void Scene1337::OptionsDialog::show() {
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.h b/engines/tsage/ringworld2/ringworld2_scenes1.h
index 91c4b88391..6c24a4e989 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.h
@@ -312,8 +312,8 @@ public:
int _availableCardsPile[100];
int _cardsAvailableNumb;
int _currentPlayerNumb;
- int _actionIdx1;
- int _actionIdx2;
+ int _actionPlayerIdx;
+ int _actionVictimIdx;
int _winnerId;
int _instructionsWaitCount;
int _cursorCurRes;
@@ -372,7 +372,7 @@ public:
void discardCard(Card *card);
void subC4CD2();
void subC4CEC();
- void subC51A0(Card *subObj1, Card *subObj2);
+ void playInterceptorCard(Card *subObj1, Card *subObj2);
void displayDialog(int dialogNumb);
void subPostInit();
void displayInstructions();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
index 3f32503fdf..9eaead630b 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
@@ -2843,8 +2843,8 @@ void Scene3400::signal() {
R2_INVENTORY.setObjectScene(R2_SAPPHIRE_BLUE, 0);
_stripManager.start(3307, this);
if (R2_GLOBALS._player._characterIndex == R2_SEEKER) {
- _sceneMode = 3400;
- R2_GLOBALS._player.setAction(&_sequenceManager, this, 3400, &R2_GLOBALS._player, &_teal, &_sapphire, NULL);
+ _sceneMode = 3404;
+ R2_GLOBALS._player.setAction(&_sequenceManager, this, 3404, &R2_GLOBALS._player, &_teal, &_sapphire, NULL);
} else {
_sceneMode = 3408;
_companion1.setAction(&_sequenceManager, this, 3408, &_companion1, &_teal, &_sapphire, NULL);
@@ -3668,11 +3668,12 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_horizontalSpeedDisplay.setPosition(Common::Point(126, 108));
_horizontalSpeedDisplay.fixPriority(200);
+ _action1._turningFl = false;
+
+ _mazeUI.postInit();
_mazeUI.setDisplayBounds(Rect(160, 89, 299, 182));
_mazeUI.load(2);
_mazeUI.setMazePosition(_mazePosition);
-
- _action1._turningFl = false;
_mazeUI.draw();
_directionChangesEnabled = true;
@@ -3876,6 +3877,11 @@ void Scene3500::dispatch() {
Rect tmpRect;
Scene::dispatch();
+ // WORKAROUND: The _mazeUI wasn't originally added to the scene in postInit.
+ // This is only needed to fix old savegames
+ if (!R2_GLOBALS._sceneObjects->contains(&_mazeUI))
+ _mazeUI.draw();
+
if (((_shuttle._frame % 2) == 0) && (!_action1._turningFl)) {
_shuttle.setFrame(_shuttle.changeFrame());
_mazeDirection = _shuttle._frame;
@@ -4215,7 +4221,6 @@ void Scene3500::dispatch() {
_rotation->_idxChange = 0;
}
- _mazeUI.draw();
if (_exitCounter != 0)
++_exitCounter;
}
diff --git a/engines/tsage/ringworld2/ringworld2_speakers.cpp b/engines/tsage/ringworld2/ringworld2_speakers.cpp
index 6d4ef4ab75..016242edd1 100644
--- a/engines/tsage/ringworld2/ringworld2_speakers.cpp
+++ b/engines/tsage/ringworld2/ringworld2_speakers.cpp
@@ -1057,7 +1057,7 @@ void SpeakerNej2800::animateSpeaker() {
_object1.setup(4023, 3, 1);
if (_object2->_visage == 2801)
- _object1.setPosition(Common::Point(R2_GLOBALS._player._position.x - 12, R2_GLOBALS._player._position.y));
+ _object1.setPosition(Common::Point(_object2->_position.x - 12, _object2->_position.y));
_object1.animate(ANIM_MODE_5, this);
}
}
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index c5c38505a7..b95b614f09 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -164,7 +164,7 @@ Common::List<SoundDriverEntry> &SoundManager::buildDriverList(bool detectFlag) {
sd._status = detectFlag ? SNDSTATUS_DETECTED : SNDSTATUS_SKIPPED;
sd._field2 = 0;
sd._field6 = 15000;
- sd._shortDescription = "Adlib or SoundBlaster";
+ sd._shortDescription = "AdLib or SoundBlaster";
sd._longDescription = "3812fm";
_availableDrivers.push_back(sd);
@@ -379,7 +379,6 @@ void SoundManager::updateSoundLoop(Sound *sound) {
}
void SoundManager::rethinkVoiceTypes() {
- Common::StackLock slock(sfManager()._serverSuspendedMutex);
sfRethinkVoiceTypes();
}
@@ -1442,8 +1441,6 @@ bool SoundManager::sfDoRemoveFromPlayList(Sound *sound) {
}
void SoundManager::sfDoUpdateVolume(Sound *sound) {
- Common::StackLock slock(sfManager()._serverSuspendedMutex);
-
for (int voiceIndex = 0; voiceIndex < SOUND_ARR_SIZE; ++voiceIndex) {
VoiceTypeStruct *vs = sfManager()._voiceTypeStructPtrs[voiceIndex];
if (!vs)
@@ -1707,8 +1704,6 @@ void Sound::pause(bool flag) {
}
void Sound::mute(bool flag) {
- Common::StackLock slock(g_globals->_soundManager._serverSuspendedMutex);
-
if (flag)
++_mutedCount;
else if (_mutedCount > 0)
diff --git a/engines/tsage/user_interface.cpp b/engines/tsage/user_interface.cpp
index 45bfe2b5ea..3ee585d5ef 100644
--- a/engines/tsage/user_interface.cpp
+++ b/engines/tsage/user_interface.cpp
@@ -289,12 +289,13 @@ void UICollection::draw() {
void UICollection::r2rDrawFrame() {
Visage visage;
visage.setVisage(2, 1);
- GfxSurface vertLine = visage.getFrame(1);
+ GfxSurface vertLineLeft = visage.getFrame(1);
+ GfxSurface vertLineRight = visage.getFrame(3);
GfxSurface horizLine = visage.getFrame(2);
GLOBALS._screenSurface.copyFrom(horizLine, 0, 0);
- GLOBALS._screenSurface.copyFrom(vertLine, 0, 3);
- GLOBALS._screenSurface.copyFrom(vertLine, SCREEN_WIDTH - 4, 3);
+ GLOBALS._screenSurface.copyFrom(vertLineLeft, 0, 3);
+ GLOBALS._screenSurface.copyFrom(vertLineRight, SCREEN_WIDTH - 4, 3);
// Restrict drawing area to exclude the borders at the edge of the screen
R2_GLOBALS._screenSurface._clipRect = Rect(4, 3, SCREEN_WIDTH - 4,
diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp
index 5f06334720..9cba7b523d 100644
--- a/engines/tucker/resource.cpp
+++ b/engines/tucker/resource.cpp
@@ -535,7 +535,10 @@ void TuckerEngine::loadObj() {
return;
}
debug(2, "loadObj() partNum %d locationNum %d", _partNum, _locationNum);
- if ((_gameFlags & kGameFlagDemo) == 0) {
+ // If a savegame is loaded from the launcher, skip the display chapter
+ if (_startSlot != -1)
+ _startSlot = -1;
+ else if ((_gameFlags & kGameFlagDemo) == 0) {
handleNewPartSequence();
}
_currentPartNum = _partNum;
@@ -662,15 +665,13 @@ void TuckerEngine::loadData4() {
t.findNextToken(kDataTokenDw);
_gameDebug = t.getNextInteger() != 0;
_displayGameHints = t.getNextInteger() != 0;
- // forces game hints feature
-// _displayGameHints = true;
_locationObjectsCount = 0;
if (t.findIndex(_locationNum)) {
while (t.findNextToken(kDataTokenDw)) {
int i = t.getNextInteger();
- if (i < 0) {
+ if (i < 0)
break;
- }
+
assert(_locationObjectsCount < kLocationObjectsTableSize);
LocationObject *d = &_locationObjectsTable[_locationObjectsCount++];
d->_xPos = i;
@@ -851,60 +852,63 @@ void TuckerEngine::unloadSprC02_01() {
void TuckerEngine::loadFx() {
loadFile("fx.c", _loadTempBuf);
DataTokenizer t(_loadTempBuf, _fileLoadSize);
- t.findIndex(_locationNum);
- t.findNextToken(kDataTokenDw);
- _locationSoundsCount = t.getNextInteger();
- _currentFxSet = 0;
- for (int i = 0; i < _locationSoundsCount; ++i) {
- LocationSound *s = &_locationSoundsTable[i];
- s->_offset = 0;
- s->_num = t.getNextInteger();
- s->_volume = t.getNextInteger();
- s->_type = t.getNextInteger();
- switch (s->_type) {
- case 5:
- _currentFxSet = 1;
- _currentFxIndex = i;
- _currentFxVolume = s->_volume;
- _currentFxDist = t.getNextInteger();
- _currentFxScale = t.getNextInteger();
- break;
- case 6:
- case 7:
- case 8:
- s->_startFxSpriteState = t.getNextInteger();
- s->_startFxSpriteNum = t.getNextInteger();
- s->_updateType = t.getNextInteger();
- if (s->_type == 7) {
- s->_flagNum = t.getNextInteger();
- s->_flagValueStartFx = t.getNextInteger();
- s->_stopFxSpriteState = t.getNextInteger();
- s->_stopFxSpriteNum = t.getNextInteger();
- s->_flagValueStopFx = t.getNextInteger();
+ if (t.findIndex(_locationNum)) {
+ t.findNextToken(kDataTokenDw);
+ _locationSoundsCount = t.getNextInteger();
+ _currentFxSet = 0;
+ for (int i = 0; i < _locationSoundsCount; ++i) {
+ LocationSound *s = &_locationSoundsTable[i];
+ s->_offset = 0;
+ s->_num = t.getNextInteger();
+ s->_volume = t.getNextInteger();
+ s->_type = t.getNextInteger();
+ switch (s->_type) {
+ case 5:
+ _currentFxSet = 1;
+ _currentFxIndex = i;
+ _currentFxVolume = s->_volume;
+ _currentFxDist = t.getNextInteger();
+ _currentFxScale = t.getNextInteger();
+ break;
+ case 6:
+ case 7:
+ case 8:
+ s->_startFxSpriteState = t.getNextInteger();
+ s->_startFxSpriteNum = t.getNextInteger();
+ s->_updateType = t.getNextInteger();
+ if (s->_type == 7) {
+ s->_flagNum = t.getNextInteger();
+ s->_flagValueStartFx = t.getNextInteger();
+ s->_stopFxSpriteState = t.getNextInteger();
+ s->_stopFxSpriteNum = t.getNextInteger();
+ s->_flagValueStopFx = t.getNextInteger();
+ }
+ break;
+ }
+ if (s->_type == 8) {
+ s->_type = 6;
}
- break;
- }
- if (s->_type == 8) {
- s->_type = 6;
}
- }
- t.findNextToken(kDataTokenDw);
- int count = t.getNextInteger();
- _locationMusicsCount = 0;
- for (int i = 0; i < count; ++i) {
- int flagNum = t.getNextInteger();
- int flagValue = t.getNextInteger();
- if (flagValue == _flagsTable[flagNum]) {
- LocationMusic *m = &_locationMusicsTable[_locationMusicsCount++];
- m->_offset = 0;
- m->_num = t.getNextInteger();
- m->_volume = t.getNextInteger();
- m->_flag = t.getNextInteger();
- } else {
- for (int j = 0; j < 3; ++j) {
- t.getNextInteger();
+ t.findNextToken(kDataTokenDw);
+ int count = t.getNextInteger();
+ _locationMusicsCount = 0;
+ for (int i = 0; i < count; ++i) {
+ int flagNum = t.getNextInteger();
+ int flagValue = t.getNextInteger();
+ if (flagValue == _flagsTable[flagNum]) {
+ LocationMusic *m = &_locationMusicsTable[_locationMusicsCount++];
+ m->_offset = 0;
+ m->_num = t.getNextInteger();
+ m->_volume = t.getNextInteger();
+ m->_flag = t.getNextInteger();
+ } else {
+ for (int j = 0; j < 3; ++j) {
+ t.getNextInteger();
+ }
}
}
+ } else {
+ error("loadFx() - Index not found for location %d", _locationNum);
}
}
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index 2fb881f77e..d9f284e443 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -40,7 +40,7 @@ void TuckerEngine::handleIntroSequence() {
_player = new AnimationSequencePlayer(_system, _mixer, _eventMan, &_compressedSound, firstSequence);
_player->mainLoop();
delete _player;
- _player = 0;
+ _player = nullptr;
}
void TuckerEngine::handleCreditsSequence() {
@@ -115,7 +115,8 @@ void TuckerEngine::handleCreditsSequence() {
if (counter4 == _creditsSequenceTimecounts[num]) {
_fadePaletteCounter = 0;
clearSprites();
- ++num;
+ if (num < 6)
+ ++num;
Common::String filename;
if (num == 6) {
for (int i = 0; i < 16; ++i) {
@@ -123,6 +124,7 @@ void TuckerEngine::handleCreditsSequence() {
loadImage(filename.c_str(), imgBuf + i * 64000, 2);
}
} else {
+ filename = "";
switch (num) {
case 1:
filename = "loc75.pcx";
@@ -140,7 +142,8 @@ void TuckerEngine::handleCreditsSequence() {
filename = "loc78.pcx";
break;
}
- loadImage(filename.c_str(), _quadBackgroundGfxBuf, 2);
+ if (filename != "")
+ loadImage(filename.c_str(), _quadBackgroundGfxBuf, 2);
}
_spritesCount = _creditsSequenceSpriteCounts[num];
++_flagsTable[236];
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
index adf4be6b65..de555cd7b6 100644
--- a/engines/tucker/tucker.cpp
+++ b/engines/tucker/tucker.cpp
@@ -50,6 +50,7 @@ TuckerEngine::TuckerEngine(OSystem *system, Common::Language language, uint32 fl
_currentSaveLoadGameState = 1;
_fileLoadSize = 0;
_csDataSize = 0;
+ _startSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
_player = nullptr;
_loadTempBuf = nullptr;
@@ -91,7 +92,8 @@ Common::Error TuckerEngine::run() {
initGraphics(kScreenWidth, kScreenHeight, false);
syncSoundSettings();
_compressedSound.openFile();
- handleIntroSequence();
+ if (_startSlot == -1)
+ handleIntroSequence();
if ((_gameFlags & kGameFlagIntroOnly) == 0 && !shouldQuit()) {
mainLoop();
}
@@ -604,6 +606,7 @@ void TuckerEngine::mainLoop() {
_flagsTable[236] = 74;
}
}
+
if (_flagsTable[236] > 70) {
handleCreditsSequence();
_quitGame = true;
@@ -890,9 +893,8 @@ void TuckerEngine::updateCharPosition() {
if (action->_testFlag1Num < 500) {
if (action->_testFlag1Num >= 300)
error("updateCharPosition() - Unexpected value for _testFlag1Num : %d", action->_testFlag1Num);
- if (_flagsTable[action->_testFlag1Num] != action->_testFlag1Value) {
+ if (_flagsTable[action->_testFlag1Num] != action->_testFlag1Value)
skip = false;
- }
} else if (_inventoryItemsState[action->_testFlag1Num - 500] != action->_testFlag1Value) {
skip = false;
}
@@ -900,9 +902,10 @@ void TuckerEngine::updateCharPosition() {
}
if (action->_testFlag2Num != 0) {
if (action->_testFlag2Num < 500) {
- if (_flagsTable[action->_testFlag2Num] != action->_testFlag2Value) {
+ if (action->_testFlag2Num >= 300)
+ error("updateCharPosition() - Unexpected value for _testFlag1Num : %d", action->_testFlag1Num);
+ if (_flagsTable[action->_testFlag2Num] != action->_testFlag2Value)
skip = false;
- }
} else if (_inventoryItemsState[action->_testFlag2Num - 500] != action->_testFlag2Value) {
skip = false;
}
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index adcd02b2fe..a423915a5f 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -613,6 +613,7 @@ protected:
CompressedSound _compressedSound;
Common::Language _gameLang;
uint32 _gameFlags;
+ int _startSlot;
bool _quitGame;
bool _fastMode;
diff --git a/engines/voyeur/animation.cpp b/engines/voyeur/animation.cpp
index c1ded75f02..62b37346da 100644
--- a/engines/voyeur/animation.cpp
+++ b/engines/voyeur/animation.cpp
@@ -48,7 +48,7 @@ RL2Decoder::~RL2Decoder() {
}
bool RL2Decoder::loadVideo(int videoId) {
- Common::String filename = Common::String::format("%s.rl2",
+ Common::String filename = Common::String::format("%s.rl2",
::Voyeur::SZ_FILENAMES[videoId * 2]);
return loadRL2File(filename, false);
}
@@ -121,7 +121,7 @@ void RL2Decoder::readNextPacket() {
if (_soundFrameNumber == -1)
_soundFrameNumber = (frameNumber == -1) ? 0 : frameNumber;
- while (audioTrack->numQueuedStreams() < SOUND_FRAMES_READAHEAD &&
+ while (audioTrack->numQueuedStreams() < SOUND_FRAMES_READAHEAD &&
(_soundFrameNumber < (int)_soundFrames.size())) {
_fileStream->seek(_soundFrames[_soundFrameNumber]._offset);
audioTrack->queueSound(_fileStream, _soundFrames[_soundFrameNumber]._size);
@@ -217,13 +217,13 @@ bool RL2Decoder::RL2FileHeader::isValid() const {
}
Common::Rational RL2Decoder::RL2FileHeader::getFrameRate() const {
- return (_soundRate > 0) ? Common::Rational(_rate, _defSoundSize) :
+ return (_soundRate > 0) ? Common::Rational(_rate, _defSoundSize) :
Common::Rational(11025, 1103);
}
/*------------------------------------------------------------------------*/
-RL2Decoder::RL2VideoTrack::RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack,
+RL2Decoder::RL2VideoTrack::RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack,
Common::SeekableReadStream *stream): _header(header), _fileStream(stream) {
_frameOffsets = nullptr;
@@ -261,7 +261,7 @@ void RL2Decoder::RL2VideoTrack::initBackSurface() {
bool RL2Decoder::RL2VideoTrack::seek(const Audio::Timestamp &time) {
int frame = getFrameAtTime(time);
-
+
if (frame < 0 || frame >= _header._numFrames)
return false;
@@ -287,7 +287,7 @@ const Graphics::Surface *RL2Decoder::RL2VideoTrack::decodeNextFrame() {
_fileStream->seek(0x324);
rl2DecodeFrameWithoutTransparency(0);
- Common::copy((byte *)_surface->getPixels(), (byte *)_surface->getPixels() + (320 * 200),
+ Common::copy((byte *)_surface->getPixels(), (byte *)_surface->getPixels() + (320 * 200),
(byte *)_backSurface->getPixels());
_dirtyRects.push_back(Common::Rect(0, 0, _surface->w, _surface->h));
_initialFrame = false;
@@ -433,7 +433,7 @@ Graphics::Surface *RL2Decoder::RL2VideoTrack::getBackSurface() {
/*------------------------------------------------------------------------*/
-RL2Decoder::RL2AudioTrack::RL2AudioTrack(const RL2FileHeader &header, Common::SeekableReadStream *stream, Audio::Mixer::SoundType soundType):
+RL2Decoder::RL2AudioTrack::RL2AudioTrack(const RL2FileHeader &header, Common::SeekableReadStream *stream, Audio::Mixer::SoundType soundType):
_header(header), _soundType(soundType) {
// Create audio straem for the audio track
_audStream = Audio::makeQueuingAudioStream(_header._rate, _header._channels == 2);
@@ -450,7 +450,7 @@ void RL2Decoder::RL2AudioTrack::queueSound(Common::SeekableReadStream *stream, i
Common::MemoryReadStream *memoryStream = new Common::MemoryReadStream(data, size,
DisposeAfterUse::YES);
- _audStream->queueAudioStream(Audio::makeRawStream(memoryStream, _header._rate,
+ _audStream->queueAudioStream(Audio::makeRawStream(memoryStream, _header._rate,
Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), DisposeAfterUse::YES);
}
@@ -458,7 +458,7 @@ Audio::AudioStream *RL2Decoder::RL2AudioTrack::getAudioStream() const {
return _audStream;
}
-void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
+void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
byte *frames, byte *imgPos) {
vm->flipPageAndWait();
int paletteStart = getPaletteStart();
@@ -472,14 +472,14 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
vm->_graphicsManager->setPalette128(palette, paletteStart, paletteCount);
}
-
+
if (needsUpdate()) {
if (frames) {
// If reached a point where a new background is needed, load it
// and copy over to the video decoder
if (getCurFrame() >= READ_LE_UINT16(frames + picCtr * 4)) {
PictureResource *newPic = vm->_bVoy->boltEntry(0x302 + picCtr)._picResource;
- Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32,
+ Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32,
READ_LE_UINT16(imgPos + 4 * picCtr + 2) - 20);
vm->_graphicsManager->sDrawPic(newPic, &videoFrame, pt);
@@ -492,7 +492,7 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
(byte *)vm->_graphicsManager->_screenSurface.getPixels());
}
-
+
vm->_eventsManager->getMouseInfo();
g_system->delayMillis(10);
}
diff --git a/engines/voyeur/animation.h b/engines/voyeur/animation.h
index b17e998214..bc6d8a361a 100644
--- a/engines/voyeur/animation.h
+++ b/engines/voyeur/animation.h
@@ -105,7 +105,7 @@ private:
class RL2VideoTrack : public FixedRateVideoTrack {
public:
- RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack,
+ RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack,
Common::SeekableReadStream *stream);
~RL2VideoTrack();
diff --git a/engines/voyeur/configure.engine b/engines/voyeur/configure.engine
index 23891fccb7..c53530a9ed 100644
--- a/engines/voyeur/configure.engine
+++ b/engines/voyeur/configure.engine
@@ -1,4 +1,4 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine voyeur "Voyeur" no
+add_engine voyeur "Voyeur" yes
diff --git a/engines/voyeur/data.cpp b/engines/voyeur/data.cpp
index cc0b81a313..b8c987f18b 100644
--- a/engines/voyeur/data.cpp
+++ b/engines/voyeur/data.cpp
@@ -94,7 +94,7 @@ SVoy::SVoy(VoyeurEngine *vm):_vm(vm) {
_evCmPtrs[i] = nullptr;
}
-void SVoy::addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId,
+void SVoy::addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId,
int on, int off, int dead) {
VoyeurEvent &e = _events[_eventCount++];
@@ -309,7 +309,7 @@ bool SVoy::checkForKey() {
if (e._audioVideoId == 40 && e._computerOn < 2 && e._computerOff > 6)
state->_victimEvidenceIndex = 4;
break;
-
+
default:
break;
}
@@ -321,7 +321,7 @@ bool SVoy::checkForKey() {
if (e._audioVideoId == 8 && e._computerOn < 2 && e._computerOff > 26)
state->_victimEvidenceIndex = 1;
break;
-
+
case 3:
if (e._audioVideoId == 20 && e._computerOn < 2 && e._computerOff > 28)
state->_victimEvidenceIndex = 3;
diff --git a/engines/voyeur/data.h b/engines/voyeur/data.h
index 98c884d0c1..a18ad84f51 100644
--- a/engines/voyeur/data.h
+++ b/engines/voyeur/data.h
@@ -101,7 +101,7 @@ public:
*/
bool isInRange(int slotIndex, int hotspotIndex, int v) const {
return _min[slotIndex][hotspotIndex] <= v &&
- v < _max[slotIndex][hotspotIndex];
+ v < _max[slotIndex][hotspotIndex];
}
};
@@ -164,7 +164,7 @@ public:
/**
* Add an event to the list of game events that have occurred
*/
- void addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId,
+ void addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId,
int on, int off, int dead);
/**
@@ -181,7 +181,7 @@ public:
* Adds the start of an audio event happening
*/
void addAudioEventStart();
-
+
/**
* Adsd the finish of an audio event happening
*/
@@ -191,17 +191,17 @@ public:
* Adds the start of an evidence event happening
*/
void addEvidEventStart(int v);
-
+
/**
* Adds the finish of an evidence event happening
*/
void addEvidEventEnd(int totalPages);
-
+
/**
* Adds the start of a computer event happening
*/
void addComputerEventStart();
-
+
/**
* Adds the finish of a computer event happening
*/
diff --git a/engines/voyeur/debugger.cpp b/engines/voyeur/debugger.cpp
index 234300bce5..e9a12180da 100644
--- a/engines/voyeur/debugger.cpp
+++ b/engines/voyeur/debugger.cpp
@@ -29,11 +29,10 @@ namespace Voyeur {
Debugger::Debugger(VoyeurEngine *vm) : GUI::Debugger(), _vm(vm) {
// Register methods
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("exit", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("time", WRAP_METHOD(Debugger, Cmd_Time));
- DCmd_Register("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots));
- DCmd_Register("mouse", WRAP_METHOD(Debugger, Cmd_Mouse));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("time", WRAP_METHOD(Debugger, Cmd_Time));
+ registerCmd("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots));
+ registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse));
// Set fields
_isTimeActive = true;
@@ -46,44 +45,44 @@ static const int TIME_STATES[] = {
bool Debugger::Cmd_Time(int argc, const char **argv) {
if (argc < 2) {
- // Get the current day and time of day
+ // Get the current day and time of day
Common::String dtString = _vm->getDayName();
Common::String timeString = _vm->getTimeOfDay();
if (!timeString.empty())
dtString += " " + timeString;
- DebugPrintf("Time period = %d, date/time is: %s, time is %s\n",
+ debugPrintf("Time period = %d, date/time is: %s, time is %s\n",
_vm->_voy->_transitionId, dtString.c_str(), _isTimeActive ? "on" : "off");
- DebugPrintf("Format: %s [on | off | 1..17 | val <amount>]\n\n", argv[0]);
+ debugPrintf("Format: %s [on | off | 1..17 | val <amount>]\n\n", argv[0]);
} else {
if (!strcmp(argv[1], "on")) {
_isTimeActive = true;
- DebugPrintf("Time is now on\n\n");
+ debugPrintf("Time is now on\n\n");
} else if (!strcmp(argv[1], "off")) {
_isTimeActive = false;
- DebugPrintf("Time is now off\n\n");
+ debugPrintf("Time is now off\n\n");
} else if (!strcmp(argv[1], "val")) {
if (argc < 3) {
- DebugPrintf("Time expired is currently %d.\n", _vm->_voy->_RTVNum);
+ debugPrintf("Time expired is currently %d.\n", _vm->_voy->_RTVNum);
} else {
_vm->_voy->_RTVNum = atoi(argv[2]);
- DebugPrintf("Time expired is now %d.\n", _vm->_voy->_RTVNum);
+ debugPrintf("Time expired is now %d.\n", _vm->_voy->_RTVNum);
}
} else {
int timeId = atoi(argv[1]);
if (timeId >= 1 && timeId < 17) {
int stateId = TIME_STATES[timeId - 1];
if (!stateId) {
- DebugPrintf("Given time period is not used in-game\n");
+ debugPrintf("Given time period is not used in-game\n");
} else {
- DebugPrintf("Changing to time period: %d\n", timeId);
+ debugPrintf("Changing to time period: %d\n", timeId);
if (_vm->_mainThread->goToState(-1, stateId))
_vm->_mainThread->parsePlayCommands();
return false;
}
} else {
- DebugPrintf("Unknown parameter\n\n");
+ debugPrintf("Unknown parameter\n\n");
}
}
}
@@ -93,7 +92,7 @@ bool Debugger::Cmd_Time(int argc, const char **argv) {
bool Debugger::Cmd_Hotspots(int argc, const char **argv) {
if (_vm->_voy->_computerTextId >= 0) {
- DebugPrintf("Hotspot Computer Screen %d - %d,%d->%d,%d\n",
+ debugPrintf("Hotspot Computer Screen %d - %d,%d->%d,%d\n",
_vm->_voy->_computerTextId,
_vm->_voy->_computerScreenRect.left,
_vm->_voy->_computerScreenRect.top,
@@ -112,9 +111,9 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) {
hotspots[hotspotIdx].right, hotspots[hotspotIdx].bottom);
int arrIndex = hotspots[hotspotIdx]._arrIndex;
if (_vm->_voy->_roomHotspotsEnabled[arrIndex - 1]) {
- DebugPrintf("Hotspot Room %d - %s - Enabled\n", arrIndex, pos);
+ debugPrintf("Hotspot Room %d - %s - Enabled\n", arrIndex, pos);
} else {
- DebugPrintf("Hotspot Room - %s - Disabled\n", pos);
+ debugPrintf("Hotspot Room - %s - Disabled\n", pos);
}
}
}
@@ -132,14 +131,14 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) {
for (int arrIndex = 0; arrIndex < 3; ++arrIndex) {
if (_vm->_voy->_audioHotspotTimes._min[arrIndex][hotspotIdx] != 9999) {
- DebugPrintf("Hotspot %d %s Audio slot %d, time: %d to %d\n",
+ debugPrintf("Hotspot %d %s Audio slot %d, time: %d to %d\n",
hotspotIdx, pos.c_str(), arrIndex,
_vm->_voy->_audioHotspotTimes._min[arrIndex][hotspotIdx],
_vm->_voy->_audioHotspotTimes._max[arrIndex][hotspotIdx]);
}
if (_vm->_voy->_evidenceHotspotTimes._min[arrIndex][hotspotIdx] != 9999) {
- DebugPrintf("Hotspot %d %s Evidence slot %d, time: %d to %d\n",
+ debugPrintf("Hotspot %d %s Evidence slot %d, time: %d to %d\n",
hotspotIdx, pos.c_str(), arrIndex,
_vm->_voy->_evidenceHotspotTimes._min[arrIndex][hotspotIdx],
_vm->_voy->_evidenceHotspotTimes._max[arrIndex][hotspotIdx]);
@@ -148,7 +147,7 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) {
for (int arrIndex = 0; arrIndex < 8; ++arrIndex) {
if (_vm->_voy->_videoHotspotTimes._min[arrIndex][hotspotIdx] != 9999) {
- DebugPrintf("Hotspot %d %s Video slot %d, time: %d to %d\n",
+ debugPrintf("Hotspot %d %s Video slot %d, time: %d to %d\n",
hotspotIdx, pos.c_str(), arrIndex,
_vm->_voy->_videoHotspotTimes._min[arrIndex][hotspotIdx],
_vm->_voy->_videoHotspotTimes._max[arrIndex][hotspotIdx]);
@@ -157,16 +156,16 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) {
}
}
- DebugPrintf("\nEnd of list\n");
+ debugPrintf("\nEnd of list\n");
return true;
}
bool Debugger::Cmd_Mouse(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("mouse [ on | off ]\n");
+ debugPrintf("mouse [ on | off ]\n");
} else {
_showMousePosition = !strcmp(argv[1], "on");
- DebugPrintf("Mouse position is now %s\n", _showMousePosition ? "on" : "off");
+ debugPrintf("Mouse position is now %s\n", _showMousePosition ? "on" : "off");
}
return true;
diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp
index 9a3c6d00ff..7ce7351e65 100644
--- a/engines/voyeur/events.cpp
+++ b/engines/voyeur/events.cpp
@@ -73,7 +73,7 @@ EventsManager::EventsManager(VoyeurEngine *vm) : _intPtr(_gameData),
Common::fill(&_cycleTime[0], &_cycleTime[4], 0);
Common::fill(&_cycleNext[0], &_cycleNext[4], (byte *)nullptr);
_cyclePtr = NULL;
-
+
_leftClick = _rightClick = false;
_mouseClicked = _newMouseClicked = false;
_newLeftClick = _newRightClick = false;;
@@ -158,7 +158,7 @@ void EventsManager::checkForNextFrameCounter() {
showMousePosition();
// Display the frame
- g_system->copyRectToScreen((byte *)_vm->_graphicsManager->_screenSurface.getPixels(),
+ g_system->copyRectToScreen((byte *)_vm->_graphicsManager->_screenSurface.getPixels(),
SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
g_system->updateScreen();
@@ -218,7 +218,7 @@ void EventsManager::videoTimer() {
_gameData._hasPalette = false;
g_system->getPaletteManager()->setPalette(_gameData._palette +
- _gameData._palStartIndex * 3, _gameData._palStartIndex,
+ _gameData._palStartIndex * 3, _gameData._palStartIndex,
_gameData._palEndIndex - _gameData._palStartIndex + 1);
}
}
@@ -241,7 +241,7 @@ void EventsManager::delayClick(int cycles) {
do {
g_system->delayMillis(10);
getMouseInfo();
- } while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd
+ } while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd
&& !_vm->_eventsManager->_mouseClicked);
}
@@ -315,7 +315,7 @@ void EventsManager::startFade(CMapResource *cMap) {
palEntry._bEntry = vgaP[2] << 8;
int bDiff = (cMap->_entries[mapIndex * 3 + 2] << 8) - palEntry._bEntry;
palEntry._bChange = bDiff / cMap->_steps;
-
+
palEntry._palIndex = idx;
if (!(cMap->_fadeStatus & 1))
++mapIndex;
@@ -431,12 +431,12 @@ void EventsManager::vDoCycleInt() {
byte b = pPal[start * 3 + 2];
Common::copy(&pPal[start * 3 + 3], &pPal[end * 3 + 3], &pPal[start * 3]);
-
+
// Place the original saved entry at the end of the range
pPal[end * 3] = r;
pPal[end * 3 + 1] = g;
pPal[end * 3 + 2] = b;
-
+
if (_fadeStatus & 1) {
//dx = start, di = end
warning("TODO: Adjustment of ViewPortListResource");
@@ -454,12 +454,12 @@ void EventsManager::vDoCycleInt() {
// Move the remainder of the range forwards one entry
Common::copy_backward(&pPal[start * 3], &pPal[end * 3], &pPal[end * 3 + 3]);
-
+
// Place the original saved entry at the end of the range
pPal[start * 3] = r;
pPal[start * 3 + 1] = g;
pPal[start * 3 + 2] = b;
-
+
if (_fadeStatus & 1) {
//dx = start, di = end
warning("TODO: Adjustment of ViewPortListResource");
diff --git a/engines/voyeur/events.h b/engines/voyeur/events.h
index 5e0bfe6404..0c1cef0955 100644
--- a/engines/voyeur/events.h
+++ b/engines/voyeur/events.h
@@ -38,7 +38,7 @@ class CMapResource;
#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
typedef void (EventsManager::*EventMethodPtr)();
-
+
class IntNode {
public:
EventMethodPtr _intFunc;
diff --git a/engines/voyeur/files.cpp b/engines/voyeur/files.cpp
index 7369d9280e..300e086f75 100644
--- a/engines/voyeur/files.cpp
+++ b/engines/voyeur/files.cpp
@@ -421,8 +421,8 @@ byte *BoltFile::getBoltMember(uint32 id) {
}
void BoltFile::initDefault() {
- _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size,
- _state._curMemberPtr->_mode);
+ _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size,
+ _state._curMemberPtr->_mode);
}
/*------------------------------------------------------------------------*/
@@ -505,7 +505,7 @@ void BVoyBoltFile::initSoundMap() {
}
void BVoyBoltFile::sInitRect() {
- _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size,
+ _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size,
_state._curMemberPtr->_mode);
// Check whether the resource Id is in the list of extended rects
@@ -522,7 +522,7 @@ void BVoyBoltFile::sInitRect() {
void BVoyBoltFile::sInitPic() {
// Read in the header data
_state._curMemberPtr->_data = _state.decompress(NULL, 24, _state._curMemberPtr->_mode);
- _state._curMemberPtr->_picResource = new PictureResource(_state,
+ _state._curMemberPtr->_picResource = new PictureResource(_state,
_state._curMemberPtr->_data);
}
@@ -567,14 +567,14 @@ void StampBoltFile::initResource(int resType) {
void StampBoltFile::initThread() {
initDefault();
- _state._curMemberPtr->_threadResource = new ThreadResource(_state,
+ _state._curMemberPtr->_threadResource = new ThreadResource(_state,
_state._curMemberPtr->_data);
}
void StampBoltFile::initPtr() {
initDefault();
- _state._curMemberPtr->_ptrResource = new PtrResource(_state,
+ _state._curMemberPtr->_ptrResource = new PtrResource(_state,
_state._curMemberPtr->_data);
}
@@ -585,7 +585,7 @@ void StampBoltFile::initControl() {
initDefault();
ControlResource *res;
- _state._curMemberPtr->_controlResource = res = new ControlResource(_state,
+ _state._curMemberPtr->_controlResource = res = new ControlResource(_state,
_state._curMemberPtr->_data);
_state._vm->_controlGroupPtr = _state._curGroupPtr;
@@ -596,7 +596,7 @@ void StampBoltFile::initState() {
initDefault();
assert(_state._curMemberPtr->_size == 16);
- _state._curMemberPtr->_stateResource = new StateResource(_state,
+ _state._curMemberPtr->_stateResource = new StateResource(_state,
_state._curMemberPtr->_data);
}
@@ -658,7 +658,7 @@ BoltEntry::BoltEntry(Common::SeekableReadStream *f, uint16 id): _file(f), _id(id
_mode = buffer[0];
_initMethod = buffer[3];
_size = READ_LE_UINT32(&buffer[4]) & 0xffffff;
- _fileOffset = READ_LE_UINT32(&buffer[8]);
+ _fileOffset = READ_LE_UINT32(&buffer[8]);
}
BoltEntry::~BoltEntry() {
@@ -687,7 +687,7 @@ void BoltEntry::load() {
*/
bool BoltEntry::hasResource() const {
return _rectResource || _picResource || _viewPortResource || _viewPortListResource
- || _fontResource || _fontInfoResource || _cMapResource || _vInitCycleResource
+ || _fontResource || _fontInfoResource || _cMapResource || _vInitCycleResource
|| _ptrResource || _controlResource || _stateResource || _threadResource;
}
@@ -719,7 +719,7 @@ RectResource::RectResource(const byte *src, int size, bool isExtendedRects) {
int x1 = READ_LE_UINT16(src);
int y1 = READ_LE_UINT16(src + 2);
- int x2 = READ_LE_UINT16(src + 4);
+ int x2 = READ_LE_UINT16(src + 4);
int y2 = READ_LE_UINT16(src + 6);
_entries.push_back(RectEntry(x1, y1, x2, y2, arrIndex, rectCount));
@@ -896,7 +896,7 @@ int DisplayResource::drawText(const Common::String &msg) {
viewPort->_fontRect.top -= fontInfo._shadow.y;
}
}
- }
+ }
if (gfxManager._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT)) {
viewPort->addSaveRect(viewPort->_pageIndex, viewPort->_fontRect);
@@ -971,7 +971,7 @@ int DisplayResource::drawText(const Common::String &msg) {
fontChar._imgData = fontData._charImages + offset * 2;
gfxManager.sDrawPic(&fontChar, this, Common::Point(xp, yp));
-
+
fontChar._imgData = NULL;
xp += charWidth + padding;
msgWidth += charWidth + padding;
@@ -1056,13 +1056,18 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src):
byte *imgData = state._curLibPtr->boltEntry(id)._picResource->_imgData;
_freeImgData = DisposeAfterUse::NO;
- // TODO: Double check code below. Despite different coding in the
- // original, both looked like they do the same formula
+#if 0
+ // TODO: Double check code below. Despite different coding in the
+ // original, both looked like they do the same formula.
+ // Until it's clarified, this check is disabled and replaced by the
+ // common code.
if (_flags & PICFLAG_PIC_OFFSET) {
_imgData = imgData + (READ_LE_UINT32(&src[18]) & 0xffff);
} else {
_imgData = imgData + (READ_LE_UINT32(&src[18]) & 0xffff);
}
+#endif
+ _imgData = imgData + (READ_LE_UINT32(&src[18]) & 0xffff);
}
} else if (_flags & PICFLAG_PIC_OFFSET) {
int mode = 0;
@@ -1082,7 +1087,7 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src):
if (mode != state._vm->_graphicsManager->_SVGAMode) {
state._vm->_graphicsManager->_SVGAMode = mode;
- state._vm->_graphicsManager->clearPalette();
+ state._vm->_graphicsManager->clearPalette();
}
int screenOffset = READ_LE_UINT32(&src[18]) & 0xffff;
@@ -1118,7 +1123,7 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src):
_imgData = new byte[nbytes];
Common::fill(_imgData, _imgData + nbytes, 0);
} else {
- _imgData = state.decompress(NULL, nbytes, state._curMemberPtr->_mode);
+ _imgData = state.decompress(NULL, nbytes, state._curMemberPtr->_mode);
}
}
}
@@ -1131,7 +1136,7 @@ PictureResource::PictureResource(Graphics::Surface *surface) {
_maskData = 0;
_planeSize = 0;
_keyColor = 0;
-
+
_bounds = Common::Rect(0, 0, surface->w, surface->h);
_imgData = (byte *)surface->getPixels();
_freeImgData = DisposeAfterUse::NO;
@@ -1150,7 +1155,7 @@ PictureResource::PictureResource() {
_freeImgData = DisposeAfterUse::NO;
}
-PictureResource::PictureResource(int flags, int select, int pick, int onOff,
+PictureResource::PictureResource(int flags, int select, int pick, int onOff,
const Common::Rect &bounds, int maskData, byte *imgData, int planeSize) {
_flags = flags;
_select = select;
@@ -1189,7 +1194,7 @@ void PictureResource::flipVertical(const byte *data) {
for (int y = 0; y < _bounds.height(); ++y) {
Common::copy(srcP, srcP + _bounds.width(), destP);
srcP += _bounds.width();
- destP -= _bounds.width();
+ destP -= _bounds.width();
}
}
@@ -1205,7 +1210,7 @@ ViewPortResource::ViewPortResource(BoltFilesState &state, const byte *src):
int xs = READ_LE_UINT16(src + 12);
int ys = READ_LE_UINT16(src + 14);
- _bounds = Common::Rect(xs, ys, xs + READ_LE_UINT16(src + 16),
+ _bounds = Common::Rect(xs, ys, xs + READ_LE_UINT16(src + 16),
ys + READ_LE_UINT16(src + 18));
_currentPic = state._curLibPtr->getPictureResource(READ_LE_UINT32(src + 0x20));
@@ -1285,7 +1290,7 @@ void ViewPortResource::setupViewPort(PictureResource *page, Common::Rect *clippi
yDiff = r.bottom - page->_bounds.bottom;
if (xDiff > 0)
- r.setWidth(xDiff <= r.width() ? r.width() - xDiff : 0);
+ r.setWidth(xDiff <= r.width() ? r.width() - xDiff : 0);
if (yDiff > 0)
r.setHeight(yDiff <= r.height() ? r.height() - yDiff : 0);
}
@@ -1305,7 +1310,7 @@ void ViewPortResource::setupViewPort(PictureResource *page, Common::Rect *clippi
r.top = clippingRect->top;
r.setHeight(yDiff <= height ? height - yDiff : 0);
}
-
+
xDiff = r.right - clippingRect->right;
yDiff = r.bottom - clippingRect->bottom;
@@ -1339,7 +1344,7 @@ void ViewPortResource::setupViewPort(PictureResource *pic, Common::Rect *clippin
void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) {
Common::Rect rect = r;
-
+
if (clipRect(rect)) {
if (_addFn) {
(_state._vm->_graphicsManager->*_addFn)(this, pageIndex, rect);
@@ -1355,21 +1360,21 @@ void ViewPortResource::fillPic(byte onOff) {
void ViewPortResource::drawIfaceTime() {
// Hour display
- _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+ _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
(_state._vm->_gameHour / 10) == 0 ? 10 : _state._vm->_gameHour / 10,
Common::Point(161, 25));
- _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+ _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
_state._vm->_gameHour % 10, Common::Point(172, 25));
// Minute display
- _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+ _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
_state._vm->_gameMinute / 10, Common::Point(190, 25));
- _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+ _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
_state._vm->_gameMinute % 10, Common::Point(201, 25));
// AM/PM indicator
PictureResource *pic = _state._vm->_bVoy->boltEntry(_state._vm->_voy->_isAM ? 272 : 273)._picResource;
- _state._vm->_graphicsManager->sDrawPic(pic, _state._vm->_graphicsManager->_vPort,
+ _state._vm->_graphicsManager->sDrawPic(pic, _state._vm->_graphicsManager->_vPort,
Common::Point(215, 27));
}
@@ -1488,9 +1493,9 @@ FontInfoResource::FontInfoResource() {
_shadowColor = 0;
}
-FontInfoResource::FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff,
- byte fontFlags, FontJustify justify, int fontSaveBack, const Common::Point &pos,
- int justifyWidth, int justifyHeight, const Common::Point &shadow, int foreColor,
+FontInfoResource::FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff,
+ byte fontFlags, FontJustify justify, int fontSaveBack, const Common::Point &pos,
+ int justifyWidth, int justifyHeight, const Common::Point &shadow, int foreColor,
int backColor, int shadowColor) {
_curFont = NULL;
_picFlags = picFlags;
@@ -1516,7 +1521,7 @@ CMapResource::CMapResource(BoltFilesState &state, const byte *src): _vm(state._v
_fadeStatus = src[1];
_start = READ_LE_UINT16(src + 2);
_end = READ_LE_UINT16(src + 4);
-
+
int count = _end - _start + 1;
_entries = new byte[count * 3];
Common::copy(src + 6, src + 6 + 3 * count, _entries);
@@ -1607,7 +1612,7 @@ ControlResource::ControlResource(BoltFilesState &state, const byte *src) {
/*------------------------------------------------------------------------*/
StateResource::StateResource(BoltFilesState &state, const byte *src):
- _victimIndex(_vals[1]), _victimEvidenceIndex(_vals[2]),
+ _victimIndex(_vals[1]), _victimEvidenceIndex(_vals[2]),
_victimMurderIndex(_vals[3]) {
for (int i = 0; i < 4; ++i)
_vals[i] = READ_LE_UINT32(src + i * 4);
diff --git a/engines/voyeur/files.h b/engines/voyeur/files.h
index 49c0b2c8a4..eef5df497c 100644
--- a/engines/voyeur/files.h
+++ b/engines/voyeur/files.h
@@ -114,7 +114,7 @@ public:
void resolveIt(uint32 id, byte **p);
void resolveFunction(uint32 id, GraphicMethodPtr *fn);
- BoltEntry &boltEntry(uint16 id);
+ BoltEntry &boltEntry(uint16 id);
BoltEntry &getBoltEntryFromLong(uint32 id);
PictureResource *getPictureResource(uint32 id);
CMapResource *getCMapResource(uint32 id);
@@ -160,7 +160,7 @@ public:
int _fileOffset;
Common::Array<BoltEntry> _entries;
public:
- BoltGroup(Common::SeekableReadStream *f);
+ BoltGroup(Common::SeekableReadStream *f);
virtual ~BoltGroup();
void load(uint16 groupId);
@@ -234,15 +234,15 @@ public:
/* bvoy.blt resource types */
enum PictureFlag {
- PICFLAG_2 = 2, PICFLAG_PIC_OFFSET = 8, PICFLAG_CLEAR_SCREEN = 0x10,
+ PICFLAG_2 = 2, PICFLAG_PIC_OFFSET = 8, PICFLAG_CLEAR_SCREEN = 0x10,
PICFLAG_20 = 0x20, PICFLAG_HFLIP = 0x40, PICFLAG_VFLIP = 0x80, PICFLAG_100 = 0x100,
- PICFLAG_CLEAR_SCREEN00 = 0x1000
+ PICFLAG_CLEAR_SCREEN00 = 0x1000
};
enum DisplayFlag {
- DISPFLAG_1 = 1, DISPFLAG_2 = 2, DISPFLAG_4 = 4, DISPFLAG_8 = 8,
+ DISPFLAG_1 = 1, DISPFLAG_2 = 2, DISPFLAG_4 = 4, DISPFLAG_8 = 8,
DISPFLAG_10 = 0x10, DISPFLAG_20 = 0x20, DISPFLAG_40 = 0x40, DISPFLAG_80 = 0x80,
- DISPFLAG_100 = 0x100, DISPFLAG_200 = 0x200, DISPFLAG_400 = 0x400,
+ DISPFLAG_100 = 0x100, DISPFLAG_200 = 0x200, DISPFLAG_400 = 0x400,
DISPFLAG_800 = 0x800, DISPFLAG_1000 = 0x1000, DISPFLAG_2000 = 0x2000,
DISPFLAG_4000 = 0x4000, DISPFLAG_VIEWPORT = 0x8000, DISPFLAG_CURSOR = 0x10000,
DISPFLAG_NONE = 0};
@@ -256,7 +256,7 @@ public:
DisplayResource();
DisplayResource(VoyeurEngine *vm);
- /**
+ /**
* Fill a box of the given size at the current _drawPtr location
*/
void sFillBox(int width, int height);
@@ -308,7 +308,7 @@ public:
DisposeAfterUse::Flag _freeImgData;
public:
PictureResource(BoltFilesState &state, const byte *src);
- PictureResource(int flags, int select, int pick, int onOff,
+ PictureResource(int flags, int select, int pick, int onOff,
const Common::Rect &bounds, int maskData, byte *imgData, int planeSize);
PictureResource(Graphics::Surface *surface);
PictureResource();
@@ -334,7 +334,7 @@ public:
PictureResource *_pages[2];
// Rect lists and counts. Note that _rectListCount values of '-1' seem to have
- // special significance, which is why I'm not making them redundant in favor
+ // special significance, which is why I'm not making them redundant in favor
// of the arrays' .size() method
Common::Array<Common::Rect> *_rectListPtr[3];
int _rectListCount[3];
@@ -413,9 +413,9 @@ public:
public:
FontInfoResource(BoltFilesState &state, const byte *src);
FontInfoResource();
- FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, byte fontFlags,
- FontJustify justify, int fontSaveBack, const Common::Point &pos, int justifyWidth,
- int justifyHeight, const Common::Point &shadow, int foreColor, int backColor,
+ FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, byte fontFlags,
+ FontJustify justify, int fontSaveBack, const Common::Point &pos, int justifyWidth,
+ int justifyHeight, const Common::Point &shadow, int foreColor, int backColor,
int shadowColor);
};
diff --git a/engines/voyeur/files_threads.cpp b/engines/voyeur/files_threads.cpp
index 700944f7ef..0615c67ba0 100644
--- a/engines/voyeur/files_threads.cpp
+++ b/engines/voyeur/files_threads.cpp
@@ -97,7 +97,7 @@ void ThreadResource::unloadAStack(int stackId) {
}
bool ThreadResource::doState() {
- if (!getStateInfo())
+ if (!getStateInfo())
return false;
getButtonsFlags();
@@ -122,7 +122,7 @@ bool ThreadResource::getStateInfo() {
uint32 fld = READ_LE_UINT32(_ctlPtr + 2);
fld += _stateId << 3;
_nextStateId = READ_LE_UINT32(_ctlPtr + fld + 4);
-
+
fld = READ_LE_UINT32(_ctlPtr + fld);
byte *baseP = _ctlPtr + fld;
_stateCount = READ_LE_UINT16(baseP);
@@ -133,7 +133,7 @@ bool ThreadResource::getStateInfo() {
_playCommandsPtr += (READ_LE_UINT32(baseP + 6) / 2) << 1;
_threadInfoPtr = baseP + 10;
-
+
getButtonsText();
return true;
}
@@ -146,7 +146,7 @@ byte *ThreadResource::getDataOffset() {
void ThreadResource::getButtonsText() {
int idx = 0;
-
+
for (const byte *p = _threadInfoPtr; *p != 0x49; p = getNextRecord(p)) {
if (*p == 0xC0) {
++p;
@@ -162,7 +162,7 @@ void ThreadResource::getButtonsText() {
void ThreadResource::getButtonsFlags() {
int idx = 0;
-
+
for (const byte *p = _threadInfoPtr; *p != 0x49; p = getNextRecord(p)) {
if (*p == 0xC0) {
if (*++p & 0x20)
@@ -379,9 +379,9 @@ void ThreadResource::parsePlayCommands() {
_vm->_eventsManager->incrementTime(1);
_vm->_audioVideoId = -1;
parseIndex = 999;
- }
- }
-
+ }
+ }
+
dataP += 8;
break;
@@ -408,7 +408,7 @@ void ThreadResource::parsePlayCommands() {
_vm->_voy->_eventFlags |= EVTFLAG_TIME_DISABLED;
_vm->_voy->addVideoEventEnd();
_vm->_eventsManager->incrementTime(1);
-
+
_vm->_audioVideoId = -1;
_vm->_playStampGroupId = -1;
@@ -494,7 +494,7 @@ void ThreadResource::parsePlayCommands() {
_vm->_audioVideoId = -1;
parseIndex = 999;
}
- break;
+ break;
case 5:
// Check whether transition to a given time period is allowed, and
@@ -587,8 +587,8 @@ void ThreadResource::parsePlayCommands() {
case 10:
// Pick the person who is to die, during startup
if (_vm->_iForceDeath == -1) {
- // No specific person has been preset to be killed, so pick one randomly.
- // The loop below was used because the victim was persisted from the previous
+ // No specific person has been preset to be killed, so pick one randomly.
+ // The loop below was used because the victim was persisted from the previous
// play-through, so it ensured that a different victim is picked.
int randomVal;
do {
@@ -663,7 +663,7 @@ void ThreadResource::parsePlayCommands() {
if (v2 == 0 || _vm->_controlPtr->_state->_victimIndex == v2)
_vm->_voy->_murderThreshold = v3;
-
+
dataP += 4;
break;
@@ -819,7 +819,7 @@ const byte *ThreadResource::cardPerform(const byte *card) {
case 24:
case 27:
case 28:
- subId -= 3;
+ subId -= 3;
// Deliberate fall-through
case 21:
@@ -858,13 +858,13 @@ const byte *ThreadResource::cardPerform(const byte *card) {
++count;
}
}
-
+
++card;
} else {
if (cardPerform2(card, id)) {
card += subId;
card = cardPerform(card);
- while (*card++ != 61) ;
+ while (*card++ != 61) ;
} else {
card += subId;
while (*card != 61 && *card != 29)
@@ -878,7 +878,7 @@ const byte *ThreadResource::cardPerform(const byte *card) {
assert(bVal < 8);
card += 6;
break;
-
+
case 45:
_newStateId = _nextStateId;
_newStackId = _stackId;
@@ -929,12 +929,12 @@ bool ThreadResource::cardPerform2(const byte *pSrc, int cardCmdId) {
return vLong != vLong2;
case 25:
- vLong = _vm->_controlPtr->_state->_vals[*pSrc];
+ vLong = _vm->_controlPtr->_state->_vals[*pSrc];
vLong2 = (int32)READ_LE_UINT32(pSrc + 1);
return vLong < vLong2;
case 26:
- vLong = _vm->_controlPtr->_state->_vals[*pSrc];
+ vLong = _vm->_controlPtr->_state->_vals[*pSrc];
vLong2 = (int32)READ_LE_UINT32(pSrc + 1);
return vLong > vLong2;
@@ -951,13 +951,13 @@ bool ThreadResource::cardPerform2(const byte *pSrc, int cardCmdId) {
default:
return false;
}
-}
+}
int ThreadResource::doApt() {
loadTheApt();
_vm->_currentVocId = 151;
- _vm->_voy->_viewBounds = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._rectResource;
+ _vm->_voy->_viewBounds = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._rectResource;
Common::Array<RectEntry> &hotspots = _vm->_bVoy->boltEntry(
_vm->_playStampGroupId + 1)._rectResource->_entries;
_vm->_eventsManager->getMouseInfo();
@@ -1007,8 +1007,11 @@ int ThreadResource::doApt() {
if (_vm->_loadGameSlot != -1) {
// Load a savegame
- _vm->loadGame(_vm->_loadGameSlot);
+ int slot = _vm->_loadGameSlot;
_vm->_loadGameSlot = -1;
+ _vm->loadGame(slot);
+
+ _vm->_eventsManager->showCursor();
}
_vm->_eventsManager->getMouseInfo();
@@ -1039,7 +1042,7 @@ int ThreadResource::doApt() {
hotspotId = 5;
// Draw the text description for the highlighted hotspot
- pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId +
+ pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId +
hotspotId + 6)._picResource;
_vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort,
Common::Point(106, 200));
@@ -1101,10 +1104,10 @@ int ThreadResource::doApt() {
void ThreadResource::doRoom() {
VoyeurEngine &vm = *_vm;
SVoy voy = *vm._voy;
-
+
vm.makeViewFinderP();
voy._fadingType = 0;
-
+
if (!vm._bVoy->getBoltGroup(vm._playStampGroupId))
return;
@@ -1116,7 +1119,7 @@ void ThreadResource::doRoom() {
voy._fadingStep1 = 2;
voy._fadingStep2 = 0;
voy._fadingType = 1;
-
+
Common::Array<RectEntry> &hotspots = vm._bVoy->boltEntry(vm._playStampGroupId + 4)._rectResource->_entries;
int hotspotId = -1;
@@ -1214,7 +1217,7 @@ void ThreadResource::doRoom() {
vm._eventsManager->_mouseClicked = false;
vm._eventsManager->startCursorBlink();
- int totalChars = vm.doComputerText(9999);
+ int totalChars = vm.doComputerText(9999);
if (totalChars)
vm._voy->addComputerEventEnd(totalChars);
@@ -1345,12 +1348,12 @@ int ThreadResource::doInterface() {
Common::String fname = _vm->_soundManager->getVOCFileName(_vm->_currentVocId);
_vm->_soundManager->startVOCPlay(fname);
_vm->_eventsManager->getMouseInfo();
-
+
_vm->_graphicsManager->setColor(240, 220, 220, 220);
_vm->_eventsManager->_intPtr._hasPalette = true;
_vm->_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
- // Set the cusor
+ // Set the cusor
PictureResource *crosshairsCursor = _vm->_bVoy->boltEntry(0x112)._picResource;
PictureResource *eyeCursor = _vm->_bVoy->boltEntry(0x113)._picResource;
PictureResource *listenCursor = _vm->_bVoy->boltEntry(0x114)._picResource;
@@ -1382,7 +1385,7 @@ int ThreadResource::doInterface() {
if (!mansionViewBounds.contains(pt))
pt = Common::Point(-1, -1);
else
- pt = _vm->_mansionViewPos +
+ pt = _vm->_mansionViewPos +
Common::Point(pt.x - MANSION_VIEW_X, pt.y - MANSION_VIEW_Y);
regionIndex = -1;
@@ -1420,20 +1423,20 @@ int ThreadResource::doInterface() {
// Regularly update the time display
if (_vm->_voy->_RTANum & 2) {
- _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+ _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
_vm->_gameMinute / 10, Common::Point(190, 25));
- _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+ _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
_vm->_gameMinute % 10, Common::Point(201, 25));
if (_vm->_voy->_RTANum & 4) {
int v = _vm->_gameHour / 10;
- _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+ _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
v == 0 ? 10 : v, Common::Point(161, 25));
- _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+ _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
_vm->_gameHour % 10, Common::Point(172, 25));
pic = _vm->_bVoy->boltEntry(_vm->_voy->_isAM ? 272 : 273)._picResource;
- _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort,
+ _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort,
Common::Point(215, 27));
}
}
@@ -1462,7 +1465,7 @@ int ThreadResource::doInterface() {
_vm->makeViewFinder();
_vm->initIFace();
-
+
hotspots = &_vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._rectResource->_entries;
_vm->_eventsManager->getMouseInfo();
@@ -1471,7 +1474,7 @@ int ThreadResource::doInterface() {
_vm->_eventsManager->_intPtr._flashTimer = 0;
}
}
- } while (!_vm->_eventsManager->_rightClick && !_vm->shouldQuit() &&
+ } while (!_vm->_eventsManager->_rightClick && !_vm->shouldQuit() &&
(!_vm->_eventsManager->_leftClick || regionIndex == -1));
_vm->_eventsManager->hideCursor();
@@ -1596,7 +1599,9 @@ void ThreadResource::loadTheApt() {
_vm->_voy->_aptLoadMode = -1;
if (_vm->_voy->_aptLoadMode != -1) {
- doAptAnim(1);
+ if (_vm->_loadGameSlot != -1)
+ doAptAnim(1);
+
_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId);
_vm->_voy->_aptLoadMode = -1;
_vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(
@@ -1612,7 +1617,7 @@ void ThreadResource::loadTheApt() {
}
CMapResource *pal = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 4)._cMapResource;
- pal->_steps = 1;
+ pal->_steps = 1;
pal->startFade();
_vm->flipPageAndWaitForFade();
}
@@ -1715,7 +1720,7 @@ void ThreadResource::doAptAnim(int mode) {
void ThreadResource::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(_aptPos.x);
s.syncAsSint16LE(_aptPos.y);
-
+
int stateId = _stateId;
int stackId = _stackId;
s.syncAsSint16LE(stateId);
diff --git a/engines/voyeur/graphics.cpp b/engines/voyeur/graphics.cpp
index f756b9cc85..68a30e41f4 100644
--- a/engines/voyeur/graphics.cpp
+++ b/engines/voyeur/graphics.cpp
@@ -97,9 +97,9 @@ void GraphicsManager::restoreMCGASaveRect(ViewPortResource *viewPort) {
restoreBack(*viewPort->_rectListPtr[1], viewPort->_rectListCount[1], viewPort->_pages[0],
viewPort->_pages[1]);
-
+
int count = viewPort->_rectListCount[0];
- restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0],
+ restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0],
viewPort->_activePage, viewPort->_currentPic);
SWAP(viewPort->_rectListPtr[0], viewPort->_rectListPtr[1]);
@@ -150,7 +150,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
destPic = (PictureResource *)destDisplay;
}
- Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left,
+ Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left,
initialOffset.y + srcPic->_bounds.top - destPic->_bounds.top);
width1 = width2 = srcPic->_bounds.width();
height1 = srcPic->_bounds.height();
@@ -178,7 +178,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
srcOffset -= tmpHeight * width2;
height1 += tmpHeight;
offset.y = newBounds.top;
-
+
if (height1 <= 0)
return;
@@ -258,7 +258,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
for (uint idx = 0; idx < srcPic->_maskData; ++idx) {
if (imageDataShift < 4)
++imageDataShift;
- }
+ }
} else {
srcImgData = srcPic->_imgData;
destImgData = destPic->_imgData;
@@ -367,7 +367,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
width2 = srcPic->_bounds.width();
height1 = tmpHeight + height1;
-
+
for (int yp = 0; yp < height1; ++yp) {
runLength = 0;
@@ -509,7 +509,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
if (srcFlags & DISPFLAG_2) {
if (!(srcFlags & DISPFLAG_8)) {
srcP = srcImgData + srcOffset;
-
+
if (destFlags & DISPFLAG_8) {
// loc_272C3
error("TODO: sDrawPic variation");
@@ -786,7 +786,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
} else {
// loc_271F0
srcP = srcImgData;
-
+
if (isClipped) {
// loc_2700A
tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
@@ -886,7 +886,7 @@ void GraphicsManager::flipPage() {
for (uint idx = 0; idx < viewPorts.size(); ++idx) {
if (viewPorts[idx]->_flags & DISPFLAG_20) {
- if ((viewPorts[idx]->_flags & (DISPFLAG_8 || DISPFLAG_1))
+ if ((viewPorts[idx]->_flags & (DISPFLAG_8 || DISPFLAG_1))
== (DISPFLAG_8 || DISPFLAG_1)) {
if (_planeSelect == idx)
sDisplayPic(viewPorts[idx]->_currentPic);
@@ -992,7 +992,7 @@ void GraphicsManager::screenReset() {
_backgroundPage = NULL;
_vPort->setupViewPort(NULL);
- fillPic(_vPort, 0);
+ fillPic(_vPort, 0);
_vm->flipPageAndWait();
}
diff --git a/engines/voyeur/graphics.h b/engines/voyeur/graphics.h
index 221d31061d..e4d0b38650 100644
--- a/engines/voyeur/graphics.h
+++ b/engines/voyeur/graphics.h
@@ -54,14 +54,13 @@ public:
DrawInfo(int penColor, const Common::Point &pos);
};
-typedef void (GraphicsManager::*GraphicMethodPtr)();
+typedef void (GraphicsManager::*GraphicMethodPtr)();
typedef void (GraphicsManager::*ViewPortSetupPtr)(ViewPortResource *);
typedef void (GraphicsManager::*ViewPortAddPtr)(ViewPortResource *, int idx, const Common::Rect &bounds);
typedef void (GraphicsManager::*ViewPortRestorePtr)(ViewPortResource *);
class GraphicsManager {
public:
- VoyeurEngine *_vm;
byte _VGAColors[PALETTE_SIZE];
PictureResource *_backgroundPage;
int _SVGAMode;
@@ -77,6 +76,8 @@ public:
DrawInfo *_drawPtr;
DrawInfo _defaultDrawInfo;
private:
+ VoyeurEngine *_vm;
+
void restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
PictureResource *srcPic, PictureResource *destPic);
public:
@@ -86,7 +87,7 @@ public:
void sInitGraphics();
void setupMCGASaveRect(ViewPortResource *viewPort);
- void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
+ void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
void restoreMCGASaveRect(ViewPortResource *viewPort);
void addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
@@ -101,7 +102,7 @@ public:
void resetPalette();
void setColor(int idx, byte r, byte g, byte b);
void setOneColor(int idx, byte r, byte g, byte b);
- void setColors(int start, int count, const byte *pal);
+ void setColors(int start, int count, const byte *pal);
void screenReset();
void fadeDownICF1(int steps);
void fadeUpICF1(int steps = 0);
diff --git a/engines/voyeur/sound.cpp b/engines/voyeur/sound.cpp
index 26145bd743..c0e5a043cd 100644
--- a/engines/voyeur/sound.cpp
+++ b/engines/voyeur/sound.cpp
@@ -62,7 +62,7 @@ void SoundManager::startVOCPlay(const Common::String &filename) {
if (!f.open(filename))
error("Could not find voc file - %s", filename.c_str());
- Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(f.readStream(f.size()),
+ Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(f.readStream(f.size()),
Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream);
diff --git a/engines/voyeur/staticres.cpp b/engines/voyeur/staticres.cpp
index 7016793ddc..372da508f1 100644
--- a/engines/voyeur/staticres.cpp
+++ b/engines/voyeur/staticres.cpp
@@ -43,7 +43,7 @@ const int RESOLVE_TABLE[] = {
0x7500
};
-const int LEVEL_H[] = {
+const int LEVEL_H[] = {
4, 7, 7, 8, 9, 10, 2, 2, 4, 8, 8, 9, 9, 10, 10, 11, 11
};
@@ -58,40 +58,40 @@ const int BLIND_TABLE[] = {
};
const int COMPUTER_SCREEN_TABLE[] = {
- 269, 128, 307, 163,
- 269, 128, 307, 163,
- 68, 79, 98, 102,
- 68, 79, 98, 102,
- 68, 79, 98, 102,
+ 269, 128, 307, 163,
+ 269, 128, 307, 163,
+ 68, 79, 98, 102,
+ 68, 79, 98, 102,
+ 68, 79, 98, 102,
+ 68, 79, 98, 102,
+ 248, 138, 291, 163,
+ 83, 132, 143, 156,
+ 248, 138, 291, 163,
+ 83, 132, 143, 156,
+ 83, 132, 143, 156,
+ 248, 138, 291, 163,
68, 79, 98, 102,
- 248, 138, 291, 163,
- 83, 132, 143, 156,
- 248, 138, 291, 163,
- 83, 132, 143, 156,
- 83, 132, 143, 156,
- 248, 138, 291, 163,
- 68, 79, 98, 102,
68, 79, 98, 102
};
const char *const SZ_FILENAMES[] = {
- "A2110100", nullptr, "A2300100", nullptr, "B1220100", nullptr, "C1220100", nullptr,
- "C1290100", nullptr, "D1220100", nullptr, "D1270100", nullptr, "E1210100", nullptr,
+ "A2110100", nullptr, "A2300100", nullptr, "B1220100", nullptr, "C1220100", nullptr,
+ "C1290100", nullptr, "D1220100", nullptr, "D1270100", nullptr, "E1210100", nullptr,
"E1260100", nullptr, "E1280100", nullptr, "E1325100", nullptr, "F1200100", nullptr,
- "G1250100", nullptr, "G1260100", nullptr, "H1200100", nullptr, "H1230100", nullptr,
- "H1310100", nullptr, "I1300100", nullptr, "J1220100", nullptr, "J1230100", nullptr,
+ "G1250100", nullptr, "G1260100", nullptr, "H1200100", nullptr, "H1230100", nullptr,
+ "H1310100", nullptr, "I1300100", nullptr, "J1220100", nullptr, "J1230100", nullptr,
"J1320100", nullptr, "K1260100", nullptr, "K1280100", nullptr, "K1325100", nullptr,
- "L1210100", nullptr, "L1280100", nullptr, "L1290100", nullptr, "L1300100", nullptr,
- "L1310100", nullptr, "M1260100", nullptr, "M1310100", nullptr, "N1210100", nullptr,
+ "L1210100", nullptr, "L1280100", nullptr, "L1290100", nullptr, "L1300100", nullptr,
+ "L1310100", nullptr, "M1260100", nullptr, "M1310100", nullptr, "N1210100", nullptr,
"N1225100", nullptr, "N1275510", nullptr, "N1280510", nullptr, "N1325100", nullptr,
- "O1230100", nullptr, "O1260100", nullptr, "O1260520", nullptr, "O1280100", nullptr,
- "O1325540", nullptr, "P1276710", nullptr, "P1280540", nullptr, "P1280740", nullptr,
+ "O1230100", nullptr, "O1260100", nullptr, "O1260520", nullptr, "O1280100", nullptr,
+ "O1325540", nullptr, "P1276710", nullptr, "P1280540", nullptr, "P1280740", nullptr,
"P1290510", nullptr, "P1325100", nullptr, "P1325300", nullptr, "P1325520", nullptr,
- "Q1230100", nullptr, "Q1240530", nullptr, "Q1240730", nullptr, "Q1260100", nullptr,
- "Q1260520", nullptr, "Q1260720", nullptr, "Q1325100", nullptr, "R1280540", nullptr,
+ "Q1230100", nullptr, "Q1240530", nullptr, "Q1240730", nullptr, "Q1260100", nullptr,
+ "Q1260520", nullptr, "Q1260720", nullptr, "Q1325100", nullptr, "R1280540", nullptr,
"Z1110510", nullptr, "Z1110520", nullptr, "Z1110530", nullptr, "Z1110540", nullptr,
- "Z1110545", nullptr, "Z2320100", nullptr, "Z2905300", nullptr, "Z3110100", nullptr,
- "Z3115510", nullptr, "Z3115520", nullptr, "Z3115530", nullptr, "Z3115540", nullptr,
+ "Z1110545", nullptr, "Z2320100", nullptr, "Z2905300", nullptr, "Z3110100", nullptr,
+ "Z3115510", nullptr, "Z3115520", nullptr, "Z3115530", nullptr, "Z3115540", nullptr,
"Z4915100", nullptr, "Z4915200", nullptr, "Z4915300",
nullptr, nullptr, nullptr, nullptr, nullptr,
"MMARG", "MZACK", "MREED", "MJESSI", "MCHLOE", "MCAMERA", "MENDCRED",
diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp
index 9843930bd3..dad634c9bb 100644
--- a/engines/voyeur/voyeur.cpp
+++ b/engines/voyeur/voyeur.cpp
@@ -37,7 +37,7 @@ VoyeurEngine *g_vm;
VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc) : Engine(syst),
_gameDescription(gameDesc), _randomSource("Voyeur"),
- _defaultFontInfo(3, 0xff, 0xff, 0, 0, ALIGN_LEFT, 0, Common::Point(), 1, 1,
+ _defaultFontInfo(3, 0xff, 0xff, 0, 0, ALIGN_LEFT, 0, Common::Point(), 1, 1,
Common::Point(1, 1), 1, 0, 0) {
_debugger = nullptr;
_eventsManager = nullptr;
@@ -82,6 +82,8 @@ VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc)
_glGoStack = -1;
_resolvePtr = nullptr;
_mainThread = nullptr;
+
+ centerMansionView();
}
VoyeurEngine::~VoyeurEngine() {
@@ -158,7 +160,7 @@ void VoyeurEngine::initInput() {
bool VoyeurEngine::doHeadTitle() {
// char dest[144];
-
+
_eventsManager->startMainClockInt();
if (_loadGameSlot == -1) {
@@ -205,7 +207,7 @@ bool VoyeurEngine::doHeadTitle() {
_voy->addEvent(18, 7, EVTYPE_VIDEO, 40, 0, 998, -1);
_voy->addEvent(18, 8, EVTYPE_VIDEO, 43, 0, 998, -1);
_voy->addEvent(19, 1, EVTYPE_AUDIO, 20, 0, 998, -1);
- }
+ }
}
_voy->_aptLoadMode = 140;
@@ -271,7 +273,7 @@ bool VoyeurEngine::doLock() {
_graphicsManager->setColor(2, 96, 96, 96);
_graphicsManager->setColor(3, 160, 160, 160);
_graphicsManager->setColor(4, 224, 224, 224);
-
+
// Set up the cursor
_eventsManager->setCursor(cursorPic);
_eventsManager->showCursor();
@@ -464,11 +466,11 @@ void VoyeurEngine::doOpening() {
_eventsManager->_intPtr._hasPalette = true;
_graphicsManager->_vPort->setupViewPort();
flipPageAndWait();
-
+
RL2Decoder decoder;
decoder.loadRL2File("a2300100.rl2", false);
decoder.start();
-
+
while (!shouldQuit() && !decoder.endOfVideo() && !_eventsManager->_mouseClicked) {
if (decoder.hasDirtyPalette()) {
const byte *palette = decoder.getPalette();
@@ -487,7 +489,7 @@ void VoyeurEngine::doOpening() {
textPic = _bVoy->boltEntry(frameIndex / 2 + 0x202)._picResource;
textPos = Common::Point(READ_LE_UINT16(xyTable + frameIndex * 2),
READ_LE_UINT16(xyTable + (frameIndex + 1) * 2));
-
+
creditShow = false;
} else {
textPic = nullptr;
@@ -500,8 +502,9 @@ void VoyeurEngine::doOpening() {
if (textPic) {
_graphicsManager->sDrawPic(textPic, _graphicsManager->_vPort, textPos);
- flipPageAndWait();
}
+
+ flipPageAndWait();
}
_eventsManager->getMouseInfo();
@@ -553,6 +556,7 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
PictureResource *pic = NULL;
if (videoId == 42) {
+ _bVoy->getBoltGroup(0xE00);
_eventsManager->_videoDead = 0;
pic = _bVoy->boltEntry(0xE00 + _eventsManager->_videoDead)._picResource;
}
@@ -560,9 +564,9 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
RL2Decoder decoder;
decoder.loadVideo(videoId);
- decoder.seek(Audio::Timestamp(_voy->_vocSecondsOffset * 1000));
+ decoder.seek(Audio::Timestamp(_voy->_vocSecondsOffset * 1000));
decoder.start();
- int endFrame = decoder.getCurFrame() + totalFrames;
+ int endFrame = decoder.getCurFrame() + totalFrames;
_eventsManager->getMouseInfo();
_eventsManager->startCursorBlink();
@@ -599,13 +603,16 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
pic->_imgData = imgData;
_voy->_eventFlags &= ~EVTFLAG_8;
}
+
+ if (videoId == 42)
+ _bVoy->freeBoltGroup(0xE00);
}
void VoyeurEngine::playAudio(int audioId) {
_bVoy->getBoltGroup(0x7F00);
- _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 +
+ _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 +
BLIND_TABLE[audioId] * 2)._picResource;
- _graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 +
+ _graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 +
BLIND_TABLE[audioId] * 2)._cMapResource;
_graphicsManager->_vPort->setupViewPort();
@@ -620,7 +627,7 @@ void VoyeurEngine::playAudio(int audioId) {
_voy->_eventFlags |= EVTFLAG_RECORDING;
_eventsManager->startCursorBlink();
- while (!shouldQuit() && !_eventsManager->_mouseClicked &&
+ while (!shouldQuit() && !_eventsManager->_mouseClicked &&
_soundManager->getVOCStatus())
_eventsManager->delayClick(1);
@@ -657,7 +664,7 @@ void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::St
fi._justifyHeight = 120;
_graphicsManager->_vPort->drawText(time);
-
+
if (!location.empty()) {
fi._pos = Common::Point(0, 138);
fi._justify = ALIGN_CENTER;
@@ -723,7 +730,7 @@ void VoyeurEngine::showEndingNews() {
_soundManager->startVOCPlay(fname);
_eventsManager->getMouseInfo();
- while (!shouldQuit() && !_eventsManager->_mouseClicked &&
+ while (!shouldQuit() && !_eventsManager->_mouseClicked &&
_soundManager->getVOCStatus()) {
_eventsManager->delay(1);
_eventsManager->getMouseInfo();
@@ -901,7 +908,7 @@ void VoyeurSavegameHeader::write(Common::OutSaveFile *f, VoyeurEngine *vm, const
// Create a thumbnail and save it
Graphics::Surface *thumb = new Graphics::Surface();
- ::createThumbnail(thumb, (byte *)vm->_graphicsManager->_screenSurface.getPixels(),
+ ::createThumbnail(thumb, (byte *)vm->_graphicsManager->_screenSurface.getPixels(),
SCREEN_WIDTH, SCREEN_HEIGHT, vm->_graphicsManager->_VGAColors);
Graphics::saveThumbnail(*f, *thumb);
thumb->free();
diff --git a/engines/voyeur/voyeur.h b/engines/voyeur/voyeur.h
index a35473ba93..e0bb734fa8 100644
--- a/engines/voyeur/voyeur.h
+++ b/engines/voyeur/voyeur.h
@@ -150,6 +150,11 @@ private:
* Synchronizes the game data
*/
void synchronize(Common::Serializer &s);
+
+ /**
+ * Resets the mansion view position
+ */
+ void centerMansionView();
protected:
// Engine APIs
virtual Common::Error run();
diff --git a/engines/voyeur/voyeur_game.cpp b/engines/voyeur/voyeur_game.cpp
index a6564c32ba..c7df924f7e 100644
--- a/engines/voyeur/voyeur_game.cpp
+++ b/engines/voyeur/voyeur_game.cpp
@@ -33,7 +33,7 @@ void VoyeurEngine::playStamp() {
_stampLibPtr->getBoltGroup(0);
_controlPtr->_state = _stampLibPtr->boltEntry(_controlPtr->_stateId >> 16)._stateResource;
assert(_controlPtr->_state);
-
+
_resolvePtr = &RESOLVE_TABLE[0];
initStamp();
@@ -57,11 +57,11 @@ void VoyeurEngine::playStamp() {
_mainThread->parsePlayCommands();
bool flag = breakFlag = (_voy->_eventFlags & EVTFLAG_2) != 0;
-
+
switch (_voy->_playStampMode) {
case 5:
buttonId = _mainThread->doInterface();
-
+
if (buttonId == -2) {
switch (_mainThread->doApt()) {
case 0:
@@ -110,7 +110,7 @@ void VoyeurEngine::playStamp() {
case 16:
_voy->_transitionId = 17;
buttonId = _mainThread->doApt();
-
+
switch (buttonId) {
case 1:
_mainThread->chooseSTAMPButton(22);
@@ -234,19 +234,19 @@ void VoyeurEngine::closeStamp() {
void VoyeurEngine::doTailTitle() {
_graphicsManager->_vPort->setupViewPort(NULL);
_graphicsManager->screenReset();
-
+
if (_bVoy->getBoltGroup(0x600)) {
RL2Decoder decoder;
decoder.loadRL2File("a1100200.rl2", false);
decoder.start();
decoder.play(this);
-
+
if (!shouldQuit() && !_eventsManager->_mouseClicked) {
doClosingCredits();
if (!shouldQuit() && !_eventsManager->_mouseClicked) {
_graphicsManager->screenReset();
-
+
PictureResource *pic = _bVoy->boltEntry(0x602)._picResource;
CMapResource *pal = _bVoy->boltEntry(0x603)._cMapResource;
@@ -315,7 +315,7 @@ void VoyeurEngine::doClosingCredits() {
_graphicsManager->_vPort->drawText(msg);
msg += strlen(msg) + 1;
}
-
+
if (flags & 0x40) {
fi._foreColor = 2;
fi._curFont = _bVoy->boltEntry(0x400)._fontResource;
@@ -345,7 +345,7 @@ void VoyeurEngine::doClosingCredits() {
fi._justifyHeight = 240;
fi._pos = Common::Point(198, READ_LE_UINT16(entry));
- _graphicsManager->_vPort->drawText(msg);
+ _graphicsManager->_vPort->drawText(msg);
msg += strlen(msg) + 1;
}
@@ -500,7 +500,7 @@ void VoyeurEngine::reviewTape() {
Common::String msg = _eventsManager->getEvidString(eventNum);
_graphicsManager->_backgroundPage->drawText(msg);
-
+
yp += 15;
}
@@ -527,7 +527,7 @@ void VoyeurEngine::reviewTape() {
break;
}
}
-
+
pt = _eventsManager->getMousePos();
if (tempPos.x >= 68 && tempPos.x <= 277 && tempPos.y >= 31 && tempPos.y <= 154) {
tempPos.y -= 2;
@@ -545,7 +545,7 @@ void VoyeurEngine::reviewTape() {
flipPageAndWait();
_graphicsManager->_drawPtr->_penColor = 0;
- _graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
+ _graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
_graphicsManager->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
int yp = 45;
@@ -642,7 +642,7 @@ void VoyeurEngine::reviewTape() {
foundIndex = -1;
_eventsManager->_rightClick = 0;
}
-
+
if (_eventsManager->_rightClick)
foundIndex = 0;
@@ -652,7 +652,7 @@ void VoyeurEngine::reviewTape() {
_voy->_fadingType = 0;
_voy->_viewBounds = nullptr;
_graphicsManager->_vPort->setupViewPort(NULL);
-
+
if (_currentVocId != -1) {
_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
_soundManager->stopVOCPlay();
@@ -693,7 +693,7 @@ void VoyeurEngine::reviewTape() {
uint32 secondsDuration = e._computerOff;
_eventsManager->getMouseInfo();
- while (!_eventsManager->_mouseClicked && _soundManager->getVOCStatus() &&
+ while (!_eventsManager->_mouseClicked && _soundManager->getVOCStatus() &&
_soundManager->getVOCFrame() < secondsDuration) {
_eventsManager->getMouseInfo();
_eventsManager->delay(10);
@@ -707,7 +707,7 @@ void VoyeurEngine::reviewTape() {
case EVTYPE_EVID:
_voy->reviewAnEvidEvent(eventIndex);
-
+
_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
_soundManager->stopVOCPlay();
_bVoy->getBoltGroup(0x900);
@@ -715,7 +715,7 @@ void VoyeurEngine::reviewTape() {
case EVTYPE_COMPUTER:
_voy->reviewComputerEvent(eventIndex);
-
+
_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
_soundManager->stopVOCPlay();
_bVoy->getBoltGroup(0x900);
@@ -863,7 +863,7 @@ bool VoyeurEngine::checkForIncriminate() {
for (int idx = 0; idx < _voy->_eventCount; ++idx) {
VoyeurEvent &evt = _voy->_events[idx];
-
+
if (evt._type == EVTYPE_VIDEO) {
if (evt._audioVideoId == 44 && evt._computerOn <= 40 &&
(evt._computerOff + evt._computerOn) >= 70) {
@@ -908,7 +908,7 @@ void VoyeurEngine::playAVideoEvent(int eventIndex) {
_voy->_vocSecondsOffset = evt._computerOn;
_eventsManager->_videoDead = evt._dead;
_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
-
+
playAVideoDuration(_audioVideoId, evt._computerOff);
_voy->_eventFlags |= EVTFLAG_TIME_DISABLED;
@@ -929,7 +929,7 @@ void VoyeurEngine::playAVideoEvent(int eventIndex) {
int VoyeurEngine::getChooseButton() {
int prevIndex = -2;
- Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(_playStampGroupId
+ Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(_playStampGroupId
+ 6)._rectResource->_entries;
int selectedIndex = -1;
@@ -949,7 +949,7 @@ int VoyeurEngine::getChooseButton() {
_eventsManager->getMouseInfo();
selectedIndex = -1;
Common::Point pt = _eventsManager->getMousePos();
-
+
for (uint idx = 0; idx < hotspots.size(); ++idx) {
if (hotspots[idx].contains(pt)) {
if (!_voy->_victimMurdered || ((int)idx + 1) != _controlPtr->_state->_victimIndex) {
@@ -984,7 +984,7 @@ int VoyeurEngine::getChooseButton() {
void VoyeurEngine::makeViewFinder() {
_graphicsManager->_backgroundPage = _bVoy->boltEntry(0x103)._picResource;
- _graphicsManager->sDrawPic(_graphicsManager->_backgroundPage,
+ _graphicsManager->sDrawPic(_graphicsManager->_backgroundPage,
_graphicsManager->_vPort, Common::Point(0, 0));
CMapResource *pal = _bVoy->boltEntry(0x104)._cMapResource;
@@ -1063,11 +1063,9 @@ void VoyeurEngine::initIFace() {
CMapResource *pal = _bVoy->boltEntry(_playStampGroupId + 2)._cMapResource;
pal->startFade();
- // Start the mansion off centered
- _mansionViewPos = Common::Point((MANSION_MAX_X - MANSION_VIEW_WIDTH) / 2,
- (MANSION_MAX_Y - MANSION_VIEW_HEIGHT) / 2);
+ // Reset the mansion view off to it's prior position (if any)
doScroll(_mansionViewPos);
-
+
_voy->_viewBounds = _bVoy->boltEntry(_playStampGroupId)._rectResource;
// Show the cursor using ScummVM functionality
@@ -1138,6 +1136,7 @@ void VoyeurEngine::checkTransition() {
}
_checkTransitionId = _voy->_transitionId;
+ centerMansionView();
}
}
@@ -1150,7 +1149,7 @@ Common::String VoyeurEngine::getDayName() {
case 3:
case 4:
return SATURDAY;
- case 17:
+ case 17:
return MONDAY;
default:
return SUNDAY;
@@ -1277,7 +1276,7 @@ void VoyeurEngine::doTimeBar() {
if (_voy->_RTVLimit > 0) {
if (_voy->_RTVNum > _voy->_RTVLimit || _voy->_RTVNum < 0)
_voy->_RTVNum = _voy->_RTVLimit - 1;
-
+
_timeBarVal = _voy->_RTVNum;
int height = ((_voy->_RTVLimit - _voy->_RTVNum) * 59) / _voy->_RTVLimit;
int fullHeight = MAX(151 - height, 93);
@@ -1308,14 +1307,14 @@ void VoyeurEngine::flashTimeBar() {
_graphicsManager->setColor(240, 220, 20, 20);
else
_graphicsManager->setColor(240, 220, 220, 220);
-
+
_eventsManager->_intPtr._hasPalette = true;
_flashTimeFlag = !_flashTimeFlag;
}
}
void VoyeurEngine::checkPhoneCall() {
- if ((_voy->_RTVLimit - _voy->_RTVNum) >= 36 && _voy->_totalPhoneCalls < 5 &&
+ if ((_voy->_RTVLimit - _voy->_RTVNum) >= 36 && _voy->_totalPhoneCalls < 5 &&
_currentVocId <= 151 && _currentVocId > 146) {
if ((_voy->_switchBGNum < _checkPhoneVal || _checkPhoneVal > 180) &&
!_soundManager->getVOCStatus()) {
@@ -1361,9 +1360,9 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) {
if (count > 0) {
for (int idx = 1; idx <= count; ++idx) {
- _voy->_evPicPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 +
+ _voy->_evPicPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 +
(evidId + idx) * 2)._picResource;
- _voy->_evCmPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 +
+ _voy->_evCmPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 +
(evidId + idx) * 2 + 1)._cMapResource;
}
}
@@ -1394,7 +1393,7 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) {
break;
if (count == 0 || evidIdx >= eventId)
continue;
-
+
pic = _voy->_evPicPtrs[arrIndex];
_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort,
Common::Point((384 - pic->_bounds.width()) / 2,
@@ -1420,4 +1419,9 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) {
}
}
+void VoyeurEngine::centerMansionView() {
+ _mansionViewPos = Common::Point((MANSION_MAX_X - MANSION_VIEW_WIDTH) / 2,
+ (MANSION_MAX_Y - MANSION_VIEW_HEIGHT) / 2);
+}
+
} // End of namespace Voyeur
diff --git a/engines/wintermute/POTFILES b/engines/wintermute/POTFILES
new file mode 100644
index 0000000000..e9422415b2
--- /dev/null
+++ b/engines/wintermute/POTFILES
@@ -0,0 +1 @@
+engines/wintermute/detection.cpp
diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp
index 1f78303f52..58684b66a0 100644
--- a/engines/wintermute/base/base_file_manager.cpp
+++ b/engines/wintermute/base/base_file_manager.cpp
@@ -209,10 +209,15 @@ bool BaseFileManager::registerPackages() {
// than the equivalent of using equalsIgnoreCase.
Common::String fileName = fileIt->getName();
fileName.toLowercase();
+ bool searchSignature = false;
- if (!fileName.hasSuffix(".dcp")) {
+ if (!fileName.hasSuffix(".dcp") && !fileName.hasSuffix(".exe")) {
continue;
}
+ if (fileName.hasSuffix(".exe")) {
+ searchSignature = true;
+ }
+
// HACK: for Reversion1, avoid loading xlanguage_pt.dcp from the main folder:
if (_language != Common::PT_BRA && targetName.hasPrefix("reversion1")) {
if (fileName == "xlanguage_pt.dcp") {
@@ -263,7 +268,7 @@ bool BaseFileManager::registerPackages() {
}
}
debugC(kWintermuteDebugFileAccess, "Registering %s %s", fileIt->getPath().c_str(), fileIt->getName().c_str());
- registerPackage((*fileIt));
+ registerPackage((*fileIt), "", searchSignature);
}
}
diff --git a/engines/wintermute/base/base_file_manager.h b/engines/wintermute/base/base_file_manager.h
index 653721c8f5..d953e44704 100644
--- a/engines/wintermute/base/base_file_manager.h
+++ b/engines/wintermute/base/base_file_manager.h
@@ -63,7 +63,6 @@ private:
Common::SeekableReadStream *openFileRaw(const Common::String &filename);
Common::SeekableReadStream *openPkgFile(const Common::String &filename);
Common::FSList _packagePaths;
- bool findPackageSignature(Common::SeekableReadStream *f, uint32 *offset);
bool registerPackage(Common::FSNode package, const Common::String &filename = "", bool searchSignature = false);
bool _detectionMode;
Common::SearchSet _packages;
diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp
index f2c24b8f6a..471185f2d2 100644
--- a/engines/wintermute/base/base_frame.cpp
+++ b/engines/wintermute/base/base_frame.cpp
@@ -76,7 +76,7 @@ BaseFrame::~BaseFrame() {
//////////////////////////////////////////////////////////////////////
-bool BaseFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, bool allFrames, float rotate, TSpriteBlendMode blendMode) {
+bool BaseFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, bool allFrames, float rotate, Graphics::TSpriteBlendMode blendMode) {
bool res;
for (uint32 i = 0; i < _subframes.size(); i++) {
diff --git a/engines/wintermute/base/base_frame.h b/engines/wintermute/base/base_frame.h
index 49a56592bb..ff9e67a166 100644
--- a/engines/wintermute/base/base_frame.h
+++ b/engines/wintermute/base/base_frame.h
@@ -31,6 +31,7 @@
#include "engines/wintermute/base/base_scriptable.h"
#include "engines/wintermute/coll_templ.h"
+#include "graphics/transform_struct.h"
namespace Wintermute {
class BaseSound;
@@ -51,7 +52,7 @@ public:
int32 _moveX;
uint32 _delay;
BaseArray<BaseSubFrame *> _subframes;
- bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, bool allFrames = false, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL);
+ bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, bool allFrames = false, float rotate = 0.0f, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL);
bool loadBuffer(char *buffer, int lifeTime, bool keepLoaded);
BaseFrame(BaseGame *inGame);
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index d37a22e2a6..8df39c825a 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -3110,6 +3110,10 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferUint32(TMEMBER(_autoSaveSlot));
persistMgr->transferBool(TMEMBER(_cursorHidden));
+ if (persistMgr->checkVersion(1, 3, 1)) {
+ _settings->persist(persistMgr);
+ }
+
if (!persistMgr->getIsSaving()) {
_quitting = false;
}
diff --git a/engines/wintermute/base/base_game_settings.cpp b/engines/wintermute/base/base_game_settings.cpp
index 3b54384cc7..61c5894be3 100644
--- a/engines/wintermute/base/base_game_settings.cpp
+++ b/engines/wintermute/base/base_game_settings.cpp
@@ -219,4 +219,8 @@ char *BaseGameSettings::getKeyFromStringTable(const char *str) const {
return _stringTable->getKey(str);
}
+bool BaseGameSettings::persist(BasePersistenceManager *persistMgr) {
+ return _stringTable->persist(persistMgr);
+}
+
} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_game_settings.h b/engines/wintermute/base/base_game_settings.h
index fe0e9907e6..2059cb075e 100644
--- a/engines/wintermute/base/base_game_settings.h
+++ b/engines/wintermute/base/base_game_settings.h
@@ -34,6 +34,7 @@
namespace Wintermute {
class BaseStringTable;
class BaseGame;
+class BasePersistenceManager;
class BaseGameSettings {
public:
const char *getGameFile() const { return (_gameFile ? _gameFile : "default.game"); }
@@ -46,6 +47,8 @@ public:
bool loadStringTable(const char *filename, bool clearOld);
void expandStringByStringTable(char **str) const;
char *getKeyFromStringTable(const char *str) const;
+
+ bool persist(BasePersistenceManager *persistMgr);
private:
char *_gameFile;
int _resWidth;
diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp
index 708df8def1..cce3561f67 100644
--- a/engines/wintermute/base/base_object.cpp
+++ b/engines/wintermute/base/base_object.cpp
@@ -95,7 +95,7 @@ BaseObject::BaseObject(BaseGame *inGame) : BaseScriptHolder(inGame) {
_sFXType = SFX_NONE;
_sFXParam1 = _sFXParam2 = _sFXParam3 = _sFXParam4 = 0;
- _blendMode = BLEND_NORMAL;
+ _blendMode = Graphics::BLEND_NORMAL;
}
@@ -807,10 +807,10 @@ bool BaseObject::scSetProperty(const char *name, ScValue *value) {
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "BlendMode") == 0) {
int i = value->getInt();
- if (i < BLEND_NORMAL || i >= NUM_BLEND_MODES) {
- i = BLEND_NORMAL;
+ if (i < Graphics::BLEND_NORMAL || i >= Graphics::NUM_BLEND_MODES) {
+ i = Graphics::BLEND_NORMAL;
}
- _blendMode = (TSpriteBlendMode)i;
+ _blendMode = (Graphics::TSpriteBlendMode)i;
return STATUS_OK;
}
diff --git a/engines/wintermute/base/base_object.h b/engines/wintermute/base/base_object.h
index f5036f4ec4..8ca8ffc246 100644
--- a/engines/wintermute/base/base_object.h
+++ b/engines/wintermute/base/base_object.h
@@ -33,6 +33,7 @@
#include "engines/wintermute/base/base_script_holder.h"
#include "engines/wintermute/persistent.h"
#include "common/events.h"
+#include "graphics/transform_struct.h"
namespace Wintermute {
@@ -75,7 +76,7 @@ protected:
int32 _iD;
char *_soundEvent;
public:
- TSpriteBlendMode _blendMode;
+ Graphics::TSpriteBlendMode _blendMode;
virtual bool afterMove();
float _scale;
uint32 _alphaColor;
diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp
index bea55fb857..bb5e0c4091 100644
--- a/engines/wintermute/base/base_persistence_manager.cpp
+++ b/engines/wintermute/base/base_persistence_manager.cpp
@@ -36,7 +36,7 @@
#include "engines/wintermute/base/gfx/base_image.h"
#include "engines/wintermute/base/save_thumb_helper.h"
#include "engines/wintermute/base/sound/base_sound.h"
-#include "engines/wintermute/graphics/transparent_surface.h"
+#include "graphics/transparent_surface.h"
#include "engines/wintermute/wintermute.h"
#include "graphics/scaler.h"
#include "image/bmp.h"
@@ -173,7 +173,7 @@ void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &des
Image::BitmapDecoder bmpDecoder;
if (bmpDecoder.loadStream(thumbStream)) {
const Graphics::Surface *bmpSurface = bmpDecoder.getSurface();
- TransparentSurface *scaleableSurface = new TransparentSurface(*bmpSurface, false);
+ Graphics::TransparentSurface *scaleableSurface = new Graphics::TransparentSurface(*bmpSurface, false);
Graphics::Surface *scaled = scaleableSurface->scale(kThumbnailWidth, kThumbnailHeight2);
Graphics::Surface *thumb = scaled->convertTo(g_system->getOverlayFormat());
desc.setThumbnail(thumb);
diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp
index 2e00998037..04060bff32 100644
--- a/engines/wintermute/base/base_sprite.cpp
+++ b/engines/wintermute/base/base_sprite.cpp
@@ -418,7 +418,7 @@ bool BaseSprite::getCurrentFrame(float zoomX, float zoomY) {
//////////////////////////////////////////////////////////////////////
-bool BaseSprite::display(int x, int y, BaseObject *registerVal, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode) {
+bool BaseSprite::display(int x, int y, BaseObject *registerVal, float zoomX, float zoomY, uint32 alpha, float rotate, Graphics::TSpriteBlendMode blendMode) {
if (_currentFrame < 0 || _currentFrame >= (int32)_frames.size()) {
return STATUS_OK;
}
diff --git a/engines/wintermute/base/base_sprite.h b/engines/wintermute/base/base_sprite.h
index 92287995d9..ec71512ec9 100644
--- a/engines/wintermute/base/base_sprite.h
+++ b/engines/wintermute/base/base_sprite.h
@@ -32,7 +32,7 @@
#include "engines/wintermute/coll_templ.h"
#include "engines/wintermute/base/base_script_holder.h"
-#include "engines/wintermute/graphics/transform_tools.h"
+#include "graphics/transform_tools.h"
namespace Wintermute {
class BaseFrame;
@@ -45,17 +45,17 @@ public:
void setDefaults();
DECLARE_PERSISTENT(BaseSprite, BaseScriptHolder)
- bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = kDefaultZoomX, float scaleY = kDefaultZoomY);
+ bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = Graphics::kDefaultZoomX, float scaleY = Graphics::kDefaultZoomY);
int32 _moveY;
int32 _moveX;
- bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY, uint32 alpha = kDefaultRgbaMod, float rotate = kDefaultAngle, TSpriteBlendMode blendMode = BLEND_NORMAL);
- bool getCurrentFrame(float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY);
+ bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = Graphics::kDefaultZoomX, float zoomY = Graphics::kDefaultZoomY, uint32 alpha = Graphics::kDefaultRgbaMod, float rotate = Graphics::kDefaultAngle, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL);
+ bool getCurrentFrame(float zoomX = Graphics::kDefaultZoomX, float zoomY = Graphics::kDefaultZoomY);
void reset();
bool isChanged();
bool isFinished();
bool loadBuffer(char *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
bool loadFile(const Common::String &filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
- bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY, uint32 alpha = kDefaultRgbaMod);
+ bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = Graphics::kDefaultZoomX, float zoomY = Graphics::kDefaultZoomY, uint32 alpha = Graphics::kDefaultRgbaMod);
bool _looping;
int32 _currentFrame;
bool addFrame(const char *filename, uint32 delay = 0, int hotspotX = 0, int hotspotY = 0, Rect32 *rect = nullptr);
diff --git a/engines/wintermute/base/base_string_table.cpp b/engines/wintermute/base/base_string_table.cpp
index 9adbbdf7be..89407a7b0e 100644
--- a/engines/wintermute/base/base_string_table.cpp
+++ b/engines/wintermute/base/base_string_table.cpp
@@ -189,8 +189,10 @@ bool BaseStringTable::loadFile(const char *filename, bool clearOld) {
BaseEngine::LOG(0, "Loading string table...");
if (clearOld) {
+ _filenames.clear();
_strings.clear();
}
+ _filenames.push_back(Common::String(filename));
uint32 size;
byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename, &size);
@@ -253,4 +255,27 @@ bool BaseStringTable::loadFile(const char *filename, bool clearOld) {
return STATUS_OK;
}
+bool BaseStringTable::persist(BasePersistenceManager *persistMgr) {
+ // Do nothing if the save game is too old.
+ if (!persistMgr->checkVersion(1, 3, 1)) {
+ return true;
+ }
+ uint32 numFiles = _filenames.size();
+ persistMgr->transferUint32("NumFiles", &numFiles);
+ if (persistMgr->getIsSaving()) {
+ for (uint i = 0; i < numFiles; i++) {
+ persistMgr->transferString("Filename", &_filenames[i]);
+ }
+ } else {
+ _strings.clear();
+ _filenames.clear();
+ for (uint i = 0; i < numFiles; i++) {
+ Common::String filename = "";
+ persistMgr->transferString("Filename", &filename);
+ loadFile(filename.c_str(), false);
+ }
+ }
+ return true;
+}
+
} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_string_table.h b/engines/wintermute/base/base_string_table.h
index 9e915a1ad9..cdcf11917d 100644
--- a/engines/wintermute/base/base_string_table.h
+++ b/engines/wintermute/base/base_string_table.h
@@ -35,6 +35,8 @@
namespace Wintermute {
+class BasePersistenceManager;
+
class BaseStringTable : public BaseClass {
public:
bool loadFile(const char *filename, bool deleteAll = true);
@@ -44,8 +46,10 @@ public:
BaseStringTable(BaseGame *inGame);
virtual ~BaseStringTable();
char *getKey(const char *str) const;
+ bool persist(BasePersistenceManager *persistMgr);
private:
Common::HashMap<Common::String, Common::String> _strings;
+ Common::Array<Common::String> _filenames;
typedef Common::HashMap<Common::String, Common::String>::const_iterator StringsIter;
};
diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp
index 3a6e28b1f2..4388942064 100644
--- a/engines/wintermute/base/base_sub_frame.cpp
+++ b/engines/wintermute/base/base_sub_frame.cpp
@@ -37,8 +37,8 @@
#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/graphics/transform_tools.h"
-#include "engines/wintermute/graphics/transform_struct.h"
+#include "graphics/transform_tools.h"
+#include "graphics/transform_struct.h"
namespace Wintermute {
@@ -47,9 +47,9 @@ IMPLEMENT_PERSISTENT(BaseSubFrame, false)
//////////////////////////////////////////////////////////////////////////
BaseSubFrame::BaseSubFrame(BaseGame *inGame) : BaseScriptable(inGame, true) {
_surface = nullptr;
- _hotspotX = kDefaultHotspotX;
- _hotspotY = kDefaultHotspotY;
- _alpha = kDefaultRgbaMod;
+ _hotspotX = Graphics::kDefaultHotspotX;
+ _hotspotY = Graphics::kDefaultHotspotY;
+ _alpha = Graphics::kDefaultRgbaMod;
_transparent = 0xFFFF00FF;
_wantsDefaultRect = false;
@@ -234,7 +234,7 @@ const char* BaseSubFrame::getSurfaceFilename() {
}
//////////////////////////////////////////////////////////////////////
-bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, float rotate, TSpriteBlendMode blendMode) {
+bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, float rotate, Graphics::TSpriteBlendMode blendMode) {
rotate = fmod(rotate, 360.0f);
if (rotate < 0) {
@@ -246,7 +246,7 @@ bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, fl
}
if (registerOwner != nullptr && !_decoration) {
- if (zoomX == kDefaultZoomX && zoomY == kDefaultZoomY) {
+ if (zoomX == Graphics::kDefaultZoomX && zoomY == Graphics::kDefaultZoomY) {
BaseEngine::getRenderer()->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, x - _hotspotX + getRect().left, y - _hotspotY + getRect().top, getRect().right - getRect().left, getRect().bottom - getRect().top, zoomX, zoomY, precise));
} else {
BaseEngine::getRenderer()->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, (int)(x - (_hotspotX + getRect().left) * (zoomX / 100)), (int)(y - (_hotspotY + getRect().top) * (zoomY / 100)), (int)((getRect().right - getRect().left) * (zoomX / 100)), (int)((getRect().bottom - getRect().top) * (zoomY / 100)), zoomX, zoomY, precise));
@@ -259,24 +259,26 @@ bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, fl
bool res;
//if (Alpha==0xFFFFFFFF) Alpha = _alpha; // TODO: better (combine owner's and self alpha)
- if (_alpha != kDefaultRgbaMod) {
+ if (_alpha != Graphics::kDefaultRgbaMod) {
alpha = _alpha;
}
- if (rotate != kDefaultAngle) {
- Point32 boxOffset, rotatedHotspot, hotspotOffset, newOrigin;
- Point32 origin(x, y);
- Rect32 oldRect = getRect();
- Point32 newHotspot;
- TransformStruct transform = TransformStruct(zoomX, zoomY, (uint32)rotate, _hotspotX, _hotspotY, blendMode, alpha, _mirrorX, _mirrorY, 0, 0);
- Rect32 newRect = TransformTools::newRect (oldRect, transform, &newHotspot);
+ if (rotate != Graphics::kDefaultAngle) {
+ Point32 boxOffset, rotatedHotspot, hotspotOffset;
+ Common::Point origin(x, y);
+ Common::Point newOrigin;
+ Rect32 oldRect1 = getRect();
+ Common::Rect oldRect(oldRect1.top, oldRect1.left, oldRect1.bottom, oldRect1.right);
+ Common::Point newHotspot;
+ Graphics::TransformStruct transform = Graphics::TransformStruct(zoomX, zoomY, (uint32)rotate, _hotspotX, _hotspotY, blendMode, alpha, _mirrorX, _mirrorY, 0, 0);
+ Rect32 newRect = Graphics::TransformTools::newRect(oldRect, transform, &newHotspot);
newOrigin = origin - newHotspot;
res = _surface->displayTransform(newOrigin.x, newOrigin.y, oldRect, newRect, transform);
} else {
- if (zoomX == kDefaultZoomX && zoomY == kDefaultZoomY) {
+ if (zoomX == Graphics::kDefaultZoomX && zoomY == Graphics::kDefaultZoomY) {
res = _surface->displayTrans(x - _hotspotX, y - _hotspotY, getRect(), alpha, blendMode, _mirrorX, _mirrorY);
} else {
- res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / kDefaultZoomX)), (int)(y - _hotspotY * (zoomY / kDefaultZoomY)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY);
+ res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / Graphics::kDefaultZoomX)), (int)(y - _hotspotY * (zoomY / Graphics::kDefaultZoomY)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY);
}
}
diff --git a/engines/wintermute/base/base_sub_frame.h b/engines/wintermute/base/base_sub_frame.h
index b2859fa3f3..f156c332d6 100644
--- a/engines/wintermute/base/base_sub_frame.h
+++ b/engines/wintermute/base/base_sub_frame.h
@@ -32,6 +32,7 @@
#include "engines/wintermute/base/base.h"
#include "engines/wintermute/base/base_scriptable.h"
+#include "graphics/transform_struct.h"
namespace Wintermute {
class BaseObject;
@@ -52,7 +53,7 @@ public:
BaseSubFrame(BaseGame *inGame);
virtual ~BaseSubFrame();
bool loadBuffer(char *buffer, int lifeTime, bool keepLoaded);
- bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL);
+ bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL);
bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100);
const char* getSurfaceFilename();
diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp
index b1461283e8..ae4955390b 100644
--- a/engines/wintermute/base/file/base_package.cpp
+++ b/engines/wintermute/base/file/base_package.cpp
@@ -53,8 +53,8 @@ static bool findPackageSignature(Common::SeekableReadStream *f, uint32 *offset)
byte buf[32768];
byte signature[8];
- ((uint32 *)signature)[0] = PACKAGE_MAGIC_1;
- ((uint32 *)signature)[1] = PACKAGE_MAGIC_2;
+ WRITE_LE_UINT32(signature + 0, PACKAGE_MAGIC_1);
+ WRITE_LE_UINT32(signature + 4, PACKAGE_MAGIC_2);
uint32 fileSize = (uint32)f->size();
uint32 startPos = 1024 * 1024;
diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index df9a8648db..f27b565a7f 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -234,7 +234,7 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign
color = BYTETORGBA(RGBCOLGetR(color), RGBCOLGetG(color), RGBCOLGetB(color), RGBCOLGetA(renderer->_forceAlphaColor));
renderer->_forceAlphaColor = 0;
}
- surface->displayTransOffset(x, y - textOffset, rc, color, BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY);
+ surface->displayTransOffset(x, y - textOffset, rc, color, Graphics::BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY);
renderer->_forceAlphaColor = origForceAlpha;
}
diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp
index e676fafdbf..a1548b83ea 100644
--- a/engines/wintermute/base/gfx/base_image.cpp
+++ b/engines/wintermute/base/gfx/base_image.cpp
@@ -28,7 +28,7 @@
#include "engines/wintermute/base/gfx/base_image.h"
#include "engines/wintermute/base/base_file_manager.h"
-#include "engines/wintermute/graphics/transparent_surface.h"
+#include "graphics/transparent_surface.h"
#include "graphics/surface.h"
#include "image/png.h"
#include "image/jpeg.h"
@@ -112,7 +112,7 @@ bool BaseImage::saveBMPFile(const Common::String &filename) const {
//////////////////////////////////////////////////////////////////////////
bool BaseImage::resize(int newWidth, int newHeight) {
// WME Lite used FILTER_BILINEAR with FreeImage_Rescale here.
- TransparentSurface temp(*_surface, true);
+ Graphics::TransparentSurface temp(*_surface, true);
if (_deletableSurface) {
_deletableSurface->free();
delete _deletableSurface;
@@ -216,7 +216,7 @@ bool BaseImage::writeBMPToStream(Common::WriteStream *stream) const {
bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) {
// WME Lite used FILTER_BILINEAR with FreeImage_Rescale here.
- TransparentSurface temp(*origImage->_surface, false);
+ Graphics::TransparentSurface temp(*origImage->_surface, false);
if (_deletableSurface) {
_deletableSurface->free();
delete _deletableSurface;
diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h
index 42ff2cb9e1..6b1a4f97f4 100644
--- a/engines/wintermute/base/gfx/base_renderer.h
+++ b/engines/wintermute/base/gfx/base_renderer.h
@@ -72,7 +72,6 @@ public:
* Fade the screen to black
*
* @param alpha amount to fade by (alpha value of black)
- * @return
*/
virtual void fade(uint16 alpha) = 0;
/**
diff --git a/engines/wintermute/base/gfx/base_surface.cpp b/engines/wintermute/base/gfx/base_surface.cpp
index ec42a63c77..f8b96b5baf 100644
--- a/engines/wintermute/base/gfx/base_surface.cpp
+++ b/engines/wintermute/base/gfx/base_surface.cpp
@@ -75,7 +75,7 @@ bool BaseSurface::displayHalfTrans(int x, int y, Rect32 rect) {
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurface::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) {
+bool BaseSurface::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) {
return displayTransform(x, y, rect, newRect, transform);
}
diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h
index 7bd9bcbaea..ea743bdaf2 100644
--- a/engines/wintermute/base/gfx/base_surface.h
+++ b/engines/wintermute/base/gfx/base_surface.h
@@ -32,7 +32,7 @@
#include "engines/wintermute/base/base.h"
#include "engines/wintermute/math/rect32.h"
#include "graphics/surface.h"
-#include "engines/wintermute/graphics/transform_struct.h"
+#include "graphics/transform_struct.h"
namespace Wintermute {
@@ -50,12 +50,12 @@ public:
virtual bool displayHalfTrans(int x, int y, Rect32 rect);
virtual bool isTransparentAt(int x, int y);
- virtual bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
- virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
- virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0;
- virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
- virtual bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) = 0;
- virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0;
+ virtual bool display(int x, int y, Rect32 rect, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) = 0;
+ virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) = 0;
virtual bool restore();
virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0;
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
index 601fcc0ffa..0f6a184cb3 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -35,7 +35,7 @@
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_sprite.h"
#include "common/system.h"
-#include "engines/wintermute/graphics/transparent_surface.h"
+#include "graphics/transparent_surface.h"
#include "common/queue.h"
#include "common/config-manager.h"
@@ -254,7 +254,7 @@ void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a) {
Common::Rect sizeRect(fillRect);
sizeRect.translate(-fillRect.top, -fillRect.left);
surf.fillRect(fillRect, col);
- TransformStruct temp = TransformStruct();
+ Graphics::TransformStruct temp = Graphics::TransformStruct();
temp._alphaDisable = false;
drawSurface(nullptr, &surf, &sizeRect, &fillRect, temp);
surf.free();
@@ -268,7 +268,7 @@ Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const {
return _renderSurface->format;
}
-void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform) {
+void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Graphics::TransformStruct &transform) {
if (_disableDirtyRects) {
RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform);
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
index c9b8a52282..bc267fd656 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
@@ -33,7 +33,7 @@
#include "common/rect.h"
#include "graphics/surface.h"
#include "common/list.h"
-#include "engines/wintermute/graphics/transform_struct.h"
+#include "graphics/transform_struct.h"
namespace Wintermute {
class BaseSurfaceOSystem;
@@ -110,7 +110,7 @@ public:
virtual bool startSpriteBatch() override;
virtual bool endSpriteBatch() override;
void endSaveLoad();
- void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform);
+ void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Graphics::TransformStruct &transform);
BaseSurface *createSurface() override;
private:
/**
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
index 983f9c1296..a2a0032e26 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -32,8 +32,8 @@
#include "engines/wintermute/base/gfx/osystem/base_render_osystem.h"
#include "engines/wintermute/base/gfx/base_image.h"
#include "engines/wintermute/platform_osystem.h"
-#include "engines/wintermute/graphics/transparent_surface.h"
-#include "engines/wintermute/graphics/transform_tools.h"
+#include "graphics/transparent_surface.h"
+#include "graphics/transform_tools.h"
#include "graphics/pixelformat.h"
#include "graphics/surface.h"
#include "common/stream.h"
@@ -45,7 +45,7 @@ namespace Wintermute {
BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) {
_surface = new Graphics::Surface();
_alphaMask = nullptr;
- _alphaType = TransparentSurface::ALPHA_FULL;
+ _alphaType = Graphics::ALPHA_FULL;
_lockPixels = nullptr;
_lockPitch = 0;
_loaded = false;
@@ -68,10 +68,10 @@ BaseSurfaceOSystem::~BaseSurfaceOSystem() {
renderer->invalidateTicketsFromSurface(this);
}
-TransparentSurface::AlphaType hasTransparencyType(const Graphics::Surface *surf) {
+Graphics::AlphaType hasTransparencyType(const Graphics::Surface *surf) {
if (surf->format.bytesPerPixel != 4) {
warning("hasTransparencyType:: non 32 bpp surface passed as argument");
- return TransparentSurface::ALPHA_OPAQUE;
+ return Graphics::ALPHA_OPAQUE;
}
uint8 r, g, b, a;
bool seenAlpha = false;
@@ -93,11 +93,11 @@ TransparentSurface::AlphaType hasTransparencyType(const Graphics::Surface *surf)
}
}
if (seenFullAlpha) {
- return TransparentSurface::ALPHA_FULL;
+ return Graphics::ALPHA_FULL;
} else if (seenAlpha) {
- return TransparentSurface::ALPHA_BINARY;
+ return Graphics::ALPHA_BINARY;
} else {
- return TransparentSurface::ALPHA_OPAQUE;
+ return Graphics::ALPHA_OPAQUE;
}
}
@@ -175,7 +175,7 @@ bool BaseSurfaceOSystem::finishLoad() {
}
if (needsColorKey) {
- TransparentSurface trans(*_surface);
+ Graphics::TransparentSurface trans(*_surface);
trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha);
}
@@ -328,46 +328,46 @@ bool BaseSurfaceOSystem::endPixelOp() {
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
_rotation = 0;
- return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, mirrorX, mirrorY));
+ return drawSprite(x, y, &rect, nullptr, Graphics::TransformStruct(Graphics::kDefaultZoomX, Graphics::kDefaultZoomY, mirrorX, mirrorY));
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
_rotation = 0;
- return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, blendMode, alpha, mirrorX, mirrorY));
+ return drawSprite(x, y, &rect, nullptr, Graphics::TransformStruct(Graphics::kDefaultZoomX, Graphics::kDefaultZoomY, blendMode, alpha, mirrorX, mirrorY));
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) {
+bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) {
_rotation = 0;
- return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY, offsetX, offsetY));
+ return drawSprite(x, y, &rect, nullptr, Graphics::TransformStruct(Graphics::kDefaultZoomX, Graphics::kDefaultZoomY, Graphics::kDefaultAngle, Graphics::kDefaultHotspotX, Graphics::kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY, offsetX, offsetY));
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
_rotation = 0;
- return drawSprite(x, y, &rect, nullptr, TransformStruct((int32)zoomX, (int32)zoomY, blendMode, alpha, mirrorX, mirrorY));
+ return drawSprite(x, y, &rect, nullptr, Graphics::TransformStruct((int32)zoomX, (int32)zoomY, blendMode, alpha, mirrorX, mirrorY));
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
_rotation = 0;
- TransformStruct transform;
+ Graphics::TransformStruct transform;
if (transparent) {
- transform = TransformStruct((int32)zoomX, (int32)zoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY);
+ transform = Graphics::TransformStruct((int32)zoomX, (int32)zoomY, Graphics::kDefaultAngle, Graphics::kDefaultHotspotX, Graphics::kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY);
} else {
- transform = TransformStruct((int32)zoomX, (int32)zoomY, mirrorX, mirrorY);
+ transform = Graphics::TransformStruct((int32)zoomX, (int32)zoomY, mirrorX, mirrorY);
}
return drawSprite(x, y, &rect, nullptr, transform);
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) {
+bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) {
_rotation = (uint32)transform._angle;
if (transform._angle < 0.0f) {
warning("Negative rotation: %d %d", transform._angle, _rotation);
@@ -380,13 +380,13 @@ bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newR
//////////////////////////////////////////////////////////////////////////
bool BaseSurfaceOSystem::displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) {
assert(numTimesX > 0 && numTimesY > 0);
- TransformStruct transform(numTimesX, numTimesY);
+ Graphics::TransformStruct transform(numTimesX, numTimesY);
return drawSprite(x, y, &rect, nullptr, transform);
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transform) {
+bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, Graphics::TransformStruct transform) {
BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
if (!_loaded) {
@@ -414,13 +414,13 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect,
position.setHeight(newRect->height());
} else {
- Rect32 r;
+ Common::Rect r;
r.top = 0;
r.left = 0;
r.setWidth(rect->width());
r.setHeight(rect->height());
- r = TransformTools::newRect(r, transform, 0);
+ r = Graphics::TransformTools::newRect(r, transform, 0);
position.top = r.top + y + transform._offset.y;
position.left = r.left + x + transform._offset.x;
@@ -433,7 +433,7 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect,
// But no checking is in place for that yet.
// Optimize by not doing alpha-blits if we lack alpha
- if (_alphaType == TransparentSurface::ALPHA_OPAQUE && !transform._alphaDisable) {
+ if (_alphaType == Graphics::ALPHA_OPAQUE && !transform._alphaDisable) {
transform._alphaDisable = true;
}
@@ -452,9 +452,9 @@ bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAl
_surface->copyFrom(surface);
}
if (hasAlpha) {
- _alphaType = TransparentSurface::ALPHA_FULL;
+ _alphaType = Graphics::ALPHA_FULL;
} else {
- _alphaType = TransparentSurface::ALPHA_OPAQUE;
+ _alphaType = Graphics::ALPHA_OPAQUE;
}
BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
renderer->invalidateTicketsFromSurface(this);
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
index 4a05b2c66c..9fbbe1d498 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
@@ -30,7 +30,7 @@
#define WINTERMUTE_BASE_SURFACESDL_H
#include "graphics/surface.h"
-#include "engines/wintermute/graphics/transparent_surface.h"
+#include "graphics/transparent_surface.h"
#include "engines/wintermute/base/gfx/base_surface.h"
#include "common/list.h"
@@ -52,12 +52,12 @@ public:
bool endPixelOp() override;
- bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override;
- bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = kDefaultRgbaMod, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
- bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) override;
+ bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = Graphics::kDefaultRgbaMod, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
+ bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = Graphics::kDefaultRgbaMod, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
+ bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = Graphics::kDefaultRgbaMod, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override;
+ bool display(int x, int y, Rect32 rect, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
+ bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = Graphics::kDefaultRgbaMod, bool transparent = false, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override;
+ bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) override;
virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY);
virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) override;
/* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
@@ -82,17 +82,17 @@ public:
return _height;
}
- TransparentSurface::AlphaType getAlphaType() const { return _alphaType; }
+ Graphics::AlphaType getAlphaType() const { return _alphaType; }
private:
Graphics::Surface *_surface;
bool _loaded;
bool finishLoad();
- bool drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transformStruct);
+ bool drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, Graphics::TransformStruct transformStruct);
void genAlphaMask(Graphics::Surface *surface);
uint32 getPixelAt(Graphics::Surface *surface, int x, int y);
uint32 _rotation;
- TransparentSurface::AlphaType _alphaType;
+ Graphics::AlphaType _alphaType;
void *_lockPixels;
int _lockPitch;
byte *_alphaMask;
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
index f8579dfd41..afe884300a 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
@@ -29,12 +29,12 @@
#include "engines/wintermute/base/gfx/osystem/render_ticket.h"
#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h"
-#include "engines/wintermute/graphics/transform_tools.h"
+#include "graphics/transform_tools.h"
#include "common/textconsole.h"
namespace Wintermute {
-RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct transform) :
+RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Graphics::TransformStruct transform) :
_owner(owner),
_srcRect(*srcRect),
_dstRect(*dstRect),
@@ -57,8 +57,8 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s
// NB: Mirroring and rotation are probably done in the wrong order.
// (Mirroring should most likely be done before rotation. See also
// TransformTools.)
- if (_transform._angle != kDefaultAngle) {
- TransparentSurface src(*_surface, false);
+ if (_transform._angle != Graphics::kDefaultAngle) {
+ Graphics::TransparentSurface src(*_surface, false);
Graphics::Surface *temp = src.rotoscale(transform);
_surface->free();
delete _surface;
@@ -66,7 +66,7 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s
} else if ((dstRect->width() != srcRect->width() ||
dstRect->height() != srcRect->height()) &&
_transform._numTimesX * _transform._numTimesY == 1) {
- TransparentSurface src(*_surface, false);
+ Graphics::TransparentSurface src(*_surface, false);
Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height());
_surface->free();
delete _surface;
@@ -97,7 +97,7 @@ bool RenderTicket::operator==(const RenderTicket &t) const {
// Replacement for SDL2's SDL_RenderCopy
void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const {
- TransparentSurface src(*getSurface(), false);
+ Graphics::TransparentSurface src(*getSurface(), false);
Common::Rect clipRect;
clipRect.setWidth(getSurface()->w);
@@ -105,7 +105,7 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const {
if (_owner) {
if (_transform._alphaDisable) {
- src.setAlphaMode(TransparentSurface::ALPHA_OPAQUE);
+ src.setAlphaMode(Graphics::ALPHA_OPAQUE);
} else {
src.setAlphaMode(_owner->getAlphaType());
}
@@ -126,7 +126,7 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const {
}
void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const {
- TransparentSurface src(*getSurface(), false);
+ Graphics::TransparentSurface src(*getSurface(), false);
bool doDelete = false;
if (!clipRect) {
doDelete = true;
@@ -137,7 +137,7 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect
if (_owner) {
if (_transform._alphaDisable) {
- src.setAlphaMode(TransparentSurface::ALPHA_OPAQUE);
+ src.setAlphaMode(Graphics::ALPHA_OPAQUE);
} else {
src.setAlphaMode(_owner->getAlphaType());
}
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.h b/engines/wintermute/base/gfx/osystem/render_ticket.h
index de95273021..3d3bd2e844 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.h
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.h
@@ -29,7 +29,7 @@
#ifndef WINTERMUTE_RENDER_TICKET_H
#define WINTERMUTE_RENDER_TICKET_H
-#include "engines/wintermute/graphics/transparent_surface.h"
+#include "graphics/transparent_surface.h"
#include "graphics/surface.h"
#include "common/rect.h"
@@ -51,8 +51,8 @@ class BaseSurfaceOSystem;
*/
class RenderTicket {
public:
- RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, TransformStruct transform);
- RenderTicket() : _isValid(true), _wantsDraw(false), _transform(TransformStruct()) {}
+ RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, Graphics::TransformStruct transform);
+ RenderTicket() : _isValid(true), _wantsDraw(false), _transform(Graphics::TransformStruct()) {}
~RenderTicket();
const Graphics::Surface *getSurface() const { return _surface; }
// Non-dirty-rects:
@@ -65,7 +65,7 @@ public:
bool _isValid;
bool _wantsDraw;
- TransformStruct _transform;
+ Graphics::TransformStruct _transform;
BaseSurfaceOSystem *_owner;
bool operator==(const RenderTicket &a) const;
diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp
index f0b868209d..44fd117e61 100644
--- a/engines/wintermute/base/scriptables/script.cpp
+++ b/engines/wintermute/base/scriptables/script.cpp
@@ -488,7 +488,8 @@ double ScScript::getFloat() {
SWAP(buffer[3], buffer[4]);
#endif
- double ret = *(double *)(buffer);
+ double ret;
+ memcpy(&ret, buffer, sizeof(double));
_iP += 8; // Hardcode the double-size used originally.
return ret;
}
diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp
index 36a624367c..15ddd4bcca 100644
--- a/engines/wintermute/base/scriptables/script_ext_file.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_file.cpp
@@ -443,7 +443,7 @@ bool SXFile::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
return STATUS_OK;
}
float val;
- (*(uint32 *)&val) = _readFile->readUint32LE();
+ WRITE_UINT32(&val, _readFile->readUint32LE());
if (!_readFile->err()) {
stack->pushFloat(val);
} else {
diff --git a/engines/wintermute/base/sound/base_sound.cpp b/engines/wintermute/base/sound/base_sound.cpp
index fa452cc0d6..b5b12d55f9 100644
--- a/engines/wintermute/base/sound/base_sound.cpp
+++ b/engines/wintermute/base/sound/base_sound.cpp
@@ -89,7 +89,7 @@ bool BaseSound::setSoundSimple() {
_sound->setLooping(_soundLooping);
_sound->setPrivateVolume(_soundPrivateVolume);
_sound->setLoopStart(_soundLoopStart);
- _sound->_freezePaused = _soundFreezePaused;
+ _sound->setFreezePaused(_soundFreezePaused);
if (_soundPlaying) {
return _sound->resume();
} else {
@@ -130,7 +130,7 @@ bool BaseSound::pause(bool freezePaused) {
if (_sound) {
_soundPaused = true;
if (freezePaused) {
- _sound->_freezePaused = true;
+ _sound->setFreezePaused(true);
}
return _sound->pause();
} else {
@@ -150,13 +150,13 @@ bool BaseSound::resume() {
bool BaseSound::persist(BasePersistenceManager *persistMgr) {
if (persistMgr->getIsSaving() && _sound) {
_soundPlaying = _sound->isPlaying();
- _soundLooping = _sound->_looping;
- _soundPrivateVolume = _sound->_privateVolume;
+ _soundLooping = _sound->isLooping();
+ _soundPrivateVolume = _sound->getPrivateVolume();
if (_soundPlaying) {
_soundPosition = _sound->getPosition();
}
- _soundLoopStart = _sound->_loopStart;
- _soundFreezePaused = _sound->_freezePaused;
+ _soundLoopStart = _sound->getLoopStart();
+ _soundFreezePaused = _sound->isFreezePaused();
}
if (persistMgr->getIsSaving()) {
@@ -232,7 +232,7 @@ bool BaseSound::setPrivateVolume(int volume) {
if (!_sound) {
return STATUS_FAILED;
} else {
- _sound->_privateVolume = volume;
+ _sound->setPrivateVolume(volume);
return STATUS_OK;
}
}
@@ -241,7 +241,7 @@ int BaseSound::getVolumePercent() {
if (!_sound) {
return 0;
} else {
- return _sound->_privateVolume * 100 / 255;
+ return _sound->getPrivateVolume() * 100 / 255;
}
}
@@ -249,7 +249,7 @@ int BaseSound::getVolume() {
if (!_sound) {
return 0;
} else {
- return _sound->_privateVolume;
+ return _sound->getPrivateVolume();
}
}
diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp
index 7ec68ea752..5fdac12cef 100644
--- a/engines/wintermute/base/sound/base_sound_buffer.cpp
+++ b/engines/wintermute/base/sound/base_sound_buffer.cpp
@@ -143,8 +143,13 @@ bool BaseSoundBuffer::play(bool looping, uint32 startSample) {
_stream->seek(startSample);
_handle = new Audio::SoundHandle;
if (_looping) {
- Audio::AudioStream *loopStream = new Audio::LoopingAudioStream(_stream, 0, DisposeAfterUse::NO);
- g_system->getMixer()->playStream(_type, _handle, loopStream, -1, _volume, _pan, DisposeAfterUse::YES);
+ if (_loopStart != 0) {
+ Audio::AudioStream *loopStream = new Audio::SubLoopingAudioStream(_stream, 0, Audio::Timestamp(_loopStart, _stream->getRate()), _stream->getLength(), DisposeAfterUse::NO);
+ g_system->getMixer()->playStream(_type, _handle, loopStream, -1, _volume, _pan, DisposeAfterUse::YES);
+ } else {
+ Audio::AudioStream *loopStream = new Audio::LoopingAudioStream(_stream, 0, DisposeAfterUse::NO);
+ g_system->getMixer()->playStream(_type, _handle, loopStream, -1, _volume, _pan, DisposeAfterUse::YES);
+ }
} else {
g_system->getMixer()->playStream(_type, _handle, _stream, -1, _volume, _pan, DisposeAfterUse::NO);
}
@@ -296,4 +301,24 @@ bool BaseSoundBuffer::applyFX(TSFXType type, float param1, float param2, float p
return STATUS_OK;
}
+int32 BaseSoundBuffer::getPrivateVolume() const {
+ return _privateVolume;
+}
+
+bool BaseSoundBuffer::isLooping() const {
+ return _looping;
+}
+
+bool BaseSoundBuffer::isFreezePaused() const {
+ return _freezePaused;
+}
+
+void BaseSoundBuffer::setFreezePaused(bool freezePaused) {
+ _freezePaused = freezePaused;
+}
+
+Audio::Mixer::SoundType BaseSoundBuffer::getType() const {
+ return _type;
+}
+
} // End of namespace Wintermute
diff --git a/engines/wintermute/base/sound/base_sound_buffer.h b/engines/wintermute/base/sound/base_sound_buffer.h
index 94bc8dc6ad..b3f3046674 100644
--- a/engines/wintermute/base/sound/base_sound_buffer.h
+++ b/engines/wintermute/base/sound/base_sound_buffer.h
@@ -71,23 +71,26 @@ public:
void updateVolume();
void setType(Audio::Mixer::SoundType Type);
+ Audio::Mixer::SoundType getType() const;
bool loadFromFile(const Common::String &filename, bool forceReload = false);
void setStreaming(bool streamed, uint32 numBlocks = 0, uint32 blockSize = 0);
bool applyFX(TSFXType type, float param1, float param2, float param3, float param4);
-
+ int32 getPrivateVolume() const;
+ void setFreezePaused(bool freezePaused);
+ bool isFreezePaused() const;
+ bool isLooping() const;
//HSTREAM _stream;
//HSYNC _sync;
+
+private:
+ Audio::Mixer::SoundType _type;
Audio::SeekableAudioStream *_stream;
Audio::SoundHandle *_handle;
-
bool _freezePaused;
- uint32 _loopStart;
- Audio::Mixer::SoundType _type;
bool _looping;
-
int32 _privateVolume;
-private:
+ uint32 _loopStart;
uint32 _startPos;
Common::String _filename;
bool _streamed;
diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp
index 539dc0dd1d..f1e0c3b1f9 100644
--- a/engines/wintermute/base/sound/base_sound_manager.cpp
+++ b/engines/wintermute/base/sound/base_sound_manager.cpp
@@ -87,6 +87,7 @@ bool BaseSoundMgr::initialize() {
setMasterVolumePercent(volumeMasterPercent);
_soundAvailable = true;
+ g_engine->syncSoundSettings();
return STATUS_OK;
}
@@ -253,9 +254,9 @@ byte BaseSoundMgr::getMasterVolume() {
bool BaseSoundMgr::pauseAll(bool includingMusic) {
for (uint32 i = 0; i < _sounds.size(); i++) {
- if (_sounds[i]->isPlaying() && (_sounds[i]->_type != Audio::Mixer::kMusicSoundType || includingMusic)) {
+ if (_sounds[i]->isPlaying() && (_sounds[i]->getType() != Audio::Mixer::kMusicSoundType || includingMusic)) {
_sounds[i]->pause();
- _sounds[i]->_freezePaused = true;
+ _sounds[i]->setFreezePaused(true);
}
}
@@ -267,9 +268,9 @@ bool BaseSoundMgr::pauseAll(bool includingMusic) {
bool BaseSoundMgr::resumeAll() {
for (uint32 i = 0; i < _sounds.size(); i++) {
- if (_sounds[i]->_freezePaused) {
+ if (_sounds[i]->isFreezePaused()) {
_sounds[i]->resume();
- _sounds[i]->_freezePaused = false;
+ _sounds[i]->setFreezePaused(false);
}
}
diff --git a/engines/wintermute/dcgf.h b/engines/wintermute/dcgf.h
index 78503b8c3b..c919180e45 100644
--- a/engines/wintermute/dcgf.h
+++ b/engines/wintermute/dcgf.h
@@ -32,8 +32,8 @@
//////////////////////////////////////////////////////////////////////////
#define DCGF_VER_MAJOR 1
-#define DCGF_VER_MINOR 2
-#define DCGF_VER_BUILD 2
+#define DCGF_VER_MINOR 3
+#define DCGF_VER_BUILD 1
#define DCGF_VER_SUFFIX "ScummVM"
#define DCGF_VER_BETA true
diff --git a/engines/wintermute/dctypes.h b/engines/wintermute/dctypes.h
index 33e1cc4018..90340f437d 100644
--- a/engines/wintermute/dctypes.h
+++ b/engines/wintermute/dctypes.h
@@ -200,14 +200,6 @@ enum TTextEncoding {
NUM_TEXT_ENCODINGS
};
-enum TSpriteBlendMode {
- BLEND_UNKNOWN = -1,
- BLEND_NORMAL = 0,
- BLEND_ADDITIVE = 1,
- BLEND_SUBTRACTIVE = 2,
- NUM_BLEND_MODES
-};
-
enum TTTSType {
TTS_CAPTION = 0,
TTS_TALK,
diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp
index 51fd74e300..a313314a8b 100644
--- a/engines/wintermute/debugger.cpp
+++ b/engines/wintermute/debugger.cpp
@@ -29,8 +29,8 @@
namespace Wintermute {
Console::Console(WintermuteEngine *vm) : GUI::Debugger(), _engineRef(vm) {
- DCmd_Register("show_fps", WRAP_METHOD(Console, Cmd_ShowFps));
- DCmd_Register("dump_file", WRAP_METHOD(Console, Cmd_DumpFile));
+ registerCmd("show_fps", WRAP_METHOD(Console, Cmd_ShowFps));
+ registerCmd("dump_file", WRAP_METHOD(Console, Cmd_DumpFile));
}
Console::~Console(void) {
@@ -50,7 +50,7 @@ bool Console::Cmd_ShowFps(int argc, const char **argv) {
bool Console::Cmd_DumpFile(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Usage: %s <file path> <output file name>\n", argv[0]);
+ debugPrintf("Usage: %s <file path> <output file name>\n", argv[0]);
return true;
}
@@ -60,7 +60,7 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) {
BaseFileManager *fileManager = BaseEngine::instance().getFileManager();
Common::SeekableReadStream *inFile = fileManager->openFile(filePath);
if (!inFile) {
- DebugPrintf("File '%s' not found\n", argv[1]);
+ debugPrintf("File '%s' not found\n", argv[1]);
return true;
}
@@ -77,7 +77,7 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) {
delete outFile;
delete inFile;
- DebugPrintf("Resource file '%s' dumped to file '%s'\n", argv[1], argv[2]);
+ debugPrintf("Resource file '%s' dumped to file '%s'\n", argv[1], argv[2]);
return true;
}
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index 6556d3b34a..8206ca9643 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -28,6 +28,7 @@ static const PlainGameDescriptor wintermuteGames[] = {
{"5ld", "Five Lethal Demons"},
{"5ma", "Five Magical Amulets"},
{"actualdest", "Actual Destination"},
+ {"agustin", "Boredom of Agustin Cordes"},
{"bickadoodle", "Bickadoodle"},
{"bookofgron", "Book of Gron Part One"},
{"bthreshold", "Beyond the Threshold"},
@@ -38,39 +39,51 @@ static const PlainGameDescriptor wintermuteGames[] = {
{"carolreed8", "Carol Reed 8 - Amber's Blood"},
{"carolreed9", "Carol Reed 9 - Cold Case Summer"},
{"chivalry", "Chivalry is Not Dead"},
- {"corrosion", "Corrosion: Cold Winter Waiting"},
+ {"conspiracao", "Conspiracao Dumont"},
+ {"corrosion", "Corrosion: Cold Winter Waiting"},
{"deadcity", "Dead City"},
{"dreaming", "Des Reves Elastiques Avec Mille Insectes Nommes Georges"},
{"dirtysplit", "Dirty Split"},
{"dreamscape", "Dreamscape"},
{"escapemansion", "Escape from the Mansion"},
+ {"four", "Four"},
{"framed", "Framed"},
{"ghostsheet", "Ghost in the Sheet"},
{"hamlet", "Hamlet or the last game without MMORPS features, shaders and product placement"},
{"helga", "Helga Deep In Trouble"},
{"jamesperis", "James Peris: No License Nor Control"},
{"kulivocko", "Kulivocko"},
+ {"lifein3minutes", "Life In 3 Minutes"},
{"lonelyrobot", "Project Lonely Robot"},
{"looky", "Looky"},
{"julia", "J.U.L.I.A."},
{"mirage", "Mirage"},
+ {"nighttrain", "Night Train"},
+ {"oknytt", "Oknytt"},
{"paintaria", "Paintaria"},
{"pigeons", "Pigeons in the Park"},
{"projectdoom", "Project: Doom"},
+ {"projectjoe", "Project Joe"},
{"reversion1", "Reversion: The Escape"},
{"reversion2", "Reversion: The Meeting"},
- {"rhiannon", "Rhiannon: Curse of the four Branches"},
- {"ritter", "1 1/2 Ritter: Auf der Suche nach der hinreissenden Herzelinde"},
+ {"rhiannon", "Rhiannon: Curse of the four Branches"},
+ {"ritter", "1 1/2 Ritter: Auf der Suche nach der hinreissenden Herzelinde"},
{"rosemary", "Rosemary"},
+ {"satanandson", "Satan and Son"},
{"securanote", "Securanote"},
{"shaban", "Shaban"},
{"shinestar", "The Shine of a Star"},
{"spaceinvaders", "Space Invaders"},
{"spacemadness", "Space Madness"},
+ {"sofiasdebt", "Sofia's Debt"},
+ {"theancientmark1", "The Ancient Mark - Episode 1"},
{"thebox", "The Box"},
+ {"thekite", "The Kite"},
{"tib", "Fairy Tales About Toshechka and Boshechka"},
{"tradestory", "The Trader of Stories"},
{"twc", "the white chamber"},
+ {"war", "War"},
+ {"vsevolod", "Vsevolod"},
{"wintermute", "Wintermute engine game"},
{"wtetris", "Wilma Tetris"},
{"zilm", "Zilm: A Game of Reflex"},
@@ -108,6 +121,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Boredom of Agustin Cordes
+ {
+ "agustin",
+ "",
+ AD_ENTRY1s("data.dcp", "abb79c16c9b92e9b06525a4c7c3f5861", 2461949),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Beyond the Threshold
{
"bthreshold",
@@ -128,6 +151,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Bickadoodle (Ver 1.1)
+ {
+ "bickadoodle",
+ "Version 1.1",
+ AD_ENTRY1s("data.dcp", "8bb52ac9a9ee129c5059e8e808b669d7", 35337760),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Bickadoodle (download from http://aethericgames.com/games/bickadoodle/download-bickadoodle/)
{
"bickadoodle",
@@ -251,6 +284,17 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_TESTING,
GUIO0()
},
+ // Conspiracao Dumont
+ {
+ "conspiracao",
+ "",
+ AD_ENTRY1s("ConspiracaoDumont.exe", "106f3f2c8f18bb5ffffeed634ace256c", 32908032),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
// Corrosion: Cold Winter Waiting
{
"corrosion",
@@ -442,6 +486,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Four
+ {
+ "four",
+ "",
+ AD_ENTRY1s("data.dcp", "ec05cd5e37c9a524053b8859635a4234", 62599855),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Framed
{
"framed",
@@ -621,6 +675,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_DEMO,
GUIO0()
},
+ // Life In 3 Minutes
+ {
+ "lifein3minutes",
+ "",
+ AD_ENTRY1s("data.dcp", "c6368950e37a95bf098b02b4eaa5b929", 141787214),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Looky Demo (English)
{
"looky",
@@ -675,6 +739,27 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Oknytt
+ {
+ "oknytt",
+ "Version 1.0",
+ AD_ENTRY1s("data.dcp", "6456cf8f429905c83f07509f9da536dd", 109502959),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // Night Train Demo
+ {
+ "nighttrain",
+ "",
+ AD_ENTRY1s("data.dcp", "5a027ef84b083a730c9a4c85ec1d3a32", 131760816),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
// Paintaria
{
"paintaria",
@@ -705,6 +790,17 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Project Joe
+ {
+ "projectjoe",
+ "",
+ AD_ENTRY1s("data.dcp", "ada3c08542901295076b5349e655e73f", 160780037),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
// Project Lonely Robot
{
"lonelyrobot",
@@ -1084,6 +1180,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Rhiannon: Curse of the four Branches (English PC DVD)
+ {
+ "rhiannon",
+ "DVD",
+ AD_ENTRY1s("data.dcp", "6736bbc921bb6ce5161b3ad095a97bd4", 1053441028),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// 1 1/2 Ritter: Auf der Suche nach der hinreissenden Herzelinde
{
"ritter",
@@ -1094,6 +1200,17 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Satan and Son
+ {
+ "satanandson",
+ "",
+ AD_ENTRY1s("data.dcp", "16a6ba8174b697bbba9299619d1e20c4", 67539054),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
// Rosemary
{
"rosemary",
@@ -1134,6 +1251,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Sofia's Debt
+ {
+ "sofiasdebt",
+ "",
+ AD_ENTRY1s("SD.exe", "e9515f9ba1a2925bb6733476a826a650", 9915047),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Space Invaders (Demo)
{
"spaceinvaders",
@@ -1155,6 +1282,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // The Ancient Mark - Episode 1
+ {
+ "theancientmark1",
+ "",
+ AD_ENTRY1s("data.dcp", "ca04c26f03b2bd307368b306b297ddd7", 364664692),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// The Box
{
"thebox",
@@ -1165,6 +1302,56 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // The Kite (Version 1.1)
+ {
+ "thekite",
+ "Version 1.1",
+ AD_ENTRY1s("data.dcp", "92d29428f464469bda2d81b03d4d5c3e", 47332296),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // The Kite (Version 1.2.e)
+ {
+ "thekite",
+ "Version 1.2.e",
+ AD_ENTRY1s("data.dcp", "92451578b1bdd2b32a1db592a4f6d5fc", 47360539),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // The Kite (Version 1.2.i) (Italian)
+ {
+ "thekite",
+ "Version 1.2.i",
+ AD_ENTRY1s("data.dcp", "d3435b106a1b3b4c1df8ad596d271586", 47509274),
+ Common::IT_ITA,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // The Kite (Version 1.2.r) (Russian)
+ {
+ "thekite",
+ "Version 1.2.r",
+ AD_ENTRY1s("data.dcp", "d531e097dd884737469da014ed882cde", 47554582 ),
+ Common::RU_RUS,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // The Kite (Version 1.3.e)
+ {
+ "thekite",
+ "Version 1.3.e",
+ AD_ENTRY1s("data.dcp", "9761827b51370263b7623721545d7627", 47382987),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Fairy Tales About Toshechka and Boshechka
{
"tib",
@@ -1196,6 +1383,27 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Vsevolod Prologue (Demo)
+ {
+ "vsevolod",
+ "Prologue",
+ AD_ENTRY1s("data.dcp", "f2dcffd2692dbfcc9371fa1a87970fe7", 388669493),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
+ // War
+ {
+ "war",
+ "",
+ AD_ENTRY1s("data.dcp", "003e317cda6d0137bbd5e5d7f089ee4d", 32591890),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Wilma Tetris
{
"wtetris",
diff --git a/engines/wintermute/graphics/transform_struct.cpp b/engines/wintermute/graphics/transform_struct.cpp
deleted file mode 100644
index 9483975d94..0000000000
--- a/engines/wintermute/graphics/transform_struct.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "engines/wintermute/graphics/transform_struct.h"
-#include "engines/wintermute/graphics/transparent_surface.h"
-
-namespace Wintermute {
-void TransformStruct::init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, Point32 offset) {
- _zoom = zoom;
- _angle = angle;
- _hotspot = hotspot;
- _blendMode = blendMode;
- _rgbaMod = rgbaMod;
- _alphaDisable = alphaDisable;
- _flip = 0;
- _flip += TransparentSurface::FLIP_H * mirrorX;
- _flip += TransparentSurface::FLIP_V * mirrorY;
- _offset = offset;
- _numTimesX = 1;
- _numTimesY = 1;
-}
-
-TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) {
- init(Point32(zoomX, zoomY),
- angle,
- Point32(hotspotX, hotspotY),
- false,
- blendMode,
- rgbaMod,
- mirrorX, mirrorY,
- Point32(offsetX, offsetY));
-}
-
-TransformStruct::TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) {
- init(Point32((int32)(zoomX / 100.0 * kDefaultZoomX),
- (int32)(zoomY / 100.0 * kDefaultZoomY)),
- angle,
- Point32(hotspotX, hotspotY),
- false,
- blendMode,
- rgbaMod,
- mirrorX, mirrorY,
- Point32(offsetX, offsetY));
-}
-
-TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY) {
- init(Point32(zoomX, zoomY),
- kDefaultAngle,
- Point32(kDefaultHotspotX, kDefaultHotspotY),
- false,
- blendMode,
- rgbaMod,
- mirrorX,
- mirrorY,
- Point32(kDefaultOffsetX, kDefaultOffsetY));
-}
-
-TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY) {
- init(Point32(zoomX, zoomY),
- angle,
- Point32(hotspotX, hotspotY),
- true,
- BLEND_NORMAL,
- kDefaultRgbaMod,
- false, false,
- Point32(kDefaultOffsetX, kDefaultOffsetY));
-}
-
-TransformStruct::TransformStruct(int32 numTimesX, int32 numTimesY) {
- init(Point32(kDefaultZoomX, kDefaultZoomY),
- kDefaultAngle,
- Point32(kDefaultHotspotX, kDefaultHotspotY),
- false,
- BLEND_NORMAL,
- kDefaultRgbaMod,
- false, false,
- Point32(kDefaultOffsetX, kDefaultOffsetY));
- _numTimesX = numTimesX;
- _numTimesY = numTimesY;
-}
-
-TransformStruct::TransformStruct() {
- init(Point32(kDefaultZoomX, kDefaultZoomY),
- kDefaultAngle,
- Point32(kDefaultHotspotX, kDefaultHotspotY),
- true,
- BLEND_NORMAL,
- kDefaultRgbaMod,
- false, false,
- Point32(kDefaultOffsetX, kDefaultOffsetY));
-}
-
-bool TransformStruct::getMirrorX() const {
- return (bool)(_flip & TransparentSurface::FLIP_H);
-}
-
-bool TransformStruct::getMirrorY() const {
- return (bool)(_flip & TransparentSurface::FLIP_V);
-}
-} // End of namespace Wintermute
diff --git a/engines/wintermute/graphics/transform_struct.h b/engines/wintermute/graphics/transform_struct.h
deleted file mode 100644
index f80b0967cb..0000000000
--- a/engines/wintermute/graphics/transform_struct.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef WINTERMUTE_TRANSFORM_STRUCT_H
-#define WINTERMUTE_TRANSFORM_STRUCT_H
-
-#include "engines/wintermute/math/rect32.h"
-#include "engines/wintermute/dctypes.h"
-
-namespace Wintermute {
-/**
- * Contains all the required information that define a transform.
- * Same source sprite + same TransformStruct = Same resulting sprite.
- * Has a number of overloaded constructors to accomodate various argument lists.
- */
-
-const int32 kDefaultZoomX = 100;
-const int32 kDefaultZoomY = 100;
-const uint32 kDefaultRgbaMod = 0xFFFFFFFF;
-const int32 kDefaultHotspotX = 0;
-const int32 kDefaultHotspotY = 0;
-const int32 kDefaultOffsetX = 0;
-const int32 kDefaultOffsetY = 0;
-const int32 kDefaultAngle = 0;
-
-struct TransformStruct {
-private:
- void init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX, bool mirrorY, Point32 offset);
-
-public:
- TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0);
- TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0);
- TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false);
- TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX = 0, int32 hotspotY = 0);
- TransformStruct(int32 numTimesX, int32 numTimesY);
- TransformStruct();
-
- Point32 _zoom; ///< Zoom; 100 = no zoom
- Point32 _hotspot; ///< Position of the hotspot
- int32 _angle; ///< Rotation angle, in degrees
- byte _flip; ///< Bitflag: see TransparentSurface::FLIP_XXX
- bool _alphaDisable;
- TSpriteBlendMode _blendMode;
- uint32 _rgbaMod; ///< RGBa
- Point32 _offset;
- int32 _numTimesX;
- int32 _numTimesY;
-
- bool getMirrorX() const;
- bool getMirrorY() const;
-
- bool operator==(const TransformStruct &compare) const {
- return (compare._angle == _angle &&
- compare._flip == _flip &&
- compare._zoom == _zoom &&
- compare._offset == _offset &&
- compare._alphaDisable == _alphaDisable &&
- compare._rgbaMod == _rgbaMod &&
- compare._blendMode == _blendMode &&
- compare._numTimesX == _numTimesX &&
- compare._numTimesY == _numTimesY
- );
- }
-
- bool operator!=(const TransformStruct &compare) const {
- return !(compare == *this);
- }
-};
-} // End of namespace Wintermute
-#endif
diff --git a/engines/wintermute/graphics/transform_tools.cpp b/engines/wintermute/graphics/transform_tools.cpp
deleted file mode 100644
index 7a009c26fa..0000000000
--- a/engines/wintermute/graphics/transform_tools.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-
-#include "engines/wintermute/graphics/transform_tools.h"
-#include <math.h>
-
-namespace Wintermute {
-
-FloatPoint TransformTools::transformPoint(FloatPoint point, const float rotate, const Point32 &zoom, const bool mirrorX, const bool mirrorY) {
- float rotateRad = rotate * M_PI / 180.0f;
- float x = point.x;
- float y = point.y;
- x = (x * zoom.x) / kDefaultZoomX;
- y = (y * zoom.y) / kDefaultZoomY;
-#if 0
- // TODO: Mirroring should be done before rotation, but the blitting
- // code does the inverse, so we match that for now.
- if (mirrorX)
- x *= -1;
- if (mirrorY)
- y *= -1;
-#endif
- FloatPoint newPoint;
- newPoint.x = x * cos(rotateRad) - y * sin(rotateRad);
- newPoint.y = x * sin(rotateRad) + y * cos(rotateRad);
- if (mirrorX) {
- newPoint.x *= -1;
- }
- if (mirrorY) {
- newPoint.y *= -1;
- }
- return newPoint;
-}
-
-Rect32 TransformTools::newRect(const Rect32 &oldRect, const TransformStruct &transform, Point32 *newHotspot) {
- Point32 nw(oldRect.left, oldRect.top);
- Point32 ne(oldRect.right, oldRect.top);
- Point32 sw(oldRect.left, oldRect.bottom);
- Point32 se(oldRect.right, oldRect.bottom);
-
- FloatPoint nw1, ne1, sw1, se1;
-
- nw1 = transformPoint(nw - transform._hotspot, transform._angle, transform._zoom);
- ne1 = transformPoint(ne - transform._hotspot, transform._angle, transform._zoom);
- sw1 = transformPoint(sw - transform._hotspot, transform._angle, transform._zoom);
- se1 = transformPoint(se - transform._hotspot, transform._angle, transform._zoom);
-
- float top = MIN(nw1.y, MIN(ne1.y, MIN(sw1.y, se1.y)));
- float bottom = MAX(nw1.y, MAX(ne1.y, MAX(sw1.y, se1.y)));
- float left = MIN(nw1.x, MIN(ne1.x, MIN(sw1.x, se1.x)));
- float right = MAX(nw1.x, MAX(ne1.x, MAX(sw1.x, se1.x)));
-
- if (newHotspot) {
- newHotspot->y = (uint32)(-floor(top));
- newHotspot->x = (uint32)(-floor(left));
- }
-
- Rect32 res;
- res.top = (int32)(floor(top)) + transform._hotspot.y;
- res.bottom = (int32)(ceil(bottom)) + transform._hotspot.y;
- res.left = (int32)(floor(left)) + transform._hotspot.x;
- res.right = (int32)(ceil(right)) + transform._hotspot.x;
-
- return res;
-}
-
-} // End of namespace Wintermute
diff --git a/engines/wintermute/graphics/transform_tools.h b/engines/wintermute/graphics/transform_tools.h
deleted file mode 100644
index e259db04e5..0000000000
--- a/engines/wintermute/graphics/transform_tools.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef WINTERMUTE_TRANSFORM_TOOLS_H
-#define WINTERMUTE_TRANSFORM_TOOLS_H
-
-#include "engines/wintermute/math/rect32.h"
-#include "engines/wintermute/math/floatpoint.h"
-#include "engines/wintermute/graphics/transform_struct.h"
-
-namespace Wintermute {
-
-class TransformTools {
-public:
- /**
- * Basic transform (scale + rotate) for a single point
- */
- static FloatPoint transformPoint(FloatPoint point, const float rotate, const Point32 &zoom, const bool mirrorX = false, const bool mirrorY = false);
-
- /**
- * @param &point the point on which the transform is to be applied
- * @param rotate the angle in degrees
- * @param &zoom zoom x,y in percent
- * @param mirrorX flip along the vertical axis?
- * @param mirrorY flip along the horizontal axis?
- * @return the smallest rect that can contain the transformed sprite
- * and, as a side-effect, "newHotspot" will tell you where the hotspot will
- * have ended up in the new rect, for centering.
- */
- static Rect32 newRect(const Rect32 &oldRect, const TransformStruct &transform, Point32 *newHotspot);
-};
-
-} // End of namespace Wintermute
-#endif
diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp
deleted file mode 100644
index 5fe0d13766..0000000000
--- a/engines/wintermute/graphics/transparent_surface.cpp
+++ /dev/null
@@ -1,950 +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.
- *
- *
- * The bottom part of this is file is adapted from SDL_rotozoom.c. The
- * relevant copyright notice for those specific functions can be found at the
- * top of that section.
- *
- */
-
-
-
-#include "common/algorithm.h"
-#include "common/endian.h"
-#include "common/util.h"
-#include "common/rect.h"
-#include "common/math.h"
-#include "common/textconsole.h"
-#include "graphics/primitives.h"
-#include "engines/wintermute/graphics/transparent_surface.h"
-#include "engines/wintermute/graphics/transform_tools.h"
-
-//#define ENABLE_BILINEAR
-
-namespace Wintermute {
-
-void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep);
-void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep);
-
-// These gather together various blendPixel functions for use with templates.
-
-class BlenderAdditive {
-public:
- inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb);
- inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb);
- inline void blendPixel(byte *in, byte *out);
- inline void blendPixel(byte *in, byte *out, int colorMod);
-};
-
-class BlenderSubtractive {
-public:
- inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb);
- inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb);
- inline void blendPixel(byte *in, byte *out);
- inline void blendPixel(byte *in, byte *out, int colorMod);
-};
-
-class BlenderNormal {
-public:
- inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb);
- inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb);
- inline void blendPixel(byte *in, byte *out);
- inline void blendPixel(byte *in, byte *out, int colorMod);
-};
-
-/**
- * Perform additive blending of a pixel, applying beforehand a given colormod.
- * @param ina, inr, ing, inb: the input pixel, split into its components.
- * @param *outa, *outr, *outg, *outb pointer to the output pixel.
- * @param *outa, *outr, *outg, *outb pointer to the colormod components.
- */
-void BlenderAdditive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) {
- if (*ca != 255) {
- ina = (ina) * (*ca) >> 8;
- }
-
- if (ina == 0) {
- return;
- } else {
- if (*cb != 255) {
- *outb = MIN(*outb + ((inb * (*cb) * ina) >> 16), 255);
- } else {
- *outb = MIN(*outb + (inb * ina >> 8), 255);
- }
-
- if (*cg != 255) {
- *outg = MIN(*outg + ((ing * (*cg) * ina) >> 16), 255);
- } else {
- *outg = MIN(*outg + (ing * ina >> 8), 255);
- }
-
- if (*cr != 255) {
- *outr = MIN(*outr + ((inr * (*cr) * ina) >> 16), 255);
- } else {
- *outr = MIN(*outr + (inr * ina >> 8), 255);
- }
- }
-}
-
-/**
- * Perform subtractive blending of a pixel, applying beforehand a given colormod.
- * @param ina, inr, ing, inb: the input pixel, split into its components.
- * @param *outa, *outr, *outg, *outb pointer to the output pixel.
- * @param *outa, *outr, *outg, *outb pointer to the colormod components.
- */
-void BlenderSubtractive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) {
- //if (*ca != 255) {
- // ina = ina * (*ca) >> 8;
- // }
-
- // As weird as it is, evidence suggests that alphamod is ignored when doing
- // subtractive...
-
- // TODO if ina == 255 fast version
-
- if (ina == 0) {
- return;
- } else {
- if (*cb != 255) {
- *outb = MAX(*outb - ((inb * (*cb) * (*outb) * ina) >> 24), 0);
- } else {
- *outb = MAX(*outb - (inb * (*outb) * ina >> 16), 0);
- }
-
- if (*cg != 255) {
- *outg = MAX(*outg - ((ing * (*cg) * (*outg) * ina) >> 24), 0);
- } else {
- *outg = MAX(*outg - (ing * (*outg) * ina >> 16), 0);
- }
-
- if (*cr != 255) {
- *outr = MAX(*outr - ((inr * (*cr) * (*outr) * ina) >> 24), 0);
- } else {
- *outr = MAX(*outr - (inr * (*outr) * ina >> 16), 0);
- }
- }
-}
-
-/**
- * Perform "regular" alphablending of a pixel, applying beforehand a given colormod.
- * @param ina, inr, ing, inb: the input pixel, split into its components.
- * @param *outa, *outr, *outg, *outb pointer to the output pixel.
- * @param *outa, *outr, *outg, *outb pointer to the colormod components.
- */
-
-void BlenderNormal::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) {
- if (*ca != 255) {
- ina = ina * (*ca) >> 8;
- }
-
- if (ina == 0) {
- return;
- } else if (ina == 255) {
- if (*cb != 255) {
- *outb = (inb * (*cb)) >> 8;
- } else {
- *outb = inb;
- }
-
- if (*cr != 255) {
- *outr = (inr * (*cr)) >> 8;
- } else {
- *outr = inr;
- }
-
- if (*cg != 255) {
- *outg = (ing * (*cg)) >> 8;
- } else {
- *outg = ing;
- }
-
- *outa = ina;
-
- return;
-
- } else {
-
- *outa = 255;
- *outb = (*outb * (255 - ina) >> 8);
- *outr = (*outr * (255 - ina) >> 8);
- *outg = (*outg * (255 - ina) >> 8);
-
- if (*cb == 0) {
- *outb = *outb;
- } else if (*cb != 255) {
- *outb = *outb + (inb * ina * (*cb) >> 16);
- } else {
- *outb = *outb + (inb * ina >> 8);
- }
-
- if (*cr == 0) {
- *outr = *outr;
- } else if (*cr != 255) {
- *outr = *outr + (inr * ina * (*cr) >> 16);
- } else {
- *outr = *outr + (inr * ina >> 8);
- }
-
- if (*cg == 0) {
- *outg = *outg;
- } else if (*cg != 255) {
- *outg = *outg + (ing * ina * (*cg) >> 16);
- } else {
- *outg = *outg + (ing * ina >> 8);
- }
-
- return;
- }
-}
-
-/**
- * Perform "regular" alphablending of a pixel.
- * @param ina, inr, ing, inb: the input pixel, split into its components.
- * @param *outa, *outr, *outg, *outb pointer to the output pixel.
- */
-
-void BlenderNormal::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) {
-
- if (ina == 0) {
- return;
- } else if (ina == 255) {
- *outb = inb;
- *outg = ing;
- *outr = inr;
- *outa = ina;
- return;
- } else {
- *outa = 255;
- *outb = ((inb * ina) + *outb * (255 - ina)) >> 8;
- *outg = ((ing * ina) + *outg * (255 - ina)) >> 8;
- *outr = ((inr * ina) + *outr * (255 - ina)) >> 8;
- }
-}
-
-/**
- * Perform subtractive blending of a pixel.
- * @param ina, inr, ing, inb: the input pixel, split into its components.
- * @param *outa, *outr, *outg, *outb pointer to the output pixel.
- */
-void BlenderSubtractive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) {
-
- if (ina == 0) {
- return;
- } else if (ina == 255) {
- *outa = *outa;
- *outr = *outr - (inr * (*outr) >> 8);
- *outg = *outg - (ing * (*outg) >> 8);
- *outb = *outb - (inb * (*outb) >> 8);
- return;
- } else {
- *outa = *outa;
- *outb = MAX(*outb - ((inb * (*outb)) * ina >> 16), 0);
- *outg = MAX(*outg - ((ing * (*outg)) * ina >> 16), 0);
- *outr = MAX(*outr - ((inr * (*outr)) * ina >> 16), 0);
- return;
- }
-}
-
-/**
- * Perform additive blending of a pixel.
- * @param ina, inr, ing, inb: the input pixel, split into its components.
- * @param *outa, *outr, *outg, *outb pointer to the output pixel.
- */
-void BlenderAdditive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) {
-
- if (ina == 0) {
- return;
- } else if (ina == 255) {
- *outa = *outa;
- *outr = MIN(*outr + inr, 255);
- *outg = MIN(*outg + ing, 255);
- *outb = MIN(*outb + inb, 255);
- return;
- } else {
- *outa = *outa;
- *outb = MIN((inb * ina >> 8) + *outb, 255);
- *outg = MIN((ing * ina >> 8) + *outg, 255);
- *outr = MIN((inr * ina >> 8) + *outr, 255);
- return;
- }
-}
-
-
-TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {}
-
-TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _alphaMode(ALPHA_FULL) {
- if (copyData) {
- copyFrom(surf);
- } else {
- w = surf.w;
- h = surf.h;
- pitch = surf.pitch;
- format = surf.format;
- // We need to cast the const qualifier away here because 'pixels'
- // always needs to be writable. 'surf' however is a constant Surface,
- // thus getPixels will always return const pixel data.
- pixels = const_cast<void *>(surf.getPixels());
- }
-}
-
-/**
- * Optimized version of doBlit to be used w/opaque blitting (no alpha).
- */
-void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
-
- byte *in;
- byte *out;
-
- for (uint32 i = 0; i < height; i++) {
- out = outo;
- in = ino;
- memcpy(out, in, width * 4);
- for (uint32 j = 0; j < width; j++) {
- out[TransparentSurface::kAIndex] = 0xFF;
- out += 4;
- }
- outo += pitch;
- ino += inoStep;
- }
-}
-
-/**
- * Optimized version of doBlit to be used w/binary blitting (blit or no-blit, no blending).
- */
-void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
-
- byte *in;
- byte *out;
-
- for (uint32 i = 0; i < height; i++) {
- out = outo;
- in = ino;
- for (uint32 j = 0; j < width; j++) {
- uint32 pix = *(uint32 *)in;
- int a = (pix >> TransparentSurface::kAShift) & 0xff;
-
- if (a == 0) { // Full transparency
- } else { // Full opacity (Any value not exactly 0 is Opaque here)
- *(uint32 *)out = pix;
- out[TransparentSurface::kAIndex] = 0xFF;
- }
- out += 4;
- in += inStep;
- }
- outo += pitch;
- ino += inoStep;
- }
-}
-
-/**
- * What we have here is a template method that calls blendPixel() from a different
- * class - the one we call it with - thus performing a different type of blending.
- *
- * @param ino a pointer to the input surface
- * @param outo a pointer to the output surface
- * @param width width of the input surface
- * @param height height of the input surface
- * @param pitch pitch of the output surface - that is, width in bytes of every row, usually bpp * width of the TARGET surface (the area we are blitting to might be smaller, do the math)
- * @inStep size in bytes to skip to address each pixel, usually bpp of the source surface
- * @inoStep width in bytes of every row on the *input* surface / kind of like pitch
- * @color colormod in 0xAARRGGBB format - 0xFFFFFFFF for no colormod
- */
-
-template<class Blender>
-void doBlit(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
- Blender b;
- byte *in;
- byte *out;
-
- if (color == 0xffffffff) {
-
- for (uint32 i = 0; i < height; i++) {
- out = outo;
- in = ino;
- for (uint32 j = 0; j < width; j++) {
-
- byte *outa = &out[TransparentSurface::kAIndex];
- byte *outr = &out[TransparentSurface::kRIndex];
- byte *outg = &out[TransparentSurface::kGIndex];
- byte *outb = &out[TransparentSurface::kBIndex];
-
- b.blendPixel(in[TransparentSurface::kAIndex],
- in[TransparentSurface::kRIndex],
- in[TransparentSurface::kGIndex],
- in[TransparentSurface::kBIndex],
- outa, outr, outg, outb);
-
- in += inStep;
- out += 4;
- }
- outo += pitch;
- ino += inoStep;
- }
- } else {
-
- byte ca = (color >> TransparentSurface::kAModShift) & 0xFF;
- byte cr = (color >> TransparentSurface::kRModShift) & 0xFF;
- byte cg = (color >> TransparentSurface::kGModShift) & 0xFF;
- byte cb = (color >> TransparentSurface::kBModShift) & 0xFF;
-
- for (uint32 i = 0; i < height; i++) {
- out = outo;
- in = ino;
- for (uint32 j = 0; j < width; j++) {
-
- byte *outa = &out[TransparentSurface::kAIndex];
- byte *outr = &out[TransparentSurface::kRIndex];
- byte *outg = &out[TransparentSurface::kGIndex];
- byte *outb = &out[TransparentSurface::kBIndex];
-
- b.blendPixel(in[TransparentSurface::kAIndex],
- in[TransparentSurface::kRIndex],
- in[TransparentSurface::kGIndex],
- in[TransparentSurface::kBIndex],
- outa, outr, outg, outb, &ca, &cr, &cg, &cb);
- in += inStep;
- out += 4;
- }
- outo += pitch;
- ino += inoStep;
- }
- }
-}
-
-Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, TSpriteBlendMode blendMode) {
-
- Common::Rect retSize;
- retSize.top = 0;
- retSize.left = 0;
- retSize.setWidth(0);
- retSize.setHeight(0);
- // Check if we need to draw anything at all
- int ca = (color >> 24) & 0xff;
-
- if (ca == 0) {
- return retSize;
- }
-
- // Create an encapsulating surface for the data
- TransparentSurface srcImage(*this, false);
- // TODO: Is the data really in the screen format?
- if (format.bytesPerPixel != 4) {
- warning("TransparentSurface can only blit 32 bpp images");
- return retSize;
- }
-
- if (pPartRect) {
-
- int xOffset = pPartRect->left;
- int yOffset = pPartRect->top;
-
- if (flipping & FLIP_V) {
- yOffset = srcImage.h - pPartRect->bottom;
- }
-
- if (flipping & FLIP_H) {
- xOffset = srcImage.w - pPartRect->right;
- }
-
- srcImage.pixels = getBasePtr(xOffset, yOffset);
- srcImage.w = pPartRect->width();
- srcImage.h = pPartRect->height();
-
- debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping,
- pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height);
- } else {
-
- debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0,
- srcImage.w, srcImage.h, color, width, height);
- }
-
- if (width == -1) {
- width = srcImage.w;
- }
- if (height == -1) {
- height = srcImage.h;
- }
-
-#ifdef SCALING_TESTING
- // Hardcode scaling to 66% to test scaling
- width = width * 2 / 3;
- height = height * 2 / 3;
-#endif
-
- Graphics::Surface *img = nullptr;
- Graphics::Surface *imgScaled = nullptr;
- byte *savedPixels = nullptr;
- if ((width != srcImage.w) || (height != srcImage.h)) {
- // Scale the image
- img = imgScaled = srcImage.scale(width, height);
- savedPixels = (byte *)img->getPixels();
- } else {
- img = &srcImage;
- }
-
- // Handle off-screen clipping
- if (posY < 0) {
- img->h = MAX(0, (int)img->h - -posY);
- img->setPixels((byte *)img->getBasePtr(0, -posY));
- posY = 0;
- }
-
- if (posX < 0) {
- img->w = MAX(0, (int)img->w - -posX);
- img->setPixels((byte *)img->getBasePtr(-posX, 0));
- posX = 0;
- }
-
- img->w = CLIP((int)img->w, 0, (int)MAX((int)target.w - posX, 0));
- img->h = CLIP((int)img->h, 0, (int)MAX((int)target.h - posY, 0));
-
- if ((img->w > 0) && (img->h > 0)) {
- int xp = 0, yp = 0;
-
- int inStep = 4;
- int inoStep = img->pitch;
- if (flipping & TransparentSurface::FLIP_H) {
- inStep = -inStep;
- xp = img->w - 1;
- }
-
- if (flipping & TransparentSurface::FLIP_V) {
- inoStep = -inoStep;
- yp = img->h - 1;
- }
-
- byte *ino = (byte *)img->getBasePtr(xp, yp);
- byte *outo = (byte *)target.getBasePtr(posX, posY);
-
- if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_OPAQUE) {
- doBlitOpaqueFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
- } else if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_BINARY) {
- doBlitBinaryFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
- } else {
- if (blendMode == BLEND_ADDITIVE) {
- doBlit<BlenderAdditive>(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color);
- } else if (blendMode == BLEND_SUBTRACTIVE) {
- doBlit<BlenderSubtractive>(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color);
- } else {
- assert(blendMode == BLEND_NORMAL);
- doBlit<BlenderNormal>(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color);
- }
- }
-
- }
-
- retSize.setWidth(img->w);
- retSize.setHeight(img->h);
-
- if (imgScaled) {
- imgScaled->setPixels(savedPixels);
- imgScaled->free();
- delete imgScaled;
- }
-
- return retSize;
-}
-
-/**
- * Writes a color key to the alpha channel of the surface
- * @param rKey the red component of the color key
- * @param gKey the green component of the color key
- * @param bKey the blue component of the color key
- * @param overwriteAlpha if true, all other alpha will be set fully opaque
- */
-void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha) {
- assert(format.bytesPerPixel == 4);
- for (int i = 0; i < h; i++) {
- for (int j = 0; j < w; j++) {
- uint32 pix = ((uint32 *)pixels)[i * w + j];
- uint8 r, g, b, a;
- format.colorToARGB(pix, a, r, g, b);
- if (r == rKey && g == gKey && b == bKey) {
- a = 0;
- ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b);
- } else if (overwriteAlpha) {
- a = 255;
- ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b);
- }
- }
- }
-}
-
-TransparentSurface::AlphaType TransparentSurface::getAlphaMode() const {
- return _alphaMode;
-}
-
-void TransparentSurface::setAlphaMode(TransparentSurface::AlphaType mode) {
- _alphaMode = mode;
-}
-
-
-
-
-
-
-/*
-
-The below two functions are adapted from SDL_rotozoom.c,
-taken from SDL_gfx-2.0.18.
-
-Its copyright notice:
-
-=============================================================================
-SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
-
-Copyright (C) 2001-2012 Andreas Schiffler
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-claim that you wrote the original software. If you use this software
-in a product, an acknowledgment in the product documentation would be
-appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-
-Andreas Schiffler -- aschiffler at ferzkopp dot net
-=============================================================================
-
-
-The functions have been adapted for different structures and coordinate
-systems.
-
-*/
-
-
-
-
-
-TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const {
-
- assert(transform._angle != 0); // This would not be ideal; rotoscale() should never be called in conditional branches where angle = 0 anyway.
-
- Point32 newHotspot;
- Common::Rect srcRect(0, 0, (int16)w, (int16)h);
- Rect32 rect = TransformTools::newRect(Rect32(srcRect), transform, &newHotspot);
- Common::Rect dstRect(0, 0, (int16)(rect.right - rect.left), (int16)(rect.bottom - rect.top));
-
- TransparentSurface *target = new TransparentSurface();
- assert(format.bytesPerPixel == 4);
-
- int srcW = w;
- int srcH = h;
- int dstW = dstRect.width();
- int dstH = dstRect.height();
-
- target->create((uint16)dstW, (uint16)dstH, this->format);
-
- if (transform._zoom.x == 0 || transform._zoom.y == 0) {
- return target;
- }
-
- uint32 invAngle = 360 - (transform._angle % 360);
- float invCos = cos(invAngle * M_PI / 180.0);
- float invSin = sin(invAngle * M_PI / 180.0);
-
- struct tColorRGBA { byte r; byte g; byte b; byte a; };
- int icosx = (int)(invCos * (65536.0f * kDefaultZoomX / transform._zoom.x));
- int isinx = (int)(invSin * (65536.0f * kDefaultZoomX / transform._zoom.x));
- int icosy = (int)(invCos * (65536.0f * kDefaultZoomY / transform._zoom.y));
- int isiny = (int)(invSin * (65536.0f * kDefaultZoomY / transform._zoom.y));
-
-
- bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor
-
- int xd = (srcRect.left + transform._hotspot.x) << 16;
- int yd = (srcRect.top + transform._hotspot.y) << 16;
- int cx = newHotspot.x;
- int cy = newHotspot.y;
-
- int ax = -icosx * cx;
- int ay = -isiny * cx;
- int sw = srcW - 1;
- int sh = srcH - 1;
-
- tColorRGBA *pc = (tColorRGBA*)target->getBasePtr(0, 0);
-
- for (int y = 0; y < dstH; y++) {
- int t = cy - y;
- int sdx = ax + (isinx * t) + xd;
- int sdy = ay - (icosy * t) + yd;
- for (int x = 0; x < dstW; x++) {
- int dx = (sdx >> 16);
- int dy = (sdy >> 16);
- if (flipx) {
- dx = sw - dx;
- }
- if (flipy) {
- dy = sh - dy;
- }
-
-#ifdef ENABLE_BILINEAR
- if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) {
- const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy);
- tColorRGBA c00, c01, c10, c11, cswap;
- c00 = *sp;
- sp += 1;
- c01 = *sp;
- sp += (this->pitch / 4);
- c11 = *sp;
- sp -= 1;
- c10 = *sp;
- if (flipx) {
- cswap = c00; c00=c01; c01=cswap;
- cswap = c10; c10=c11; c11=cswap;
- }
- if (flipy) {
- cswap = c00; c00=c10; c10=cswap;
- cswap = c01; c01=c11; c11=cswap;
- }
- /*
- * Interpolate colors
- */
- int ex = (sdx & 0xffff);
- int ey = (sdy & 0xffff);
- int t1, t2;
- t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
- t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
- pc->r = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
- t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
- pc->g = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
- t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
- pc->b = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
- t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
- pc->a = (((t2 - t1) * ey) >> 16) + t1;
- }
-#else
- if ((dx >= 0) && (dy >= 0) && (dx < srcW) && (dy < srcH)) {
- const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy);
- *pc = *sp;
- }
-#endif
- sdx += icosx;
- sdy += isiny;
- pc++;
- }
- }
- return target;
-}
-
-TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const {
-
- Common::Rect srcRect(0, 0, (int16)w, (int16)h);
- Common::Rect dstRect(0, 0, (int16)newWidth, (int16)newHeight);
-
- TransparentSurface *target = new TransparentSurface();
-
- assert(format.bytesPerPixel == 4);
-
- int srcW = srcRect.width();
- int srcH = srcRect.height();
- int dstW = dstRect.width();
- int dstH = dstRect.height();
-
- target->create((uint16)dstW, (uint16)dstH, this->format);
-
-#ifdef ENABLE_BILINEAR
-
- // NB: The actual order of these bytes may not be correct, but
- // since all values are treated equal, that does not matter.
- struct tColorRGBA { byte r; byte g; byte b; byte a; };
-
- bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor
-
-
- int *sax = new int[dstW + 1];
- int *say = new int[dstH + 1];
- assert(sax && say);
-
- /*
- * Precalculate row increments
- */
- int spixelw = (srcW - 1);
- int spixelh = (srcH - 1);
- int sx = (int) (65536.0f * (float) spixelw / (float) (dstW - 1));
- int sy = (int) (65536.0f * (float) spixelh / (float) (dstH - 1));
-
- /* Maximum scaled source size */
- int ssx = (srcW << 16) - 1;
- int ssy = (srcH << 16) - 1;
-
- /* Precalculate horizontal row increments */
- int csx = 0;
- int *csax = sax;
- for (int x = 0; x <= dstW; x++) {
- *csax = csx;
- csax++;
- csx += sx;
-
- /* Guard from overflows */
- if (csx > ssx) {
- csx = ssx;
- }
- }
-
- /* Precalculate vertical row increments */
- int csy = 0;
- int *csay = say;
- for (int y = 0; y <= dstH; y++) {
- *csay = csy;
- csay++;
- csy += sy;
-
- /* Guard from overflows */
- if (csy > ssy) {
- csy = ssy;
- }
- }
-
- const tColorRGBA *sp = (const tColorRGBA *) getBasePtr(0, 0);
- tColorRGBA *dp = (tColorRGBA *) target->getBasePtr(0, 0);
- int spixelgap = srcW;
-
- if (flipx) {
- sp += spixelw;
- }
- if (flipy) {
- sp += spixelgap * spixelh;
- }
-
- csay = say;
- for (int y = 0; y < dstH; y++) {
- const tColorRGBA *csp = sp;
- csax = sax;
- for (int x = 0; x < dstW; x++) {
- /*
- * Setup color source pointers
- */
- int ex = (*csax & 0xffff);
- int ey = (*csay & 0xffff);
- int cx = (*csax >> 16);
- int cy = (*csay >> 16);
-
- const tColorRGBA *c00, *c01, *c10, *c11;
- c00 = sp;
- c01 = sp;
- c10 = sp;
- if (cy < spixelh) {
- if (flipy) {
- c10 -= spixelgap;
- } else {
- c10 += spixelgap;
- }
- }
- c11 = c10;
- if (cx < spixelw) {
- if (flipx) {
- c01--;
- c11--;
- } else {
- c01++;
- c11++;
- }
- }
-
- /*
- * Draw and interpolate colors
- */
- int t1, t2;
- t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
- t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
- dp->r = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
- t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
- dp->g = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
- t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
- dp->b = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
- t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
- dp->a = (((t2 - t1) * ey) >> 16) + t1;
-
- /*
- * Advance source pointer x
- */
- int *salastx = csax;
- csax++;
- int sstepx = (*csax >> 16) - (*salastx >> 16);
- if (flipx) {
- sp -= sstepx;
- } else {
- sp += sstepx;
- }
-
- /*
- * Advance destination pointer x
- */
- dp++;
- }
- /*
- * Advance source pointer y
- */
- int *salasty = csay;
- csay++;
- int sstepy = (*csay >> 16) - (*salasty >> 16);
- sstepy *= spixelgap;
- if (flipy) {
- sp = csp - sstepy;
- } else {
- sp = csp + sstepy;
- }
- }
-
- delete[] sax;
- delete[] say;
-
-#else
-
- int *scaleCacheX = new int[dstW];
- for (int x = 0; x < dstW; x++) {
- scaleCacheX[x] = (x * srcW) / dstW;
- }
-
- for (int y = 0; y < dstH; y++) {
- uint32 *destP = (uint32 *)target->getBasePtr(0, y);
- const uint32 *srcP = (const uint32 *)getBasePtr(0, (y * srcH) / dstH);
- for (int x = 0; x < dstW; x++) {
- *destP++ = srcP[scaleCacheX[x]];
- }
- }
- delete[] scaleCacheX;
-
-#endif
-
- return target;
-
-}
-
-} // End of namespace Wintermute
diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h
deleted file mode 100644
index 4ad9bf07eb..0000000000
--- a/engines/wintermute/graphics/transparent_surface.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef GRAPHICS_TRANSPARENTSURFACE_H
-#define GRAPHICS_TRANSPARENTSURFACE_H
-
-#include "graphics/surface.h"
-#include "engines/wintermute/graphics/transform_struct.h"
-
-/*
- * This code is based on Broken Sword 2.5 engine
- *
- * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer
- *
- * Licensed under GNU GPL v2
- *
- */
-
-// TODO: Find a better solution for this.
-#define BS_RGB(R,G,B) (0xFF000000 | ((R) << 16) | ((G) << 8) | (B))
-#define BS_ARGB(A,R,G,B) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B))
-
-namespace Wintermute {
-
-/**
- * A transparent graphics surface, which implements alpha blitting.
- */
-struct TransparentSurface : public Graphics::Surface {
- TransparentSurface();
- TransparentSurface(const Graphics::Surface &surf, bool copyData = false);
-
- void setColorKey(char r, char g, char b);
- void disableColorKey();
-
- // Enums
- /**
- @brief The possible flipping parameters for the blit methode.
- */
- enum FLIP_FLAGS {
- /// The image will not be flipped.
- FLIP_NONE = 0,
- /// The image will be flipped at the horizontal axis.
- FLIP_H = 1,
- /// The image will be flipped at the vertical axis.
- FLIP_V = 2,
- /// The image will be flipped at the horizontal and vertical axis.
- FLIP_HV = FLIP_H | FLIP_V,
- /// The image will be flipped at the horizontal and vertical axis.
- FLIP_VH = FLIP_H | FLIP_V
- };
-
- enum AlphaType {
- ALPHA_OPAQUE = 0,
- ALPHA_BINARY = 1,
- ALPHA_FULL = 2
- };
-
-#ifdef SCUMM_LITTLE_ENDIAN
- static const int kAIndex = 0;
- static const int kBIndex = 1;
- static const int kGIndex = 2;
- static const int kRIndex = 3;
-#else
- static const int kAIndex = 3;
- static const int kBIndex = 2;
- static const int kGIndex = 1;
- static const int kRIndex = 0;
-#endif
-
- static const int kBShift = 8;//img->format.bShift;
- static const int kGShift = 16;//img->format.gShift;
- static const int kRShift = 24;//img->format.rShift;
- static const int kAShift = 0;//img->format.aShift;
-
-
- static const int kBModShift = 0;//img->format.bShift;
- static const int kGModShift = 8;//img->format.gShift;
- static const int kRModShift = 16;//img->format.rShift;
- static const int kAModShift = 24;//img->format.aShift;
-
-
- /**
- @brief renders the surface to another surface
- @param target a pointer to the target surface. In most cases this is the framebuffer.
- @param posX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.<br>
- The default value is 0.
- @param posY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.<br>
- The default value is 0.
- @param flipping how the the image should be flipped.<br>
- The default value is BS_Image::FLIP_NONE (no flipping)
- @param pPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.<br>
- This referes to the unflipped and unscaled image.<br>
- The default value is NULL.
- @param color an ARGB color value, which determines the parameters for the color modulation und alpha blending.<br>
- The alpha component of the color determines the alpha blending parameter (0 = no covering, 255 = full covering).<br>
- The color components determines the color for color modulation.<br>
- The default value is BS_ARGB(255, 255, 255, 255) (full covering, no color modulation).
- The macros BS_RGB and BS_ARGB can be used for the creation of the color value.
- @param width the output width of the screen section.
- The images will be scaled if the output width of the screen section differs from the image section.<br>
- The value -1 determines that the image should not be scaled.<br>
- The default value is -1.
- @param height the output height of the screen section.
- The images will be scaled if the output width of the screen section differs from the image section.<br>
- The value -1 determines that the image should not be scaled.<br>
- The default value is -1.
- @return returns false if the rendering failed.
- */
- Common::Rect blit(Graphics::Surface &target, int posX = 0, int posY = 0,
- int flipping = FLIP_NONE,
- Common::Rect *pPartRect = nullptr,
- uint color = BS_ARGB(255, 255, 255, 255),
- int width = -1, int height = -1,
- TSpriteBlendMode blend = BLEND_NORMAL);
- void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false);
-
- /**
- * @brief Scale function; this returns a transformed version of this surface after rotation and
- * scaling. Please do not use this if angle != 0, use rotoscale.
- *
- * @param newWidth the resulting width.
- * @param newHeight the resulting height.
- * @see TransformStruct
- */
- TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const;
-
- /**
- * @brief Rotoscale function; this returns a transformed version of this surface after rotation and
- * scaling. Please do not use this if angle == 0, use plain old scaling function.
- *
- * @param transform a TransformStruct wrapping the required info. @see TransformStruct
- *
- */
- TransparentSurface *rotoscale(const TransformStruct &transform) const;
- AlphaType getAlphaMode() const;
- void setAlphaMode(AlphaType);
-private:
- AlphaType _alphaMode;
-
-};
-
-/**
- * A deleter for Surface objects which can be used with SharedPtr.
- *
- * This deleter assures Surface::free is called on deletion.
- */
-/*struct SharedPtrTransparentSurfaceDeleter {
- void operator()(TransparentSurface *ptr) {
- ptr->free();
- delete ptr;
- }
-};*/
-
-} // End of namespace Wintermute
-
-
-#endif
diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk
index 19fb3d6717..1b6c52e0b7 100644
--- a/engines/wintermute/module.mk
+++ b/engines/wintermute/module.mk
@@ -89,9 +89,6 @@ MODULE_OBJS := \
base/save_thumb_helper.o \
base/timer.o \
detection.o \
- graphics/transform_struct.o \
- graphics/transform_tools.o \
- graphics/transparent_surface.o \
math/math_util.o \
math/matrix4.o \
math/vector2.o \
diff --git a/engines/wintermute/utils/utils.cpp b/engines/wintermute/utils/utils.cpp
index d592019418..dc6476d4ea 100644
--- a/engines/wintermute/utils/utils.cpp
+++ b/engines/wintermute/utils/utils.cpp
@@ -32,11 +32,6 @@
namespace Wintermute {
-//////////////////////////////////////////////////////////////////////
-static inline unsigned Sqr(int x) {
- return (x * x);
-}
-
//////////////////////////////////////////////////////////////////////////////////
// Swap - swaps two integers
//////////////////////////////////////////////////////////////////////////////////
diff --git a/engines/zvision/POTFILES b/engines/zvision/POTFILES
new file mode 100644
index 0000000000..48e2782648
--- /dev/null
+++ b/engines/zvision/POTFILES
@@ -0,0 +1 @@
+engines/zvision/detection.cpp
diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp
index 22382bc264..e610f34474 100644
--- a/engines/zvision/core/console.cpp
+++ b/engines/zvision/core/console.cpp
@@ -45,25 +45,25 @@
namespace ZVision {
Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) {
- DCmd_Register("loadimage", WRAP_METHOD(Console, cmdLoadImage));
- DCmd_Register("loadvideo", WRAP_METHOD(Console, cmdLoadVideo));
- DCmd_Register("loadsound", WRAP_METHOD(Console, cmdLoadSound));
- DCmd_Register("raw2wav", WRAP_METHOD(Console, cmdRawToWav));
- DCmd_Register("setrenderstate", WRAP_METHOD(Console, cmdSetRenderState));
- DCmd_Register("generaterendertable", WRAP_METHOD(Console, cmdGenerateRenderTable));
- DCmd_Register("setpanoramafov", WRAP_METHOD(Console, cmdSetPanoramaFoV));
- DCmd_Register("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale));
- DCmd_Register("changelocation", WRAP_METHOD(Console, cmdChangeLocation));
- DCmd_Register("dumpfile", WRAP_METHOD(Console, cmdDumpFile));
- DCmd_Register("parseallscrfiles", WRAP_METHOD(Console, cmdParseAllScrFiles));
- DCmd_Register("rendertext", WRAP_METHOD(Console, cmdRenderText));
+ registerCmd("loadimage", WRAP_METHOD(Console, cmdLoadImage));
+ registerCmd("loadvideo", WRAP_METHOD(Console, cmdLoadVideo));
+ registerCmd("loadsound", WRAP_METHOD(Console, cmdLoadSound));
+ registerCmd("raw2wav", WRAP_METHOD(Console, cmdRawToWav));
+ registerCmd("setrenderstate", WRAP_METHOD(Console, cmdSetRenderState));
+ registerCmd("generaterendertable", WRAP_METHOD(Console, cmdGenerateRenderTable));
+ registerCmd("setpanoramafov", WRAP_METHOD(Console, cmdSetPanoramaFoV));
+ registerCmd("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale));
+ registerCmd("changelocation", WRAP_METHOD(Console, cmdChangeLocation));
+ registerCmd("dumpfile", WRAP_METHOD(Console, cmdDumpFile));
+ registerCmd("parseallscrfiles", WRAP_METHOD(Console, cmdParseAllScrFiles));
+ registerCmd("rendertext", WRAP_METHOD(Console, cmdRenderText));
}
bool Console::cmdLoadImage(int argc, const char **argv) {
if (argc == 4)
_engine->getRenderManager()->renderImageToScreen(argv[1], atoi(argv[2]), atoi(argv[3]));
else {
- DebugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n");
+ debugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n");
return true;
}
@@ -72,7 +72,7 @@ bool Console::cmdLoadImage(int argc, const char **argv) {
bool Console::cmdLoadVideo(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Use loadvideo <fileName> to load a video to the screen\n");
+ debugPrintf("Use loadvideo <fileName> to load a video to the screen\n");
return true;
}
@@ -86,7 +86,7 @@ bool Console::cmdLoadVideo(int argc, const char **argv) {
bool Console::cmdLoadSound(int argc, const char **argv) {
if (!Common::File::exists(argv[1])) {
- DebugPrintf("File does not exist\n");
+ debugPrintf("File does not exist\n");
return true;
}
@@ -105,7 +105,7 @@ bool Console::cmdLoadSound(int argc, const char **argv) {
Audio::SoundHandle handle;
_engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream, -1, 100, 0, DisposeAfterUse::YES, false, false);
} else {
- DebugPrintf("Use loadsound <fileName> [<rate> <isStereo: 1 or 0>] to load a sound\n");
+ debugPrintf("Use loadsound <fileName> [<rate> <isStereo: 1 or 0>] to load a sound\n");
return true;
}
@@ -114,7 +114,7 @@ bool Console::cmdLoadSound(int argc, const char **argv) {
bool Console::cmdRawToWav(int argc, const char **argv) {
if (argc != 3) {
- DebugPrintf("Use raw2wav <rawFilePath> <wavFileName> to dump a .RAW file to .WAV\n");
+ debugPrintf("Use raw2wav <rawFilePath> <wavFileName> to dump a .RAW file to .WAV\n");
return true;
}
@@ -124,7 +124,7 @@ bool Console::cmdRawToWav(int argc, const char **argv) {
bool Console::cmdSetRenderState(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n");
+ debugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n");
return true;
}
@@ -137,7 +137,7 @@ bool Console::cmdSetRenderState(int argc, const char **argv) {
else if (renderState.matchString("flat", true))
_engine->getRenderManager()->getRenderTable()->setRenderState(RenderTable::FLAT);
else
- DebugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n");
+ debugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n");
return true;
}
@@ -150,7 +150,7 @@ bool Console::cmdGenerateRenderTable(int argc, const char **argv) {
bool Console::cmdSetPanoramaFoV(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Use setpanoramafov <fieldOfView> to change the current panorama field of view\n");
+ debugPrintf("Use setpanoramafov <fieldOfView> to change the current panorama field of view\n");
return true;
}
@@ -161,7 +161,7 @@ bool Console::cmdSetPanoramaFoV(int argc, const char **argv) {
bool Console::cmdSetPanoramaScale(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Use setpanoramascale <scale> to change the current panorama scale\n");
+ debugPrintf("Use setpanoramascale <scale> to change the current panorama scale\n");
return true;
}
@@ -172,7 +172,7 @@ bool Console::cmdSetPanoramaScale(int argc, const char **argv) {
bool Console::cmdChangeLocation(int argc, const char **argv) {
if (argc != 6) {
- DebugPrintf("Use changelocation <char: world> <char: room> <char:node> <char:view> <int: x position> to change your location\n");
+ debugPrintf("Use changelocation <char: world> <char: room> <char:node> <char:view> <int: x position> to change your location\n");
return true;
}
@@ -183,7 +183,7 @@ bool Console::cmdChangeLocation(int argc, const char **argv) {
bool Console::cmdDumpFile(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Use dumpfile <fileName> to dump a file\n");
+ debugPrintf("Use dumpfile <fileName> to dump a file\n");
return true;
}
@@ -205,7 +205,7 @@ bool Console::cmdParseAllScrFiles(int argc, const char **argv) {
bool Console::cmdRenderText(int argc, const char **argv) {
if (argc != 7) {
- DebugPrintf("Use rendertext <text> <fontNumber> <destX> <destY> <maxWidth> <1 or 0: wrap> to render text\n");
+ debugPrintf("Use rendertext <text> <fontNumber> <destX> <destY> <maxWidth> <1 or 0: wrap> to render text\n");
return true;
}
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index e854378ae4..517278e155 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -155,7 +155,7 @@ bool ActionEnableControl::execute(ZVision *engine) {
ActionMusic::ActionMusic(const Common::String &line) : _volume(255) {
uint type;
- char fileNameBuffer[25];
+ char fileNameBuffer[26];
uint loop;
uint volume = 255;
@@ -211,7 +211,7 @@ bool ActionMusic::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionPreloadAnimation::ActionPreloadAnimation(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
// The two %*u are always 0 and dont seem to have a use
sscanf(line.c_str(), "%*[^:]:%*[^:]:%u(%25s %*u %*u %u %u)", &_key, fileName, &_mask, &_framerate);
@@ -238,7 +238,7 @@ bool ActionPreloadAnimation::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionPlayAnimation::ActionPlayAnimation(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
// The two %*u are always 0 and dont seem to have a use
sscanf(line.c_str(),
@@ -312,7 +312,7 @@ bool ActionRandom::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionSetPartialScreen::ActionSetPartialScreen(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
uint color;
sscanf(line.c_str(), "%*[^(](%u %u %25s %*u %u)", &_x, &_y, fileName, &color);
@@ -342,7 +342,7 @@ bool ActionSetPartialScreen::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionSetScreen::ActionSetScreen(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
sscanf(line.c_str(), "%*[^(](%25[^)])", fileName);
_fileName = Common::String(fileName);
@@ -360,7 +360,7 @@ bool ActionSetScreen::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionStreamVideo::ActionStreamVideo(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
uint skippable;
sscanf(line.c_str(), "%*[^(](%25s %u %u %u %u %u %u)", fileName, &_x1, &_y1, &_x2, &_y2, &_flags, &skippable);
diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp
index 5cf5086691..a35548d02e 100644
--- a/engines/zvision/scripting/controls/input_control.cpp
+++ b/engines/zvision/scripting/controls/input_control.cpp
@@ -75,7 +75,7 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre
} else if (line.matchString("*next_tabstop*", true)) {
sscanf(line.c_str(), "%*[^(](%u)", &_nextTabstop);
} else if (line.matchString("*cursor_animation*", true)) {
- char fileName[25];
+ char fileName[26];
sscanf(line.c_str(), "%*[^(](%25s %*u)", fileName);
diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp
index 55353acbb9..edee1fd16e 100644
--- a/engines/zvision/sound/zork_raw.cpp
+++ b/engines/zvision/sound/zork_raw.cpp
@@ -185,14 +185,14 @@ Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath,
char fileIdentifier = (engine->getGameId() == GID_NEMESIS) ? fileName[6] : fileName[7];
if (engine->getGameId() == GID_NEMESIS) {
- for (int i = 0; i < 6; ++i) {
+ for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zNemSoundParamLookupTable); ++i) {
if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == fileIdentifier) {
soundParams = RawZorkStream::_zNemSoundParamLookupTable[i];
foundParams = true;
}
}
} else if (engine->getGameId() == GID_GRANDINQUISITOR) {
- for (int i = 0; i < 6; ++i) {
+ for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zgiSoundParamLookupTable); ++i) {
if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == fileIdentifier) {
soundParams = RawZorkStream::_zgiSoundParamLookupTable[i];
foundParams = true;