aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorMatthew Hoops2011-05-03 17:17:27 -0400
committerMatthew Hoops2011-05-03 17:25:41 -0400
commit9cb600099f4c29298707787cafad2741a1cd6686 (patch)
treefb1930fa56b611317831d66442cba19b18d2e57a /engines
parent3b2283daf850605ca897002afbafe44489c35473 (diff)
parent95a6098f672191dc0792bd4f9bfa18706bbe8e3a (diff)
downloadscummvm-rg350-9cb600099f4c29298707787cafad2741a1cd6686.tar.gz
scummvm-rg350-9cb600099f4c29298707787cafad2741a1cd6686.tar.bz2
scummvm-rg350-9cb600099f4c29298707787cafad2741a1cd6686.zip
Merge remote branch 'upstream/master' into pegasus
Diffstat (limited to 'engines')
-rw-r--r--engines/advancedDetector.cpp4
-rw-r--r--engines/advancedDetector.h12
-rw-r--r--engines/agi/agi.cpp28
-rw-r--r--engines/agi/agi.h19
-rw-r--r--engines/agi/detection.cpp8
-rw-r--r--engines/agi/detection_tables.h5
-rw-r--r--engines/agi/graphics.cpp11
-rw-r--r--engines/agi/inv.cpp2
-rw-r--r--engines/agi/keyboard.cpp4
-rw-r--r--engines/agi/loader_v2.cpp2
-rw-r--r--engines/agi/loader_v3.cpp1
-rw-r--r--engines/agi/lzw.cpp2
-rw-r--r--engines/agi/menu.cpp2
-rw-r--r--engines/agi/objects.cpp2
-rw-r--r--engines/agi/op_cmd.cpp1
-rw-r--r--engines/agi/op_test.cpp6
-rw-r--r--engines/agi/picture.cpp8
-rw-r--r--engines/agi/preagi.cpp7
-rw-r--r--engines/agi/preagi_mickey.cpp5
-rw-r--r--engines/agi/preagi_troll.cpp1
-rw-r--r--engines/agi/preagi_winnie.cpp5
-rw-r--r--engines/agi/predictive.cpp1
-rw-r--r--engines/agi/saveload.cpp27
-rw-r--r--engines/agi/sound.cpp2
-rw-r--r--engines/agi/sound_2gs.cpp53
-rw-r--r--engines/agi/sound_2gs.h4
-rw-r--r--engines/agi/sound_midi.cpp183
-rw-r--r--engines/agi/sound_midi.h65
-rw-r--r--engines/agi/sound_sarien.cpp4
-rw-r--r--engines/agi/text.cpp4
-rw-r--r--engines/agi/wagparser.cpp1
-rw-r--r--engines/agi/words.cpp2
-rw-r--r--engines/agos/agos.cpp60
-rw-r--r--engines/agos/agos.h11
-rw-r--r--engines/agos/animation.cpp8
-rw-r--r--engines/agos/charset-fontdata.cpp1
-rw-r--r--engines/agos/debug.cpp1
-rw-r--r--engines/agos/debug.h2
-rw-r--r--engines/agos/detection.cpp1
-rw-r--r--engines/agos/draw.cpp1
-rw-r--r--engines/agos/event.cpp1
-rw-r--r--engines/agos/gfx.cpp1
-rw-r--r--engines/agos/icons.cpp8
-rw-r--r--engines/agos/items.cpp1
-rw-r--r--engines/agos/menus.cpp1
-rw-r--r--engines/agos/midi.cpp67
-rw-r--r--engines/agos/midi.h30
-rw-r--r--engines/agos/midiparser_s1d.cpp1
-rw-r--r--engines/agos/oracle.cpp6
-rw-r--r--engines/agos/res.cpp1
-rw-r--r--engines/agos/res_snd.cpp1
-rw-r--r--engines/agos/rooms.cpp1
-rw-r--r--engines/agos/saveload.cpp1
-rw-r--r--engines/agos/script.cpp1
-rw-r--r--engines/agos/script_dp.cpp2
-rw-r--r--engines/agos/script_ff.cpp9
-rw-r--r--engines/agos/script_pn.cpp2
-rw-r--r--engines/agos/script_s1.cpp2
-rw-r--r--engines/agos/script_s2.cpp2
-rw-r--r--engines/agos/sound.cpp1
-rw-r--r--engines/agos/string.cpp4
-rw-r--r--engines/agos/string_pn.cpp2
-rw-r--r--engines/agos/subroutine.cpp1
-rw-r--r--engines/agos/vga.cpp1
-rw-r--r--engines/agos/vga_e2.cpp1
-rw-r--r--engines/agos/vga_ff.cpp4
-rw-r--r--engines/agos/vga_ww.cpp1
-rw-r--r--engines/agos/window.cpp1
-rw-r--r--engines/cine/anim.cpp1
-rw-r--r--engines/cine/bg.cpp8
-rw-r--r--engines/cine/cine.cpp29
-rw-r--r--engines/cine/cine.h2
-rw-r--r--engines/cine/detection.cpp1
-rw-r--r--engines/cine/gfx.cpp3
-rw-r--r--engines/cine/msg.cpp1
-rw-r--r--engines/cine/pal.cpp3
-rw-r--r--engines/cine/part.cpp1
-rw-r--r--engines/cine/saveload.cpp14
-rw-r--r--engines/cine/saveload.h4
-rw-r--r--engines/cine/script_fw.cpp1
-rw-r--r--engines/cine/script_os.cpp3
-rw-r--r--engines/cine/sound.cpp2
-rw-r--r--engines/cine/sound.h2
-rw-r--r--engines/cine/texte.cpp4
-rw-r--r--engines/cine/various.cpp1
-rw-r--r--engines/cruise/actor.cpp2
-rw-r--r--engines/cruise/background.cpp2
-rw-r--r--engines/cruise/backgroundIncrust.cpp6
-rw-r--r--engines/cruise/cruise.cpp16
-rw-r--r--engines/cruise/cruise.h1
-rw-r--r--engines/cruise/cruise_main.cpp17
-rw-r--r--engines/cruise/ctp.cpp2
-rw-r--r--engines/cruise/ctp.h2
-rw-r--r--engines/cruise/dataLoader.cpp5
-rw-r--r--engines/cruise/detection.cpp3
-rw-r--r--engines/cruise/font.cpp4
-rw-r--r--engines/cruise/font.h2
-rw-r--r--engines/cruise/function.cpp2
-rw-r--r--engines/cruise/gfxModule.cpp10
-rw-r--r--engines/cruise/gfxModule.h4
-rw-r--r--engines/cruise/linker.cpp4
-rw-r--r--engines/cruise/mainDraw.cpp4
-rw-r--r--engines/cruise/menu.cpp1
-rw-r--r--engines/cruise/object.cpp2
-rw-r--r--engines/cruise/overlay.cpp1
-rw-r--r--engines/cruise/saveload.cpp1
-rw-r--r--engines/cruise/script.cpp5
-rw-r--r--engines/cruise/sound.cpp18
-rw-r--r--engines/dialogs.cpp12
-rw-r--r--engines/dialogs.h8
-rw-r--r--engines/draci/animation.cpp7
-rw-r--r--engines/draci/draci.cpp15
-rw-r--r--engines/draci/draci.h1
-rw-r--r--engines/draci/font.cpp30
-rw-r--r--engines/draci/font.h26
-rw-r--r--engines/draci/game.cpp36
-rw-r--r--engines/draci/game.h6
-rw-r--r--engines/draci/mouse.cpp6
-rw-r--r--engines/draci/music.cpp185
-rw-r--r--engines/draci/music.h57
-rw-r--r--engines/draci/screen.cpp20
-rw-r--r--engines/draci/screen.h2
-rw-r--r--engines/draci/script.cpp8
-rw-r--r--engines/draci/script.h2
-rw-r--r--engines/draci/sound.cpp17
-rw-r--r--engines/draci/sprite.cpp10
-rw-r--r--engines/draci/sprite.h6
-rw-r--r--engines/draci/surface.cpp10
-rw-r--r--engines/draci/surface.h13
-rw-r--r--engines/draci/walking.cpp14
-rw-r--r--engines/draci/walking.h6
-rw-r--r--engines/drascula/converse.cpp2
-rw-r--r--engines/drascula/drascula.cpp9
-rw-r--r--engines/drascula/graphics.cpp3
-rw-r--r--engines/drascula/objects.cpp2
-rw-r--r--engines/drascula/palette.cpp2
-rw-r--r--engines/drascula/rooms.cpp8
-rw-r--r--engines/drascula/saveload.cpp2
-rw-r--r--engines/drascula/sound.cpp1
-rw-r--r--engines/engine.cpp40
-rw-r--r--engines/engine.h25
-rw-r--r--engines/engines.mk17
-rw-r--r--engines/game.cpp1
-rw-r--r--engines/game.h2
-rw-r--r--engines/gob/databases.cpp1
-rw-r--r--engines/gob/dataio.h2
-rw-r--r--engines/gob/detection_tables.h30
-rw-r--r--engines/gob/gob.cpp6
-rw-r--r--engines/gob/gob.h4
-rw-r--r--engines/gob/inter_v1.cpp2
-rw-r--r--engines/gob/inter_v2.cpp5
-rw-r--r--engines/gob/inter_v4.cpp2
-rw-r--r--engines/gob/inter_v5.cpp3
-rw-r--r--engines/gob/inter_v6.cpp2
-rw-r--r--engines/gob/resources.h2
-rw-r--r--engines/gob/save/savefile.cpp2
-rw-r--r--engines/gob/save/savefile.h14
-rw-r--r--engines/gob/save/saveload.cpp3
-rw-r--r--engines/gob/save/saveload.h4
-rw-r--r--engines/gob/save/saveload_inca2.cpp4
-rw-r--r--engines/gob/save/saveload_v3.cpp6
-rw-r--r--engines/gob/sound/adlib.cpp2
-rw-r--r--engines/gob/sound/bgatmosphere.cpp6
-rw-r--r--engines/gob/sound/bgatmosphere.h4
-rw-r--r--engines/gob/sound/cdrom.cpp1
-rw-r--r--engines/gob/sound/infogrames.cpp2
-rw-r--r--engines/gob/sound/sound.cpp10
-rw-r--r--engines/gob/sound/sounddesc.cpp2
-rw-r--r--engines/gob/sound/soundmixer.cpp2
-rw-r--r--engines/gob/surface.cpp12
-rw-r--r--engines/gob/surface.h2
-rw-r--r--engines/gob/totfile.h2
-rw-r--r--engines/gob/util.cpp2
-rw-r--r--engines/gob/video.cpp1
-rw-r--r--engines/gob/videoplayer.cpp2
-rw-r--r--engines/groovie/cursor.cpp5
-rw-r--r--engines/groovie/cursor.h2
-rw-r--r--engines/groovie/debug.cpp2
-rw-r--r--engines/groovie/font.cpp4
-rw-r--r--engines/groovie/graphics.cpp8
-rw-r--r--engines/groovie/groovie.cpp4
-rw-r--r--engines/groovie/groovie.h2
-rw-r--r--engines/groovie/music.cpp64
-rw-r--r--engines/groovie/music.h16
-rw-r--r--engines/groovie/player.cpp2
-rw-r--r--engines/groovie/resource.cpp47
-rw-r--r--engines/groovie/resource.h8
-rw-r--r--engines/groovie/roq.cpp17
-rw-r--r--engines/groovie/script.cpp18
-rw-r--r--engines/groovie/script.h2
-rw-r--r--engines/groovie/vdx.cpp91
-rw-r--r--engines/groovie/vdx.h8
-rw-r--r--engines/hugo/detection.cpp6
-rw-r--r--engines/hugo/dialogs.cpp (renamed from engines/hugo/menu.cpp)77
-rw-r--r--engines/hugo/dialogs.h (renamed from engines/hugo/menu.h)27
-rw-r--r--engines/hugo/display.cpp77
-rw-r--r--engines/hugo/display.h19
-rw-r--r--engines/hugo/file.cpp76
-rw-r--r--engines/hugo/file.h1
-rw-r--r--engines/hugo/file_v1d.cpp4
-rw-r--r--engines/hugo/file_v1w.cpp2
-rw-r--r--engines/hugo/file_v2d.cpp10
-rw-r--r--engines/hugo/file_v2w.cpp2
-rw-r--r--engines/hugo/file_v3d.cpp2
-rw-r--r--engines/hugo/hugo.cpp63
-rw-r--r--engines/hugo/hugo.h18
-rw-r--r--engines/hugo/intro.cpp33
-rw-r--r--engines/hugo/inventory.cpp1
-rw-r--r--engines/hugo/module.mk2
-rw-r--r--engines/hugo/mouse.cpp8
-rw-r--r--engines/hugo/object.cpp42
-rw-r--r--engines/hugo/object_v1d.cpp1
-rw-r--r--engines/hugo/object_v1w.cpp1
-rw-r--r--engines/hugo/object_v2d.cpp1
-rw-r--r--engines/hugo/object_v3d.cpp1
-rw-r--r--engines/hugo/parser.cpp20
-rw-r--r--engines/hugo/parser.h5
-rw-r--r--engines/hugo/parser_v1d.cpp35
-rw-r--r--engines/hugo/parser_v1w.cpp19
-rw-r--r--engines/hugo/parser_v2d.cpp17
-rw-r--r--engines/hugo/parser_v3d.cpp45
-rw-r--r--engines/hugo/route.cpp1
-rw-r--r--engines/hugo/schedule.cpp435
-rw-r--r--engines/hugo/schedule.h2
-rw-r--r--engines/hugo/sound.cpp211
-rw-r--r--engines/hugo/sound.h46
-rw-r--r--engines/hugo/util.cpp70
-rw-r--r--engines/hugo/util.h26
-rw-r--r--engines/kyra/animator_hof.cpp2
-rw-r--r--engines/kyra/animator_lok.cpp5
-rw-r--r--engines/kyra/animator_mr.cpp3
-rw-r--r--engines/kyra/animator_tim.cpp5
-rw-r--r--engines/kyra/animator_v2.cpp3
-rw-r--r--engines/kyra/debugger.cpp7
-rw-r--r--engines/kyra/detection.cpp6
-rw-r--r--engines/kyra/gui.cpp2
-rw-r--r--engines/kyra/gui_hof.cpp8
-rw-r--r--engines/kyra/gui_lok.cpp16
-rw-r--r--engines/kyra/gui_lok.h2
-rw-r--r--engines/kyra/gui_lol.cpp4
-rw-r--r--engines/kyra/gui_mr.cpp19
-rw-r--r--engines/kyra/gui_mr.h2
-rw-r--r--engines/kyra/gui_v2.cpp2
-rw-r--r--engines/kyra/items_hof.cpp2
-rw-r--r--engines/kyra/items_lok.cpp8
-rw-r--r--engines/kyra/items_mr.cpp2
-rw-r--r--engines/kyra/kyra_hof.cpp88
-rw-r--r--engines/kyra/kyra_hof.h6
-rw-r--r--engines/kyra/kyra_lok.cpp33
-rw-r--r--engines/kyra/kyra_lok.h17
-rw-r--r--engines/kyra/kyra_mr.cpp63
-rw-r--r--engines/kyra/kyra_mr.h3
-rw-r--r--engines/kyra/kyra_v1.cpp15
-rw-r--r--engines/kyra/kyra_v1.h9
-rw-r--r--engines/kyra/kyra_v2.cpp12
-rw-r--r--engines/kyra/kyra_v2.h3
-rw-r--r--engines/kyra/lol.cpp18
-rw-r--r--engines/kyra/lol.h5
-rw-r--r--engines/kyra/resource.cpp4
-rw-r--r--engines/kyra/resource.h2
-rw-r--r--engines/kyra/resource_intern.cpp2
-rw-r--r--engines/kyra/saveload.cpp26
-rw-r--r--engines/kyra/saveload_hof.cpp12
-rw-r--r--engines/kyra/saveload_lok.cpp7
-rw-r--r--engines/kyra/saveload_lol.cpp3
-rw-r--r--engines/kyra/scene_hof.cpp4
-rw-r--r--engines/kyra/scene_lok.cpp23
-rw-r--r--engines/kyra/scene_lol.cpp2
-rw-r--r--engines/kyra/scene_mr.cpp53
-rw-r--r--engines/kyra/scene_v1.cpp1
-rw-r--r--engines/kyra/scene_v2.cpp14
-rw-r--r--engines/kyra/screen.cpp12
-rw-r--r--engines/kyra/screen_hof.cpp4
-rw-r--r--engines/kyra/screen_lok.cpp6
-rw-r--r--engines/kyra/screen_lol.cpp5
-rw-r--r--engines/kyra/screen_mr.cpp1
-rw-r--r--engines/kyra/script.cpp16
-rw-r--r--engines/kyra/script.h4
-rw-r--r--engines/kyra/script_hof.cpp7
-rw-r--r--engines/kyra/script_lok.cpp7
-rw-r--r--engines/kyra/script_lol.cpp3
-rw-r--r--engines/kyra/script_mr.cpp12
-rw-r--r--engines/kyra/script_tim.cpp8
-rw-r--r--engines/kyra/script_tim.h1
-rw-r--r--engines/kyra/script_v1.cpp2
-rw-r--r--engines/kyra/script_v2.cpp2
-rw-r--r--engines/kyra/seqplayer.cpp11
-rw-r--r--engines/kyra/sequences_hof.cpp16
-rw-r--r--engines/kyra/sequences_lok.cpp259
-rw-r--r--engines/kyra/sequences_lol.cpp3
-rw-r--r--engines/kyra/sequences_v2.cpp2
-rw-r--r--engines/kyra/sound.cpp7
-rw-r--r--engines/kyra/sound_adlib.cpp25
-rw-r--r--engines/kyra/sound_amiga.cpp5
-rw-r--r--engines/kyra/sound_intern.h8
-rw-r--r--engines/kyra/sound_lok.cpp4
-rw-r--r--engines/kyra/sound_lol.cpp4
-rw-r--r--engines/kyra/sound_midi.cpp17
-rw-r--r--engines/kyra/sound_towns.cpp9
-rw-r--r--engines/kyra/sprites.cpp12
-rw-r--r--engines/kyra/staticres.cpp9
-rw-r--r--engines/kyra/text.cpp6
-rw-r--r--engines/kyra/text_hof.cpp4
-rw-r--r--engines/kyra/text_lok.cpp5
-rw-r--r--engines/kyra/text_lol.cpp5
-rw-r--r--engines/kyra/text_lol.h4
-rw-r--r--engines/kyra/text_mr.cpp7
-rw-r--r--engines/kyra/timer.cpp4
-rw-r--r--engines/kyra/timer_lok.cpp13
-rw-r--r--engines/kyra/timer_lol.cpp3
-rw-r--r--engines/kyra/timer_mr.cpp2
-rw-r--r--engines/kyra/vqa.cpp48
-rw-r--r--engines/kyra/wsamovie.cpp11
-rw-r--r--engines/kyra/wsamovie.h4
-rw-r--r--engines/lastexpress/data/animation.cpp5
-rw-r--r--engines/lastexpress/data/archive.h3
-rw-r--r--engines/lastexpress/data/background.cpp1
-rw-r--r--engines/lastexpress/data/font.cpp2
-rw-r--r--engines/lastexpress/data/font.h2
-rw-r--r--engines/lastexpress/data/scene.cpp1
-rw-r--r--engines/lastexpress/data/scene.h6
-rw-r--r--engines/lastexpress/data/sequence.cpp3
-rw-r--r--engines/lastexpress/data/sequence.h2
-rw-r--r--engines/lastexpress/data/snd.cpp40
-rw-r--r--engines/lastexpress/data/snd.h4
-rw-r--r--engines/lastexpress/data/subtitle.cpp2
-rw-r--r--engines/lastexpress/entities/entity.h1
-rw-r--r--engines/lastexpress/game/state.h2
-rw-r--r--engines/lastexpress/graphics.cpp13
-rw-r--r--engines/lastexpress/lastexpress.cpp4
-rw-r--r--engines/lastexpress/resource.cpp1
-rw-r--r--engines/lure/debugger.cpp4
-rw-r--r--engines/lure/decode.cpp6
-rw-r--r--engines/lure/disk.h2
-rw-r--r--engines/lure/fights.cpp6
-rw-r--r--engines/lure/hotspots.cpp28
-rw-r--r--engines/lure/hotspots.h6
-rw-r--r--engines/lure/lure.cpp6
-rw-r--r--engines/lure/lure.h2
-rw-r--r--engines/lure/luredefs.h14
-rw-r--r--engines/lure/memory.cpp1
-rw-r--r--engines/lure/menu.cpp36
-rw-r--r--engines/lure/palette.cpp4
-rw-r--r--engines/lure/res.cpp2
-rw-r--r--engines/lure/res_struct.cpp2
-rw-r--r--engines/lure/res_struct.h6
-rw-r--r--engines/lure/room.cpp6
-rw-r--r--engines/lure/screen.cpp8
-rw-r--r--engines/lure/sound.cpp27
-rw-r--r--engines/lure/sound.h33
-rw-r--r--engines/lure/surface.cpp88
-rw-r--r--engines/lure/surface.h16
-rw-r--r--engines/m4/actor.cpp3
-rw-r--r--engines/m4/animation.cpp4
-rw-r--r--engines/m4/assets.h16
-rw-r--r--engines/m4/compression.cpp1
-rw-r--r--engines/m4/console.cpp2
-rw-r--r--engines/m4/converse.cpp53
-rw-r--r--engines/m4/dialogs.cpp9
-rw-r--r--engines/m4/events.cpp2
-rw-r--r--engines/m4/font.cpp16
-rw-r--r--engines/m4/font.h4
-rw-r--r--engines/m4/globals.cpp2
-rw-r--r--engines/m4/graphics.cpp31
-rw-r--r--engines/m4/graphics.h33
-rw-r--r--engines/m4/gui.cpp13
-rw-r--r--engines/m4/m4.cpp26
-rw-r--r--engines/m4/m4.h1
-rw-r--r--engines/m4/m4_menus.cpp1
-rw-r--r--engines/m4/m4_scene.cpp15
-rw-r--r--engines/m4/m4_scene.h6
-rw-r--r--engines/m4/m4_views.cpp2
-rw-r--r--engines/m4/m4_views.h2
-rw-r--r--engines/m4/mads_anim.cpp4
-rw-r--r--engines/m4/mads_logic.cpp2
-rw-r--r--engines/m4/mads_menus.cpp22
-rw-r--r--engines/m4/mads_scene.cpp17
-rw-r--r--engines/m4/mads_views.cpp21
-rw-r--r--engines/m4/mads_views.h12
-rw-r--r--engines/m4/midi.cpp137
-rw-r--r--engines/m4/midi.h46
-rw-r--r--engines/m4/rails.cpp5
-rw-r--r--engines/m4/resource.cpp6
-rw-r--r--engines/m4/scene.cpp2
-rw-r--r--engines/m4/script.cpp1
-rw-r--r--engines/m4/sound.cpp1
-rw-r--r--engines/m4/sprite.cpp11
-rw-r--r--engines/m4/woodscript.cpp3
-rw-r--r--engines/m4/woodscript.h6
-rw-r--r--engines/m4/ws_sequence.cpp2
-rw-r--r--engines/made/database.cpp7
-rw-r--r--engines/made/graphics.cpp2
-rw-r--r--engines/made/made.cpp29
-rw-r--r--engines/made/music.cpp148
-rw-r--r--engines/made/music.h52
-rw-r--r--engines/made/pmvplayer.cpp12
-rw-r--r--engines/made/redreader.cpp1
-rw-r--r--engines/made/resource.cpp19
-rw-r--r--engines/made/resource.h21
-rw-r--r--engines/made/screen.cpp8
-rw-r--r--engines/made/script.h1
-rw-r--r--engines/made/scriptfuncs.cpp2
-rw-r--r--engines/made/scriptfuncs.h2
-rw-r--r--engines/metaengine.h4
-rw-r--r--engines/mohawk/bitmap.cpp32
-rw-r--r--engines/mohawk/bitmap.h10
-rw-r--r--engines/mohawk/console.cpp72
-rw-r--r--engines/mohawk/console.h22
-rw-r--r--engines/mohawk/cstime.cpp5
-rw-r--r--engines/mohawk/cstime_cases.cpp2
-rw-r--r--engines/mohawk/cstime_game.cpp10
-rw-r--r--engines/mohawk/cstime_ui.cpp42
-rw-r--r--engines/mohawk/cstime_ui.h6
-rw-r--r--engines/mohawk/cstime_view.cpp6
-rw-r--r--engines/mohawk/cursors.cpp237
-rw-r--r--engines/mohawk/cursors.h94
-rw-r--r--engines/mohawk/detection.cpp54
-rw-r--r--engines/mohawk/detection_tables.h309
-rw-r--r--engines/mohawk/dialogs.cpp30
-rw-r--r--engines/mohawk/dialogs.h14
-rw-r--r--engines/mohawk/graphics.cpp129
-rw-r--r--engines/mohawk/graphics.h67
-rw-r--r--engines/mohawk/installer_archive.cpp88
-rw-r--r--engines/mohawk/installer_archive.h2
-rw-r--r--engines/mohawk/livingbooks.cpp643
-rw-r--r--engines/mohawk/livingbooks.h119
-rw-r--r--engines/mohawk/livingbooks_code.cpp1113
-rw-r--r--engines/mohawk/livingbooks_code.h191
-rw-r--r--engines/mohawk/module.mk40
-rw-r--r--engines/mohawk/mohawk.cpp14
-rw-r--r--engines/mohawk/mohawk.h2
-rw-r--r--engines/mohawk/myst.cpp16
-rw-r--r--engines/mohawk/myst.h2
-rw-r--r--engines/mohawk/myst_areas.cpp4
-rw-r--r--engines/mohawk/myst_areas.h1
-rw-r--r--engines/mohawk/myst_scripts.cpp2
-rw-r--r--engines/mohawk/myst_stacks/channelwood.cpp4
-rw-r--r--engines/mohawk/myst_stacks/credits.cpp1
-rw-r--r--engines/mohawk/myst_stacks/dni.cpp2
-rw-r--r--engines/mohawk/myst_stacks/mechanical.cpp282
-rw-r--r--engines/mohawk/myst_stacks/mechanical.h31
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp5
-rw-r--r--engines/mohawk/myst_stacks/preview.cpp1
-rw-r--r--engines/mohawk/myst_stacks/selenitic.cpp7
-rw-r--r--engines/mohawk/myst_stacks/slides.cpp1
-rw-r--r--engines/mohawk/myst_stacks/stoneship.cpp4
-rw-r--r--engines/mohawk/myst_state.cpp2
-rw-r--r--engines/mohawk/myst_state.h2
-rw-r--r--engines/mohawk/myst_vars.cpp578
-rw-r--r--engines/mohawk/resource.cpp1
-rw-r--r--engines/mohawk/resource.h148
-rw-r--r--engines/mohawk/riven.cpp152
-rw-r--r--engines/mohawk/riven.h30
-rw-r--r--engines/mohawk/riven_cursors.h670
-rw-r--r--engines/mohawk/riven_external.cpp794
-rw-r--r--engines/mohawk/riven_external.h5
-rw-r--r--engines/mohawk/riven_saveload.cpp46
-rw-r--r--engines/mohawk/riven_scripts.cpp100
-rw-r--r--engines/mohawk/riven_scripts.h20
-rw-r--r--engines/mohawk/riven_vars.cpp95
-rw-r--r--engines/mohawk/sound.cpp20
-rw-r--r--engines/mohawk/sound.h3
-rw-r--r--engines/mohawk/video.cpp16
-rw-r--r--engines/mohawk/video.h1
-rw-r--r--engines/mohawk/view.cpp2
-rw-r--r--engines/parallaction/balloons.cpp6
-rw-r--r--engines/parallaction/callables_br.cpp2
-rw-r--r--engines/parallaction/detection.cpp1
-rw-r--r--engines/parallaction/dialogue.cpp1
-rw-r--r--engines/parallaction/disk.cpp5
-rw-r--r--engines/parallaction/disk.h10
-rw-r--r--engines/parallaction/disk_br.cpp3
-rw-r--r--engines/parallaction/disk_ns.cpp7
-rw-r--r--engines/parallaction/exec_br.cpp2
-rw-r--r--engines/parallaction/exec_ns.cpp1
-rw-r--r--engines/parallaction/font.cpp1
-rw-r--r--engines/parallaction/gfxbase.cpp1
-rw-r--r--engines/parallaction/graphics.cpp6
-rw-r--r--engines/parallaction/gui.cpp2
-rw-r--r--engines/parallaction/gui_br.cpp3
-rw-r--r--engines/parallaction/gui_ns.cpp5
-rw-r--r--engines/parallaction/input.cpp7
-rw-r--r--engines/parallaction/inventory.cpp4
-rw-r--r--engines/parallaction/objects.cpp2
-rw-r--r--engines/parallaction/parallaction.cpp7
-rw-r--r--engines/parallaction/parallaction.h3
-rw-r--r--engines/parallaction/parallaction_br.cpp5
-rw-r--r--engines/parallaction/parallaction_ns.cpp5
-rw-r--r--engines/parallaction/parser.cpp2
-rw-r--r--engines/parallaction/parser_br.cpp1
-rw-r--r--engines/parallaction/parser_ns.cpp2
-rw-r--r--engines/parallaction/saveload.cpp3
-rw-r--r--engines/parallaction/sound.h4
-rw-r--r--engines/parallaction/sound_br.cpp173
-rw-r--r--engines/parallaction/sound_ns.cpp186
-rw-r--r--engines/pegasus/graphics.cpp11
-rw-r--r--engines/pegasus/pegasus.cpp14
-rw-r--r--engines/pegasus/sound.cpp1
-rw-r--r--engines/pegasus/video.cpp5
-rw-r--r--engines/queen/command.cpp2
-rw-r--r--engines/queen/cutaway.cpp1
-rw-r--r--engines/queen/display.cpp7
-rw-r--r--engines/queen/display.h3
-rw-r--r--engines/queen/graphics.cpp3
-rw-r--r--engines/queen/input.cpp1
-rw-r--r--engines/queen/journal.cpp1
-rw-r--r--engines/queen/logic.cpp3
-rw-r--r--engines/queen/midiadlib.cpp3
-rw-r--r--engines/queen/music.cpp41
-rw-r--r--engines/queen/music.h26
-rw-r--r--engines/queen/queen.cpp20
-rw-r--r--engines/queen/queen.h2
-rw-r--r--engines/queen/resource.cpp5
-rw-r--r--engines/queen/sound.cpp9
-rw-r--r--engines/queen/sound.h2
-rw-r--r--engines/queen/talk.cpp3
-rw-r--r--engines/queen/walk.cpp1
-rw-r--r--engines/saga/detection.cpp7
-rw-r--r--engines/saga/font.cpp3
-rw-r--r--engines/saga/gfx.cpp3
-rw-r--r--engines/saga/gfx.h1
-rw-r--r--engines/saga/image.cpp2
-rw-r--r--engines/saga/interface.cpp14
-rw-r--r--engines/saga/interface.h2
-rw-r--r--engines/saga/introproc_saga2.cpp5
-rw-r--r--engines/saga/music.cpp183
-rw-r--r--engines/saga/music.h49
-rw-r--r--engines/saga/render.cpp2
-rw-r--r--engines/saga/resource_hrs.cpp2
-rw-r--r--engines/saga/resource_rsc.cpp2
-rw-r--r--engines/saga/saga.cpp2
-rw-r--r--engines/saga/saga.h1
-rw-r--r--engines/saga/saveload.cpp10
-rw-r--r--engines/saga/script.cpp4
-rw-r--r--engines/saga/shorten.cpp3
-rw-r--r--engines/saga/sound.cpp8
-rw-r--r--engines/savestate.cpp1
-rw-r--r--engines/savestate.h2
-rw-r--r--engines/sci/console.cpp131
-rw-r--r--engines/sci/console.h3
-rw-r--r--engines/sci/debug.h12
-rw-r--r--engines/sci/decompressor.cpp3
-rw-r--r--engines/sci/decompressor.h4
-rw-r--r--engines/sci/detection_tables.h68
-rw-r--r--engines/sci/engine/features.cpp20
-rw-r--r--engines/sci/engine/gc.cpp61
-rw-r--r--engines/sci/engine/gc.h9
-rw-r--r--engines/sci/engine/kernel.h5
-rw-r--r--engines/sci/engine/kernel_tables.h18
-rw-r--r--engines/sci/engine/kevent.cpp38
-rw-r--r--engines/sci/engine/kfile.cpp13
-rw-r--r--engines/sci/engine/kgraphics.cpp192
-rw-r--r--engines/sci/engine/kmath.cpp14
-rw-r--r--engines/sci/engine/kmenu.cpp3
-rw-r--r--engines/sci/engine/kmisc.cpp47
-rw-r--r--engines/sci/engine/kmovement.cpp64
-rw-r--r--engines/sci/engine/kparse.cpp4
-rw-r--r--engines/sci/engine/kpathing.cpp12
-rw-r--r--engines/sci/engine/kscripts.cpp38
-rw-r--r--engines/sci/engine/ksound.cpp1
-rw-r--r--engines/sci/engine/kstring.cpp34
-rw-r--r--engines/sci/engine/kvideo.cpp9
-rw-r--r--engines/sci/engine/object.cpp64
-rw-r--r--engines/sci/engine/object.h1
-rw-r--r--engines/sci/engine/savegame.cpp10
-rw-r--r--engines/sci/engine/script.cpp36
-rw-r--r--engines/sci/engine/script_patches.cpp442
-rw-r--r--engines/sci/engine/scriptdebug.cpp217
-rw-r--r--engines/sci/engine/seg_manager.cpp45
-rw-r--r--engines/sci/engine/seg_manager.h11
-rw-r--r--engines/sci/engine/segment.cpp190
-rw-r--r--engines/sci/engine/segment.h104
-rw-r--r--engines/sci/engine/selector.cpp1
-rw-r--r--engines/sci/engine/selector.h1
-rw-r--r--engines/sci/engine/state.cpp3
-rw-r--r--engines/sci/engine/state.h13
-rw-r--r--engines/sci/engine/static_selectors.cpp214
-rw-r--r--engines/sci/engine/vm.cpp541
-rw-r--r--engines/sci/engine/vm.h28
-rw-r--r--engines/sci/engine/vm_types.cpp135
-rw-r--r--engines/sci/engine/vm_types.h64
-rw-r--r--engines/sci/engine/workarounds.cpp62
-rw-r--r--engines/sci/engine/workarounds.h1
-rw-r--r--engines/sci/event.cpp340
-rw-r--r--engines/sci/event.h12
-rw-r--r--engines/sci/graphics/animate.cpp363
-rw-r--r--engines/sci/graphics/animate.h6
-rw-r--r--engines/sci/graphics/compare.cpp25
-rw-r--r--engines/sci/graphics/cursor.cpp27
-rw-r--r--engines/sci/graphics/fontsjis.h2
-rw-r--r--engines/sci/graphics/frameout.cpp39
-rw-r--r--engines/sci/graphics/helpers.h18
-rw-r--r--engines/sci/graphics/maciconbar.cpp156
-rw-r--r--engines/sci/graphics/maciconbar.h17
-rw-r--r--engines/sci/graphics/menu.cpp34
-rw-r--r--engines/sci/graphics/paint.cpp5
-rw-r--r--engines/sci/graphics/paint.h1
-rw-r--r--engines/sci/graphics/paint16.cpp42
-rw-r--r--engines/sci/graphics/paint16.h1
-rw-r--r--engines/sci/graphics/paint32.cpp16
-rw-r--r--engines/sci/graphics/paint32.h1
-rw-r--r--engines/sci/graphics/palette.cpp75
-rw-r--r--engines/sci/graphics/palette.h2
-rw-r--r--engines/sci/graphics/picture.cpp202
-rw-r--r--engines/sci/graphics/portrait.cpp4
-rw-r--r--engines/sci/graphics/ports.cpp93
-rw-r--r--engines/sci/graphics/ports.h22
-rw-r--r--engines/sci/graphics/screen.cpp73
-rw-r--r--engines/sci/graphics/screen.h24
-rw-r--r--engines/sci/graphics/text16.cpp11
-rw-r--r--engines/sci/graphics/transitions.cpp14
-rw-r--r--engines/sci/graphics/transitions.h3
-rw-r--r--engines/sci/graphics/view.cpp320
-rw-r--r--engines/sci/graphics/view.h14
-rw-r--r--engines/sci/parser/grammar.cpp4
-rw-r--r--engines/sci/parser/said.cpp2
-rw-r--r--engines/sci/parser/vocabulary.cpp2
-rw-r--r--engines/sci/parser/vocabulary.h3
-rw-r--r--engines/sci/resource.cpp96
-rw-r--r--engines/sci/resource.h2
-rw-r--r--engines/sci/resource_audio.cpp9
-rw-r--r--engines/sci/resource_intern.h2
-rw-r--r--engines/sci/sci.cpp143
-rw-r--r--engines/sci/sci.h31
-rw-r--r--engines/sci/sound/audio.cpp12
-rw-r--r--engines/sci/sound/drivers/adlib.cpp16
-rw-r--r--engines/sci/sound/drivers/amigamac.cpp97
-rw-r--r--engines/sci/sound/drivers/cms.cpp4
-rw-r--r--engines/sci/sound/drivers/fb01.cpp3
-rw-r--r--engines/sci/sound/drivers/midi.cpp98
-rw-r--r--engines/sci/sound/drivers/mididriver.h6
-rw-r--r--engines/sci/sound/drivers/pcjr.cpp3
-rw-r--r--engines/sci/sound/music.cpp89
-rw-r--r--engines/sci/sound/soundcmd.cpp32
-rw-r--r--engines/sci/util.cpp26
-rw-r--r--engines/sci/util.h5
-rw-r--r--engines/sci/video/robot_decoder.cpp10
-rw-r--r--engines/sci/video/robot_decoder.h1
-rw-r--r--engines/sci/video/seq_decoder.cpp6
-rw-r--r--engines/sci/video/seq_decoder.h10
-rw-r--r--engines/scumm/actor.cpp27
-rw-r--r--engines/scumm/actor.h41
-rw-r--r--engines/scumm/actor_he.h92
-rw-r--r--engines/scumm/akos.cpp32
-rw-r--r--engines/scumm/charset.cpp47
-rw-r--r--engines/scumm/costume.cpp5
-rw-r--r--engines/scumm/cursor.cpp6
-rw-r--r--engines/scumm/debugger.cpp3
-rw-r--r--engines/scumm/detection.cpp166
-rw-r--r--engines/scumm/detection_tables.h5
-rw-r--r--engines/scumm/dialogs.h4
-rw-r--r--engines/scumm/file_nes.cpp1
-rw-r--r--engines/scumm/gfx.cpp139
-rw-r--r--engines/scumm/gfx.h4
-rw-r--r--engines/scumm/gfxARM.s8
-rw-r--r--engines/scumm/gfx_towns.cpp2
-rw-r--r--engines/scumm/he/animation_he.cpp2
-rw-r--r--engines/scumm/he/cup_player_he.cpp41
-rw-r--r--engines/scumm/he/floodfill_he.cpp4
-rw-r--r--engines/scumm/he/intern_he.h13
-rw-r--r--engines/scumm/he/logic_he.cpp422
-rw-r--r--engines/scumm/he/logic_he.h42
-rw-r--r--engines/scumm/he/palette_he.cpp7
-rw-r--r--engines/scumm/he/resource_he.cpp1114
-rw-r--r--engines/scumm/he/resource_he.h381
-rw-r--r--engines/scumm/he/script_v100he.cpp2
-rw-r--r--engines/scumm/he/script_v60he.cpp10
-rw-r--r--engines/scumm/he/script_v71he.cpp8
-rw-r--r--engines/scumm/he/script_v72he.cpp37
-rw-r--r--engines/scumm/he/script_v90he.cpp12
-rw-r--r--engines/scumm/he/sound_he.cpp38
-rw-r--r--engines/scumm/he/sprite_he.cpp2
-rw-r--r--engines/scumm/he/wiz_he.cpp76
-rw-r--r--engines/scumm/help.cpp24
-rw-r--r--engines/scumm/imuse/imuse.cpp39
-rw-r--r--engines/scumm/imuse/imuse.h1
-rw-r--r--engines/scumm/imuse/imuse_internal.h13
-rw-r--r--engines/scumm/imuse/imuse_part.cpp2
-rw-r--r--engines/scumm/imuse/imuse_player.cpp18
-rw-r--r--engines/scumm/imuse/sysex_scumm.cpp1
-rw-r--r--engines/scumm/imuse_digi/dimuse.cpp1
-rw-r--r--engines/scumm/imuse_digi/dimuse.h2
-rw-r--r--engines/scumm/imuse_digi/dimuse_bndmgr.cpp7
-rw-r--r--engines/scumm/imuse_digi/dimuse_bndmgr.h8
-rw-r--r--engines/scumm/imuse_digi/dimuse_codecs.cpp311
-rw-r--r--engines/scumm/imuse_digi/dimuse_codecs.h (renamed from engines/mohawk/myst_vars.h)42
-rw-r--r--engines/scumm/imuse_digi/dimuse_sndmgr.cpp42
-rw-r--r--engines/scumm/insane/insane.cpp2
-rw-r--r--engines/scumm/insane/insane_iact.cpp20
-rw-r--r--engines/scumm/midiparser_ro.cpp1
-rw-r--r--engines/scumm/nut_renderer.cpp8
-rw-r--r--engines/scumm/object.cpp88
-rw-r--r--engines/scumm/palette.cpp9
-rw-r--r--engines/scumm/player_mod.h2
-rw-r--r--engines/scumm/player_nes.h2
-rw-r--r--engines/scumm/player_pce.cpp4
-rw-r--r--engines/scumm/player_pce.h1
-rw-r--r--engines/scumm/player_sid.cpp20
-rw-r--r--engines/scumm/player_towns.cpp8
-rw-r--r--engines/scumm/player_v4a.h1
-rw-r--r--engines/scumm/proc3ARM.s64
-rw-r--r--engines/scumm/resource.cpp186
-rw-r--r--engines/scumm/resource_v3.cpp4
-rw-r--r--engines/scumm/resource_v4.cpp4
-rw-r--r--engines/scumm/room.cpp49
-rw-r--r--engines/scumm/saveload.cpp16
-rw-r--r--engines/scumm/saveload.h4
-rw-r--r--engines/scumm/script.cpp44
-rw-r--r--engines/scumm/script.h21
-rw-r--r--engines/scumm/script_v5.cpp24
-rw-r--r--engines/scumm/script_v6.cpp8
-rw-r--r--engines/scumm/scumm-md5.h3
-rw-r--r--engines/scumm/scumm.cpp41
-rw-r--r--engines/scumm/scumm.h45
-rw-r--r--engines/scumm/scumm_v3.h2
-rw-r--r--engines/scumm/scumm_v4.h2
-rw-r--r--engines/scumm/smush/channel.cpp2
-rw-r--r--engines/scumm/smush/channel.h2
-rw-r--r--engines/scumm/smush/codec37.cpp1
-rw-r--r--engines/scumm/smush/codec47.cpp3
-rw-r--r--engines/scumm/smush/imuse_channel.cpp37
-rw-r--r--engines/scumm/smush/saud_channel.cpp11
-rw-r--r--engines/scumm/smush/smush_mixer.h2
-rw-r--r--engines/scumm/smush/smush_player.cpp33
-rw-r--r--engines/scumm/sound.cpp91
-rw-r--r--engines/scumm/util.cpp1
-rw-r--r--engines/scumm/verbs.cpp2
-rw-r--r--engines/sky/autoroute.cpp1
-rw-r--r--engines/sky/compact.cpp5
-rw-r--r--engines/sky/compact.h2
-rw-r--r--engines/sky/control.cpp7
-rw-r--r--engines/sky/control.h2
-rw-r--r--engines/sky/debug.cpp2
-rw-r--r--engines/sky/detection.cpp1
-rw-r--r--engines/sky/disk.cpp4
-rw-r--r--engines/sky/disk.h3
-rw-r--r--engines/sky/intro.cpp1
-rw-r--r--engines/sky/logic.cpp7
-rw-r--r--engines/sky/mouse.cpp1
-rw-r--r--engines/sky/music/adlibchannel.cpp1
-rw-r--r--engines/sky/music/gmchannel.cpp1
-rw-r--r--engines/sky/music/gmmusic.cpp5
-rw-r--r--engines/sky/music/mt32music.cpp1
-rw-r--r--engines/sky/music/musicbase.cpp10
-rw-r--r--engines/sky/screen.cpp49
-rw-r--r--engines/sky/screen.h11
-rw-r--r--engines/sky/sky.cpp30
-rw-r--r--engines/sky/sky.h8
-rw-r--r--engines/sky/skydefs.h4
-rw-r--r--engines/sky/sound.cpp2
-rw-r--r--engines/sky/struc.h6
-rw-r--r--engines/sky/text.cpp16
-rw-r--r--engines/sky/text.h8
-rw-r--r--engines/sword1/animation.cpp7
-rw-r--r--engines/sword1/control.cpp2
-rw-r--r--engines/sword1/control.h4
-rw-r--r--engines/sword1/detection.cpp2
-rw-r--r--engines/sword1/eventman.cpp1
-rw-r--r--engines/sword1/logic.cpp3
-rw-r--r--engines/sword1/memman.cpp1
-rw-r--r--engines/sword1/menu.cpp2
-rw-r--r--engines/sword1/mouse.cpp11
-rw-r--r--engines/sword1/mouse.h4
-rw-r--r--engines/sword1/music.cpp3
-rw-r--r--engines/sword1/objectman.cpp1
-rw-r--r--engines/sword1/resman.cpp9
-rw-r--r--engines/sword1/router.cpp1
-rw-r--r--engines/sword1/screen.cpp5
-rw-r--r--engines/sword1/sound.cpp3
-rw-r--r--engines/sword1/sound.h2
-rw-r--r--engines/sword1/sword1.cpp6
-rw-r--r--engines/sword1/sword1.h6
-rw-r--r--engines/sword1/text.cpp3
-rw-r--r--engines/sword2/animation.cpp42
-rw-r--r--engines/sword2/animation.h6
-rw-r--r--engines/sword2/controls.cpp4
-rw-r--r--engines/sword2/events.cpp1
-rw-r--r--engines/sword2/function.cpp17
-rw-r--r--engines/sword2/header.h10
-rw-r--r--engines/sword2/icons.cpp20
-rw-r--r--engines/sword2/interpreter.cpp3
-rw-r--r--engines/sword2/layers.cpp3
-rw-r--r--engines/sword2/logic.cpp1
-rw-r--r--engines/sword2/logic.h2
-rw-r--r--engines/sword2/maketext.cpp39
-rw-r--r--engines/sword2/maketext.h12
-rw-r--r--engines/sword2/memory.cpp1
-rw-r--r--engines/sword2/mouse.cpp23
-rw-r--r--engines/sword2/music.cpp1
-rw-r--r--engines/sword2/object.h2
-rw-r--r--engines/sword2/palette.cpp27
-rw-r--r--engines/sword2/protocol.cpp4
-rw-r--r--engines/sword2/render.cpp16
-rw-r--r--engines/sword2/resman.cpp1
-rw-r--r--engines/sword2/resman.h2
-rw-r--r--engines/sword2/router.cpp7
-rw-r--r--engines/sword2/router.h2
-rw-r--r--engines/sword2/saveload.cpp1
-rw-r--r--engines/sword2/screen.cpp17
-rw-r--r--engines/sword2/screen.h6
-rw-r--r--engines/sword2/scroll.cpp2
-rw-r--r--engines/sword2/sound.cpp1
-rw-r--r--engines/sword2/sound.h1
-rw-r--r--engines/sword2/speech.cpp9
-rw-r--r--engines/sword2/sprite.cpp32
-rw-r--r--engines/sword2/startup.cpp1
-rw-r--r--engines/sword2/sword2.cpp6
-rw-r--r--engines/sword2/sync.cpp1
-rw-r--r--engines/sword25/detection.cpp2
-rw-r--r--engines/sword25/fmv/movieplayer.cpp8
-rw-r--r--engines/sword25/fmv/theora_decoder.cpp3
-rw-r--r--engines/sword25/fmv/theora_decoder.h3
-rw-r--r--engines/sword25/gfx/graphicengine.cpp17
-rw-r--r--engines/sword25/gfx/graphicengine_script.cpp51
-rw-r--r--engines/sword25/gfx/image/art.cpp60
-rw-r--r--engines/sword25/gfx/image/art.h145
-rw-r--r--engines/sword25/gfx/image/image.h144
-rw-r--r--engines/sword25/gfx/image/pngloader.cpp32
-rw-r--r--engines/sword25/gfx/image/renderedimage.cpp75
-rw-r--r--engines/sword25/gfx/image/renderedimage.h24
-rw-r--r--engines/sword25/gfx/image/swimage.cpp8
-rw-r--r--engines/sword25/gfx/image/vectorimage.cpp102
-rw-r--r--engines/sword25/gfx/image/vectorimagerenderer.cpp35
-rw-r--r--engines/sword25/gfx/screenshot.cpp5
-rw-r--r--engines/sword25/gfx/text.cpp4
-rw-r--r--engines/sword25/kernel/filesystemutil.cpp3
-rw-r--r--engines/sword25/kernel/inputpersistenceblock.cpp2
-rw-r--r--engines/sword25/kernel/kernel.cpp4
-rw-r--r--engines/sword25/kernel/kernel.h1
-rw-r--r--engines/sword25/kernel/objectregistry.h1
-rw-r--r--engines/sword25/kernel/persistenceservice.cpp3
-rw-r--r--engines/sword25/math/geometry_script.cpp29
-rw-r--r--engines/sword25/script/luabindhelper.cpp21
-rw-r--r--engines/sword25/script/luabindhelper.h2
-rw-r--r--engines/sword25/script/luacallback.cpp2
-rw-r--r--engines/sword25/sfx/soundengine.cpp2
-rw-r--r--engines/sword25/sword25.cpp18
-rw-r--r--engines/sword25/sword25.h10
-rw-r--r--engines/sword25/util/lua/lmathlib.cpp14
-rw-r--r--engines/sword25/util/pluto/Makefile29
-rw-r--r--engines/sword25/util/pluto/pdep/lauxlib.h174
-rw-r--r--engines/sword25/util/pluto/pdep/ldo.h57
-rw-r--r--engines/sword25/util/pluto/pdep/lfunc.h34
-rw-r--r--engines/sword25/util/pluto/pdep/lgc.h110
-rw-r--r--engines/sword25/util/pluto/pdep/llimits.h128
-rw-r--r--engines/sword25/util/pluto/pdep/lobject.h381
-rw-r--r--engines/sword25/util/pluto/pdep/lopcodes.h268
-rw-r--r--engines/sword25/util/pluto/pdep/lstate.h169
-rw-r--r--engines/sword25/util/pluto/pdep/lstring.h31
-rw-r--r--engines/sword25/util/pluto/pdep/ltm.h54
-rw-r--r--engines/sword25/util/pluto/pdep/lua.h388
-rw-r--r--engines/sword25/util/pluto/pdep/lzio.h2
-rw-r--r--engines/sword25/util/pluto/pdep/pdep.h21
-rw-r--r--engines/sword25/util/pluto/pptest.cpp95
-rw-r--r--engines/sword25/util/pluto/pptest.lua168
-rw-r--r--engines/sword25/util/pluto/puptest.cpp81
-rw-r--r--engines/sword25/util/pluto/puptest.lua93
-rw-r--r--engines/teenagent/actor.cpp1
-rw-r--r--engines/teenagent/animation.cpp1
-rw-r--r--engines/teenagent/callbacks.cpp2
-rw-r--r--engines/teenagent/console.h4
-rw-r--r--engines/teenagent/font.cpp4
-rw-r--r--engines/teenagent/font.h1
-rw-r--r--engines/teenagent/inventory.cpp1
-rw-r--r--engines/teenagent/music.cpp2
-rw-r--r--engines/teenagent/resources.cpp1
-rw-r--r--engines/teenagent/scene.cpp5
-rw-r--r--engines/teenagent/scene.h4
-rw-r--r--engines/teenagent/segment.cpp1
-rw-r--r--engines/teenagent/surface.cpp2
-rw-r--r--engines/teenagent/surface.h6
-rw-r--r--engines/teenagent/teenagent.cpp2
-rw-r--r--engines/testbed/detection.cpp2
-rw-r--r--engines/testbed/events.cpp7
-rw-r--r--engines/testbed/graphics.cpp19
-rw-r--r--engines/testbed/midi.cpp2
-rw-r--r--engines/testbed/savegame.cpp6
-rw-r--r--engines/testbed/sound.cpp2
-rw-r--r--engines/testbed/testbed.cpp7
-rw-r--r--engines/testbed/testbed.h4
-rw-r--r--engines/testbed/testsuite.h5
-rw-r--r--engines/tinsel/actors.cpp35
-rw-r--r--engines/tinsel/actors.h2
-rw-r--r--engines/tinsel/adpcm.cpp171
-rw-r--r--engines/tinsel/adpcm.h105
-rw-r--r--engines/tinsel/anim.cpp1
-rw-r--r--engines/tinsel/background.cpp16
-rw-r--r--engines/tinsel/background.h6
-rw-r--r--engines/tinsel/bg.cpp3
-rw-r--r--engines/tinsel/bmv.cpp42
-rw-r--r--engines/tinsel/bmv.h5
-rw-r--r--engines/tinsel/detection.cpp7
-rw-r--r--engines/tinsel/dialogs.cpp46
-rw-r--r--engines/tinsel/dialogs.h2
-rw-r--r--engines/tinsel/drives.cpp7
-rw-r--r--engines/tinsel/dw.h2
-rw-r--r--engines/tinsel/faders.cpp68
-rw-r--r--engines/tinsel/faders.h2
-rw-r--r--engines/tinsel/font.cpp4
-rw-r--r--engines/tinsel/graphics.cpp50
-rw-r--r--engines/tinsel/graphics.h2
-rw-r--r--engines/tinsel/handle.cpp9
-rw-r--r--engines/tinsel/mareels.cpp1
-rw-r--r--engines/tinsel/module.mk1
-rw-r--r--engines/tinsel/move.cpp28
-rw-r--r--engines/tinsel/music.cpp180
-rw-r--r--engines/tinsel/music.h52
-rw-r--r--engines/tinsel/object.cpp10
-rw-r--r--engines/tinsel/object.h4
-rw-r--r--engines/tinsel/palette.cpp182
-rw-r--r--engines/tinsel/palette.h42
-rw-r--r--engines/tinsel/pcode.cpp1
-rw-r--r--engines/tinsel/pcode.h2
-rw-r--r--engines/tinsel/pdisplay.cpp24
-rw-r--r--engines/tinsel/pid.h6
-rw-r--r--engines/tinsel/polygons.cpp39
-rw-r--r--engines/tinsel/polygons.h4
-rw-r--r--engines/tinsel/rince.cpp11
-rw-r--r--engines/tinsel/rince.h8
-rw-r--r--engines/tinsel/saveload.cpp66
-rw-r--r--engines/tinsel/savescn.cpp4
-rw-r--r--engines/tinsel/scene.cpp21
-rw-r--r--engines/tinsel/sched.cpp1
-rw-r--r--engines/tinsel/scn.cpp3
-rw-r--r--engines/tinsel/sound.cpp33
-rw-r--r--engines/tinsel/strres.cpp1
-rw-r--r--engines/tinsel/sysvar.cpp6
-rw-r--r--engines/tinsel/sysvar.h4
-rw-r--r--engines/tinsel/text.cpp12
-rw-r--r--engines/tinsel/text.h8
-rw-r--r--engines/tinsel/timers.cpp2
-rw-r--r--engines/tinsel/timers.h2
-rw-r--r--engines/tinsel/tinlib.cpp43
-rw-r--r--engines/tinsel/tinlib.h2
-rw-r--r--engines/tinsel/tinsel.cpp37
-rw-r--r--engines/tinsel/tinsel.h7
-rw-r--r--engines/toon/anim.cpp29
-rw-r--r--engines/toon/anim.h2
-rw-r--r--engines/toon/audio.cpp91
-rw-r--r--engines/toon/audio.h9
-rw-r--r--engines/toon/character.cpp54
-rw-r--r--engines/toon/character.h2
-rw-r--r--engines/toon/conversation.cpp1
-rw-r--r--engines/toon/conversation.h4
-rw-r--r--engines/toon/detection.cpp9
-rw-r--r--engines/toon/drew.cpp5
-rw-r--r--engines/toon/drew.h2
-rw-r--r--engines/toon/flux.cpp4
-rw-r--r--engines/toon/flux.h1
-rw-r--r--engines/toon/font.cpp14
-rw-r--r--engines/toon/hotspot.cpp10
-rw-r--r--engines/toon/movie.cpp27
-rw-r--r--engines/toon/movie.h2
-rw-r--r--engines/toon/path.cpp17
-rw-r--r--engines/toon/path.h1
-rw-r--r--engines/toon/picture.cpp84
-rw-r--r--engines/toon/picture.h1
-rw-r--r--engines/toon/resource.cpp157
-rw-r--r--engines/toon/resource.h29
-rw-r--r--engines/toon/script.cpp12
-rw-r--r--engines/toon/script.h5
-rw-r--r--engines/toon/script_func.cpp20
-rw-r--r--engines/toon/state.cpp3
-rw-r--r--engines/toon/state.h2
-rw-r--r--engines/toon/text.cpp2
-rw-r--r--engines/toon/tools.cpp42
-rw-r--r--engines/toon/tools.h8
-rw-r--r--engines/toon/toon.cpp376
-rw-r--r--engines/toon/toon.h17
-rw-r--r--engines/touche/menu.cpp4
-rw-r--r--engines/touche/midi.cpp156
-rw-r--r--engines/touche/midi.h44
-rw-r--r--engines/touche/resource.cpp1
-rw-r--r--engines/touche/saveload.cpp1
-rw-r--r--engines/touche/staticres.cpp11
-rw-r--r--engines/touche/touche.cpp20
-rw-r--r--engines/tsage/converse.cpp953
-rw-r--r--engines/tsage/converse.h229
-rw-r--r--engines/tsage/core.cpp3646
-rw-r--r--engines/tsage/core.h940
-rw-r--r--engines/tsage/debugger.cpp399
-rw-r--r--engines/tsage/debugger.h54
-rw-r--r--engines/tsage/detection.cpp192
-rw-r--r--engines/tsage/detection_tables.h119
-rw-r--r--engines/tsage/dialogs.cpp600
-rw-r--r--engines/tsage/dialogs.h136
-rw-r--r--engines/tsage/events.cpp311
-rw-r--r--engines/tsage/events.h112
-rw-r--r--engines/tsage/globals.cpp127
-rw-r--r--engines/tsage/globals.h104
-rw-r--r--engines/tsage/graphics.cpp1444
-rw-r--r--engines/tsage/graphics.h349
-rw-r--r--engines/tsage/module.mk36
-rw-r--r--engines/tsage/resources.cpp501
-rw-r--r--engines/tsage/resources.h183
-rw-r--r--engines/tsage/ringworld_demo.cpp58
-rw-r--r--engines/tsage/ringworld_demo.h52
-rw-r--r--engines/tsage/ringworld_logic.cpp1421
-rw-r--r--engines/tsage/ringworld_logic.h473
-rw-r--r--engines/tsage/ringworld_scenes1.cpp3302
-rw-r--r--engines/tsage/ringworld_scenes1.h536
-rw-r--r--engines/tsage/ringworld_scenes10.cpp2072
-rw-r--r--engines/tsage/ringworld_scenes10.h533
-rw-r--r--engines/tsage/ringworld_scenes2.cpp927
-rw-r--r--engines/tsage/ringworld_scenes2.h152
-rw-r--r--engines/tsage/ringworld_scenes3.cpp6110
-rw-r--r--engines/tsage/ringworld_scenes3.h896
-rw-r--r--engines/tsage/ringworld_scenes4.cpp253
-rw-r--r--engines/tsage/ringworld_scenes4.h95
-rw-r--r--engines/tsage/ringworld_scenes5.cpp4413
-rw-r--r--engines/tsage/ringworld_scenes5.h696
-rw-r--r--engines/tsage/ringworld_scenes6.cpp2191
-rw-r--r--engines/tsage/ringworld_scenes6.h333
-rw-r--r--engines/tsage/ringworld_scenes8.cpp2526
-rw-r--r--engines/tsage/ringworld_scenes8.h496
-rw-r--r--engines/tsage/saveload.cpp401
-rw-r--r--engines/tsage/saveload.h223
-rw-r--r--engines/tsage/scenes.cpp495
-rw-r--r--engines/tsage/scenes.h116
-rw-r--r--engines/tsage/sound.cpp60
-rw-r--r--engines/tsage/sound.h49
-rw-r--r--engines/tsage/staticres.cpp120
-rw-r--r--engines/tsage/staticres.h88
-rw-r--r--engines/tsage/tsage.cpp136
-rw-r--r--engines/tsage/tsage.h104
-rw-r--r--engines/tucker/detection.cpp5
-rw-r--r--engines/tucker/locations.cpp1
-rw-r--r--engines/tucker/resource.cpp1
-rw-r--r--engines/tucker/saveload.cpp1
-rw-r--r--engines/tucker/sequences.cpp3
-rw-r--r--engines/tucker/tucker.cpp27
-rw-r--r--engines/tucker/tucker.h1
1032 files changed, 53602 insertions, 15600 deletions
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index bf152ce90a..8170452102 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -23,7 +23,8 @@
*
*/
-#include "base/plugins.h"
+// FIXME: Avoid using printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#include "common/debug.h"
#include "common/util.h"
@@ -32,6 +33,7 @@
#include "common/macresman.h"
#include "common/md5.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
#include "engines/advancedDetector.h"
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 515127b23d..757fb12f33 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -25,11 +25,13 @@
#ifndef ENGINES_ADVANCED_DETECTOR_H
#define ENGINES_ADVANCED_DETECTOR_H
-#include "common/fs.h"
-#include "common/error.h"
-
#include "engines/metaengine.h"
+namespace Common {
+class Error;
+class FSList;
+}
+
struct ADGameFileDescription {
const char *fileName;
@@ -62,8 +64,8 @@ struct ADGameDescription {
Common::Platform platform;
/**
- * A bitmask of extra flags. The top 8 bits are reserved for generic flags
- * defined in the ADGameFlags. This leaves 24 flags to be used by client
+ * A bitmask of extra flags. The top 16 bits are reserved for generic flags
+ * defined in the ADGameFlags. This leaves 16 bits to be used by client
* code.
*/
uint32 flags;
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index fdc05f0ba9..a69d19f06c 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -32,6 +32,7 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/random.h"
+#include "common/textconsole.h"
#include "engines/util.h"
@@ -273,23 +274,16 @@ void AgiEngine::processEvents() {
}
void AgiEngine::pollTimer() {
- uint32 dm;
+ _lastTick += 50;
- if (_tickTimer < _lastTickTimer)
- _lastTickTimer = 0;
-
- while ((dm = _tickTimer - _lastTickTimer) < 5) {
+ while (_system->getMillis() < _lastTick) {
processEvents();
_console->onFrame();
_system->delayMillis(10);
_system->updateScreen();
}
- _lastTickTimer = _tickTimer;
-}
-void AgiEngine::agiTimerFunctionLow(void *refCon) {
- AgiEngine *self = (AgiEngine *)refCon;
- self->_tickTimer++;
+ _lastTick = _system->getMillis();
}
void AgiEngine::pause(uint32 msec) {
@@ -361,12 +355,12 @@ int AgiEngine::agiInit() {
switch (getVersion() >> 12) {
case 2:
- debug("Emulating Sierra AGI v%x.%03x\n",
+ debug("Emulating Sierra AGI v%x.%03x",
(int)(getVersion() >> 12) & 0xF,
(int)(getVersion()) & 0xFFF);
break;
case 3:
- debug("Emulating Sierra AGI v%x.002.%03x\n",
+ debug("Emulating Sierra AGI v%x.002.%03x",
(int)(getVersion() >> 12) & 0xF,
(int)(getVersion()) & 0xFFF);
break;
@@ -532,9 +526,6 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_allowSynthetic = false;
- _tickTimer = 0;
- _lastTickTimer = 0;
-
_intobj = NULL;
_menu = NULL;
@@ -646,11 +637,10 @@ void AgiEngine::initialize() {
_lastSaveTime = 0;
- _timer->installTimerProc(agiTimerFunctionLow, 10 * 1000, this);
+ _lastTick = _system->getMillis();
debugC(2, kDebugLevelMain, "Detect game");
-
if (agiDetectGame() == errOK) {
_game.state = STATE_LOADED;
debugC(2, kDebugLevelMain, "game loaded");
@@ -662,8 +652,6 @@ void AgiEngine::initialize() {
}
AgiEngine::~AgiEngine() {
- _timer->removeTimerProc(agiTimerFunctionLow);
-
// If the engine hasn't been initialized yet via AgiEngine::initialize(), don't attempt to free any resources,
// as they haven't been allocated. Fixes bug #1742432 - AGI: Engine crashes if no game is detected
if (_game.state == STATE_INIT) {
@@ -719,7 +707,7 @@ void AgiEngine::parseFeatures() {
/* FIXME: Seems this method doesn't really do anything. It might
be a leftover that could be removed, except that some of its
intended purpose may still need to be reimplemented.
-
+
[0:29] <Fingolfin> can you tell me what the point behind AgiEngine::parseFeatures() is?
[0:30] <_sev> when games are created with WAGI studio
[0:31] <_sev> it creates .wag site with game-specific features such as full game title, whether to use AGIMOUSE etc
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 89b116daec..c71a0ebf64 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -27,9 +27,10 @@
#define AGI_H
#include "common/scummsys.h"
-#include "common/endian.h"
+#include "common/error.h"
#include "common/util.h"
#include "common/file.h"
+#include "common/rect.h"
#include "common/stack.h"
#include "common/system.h"
@@ -45,7 +46,9 @@
#include "agi/sound.h"
-namespace Common { class RandomSource; }
+namespace Common {
+class RandomSource;
+}
/**
* This is the namespace of the AGI engine.
@@ -92,7 +95,7 @@ typedef signed int Err;
#define CRYPT_KEY_SIERRA "Avis Durgan"
#define CRYPT_KEY_AGDS "Alex Simkin"
-#define MSG_BOX_COLOUR 0x0f // White
+#define MSG_BOX_COLOR 0x0f // White
#define MSG_BOX_TEXT 0x00 // Black
#define MSG_BOX_LINE 0x04 // Red
#define BUTTON_BORDER 0x00 // Black
@@ -693,7 +696,6 @@ public:
class GfxMgr;
class SpritesMgr;
class Menu;
-class SearchTree;
// Image stack support
struct ImageStackElement {
@@ -727,7 +729,7 @@ protected:
virtual Common::Error run() {
Common::Error err;
err = init();
- if (err != Common::kNoError)
+ if (err.getCode() != Common::kNoError)
return err;
return go();
}
@@ -810,9 +812,7 @@ public:
Common::Error saveGameState(int slot, const char *desc);
private:
-
- uint32 _tickTimer;
- uint32 _lastTickTimer;
+ uint32 _lastTick;
int _keyQueue[KEY_QUEUE_SIZE];
int _keyQueueStart;
@@ -883,7 +883,6 @@ public:
virtual bool isKeypress();
virtual void clearKeyQueue();
- static void agiTimerFunctionLow(void *refCon);
void initPriTable();
void newInputMode(InputMode mode);
@@ -938,7 +937,7 @@ public:
private:
// Some submethods of testIfCode
uint8 testObjRight(uint8, uint8, uint8, uint8, uint8);
- uint8 testObjCentre(uint8, uint8, uint8, uint8, uint8);
+ uint8 testObjCenter(uint8, uint8, uint8, uint8, uint8);
uint8 testObjInBox(uint8, uint8, uint8, uint8, uint8);
uint8 testPosn(uint8, uint8, uint8, uint8, uint8);
uint8 testSaid(uint8, uint8 *);
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 6e9a996756..fb92344de2 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -23,12 +23,16 @@
*
*/
+// FIXME: Avoid using printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
+
#include "base/plugins.h"
#include "engines/advancedDetector.h"
#include "common/config-manager.h"
#include "common/file.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "graphics/thumbnail.h"
#include "graphics/surface.h"
@@ -218,7 +222,7 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD
}
SaveStateList AgiMetaEngine::listSaves(const char *target) const {
- const uint32 AGIflag = MKID_BE('AGI:');
+ const uint32 AGIflag = MKTAG('A','G','I',':');
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
char saveDesc[31];
@@ -257,7 +261,7 @@ void AgiMetaEngine::removeSaveState(const char *target, int slot) const {
}
SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
- const uint32 AGIflag = MKID_BE('AGI:');
+ const uint32 AGIflag = MKTAG('A','G','I',':');
char fileName[MAXPATHLEN];
sprintf(fileName, "%s.%03d", target, slot);
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index 711701f55a..4689915007 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -528,6 +528,10 @@ static const AGIGameDescription gameDescriptions[] = {
// Space Quest 2 (PC 5.25") 2.0A [AGI 2.912]
GAME_PS("sq2", "2.0A 1987-11-06 5.25\"", "ad7ce8f800581ecc536f3e8021d7a74d", 423, 0x2917, GID_SQ2, Common::kPlatformPC),
+ // reported by RadG (radg123) in bug report #3260349
+ // Space Quest 2 (Spanish)
+ GAME_LPS("sq2", "", "1ae7640dd4d253c3ac2d708d61a35379", 426, Common::ES_ESP, 0x2917, GID_SQ2, Common::kPlatformPC),
+
// Space Quest 2 (Russian)
GAME_LPS("sq2", "", "ba21c8934caf28e3ba45ce7d1cd6b041", 423, Common::RU_RUS, 0x2917, GID_SQ2, Common::kPlatformPC),
@@ -569,6 +573,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3),
FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE),
+ FANMADE("AGI Combat", "0be6a8a9e19203dcca0067d280798871"),
FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"),
FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"),
FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"),
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index 58982a2931..f0d38761d0 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -24,9 +24,10 @@
*/
#include "common/file.h"
-
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
#include "agi/agi.h"
#include "agi/graphics.h"
@@ -685,14 +686,14 @@ void GfxMgr::drawFrame(int x1, int y1, int x2, int y2, int c1, int c2) {
}
}
-void GfxMgr::drawBox(int x1, int y1, int x2, int y2, int colour1, int colour2, int m) {
+void GfxMgr::drawBox(int x1, int y1, int x2, int y2, int color1, int color2, int m) {
x1 += m;
y1 += m;
x2 -= m;
y2 -= m;
- drawRectangle(x1, y1, x2, y2, colour1);
- drawFrame(x1 + 2, y1 + 2, x2 - 2, y2 - 2, colour2, colour2);
+ drawRectangle(x1, y1, x2, y2, color1);
+ drawFrame(x1 + 2, y1 + 2, x2 - 2, y2 - 2, color2, color2);
flushBlock(x1, y1, x2, y2);
}
@@ -752,7 +753,7 @@ void GfxMgr::rawDrawButton(int x, int y, const char *s, int fgcolor, int bgcolor
// Draw a filled rectangle that's larger than the button. Used for drawing
// a border around the button as the button itself is drawn after this.
- drawRectangle(x1, y1, x2, y2, border ? BUTTON_BORDER : MSG_BOX_COLOUR);
+ drawRectangle(x1, y1, x2, y2, border ? BUTTON_BORDER : MSG_BOX_COLOR);
while (*s) {
putTextCharacter(0, x + textOffset, y + textOffset, *s++, fgcolor, bgcolor);
diff --git a/engines/agi/inv.cpp b/engines/agi/inv.cpp
index 46dfcb2b43..f1d9523887 100644
--- a/engines/agi/inv.cpp
+++ b/engines/agi/inv.cpp
@@ -66,7 +66,7 @@ namespace Agi {
#define SELECT_MSG_RU "ENTER - \xa2\xeb\xa1\xe0\xa0\xe2\xec, ESC - \xae\xe2\xac\xa5\xad\xa8\xe2\xec."
void AgiEngine::printItem(int n, int fg, int bg) {
- printText(objectName(_intobj[n]), 0, n % 2 ? 39 - strlen(objectName(_intobj[n])) : 1,
+ printText(objectName(_intobj[n]), 0, ((n % 2) ? 39 - strlen(objectName(_intobj[n])) : 1),
(n / 2) + 2, 40, fg, bg);
}
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index 344654128d..95211f8e3c 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -279,7 +279,7 @@ void AgiEngine::handleGetstring(int key) {
void AgiEngine::handleKeys(int key) {
uint8 *p = NULL;
int c = 0;
- static uint8 formattedEntry[256];
+ static uint8 formattedEntry[40];
int l = _game.lineUserInput;
int fg = _game.colorFg, bg = _game.colorBg;
int promptLength = strlen(agiSprintf(_game.strings[0]));
@@ -298,7 +298,7 @@ void AgiEngine::handleKeys(int key) {
;
// Copy to internal buffer
- for (; *p; p++) {
+ for (; *p && c < 40-1; p++) {
// Squash spaces
if (*p == 0x20 && *(p + 1) == 0x20) {
p++;
diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp
index 8780e1dab8..0141a61065 100644
--- a/engines/agi/loader_v2.cpp
+++ b/engines/agi/loader_v2.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "agi/agi.h"
namespace Agi {
diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp
index 18ea4cae7d..025e755c8b 100644
--- a/engines/agi/loader_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -28,6 +28,7 @@
#include "common/config-manager.h"
#include "common/fs.h"
+#include "common/textconsole.h"
namespace Agi {
diff --git a/engines/agi/lzw.cpp b/engines/agi/lzw.cpp
index f645cb16d3..495d6458da 100644
--- a/engines/agi/lzw.cpp
+++ b/engines/agi/lzw.cpp
@@ -36,6 +36,8 @@
#include "agi/agi.h"
#include "agi/lzw.h"
+#include "common/textconsole.h"
+
namespace Agi {
diff --git a/engines/agi/menu.cpp b/engines/agi/menu.cpp
index 5ec4908e4a..b62bcd9ad8 100644
--- a/engines/agi/menu.cpp
+++ b/engines/agi/menu.cpp
@@ -117,7 +117,7 @@ void Menu::drawMenuOptionHilite(int hMenu, int vMenu) {
AgiMenuOption *d = getMenuOption(hMenu, vMenu);
// Disabled menu items are "greyed out" with a checkerboard effect,
- // rather than having a different colour. -- dsymonds
+ // rather than having a different color. -- dsymonds
_vm->printText(d->text, 0, m->wincol + 1, vMenu + 2, m->width + 2,
MENU_BG, MENU_FG, !d->enabled);
}
diff --git a/engines/agi/objects.cpp b/engines/agi/objects.cpp
index d942a2b538..bea53d7fa4 100644
--- a/engines/agi/objects.cpp
+++ b/engines/agi/objects.cpp
@@ -25,6 +25,8 @@
#include "agi/agi.h"
+#include "common/textconsole.h"
+
namespace Agi {
int AgiEngine::allocObjects(int n) {
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index 2ea53e57ad..e1f99456e8 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -32,6 +32,7 @@
#include "agi/menu.h"
#include "common/random.h"
+#include "common/textconsole.h"
namespace Agi {
diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp
index ab4f6cadc5..f5234d4e6c 100644
--- a/engines/agi/op_test.cpp
+++ b/engines/agi/op_test.cpp
@@ -132,8 +132,8 @@ uint8 AgiEngine::testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
v->yPos >= y1 && v->xPos + v->xSize - 1 <= x2 && v->yPos <= y2;
}
-// if n is in centre of box
-uint8 AgiEngine::testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
+// if n is in center of box
+uint8 AgiEngine::testObjCenter(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
VtEntry *v = &_game.viewTable[n];
return v->xPos + v->xSize / 2 >= x1 &&
@@ -311,7 +311,7 @@ int AgiEngine::testIfCode(int lognum) {
ec = testObjInBox(p[0], p[1], p[2], p[3], p[4]);
break;
case 0x11:
- ec = testObjCentre(p[0], p[1], p[2], p[3], p[4]);
+ ec = testObjCenter(p[0], p[1], p[2], p[3], p[4]);
break;
case 0x12:
ec = testObjRight(p[0], p[1], p[2], p[3], p[4]);
diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp
index 47b72cc8c6..8951fc81df 100644
--- a/engines/agi/picture.cpp
+++ b/engines/agi/picture.cpp
@@ -26,6 +26,8 @@
#include "agi/agi.h"
#include "agi/graphics.h"
+#include "common/textconsole.h"
+
namespace Agi {
PictureMgr::PictureMgr(AgiBase *agi, GfxMgr *gfx) {
@@ -601,7 +603,7 @@ void PictureMgr::drawPicture() {
_patCode = nextByte();
plotBrush();
break;
- case 0xf0: // set colour on screen (AGI pic v2)
+ case 0xf0: // set color on screen (AGI pic v2)
if (_pictureVersion == AGIPIC_V15)
break;
@@ -615,7 +617,7 @@ void PictureMgr::drawPicture() {
_scrColor &= 0xF; // for v3 drawing diff
_scrOn = true;
_priOn = false;
- } else if (_pictureVersion == AGIPIC_V15) { // set colour on screen
+ } else if (_pictureVersion == AGIPIC_V15) { // set color on screen
_scrColor = nextByte();
_scrColor &= 0xF;
_scrOn = true;
@@ -623,7 +625,7 @@ void PictureMgr::drawPicture() {
_scrOn = false;
}
break;
- case 0xf2: // set colour on priority (AGI pic v2)
+ case 0xf2: // set color on priority (AGI pic v2)
if (_pictureVersion == AGIPIC_V15)
break;
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp
index fe864d7659..c51c53e76e 100644
--- a/engines/agi/preagi.cpp
+++ b/engines/agi/preagi.cpp
@@ -26,6 +26,7 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/random.h"
+#include "common/textconsole.h"
#include "audio/mididrv.h"
@@ -42,8 +43,7 @@ namespace Agi {
PreAgiEngine::PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBase(syst, gameDesc) {
// Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ syncSoundSettings();
_rnd = new Common::RandomSource();
@@ -122,9 +122,6 @@ void PreAgiEngine::initialize() {
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- //_timer->installTimerProc(agiTimerFunctionLow, 10 * 1000, NULL);
-
debugC(2, kDebugLevelMain, "Detect game");
// clear all resources and events
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index ea041a93c7..64fc4e9ae5 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -25,6 +25,7 @@
#include "common/events.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
@@ -1003,7 +1004,7 @@ bool Mickey::loadGame() {
if (_vm->getSelection(kSelAnyKey) == 0)
return false;
} else {
- if (infile->readUint32BE() != MKID_BE('MICK')) {
+ if (infile->readUint32BE() != MKTAG('M','I','C','K')) {
warning("Mickey::loadGame wrong save game format");
return false;
}
@@ -1120,7 +1121,7 @@ void Mickey::saveGame() {
if (_vm->getSelection(kSelAnyKey) == 0)
return;
} else {
- outfile->writeUint32BE(MKID_BE('MICK')); // header
+ outfile->writeUint32BE(MKTAG('M','I','C','K')); // header
outfile->writeByte(MSA_SAVEGAME_VERSION);
outfile->writeByte(_game.iRoom);
diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp
index 4e87c8063c..76849949c7 100644
--- a/engines/agi/preagi_troll.cpp
+++ b/engines/agi/preagi_troll.cpp
@@ -28,6 +28,7 @@
#include "agi/graphics.h"
#include "common/events.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp
index 643cbd86a9..c92434c15f 100644
--- a/engines/agi/preagi_winnie.cpp
+++ b/engines/agi/preagi_winnie.cpp
@@ -32,6 +32,7 @@
#include "common/events.h"
#include "common/memstream.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
namespace Agi {
@@ -1159,7 +1160,7 @@ void Winnie::saveGame() {
if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile)))
return;
- outfile->writeUint32BE(MKID_BE('WINN')); // header
+ outfile->writeUint32BE(MKTAG('W','I','N','N')); // header
outfile->writeByte(WTP_SAVEGAME_VERSION);
outfile->writeByte(_game.fSound);
@@ -1195,7 +1196,7 @@ void Winnie::loadGame() {
if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile)))
return;
- if (infile->readUint32BE() == MKID_BE('WINN')) {
+ if (infile->readUint32BE() == MKTAG('W','I','N','N')) {
saveVersion = infile->readByte();
if (saveVersion != WTP_SAVEGAME_VERSION)
warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, WTP_SAVEGAME_VERSION);
diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp
index 0230b9bd74..96ad78ace5 100644
--- a/engines/agi/predictive.cpp
+++ b/engines/agi/predictive.cpp
@@ -28,6 +28,7 @@
#include "agi/keyboard.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
#ifdef __DS__
#include "wordcompletion.h"
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index 94df063609..c8df726fc7 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -31,6 +31,7 @@
#include "common/file.h"
#include "common/config-manager.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "graphics/thumbnail.h"
#include "graphics/surface.h"
@@ -53,7 +54,7 @@
namespace Agi {
-static const uint32 AGIflag = MKID_BE('AGI:');
+static const uint32 AGIflag = MKTAG('A','G','I',':');
int AgiEngine::saveGame(const char *fileName, const char *description) {
char gameIDstring[8] = "gameIDX";
@@ -597,7 +598,7 @@ int AgiEngine::selectSlot() {
int hm = 1, vm = 3; // box margins
int xmin, xmax, slotClicked;
char desc[NUM_VISIBLE_SLOTS][40];
- int textCentre, buttonLength, buttonX[2], buttonY;
+ int textCenter, buttonLength, buttonX[2], buttonY;
const char *buttonText[] = { " OK ", "Cancel", NULL };
_noSaveLoadAllowed = true;
@@ -606,10 +607,10 @@ int AgiEngine::selectSlot() {
getSavegameDescription(_firstSlot + i, desc[i]);
}
- textCentre = GFX_WIDTH / CHAR_LINES / 2;
+ textCenter = GFX_WIDTH / CHAR_LINES / 2;
buttonLength = 6;
- buttonX[0] = (textCentre - 3 * buttonLength / 2) * CHAR_COLS;
- buttonX[1] = (textCentre + buttonLength / 2) * CHAR_COLS;
+ buttonX[0] = (textCenter - 3 * buttonLength / 2) * CHAR_COLS;
+ buttonX[1] = (textCenter + buttonLength / 2) * CHAR_COLS;
buttonY = (vm + 17) * CHAR_LINES;
for (i = 0; i < 2; i++)
@@ -642,8 +643,8 @@ int AgiEngine::selectSlot() {
for (i = 0; i < NUM_VISIBLE_SLOTS; i++) {
sprintf(dstr, "[%2d. %-28.28s]", i + _firstSlot, desc[i]);
printText(dstr, 0, hm + 1, vm + 4 + i,
- (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT,
- i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR);
+ (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOR : MSG_BOX_TEXT,
+ i == active ? MSG_BOX_TEXT : MSG_BOX_COLOR);
}
char upArrow[] = "^";
@@ -651,11 +652,11 @@ int AgiEngine::selectSlot() {
char scrollBar[] = " ";
for (i = 1; i < NUM_VISIBLE_SLOTS - 1; i++)
- printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOUR, 7, true);
+ printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOR, 7, true);
printText(upArrow, 35, hm + 1, vm + 4, 1, 8, 7);
printText(downArrow, 35, hm + 1, vm + 4 + NUM_VISIBLE_SLOTS - 1, 1, 8, 7);
- printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOUR, MSG_BOX_TEXT);
+ printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOR, MSG_BOX_TEXT);
oldActive = active;
oldFirstSlot = _firstSlot;
@@ -808,7 +809,7 @@ int AgiEngine::saveGameDialog() {
do {
drawWindow(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp);
printText("Select a slot in which you wish to\nsave the game:",
- 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOUR);
+ 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOR);
slot = selectSlot();
if (slot + _firstSlot == 0)
messageBox("That slot is for Autosave only.");
@@ -819,7 +820,7 @@ int AgiEngine::saveGameDialog() {
drawWindow(hp, vp + 5 * CHAR_LINES, GFX_WIDTH - hp,
GFX_HEIGHT - vp - 9 * CHAR_LINES);
printText("Enter a description for this game:",
- 0, hm + 1, vm + 6, w, MSG_BOX_TEXT, MSG_BOX_COLOUR);
+ 0, hm + 1, vm + 6, w, MSG_BOX_TEXT, MSG_BOX_COLOR);
_gfx->drawRectangle(3 * CHAR_COLS, 11 * CHAR_LINES - 1,
37 * CHAR_COLS, 12 * CHAR_LINES, MSG_BOX_TEXT);
_gfx->flushBlock(3 * CHAR_COLS, 11 * CHAR_LINES - 1,
@@ -844,7 +845,7 @@ int AgiEngine::saveGameDialog() {
for (numChars = 0; numChars < 28 && name[numChars]; numChars++)
handleGetstring(name[numChars]);
- _gfx->printCharacter(numChars + 3, 11, _game.cursorChar, MSG_BOX_COLOUR, MSG_BOX_TEXT);
+ _gfx->printCharacter(numChars + 3, 11, _game.cursorChar, MSG_BOX_COLOR, MSG_BOX_TEXT);
do {
mainCycle();
} while (_game.inputMode == INPUT_GETSTRING);
@@ -902,7 +903,7 @@ int AgiEngine::loadGameDialog() {
drawWindow(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp);
printText("Select a game which you wish to\nrestore:",
- 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOUR);
+ 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOR);
slot = selectSlot();
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index b215822917..b40cef67ef 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -31,6 +31,8 @@
#include "agi/sound_sarien.h"
#include "agi/sound_pcjr.h"
+#include "common/textconsole.h"
+
namespace Agi {
//
diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp
index 4ed4fb7bab..f5758ed140 100644
--- a/engines/agi/sound_2gs.cpp
+++ b/engines/agi/sound_2gs.cpp
@@ -28,6 +28,7 @@
#include "common/md5.h"
#include "common/memstream.h"
#include "common/str-array.h"
+#include "common/textconsole.h"
#include "agi/agi.h"
#include "agi/sound_2gs.h"
@@ -766,7 +767,7 @@ bool SoundGen2GS::loadInstruments() {
// load the instrument headers and their sample data.
// None of the tested SIERRASTANDARD-files have zeroes in them so
// there's no need to check for prematurely ending samples here.
- setProgramChangeMapping(&exeInfo->instSet.progToInst);
+ setProgramChangeMapping(exeInfo->instSet->progToInst);
return loadWaveFile(*waveFsnode, *exeInfo) && loadInstrumentHeaders(*exeFsnode, *exeInfo);
}
@@ -792,29 +793,29 @@ static const MidiProgramChangeMapping progToInstMappingV2 = {
/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */
static const InstrumentSetInfo instSetV1 = {
- 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1
+ 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", &progToInstMappingV1
};
/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */
static const InstrumentSetInfo instSetV2 = {
- 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2
+ 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", &progToInstMappingV2
};
/** Information about different Apple IIGS AGI executables. */
static const IIgsExeInfo IIgsExeInfos[] = {
- {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1},
- {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2},
- {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2},
- {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2},
- {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2},
- {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2},
- {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2},
- {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2},
- {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2},
- {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2},
- {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2},
- {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2},
- {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2}
+ {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, &instSetV1},
+ {GID_LSL1, "LL", 0x1003, 141003, 0x844E, &instSetV2},
+ {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, &instSetV2},
+ {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, &instSetV2},
+ {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, &instSetV2},
+ {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, &instSetV2},
+ {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, &instSetV2},
+ {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, &instSetV2},
+ {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, &instSetV2},
+ {GID_MH1, "MH", 0x2004, 147678, 0x8979, &instSetV2},
+ {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, &instSetV2},
+ {GID_BC, "BC", 0x3001, 148192, 0x8979, &instSetV2},
+ {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, &instSetV2}
};
/**
@@ -844,20 +845,20 @@ bool SoundGen2GS::loadInstrumentHeaders(const Common::FSNode &exePath, const IIg
file.close();
// Check that we got enough data to be able to parse the instruments
- if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet.byteCount)) {
+ if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet->byteCount)) {
// Check instrument set's length (The info's saved in the executable)
data->seek(exeInfo.instSetStart - 4);
uint16 instSetByteCount = data->readUint16LE();
- if (instSetByteCount != exeInfo.instSet.byteCount) {
+ if (instSetByteCount != exeInfo.instSet->byteCount) {
debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)",
- instSetByteCount, exeInfo.instSet.byteCount, exePath.getPath().c_str());
+ instSetByteCount, exeInfo.instSet->byteCount, exePath.getPath().c_str());
}
// Check instrument set's md5sum
data->seek(exeInfo.instSetStart);
- Common::String md5str = Common::computeStreamMD5AsString(*data, exeInfo.instSet.byteCount);
- if (md5str != exeInfo.instSet.md5) {
+ Common::String md5str = Common::computeStreamMD5AsString(*data, exeInfo.instSet->byteCount);
+ if (md5str != exeInfo.instSet->md5) {
warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless",
md5str.c_str(), exePath.getPath().c_str());
}
@@ -867,20 +868,20 @@ bool SoundGen2GS::loadInstrumentHeaders(const Common::FSNode &exePath, const IIg
// Load the instruments
_instruments.clear();
- _instruments.reserve(exeInfo.instSet.instCount);
+ _instruments.reserve(exeInfo.instSet->instCount);
IIgsInstrumentHeader instrument;
- for (uint i = 0; i < exeInfo.instSet.instCount; i++) {
+ for (uint i = 0; i < exeInfo.instSet->instCount; i++) {
if (!instrument.read(*data)) {
warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments",
- i + 1, exeInfo.instSet.instCount, exePath.getPath().c_str());
+ i + 1, exeInfo.instSet->instCount, exePath.getPath().c_str());
break;
}
_instruments.push_back(instrument); // Add the successfully loaded instrument to the instruments array
}
// Loading was successful only if all instruments were loaded successfully
- loadedOk = (_instruments.size() == exeInfo.instSet.instCount);
+ loadedOk = (_instruments.size() == exeInfo.instSet->instCount);
} else // Couldn't read enough data from the executable file
warning("Error loading instruments from Apple IIGS executable (%s)", exePath.getPath().c_str());
@@ -899,7 +900,7 @@ bool SoundGen2GS::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo
if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) {
// Check wave file's md5sum
Common::String md5str = Common::computeStreamMD5AsString(*uint8Wave, SIERRASTANDARD_SIZE);
- if (md5str != exeInfo.instSet.waveFileMd5) {
+ if (md5str != exeInfo.instSet->waveFileMd5) {
warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \
"Please report the information on the previous line to the ScummVM team.\n" \
"Using the wave file as it is - music may sound weird", md5str.c_str(), exeInfo.exePrefix);
diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h
index 391646d6ce..76f0642b7b 100644
--- a/engines/agi/sound_2gs.h
+++ b/engines/agi/sound_2gs.h
@@ -238,7 +238,7 @@ struct InstrumentSetInfo {
uint instCount; ///< Amount of instrument in the set
const char *md5; ///< MD5 hex digest of the whole instrument set
const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments)
- const MidiProgramChangeMapping &progToInst; ///< Program change to instrument number mapping
+ const MidiProgramChangeMapping *progToInst; ///< Program change to instrument number mapping
};
/** Apple IIGS AGI executable file information. */
@@ -248,7 +248,7 @@ struct IIgsExeInfo {
uint agiVer; ///< Apple IIGS AGI version number, not strictly needed
uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes
uint instSetStart; ///< Starting offset of the instrument set inside the executable file
- const InstrumentSetInfo &instSet; ///< Information about the used instrument set
+ const InstrumentSetInfo *instSet; ///< Information about the used instrument set
};
class IIgsMidiChannel {
diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp
index 47cab0019f..997c1edd6b 100644
--- a/engines/agi/sound_midi.cpp
+++ b/engines/agi/sound_midi.cpp
@@ -49,6 +49,7 @@
#include "common/file.h"
#include "common/memstream.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "agi/agi.h"
@@ -71,134 +72,47 @@ MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A
warning("Error creating MIDI sound from resource %d (Type %d, length %d)", resnum, _type, len);
}
-SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _parser(0), _isPlaying(false), _passThrough(false), _isGM(false) {
- DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
- _driver = MidiDriver::createMidi(dev);
-
- if (ConfMan.getBool("native_mt32") || MidiDriver::getMusicType(dev) == MT_MT32) {
- _nativeMT32 = true;
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- } else {
- _nativeMT32 = false;
- }
-
- memset(_channel, 0, sizeof(_channel));
- memset(_channelVolume, 127, sizeof(_channelVolume));
- _masterVolume = 0;
- this->open();
- _smfParser = MidiParser::createParser_SMF();
- _midiMusicData = NULL;
-}
-
-SoundGenMIDI::~SoundGenMIDI() {
- _driver->setTimerCallback(NULL, NULL);
- stop();
- this->close();
- _smfParser->setMidiDriver(NULL);
- delete _smfParser;
- delete[] _midiMusicData;
-}
-
-void SoundGenMIDI::setChannelVolume(int channel) {
- int newVolume = _channelVolume[channel] * _masterVolume / 255;
- _channel[channel]->volume(newVolume);
-}
-
-void SoundGenMIDI::setVolume(int volume) {
- Common::StackLock lock(_mutex);
-
- volume = CLIP(volume, 0, 255);
- if (_masterVolume == volume)
- return;
- _masterVolume = volume;
-
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- setChannelVolume(i);
- }
- }
-}
-
-int SoundGenMIDI::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
+SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _isGM(false) {
+ MidiPlayer::createDriver(MDT_MIDI | MDT_ADLIB);
int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->setTimerCallback(this, &onTimer);
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
-
- return 0;
-}
-
-void SoundGenMIDI::close() {
- stop();
- if (_driver)
- _driver->close();
- _driver = 0;
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ // FIXME: We need to cast "this" here due to the effects of
+ // multiple inheritance. This hack can go away once this
+ // setTimerCallback() has been moved inside Audio::MidiPlayer code.
+ _driver->setTimerCallback(static_cast<Audio::MidiPlayer *>(this), &timerCallback);
+ }
}
void SoundGenMIDI::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
}
- else if ((b & 0xFFF0) == 0x007BB0) {
- //Only respond to All Notes Off if this channel
- //has currently been allocated
- if (_channel[b & 0x0F])
- return;
- }
- if (!_channel[channel]) {
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ Audio::MidiPlayer::send(b);
+}
+
+void SoundGenMIDI::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 (_channel[channel])
- setChannelVolume(channel);
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
}
- if (_channel[channel])
- _channel[channel]->send(b);
-}
-
-void SoundGenMIDI::metaEvent(byte type, byte *data, uint16 length) {
-
- switch (type) {
- case 0x2F: // End of Track
- stop();
- _vm->_sound->soundIsFinished();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
- }
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
-void SoundGenMIDI::onTimer(void *refCon) {
- SoundGenMIDI *music = (SoundGenMIDI *)refCon;
- Common::StackLock lock(music->_mutex);
-
- if (music->_parser)
- music->_parser->onTimer();
+void SoundGenMIDI::endOfTrack() {
+ stop();
+ _vm->_sound->soundIsFinished();
}
void SoundGenMIDI::play(int resnum) {
@@ -211,13 +125,13 @@ void SoundGenMIDI::play(int resnum) {
track = (MIDISound *)_vm->_game.sounds[resnum];
// Convert AGI Sound data to MIDI
- int midiMusicSize = convertSND2MIDI(track->_data, &_midiMusicData);
+ int midiMusicSize = convertSND2MIDI(track->_data, &_midiData);
- if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) {
- MidiParser *parser = _smfParser;
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_midiData, midiMusicSize)) {
parser->setTrack(0);
parser->setMidiDriver(this);
- parser->setTimerRate(getBaseTempo());
+ parser->setTimerRate(_driver->getBaseTempo());
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_parser = parser;
@@ -225,40 +139,11 @@ void SoundGenMIDI::play(int resnum) {
syncVolume();
_isPlaying = true;
+ } else {
+ delete parser;
}
}
-void SoundGenMIDI::stop() {
- Common::StackLock lock(_mutex);
-
- if (!_isPlaying)
- return;
-
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
- }
-}
-
-void SoundGenMIDI::pause() {
- setVolume(-1);
- _isPlaying = false;
-}
-
-void SoundGenMIDI::resume() {
- syncVolume();
- _isPlaying = true;
-}
-
-void SoundGenMIDI::syncVolume() {
- int volume = ConfMan.getInt("music_volume");
- if (ConfMan.getBool("mute")) {
- volume = -1;
- }
- setVolume(volume);
-}
-
/* channel / intrument setup: */
/* most songs are good with this: */
diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h
index 059d41208c..5733358fee 100644
--- a/engines/agi/sound_midi.h
+++ b/engines/agi/sound_midi.h
@@ -28,9 +28,9 @@
#ifndef AGI_SOUND_MIDI_H
#define AGI_SOUND_MIDI_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
-#include "common/mutex.h"
+#include "agi/sound.h"
+
+#include "audio/midiplayer.h"
namespace Agi {
@@ -46,65 +46,24 @@ protected:
uint16 _type; ///< Sound resource type
};
-class SoundGenMIDI : public SoundGen, public MidiDriver {
+class SoundGenMIDI : public SoundGen, public Audio::MidiPlayer {
public:
SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer);
- ~SoundGenMIDI();
void play(int resnum);
- void stop();
-
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
-
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
- void syncVolume();
-
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
- void pause();
- void resume();
- void setLoop(bool loop) { _looping = loop; }
- void setPassThrough(bool b) { _passThrough = b; }
-
- void setGM(bool isGM) { _isGM = isGM; }
-
- // MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
+ // We must overload stop() here to implement the pure virtual
+ // stop() method of the SoundGen class.
+ void stop() { Audio::MidiPlayer::stop(); }
- void metaEvent(byte type, byte *data, uint16 length);
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- // Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- MidiParser *_parser;
- Common::Mutex _mutex;
+ // Overload Audio::MidiPlayer method
+ virtual void sendToChannel(byte channel, uint32 b);
+ virtual void endOfTrack();
private:
-
- static void onTimer(void *data);
- void setChannelVolume(int channel);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_smfParser;
- byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
-
- bool _isPlaying;
- bool _looping;
- byte _masterVolume;
-
- byte *_midiMusicData;
SoundMgr *_manager;
};
diff --git a/engines/agi/sound_sarien.cpp b/engines/agi/sound_sarien.cpp
index 4ed7f8d029..6f2f3c5ad3 100644
--- a/engines/agi/sound_sarien.cpp
+++ b/engines/agi/sound_sarien.cpp
@@ -23,11 +23,7 @@
*
*/
-#include "common/md5.h"
-#include "common/config-manager.h"
-#include "common/fs.h"
#include "common/random.h"
-#include "common/str-array.h"
#include "audio/mididrv.h"
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index af3881170a..f85c4c1cdd 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -166,7 +166,7 @@ void AgiEngine::blitTextbox(const char *p, int y, int x, int len) {
drawWindow(xoff, yoff, xoff + w - 1, yoff + h - 1);
printText2(2, msg, 0, CHAR_COLS + xoff, CHAR_LINES + yoff,
- len + 1, MSG_BOX_TEXT, MSG_BOX_COLOUR);
+ len + 1, MSG_BOX_TEXT, MSG_BOX_COLOR);
free(msg);
@@ -730,7 +730,7 @@ void AgiEngine::drawWindow(int x1, int y1, int x2, int y2) {
debugC(4, kDebugLevelText, "x1=%d, y1=%d, x2=%d, y2=%d", x1, y1, x2, y2);
_gfx->saveBlock(x1, y1, x2, y2, _game.window.buffer);
- _gfx->drawBox(x1, y1, x2, y2, MSG_BOX_COLOUR, MSG_BOX_LINE, 2);
+ _gfx->drawBox(x1, y1, x2, y2, MSG_BOX_COLOR, MSG_BOX_LINE, 2);
}
} // End of namespace Agi
diff --git a/engines/agi/wagparser.cpp b/engines/agi/wagparser.cpp
index 22de66712d..fab3b5cf50 100644
--- a/engines/agi/wagparser.cpp
+++ b/engines/agi/wagparser.cpp
@@ -27,6 +27,7 @@
#include "common/util.h"
#include "common/fs.h"
#include "common/debug.h"
+#include "common/textconsole.h"
#include "agi/wagparser.h"
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index c48ed90ad8..d8596dec97 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -29,6 +29,8 @@
#include "agi/agi.h"
+#include "common/textconsole.h"
+
namespace Agi {
static uint8 *words; // words in the game
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index ae95bb0d2b..56501b5294 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -25,9 +25,9 @@
#include "common/config-manager.h"
#include "common/EventRecorder.h"
-#include "common/events.h"
#include "common/file.h"
#include "common/fs.h"
+#include "common/textconsole.h"
#include "common/system.h"
#include "engines/util.h"
@@ -35,14 +35,12 @@
#include "agos/debugger.h"
#include "agos/intern.h"
#include "agos/agos.h"
-#include "agos/vga.h"
#include "backends/audiocd/audiocd.h"
#include "graphics/surface.h"
#include "audio/mididrv.h"
-#include "audio/mods/protracker.h"
namespace AGOS {
@@ -470,7 +468,6 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_planarBuf = 0;
_midiEnabled = false;
- _nativeMT32 = false;
_vgaTickCounter = 0;
@@ -555,30 +552,13 @@ Common::Error AGOSEngine::init() {
((getFeatures() & GF_TALKIE) && getPlatform() == Common::kPlatformAcorn) ||
(getPlatform() == Common::kPlatformPC)) {
- // Setup midi driver
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (getGameType() == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM));
- _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-
- _driver = MidiDriver::createMidi(dev);
-
- if (_nativeMT32)
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _midi.setNativeMT32(_nativeMT32);
- _midi.mapMT32toGM(getGameType() != GType_SIMON2 && !_nativeMT32);
-
- _midi.setDriver(_driver);
-
- int ret = _midi.open();
+ int ret = _midi.open(getGameType());
if (ret)
- warning("MIDI Player init failed: \"%s\"", _midi.getErrorName (ret));
+ warning("MIDI Player init failed: \"%s\"", MidiDriver::getErrorName(ret));
_midi.setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
-
_midiEnabled = true;
- } else {
- _driver = NULL;
}
// Setup mixer
@@ -586,33 +566,33 @@ Common::Error AGOSEngine::init() {
// allocate buffers
_backGroundBuf = new Graphics::Surface();
- _backGroundBuf->create(_screenWidth, _screenHeight, 1);
+ _backGroundBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
if (getGameType() == GType_FF || getGameType() == GType_PP) {
_backBuf = new Graphics::Surface();
- _backBuf->create(_screenWidth, _screenHeight, 1);
+ _backBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
_scaleBuf = new Graphics::Surface();
- _scaleBuf->create(_screenWidth, _screenHeight, 1);
+ _scaleBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
}
if (getGameType() == GType_SIMON2) {
_window4BackScn = new Graphics::Surface();
- _window4BackScn->create(_screenWidth, _screenHeight, 1);
+ _window4BackScn->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
} else if (getGameType() == GType_SIMON1) {
_window4BackScn = new Graphics::Surface();
- _window4BackScn->create(_screenWidth, 134, 1);
+ _window4BackScn->create(_screenWidth, 134, Graphics::PixelFormat::createFormatCLUT8());
} else if (getGameType() == GType_WW || getGameType() == GType_ELVIRA2) {
_window4BackScn = new Graphics::Surface();
- _window4BackScn->create(224, 127, 1);
+ _window4BackScn->create(224, 127, Graphics::PixelFormat::createFormatCLUT8());
} else if (getGameType() == GType_ELVIRA1) {
_window4BackScn = new Graphics::Surface();
if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_DEMO)) {
- _window4BackScn->create(224, 196, 1);
+ _window4BackScn->create(224, 196, Graphics::PixelFormat::createFormatCLUT8());
} else {
- _window4BackScn->create(224, 144, 1);
+ _window4BackScn->create(224, 144, Graphics::PixelFormat::createFormatCLUT8());
}
_window6BackScn = new Graphics::Surface();
- _window6BackScn->create(48, 80, 1);
+ _window6BackScn->create(48, 80, Graphics::PixelFormat::createFormatCLUT8());
}
setupGame();
@@ -734,7 +714,7 @@ void AGOSEngine_Simon2::setupGame() {
_itemMemSize = 20000;
_tableMemSize = 100000;
// Check whether to use MT-32 MIDI tracks in Simon the Sorcerer 2
- if (getGameType() == GType_SIMON2 && _nativeMT32)
+ if (getGameType() == GType_SIMON2 && _midi.hasNativeMT32())
_musicIndexBase = (1128 + 612) / 4;
else
_musicIndexBase = 1128 / 4;
@@ -895,9 +875,6 @@ void AGOSEngine::setupGame() {
}
AGOSEngine::~AGOSEngine() {
- _midi.close();
- delete _driver;
-
_system->getAudioCDManager()->stop();
for (uint i = 0; i < _itemHeap.size(); i++) {
@@ -1045,18 +1022,15 @@ uint32 AGOSEngine::getTime() const {
}
void AGOSEngine::syncSoundSettings() {
- // Sync the engine with the config manager
- int soundVolumeMusic = ConfMan.getInt("music_volume");
- int soundVolumeSFX = ConfMan.getInt("sfx_volume");
- int soundVolumeSpeech = ConfMan.getInt("speech_volume");
+ Engine::syncSoundSettings();
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : (_musicPaused ? 0 : soundVolumeMusic)));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech));
+ // Sync the engine with the config manager
+ int soundVolumeMusic = ConfMan.getInt("music_volume");
+ int soundVolumeSFX = ConfMan.getInt("sfx_volume");
if (_midiEnabled)
_midi.setVolume((mute ? 0 : soundVolumeMusic), (mute ? 0 : soundVolumeSFX));
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index 7201dfd9d3..aecf2437a7 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -29,6 +29,7 @@
#include "engines/engine.h"
#include "common/array.h"
+#include "common/error.h"
#include "common/keyboard.h"
#include "common/random.h"
#include "common/rect.h"
@@ -186,7 +187,7 @@ class AGOSEngine : public Engine {
virtual Common::Error run() {
Common::Error err;
err = init();
- if (err != Common::kNoError)
+ if (err.getCode() != Common::kNoError)
return err;
return go();
}
@@ -550,9 +551,7 @@ protected:
byte _lettersToPrintBuf[80];
MidiPlayer _midi;
- MidiDriver *_driver;
bool _midiEnabled;
- bool _nativeMT32;
int _vgaTickCounter;
@@ -1142,7 +1141,7 @@ protected:
int getScale(int16 y, int16 x);
void checkScrollX(int16 x, int16 xpos);
void checkScrollY(int16 y, int16 ypos);
- void centreScroll();
+ void centerScroll();
virtual void clearVideoWindow(uint16 windowNum, uint16 color);
void clearVideoBackGround(uint16 windowNum, uint16 color);
@@ -1923,7 +1922,7 @@ public:
void off_mouseOff();
void off_loadVideo();
void off_playVideo();
- void off_centreScroll();
+ void off_centerScroll();
void off_resetPVCount();
void off_setPathValues();
void off_stopClock();
@@ -2018,7 +2017,7 @@ protected:
void scrollOracleUp();
void scrollOracleDown();
- void listSaveGames(int n);
+ void listSaveGamesFeeble();
void saveUserGame(int slot);
void windowBackSpace(WindowBlock *window);
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index d39ca377dc..ee47f62a58 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -31,8 +31,10 @@
#include "common/events.h"
#include "common/file.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "agos/animation.h"
@@ -301,7 +303,7 @@ void MoviePlayerDXA::stopVideo() {
void MoviePlayerDXA::startSound() {
uint32 offset, size;
- if (getSoundTag() == MKID_BE('WAVE')) {
+ if (getSoundTag() == MKTAG('W','A','V','E')) {
size = _fileStream->readUint32BE();
if (_sequenceNum) {
@@ -368,7 +370,7 @@ void MoviePlayerDXA::handleNextFrame() {
bool MoviePlayerDXA::processFrame() {
Graphics::Surface *screen = _vm->_system->lockScreen();
- copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
+ copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
Common::Rational soundTime(_mixer->getSoundElapsedTime(_bgSound), 1000);
@@ -482,7 +484,7 @@ void MoviePlayerSMK::nextFrame() {
bool MoviePlayerSMK::processFrame() {
Graphics::Surface *screen = _vm->_system->lockScreen();
- copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
+ copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
uint32 waitTime = getTimeToNextFrame();
diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp
index a477b3dedc..a131bb841b 100644
--- a/engines/agos/charset-fontdata.cpp
+++ b/engines/agos/charset-fontdata.cpp
@@ -26,6 +26,7 @@
#include "common/system.h"
+#include "common/textconsole.h"
#include "agos/agos.h"
#include "agos/intern.h"
diff --git a/engines/agos/debug.cpp b/engines/agos/debug.cpp
index d0dc8cc42e..bb27557a6b 100644
--- a/engines/agos/debug.cpp
+++ b/engines/agos/debug.cpp
@@ -27,6 +27,7 @@
#include "common/file.h"
+#include "common/textconsole.h"
#include "agos/debug.h"
#include "agos/agos.h"
diff --git a/engines/agos/debug.h b/engines/agos/debug.h
index 38674de765..5865065ac3 100644
--- a/engines/agos/debug.h
+++ b/engines/agos/debug.h
@@ -2058,7 +2058,7 @@ static const char *const feeblefiles_opcodeNameTable[256] = {
"W|UNLOAD_ZONE",
NULL,
"|UNFREEZE_ZONES",
- "|CENTRE_SCROLL",
+ "|CENTER_SCROLL",
/* 188 */
"BSJ|STRING2_IS",
"|CLEAR_MARKS",
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index 646e63dacf..c8c70c0ecc 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -29,6 +29,7 @@
#include "common/config-manager.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "agos/intern.h"
#include "agos/agos.h"
diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp
index 317c68d31a..6b9f65ee2b 100644
--- a/engines/agos/draw.cpp
+++ b/engines/agos/draw.cpp
@@ -28,6 +28,7 @@
#include "common/system.h"
#include "graphics/surface.h"
+#include "graphics/palette.h"
#include "agos/agos.h"
#include "agos/intern.h"
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp
index fc0b4f96cd..8799dbaa28 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -32,6 +32,7 @@
#include "common/events.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "backends/audiocd/audiocd.h"
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index 710c9ddd7e..4c998dfa5f 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -26,6 +26,7 @@
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp
index 08a3d4e2f0..39a7705c54 100644
--- a/engines/agos/icons.cpp
+++ b/engines/agos/icons.cpp
@@ -25,9 +25,9 @@
-#include "common/system.h"
-
#include "common/file.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
@@ -484,7 +484,7 @@ void AGOSEngine::drawIconArray(uint num, Item *itemRef, int line, int classMask)
Item *item_ptr_org = itemRef;
WindowBlock *window;
uint width, height;
- uint k, i, curWidth;
+ uint k, curWidth;
bool item_again, showArrows;
uint x_pos, y_pos;
const int iconSize = (getGameType() == GType_SIMON2) ? 20 : 1;
@@ -502,8 +502,6 @@ void AGOSEngine::drawIconArray(uint num, Item *itemRef, int line, int classMask)
height = window->height / 3;
}
- i = 0;
-
if (window == NULL)
return;
diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp
index 81da5264ba..5d1523bbd5 100644
--- a/engines/agos/items.cpp
+++ b/engines/agos/items.cpp
@@ -26,6 +26,7 @@
#include "common/file.h"
+#include "common/textconsole.h"
#include "agos/intern.h"
#include "agos/agos.h"
diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp
index 5629a1dca6..2b103a75cb 100644
--- a/engines/agos/menus.cpp
+++ b/engines/agos/menus.cpp
@@ -27,6 +27,7 @@
#include "common/file.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index fe2d1cd25b..26e2f2c736 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -25,8 +25,10 @@
+#include "common/config-manager.h"
#include "common/file.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "agos/agos.h"
@@ -44,7 +46,6 @@ MidiPlayer::MidiPlayer() {
// between songs.
_driver = 0;
_map_mt32_to_gm = false;
- _passThrough = false;
_enable_sfx = true;
_current = 0;
@@ -62,16 +63,34 @@ MidiPlayer::MidiPlayer() {
}
MidiPlayer::~MidiPlayer() {
- _mutex.lock();
- close();
- _mutex.unlock();
+ stop();
+
+ Common::StackLock lock(_mutex);
+ if (_driver) {
+ _driver->close();
+ delete _driver;
+ }
+ _driver = NULL;
+ clearConstructs();
}
-int MidiPlayer::open() {
- // Don't ever call open without first setting the output driver!
+int MidiPlayer::open(int gameType) {
+ // Don't call open() twice!
+ assert(!_driver);
+
+ // Setup midi driver
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (gameType == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM));
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+
+ _driver = MidiDriver::createMidi(dev);
if (!_driver)
return 255;
+ if (_nativeMT32)
+ _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+
+ _map_mt32_to_gm = (gameType != GType_SIMON2 && !_nativeMT32);
+
int ret = _driver->open();
if (ret)
return ret;
@@ -85,25 +104,10 @@ int MidiPlayer::open() {
return 0;
}
-void MidiPlayer::close() {
- stop();
-// _system->lockMutex(_mutex);
- if (_driver)
- _driver->close();
- _driver = NULL;
- clearConstructs();
-// _system->unlockMutex(_mutex);
-}
-
void MidiPlayer::send(uint32 b) {
if (!_current)
return;
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
byte channel = (byte)(b & 0x0F);
if ((b & 0xFFF0) == 0x07B0) {
// Adjust volume changes by master music and master sfx volume.
@@ -205,6 +209,8 @@ void MidiPlayer::onTimer(void *data) {
}
void MidiPlayer::startTrack(int track) {
+ Common::StackLock lock(_mutex);
+
if (track == _currentTrack)
return;
@@ -212,8 +218,6 @@ void MidiPlayer::startTrack(int track) {
if (track >= _music.num_songs)
return;
- _mutex.lock();
-
if (_music.parser) {
_current = &_music;
delete _music.parser;
@@ -234,9 +238,7 @@ void MidiPlayer::startTrack(int track) {
_currentTrack = (byte)track;
_music.parser = parser; // That plugs the power cord into the wall
} else if (_music.parser) {
- _mutex.lock();
if (!_music.parser->setTrack(track)) {
- _mutex.unlock();
return;
}
_currentTrack = (byte)track;
@@ -244,8 +246,6 @@ void MidiPlayer::startTrack(int track) {
_music.parser->jumpToTick(0);
_current = 0;
}
-
- _mutex.unlock();
}
void MidiPlayer::stop() {
@@ -301,19 +301,6 @@ void MidiPlayer::setVolume(int musicVol, int sfxVol) {
}
}
-void MidiPlayer::setDriver(MidiDriver *md) {
- // Don't try to set this more than once.
- if (_driver)
- return;
- _driver = md;
-}
-
-void MidiPlayer::mapMT32toGM(bool map) {
- Common::StackLock lock(_mutex);
-
- _map_mt32_to_gm = map;
-}
-
void MidiPlayer::setLoop(bool loop) {
Common::StackLock lock(_mutex);
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index 9c8303ba3c..40f54dbaf0 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -31,7 +31,7 @@
#include "common/mutex.h"
namespace Common {
- class File;
+class File;
}
namespace AGOS {
@@ -55,12 +55,11 @@ struct MusicInfo {
}
};
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
protected:
Common::Mutex _mutex;
MidiDriver *_driver;
bool _map_mt32_to_gm;
- bool _passThrough;
bool _nativeMT32;
MusicInfo _music;
@@ -97,8 +96,7 @@ public:
void loadXMIDI(Common::File *in, bool sfx = false);
void loadS1D(Common::File *in, bool sfx = false);
- void mapMT32toGM(bool map);
- void setNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; }
+ bool hasNativeMT32() const { return _nativeMT32; }
void setLoop(bool loop);
void startTrack(int track);
void queueTrack(int track, bool loop);
@@ -107,27 +105,17 @@ public:
void stop();
void pause(bool b);
- int getMusicVolume() { return _musicVolume; }
- int getSFXVolume() { return _sfxVolume; }
+ int getMusicVolume() const { return _musicVolume; }
+ int getSFXVolume() const { return _sfxVolume; }
void setVolume(int musicVol, int sfxVol);
- void setDriver(MidiDriver *md);
public:
- // MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
+ int open(int gameType);
- void metaEvent(byte type, byte *data, uint16 length);
- void setPassThrough(bool b) { _passThrough = b; }
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
- // Timing functions - MidiDriver now operates timers
- void setTimerCallback(void *timer_param, void (*timer_proc) (void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- // Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
};
} // End of namespace AGOS
diff --git a/engines/agos/midiparser_s1d.cpp b/engines/agos/midiparser_s1d.cpp
index 156dc6ecaa..f96518b5e9 100644
--- a/engines/agos/midiparser_s1d.cpp
+++ b/engines/agos/midiparser_s1d.cpp
@@ -25,6 +25,7 @@
#include "common/debug.h"
#include "common/util.h"
+#include "common/textconsole.h"
#include "audio/mididrv.h"
#include "audio/midiparser.h"
diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp
index 0a4ab8246f..8ff79965e4 100644
--- a/engines/agos/oracle.cpp
+++ b/engines/agos/oracle.cpp
@@ -369,7 +369,7 @@ void AGOSEngine_Feeble::swapCharacterLogo() {
}
}
-void AGOSEngine_Feeble::listSaveGames(int n) {
+void AGOSEngine_Feeble::listSaveGamesFeeble() {
char b[108];
Common::InSaveFile *in;
uint16 j, k, z, maxFiles;
@@ -377,8 +377,8 @@ void AGOSEngine_Feeble::listSaveGames(int n) {
memset(b, 0, 108);
maxFiles = countSaveGames() - 1;
- j = maxFiles - n + 1;
- k = maxFiles - j + 1;
+ j = maxFiles;
+ k = 1;
z = maxFiles;
if (getBitFlag(95)) {
j++;
diff --git a/engines/agos/res.cpp b/engines/agos/res.cpp
index b8409669ee..0e818963e2 100644
--- a/engines/agos/res.cpp
+++ b/engines/agos/res.cpp
@@ -28,6 +28,7 @@
#include "common/file.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "agos/agos.h"
diff --git a/engines/agos/res_snd.cpp b/engines/agos/res_snd.cpp
index fe09e746ff..34deff37ab 100644
--- a/engines/agos/res_snd.cpp
+++ b/engines/agos/res_snd.cpp
@@ -26,6 +26,7 @@
#include "common/config-manager.h"
#include "common/file.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "agos/intern.h"
#include "agos/agos.h"
diff --git a/engines/agos/rooms.cpp b/engines/agos/rooms.cpp
index a2eff06fcc..0993197594 100644
--- a/engines/agos/rooms.cpp
+++ b/engines/agos/rooms.cpp
@@ -26,6 +26,7 @@
#include "common/file.h"
+#include "common/textconsole.h"
#include "agos/agos.h"
#include "agos/intern.h"
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index eefa2460ec..d6f25814bb 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -26,6 +26,7 @@
#include "common/file.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "common/translation.h"
#include "gui/about.h"
diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp
index 90992b52fe..94a3f371cc 100644
--- a/engines/agos/script.cpp
+++ b/engines/agos/script.cpp
@@ -28,6 +28,7 @@
#include "common/system.h"
+#include "common/textconsole.h"
#include "agos/animation.h"
#include "agos/agos.h"
diff --git a/engines/agos/script_dp.cpp b/engines/agos/script_dp.cpp
index 57610017a1..6eb3ca4779 100644
--- a/engines/agos/script_dp.cpp
+++ b/engines/agos/script_dp.cpp
@@ -271,7 +271,7 @@ void AGOSEngine_DIMP::setupOpcodes() {
OPCODE(os1_unloadZone),
OPCODE(o_invalid),
OPCODE(os1_unfreezeZones),
- OPCODE(off_centreScroll),
+ OPCODE(off_centerScroll),
/* 188 */
OPCODE(os2_isShortText),
OPCODE(os2_clearMarks),
diff --git a/engines/agos/script_ff.cpp b/engines/agos/script_ff.cpp
index 3198b1b499..8dfee7f7c7 100644
--- a/engines/agos/script_ff.cpp
+++ b/engines/agos/script_ff.cpp
@@ -272,7 +272,7 @@ void AGOSEngine_Feeble::setupOpcodes() {
OPCODE(os1_unloadZone),
OPCODE(o_invalid),
OPCODE(os1_unfreezeZones),
- OPCODE(off_centreScroll),
+ OPCODE(off_centerScroll),
/* 188 */
OPCODE(os2_isShortText),
OPCODE(os2_clearMarks),
@@ -430,8 +430,7 @@ void AGOSEngine_Feeble::off_loadUserGame() {
}
void AGOSEngine_Feeble::off_listSaveGames() {
- // 134: dummy opcode?
- listSaveGames(1);
+ listSaveGamesFeeble();
}
void AGOSEngine_Feeble::off_checkCD() {
@@ -591,9 +590,9 @@ void AGOSEngine_Feeble::off_playVideo() {
}
}
-void AGOSEngine_Feeble::off_centreScroll() {
+void AGOSEngine_Feeble::off_centerScroll() {
// 187
- centreScroll();
+ centerScroll();
}
void AGOSEngine_Feeble::off_resetPVCount() {
diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp
index 909c051362..b8ba7fb015 100644
--- a/engines/agos/script_pn.cpp
+++ b/engines/agos/script_pn.cpp
@@ -26,6 +26,8 @@
#include "agos/agos.h"
#include "agos/vga.h"
+#include "common/textconsole.h"
+
namespace AGOS {
enum {
diff --git a/engines/agos/script_s1.cpp b/engines/agos/script_s1.cpp
index 05a725cb50..dab0302631 100644
--- a/engines/agos/script_s1.cpp
+++ b/engines/agos/script_s1.cpp
@@ -26,6 +26,8 @@
#include "common/system.h"
+#include "graphics/palette.h"
+
#include "agos/agos.h"
#ifdef _WIN32_WCE
diff --git a/engines/agos/script_s2.cpp b/engines/agos/script_s2.cpp
index dd525163c7..a0b14525f2 100644
--- a/engines/agos/script_s2.cpp
+++ b/engines/agos/script_s2.cpp
@@ -27,6 +27,8 @@
#include "agos/agos.h"
+#include "common/textconsole.h"
+
namespace AGOS {
#define OPCODE(x) _OPCODE(AGOSEngine_Simon2, x)
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index 35301793bf..25d861acb5 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -25,6 +25,7 @@
#include "common/file.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "agos/agos.h"
diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp
index ed56cbd266..1152d6ed04 100644
--- a/engines/agos/string.cpp
+++ b/engines/agos/string.cpp
@@ -26,6 +26,7 @@
#include "common/file.h"
+#include "common/textconsole.h"
#include "gui/about.h"
#include "gui/message.h"
@@ -725,12 +726,11 @@ void AGOSEngine_Feeble::printScreenText(uint vgaSpriteId, uint color, const char
const char *string2 = string;
int16 height, talkDelay;
int stringLength = strlen(string);
- int lettersPerRow, lettersPerRowJustified;
+ int lettersPerRow;
const int textHeight = 15;
height = textHeight;
lettersPerRow = width / 6;
- lettersPerRowJustified = stringLength / (stringLength / lettersPerRow + 1) + 1;
talkDelay = (stringLength + 3) / 3;
if (_variableArray[86] == 0)
diff --git a/engines/agos/string_pn.cpp b/engines/agos/string_pn.cpp
index a4e40d8306..92d85ab96c 100644
--- a/engines/agos/string_pn.cpp
+++ b/engines/agos/string_pn.cpp
@@ -26,6 +26,8 @@
#include "agos/agos.h"
#include "agos/intern.h"
+#include "common/textconsole.h"
+
namespace AGOS {
uint32 AGOSEngine_PN::ftext(uint32 base, int n) {
diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp
index 733d40e52d..bd07596a46 100644
--- a/engines/agos/subroutine.cpp
+++ b/engines/agos/subroutine.cpp
@@ -26,6 +26,7 @@
#include "common/file.h"
+#include "common/textconsole.h"
#include "agos/agos.h"
#include "agos/intern.h"
diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp
index 83ee05036c..6c07db13c1 100644
--- a/engines/agos/vga.cpp
+++ b/engines/agos/vga.cpp
@@ -31,6 +31,7 @@
#include "agos/vga.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp
index b0431db801..9e163ba91f 100644
--- a/engines/agos/vga_e2.cpp
+++ b/engines/agos/vga_e2.cpp
@@ -32,6 +32,7 @@
#include "common/system.h"
#include "graphics/surface.h"
+#include "graphics/palette.h"
namespace AGOS {
diff --git a/engines/agos/vga_ff.cpp b/engines/agos/vga_ff.cpp
index 38a3479292..14a1c60ae5 100644
--- a/engines/agos/vga_ff.cpp
+++ b/engines/agos/vga_ff.cpp
@@ -201,7 +201,7 @@ void AGOSEngine::vc78_computeXY() {
if (getGameType() == GType_FF) {
setBitFlag(85, false);
if (getBitFlag(74)) {
- centreScroll();
+ centerScroll();
}
}
}
@@ -348,7 +348,7 @@ void AGOSEngine::checkScrollY(int16 y, int16 ypos) {
}
}
-void AGOSEngine::centreScroll() {
+void AGOSEngine::centerScroll() {
int16 x, y, tmp;
if (_scrollXMax != 0) {
diff --git a/engines/agos/vga_ww.cpp b/engines/agos/vga_ww.cpp
index 8aecd3448a..08b2cee303 100644
--- a/engines/agos/vga_ww.cpp
+++ b/engines/agos/vga_ww.cpp
@@ -32,6 +32,7 @@
#include "common/system.h"
#include "graphics/surface.h"
+#include "graphics/palette.h"
namespace AGOS {
diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp
index a03c7e178a..08680c9e45 100644
--- a/engines/agos/window.cpp
+++ b/engines/agos/window.cpp
@@ -26,6 +26,7 @@
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 14b8de9e39..6b4b29dcfe 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -29,6 +29,7 @@
#include "common/endian.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/anim.h"
diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp
index 1c6a55c270..22fd28a99c 100644
--- a/engines/cine/bg.cpp
+++ b/engines/cine/bg.cpp
@@ -26,6 +26,7 @@
#include "common/endian.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/various.h"
@@ -39,7 +40,6 @@ int16 currentAdditionalBgIdx = 0, currentAdditionalBgIdx2 = 0;
byte loadCtFW(const char *ctName) {
debugC(1, kCineDebugCollision, "loadCtFW(\"%s\")", ctName);
- uint16 header[32];
byte *ptr, *dataPtr;
int16 foundFileIdx = findFileInBundle(ctName);
@@ -59,12 +59,6 @@ byte loadCtFW(const char *ctName) {
assert(strstr(ctName, ".NEO"));
- Common::MemoryReadStream readS(ptr, 32);
-
- for (int i = 0; i < 16; i++) {
- header[i] = readS.readUint16BE();
- }
-
gfxConvertSpriteToRaw(collisionPage, ptr + 0x80, 160, 200);
free(dataPtr);
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index d80ab70660..8104ad38cd 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -23,13 +23,9 @@
*
*/
-#include "common/events.h"
#include "common/EventRecorder.h"
-#include "common/file.h"
-#include "common/savefile.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
-#include "common/system.h"
#include "engines/util.h"
@@ -50,20 +46,15 @@ Sound *g_sound = 0;
CineEngine *g_cine = 0;
CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
+ // Setup mixer
+ syncSoundSettings();
+
DebugMan.addDebugChannel(kCineDebugScript, "Script", "Script debug level");
DebugMan.addDebugChannel(kCineDebugPart, "Part", "Part debug level");
DebugMan.addDebugChannel(kCineDebugSound, "Sound", "Sound debug level");
DebugMan.addDebugChannel(kCineDebugCollision, "Collision", "Collision debug level");
_console = new CineConsole(this);
- // Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
- // Use music volume for plain sound types (At least the AdLib player uses a plain sound type
- // so previously the music and sfx volume controls didn't affect it at all).
- // FIXME: Make AdLib player differentiate between playing sound effects and music and remove this.
- _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("music_volume"));
-
g_cine = this;
g_eventRec.registerRandomSource(_rnd, "cine");
@@ -78,6 +69,20 @@ CineEngine::~CineEngine() {
delete _console;
}
+void CineEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ // Use music volume for plain sound types (At least the AdLib player uses a plain sound type
+ // so previously the music and sfx volume controls didn't affect it at all).
+ // FIXME: Make AdLib player differentiate between playing sound effects and music and remove this.
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType,
+ mute ? 0 : ConfMan.getInt("music_volume"));
+}
+
Common::Error CineEngine::run() {
// Initialize backend
initGraphics(320, 200, false);
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index 5f49a2907f..7de0bdc86f 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -117,6 +117,8 @@ public:
CineEngine(OSystem *syst, const CINEGameDescription *gameDesc);
virtual ~CineEngine();
+ virtual void syncSoundSettings();
+
int getGameType() const;
uint32 getFeatures() const;
Common::Language getLanguage() const;
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index 9dfa2f71ea..058c1a1140 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -27,6 +27,7 @@
#include "engines/advancedDetector.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/various.h"
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index 3970d88117..18feacd08b 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -30,8 +30,9 @@
#include "cine/pal.h"
#include "common/endian.h"
-#include "common/system.h"
#include "common/events.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
diff --git a/engines/cine/msg.cpp b/engines/cine/msg.cpp
index a01afd147b..3d58d6ddcd 100644
--- a/engines/cine/msg.cpp
+++ b/engines/cine/msg.cpp
@@ -25,6 +25,7 @@
#include "common/debug.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "cine/msg.h"
#include "cine/various.h"
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index 3c8ffc295b..0f52600db5 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -27,6 +27,9 @@
#include "cine/various.h"
#include "cine/pal.h"
#include "common/system.h" // For g_system->getPaletteManager()->setPalette
+#include "common/textconsole.h"
+
+#include "graphics/palette.h"
namespace Cine {
diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp
index f5c9402388..17ef01948c 100644
--- a/engines/cine/part.cpp
+++ b/engines/cine/part.cpp
@@ -25,6 +25,7 @@
#include "common/debug.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/unpack.h"
diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp
index fd426be66a..1fc2a8b2fd 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -25,6 +25,7 @@
#include "common/debug.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/bg_list.h"
@@ -996,9 +997,8 @@ void CineEngine::makeSave(char *saveFileName) {
* at a time.
*/
void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat) {
- int16 currentAnim, foundFileIdx, frame;
+ int16 currentAnim, foundFileIdx;
char *animName, part[256], name[10];
- uint16 width, height, bpp, var1;
strcpy(part, currentPartName);
@@ -1012,10 +1012,10 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
// Seek to the start of the current animation's entry
fHandle.seek(fileStartPos + currentAnim * entrySize);
// Read in the current animation entry
- width = fHandle.readUint16BE();
- var1 = fHandle.readUint16BE();
- bpp = fHandle.readUint16BE();
- height = fHandle.readUint16BE();
+ fHandle.readUint16BE(); // width
+ fHandle.readUint16BE();
+ fHandle.readUint16BE(); // bpp
+ fHandle.readUint16BE(); // height
bool validPtr = false;
// Handle variables only present in animation entries of size 30
@@ -1025,7 +1025,7 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
}
foundFileIdx = fHandle.readSint16BE();
- frame = fHandle.readSint16BE();
+ fHandle.readSint16BE(); // frame
fHandle.read(name, 10);
// Handle variables only present in animation entries of size 23
diff --git a/engines/cine/saveload.h b/engines/cine/saveload.h
index a6e0e3f1ab..f88338ed82 100644
--- a/engines/cine/saveload.h
+++ b/engines/cine/saveload.h
@@ -71,14 +71,14 @@ enum CineSaveGameFormat {
};
/** Identifier for the temporary Operation Stealth savegame format. */
-static const uint32 TEMP_OS_FORMAT_ID = MKID_BE('TEMP');
+static const uint32 TEMP_OS_FORMAT_ID = MKTAG('T','E','M','P');
/** The current version number of Operation Stealth's savegame format. */
static const uint32 CURRENT_OS_SAVE_VER = 1;
/** Chunk header used by the temporary Operation Stealth savegame format. */
struct ChunkHeader {
- uint32 id; ///< Identifier (e.g. MKID_BE('TEMP'))
+ uint32 id; ///< Identifier (e.g. MKTAG('T','E','M','P'))
uint32 version; ///< Version number
uint32 size; ///< Size of the chunk after this header in bytes
};
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index ffbee3d389..674bf4dd86 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -28,6 +28,7 @@
*/
#include "common/endian.h"
+#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/bg_list.h"
diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp
index ab1ad7ff9c..aa2c8c33ac 100644
--- a/engines/cine/script_os.cpp
+++ b/engines/cine/script_os.cpp
@@ -28,6 +28,7 @@
*/
#include "common/endian.h"
+#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/bg_list.h"
@@ -124,7 +125,7 @@ void OSScript::setupTable() {
{ 0, 0 },
{ &FWScript::o2_loadPart, "s" },
/* 40 */
- { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */
+ { &FWScript::o1_closePart, "" },
{ &FWScript::o1_loadNewPrcName, "bs" },
{ &FWScript::o1_requestCheckPendingDataLoad, "" },
{ 0, 0 },
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index f0c0668e33..414761159b 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -26,6 +26,8 @@
#include "common/endian.h"
#include "common/file.h"
#include "common/memstream.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/sound.h"
diff --git a/engines/cine/sound.h b/engines/cine/sound.h
index e9a797989e..7b506ab5f3 100644
--- a/engines/cine/sound.h
+++ b/engines/cine/sound.h
@@ -30,7 +30,7 @@
#include "audio/mixer.h"
namespace Audio {
- class AudioStream;
+class AudioStream;
}
namespace Cine {
diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp
index 9dbfa315d9..fb6818d690 100644
--- a/engines/cine/texte.cpp
+++ b/engines/cine/texte.cpp
@@ -23,8 +23,10 @@
*
*/
-#include "cine/cine.h"
#include "common/file.h"
+#include "common/textconsole.h"
+
+#include "cine/cine.h"
#include "cine/various.h"
namespace Cine {
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 5b8663606e..fdc7a28867 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -26,6 +26,7 @@
#include "common/endian.h"
#include "common/events.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
diff --git a/engines/cruise/actor.cpp b/engines/cruise/actor.cpp
index 9cbc3dd9ae..2c83aff743 100644
--- a/engines/cruise/actor.cpp
+++ b/engines/cruise/actor.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "cruise/cruise.h"
#include "cruise/staticres.h"
diff --git a/engines/cruise/background.cpp b/engines/cruise/background.cpp
index edd52d3b4a..7c63c155d3 100644
--- a/engines/cruise/background.cpp
+++ b/engines/cruise/background.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "cruise/cruise_main.h"
namespace Cruise {
diff --git a/engines/cruise/backgroundIncrust.cpp b/engines/cruise/backgroundIncrust.cpp
index 6bd8b270e0..1685044c9d 100644
--- a/engines/cruise/backgroundIncrust.cpp
+++ b/engines/cruise/backgroundIncrust.cpp
@@ -198,17 +198,13 @@ void regenerateBackgroundIncrust(backgroundIncrustStruct *pHead) {
while (pl) {
backgroundIncrustStruct* pl2 = pl->next;
- bool bLoad = false;
int frame = pl->frame;
//int screen = pl->backgroundIdx;
if ((filesDatabase[frame].subData.ptr == NULL) || (strcmp(pl->name, filesDatabase[frame].subData.name))) {
frame = NUM_FILE_ENTRIES - 1;
- if (loadFile(pl->name, frame, pl->spriteId) >= 0) {
- bLoad = true;
- } else {
+ if (loadFile(pl->name, frame, pl->spriteId) < 0)
frame = -1;
- }
}
if (frame >= 0) {
diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp
index c1ea711228..9712bd9439 100644
--- a/engines/cruise/cruise.cpp
+++ b/engines/cruise/cruise.cpp
@@ -23,13 +23,10 @@
*
*/
-#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/file.h"
-#include "common/savefile.h"
-#include "common/config-manager.h"
#include "common/debug-channels.h"
-#include "common/system.h"
+#include "common/textconsole.h"
#include "engines/util.h"
@@ -52,16 +49,13 @@ CruiseEngine::CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc
DebugMan.addDebugChannel(kCruiseDebugScript, "scripts", "Scripts debug level");
DebugMan.addDebugChannel(kCruiseDebugSound, "sound", "Sound debug level");
- // Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType,
- ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType,
- ConfMan.getInt("music_volume"));
-
_vm = this;
_debugger = new Debugger();
_sound = new PCSound(_mixer, this);
+ // Setup mixer
+ syncSoundSettings();
+
g_eventRec.registerRandomSource(_rnd, "cruise");
}
@@ -235,6 +229,8 @@ const char *CruiseEngine::getSavegameFile(int saveGameIdx) {
}
void CruiseEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
_sound->syncSounds();
}
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h
index ad3bb20ca1..8d03d47327 100644
--- a/engines/cruise/cruise.h
+++ b/engines/cruise/cruise.h
@@ -31,7 +31,6 @@
#include "common/random.h"
#include "engines/engine.h"
-#include "engines/game.h"
#include "cruise/cruise_main.h"
#include "cruise/debugger.h"
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index 6b487fadc9..e2f2d7468e 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -27,6 +27,7 @@
#include "common/endian.h"
#include "common/events.h"
#include "common/system.h" // for g_system->getEventManager()
+#include "common/textconsole.h"
#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
@@ -1004,18 +1005,7 @@ bool findRelation(int objOvl, int objIdx, int x, int y) {
if (!obj2Ovl) obj2Ovl = j;
char verbe_name[80];
- char obj1_name[80];
- char obj2_name[80];
- char r_verbe_name[80];
- char r_obj1_name[80];
- char r_obj2_name[80];
-
verbe_name[0] = 0;
- obj1_name[0] = 0;
- obj2_name[0] = 0;
- r_verbe_name[0] = 0;
- r_obj1_name[0] = 0;
- r_obj2_name[0] = 0;
ovlDataStruct *ovl2 = NULL;
ovlDataStruct *ovl3 = NULL;
@@ -1889,7 +1879,7 @@ void CruiseEngine::mainLoop() {
// FIXME: I suspect that the original game does multiple script executions between game frames; the bug with
// 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 when a background changes, a few extra script executions are done
+ // that does a few extra script executions for that scene
bool bgChanged;
int numIterations = 1;
@@ -1902,7 +1892,8 @@ void CruiseEngine::mainLoop() {
removeFinishedScripts(&relHead);
removeFinishedScripts(&procHead);
- if (!bgChanged && backgroundChanged[masterScreen]) {
+ if (!bgChanged && backgroundChanged[masterScreen] &&
+ !strcmp(backgroundTable[0].name, "S06B.PI1")) {
bgChanged = true;
numIterations += 2;
}
diff --git a/engines/cruise/ctp.cpp b/engines/cruise/ctp.cpp
index 4f6c21e0e4..f1223c12e6 100644
--- a/engines/cruise/ctp.cpp
+++ b/engines/cruise/ctp.cpp
@@ -167,7 +167,7 @@ void makeCtStruct(Common::Array<CtStruct> &lst, int16 table[][40], int num, int
}
ct.num = num;
- ct.colour = walkboxColor[num];
+ ct.color = walkboxColor[num];
ct.bounds.left = minX;
ct.bounds.right = maxX;
ct.bounds.top = minY;
diff --git a/engines/cruise/ctp.h b/engines/cruise/ctp.h
index 3c6c9582cc..0aec9c52d8 100644
--- a/engines/cruise/ctp.h
+++ b/engines/cruise/ctp.h
@@ -57,7 +57,7 @@ class CtStruct {
public:
CtStruct *next;
int16 num;
- int16 colour;
+ int16 color;
Common::Rect bounds;
Common::Array<CtEntry> slices;
};
diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp
index 03a2117f07..3ccd1689b8 100644
--- a/engines/cruise/dataLoader.cpp
+++ b/engines/cruise/dataLoader.cpp
@@ -26,6 +26,7 @@
#include "cruise/cruise_main.h"
#include "common/endian.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
namespace Cruise {
@@ -358,7 +359,7 @@ int loadFNTSub(uint8 *ptr, int destIdx) {
uint8 *ptr2 = ptr;
uint8 *destPtr;
int fileIndex;
- uint32 fontSize;
+ //uint32 fontSize;
ptr2 += 4;
loadFileVar1 = READ_BE_UINT32(ptr2);
@@ -373,7 +374,7 @@ int loadFNTSub(uint8 *ptr, int destIdx) {
memcpy(destPtr, ptr2, loadFileVar1);
- fontSize = READ_BE_UINT32(ptr2);
+ //fontSize = READ_BE_UINT32(ptr2);
if (destPtr != NULL) {
int32 i;
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index e43fadf598..63d7328e78 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -27,6 +27,7 @@
#include "base/plugins.h"
#include "common/savefile.h"
+#include "common/system.h"
#include "engines/advancedDetector.h"
#include "cruise/cruise.h"
@@ -74,7 +75,7 @@ static const CRUISEGameDescription gameDescriptions[] = {
{
{
"cruise",
- "16 colours",
+ "16 colors",
AD_ENTRY1("D1", "cd29a4cd9162076e9a18495fe56a48f3"),
Common::EN_GRB,
Common::kPlatformPC,
diff --git a/engines/cruise/font.cpp b/engines/cruise/font.cpp
index 3a609cb8d4..2bf36bbdbd 100644
--- a/engines/cruise/font.cpp
+++ b/engines/cruise/font.cpp
@@ -266,13 +266,13 @@ int32 prepareWordRender(int32 inRightBorder_X, int16 wordSpacingWidth,
return counter;
}
-void drawString(int32 x, int32 y, const char *string, uint8 *buffer, uint8 fontColour, int32 rightBorder_X) {
+void drawString(int32 x, int32 y, const char *string, uint8 *buffer, uint8 fontColor, int32 rightBorder_X) {
// Get the rendered text to display
gfxEntryStruct *s = renderText(rightBorder_X, string);
// Draw the message
- drawMessage(s, x, y, rightBorder_X - x, fontColour, buffer);
+ drawMessage(s, x, y, rightBorder_X - x, fontColor, buffer);
// Free the data
delete s->imagePtr;
diff --git a/engines/cruise/font.h b/engines/cruise/font.h
index 849c074ac5..17bb4372cf 100644
--- a/engines/cruise/font.h
+++ b/engines/cruise/font.h
@@ -66,7 +66,7 @@ void renderWord(uint8 *fontPtr_Data, uint8 *outBufferPtr,
int32 drawPosPixel_X, int32 heightOff, int32 height, int32 param4,
int32 stringRenderBufferSize, int32 width, int32 charWidth);
gfxEntryStruct *renderText(int inRightBorder_X, const char *string);
-void drawString(int32 x, int32 y, const char *string, uint8 * buffer, uint8 fontColour,
+void drawString(int32 x, int32 y, const char *string, uint8 * buffer, uint8 fontColor,
int32 inRightBorder_X);
void freeGfx(gfxEntryStruct *pGfx);
diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp
index 0b25ee59c1..75b90f7ec8 100644
--- a/engines/cruise/function.cpp
+++ b/engines/cruise/function.cpp
@@ -28,6 +28,8 @@
#include "cruise/cell.h"
#include "cruise/sound.h"
#include "cruise/staticres.h"
+
+#include "common/textconsole.h"
#include "common/util.h"
namespace Cruise {
diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp
index f9ab193399..4d48c2c466 100644
--- a/engines/cruise/gfxModule.cpp
+++ b/engines/cruise/gfxModule.cpp
@@ -29,6 +29,8 @@
#include "common/list.h"
#include "common/rect.h"
+#include "graphics/palette.h"
+
#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
@@ -203,7 +205,7 @@ void gfxModuleData_gfxWaitVSync() {
void gfxModuleData_flip() {
}
-void gfxCopyRect(const uint8 *sourceBuffer, int width, int height, byte *dest, int x, int y, int colour) {
+void gfxCopyRect(const uint8 *sourceBuffer, int width, int height, byte *dest, int x, int y, int color) {
int xp, yp;
for (yp = 0; yp < height; ++yp) {
@@ -216,7 +218,7 @@ void gfxCopyRect(const uint8 *sourceBuffer, int width, int height, byte *dest, i
int yDest = y + yp;
if ((v != 0) && (xDest >= 0) && (yDest >= 0) && (xDest < 320) && (yDest < 200))
- *destP = (v == 1) ? 0 : colour;
+ *destP = (v == 1) ? 0 : color;
}
}
}
@@ -324,10 +326,10 @@ void flip() {
g_system->updateScreen();
}
-void drawSolidBox(int32 x1, int32 y1, int32 x2, int32 y2, uint8 colour) {
+void drawSolidBox(int32 x1, int32 y1, int32 x2, int32 y2, uint8 color) {
for (int y = y1; y < y2; ++y) {
byte *p = &gfxModuleData.pPage00[y * 320 + x1];
- Common::set_to(p, p + (x2 - x1), colour);
+ Common::set_to(p, p + (x2 - x1), color);
}
}
diff --git a/engines/cruise/gfxModule.h b/engines/cruise/gfxModule.h
index 1dbc5afc9b..1ca2581af5 100644
--- a/engines/cruise/gfxModule.h
+++ b/engines/cruise/gfxModule.h
@@ -55,7 +55,7 @@ void gfxModuleData_flip();
void gfxModuleData_updatePalette();
void gfxModuleData_updateScreen();
-void gfxCopyRect(const uint8 *sourceBuffer, int width, int height, byte *dest, int x, int y, int colour);
+void gfxCopyRect(const uint8 *sourceBuffer, int width, int height, byte *dest, int x, int y, int color);
void gfxModuleData_gfxCopyScreen(const uint8 *sourcePtr, uint8 *destPtr);
void convertGfxFromMode4(const uint8 *sourcePtr, int width, int height, uint8 *destPtr);
void convertGfxFromMode5(const uint8 *sourcePtr, int width, int height, uint8 *destPtr);
@@ -67,7 +67,7 @@ void gfxModuleData_setPalEntries(const byte *ptr, int start, int num);
void gfxModuleData_setPal256(const byte *ptr);
void gfxModuleData_addDirtyRect(const Common::Rect &r);
void flip();
-void drawSolidBox(int32 x1, int32 y1, int32 x2, int32 y2, uint8 colour);
+void drawSolidBox(int32 x1, int32 y1, int32 x2, int32 y2, uint8 color);
void resetBitmap(uint8 *dataPtr, int32 dataSize);
void switchBackground(const byte *newBg);
diff --git a/engines/cruise/linker.cpp b/engines/cruise/linker.cpp
index 49e97ebc11..afc7992493 100644
--- a/engines/cruise/linker.cpp
+++ b/engines/cruise/linker.cpp
@@ -147,8 +147,6 @@ int updateScriptImport(int ovlIdx) {
const char *ptrImportName;
uint8 *ptrData;
- int var_22 = 0;
-
if (param == 0) {
pScript = getOvlData3Entry(ovlIdx, i);
} else {
@@ -159,8 +157,6 @@ int updateScriptImport(int ovlIdx) {
ptrImportName = (const char*)(pScript->dataPtr + pScript->offsetToImportName); // import name
ptrData = pScript->dataPtr;
- var_22 = 0;
-
if (pScript->numRelocGlob > 0) {
int counter = pScript->numRelocGlob;
diff --git a/engines/cruise/mainDraw.cpp b/engines/cruise/mainDraw.cpp
index aaa6f987b6..f6b04e6d9d 100644
--- a/engines/cruise/mainDraw.cpp
+++ b/engines/cruise/mainDraw.cpp
@@ -1081,8 +1081,6 @@ void mainDrawPolygons(int fileIndex, cellStruct *plWork, int X, int scale, int Y
int newScale;
char *newFrame;
- int var_8; // unused
-
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)
@@ -1125,8 +1123,6 @@ void mainDrawPolygons(int fileIndex, cellStruct *plWork, int X, int scale, int Y
gfxModuleData_addDirtyRect(Common::Rect(spriteX2, spriteY2, spriteX1, spriteY1));
- var_8 = 0;
-
memset(polygonMask, 0xFF, (320*200) / 8);
int numPasses = 0;
diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp
index a722b947ff..36689ca0e3 100644
--- a/engines/cruise/menu.cpp
+++ b/engines/cruise/menu.cpp
@@ -29,6 +29,7 @@
#include "engines/metaengine.h"
#include "gui/saveload.h"
+#include "common/system.h"
#include "common/translation.h"
namespace Cruise {
diff --git a/engines/cruise/object.cpp b/engines/cruise/object.cpp
index 864491605f..8e2be0cf13 100644
--- a/engines/cruise/object.cpp
+++ b/engines/cruise/object.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "cruise/cruise_main.h"
namespace Cruise {
diff --git a/engines/cruise/overlay.cpp b/engines/cruise/overlay.cpp
index 9a77891deb..b7a0293f33 100644
--- a/engines/cruise/overlay.cpp
+++ b/engines/cruise/overlay.cpp
@@ -24,6 +24,7 @@
*/
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index a1a306705e..6e75088d45 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -30,6 +30,7 @@
#include "common/serializer.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
diff --git a/engines/cruise/script.cpp b/engines/cruise/script.cpp
index 317dcfbbe6..d6ff784644 100644
--- a/engines/cruise/script.cpp
+++ b/engines/cruise/script.cpp
@@ -26,6 +26,7 @@
#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
#include "common/endian.h"
+#include "common/textconsole.h"
namespace Cruise {
@@ -619,13 +620,13 @@ int executeScripts(scriptInstanceStruct *ptr) {
positionInStack = 0;
do {
-//#ifdef SKIP_INTRO
+#ifdef SKIP_INTRO
if (currentScriptPtr->scriptOffset == 290
&& currentScriptPtr->overlayNumber == 4
&& currentScriptPtr->scriptNumber == 0) {
currentScriptPtr->scriptOffset = 923;
}
-//#endif
+#endif
opcodeType = getByteFromScript();
debugC(5, kCruiseDebugScript, "Script %s/%d ip=%d opcode=%d",
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 8a4b1d0d2b..322f808439 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -24,6 +24,8 @@
*/
#include "common/endian.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "cruise/cruise.h"
#include "cruise/cruise_main.h"
@@ -283,9 +285,21 @@ void PCSoundDriver::resetChannel(int channel) {
}
void PCSoundDriver::syncSounds() {
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ bool music_mute = mute;
+ bool sfx_mute = mute;
+
+ if (!mute) {
+ music_mute = ConfMan.getBool("music_mute");
+ sfx_mute = ConfMan.getBool("sfx_mute");
+ }
+
// Get the new music and sfx volumes
- _musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume"));
- _sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
+ _musicVolume = music_mute ? 0 : MIN(255, ConfMan.getInt("music_volume"));
+ _sfxVolume = sfx_mute ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
}
AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index 18c184e568..7e1f29271e 100644
--- a/engines/dialogs.cpp
+++ b/engines/dialogs.cpp
@@ -25,21 +25,21 @@
#include "base/version.h"
#include "common/config-manager.h"
-#include "common/savefile.h"
-#include "common/system.h"
#include "common/events.h"
+#include "common/str.h"
+#include "common/system.h"
#include "common/translation.h"
-#include "graphics/scaler.h"
-
#include "gui/about.h"
#include "gui/gui-manager.h"
-#include "gui/launcher.h"
-#include "gui/widgets/list.h"
#include "gui/message.h"
#include "gui/options.h"
#include "gui/saveload.h"
+#include "gui/ThemeEngine.h"
#include "gui/ThemeEval.h"
+#include "gui/widget.h"
+
+#include "graphics/font.h"
#include "engines/dialogs.h"
#include "engines/engine.h"
diff --git a/engines/dialogs.h b/engines/dialogs.h
index 6e5338b317..587e91a2bb 100644
--- a/engines/dialogs.h
+++ b/engines/dialogs.h
@@ -25,15 +25,15 @@
#ifndef GLOBAL_DIALOGS_H
#define GLOBAL_DIALOGS_H
-#include "common/str.h"
#include "gui/dialog.h"
class Engine;
namespace GUI {
- class ButtonWidget;
- class GraphicsWidget;
- class SaveLoadChooser;
+class ButtonWidget;
+class CommandSender;
+class GraphicsWidget;
+class SaveLoadChooser;
}
class MainMenuDialog : public GUI::Dialog {
diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp
index d7582ec31d..f2f1727fdd 100644
--- a/engines/draci/animation.cpp
+++ b/engines/draci/animation.cpp
@@ -32,6 +32,7 @@
#include "draci/surface.h"
#include "common/memstream.h"
+#include "common/system.h"
namespace Draci {
@@ -359,7 +360,7 @@ void AnimationManager::insert(Animation *anim, bool allocateIndex) {
}
void AnimationManager::drawScene(Surface *surf) {
- // Fill the screen with colour zero since some rooms may rely on the screen being black
+ // Fill the screen with color zero since some rooms may rely on the screen being black
_vm->_screen->getSurface()->fill(0);
sortAnimations();
@@ -498,8 +499,8 @@ const Animation *AnimationManager::getTopAnimation(int x, int y) const {
Animation *retval = NULL;
- // Get transparent colour for the current screen
- const int transparent = _vm->_screen->getSurface()->getTransparentColour();
+ // Get transparent color for the current screen
+ const int transparent = _vm->_screen->getSurface()->getTransparentColor();
for (it = _animations.reverse_begin(); it != _animations.end(); --it) {
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp
index d0eb511cbd..45d17ea24f 100644
--- a/engines/draci/draci.cpp
+++ b/engines/draci/draci.cpp
@@ -162,18 +162,10 @@ int DraciEngine::init() {
_dubbingArchive = openAnyPossibleDubbing();
_sound = new Sound(_mixer);
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
+ _music = new MusicPlayer(musicPathMask);
- _midiDriver = MidiDriver::createMidi(dev);
- if (native_mt32)
- _midiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _music = new MusicPlayer(_midiDriver, musicPathMask);
- _music->setNativeMT32(native_mt32);
- _music->open();
- //_music->setAdLib(adlib);
+ // Setup mixer
+ syncSoundSettings();
// Load the game's fonts
_smallFont = new Font(kFontSmall);
@@ -401,7 +393,6 @@ DraciEngine::~DraciEngine() {
delete _sound;
delete _music;
- delete _midiDriver;
delete _soundsArchive;
delete _dubbingArchive;
diff --git a/engines/draci/draci.h b/engines/draci/draci.h
index aa6080ca05..6a597e123e 100644
--- a/engines/draci/draci.h
+++ b/engines/draci/draci.h
@@ -85,7 +85,6 @@ public:
AnimationManager *_anims;
Sound *_sound;
MusicPlayer *_music;
- MidiDriver *_midiDriver;
Font *_smallFont;
Font *_bigFont;
diff --git a/engines/draci/font.cpp b/engines/draci/font.cpp
index 688458f3d4..d869d046f3 100644
--- a/engines/draci/font.cpp
+++ b/engines/draci/font.cpp
@@ -125,7 +125,7 @@ uint8 Font::getCharWidth(uint8 chr) const {
* @param ty Vertical offset on the surface
*/
-void Font::drawChar(Surface *dst, uint8 chr, int tx, int ty, int with_colour) const {
+void Font::drawChar(Surface *dst, uint8 chr, int tx, int ty, int with_color) const {
assert(dst != NULL);
assert(tx >= 0);
assert(ty >= 0);
@@ -147,39 +147,39 @@ void Font::drawChar(Surface *dst, uint8 chr, int tx, int ty, int with_colour) co
int ySpaceLeft = dst->h - ty - 1;
int yPixelsToDraw = (_fontHeight < ySpaceLeft) ? _fontHeight : ySpaceLeft;
- int _transparent = dst->getTransparentColour();
+ int _transparent = dst->getTransparentColor();
for (int y = 0; y < yPixelsToDraw; ++y) {
for (int x = 0; x <= xPixelsToDraw; ++x) {
int curr = y * _maxCharWidth + x;
- int colour = _charData[charOffset + curr];
+ int color = _charData[charOffset + curr];
// If pixel is transparent, skip it
- if (colour == _transparent)
+ if (color == _transparent)
continue;
- // Replace colour with font colours
- switch (colour) {
+ // Replace color with font colors
+ switch (color) {
case 254:
- colour = with_colour;
+ color = with_color;
break;
case 253:
- colour = kFontColour2;
+ color = kFontColor2;
break;
case 252:
- colour = kFontColour3;
+ color = kFontColor3;
break;
case 251:
- colour = kFontColour4;
+ color = kFontColor4;
break;
}
// Paint the pixel
- ptr[x] = colour;
+ ptr[x] = color;
}
// Advance to next row
@@ -198,8 +198,8 @@ void Font::drawChar(Surface *dst, uint8 chr, int tx, int ty, int with_colour) co
* @param spacing Space to leave between individual characters. Defaults to 0.
*/
void Font::drawString(Surface *dst, const byte *str, uint len,
- int x, int y, int with_colour, int spacing, bool markDirty) const {
- drawString(dst, Common::String((const char *)str, len), x, y, with_colour, spacing, markDirty);
+ int x, int y, int with_color, int spacing, bool markDirty) const {
+ drawString(dst, Common::String((const char *)str, len), x, y, with_color, spacing, markDirty);
}
/**
@@ -213,7 +213,7 @@ void Font::drawString(Surface *dst, const byte *str, uint len,
*/
void Font::drawString(Surface *dst, const Common::String &str,
- int x, int y, int with_colour, int spacing, bool markDirty) const {
+ int x, int y, int with_color, int spacing, bool markDirty) const {
assert(dst != NULL);
assert(x >= 0);
assert(y >= 0);
@@ -238,7 +238,7 @@ void Font::drawString(Surface *dst, const Common::String &str,
break;
}
- drawChar(dst, str[i], curx, cury, with_colour);
+ drawChar(dst, str[i], curx, cury, with_color);
curx += getCharWidth(str[i]) + spacing;
}
diff --git a/engines/draci/font.h b/engines/draci/font.h
index 010de66e2c..0ccc900465 100644
--- a/engines/draci/font.h
+++ b/engines/draci/font.h
@@ -36,19 +36,19 @@ extern const char * const kFontBig;
class Surface;
/**
- * Default font colours. They all seem to remain constant except for the
+ * Default font colors. They all seem to remain constant except for the
* first one which varies depending on the character speaking.
- * kOverFontColour is set to transparent.
+ * kOverFontColor is set to transparent.
*/
enum {
- kFontColour1 = 2,
- kFontColour2 = 0,
- kFontColour3 = 3,
- kFontColour4 = 4,
- kOverFontColour = 255,
- kTitleColour = 255,
- kLineActiveColour = 254,
- kLineInactiveColour = 255
+ kFontColor1 = 2,
+ kFontColor2 = 0,
+ kFontColor3 = 3,
+ kFontColor4 = 4,
+ kOverFontColor = 255,
+ kTitleColor = 255,
+ kLineActiveColor = 254,
+ kLineInactiveColor = 255
};
/**
@@ -64,12 +64,12 @@ public:
uint8 getFontHeight() const { return _fontHeight; }
uint8 getMaxCharWidth() const { return _maxCharWidth; }
uint8 getCharWidth(byte chr) const;
- void drawChar(Surface *dst, uint8 chr, int tx, int ty, int with_colour) const;
+ void drawChar(Surface *dst, uint8 chr, int tx, int ty, int with_color) const;
- void drawString(Surface *dst, const byte *str, uint len, int x, int y, int with_colour,
+ void drawString(Surface *dst, const byte *str, uint len, int x, int y, int with_color,
int spacing, bool markDirty) const;
void drawString(Surface *dst, const Common::String &str,
- int x, int y, int with_colour, int spacing, bool markDirty) const;
+ int x, int y, int with_color, int spacing, bool markDirty) const;
uint getStringWidth(const Common::String &str, int spacing) const;
uint getStringHeight(const Common::String &str) const;
diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp
index 060ee41077..e19ec67810 100644
--- a/engines/draci/game.cpp
+++ b/engines/draci/game.cpp
@@ -47,9 +47,9 @@ static const char *dialoguePath = "ROZH";
static double real_to_double(byte real[6]);
enum {
- kWalkingMapOverlayColour = 2,
- kWalkingShortestPathOverlayColour = 120,
- kWalkingObliquePathOverlayColour = 73
+ kWalkingMapOverlayColor = 2,
+ kWalkingShortestPathOverlayColor = 120,
+ kWalkingObliquePathOverlayColor = 73
};
Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
@@ -69,7 +69,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) {
for (i = 0; i < numPersons; ++i) {
_persons[i]._x = personData.readUint16LE();
_persons[i]._y = personData.readUint16LE();
- _persons[i]._fontColour = personData.readByte();
+ _persons[i]._fontColor = personData.readByte();
}
// Read in dialogue offsets
@@ -217,12 +217,12 @@ void Game::init() {
// Initialize animation for object / room titles
_titleAnim = new Animation(_vm, kTitleText, 257, true);
- _titleAnim->addFrame(new Text("", _vm->_smallFont, kTitleColour, 0, 0, 0), NULL);
+ _titleAnim->addFrame(new Text("", _vm->_smallFont, kTitleColor, 0, 0, 0), NULL);
_vm->_anims->insert(_titleAnim, false);
// Initialize animation for speech text
Animation *speechAnim = new Animation(_vm, kSpeechText, 257, true);
- speechAnim->addFrame(new Text("", _vm->_bigFont, kFontColour1, 0, 0, 0), NULL);
+ speechAnim->addFrame(new Text("", _vm->_bigFont, kFontColor1, 0, 0, 0), NULL);
_vm->_anims->insert(speechAnim, false);
// Initialize inventory animation. _iconsArchive is never flushed.
@@ -236,7 +236,7 @@ void Game::init() {
for (uint i = 0; i < kDialogueLines; ++i) {
_dialogueAnims[i] = new Animation(_vm, kDialogueLinesID - i, 254, true);
- _dialogueAnims[i]->addFrame(new Text("", _vm->_smallFont, kLineInactiveColour, 0, 0, 0), NULL);
+ _dialogueAnims[i]->addFrame(new Text("", _vm->_smallFont, kLineInactiveColor, 0, 0, 0), NULL);
_dialogueAnims[i]->setRelative(1,
kScreenHeight - (i + 1) * _vm->_smallFont->getFontHeight());
@@ -418,9 +418,9 @@ void Game::handleDialogueLoop() {
text = reinterpret_cast<Text *>(_dialogueAnims[i]->getCurrentFrame());
if (_animUnderCursor == _dialogueAnims[i]) {
- text->setColour(kLineActiveColour);
+ text->setColor(kLineActiveColor);
} else {
- text->setColour(kLineInactiveColour);
+ text->setColor(kLineInactiveColor);
}
}
@@ -442,7 +442,7 @@ void Game::fadePalette(bool fading_out) {
}
for (int i = 1; i <= kBlackFadingIterations; ++i) {
_vm->_system->delayMillis(kBlackFadingTimeUnit);
- _vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColours, i, kBlackFadingIterations);
+ _vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColors, i, kBlackFadingIterations);
_vm->_screen->copyToScreen();
}
}
@@ -454,7 +454,7 @@ void Game::advanceAnimationsAndTestLoopExit() {
--_fadePhase;
const byte *startPal = _currentRoom._palette >= 0 ? _vm->_paletteArchive->getFile(_currentRoom._palette)->_data : NULL;
const byte *endPal = getScheduledPalette() >= 0 ? _vm->_paletteArchive->getFile(getScheduledPalette())->_data : NULL;
- _vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColours, _fadePhases - _fadePhase, _fadePhases);
+ _vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColors, _fadePhases - _fadePhase, _fadePhases);
if (_fadePhase == 0) {
if (_loopSubstatus == kInnerWhileFade) {
setExitLoop(true);
@@ -997,7 +997,7 @@ int Game::dialogueDraw() {
dialogueLine = reinterpret_cast<Text *>(anim->getCurrentFrame());
dialogueLine->setText(_dialogueBlocks[i]._title);
- dialogueLine->setColour(kLineInactiveColour);
+ dialogueLine->setColor(kLineInactiveColor);
_lines[_dialogueLinesNum] = i;
_dialogueLinesNum++;
}
@@ -1114,8 +1114,8 @@ int Game::playHeroAnimation(int anim_index) {
return anim->currentFrameNum();
}
-void Game::redrawWalkingPath(Animation *anim, byte colour, const WalkingPath &path) {
- Sprite *ov = _walkingMap.newOverlayFromPath(path, colour);
+void Game::redrawWalkingPath(Animation *anim, byte color, const WalkingPath &path) {
+ Sprite *ov = _walkingMap.newOverlayFromPath(path, color);
delete anim->getFrame(0);
anim->replaceFrame(0, ov, NULL);
anim->markDirtyRect(_vm->_screen->getSurface());
@@ -1148,8 +1148,8 @@ void Game::walkHero(int x, int y, SightDirection dir) {
_walkingMap.obliquePath(shortestPath, &obliquePath);
debugC(2, kDraciWalkingDebugLevel, "Walking path lengths: shortest=%d oblique=%d", shortestPath.size(), obliquePath.size());
if (_vm->_showWalkingMap) {
- redrawWalkingPath(_walkingShortestPathOverlay, kWalkingShortestPathOverlayColour, shortestPath);
- redrawWalkingPath(_walkingObliquePathOverlay, kWalkingObliquePathOverlayColour, obliquePath);
+ redrawWalkingPath(_walkingShortestPathOverlay, kWalkingShortestPathOverlayColor, shortestPath);
+ redrawWalkingPath(_walkingObliquePathOverlay, kWalkingObliquePathOverlayColor, obliquePath);
}
// Start walking. Walking will be gradually advanced by
@@ -1211,7 +1211,7 @@ void Game::loadWalkingMap(int mapID) {
f = _vm->_walkingMapsArchive->getFile(mapID);
_walkingMap.load(f->_data, f->_length);
- Sprite *ov = _walkingMap.newOverlayFromMap(kWalkingMapOverlayColour);
+ Sprite *ov = _walkingMap.newOverlayFromMap(kWalkingMapOverlayColor);
delete _walkingMapOverlay->getFrame(0);
_walkingMapOverlay->replaceFrame(0, ov, NULL);
_walkingMapOverlay->markDirtyRect(_vm->_screen->getSurface());
@@ -1385,7 +1385,7 @@ void Game::enterNewRoom() {
loadOverlays();
// Draw the scene with the black palette and slowly fade into the right palette.
- _vm->_screen->setPalette(NULL, 0, kNumColours);
+ _vm->_screen->setPalette(NULL, 0, kNumColors);
_vm->_anims->drawScene(_vm->_screen->getSurface());
_vm->_screen->copyToScreen();
fadePalette(false);
diff --git a/engines/draci/game.h b/engines/draci/game.h
index 21baaed5cc..0b5b3a03cc 100644
--- a/engines/draci/game.h
+++ b/engines/draci/game.h
@@ -31,7 +31,7 @@
#include "draci/walking.h"
namespace Common {
- class Serializer;
+class Serializer;
}
namespace Draci {
@@ -145,7 +145,7 @@ public:
struct Person {
uint _x, _y;
- byte _fontColour;
+ byte _fontColor;
};
struct Dialogue {
@@ -348,7 +348,7 @@ private:
void enterNewRoom();
void initWalkingOverlays();
void loadRoomObjects();
- void redrawWalkingPath(Animation *anim, byte colour, const WalkingPath &path);
+ void redrawWalkingPath(Animation *anim, byte color, const WalkingPath &path);
DraciEngine *_vm;
diff --git a/engines/draci/mouse.cpp b/engines/draci/mouse.cpp
index 14d1162fed..5853d15d21 100644
--- a/engines/draci/mouse.cpp
+++ b/engines/draci/mouse.cpp
@@ -106,14 +106,14 @@ void Mouse::setCursorType(CursorType cur) {
f = _vm->_iconsArchive->getFile(cur);
Sprite sp(f->_data, f->_length, 0, 0, true);
- CursorMan.replaceCursorPalette(_vm->_screen->getPalette(), 0, kNumColours);
+ CursorMan.replaceCursorPalette(_vm->_screen->getPalette(), 0, kNumColors);
CursorMan.replaceCursor(sp.getBuffer(), sp.getWidth(), sp.getHeight(),
sp.getWidth() / 2, sp.getHeight() / 2, 255);
}
void Mouse::loadItemCursor(const GameItem *item, bool highlighted) {
const int itemID = item->_absNum;
- const int archiveIndex = 2 * itemID + highlighted;
+ const int archiveIndex = 2 * itemID + (highlighted ? 1 : 0);
CursorType newCursor = static_cast<CursorType> (kItemCursor + archiveIndex);
if (newCursor == getCursorType()) {
return;
@@ -124,7 +124,7 @@ void Mouse::loadItemCursor(const GameItem *item, bool highlighted) {
f = _vm->_itemImagesArchive->getFile(archiveIndex);
Sprite sp(f->_data, f->_length, 0, 0, true);
- CursorMan.replaceCursorPalette(_vm->_screen->getPalette(), 0, kNumColours);
+ CursorMan.replaceCursorPalette(_vm->_screen->getPalette(), 0, kNumColors);
CursorMan.replaceCursor(sp.getBuffer(), sp.getWidth(), sp.getHeight(),
sp.getWidth() / 2, sp.getHeight() / 2, 255);
}
diff --git a/engines/draci/music.cpp b/engines/draci/music.cpp
index caa82c2cc0..1d725ebb15 100644
--- a/engines/draci/music.cpp
+++ b/engines/draci/music.cpp
@@ -29,6 +29,7 @@
#include "audio/mididrv.h"
#include "audio/midiparser.h"
#include "common/config-manager.h"
+#include "common/debug.h"
#include "common/file.h"
#include "draci/draci.h"
@@ -36,133 +37,41 @@
namespace Draci {
-MusicPlayer::MusicPlayer(MidiDriver *driver, const char *pathMask) : _parser(0), _driver(driver), _pathMask(pathMask), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false), _track(-1) {
- memset(_channel, 0, sizeof(_channel));
- memset(_channelVolume, 127, sizeof(_channelVolume));
- _masterVolume = 0;
- _smfParser = MidiParser::createParser_SMF();
- _midiMusicData = NULL;
-}
-
-MusicPlayer::~MusicPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- stop();
- this->close();
- _smfParser->setMidiDriver(NULL);
- delete _smfParser;
- delete[] _midiMusicData;
-}
-
-void MusicPlayer::setChannelVolume(int channel) {
- int newVolume = _channelVolume[channel] * _masterVolume / 255;
- debugC(3, kDraciSoundDebugLevel, "Music channel %d: volume %d->%d",
- channel, _channelVolume[channel], newVolume);
- _channel[channel]->volume(newVolume);
-}
-
-void MusicPlayer::setVolume(int volume) {
- Common::StackLock lock(_mutex);
-
- volume = CLIP(volume, 0, 255);
- if (_masterVolume == volume)
- return;
- _masterVolume = volume;
-
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- setChannelVolume(i);
- }
- }
-}
+MusicPlayer::MusicPlayer(const char *pathMask) : _pathMask(pathMask), _isGM(false), _track(-1) {
-int MusicPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
+ MidiPlayer::createDriver();
int ret = _driver->open();
- if (ret)
- return ret;
-
- 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, &onTimer);
- return 0;
-}
-
-void MusicPlayer::close() {
- stop();
- if (_driver)
- _driver->close();
- _driver = 0;
-}
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
-void MusicPlayer::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
+ // 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.
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
- b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
- }
- else if ((b & 0xFFF0) == 0x007BB0) {
- //Only respond to All Notes Off if this channel
- //has currently been allocated
- if (_channel[b & 0x0F])
- return;
+ _driver->setTimerCallback(this, &timerCallback);
}
+}
- if (!_channel[channel]) {
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+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 (_channel[channel])
- setChannelVolume(channel);
- }
-
- if (_channel[channel])
- _channel[channel]->send(b);
-}
-
-void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
-
- switch (type) {
- case 0x2F: // End of Track
- if (_looping)
- _parser->jumpToTick(0);
- else
- stop();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
}
-}
-
-void MusicPlayer::onTimer(void *refCon) {
- MusicPlayer *music = (MusicPlayer *)refCon;
- Common::StackLock lock(music->_mutex);
- if (music->_parser)
- music->_parser->onTimer();
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
void MusicPlayer::playSMF(int track, bool loop) {
+ Common::StackLock lock(_mutex);
+
if (_isPlaying && track == _track) {
debugC(2, kDraciSoundDebugLevel, "Already plaing track %d", track);
return;
@@ -172,76 +81,46 @@ void MusicPlayer::playSMF(int track, bool loop) {
_isGM = true;
-
// Load MIDI resource data
Common::File musicFile;
char musicFileName[40];
- sprintf(musicFileName, _pathMask.c_str(), track);
+ snprintf(musicFileName, sizeof(musicFileName), _pathMask.c_str(), track);
musicFile.open(musicFileName);
if (!musicFile.isOpen()) {
debugC(2, kDraciSoundDebugLevel, "Cannot open track %d", track);
return;
}
int midiMusicSize = musicFile.size();
- delete[] _midiMusicData;
- _midiMusicData = new byte[midiMusicSize];
- musicFile.read(_midiMusicData, midiMusicSize);
+ free(_midiData);
+ _midiData = (byte *)malloc(midiMusicSize);
+ musicFile.read(_midiData, midiMusicSize);
musicFile.close();
- if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) {
- MidiParser *parser = _smfParser;
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_midiData, midiMusicSize)) {
parser->setTrack(0);
parser->setMidiDriver(this);
- parser->setTimerRate(getBaseTempo());
+ parser->setTimerRate(_driver->getBaseTempo());
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_parser = parser;
syncVolume();
- _looping = loop;
+ _isLooping = loop;
_isPlaying = true;
_track = track;
debugC(2, kDraciSoundDebugLevel, "Playing track %d", track);
} else {
debugC(2, kDraciSoundDebugLevel, "Cannot play track %d", track);
+ delete parser;
}
}
void MusicPlayer::stop() {
- Common::StackLock lock(_mutex);
-
- if (!_isPlaying)
- return;
-
+ Audio::MidiPlayer::stop();
debugC(2, kDraciSoundDebugLevel, "Stopping track %d", _track);
_track = -1;
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
- }
-}
-
-void MusicPlayer::pause() {
- debugC(2, kDraciSoundDebugLevel, "Pausing track %d", _track);
- setVolume(-1);
- _isPlaying = false;
-}
-
-void MusicPlayer::resume() {
- debugC(2, kDraciSoundDebugLevel, "Resuming track %d", _track);
- syncVolume();
- _isPlaying = true;
-}
-
-void MusicPlayer::syncVolume() {
- int volume = ConfMan.getInt("music_volume");
- if (ConfMan.getBool("mute")) {
- volume = -1;
- }
- debugC(2, kDraciSoundDebugLevel, "Syncing music volume to %d", volume);
- setVolume(volume);
}
} // End of namespace Draci
diff --git a/engines/draci/music.h b/engines/draci/music.h
index f6f3a5ae50..c0228074e5 100644
--- a/engines/draci/music.h
+++ b/engines/draci/music.h
@@ -28,74 +28,27 @@
#ifndef DRACI_MUSIC_H
#define DRACI_MUSIC_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
-#include "common/mutex.h"
+#include "audio/midiplayer.h"
namespace Draci {
// Taken from MADE, which took it from SAGA.
-class MusicPlayer : public MidiDriver {
+class MusicPlayer : public Audio::MidiPlayer {
public:
- MusicPlayer(MidiDriver *driver, const char *pathMask);
- ~MusicPlayer();
+ MusicPlayer(const char *pathMask);
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
-
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
- void syncVolume();
-
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
void playSMF(int track, bool loop);
void stop();
- void pause();
- void resume();
- void setLoop(bool loop) { _looping = loop; }
- void setPassThrough(bool b) { _passThrough = b; }
-
- void setGM(bool isGM) { _isGM = isGM; }
-
- // MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- MidiParser *_parser;
- Common::Mutex _mutex;
+ // Overload Audio::MidiPlayer method
+ virtual void sendToChannel(byte channel, uint32 b);
protected:
-
- static void onTimer(void *data);
- void setChannelVolume(int channel);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_smfParser;
Common::String _pathMask;
- byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
- bool _isPlaying;
- bool _looping;
- byte _masterVolume;
int _track;
-
- byte *_midiMusicData;
};
} // End of namespace Draci
diff --git a/engines/draci/screen.cpp b/engines/draci/screen.cpp
index dbe3fd98b8..ab9c49c63a 100644
--- a/engines/draci/screen.cpp
+++ b/engines/draci/screen.cpp
@@ -26,6 +26,8 @@
#include "common/memstream.h"
#include "common/system.h"
+#include "graphics/palette.h"
+
#include "draci/draci.h"
#include "draci/screen.h"
#include "draci/surface.h"
@@ -36,12 +38,12 @@ namespace Draci {
Screen::Screen(DraciEngine *vm) : _vm(vm) {
_surface = new Surface(kScreenWidth, kScreenHeight);
- _palette = new byte[3 * kNumColours];
- _blackPalette = new byte[3 * kNumColours];
- for (int i = 0; i < 3 * kNumColours; ++i) {
+ _palette = new byte[3 * kNumColors];
+ _blackPalette = new byte[3 * kNumColors];
+ for (int i = 0; i < 3 * kNumColors; ++i) {
_blackPalette[i] = 0;
}
- setPalette(NULL, 0, kNumColours);
+ setPalette(NULL, 0, kNumColors);
this->clearScreen();
}
@@ -54,11 +56,11 @@ Screen::~Screen() {
/**
* @brief Sets a part of the palette
* @param data Pointer to a buffer containing new palette data
- * start Index of the colour where replacement should start
- * num Number of colours to replace
+ * start Index of the color where replacement should start
+ * num Number of colors to replace
*/
void Screen::setPalette(const byte *data, uint16 start, uint16 num) {
- Common::MemoryReadStream pal(data ? data : _blackPalette, 3 * kNumColours);
+ Common::MemoryReadStream pal(data ? data : _blackPalette, 3 * kNumColors);
pal.seek(start * 3);
// Copy the palette
@@ -78,8 +80,8 @@ void Screen::setPalette(const byte *data, uint16 start, uint16 num) {
}
void Screen::interpolatePalettes(const byte *first, const byte *second, uint16 start, uint16 num, int index, int number) {
- Common::MemoryReadStream firstPal(first ? first : _blackPalette, 3 * kNumColours);
- Common::MemoryReadStream secondPal(second ? second : _blackPalette, 3 * kNumColours);
+ Common::MemoryReadStream firstPal(first ? first : _blackPalette, 3 * kNumColors);
+ Common::MemoryReadStream secondPal(second ? second : _blackPalette, 3 * kNumColors);
firstPal.seek(start * 3);
secondPal.seek(start * 3);
diff --git a/engines/draci/screen.h b/engines/draci/screen.h
index dc1aca092d..e4e910475a 100644
--- a/engines/draci/screen.h
+++ b/engines/draci/screen.h
@@ -33,7 +33,7 @@ namespace Draci {
enum ScreenParameters {
kScreenWidth = 320,
kScreenHeight = 200,
- kNumColours = 256,
+ kNumColors = 256,
kDefaultTransparent = 255
};
diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp
index 2a27541ad9..a7ce8b27d9 100644
--- a/engines/draci/script.cpp
+++ b/engines/draci/script.cpp
@@ -716,14 +716,14 @@ void Script::talk(const Common::Array<int> &params) {
SoundSample *sample = _vm->_sound->isMutedVoice()
? NULL : _vm->_dubbingArchive->getSample(sentenceID, 0);
- // Set the string and text colour
+ // Set the string and text color
surface->markDirtyRect(speechFrame->getRect(kNoDisplacement));
if (_vm->_sound->showSubtitles() || !sample) {
speechFrame->setText(Common::String((const char *)f->_data+1, f->_length-1));
} else {
speechFrame->setText("");
}
- speechFrame->setColour(person->_fontColour);
+ speechFrame->setColor(person->_fontColor);
speechFrame->repeatedlySplitLongLines(kScreenWidth);
// Speak the dubbing if possible
@@ -873,11 +873,11 @@ void Script::fadePalettePlay(const Common::Array<int> &params) {
void Script::setPalette(const Common::Array<int> &params) {
if (_vm->_game->getScheduledPalette() == -1) {
- _vm->_screen->setPalette(NULL, 0, kNumColours);
+ _vm->_screen->setPalette(NULL, 0, kNumColors);
} else {
const BAFile *f;
f = _vm->_paletteArchive->getFile(_vm->_game->getScheduledPalette());
- _vm->_screen->setPalette(f->_data, 0, kNumColours);
+ _vm->_screen->setPalette(f->_data, 0, kNumColors);
}
// Immediately update the palette
_vm->_screen->copyToScreen();
diff --git a/engines/draci/script.h b/engines/draci/script.h
index e81691204e..a75f6bcbc3 100644
--- a/engines/draci/script.h
+++ b/engines/draci/script.h
@@ -30,7 +30,7 @@
#include "common/stream.h"
namespace Common {
- class ReadStream;
+class ReadStream;
}
namespace Draci {
diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp
index dc8f548d6b..ab2479f811 100644
--- a/engines/draci/sound.cpp
+++ b/engines/draci/sound.cpp
@@ -29,6 +29,7 @@
#include "common/file.h"
#include "common/str.h"
#include "common/substream.h"
+#include "common/textconsole.h"
#include "common/memstream.h"
#include "common/unzip.h"
@@ -408,21 +409,25 @@ void Sound::stopVoice() {
}
void Sound::setVolume() {
+ _showSubtitles = ConfMan.getBool("subtitles");
+ _talkSpeed = ConfMan.getInt("talkspeed");
+
if (_mixer->isReady()) {
_muteSound = ConfMan.getBool("sfx_mute");
_muteVoice = ConfMan.getBool("speech_mute");
} else {
_muteSound = _muteVoice = true;
}
+
if (ConfMan.getBool("mute")) {
_muteSound = _muteVoice = true;
}
- _showSubtitles = ConfMan.getBool("subtitles");
- _talkSpeed = ConfMan.getInt("talkspeed");
- const int soundVolume = ConfMan.getInt("sfx_volume");
- const int speechVolume = ConfMan.getInt("speech_volume");
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolume);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, speechVolume);
+
+ _mixer->muteSoundType(Audio::Mixer::kSFXSoundType, _muteSound);
+ _mixer->muteSoundType(Audio::Mixer::kSpeechSoundType, _muteVoice);
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
}
} // End of namespace Draci
diff --git a/engines/draci/sprite.cpp b/engines/draci/sprite.cpp
index 65c6e21ee4..b4296375f2 100644
--- a/engines/draci/sprite.cpp
+++ b/engines/draci/sprite.cpp
@@ -144,7 +144,7 @@ void Sprite::drawReScaled(Surface *surface, bool markDirty, const Displacement &
// Get pointers to source and destination buffers
byte *dst = (byte *)surface->getBasePtr(clippedDestRect.left, clippedDestRect.top);
- const int transparent = surface->getTransparentColour();
+ const int transparent = surface->getTransparentColor();
// Calculate how many rows and columns we need to draw
const int rows = clippedDestRect.height();
@@ -212,7 +212,7 @@ void Sprite::draw(Surface *surface, bool markDirty, int relX, int relY) const {
const byte *src = _data + croppedBy.y * _width +
(!_mirror ? croppedBy.x : _width - 1 - croppedBy.x);
- const int transparent = surface->getTransparentColour();
+ const int transparent = surface->getTransparentColor();
// Calculate how many rows and columns we need to draw
const int rows = clippedDestRect.height();
@@ -252,7 +252,7 @@ Common::Rect Sprite::getRect(const Displacement &displacement) const {
_y + displacement.relY + scummvm_lround(_scaledHeight * displacement.extraScaleY));
}
-Text::Text(const Common::String &str, const Font *font, byte fontColour,
+Text::Text(const Common::String &str, const Font *font, byte fontColor,
int x, int y, uint spacing) {
_x = x;
_y = y;
@@ -268,7 +268,7 @@ Text::Text(const Common::String &str, const Font *font, byte fontColour,
}
_spacing = spacing;
- _colour = fontColour;
+ _color = fontColor;
_font = font;
@@ -294,7 +294,7 @@ void Text::setText(const Common::String &str) {
}
void Text::draw(Surface *surface, bool markDirty, int relX, int relY) const {
- _font->drawString(surface, _text, _x + relX, _y + relY, _colour, _spacing, true);
+ _font->drawString(surface, _text, _x + relX, _y + relY, _color, _spacing, true);
}
Common::Rect Text::getRect(const Displacement &displacement) const {
diff --git a/engines/draci/sprite.h b/engines/draci/sprite.h
index ddc56ecd80..15e1cf80ca 100644
--- a/engines/draci/sprite.h
+++ b/engines/draci/sprite.h
@@ -139,12 +139,12 @@ private:
class Text : public Drawable {
public:
- Text(const Common::String &str, const Font *font, byte fontColour,
+ Text(const Common::String &str, const Font *font, byte fontColor,
int x, int y, uint spacing);
~Text() {}
void setText(const Common::String &str);
- void setColour(byte fontColour) { _colour = fontColour; }
+ void setColor(byte fontColor) { _color = fontColor; }
void setSpacing(uint spacing) { _spacing = spacing; }
void setFont(const Font *font);
@@ -165,7 +165,7 @@ private:
Common::String _text;
uint _length;
- uint8 _colour;
+ uint8 _color;
uint _spacing;
const Font *_font;
};
diff --git a/engines/draci/surface.cpp b/engines/draci/surface.cpp
index 1c7ecfb23b..37a76dbe0e 100644
--- a/engines/draci/surface.cpp
+++ b/engines/draci/surface.cpp
@@ -29,9 +29,9 @@
namespace Draci {
Surface::Surface(int width, int height) {
- this->create(width, height, 1);
+ this->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
this->markClean();
- _transparentColour = kDefaultTransparent;
+ _transparentColor = kDefaultTransparent;
}
Surface::~Surface() {
@@ -80,12 +80,12 @@ void Surface::markClean() {
}
/**
- * @brief Fills the surface with the specified colour
+ * @brief Fills the surface with the specified color
*/
-void Surface::fill(uint colour) {
+void Surface::fill(uint color) {
byte *ptr = (byte *)getBasePtr(0, 0);
- memset(ptr, colour, w * h);
+ memset(ptr, color, w * h);
}
/**
diff --git a/engines/draci/surface.h b/engines/draci/surface.h
index a5c9ddb597..cb15ecebe4 100644
--- a/engines/draci/surface.h
+++ b/engines/draci/surface.h
@@ -27,6 +27,7 @@
#define DRACI_SURFACE_H
#include "common/list.h"
+#include "common/rect.h"
#include "graphics/surface.h"
namespace Draci {
@@ -43,18 +44,18 @@ public:
void markDirty();
void markClean();
bool needsFullUpdate() const { return _fullUpdate; }
- uint getTransparentColour() const { return _transparentColour; }
- void setTransparentColour(uint colour) { _transparentColour = colour; }
- void fill(uint colour);
+ uint getTransparentColor() const { return _transparentColor; }
+ void setTransparentColor(uint color) { _transparentColor = color; }
+ void fill(uint color);
uint putAboveY(int y, int height) const;
uint centerOnX(int x, int width) const;
Common::Rect getDimensions() const { return Common::Rect(w, h); }
private:
- /** The current transparent colour of the surface. See getTransparentColour() and
- * setTransparentColour().
+ /** The current transparent color of the surface. See getTransparentColor() and
+ * setTransparentColor().
*/
- uint _transparentColour;
+ uint _transparentColor;
/** Set when the surface is scheduled for a full update.
* See markDirty(), markClean(). Accessed via needsFullUpdate().
diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp
index c6f9a58a85..d72e50be07 100644
--- a/engines/draci/walking.cpp
+++ b/engines/draci/walking.cpp
@@ -58,7 +58,7 @@ bool WalkingMap::isWalkable(const Common::Point &p) const {
return getPixel(p.x / _deltaX, p.y / _deltaY);
}
-Sprite *WalkingMap::newOverlayFromMap(byte colour) const {
+Sprite *WalkingMap::newOverlayFromMap(byte color) const {
// HACK: Create a visible overlay from the walking map so we can test it
byte *wlk = new byte[_realWidth * _realHeight];
memset(wlk, 255, _realWidth * _realHeight);
@@ -66,7 +66,7 @@ Sprite *WalkingMap::newOverlayFromMap(byte colour) const {
for (int i = 0; i < _mapWidth; ++i) {
for (int j = 0; j < _mapHeight; ++j) {
if (getPixel(i, j)) {
- drawOverlayRectangle(Common::Point(i, j), colour, wlk);
+ drawOverlayRectangle(Common::Point(i, j), color, wlk);
}
}
}
@@ -285,7 +285,7 @@ void WalkingMap::obliquePath(const WalkingPath& path, WalkingPath *obliquedPath)
while (managedToOblique(obliquedPath)) {}
}
-Sprite *WalkingMap::newOverlayFromPath(const WalkingPath &path, byte colour) const {
+Sprite *WalkingMap::newOverlayFromPath(const WalkingPath &path, byte color) const {
// HACK: Create a visible overlay from the walking map so we can test it
byte *wlk = new byte[_realWidth * _realHeight];
memset(wlk, 255, _realWidth * _realHeight);
@@ -297,14 +297,14 @@ Sprite *WalkingMap::newOverlayFromPath(const WalkingPath &path, byte colour) con
// Draw only points in the interval [v1, v2). These half-open
// half-closed intervals connect all the way to the last point.
for (int step = 0; step < steps; ++step) {
- drawOverlayRectangle(interpolate(v1, v2, step, steps), colour, wlk);
+ drawOverlayRectangle(interpolate(v1, v2, step, steps), color, wlk);
}
}
// Draw the last point. This works also when the path has no segment,
// but just one point.
if (path.size() > 0) {
const Common::Point &vLast = path[path.size()-1];
- drawOverlayRectangle(vLast, colour, wlk);
+ drawOverlayRectangle(vLast, color, wlk);
}
Sprite *ov = new Sprite(_realWidth, _realHeight, wlk, 0, 0, false);
@@ -313,10 +313,10 @@ Sprite *WalkingMap::newOverlayFromPath(const WalkingPath &path, byte colour) con
return ov;
}
-void WalkingMap::drawOverlayRectangle(const Common::Point &p, byte colour, byte *buf) const {
+void WalkingMap::drawOverlayRectangle(const Common::Point &p, byte color, byte *buf) const {
for (int i = 0; i < _deltaX; ++i) {
for (int j = 0; j < _deltaY; ++j) {
- buf[(p.y * _deltaY + j) * _realWidth + (p.x * _deltaX + i)] = colour;
+ buf[(p.y * _deltaY + j) * _realWidth + (p.x * _deltaX + i)] = color;
}
}
}
diff --git a/engines/draci/walking.h b/engines/draci/walking.h
index 55b39792f1..d6c7f0691d 100644
--- a/engines/draci/walking.h
+++ b/engines/draci/walking.h
@@ -45,12 +45,12 @@ public:
bool getPixel(int x, int y) const;
bool isWalkable(const Common::Point &p) const;
- Sprite *newOverlayFromMap(byte colour) const;
+ Sprite *newOverlayFromMap(byte color) const;
Common::Point findNearestWalkable(int x, int y) const;
bool findShortestPath(Common::Point p1, Common::Point p2, WalkingPath *path) const;
void obliquePath(const WalkingPath& path, WalkingPath *obliquedPath);
- Sprite *newOverlayFromPath(const WalkingPath &path, byte colour) const;
+ Sprite *newOverlayFromPath(const WalkingPath &path, byte color) const;
Common::Point getDelta() const { return Common::Point(_deltaX, _deltaY); }
static int pointsBetween(const Common::Point &p1, const Common::Point &p2);
@@ -68,7 +68,7 @@ private:
// 4 possible directions to walk from a pixel.
static const int kDirections[][2];
- void drawOverlayRectangle(const Common::Point &p, byte colour, byte *buf) const;
+ void drawOverlayRectangle(const Common::Point &p, byte color, byte *buf) const;
bool lineIsCovered(const Common::Point &p1, const Common::Point &p2) const;
// Returns true if the number of vertices on the path was decreased.
diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp
index d0906fdf55..dcd93d84d7 100644
--- a/engines/drascula/converse.cpp
+++ b/engines/drascula/converse.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "drascula/drascula.h"
namespace Drascula {
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index e84e80ccd3..470f28ccff 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -29,6 +29,7 @@
#include "common/file.h"
#include "common/savefile.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
#include "backends/audiocd/audiocd.h"
@@ -195,8 +196,7 @@ Common::Error DrasculaEngine::run() {
loadArchives();
// Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ syncSoundSettings();
currentChapter = 1; // values from 1 to 6 will start each part of game
loadedDifferentChapter = 0;
@@ -512,7 +512,7 @@ bool DrasculaEngine::runCurrentChapter() {
checkObjects();
#ifdef _WIN32_WCE
- if (rightMouseButton)
+ if (rightMouseButton) {
if (_menuScreen) {
#else
if (rightMouseButton == 1 && _menuScreen) {
@@ -570,6 +570,9 @@ bool DrasculaEngine::runCurrentChapter() {
#endif
selectVerb(kVerbNone);
}
+#ifdef _WIN32_WCE
+ }
+#endif
if (leftMouseButton == 1 && _menuBar) {
delay(100);
diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp
index 9c5f3dc12a..4cd91e48a0 100644
--- a/engines/drascula/graphics.cpp
+++ b/engines/drascula/graphics.cpp
@@ -25,8 +25,9 @@
#include "drascula/drascula.h"
#include "graphics/surface.h"
-#include "common/stream.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
namespace Drascula {
diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp
index 6b507abc65..630eb08d3c 100644
--- a/engines/drascula/objects.cpp
+++ b/engines/drascula/objects.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "drascula/drascula.h"
namespace Drascula {
diff --git a/engines/drascula/palette.cpp b/engines/drascula/palette.cpp
index b521c0313b..a75e72e249 100644
--- a/engines/drascula/palette.cpp
+++ b/engines/drascula/palette.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "graphics/palette.h"
+
#include "drascula/drascula.h"
namespace Drascula {
diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp
index 884697dec7..35d4eedb5d 100644
--- a/engines/drascula/rooms.cpp
+++ b/engines/drascula/rooms.cpp
@@ -24,6 +24,7 @@
*/
#include "common/array.h"
+#include "common/textconsole.h"
#include "drascula/drascula.h"
@@ -140,6 +141,9 @@ void DrasculaEngine::setupRoomsTable() {
}
void DrasculaEngine::freeRoomsTable() {
+ if (_roomHandlers == 0)
+ return;
+
for (uint32 i = 0; i < _roomHandlers->roomParsers.size(); i++)
delete _roomHandlers->roomParsers[i];
_roomHandlers->roomParsers.clear();
@@ -182,11 +186,11 @@ bool DrasculaEngine::roomParse(int rN, int fl) {
}
bool DrasculaEngine::room_0(int fl) {
+ (void)fl;
+
static const int lookExcuses[3] = {100, 101, 54};
static const int actionExcuses[6] = {11, 109, 111, 110, 115, 116};
- fl = -1; // avoid warning
-
// non-default actions
if (currentChapter == 2 || currentChapter == 4 ||
currentChapter == 5 || currentChapter == 6) {
diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp
index db67409890..eacbe6756d 100644
--- a/engines/drascula/saveload.cpp
+++ b/engines/drascula/saveload.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "drascula/drascula.h"
namespace Drascula {
diff --git a/engines/drascula/sound.cpp b/engines/drascula/sound.cpp
index 48e7492b11..5cb1c4486a 100644
--- a/engines/drascula/sound.cpp
+++ b/engines/drascula/sound.cpp
@@ -29,6 +29,7 @@
#include "audio/decoders/voc.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
#include "backends/audiocd/audiocd.h"
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 0d92c1aef1..2c1d3a732c 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -22,6 +22,8 @@
* $Id$
*/
+#define FORBIDDEN_SYMBOL_EXCEPTION_getcwd
+
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -32,25 +34,26 @@
#include "engines/engine.h"
#include "engines/dialogs.h"
-#include "engines/metaengine.h"
-#include "engines/util.h"
#include "common/config-manager.h"
-#include "common/debug.h"
#include "common/events.h"
#include "common/file.h"
-#include "common/timer.h"
-#include "common/savefile.h"
#include "common/system.h"
#include "common/str.h"
+#include "common/error.h"
+#include "common/list.h"
+#include "common/list_intern.h"
+#include "common/scummsys.h"
+#include "common/textconsole.h"
#include "gui/debugger.h"
+#include "gui/dialog.h"
#include "gui/message.h"
-#include "gui/gui-manager.h"
#include "audio/mixer.h"
#include "graphics/cursorman.h"
+#include "graphics/pixelformat.h"
#ifdef _WIN32_WCE
extern bool isSmartphone();
@@ -145,7 +148,11 @@ void initCommonGFX(bool defaultTo1XScaler) {
assert(transientDomain);
const bool useDefaultGraphicsMode =
- !transientDomain->contains("gfx_mode") &&
+ (!transientDomain->contains("gfx_mode") ||
+ !scumm_stricmp(transientDomain->getVal("gfx_mode").c_str(), "normal") ||
+ !scumm_stricmp(transientDomain->getVal("gfx_mode").c_str(), "default")
+ )
+ &&
(
!gameDomain ||
!gameDomain->contains("gfx_mode") ||
@@ -155,10 +162,7 @@ void initCommonGFX(bool defaultTo1XScaler) {
// See if the game should default to 1x scaler
if (useDefaultGraphicsMode && defaultTo1XScaler) {
- // FIXME: As a hack, we use "1x" here. Would be nicer to use
- // getDefaultGraphicsMode() instead, but right now, we do not specify
- // whether that is a 1x scaler or not...
- g_system->setGraphicsMode("1x");
+ g_system->resetGraphicsScale();
} else {
// Override global scaler with any game-specific define
if (ConfMan.hasKey("gfx_mode")) {
@@ -280,7 +284,7 @@ void initGraphics(int width, int height, bool defaultTo1xScaler) {
initGraphics(width, height, defaultTo1xScaler, &format);
}
-void GUIErrorMessage(const Common::String msg) {
+void GUIErrorMessage(const Common::String &msg) {
g_system->setWindowCaption("Error");
g_system->beginGFXTransaction();
initCommonGFX(false);
@@ -429,7 +433,6 @@ int Engine::runDialog(GUI::Dialog &dialog) {
}
void Engine::syncSoundSettings() {
-
// Sync the engine with the config manager
int soundVolumeMusic = ConfMan.getInt("music_volume");
int soundVolumeSFX = ConfMan.getInt("sfx_volume");
@@ -439,9 +442,14 @@ void Engine::syncSoundSettings() {
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : soundVolumeMusic));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech));
+ _mixer->muteSoundType(Audio::Mixer::kPlainSoundType, mute);
+ _mixer->muteSoundType(Audio::Mixer::kMusicSoundType, mute);
+ _mixer->muteSoundType(Audio::Mixer::kSFXSoundType, mute);
+ _mixer->muteSoundType(Audio::Mixer::kSpeechSoundType, mute);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, Audio::Mixer::kMaxMixerVolume);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSFX);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech);
}
void Engine::flipMute() {
diff --git a/engines/engine.h b/engines/engine.h
index b4764319b8..b7afc0f09d 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -26,28 +26,28 @@
#define ENGINES_ENGINE_H
#include "common/scummsys.h"
-#include "common/error.h"
#include "common/str.h"
class OSystem;
namespace Audio {
- class Mixer;
+class Mixer;
}
namespace Common {
- class EventManager;
- class SaveFileManager;
- class TimerManager;
+class Error;
+class EventManager;
+class SaveFileManager;
+class TimerManager;
}
namespace GUI {
- class Debugger;
- class Dialog;
+class Debugger;
+class Dialog;
}
/**
* Initializes graphics and shows error message.
*/
-void GUIErrorMessage(const Common::String msg);
+void GUIErrorMessage(const Common::String &msg);
class Engine {
@@ -163,6 +163,15 @@ public:
* Notify the engine that the sound settings in the config manager may have
* changed and that it hence should adjust any internal volume etc. values
* accordingly.
+ * The default implementation sets the volume levels of all mixer sound
+ * types according to the config entries of the active domain.
+ * When overwriting, call the default implementation first, then adjust the
+ * volumes further (if required).
+ *
+ * @note When setting volume levels, respect the "mute" config entry.
+ * @note The volume for the plain sound type is reset to the maximum
+ * volume. If the engine can associate its own value for this
+ * type, it needs to overwrite this member and set it accordingly.
* @todo find a better name for this
*/
virtual void syncSoundSettings();
diff --git a/engines/engines.mk b/engines/engines.mk
index 5d62525a56..860ea7abb3 100644
--- a/engines/engines.mk
+++ b/engines/engines.mk
@@ -97,6 +97,18 @@ endif
ifdef ENABLE_MOHAWK
DEFINES += -DENABLE_MOHAWK=$(ENABLE_MOHAWK)
MODULES += engines/mohawk
+
+ifdef ENABLE_CSTIME
+DEFINES += -DENABLE_CSTIME
+endif
+
+ifdef ENABLE_MYST
+DEFINES += -DENABLE_MYST
+endif
+
+ifdef ENABLE_RIVEN
+DEFINES += -DENABLE_RIVEN
+endif
endif
ifdef ENABLE_PARALLACTION
@@ -181,6 +193,11 @@ DEFINES += -DENABLE_TOUCHE=$(ENABLE_TOUCHE)
MODULES += engines/touche
endif
+ifdef ENABLE_TSAGE
+DEFINES += -DENABLE_TSAGE=$(ENABLE_TSAGE)
+MODULES += engines/tsage
+endif
+
ifdef ENABLE_TUCKER
DEFINES += -DENABLE_TUCKER=$(ENABLE_TUCKER)
MODULES += engines/tucker
diff --git a/engines/game.cpp b/engines/game.cpp
index dea6d37485..a27080cbf8 100644
--- a/engines/game.cpp
+++ b/engines/game.cpp
@@ -24,7 +24,6 @@
*/
#include "engines/game.h"
-#include "base/plugins.h"
const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list) {
diff --git a/engines/game.h b/engines/game.h
index 3e5d7f262c..c9a3b25853 100644
--- a/engines/game.h
+++ b/engines/game.h
@@ -28,6 +28,8 @@
#include "common/array.h"
#include "common/hash-str.h"
+#include "common/str.h"
+#include "common/util.h"
/**
* A simple structure used to map gameids (like "monkey", "sword1", ...) to
diff --git a/engines/gob/databases.cpp b/engines/gob/databases.cpp
index 66a711e46e..94f641db4e 100644
--- a/engines/gob/databases.cpp
+++ b/engines/gob/databases.cpp
@@ -24,6 +24,7 @@
*/
#include "common/file.h"
+#include "common/textconsole.h"
#include "gob/databases.h"
diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h
index 6e12d15af8..f2b39aed09 100644
--- a/engines/gob/dataio.h
+++ b/engines/gob/dataio.h
@@ -33,7 +33,7 @@
#include "common/file.h"
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Gob {
diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h
index 43f15b8845..b12fb81be1 100644
--- a/engines/gob/detection_tables.h
+++ b/engines/gob/detection_tables.h
@@ -3723,6 +3723,20 @@ static const GOBGameDescription gameDescriptions[] = {
kFeatures640x480 | kFeaturesTrueColor,
0, 0, 0
},
+ { // Supplied by Collector9 in bug report #3228040
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "6ce3d878178932053267237ec4843ce1", 1252518),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+ },
{ // Supplied by gamin in the forums
{
"urban",
@@ -3751,6 +3765,20 @@ static const GOBGameDescription gameDescriptions[] = {
kFeatures640x480 | kFeaturesTrueColor,
0, 0, 0
},
+ { // Supplied by Alex on the gobsmacked blog
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "9ea647085a16dd0fb9ecd84cd8778ec9", 1253436),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+ },
{ // Supplied by goodoldgeorg in bug report #2770340
{
"urban",
@@ -4921,7 +4949,7 @@ static const GOBGameDescription fallbackDescs[] = {
GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeUrban,
- kFeaturesCD | kFeaturesTrueColor,
+ kFeatures640x480 | kFeaturesTrueColor,
0, 0, 0
},
{ //13
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index b65bbe0d0f..3d697d3693 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -24,14 +24,11 @@
*/
#include "common/debug-channels.h"
-#include "common/endian.h"
-#include "common/events.h"
#include "common/EventRecorder.h"
#include "backends/audiocd/audiocd.h"
#include "base/plugins.h"
#include "common/config-manager.h"
-#include "common/md5.h"
#include "audio/mididrv.h"
#include "gui/gui-manager.h"
@@ -575,6 +572,9 @@ bool GobEngine::initGameParts() {
return false;
}
+ // Setup mixer
+ syncSoundSettings();
+
_inter->setupOpcodes();
return true;
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 9bdbed45cf..4a928747b0 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -30,12 +30,14 @@
#include "common/system.h"
#include "common/savefile.h"
+#include "graphics/pixelformat.h"
+
#include "engines/engine.h"
#include "gob/console.h"
namespace GUI {
- class StaticTextWidget;
+class StaticTextWidget;
}
/**
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index 262fdc8045..8f1ff4c73f 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -23,9 +23,7 @@
*
*/
-#include "common/endian.h"
#include "common/str.h"
-#include "common/file.h"
#include "gob/gob.h"
#include "gob/inter.h"
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 63b2d7f681..6a42b5ecd4 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -1172,12 +1172,11 @@ void Inter_v2::o2_addHotspot(OpFuncParams &params) {
top = 0;
}
- int16 index;
if (id < 0)
- index = _vm->_game->_hotspots->add(0xD000 - id, left & 0xFFFC, top & 0xFFFC,
+ _vm->_game->_hotspots->add(0xD000 - id, left & 0xFFFC, top & 0xFFFC,
left + width + 3, top + height + 3, flags, key, 0, 0, funcPos);
else
- index = _vm->_game->_hotspots->add(0xE000 + id, left, top,
+ _vm->_game->_hotspots->add(0xE000 + id, left, top,
left + width - 1, top + height - 1, flags, key, 0, 0, funcPos);
}
diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp
index 778387e52d..1da92b3766 100644
--- a/engines/gob/inter_v4.cpp
+++ b/engines/gob/inter_v4.cpp
@@ -23,9 +23,7 @@
*
*/
-#include "common/endian.h"
#include "common/str.h"
-#include "common/file.h"
#include "gob/gob.h"
#include "gob/inter.h"
diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp
index 85b213ae66..f5e87bb936 100644
--- a/engines/gob/inter_v5.cpp
+++ b/engines/gob/inter_v5.cpp
@@ -23,9 +23,6 @@
*
*/
-#include "common/endian.h"
-#include "common/file.h"
-
#include "gui/message.h"
#include "gob/gob.h"
diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp
index 06a06f4fb6..53ebfe7513 100644
--- a/engines/gob/inter_v6.cpp
+++ b/engines/gob/inter_v6.cpp
@@ -23,9 +23,7 @@
*
*/
-#include "common/endian.h"
#include "common/str.h"
-#include "common/file.h"
#include "graphics/dither.h"
#include "gob/gob.h"
diff --git a/engines/gob/resources.h b/engines/gob/resources.h
index 9921dc6e76..dec64f6b7c 100644
--- a/engines/gob/resources.h
+++ b/engines/gob/resources.h
@@ -29,7 +29,7 @@
#include "common/str.h"
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Gob {
diff --git a/engines/gob/save/savefile.cpp b/engines/gob/save/savefile.cpp
index d472ef600b..45cd2a2b7d 100644
--- a/engines/gob/save/savefile.cpp
+++ b/engines/gob/save/savefile.cpp
@@ -336,7 +336,7 @@ bool SavePartSprite::read(Common::ReadStream &stream) {
// If it's in the current format, the true color flag has to be the same too
if (!_oldFormat)
- if (stream.readByte() != _trueColor)
+ if ((stream.readByte() != 0) != _trueColor)
return false;
// Sprite data
diff --git a/engines/gob/save/savefile.h b/engines/gob/save/savefile.h
index eeee03847a..22eb79f4bf 100644
--- a/engines/gob/save/savefile.h
+++ b/engines/gob/save/savefile.h
@@ -48,8 +48,8 @@ class SaveHeader {
public:
/** The size of the header. */
static const int kSize = 20;
- static const uint32 kID1 = MKID_BE('\0SCV');
- static const uint32 kID2 = MKID_BE('MGOB');
+ static const uint32 kID1 = MKTAG(0,'S','C','V');
+ static const uint32 kID2 = MKTAG('M','G','O','B');
SaveHeader(uint32 type = 0, uint32 version = 0, uint32 size = 0);
@@ -106,7 +106,7 @@ protected:
class SavePartMem : public SavePart {
public:
static const uint32 kVersion = 1;
- static const uint32 kID = MKID_BE('PMEM');
+ static const uint32 kID = MKTAG('P','M','E','M');
SavePartMem(uint32 size);
~SavePartMem();
@@ -128,7 +128,7 @@ private:
class SavePartVars : public SavePart {
public:
static const uint32 kVersion = 1;
- static const uint32 kID = MKID_BE('VARS');
+ static const uint32 kID = MKTAG('V','A','R','S');
SavePartVars(GobEngine *vm, uint32 size);
~SavePartVars();
@@ -155,7 +155,7 @@ private:
class SavePartSprite : public SavePart {
public:
static const uint32 kVersion = 2;
- static const uint32 kID = MKID_BE('SPRT');
+ static const uint32 kID = MKTAG('S','P','R','T');
SavePartSprite(uint32 width, uint32 height, bool trueColor = false);
~SavePartSprite();
@@ -193,7 +193,7 @@ private:
class SavePartInfo : public SavePart {
public:
static const uint32 kVersion = 1;
- static const uint32 kID = MKID_BE('INFO');
+ static const uint32 kID = MKTAG('I','N','F','O');
/**
* The constructor.
@@ -235,7 +235,7 @@ private:
class SaveContainer {
public:
static const uint32 kVersion = 1;
- static const uint32 kID = MKID_BE('CONT');
+ static const uint32 kID = MKTAG('C','O','N','T');
/**
* The constructor.
diff --git a/engines/gob/save/saveload.cpp b/engines/gob/save/saveload.cpp
index 3508e58f16..e490509914 100644
--- a/engines/gob/save/saveload.cpp
+++ b/engines/gob/save/saveload.cpp
@@ -23,9 +23,6 @@
*
*/
-#include "common/endian.h"
-#include "common/savefile.h"
-
#include "gob/gob.h"
#include "gob/save/saveload.h"
#include "gob/global.h"
diff --git a/engines/gob/save/saveload.h b/engines/gob/save/saveload.h
index c231c1dbbb..dc1c184504 100644
--- a/engines/gob/save/saveload.h
+++ b/engines/gob/save/saveload.h
@@ -305,7 +305,7 @@ protected:
int getSlot(int32 offset) const;
int getSlotRemainder(int32 offset) const;
- void buildIndex(byte *buffer) const;
+ void buildScreenshotIndex(byte *buffer) const;
protected:
uint32 _shotSize;
@@ -430,7 +430,7 @@ protected:
int getSlot(int32 offset) const;
int getSlotRemainder(int32 offset) const;
- void buildIndex(byte *buffer) const;
+ void buildScreenshotIndex(byte *buffer) const;
};
File *_file;
diff --git a/engines/gob/save/saveload_inca2.cpp b/engines/gob/save/saveload_inca2.cpp
index 68c76c3f2b..5fa1b69fa7 100644
--- a/engines/gob/save/saveload_inca2.cpp
+++ b/engines/gob/save/saveload_inca2.cpp
@@ -260,7 +260,7 @@ int SaveLoad_Inca2::ScreenshotHandler::File::getSlotRemainder(int32 offset) cons
return (offset - 80) % 15168;
}
-void SaveLoad_Inca2::ScreenshotHandler::File::buildIndex(byte *buffer) const {
+void SaveLoad_Inca2::ScreenshotHandler::File::buildScreenshotIndex(byte *buffer) const {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
@@ -306,7 +306,7 @@ bool SaveLoad_Inca2::ScreenshotHandler::load(int16 dataVar, int32 size, int32 of
}
// Create/Fake the index
- _file->buildIndex(_index + 40);
+ _file->buildScreenshotIndex(_index + 40);
_vm->_inter->_variables->copyFrom(dataVar, _index + offset, size);
diff --git a/engines/gob/save/saveload_v3.cpp b/engines/gob/save/saveload_v3.cpp
index 098b8e1160..39edddb66f 100644
--- a/engines/gob/save/saveload_v3.cpp
+++ b/engines/gob/save/saveload_v3.cpp
@@ -367,7 +367,7 @@ int SaveLoad_v3::ScreenshotHandler::File::getSlotRemainder(int32 offset) const {
return ((offset - _shotIndexSize) % _shotSize);
}
-void SaveLoad_v3::ScreenshotHandler::File::buildIndex(byte *buffer) const {
+void SaveLoad_v3::ScreenshotHandler::File::buildScreenshotIndex(byte *buffer) const {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
@@ -418,12 +418,12 @@ bool SaveLoad_v3::ScreenshotHandler::load(int16 dataVar, int32 size, int32 offse
if (_sShotType == kScreenshotTypeGob3) {
// Create/Fake the index
- _file->buildIndex(_index + 40);
+ _file->buildScreenshotIndex(_index + 40);
// The last 10 bytes are 0
memset(_index + 70, 0, 10);
} else if (_sShotType == kScreenshotTypeLost) {
// Create/Fake the index
- _file->buildIndex(_index);
+ _file->buildScreenshotIndex(_index);
// The last byte is 0
_index[30] = 0;
}
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index f070bf14fa..4244df68e5 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -23,8 +23,10 @@
*
*/
+#include "common/debug.h"
#include "common/file.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "gob/gob.h"
#include "gob/sound/adlib.h"
diff --git a/engines/gob/sound/bgatmosphere.cpp b/engines/gob/sound/bgatmosphere.cpp
index f0977aa45b..b351d92275 100644
--- a/engines/gob/sound/bgatmosphere.cpp
+++ b/engines/gob/sound/bgatmosphere.cpp
@@ -23,8 +23,6 @@
*
*/
-#include "common/system.h"
-#include "common/events.h"
#include "common/EventRecorder.h"
#include "gob/sound/bgatmosphere.h"
@@ -47,7 +45,7 @@ BackgroundAtmosphere::~BackgroundAtmosphere() {
queueClear();
}
-void BackgroundAtmosphere::play() {
+void BackgroundAtmosphere::playBA() {
Common::StackLock slock(_mutex);
_queuePos = -1;
@@ -59,7 +57,7 @@ void BackgroundAtmosphere::play() {
SoundMixer::play(*_queue[_queuePos], 1, 0);
}
-void BackgroundAtmosphere::stop() {
+void BackgroundAtmosphere::stopBA() {
SoundMixer::stop(0);
}
diff --git a/engines/gob/sound/bgatmosphere.h b/engines/gob/sound/bgatmosphere.h
index 71a2263341..7e58c0b4e9 100644
--- a/engines/gob/sound/bgatmosphere.h
+++ b/engines/gob/sound/bgatmosphere.h
@@ -46,8 +46,8 @@ public:
BackgroundAtmosphere(Audio::Mixer &mixer);
~BackgroundAtmosphere();
- void play();
- void stop();
+ void playBA();
+ void stopBA();
void setPlayMode(PlayMode mode);
diff --git a/engines/gob/sound/cdrom.cpp b/engines/gob/sound/cdrom.cpp
index 4f3d783046..217aa9c18e 100644
--- a/engines/gob/sound/cdrom.cpp
+++ b/engines/gob/sound/cdrom.cpp
@@ -25,6 +25,7 @@
#include "common/endian.h"
#include "common/str.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "backends/audiocd/audiocd.h"
diff --git a/engines/gob/sound/infogrames.cpp b/engines/gob/sound/infogrames.cpp
index 6377b4e798..9fb7410740 100644
--- a/engines/gob/sound/infogrames.cpp
+++ b/engines/gob/sound/infogrames.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "gob/sound/infogrames.h"
namespace Gob {
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
index 5950388c28..1aa63eb940 100644
--- a/engines/gob/sound/sound.cpp
+++ b/engines/gob/sound/sound.cpp
@@ -648,7 +648,7 @@ void Sound::bgPlay(const char *file, SoundType type) {
debugC(1, kDebugSound, "BackgroundAtmosphere: Playing \"%s\"", file);
- _bgatmos->stop();
+ _bgatmos->stopBA();
_bgatmos->queueClear();
SoundDesc *sndDesc = new SoundDesc;
@@ -658,7 +658,7 @@ void Sound::bgPlay(const char *file, SoundType type) {
}
_bgatmos->queueSample(*sndDesc);
- _bgatmos->play();
+ _bgatmos->playBA();
}
void Sound::bgPlay(const char *base, const char *ext, SoundType type, int count) {
@@ -667,7 +667,7 @@ void Sound::bgPlay(const char *base, const char *ext, SoundType type, int count)
debugC(1, kDebugSound, "BackgroundAtmosphere: Playing \"%s\" (%d)", base, count);
- _bgatmos->stop();
+ _bgatmos->stopBA();
_bgatmos->queueClear();
int length = strlen(base) + 7;
@@ -684,7 +684,7 @@ void Sound::bgPlay(const char *base, const char *ext, SoundType type, int count)
delete sndDesc;
}
- _bgatmos->play();
+ _bgatmos->playBA();
}
void Sound::bgStop() {
@@ -693,7 +693,7 @@ void Sound::bgStop() {
debugC(1, kDebugSound, "BackgroundAtmosphere: Stopping playback");
- _bgatmos->stop();
+ _bgatmos->stopBA();
_bgatmos->queueClear();
}
diff --git a/engines/gob/sound/sounddesc.cpp b/engines/gob/sound/sounddesc.cpp
index d33ea89147..cc1c6b1f6b 100644
--- a/engines/gob/sound/sounddesc.cpp
+++ b/engines/gob/sound/sounddesc.cpp
@@ -25,6 +25,8 @@
#include "common/util.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
+
#include "audio/mixer.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/wave.h"
diff --git a/engines/gob/sound/soundmixer.cpp b/engines/gob/sound/soundmixer.cpp
index b6082c577c..3b6b2e5d52 100644
--- a/engines/gob/sound/soundmixer.cpp
+++ b/engines/gob/sound/soundmixer.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/util.h"
+
#include "gob/sound/soundmixer.h"
#include "gob/sound/sounddesc.h"
diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp
index 8d06ca8d63..7bd8aae597 100644
--- a/engines/gob/surface.cpp
+++ b/engines/gob/surface.cpp
@@ -31,6 +31,8 @@
#include "common/frac.h"
#include "graphics/primitives.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
namespace Gob {
@@ -420,25 +422,25 @@ void Surface::blit(const Surface &from, int16 left, int16 top, int16 right, int1
return;
if ((left == 0) && (_width == from._width) && (_width == width) && (transp == -1)) {
- // If these conditions are met, we can directly use memcpy
+ // If these conditions are met, we can directly use memmove
// Pointers to the blit destination and source start points
byte *dst = getData(x , y);
const byte *src = from.getData(left, top);
- memcpy(dst, src, width * height * _bpp);
+ memmove(dst, src, width * height * _bpp);
return;
}
if (transp == -1) {
- // We don't have to look for transparency => we can use memcpy line-wise
+ // We don't have to look for transparency => we can use memmove line-wise
// Pointers to the blit destination and source start points
byte *dst = getData(x , y);
const byte *src = from.getData(left, top);
while (height-- > 0) {
- memcpy(dst, src, width * _bpp);
+ memmove(dst, src, width * _bpp);
dst += _width * _bpp;
src += from._width * from._bpp;
@@ -521,7 +523,7 @@ void Surface::blitScaled(const Surface &from, int16 left, int16 top, int16 right
posW = 0;
for (uint16 i = 0; i < width; i++, dstRow += _bpp) {
- memcpy(dstRow, srcRow, _bpp);
+ memmove(dstRow, srcRow, _bpp);
posW += step;
while (posW >= ((frac_t) FRAC_ONE)) {
diff --git a/engines/gob/surface.h b/engines/gob/surface.h
index 3dea18e36e..b84927af70 100644
--- a/engines/gob/surface.h
+++ b/engines/gob/surface.h
@@ -34,7 +34,7 @@
#include "graphics/iff.h"
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Gob {
diff --git a/engines/gob/totfile.h b/engines/gob/totfile.h
index 211232f870..ce467425e2 100644
--- a/engines/gob/totfile.h
+++ b/engines/gob/totfile.h
@@ -29,7 +29,7 @@
#include "common/str.h"
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Gob {
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 4d51b3d61f..787f85175a 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -36,6 +36,8 @@
#include "common/events.h"
+#include "graphics/palette.h"
+
namespace Gob {
Util::Util(GobEngine *vm) : _vm(vm) {
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 444ff8ed9e..1d74a07bfc 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -29,6 +29,7 @@
#include "graphics/cursorman.h"
#include "graphics/fontman.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "gob/gob.h"
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index 8222c99ef3..de149c9787 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -720,7 +720,7 @@ bool VideoPlayer::copyFrame(int slot, Surface &dest,
if (!surface)
return false;
- Surface src(surface->w, surface->h, surface->bytesPerPixel, (byte *)surface->pixels);
+ Surface src(surface->w, surface->h, surface->format.bytesPerPixel, (byte *)surface->pixels);
dest.blit(src, left, top, left + width - 1, top + height - 1, x, y, transp);
return true;
diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp
index 6a87af8daf..8b62b829e1 100644
--- a/engines/groovie/cursor.cpp
+++ b/engines/groovie/cursor.cpp
@@ -26,8 +26,11 @@
#include "groovie/cursor.h"
#include "groovie/groovie.h"
+#include "common/debug.h"
#include "common/archive.h"
+#include "common/file.h"
#include "common/macresman.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
namespace Groovie {
@@ -404,7 +407,7 @@ GrvCursorMan_v2::GrvCursorMan_v2(OSystem *system) :
// Verify the signature
uint32 tmp32 = iconsFile.readUint32BE();
uint16 tmp16 = iconsFile.readUint16LE();
- if (tmp32 != MKID_BE('icon') || tmp16 != 1)
+ if (tmp32 != MKTAG('i','c','o','n') || tmp16 != 1)
error("Groovie::Cursor: icons.ph signature failed: %s %d", tag2str(tmp32), tmp16);
diff --git a/engines/groovie/cursor.h b/engines/groovie/cursor.h
index 7a1f3ccc0e..e40dc0c486 100644
--- a/engines/groovie/cursor.h
+++ b/engines/groovie/cursor.h
@@ -30,7 +30,7 @@
#include "common/system.h"
namespace Common {
- class MacResManager;
+class MacResManager;
}
namespace Groovie {
diff --git a/engines/groovie/debug.cpp b/engines/groovie/debug.cpp
index bd4b671e11..0b70e4f83a 100644
--- a/engines/groovie/debug.cpp
+++ b/engines/groovie/debug.cpp
@@ -31,6 +31,8 @@
#include "common/debug-channels.h"
#include "common/system.h"
+#include "graphics/palette.h"
+
namespace Groovie {
Debugger::Debugger(GroovieEngine *vm) :
diff --git a/engines/groovie/font.cpp b/engines/groovie/font.cpp
index 92ebcce298..13d0df0005 100644
--- a/engines/groovie/font.cpp
+++ b/engines/groovie/font.cpp
@@ -23,6 +23,10 @@
*
*/
+#include "common/array.h"
+#include "common/textconsole.h"
+#include "graphics/surface.h"
+
#include "groovie/font.h"
namespace Groovie {
diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp
index 3ceeeb6018..71ee231b80 100644
--- a/engines/groovie/graphics.cpp
+++ b/engines/groovie/graphics.cpp
@@ -25,15 +25,19 @@
#include "groovie/graphics.h"
#include "groovie/groovie.h"
+
+#include "common/rect.h"
#include "common/system.h"
+#include "graphics/palette.h"
+
namespace Groovie {
GraphicsMan::GraphicsMan(GroovieEngine *vm) :
_vm(vm), _changed(false), _fading(0) {
// Create the game surfaces
- _foreground.create(640, 320, _vm->_pixelFormat.bytesPerPixel);
- _background.create(640, 320, _vm->_pixelFormat.bytesPerPixel);
+ _foreground.create(640, 320, _vm->_pixelFormat);
+ _background.create(640, 320, _vm->_pixelFormat);
}
GraphicsMan::~GraphicsMan() {
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 4a4f5e0de5..795cd6feb9 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -35,7 +35,9 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
+#include "common/file.h"
#include "common/macresman.h"
+#include "common/textconsole.h"
#include "backends/audiocd/audiocd.h"
#include "engines/util.h"
@@ -322,6 +324,8 @@ void GroovieEngine::errorString(const char *buf_input, char *buf_output, int buf
}
void GroovieEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
bool mute = ConfMan.getBool("mute");
// Set the music volume
diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h
index f8fad8d91f..9335ffb7e4 100644
--- a/engines/groovie/groovie.h
+++ b/engines/groovie/groovie.h
@@ -33,7 +33,7 @@
#include "graphics/pixelformat.h"
namespace Common {
- class MacResManager;
+class MacResManager;
}
/**
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 011409155c..b7078f4c9e 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -29,8 +29,11 @@
#include "backends/audiocd/audiocd.h"
#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/file.h"
#include "common/macresman.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "audio/midiparser.h"
namespace Groovie {
@@ -247,25 +250,12 @@ MusicPlayerMidi::~MusicPlayerMidi() {
delete _midiParser;
// Unload the MIDI Driver
- if (_driver)
+ if (_driver) {
_driver->close();
- delete _driver;
-}
-
-int MusicPlayerMidi::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
-
- int ret = _driver->open();
- if (ret)
- return ret;
-
- return 0;
+ delete _driver;
+ }
}
-void MusicPlayerMidi::close() {}
-
void MusicPlayerMidi::send(uint32 b) {
if ((b & 0xFFF0) == 0x07B0) { // Volume change
// Save the specific channel volume
@@ -294,32 +284,6 @@ void MusicPlayerMidi::metaEvent(byte type, byte *data, uint16 length) {
}
}
-void MusicPlayerMidi::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
- if (_driver)
- _driver->setTimerCallback(timer_param, timer_proc);
-}
-
-uint32 MusicPlayerMidi::getBaseTempo() {
- if (_driver)
- return _driver->getBaseTempo();
- else
- return 0;
-}
-
-MidiChannel *MusicPlayerMidi::allocateChannel() {
- if (_driver)
- return _driver->allocateChannel();
- else
- return 0;
-}
-
-MidiChannel *MusicPlayerMidi::getPercussionChannel() {
- if (_driver)
- return _driver->getPercussionChannel();
- else
- return 0;
-}
-
void MusicPlayerMidi::updateChanVolume(byte channel) {
// Generate a MIDI Control change message for the volume
uint32 b = 0x7B0;
@@ -402,8 +366,10 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
// Create the driver
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _driver = createMidi(dev);
- this->open();
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
+
+ _driver->open(); // TODO: Handle return value != 0 (indicating an error)
// Set the parser's driver
_midiParser->setMidiDriver(this);
@@ -702,8 +668,10 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) {
// Create the driver
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _driver = createMidi(dev);
- this->open();
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
+
+ _driver->open(); // TODO: Handle return value != 0 (indicating an error)
// Set the parser's driver
_midiParser->setMidiDriver(this);
@@ -719,7 +687,7 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) {
debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref);
// First try for compressed MIDI
- Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKID_BE('cmid'), fileref & 0x3FF);
+ Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKTAG('c','m','i','d'), fileref & 0x3FF);
if (file) {
// Found the resource, decompress it
@@ -728,7 +696,7 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) {
file = tmp;
} else {
// Otherwise, it's uncompressed
- file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF);
+ file = _vm->_macResFork->getResource(MKTAG('M','i','d','i'), fileref & 0x3FF);
if (!file)
error("Groovie::Music: Couldn't find resource 0x%04X", fileref);
}
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index 74bb6f98e5..bde0a7a16f 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -88,20 +88,14 @@ protected:
virtual void unload();
};
-class MusicPlayerMidi : public MusicPlayer, public MidiDriver {
+class MusicPlayerMidi : public MusicPlayer, public MidiDriver_BASE {
public:
MusicPlayerMidi(GroovieEngine *vm);
~MusicPlayerMidi();
- // MidiDriver interface
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
- uint32 getBaseTempo();
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel();
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
private:
// Channel volumes
@@ -115,7 +109,7 @@ protected:
MidiParser *_midiParser;
MidiDriver *_driver;
- void onTimerInternal();
+ virtual void onTimerInternal();
void updateVolume();
void unload();
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index 8badd90012..3fee87d7bb 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "groovie/player.h"
#include "groovie/groovie.h"
diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp
index 5d4ccf7d91..7670ab4315 100644
--- a/engines/groovie/resource.cpp
+++ b/engines/groovie/resource.cpp
@@ -24,8 +24,11 @@
*/
#include "common/archive.h"
+#include "common/debug.h"
+#include "common/file.h"
#include "common/macresman.h"
#include "common/substream.h"
+#include "common/textconsole.h"
#include "groovie/resource.h"
#include "groovie/groovie.h"
@@ -92,7 +95,7 @@ ResMan_t7g::ResMan_t7g(Common::MacResManager *macResFork) : _macResFork(macResFo
}
}
-uint16 ResMan_t7g::getRef(Common::String name, Common::String scriptname) {
+uint32 ResMan_t7g::getRef(Common::String name, Common::String scriptname) {
// Get the name of the RL file
Common::String rlFileName(t7g_gjds[_lastGjd]);
rlFileName += ".rl";
@@ -110,7 +113,7 @@ uint16 ResMan_t7g::getRef(Common::String name, Common::String scriptname) {
if (!rlFile)
error("Groovie::Resource: Couldn't open %s", rlFileName.c_str());
- uint16 resNum;
+ uint32 resNum;
bool found = false;
for (resNum = 0; !found && !rlFile->err() && !rlFile->eos(); resNum++) {
// Read the resource name
@@ -134,7 +137,7 @@ uint16 ResMan_t7g::getRef(Common::String name, Common::String scriptname) {
// Verify we really found the resource
if (!found) {
error("Groovie::Resource: Couldn't find resource %s in %s", name.c_str(), rlFileName.c_str());
- return (uint16)-1;
+ return (uint32)-1;
}
return (_lastGjd << 10) | (resNum - 1);
@@ -217,8 +220,42 @@ ResMan_v2::ResMan_v2() {
indexfile.close();
}
-uint16 ResMan_v2::getRef(Common::String name, Common::String scriptname) {
- return 0;
+uint32 ResMan_v2::getRef(Common::String name, Common::String scriptname) {
+ // Open the RL file
+ Common::File rlFile;
+ if (!rlFile.open("dir.rl")) {
+ error("Groovie::Resource: Couldn't open dir.rl");
+ return false;
+ }
+
+ uint32 resNum;
+ bool found = false;
+ for (resNum = 0; !found && !rlFile.err() && !rlFile.eos(); resNum++) {
+ // Seek past metadata
+ rlFile.seek(14, SEEK_CUR);
+
+ // Read the resource name
+ char readname[18];
+ rlFile.read(readname, 18);
+
+ // 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 %12s matches %s", readname, name.c_str());
+ found = true;
+ }
+ }
+
+ // Close the RL file
+ rlFile.close();
+
+ // Verify we really found the resource
+ if (!found) {
+ error("Groovie::Resource: Couldn't find resource %s", name.c_str());
+ return (uint32)-1;
+ }
+
+ return resNum;
}
bool ResMan_v2::getResInfo(uint32 fileRef, ResInfo &resInfo) {
diff --git a/engines/groovie/resource.h b/engines/groovie/resource.h
index ca2ea177cb..9c306beecb 100644
--- a/engines/groovie/resource.h
+++ b/engines/groovie/resource.h
@@ -27,7 +27,7 @@
#define GROOVIE_RESOURCE_H
namespace Common {
- class MacResManager;
+class MacResManager;
}
namespace Groovie {
@@ -43,7 +43,7 @@ public:
virtual ~ResMan() {}
Common::SeekableReadStream *open(uint32 fileRef);
- virtual uint16 getRef(Common::String name, Common::String scriptname = "") = 0;
+ virtual uint32 getRef(Common::String name, Common::String scriptname = "") = 0;
protected:
Common::Array<Common::String> _gjds;
@@ -57,7 +57,7 @@ public:
ResMan_t7g(Common::MacResManager *macResFork = 0);
~ResMan_t7g() {}
- uint16 getRef(Common::String name, Common::String scriptname);
+ uint32 getRef(Common::String name, Common::String scriptname);
bool getResInfo(uint32 fileRef, ResInfo &resInfo);
private:
@@ -69,7 +69,7 @@ public:
ResMan_v2();
~ResMan_v2() {}
- uint16 getRef(Common::String name, Common::String scriptname);
+ uint32 getRef(Common::String name, Common::String scriptname);
bool getResInfo(uint32 fileRef, ResInfo &resInfo);
};
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 4d7157c797..be9c4f6921 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -30,7 +30,11 @@
#include "groovie/graphics.h"
#include "groovie/groovie.h"
+#include "common/debug.h"
+#include "common/textconsole.h"
+
#include "graphics/jpeg.h"
+#include "graphics/palette.h"
#ifdef USE_RGB_COLOR
// Required for the YUV to RGB conversion
@@ -175,7 +179,7 @@ void ROQPlayer::buildShowBuf() {
// Skip to the next pixel
out += _vm->_pixelFormat.bytesPerPixel;
if (!(x % _scaleX))
- in += _currBuf->bytesPerPixel;
+ in += _currBuf->format.bytesPerPixel;
}
#ifdef DITHER
_dither->nextLine();
@@ -328,8 +332,13 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
_prevBuf->free();
// Allocate new buffers
- _currBuf->create(width, height, 3);
- _prevBuf->create(width, height, 3);
+ // 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->getBasePtr(0, 0);
@@ -697,7 +706,7 @@ void ROQPlayer::copy(byte size, int destx, int desty, int offx, int offy) {
for (int i = 0; i < size; i++) {
// Copy the current line
- memcpy(dst, src, size * _currBuf->bytesPerPixel);
+ memcpy(dst, src, size * _currBuf->format.bytesPerPixel);
// Move to the beginning of the next line
dst += _currBuf->pitch;
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 4abfff74f2..fabb70cca0 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -37,8 +37,11 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/EventRecorder.h"
+#include "common/file.h"
#include "common/macresman.h"
+#include "gui/message.h"
+
#define NUM_OPCODES 90
namespace Groovie {
@@ -320,7 +323,7 @@ uint8 Script::readScriptChar(bool allow7C, bool limitVal, bool limitVar) {
return result;
}
-uint16 Script::getVideoRefString() {
+uint32 Script::getVideoRefString() {
Common::String str;
byte c;
@@ -411,6 +414,13 @@ void Script::savegame(uint slot) {
char newchar;
Common::OutSaveFile *file = SaveLoad::openForSaving(ConfMan.getActiveDomainName(), slot);
+ if (!file) {
+ debugC(9, kGroovieDebugScript, "Save file pointer is null");
+ GUI::MessageDialog dialog("Failed to save game", "OK");
+ dialog.runModal();
+ return;
+ }
+
// Saving the variables. It is endian safe because they're byte variables
file->write(_variables, 0x400);
delete file;
@@ -717,7 +727,7 @@ void Script::o_hotspot_center() {
debugScript(5, true, "HOTSPOT-CENTER @0x%04X", address);
- // Mark the centremost 240 pixels of the game area
+ // Mark the centermost 240 pixels of the game area
Common::Rect rect(200, 80, 440, 400);
hotspot(rect, address, 0);
}
@@ -1015,7 +1025,7 @@ void Script::o_add() {
void Script::o_videofromstring1() {
uint16 instStart = _currentInstruction;
- uint16 fileref = getVideoRefString();
+ uint32 fileref = getVideoRefString();
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
@@ -1031,7 +1041,7 @@ void Script::o_videofromstring1() {
void Script::o_videofromstring2() {
uint16 instStart = _currentInstruction;
- uint16 fileref = getVideoRefString();
+ uint32 fileref = getVideoRefString();
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index cda87a8917..b959810bb6 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -137,7 +137,7 @@ private:
uint16 readScript8or16bits();
uint8 readScriptChar(bool allow7C, bool limitVal, bool limitVar);
uint8 readScriptVar();
- uint16 getVideoRefString();
+ uint32 getVideoRefString();
bool hotspot(Common::Rect rect, uint16 addr, uint8 cursor);
diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp
index 1b4a2b7800..432b17802c 100644
--- a/engines/groovie/vdx.cpp
+++ b/engines/groovie/vdx.cpp
@@ -28,9 +28,12 @@
#include "groovie/groovie.h"
#include "groovie/lzss.h"
+#include "common/debug.h"
#include "common/debug-channels.h"
+#include "common/textconsole.h"
#include "audio/mixer.h"
#include "audio/decoders/raw.h"
+#include "graphics/palette.h"
#define TILE_SIZE 4 // Size of each tile on the image: only ever seen 4 so far
#define VDX_IDENT 0x9267 // 37479
@@ -70,7 +73,7 @@ uint16 VDXPlayer::loadInternal() {
}
// Flags:
// - 1 Puzzle piece? Skip palette, don't redraw full screen, draw still to b/ack buffer
- // - 2 Transparent colour is 0xFF
+ // - 2 Transparent color is 0xFF
// - 5 Skip still chunks
// - 7
// - 8 Just show the first frame
@@ -251,26 +254,26 @@ void VDXPlayer::getDelta(Common::ReadStream *in) {
uint16 currentLine = 0;
uint32 offset = 0;
while (!in->eos()) {
- byte colours[16];
+ byte colors[16];
if (currOpCode < 0x60) {
param1 = in->readByte();
param2 = in->readByte();
- expandColourMap(colours, vdxBlockMapLookup[currOpCode], param1, param2);
- decodeBlockDelta(offset, colours, 640);
+ expandColorMap(colors, vdxBlockMapLookup[currOpCode], param1, param2);
+ decodeBlockDelta(offset, colors, 640);
offset += TILE_SIZE;
} else if (currOpCode > 0x7f) {
param1 = in->readByte();
param2 = in->readByte();
param3 = in->readByte();
- expandColourMap(colours, (param1 << 8) + currOpCode, param2, param3);
- decodeBlockDelta(offset, colours, 640);
+ expandColorMap(colors, (param1 << 8) + currOpCode, param2, param3);
+ decodeBlockDelta(offset, colors, 640);
offset += TILE_SIZE;
} else switch (currOpCode) {
- case 0x60: /* Fill tile with the 16 colours given as parameters */
+ case 0x60: /* Fill tile with the 16 colors given as parameters */
for (l = 0; l < 16; l++) {
- colours[l] = in->readByte();
+ colors[l] = in->readByte();
}
- decodeBlockDelta(offset, colours, 640);
+ decodeBlockDelta(offset, colors, 640);
offset += TILE_SIZE;
break;
case 0x61: /* Skip to the end of this line, next block is start of next */
@@ -299,14 +302,14 @@ void VDXPlayer::getDelta(Common::ReadStream *in) {
case 0x72:
case 0x73:
case 0x74:
- case 0x75: /* Next param1 blocks are filled with colour param2 */
+ case 0x75: /* Next param1 blocks are filled with color param2 */
param1 = currOpCode - 0x6b;
param2 = in->readByte();
for (l = 0; l < 16; l++) {
- colours[l] = param2;
+ colors[l] = param2;
}
for (k = 0; k < param1; k++) {
- decodeBlockDelta(offset, colours, 640);
+ decodeBlockDelta(offset, colors, 640);
offset += TILE_SIZE;
}
break;
@@ -319,14 +322,14 @@ void VDXPlayer::getDelta(Common::ReadStream *in) {
case 0x7c:
case 0x7d:
case 0x7e:
- case 0x7f: /* Next bytes contain colours to fill the next param1 blocks in the current line*/
+ case 0x7f: /* Next bytes contain colors to fill the next param1 blocks in the current line*/
param1 = currOpCode - 0x75;
for (k = 0; k < param1; k++) {
param2 = in->readByte();
for (l = 0; l < 16; l++) {
- colours[l] = param2;
+ colors[l] = param2;
}
- decodeBlockDelta(offset, colours, 640);
+ decodeBlockDelta(offset, colors, 640);
offset += TILE_SIZE;
}
break;
@@ -344,8 +347,8 @@ void VDXPlayer::getStill(Common::ReadStream *in) {
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: numYTiles=%d", numYTiles);
// It's skipped in the original:
- uint16 colourDepth = in->readUint16LE();
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: colourDepth=%d", colourDepth);
+ uint16 colorDepth = in->readUint16LE();
+ debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: colorDepth=%d", colorDepth);
uint16 imageWidth = TILE_SIZE * numXTiles;
@@ -378,15 +381,15 @@ void VDXPlayer::getStill(Common::ReadStream *in) {
// Skip the frame when flag 5 is set, unless flag 1 is set
if (!_flagFive || _flagOne) {
- byte colours[16];
+ byte colors[16];
for (uint16 j = 0; j < numYTiles; j++) {
byte *currentTile = buf + j * TILE_SIZE * imageWidth;
for (uint16 i = numXTiles; i; i--) {
- uint8 colour1 = in->readByte();
- uint8 colour0 = in->readByte();
- uint16 colourMap = in->readUint16LE();
- expandColourMap(colours, colourMap, colour1, colour0);
- decodeBlockStill(currentTile, colours, 640, mask);
+ uint8 color1 = in->readByte();
+ uint8 color0 = in->readByte();
+ uint16 colorMap = in->readUint16LE();
+ expandColorMap(colors, colorMap, color1, color0);
+ decodeBlockStill(currentTile, colors, 640, mask);
currentTile += TILE_SIZE;
}
@@ -425,22 +428,22 @@ void VDXPlayer::getStill(Common::ReadStream *in) {
}
}
-void VDXPlayer::expandColourMap(byte *out, uint16 colourMap, uint8 colour1, uint8 colour0) {
+void VDXPlayer::expandColorMap(byte *out, uint16 colorMap, uint8 color1, uint8 color0) {
// It's a bit faster to start from the end
out += 16;
for (int i = 16; i; i--) {
- // Set the corresponding colour
+ // Set the corresponding color
// The following is an optimized version of:
- // *--out = (colourMap & 1) ? colour1 : colour0;
- uint8 selector = -(colourMap & 1);
- *--out = (selector & colour1) | (~selector & colour0);
+ // *--out = (colorMap & 1) ? color1 : color0;
+ uint8 selector = -(colorMap & 1);
+ *--out = (selector & color1) | (~selector & color0);
- // Update the flag map to test the next colour
- colourMap >>= 1;
+ // Update the flag map to test the next color
+ colorMap >>= 1;
}
}
-void VDXPlayer::decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, uint8 mask) {
+void VDXPlayer::decodeBlockStill(byte *buf, byte *colors, uint16 imageWidth, uint8 mask) {
assert(TILE_SIZE == 4);
for (int y = TILE_SIZE; y; y--) {
@@ -448,15 +451,15 @@ void VDXPlayer::decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, ui
// TODO: optimize with bit logic?
for (int x = 0; x < TILE_SIZE; x++) {
// 0xff pixels don't modify the buffer
- if (*colours != 0xff) {
- // Write the colour
- *buf = *colours | mask;
+ if (*colors != 0xff) {
+ // Write the color
+ *buf = *colors | mask;
// Note: if the mask is 0, it paints the image
// else, it paints the image's mask using 0xff
}
- // Point to the next colour
- colours++;
+ // Point to the next color
+ colors++;
// Point to the next pixel
buf++;
@@ -465,8 +468,8 @@ void VDXPlayer::decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, ui
// Point to the start of the next line
buf += imageWidth - TILE_SIZE;
} else {
- *((uint32 *)buf) = *((uint32 *)colours);
- colours += 4;
+ *((uint32 *)buf) = *((uint32 *)colors);
+ colors += 4;
// Point to the start of the next line
buf += imageWidth;
@@ -474,7 +477,7 @@ void VDXPlayer::decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, ui
}
}
-void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colours, uint16 imageWidth) {
+void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colors, uint16 imageWidth) {
assert(TILE_SIZE == 4);
byte *dest;
@@ -501,19 +504,19 @@ void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colours, uint16 imageWidth
for (int x = 0; x < TILE_SIZE; x++) {
// TODO: this can probably be optimized with bit logic
if (fgBuf[x] != 0xff) {
- if (*colours == 0xff) {
+ if (*colors == 0xff) {
dest[x] = fgBuf[x];
} else {
- dest[x] = *colours;
+ dest[x] = *colors;
}
}
- colours++;
+ colors++;
}
fgBuf += imageWidth;
} else {
// Paint directly
- *((uint32 *)dest) = *((uint32 *)colours);
- colours += 4;
+ *((uint32 *)dest) = *((uint32 *)colors);
+ colors += 4;
}
// Move to the next line
diff --git a/engines/groovie/vdx.h b/engines/groovie/vdx.h
index 0b29493108..31c7606cb7 100644
--- a/engines/groovie/vdx.h
+++ b/engines/groovie/vdx.h
@@ -29,7 +29,7 @@
#include "groovie/player.h"
namespace Common {
- class ReadStream;
+class ReadStream;
}
namespace Groovie {
@@ -73,9 +73,9 @@ private:
void getStill(Common::ReadStream *in);
void getDelta(Common::ReadStream *in);
- void expandColourMap(byte *out, uint16 colourMap, uint8 colour1, uint8 colour0);
- void decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, uint8 mask);
- void decodeBlockDelta(uint32 offset, byte *colours, uint16 imageWidth);
+ void expandColorMap(byte *out, uint16 colorMap, uint8 color1, uint8 color0);
+ void decodeBlockStill(byte *buf, byte *colors, uint16 imageWidth, uint8 mask);
+ void decodeBlockDelta(uint32 offset, byte *colors, uint16 imageWidth);
void chunkSound(Common::ReadStream *in);
void setPalette(uint8 *palette);
void fadeIn(uint8 *palette);
diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp
index c99db2433f..95302c9235 100644
--- a/engines/hugo/detection.cpp
+++ b/engines/hugo/detection.cpp
@@ -26,6 +26,7 @@
#include "engines/advancedDetector.h"
#include "common/system.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "graphics/thumbnail.h"
#include "graphics/surface.h"
@@ -292,6 +293,11 @@ SaveStateDescriptor HugoMetaEngine::querySaveMetaInfos(const char *target, int s
desc.setSaveTime(hour, minutes);
+ // Slot 0 is used for the 'restart game' save in all Hugo games, thus
+ // we prevent it from being deleted.
+ desc.setDeletableFlag(slot != 0);
+ desc.setWriteProtectedFlag(slot == 0);
+
delete file;
return desc;
}
diff --git a/engines/hugo/menu.cpp b/engines/hugo/dialogs.cpp
index 428a3e096a..f0dc84eae8 100644
--- a/engines/hugo/menu.cpp
+++ b/engines/hugo/dialogs.cpp
@@ -26,6 +26,7 @@
#include "common/substream.h"
#include "graphics/imagedec.h"
#include "gui/gui-manager.h"
+#include "gui/ThemeEval.h"
#include "hugo/hugo.h"
#include "hugo/display.h"
@@ -132,7 +133,7 @@ void TopMenu::loadBmpArr(Common::SeekableReadStream &in) {
Common::SeekableSubReadStream stream(&in, filPos, filPos + bmpSize);
arrayBmp[i * 2] = Graphics::ImageDecoder::loadFile(stream, g_system->getOverlayFormat());
arrayBmp[i * 2 + 1] = new Graphics::Surface();
- arrayBmp[i * 2 + 1]->create(arrayBmp[i * 2]->w * 2, arrayBmp[i * 2]->h * 2, arrayBmp[i * 2]->bytesPerPixel);
+ arrayBmp[i * 2 + 1]->create(arrayBmp[i * 2]->w * 2, arrayBmp[i * 2]->h * 2, g_system->getOverlayFormat());
byte *src = (byte *)arrayBmp[i * 2]->pixels;
byte *dst = (byte *)arrayBmp[i * 2 + 1]->pixels;
@@ -140,12 +141,12 @@ void TopMenu::loadBmpArr(Common::SeekableReadStream &in) {
src = (byte *)arrayBmp[i * 2]->getBasePtr(0, j);
dst = (byte *)arrayBmp[i * 2 + 1]->getBasePtr(0, j * 2);
for (int k = arrayBmp[i * 2]->w; k > 0; k--) {
- for (int m = arrayBmp[i * 2]->bytesPerPixel; m > 0; m--) {
+ for (int m = arrayBmp[i * 2]->format.bytesPerPixel; m > 0; m--) {
*dst++ = *src++;
}
- src -= arrayBmp[i * 2]->bytesPerPixel;
+ src -= arrayBmp[i * 2]->format.bytesPerPixel;
- for (int m = arrayBmp[i * 2]->bytesPerPixel; m > 0; m--) {
+ for (int m = arrayBmp[i * 2]->format.bytesPerPixel; m > 0; m--) {
*dst++ = *src++;
}
}
@@ -164,7 +165,8 @@ void TopMenu::handleCommand(GUI::CommandSender *sender, uint32 command, uint32 d
switch (command) {
case kCmdWhat:
close();
- _vm->_file->instructions();
+ _vm->getGameStatus().helpFl = true;
+
break;
case kCmdMusic:
_vm->_sound->toggleMusic();
@@ -196,8 +198,6 @@ void TopMenu::handleCommand(GUI::CommandSender *sender, uint32 command, uint32 d
case kCmdLoad:
close();
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- _vm->getGameStatus().viewState = kViewPlay;
break;
case kCmdRecall:
close();
@@ -232,4 +232,67 @@ void TopMenu::handleMouseUp(int x, int y, int button, int clickCount) {
Dialog::handleMouseUp(x, y, button, clickCount);
}
+EntryDialog::EntryDialog(const Common::String &title, const Common::String &buttonLabel, const Common::String &defaultValue) : GUI::Dialog(20, 20, 100, 50) {
+ const int screenW = g_system->getOverlayWidth();
+ const int screenH = g_system->getOverlayHeight();
+
+ int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0);
+ int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0);
+
+ // First, determine the size the dialog needs. For this we have to break
+ // down the string into lines, and taking the maximum of their widths.
+ // Using this, and accounting for the space the button(s) need, we can set
+ // the real size of the dialog
+ Common::Array<Common::String> lines;
+ int lineCount, buttonPos;
+ int maxlineWidth = g_gui.getFont().wordWrapText(title, screenW - 2 * 30, lines);
+
+ // Calculate the desired dialog size (maxing out at 300*180 for now)
+ _w = MAX(maxlineWidth, buttonWidth) + 20;
+
+ lineCount = lines.size();
+
+ _h = 16 + buttonHeight + 8;
+
+ // Limit the number of lines so that the dialog still fits on the screen.
+ if (lineCount > (screenH - 20 - _h) / kLineHeight) {
+ lineCount = (screenH - 20 - _h) / kLineHeight;
+ }
+ _h += lineCount * kLineHeight;
+
+ // Center the dialog
+ _x = (screenW - _w) / 2;
+ _y = (screenH - _h) / 2;
+
+ // Each line is represented by one static text item.
+ for (int i = 0; i < lineCount; i++) {
+ new GUI::StaticTextWidget(this, 10, 10 + i * kLineHeight, maxlineWidth, kLineHeight,
+ lines[i], Graphics::kTextAlignCenter);
+ }
+
+ _text = new GUI::EditTextWidget(this, 10, 10 + lineCount * (kLineHeight + 1), _w - 20, kLineHeight, "", "", 0, kCmdFinishEdit);
+ _text->setEditString(defaultValue);
+
+ _h += kLineHeight + 5;
+
+ buttonPos = (_w - buttonWidth) / 2;
+
+ new GUI::ButtonWidget(this, buttonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, buttonLabel, 0, kCmdButton, Common::ASCII_RETURN); // Confirm dialog
+
+}
+
+EntryDialog::~EntryDialog() {
+}
+
+void EntryDialog::handleCommand(GUI::CommandSender *sender, uint32 command, uint32 data) {
+ switch (command) {
+ case kCmdButton:
+ case kCmdFinishEdit:
+ close();
+ break;
+ default:
+ Dialog::handleCommand(sender, command, data);
+ }
+}
+
} // End of namespace Hugo
diff --git a/engines/hugo/menu.h b/engines/hugo/dialogs.h
index 6e2a9063bc..56dbd41f81 100644
--- a/engines/hugo/menu.h
+++ b/engines/hugo/dialogs.h
@@ -23,10 +23,11 @@
*
*/
-#ifndef HUGO_TOPMENU_H
-#define HUGO_TOPMENU_H
+#ifndef HUGO_DIALOGS_H
+#define HUGO_DIALOGS_H
#include "gui/dialog.h"
+#include "gui/widgets/edittext.h"
namespace Hugo {
@@ -54,6 +55,7 @@ enum {
};
enum {
+ // TopMenu commands
kCmdWhat = 'WHAT',
kCmdMusic = 'MUZK',
kCmdSoundFX = 'SOUN',
@@ -62,7 +64,11 @@ enum {
kCmdRecall = 'RECL',
kCmdTurbo = 'TURB',
kCmdLook = 'LOOK',
- kCmdInvent = 'INVT'
+ kCmdInvent = 'INVT',
+
+ // EntryDialog commands
+ kCmdButton = 'BTNP',
+ kCmdFinishEdit = 'FNSH'
};
class TopMenu : public GUI::Dialog {
@@ -95,6 +101,19 @@ protected:
uint16 arraySize;
};
+class EntryDialog : public GUI::Dialog {
+public:
+ EntryDialog(const Common::String &title, const Common::String &buttonLabel, const Common::String &defaultValue);
+ virtual ~EntryDialog();
+
+ void handleCommand(GUI::CommandSender *sender, uint32 command, uint32 data);
+
+ const Common::String &getEditString() const { return _text->getEditString(); }
+
+protected:
+ GUI::EditTextWidget *_text;
+};
+
}
-#endif // HUGO_TOPMENU_H
+#endif // HUGO_DIALOGS_H
diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp
index 0210eb8f04..af4d094ceb 100644
--- a/engines/hugo/display.cpp
+++ b/engines/hugo/display.cpp
@@ -32,8 +32,11 @@
// Display.c - DIB related code for HUGOWIN
+#include "common/debug.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
#include "hugo/hugo.h"
#include "hugo/display.h"
@@ -189,13 +192,13 @@ void Screen::displayRect(const int16 x, const int16 y, const int16 dx, const int
* Alse save the new color in the current palette.
*/
void Screen::remapPal(const uint16 oldIndex, const uint16 newIndex) {
- debugC(1, kDebugDisplay, "Remap_pal(%d, %d)", oldIndex, newIndex);
+ debugC(1, kDebugDisplay, "RemapPal(%d, %d)", oldIndex, newIndex);
_curPalette[3 * oldIndex + 0] = _mainPalette[newIndex * 3 + 0];
_curPalette[3 * oldIndex + 1] = _mainPalette[newIndex * 3 + 1];
_curPalette[3 * oldIndex + 2] = _mainPalette[newIndex * 3 + 2];
- g_system->getPaletteManager()->setPalette(_curPalette, oldIndex, 1);
+ g_system->getPaletteManager()->setPalette(_curPalette, 0, _paletteSize / 3);
}
/**
@@ -214,10 +217,10 @@ void Screen::savePal(Common::WriteStream *f) const {
void Screen::restorePal(Common::ReadStream *f) {
debugC(1, kDebugDisplay, "restorePal()");
- for (int i = 0; i < _paletteSize; i++) {
+ for (int i = 0; i < _paletteSize; i++)
_curPalette[i] = f->readByte();
- g_system->getPaletteManager()->setPalette(_curPalette, i, 1);
- }
+
+ g_system->getPaletteManager()->setPalette(_curPalette, 0, _paletteSize / 3);
}
@@ -233,24 +236,6 @@ void Screen::setBackgroundColor(const uint16 color) {
}
/**
- * Return the overlay state (Foreground/Background) of the currently
- * processed object by looking down the current column for an overlay
- * base bit set (in which case the object is foreground).
- */
-overlayState_t Screen::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) {
- debugC(4, kDebugDisplay, "findOvl()");
-
- for (; y < seq_p->lines; y++) { // Each line in object
- byte ovb = _vm->_object->getBaseBoundary((uint16)(dst_p - _frontBuffer) >> 3); // Ptr into overlay bits
- if (ovb & (0x80 >> ((uint16)(dst_p - _frontBuffer) & 7))) // Overlay bit is set
- return kOvlForeground; // Found a bit - must be foreground
- dst_p += kXPix;
- }
-
- return kOvlBackground; // No bits set, must be background
-}
-
-/**
* Merge an object frame into _frontBuffer at sx, sy and update rectangle list.
* If fore TRUE, force object above any overlay
*/
@@ -261,7 +246,7 @@ void Screen::displayFrame(const int sx, const int sy, seq_t *seq, const bool for
image_pt subFrontBuffer = &_frontBuffer[sy * kXPix + sx]; // Ptr to offset in _frontBuffer
int16 frontBufferwrap = kXPix - seq->x2 - 1; // Wraps dest_p after each line
int16 imageWrap = seq->bytesPerLine8 - seq->x2 - 1;
- overlayState_t overlayState = kOvlUndef; // Overlay state of object
+ overlayState_t overlayState = (foreFl) ? kOvlForeground : kOvlUndef; // Overlay state of object
for (uint16 y = 0; y < seq->lines; y++) { // Each line in object
for (uint16 x = 0; x <= seq->x2; x++) {
if (*image) { // Non-transparent
@@ -269,7 +254,7 @@ void Screen::displayFrame(const int sx, const int sy, seq_t *seq, const bool for
if (ovlBound & (0x80 >> ((uint16)(subFrontBuffer - _frontBuffer) & 7))) { // Overlay bit is set
if (overlayState == kOvlUndef) // Overlay defined yet?
overlayState = findOvl(seq, subFrontBuffer, y);// No, find it.
- if (foreFl || overlayState == kOvlForeground) // Object foreground
+ if (overlayState == kOvlForeground) // Object foreground
*subFrontBuffer = *image; // Copy pixel
} else { // No overlay
*subFrontBuffer = *image; // Copy pixel
@@ -497,7 +482,7 @@ void Screen::shadowStr(int16 sx, const int16 sy, const char *s, const byte color
* present in the DOS versions
*/
void Screen::userHelp() const {
- Utils::Box(kBoxAny , "%s",
+ Utils::notifyBox(
"F1 - Press F1 again\n"
" for instructions\n"
"F2 - Sound on/off\n"
@@ -525,6 +510,9 @@ void Screen::drawStatusText() {
sdx = stringLength(_vm->_scoreLine);
posY = 0;
+
+ //Display a black behind the score line
+ _vm->_screen->drawRectangle(true, 0, 0, kXPix, 8, _TBLACK);
writeStr(posX, posY, _vm->_scoreLine, _TCYAN);
displayList(kDisplayAdd, posX, posY, sdx, sdy);
}
@@ -740,6 +728,25 @@ void Screen_v1d::loadFontArr(Common::ReadStream &in) {
}
}
+/**
+ * Return the overlay state (Foreground/Background) of the currently
+ * processed object by looking down the current column for an overlay
+ * base byte set (in which case the object is foreground).
+ */
+overlayState_t Screen_v1d::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) {
+ debugC(4, kDebugDisplay, "findOvl()");
+
+ uint16 index = (uint16)(dst_p - _frontBuffer) >> 3;
+
+ for (int i = 0; i < seq_p->lines-y; i++) { // Each line in object
+ if (_vm->_object->getBaseBoundary(index)) // If any overlay base byte is non-zero then the object is foreground, else back.
+ return kOvlForeground;
+ index += kCompLineSize;
+ }
+
+ return kOvlBackground; // No bits set, must be background
+}
+
Screen_v1w::Screen_v1w(HugoEngine *vm) : Screen(vm) {
}
@@ -790,5 +797,23 @@ void Screen_v1w::loadFontArr(Common::ReadStream &in) {
}
}
+/**
+ * Return the overlay state (Foreground/Background) of the currently
+ * processed object by looking down the current column for an overlay
+ * base bit set (in which case the object is foreground).
+ */
+overlayState_t Screen_v1w::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) {
+ debugC(4, kDebugDisplay, "findOvl()");
+
+ for (; y < seq_p->lines; y++) { // Each line in object
+ byte ovb = _vm->_object->getBaseBoundary((uint16)(dst_p - _frontBuffer) >> 3); // Ptr into overlay bits
+ if (ovb & (0x80 >> ((uint16)(dst_p - _frontBuffer) & 7))) // Overlay bit is set
+ return kOvlForeground; // Found a bit - must be foreground
+ dst_p += kXPix;
+ }
+
+ return kOvlBackground; // No bits set, must be background
+}
+
} // End of namespace Hugo
diff --git a/engines/hugo/display.h b/engines/hugo/display.h
index f234f76019..91e1752df0 100644
--- a/engines/hugo/display.h
+++ b/engines/hugo/display.h
@@ -101,10 +101,6 @@ protected:
static const byte stdMouseCursorHeight = 20;
static const byte stdMouseCursorWidth = 12;
- inline bool isInX(const int16 x, const rect_t *rect) const;
- inline bool isInY(const int16 y, const rect_t *rect) const;
- inline bool isOverlapping(const rect_t *rectA, const rect_t *rectB) const;
-
bool fontLoadedFl[kNumFonts];
// Fonts used in dib (non-GDI)
@@ -115,6 +111,14 @@ protected:
byte *_mainPalette;
int16 _arrayFontSize[kNumFonts];
+ viewdib_t _frontBuffer;
+
+ inline bool isInX(const int16 x, const rect_t *rect) const;
+ inline bool isInY(const int16 y, const rect_t *rect) const;
+ inline bool isOverlapping(const rect_t *rectA, const rect_t *rectB) const;
+
+ virtual overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) = 0;
+
private:
byte *_curPalette;
byte _iconImage[kInvDx * kInvDy];
@@ -125,9 +129,6 @@ private:
int16 mergeLists(rect_t *list, rect_t *blist, const int16 len, int16 blen);
int16 center(const char *s) const;
- overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y);
-
- viewdib_t _frontBuffer;
viewdib_t _backBuffer;
viewdib_t _GUIBuffer; // User interface images
viewdib_t _backBufferBackup; // Backup _backBuffer during inventory
@@ -151,6 +152,8 @@ public:
void loadFont(int16 fontId);
void loadFontArr(Common::ReadStream &in);
+protected:
+ overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y);
};
class Screen_v1w : public Screen {
@@ -160,6 +163,8 @@ public:
void loadFont(int16 fontId);
void loadFontArr(Common::ReadStream &in);
+protected:
+ overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y);
};
} // End of namespace Hugo
diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp
index 740513d7b2..ba4e420111 100644
--- a/engines/hugo/file.cpp
+++ b/engines/hugo/file.cpp
@@ -30,8 +30,10 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "common/config-manager.h"
#include "graphics/thumbnail.h"
#include "gui/saveload.h"
@@ -46,6 +48,13 @@
#include "hugo/mouse.h"
namespace Hugo {
+
+namespace {
+static const char s_bootCypher[] = "Copyright 1992, David P Gray, Gray Design Associates";
+static const int s_bootCypherLen = sizeof(s_bootCypher) - 1;
+}
+
+
FileManager::FileManager(HugoEngine *vm) : _vm(vm) {
has_read_header = false;
firstUIFFl = true;
@@ -291,7 +300,11 @@ sound_pt FileManager::getSound(const int16 sound, uint16 *size) {
}
if (!has_read_header) {
- if (fp.read(s_hdr, sizeof(s_hdr)) != sizeof(s_hdr))
+ for (int i = 0; i < kMaxSounds; i++) {
+ s_hdr[i].size = fp.readUint16LE();
+ s_hdr[i].offset = fp.readUint32LE();
+ }
+ if (fp.err())
error("Wrong sound file format");
has_read_header = true;
}
@@ -393,7 +406,7 @@ bool FileManager::saveGame(const int16 slot, const Common::String &descrip) {
out->writeByte((gameStatus.gameOverFl) ? 1 : 0);
// Save screen states
- for (int i = 0; i < _vm->_numScreens; i++)
+ for (int i = 0; i < _vm->_numStates; i++)
out->writeByte(_vm->_screenStates[i]);
_vm->_scheduler->saveSchedulerData(out);
@@ -411,6 +424,8 @@ bool FileManager::saveGame(const int16 slot, const Common::String &descrip) {
out->writeSint16BE(_vm->_maze.x4);
out->writeByte(_vm->_maze.firstScreenIndex);
+ out->writeByte((byte)_vm->getGameStatus().viewState);
+
out->finalize();
delete out;
@@ -488,7 +503,7 @@ bool FileManager::restoreGame(const int16 slot) {
gameStatus.storyModeFl = (in->readByte() == 1);
_vm->_mouse->setJumpExitFl(in->readByte() == 1);
gameStatus.gameOverFl = (in->readByte() == 1);
- for (int i = 0; i < _vm->_numScreens; i++)
+ for (int i = 0; i < _vm->_numStates; i++)
_vm->_screenStates[i] = in->readByte();
_vm->_scheduler->restoreSchedulerData(in);
@@ -507,6 +522,11 @@ bool FileManager::restoreGame(const int16 slot) {
_vm->_maze.x4 = in->readSint16BE();
_vm->_maze.firstScreenIndex = in->readByte();
+ _vm->_scheduler->restoreScreen(*_vm->_screen_p);
+ if ((_vm->getGameStatus().viewState = (vstate_t) in->readByte()) != kViewPlay)
+ _vm->_screen->hideCursor();
+
+
delete in;
return true;
}
@@ -516,16 +536,17 @@ bool FileManager::restoreGame(const int16 slot) {
*/
void FileManager::printBootText() {
debugC(1, kDebugFile, "printBootText()");
- static const char *cypher = getBootCypher();
Common::File ofp;
if (!ofp.open(getBootFilename())) {
- if (_vm->_gameVariant == kGameVariantH1Dos) {
+ if (_vm->getPlatform() == Common::kPlatformPC) {
//TODO initialize properly _boot structure
- warning("printBootText - Skipping as H1 Dos may be a freeware");
+ warning("printBootText - Skipping as Dos versions may be a freeware or shareware");
return;
} else {
- error("Missing startup file");
+ Utils::notifyBox(Common::String::format("Missing startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ return;
}
}
@@ -534,16 +555,19 @@ void FileManager::printBootText() {
if (buf) {
// Skip over the boot structure (already read) and read exit text
ofp.seek((long)sizeof(_vm->_boot), SEEK_SET);
- if (ofp.read(buf, _vm->_boot.exit_len) != (size_t)_vm->_boot.exit_len)
- error("Error while reading startup file");
+ if (ofp.read(buf, _vm->_boot.exit_len) != (size_t)_vm->_boot.exit_len) {
+ Utils::notifyBox(Common::String::format("Error while reading startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ return;
+ }
// Decrypt the exit text, using CRYPT substring
int i;
for (i = 0; i < _vm->_boot.exit_len; i++)
- buf[i] ^= cypher[i % strlen(cypher)];
+ buf[i] ^= s_bootCypher[i % s_bootCypherLen];
buf[i] = '\0';
- Utils::Box(kBoxOk, "%s", buf);
+ Utils::notifyBox(buf);
}
free(buf);
@@ -556,21 +580,32 @@ void FileManager::printBootText() {
*/
void FileManager::readBootFile() {
debugC(1, kDebugFile, "readBootFile()");
- static const char *cypher = getBootCypher();
Common::File ofp;
if (!ofp.open(getBootFilename())) {
if (_vm->_gameVariant == kGameVariantH1Dos) {
//TODO initialize properly _boot structure
warning("readBootFile - Skipping as H1 Dos may be a freeware");
+ memset(_vm->_boot.distrib, '\0', sizeof(_vm->_boot.distrib));
+ _vm->_boot.registered = kRegFreeware;
+ return;
+ } else if (_vm->getPlatform() == Common::kPlatformPC) {
+ warning("readBootFile - Skipping as H2 and H3 Dos may be shareware");
+ memset(_vm->_boot.distrib, '\0', sizeof(_vm->_boot.distrib));
+ _vm->_boot.registered = kRegShareware;
return;
} else {
- error("Missing startup file");
+ Utils::notifyBox(Common::String::format("Missing startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ return;
}
}
- if (ofp.size() < (int32)sizeof(_vm->_boot))
- error("Corrupted startup file");
+ if (ofp.size() < (int32)sizeof(_vm->_boot)) {
+ Utils::notifyBox(Common::String::format("Corrupted startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ return;
+ }
_vm->_boot.checksum = ofp.readByte();
_vm->_boot.registered = ofp.readByte();
@@ -583,12 +618,14 @@ void FileManager::readBootFile() {
byte checksum = 0;
for (uint32 i = 0; i < sizeof(_vm->_boot); i++) {
checksum ^= p[i];
- p[i] ^= cypher[i % strlen(cypher)];
+ p[i] ^= s_bootCypher[i % s_bootCypherLen];
}
ofp.close();
- if (checksum)
- error("Corrupted startup file");
+ if (checksum) {
+ Utils::notifyBox(Common::String::format("Corrupted startup file '%s'", getBootFilename()));
+ _vm->getGameStatus().doQuitFl = true;
+ }
}
/**
@@ -660,8 +697,5 @@ void FileManager::readUIFImages() {
readUIFItem(UIF_IMAGES, _vm->_screen->getGUIBuffer()); // Read all uif images
}
-const char *FileManager::getBootCypher() const {
- return "Copyright 1992, David P Gray, Gray Design Associates";
-}
} // End of namespace Hugo
diff --git a/engines/hugo/file.h b/engines/hugo/file.h
index 77c6811df1..0e131348f9 100644
--- a/engines/hugo/file.h
+++ b/engines/hugo/file.h
@@ -118,7 +118,6 @@ protected:
PCC_header_t PCC_header;
seq_t *readPCX(Common::ReadStream &f, seq_t *seqPtr, byte *imagePtr, const bool firstFl, const char *name);
- const char *getBootCypher() const;
// If this is the first call, read the lookup table
bool has_read_header;
diff --git a/engines/hugo/file_v1d.cpp b/engines/hugo/file_v1d.cpp
index d8b3fa494f..021969f306 100644
--- a/engines/hugo/file_v1d.cpp
+++ b/engines/hugo/file_v1d.cpp
@@ -30,7 +30,9 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "hugo/hugo.h"
#include "hugo/file.h"
@@ -121,7 +123,7 @@ void FileManager_v1d::instructions() const {
f.read(wrkLine, 1);
} while (*wrkLine++ != '#'); // '#' is EOP
wrkLine[-2] = '\0'; // Remove EOP and previous CR
- Utils::Box(kBoxAny, "%s", line);
+ Utils::notifyBox(line);
wrkLine = line;
f.read(readBuf, 2); // Remove CRLF after EOP
}
diff --git a/engines/hugo/file_v1w.cpp b/engines/hugo/file_v1w.cpp
index dbb093752a..4f327b3095 100644
--- a/engines/hugo/file_v1w.cpp
+++ b/engines/hugo/file_v1w.cpp
@@ -30,7 +30,9 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "hugo/hugo.h"
#include "hugo/file.h"
diff --git a/engines/hugo/file_v2d.cpp b/engines/hugo/file_v2d.cpp
index ffadd17481..0ad89e987e 100644
--- a/engines/hugo/file_v2d.cpp
+++ b/engines/hugo/file_v2d.cpp
@@ -30,7 +30,9 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "hugo/hugo.h"
#include "hugo/file.h"
@@ -167,10 +169,10 @@ const char *FileManager_v2d::fetchString(const int index) {
// Get offset to string[index] (and next for length calculation)
_stringArchive.seek((uint32)index * sizeof(uint32), SEEK_SET);
- uint32 off1, off2;
- if (_stringArchive.read((char *)&off1, sizeof(uint32)) == 0)
- error("An error has occurred: bad String offset");
- if (_stringArchive.read((char *)&off2, sizeof(uint32)) == 0)
+
+ uint32 off1 = _stringArchive.readUint32LE();
+ uint32 off2 = _stringArchive.readUint32LE();
+ if (!off1 || !off2)
error("An error has occurred: bad String offset");
// Check size of string
diff --git a/engines/hugo/file_v2w.cpp b/engines/hugo/file_v2w.cpp
index b917d81bd5..245d4d017e 100644
--- a/engines/hugo/file_v2w.cpp
+++ b/engines/hugo/file_v2w.cpp
@@ -48,7 +48,7 @@ FileManager_v2w::~FileManager_v2w() {
* Same comment than in SCI: maybe in the future we can implement this, but for now this message should suffice
*/
void FileManager_v2w::instructions() const {
- Utils::Box(kBoxAny, "Please use an external viewer to open the game's help file: HUGOWIN%d.HLP", _vm->_gameVariant + 1);
+ Utils::notifyBox(Common::String::format("Please use an external viewer to open the game's help file: HUGOWIN%d.HLP", _vm->_gameVariant + 1));
}
} // End of namespace Hugo
diff --git a/engines/hugo/file_v3d.cpp b/engines/hugo/file_v3d.cpp
index 2f3e5af3f0..6370fffa4d 100644
--- a/engines/hugo/file_v3d.cpp
+++ b/engines/hugo/file_v3d.cpp
@@ -30,7 +30,9 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "hugo/hugo.h"
#include "hugo/file.h"
diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp
index 2143b8cfde..a872a97bae 100644
--- a/engines/hugo/hugo.cpp
+++ b/engines/hugo/hugo.cpp
@@ -25,12 +25,14 @@
#include "common/system.h"
#include "common/random.h"
+#include "common/error.h"
#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/debug-channels.h"
+#include "common/config-manager.h"
+#include "common/textconsole.h"
#include "hugo/hugo.h"
-#include "hugo/game.h"
#include "hugo/file.h"
#include "hugo/schedule.h"
#include "hugo/display.h"
@@ -52,7 +54,7 @@ HugoEngine *HugoEngine::s_Engine = 0;
HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(syst), _gameDescription(gd),
_hero(0), _heroImage(0), _defltTunes(0), _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0),
- _screenStates(0), _score(0), _maxscore(0), _lastTime(0), _curTime(0)
+ _screenStates(0), _numStates(0), _score(0), _maxscore(0), _lastTime(0), _curTime(0), _episode(0)
{
_system = syst;
DebugMan.addDebugChannel(kDebugSchedule, "Schedule", "Script Schedule debug level");
@@ -164,7 +166,7 @@ bool HugoEngine::isPacked() const {
* Print options for user when dead
*/
void HugoEngine::gameOverMsg() {
- Utils::Box(kBoxOk, "%s", _text->getTextUtil(kGameOver));
+ Utils::notifyBox(_text->getTextUtil(kGameOver));
}
Common::Error HugoEngine::run() {
@@ -175,6 +177,10 @@ Common::Error HugoEngine::run() {
_inventory = new InventoryHandler(this);
_route = new Route(this);
_sound = new SoundHandler(this);
+
+ // Setup mixer
+ syncSoundSettings();
+
_text = new TextHandler(this);
_topMenu = new TopMenu(this);
@@ -247,20 +253,28 @@ Common::Error HugoEngine::run() {
initStatus(); // Initialize game status
initConfig(); // Initialize user's config
- initialize();
- resetConfig(); // Reset user's config
- initMachine();
-
- // Start the state machine
- _status.viewState = kViewIntroInit;
-
- _status.doQuitFl = false;
+ if (!_status.doQuitFl) {
+ initialize();
+ resetConfig(); // Reset user's config
+ initMachine();
+
+ // Start the state machine
+ _status.viewState = kViewIntroInit;
+
+ int16 loadSlot = Common::ConfigManager::instance().getInt("save_slot");
+ if (loadSlot >= 0) {
+ _status.skipIntroFl = true;
+ _file->restoreGame(loadSlot);
+ } else {
+ _file->saveGame(0, "New Game");
+ }
+ }
while (!_status.doQuitFl) {
_screen->drawBoundaries();
-
g_system->updateScreen();
runMachine();
+
// Handle input
Common::Event event;
while (_eventMan->pollEvent(event)) {
@@ -285,6 +299,11 @@ Common::Error HugoEngine::run() {
break;
}
}
+ if (_status.helpFl) {
+ _status.helpFl = false;
+ _file->instructions();
+ }
+
_mouse->mouseHandler(); // Mouse activity - adds to display list
_screen->displayList(kDisplayDisplay); // Blit the display list to screen
_status.doQuitFl |= shouldQuit(); // update game quit flag
@@ -309,9 +328,6 @@ void HugoEngine::initMachine() {
*/
void HugoEngine::runMachine() {
status_t &gameStatus = getGameStatus();
- // Don't process if we're in a textbox
- if (gameStatus.textBoxFl)
- return;
// Don't process if gameover
if (gameStatus.gameOverFl)
@@ -449,6 +465,7 @@ bool HugoEngine::loadHugoDat() {
for (int varnt = 0; varnt < _numVariant; varnt++) {
numElem = in.readUint16BE();
if (varnt == _gameVariant) {
+ _numStates = numElem;
_screenStates = (byte *)malloc(sizeof(byte) * numElem);
memset(_screenStates, 0, sizeof(_screenStates));
}
@@ -516,13 +533,13 @@ void HugoEngine::initStatus() {
debugC(1, kDebugEngine, "initStatus");
_status.storyModeFl = false; // Not in story mode
_status.gameOverFl = false; // Hero not knobbled yet
- _status.textBoxFl = false; // Not processing a text box
_status.lookFl = false; // Toolbar "look" button
_status.recallFl = false; // Toolbar "recall" button
_status.newScreenFl = false; // Screen not just loaded
_status.godModeFl = false; // No special cheats allowed
_status.doQuitFl = false;
_status.skipIntroFl = false;
+ _status.helpFl = false;
// Initialize every start of new game
_status.tick = 0; // Tick count
@@ -539,6 +556,7 @@ void HugoEngine::initStatus() {
// _status.screenWidth = 0; // Desktop screen width
// _status.saveTick = 0; // Time of last save
// _status.saveSlot = 0; // Slot to save/restore game
+// _status.textBoxFl = false; // Not processing a text box
}
/**
@@ -623,6 +641,13 @@ void HugoEngine::readScreenFiles(const int screenNum) {
_file->readBackground(screenNum); // Scenery file
memcpy(_screen->getBackBuffer(), _screen->getFrontBuffer(), sizeof(_screen->getFrontBuffer())); // Make a copy
+
+ // Workaround for graphic glitches in DOS versions. Cleaning the overlays fix the problem
+ memset(_object->_objBound, '\0', sizeof(overlay_t));
+ memset(_object->_boundary, '\0', sizeof(overlay_t));
+ memset(_object->_overlay, '\0', sizeof(overlay_t));
+ memset(_object->_ovlBase, '\0', sizeof(overlay_t));
+
_file->readOverlay(screenNum, _object->_boundary, kOvlBoundary); // Boundary file
_file->readOverlay(screenNum, _object->_overlay, kOvlOverlay); // Overlay file
_file->readOverlay(screenNum, _object->_ovlBase, kOvlBase); // Overlay base file
@@ -658,9 +683,9 @@ void HugoEngine::calcMaxScore() {
void HugoEngine::endGame() {
debugC(1, kDebugEngine, "endGame");
- if (!_boot.registered)
- Utils::Box(kBoxAny, "%s", _text->getTextEngine(kEsAdvertise));
- Utils::Box(kBoxAny, "%s\n%s", _episode, getCopyrightString());
+ if (_boot.registered != kRegRegistered)
+ Utils::notifyBox(_text->getTextEngine(kEsAdvertise));
+ Utils::notifyBox(Common::String::format("%s\n%s", _episode, getCopyrightString()));
_status.viewState = kViewExit;
}
diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h
index b2739c829e..b2d241f241 100644
--- a/engines/hugo/hugo.h
+++ b/engines/hugo/hugo.h
@@ -29,7 +29,7 @@
#include "engines/engine.h"
#include "common/file.h"
#include "hugo/console.h"
-#include "hugo/menu.h"
+#include "hugo/dialogs.h"
// This include is here temporarily while the engine is being refactored.
#include "hugo/game.h"
@@ -58,7 +58,7 @@ class RandomSource;
*/
namespace Hugo {
-static const int kSavegameVersion = 3;
+static const int kSavegameVersion = 6;
static const int kInvDx = 32; // Width of an inventory icon
static const int kInvDy = 32; // Height of inventory icon
static const int kMaxTunes = 16; // Max number of tunes
@@ -125,10 +125,11 @@ enum HugoDebugChannels {
kDebugMusic = 1 << 9
};
-/**
- * Ways to dismiss a text/prompt box
- */
-enum box_t {kBoxAny, kBoxOk, kBoxPrompt, kBoxYesNo};
+enum HugoRegistered {
+ kRegShareware = 0,
+ kRegRegistered,
+ kRegFreeware
+};
/**
* Inventory icon bar states
@@ -175,13 +176,13 @@ struct HugoGameDescription;
struct status_t { // Game status (not saved)
bool storyModeFl; // Game is telling story - no commands
bool gameOverFl; // Game is over - hero knobbled
- bool textBoxFl; // Game is (halted) in text box
bool lookFl; // Toolbar "look" button pressed
bool recallFl; // Toolbar "recall" button pressed
bool newScreenFl; // New screen just loaded in dib_a
bool godModeFl; // Allow DEBUG features in live version
bool doQuitFl;
bool skipIntroFl;
+ bool helpFl;
uint32 tick; // Current time in ticks
vstate_t viewState; // View state machine
int16 song; // Current song
@@ -193,6 +194,7 @@ struct status_t { // Game status (not saved)
// bool helpFl; // Calling WinHelp (don't disable music)
// bool mmtimeFl; // Multimedia timer supported
// bool demoFl; // Game is in demo mode
+// bool textBoxFl; // Game is (halted) in text box
// int16 screenWidth; // Desktop screen width
// int16 saveSlot; // Current slot to save/restore game
// int16 cx, cy; // Cursor position (dib coords)
@@ -237,12 +239,12 @@ public:
int8 _soundTest;
int8 _tunesNbr;
uint16 _numScreens;
+ uint16 _numStates;
int8 _normalTPS; // Number of ticks (frames) per second.
// 8 for Win versions, 9 for DOS versions
object_t *_hero;
byte *_screen_p;
byte _heroImage;
-
byte *_screenStates;
command_t _line; // Line of user text input
config_t _config; // User's config
diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp
index 689dfbfd7c..c31d76abd0 100644
--- a/engines/hugo/intro.cpp
+++ b/engines/hugo/intro.cpp
@@ -31,6 +31,7 @@
*/
#include "common/system.h"
+#include "common/textconsole.h"
#include "hugo/hugo.h"
#include "hugo/intro.h"
@@ -93,7 +94,7 @@ void intro_v1d::introInit() {
surf.h = 200;
surf.pixels = _vm->_screen->getFrontBuffer();
surf.pitch = 320;
- surf.bytesPerPixel = 1;
+ surf.format = Graphics::PixelFormat::createFormatCLUT8();
_vm->_screen->displayList(kDisplayInit);
}
@@ -119,15 +120,19 @@ bool intro_v1d::introPlay() {
error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 8");
char buffer[80];
- if (_vm->_boot.registered)
+ if (_vm->_boot.registered == kRegRegistered)
strcpy(buffer, "Registered Version");
- else
+ else if (_vm->_boot.registered == kRegShareware)
strcpy(buffer, "Shareware Version");
+ else if (_vm->_boot.registered == kRegFreeware)
+ strcpy(buffer, "Freeware Version");
+ else
+ error("Unknown registration flag in hugo.bsf: %d", _vm->_boot.registered);
font.drawString(&surf, buffer, 0, 163, 320, _TLIGHTMAGENTA, Graphics::kTextAlignCenter);
font.drawString(&surf, _vm->getCopyrightString(), 0, 176, 320, _TLIGHTMAGENTA, Graphics::kTextAlignCenter);
- if (scumm_stricmp(_vm->_boot.distrib, "David P. Gray")) {
+ if ((*_vm->_boot.distrib != '\0') && (scumm_stricmp(_vm->_boot.distrib, "David P. Gray"))) {
sprintf(buffer, "Distributed by %s.", _vm->_boot.distrib);
font.drawString(&surf, buffer, 0, 75, 320, _TMAGENTA, Graphics::kTextAlignCenter);
}
@@ -243,7 +248,7 @@ void intro_v2d::introInit() {
surf.h = 200;
surf.pixels = _vm->_screen->getFrontBuffer();
surf.pitch = 320;
- surf.bytesPerPixel = 1;
+ surf.format = Graphics::PixelFormat::createFormatCLUT8();
char buffer[128];
@@ -258,7 +263,7 @@ void intro_v2d::introInit() {
font.drawString(&surf, buffer, 0, 186, 320, _TLIGHTRED, Graphics::kTextAlignCenter);
- if (scumm_stricmp(_vm->_boot.distrib, "David P. Gray")) {
+ if ((*_vm->_boot.distrib != '\0') && (scumm_stricmp(_vm->_boot.distrib, "David P. Gray"))) {
// TROMAN, size 10-5
sprintf(buffer, "Distributed by %s.", _vm->_boot.distrib);
font.drawString(&surf, buffer, 0, 1, 320, _TLIGHTRED, Graphics::kTextAlignCenter);
@@ -289,7 +294,7 @@ void intro_v3d::introInit() {
surf.h = 200;
surf.pixels = _vm->_screen->getFrontBuffer();
surf.pitch = 320;
- surf.bytesPerPixel = 1;
+ surf.format = Graphics::PixelFormat::createFormatCLUT8();
char buffer[128];
if (_vm->_boot.registered)
@@ -303,7 +308,7 @@ void intro_v3d::introInit() {
font.drawString(&surf, buffer, 0, 190, 320, _TBROWN, Graphics::kTextAlignCenter);
- if (scumm_stricmp(_vm->_boot.distrib, "David P. Gray")) {
+ if ((*_vm->_boot.distrib != '\0') && (scumm_stricmp(_vm->_boot.distrib, "David P. Gray"))) {
sprintf(buffer, "Distributed by %s.", _vm->_boot.distrib);
font.drawString(&surf, buffer, 0, 0, 320, _TBROWN, Graphics::kTextAlignCenter);
}
@@ -333,13 +338,13 @@ bool intro_v3d::introPlay() {
// Text boxes at various times
switch (introTicks) {
case 4:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro1));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro1));
break;
case 9:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro2));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro2));
break;
case 35:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro3));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro3));
break;
}
}
@@ -425,13 +430,13 @@ bool intro_v3w::introPlay() {
// Text boxes at various times
switch (introTicks) {
case 4:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro1));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro1));
break;
case 9:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro2));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro2));
break;
case 35:
- Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro3));
+ Utils::notifyBox(_vm->_text->getTextIntro(kIntro3));
break;
}
}
diff --git a/engines/hugo/inventory.cpp b/engines/hugo/inventory.cpp
index ab58e386ba..45893f6965 100644
--- a/engines/hugo/inventory.cpp
+++ b/engines/hugo/inventory.cpp
@@ -30,6 +30,7 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
#include "hugo/hugo.h"
diff --git a/engines/hugo/module.mk b/engines/hugo/module.mk
index 3a1ceded73..2ded997437 100644
--- a/engines/hugo/module.mk
+++ b/engines/hugo/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/hugo
MODULE_OBJS := \
console.o \
detection.o \
+ dialogs.o \
display.o \
file.o \
file_v1d.o \
@@ -13,7 +14,6 @@ MODULE_OBJS := \
hugo.o \
intro.o \
inventory.o \
- menu.o \
mouse.o \
object.o \
object_v1d.o \
diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp
index 73805dcfba..c02908e579 100644
--- a/engines/hugo/mouse.cpp
+++ b/engines/hugo/mouse.cpp
@@ -32,6 +32,7 @@
// mouse.cpp : Handle all mouse activity
+#include "common/debug.h"
#include "common/system.h"
#include "hugo/hugo.h"
@@ -187,7 +188,7 @@ void MouseHandler::processRightClick(const int16 objId, const int16 cx, const in
if (_vm->_hero->cycling == kCycleInvisible) // If invisible do
_vm->_object->useObject(objId); // immediate use
else
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
+ Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
}
break;
}
@@ -241,7 +242,7 @@ void MouseHandler::processLeftClick(const int16 objId, const int16 cx, const int
else if (_hotspots[i].direction == Common::KEYCODE_LEFT)
x += kHeroMaxWidth;
if (!_vm->_route->startRoute(kRouteExit, i, x, y))
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
+ Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
}
// Get rid of any attached icon
@@ -271,7 +272,7 @@ void MouseHandler::processLeftClick(const int16 objId, const int16 cx, const int
if (_vm->_hero->cycling == kCycleInvisible) // If invisible do
_vm->_object->lookObject(obj); // immediate decription
else
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
+ Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there
}
break;
}
@@ -363,6 +364,7 @@ void MouseHandler::readHotspot(Common::ReadStream &in, hotspot_t &hotspot) {
void MouseHandler::loadHotspots(Common::ReadStream &in) {
hotspot_t *wrkHotspots = 0;
hotspot_t tmp;
+ memset(&tmp, 0, sizeof(tmp));
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
int numRows = in.readUint16BE();
if (varnt == _vm->_gameVariant)
diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp
index 04e3449cbb..acf9f6e50c 100644
--- a/engines/hugo/object.cpp
+++ b/engines/hugo/object.cpp
@@ -30,8 +30,7 @@
*
*/
-#include "common/system.h"
-#include "common/random.h"
+#include "common/debug.h"
#include "hugo/hugo.h"
#include "hugo/game.h"
@@ -175,7 +174,7 @@ void ObjectHandler::useObject(int16 objId) {
// Deselect dragged icon if inventory not active
if (_vm->_inventory->getInventoryState() != kInventoryActive)
_vm->_screen->resetInventoryObjId();
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(use->dataIndex));
+ Utils::notifyBox(_vm->_text->getTextData(use->dataIndex));
return;
}
}
@@ -353,7 +352,7 @@ void ObjectHandler::showTakeables() {
if ((obj->cycling != kCycleInvisible) &&
(obj->screenIndex == *_vm->_screen_p) &&
(((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) {
- Utils::Box(kBoxAny, "You can also see:\n%s.", _vm->_text->getNoun(obj->nounIndex, LOOK_NAME));
+ Utils::notifyBox(Common::String::format("You can also see:\n%s.", _vm->_text->getNoun(obj->nounIndex, LOOK_NAME)));
}
}
}
@@ -418,20 +417,25 @@ void ObjectHandler::readUse(Common::ReadStream &in, uses_t &curUse) {
*/
void ObjectHandler::loadObjectUses(Common::ReadStream &in) {
uses_t tmpUse;
+ tmpUse.targets = 0;
+
//Read _uses
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
- tmpUse.targets = 0;
uint16 numElem = in.readUint16BE();
if (varnt == _vm->_gameVariant) {
_usesSize = numElem;
_uses = (uses_t *)malloc(sizeof(uses_t) * numElem);
}
- for (int i = 0; i < numElem; i++)
- readUse(in, (varnt == _vm->_gameVariant) ? _uses[i] : tmpUse);
-
- if (tmpUse.targets)
- free(tmpUse.targets);
+ for (int i = 0; i < numElem; i++) {
+ if (varnt == _vm->_gameVariant)
+ readUse(in, _uses[i]);
+ else {
+ readUse(in, tmpUse);
+ free(tmpUse.targets);
+ tmpUse.targets = 0;
+ }
+ }
}
}
@@ -497,20 +501,26 @@ void ObjectHandler::readObject(Common::ReadStream &in, object_t &curObject) {
void ObjectHandler::loadObjectArr(Common::ReadStream &in) {
debugC(6, kDebugObject, "loadObject(&in)");
object_t tmpObject;
+ tmpObject.stateDataIndex = 0;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
uint16 numElem = in.readUint16BE();
- tmpObject.stateDataIndex = 0;
+
if (varnt == _vm->_gameVariant) {
_objCount = numElem;
_objects = (object_t *)malloc(sizeof(object_t) * numElem);
}
- for (int i = 0; i < numElem; i++)
- readObject(in, (varnt == _vm->_gameVariant) ? _objects[i] : tmpObject);
-
- if (tmpObject.stateDataIndex)
- free(tmpObject.stateDataIndex);
+ for (int i = 0; i < numElem; i++) {
+ if (varnt == _vm->_gameVariant)
+ readObject(in, _objects[i]);
+ else {
+ // Skip over uneeded objects.
+ readObject(in, tmpObject);
+ free(tmpObject.stateDataIndex);
+ tmpObject.stateDataIndex = 0;
+ }
+ }
}
}
diff --git a/engines/hugo/object_v1d.cpp b/engines/hugo/object_v1d.cpp
index a8edb45746..95bedf4fa2 100644
--- a/engines/hugo/object_v1d.cpp
+++ b/engines/hugo/object_v1d.cpp
@@ -30,6 +30,7 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
#include "common/random.h"
diff --git a/engines/hugo/object_v1w.cpp b/engines/hugo/object_v1w.cpp
index f3ba793a3b..54becd8234 100644
--- a/engines/hugo/object_v1w.cpp
+++ b/engines/hugo/object_v1w.cpp
@@ -30,6 +30,7 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
#include "common/random.h"
diff --git a/engines/hugo/object_v2d.cpp b/engines/hugo/object_v2d.cpp
index b3c49262ad..7c47bf4f92 100644
--- a/engines/hugo/object_v2d.cpp
+++ b/engines/hugo/object_v2d.cpp
@@ -30,6 +30,7 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
#include "common/random.h"
diff --git a/engines/hugo/object_v3d.cpp b/engines/hugo/object_v3d.cpp
index 2c6fc5d99d..3ff6c56ad3 100644
--- a/engines/hugo/object_v3d.cpp
+++ b/engines/hugo/object_v3d.cpp
@@ -30,6 +30,7 @@
*
*/
+#include "common/debug.h"
#include "common/system.h"
#include "common/random.h"
diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp
index c845e03eee..29a1d5efa3 100644
--- a/engines/hugo/parser.cpp
+++ b/engines/hugo/parser.cpp
@@ -30,12 +30,8 @@
*
*/
-#include "common/system.h"
#include "common/events.h"
-
-#include "common/random.h"
-#include "common/EventRecorder.h"
-#include "common/debug-channels.h"
+#include "common/textconsole.h"
#include "hugo/hugo.h"
#include "hugo/display.h"
@@ -87,6 +83,7 @@ void Parser::readCmd(Common::ReadStream &in, cmd &curCmd) {
*/
void Parser::loadCmdList(Common::ReadStream &in) {
cmd tmpCmd;
+ memset(&tmpCmd, 0, sizeof(tmpCmd));
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
uint16 numElem = in.readUint16BE();
if (varnt == _vm->_gameVariant) {
@@ -119,6 +116,7 @@ void Parser::readBG(Common::ReadStream &in, background_t &curBG) {
*/
void Parser::loadBackgroundObjects(Common::ReadStream &in) {
background_t tmpBG;
+ memset(&tmpBG, 0, sizeof(tmpBG));
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
uint16 numElem = in.readUint16BE();
@@ -145,6 +143,7 @@ void Parser::loadBackgroundObjects(Common::ReadStream &in) {
void Parser::loadCatchallList(Common::ReadStream &in) {
background_t *wrkCatchallList = 0;
background_t tmpBG;
+ memset(&tmpBG, 0, sizeof(tmpBG));
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
uint16 numElem = in.readUint16BE();
@@ -286,11 +285,10 @@ void Parser::keyHandler(Common::Event event) {
break;
case Common::KEYCODE_l:
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
break;
case Common::KEYCODE_n:
- warning("STUB: CTRL-N (WIN) - New Game");
+ if (Utils::yesNoBox("Are you sure you want to start a new game?"))
+ _vm->_file->restoreGame(0);
break;
case Common::KEYCODE_s:
if (gameStatus.viewState == kViewPlay) {
@@ -338,7 +336,7 @@ void Parser::keyHandler(Common::Event event) {
break;
case Common::KEYCODE_F1: // User Help (DOS)
if (_checkDoubleF1Fl)
- _vm->_file->instructions();
+ gameStatus.helpFl = true;
else
_vm->_screen->userHelp();
_checkDoubleF1Fl = !_checkDoubleF1Fl;
@@ -360,8 +358,6 @@ void Parser::keyHandler(Common::Event event) {
break;
case Common::KEYCODE_F5: // Restore game
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
break;
case Common::KEYCODE_F6: // Inventory
showInventory();
@@ -488,7 +484,7 @@ void Parser::showDosInventory() const {
if (index & 1)
buffer += "\n";
buffer += Common::String(_vm->_text->getTextParser(kTBOutro));
- Utils::Box(kBoxAny, "%s", buffer.c_str());
+ Utils::notifyBox(buffer.c_str());
}
} // End of namespace Hugo
diff --git a/engines/hugo/parser.h b/engines/hugo/parser.h
index dd9244ba93..b00b8d5c43 100644
--- a/engines/hugo/parser.h
+++ b/engines/hugo/parser.h
@@ -32,6 +32,11 @@
#ifndef HUGO_PARSER_H
#define HUGO_PARSER_H
+
+namespace Common {
+struct Event;
+}
+
namespace Hugo {
enum seqTextParser {
diff --git a/engines/hugo/parser_v1d.cpp b/engines/hugo/parser_v1d.cpp
index 424ca66b38..b2e515fd42 100644
--- a/engines/hugo/parser_v1d.cpp
+++ b/engines/hugo/parser_v1d.cpp
@@ -32,6 +32,7 @@
// parser.c - handles all keyboard/command input
+#include "common/debug.h"
#include "common/system.h"
#include "hugo/hugo.h"
@@ -151,25 +152,25 @@ bool Parser_v1d::isGenericVerb_v1(const char *word, object_t *obj) {
// Following is equivalent to switch, but couldn't do one
if (word == _vm->_text->getVerb(_vm->_look, 0)) {
if ((LOOK & obj->genericCmd) == LOOK)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->dataIndex));
+ Utils::notifyBox(_vm->_text->getTextData(obj->dataIndex));
else
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBUnusual_1d));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBUnusual_1d));
} else if (word == _vm->_text->getVerb(_vm->_take, 0)) {
if (obj->carriedFl)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBHave));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBHave));
else if ((TAKE & obj->genericCmd) == TAKE)
takeObject(obj);
else if (!obj->verbOnlyFl) // Make sure not taking object in context!
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse));
else
return false;
} else if (word == _vm->_text->getVerb(_vm->_drop, 0)) {
if (!obj->carriedFl)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBDontHave));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBDontHave));
else if ((DROP & obj->genericCmd) == DROP)
dropObject(obj);
else
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNeed));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNeed));
} else { // It was not a generic cmd
return false;
}
@@ -206,7 +207,7 @@ bool Parser_v1d::isObjectVerb_v1(const char *word, object_t *obj) {
uint16 *reqs = _arrayReqs[cmnd->reqIndex]; // ptr to list of required objects
for (i = 0; reqs[i]; i++) { // for each obj
if (!_vm->_object->isCarrying(reqs[i])) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataNoCarryIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataNoCarryIndex));
return true;
}
}
@@ -214,14 +215,14 @@ bool Parser_v1d::isObjectVerb_v1(const char *word, object_t *obj) {
// Required objects are present, now check state is correct
if ((obj->state != cmnd->reqState) && (cmnd->reqState != kStateDontCare)){
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataWrongIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataWrongIndex));
return true;
}
// Everything checked. Change the state and carry out any actions
if (cmnd->reqState != kStateDontCare) // Don't change new state if required state didn't care
obj->state = cmnd->newState;
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataDoneIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataDoneIndex));
_vm->_scheduler->insertActionList(cmnd->actIndex);
// Special case if verb is Take or Drop. Assume additional generic actions
if ((word == _vm->_text->getVerb(_vm->_take, 0)) || (word == _vm->_text->getVerb(_vm->_drop, 0)))
@@ -241,7 +242,7 @@ bool Parser_v1d::isBackgroundWord_v1(const char *noun, const char *verb, objectL
for (int i = 0; obj[i].verbIndex; i++) {
if ((verb == _vm->_text->getVerb(obj[i].verbIndex, 0)) && (noun == _vm->_text->getNoun(obj[i].nounIndex, 0))) {
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex));
+ Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex));
return true;
}
}
@@ -260,7 +261,7 @@ void Parser_v1d::takeObject(object_t *obj) {
_vm->adjustScore(obj->objValue);
- Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME));
+ Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME)));
}
/**
@@ -276,7 +277,7 @@ void Parser_v1d::dropObject(object_t *obj) {
obj->x = _vm->_hero->x - 1;
obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1;
_vm->adjustScore(-obj->objValue);
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBOk));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBOk));
}
/**
@@ -294,7 +295,7 @@ bool Parser_v1d::isCatchallVerb_v1(bool testNounFl, const char *noun, const char
for (int i = 0; obj[i].verbIndex; i++) {
if ((verb == _vm->_text->getVerb(obj[i].verbIndex, 0)) && ((noun == _vm->_text->getNoun(obj[i].nounIndex, 0)) || (obj[i].nounIndex == 0))) {
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex));
+ Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex));
return true;
}
}
@@ -364,7 +365,7 @@ void Parser_v1d::lineHandler() {
}
if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) {
- if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0)
+ if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d)))
_vm->endGame();
return;
}
@@ -380,8 +381,6 @@ void Parser_v1d::lineHandler() {
if (!strcmp("restore", _vm->_line)) {
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
return;
}
@@ -420,11 +419,11 @@ void Parser_v1d::lineHandler() {
}
noun = findNextNoun(noun);
if (*farComment != '\0') // An object matched but not near enough
- Utils::Box(kBoxAny, "%s", farComment);
+ Utils::notifyBox(farComment);
else if (!isCatchallVerb_v1(true, noun, verb, _catchallList) &&
!isCatchallVerb_v1(false, noun, verb, _backgroundObjects[*_vm->_screen_p]) &&
!isCatchallVerb_v1(false, noun, verb, _catchallList))
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh_1d));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBEh_1d));
}
void Parser_v1d::showInventory() const {
diff --git a/engines/hugo/parser_v1w.cpp b/engines/hugo/parser_v1w.cpp
index 5d901e8ffe..a39063357b 100644
--- a/engines/hugo/parser_v1w.cpp
+++ b/engines/hugo/parser_v1w.cpp
@@ -32,8 +32,7 @@
// parser.c - handles all keyboard/command input
-#include "common/system.h"
-#include "common/events.h"
+#include "common/debug.h"
#include "hugo/hugo.h"
#include "hugo/parser.h"
@@ -119,7 +118,7 @@ void Parser_v1w::lineHandler() {
// Special meta commands
// EXIT/QUIT
if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) {
- if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0)
+ if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d)))
_vm->endGame();
return;
}
@@ -132,8 +131,6 @@ void Parser_v1w::lineHandler() {
if (!strcmp("restore", _vm->_line) && (gameStatus.viewState == kViewPlay || gameStatus.viewState == kViewIdle)) {
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
return;
}
@@ -184,7 +181,7 @@ void Parser_v1w::lineHandler() {
// If a not-near comment was generated, print it
if (*farComment != '\0') {
- Utils::Box(kBoxAny, "%s", farComment);
+ Utils::notifyBox(farComment);
return;
}
@@ -192,16 +189,16 @@ void Parser_v1w::lineHandler() {
const char *verb = findVerb();
const char *noun = findNoun();
if (verb == _vm->_text->getVerb(_vm->_look, 0) && _vm->_maze.enabledFl) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBMaze));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBMaze));
_vm->_object->showTakeables();
} else if (verb && noun) { // A combination I didn't think of
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoPoint));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoPoint));
} else if (noun) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoun));
} else if (verb) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBVerb));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBVerb));
} else {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBEh));
}
}
diff --git a/engines/hugo/parser_v2d.cpp b/engines/hugo/parser_v2d.cpp
index 580d78100d..6233f11c29 100644
--- a/engines/hugo/parser_v2d.cpp
+++ b/engines/hugo/parser_v2d.cpp
@@ -32,6 +32,7 @@
// parser.c - handles all keyboard/command input
+#include "common/debug.h"
#include "common/system.h"
#include "hugo/hugo.h"
@@ -114,14 +115,13 @@ void Parser_v2d::lineHandler() {
}
if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) {
- if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0)
+ if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d)))
_vm->endGame();
return;
}
// SAVE/RESTORE
if (!strcmp("save", _vm->_line)) {
- _vm->_config.soundFl = false;
if (gameStatus.gameOverFl)
_vm->gameOverMsg();
else
@@ -130,10 +130,7 @@ void Parser_v2d::lineHandler() {
}
if (!strcmp("restore", _vm->_line)) {
- _vm->_config.soundFl = false;
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
return;
}
@@ -177,16 +174,16 @@ void Parser_v2d::lineHandler() {
&& !isCatchallVerb_v1(false, noun, verb, _backgroundObjects[*_vm->_screen_p])
&& !isCatchallVerb_v1(false, noun, verb, _catchallList)) {
if (*farComment != '\0') { // An object matched but not near enough
- Utils::Box(kBoxAny, "%s", farComment);
+ Utils::notifyBox(farComment);
} else if (_vm->_maze.enabledFl && (verb == _vm->_text->getVerb(_vm->_look, 0))) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBMaze));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBMaze));
_vm->_object->showTakeables();
} else if (verb && noun) { // A combination I didn't think of
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse_2d));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse_2d));
} else if (verb || noun) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoun));
} else {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh_2d));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBEh_2d));
}
}
}
diff --git a/engines/hugo/parser_v3d.cpp b/engines/hugo/parser_v3d.cpp
index b3d0125d20..8c4946c534 100644
--- a/engines/hugo/parser_v3d.cpp
+++ b/engines/hugo/parser_v3d.cpp
@@ -32,6 +32,7 @@
// parser.c - handles all keyboard/command input
+#include "common/debug.h"
#include "common/system.h"
#include "hugo/hugo.h"
@@ -116,14 +117,13 @@ void Parser_v3d::lineHandler() {
// Special meta commands
// EXIT/QUIT
if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) {
- if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0)
+ if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d)))
_vm->endGame();
return;
}
// SAVE/RESTORE
if (!strcmp("save", _vm->_line)) {
- _vm->_config.soundFl = false;
if (gameStatus.gameOverFl)
_vm->gameOverMsg();
else
@@ -132,10 +132,7 @@ void Parser_v3d::lineHandler() {
}
if (!strcmp("restore", _vm->_line)) {
- _vm->_config.soundFl = false;
_vm->_file->restoreGame(-1);
- _vm->_scheduler->restoreScreen(*_vm->_screen_p);
- gameStatus.viewState = kViewPlay;
return;
}
@@ -186,7 +183,7 @@ void Parser_v3d::lineHandler() {
// If a not-near comment was generated, print it
if (*farComment != '\0') {
- Utils::Box(kBoxAny, "%s", farComment);
+ Utils::notifyBox(farComment);
return;
}
@@ -195,13 +192,13 @@ void Parser_v3d::lineHandler() {
const char *noun = findNoun();
if (verb && noun) { // A combination I didn't think of
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoPoint));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoPoint));
} else if (noun) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoun));
} else if (verb) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBVerb));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBVerb));
} else {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBEh));
}
}
@@ -238,7 +235,7 @@ bool Parser_v3d::isObjectVerb_v3(object_t *obj, char *comment) {
uint16 *reqs = _arrayReqs[cmnd->reqIndex]; // ptr to list of required objects
for (i = 0; reqs[i]; i++) { // for each obj
if (!_vm->_object->isCarrying(reqs[i])) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataNoCarryIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataNoCarryIndex));
return true;
}
}
@@ -246,14 +243,14 @@ bool Parser_v3d::isObjectVerb_v3(object_t *obj, char *comment) {
// Required objects are present, now check state is correct
if ((obj->state != cmnd->reqState) && (cmnd->reqState != kStateDontCare)) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataWrongIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataWrongIndex));
return true;
}
// Everything checked. Change the state and carry out any actions
if (cmnd->reqState != kStateDontCare) // Don't change new state if required state didn't care
obj->state = cmnd->newState;
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataDoneIndex));
+ Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataDoneIndex));
_vm->_scheduler->insertActionList(cmnd->actIndex);
// See if any additional generic actions
@@ -275,35 +272,35 @@ bool Parser_v3d::isGenericVerb_v3(object_t *obj, char *comment) {
if (isWordPresent(_vm->_text->getVerbArray(_vm->_look)) && isNear_v3(obj, _vm->_text->getVerb(_vm->_look, 0), comment)) {
// Test state-dependent look before general look
if ((obj->genericCmd & LOOK_S) == LOOK_S) {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->stateDataIndex[obj->state]));
+ Utils::notifyBox(_vm->_text->getTextData(obj->stateDataIndex[obj->state]));
} else {
if ((LOOK & obj->genericCmd) == LOOK) {
if (obj->dataIndex != 0)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->dataIndex));
+ Utils::notifyBox(_vm->_text->getTextData(obj->dataIndex));
else
return false;
} else {
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBUnusual));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBUnusual));
}
}
} else if (isWordPresent(_vm->_text->getVerbArray(_vm->_take)) && isNear_v3(obj, _vm->_text->getVerb(_vm->_take, 0), comment)) {
if (obj->carriedFl)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBHave));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBHave));
else if ((TAKE & obj->genericCmd) == TAKE)
takeObject(obj);
else if (obj->cmdIndex) // No comment if possible commands
return false;
else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context!
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse));
else
return false;
} else if (isWordPresent(_vm->_text->getVerbArray(_vm->_drop))) {
if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP))
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBDontHave));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBDontHave));
else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP))
dropObject(obj);
else if (obj->cmdIndex == 0)
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNeed));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBNeed));
else
return false;
} else { // It was not a generic cmd
@@ -385,7 +382,7 @@ void Parser_v3d::takeObject(object_t *obj) {
if (obj->seqNumb > 0) // If object has an image, force walk to dropped
obj->viewx = -1; // (possibly moved) object next time taken!
- Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME));
+ Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME)));
}
/**
@@ -404,7 +401,7 @@ void Parser_v3d::dropObject(object_t *obj) {
obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1;
obj->y = (obj->y + obj->currImagePtr->y2 < kYPix) ? obj->y : kYPix - obj->currImagePtr->y2 - 10;
_vm->adjustScore(-obj->objValue);
- Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBOk));
+ Utils::notifyBox(_vm->_text->getTextParser(kTBOk));
}
/**
@@ -424,7 +421,7 @@ bool Parser_v3d::isCatchallVerb_v3(objectList_t obj) const {
(!obj[i].matchFl || !findNoun()) &&
((obj[i].roomState == kStateDontCare) ||
(obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) {
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex));
+ Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex));
_vm->_scheduler->processBonus(obj[i].bonusIndex);
// If this is LOOK (without a noun), show any takeable objects
@@ -452,7 +449,7 @@ bool Parser_v3d::isBackgroundWord_v3(objectList_t obj) const {
isWordPresent(_vm->_text->getNounArray(obj[i].nounIndex)) &&
((obj[i].roomState == kStateDontCare) ||
(obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) {
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex));
+ Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex));
_vm->_scheduler->processBonus(obj[i].bonusIndex);
return true;
}
diff --git a/engines/hugo/route.cpp b/engines/hugo/route.cpp
index 76ec583857..68b659cd3f 100644
--- a/engines/hugo/route.cpp
+++ b/engines/hugo/route.cpp
@@ -32,6 +32,7 @@
// Find shortest route from hero to destination
+#include "common/debug.h"
#include "common/system.h"
#include "hugo/hugo.h"
diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp
index 5843c2317e..0e91124a7e 100644
--- a/engines/hugo/schedule.cpp
+++ b/engines/hugo/schedule.cpp
@@ -32,7 +32,9 @@
// This module contains all the scheduling and timing stuff
+#include "common/debug.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "hugo/hugo.h"
#include "hugo/schedule.h"
@@ -708,21 +710,19 @@ void Scheduler::saveEvents(Common::WriteStream *f) {
f->writeSint16BE(tailIndex);
// Convert event ptrs to indexes
- event_t saveEventArr[kMaxEvents]; // Convert event ptrs to indexes
for (int16 i = 0; i < kMaxEvents; i++) {
event_t *wrkEvent = &_events[i];
- saveEventArr[i] = *wrkEvent;
- // fix up action pointer (to do better)
+ // fix up action pointer (to do better)
int16 index, subElem;
- findAction(saveEventArr[i].action, &index, &subElem);
- saveEventArr[i].action = (act*)((index << 16)| subElem);
-
- saveEventArr[i].prevEvent = (wrkEvent->prevEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->prevEvent - _events);
- saveEventArr[i].nextEvent = (wrkEvent->nextEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->nextEvent - _events);
+ findAction(wrkEvent->action, &index, &subElem);
+ f->writeSint16BE(index);
+ f->writeSint16BE(subElem);
+ f->writeByte((wrkEvent->localActionFl) ? 1 : 0);
+ f->writeUint32BE(wrkEvent->time);
+ f->writeSint16BE((wrkEvent->prevEvent == 0) ? -1 : (wrkEvent->prevEvent - _events));
+ f->writeSint16BE((wrkEvent->nextEvent == 0) ? -1 : (wrkEvent->nextEvent - _events));
}
-
- f->write(saveEventArr, sizeof(saveEventArr));
}
/**
@@ -730,27 +730,11 @@ void Scheduler::saveEvents(Common::WriteStream *f) {
*/
void Scheduler::restoreActions(Common::ReadStream *f) {
-
for (int i = 0; i < _actListArrSize; i++) {
-
- // read all the sub elems
- int j = 0;
- do {
-
- // handle special case for a3, keep list pointer
- int* responsePtr = 0;
- if (_actListArr[i][j].a3.actType == PROMPT) {
- responsePtr = _actListArr[i][j].a3.responsePtr;
- }
-
- f->read(&_actListArr[i][j], sizeof(act));
-
- // handle special case for a3, reset list pointer
- if (_actListArr[i][j].a3.actType == PROMPT) {
- _actListArr[i][j].a3.responsePtr = responsePtr;
- }
- j++;
- } while (_actListArr[i][j-1].a0.actType != ANULL);
+ uint16 numSubElem = f->readUint16BE();
+ for (int j = 0; j < numSubElem; j++) {
+ readAct(*f, _actListArr[i][j]);
+ }
}
}
@@ -764,23 +748,301 @@ int16 Scheduler::calcMaxPoints() const {
/*
* Save the action data in the file with handle f
*/
-void Scheduler::saveActions(Common::WriteStream* f) const {
+void Scheduler::saveActions(Common::WriteStream *f) const {
+ byte subElemType;
+ int16 nbrCpt;
+ uint16 nbrSubElem;
+
for (int i = 0; i < _actListArrSize; i++) {
// write all the sub elems data
-
- int j = 0;
- do {
- f->write(&_actListArr[i][j], sizeof(act));
- j++;
- } while (_actListArr[i][j-1].a0.actType != ANULL);
+ for (nbrSubElem = 1; _actListArr[i][nbrSubElem - 1].a0.actType != ANULL; nbrSubElem++)
+ ;
+
+ f->writeUint16BE(nbrSubElem);
+ for (int j = 0; j < nbrSubElem; j++) {
+ subElemType = _actListArr[i][j].a0.actType;
+ f->writeByte(subElemType);
+ switch (subElemType) {
+ case ANULL: // -1
+ break;
+ case ASCHEDULE: // 0
+ f->writeSint16BE(_actListArr[i][j].a0.timer);
+ f->writeUint16BE(_actListArr[i][j].a0.actIndex);
+ break;
+ case START_OBJ: // 1
+ f->writeSint16BE(_actListArr[i][j].a1.timer);
+ f->writeSint16BE(_actListArr[i][j].a1.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a1.cycleNumb);
+ f->writeByte(_actListArr[i][j].a1.cycle);
+ break;
+ case INIT_OBJXY: // 2
+ f->writeSint16BE(_actListArr[i][j].a2.timer);
+ f->writeSint16BE(_actListArr[i][j].a2.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a2.x);
+ f->writeSint16BE(_actListArr[i][j].a2.y);
+ break;
+ case PROMPT: // 3
+ f->writeSint16BE(_actListArr[i][j].a3.timer);
+ f->writeSint16BE(_actListArr[i][j].a3.promptIndex);
+ for (nbrCpt = 0; _actListArr[i][j].a3.responsePtr[nbrCpt] != -1; nbrCpt++)
+ ;
+ nbrCpt++;
+ f->writeUint16BE(nbrCpt);
+ for (int k = 0; k < nbrCpt; k++)
+ f->writeSint16BE(_actListArr[i][j].a3.responsePtr[k]);
+ f->writeUint16BE(_actListArr[i][j].a3.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a3.actFailIndex);
+ f->writeByte((_actListArr[i][j].a3.encodedFl) ? 1 : 0);
+ break;
+ case BKGD_COLOR: // 4
+ f->writeSint16BE(_actListArr[i][j].a4.timer);
+ f->writeUint32BE(_actListArr[i][j].a4.newBackgroundColor);
+ break;
+ case INIT_OBJVXY: // 5
+ f->writeSint16BE(_actListArr[i][j].a5.timer);
+ f->writeSint16BE(_actListArr[i][j].a5.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a5.vx);
+ f->writeSint16BE(_actListArr[i][j].a5.vy);
+ break;
+ case INIT_CARRY: // 6
+ f->writeSint16BE(_actListArr[i][j].a6.timer);
+ f->writeSint16BE(_actListArr[i][j].a6.objIndex);
+ f->writeByte((_actListArr[i][j].a6.carriedFl) ? 1 : 0);
+ break;
+ case INIT_HF_COORD: // 7
+ f->writeSint16BE(_actListArr[i][j].a7.timer);
+ f->writeSint16BE(_actListArr[i][j].a7.objIndex);
+ break;
+ case NEW_SCREEN: // 8
+ f->writeSint16BE(_actListArr[i][j].a8.timer);
+ f->writeSint16BE(_actListArr[i][j].a8.screenIndex);
+ break;
+ case INIT_OBJSTATE: // 9
+ f->writeSint16BE(_actListArr[i][j].a9.timer);
+ f->writeSint16BE(_actListArr[i][j].a9.objIndex);
+ f->writeByte(_actListArr[i][j].a9.newState);
+ break;
+ case INIT_PATH: // 10
+ f->writeSint16BE(_actListArr[i][j].a10.timer);
+ f->writeSint16BE(_actListArr[i][j].a10.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a10.newPathType);
+ f->writeByte(_actListArr[i][j].a10.vxPath);
+ f->writeByte(_actListArr[i][j].a10.vyPath);
+ break;
+ case COND_R: // 11
+ f->writeSint16BE(_actListArr[i][j].a11.timer);
+ f->writeSint16BE(_actListArr[i][j].a11.objIndex);
+ f->writeByte(_actListArr[i][j].a11.stateReq);
+ f->writeUint16BE(_actListArr[i][j].a11.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a11.actFailIndex);
+ break;
+ case TEXT: // 12
+ f->writeSint16BE(_actListArr[i][j].a12.timer);
+ f->writeSint16BE(_actListArr[i][j].a12.stringIndex);
+ break;
+ case SWAP_IMAGES: // 13
+ f->writeSint16BE(_actListArr[i][j].a13.timer);
+ f->writeSint16BE(_actListArr[i][j].a13.objIndex1);
+ f->writeSint16BE(_actListArr[i][j].a13.objIndex2);
+ break;
+ case COND_SCR: // 14
+ f->writeSint16BE(_actListArr[i][j].a14.timer);
+ f->writeSint16BE(_actListArr[i][j].a14.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a14.screenReq);
+ f->writeUint16BE(_actListArr[i][j].a14.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a14.actFailIndex);
+ break;
+ case AUTOPILOT: // 15
+ f->writeSint16BE(_actListArr[i][j].a15.timer);
+ f->writeSint16BE(_actListArr[i][j].a15.objIndex1);
+ f->writeSint16BE(_actListArr[i][j].a15.objIndex2);
+ f->writeByte(_actListArr[i][j].a15.dx);
+ f->writeByte(_actListArr[i][j].a15.dy);
+ break;
+ case INIT_OBJ_SEQ: // 16
+ f->writeSint16BE(_actListArr[i][j].a16.timer);
+ f->writeSint16BE(_actListArr[i][j].a16.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a16.seqIndex);
+ break;
+ case SET_STATE_BITS: // 17
+ f->writeSint16BE(_actListArr[i][j].a17.timer);
+ f->writeSint16BE(_actListArr[i][j].a17.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a17.stateMask);
+ break;
+ case CLEAR_STATE_BITS: // 18
+ f->writeSint16BE(_actListArr[i][j].a18.timer);
+ f->writeSint16BE(_actListArr[i][j].a18.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a18.stateMask);
+ break;
+ case TEST_STATE_BITS: // 19
+ f->writeSint16BE(_actListArr[i][j].a19.timer);
+ f->writeSint16BE(_actListArr[i][j].a19.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a19.stateMask);
+ f->writeUint16BE(_actListArr[i][j].a19.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a19.actFailIndex);
+ break;
+ case DEL_EVENTS: // 20
+ f->writeSint16BE(_actListArr[i][j].a20.timer);
+ f->writeByte(_actListArr[i][j].a20.actTypeDel);
+ break;
+ case GAMEOVER: // 21
+ f->writeSint16BE(_actListArr[i][j].a21.timer);
+ break;
+ case INIT_HH_COORD: // 22
+ f->writeSint16BE(_actListArr[i][j].a22.timer);
+ f->writeSint16BE(_actListArr[i][j].a22.objIndex);
+ break;
+ case EXIT: // 23
+ f->writeSint16BE(_actListArr[i][j].a23.timer);
+ break;
+ case BONUS: // 24
+ f->writeSint16BE(_actListArr[i][j].a24.timer);
+ f->writeSint16BE(_actListArr[i][j].a24.pointIndex);
+ break;
+ case COND_BOX: // 25
+ f->writeSint16BE(_actListArr[i][j].a25.timer);
+ f->writeSint16BE(_actListArr[i][j].a25.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a25.x1);
+ f->writeSint16BE(_actListArr[i][j].a25.y1);
+ f->writeSint16BE(_actListArr[i][j].a25.x2);
+ f->writeSint16BE(_actListArr[i][j].a25.y2);
+ f->writeUint16BE(_actListArr[i][j].a25.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a25.actFailIndex);
+ break;
+ case SOUND: // 26
+ f->writeSint16BE(_actListArr[i][j].a26.timer);
+ f->writeSint16BE(_actListArr[i][j].a26.soundIndex);
+ break;
+ case ADD_SCORE: // 27
+ f->writeSint16BE(_actListArr[i][j].a27.timer);
+ f->writeSint16BE(_actListArr[i][j].a27.objIndex);
+ break;
+ case SUB_SCORE: // 28
+ f->writeSint16BE(_actListArr[i][j].a28.timer);
+ f->writeSint16BE(_actListArr[i][j].a28.objIndex);
+ break;
+ case COND_CARRY: // 29
+ f->writeSint16BE(_actListArr[i][j].a29.timer);
+ f->writeSint16BE(_actListArr[i][j].a29.objIndex);
+ f->writeUint16BE(_actListArr[i][j].a29.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a29.actFailIndex);
+ break;
+ case INIT_MAZE: // 30
+ f->writeSint16BE(_actListArr[i][j].a30.timer);
+ f->writeByte(_actListArr[i][j].a30.mazeSize);
+ f->writeSint16BE(_actListArr[i][j].a30.x1);
+ f->writeSint16BE(_actListArr[i][j].a30.y1);
+ f->writeSint16BE(_actListArr[i][j].a30.x2);
+ f->writeSint16BE(_actListArr[i][j].a30.y2);
+ f->writeSint16BE(_actListArr[i][j].a30.x3);
+ f->writeSint16BE(_actListArr[i][j].a30.x4);
+ f->writeByte(_actListArr[i][j].a30.firstScreenIndex);
+ break;
+ case EXIT_MAZE: // 31
+ f->writeSint16BE(_actListArr[i][j].a31.timer);
+ break;
+ case INIT_PRIORITY: // 32
+ f->writeSint16BE(_actListArr[i][j].a32.timer);
+ f->writeSint16BE(_actListArr[i][j].a32.objIndex);
+ f->writeByte(_actListArr[i][j].a32.priority);
+ break;
+ case INIT_SCREEN: // 33
+ f->writeSint16BE(_actListArr[i][j].a33.timer);
+ f->writeSint16BE(_actListArr[i][j].a33.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a33.screenIndex);
+ break;
+ case AGSCHEDULE: // 34
+ f->writeSint16BE(_actListArr[i][j].a34.timer);
+ f->writeUint16BE(_actListArr[i][j].a34.actIndex);
+ break;
+ case REMAPPAL: // 35
+ f->writeSint16BE(_actListArr[i][j].a35.timer);
+ f->writeSint16BE(_actListArr[i][j].a35.oldColorIndex);
+ f->writeSint16BE(_actListArr[i][j].a35.newColorIndex);
+ break;
+ case COND_NOUN: // 36
+ f->writeSint16BE(_actListArr[i][j].a36.timer);
+ f->writeUint16BE(_actListArr[i][j].a36.nounIndex);
+ f->writeUint16BE(_actListArr[i][j].a36.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a36.actFailIndex);
+ break;
+ case SCREEN_STATE: // 37
+ f->writeSint16BE(_actListArr[i][j].a37.timer);
+ f->writeSint16BE(_actListArr[i][j].a37.screenIndex);
+ f->writeByte(_actListArr[i][j].a37.newState);
+ break;
+ case INIT_LIPS: // 38
+ f->writeSint16BE(_actListArr[i][j].a38.timer);
+ f->writeSint16BE(_actListArr[i][j].a38.lipsObjIndex);
+ f->writeSint16BE(_actListArr[i][j].a38.objIndex);
+ f->writeByte(_actListArr[i][j].a38.dxLips);
+ f->writeByte(_actListArr[i][j].a38.dyLips);
+ break;
+ case INIT_STORY_MODE: // 39
+ f->writeSint16BE(_actListArr[i][j].a39.timer);
+ f->writeByte((_actListArr[i][j].a39.storyModeFl) ? 1 : 0);
+ break;
+ case WARN: // 40
+ f->writeSint16BE(_actListArr[i][j].a40.timer);
+ f->writeSint16BE(_actListArr[i][j].a40.stringIndex);
+ break;
+ case COND_BONUS: // 41
+ f->writeSint16BE(_actListArr[i][j].a41.timer);
+ f->writeSint16BE(_actListArr[i][j].a41.BonusIndex);
+ f->writeUint16BE(_actListArr[i][j].a41.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a41.actFailIndex);
+ break;
+ case TEXT_TAKE: // 42
+ f->writeSint16BE(_actListArr[i][j].a42.timer);
+ f->writeSint16BE(_actListArr[i][j].a42.objIndex);
+ break;
+ case YESNO: // 43
+ f->writeSint16BE(_actListArr[i][j].a43.timer);
+ f->writeSint16BE(_actListArr[i][j].a43.promptIndex);
+ f->writeUint16BE(_actListArr[i][j].a43.actYesIndex);
+ f->writeUint16BE(_actListArr[i][j].a43.actNoIndex);
+ break;
+ case STOP_ROUTE: // 44
+ f->writeSint16BE(_actListArr[i][j].a44.timer);
+ break;
+ case COND_ROUTE: // 45
+ f->writeSint16BE(_actListArr[i][j].a45.timer);
+ f->writeSint16BE(_actListArr[i][j].a45.routeIndex);
+ f->writeUint16BE(_actListArr[i][j].a45.actPassIndex);
+ f->writeUint16BE(_actListArr[i][j].a45.actFailIndex);
+ break;
+ case INIT_JUMPEXIT: // 46
+ f->writeSint16BE(_actListArr[i][j].a46.timer);
+ f->writeByte((_actListArr[i][j].a46.jumpExitFl) ? 1 : 0);
+ break;
+ case INIT_VIEW: // 47
+ f->writeSint16BE(_actListArr[i][j].a47.timer);
+ f->writeSint16BE(_actListArr[i][j].a47.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a47.viewx);
+ f->writeSint16BE(_actListArr[i][j].a47.viewy);
+ f->writeSint16BE(_actListArr[i][j].a47.direction);
+ break;
+ case INIT_OBJ_FRAME: // 48
+ f->writeSint16BE(_actListArr[i][j].a48.timer);
+ f->writeSint16BE(_actListArr[i][j].a48.objIndex);
+ f->writeSint16BE(_actListArr[i][j].a48.seqIndex);
+ f->writeSint16BE(_actListArr[i][j].a48.frameIndex);
+ break;
+ case OLD_SONG: // 49, Added by Strangerke for DOS versions
+ f->writeSint16BE(_actListArr[i][j].a49.timer);
+ f->writeUint16BE(_actListArr[i][j].a49.songIndex);
+ break;
+ default:
+ error("Unknown action %d", subElemType);
+ }
+ }
}
}
/*
* Find the index in the action list to be able to serialize the action to save game
*/
-
-void Scheduler::findAction(act* action, int16* index, int16* subElem) {
+void Scheduler::findAction(const act* action, int16* index, int16* subElem) {
assert(index && subElem);
if (!action) {
@@ -831,28 +1093,30 @@ void Scheduler::restoreSchedulerData(Common::ReadStream *in) {
void Scheduler::restoreEvents(Common::ReadStream *f) {
debugC(1, kDebugSchedule, "restoreEvents");
- event_t savedEvents[kMaxEvents]; // Convert event ptrs to indexes
-
uint32 saveTime = f->readUint32BE(); // time of save
int16 freeIndex = f->readSint16BE(); // Free list index
int16 headIndex = f->readSint16BE(); // Head of list index
int16 tailIndex = f->readSint16BE(); // Tail of list index
- f->read(savedEvents, sizeof(savedEvents));
- event_t *wrkEvent;
// Restore events indexes to pointers
for (int i = 0; i < kMaxEvents; i++) {
- wrkEvent = &savedEvents[i];
- _events[i] = *wrkEvent;
+ int16 index = f->readSint16BE();
+ int16 subElem = f->readSint16BE();
+
// fix up action pointer (to do better)
- int32 val = (size_t)_events[i].action;
- if ((val & 0xffff) == 0xffff) {
+ if ((index == -1) && (subElem == -1))
_events[i].action = 0;
- } else {
- _events[i].action = (act*)&_actListArr[val >> 16][val & 0xffff];
- }
- _events[i].prevEvent = (wrkEvent->prevEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->prevEvent ];
- _events[i].nextEvent = (wrkEvent->nextEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->nextEvent ];
+ else
+ _events[i].action = (act*)&_actListArr[index][subElem];
+
+ _events[i].localActionFl = (f->readByte() == 1) ? true : false;
+ _events[i].time = f->readUint32BE();
+
+ int16 prevIndex = f->readSint16BE();
+ int16 nextIndex = f->readSint16BE();
+
+ _events[i].prevEvent = (prevIndex == -1) ? (event_t *)0 : &_events[prevIndex];
+ _events[i].nextEvent = (nextIndex == -1) ? (event_t *)0 : &_events[nextIndex];
}
_freeEvent = (freeIndex == -1) ? 0 : &_events[freeIndex];
_headEvent = (headIndex == -1) ? 0 : &_events[headIndex];
@@ -860,7 +1124,7 @@ void Scheduler::restoreEvents(Common::ReadStream *f) {
// Adjust times to fit our time
uint32 curTime = getTicks();
- wrkEvent = _headEvent; // The earliest event
+ event_t *wrkEvent = _headEvent; // The earliest event
while (wrkEvent) { // While mature events found
wrkEvent->time = wrkEvent->time - saveTime + curTime;
wrkEvent = wrkEvent->nextEvent;
@@ -881,6 +1145,10 @@ void Scheduler::insertAction(act *action) {
case AGSCHEDULE:
curEvent->localActionFl = false; // Lasts over a new screen
break;
+ // Workaround: When dying, switch to storyMode in order to block the keyboard.
+ case GAMEOVER:
+ _vm->getGameStatus().storyModeFl = true;
+ // No break on purpose
default:
curEvent->localActionFl = true; // Rest are for current screen only
break;
@@ -980,7 +1248,7 @@ event_t *Scheduler::doAction(event_t *curEvent) {
insertActionList(action->a11.actFailIndex);
break;
case TEXT: // act12: Text box (CF WARN)
- Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file
+ Utils::notifyBox(_vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file
break;
case SWAP_IMAGES: // act13: Swap 2 object images
_vm->_object->swapImages(action->a13.objIndex1, action->a13.objIndex2);
@@ -1105,7 +1373,7 @@ event_t *Scheduler::doAction(event_t *curEvent) {
gameStatus.storyModeFl = action->a39.storyModeFl;
break;
case WARN: // act40: Text box (CF TEXT)
- Utils::Box(kBoxOk, "%s", _vm->_file->fetchString(action->a40.stringIndex));
+ Utils::notifyBox(_vm->_file->fetchString(action->a40.stringIndex));
break;
case COND_BONUS: // act41: Perform action if got bonus
if (_points[action->a41.BonusIndex].scoredFl)
@@ -1114,10 +1382,10 @@ event_t *Scheduler::doAction(event_t *curEvent) {
insertActionList(action->a41.actFailIndex);
break;
case TEXT_TAKE: // act42: Text box with "take" message
- Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(_vm->_object->_objects[action->a42.objIndex].nounIndex, TAKE_NAME));
+ Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(_vm->_object->_objects[action->a42.objIndex].nounIndex, TAKE_NAME)));
break;
case YESNO: // act43: Prompt user for Yes or No
- if (Utils::Box(kBoxYesNo, "%s", _vm->_file->fetchString(action->a43.promptIndex)) != 0)
+ if (Utils::yesNoBox(_vm->_file->fetchString(action->a43.promptIndex)))
insertActionList(action->a43.actYesIndex);
else
insertActionList(action->a43.actNoIndex);
@@ -1267,28 +1535,22 @@ void Scheduler_v1d::runScheduler() {
}
void Scheduler_v1d::promptAction(act *action) {
- Utils::Box(kBoxPrompt, "%s", _vm->_file->fetchString(action->a3.promptIndex));
-
- warning("STUB: doAction(act3)");
- // TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block
-#if 0
- char response[256];
- // TODO: Put user input in response
-
- Utils::strlwr(response);
- if (action->a3.encodedFl) {
- warning("Encrypted flag set");
- decodeString(response);
- }
+ Common::String response;
+
+ response = Utils::promptBox(_vm->_file->fetchString(action->a3.promptIndex));
+
+ response.toLowercase();
+
+ char resp[256];
+ strncpy(resp, response.c_str(), 256);
- if (strstr(response, _vm->_file->fetchString(action->a3.responsePtr[0]))
+ if (action->a3.encodedFl)
+ decodeString(resp);
+
+ if (strstr(resp, _vm->_file->fetchString(action->a3.responsePtr[0])))
insertActionList(action->a3.actPassIndex);
else
insertActionList(action->a3.actFailIndex);
-#endif
-
- // HACK: As the answer is not read, currently it's always considered correct
- insertActionList(action->a3.actPassIndex);
}
/**
@@ -1316,19 +1578,22 @@ const char *Scheduler_v2d::getCypher() const {
}
void Scheduler_v2d::promptAction(act *action) {
- Utils::Box(kBoxPrompt, "%s", _vm->_file->fetchString(action->a3.promptIndex));
- warning("STUB: doAction(act3), expecting answer %s", _vm->_file->fetchString(action->a3.responsePtr[0]));
+ Common::String response;
+
+ response = Utils::promptBox(_vm->_file->fetchString(action->a3.promptIndex));
+ response.toLowercase();
- // TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block
-#if 0
- char *response = Utils::Box(BOX_PROMPT, "%s", _vm->_file->fetchString(action->a3.promptIndex));
+ debug(1, "doAction(act3), expecting answer %s", _vm->_file->fetchString(action->a3.responsePtr[0]));
bool found = false;
- char *tmpStr; // General purpose string ptr
+ const char *tmpStr; // General purpose string ptr
- for (dx = 0; !found && (action->a3.responsePtr[dx] != -1); dx++) {
+ char resp[256];
+ strncpy(resp, response.c_str(), 256);
+
+ for (int dx = 0; !found && (action->a3.responsePtr[dx] != -1); dx++) {
tmpStr = _vm->_file->fetchString(action->a3.responsePtr[dx]);
- if (strstr(Utils::strlwr(response) , tmpStr))
+ if (strstr(Utils::strlwr(resp), tmpStr))
found = true;
}
@@ -1336,10 +1601,6 @@ void Scheduler_v2d::promptAction(act *action) {
insertActionList(action->a3.actPassIndex);
else
insertActionList(action->a3.actFailIndex);
-#endif
-
- // HACK: As the answer is not read, currently it's always considered correct
- insertActionList(action->a3.actPassIndex);
}
/**
diff --git a/engines/hugo/schedule.h b/engines/hugo/schedule.h
index 953e9affea..a066fc63c4 100644
--- a/engines/hugo/schedule.h
+++ b/engines/hugo/schedule.h
@@ -583,7 +583,7 @@ protected:
void delEventType(const action_t actTypeDel);
void delQueue(event_t *curEvent);
- void findAction(act* action, int16* index, int16* subElem);
+ void findAction(const act* action, int16* index, int16* subElem);
void insertAction(act *action);
void readAct(Common::ReadStream &in, act &curAct);
void restoreActions(Common::ReadStream *f);
diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index 5ef843977f..d657eb96a6 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -32,11 +32,14 @@
// sound.c - sound effects and music support
+#include "common/debug.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "common/config-manager.h"
#include "audio/decoders/raw.h"
#include "audio/audiostream.h"
+#include "audio/midiparser.h"
#include "hugo/hugo.h"
#include "hugo/game.h"
@@ -46,220 +49,80 @@
namespace Hugo {
-MidiPlayer::MidiPlayer(MidiDriver *driver)
- : _driver(driver), _parser(0), _midiData(0) {
+MidiPlayer::MidiPlayer() {
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = MidiDriver::createMidi(dev);
assert(_driver);
- memset(_channelsTable, 0, sizeof(_channelsTable));
- for (int i = 0; i < kNumbChannels; i++) {
- _channelsVolume[i] = 127;
- }
- _isLooping = false;
- _isPlaying = false;
_paused = false;
- _masterVolume = 0;
-}
-
-MidiPlayer::~MidiPlayer() {
- close();
-}
-
-bool MidiPlayer::isPlaying() const {
- return _isPlaying;
-}
-
-int MidiPlayer::getVolume() const {
- return _masterVolume;
-}
-
-void MidiPlayer::setLooping(bool loop) {
- _isLooping = loop;
-}
-MidiChannel *MidiPlayer::allocateChannel() {
- return 0;
-}
-MidiChannel *MidiPlayer::getPercussionChannel() {
- return 0;
-}
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->sendGMReset();
-uint32 MidiPlayer::getBaseTempo() {
- return _driver ? _driver->getBaseTempo() : 0;
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MidiPlayer::play(uint8 *stream, uint16 size) {
debugC(3, kDebugMusic, "MidiPlayer::play");
- if (!stream) {
- stop();
- return;
- }
+
+ Common::StackLock lock(_mutex);
stop();
+ if (!stream)
+ return;
+
_midiData = (uint8 *)malloc(size);
if (_midiData) {
memcpy(_midiData, stream, size);
- _mutex.lock();
- syncVolume();
+
+ syncVolume(); // FIXME: syncVolume calls setVolume which in turn also locks the mutex! ugh
+
+ _parser = MidiParser::createParser_SMF();
_parser->loadMusic(_midiData, size);
_parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
_isLooping = false;
_isPlaying = true;
- _mutex.unlock();
- }
-}
-
-void MidiPlayer::stop() {
- debugC(3, kDebugMusic, "MidiPlayer::stop");
- _mutex.lock();
- if (_isPlaying) {
- _isPlaying = false;
- _parser->unloadMusic();
- free(_midiData);
- _midiData = 0;
}
- _mutex.unlock();
}
void MidiPlayer::pause(bool p) {
_paused = p;
- for (int i = 0; i < kNumbChannels; ++i) {
+ for (int i = 0; i < kNumChannels; ++i) {
if (_channelsTable[i]) {
_channelsTable[i]->volume(_paused ? 0 : _channelsVolume[i] * _masterVolume / 255);
}
}
}
-void MidiPlayer::updateTimer() {
- if (_paused) {
- return;
- }
+void MidiPlayer::onTimer() {
+ Common::StackLock lock(_mutex);
- _mutex.lock();
- if (_isPlaying) {
+ if (!_paused && _isPlaying && _parser) {
_parser->onTimer();
}
- _mutex.unlock();
-}
-
-void MidiPlayer::adjustVolume(int diff) {
- debugC(3, kDebugMusic, "MidiPlayer::adjustVolume");
- setVolume(_masterVolume + diff);
-}
-
-void MidiPlayer::syncVolume() {
- int volume = ConfMan.getInt("music_volume");
- if (ConfMan.getBool("mute")) {
- volume = -1;
- }
- debugC(2, kDebugMusic, "Syncing music volume to %d", volume);
- setVolume(volume);
}
-void MidiPlayer::setVolume(int volume) {
- debugC(3, kDebugMusic, "MidiPlayer::setVolume");
- _masterVolume = CLIP(volume, 0, 255);
- _mutex.lock();
- for (int i = 0; i < kNumbChannels; ++i) {
- if (_channelsTable[i]) {
- _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
- }
- }
- _mutex.unlock();
-}
-
-void MidiPlayer::setChannelVolume(int channel) {
- int newVolume = _channelsVolume[channel] * _masterVolume / 255;
- debugC(3, kDebugMusic, "Music channel %d: volume %d->%d",
- channel, _channelsVolume[channel], newVolume);
- _channelsTable[channel]->volume(newVolume);
-}
-
-int MidiPlayer::open() {
- if (!_driver)
- return 255;
- int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->sendGMReset();
-
- _parser = MidiParser::createParser_SMF();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(_driver->getBaseTempo());
- _driver->setTimerCallback(this, &timerCallback);
-
- return 0;
-}
-
-void MidiPlayer::close() {
- stop();
- _mutex.lock();
- _driver->setTimerCallback(0, 0);
- _driver->close();
- delete _driver;
- _driver = 0;
- if (_parser)
- _parser->setMidiDriver(0);
- delete _parser;
- _mutex.unlock();
-}
-
-void MidiPlayer::send(uint32 b) {
- byte volume, ch = (byte)(b & 0xF);
- debugC(9, kDebugMusic, "MidiPlayer::send, channel %d (volume is %d)", ch, _channelsVolume[ch]);
- switch (b & 0xFFF0) {
- case 0x07B0: // volume change
- volume = (byte)((b >> 16) & 0x7F);
- _channelsVolume[ch] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- debugC(8, kDebugMusic, "Volume change, channel %d volume %d", ch, volume);
- break;
- case 0x7BB0: // all notes off
- debugC(8, kDebugMusic, "All notes off, channel %d", ch);
- if (!_channelsTable[ch]) { // channel not yet allocated, no need to send the event
- return;
- }
- break;
- }
-
- if (!_channelsTable[ch]) {
- _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- if (_channelsTable[ch])
- setChannelVolume(ch);
- }
- if (_channelsTable[ch]) {
- _channelsTable[ch]->send(b);
+void MidiPlayer::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // If a new channel is allocated during the playback, make sure
+ // its volume is correctly initialized.
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
}
-}
-void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // end of Track
- if (_isLooping) {
- _parser->jumpToTick(0);
- } else {
- stop();
- }
- break;
- default:
-// warning("Unhandled meta event: %02x", type);
- break;
- }
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
-void MidiPlayer::timerCallback(void *p) {
- MidiPlayer *player = (MidiPlayer *)p;
-
- player->updateTimer();
-}
SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) {
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- MidiDriver *driver = MidiDriver::createMidi(dev);
-
- _midiPlayer = new MidiPlayer(driver);
+ _midiPlayer = new MidiPlayer();
_speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate());
_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
@@ -361,7 +224,7 @@ void SoundHandler::playSound(int16 sound, const byte priority) {
* Initialize for MCI sound and midi
*/
void SoundHandler::initSound() {
- _midiPlayer->open();
+ //_midiPlayer->open();
}
void SoundHandler::syncVolume() {
diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h
index 49e78a4aeb..d5f51704aa 100644
--- a/engines/hugo/sound.h
+++ b/engines/hugo/sound.h
@@ -34,58 +34,26 @@
#define HUGO_SOUND_H
#include "audio/mixer.h"
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
#include "audio/softsynth/pcspk.h"
namespace Hugo {
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public Audio::MidiPlayer {
public:
- MidiPlayer(MidiDriver *driver);
- ~MidiPlayer();
+ MidiPlayer();
- bool isPlaying() const;
- int getVolume() const;
-
- void adjustVolume(int diff);
void pause(bool p);
void play(uint8 *stream, uint16 size);
- void setChannelVolume(int channel);
- void setLooping(bool loop);
- void setVolume(int volume);
- void stop();
- void syncVolume();
- void updateTimer();
-
- // MidiDriver interface
- int open();
-
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel();
-
- void close();
- void metaEvent(byte type, byte *data, uint16 length);
- void send(uint32 b);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
uint32 getBaseTempo();
-private:
- static void timerCallback(void *p);
-
- static const int kNumbChannels = 16;
+ // Overload Audio::MidiPlayer method
+ virtual void sendToChannel(byte channel, uint32 b);
+ virtual void onTimer();
- MidiDriver *_driver;
- MidiParser *_parser;
- uint8 *_midiData;
- bool _isLooping;
- bool _isPlaying;
+private:
bool _paused;
- int _masterVolume;
- MidiChannel *_channelsTable[kNumbChannels];
- uint8 _channelsVolume[kNumbChannels];
- Common::Mutex _mutex;
};
class SoundHandler {
diff --git a/engines/hugo/util.cpp b/engines/hugo/util.cpp
index f342d4e354..6846bc98af 100644
--- a/engines/hugo/util.cpp
+++ b/engines/hugo/util.cpp
@@ -41,10 +41,12 @@
namespace Hugo {
+namespace Utils {
+
/**
* Returns index (0 to 7) of first 1 in supplied byte, or 8 if not found
*/
-int Utils::firstBit(byte data) {
+int firstBit(byte data) {
if (!data)
return 8;
@@ -60,7 +62,7 @@ int Utils::firstBit(byte data) {
/**
* Returns index (0 to 7) of last 1 in supplied byte, or 8 if not found
*/
-int Utils::lastBit(byte data) {
+int lastBit(byte data) {
if (!data)
return 8;
@@ -76,7 +78,7 @@ int Utils::lastBit(byte data) {
/**
* Reverse the bit order in supplied byte
*/
-void Utils::reverseByte(byte *data) {
+void reverseByte(byte *data) {
byte maskIn = 0x80;
byte maskOut = 0x01;
byte result = 0;
@@ -89,58 +91,34 @@ void Utils::reverseByte(byte *data) {
*data = result;
}
-char *Utils::Box(box_t dismiss, const char *s, ...) {
- static char buffer[kMaxStrLength + 1]; // Format text into this
+void notifyBox(const Common::String &msg) {
+ if (msg.empty())
+ return;
- if (!s)
- return 0; // NULL strings catered for
+ GUI::MessageDialog dialog(msg, "OK");
+ dialog.runModal();
+}
- if (s[0] == '\0')
- return 0;
+Common::String promptBox(const Common::String &msg) {
+ if (msg.empty())
+ return Common::String();
- if (strlen(s) > kMaxStrLength - 100) { // Test length
- warning("String too long: '%s'", s);
- return 0;
- }
+ EntryDialog dialog(msg, "OK", "");
- va_list marker;
- va_start(marker, s);
- vsprintf(buffer, s, marker); // Format string into buffer
- va_end(marker);
+ dialog.runModal();
- if (buffer[0] == '\0')
- return 0;
+ return dialog.getEditString();
+}
- switch(dismiss) {
- case kBoxAny:
- case kBoxOk: {
- GUI::MessageDialog dialog(buffer, "OK");
- dialog.runModal();
- break;
- }
- case kBoxYesNo: {
- GUI::MessageDialog dialog(buffer, "YES", "NO");
- if (dialog.runModal() == GUI::kMessageOK)
- return buffer;
+bool yesNoBox(const Common::String &msg) {
+ if (msg.empty())
return 0;
- break;
- }
- case kBoxPrompt: {
- // TODO: Some boxes (i.e. the combination code for the shed), needs to return an input.
- warning("Box: unhandled BOX_PROMPT");
- int boxTime = strlen(buffer) * 30;
- GUI::TimedMessageDialog dialog(buffer, MAX(1500, boxTime));
- dialog.runModal();
- break;
- }
- default:
- error("Unknown BOX Type %d", dismiss);
- }
- return buffer;
+ GUI::MessageDialog dialog(msg, "YES", "NO");
+ return (dialog.runModal() == GUI::kMessageOK);
}
-char *Utils::strlwr(char *buffer) {
+char *strlwr(char *buffer) {
char *result = buffer;
while (*buffer != '\0') {
@@ -152,4 +130,6 @@ char *Utils::strlwr(char *buffer) {
return result;
}
+} // End of namespace Utils
+
} // End of namespace Hugo
diff --git a/engines/hugo/util.h b/engines/hugo/util.h
index 10376c8381..85fef01a6e 100644
--- a/engines/hugo/util.h
+++ b/engines/hugo/util.h
@@ -40,16 +40,36 @@ enum seqTextUtil {
};
namespace Utils {
-static const int kMaxStrLength = 1024;
int firstBit(byte data);
int lastBit(byte data);
void reverseByte(byte *data);
-char *Box(box_t, const char *, ...) GCC_PRINTF(2, 3);
+/**
+ * Show a dialog notifying the user about something, with
+ * only a simple "OK" button to dismiss it.
+ */
+void notifyBox(const Common::String &msg);
+
+/**
+ * Show a dialog prompting the player to input some text.
+ */
+Common::String promptBox(const Common::String &msg);
+
+/**
+ * Show a dialog prompting the player for a "yes"/"no" choice.
+ */
+bool yesNoBox(const Common::String &msg);
+
+/**
+ * Convert a string to lower case, in place.
+ * @param buffer string to convert to lower case
+ * @return the string which was passed in
+ */
char *strlwr(char *buffer);
-}
+
+} // End of namespace Utils
} // End of namespace Hugo
diff --git a/engines/kyra/animator_hof.cpp b/engines/kyra/animator_hof.cpp
index e1471239da..a563bc2b4f 100644
--- a/engines/kyra/animator_hof.cpp
+++ b/engines/kyra/animator_hof.cpp
@@ -26,7 +26,7 @@
#include "kyra/kyra_hof.h"
#include "kyra/wsamovie.h"
-#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/animator_lok.cpp b/engines/kyra/animator_lok.cpp
index b906d3a724..452d5e8062 100644
--- a/engines/kyra/animator_lok.cpp
+++ b/engines/kyra/animator_lok.cpp
@@ -23,16 +23,13 @@
*
*/
-#include "common/endian.h"
-
#include "kyra/kyra_lok.h"
#include "kyra/screen.h"
#include "kyra/animator_lok.h"
#include "kyra/sprites.h"
-#include "common/system.h"
-
namespace Kyra {
+
Animator_LoK::Animator_LoK(KyraEngine_LoK *vm, OSystem *system) {
_vm = vm;
_screen = vm->screen();
diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp
index 12f1061432..47c0e3b03a 100644
--- a/engines/kyra/animator_mr.cpp
+++ b/engines/kyra/animator_mr.cpp
@@ -27,6 +27,8 @@
#include "kyra/resource.h"
#include "kyra/wsamovie.h"
+#include "common/system.h"
+
namespace Kyra {
void KyraEngine_MR::restorePage3() {
@@ -336,7 +338,6 @@ void KyraEngine_MR::setupSceneAnimObject(int animId, uint16 flags, int x, int y,
if (flags & 8) {
_sceneAnimMovie[animId]->open(filename, 1, 0);
- musicUpdate(0);
if (_sceneAnimMovie[animId]->opened()) {
anim.wsaFlag = 1;
if (x2 == -1)
diff --git a/engines/kyra/animator_tim.cpp b/engines/kyra/animator_tim.cpp
index 0290b2aa7f..fa42042bef 100644
--- a/engines/kyra/animator_tim.cpp
+++ b/engines/kyra/animator_tim.cpp
@@ -23,9 +23,6 @@
*
*/
-#include "common/endian.h"
-#include "common/system.h"
-
#include "kyra/script_tim.h"
#include "kyra/wsamovie.h"
#include "kyra/screen_lol.h"
@@ -36,6 +33,8 @@
#include "kyra/screen_v2.h"
#endif
+#include "common/system.h"
+
namespace Kyra {
#ifdef ENABLE_LOL
diff --git a/engines/kyra/animator_v2.cpp b/engines/kyra/animator_v2.cpp
index b06dffd36f..07ff4456e5 100644
--- a/engines/kyra/animator_v2.cpp
+++ b/engines/kyra/animator_v2.cpp
@@ -25,9 +25,6 @@
#include "kyra/kyra_v2.h"
#include "kyra/screen_v2.h"
-#include "kyra/wsamovie.h"
-
-#include "common/endian.h"
namespace Kyra {
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index 301271ad3c..066648b96f 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -23,18 +23,15 @@
*
*/
-
-#include "common/config-manager.h"
-#include "common/system.h"
#include "kyra/debugger.h"
#include "kyra/kyra_lok.h"
-#include "kyra/kyra_v2.h"
#include "kyra/kyra_hof.h"
-#include "kyra/screen.h"
#include "kyra/timer.h"
#include "kyra/resource.h"
#include "kyra/lol.h"
+#include "common/system.h"
+
namespace Kyra {
Debugger::Debugger(KyraEngine_v1 *vm)
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 6c111a6601..87cda9f3b6 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -22,17 +22,17 @@
* $Id$
*/
-#include "kyra/kyra_v1.h"
#include "kyra/kyra_lok.h"
#include "kyra/lol.h"
#include "kyra/kyra_hof.h"
#include "kyra/kyra_mr.h"
-
#include "common/config-manager.h"
-#include "engines/advancedDetector.h"
+#include "common/system.h"
#include "common/savefile.h"
+#include "engines/advancedDetector.h"
+
#include "base/plugins.h"
struct KYRAGameDescription {
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp
index ff7bf233d2..849b65a24b 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui.cpp
@@ -25,11 +25,11 @@
#include "kyra/gui.h"
-#include "kyra/screen.h"
#include "kyra/text.h"
#include "kyra/wsamovie.h"
#include "common/savefile.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp
index 56971e563c..26e0d8f18a 100644
--- a/engines/kyra/gui_hof.cpp
+++ b/engines/kyra/gui_hof.cpp
@@ -23,15 +23,13 @@
*
*/
-#include "kyra/kyra_v1.h"
+#include "kyra/gui_hof.h"
#include "kyra/kyra_hof.h"
-#include "kyra/screen.h"
-#include "kyra/wsamovie.h"
#include "kyra/timer.h"
-#include "kyra/sound.h"
#include "kyra/resource.h"
+#include "kyra/sound.h"
-#include "common/savefile.h"
+#include "common/system.h"
#include "graphics/scaler.h"
diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp
index b7952eb81e..c31cbe3db2 100644
--- a/engines/kyra/gui_lok.cpp
+++ b/engines/kyra/gui_lok.cpp
@@ -23,18 +23,13 @@
*
*/
+#include "kyra/gui_lok.h"
#include "kyra/kyra_lok.h"
-#include "kyra/screen.h"
-#include "kyra/script.h"
-#include "kyra/text.h"
#include "kyra/animator_lok.h"
-#include "kyra/sound.h"
-#include "kyra/gui_lok.h"
+#include "kyra/text.h"
#include "kyra/timer.h"
#include "kyra/util.h"
-#include "kyra/item.h"
-#include "common/config-manager.h"
#include "common/savefile.h"
#include "common/system.h"
@@ -564,7 +559,6 @@ int GUI_LoK::resumeGame(Button *button) {
void GUI_LoK::setupSavegames(Menu &menu, int num) {
Common::InSaveFile *in;
- static char savenames[5][35];
uint8 startSlot;
assert(num <= 5);
@@ -583,11 +577,11 @@ void GUI_LoK::setupSavegames(Menu &menu, int num) {
KyraEngine_LoK::SaveHeader header;
for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); i++) {
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) {
- Common::strlcpy(savenames[i], header.description.c_str(), ARRAYSIZE(savenames[0]));
+ Common::strlcpy(_savegameNames[i], header.description.c_str(), ARRAYSIZE(_savegameNames[0]));
- Util::convertISOToDOS(savenames[i]);
+ Util::convertISOToDOS(_savegameNames[i]);
- menu.item[i].itemString = savenames[i];
+ menu.item[i].itemString = _savegameNames[i];
menu.item[i].enabled = 1;
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
delete in;
diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h
index 05dd1533b1..084a798de4 100644
--- a/engines/kyra/gui_lok.h
+++ b/engines/kyra/gui_lok.h
@@ -27,6 +27,7 @@
#define KYRA_GUI_LOK_H
#include "kyra/gui.h"
+#include "kyra/screen_lok.h"
namespace Kyra {
@@ -166,6 +167,7 @@ private:
uint8 _toplevelMenu;
int _savegameOffset;
char _savegameName[35];
+ char _savegameNames[5][35];
const char *_specialSavegameString;
Button::Callback _scrollUpFunctor;
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index 07fbf1664d..2625347d50 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -25,13 +25,15 @@
#ifdef ENABLE_LOL
+#include "kyra/gui_lol.h"
#include "kyra/lol.h"
#include "kyra/screen_lol.h"
-#include "kyra/gui_lol.h"
#include "kyra/resource.h"
#include "kyra/util.h"
+#include "kyra/sound.h"
#include "common/savefile.h"
+#include "common/system.h"
#include "common/config-manager.h"
#include "graphics/scaler.h"
diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp
index a04ec49324..6eca24fd46 100644
--- a/engines/kyra/gui_mr.cpp
+++ b/engines/kyra/gui_mr.cpp
@@ -26,12 +26,11 @@
#include "kyra/gui_mr.h"
#include "kyra/kyra_mr.h"
#include "kyra/text_mr.h"
-#include "kyra/wsamovie.h"
#include "kyra/resource.h"
-#include "kyra/sound.h"
#include "kyra/timer.h"
+#include "kyra/sound.h"
-#include "common/savefile.h"
+#include "common/system.h"
#include "graphics/scaler.h"
@@ -830,8 +829,6 @@ void KyraEngine_MR::processAlbum() {
checkInput(buttonList);
removeInputTop();
- musicUpdate(0);
-
if (_album.curPage != _album.nextPage) {
int oldPage = _album.curPage;
_album.curPage = _album.nextPage;
@@ -1085,11 +1082,6 @@ void GUI_MR::flagButtonDisable(Button *button) {
}
}
-void GUI_MR::getInput() {
- _vm->musicUpdate(0);
- GUI_v2::getInput();
-}
-
const char *GUI_MR::getMenuTitle(const Menu &menu) {
if (!menu.menuNameId)
return 0;
@@ -1173,8 +1165,6 @@ int GUI_MR::quitGame(Button *caller) {
int GUI_MR::optionsButton(Button *button) {
PauseTimer pause(*_vm->_timer);
- _vm->musicUpdate(0);
-
_screen->hideMouse();
updateButton(&_vm->_mainButtonData[0]);
_screen->showMouse();
@@ -1200,7 +1190,6 @@ int GUI_MR::optionsButton(Button *button) {
int oldHandItem = _vm->_itemInHand;
_screen->setMouseCursor(0, 0, _vm->getShapePtr(0));
- _vm->musicUpdate(0);
_displayMenu = true;
for (int i = 0; i < 4; ++i) {
@@ -1226,8 +1215,6 @@ int GUI_MR::optionsButton(Button *button) {
_currentMenu = &_mainMenu;
- _vm->musicUpdate(0);
-
if (_vm->_menuDirectlyToLoad) {
backUpPage1(_vm->_screenBuffer);
@@ -1256,7 +1243,6 @@ int GUI_MR::optionsButton(Button *button) {
_isDeathMenu = false;
}
- _vm->musicUpdate(0);
backUpPage1(_vm->_screenBuffer);
initMenu(*_currentMenu);
_madeSave = false;
@@ -1407,7 +1393,6 @@ int GUI_MR::gameOptions(Button *caller) {
}
void GUI_MR::setupOptionsButtons() {
- _vm->musicUpdate(0);
if (_vm->_configWalkspeed == 3)
_gameOptions.item[0].itemId = 28;
else
diff --git a/engines/kyra/gui_mr.h b/engines/kyra/gui_mr.h
index 89aaa447d1..b104626db7 100644
--- a/engines/kyra/gui_mr.h
+++ b/engines/kyra/gui_mr.h
@@ -50,8 +50,6 @@ public:
void createScreenThumbnail(Graphics::Surface &dst);
private:
- void getInput();
-
const char *getMenuTitle(const Menu &menu);
const char *getMenuItemTitle(const MenuItem &menuItem);
const char *getMenuItemLabel(const MenuItem &menuItem);
diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp
index 2247a0ca2e..01922de7cf 100644
--- a/engines/kyra/gui_v2.cpp
+++ b/engines/kyra/gui_v2.cpp
@@ -24,12 +24,12 @@
*/
#include "kyra/gui_v2.h"
-#include "kyra/kyra_v2.h"
#include "kyra/screen_v2.h"
#include "kyra/text.h"
#include "kyra/util.h"
#include "common/savefile.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/items_hof.cpp b/engines/kyra/items_hof.cpp
index 6a78a77c23..d460698272 100644
--- a/engines/kyra/items_hof.cpp
+++ b/engines/kyra/items_hof.cpp
@@ -25,6 +25,8 @@
#include "kyra/kyra_hof.h"
+#include "common/system.h"
+
namespace Kyra {
int KyraEngine_HoF::checkItemCollision(int x, int y) {
diff --git a/engines/kyra/items_lok.cpp b/engines/kyra/items_lok.cpp
index 322314e3ad..ed1299d239 100644
--- a/engines/kyra/items_lok.cpp
+++ b/engines/kyra/items_lok.cpp
@@ -24,17 +24,9 @@
*/
#include "kyra/kyra_lok.h"
-#include "kyra/seqplayer.h"
-#include "kyra/screen.h"
-#include "kyra/resource.h"
-#include "kyra/sound.h"
-#include "kyra/sprites.h"
-#include "kyra/wsamovie.h"
#include "kyra/animator_lok.h"
-#include "kyra/text.h"
#include "common/system.h"
-#include "common/savefile.h"
namespace Kyra {
diff --git a/engines/kyra/items_mr.cpp b/engines/kyra/items_mr.cpp
index 2bc268ace3..5659876307 100644
--- a/engines/kyra/items_mr.cpp
+++ b/engines/kyra/items_mr.cpp
@@ -26,6 +26,8 @@
#include "kyra/kyra_mr.h"
#include "kyra/timer.h"
+#include "common/system.h"
+
namespace Kyra {
void KyraEngine_MR::removeTrashItems() {
diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp
index 990e55bcf2..de6aa55b08 100644
--- a/engines/kyra/kyra_hof.cpp
+++ b/engines/kyra/kyra_hof.cpp
@@ -23,18 +23,13 @@
*
*/
-#include "kyra/kyra_v1.h"
#include "kyra/kyra_hof.h"
-#include "kyra/screen.h"
#include "kyra/resource.h"
-#include "kyra/wsamovie.h"
-#include "kyra/sound.h"
-#include "kyra/script.h"
-#include "kyra/script_tim.h"
#include "kyra/text_hof.h"
#include "kyra/timer.h"
#include "kyra/debugger.h"
#include "kyra/util.h"
+#include "kyra/sound.h"
#include "common/system.h"
#include "common/config-manager.h"
@@ -87,7 +82,9 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn
_pathfinderFlag = 0;
_mouseX = _mouseY = 0;
+ _nextIdleAnim = 0;
_lastIdleScript = -1;
+ _useSceneIdleAnim = false;
_currentTalkSections.STATim = 0;
_currentTalkSections.TLKTim = 0;
@@ -145,6 +142,11 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn
_menu = 0;
_chatIsNote = false;
memset(&_npcScriptData, 0, sizeof(_npcScriptData));
+
+ _setCharPalFinal = false;
+ _useCharPal = false;
+
+ memset(_characterFacingCountTable, 0, sizeof(_characterFacingCountTable));
}
KyraEngine_HoF::~KyraEngine_HoF() {
@@ -1135,8 +1137,6 @@ void KyraEngine_HoF::restorePage0() {
}
void KyraEngine_HoF::updateCharPal(int unk1) {
- static bool unkVar1 = false;
-
if (!_useCharPal)
return;
@@ -1152,12 +1152,12 @@ void KyraEngine_HoF::updateCharPal(int unk1) {
++src;
}
_screen->setScreenPalette(_screen->getPalette(0));
- unkVar1 = true;
+ _setCharPalFinal = true;
_charPalEntry = palEntry;
- } else if (unkVar1 || !unk1) {
+ } else if (_setCharPalFinal || !unk1) {
_screen->getPalette(0).copy(_scenePal, palEntry << 4, 16, 112);
_screen->setScreenPalette(_screen->getPalette(0));
- unkVar1 = false;
+ _setCharPalFinal = false;
}
}
@@ -1274,15 +1274,14 @@ int KyraEngine_HoF::getCharacterWalkspeed() const {
return _timer->getDelay(0);
}
-void KyraEngine_HoF::updateCharAnimFrame(int charId, int *table) {
- static int unkTable1[] = { 0, 0 };
- static const int unkTable2[] = { 17, 0 };
- static const int unkTable3[] = { 10, 0 };
- static const int unkTable4[] = { 24, 0 };
- static const int unkTable5[] = { 19, 0 };
- static const int unkTable6[] = { 21, 0 };
- static const int unkTable7[] = { 31, 0 };
- static const int unkTable8[] = { 26, 0 };
+void KyraEngine_HoF::updateCharAnimFrame(int *table) {
+ static const int unkFrame1 = 17;
+ static const int unkFrame2 = 10;
+ static const int unkFrame3 = 24;
+ static const int unkFrame4 = 19;
+ static const int unkFrame5 = 21;
+ static const int unkFrame6 = 31;
+ static const int unkFrame7 = 26;
Character *character = &_mainCharacter;
++character->animFrame;
@@ -1297,46 +1296,46 @@ void KyraEngine_HoF::updateCharAnimFrame(int charId, int *table) {
}
if (!facing) {
- ++unkTable1[charId];
+ ++_characterFacingCountTable[0];
} else if (facing == 4) {
- ++unkTable1[charId+1];
+ ++_characterFacingCountTable[1];
} else if (facing == 7 || facing == 1 || facing == 5 || facing == 3) {
if (facing == 7 || facing == 1) {
- if (unkTable1[charId] > 2)
+ if (_characterFacingCountTable[0] > 2)
facing = 0;
} else {
- if (unkTable1[charId+1] > 2)
+ if (_characterFacingCountTable[1] > 2)
facing = 4;
}
- unkTable1[charId] = 0;
- unkTable1[charId+1] = 0;
+ _characterFacingCountTable[0] = 0;
+ _characterFacingCountTable[1] = 0;
}
if (facing == 0) {
- if (character->animFrame < unkTable8[charId])
- character->animFrame = unkTable8[charId];
+ if (character->animFrame < unkFrame7)
+ character->animFrame = unkFrame7;
- if (character->animFrame > unkTable7[charId])
- character->animFrame = unkTable8[charId];
+ if (character->animFrame > unkFrame6)
+ character->animFrame = unkFrame7;
} else if (facing == 4) {
- if (character->animFrame < unkTable5[charId])
- character->animFrame = unkTable5[charId];
+ if (character->animFrame < unkFrame4)
+ character->animFrame = unkFrame4;
- if (character->animFrame > unkTable4[charId])
- character->animFrame = unkTable5[charId];
+ if (character->animFrame > unkFrame3)
+ character->animFrame = unkFrame4;
} else {
- if (character->animFrame > unkTable5[charId])
- character->animFrame = unkTable6[charId];
+ if (character->animFrame > unkFrame4)
+ character->animFrame = unkFrame5;
- if (character->animFrame == unkTable2[charId])
- character->animFrame = unkTable3[charId];
+ if (character->animFrame == unkFrame1)
+ character->animFrame = unkFrame2;
- if (character->animFrame > unkTable2[charId])
- character->animFrame = unkTable3[charId] + 2;
+ if (character->animFrame > unkFrame1)
+ character->animFrame = unkFrame2 + 2;
}
- updateCharacterAnim(charId);
+ updateCharacterAnim(0);
}
bool KyraEngine_HoF::checkCharCollision(int x, int y) {
@@ -1393,12 +1392,11 @@ void KyraEngine_HoF::showIdleAnim() {
if (queryGameFlag(0x159) && _flags.isTalkie)
return;
- static bool scriptAnimation = false;
- if (!scriptAnimation && _flags.isTalkie) {
- scriptAnimation = true;
+ if (!_useSceneIdleAnim && _flags.isTalkie) {
+ _useSceneIdleAnim = true;
randomSceneChat();
} else {
- scriptAnimation = false;
+ _useSceneIdleAnim = false;
if (_characterShapeFile > 8)
return;
diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h
index b862a89dd0..308698484d 100644
--- a/engines/kyra/kyra_hof.h
+++ b/engines/kyra/kyra_hof.h
@@ -574,13 +574,16 @@ protected:
// character
bool _useCharPal;
+ bool _setCharPalFinal;
int _charPalEntry;
uint8 _charPalTable[16];
void updateCharPal(int unk1);
void setCharPalEntry(int entry, int value);
+ int _characterFacingCountTable[2];
+
int getCharacterWalkspeed() const;
- void updateCharAnimFrame(int num, int *table);
+ void updateCharAnimFrame(int *table);
bool checkCharCollision(int x, int y);
@@ -681,6 +684,7 @@ protected:
uint32 _nextIdleAnim;
int _lastIdleScript;
+ bool _useSceneIdleAnim;
void setNextIdleAnimTimer();
void showIdleAnim();
diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp
index 7526216066..a04c28cad8 100644
--- a/engines/kyra/kyra_lok.cpp
+++ b/engines/kyra/kyra_lok.cpp
@@ -24,26 +24,19 @@
*/
#include "kyra/kyra_lok.h"
-
-#include "common/file.h"
-#include "common/system.h"
-#include "common/savefile.h"
-#include "common/config-manager.h"
-#include "common/debug-channels.h"
-
-#include "gui/message.h"
-
#include "kyra/resource.h"
-#include "kyra/screen.h"
-#include "kyra/script.h"
#include "kyra/seqplayer.h"
-#include "kyra/sound.h"
#include "kyra/sprites.h"
-#include "kyra/wsamovie.h"
#include "kyra/animator_lok.h"
-#include "kyra/text.h"
#include "kyra/debugger.h"
#include "kyra/timer.h"
+#include "kyra/sound.h"
+
+#include "common/system.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+
+#include "gui/message.h"
namespace Kyra {
@@ -92,10 +85,22 @@ KyraEngine_LoK::KyraEngine_LoK(OSystem *system, const GameFlags &flags)
memset(_panPagesTable, 0, sizeof(_panPagesTable));
memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable));
_currHeadShape = 0;
+ _currentHeadFrameTableIndex = 0;
_speechPlayTime = 0;
_seqPlayerFlag = false;
+ memset(&_characterFacingZeroCount, 0, sizeof(_characterFacingZeroCount));
+ memset(&_characterFacingFourCount, 0, sizeof(_characterFacingFourCount));
+
memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp));
+
+ _beadStateTimer1 = _beadStateTimer2 = 0;
+ memset(&_beadState1, 0, sizeof(_beadState1));
+ _beadState1.x = -1;
+ memset(&_beadState2, 0, sizeof(_beadState2));
+
+ _malcolmFrame = 0;
+ _malcolmTimer1 = _malcolmTimer2 = 0;
}
KyraEngine_LoK::~KyraEngine_LoK() {
diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h
index dfbf5bddd8..cfa231e2d0 100644
--- a/engines/kyra/kyra_lok.h
+++ b/engines/kyra/kyra_lok.h
@@ -32,6 +32,10 @@
#include "kyra/gui_lok.h"
#include "kyra/item.h"
+namespace Graphics {
+struct Surface;
+}
+
namespace Kyra {
class Movie;
@@ -447,6 +451,9 @@ protected:
uint16 _currentChatPartnerBackupFrame;
uint16 _currentCharAnimFrame;
+ int _characterFacingZeroCount[8];
+ int _characterFacingFourCount[8];
+
int8 *_sceneAnimTable[50];
uint8 _itemHtDat[145];
@@ -471,6 +478,7 @@ protected:
int8 _charSayUnk2;
int8 _charSayUnk3;
int8 _currHeadShape;
+ int _currentHeadFrameTableIndex;
int8 _disabledTalkAnimObject;
int8 _enabledTalkAnimObject;
uint8 _currSentenceColor[3];
@@ -498,6 +506,15 @@ protected:
Button *_buttonList;
GUI_LoK *_gui;
+ uint16 _malcolmFrame;
+ uint32 _malcolmTimer1;
+ uint32 _malcolmTimer2;
+
+ uint32 _beadStateTimer1;
+ uint32 _beadStateTimer2;
+ BeadState _beadState1;
+ BeadState _beadState2;
+
struct KyragemState {
uint16 nextOperation;
uint16 rOffset;
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index b863ef5725..570ebe0bab 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -23,18 +23,15 @@
*
*/
-#include "kyra/kyra_v1.h"
#include "kyra/kyra_mr.h"
-#include "kyra/screen_mr.h"
#include "kyra/wsamovie.h"
-#include "kyra/sound.h"
#include "kyra/text_mr.h"
#include "kyra/vqa.h"
-#include "kyra/gui.h"
#include "kyra/timer.h"
#include "kyra/debugger.h"
#include "kyra/gui_mr.h"
#include "kyra/resource.h"
+#include "kyra/sound.h"
#include "common/system.h"
#include "common/config-manager.h"
@@ -426,9 +423,7 @@ void KyraEngine_MR::snd_playWanderScoreViaMap(int track, int force) {
if (_musicSoundChannel == -1) {
assert(track < _soundListSize && track >= 0);
- char file[13];
- sprintf(file, "%s", _soundList[track]);
- _musicSoundChannel = _soundDigital->playSound(file, 0xFF, Audio::Mixer::kMusicSoundType);
+ _musicSoundChannel = _soundDigital->playSound(_soundList[track], 0xFF, Audio::Mixer::kMusicSoundType, 255, true);
}
_lastMusicCommand = track;
@@ -442,31 +437,6 @@ void KyraEngine_MR::stopMusicTrack() {
_musicSoundChannel = -1;
}
-int KyraEngine_MR::musicUpdate(int forceRestart) {
- static uint32 mTimer = 0;
- static uint16 lock = 0;
-
- if (ABS<int>(_system->getMillis() - mTimer) > (int)(0x0F * _tickLength))
- mTimer = _system->getMillis();
-
- if (_system->getMillis() < mTimer && !forceRestart)
- return 1;
-
- if (!lock) {
- lock = 1;
- if (_musicSoundChannel >= 0) {
- if (!_soundDigital->isPlaying(_musicSoundChannel)) {
- if (_lastMusicCommand != -1)
- snd_playWanderScoreViaMap(_lastMusicCommand, 1);
- }
- }
- lock = 0;
- mTimer = _system->getMillis() + 0x0F * _tickLength;
- }
-
- return 1;
-}
-
void KyraEngine_MR::fadeOutMusic(int ticks) {
if (_musicSoundChannel >= 0) {
_fadeOutMusicChannel = _musicSoundChannel;
@@ -550,11 +520,8 @@ void KyraEngine_MR::startup() {
assert(_album.leftPage.wsa);
_album.rightPage.wsa = new WSAMovie_v2(this);
assert(_album.rightPage.wsa);
- musicUpdate(0);
_gamePlayBuffer = new uint8[64000];
- musicUpdate(0);
- musicUpdate(0);
_interface = new uint8[17920];
_interfaceCommandLine = new uint8[3840];
@@ -562,17 +529,11 @@ void KyraEngine_MR::startup() {
_screen->setFont(Screen::FID_8_FNT);
_stringBuffer = new char[500];
- musicUpdate(0);
allocAnimObjects(1, 16, 50);
- musicUpdate(0);
-
memset(_sceneShapes, 0, sizeof(_sceneShapes));
_screenBuffer = new uint8[64000];
- musicUpdate(0);
- musicUpdate(0);
-
if (!loadLanguageFile("ITEMS.", _itemFile))
error("Couldn't load ITEMS");
if (!loadLanguageFile("SCORE.", _scoreFile))
@@ -586,13 +547,10 @@ void KyraEngine_MR::startup() {
if (!loadLanguageFile("_ACTOR.", _actorFile))
error("couldn't load _ACTOR");
- musicUpdate(0);
openTalkFile(0);
- musicUpdate(0);
_currentTalkFile = 0;
openTalkFile(1);
loadCostPal();
- musicUpdate(0);
for (int i = 0; i < 16; ++i) {
_sceneAnims[i].flags = 0;
@@ -607,30 +565,24 @@ void KyraEngine_MR::startup() {
for (int i = 0; i < 88; ++i)
_talkObjectList[i].sceneId = 0xFF;
- musicUpdate(0);
_gfxBackUpRect = new uint8[_screen->getRectSize(32, 32)];
initItemList(50);
resetItemList();
loadShadowShape();
- musicUpdate(0);
loadExtrasShapes();
- musicUpdate(0);
_characterShapeFile = 0;
loadCharacterShapes(_characterShapeFile);
updateMalcolmShapes();
- musicUpdate(0);
initMainButtonList(true);
loadButtonShapes();
loadInterfaceShapes();
- musicUpdate(0);
_screen->loadPalette("PALETTE.COL", _screen->getPalette(0));
_paletteOverlay = new uint8[256];
_screen->generateOverlay(_screen->getPalette(0), _paletteOverlay, 0xF0, 0x19);
loadInterface();
- musicUpdate(0);
clearAnimObjects();
@@ -640,8 +592,6 @@ void KyraEngine_MR::startup() {
_scoreMax += _scoreTable[i];
}
- musicUpdate(0);
-
memset(_newSceneDlgState, 0, sizeof(_newSceneDlgState));
memset(_conversationState, -1, sizeof(_conversationState));
@@ -650,7 +600,6 @@ void KyraEngine_MR::startup() {
memset(_sceneList, 0, sizeof(SceneDesc)*98);
_sceneListSize = 98;
- musicUpdate(0);
runStartupScript(1, 0);
_res->exists("MOODOMTR.WSA", true);
_invWsa = new WSAMovie_v2(this);
@@ -667,7 +616,6 @@ void KyraEngine_MR::startup() {
(*_mainButtonData[0].buttonCallback)(&_mainButtonData[0]);
_screen->updateScreen();
- musicUpdate(0);
_screen->showMouse();
setNextIdleAnimTimer();
@@ -837,7 +785,7 @@ int KyraEngine_MR::getCharacterWalkspeed() const {
return _mainCharacter.walkspeed;
}
-void KyraEngine_MR::updateCharAnimFrame(int character, int *table) {
+void KyraEngine_MR::updateCharAnimFrame(int *table) {
++_mainCharacter.animFrame;
int facing = _mainCharacter.facing;
@@ -1113,14 +1061,11 @@ int KyraEngine_MR::inputSceneChange(int x, int y, int unk1, int unk2) {
void KyraEngine_MR::update() {
updateInput();
- musicUpdate(0);
refreshAnimObjectsIfNeed();
- musicUpdate(0);
updateMouse();
updateSpecialSceneScripts();
updateCommandLine();
updateItemAnimations();
- musicUpdate(0);
_screen->updateScreen();
}
@@ -1128,12 +1073,10 @@ void KyraEngine_MR::update() {
void KyraEngine_MR::updateWithText() {
updateInput();
- musicUpdate(0);
updateMouse();
updateItemAnimations();
updateSpecialSceneScripts();
updateCommandLine();
- musicUpdate(0);
restorePage3();
drawAnimObjects();
diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h
index fd31089953..912c615757 100644
--- a/engines/kyra/kyra_mr.h
+++ b/engines/kyra/kyra_mr.h
@@ -122,7 +122,6 @@ private:
void snd_playWanderScoreViaMap(int track, int force);
void stopMusicTrack();
- int musicUpdate(int forceRestart);
void fadeOutMusic(int ticks);
void snd_playSoundEffect(int item, int volume);
@@ -387,7 +386,7 @@ private:
// character
int getCharacterWalkspeed() const;
- void updateCharAnimFrame(int character, int *table);
+ void updateCharAnimFrame(int *table);
int8 _characterAnimTable[2];
static const uint8 _characterFrameTable[];
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index 3a5d21196b..fb56e4a62a 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -23,22 +23,17 @@
*
*/
-#include "common/config-manager.h"
-#include "common/debug-channels.h"
-#include "common/EventRecorder.h"
-
-#include "audio/mididrv.h"
-#include "audio/mixer.h"
-
#include "kyra/kyra_v1.h"
#include "kyra/sound_intern.h"
#include "kyra/resource.h"
-#include "kyra/screen.h"
-#include "kyra/text.h"
#include "kyra/timer.h"
-#include "kyra/script.h"
#include "kyra/debugger.h"
+#include "common/error.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/EventRecorder.h"
+
namespace Kyra {
KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags)
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index cf51774b0f..08dc831dd9 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -29,10 +29,10 @@
#include "engines/engine.h"
#include "common/array.h"
+#include "common/error.h"
#include "common/events.h"
#include "common/random.h"
#include "common/hashmap.h"
-#include "common/system.h"
#include "audio/mixer.h"
@@ -44,6 +44,10 @@ class SeekableReadStream;
class WriteStream;
} // End of namespace Common
+namespace Graphics {
+struct Surface;
+}
+
class KyraMetaEngine;
/**
@@ -166,7 +170,6 @@ enum MusicDataID {
class Screen;
class Resource;
class Sound;
-class Movie;
class TextDisplayer;
class StaticResource;
class TimerManager;
@@ -247,7 +250,7 @@ protected:
Common::Error err;
registerDefaultSettings();
err = init();
- if (err != Common::kNoError)
+ if (err.getCode() != Common::kNoError)
return err;
return go();
}
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 53c57c21cd..16b5ffa4e8 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -23,11 +23,12 @@
*
*/
-#include "common/config-manager.h"
-
#include "kyra/kyra_v2.h"
#include "kyra/screen_v2.h"
-#include "kyra/debugger.h"
+
+#include "common/config-manager.h"
+#include "common/error.h"
+#include "common/system.h"
namespace Kyra {
@@ -74,6 +75,9 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const Engi
_pauseStart = 0;
+ _pathfinderFlag = 0;
+ _smoothingPath = false;
+
_lang = 0;
Common::Language lang = Common::parseLanguage(ConfMan.get("language"));
if (lang == _flags.fanLang && _flags.replacedLang != Common::UNK_LANG)
@@ -236,7 +240,7 @@ int KyraEngine_v2::updateCharPos(int *table, int force) {
return 0;
_mainCharacter.x1 += _charAddXPosTable[_mainCharacter.facing];
_mainCharacter.y1 += _charAddYPosTable[_mainCharacter.facing];
- updateCharAnimFrame(0, table);
+ updateCharAnimFrame(table);
_updateCharPosNextUpdate = _system->getMillis() + getCharacterWalkspeed() * _tickLength;
return 1;
}
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index 084b159ee2..9f0aecd78c 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -269,6 +269,7 @@ protected:
// pathfinder
int _movFacingTable[600];
int _pathfinderFlag;
+ bool _smoothingPath;
int findWay(int curX, int curY, int dstX, int dstY, int *moveTable, int moveTableSize);
@@ -340,7 +341,7 @@ protected:
uint32 _updateCharPosNextUpdate;
virtual int getCharacterWalkspeed() const = 0;
- virtual void updateCharAnimFrame(int num, int *table) = 0;
+ virtual void updateCharAnimFrame(int *table) = 0;
// chat
int _vocHigh;
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 7003d8c38f..ce73bffc89 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -28,17 +28,15 @@
#include "kyra/lol.h"
#include "kyra/screen_lol.h"
#include "kyra/resource.h"
-
-#include "kyra/sound.h"
#include "kyra/timer.h"
#include "kyra/util.h"
#include "kyra/debugger.h"
+#include "kyra/sound.h"
-#include "audio/decoders/voc.h"
#include "audio/audiostream.h"
#include "common/config-manager.h"
-#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
@@ -591,7 +589,9 @@ Common::Error LoLEngine::go() {
if (action == 0) {
startupNew();
} else if (_gameToLoad != -1) {
- if (loadGameState(_gameToLoad) != Common::kNoError)
+ // FIXME: Instead of throwing away the error returned by
+ // loadGameState, we should use it / augment it.
+ if (loadGameState(_gameToLoad).getCode() != Common::kNoError)
error("Couldn't load game slot %d on startup", _gameToLoad);
_gameToLoad = -1;
}
@@ -898,7 +898,9 @@ void LoLEngine::startupNew() {
memset(_globalScriptVars2, 0x100, 8);
- static int selectIds[] = { -9, -1, -8, -5 };
+ static const int selectIds[] = { -9, -1, -8, -5 };
+ assert(_charSelection >= 0);
+ assert(_charSelection < ARRAYSIZE(selectIds));
addCharacter(selectIds[_charSelection]);
gui_enableDefaultPlayfieldButtons();
@@ -916,7 +918,9 @@ void LoLEngine::runLoop() {
while (!shouldQuit() && _runFlag) {
if (_gameToLoad != -1) {
- if (loadGameState(_gameToLoad) != Common::kNoError)
+ // FIXME: Instead of throwing away the error returned by
+ // loadGameState, we should use it / augment it.
+ if (loadGameState(_gameToLoad).getCode() != Common::kNoError)
error("Couldn't load game slot %d", _gameToLoad);
_gameToLoad = -1;
}
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index d24f3b427f..a3170c2193 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -31,12 +31,15 @@
#include "kyra/kyra_v1.h"
#include "kyra/script_tim.h"
#include "kyra/script.h"
-#include "kyra/sound.h"
#include "kyra/gui_lol.h"
#include "kyra/text_lol.h"
#include "common/list.h"
+namespace Audio {
+class SeekableAudioStream;
+} // End of namespace Audio
+
namespace Kyra {
class Screen_LoL;
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index 63b8072654..22786c1c7e 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -27,11 +27,7 @@
#include "kyra/resource_intern.h"
#include "common/config-manager.h"
-#include "common/endian.h"
-#include "common/file.h"
#include "common/fs.h"
-#include "common/func.h"
-#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 8372bf9ad1..9948c52001 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -102,7 +102,7 @@ protected:
enum KyraResources {
kLoadAll = -1,
- // This list has to match orderwise (and thus value wise) the static data list of "tools/create_kyradat/create_kyradat.h"!
+ // This list has to match orderwise (and thus value wise) the static data list of "devtools/create_kyradat/create_kyradat.h"!
k1ForestSeq = 1,
k1KallakWritingSeq,
k1KyrandiaLogoSeq,
diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp
index f26cb8fb26..1dc084f14d 100644
--- a/engines/kyra/resource_intern.cpp
+++ b/engines/kyra/resource_intern.cpp
@@ -356,7 +356,7 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common:
const uint32 magic = stream.readUint32BE();
- if (magic != MKID_BE('SCVM'))
+ if (magic != MKTAG('S','C','V','M'))
error("LINKLIST file does not contain 'SCVM' header");
const uint32 links = stream.readUint32BE();
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index cd5ef52b92..81b3ec15ae 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -23,15 +23,15 @@
*
*/
-#include "common/endian.h"
+#include "kyra/kyra_v1.h"
+#include "kyra/util.h"
+
#include "common/savefile.h"
#include "common/system.h"
+
#include "graphics/thumbnail.h"
#include "graphics/surface.h"
-#include "kyra/kyra_v1.h"
-#include "kyra/util.h"
-
#define CURRENT_SAVE_VERSION 16
#define GF_FLOPPY (1 << 0)
@@ -47,13 +47,13 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
header.flags = 0;
header.thumbnail = 0;
- if (type == MKID_BE('KYRA') || type == MKID_BE('ARYK')) { // old Kyra1 header ID
+ if (type == MKTAG('K','Y','R','A') || type == MKTAG('A','R','Y','K')) { // old Kyra1 header ID
header.gameID = GI_KYRA1;
header.oldHeader = true;
- } else if (type == MKID_BE('HOFS')) { // old Kyra2 header ID
+ } else if (type == MKTAG('H','O','F','S')) { // old Kyra2 header ID
header.gameID = GI_KYRA2;
header.oldHeader = true;
- } else if (type == MKID_BE('WWSV')) {
+ } else if (type == MKTAG('W','W','S','V')) {
header.gameID = in->readByte();
} else {
// try checking for original save header
@@ -71,12 +71,12 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
type = in->readUint32BE();
header.version = in->readUint16LE();
- if (type == MKID_BE('MBL3') && header.version == 100) {
+ if (type == MKTAG('M','B','L','3') && header.version == 100) {
saveOk = true;
header.description = descriptionBuffer;
header.gameID = GI_KYRA2;
break;
- } else if (type == MKID_BE('MBL4') && header.version == 102) {
+ } else if (type == MKTAG('M','B','L','4') && header.version == 102) {
saveOk = true;
header.description = descriptionBuffer;
header.gameID = GI_KYRA3;
@@ -94,7 +94,7 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
}
header.version = in->readUint32BE();
- if (header.version > CURRENT_SAVE_VERSION || (header.oldHeader && header.version > 8) || (type == MKID_BE('ARYK') && header.version > 3))
+ if (header.version > CURRENT_SAVE_VERSION || (header.oldHeader && header.version > 8) || (type == MKTAG('A','R','Y','K') && header.version > 3))
return kRSHEInvalidVersion;
// Versions prior to 9 are using a fixed length description field
@@ -190,7 +190,7 @@ Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, con
}
// Savegame version
- out->writeUint32BE(MKID_BE('WWSV'));
+ out->writeUint32BE(MKTAG('W','W','S','V'));
out->writeByte(_flags.gameID);
out->writeUint32BE(CURRENT_SAVE_VERSION);
out->write(saveName, strlen(saveName)+1);
@@ -257,7 +257,9 @@ void KyraEngine_v1::checkAutosave() {
}
void KyraEngine_v1::loadGameStateCheck(int slot) {
- if (loadGameState(slot) != Common::kNoError) {
+ // FIXME: Instead of throwing away the error returned by
+ // loadGameState, we should use it / augment it.
+ if (loadGameState(slot).getCode() != Common::kNoError) {
const char *filename = getSavegameFilename(slot);
Common::String errorMessage = "Could not load savegame: '";
errorMessage += filename;
diff --git a/engines/kyra/saveload_hof.cpp b/engines/kyra/saveload_hof.cpp
index 7a487dcf7b..1fd6c0f3c8 100644
--- a/engines/kyra/saveload_hof.cpp
+++ b/engines/kyra/saveload_hof.cpp
@@ -23,17 +23,15 @@
*
*/
-#include "common/endian.h"
-#include "common/savefile.h"
-#include "common/substream.h"
-#include "common/system.h"
-
-#include "kyra/kyra_v2.h"
+#include "kyra/kyra_hof.h"
#include "kyra/screen_v2.h"
-#include "kyra/resource.h"
#include "kyra/sound.h"
#include "kyra/timer.h"
+#include "common/savefile.h"
+#include "common/substream.h"
+#include "common/system.h"
+
namespace Kyra {
Common::Error KyraEngine_HoF::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) {
diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp
index 012ff138b5..5af4f1d8ca 100644
--- a/engines/kyra/saveload_lok.cpp
+++ b/engines/kyra/saveload_lok.cpp
@@ -23,17 +23,14 @@
*
*/
-#include "common/endian.h"
-#include "common/savefile.h"
-#include "common/system.h"
-
#include "kyra/kyra_lok.h"
#include "kyra/animator_lok.h"
-#include "kyra/screen.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
#include "kyra/timer.h"
+#include "common/savefile.h"
+
namespace Kyra {
Common::Error KyraEngine_LoK::loadGameState(int slot) {
diff --git a/engines/kyra/saveload_lol.cpp b/engines/kyra/saveload_lol.cpp
index b6c0693a16..c5240e2624 100644
--- a/engines/kyra/saveload_lol.cpp
+++ b/engines/kyra/saveload_lol.cpp
@@ -27,12 +27,9 @@
#include "kyra/lol.h"
#include "kyra/screen_lol.h"
-#include "kyra/resource.h"
-#include "common/endian.h"
#include "common/savefile.h"
#include "common/substream.h"
-#include "common/system.h"
#include "graphics/scaler.h"
diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp
index 79827361a3..b44c88a0b4 100644
--- a/engines/kyra/scene_hof.cpp
+++ b/engines/kyra/scene_hof.cpp
@@ -24,12 +24,10 @@
*/
#include "kyra/kyra_hof.h"
-#include "kyra/screen_v2.h"
#include "kyra/sound.h"
-#include "kyra/wsamovie.h"
#include "kyra/resource.h"
-#include "common/func.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp
index f7ada5d623..6200e2ab1e 100644
--- a/engines/kyra/scene_lok.cpp
+++ b/engines/kyra/scene_lok.cpp
@@ -24,19 +24,13 @@
*/
#include "kyra/kyra_lok.h"
-#include "kyra/seqplayer.h"
-#include "kyra/screen.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
#include "kyra/sprites.h"
-#include "kyra/wsamovie.h"
#include "kyra/animator_lok.h"
-#include "kyra/text.h"
-#include "kyra/script.h"
#include "kyra/timer.h"
#include "common/system.h"
-#include "common/savefile.h"
namespace Kyra {
@@ -314,38 +308,35 @@ void KyraEngine_LoK::setCharacterPositionHelper(int character, int *facingTable)
}
}
- static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
if (facing == 0) {
- ++facingIsZero[character];
+ ++_characterFacingZeroCount[character];
} else {
bool resetTables = false;
if (facing != 7) {
if (facing - 1 != 0) {
if (facing != 4) {
if (facing == 3 || facing == 5) {
- if (facingIsFour[character] > 2)
+ if (_characterFacingFourCount[character] > 2)
facing = 4;
resetTables = true;
}
} else {
- ++facingIsFour[character];
+ ++_characterFacingFourCount[character];
}
} else {
- if (facingIsZero[character] > 2)
+ if (_characterFacingZeroCount[character] > 2)
facing = 0;
resetTables = true;
}
} else {
- if (facingIsZero[character] > 2)
+ if (_characterFacingZeroCount[character] > 2)
facing = 0;
resetTables = true;
}
if (resetTables) {
- facingIsZero[character] = 0;
- facingIsFour[character] = 0;
+ _characterFacingZeroCount[character] = 0;
+ _characterFacingFourCount[character] = 0;
}
}
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index e070b91a44..ab9f89456b 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -29,9 +29,9 @@
#include "kyra/screen_lol.h"
#include "kyra/resource.h"
#include "kyra/timer.h"
-#include "kyra/sound.h"
#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp
index f1ea79f49b..4eac4889b6 100644
--- a/engines/kyra/scene_mr.cpp
+++ b/engines/kyra/scene_mr.cpp
@@ -25,10 +25,11 @@
#include "kyra/kyra_mr.h"
#include "kyra/screen_mr.h"
-#include "kyra/wsamovie.h"
#include "kyra/sound.h"
#include "kyra/resource.h"
+#include "common/system.h"
+
namespace Kyra {
void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2, int unk3) {
@@ -36,20 +37,13 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
_screen->hideMouse();
showMessage(0, 0xF0, 0xF0);
- if (_inventoryState) {
+ if (_inventoryState)
hideInventory();
- musicUpdate(0);
- }
- musicUpdate(0);
if (_currentChapter != _currentTalkFile) {
_currentTalkFile = _currentChapter;
openTalkFile(_currentTalkFile);
}
- musicUpdate(0);
-
- if (!unk3)
- musicUpdate(0);
if (unk1) {
int x = _mainCharacter.x1;
@@ -73,11 +67,9 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
break;
}
- musicUpdate(0);
moveCharacter(facing, x, y);
}
- musicUpdate(0);
uint32 waitUntilTimer = 0;
if (_lastMusicCommand != _sceneList[sceneId].sound) {
fadeOutMusic(60);
@@ -89,33 +81,23 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
if (!unk3) {
_emc->init(&_sceneScriptState, &_sceneScriptData);
_emc->start(&_sceneScriptState, 5);
- while (_emc->isValid(&_sceneScriptState)) {
+ while (_emc->isValid(&_sceneScriptState))
_emc->run(&_sceneScriptState);
- musicUpdate(0);
- }
}
- musicUpdate(0);
-
_specialExitCount = 0;
Common::set_to(_specialExitTable, _specialExitTable+ARRAYSIZE(_specialExitTable), 0xFFFF);
- musicUpdate(0);
-
_mainCharacter.sceneId = sceneId;
_sceneList[sceneId].flags &= ~1;
- musicUpdate(0);
unloadScene();
- musicUpdate(0);
for (int i = 0; i < 4; ++i) {
if (i != _musicSoundChannel && i != _fadeOutMusicChannel)
_soundDigital->stopSound(i);
}
_fadeOutMusicChannel = -1;
- musicUpdate(0);
loadScenePal();
- musicUpdate(0);
if (queryGameFlag(0x1D9)) {
char filename[20];
@@ -141,9 +123,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
resetGameFlag(0x1D9);
}
- musicUpdate(0);
loadSceneMsc();
- musicUpdate(0);
_sceneExit1 = _sceneList[sceneId].exit1;
_sceneExit2 = _sceneList[sceneId].exit2;
_sceneExit3 = _sceneList[sceneId].exit3;
@@ -152,9 +132,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
while (_system->getMillis() < waitUntilTimer)
_system->delayMillis(10);
- musicUpdate(0);
initSceneScript(unk3);
- musicUpdate(0);
if (_overwriteSceneFacing) {
facing = _mainCharacter.facing;
@@ -162,7 +140,6 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
}
enterNewSceneUnk1(facing, unk2, unk3);
- musicUpdate(0);
setCommandLineRestoreTimer(-1);
_sceneScriptState.regs[3] = 1;
enterNewSceneUnk2(unk3);
@@ -306,13 +283,9 @@ void KyraEngine_MR::enterNewSceneUnk2(int unk1) {
void KyraEngine_MR::unloadScene() {
delete[] _sceneStrings;
_sceneStrings = 0;
- musicUpdate(0);
_emc->unload(&_sceneScriptData);
- musicUpdate(0);
freeSceneShapes();
- musicUpdate(0);
freeSceneAnims();
- musicUpdate(0);
}
void KyraEngine_MR::freeSceneShapes() {
@@ -356,13 +329,11 @@ void KyraEngine_MR::loadSceneMsc() {
height = stream->readSint16LE();
delete stream;
stream = 0;
- musicUpdate(0);
_maskPageMinY = minY;
_maskPageMaxY = minY + height - 1;
_screen->setShapePages(5, 3, _maskPageMinY, _maskPageMaxY);
- musicUpdate(0);
_screen->loadBitmap(filename, 5, 5, 0, true);
// HACK
@@ -372,12 +343,10 @@ void KyraEngine_MR::loadSceneMsc() {
_screen->copyBlockToPage(5, 0, _maskPageMinY, 320, height, data);
delete[] data;
- musicUpdate(0);
}
void KyraEngine_MR::initSceneScript(int unk1) {
const SceneDesc &scene = _sceneList[_mainCharacter.sceneId];
- musicUpdate(0);
char filename[16];
strcpy(filename, scene.filename1);
@@ -400,7 +369,6 @@ void KyraEngine_MR::initSceneScript(int unk1) {
if (shapesCount > 0) {
strcpy(filename, scene.filename1);
strcat(filename, "9.CPS");
- musicUpdate(0);
_screen->loadBitmap(filename, 3, 3, 0);
int pageBackUp = _screen->_curPage;
_screen->_curPage = 2;
@@ -413,19 +381,15 @@ void KyraEngine_MR::initSceneScript(int unk1) {
_sceneShapeDescs[i].drawY = stream->readSint16LE();
_sceneShapes[i] = _screen->encodeShape(x, y, w, h, 0);
assert(_sceneShapes[i]);
- musicUpdate(0);
}
_screen->_curPage = pageBackUp;
- musicUpdate(0);
}
delete stream;
stream = 0;
- musicUpdate(0);
strcpy(filename, scene.filename1);
strcat(filename, ".CPS");
_screen->loadBitmap(filename, 3, 3, 0);
- musicUpdate(0);
Common::set_to(_specialSceneScriptState, _specialSceneScriptState+ARRAYSIZE(_specialSceneScriptState), false);
_sceneEnterX1 = 160;
@@ -442,14 +406,12 @@ void KyraEngine_MR::initSceneScript(int unk1) {
_emc->init(&_sceneScriptState, &_sceneScriptData);
strcpy(filename, scene.filename2);
strcat(filename, ".EMC");
- musicUpdate(0);
_res->exists(filename, true);
_emc->load(filename, &_sceneScriptData, &_opcodes);
strcpy(filename, scene.filename2);
strcat(filename, ".");
loadLanguageFile(filename, _sceneStrings);
- musicUpdate(0);
runSceneScript8();
_emc->start(&_sceneScriptState, 0);
@@ -459,12 +421,10 @@ void KyraEngine_MR::initSceneScript(int unk1) {
_emc->run(&_sceneScriptState);
_screen->copyRegionToBuffer(3, 0, 0, 320, 200, _gamePlayBuffer);
- musicUpdate(0);
for (int i = 0; i < 10; ++i) {
_emc->init(&_sceneSpecialScripts[i], &_sceneScriptData);
_emc->start(&_sceneSpecialScripts[i], i+9);
- musicUpdate(0);
_sceneSpecialScriptsTimer[i] = 0;
}
@@ -476,7 +436,6 @@ void KyraEngine_MR::initSceneScript(int unk1) {
_sceneEnterY3 &= ~1;
_sceneEnterX4 &= ~3;
_sceneEnterY4 &= ~1;
- musicUpdate(0);
}
void KyraEngine_MR::initSceneAnims(int unk1) {
@@ -789,10 +748,8 @@ void KyraEngine_MR::runSceneScript4(int unk1) {
void KyraEngine_MR::runSceneScript8() {
_emc->start(&_sceneScriptState, 8);
- while (_emc->isValid(&_sceneScriptState)) {
- musicUpdate(0);
+ while (_emc->isValid(&_sceneScriptState))
_emc->run(&_sceneScriptState);
- }
}
bool KyraEngine_MR::lineIsPassable(int x, int y) {
diff --git a/engines/kyra/scene_v1.cpp b/engines/kyra/scene_v1.cpp
index 848735b4a5..bc88377892 100644
--- a/engines/kyra/scene_v1.cpp
+++ b/engines/kyra/scene_v1.cpp
@@ -24,7 +24,6 @@
*/
#include "kyra/kyra_v1.h"
-#include "kyra/screen.h"
namespace Kyra {
diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp
index f0c26acd54..897f2e937f 100644
--- a/engines/kyra/scene_v2.cpp
+++ b/engines/kyra/scene_v2.cpp
@@ -24,7 +24,8 @@
*/
#include "kyra/kyra_v2.h"
-#include "kyra/screen.h"
+
+#include "common/system.h"
namespace Kyra {
@@ -86,15 +87,16 @@ int KyraEngine_v2::findWay(int x, int y, int toX, int toY, int *moveTable, int m
x &= ~3; toX &= ~3;
y &= ~1; toY &= ~1;
int size = KyraEngine_v1::findWay(x, y, toX, toY, moveTable, moveTableSize);
- static bool usePostProcess = false;
- if (size && !usePostProcess) {
- usePostProcess = true;
+
+ if (size && !_smoothingPath) {
+ _smoothingPath = true;
int temp = pathfinderInitPositionTable(moveTable);
temp = pathfinderInitPositionIndexTable(temp, x, y);
pathfinderFinializePath(moveTable, temp, x, y, moveTableSize);
- usePostProcess = false;
+ _smoothingPath = false;
}
- return usePostProcess ? size : getMoveTableSize(moveTable);
+
+ return _smoothingPath ? size : getMoveTableSize(moveTable);
}
bool KyraEngine_v2::directLinePassable(int x, int y, int toX, int toY) {
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index a6754610ef..20a1022b26 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -23,6 +23,9 @@
*
*/
+#include "kyra/screen.h"
+#include "kyra/kyra_v1.h"
+#include "kyra/resource.h"
#include "common/endian.h"
#include "common/memstream.h"
@@ -31,12 +34,9 @@
#include "engines/util.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
#include "graphics/sjis.h"
-#include "kyra/screen.h"
-#include "kyra/kyra_v1.h"
-#include "kyra/resource.h"
-
namespace Kyra {
Screen::Screen(KyraEngine_v1 *vm, OSystem *system)
@@ -2375,7 +2375,7 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) {
if (flags & 1)
shapeSize += 16;
- static uint8 table[274];
+ uint8 table[274];
int tableIndex = 0;
uint8 *newShape = 0;
@@ -2397,7 +2397,7 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) {
byte *src = srcPtr;
if (flags & 1) {
dst += 16;
- memset(table, 0, sizeof(uint8)*274);
+ memset(table, 0, sizeof(table));
tableIndex = 1;
}
diff --git a/engines/kyra/screen_hof.cpp b/engines/kyra/screen_hof.cpp
index a180c28442..f0af53f024 100644
--- a/engines/kyra/screen_hof.cpp
+++ b/engines/kyra/screen_hof.cpp
@@ -23,10 +23,8 @@
*
*/
-#include "common/endian.h"
-
-#include "kyra/kyra_hof.h"
#include "kyra/screen_hof.h"
+#include "kyra/kyra_hof.h"
namespace Kyra {
diff --git a/engines/kyra/screen_lok.cpp b/engines/kyra/screen_lok.cpp
index 227349754f..2431cde20b 100644
--- a/engines/kyra/screen_lok.cpp
+++ b/engines/kyra/screen_lok.cpp
@@ -23,10 +23,12 @@
*
*/
-#include "kyra/kyra_lok.h"
#include "kyra/screen_lok.h"
+#include "kyra/kyra_lok.h"
+
+#include "common/system.h"
-#include "graphics/cursorman.h"
+#include "graphics/palette.h"
namespace Kyra {
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index ff35facbb5..20756e1fae 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -27,7 +27,10 @@
#include "kyra/screen_lol.h"
#include "kyra/lol.h"
-#include "kyra/resource.h"
+
+#include "common/system.h"
+
+#include "graphics/palette.h"
namespace Kyra {
diff --git a/engines/kyra/screen_mr.cpp b/engines/kyra/screen_mr.cpp
index 33bfc517f7..4ae52b924d 100644
--- a/engines/kyra/screen_mr.cpp
+++ b/engines/kyra/screen_mr.cpp
@@ -24,7 +24,6 @@
*/
#include "kyra/screen_mr.h"
-
#include "kyra/kyra_mr.h"
namespace Kyra {
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index 0343cbfeae..21dfe0bd31 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -23,15 +23,11 @@
*
*/
-
-#include "common/endian.h"
-#include "common/stream.h"
-#include "common/util.h"
-#include "common/system.h"
-
+#include "kyra/script.h"
#include "kyra/kyra_v1.h"
#include "kyra/resource.h"
-#include "kyra/script.h"
+
+#include "common/endian.h"
namespace Kyra {
EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm), _scriptData(0), _filename(0) {
@@ -68,14 +64,14 @@ EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm), _scriptData(0), _fi
bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
switch (chunk._type) {
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
_scriptData->text = new byte[chunk._size];
assert(_scriptData->text);
if (chunk._stream->read(_scriptData->text, chunk._size) != chunk._size)
error("Couldn't read TEXT chunk from file '%s'", _filename);
break;
- case MKID_BE('ORDR'):
+ case MKTAG('O','R','D','R'):
_scriptData->ordr = new uint16[chunk._size >> 1];
assert(_scriptData->ordr);
if (chunk._stream->read(_scriptData->ordr, chunk._size) != chunk._size)
@@ -85,7 +81,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
_scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]);
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
_scriptData->data = new uint16[chunk._size >> 1];
assert(_scriptData->data);
if (chunk._stream->read(_scriptData->data, chunk._size) != chunk._size)
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index 68620829bb..faa80a3f21 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -84,9 +84,9 @@ public:
// Both lead to some problems in our IFF parser, either reading after the end
// of file or producing a "Chunk overread" error message. To work around this
// we need to adjust the size field properly.
- if (_formType == MKID_BE('EMC2'))
+ if (_formType == MKTAG('E','M','C','2'))
_formChunk.size -= 8;
- else if (_formType == MKID_BE('AVFS'))
+ else if (_formType == MKTAG('A','V','F','S'))
_formChunk.size += 4;
}
};
diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp
index d57bb7efc5..056319e6d4 100644
--- a/engines/kyra/script_hof.cpp
+++ b/engines/kyra/script_hof.cpp
@@ -24,14 +24,11 @@
*/
#include "kyra/kyra_hof.h"
-#include "kyra/text_hof.h"
-#include "kyra/wsamovie.h"
-#include "kyra/sound.h"
#include "kyra/timer.h"
-#include "kyra/script_tim.h"
#include "kyra/resource.h"
+#include "kyra/sound.h"
-#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp
index a2bad8035e..30f1138360 100644
--- a/engines/kyra/script_lok.cpp
+++ b/engines/kyra/script_lok.cpp
@@ -23,12 +23,7 @@
*
*/
-#include "common/endian.h"
-#include "common/system.h"
-
#include "kyra/kyra_lok.h"
-#include "kyra/script.h"
-#include "kyra/screen.h"
#include "kyra/sprites.h"
#include "kyra/wsamovie.h"
#include "kyra/animator_lok.h"
@@ -36,6 +31,8 @@
#include "kyra/timer.h"
#include "kyra/sound.h"
+#include "common/system.h"
+
namespace Kyra {
int KyraEngine_LoK::o1_magicInMouseItem(EMCState *script) {
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index c9fb8df1fb..3185032218 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -29,8 +29,9 @@
#include "kyra/screen_lol.h"
#include "kyra/timer.h"
#include "kyra/resource.h"
+#include "kyra/sound.h"
-#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp
index 5cd100b69c..b3943e1aef 100644
--- a/engines/kyra/script_mr.cpp
+++ b/engines/kyra/script_mr.cpp
@@ -24,14 +24,10 @@
*/
#include "kyra/kyra_mr.h"
-#include "kyra/script.h"
-#include "kyra/screen_mr.h"
#include "kyra/text_mr.h"
-#include "kyra/wsamovie.h"
-#include "kyra/timer.h"
#include "kyra/resource.h"
-#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
@@ -857,8 +853,6 @@ int KyraEngine_MR::o3_defineSceneAnim(EMCState *script) {
const int animId = stackPos(0);
SceneAnim &anim = _sceneAnims[animId];
- musicUpdate(0);
-
uint16 flags = anim.flags = stackPos(1);
int x = anim.x = stackPos(2);
int y = anim.y = stackPos(3);
@@ -875,7 +869,6 @@ int KyraEngine_MR::o3_defineSceneAnim(EMCState *script) {
if (flags & 8) {
_sceneAnimMovie[animId]->open(filename, 1, 0);
- musicUpdate(0);
if (_sceneAnimMovie[animId]->opened()) {
anim.wsaFlag = 1;
if (x2 == -1)
@@ -900,8 +893,6 @@ int KyraEngine_MR::o3_defineSceneAnim(EMCState *script) {
}
}
- musicUpdate(0);
-
return 9;
}
@@ -1080,7 +1071,6 @@ int KyraEngine_MR::o3_setupSceneAnimObject(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_setupSceneAnimObject(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s)", (const void *)script,
stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9),
stackPos(10), stackPos(11), stackPosString(12));
- musicUpdate(0);
setupSceneAnimObject(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8),
stackPos(9), stackPos(10), stackPos(11), stackPosString(12));
return 0;
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 28f18a1f79..004ceb97bb 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -24,10 +24,8 @@
*/
#include "kyra/script_tim.h"
-#include "kyra/script.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
-#include "kyra/wsamovie.h"
#ifdef ENABLE_LOL
#include "kyra/lol.h"
@@ -35,7 +33,7 @@
#endif // ENABLE_LOL
#include "common/iff_container.h"
-#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
@@ -115,14 +113,14 @@ TIMInterpreter::~TIMInterpreter() {
bool TIMInterpreter::callback(Common::IFFChunk &chunk) {
switch (chunk._type) {
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
_tim->text = new byte[chunk._size];
assert(_tim->text);
if (chunk._stream->read(_tim->text, chunk._size) != chunk._size)
error("Couldn't read TEXT chunk from file '%s'", _filename);
break;
- case MKID_BE('AVTL'):
+ case MKTAG('A','V','T','L'):
_avtlChunkSize = chunk._size >> 1;
_tim->avtl = new uint16[_avtlChunkSize];
assert(_tim->avtl);
diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h
index 91f2e8589e..7cf7d0a7dd 100644
--- a/engines/kyra/script_tim.h
+++ b/engines/kyra/script_tim.h
@@ -36,6 +36,7 @@ namespace Kyra {
class WSAMovie_v2;
class Screen_v2;
+class Movie;
class LoLEngine;
class TimAnimator {
diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp
index 12f26ec5f6..13fdcb7d97 100644
--- a/engines/kyra/script_v1.cpp
+++ b/engines/kyra/script_v1.cpp
@@ -26,6 +26,8 @@
#include "kyra/kyra_v1.h"
#include "kyra/screen.h"
+#include "common/system.h"
+
namespace Kyra {
int KyraEngine_v1::o1_queryGameFlag(EMCState *script) {
diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp
index 17e882398e..081f9dd517 100644
--- a/engines/kyra/script_v2.cpp
+++ b/engines/kyra/script_v2.cpp
@@ -27,7 +27,7 @@
#include "kyra/screen_v2.h"
#include "kyra/timer.h"
-#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp
index 5160224591..16e89de146 100644
--- a/engines/kyra/seqplayer.cpp
+++ b/engines/kyra/seqplayer.cpp
@@ -23,18 +23,11 @@
*
*/
-
-#include "common/system.h"
-
-#include "engines/engine.h"
-
+#include "kyra/seqplayer.h"
#include "kyra/resource.h"
-#include "kyra/screen.h"
#include "kyra/sound.h"
-#include "kyra/wsamovie.h"
-#include "kyra/text.h"
-#include "kyra/seqplayer.h"
+#include "common/system.h"
#define SEQOP(n, x) { n, &SeqPlayer::x, #x }
diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp
index 441436a825..b268f13fc1 100644
--- a/engines/kyra/sequences_hof.cpp
+++ b/engines/kyra/sequences_hof.cpp
@@ -23,14 +23,10 @@
*
*/
-#include "kyra/kyra_v1.h"
#include "kyra/kyra_hof.h"
-#include "kyra/screen.h"
-#include "kyra/wsamovie.h"
-#include "kyra/sound.h"
-#include "kyra/text_hof.h"
#include "kyra/timer.h"
#include "kyra/resource.h"
+#include "kyra/sound.h"
#include "common/system.h"
@@ -1216,7 +1212,7 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm)
int chatW = 0;
int chatFirstFrame = 0;
int chatLastFrame = 0;
- int textCol = 0;
+ //int textCol = 0;
uint16 voiceIndex = 0;
@@ -1257,13 +1253,13 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm)
if (_flags.isTalkie) {
chatX = 82;
- textCol = 143;
+ //textCol = 143;
chatFirstFrame = 16;
chatLastFrame = 21;
voiceIndex = 41;
} else {
chatX = 62;
- textCol = 137;
+ //textCol = 137;
chatFirstFrame = 9;
chatLastFrame = 13;
}
@@ -1281,7 +1277,7 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm)
if (frm == 16)
break;
chatX = 64;
- textCol = 137;
+ //textCol = 137;
chatFirstFrame = 9;
chatLastFrame = 13;
voiceIndex = 42;
@@ -1289,7 +1285,7 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm)
if (frm == 9)
break;
chatX = 80;
- textCol = 143;
+ //textCol = 143;
chatFirstFrame = 16;
chatLastFrame = 21;
}
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index c4bdc29f57..0b39201f85 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -25,14 +25,12 @@
#include "kyra/kyra_lok.h"
#include "kyra/seqplayer.h"
-#include "kyra/screen_lok.h"
#include "kyra/resource.h"
-#include "kyra/sound.h"
#include "kyra/sprites.h"
#include "kyra/wsamovie.h"
#include "kyra/animator_lok.h"
-#include "kyra/text.h"
#include "kyra/timer.h"
+#include "kyra/sound.h"
#include "common/system.h"
#include "common/savefile.h"
@@ -1483,53 +1481,49 @@ bool KyraEngine_LoK::seq_skipSequence() const {
}
int KyraEngine_LoK::handleMalcolmFlag() {
- static uint16 frame = 0;
- static uint32 timer1 = 0;
- static uint32 timer2 = 0;
-
switch (_malcolmFlag) {
case 1:
- frame = 0;
+ _malcolmFrame = 0;
_malcolmFlag = 2;
- timer2 = 0;
+ _malcolmTimer2 = 0;
// Fall through to the next case
case 2:
- if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 13) {
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 13) {
_malcolmFlag = 3;
- timer1 = _system->getMillis() + 180 * _tickLength;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
}
}
break;
case 3:
- if (_system->getMillis() < timer1) {
- if (_system->getMillis() >= timer2) {
- frame = _rnd.getRandomNumberRng(14, 17);
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() < _malcolmTimer1) {
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _malcolmFrame = _rnd.getRandomNumberRng(14, 17);
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
}
} else {
_malcolmFlag = 4;
- frame = 18;
+ _malcolmFrame = 18;
}
break;
case 4:
- if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 25) {
- frame = 26;
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 25) {
+ _malcolmFrame = 26;
_malcolmFlag = 5;
_beadStateVar = 1;
}
@@ -1537,13 +1531,13 @@ int KyraEngine_LoK::handleMalcolmFlag() {
break;
case 5:
- if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 31) {
- frame = 32;
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 31) {
+ _malcolmFrame = 32;
_malcolmFlag = 6;
}
}
@@ -1551,14 +1545,14 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 6:
if (_unkEndSeqVar4) {
- if (frame <= 33 && _system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_malcolmFrame <= 33 && _system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 33) {
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 33) {
_malcolmFlag = 7;
- frame = 32;
+ _malcolmFrame = 32;
_unkEndSeqVar5 = 0;
}
}
@@ -1568,20 +1562,20 @@ int KyraEngine_LoK::handleMalcolmFlag() {
case 7:
if (_unkEndSeqVar5 == 1) {
_malcolmFlag = 8;
- frame = 34;
+ _malcolmFrame = 34;
} else if (_unkEndSeqVar5 == 2) {
_malcolmFlag = 3;
- timer1 = _system->getMillis() + 180 * _tickLength;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
}
break;
case 8:
- if (_system->getMillis() >= timer2) {
- _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0);
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
_screen->updateScreen();
- timer2 = _system->getMillis() + 8 * _tickLength;
- ++frame;
- if (frame > 37) {
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 37) {
_malcolmFlag = 0;
_deathHandler = 8;
return 1;
@@ -1593,10 +1587,10 @@ int KyraEngine_LoK::handleMalcolmFlag() {
snd_playSoundEffect(12);
snd_playSoundEffect(12);
for (int i = 0; i < 18; ++i) {
- timer2 = _system->getMillis() + 4 * _tickLength;
+ _malcolmTimer2 = _system->getMillis() + 4 * _tickLength;
_finalC->displayFrame(i, 0, 16, 50, 0, 0, 0);
_screen->updateScreen();
- delayUntil(timer2);
+ delayUntil(_malcolmTimer2);
}
snd_playWanderScoreViaMap(51, 1);
delay(60 * _tickLength);
@@ -1609,16 +1603,16 @@ int KyraEngine_LoK::handleMalcolmFlag() {
_screen->bitBlitRects();
assert(_veryClever);
_text->printTalkTextMessage(_veryClever[0], 60, 31, 5, 0, 2);
- timer2 = _system->getMillis() + 180 * _tickLength;
+ _malcolmTimer2 = _system->getMillis() + 180 * _tickLength;
_malcolmFlag = 11;
}
break;
case 11:
- if (_system->getMillis() >= timer2) {
+ if (_system->getMillis() >= _malcolmTimer2) {
_text->restoreTalkTextMessageBkgd(2, 0);
_malcolmFlag = 3;
- timer1 = _system->getMillis() + 180 * _tickLength;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
}
break;
@@ -1630,16 +1624,12 @@ int KyraEngine_LoK::handleMalcolmFlag() {
}
int KyraEngine_LoK::handleBeadState() {
- static uint32 timer1 = 0;
- static uint32 timer2 = 0;
- static BeadState beadState1 = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static BeadState beadState2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
static const int table1[] = {
-1, -2, -4, -5, -6, -7, -6, -5,
-4, -2, -1, 0, 1, 2, 4, 5,
6, 7, 6, 5, 4, 2, 1, 0, 0
};
+
static const int table2[] = {
0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 5, 5, 4, 4,
@@ -1651,120 +1641,120 @@ int KyraEngine_LoK::handleBeadState() {
switch (_beadStateVar) {
case 0:
- if (beadState1.x != -1 && _endSequenceBackUpRect) {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ if (_beadState1.x != -1 && _endSequenceBackUpRect) {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
}
- beadState1.x = -1;
- beadState1.tableIndex = 0;
- timer1 = 0;
- timer2 = 0;
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
+ _beadStateTimer1 = 0;
+ _beadStateTimer2 = 0;
_lastDisplayedPanPage = 0;
return 1;
case 1:
- if (beadState1.x != -1) {
+ if (_beadState1.x != -1) {
if (_endSequenceBackUpRect) {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
}
- beadState1.x = -1;
- beadState1.tableIndex = 0;
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
}
_beadStateVar = 2;
break;
case 2:
- if (_system->getMillis() >= timer1) {
+ if (_system->getMillis() >= _beadStateTimer1) {
int x = 0, y = 0;
- timer1 = _system->getMillis() + 4 * _tickLength;
- if (beadState1.x == -1) {
+ _beadStateTimer1 = _system->getMillis() + 4 * _tickLength;
+ if (_beadState1.x == -1) {
assert(_panPagesTable);
- beadState1.width2 = _animator->fetchAnimWidth(_panPagesTable[19], 256);
- beadState1.width = ((beadState1.width2 + 7) >> 3) + 1;
- beadState1.height = _animator->fetchAnimHeight(_panPagesTable[19], 256);
+ _beadState1.width2 = _animator->fetchAnimWidth(_panPagesTable[19], 256);
+ _beadState1.width = ((_beadState1.width2 + 7) >> 3) + 1;
+ _beadState1.height = _animator->fetchAnimHeight(_panPagesTable[19], 256);
if (!_endSequenceBackUpRect) {
- _endSequenceBackUpRect = new uint8[(beadState1.width * beadState1.height) << 3];
+ _endSequenceBackUpRect = new uint8[(_beadState1.width * _beadState1.height) << 3];
assert(_endSequenceBackUpRect);
- memset(_endSequenceBackUpRect, 0, ((beadState1.width * beadState1.height) << 3) * sizeof(uint8));
+ memset(_endSequenceBackUpRect, 0, ((_beadState1.width * _beadState1.height) << 3) * sizeof(uint8));
}
- x = beadState1.x = 60;
- y = beadState1.y = 40;
- initBeadState(x, y, x, 25, 8, &beadState2);
+ x = _beadState1.x = 60;
+ y = _beadState1.y = 40;
+ initBeadState(x, y, x, 25, 8, &_beadState2);
} else {
- if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) {
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
_beadStateVar = 3;
- timer2 = _system->getMillis() + 240 * _tickLength;
+ _beadStateTimer2 = _system->getMillis() + 240 * _tickLength;
_unkEndSeqVar4 = 0;
- beadState1.dstX = beadState1.x;
- beadState1.dstY = beadState1.y;
+ _beadState1.dstX = _beadState1.x;
+ _beadState1.dstY = _beadState1.y;
return 0;
} else {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
- beadState1.x = x;
- beadState1.y = y;
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
}
}
- _screen->copyRegionToBuffer(_screen->_curPage, x, y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyRegionToBuffer(_screen->_curPage, x, y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17)
_lastDisplayedPanPage = 0;
- _screen->addBitBlitRect(x, y, beadState1.width2, beadState1.height);
+ _screen->addBitBlitRect(x, y, _beadState1.width2, _beadState1.height);
}
break;
case 3:
- if (_system->getMillis() >= timer1) {
- timer1 = _system->getMillis() + 4 * _tickLength;
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ if (_system->getMillis() >= _beadStateTimer1) {
+ _beadStateTimer1 = _system->getMillis() + 4 * _tickLength;
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
- beadState1.x = beadState1.dstX + table1[beadState1.tableIndex];
- beadState1.y = beadState1.dstY + table2[beadState1.tableIndex];
- _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ _beadState1.x = _beadState1.dstX + table1[_beadState1.tableIndex];
+ _beadState1.y = _beadState1.dstY + table2[_beadState1.tableIndex];
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
- _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], beadState1.x, beadState1.y, 0, 0);
+ _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], _beadState1.x, _beadState1.y, 0, 0);
if (_lastDisplayedPanPage >= 17)
_lastDisplayedPanPage = 0;
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
- ++beadState1.tableIndex;
- if (beadState1.tableIndex > 24)
- beadState1.tableIndex = 0;
+ ++_beadState1.tableIndex;
+ if (_beadState1.tableIndex > 24)
+ _beadState1.tableIndex = 0;
_unkEndSeqVar4 = 1;
- if (_system->getMillis() > timer2 && _malcolmFlag == 7 && !_unkAmuletVar && !_text->printed()) {
+ if (_system->getMillis() > _beadStateTimer2 && _malcolmFlag == 7 && !_unkAmuletVar && !_text->printed()) {
snd_playSoundEffect(0x0B);
if (_currentCharacter->x1 > 233 && _currentCharacter->x1 < 305 && _currentCharacter->y1 > 85 && _currentCharacter->y1 < 105 &&
(_brandonStatusBit & 0x20)) {
- beadState1.unk8 = 290;
- beadState1.unk9 = 40;
+ _beadState1.unk8 = 290;
+ _beadState1.unk9 = 40;
_beadStateVar = 5;
} else {
_beadStateVar = 4;
- beadState1.unk8 = _currentCharacter->x1 - 4;
- beadState1.unk9 = _currentCharacter->y1 - 30;
+ _beadState1.unk8 = _currentCharacter->x1 - 4;
+ _beadState1.unk9 = _currentCharacter->y1 - 30;
}
if (_text->printed())
_text->restoreTalkTextMessageBkgd(2, 0);
- initBeadState(beadState1.x, beadState1.y, beadState1.unk8, beadState1.unk9, 12, &beadState2);
+ initBeadState(_beadState1.x, _beadState1.y, _beadState1.unk8, _beadState1.unk9, 12, &_beadState2);
_lastDisplayedPanPage = 18;
}
}
break;
case 4:
- if (_system->getMillis() >= timer1) {
+ if (_system->getMillis() >= _beadStateTimer1) {
int x = 0, y = 0;
- timer1 = _system->getMillis() + _tickLength;
- if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) {
+ _beadStateTimer1 = _system->getMillis() + _tickLength;
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
if (_brandonStatusBit & 20) {
_unkEndSeqVar5 = 2;
_beadStateVar = 6;
@@ -1775,27 +1765,27 @@ int KyraEngine_LoK::handleBeadState() {
_beadStateVar = 0;
}
} else {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
- beadState1.x = x;
- beadState1.y = y;
- _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17) {
_lastDisplayedPanPage = 0;
}
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
}
}
break;
case 5:
- if (_system->getMillis() >= timer1) {
- timer1 = _system->getMillis() + _tickLength;
+ if (_system->getMillis() >= _beadStateTimer1) {
+ _beadStateTimer1 = _system->getMillis() + _tickLength;
int x = 0, y = 0;
- if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) {
- if (beadState2.dstX == 290) {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
+ if (_beadState2.dstX == 290) {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
uint32 nextRun = 0;
for (int i = 0; i < 8; ++i) {
nextRun = _system->getMillis() + _tickLength;
@@ -1810,38 +1800,39 @@ int KyraEngine_LoK::handleBeadState() {
_screen->updateScreen();
delayUntil(nextRun);
}
- initBeadState(beadState1.x, beadState1.y, 63, 60, 12, &beadState2);
+ initBeadState(_beadState1.x, _beadState1.y, 63, 60, 12, &_beadState2);
} else {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
- beadState1.x = -1;
- beadState1.tableIndex = 0;
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
_beadStateVar = 0;
_malcolmFlag = 9;
}
} else {
- _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
- beadState1.x = x;
- beadState1.y = y;
- _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect);
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
_screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
if (_lastDisplayedPanPage > 17)
_lastDisplayedPanPage = 0;
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
}
}
break;
case 6:
- _screen->drawShape(2, _panPagesTable[19], beadState1.x, beadState1.y, 0, 0);
- _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height);
+ _screen->drawShape(2, _panPagesTable[19], _beadState1.x, _beadState1.y, 0, 0);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
_beadStateVar = 0;
break;
default:
break;
}
+
return 0;
}
diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp
index e8ea7a9dcb..da1245d7e6 100644
--- a/engines/kyra/sequences_lol.cpp
+++ b/engines/kyra/sequences_lol.cpp
@@ -28,9 +28,12 @@
#include "kyra/lol.h"
#include "kyra/screen_lol.h"
#include "kyra/resource.h"
+#include "kyra/sound.h"
#include "base/version.h"
+#include "common/system.h"
+
namespace Kyra {
#pragma mark - Intro
diff --git a/engines/kyra/sequences_v2.cpp b/engines/kyra/sequences_v2.cpp
index 3824676213..4d9cdf0d5d 100644
--- a/engines/kyra/sequences_v2.cpp
+++ b/engines/kyra/sequences_v2.cpp
@@ -26,6 +26,8 @@
#include "kyra/kyra_v2.h"
#include "kyra/resource.h"
+#include "common/system.h"
+
namespace Kyra {
void KyraEngine_v2::runAnimationScript(const char *filename, int allowSkip, int resetChar, int newShapes, int shapeUnload) {
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index 9dd046e50b..1392824235 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -24,19 +24,16 @@
*/
-#include "common/system.h"
-#include "common/config-manager.h"
-
-#include "kyra/resource.h"
#include "kyra/sound.h"
+#include "kyra/resource.h"
#include "audio/mixer.h"
-#include "audio/decoders/voc.h"
#include "audio/audiostream.h"
#include "audio/decoders/flac.h"
#include "audio/decoders/mp3.h"
#include "audio/decoders/raw.h"
+#include "audio/decoders/voc.h"
#include "audio/decoders/vorbis.h"
namespace Kyra {
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index 758d66192d..16f6ca3eaa 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -40,10 +40,11 @@
*/
+#include "kyra/sound_intern.h"
+#include "kyra/resource.h"
+
#include "common/system.h"
#include "common/mutex.h"
-#include "kyra/resource.h"
-#include "kyra/sound_intern.h"
#include "audio/mixer.h"
#include "audio/fmopl.h"
@@ -909,7 +910,7 @@ void AdLibDriver::unkOutput2(uint8 chan) {
// including the two most significant frequency bit, and the octave -
// set to zero.
//
- // This is very strange behaviour, and causes problems with the ancient
+ // This is very strange behavior, and causes problems with the ancient
// FMOPL code we borrowed from AdPlug. I've added a workaround. See
// fmopl.cpp for more details.
//
@@ -984,7 +985,7 @@ void AdLibDriver::setupNote(uint8 rawNote, Channel &channel, bool flag) {
uint16 freq = _unkTable[note] + channel.baseFreq;
- // When called from callback 41, the behaviour is slightly different:
+ // When called from callback 41, the behavior is slightly different:
// We adjust the frequency, even when channel.unk16 is 0.
if (channel.unk16 || flag) {
@@ -1093,12 +1094,12 @@ void AdLibDriver::adjustVolume(Channel &channel) {
// tree) and turning Kallak to stone. Related functions and variables:
//
// update_setupPrimaryEffect1()
-// - Initialises unk29, unk30 and unk31
+// - Initializes unk29, unk30 and unk31
// - unk29 is not further modified
// - unk30 is not further modified, except by update_removePrimaryEffect1()
//
// update_removePrimaryEffect1()
-// - Deinitialises unk30
+// - Deinitializes unk30
//
// unk29 - determines how often the notes are played
// unk30 - modifies the frequency
@@ -1115,7 +1116,7 @@ void AdLibDriver::primaryEffect1(Channel &channel) {
if (channel.unk31 >= temp)
return;
- // Initialise unk1 to the current frequency
+ // Initialize unk1 to the current frequency
uint16 unk1 = ((channel.regBx & 3) << 8) | channel.regAx;
// This is presumably to shift the "note on" bit so far to the left
@@ -1167,10 +1168,10 @@ void AdLibDriver::primaryEffect1(Channel &channel) {
// and leaving Kallak's hut. Related functions and variables:
//
// update_setupPrimaryEffect2()
-// - Initialises unk32, unk33, unk34, unk35 and unk36
+// - Initializes unk32, unk33, unk34, unk35 and unk36
// - unk32 is not further modified
// - unk33 is not further modified
-// - unk34 is a countdown that gets reinitialised to unk35 on zero
+// - unk34 is a countdown that gets reinitialized to unk35 on zero
// - unk35 is based on unk34 and not further modified
// - unk36 is not further modified
//
@@ -1182,13 +1183,13 @@ void AdLibDriver::primaryEffect1(Channel &channel) {
// unk32 - determines how often the notes are played
// unk33 - modifies the frequency
// unk34 - countdown, updates frequency on zero
-// unk35 - initialiser for unk34 countdown
-// unk36 - initialiser for unk38 countdown
+// unk35 - initializer for unk34 countdown
+// unk36 - initializer for unk38 countdown
// unk37 - frequency
// unk38 - countdown, begins playing on zero
// unk41 - determines how often the notes are played
//
-// Note that unk41 is never initialised. Not that it should matter much, but it
+// Note that unk41 is never initialized. Not that it should matter much, but it
// is a bit sloppy.
void AdLibDriver::primaryEffect2(Channel &channel) {
diff --git a/engines/kyra/sound_amiga.cpp b/engines/kyra/sound_amiga.cpp
index c5e9f6171d..fed21eba84 100644
--- a/engines/kyra/sound_amiga.cpp
+++ b/engines/kyra/sound_amiga.cpp
@@ -23,14 +23,11 @@
*
*/
-#include "common/system.h"
-#include "common/mutex.h"
-#include "kyra/resource.h"
#include "kyra/sound_intern.h"
+#include "kyra/resource.h"
#include "audio/mixer.h"
#include "audio/mods/maxtrax.h"
-#include "audio/audiostream.h"
namespace Kyra {
diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h
index 7b33fc218c..354f5732bf 100644
--- a/engines/kyra/sound_intern.h
+++ b/engines/kyra/sound_intern.h
@@ -219,12 +219,12 @@ public:
~MidiDriver_PCSpeaker();
// MidiDriver interface
- void close() {}
+ virtual void close() {}
- void send(uint32 data);
+ virtual void send(uint32 data);
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ virtual MidiChannel *allocateChannel() { return 0; }
+ virtual MidiChannel *getPercussionChannel() { return 0; }
// MidiDriver_Emulated interface
void generateSamples(int16 *buffer, int numSamples);
diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp
index 40daa0b5bd..83566372bf 100644
--- a/engines/kyra/sound_lok.cpp
+++ b/engines/kyra/sound_lok.cpp
@@ -23,8 +23,10 @@
*
*/
-#include "kyra/sound.h"
#include "kyra/kyra_lok.h"
+#include "kyra/sound.h"
+
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp
index 87679f5bfb..10d35e03d5 100644
--- a/engines/kyra/sound_lol.cpp
+++ b/engines/kyra/sound_lol.cpp
@@ -25,10 +25,12 @@
#ifdef ENABLE_LOL
-#include "kyra/sound.h"
#include "kyra/lol.h"
+#include "kyra/sound.h"
#include "kyra/resource.h"
+#include "common/system.h"
+
#include "audio/audiostream.h"
namespace Kyra {
diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp
index cd5af12106..02ba735a70 100644
--- a/engines/kyra/sound_midi.cpp
+++ b/engines/kyra/sound_midi.cpp
@@ -33,7 +33,7 @@
namespace Kyra {
-class MidiOutput : public MidiDriver {
+class MidiOutput : public MidiDriver_BASE {
public:
MidiOutput(OSystem *system, MidiDriver *output, bool isMT32, bool defaultMT32);
~MidiOutput();
@@ -46,19 +46,16 @@ public:
void setSoundSource(int source) { _curSource = source; }
- void send(uint32 b);
- void sysEx(const byte *msg, uint16 length);
- void metaEvent(byte type, byte *data, uint16 length);
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
+ virtual void sysEx(const byte *msg, uint16 length);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
+ // TODO: Get rid of the following two methods
void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _output->setTimerCallback(timerParam, timerProc); }
uint32 getBaseTempo() { return _output->getBaseTempo(); }
- // DUMMY
- int open() { return 0; }
- void close() {}
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
private:
void sendIntern(const byte event, const byte channel, byte param1, const byte param2);
void sendSysEx(const byte p1, const byte p2, const byte p3, const byte *buffer, const int size);
@@ -265,7 +262,7 @@ void MidiOutput::sendIntern(const byte event, const byte channel, byte param1, c
if (event == 0xC0) {
// MT32 -> GM conversion
if (!_isMT32 && _defaultMT32)
- param1 = _mt32ToGm[param1];
+ param1 = MidiDriver::_mt32ToGm[param1];
}
_output->send(event | channel, param1, param2);
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index 084bae5aab..6b30824a2f 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -23,20 +23,17 @@
*
*/
+#include "kyra/sound_intern.h"
+#include "kyra/resource.h"
+
#include "common/config-manager.h"
#include "common/system.h"
-#include "kyra/resource.h"
-#include "kyra/sound_intern.h"
-#include "kyra/screen.h"
-
#include "backends/audiocd/audiocd.h"
#include "audio/audiostream.h"
#include "audio/decoders/raw.h"
-#include "common/util.h"
-
namespace Kyra {
SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer)
diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp
index 52689869c6..23775d2946 100644
--- a/engines/kyra/sprites.cpp
+++ b/engines/kyra/sprites.cpp
@@ -23,19 +23,13 @@
*
*/
-
-#include "common/endian.h"
-#include "common/stream.h"
-#include "common/util.h"
-#include "common/system.h"
-#include "common/EventRecorder.h"
-
-#include "kyra/screen.h"
-#include "kyra/kyra_lok.h"
#include "kyra/sprites.h"
#include "kyra/resource.h"
#include "kyra/animator_lok.h"
+#include "common/system.h"
+#include "common/EventRecorder.h"
+
namespace Kyra {
Sprites::Sprites(KyraEngine_LoK *vm, OSystem *system) {
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index fe4bd2ad71..f83546e0dd 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -23,23 +23,22 @@
*
*/
-#include "common/endian.h"
-#include "common/md5.h"
-#include "kyra/kyra_v1.h"
+#include "kyra/resource.h"
#include "kyra/kyra_lok.h"
-#include "kyra/kyra_v2.h"
#include "kyra/kyra_hof.h"
#include "kyra/kyra_mr.h"
#include "kyra/screen.h"
#include "kyra/screen_lok.h"
#include "kyra/screen_hof.h"
#include "kyra/screen_mr.h"
-#include "kyra/resource.h"
#include "kyra/gui_lok.h"
#include "kyra/gui_hof.h"
#include "kyra/gui_mr.h"
#include "kyra/sound_intern.h"
+#include "common/endian.h"
+#include "common/md5.h"
+
namespace Kyra {
#define RESFILE_VERSION 73
diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp
index 09f952f67e..e0114cda29 100644
--- a/engines/kyra/text.cpp
+++ b/engines/kyra/text.cpp
@@ -23,12 +23,8 @@
*
*/
-#include "kyra/kyra_v1.h"
-#include "kyra/screen.h"
#include "kyra/text.h"
-
-#include "common/system.h"
-#include "common/endian.h"
+#include "kyra/kyra_v1.h"
namespace Kyra {
diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp
index 4c292b70db..c961d2bf49 100644
--- a/engines/kyra/text_hof.cpp
+++ b/engines/kyra/text_hof.cpp
@@ -24,11 +24,9 @@
*/
#include "kyra/text_hof.h"
-#include "kyra/kyra_hof.h"
-#include "kyra/script_tim.h"
#include "kyra/resource.h"
-#include "common/endian.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp
index 40f2217a2b..cca8e5aaf5 100644
--- a/engines/kyra/text_lok.cpp
+++ b/engines/kyra/text_lok.cpp
@@ -23,13 +23,14 @@
*
*/
-#include "kyra/kyra_lok.h"
-#include "kyra/screen_lok.h"
#include "kyra/text.h"
+#include "kyra/kyra_lok.h"
#include "kyra/animator_lok.h"
#include "kyra/sprites.h"
#include "kyra/timer.h"
+#include "common/system.h"
+
namespace Kyra {
void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum, const bool printText) {
diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp
index 9f98586303..c9a77be1b2 100644
--- a/engines/kyra/text_lol.cpp
+++ b/engines/kyra/text_lol.cpp
@@ -25,10 +25,13 @@
#ifdef ENABLE_LOL
+#include "kyra/text_lol.h"
#include "kyra/lol.h"
#include "kyra/screen_lol.h"
#include "kyra/timer.h"
-#include "kyra/util.h"
+#include "kyra/sound.h"
+
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h
index 1e5bc8884e..edac131106 100644
--- a/engines/kyra/text_lol.h
+++ b/engines/kyra/text_lol.h
@@ -28,9 +28,11 @@
#ifndef KYRA_TEXT_LOL_H
#define KYRA_TEXT_LOL_H
+#include "common/scummsys.h"
+
namespace Kyra {
-class Screen_v2;
+class Screen_LoL;
class LoLEngine;
struct EMCState;
diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp
index 98c6ef3130..5679dc1ee6 100644
--- a/engines/kyra/text_mr.cpp
+++ b/engines/kyra/text_mr.cpp
@@ -24,9 +24,10 @@
*/
#include "kyra/text_mr.h"
-#include "kyra/screen_mr.h"
#include "kyra/resource.h"
+#include "common/system.h"
+
namespace Kyra {
TextDisplayer_MR::TextDisplayer_MR(KyraEngine_MR *vm, Screen_MR *screen)
@@ -340,10 +341,8 @@ void KyraEngine_MR::objectChatWaitToFinish() {
_emc->start(&_chatScriptState, 1);
_animNeedUpdate = false;
- while (!_animNeedUpdate && _emc->isValid(&_chatScriptState) && !shouldQuit()) {
- musicUpdate(0);
+ while (!_animNeedUpdate && _emc->isValid(&_chatScriptState) && !shouldQuit())
_emc->run(&_chatScriptState);
- }
int curFrame = _animNewFrame;
uint32 delayTime = _animDelayTime;
diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp
index 66b78d3c03..475f17cadc 100644
--- a/engines/kyra/timer.cpp
+++ b/engines/kyra/timer.cpp
@@ -23,11 +23,9 @@
*
*/
-#include "kyra/kyra_v1.h"
#include "kyra/timer.h"
-#include "common/func.h"
-#include "common/stream.h"
+#include "common/system.h"
namespace Kyra {
diff --git a/engines/kyra/timer_lok.cpp b/engines/kyra/timer_lok.cpp
index 6f4948c279..3a312c22c6 100644
--- a/engines/kyra/timer_lok.cpp
+++ b/engines/kyra/timer_lok.cpp
@@ -23,14 +23,10 @@
*
*/
-#include "kyra/kyra_v1.h"
#include "kyra/kyra_lok.h"
-#include "kyra/screen.h"
#include "kyra/animator_lok.h"
#include "kyra/timer.h"
-#include "common/system.h"
-
namespace Kyra {
#define TimerV1(x) new Common::Functor1Mem<int, void, KyraEngine_LoK>(this, &KyraEngine_LoK::x)
@@ -75,7 +71,6 @@ void KyraEngine_LoK::setupTimers() {
}
void KyraEngine_LoK::timerUpdateHeadAnims(int timerNum) {
- static int8 currentFrame = 0;
static const int8 frameTable[] = {
4, 5, 4, 5, 4, 5, 0, 1,
4, 5, 4, 4, 6, 4, 8, 1,
@@ -85,11 +80,11 @@ void KyraEngine_LoK::timerUpdateHeadAnims(int timerNum) {
if (_talkingCharNum < 0)
return;
- _currHeadShape = frameTable[currentFrame];
- currentFrame++;
+ _currHeadShape = frameTable[_currentHeadFrameTableIndex];
+ ++_currentHeadFrameTableIndex;
- if (frameTable[currentFrame] == -1)
- currentFrame = 0;
+ if (frameTable[_currentHeadFrameTableIndex] == -1)
+ _currentHeadFrameTableIndex = 0;
_animator->animRefreshNPC(0);
_animator->animRefreshNPC(_talkingCharNum);
diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp
index 90cfc1af78..a3dab365c7 100644
--- a/engines/kyra/timer_lol.cpp
+++ b/engines/kyra/timer_lol.cpp
@@ -26,9 +26,10 @@
#ifdef ENABLE_LOL
#include "kyra/lol.h"
-#include "kyra/screen_lol.h"
#include "kyra/timer.h"
+#include "common/system.h"
+
namespace Kyra {
#define TimerV2(x) new Common::Functor1Mem<int, void, LoLEngine>(this, &LoLEngine::x)
diff --git a/engines/kyra/timer_mr.cpp b/engines/kyra/timer_mr.cpp
index 0d89decf5a..97ce7c166d 100644
--- a/engines/kyra/timer_mr.cpp
+++ b/engines/kyra/timer_mr.cpp
@@ -26,6 +26,8 @@
#include "kyra/kyra_mr.h"
#include "kyra/timer.h"
+#include "common/system.h"
+
namespace Kyra {
#define TimerV3(x) new Common::Functor1Mem<int, void, KyraEngine_MR>(this, &KyraEngine_MR::x)
diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp
index 382ec2429d..28071bc171 100644
--- a/engines/kyra/vqa.cpp
+++ b/engines/kyra/vqa.cpp
@@ -33,16 +33,14 @@
#include "kyra/vqa.h"
+#include "kyra/resource.h"
#include "common/system.h"
+
#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "audio/decoders/raw.h"
-#include "kyra/sound.h"
-#include "kyra/screen.h"
-#include "kyra/resource.h"
-
namespace Kyra {
VQAMovie::VQAMovie(KyraEngine_v1 *vm, OSystem *system) {
@@ -204,7 +202,7 @@ bool VQAMovie::open(const char *filename) {
if (!_file)
return false;
- if (_file->readUint32BE() != MKID_BE('FORM')) {
+ if (_file->readUint32BE() != MKTAG('F','O','R','M')) {
warning("VQAMovie::open: Cannot find `FORM' tag");
return false;
}
@@ -212,7 +210,7 @@ bool VQAMovie::open(const char *filename) {
// For now, we ignore the size of the FORM chunk.
_file->readUint32BE();
- if (_file->readUint32BE() != MKID_BE('WVQA')) {
+ if (_file->readUint32BE() != MKTAG('W','V','Q','A')) {
warning("WQAMovie::open: Cannot find `WVQA' tag");
return false;
}
@@ -228,7 +226,7 @@ bool VQAMovie::open(const char *filename) {
uint32 size = _file->readUint32BE();
switch (tag) {
- case MKID_BE('VQHD'): // VQA header
+ case MKTAG('V','Q','H','D'): // VQA header
_header.version = _file->readUint16LE();
_header.flags = _file->readUint16LE();
_header.numFrames = _file->readUint16LE();
@@ -304,7 +302,7 @@ bool VQAMovie::open(const char *filename) {
foundHeader = true;
break;
- case MKID_BE('FINF'): // Frame info
+ case MKTAG('F','I','N','F'): // Frame info
if (!foundHeader) {
warning("VQAMovie::open: Found `FINF' before `VQHD'");
return false;
@@ -343,7 +341,7 @@ bool VQAMovie::open(const char *filename) {
if (_file->eos())
break;
- if (scanTag == MKID_BE('VQFR')) {
+ if (scanTag == MKTAG('V','Q','F','R')) {
_frameInfo[0] = (_file->pos() - 8) | 0x80000000;
break;
}
@@ -421,7 +419,7 @@ void VQAMovie::displayFrame(uint frameNum) {
int32 end;
switch (tag) {
- case MKID_BE('SND0'): // Uncompressed sound
+ case MKTAG('S','N','D','0'): // Uncompressed sound
foundSound = true;
inbuf = (byte *)malloc(size);
_file->read(inbuf, size);
@@ -429,7 +427,7 @@ void VQAMovie::displayFrame(uint frameNum) {
_stream->queueBuffer(inbuf, size, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
break;
- case MKID_BE('SND1'): // Compressed sound, almost like AUD
+ case MKTAG('S','N','D','1'): // Compressed sound, almost like AUD
foundSound = true;
outsize = _file->readUint16LE();
insize = _file->readUint16LE();
@@ -449,13 +447,13 @@ void VQAMovie::displayFrame(uint frameNum) {
}
break;
- case MKID_BE('SND2'): // Compressed sound
+ case MKTAG('S','N','D','2'): // Compressed sound
foundSound = true;
warning("VQAMovie::displayFrame: `SND2' is not implemented");
_file->seek(size, SEEK_CUR);
break;
- case MKID_BE('VQFR'):
+ case MKTAG('V','Q','F','R'):
foundFrame = true;
end = _file->pos() + size - 8;
@@ -464,49 +462,49 @@ void VQAMovie::displayFrame(uint frameNum) {
size = _file->readUint32BE();
switch (tag) {
- case MKID_BE('CBF0'): // Full codebook
+ case MKTAG('C','B','F','0'): // Full codebook
_file->read(_codeBook, size);
break;
- case MKID_BE('CBFZ'): // Full codebook
+ case MKTAG('C','B','F','Z'): // Full codebook
inbuf = (byte *)allocBuffer(0, size);
_file->read(inbuf, size);
Screen::decodeFrame4(inbuf, _codeBook, _codeBookSize);
break;
- case MKID_BE('CBP0'): // Partial codebook
+ case MKTAG('C','B','P','0'): // Partial codebook
_compressedCodeBook = false;
_file->read(_partialCodeBook + _partialCodeBookSize, size);
_partialCodeBookSize += size;
_numPartialCodeBooks++;
break;
- case MKID_BE('CBPZ'): // Partial codebook
+ case MKTAG('C','B','P','Z'): // Partial codebook
_compressedCodeBook = true;
_file->read(_partialCodeBook + _partialCodeBookSize, size);
_partialCodeBookSize += size;
_numPartialCodeBooks++;
break;
- case MKID_BE('CPL0'): // Palette
+ case MKTAG('C','P','L','0'): // Palette
assert(size <= 3 * 256);
_file->read(_screen->getPalette(0).getData(), size);
break;
- case MKID_BE('CPLZ'): // Palette
+ case MKTAG('C','P','L','Z'): // Palette
inbuf = (byte *)allocBuffer(0, size);
_file->read(inbuf, size);
Screen::decodeFrame4(inbuf, _screen->getPalette(0).getData(), 768);
break;
- case MKID_BE('VPT0'): // Frame data
+ case MKTAG('V','P','T','0'): // Frame data
assert(size / 2 <= _numVectorPointers);
for (i = 0; i < size / 2; i++)
_vectorPointers[i] = _file->readUint16LE();
break;
- case MKID_BE('VPTZ'): // Frame data
+ case MKTAG('V','P','T','Z'): // Frame data
inbuf = (byte *)allocBuffer(0, size);
outbuf = (byte *)allocBuffer(1, 2 * _numVectorPointers);
@@ -613,13 +611,13 @@ void VQAMovie::play() {
}
switch (tag) {
- case MKID_BE('SND0'): // Uncompressed sound
+ case MKTAG('S','N','D','0'): // Uncompressed sound
inbuf = (byte *)malloc(size);
_file->read(inbuf, size);
_stream->queueBuffer(inbuf, size, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
break;
- case MKID_BE('SND1'): // Compressed sound
+ case MKTAG('S','N','D','1'): // Compressed sound
outsize = _file->readUint16LE();
insize = _file->readUint16LE();
@@ -636,12 +634,12 @@ void VQAMovie::play() {
}
break;
- case MKID_BE('SND2'): // Compressed sound
+ case MKTAG('S','N','D','2'): // Compressed sound
warning("VQAMovie::play: `SND2' is not implemented");
_file->seek(size, SEEK_CUR);
break;
- case MKID_BE('CMDS'): // Unused tag, always empty in kyra3
+ case MKTAG('C','M','D','S'): // Unused tag, always empty in kyra3
_file->seek(size, SEEK_CUR);
break;
diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp
index c9536484a3..db324d48d4 100644
--- a/engines/kyra/wsamovie.cpp
+++ b/engines/kyra/wsamovie.cpp
@@ -23,18 +23,13 @@
*
*/
-
-#include "common/endian.h"
-#include "common/system.h"
-
-#include "kyra/kyra_v1.h"
-#include "kyra/kyra_v2.h"
-#include "kyra/screen.h"
-#include "kyra/screen_v2.h"
#include "kyra/wsamovie.h"
#include "kyra/resource.h"
+#include "common/endian.h"
+
namespace Kyra {
+
WSAMovie_v1::WSAMovie_v1(KyraEngine_v1 *vm)
: Movie(vm), _frameData(0), _frameOffsTable(0), _offscreenBuffer(0), _deltaBuffer(0) {
}
diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h
index d2c041742a..f755cdd557 100644
--- a/engines/kyra/wsamovie.h
+++ b/engines/kyra/wsamovie.h
@@ -26,10 +26,10 @@
#ifndef KYRA_WSAMOVIE_H
#define KYRA_WSAMOVIE_H
+#include "kyra/kyra_v1.h"
+
namespace Kyra {
-class KyraEngine_v1;
-class Screen_v2;
class Palette;
class Movie {
diff --git a/engines/lastexpress/data/animation.cpp b/engines/lastexpress/data/animation.cpp
index 7288889f09..2bf9bd4999 100644
--- a/engines/lastexpress/data/animation.cpp
+++ b/engines/lastexpress/data/animation.cpp
@@ -35,7 +35,10 @@
#include "common/events.h"
#include "common/rational.h"
+#include "common/rect.h"
#include "common/stream.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "engines/engine.h"
@@ -266,7 +269,7 @@ void Animation::play() {
if (_changed) {
// Create a temporary surface to merge the overlay with the background
Graphics::Surface *s = new Graphics::Surface;
- s->create(640, 480, 2);
+ s->create(640, 480, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
draw(s);
diff --git a/engines/lastexpress/data/archive.h b/engines/lastexpress/data/archive.h
index 3860245bc5..17b1d661fa 100644
--- a/engines/lastexpress/data/archive.h
+++ b/engines/lastexpress/data/archive.h
@@ -39,6 +39,9 @@
*/
#include "common/archive.h"
+#include "common/hash-str.h"
+#include "common/hashmap.h"
+#include "common/str.h"
namespace LastExpress {
diff --git a/engines/lastexpress/data/background.cpp b/engines/lastexpress/data/background.cpp
index 8b0d338f64..e8236bca86 100644
--- a/engines/lastexpress/data/background.cpp
+++ b/engines/lastexpress/data/background.cpp
@@ -31,6 +31,7 @@
#include "lastexpress/debug.h"
+#include "common/rect.h"
#include "common/stream.h"
namespace LastExpress {
diff --git a/engines/lastexpress/data/font.cpp b/engines/lastexpress/data/font.cpp
index 99239606ab..d9acbb8382 100644
--- a/engines/lastexpress/data/font.cpp
+++ b/engines/lastexpress/data/font.cpp
@@ -25,8 +25,10 @@
#include "lastexpress/data/font.h"
+#include "common/rect.h"
#include "common/stream.h"
#include "common/system.h"
+#include "common/textconsole.h"
namespace LastExpress {
diff --git a/engines/lastexpress/data/font.h b/engines/lastexpress/data/font.h
index d49db35ba5..7bcf03ed7d 100644
--- a/engines/lastexpress/data/font.h
+++ b/engines/lastexpress/data/font.h
@@ -39,10 +39,12 @@
byte {x} - Unknown data (probably just garbage)
*/
+#include "common/str.h"
#include "graphics/surface.h"
namespace Common {
class SeekableReadStream;
+struct Rect;
}
namespace LastExpress {
diff --git a/engines/lastexpress/data/scene.cpp b/engines/lastexpress/data/scene.cpp
index 5a943982c4..e893d641a5 100644
--- a/engines/lastexpress/data/scene.cpp
+++ b/engines/lastexpress/data/scene.cpp
@@ -31,6 +31,7 @@
#include "lastexpress/lastexpress.h"
#include "lastexpress/resource.h"
+#include "common/textconsole.h"
#include "common/stream.h"
namespace LastExpress {
diff --git a/engines/lastexpress/data/scene.h b/engines/lastexpress/data/scene.h
index 7fc9425f28..9ec1899402 100644
--- a/engines/lastexpress/data/scene.h
+++ b/engines/lastexpress/data/scene.h
@@ -72,9 +72,15 @@
#include "lastexpress/shared.h"
#include "common/array.h"
+#include "common/rect.h"
namespace Common {
class SeekableReadStream;
+class String;
+}
+
+namespace Graphics {
+struct Surface;
}
namespace LastExpress {
diff --git a/engines/lastexpress/data/sequence.cpp b/engines/lastexpress/data/sequence.cpp
index 2308d70a2b..b986a33d5c 100644
--- a/engines/lastexpress/data/sequence.cpp
+++ b/engines/lastexpress/data/sequence.cpp
@@ -30,6 +30,7 @@
#include "lastexpress/debug.h"
#include "common/stream.h"
+#include "common/textconsole.h"
namespace LastExpress {
@@ -82,7 +83,7 @@ void FrameInfo::read(Common::SeekableReadStream *in, bool isSequence) {
AnimFrame::AnimFrame(Common::SeekableReadStream *in, const FrameInfo &f) : _palette(NULL) {
_palSize = 1;
// TODO: use just the needed rectangle
- _image.create(640, 480, 1);
+ _image.create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
//debugC(6, kLastExpressDebugGraphics, " Offsets: data=%d, unknown=%d, palette=%d", f.dataOffset, f.unknown, f.paletteOffset);
//debugC(6, kLastExpressDebugGraphics, " Position: (%d, %d) - (%d, %d)", f.xPos1, f.yPos1, f.xPos2, f.yPos2);
diff --git a/engines/lastexpress/data/sequence.h b/engines/lastexpress/data/sequence.h
index 7ad0a57254..cd16f26ab2 100644
--- a/engines/lastexpress/data/sequence.h
+++ b/engines/lastexpress/data/sequence.h
@@ -77,6 +77,8 @@
#include "lastexpress/shared.h"
#include "common/array.h"
+#include "common/rect.h"
+#include "common/str.h"
namespace Common {
class SeekableReadStream;
diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp
index bd2320726a..a50fa7be08 100644
--- a/engines/lastexpress/data/snd.cpp
+++ b/engines/lastexpress/data/snd.cpp
@@ -30,12 +30,48 @@
#include "lastexpress/debug.h"
-#include "audio/decoders/adpcm.h"
+#include "audio/decoders/adpcm_intern.h"
#include "audio/audiostream.h"
+#include "common/debug.h"
#include "common/memstream.h"
+#include "common/system.h"
+#include "common/textconsole.h"
namespace LastExpress {
+// Last Express ADPCM is similar to MS IMA mono, but inverts its nibbles
+// and does not have the 4 byte per channel requirement
+
+class LastExpress_ADPCMStream : public Audio::Ima_ADPCMStream {
+public:
+ LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize) :
+ Audio::Ima_ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) {}
+
+ int readBuffer(int16 *buffer, const int numSamples) {
+ int samples = 0;
+
+ assert(numSamples % 2 == 0);
+
+ while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
+ if (_blockPos[0] == _blockAlign) {
+ // read block header
+ _status.ima_ch[0].last = _stream->readSint16LE();
+ _status.ima_ch[0].stepIndex = _stream->readSint16LE();
+ _blockPos[0] = 4;
+ }
+
+ for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
+ byte data = _stream->readByte();
+ _blockPos[0]++;
+ buffer[samples] = decodeIMA((data >> 4) & 0x0f);
+ buffer[samples + 1] = decodeIMA(data & 0x0f);
+ }
+ }
+
+ return samples;
+ }
+};
+
//////////////////////////////////////////////////////////////////////////
// Sound
//////////////////////////////////////////////////////////////////////////
@@ -60,7 +96,7 @@ void SimpleSound::loadHeader(Common::SeekableReadStream *in) {
}
Audio::AudioStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size) const {
- return Audio::makeADPCMStream(in, DisposeAfterUse::YES, size, Audio::kADPCMMSImaLastExpress, 44100, 1, _blockSize);
+ return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize);
}
void SimpleSound::play(Audio::AudioStream *as) {
diff --git a/engines/lastexpress/data/snd.h b/engines/lastexpress/data/snd.h
index 2d28404f42..61d1c0951a 100644
--- a/engines/lastexpress/data/snd.h
+++ b/engines/lastexpress/data/snd.h
@@ -42,8 +42,8 @@
#include "audio/mixer.h"
namespace Audio {
- class AudioStream;
- class QueuingAudioStream;
+class AudioStream;
+class QueuingAudioStream;
}
namespace Common {
diff --git a/engines/lastexpress/data/subtitle.cpp b/engines/lastexpress/data/subtitle.cpp
index 953edd1d1a..2bc5d3c5ad 100644
--- a/engines/lastexpress/data/subtitle.cpp
+++ b/engines/lastexpress/data/subtitle.cpp
@@ -33,7 +33,9 @@
#include "lastexpress/debug.h"
#include "common/debug.h"
+#include "common/rect.h"
#include "common/stream.h"
+#include "common/textconsole.h"
namespace LastExpress {
diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h
index ccef312cd6..8c6cc2bafc 100644
--- a/engines/lastexpress/entities/entity.h
+++ b/engines/lastexpress/entities/entity.h
@@ -35,6 +35,7 @@
#include "common/array.h"
#include "common/func.h"
#include "common/serializer.h"
+#include "common/textconsole.h"
namespace LastExpress {
diff --git a/engines/lastexpress/game/state.h b/engines/lastexpress/game/state.h
index d97ebc1b55..4196bfe06a 100644
--- a/engines/lastexpress/game/state.h
+++ b/engines/lastexpress/game/state.h
@@ -28,8 +28,10 @@
#include "lastexpress/shared.h"
+#include "common/rect.h"
#include "common/serializer.h"
#include "common/system.h"
+#include "common/textconsole.h"
namespace LastExpress {
diff --git a/engines/lastexpress/graphics.cpp b/engines/lastexpress/graphics.cpp
index e5a69d16ea..c45baba808 100644
--- a/engines/lastexpress/graphics.cpp
+++ b/engines/lastexpress/graphics.cpp
@@ -25,20 +25,23 @@
#include "lastexpress/graphics.h"
+#include "common/rect.h"
#include "common/system.h"
+#include "common/textconsole.h"
namespace LastExpress {
#define COLOR_KEY 0xFFFF
GraphicsManager::GraphicsManager() : _changed(false) {
- _screen.create(640, 480, 2);
+ const Graphics::PixelFormat format(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ _screen.create(640, 480, format);
// Create the game surfaces
- _backgroundA.create(640, 480, 2);
- _backgroundC.create(640, 480, 2);
- _overlay.create(640, 480, 2);
- _inventory.create(640, 480, 2);
+ _backgroundA.create(640, 480, format);
+ _backgroundC.create(640, 480, format);
+ _overlay.create(640, 480, format);
+ _inventory.create(640, 480, format);
clear(kBackgroundAll);
}
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index ad6e5f2a24..7c08fef627 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -56,6 +56,8 @@ LastExpressEngine::LastExpressEngine(OSystem *syst, const ADGameDescription *gd)
_font(NULL), _logic(NULL), _menu(NULL), _frameCounter(0), _lastFrameCount(0),
_graphicsMan(NULL), _resMan(NULL), _sceneMan(NULL), _soundMan(NULL),
_eventMouse(NULL), _eventTick(NULL), _eventMouseBackup(NULL), _eventTickBackup(NULL) {
+ // Setup mixer
+ syncSoundSettings();
// Adding the default directories
const Common::FSNode gameDataDir(ConfMan.get("path"));
@@ -139,7 +141,7 @@ Common::Error LastExpressEngine::run() {
// Start sound manager and setup timer
_soundMan = new SoundManager(this);
- _timer->installTimerProc(&soundTimer, 17, this);
+ _timer->installTimerProc(&soundTimer, 17000, this);
// Menu
_menu = new Menu(this);
diff --git a/engines/lastexpress/resource.cpp b/engines/lastexpress/resource.cpp
index 5a77b23602..dff686a503 100644
--- a/engines/lastexpress/resource.cpp
+++ b/engines/lastexpress/resource.cpp
@@ -34,6 +34,7 @@
#include "common/debug.h"
#include "common/file.h"
+#include "common/textconsole.h"
namespace LastExpress {
diff --git a/engines/lure/debugger.cpp b/engines/lure/debugger.cpp
index 9b1bb743e4..fc2029c6c4 100644
--- a/engines/lure/debugger.cpp
+++ b/engines/lure/debugger.cpp
@@ -312,7 +312,7 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) {
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, Colour offset = %d\n", hs->animRecordId, hs->colourOffset);
+ 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);
@@ -543,7 +543,7 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) {
hotspot->setSize(width, height);
Hotspot *player = res.activateHotspot(PLAYER_ID);
- hotspot->setColourOffset(player->resource()->colourOffset);
+ hotspot->setColorOffset(player->resource()->colorOffset);
hotspot->setAnimation(animId);
diff --git a/engines/lure/decode.cpp b/engines/lure/decode.cpp
index ae91cc1c52..5ffdcf1884 100644
--- a/engines/lure/decode.cpp
+++ b/engines/lure/decode.cpp
@@ -111,7 +111,7 @@ MemoryBlock *PictureDecoder::egaDecode(MemoryBlock *src, uint32 maxOutputSize) {
dataPos += sizeof(uint16);
int bitCtr = 8;
- // Decode the colour popularity table
+ // Decode the color popularity table
for (int nibbleCtr = 0; nibbleCtr < 32; ++nibbleCtr) {
for (int byteCtr = 0; byteCtr < 128; byteCtr += 32) {
@@ -134,7 +134,7 @@ MemoryBlock *PictureDecoder::egaDecode(MemoryBlock *src, uint32 maxOutputSize) {
READ_BIT_DX
if (!bitFlag) {
- // Get the favourite colour
+ // Get the favourite color
v = popTable[tableOffset];
} else {
@@ -182,7 +182,7 @@ MemoryBlock *PictureDecoder::egaDecode(MemoryBlock *src, uint32 maxOutputSize) {
continue;
} else {
- // It's a new colour
+ // It's a new color
v = al;
}
diff --git a/engines/lure/disk.h b/engines/lure/disk.h
index d2848cc587..79aaf80bbc 100644
--- a/engines/lure/disk.h
+++ b/engines/lure/disk.h
@@ -33,7 +33,7 @@
#include "lure/res_struct.h"
namespace Common {
- class File;
+class File;
}
namespace Lure {
diff --git a/engines/lure/fights.cpp b/engines/lure/fights.cpp
index 789c9d924e..983033281a 100644
--- a/engines/lure/fights.cpp
+++ b/engines/lure/fights.cpp
@@ -74,7 +74,7 @@ void FightsManager::setupPigFight() {
Resources &res = Resources::getReference();
Hotspot *player = res.getActiveHotspot(PLAYER_ID);
player->setSkipFlag(false);
- player->resource()->colourOffset = 16;
+ player->resource()->colorOffset = 16;
player->setTickProc(PLAYER_FIGHT_TICK_PROC_ID);
player->setSize(48, 53);
player->setAnimationIndex(PLAYER_FIGHT_ANIM_INDEX);
@@ -103,7 +103,7 @@ void FightsManager::setupSkorlFight() {
rec.fwtrue_x = 282;
rec.fwtrue_y = 136;
player->setPosition(282, 136);
- player->resource()->colourOffset = 96;
+ player->resource()->colorOffset = 96;
}
bool FightsManager::isFighting() {
@@ -598,7 +598,7 @@ void FightsManager::enemyKilled() {
playerHotspot->setTickProc(PLAYER_TICK_PROC_ID);
playerRec.fwhits = GENERAL_MAGIC_ID;
- playerHotspot->resource()->colourOffset = 128;
+ playerHotspot->resource()->colorOffset = 128;
playerHotspot->setSize(32, 48);
playerHotspot->resource()->width = 32;
playerHotspot->resource()->height = 48;
diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp
index bce98b28fd..5644ef798c 100644
--- a/engines/lure/hotspots.cpp
+++ b/engines/lure/hotspots.cpp
@@ -73,7 +73,7 @@ Hotspot::Hotspot(HotspotData *res): _pathFinder(this) {
_hotspotScriptOffset = res->hotspotScriptOffset;
_frameCtr = res->tickTimeout;
_tempDest.counter = 0;
- _colourOffset = isEGA ? 0 : res->colourOffset;
+ _colorOffset = isEGA ? 0 : res->colorOffset;
_override = resources.getHotspotOverride(res->hotspotId);
setAnimation(_data->animRecordId);
@@ -103,7 +103,7 @@ Hotspot::Hotspot(Hotspot *character, uint16 objType): _pathFinder(this) {
_persistant = false;
_hotspotId = 0xffff;
_override = NULL;
- _colourOffset = 0;
+ _colorOffset = 0;
_destHotspotId = character->hotspotId();
_blockedOffset = 0;
_exitCtr = 0;
@@ -174,7 +174,7 @@ Hotspot::Hotspot(): _pathFinder(NULL) {
_persistant = false;
_hotspotId = 0xffff;
_override = NULL;
- _colourOffset = 0;
+ _colorOffset = 0;
_destHotspotId = 0;
_blockedOffset = 0;
_exitCtr = 0;
@@ -303,7 +303,7 @@ void Hotspot::setAnimation(HotspotAnimData *newRecord) {
_frames = new Surface(_width * _numFrames, _height);
_frameStartsUsed = false;
}
- _frames->data().setBytes(_colourOffset, 0, _frames->data().size());
+ _frames->data().setBytes(_colorOffset, 0, _frames->data().size());
byte *pSrc = dest->data() + 0x40;
byte *pDest;
@@ -353,13 +353,13 @@ void Hotspot::setAnimation(HotspotAnimData *newRecord) {
xStart = frameNumCtr * _width;
}
- // Copy over the frame, applying the colour offset to each nibble
+ // Copy over the frame, applying the color offset to each nibble
for (uint16 yPos = 0; yPos < tempHeight; ++yPos) {
pDest = mDest.data() + yPos * _frames->width() + xStart;
for (uint16 xPos = 0; xPos < tempWidth / 2; ++xPos) {
- *pDest++ = _colourOffset + (*pSrc >> 4);
- *pDest++ = _colourOffset + (*pSrc & 0xf);
+ *pDest++ = _colorOffset + (*pSrc >> 4);
+ *pDest++ = _colorOffset + (*pSrc & 0xf);
++pSrc;
}
}
@@ -421,7 +421,7 @@ void Hotspot::copyTo(Surface *dest) {
if ((r.top >= r.bottom) || (r.left >= r.right))
return;
- _frames->copyTo(dest, r, (uint16) xPos, (uint16) yPos, _colourOffset);
+ _frames->copyTo(dest, r, (uint16) xPos, (uint16) yPos, _colorOffset);
}
void Hotspot::incFrameNumber() {
@@ -2313,7 +2313,7 @@ void Hotspot::saveToStream(Common::WriteStream *stream) {
stream->writeUint16LE(_talkY);
stream->writeByte(_layer);
stream->writeUint16LE(_hotspotScriptOffset);
- stream->writeByte(_colourOffset);
+ stream->writeByte(_colorOffset);
stream->writeByte((byte)_direction);
stream->writeUint16LE(_animId);
stream->writeUint16LE(_frameNumber);
@@ -2358,7 +2358,7 @@ void Hotspot::loadFromStream(Common::ReadStream *stream) {
_talkY = stream->readUint16LE();
_layer = stream->readByte();
_hotspotScriptOffset = stream->readUint16LE();
- _colourOffset = stream->readByte();
+ _colorOffset = stream->readByte();
_direction = (Direction)stream->readByte();
setAnimation(stream->readUint16LE());
setFrameNumber(stream->readUint16LE());
@@ -3505,10 +3505,10 @@ void HotspotTickHandlers::talkAnimHandler(Hotspot &h) {
screen.screen().fillRect(r, 0);
// Display line
- byte colour = LureEngine::getReference().isEGA() ?
- ((lineNum + 1 == selectedLine) ? EGA_DIALOG_WHITE_COLOUR : EGA_DIALOG_TEXT_COLOUR) :
- ((lineNum + 1 == selectedLine) ? VGA_DIALOG_WHITE_COLOUR : VGA_DIALOG_TEXT_COLOUR);
- screen.screen().writeString(r.left, r.top, buffer, false, colour);
+ byte color = LureEngine::getReference().isEGA() ?
+ ((lineNum + 1 == selectedLine) ? EGA_DIALOG_WHITE_COLOR : EGA_DIALOG_TEXT_COLOR) :
+ ((lineNum + 1 == selectedLine) ? VGA_DIALOG_WHITE_COLOR : VGA_DIALOG_TEXT_COLOR);
+ screen.screen().writeString(r.left, r.top, buffer, false, color);
}
if (mouse.mButton() || mouse.rButton()) {
diff --git a/engines/lure/hotspots.h b/engines/lure/hotspots.h
index 2ae2e91ecf..e9f5d56edd 100644
--- a/engines/lure/hotspots.h
+++ b/engines/lure/hotspots.h
@@ -203,7 +203,7 @@ private:
Direction _direction;
uint8 _layer;
uint16 _hotspotScriptOffset;
- uint8 _colourOffset;
+ uint8 _colorOffset;
bool _persistant;
HotspotOverrideData *_override;
bool _skipFlag;
@@ -324,8 +324,8 @@ public:
void setTickProc(uint16 newVal);
bool persistant() { return _persistant; }
void setPersistant(bool value) { _persistant = value; }
- uint8 colourOffset() { return _colourOffset; }
- void setColourOffset(uint8 value) { _colourOffset = value; }
+ uint8 colorOffset() { return _colorOffset; }
+ void setColorOffset(uint8 value) { _colorOffset = value; }
void setRoomNumber(uint16 roomNum) {
_roomNumber = roomNum;
if (_data) _data->roomNumber = roomNum;
diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp
index ca102e237c..b0968c1956 100644
--- a/engines/lure/lure.cpp
+++ b/engines/lure/lure.cpp
@@ -95,6 +95,10 @@ Common::Error LureEngine::init() {
_gameToLoad = -1;
_initialised = true;
+
+ // Setup mixer
+ syncSoundSettings();
+
return Common::kNoError;
}
@@ -264,6 +268,8 @@ GUI::Debugger *LureEngine::getDebugger() {
}
void LureEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
Sound.syncSounds();
}
diff --git a/engines/lure/lure.h b/engines/lure/lure.h
index 99e9e3d93e..52b785a09a 100644
--- a/engines/lure/lure.h
+++ b/engines/lure/lure.h
@@ -98,7 +98,7 @@ public:
virtual Common::Error run() {
Common::Error err;
err = init();
- if (err != Common::kNoError)
+ if (err.getCode() != Common::kNoError)
return err;
return go();
}
diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h
index b13c4a0724..0ef7a73b7e 100644
--- a/engines/lure/luredefs.h
+++ b/engines/lure/luredefs.h
@@ -111,7 +111,7 @@ enum Action {
// Basic game dimensions
#define FULL_SCREEN_WIDTH 320
#define FULL_SCREEN_HEIGHT 200
-#define GAME_COLOURS 256
+#define GAME_COLORS 256
#define SCREEN_SIZE (FULL_SCREEN_HEIGHT * FULL_SCREEN_WIDTH)
// Some resources include multiple packed palettes of 64 entries each
@@ -120,7 +120,7 @@ enum Action {
#define RES_PALETTE_ENTRIES 220
// Main working palette size
#define MAIN_PALETTE_SIZE 228
-// Palette colour increment amouns for palette fade in/outs
+// Palette color increment amouns for palette fade in/outs
#define PALETTE_FADE_INC_SIZE 4
// EGA constants
@@ -189,11 +189,11 @@ enum CursorType {CURSOR_ARROW = 0, CURSOR_DISK = 1, CURSOR_TIME_START = 2,
#define POPMENU_CHANGE_SENSITIVITY 5
// Dialog related defines
-#define EGA_DIALOG_TEXT_COLOUR 6
-#define EGA_DIALOG_WHITE_COLOUR 2
-#define VGA_DIALOG_TEXT_COLOUR 0xe2
-#define VGA_DIALOG_WHITE_COLOUR 0xe3
-#define EGA_DIALOG_BG_COLOUR 13
+#define EGA_DIALOG_TEXT_COLOR 6
+#define EGA_DIALOG_WHITE_COLOR 2
+#define VGA_DIALOG_TEXT_COLOR 0xe2
+#define VGA_DIALOG_WHITE_COLOR 0xe3
+#define EGA_DIALOG_BG_COLOR 13
#define INFO_DIALOG_X 69
#define INFO_DIALOG_Y 61
#define INFO_DIALOG_WIDTH 191
diff --git a/engines/lure/memory.cpp b/engines/lure/memory.cpp
index f96b5015bc..d3d5067cce 100644
--- a/engines/lure/memory.cpp
+++ b/engines/lure/memory.cpp
@@ -25,6 +25,7 @@
#include "lure/memory.h"
#include "common/file.h"
+#include "common/textconsole.h"
namespace Lure {
diff --git a/engines/lure/menu.cpp b/engines/lure/menu.cpp
index 7d0816ee79..f9a78d8fc8 100644
--- a/engines/lure/menu.cpp
+++ b/engines/lure/menu.cpp
@@ -34,7 +34,7 @@
#include "lure/events.h"
#include "lure/lure.h"
-#if defined(_WIN32_WCE) || defined(__SYMBIAN32__)
+#if defined(_WIN32_WCE) || defined(__SYMBIAN32__) || defined(WEBOS)
#define LURE_CLICKABLE_MENUS
#endif
@@ -153,7 +153,7 @@ uint8 Menu::execute() {
toggleHighlight(_selectedMenu);
_surfaceMenu = Surface::newDialog(
_selectedMenu->width(), _selectedMenu->numEntries(),
- _selectedMenu->entries(), false, DEFAULT_TEXT_COLOUR, false);
+ _selectedMenu->entries(), false, DEFAULT_TEXT_COLOR, false);
_surfaceMenu->copyToScreen(_selectedMenu->xstart(), MENUBAR_Y_SIZE);
}
@@ -230,26 +230,26 @@ uint8 Menu::getIndexAt(uint16 x, uint16 y) {
return index;
}
-#define MENUBAR_SELECTED_COLOUR 0xf7
+#define MENUBAR_SELECTED_COLOR 0xf7
void Menu::toggleHighlight(MenuRecord *menuRec) {
- const byte colourList[4] = {4, 2, 0, 0xf7};
- const byte *colours = LureEngine::getReference().isEGA() ? &colourList[0] : &colourList[2];
+ const byte colorList[4] = {4, 2, 0, 0xf7};
+ const byte *colors = LureEngine::getReference().isEGA() ? &colorList[0] : &colorList[2];
byte *addr = _menu->data();
for (uint16 y=0; y<MENUBAR_Y_SIZE; ++y) {
for (uint16 x=menuRec->hsxstart(); x<=menuRec->hsxend(); ++x) {
- if (addr[x] == colours[0]) addr[x] = colours[1];
- else if (addr[x] == colours[1]) addr[x] = colours[0];
+ if (addr[x] == colors[0]) addr[x] = colors[1];
+ else if (addr[x] == colors[1]) addr[x] = colors[0];
}
addr += FULL_SCREEN_WIDTH;
}
}
void Menu::toggleHighlightItem(uint8 index) {
- const byte colourList[4] = {EGA_DIALOG_TEXT_COLOUR, EGA_DIALOG_WHITE_COLOUR,
- VGA_DIALOG_TEXT_COLOUR, VGA_DIALOG_WHITE_COLOUR};
- const byte *colours = LureEngine::getReference().isEGA() ? &colourList[0] : &colourList[2];
+ const byte colorList[4] = {EGA_DIALOG_TEXT_COLOR, EGA_DIALOG_WHITE_COLOR,
+ VGA_DIALOG_TEXT_COLOR, VGA_DIALOG_WHITE_COLOR};
+ const byte *colors = LureEngine::getReference().isEGA() ? &colorList[0] : &colorList[2];
byte *p = _surfaceMenu->data().data() + (Surface::textY() +
((index - 1) * FONT_HEIGHT)) * _surfaceMenu->width() + Surface::textX();
int numBytes =_surfaceMenu->width() - Surface::textX() * 2;
@@ -258,8 +258,8 @@ void Menu::toggleHighlightItem(uint8 index) {
byte *pTemp = p;
for (int x = 0; x < numBytes; ++x, ++pTemp) {
- if (*pTemp == colours[0]) *pTemp = colours[1];
- else if (*pTemp == colours[1]) *pTemp = colours[0];
+ if (*pTemp == colors[0]) *pTemp = colors[1];
+ else if (*pTemp == colors[1]) *pTemp = colors[0];
}
}
@@ -475,9 +475,9 @@ uint16 PopupMenu::Show(int numEntries, const char *actions[]) {
Screen &screen = Screen::getReference();
Common::Rect r;
bool isEGA = LureEngine::getReference().isEGA();
- byte bgColour = isEGA ? EGA_DIALOG_BG_COLOUR : 0;
- byte textColour = isEGA ? EGA_DIALOG_TEXT_COLOUR : VGA_DIALOG_TEXT_COLOUR;
- byte whiteColour = isEGA ? EGA_DIALOG_WHITE_COLOUR : VGA_DIALOG_WHITE_COLOUR;
+ byte bgColor = isEGA ? EGA_DIALOG_BG_COLOR : 0;
+ byte textColor = isEGA ? EGA_DIALOG_TEXT_COLOR : VGA_DIALOG_TEXT_COLOR;
+ byte whiteColor = isEGA ? EGA_DIALOG_WHITE_COLOR : VGA_DIALOG_WHITE_COLOR;
const uint16 yMiddle = FULL_SCREEN_HEIGHT / 2;
@@ -521,7 +521,7 @@ uint16 PopupMenu::Show(int numEntries, const char *actions[]) {
for (;;) {
if (refreshFlag) {
// Set up the contents of the menu
- s->fillRect(r, bgColour);
+ s->fillRect(r, bgColor);
for (int index = 0; index < numLines; ++index) {
#ifndef LURE_CLICKABLE_MENUS
@@ -533,9 +533,9 @@ uint16 PopupMenu::Show(int numEntries, const char *actions[]) {
s->writeString(Surface::textX(), Surface::textY() + index * FONT_HEIGHT,
actions[actionIndex], true,
#ifndef LURE_CLICKABLE_MENUS
- (index == (numLines / 2)) ? whiteColour : textColour,
+ (index == (numLines / 2)) ? whiteColor : textColor,
#else
- (index == selectedIndex) ? whiteColour : textColour,
+ (index == selectedIndex) ? whiteColor : textColor,
#endif
false);
}
diff --git a/engines/lure/palette.cpp b/engines/lure/palette.cpp
index d77f64f00a..b08ca64dfb 100644
--- a/engines/lure/palette.cpp
+++ b/engines/lure/palette.cpp
@@ -33,7 +33,7 @@ namespace Lure {
// Defaults the palette to a full 256 entry palette
Palette::Palette() {
- _numEntries = GAME_COLOURS;
+ _numEntries = GAME_COLORS;
_palette = Memory::allocate(_numEntries * 4);
_palette->empty();
}
@@ -91,7 +91,7 @@ Palette::Palette(uint16 resourceId, PaletteSource paletteSource) {
break;
case RGB64:
- if (((srcData->size() % 3) != 0) || ((srcData->size() / 3) > GAME_COLOURS))
+ if (((srcData->size() % 3) != 0) || ((srcData->size() / 3) > GAME_COLORS))
error("Specified resource %d is not a palette", resourceId);
_numEntries = srcData->size() / 3;
diff --git a/engines/lure/res.cpp b/engines/lure/res.cpp
index 90c2b67b85..01b0bd0d4a 100644
--- a/engines/lure/res.cpp
+++ b/engines/lure/res.cpp
@@ -432,7 +432,7 @@ byte *Resources::getCursor(uint8 cursorNum) {
}
}
- // Post-process the cells to adjust the colour
+ // Post-process the cells to adjust the color
for (int index = 0; index < CURSOR_SIZE; ++index) {
if (_cursor[index] == 3) _cursor[index] = 15;
}
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index f6a2092ddc..39beb2729e 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -406,7 +406,7 @@ HotspotData::HotspotData(HotspotResource *rec) {
walkY = READ_LE_UINT16(&rec->walkY);
talkX = rec->talkX;
talkY = rec->talkY;
- colourOffset = READ_LE_UINT16(&rec->colourOffset);
+ colorOffset = READ_LE_UINT16(&rec->colorOffset);
animRecordId = READ_LE_UINT16(&rec->animRecordId);
hotspotScriptOffset = READ_LE_UINT16(&rec->hotspotScriptOffset);
talkScriptOffset = READ_LE_UINT16(&rec->talkScriptOffset);
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index e4b8c02f6a..58ee3f4c02 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -27,9 +27,11 @@
#define LURE_RESSTRUCT_H
#include "lure/luredefs.h"
+#include "common/rect.h"
#include "common/list.h"
#include "common/file.h"
#include "common/ptr.h"
+#include "common/textconsole.h"
namespace Lure {
@@ -88,7 +90,7 @@ struct HotspotResource {
uint16 walkY;
int8 talkX;
int8 talkY;
- uint16 colourOffset;
+ uint16 colorOffset;
uint16 animRecordId;
uint16 hotspotScriptOffset;
uint16 talkScriptOffset;
@@ -538,7 +540,7 @@ public:
uint16 walkY;
int8 talkX;
int8 talkY;
- uint16 colourOffset;
+ uint16 colorOffset;
uint16 animRecordId;
uint16 hotspotScriptOffset;
uint16 talkScriptOffset;
diff --git a/engines/lure/room.cpp b/engines/lure/room.cpp
index 746d6ef094..4cefe1fabb 100644
--- a/engines/lure/room.cpp
+++ b/engines/lure/room.cpp
@@ -432,7 +432,7 @@ void Room::update() {
Surface &s = _screen.screen();
Resources &res = Resources::getReference();
HotspotList &hotspots = res.activeHotspots();
- byte white = LureEngine::getReference().isEGA() ? EGA_DIALOG_WHITE_COLOUR : VGA_DIALOG_WHITE_COLOUR;
+ byte white = LureEngine::getReference().isEGA() ? EGA_DIALOG_WHITE_COLOR : VGA_DIALOG_WHITE_COLOR;
HotspotList::iterator i;
// Copy the background to the temporary screen surface
@@ -564,9 +564,9 @@ void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) {
if (isEGA)
_screen.setPaletteEmpty();
else
- // Fade out all the colours except the high index 0FFh, which is used to show the
+ // Fade out all the colors except the high index 0FFh, which is used to show the
// disk cursor as a room changes
- _screen.paletteFadeOut(GAME_COLOURS - 1);
+ _screen.paletteFadeOut(GAME_COLORS - 1);
// Deallocate graphical layers from the room
for (int layerNum = 0; layerNum < _numLayers; ++layerNum) {
diff --git a/engines/lure/screen.cpp b/engines/lure/screen.cpp
index 282e382bba..e02f492ef2 100644
--- a/engines/lure/screen.cpp
+++ b/engines/lure/screen.cpp
@@ -30,6 +30,8 @@
#include "lure/decode.h"
#include "lure/events.h"
+#include "graphics/palette.h"
+
namespace Lure {
static Screen *int_disk = NULL;
@@ -44,7 +46,7 @@ Screen::Screen(OSystem &system): _system(system),
_palette(new Palette(GAME_PALETTE_RESOURCE_ID, RGB64)) {
int_disk = this;
_screen->empty();
- _system.getPaletteManager()->setPalette(_palette->data(), 0, GAME_COLOURS);
+ _system.getPaletteManager()->setPalette(_palette->data(), 0, GAME_COLORS);
}
Screen::~Screen() {
@@ -87,7 +89,7 @@ void Screen::setPaletteEmpty(int numEntries) {
void Screen::setPalette(Palette *p) {
_palette->copyFrom(p);
- setSystemPalette(_palette, 0, GAME_COLOURS);
+ setSystemPalette(_palette, 0, GAME_COLORS);
_system.updateScreen();
}
@@ -138,7 +140,7 @@ void Screen::paletteFadeIn(Palette *p) {
}
// paletteFadeOut
-// Fades the screen to black by gradually decreasing the palette colours
+// Fades the screen to black by gradually decreasing the palette colors
void Screen::paletteFadeOut(int numEntries) {
assert((uint32)numEntries <= _palette->palette()->size());
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 5f954eb337..da9e136ec3 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -97,8 +97,8 @@ SoundManager::~SoundManager() {
if (_driver) {
_driver->close();
delete _driver;
+ _driver = NULL;
}
- _driver = NULL;
g_system->deleteMutex(_soundMutex);
}
@@ -597,6 +597,7 @@ void SoundManager::doTimer() {
MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size) {
_driver = driver;
+ assert(_driver);
_channels = channels;
_soundNumber = soundNum;
_channelNumber = channelNum;
@@ -614,15 +615,11 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
else
setVolume(Sound.sfxVolume());
- _passThrough = false;
-
_parser = MidiParser::createParser_SMF();
_parser->setMidiDriver(this);
_parser->setTimerRate(_driver->getBaseTempo());
- this->open();
-
- _soundData = (uint8 *) soundData;
+ _soundData = (uint8 *)soundData;
_soundSize = size;
// Check whether the music data is compressed - if so, decompress it for the duration
@@ -654,7 +651,6 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
MidiMusic::~MidiMusic() {
_parser->unloadMusic();
delete _parser;
- this->close();
delete _decompressedSound;
}
@@ -686,23 +682,7 @@ void MidiMusic::playMusic() {
_isPlaying = true;
}
-int MidiMusic::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
-
- return 0;
-}
-
-void MidiMusic::close() {
-}
-
void MidiMusic::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
#ifdef SOUND_CROP_CHANNELS
if ((b & 0xF) >= _numChannels) return;
byte channel = _channelNumber + (byte)(b & 0x0F);
@@ -749,7 +729,6 @@ void MidiMusic::stopMusic() {
debugC(ERROR_DETAILED, kLureDebugSounds, "MidiMusic::stopMusic sound %d", _soundNumber);
_isPlaying = false;
_parser->unloadMusic();
- close();
}
} // End of namespace Lure
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index f50748ab0a..7a894d814d 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -30,6 +30,7 @@
#include "lure/disk.h"
#include "lure/memory.h"
+#include "common/mutex.h"
#include "common/singleton.h"
#include "common/ptr.h"
#include "audio/mididrv.h"
@@ -46,7 +47,7 @@ struct ChannelEntry {
uint8 volume;
};
-class MidiMusic: public MidiDriver {
+class MidiMusic: public MidiDriver_BASE {
private:
uint8 _soundNumber;
uint8 _channelNumber;
@@ -66,14 +67,12 @@ private:
uint32 songOffset(uint16 songNum) const;
uint32 songLength(uint16 songNum) const;
- bool _passThrough;
-
public:
MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size);
~MidiMusic();
void setVolume(int volume);
- int getVolume() { return _volume; }
+ int getVolume() const { return _volume; }
void playSong(uint16 songNum);
void stopSong() { stopMusic(); }
@@ -81,28 +80,18 @@ public:
void stopMusic();
void queueTuneList(int16 tuneList);
bool queueSong(uint16 songNum);
- void setPassThrough(bool b) { _passThrough = b; }
void toggleVChange();
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
- void onTimer();
-
- void metaEvent(byte type, byte *data, uint16 length);
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ void onTimer();
- uint8 channelNumber() { return _channelNumber; }
- uint8 soundNumber() { return _soundNumber; }
- bool isPlaying() { return _isPlaying; }
- bool isMusic() {return _isMusic; }
+ uint8 channelNumber() const { return _channelNumber; }
+ uint8 soundNumber() const { return _soundNumber; }
+ bool isPlaying() const { return _isPlaying; }
+ bool isMusic() const { return _isMusic; }
};
class SoundManager : public Common::Singleton<SoundManager> {
diff --git a/engines/lure/surface.cpp b/engines/lure/surface.cpp
index c4ee0f7dad..783401fde2 100644
--- a/engines/lure/surface.cpp
+++ b/engines/lure/surface.cpp
@@ -123,21 +123,21 @@ void Surface::getDialogBounds(Common::Point &size, int charWidth, int numLines,
// Forms a dialog encompassing the entire surface
void Surface::egaCreateDialog(bool blackFlag) {
- byte lineColours1[3] = {6, 0, 9};
- byte lineColours2[3] = {7, 0, 12};
+ byte lineColors1[3] = {6, 0, 9};
+ byte lineColors2[3] = {7, 0, 12};
// Surface contents
- data().setBytes(blackFlag ? 0 : EGA_DIALOG_BG_COLOUR, 0, data().size());
+ data().setBytes(blackFlag ? 0 : EGA_DIALOG_BG_COLOR, 0, data().size());
// Top/bottom lines
for (int y = 2; y >= 0; --y) {
- data().setBytes(lineColours1[y], y * width(), width());
- data().setBytes(lineColours2[y], (height() - y - 1) * width(), width());
+ data().setBytes(lineColors1[y], y * width(), width());
+ data().setBytes(lineColors2[y], (height() - y - 1) * width(), width());
for (int p = y + 1; p < height() - y; ++p) {
byte *line = data().data() + p * width();
- *(line + y) = lineColours2[y];
- *(line + width() - y - 1) = lineColours1[y];
+ *(line + y) = lineColors2[y];
+ *(line + width() - y - 1) = lineColors1[y];
}
}
}
@@ -220,10 +220,10 @@ void Surface::loadScreen(MemoryBlock *rawData) {
delete tmpScreen;
}
-int Surface::writeChar(uint16 x, uint16 y, uint8 ascii, bool transparent, int colour) {
+int Surface::writeChar(uint16 x, uint16 y, uint8 ascii, bool transparent, int color) {
byte *const addr = _data->data() + (y * _width) + x;
- if (colour == DEFAULT_TEXT_COLOUR)
- colour = LureEngine::getReference().isEGA() ? EGA_DIALOG_TEXT_COLOUR : VGA_DIALOG_TEXT_COLOUR;
+ if (color == DEFAULT_TEXT_COLOR)
+ color = LureEngine::getReference().isEGA() ? EGA_DIALOG_TEXT_COLOR : VGA_DIALOG_TEXT_COLOR;
if ((ascii < 32) || (ascii >= 32 + numFontChars))
error("Invalid ascii character passed for display '%d'", ascii);
@@ -239,7 +239,7 @@ int Surface::writeChar(uint16 x, uint16 y, uint8 ascii, bool transparent, int co
for (int x1 = 0; x1 < 8; ++x1, ++pDest) {
if (v & 0x80) {
- *pDest = colour;
+ *pDest = color;
if (x1+1 > charWidth) charWidth = x1 + 1;
}
else if (!transparent) *pDest = 0;
@@ -251,16 +251,16 @@ int Surface::writeChar(uint16 x, uint16 y, uint8 ascii, bool transparent, int co
}
void Surface::writeString(uint16 x, uint16 y, Common::String line, bool transparent,
- int colour, bool varLength) {
- writeSubstring(x, y, line, line.size(), transparent, colour, varLength);
+ int color, bool varLength) {
+ writeSubstring(x, y, line, line.size(), transparent, color, varLength);
}
void Surface::writeSubstring(uint16 x, uint16 y, Common::String line, int len,
- bool transparent, int colour, bool varLength) {
+ bool transparent, int color, bool varLength) {
const char *sPtr = line.c_str();
- if (colour == DEFAULT_TEXT_COLOUR)
- colour = LureEngine::getReference().isEGA() ? EGA_DIALOG_TEXT_COLOUR : VGA_DIALOG_TEXT_COLOUR;
+ if (color == DEFAULT_TEXT_COLOR)
+ color = LureEngine::getReference().isEGA() ? EGA_DIALOG_TEXT_COLOR : VGA_DIALOG_TEXT_COLOR;
for (int index = 0; (index < len) && (*sPtr != '\0'); ++index, ++sPtr) {
int charSize = varLength ? fontSize[(uint8)*sPtr - 32] + 2 : FONT_WIDTH;
@@ -269,7 +269,7 @@ void Surface::writeSubstring(uint16 x, uint16 y, Common::String line, int len,
break;
// Write next character
- writeChar(x, y, (uint8) *sPtr, transparent, colour);
+ writeChar(x, y, (uint8) *sPtr, transparent, color);
// Move to after the character in preparation for the next character
x += charSize;
@@ -312,7 +312,7 @@ void Surface::copyTo(Surface *dest, uint16 x, uint16 y) {
}
void Surface::copyTo(Surface *dest, const Common::Rect &srcBounds,
- uint16 destX, uint16 destY, int transparentColour) {
+ uint16 destX, uint16 destY, int transparentColor) {
int numBytes = srcBounds.right - srcBounds.left + 1;
if (destX + numBytes > dest->width())
numBytes = dest->width() - destX;
@@ -322,8 +322,8 @@ void Surface::copyTo(Surface *dest, const Common::Rect &srcBounds,
const uint32 srcPos = (srcBounds.top + y) * _width + srcBounds.left;
const uint32 destPos = (destY+y) * dest->width() + destX;
- if (transparentColour == -1) {
- // No trnnsparent colour, so copy all the bytes of the line
+ if (transparentColor == -1) {
+ // No trnnsparent color, so copy all the bytes of the line
dest->data().copyFrom(_data, srcPos, destPos, numBytes);
} else {
byte *pSrc = _data->data() + srcPos;
@@ -331,7 +331,7 @@ void Surface::copyTo(Surface *dest, const Common::Rect &srcBounds,
int bytesCtr = numBytes;
while (bytesCtr-- > 0) {
- if (*pSrc != (uint8) transparentColour)
+ if (*pSrc != (uint8) transparentColor)
*pDest = *pSrc;
++pSrc;
++pDest;
@@ -347,12 +347,12 @@ void Surface::copyFrom(MemoryBlock *src, uint32 destOffset) {
}
// fillRect
-// Fills a rectangular area with a colour
+// Fills a rectangular area with a color
-void Surface::fillRect(const Common::Rect &r, uint8 colour) {
+void Surface::fillRect(const Common::Rect &r, uint8 color) {
for (int yp = r.top; yp <= r.bottom; ++yp) {
byte *const addr = _data->data() + (yp * _width) + r.left;
- memset(addr, colour, r.width());
+ memset(addr, color, r.width());
}
}
@@ -464,7 +464,7 @@ void Surface::wordWrap(char *text, uint16 width, char **&lines, uint8 &numLines)
}
Surface *Surface::newDialog(uint16 width, uint8 numLines, const char **lines, bool varLength,
- int colour, bool squashedLines) {
+ int color, bool squashedLines) {
Common::Point size;
Surface::getDialogBounds(size, 0, numLines, squashedLines);
@@ -473,21 +473,21 @@ Surface *Surface::newDialog(uint16 width, uint8 numLines, const char **lines, bo
uint16 yP = Surface::textY();
for (uint8 ctr = 0; ctr < numLines; ++ctr) {
- s->writeString(Surface::textX(), yP, lines[ctr], true, colour, varLength);
+ s->writeString(Surface::textX(), yP, lines[ctr], true, color, varLength);
yP += squashedLines ? FONT_HEIGHT - 1 : FONT_HEIGHT;
}
return s;
}
-Surface *Surface::newDialog(uint16 width, const char *line, int colour) {
+Surface *Surface::newDialog(uint16 width, const char *line, int color) {
char **lines;
char *lineCopy = strdup(line);
uint8 numLines;
wordWrap(lineCopy, width - (Surface::textX() * 2), lines, numLines);
// Create the dialog
- Surface *result = newDialog(width, numLines, const_cast<const char **>(lines), true, colour);
+ Surface *result = newDialog(width, numLines, const_cast<const char **>(lines), true, color);
// Deallocate used resources
free(lines);
@@ -510,7 +510,7 @@ bool Surface::getString(Common::String &line, int maxSize, bool isNumeric, bool
Mouse &mouse = Mouse::getReference();
Events &events = Events::getReference();
Screen &screen = Screen::getReference();
- uint8 bgColour = *(screen.screen().data().data() + (y * FULL_SCREEN_WIDTH) + x);
+ uint8 bgColor = *(screen.screen().data().data() + (y * FULL_SCREEN_WIDTH) + x);
Common::String newLine(line);
bool abortFlag = false;
bool refreshFlag = false;
@@ -527,7 +527,7 @@ bool Surface::getString(Common::String &line, int maxSize, bool isNumeric, bool
while (!abortFlag) {
// Display the string
- screen.screen().writeString(x, y, newLine, true, DEFAULT_TEXT_COLOUR, varLength);
+ screen.screen().writeString(x, y, newLine, true, DEFAULT_TEXT_COLOR, varLength);
screen.update();
int stringSize = textWidth(newLine.c_str());
@@ -545,7 +545,7 @@ bool Surface::getString(Common::String &line, int maxSize, bool isNumeric, bool
if ((keycode == Common::KEYCODE_RETURN) || (keycode == Common::KEYCODE_KP_ENTER)) {
// Return character
screen.screen().fillRect(
- Common::Rect(x, y, x + maxSize - 1, y + FONT_HEIGHT), bgColour);
+ Common::Rect(x, y, x + maxSize - 1, y + FONT_HEIGHT), bgColor);
screen.update();
newLine.deleteLastChar();
line = newLine;
@@ -556,7 +556,7 @@ bool Surface::getString(Common::String &line, int maxSize, bool isNumeric, bool
else if (keycode == Common::KEYCODE_ESCAPE) {
// Escape character
screen.screen().fillRect(
- Common::Rect(x, y, x + maxSize - 1, y + FONT_HEIGHT), bgColour);
+ Common::Rect(x, y, x + maxSize - 1, y + FONT_HEIGHT), bgColor);
screen.update();
abortFlag = true;
} else if (keycode == Common::KEYCODE_BACKSPACE) {
@@ -564,14 +564,14 @@ bool Surface::getString(Common::String &line, int maxSize, bool isNumeric, bool
if (newLine.size() == 1) continue;
screen.screen().fillRect(
- Common::Rect(x, y, x + maxSize - 1, y + FONT_HEIGHT), bgColour);
+ Common::Rect(x, y, x + maxSize - 1, y + FONT_HEIGHT), bgColor);
newLine.deleteChar(newLine.size() - 2);
refreshFlag = true;
} else if ((ch >= ' ') && (stringSize + 8 < maxSize)) {
if (((ch >= '0') && (ch <= '9')) || !isNumeric) {
screen.screen().fillRect(
- Common::Rect(x, y, x + maxSize - 1, y + FONT_HEIGHT), bgColour);
+ Common::Rect(x, y, x + maxSize - 1, y + FONT_HEIGHT), bgColor);
newLine.insertChar(ch, newLine.size() - 1);
refreshFlag = true;
}
@@ -818,7 +818,7 @@ TalkDialog::TalkDialog(uint16 characterId, uint16 destCharacterId, uint16 active
// Write out the character name
uint16 charWidth = Surface::textWidth(srcCharName);
- byte white = LureEngine::getReference().isEGA() ? EGA_DIALOG_WHITE_COLOUR : VGA_DIALOG_WHITE_COLOUR;
+ byte white = LureEngine::getReference().isEGA() ? EGA_DIALOG_WHITE_COLOR : VGA_DIALOG_WHITE_COLOR;
_surface->writeString((TALK_DIALOG_WIDTH - charWidth) / 2, TALK_DIALOG_EDGE_SIZE + 2,
srcCharName, true, white);
debugC(ERROR_DETAILED, kLureDebugAnimations, "TalkDialog end");
@@ -903,14 +903,14 @@ TalkDialog *TalkDialog::loadFromStream(Common::ReadStream *stream) {
void SaveRestoreDialog::toggleHightlight(int xs, int xe, int ys, int ye) {
Screen &screen = Screen::getReference();
byte *addr = screen.screen().data().data() + FULL_SCREEN_WIDTH * ys + xs;
- const byte colourList[4] = {EGA_DIALOG_TEXT_COLOUR, EGA_DIALOG_WHITE_COLOUR,
- VGA_DIALOG_TEXT_COLOUR, VGA_DIALOG_WHITE_COLOUR};
- const byte *colours = LureEngine::getReference().isEGA() ? &colourList[0] : &colourList[2];
+ const byte colorList[4] = {EGA_DIALOG_TEXT_COLOR, EGA_DIALOG_WHITE_COLOR,
+ VGA_DIALOG_TEXT_COLOR, VGA_DIALOG_WHITE_COLOR};
+ const byte *colors = LureEngine::getReference().isEGA() ? &colorList[0] : &colorList[2];
for (int y = 0; y < ye - ys + 1; ++y, addr += FULL_SCREEN_WIDTH) {
for (int x = 0; x < xe - xs + 1; ++x) {
- if (addr[x] == colours[0]) addr[x] = colours[1];
- else if (addr[x] == colours[1]) addr[x] = colours[0];
+ if (addr[x] == colors[0]) addr[x] = colors[1];
+ else if (addr[x] == colors[1]) addr[x] = colors[0];
}
}
@@ -951,9 +951,9 @@ bool SaveRestoreDialog::show(bool saveDialog) {
// Create the outer dialog and dividing line
s->createDialog();
byte *pDest = s->data().data() + (s->width() * SR_SEPARATOR_Y) + SR_SEPARATOR_X;
- uint8 rowColours[5] = {*(pDest-2), *(pDest-1), *(pDest-1), *(pDest-2), *(pDest+1)};
+ uint8 rowColors[5] = {*(pDest-2), *(pDest-1), *(pDest-1), *(pDest-2), *(pDest+1)};
for (int y = 0; y < SR_SEPARATOR_HEIGHT; ++y, pDest += s->width())
- memset(pDest, rowColours[y], s->width() - 12);
+ memset(pDest, rowColors[y], s->width() - 12);
// Create title line
Common::String title(res.stringList().getString(
@@ -1248,7 +1248,7 @@ struct ItemDesc {
int16 x, y;
uint16 width, height;
uint16 animId;
- uint8 startColour;
+ uint8 startColor;
};
#define PROT_SPR_HEADER 0x1830
@@ -1286,7 +1286,7 @@ CopyProtectionDialog::CopyProtectionDialog() {
Hotspot *h = new Hotspot();
h->setPosition(ptr->x, ptr->y);
h->setSize(ptr->width, ptr->height);
- h->setColourOffset(ptr->startColour);
+ h->setColorOffset(ptr->startColor);
h->setAnimation(ptr->animId);
_hotspots.push_back(HotspotsList::value_type(h));
diff --git a/engines/lure/surface.h b/engines/lure/surface.h
index 8fd8ae49a6..9a677cf749 100644
--- a/engines/lure/surface.h
+++ b/engines/lure/surface.h
@@ -34,7 +34,7 @@
namespace Lure {
-#define DEFAULT_TEXT_COLOUR -1
+#define DEFAULT_TEXT_COLOR -1
class Surface {
private:
@@ -61,20 +61,20 @@ public:
void loadScreen(uint16 resourceId);
void loadScreen(MemoryBlock *data);
- int writeChar(uint16 x, uint16 y, uint8 ascii, bool transparent, int colour);
+ int writeChar(uint16 x, uint16 y, uint8 ascii, bool transparent, int color);
void writeString(uint16 x, uint16 y, Common::String line, bool transparent,
- int colour = DEFAULT_TEXT_COLOUR, bool varLength = true);
+ int color = DEFAULT_TEXT_COLOR, bool varLength = true);
void writeSubstring(uint16 x, uint16 y, Common::String line, int len,
- bool transparent, int colour = DEFAULT_TEXT_COLOUR, bool varLength = true);
+ bool transparent, int color = DEFAULT_TEXT_COLOR, bool varLength = true);
void transparentCopyTo(Surface *dest);
void copyTo(Surface *dest);
void copyTo(Surface *dest, uint16 x, uint16 y);
void copyTo(Surface *dest, const Common::Rect &srcBounds, uint16 destX, uint16 destY,
- int transparentColour = -1);
+ int transparentColor = -1);
void copyFrom(MemoryBlock *src) { _data->copyFrom(src); }
void copyFrom(MemoryBlock *src, uint32 destOffset);
void empty() { _data->empty(); }
- void fillRect(const Common::Rect &r, uint8 colour);
+ void fillRect(const Common::Rect &r, uint8 color);
void createDialog(bool blackFlag = false);
void copyToScreen(uint16 x, uint16 y);
void centerOnScreen();
@@ -82,8 +82,8 @@ public:
static uint16 textWidth(const char *s, int numChars = 0);
static void wordWrap(char *text, uint16 width, char **&lines, uint8 &numLines);
static Surface *newDialog(uint16 width, uint8 numLines, const char **lines, bool varLength = true,
- int colour = DEFAULT_TEXT_COLOUR, bool squashedLines = true);
- static Surface *newDialog(uint16 width, const char *lines, int colour = DEFAULT_TEXT_COLOUR);
+ int color = DEFAULT_TEXT_COLOR, bool squashedLines = true);
+ static Surface *newDialog(uint16 width, const char *lines, int color = DEFAULT_TEXT_COLOR);
static Surface *getScreen(uint16 resourceId);
bool getString(Common::String &line, int maxSize, bool isNumeric, bool varLength, int16 x, int16 y);
};
diff --git a/engines/m4/actor.cpp b/engines/m4/actor.cpp
index f342ca6b46..c61c6fe7d8 100644
--- a/engines/m4/actor.cpp
+++ b/engines/m4/actor.cpp
@@ -25,6 +25,7 @@
#include "common/system.h"
#include "common/array.h"
+#include "common/textconsole.h"
#include "m4/actor.h"
#include "m4/m4_views.h"
#include "m4/assets.h"
@@ -59,7 +60,7 @@ void Actor::placeWalkerSpriteAt(int spriteNum, int x, int y) {
info.height = info.sprite->height();
info.scaleX = info.scaleY = _scaling;
info.palette = _walkerSprites[_direction]->getPalette();
- info.inverseColourTable = _m4Vm->scene()->getInverseColourTable();
+ info.inverseColorTable = _m4Vm->scene()->getInverseColorTable();
_vm->_scene->drawSprite(x, y, info, Common::Rect(640, 400));
}
diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp
index 37314eff44..3fe050e604 100644
--- a/engines/m4/animation.cpp
+++ b/engines/m4/animation.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "m4/assets.h"
#include "m4/animation.h"
#include "m4/compression.h"
@@ -426,7 +428,7 @@ void MadsAnimation::update() {
// Start displaying the message
AnimMessage &me = _messages[idx];
- // The colour index to use is dependant on how many messages are currently on-screen
+ // The color index to use is dependant on how many messages are currently on-screen
uint8 colIndex;
switch (_messageCtr) {
case 1:
diff --git a/engines/m4/assets.h b/engines/m4/assets.h
index 3ae7fb2e22..940646b5f2 100644
--- a/engines/m4/assets.h
+++ b/engines/m4/assets.h
@@ -33,16 +33,16 @@
namespace M4 {
// Sequence chunks
-#define CHUNK_SCEN MKID_BE('SCEN')
-#define CHUNK_MACH MKID_BE('MACH')
-#define CHUNK_SEQU MKID_BE('SEQU')
-#define CHUNK_DATA MKID_BE('DATA')
-#define CHUNK_CELS MKID_BE('CELS')
+#define CHUNK_SCEN MKTAG('S','C','E','N')
+#define CHUNK_MACH MKTAG('M','A','C','H')
+#define CHUNK_SEQU MKTAG('S','E','Q','U')
+#define CHUNK_DATA MKTAG('D','A','T','A')
+#define CHUNK_CELS MKTAG('C','E','L','S')
// Sprite chunks
-#define HEAD_M4SS MKID_BE('M4SS') //'M4SS'
-#define CELS__PAL MKID_BE(' PAL') //' PAL'
-#define CELS___SS MKID_BE(' SS') //' SS'
+#define HEAD_M4SS MKTAG('M','4','S','S') //'M4SS'
+#define CELS__PAL MKTAG(' ','P','A','L') //' PAL'
+#define CELS___SS MKTAG(' ',' ','S','S') //' SS'
#define SPRITE_SET_CHAR_INFO 4
diff --git a/engines/m4/compression.cpp b/engines/m4/compression.cpp
index 9b1416945c..8fe4fbf1eb 100644
--- a/engines/m4/compression.cpp
+++ b/engines/m4/compression.cpp
@@ -27,6 +27,7 @@
#include "m4/m4.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
namespace M4 {
diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp
index 88b4240901..cbcaa04669 100644
--- a/engines/m4/console.cpp
+++ b/engines/m4/console.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "m4/m4.h"
#include "m4/console.h"
#include "m4/dialogs.h"
diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp
index 70c30d28f2..46c4b35b79 100644
--- a/engines/m4/converse.cpp
+++ b/engines/m4/converse.cpp
@@ -26,6 +26,7 @@
#include "common/array.h"
#include "common/hashmap.h"
#include "common/substream.h"
+#include "common/textconsole.h"
#include "m4/converse.h"
#include "m4/resource.h"
@@ -45,35 +46,35 @@ namespace M4 {
// Conversation chunks
// Header
-#define HEAD_CONV MKID_BE('CONV') // conversation
-#define CHUNK_DECL MKID_BE('DECL') // declaration
-#define CHUNK_NODE MKID_BE('NODE') // node
-#define CHUNK_LNOD MKID_BE('LNOD') // linear node
-#define CHUNK_ETRY MKID_BE('ETRY') // entry
-#define CHUNK_TEXT MKID_BE('TEXT') // text
-#define CHUNK_MESG MKID_BE('MESG') // message
+#define HEAD_CONV MKTAG('C','O','N','V') // conversation
+#define CHUNK_DECL MKTAG('D','E','C','L') // declaration
+#define CHUNK_NODE MKTAG('N','O','D','E') // node
+#define CHUNK_LNOD MKTAG('L','N','O','D') // linear node
+#define CHUNK_ETRY MKTAG('E','T','R','Y') // entry
+#define CHUNK_TEXT MKTAG('T','E','X','T') // text
+#define CHUNK_MESG MKTAG('M','E','S','G') // message
// Conversation chunks - entry related (unconditional)
-#define CHUNK_RPLY MKID_BE('RPLY') // reply
-#define CHUNK_HIDE MKID_BE('HIDE') // hide entry
-#define CHUNK_UHID MKID_BE('UHID') // unhide entry
-#define CHUNK_DSTR MKID_BE('DSTR') // destroy entry
+#define CHUNK_RPLY MKTAG('R','P','L','Y') // reply
+#define CHUNK_HIDE MKTAG('H','I','D','E') // hide entry
+#define CHUNK_UHID MKTAG('U','H','I','D') // unhide entry
+#define CHUNK_DSTR MKTAG('D','S','T','R') // destroy entry
// Conversation chunks - entry related (conditional)
-#define CHUNK_CRPL MKID_BE('CRPL') // reply
-#define CHUNK_CHDE MKID_BE('CHDE') // hide entry
-#define CHUNK_CUHD MKID_BE('CUHD') // unhide entry
-#define CHUNK_CDST MKID_BE('DDTS') // destroy entry
+#define CHUNK_CRPL MKTAG('C','R','P','L') // reply
+#define CHUNK_CHDE MKTAG('C','H','D','E') // hide entry
+#define CHUNK_CUHD MKTAG('C','U','H','D') // unhide entry
+#define CHUNK_CDST MKTAG('D','D','T','S') // destroy entry
// Conversation chunks - branching and logic (unconditional)
-#define CHUNK_ASGN MKID_BE('ASGN') // assign
-#define CHUNK_GOTO MKID_BE('GOTO') // goto chunk
-#define CHUNK_EXIT MKID_BE('EXIT') // exit/return from goto
+#define CHUNK_ASGN MKTAG('A','S','G','N') // assign
+#define CHUNK_GOTO MKTAG('G','O','T','O') // goto chunk
+#define CHUNK_EXIT MKTAG('E','X','I','T') // exit/return from goto
// Conversation chunks - branching and logic (conditional)
-#define CHUNK_CASN MKID_BE('CASN') // assign
-#define CHUNK_CCGO MKID_BE('CCGO') // goto chunk
-#define CHUNK_CEGO MKID_BE('CEGO') // exit/return from goto
+#define CHUNK_CASN MKTAG('C','A','S','N') // assign
+#define CHUNK_CCGO MKTAG('C','C','G','O') // goto chunk
+#define CHUNK_CEGO MKTAG('C','E','G','O') // exit/return from goto
// Others
-#define CHUNK_FALL MKID_BE('FALL') // fallthrough
-#define CHUNK_WRPL MKID_BE('WRPL') // weighted reply chunk
-#define CHUNK_WPRL MKID_BE('WPRL') // weighted preply chunk
+#define CHUNK_FALL MKTAG('F','A','L','L') // fallthrough
+#define CHUNK_WRPL MKTAG('W','R','P','L') // weighted reply chunk
+#define CHUNK_WPRL MKTAG('W','P','R','L') // weighted preply chunk
ConversationView::ConversationView(MadsM4Engine *vm): View(vm, Common::Rect(0,
@@ -97,7 +98,7 @@ void ConversationView::setNode(int32 nodeIndex) {
_vm->_font->setFont(FONT_CONVERSATION);
// TODO: Conversation styles and colors
- _vm->_font->current()->setColours(2, 1, 3);
+ _vm->_font->current()->setColors(2, 1, 3);
_currentNodeIndex = nodeIndex;
@@ -164,7 +165,7 @@ void ConversationView::onRefresh(RectList *rects, M4Surface *destSurface) {
if (i > CONV_MAX_SHOWN_ENTRIES - 1)
break;
- _vm->_font->current()->setColour((_highlightedIndex == i) ? CONVERSATION_ENTRY_HIGHLIGHTED :
+ _vm->_font->current()->setColor((_highlightedIndex == i) ? CONVERSATION_ENTRY_HIGHLIGHTED :
CONVERSATION_ENTRY_NORMAL);
_vm->_font->current()->writeString(this, _activeItems[i]->text, CONV_ENTRIES_X_OFFSET,
diff --git a/engines/m4/dialogs.cpp b/engines/m4/dialogs.cpp
index da828ccf5b..bc6228658d 100644
--- a/engines/m4/dialogs.cpp
+++ b/engines/m4/dialogs.cpp
@@ -25,6 +25,7 @@
#include "m4/dialogs.h"
#include "common/file.h"
+#include "common/textconsole.h"
namespace M4 {
@@ -444,7 +445,7 @@ void Dialog::draw() {
int dialogY = (_vm->_screen->height() - dlgHeight) / 2;
// Create the surface for the dialog
- create(dlgWidth, dlgHeight, 1);
+ create(dlgWidth, dlgHeight, Graphics::PixelFormat::createFormatCLUT8());
_coords.left = dialogX;
_coords.top = dialogY;
_coords.right = dialogX + dlgWidth + 1;
@@ -452,7 +453,7 @@ void Dialog::draw() {
// Set up the dialog
fillRect(Common::Rect(0, 0, width(), height()), 3);
- setColour(2);
+ setColor(2);
hLine(1, width() - 1, height() - 2); // Bottom edge
hLine(0, width(), height() - 1);
vLine(width() - 2, 2, height()); // Right edge
@@ -480,8 +481,8 @@ void Dialog::draw() {
}
// Handle drawing the text contents
- _vm->_font->current()->setColours(7, 7, 7);
- setColour(7);
+ _vm->_font->current()->setColors(7, 7, 7);
+ setColor(7);
for (uint lineCtr = 0, yp = 5; lineCtr < _lines.size(); ++lineCtr, yp += _vm->_font->current()->getHeight() + 1) {
diff --git a/engines/m4/events.cpp b/engines/m4/events.cpp
index 29b243aceb..a9641eb542 100644
--- a/engines/m4/events.cpp
+++ b/engines/m4/events.cpp
@@ -257,7 +257,7 @@ bool Mouse::setCursorNum(int cursorIndex) {
// Set the cursor to the sprite
CursorMan.replaceCursor((const byte *)_cursor->getBasePtr(), _cursor->width(), _cursor->height(),
- _cursor->xOffset, _cursor->yOffset, TRANSPARENT_COLOUR_INDEX);
+ _cursor->xOffset, _cursor->yOffset, TRANSPARENT_COLOR_INDEX);
return true;
}
diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp
index cba32c2225..582fbaebc7 100644
--- a/engines/m4/font.cpp
+++ b/engines/m4/font.cpp
@@ -81,7 +81,7 @@ Font::Font(MadsM4Engine *vm, const char *filename) : _vm(vm) {
void Font::setFontM4(const char *filename) {
Common::SeekableReadStream *fontFile = _vm->res()->openFile(filename);
- if (fontFile->readUint32LE() != MKID_BE('FONT')) {
+ if (fontFile->readUint32LE() != MKTAG('F','O','N','T')) {
debugCN(kDebugGraphics, "Font::Font: FONT tag expected\n");
return;
}
@@ -92,7 +92,7 @@ void Font::setFontM4(const char *filename) {
//debugCN(kDebugGraphics, "Font::Font: _maxWidth = %d, _maxHeight = %d, fontSize = %d\n", _maxWidth, _maxHeight, fontSize);
- if (fontFile->readUint32LE() != MKID_BE('WIDT')) {
+ if (fontFile->readUint32LE() != MKTAG('W','I','D','T')) {
debugCN(kDebugGraphics, "Font::Font: WIDT tag expected\n");
return;
}
@@ -100,7 +100,7 @@ void Font::setFontM4(const char *filename) {
_charWidths = new uint8[256];
fontFile->read(_charWidths, 256);
- if (fontFile->readUint32LE() != MKID_BE('OFFS')) {
+ if (fontFile->readUint32LE() != MKTAG('O','F','F','S')) {
debugCN(kDebugGraphics, "Font::Font: OFFS tag expected\n");
return;
}
@@ -110,7 +110,7 @@ void Font::setFontM4(const char *filename) {
for (int i = 0; i < 256; i++)
_charOffs[i] = fontFile->readUint16LE();
- if (fontFile->readUint32LE() != MKID_BE('PIXS')) {
+ if (fontFile->readUint32LE() != MKTAG('P','I','X','S')) {
debugCN(kDebugGraphics, "Font::Font: PIXS tag expected\n");
return;
}
@@ -159,14 +159,14 @@ Font::~Font() {
}
}
-void Font::setColour(uint8 colour) {
+void Font::setColor(uint8 color) {
if (_sysFont)
- _fontColors[1] = colour;
+ _fontColors[1] = color;
else
- _fontColors[3] = colour;
+ _fontColors[3] = color;
}
-void Font::setColours(uint8 col1, uint8 col2, uint8 col3) {
+void Font::setColors(uint8 col1, uint8 col2, uint8 col3) {
if (_sysFont)
_fontColors[1] = col3;
else {
diff --git a/engines/m4/font.h b/engines/m4/font.h
index 19d15faa1e..64e54f35b5 100644
--- a/engines/m4/font.h
+++ b/engines/m4/font.h
@@ -62,8 +62,8 @@ public:
Font(MadsM4Engine *vm, const char *filename);
~Font();
- void setColour(uint8 colour);
- void setColours(uint8 col1, uint8 col2, uint8 col3);
+ void setColor(uint8 color);
+ void setColors(uint8 col1, uint8 col2, uint8 col3);
int32 getWidth(const char *text, int spaceWidth = -1);
int32 getHeight() const { return _maxHeight; }
diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp
index d982ecad0e..3db9934cec 100644
--- a/engines/m4/globals.cpp
+++ b/engines/m4/globals.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "m4/m4.h"
#include "m4/globals.h"
#include "m4/graphics.h"
diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp
index 5fc46d3881..689a6ab8b4 100644
--- a/engines/m4/graphics.cpp
+++ b/engines/m4/graphics.cpp
@@ -23,11 +23,12 @@
*
*/
-#include "common/file.h"
-#include "common/endian.h"
#include "common/system.h"
#include "common/util.h"
#include "common/ptr.h"
+#include "common/textconsole.h"
+
+#include "graphics/palette.h"
#include "m4/globals.h"
#include "m4/graphics.h"
@@ -96,7 +97,7 @@ void M4Surface::loadCodesM4(Common::SeekableReadStream *source) {
uint16 widthVal = source->readUint16LE();
uint16 heightVal = source->readUint16LE();
- create(widthVal, heightVal, 1);
+ create(widthVal, heightVal, Graphics::PixelFormat::createFormatCLUT8());
source->read(pixels, widthVal * heightVal);
}
@@ -110,7 +111,7 @@ void M4Surface::loadCodesMads(Common::SeekableReadStream *source) {
uint16 heightVal = 156;
byte *walkMap = new byte[source->size()];
- create(widthVal, heightVal, 1);
+ create(widthVal, heightVal, Graphics::PixelFormat::createFormatCLUT8());
source->read(walkMap, source->size());
byte *ptr = (byte *)getBasePtr(0, 0);
@@ -300,7 +301,7 @@ void M4Surface::drawSprite(int x, int y, SpriteInfo &info, const Common::Rect &c
r = CLIP((info.palette[destPixel].r * pixel) >> 10, 0, 31);
g = CLIP((info.palette[destPixel].g * pixel) >> 10, 0, 31);
b = CLIP((info.palette[destPixel].b * pixel) >> 10, 0, 31);
- pixel = info.inverseColourTable[(b << 10) | (g << 5) | r];
+ pixel = info.inverseColorTable[(b << 10) | (g << 5) | r];
}
}
@@ -361,7 +362,7 @@ void M4Surface::fillRect(const Common::Rect &r, uint8 color) {
}
void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY,
- int transparentColour) {
+ int transparentColor) {
// Validation of the rectangle and position
if ((destX >= w) || (destY >= h))
return;
@@ -390,13 +391,13 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest
byte *destPtr = (byte *)pixels + (destY * width()) + destX;
for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
- if (transparentColour == -1)
+ 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] != transparentColour) destPtr[xCtr] = srcPtr[xCtr];
+ if (srcPtr[xCtr] != transparentColor) destPtr[xCtr] = srcPtr[xCtr];
}
srcPtr += src->width();
@@ -411,7 +412,7 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest
* the specified depth requirement on a secondary surface contain depth information
*/
void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth,
- M4Surface *depthsSurface, int scale, int transparentColour) {
+ M4Surface *depthsSurface, int scale, int transparentColor) {
if (scale == 100) {
// Copy the specified area
@@ -443,7 +444,7 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth,
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) {
- if ((depth <= (depthsPtr[xCtr] & 0x7f)) && (srcPtr[xCtr] != transparentColour))
+ if ((depth <= (depthsPtr[xCtr] & 0x7f)) && (srcPtr[xCtr] != transparentColor))
destPtr[xCtr] = srcPtr[xCtr];
}
@@ -557,7 +558,7 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth,
// Not a display pixel
continue;
- if ((*srcP != transparentColour) && (depth <= (*depthP & 0x7f)))
+ if ((*srcP != transparentColor) && (depth <= (*depthP & 0x7f)))
*destP = *srcP;
++destP;
@@ -760,7 +761,7 @@ void M4Surface::rexLoadBackground(Common::SeekableReadStream *source, RGBList **
sourceUnc = packData.getItemStream(1);
assert((int)sourceUnc->size() >= sceneSize);
- create(sceneWidth, sceneHeight, 1);
+ create(sceneWidth, sceneHeight, Graphics::PixelFormat::createFormatCLUT8());
byte *pData = (byte *)pixels;
sourceUnc->read(pData, sceneSize);
@@ -813,7 +814,7 @@ void M4Surface::m4LoadBackground(Common::SeekableReadStream *source) {
assert(width() == (int)widthVal);
//debugCN(kDebugGraphics, "width(): %d, widthVal: %d, height(): %d, heightVal: %d\n", width(), widthVal, height(), heightVal);
- tileBuffer->create(tileWidth, tileHeight, 1);
+ tileBuffer->create(tileWidth, tileHeight, Graphics::PixelFormat::createFormatCLUT8());
for (curTileY = 0; curTileY < tilesY; curTileY++) {
clipY = MIN(heightVal, (1 + curTileY) * tileHeight) - (curTileY * tileHeight);
@@ -854,7 +855,7 @@ void M4Surface::madsLoadInterface(const Common::String &filename) {
// Chunk 1, data
intStream = intFile.getItemStream(1);
- create(320, 44, 1);
+ create(320, 44, Graphics::PixelFormat::createFormatCLUT8());
intStream->read(pixels, 320 * 44);
delete intStream;
@@ -933,7 +934,7 @@ void M4Surface::translate(RGBList *list, bool isTransparent) {
byte *palIndexes = list->palIndexes();
for (int i = 0; i < width() * height(); ++i, ++p) {
- if (!isTransparent || (*p != TRANSPARENT_COLOUR_INDEX)) {
+ if (!isTransparent || (*p != TRANSPARENT_COLOR_INDEX)) {
if (*p < list->size())
*p = palIndexes[*p];
else
diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h
index d58ed69403..96e81f746e 100644
--- a/engines/m4/graphics.h
+++ b/engines/m4/graphics.h
@@ -40,7 +40,7 @@ namespace M4 {
#define MADS_SCREEN_HEIGHT 200
#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2)
-#define TRANSPARENT_COLOUR_INDEX 0xFF
+#define TRANSPARENT_COLOR_INDEX 0xFF
struct BGR8 {
uint8 b, g, r;
@@ -89,7 +89,7 @@ struct SpriteInfo {
int width, height;
int scaleX, scaleY;
uint8 encoding;
- byte *inverseColourTable;
+ byte *inverseColorTable;
RGB8 *palette;
};
@@ -105,19 +105,19 @@ private:
void m4LoadBackground(Common::SeekableReadStream *source);
public:
M4Surface(bool isScreen = false) {
- create(g_system->getWidth(), isScreen ? g_system->getHeight() : MADS_SURFACE_HEIGHT, 1);
+ create(g_system->getWidth(), isScreen ? g_system->getHeight() : MADS_SURFACE_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
_isScreen = isScreen;
_rgbList = NULL;
_ownsData = true;
}
M4Surface(int width_, int height_) {
- create(width_, height_, 1);
+ create(width_, height_, Graphics::PixelFormat::createFormatCLUT8());
_isScreen = false;
_rgbList = NULL;
_ownsData = true;
}
M4Surface(int width_, int height_, byte *srcPixels, int pitch_) {
- bytesPerPixel = 1;
+ format = Graphics::PixelFormat::createFormatCLUT8();
w = width_;
h = height_;
pitch = pitch_;
@@ -141,7 +141,6 @@ public:
void madsLoadInterface(const Common::String &filename);
void setColor(byte value) { _color = value; }
- void setColour(byte value) { _color = value; }
inline byte getColor() const { return _color; }
void vLine(int x, int y1, int y2);
void hLine(int x1, int x2, int y);
@@ -158,7 +157,7 @@ public:
inline int width() const { return w; }
inline int height() const { return h; }
inline int getPitch() const { return pitch; }
- void setSize(int sizeX, int sizeY) { create(sizeX, sizeY, 1); }
+ void setSize(int sizeX, int sizeY) { create(sizeX, sizeY, Graphics::PixelFormat::createFormatCLUT8()); }
inline byte *getBasePtr() {
return (byte *)pixels;
}
@@ -173,9 +172,9 @@ public:
void reset();
void frameRect(const Common::Rect &r, uint8 color);
void fillRect(const Common::Rect &r, uint8 color);
- void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, int transparentColour = -1);
+ void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, int transparentColor = -1);
void copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthSurface,
- int scale, int transparentColour = -1);
+ int scale, int transparentColor = -1);
void update() {
if (_isScreen) {
@@ -185,19 +184,19 @@ public:
}
// copyTo methods
- inline void copyTo(M4Surface *dest, int transparentColour = -1) {
- dest->copyFrom(this, Common::Rect(width(), height()), 0, 0, transparentColour);
+ inline void copyTo(M4Surface *dest, int transparentColor = -1) {
+ dest->copyFrom(this, Common::Rect(width(), height()), 0, 0, transparentColor);
}
- inline void copyTo(M4Surface *dest, int x, int y, int transparentColour = -1) {
- dest->copyFrom(this, Common::Rect(width(), height()), x, y, transparentColour);
+ inline void copyTo(M4Surface *dest, int x, int y, int transparentColor = -1) {
+ dest->copyFrom(this, Common::Rect(width(), height()), x, y, transparentColor);
}
inline void copyTo(M4Surface *dest, const Common::Rect &srcBounds, int destX, int destY,
- int transparentColour = -1) {
- dest->copyFrom(this, srcBounds, destX, destY, transparentColour);
+ int transparentColor = -1) {
+ dest->copyFrom(this, srcBounds, destX, destY, transparentColor);
}
inline void copyTo(M4Surface *dest, int destX, int destY, int depth, M4Surface *depthsSurface, int scale,
- int transparentColour = -1) {
- dest->copyFrom(this, destX, destY, depth, depthsSurface, scale, transparentColour);
+ int transparentColor = -1) {
+ dest->copyFrom(this, destX, destY, depth, depthsSurface, scale, transparentColor);
}
void scrollX(int xAmount);
diff --git a/engines/m4/gui.cpp b/engines/m4/gui.cpp
index 8665b4e767..56cf96b589 100644
--- a/engines/m4/gui.cpp
+++ b/engines/m4/gui.cpp
@@ -25,6 +25,7 @@
#include "common/events.h"
#include "common/keyboard.h"
+#include "common/textconsole.h"
#include "m4/globals.h"
#include "m4/events.h"
@@ -290,26 +291,26 @@ void MenuButton::onRefresh() {
case OBJTYPE_SL_TEXT:
switch (_objectState) {
case OS_MOUSEOVER:
- _vm->_font->current()->setColours(TEXT_COLOR_MOUSEOVER_SHADOW, TEXT_COLOR_MOUSEOVER_FOREGROUND,
+ _vm->_font->current()->setColors(TEXT_COLOR_MOUSEOVER_SHADOW, TEXT_COLOR_MOUSEOVER_FOREGROUND,
TEXT_COLOR_MOUSEOVER_HILIGHT);
sprite = sprites[SL_LINE_MOUSEOVER];
break;
case OS_PRESSED:
- _vm->_font->current()->setColours(TEXT_COLOR_PRESSED_SHADOW, TEXT_COLOR_PRESSED_FOREGROUND,
+ _vm->_font->current()->setColors(TEXT_COLOR_PRESSED_SHADOW, TEXT_COLOR_PRESSED_FOREGROUND,
TEXT_COLOR_PRESSED_HILIGHT);
sprite = sprites[SL_LINE_PRESSED];
break;
case OS_GREYED:
- _vm->_font->current()->setColours(TEXT_COLOR_GREYED_SHADOW, TEXT_COLOR_GREYED_FOREGROUND,
+ _vm->_font->current()->setColors(TEXT_COLOR_GREYED_SHADOW, TEXT_COLOR_GREYED_FOREGROUND,
TEXT_COLOR_GREYED_HILIGHT);
sprite = sprites[SL_LINE_NORMAL];
break;
default:
case OS_NORMAL:
- _vm->_font->current()->setColours(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
+ _vm->_font->current()->setColors(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
TEXT_COLOR_NORMAL_HILIGHT);
sprite = sprites[SL_LINE_NORMAL];
break;
@@ -955,7 +956,7 @@ void MenuTextField::onRefresh() {
// Draw the text
_vm->_font->setFont(FONT_MENU);
- _vm->_font->current()->setColours(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
+ _vm->_font->current()->setColors(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
TEXT_COLOR_NORMAL_HILIGHT);
int xp = _bounds.left + 4;
@@ -1140,7 +1141,7 @@ GUITextField::GUITextField(View *owner, const Common::Rect &bounds): GUIRect(own
void GUITextField::onRefresh() {
_parent->fillRect(_bounds, _vm->_palette->BLACK);
- _vm->_font->current()->setColours(3, 3, 3);
+ _vm->_font->current()->setColors(3, 3, 3);
_vm->_font->setFont(FONT_INTERFACE);
_vm->_font->current()->writeString(_parent, _text.c_str(), _bounds.left, _bounds.top, 0, 1);
}
diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp
index 2bdd53040a..1a484322fd 100644
--- a/engines/m4/m4.cpp
+++ b/engines/m4/m4.cpp
@@ -30,7 +30,6 @@
#include "m4/burger_data.h"
#include "m4/m4.h"
#include "m4/resource.h"
-#include "m4/sprite.h"
#include "m4/hotspot.h"
#include "m4/font.h"
#include "m4/rails.h"
@@ -50,17 +49,15 @@
#include "m4/mads_anim.h"
#include "m4/mads_menus.h"
+#include "common/error.h"
#include "common/file.h"
#include "common/fs.h"
-#include "common/events.h"
#include "common/EventRecorder.h"
-#include "common/endian.h"
#include "common/system.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
+#include "common/textconsole.h"
#include "engines/util.h"
-#include "graphics/surface.h"
-#include "audio/mididrv.h"
namespace M4 {
@@ -107,6 +104,8 @@ void gameMenuHotkeyHandler(MadsM4Engine *vm, View *view, uint32 key) {
MadsM4Engine::MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc) {
+ // Setup mixer
+ syncSoundSettings();
// FIXME
_vm = this;
@@ -149,7 +148,6 @@ MadsM4Engine::~MadsM4Engine() {
delete _palette;
delete _globals;
delete _sound;
- delete _driver;
delete _resourceManager;
}
@@ -157,16 +155,8 @@ Common::Error MadsM4Engine::run() {
// Initialize backend
_screen = new M4Surface(true); // Special form for creating screen reference
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
-
- _driver = MidiDriver::createMidi(dev);
- if (native_mt32)
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _midi = new MidiPlayer(this, _driver);
- _midi->setGM(true);
- _midi->setNativeMT32(native_mt32);
+ _midi = new MidiPlayer(this);
+ _midi->setGM(true); // FIXME: Really? Always?
_saveLoad = new SaveLoad(this);
_palette = new Palette(this);
@@ -423,7 +413,7 @@ Common::Error M4Engine::run() {
_scene->loadScene(_kernel->currentRoom);
_ws->setBackgroundSurface(_scene->getBackgroundSurface());
- _ws->setInverseColourTable(scene()->getInverseColourTable());
+ _ws->setInverseColorTable(scene()->getInverseColorTable());
_kernel->loadSectionScriptFunctions();
_kernel->loadRoomScriptFunctions();
@@ -561,7 +551,7 @@ Common::Error MadsEngine::run() {
_scene->show();
_font->setFont(FONT_MAIN_MADS);
- _font->current()->setColours(2, 1, 3);
+ _font->current()->setColors(2, 1, 3);
_font->current()->writeString(_scene->getBackgroundSurface(), "Testing the M4/MADS ScummVM engine", 5, 160, 310, 2);
_font->current()->writeString(_scene->getBackgroundSurface(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 5, 180, 310, 2);
diff --git a/engines/m4/m4.h b/engines/m4/m4.h
index f665df262b..a43f3e1387 100644
--- a/engines/m4/m4.h
+++ b/engines/m4/m4.h
@@ -148,7 +148,6 @@ protected:
void shutdown();
- MidiDriver *_driver;
MidiPlayer *_midi;
public:
diff --git a/engines/m4/m4_menus.cpp b/engines/m4/m4_menus.cpp
index 118b09f50b..a20bb2660b 100644
--- a/engines/m4/m4_menus.cpp
+++ b/engines/m4/m4_menus.cpp
@@ -24,6 +24,7 @@
*/
#include "common/algorithm.h" // for find()
+#include "common/textconsole.h"
#include "gui/dialog.h"
#include "gui/message.h"
diff --git a/engines/m4/m4_scene.cpp b/engines/m4/m4_scene.cpp
index 738f414add..a0d8a503ab 100644
--- a/engines/m4/m4_scene.cpp
+++ b/engines/m4/m4_scene.cpp
@@ -24,6 +24,7 @@
*/
#include "common/system.h"
+#include "common/textconsole.h"
#include "m4/m4_scene.h"
#include "m4/dialogs.h"
@@ -41,7 +42,7 @@ namespace M4 {
M4Scene::M4Scene(M4Engine *vm): _sceneResources(), Scene(vm, &_sceneResources) {
_vm = vm;
_sceneSprites = NULL;
- _inverseColourTable = NULL;
+ _inverseColorTable = NULL;
_sceneResources.hotspots = new HotSpotList();
_sceneResources.parallax = new HotSpotList();
@@ -110,15 +111,15 @@ void M4Scene::loadSceneResources(int sceneNumber) {
}
}
-void M4Scene::loadSceneInverseColourTable(int sceneNumber) {
+void M4Scene::loadSceneInverseColorTable(int sceneNumber) {
char filename[kM4MaxFilenameSize];
Common::SeekableReadStream *iplS;
sprintf(filename, "%i.ipl", sceneNumber);
iplS = _vm->res()->openFile(filename);
- delete[] _inverseColourTable;
- _inverseColourTable = new byte[iplS->size()];
- iplS->read(_inverseColourTable, iplS->size());
+ delete[] _inverseColorTable;
+ _inverseColorTable = new byte[iplS->size()];
+ iplS->read(_inverseColorTable, iplS->size());
_vm->res()->toss(filename);
}
@@ -163,7 +164,7 @@ void M4Scene::loadScene(int sceneNumber) {
loadSceneCodes(sceneNumber);
// Load inverse color table file (*.IPL)
- loadSceneInverseColourTable(sceneNumber);
+ loadSceneInverseColorTable(sceneNumber);
if (_vm->getGameType() != GType_Burger) {
// Load scene sprites file (*.SSB)
@@ -202,7 +203,7 @@ void M4Scene::leaveScene() {
_sceneResources.parallax->clear();
delete _sceneResources.parallax;
- delete[] _inverseColourTable;
+ delete[] _inverseColorTable;
Scene::leaveScene();
}
diff --git a/engines/m4/m4_scene.h b/engines/m4/m4_scene.h
index 2216779a3e..9c2edbc06c 100644
--- a/engines/m4/m4_scene.h
+++ b/engines/m4/m4_scene.h
@@ -53,11 +53,11 @@ private:
M4SceneResources _sceneResources;
SpriteAsset *_sceneSprites;
SpriteAsset *_walkerSprite;
- byte *_inverseColourTable;
+ byte *_inverseColorTable;
void loadSceneSprites(int sceneNumber);
void loadSceneResources(int sceneNumber);
- void loadSceneInverseColourTable(int sceneNumber);
+ void loadSceneInverseColorTable(int sceneNumber);
void loadSceneSpriteCodes(int sceneNumber);
void nextCommonCursor();
public:
@@ -75,7 +75,7 @@ public:
virtual void update();
virtual void showHotSpots();
- byte *getInverseColourTable() const { return _inverseColourTable; }
+ byte *getInverseColorTable() const { return _inverseColorTable; }
M4InterfaceView *getInterface() { return (M4InterfaceView *)_interfaceSurface; }
M4SceneResources &getSceneResources() { return _sceneResources; }
void setStatusText(const char *text);
diff --git a/engines/m4/m4_views.cpp b/engines/m4/m4_views.cpp
index f4345787df..83f23edd3d 100644
--- a/engines/m4/m4_views.cpp
+++ b/engines/m4/m4_views.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "m4/m4_views.h"
#include "m4/events.h"
#include "m4/font.h"
diff --git a/engines/m4/m4_views.h b/engines/m4/m4_views.h
index 9a0651a2c5..e390904aae 100644
--- a/engines/m4/m4_views.h
+++ b/engines/m4/m4_views.h
@@ -42,7 +42,7 @@ public:
int iconIndex;
GUIInventoryItem(const char *_name, const char *_verb, M4Surface *_icon, int _iconIndex) {
- name = _name; _verb = verb; icon = _icon; iconIndex = _iconIndex;
+ name = _name; verb = _verb; icon = _icon; iconIndex = _iconIndex;
}
};
diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp
index 1d15cbbaf7..e7ca9cb14d 100644
--- a/engines/m4/mads_anim.cpp
+++ b/engines/m4/mads_anim.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "m4/mads_anim.h"
#include "m4/m4.h"
#include "m4/compression.h"
@@ -60,7 +62,7 @@ TextviewView::TextviewView(MadsM4Engine *vm):
_vm->_palette->setPalette(&palData[0], 4, 3);
_vm->_palette->blockRange(4, 3);
- _vm->_font->current()->setColours(5, 6, 4);
+ _vm->_font->current()->setColors(5, 6, 4);
clear();
_bgSurface.clear();
diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp
index 878e86c573..98a0d06412 100644
--- a/engines/m4/mads_logic.cpp
+++ b/engines/m4/mads_logic.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "m4/m4.h"
#include "m4/dialogs.h"
#include "m4/mads_logic.h"
diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp
index 91db7d343a..437e9d2a6b 100644
--- a/engines/m4/mads_menus.cpp
+++ b/engines/m4/mads_menus.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "m4/mads_menus.h"
#include "m4/m4.h"
@@ -695,11 +697,11 @@ void RexDialogView::updateState() {
void RexDialogView::onRefresh(RectList *rects, M4Surface *destSurface) {
// Draw the framed base area
fillRect(this->bounds(), _madsVm->_palette->BLACK);
- setColour(2);
+ setColor(2);
hLine(0, width(), MADS_Y_OFFSET - 2);
hLine(0, width(), MADS_Y_OFFSET + MADS_SURFACE_HEIGHT + 2);
- // Add in the loaded background vertically centred
+ // Add in the loaded background vertically centered
_backgroundSurface->copyTo(this, 0, (height() - MADS_SURFACE_HEIGHT) / 2);
// Check whether any of the dialog text entries need to be refreshed
@@ -943,20 +945,20 @@ void RexDialogView::refreshText() {
if (!_dialogText[i].in_use)
continue;
- // Get the item's colours
- uint colour;
+ // Get the item's colors
+ uint color;
if (_dialogText[i].state == STATE_DESELECTED)
- colour = 0xB0A;
+ color = 0xB0A;
else if (_dialogText[i].state == STATE_SELECTED)
- colour = 0xD0C;
+ color = 0xD0C;
else
- colour = 0xF0E;
+ color = 0xF0E;
- // If there's an associated text display entry, check to see if it's colour needs to change
+ // If there's an associated text display entry, check to see if it's color needs to change
if (_dialogText[i].textDisplay_index >= 0) {
MadsTextDisplayEntry &tdEntry = _textDisplay[_dialogText[i].textDisplay_index];
- if ((tdEntry.colour1 == (colour & 0xff)) && (tdEntry.colour2 == (colour >> 8)))
+ if ((tdEntry.color1 == (color & 0xff)) && (tdEntry.color2 == (color >> 8)))
// It's still the same, so no further action needed
continue;
@@ -967,7 +969,7 @@ void RexDialogView::refreshText() {
// Create a new text display entry for the dialog text line
_dialogText[i].textDisplay_index = _textDisplay.add(_dialogText[i].pos.x, _dialogText[i].pos.y,
- colour, _dialogText[i].widthAdjust, _dialogText[i].text, _dialogText[i].font);
+ color, _dialogText[i].widthAdjust, _dialogText[i].text, _dialogText[i].font);
}
}
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index 4d9dcc5219..7b82480ee2 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -24,6 +24,7 @@
*/
#include "common/system.h"
+#include "common/textconsole.h"
#include "m4/mads_scene.h"
#include "m4/dialogs.h"
@@ -855,13 +856,13 @@ MadsInterfaceView::~MadsInterfaceView() {
void MadsInterfaceView::setFontMode(InterfaceFontMode newMode) {
switch (newMode) {
case ITEM_NORMAL:
- _vm->_font->current()->setColours(4, 4, 0xff);
+ _vm->_font->current()->setColors(4, 4, 0xff);
break;
case ITEM_HIGHLIGHTED:
- _vm->_font->current()->setColours(5, 5, 0xff);
+ _vm->_font->current()->setColors(5, 5, 0xff);
break;
case ITEM_SELECTED:
- _vm->_font->current()->setColours(6, 6, 0xff);
+ _vm->_font->current()->setColors(6, 6, 0xff);
break;
}
}
@@ -939,7 +940,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
int actionIndex = 0;
for (int x = 0; x < 2; ++x) {
for (int y = 0; y < 5; ++y, ++actionIndex) {
- // Determine the font colour depending on whether an item is selected. Note that the first action,
+ // Determine the font color depending on whether an item is selected. Note that the first action,
// 'Look', is always 'selected', even when another action is clicked on
setFontMode((_highlightedElement == actionIndex) ? ITEM_HIGHLIGHTED :
((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL));
@@ -994,7 +995,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
// Display object sprite. Note that the frame number isn't used directly, because it would result
// in too fast an animation
M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED);
- spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, TRANSPARENT_COLOUR_INDEX);
+ spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, TRANSPARENT_COLOR_INDEX);
if (!_madsVm->globals()->_config.invObjectsStill && !dialogVisible) {
// If objects need to be animated, move to the next frame
@@ -1127,12 +1128,10 @@ bool MadsInterfaceView::handleCheatKey(int32 keycode) {
_madsVm->scene()->_showMousePos = !_madsVm->scene()->_showMousePos;
break;
- case Common::KEYCODE_t | (Common::KEYCODE_LALT << 24):
- case Common::KEYCODE_t | (Common::KEYCODE_RALT << 24):
- {
+ case Common::KEYCODE_t | (Common::KBD_ALT << 24): {
// Teleport to room
//Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE);
-
+ // TODO: Implement teleport code
return true;
}
diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp
index cc127032eb..33c679c9bd 100644
--- a/engines/m4/mads_views.cpp
+++ b/engines/m4/mads_views.cpp
@@ -34,6 +34,7 @@
#include "m4/staticres.h"
#include "common/algorithm.h"
+#include "common/textconsole.h"
namespace M4 {
@@ -244,10 +245,10 @@ void MadsAction::refresh() {
}
// Add a new text display entry to display the status text at the bottom of the screen area
- uint colours = (_vm->getGameType() == GType_DragonSphere) ? 0x0300 : 0x0003;
+ uint colors = (_vm->getGameType() == GType_DragonSphere) ? 0x0300 : 0x0003;
_statusTextIndex = _owner._textDisplay.add(160 - (strWidth / 2),
- MADS_SURFACE_HEIGHT + _owner._posAdjust.y - 13, colours, textSpacing, _statusText, font);
+ MADS_SURFACE_HEIGHT + _owner._posAdjust.y - 13, colors, textSpacing, _statusText, font);
}
}
@@ -616,7 +617,7 @@ void MadsTextDisplay::clear() {
_entries[i].active = false;
}
-int MadsTextDisplay::add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font) {
+int MadsTextDisplay::add(int xp, int yp, uint fontColor, int charSpacing, const char *msg, Font *font) {
int usedSlot = -1;
for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
@@ -629,8 +630,8 @@ int MadsTextDisplay::add(int xp, int yp, uint fontColour, int charSpacing, const
_entries[idx].msg = msg;
_entries[idx].bounds.setWidth(font->getWidth(msg, charSpacing));
_entries[idx].bounds.setHeight(font->getHeight());
- _entries[idx].colour1 = fontColour & 0xff;
- _entries[idx].colour2 = fontColour >> 8;
+ _entries[idx].color1 = fontColor & 0xff;
+ _entries[idx].color2 = fontColor >> 8;
_entries[idx].spacing = charSpacing;
_entries[idx].expire = 1;
_entries[idx].active = true;
@@ -666,7 +667,7 @@ void MadsTextDisplay::setDirtyAreas2() {
void MadsTextDisplay::draw(M4Surface *view) {
for (uint idx = 0; idx < _entries.size(); ++idx) {
if (_entries[idx].active && (_entries[idx].expire >= 0)) {
- _entries[idx].font->setColours(_entries[idx].colour1, _entries[idx].colour2, 0);
+ _entries[idx].font->setColors(_entries[idx].color1, _entries[idx].color2, 0);
_entries[idx].font->writeString(view, _entries[idx].msg,
_entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(),
_entries[idx].spacing);
@@ -707,7 +708,7 @@ void MadsKernelMessageList::clear() {
_talkFont = _vm->_font->getFont(FONT_CONVERSATION_MADS);
}
-int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 abortTimers, uint32 timeout, const char *msg) {
+int MadsKernelMessageList::add(const Common::Point &pt, uint fontColor, uint8 flags, uint8 abortTimers, uint32 timeout, const char *msg) {
// Find a free slot
uint idx = 0;
while ((idx < _entries.size()) && ((_entries[idx].flags & KMSG_ACTIVE) != 0))
@@ -722,8 +723,8 @@ int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 f
MadsKernelMessageEntry &rec = _entries[idx];
strcpy(rec.msg, msg);
rec.flags = flags | KMSG_ACTIVE;
- rec.colour1 = fontColour & 0xff;
- rec.colour2 = fontColour >> 8;
+ rec.color1 = fontColor & 0xff;
+ rec.color2 = fontColor >> 8;
rec.position = pt;
rec.textDisplayIndex = -1;
rec.timeout = timeout;
@@ -918,7 +919,7 @@ void MadsKernelMessageList::processText(int msgIndex) {
if (msg.textDisplayIndex < 0) {
// Need to create a new text display entry for this message
- int idx = _owner._textDisplay.add(x1, y1, msg.colour1 | (msg.colour2 << 8), _owner._textSpacing, msg.msg, _talkFont);
+ int idx = _owner._textDisplay.add(x1, y1, msg.color1 | (msg.color2 << 8), _owner._textSpacing, msg.msg, _talkFont);
if (idx >= 0)
msg.textDisplayIndex = idx;
}
diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h
index c93d0beda3..ce5ba9c4e5 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -174,8 +174,8 @@ public:
int expire;
int spacing;
Common::Rect bounds;
- uint8 colour1;
- uint8 colour2;
+ uint8 color1;
+ uint8 color2;
Font *font;
const char *msg;
@@ -201,7 +201,7 @@ public:
_entries[idx].expire = -1;
}
- int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font);
+ int add(int xp, int yp, uint fontColor, int charSpacing, const char *msg, Font *font);
void clear();
void draw(M4Surface *view);
void setDirtyAreas();
@@ -221,8 +221,8 @@ public:
int sequenceIndex;
char asciiChar;
char asciiChar2;
- int colour1;
- int colour2;
+ int color1;
+ int color2;
Common::Point position;
int textDisplayIndex;
int msgOffset;
@@ -251,7 +251,7 @@ public:
MadsKernelMessageList(MadsView &owner);
void clear();
- int add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 abortTimers, uint32 timeout, const char *msg);
+ int add(const Common::Point &pt, uint fontColor, uint8 flags, uint8 abortTimers, uint32 timeout, const char *msg);
int addQuote(int quoteId, int abortTimers, uint32 timeout);
void scrollMessage(int msgIndex, int numTicks, bool quoted);
void setSeqIndex(int msgIndex, int seqIndex);
diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp
index f130ddc3b5..24ac60c22e 100644
--- a/engines/m4/midi.cpp
+++ b/engines/m4/midi.cpp
@@ -28,123 +28,35 @@
#include "m4/m4.h"
#include "m4/midi.h"
+#include "audio/midiparser.h"
+#include "common/config-manager.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
namespace M4 {
-MidiPlayer::MidiPlayer(MadsM4Engine *vm, MidiDriver *driver) : _vm(vm), _midiData(NULL), _driver(driver), _isPlaying(false), _passThrough(false), _isGM(false) {
- memset(_channel, 0, sizeof(_channel));
- _masterVolume = 0;
- _parser = MidiParser::createParser_SMF();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(getBaseTempo());
- open();
-}
-
-MidiPlayer::~MidiPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- _parser->setMidiDriver(NULL);
- stopMusic();
- close();
- delete _parser;
- free(_midiData);
-}
-
-void MidiPlayer::setVolume(int volume) {
- Common::StackLock lock(_mutex);
+MidiPlayer::MidiPlayer(MadsM4Engine *vm) : _vm(vm), _isGM(false) {
- if (volume < 0)
- volume = 0;
- else if (volume > 255)
- volume = 255;
-
- if (_masterVolume == volume)
- return;
-
- _masterVolume = volume;
-
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
- }
- }
-}
-
-int MidiPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
+ MidiPlayer::createDriver();
int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
-
-void MidiPlayer::close() {
- stopMusic();
- if (_driver)
- _driver->close();
- _driver = 0;
+ if (ret == 0) {
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MidiPlayer::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
}
- else if ((b & 0xFFF0) == 0x007BB0) {
- //Only respond to All Notes Off if this channel
- //has currently been allocated
- if (!_channel[b & 0x0F])
- return;
- }
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
-
- if (_channel[channel])
- _channel[channel]->send(b);
-}
-
-void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F:
- // End of track. (Not called when auto-looping.)
- stopMusic();
- break;
- case 0x51:
- // Set tempo. Handled by the standard MIDI parser already.
- break;
- default:
- warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MidiPlayer::onTimer(void *refCon) {
- MidiPlayer *midi = (MidiPlayer *)refCon;
- Common::StackLock lock(midi->_mutex);
-
- if (midi->_isPlaying)
- midi->_parser->onTimer();
+ Audio::MidiPlayer::send(b);
}
void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger, int32 scene) {
- stopMusic();
+ Common::StackLock lock(_mutex);
+
+ stop();
char fullname[144];
_vm->res()->changeExtension(fullname, name, "HMP");
@@ -160,11 +72,10 @@ void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger
_vm->res()->purge();
if (_midiData) {
- /*
- FILE *out = fopen("music.mid", "wb");
- fwrite(_midiData, smfSize, 1, out);
- fclose(out);
- */
+ _parser = MidiParser::createParser_SMF();
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+
_parser->loadMusic(_midiData, smfSize);
_parser->property(MidiParser::mpAutoLoop, loop);
}
@@ -174,20 +85,6 @@ void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger
_isPlaying = true;
}
-void MidiPlayer::stopMusic() {
- Common::StackLock lock(_mutex);
-
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- }
-
- if (_midiData) {
- free(_midiData);
- _midiData = NULL;
- }
-}
-
// This function will convert HMP music into type 1 SMF, which our SMF parser
// will be able to handle. It is based on Hans de Goede's HMP 2 MIDI file
// converter, which in turn is "based on the conversion algorithms found in
diff --git a/engines/m4/midi.h b/engines/m4/midi.h
index 8344f8d485..a544fb72aa 100644
--- a/engines/m4/midi.h
+++ b/engines/m4/midi.h
@@ -28,68 +28,32 @@
#ifndef M4_MIDI_H
#define M4_MIDI_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
-#include "common/mutex.h"
+#include "audio/midiplayer.h"
namespace M4 {
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public Audio::MidiPlayer {
public:
- MidiPlayer(MadsM4Engine *vm, MidiDriver *driver);
- ~MidiPlayer();
+ MidiPlayer(MadsM4Engine *vm);
- bool isPlaying() { return _isPlaying; }
-
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
-
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
void playMusic(const char *name, int32 vol, bool loop, int32 trigger, int32 scene);
- void stopMusic();
- void setPassThrough(bool b) { _passThrough = b; }
void setGM(bool isGM) { _isGM = isGM; }
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
protected:
- static void onTimer(void *data);
-
MadsM4Engine *_vm;
- byte *_midiData;
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_parser;
- byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
- bool _isPlaying;
bool _randomLoop;
- byte _masterVolume;
byte *_musicData;
uint16 *_buf;
size_t _musicDataSize;
- Common::Mutex _mutex;
-
byte *convertHMPtoSMF(byte *data, uint32 inSize, uint32 &outSize);
};
diff --git a/engines/m4/rails.cpp b/engines/m4/rails.cpp
index ff18d645e7..39cba9ab84 100644
--- a/engines/m4/rails.cpp
+++ b/engines/m4/rails.cpp
@@ -194,9 +194,8 @@ long SqrtF16(long n) {
void Rails::createEdge(int32 node1, int32 node2) {
uint32 index;
int32 x1, y1, x2, y2;
- bool valid, finished;
+ bool valid;
long deltaX, deltaY, distance;
- uint8 *walkCodePtr;
if ((node1 < 0) || (node1 >= MAXRAILNODES) || (node2 < 0) || (node2 >= MAXRAILNODES))
return;
@@ -214,8 +213,6 @@ void Rails::createEdge(int32 node1, int32 node2) {
_edges.resize(index + 1);
_edges.insert_at(index, 0);
valid = true;
- walkCodePtr = NULL;
- finished = false;
if (_nodes.size() <= (uint32)node1 || _nodes.size() <= (uint32)node2)
return;
diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp
index 70abc47960..1946797f75 100644
--- a/engines/m4/resource.cpp
+++ b/engines/m4/resource.cpp
@@ -28,6 +28,7 @@
#include "m4/events.h"
#include "common/substream.h"
+#include "common/textconsole.h"
namespace M4 {
@@ -465,7 +466,6 @@ Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resour
bool MADSResourceManager::resourceExists(const char *resourceName) {
Common::File hagFile;
- uint32 offset, size;
// If the first character is the wildcard (resource indicator), skip over it
if (*resourceName == '*')
@@ -488,8 +488,8 @@ bool MADSResourceManager::resourceExists(const char *resourceName) {
while (++resIndex < numEntries) {
// Read in the details of the next resource
char resourceBuffer[14];
- offset = hagFile.readUint32LE();
- size = hagFile.readUint32LE();
+ hagFile.readUint32LE(); // offset
+ hagFile.readUint32LE(); // size
hagFile.read(resourceBuffer, 14);
if (!strcmp(resName, resourceBuffer))
diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp
index 0f684ebced..c0cbd879b2 100644
--- a/engines/m4/scene.cpp
+++ b/engines/m4/scene.cpp
@@ -163,7 +163,7 @@ void Scene::showCodes() {
// Show all the scene's walk nodes
SceneNodeList &nodeList = _madsVm->scene()->getSceneResources()._nodes;
- _backgroundSurface->setColour(_madsVm->_palette->WHITE);
+ _backgroundSurface->setColor(_madsVm->_palette->WHITE);
for (uint i = 0; i < nodeList.size() - 2; ++i) {
// Draw a little cross at the node's position
_backgroundSurface->hLine(nodeList[i].pt.x - 2, nodeList[i].pt.x + 2, nodeList[i].pt.y);
diff --git a/engines/m4/script.cpp b/engines/m4/script.cpp
index 42d55c6dc7..cc60ec310d 100644
--- a/engines/m4/script.cpp
+++ b/engines/m4/script.cpp
@@ -24,6 +24,7 @@
*/
#include "common/system.h"
+#include "common/textconsole.h"
#include "m4/m4.h"
#include "m4/script.h"
diff --git a/engines/m4/sound.cpp b/engines/m4/sound.cpp
index 14c60c1c58..fb90cea5cc 100644
--- a/engines/m4/sound.cpp
+++ b/engines/m4/sound.cpp
@@ -28,6 +28,7 @@
#include "m4/compression.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp
index 641b93baea..cef9917381 100644
--- a/engines/m4/sprite.cpp
+++ b/engines/m4/sprite.cpp
@@ -24,6 +24,7 @@
*/
#include "common/rect.h"
+#include "common/textconsole.h"
#include "m4/globals.h"
#include "m4/graphics.h"
@@ -124,7 +125,7 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) {
bool spriteEnd = false;
// Set entire sprite contents to transparent pixels
- fillRect(bounds(), TRANSPARENT_COLOUR_INDEX);
+ fillRect(bounds(), TRANSPARENT_COLOR_INDEX);
// Major line loop
for (int yp = 0; yp < h; ++yp) {
@@ -153,7 +154,7 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) {
byte v = source->readByte();
while (cmd-- > 0) {
if (x2 < w)
- *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v;
+ *destP++ = (v == 0xFD) ? TRANSPARENT_COLOR_INDEX : v;
++x2;
}
}
@@ -173,13 +174,13 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) {
byte v = source->readByte();
while (cmd-- > 0) {
if (x2 < w) {
- *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v;
+ *destP++ = (v == 0xFD) ? TRANSPARENT_COLOR_INDEX : v;
}
++x2;
}
} else {
// Handle writing out single pixel
- *destP++ = (cmd == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd;
+ *destP++ = (cmd == 0xFD) ? TRANSPARENT_COLOR_INDEX : cmd;
++x2;
}
}
@@ -203,7 +204,7 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) {
}
byte M4Sprite::getTransparencyIndex() const {
- return TRANSPARENT_COLOUR_INDEX;
+ return TRANSPARENT_COLOR_INDEX;
}
} // End of namespace M4
diff --git a/engines/m4/woodscript.cpp b/engines/m4/woodscript.cpp
index 1235cc9cb6..dc24548f84 100644
--- a/engines/m4/woodscript.cpp
+++ b/engines/m4/woodscript.cpp
@@ -26,6 +26,7 @@
#include "m4/woodscript.h"
#include "common/memstream.h"
+#include "graphics/palette.h"
namespace M4 {
@@ -164,7 +165,7 @@ WoodScript::WoodScript(MadsM4Engine *vm) {
_backgroundSurface = NULL;
- Common::Rect viewBounds = Common::Rect(0, 0, 640, 480);
+ //Common::Rect viewBounds = Common::Rect(0, 0, 640, 480);
//_surfaceView = new View(viewBounds);
}
diff --git a/engines/m4/woodscript.h b/engines/m4/woodscript.h
index 4b0f457193..a9a884a4b0 100644
--- a/engines/m4/woodscript.h
+++ b/engines/m4/woodscript.h
@@ -319,8 +319,8 @@ public:
RGB8 *getMainPalette() const;
- void setInverseColourTable(byte *inverseColourTable) { _inverseColourTable = inverseColourTable; }
- byte *getInverseColourTable() const { return _inverseColourTable; }
+ void setInverseColorTable(byte *inverseColorTable) { _inverseColorTable = inverseColorTable; }
+ byte *getInverseColorTable() const { return _inverseColorTable; }
protected:
MadsM4Engine *_vm;
@@ -338,7 +338,7 @@ protected:
/* Misc */
int16 *_depthTable;
- byte *_inverseColourTable;
+ byte *_inverseColorTable;
M4Surface *_backgroundSurface;
View *_surfaceView;
diff --git a/engines/m4/ws_sequence.cpp b/engines/m4/ws_sequence.cpp
index bb6230d041..3ee496da0d 100644
--- a/engines/m4/ws_sequence.cpp
+++ b/engines/m4/ws_sequence.cpp
@@ -291,7 +291,7 @@ void Sequence::draw(M4Surface *surface, const Common::Rect &clipRect, Common::Re
info.hotX = _curFrame->xOffset;
info.hotY = _curFrame->yOffset;
info.encoding = _curFrame->encoding;
- info.inverseColourTable = _m4Vm->scene()->getInverseColourTable();
+ info.inverseColorTable = _m4Vm->scene()->getInverseColorTable();
info.palette = _ws->getMainPalette();
info.width = _curFrame->width();
info.height = _curFrame->height();
diff --git a/engines/made/database.cpp b/engines/made/database.cpp
index 2aa378edf5..4e7a0467b1 100644
--- a/engines/made/database.cpp
+++ b/engines/made/database.cpp
@@ -27,6 +27,7 @@
#include "common/endian.h"
#include "common/util.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "made/database.h"
@@ -659,7 +660,7 @@ bool GameDatabaseV3::getSavegameDescription(const char *filename, Common::String
}
uint32 header = in->readUint32BE();
- if (header != MKID_BE('SGAM')) {
+ if (header != MKTAG('S','G','A','M')) {
warning("Save game header missing");
delete in;
return false;
@@ -696,7 +697,7 @@ int16 GameDatabaseV3::savegame(const char *filename, const char *description, in
return 6;
}
strncpy(desc, description, 64);
- out->writeUint32BE(MKID_BE('SGAM'));
+ out->writeUint32BE(MKTAG('S','G','A','M'));
out->writeUint32LE(size);
out->writeUint16LE(version);
out->write(desc, 64);
@@ -715,7 +716,7 @@ int16 GameDatabaseV3::loadgame(const char *filename, int16 version) {
}
uint32 header = in->readUint32BE();
- if (header != MKID_BE('SGAM')) {
+ if (header != MKTAG('S','G','A','M')) {
warning("Save game header missing");
delete in;
return 1;
diff --git a/engines/made/graphics.cpp b/engines/made/graphics.cpp
index 7e8330d3f4..388ff60aa8 100644
--- a/engines/made/graphics.cpp
+++ b/engines/made/graphics.cpp
@@ -23,7 +23,9 @@
*
*/
+#include "common/debug.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "made/graphics.h"
diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 11f7734495..c791b657e7 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -26,8 +26,6 @@
#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/keyboard.h"
-#include "common/file.h"
-#include "common/savefile.h"
#include "common/config-manager.h"
#include "common/stream.h"
@@ -100,18 +98,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
_script = new ScriptInterpreter(this);
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
-
- MidiDriver *driver = MidiDriver::createMidi(dev);
- if (native_mt32)
- driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _music = new MusicPlayer(driver);
- _music->setNativeMT32(native_mt32);
- _music->open();
- //_music->setAdLib(adlib);
+ _music = new MusicPlayer();
// Set default sound frequency
switch (getGameID()) {
@@ -146,11 +133,15 @@ MadeEngine::~MadeEngine() {
}
void MadeEngine::syncSoundSettings() {
- _music->setVolume(ConfMan.getInt("music_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ Engine::syncSoundSettings();
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _music->setVolume(mute ? 0 : ConfMan.getInt("music_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType,
+ mute ? 0 : ConfMan.getInt("sfx_volume"));
}
int16 MadeEngine::getTicks() {
diff --git a/engines/made/music.cpp b/engines/made/music.cpp
index 8c9248a262..e5bbbc3b42 100644
--- a/engines/made/music.cpp
+++ b/engines/made/music.cpp
@@ -30,126 +30,36 @@
#include "audio/audiostream.h"
#include "audio/mididrv.h"
#include "audio/midiparser.h"
-#include "common/config-manager.h"
-#include "common/file.h"
#include "made/music.h"
namespace Made {
-MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
- memset(_channel, 0, sizeof(_channel));
- _masterVolume = 0;
- _xmidiParser = MidiParser::createParser_XMIDI();
- _smfParser = MidiParser::createParser_SMF();
-}
-
-MusicPlayer::~MusicPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- stop();
- this->close();
- _xmidiParser->setMidiDriver(NULL);
- _smfParser->setMidiDriver(NULL);
- delete _xmidiParser;
- delete _smfParser;
-}
-
-void MusicPlayer::setVolume(int volume) {
- volume = CLIP(volume, 0, 255);
-
- if (_masterVolume == volume)
- return;
-
- _masterVolume = volume;
-
- Common::StackLock lock(_mutex);
-
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
- }
- }
-}
-
-int MusicPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
+MusicPlayer::MusicPlayer() : _isGM(false) {
+ MidiPlayer::createDriver();
int ret = _driver->open();
- if (ret)
- return ret;
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
-
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
-void MusicPlayer::close() {
- stop();
- if (_driver)
- _driver->close();
- _driver = 0;
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MusicPlayer::send(uint32 b) {
- if (_passThrough) {
- _driver->send(b);
- return;
- }
-
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
}
- else if ((b & 0xFFF0) == 0x007BB0) {
- // Only respond to All Notes Off if this channel
- // has currently been allocated
- if (!_channel[b & 0x0F])
- return;
- }
-
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
-
- if (_channel[channel])
- _channel[channel]->send(b);
-}
-
-void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
-
- switch (type) {
- case 0x2F: // End of Track
- if (_looping)
- _parser->jumpToTick(0);
- else
- stop();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MusicPlayer::onTimer(void *refCon) {
- MusicPlayer *music = (MusicPlayer *)refCon;
- Common::StackLock lock(music->_mutex);
- if (music->_isPlaying)
- music->_parser->onTimer();
+ Audio::MidiPlayer::send(b);
}
void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) {
+ Common::StackLock lock(_mutex);
+
if (_isPlaying)
return;
@@ -159,11 +69,11 @@ void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) {
_isGM = true;
- if (_xmidiParser->loadMusic(midiResource->getData(), midiResource->getSize())) {
- MidiParser *parser = _xmidiParser;
+ MidiParser *parser = MidiParser::createParser_XMIDI();
+ if (parser->loadMusic(midiResource->getData(), midiResource->getSize())) {
parser->setTrack(0);
parser->setMidiDriver(this);
- parser->setTimerRate(getBaseTempo());
+ parser->setTimerRate(_driver->getBaseTempo());
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
@@ -171,12 +81,16 @@ void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) {
setVolume(127);
- _looping = flags & MUSIC_LOOP;
+ _isLooping = flags & MUSIC_LOOP;
_isPlaying = true;
+ } else {
+ delete parser;
}
}
void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) {
+ Common::StackLock lock(_mutex);
+
if (_isPlaying)
return;
@@ -186,29 +100,21 @@ void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) {
_isGM = true;
- if (_smfParser->loadMusic(midiResource->getData(), midiResource->getSize())) {
- MidiParser *parser = _smfParser;
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(midiResource->getData(), midiResource->getSize())) {
parser->setTrack(0);
parser->setMidiDriver(this);
- parser->setTimerRate(getBaseTempo());
+ parser->setTimerRate(_driver->getBaseTempo());
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_parser = parser;
setVolume(127);
- _looping = flags & MUSIC_LOOP;
+ _isLooping = flags & MUSIC_LOOP;
_isPlaying = true;
- }
-}
-
-void MusicPlayer::stop() {
- Common::StackLock lock(_mutex);
-
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
+ } else {
+ delete parser;
}
}
diff --git a/engines/made/music.h b/engines/made/music.h
index 9840c50cfa..f8f70cdad6 100644
--- a/engines/made/music.h
+++ b/engines/made/music.h
@@ -28,7 +28,7 @@
#ifndef MADE_MUSIC_H
#define MADE_MUSIC_H
-#include "audio/mididrv.h"
+#include "audio/midiplayer.h"
#include "audio/midiparser.h"
#include "common/mutex.h"
@@ -41,61 +41,21 @@ enum MusicFlags {
MUSIC_LOOP = 1
};
-class MusicPlayer : public MidiDriver {
+class MusicPlayer : public Audio::MidiPlayer {
public:
- MusicPlayer(MidiDriver *driver);
- ~MusicPlayer();
+ MusicPlayer();
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
-
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
-
- void setNativeMT32(bool b) { _nativeMT32 = b; }
- bool hasNativeMT32() { return _nativeMT32; }
void playXMIDI(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL);
void playSMF(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL);
- void stop();
+// void stop();
void pause();
void resume();
- void setLoop(bool loop) { _looping = loop; }
- void setPassThrough(bool b) { _passThrough = b; }
-
- void setGM(bool isGM) { _isGM = isGM; }
-
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- MidiParser *_parser;
- Common::Mutex _mutex;
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
protected:
-
- static void onTimer(void *data);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_xmidiParser, *_smfParser;
- byte _channelVolume[16];
- bool _nativeMT32;
bool _isGM;
- bool _passThrough;
-
- bool _isPlaying;
- bool _looping;
- byte _masterVolume;
};
} // End of namespace Made
diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp
index 34163a940d..5ab24c1984 100644
--- a/engines/made/pmvplayer.cpp
+++ b/engines/made/pmvplayer.cpp
@@ -50,14 +50,14 @@ bool PmvPlayer::play(const char *filename) {
uint32 chunkType, chunkSize, prevChunkSize = 0;
readChunk(chunkType, chunkSize); // "MOVE"
- if (chunkType != MKID_BE('MOVE')) {
+ if (chunkType != MKTAG('M','O','V','E')) {
warning("Unexpected PMV video header, expected 'MOVE'");
delete _fd;
return false;
}
readChunk(chunkType, chunkSize); // "MHED"
- if (chunkType != MKID_BE('MHED')) {
+ if (chunkType != MKTAG('M','H','E','D')) {
warning("Unexpected PMV video header, expected 'MHED'");
delete _fd;
return false;
@@ -98,7 +98,7 @@ bool PmvPlayer::play(const char *filename) {
uint32 soundStartTime = 0, skipFrames = 0;
- uint32 frameNum, bytesRead;
+ uint32 bytesRead;
uint16 width, height, cmdOffs, pixelOffs, maskOffs, lineSize;
// TODO: Sound can still be a little choppy. A bug in the decoder or -
@@ -111,7 +111,7 @@ bool PmvPlayer::play(const char *filename) {
int32 frameTime = _vm->_system->getMillis();
readChunk(chunkType, chunkSize);
- if (chunkType != MKID_BE('MFRM')) {
+ if (chunkType != MKTAG('M','F','R','M')) {
warning("Unknown chunk type");
}
@@ -156,7 +156,7 @@ bool PmvPlayer::play(const char *filename) {
// Handle video
imageData = frameData + READ_LE_UINT32(frameData + 12) - 8;
- frameNum = READ_LE_UINT32(frameData);
+ // frameNum @0
width = READ_LE_UINT16(imageData + 8);
height = READ_LE_UINT16(imageData + 10);
cmdOffs = READ_LE_UINT16(imageData + 12);
@@ -169,7 +169,7 @@ bool PmvPlayer::play(const char *filename) {
if (!_surface) {
_surface = new Graphics::Surface();
- _surface->create(width, height, 1);
+ _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
}
decompressMovieImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize);
diff --git a/engines/made/redreader.cpp b/engines/made/redreader.cpp
index 3d36b69a28..2fcd7f43da 100644
--- a/engines/made/redreader.cpp
+++ b/engines/made/redreader.cpp
@@ -25,6 +25,7 @@
#include "made/redreader.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
namespace Made {
diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp
index f8582aec40..403520bec3 100644
--- a/engines/made/resource.cpp
+++ b/engines/made/resource.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/debug.h"
#include "common/endian.h"
#include "common/memstream.h"
#include "audio/mixer.h"
@@ -57,7 +58,7 @@ PictureResource::~PictureResource() {
}
void PictureResource::load(byte *source, int size) {
- if (READ_BE_UINT32(source) == MKID_BE('Flex')) {
+ if (READ_BE_UINT32(source) == MKTAG('F','l','e','x')) {
loadChunked(source, size);
} else {
loadRaw(source, size);
@@ -95,7 +96,7 @@ void PictureResource::loadRaw(byte *source, int size) {
}
_picture = new Graphics::Surface();
- _picture->create(width, height, 1);
+ _picture->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags);
@@ -126,13 +127,13 @@ void PictureResource::loadChunked(byte *source, int size) {
debug(0, "chunkType = %08X; chunkSize = %d", chunkType, chunkSize);
- if (chunkType == MKID_BE('Rect')) {
+ if (chunkType == MKTAG('R','e','c','t')) {
debug(0, "Rect");
sourceS->skip(4);
height = sourceS->readUint16BE();
width = sourceS->readUint16BE();
debug(0, "width = %d; height = %d", width, height);
- } else if (chunkType == MKID_BE('fMap')) {
+ } else if (chunkType == MKTAG('f','M','a','p')) {
debug(0, "fMap");
lineSize = sourceS->readUint16BE();
sourceS->skip(11);
@@ -140,21 +141,21 @@ void PictureResource::loadChunked(byte *source, int size) {
cmdOffs = sourceS->pos();
sourceS->skip(chunkSize - 14);
debug(0, "lineSize = %d; cmdFlags = %d; cmdOffs = %04X", lineSize, cmdFlags, cmdOffs);
- } else if (chunkType == MKID_BE('fLCo')) {
+ } else if (chunkType == MKTAG('f','L','C','o')) {
debug(0, "fLCo");
sourceS->skip(9);
pixelFlags = sourceS->readByte();
pixelOffs = sourceS->pos();
sourceS->skip(chunkSize - 10);
debug(0, "pixelFlags = %d; pixelOffs = %04X", pixelFlags, pixelOffs);
- } else if (chunkType == MKID_BE('fPix')) {
+ } else if (chunkType == MKTAG('f','P','i','x')) {
debug(0, "fPix");
sourceS->skip(9);
maskFlags = sourceS->readByte();
maskOffs = sourceS->pos();
sourceS->skip(chunkSize - 10);
debug(0, "maskFlags = %d; maskOffs = %04X", maskFlags, maskOffs);
- } else if (chunkType == MKID_BE('fGCo')) {
+ } else if (chunkType == MKTAG('f','G','C','o')) {
debug(0, "fGCo");
_hasPalette = true;
_paletteColorCount = chunkSize / 3;
@@ -171,7 +172,7 @@ void PictureResource::loadChunked(byte *source, int size) {
}
_picture = new Graphics::Surface();
- _picture->create(width, height, 1);
+ _picture->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags);
@@ -227,7 +228,7 @@ void AnimationResource::load(byte *source, int size) {
uint16 lineSize = sourceS->readUint16LE();
Graphics::Surface *frame = new Graphics::Surface();
- frame->create(frameWidth, frameHeight, 1);
+ frame->create(frameWidth, frameHeight, Graphics::PixelFormat::createFormatCLUT8());
decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, 0, 0, 0, _flags & 1);
diff --git a/engines/made/resource.h b/engines/made/resource.h
index 5d5664b4c7..f1aeb7a87c 100644
--- a/engines/made/resource.h
+++ b/engines/made/resource.h
@@ -30,6 +30,7 @@
#include "common/file.h"
#include "common/stream.h"
#include "common/hashmap.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
#include "audio/audiostream.h"
@@ -49,16 +50,16 @@ const int kMaxResourceCacheSize = 400 * 1024;
enum ResourceType {
- kResARCH = MKID_BE('ARCH'),
- kResFREE = MKID_BE('FREE'),
- kResOMNI = MKID_BE('OMNI'),
- kResFLEX = MKID_BE('FLEX'),
- kResSNDS = MKID_BE('SNDS'),
- kResANIM = MKID_BE('ANIM'),
- kResMENU = MKID_BE('MENU'),
- kResFONT = MKID_BE('FONT'),
- kResXMID = MKID_BE('XMID'),
- kResMIDI = MKID_BE('MIDI')
+ kResARCH = MKTAG('A','R','C','H'),
+ kResFREE = MKTAG('F','R','E','E'),
+ kResOMNI = MKTAG('O','M','N','I'),
+ kResFLEX = MKTAG('F','L','E','X'),
+ kResSNDS = MKTAG('S','N','D','S'),
+ kResANIM = MKTAG('A','N','I','M'),
+ kResMENU = MKTAG('M','E','N','U'),
+ kResFONT = MKTAG('F','O','N','T'),
+ kResXMID = MKTAG('X','M','I','D'),
+ kResMIDI = MKTAG('M','I','D','I')
};
struct ResourceSlot;
diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp
index 2649e2bd37..4a73ba8e38 100644
--- a/engines/made/screen.cpp
+++ b/engines/made/screen.cpp
@@ -28,6 +28,8 @@
#include "made/resource.h"
#include "made/database.h"
+#include "graphics/palette.h"
+
namespace Made {
Screen::Screen(MadeEngine *vm) : _vm(vm) {
@@ -36,10 +38,10 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) {
_newPalette = new byte[768];
_backgroundScreen = new Graphics::Surface();
- _backgroundScreen->create(320, 200, 1);
+ _backgroundScreen->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
_workScreen = new Graphics::Surface();
- _workScreen->create(320, 200, 1);
+ _workScreen->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
_backgroundScreenDrawCtx.clipRect = Common::Rect(320, 200);
_workScreenDrawCtx.clipRect = Common::Rect(320, 200);
@@ -51,7 +53,7 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) {
// Screen mask is only needed in v2 games
if (_vm->getGameID() != GID_RTZ) {
_screenMask = new Graphics::Surface();
- _screenMask->create(320, 200, 1);
+ _screenMask->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
_maskDrawCtx.clipRect = Common::Rect(320, 200);
_maskDrawCtx.destSurface = _screenMask;
}
diff --git a/engines/made/script.h b/engines/made/script.h
index 16c5ad604f..be719eba5f 100644
--- a/engines/made/script.h
+++ b/engines/made/script.h
@@ -29,6 +29,7 @@
#include "common/util.h"
#include "common/file.h"
#include "common/stream.h"
+#include "common/textconsole.h"
namespace Made {
diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp
index 4f1937c057..c0a723438e 100644
--- a/engines/made/scriptfuncs.cpp
+++ b/engines/made/scriptfuncs.cpp
@@ -23,9 +23,7 @@
*
*/
-#include "common/endian.h"
#include "common/util.h"
-#include "common/events.h"
#include "backends/audiocd/audiocd.h"
#include "graphics/cursorman.h"
diff --git a/engines/made/scriptfuncs.h b/engines/made/scriptfuncs.h
index 3bed27c5c8..b8b2a87d19 100644
--- a/engines/made/scriptfuncs.h
+++ b/engines/made/scriptfuncs.h
@@ -34,7 +34,7 @@
#include "made/resource.h"
namespace Audio {
- class PCSpeaker;
+class PCSpeaker;
}
namespace Made {
diff --git a/engines/metaengine.h b/engines/metaengine.h
index 2afed0703b..ef34506991 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -37,8 +37,8 @@ class Engine;
class OSystem;
namespace Common {
- class FSList;
- class String;
+class FSList;
+class String;
}
/**
diff --git a/engines/mohawk/bitmap.cpp b/engines/mohawk/bitmap.cpp
index 7f022803ed..02548d58fc 100644
--- a/engines/mohawk/bitmap.cpp
+++ b/engines/mohawk/bitmap.cpp
@@ -31,6 +31,7 @@
#include "common/memstream.h"
#include "common/substream.h"
#include "common/system.h"
+#include "common/textconsole.h"
namespace Mohawk {
@@ -135,8 +136,12 @@ Common::Array<MohawkSurface *> MohawkBitmap::decodeImages(Common::SeekableReadSt
Graphics::Surface *MohawkBitmap::createSurface(uint16 width, uint16 height) {
Graphics::Surface *surface = new Graphics::Surface();
- byte bytesPerPixel = (getBitsPerPixel() <= 8) ? 1 : g_system->getScreenFormat().bytesPerPixel;
- surface->create(width, height, bytesPerPixel);
+ Graphics::PixelFormat format;
+ if (getBitsPerPixel() <= 8)
+ format = Graphics::PixelFormat::createFormatCLUT8();
+ else
+ format = g_system->getScreenFormat();
+ surface->create(width, height, format);
return surface;
}
@@ -569,7 +574,7 @@ void MohawkBitmap::drawRaw(Graphics::Surface *surface) {
byte b = _data->readByte();
byte g = _data->readByte();
byte r = _data->readByte();
- if (surface->bytesPerPixel == 2)
+ if (surface->format.bytesPerPixel == 2)
*((uint16 *)surface->getBasePtr(x, y)) = pixelFormat.RGBToColor(r, g, b);
else
*((uint32 *)surface->getBasePtr(x, y)) = pixelFormat.RGBToColor(r, g, b);
@@ -608,13 +613,12 @@ void MohawkBitmap::drawRLE8(Graphics::Surface *surface, bool isLE) {
if (code & 0x80) {
byte val = _data->readByte();
- for (uint16 j = 0; j < runLen; j++)
- *dst++ = val;
+ memset(dst, val, runLen);
} else {
- for (uint16 j = 0; j < runLen; j++)
- *dst++ = _data->readByte();
+ _data->read(dst, runLen);
}
+ dst += runLen;
remaining -= runLen;
}
@@ -622,6 +626,8 @@ void MohawkBitmap::drawRLE8(Graphics::Surface *surface, bool isLE) {
}
}
+#ifdef ENABLE_MYST
+
//////////////////////////////////////////
// Myst Bitmap Decoder
//////////////////////////////////////////
@@ -721,7 +727,9 @@ MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream* stream) {
return new MohawkSurface(surface, palData);
}
-MohawkSurface *OldMohawkBitmap::decodeImage(Common::SeekableReadStream *stream) {
+#endif
+
+MohawkSurface *LivingBooksBitmap_v1::decodeImage(Common::SeekableReadStream *stream) {
Common::SeekableSubReadStreamEndian *endianStream = (Common::SeekableSubReadStreamEndian *)stream;
// 12 bytes header for the image
@@ -756,10 +764,10 @@ MohawkSurface *OldMohawkBitmap::decodeImage(Common::SeekableReadStream *stream)
_data = decompressLZ(stream, uncompressedSize);
if (endianStream->pos() != endianStream->size())
- error("OldMohawkBitmap decompression failed");
+ error("LivingBooksBitmap_v1 decompression failed");
} else {
if ((_header.format & 0xf0) != 0)
- error("Tried to use unknown OldMohawkBitmap compression (format %02x)", _header.format & 0xf0);
+ error("Tried to use unknown LivingBooksBitmap_v1 compression (format %02x)", _header.format & 0xf0);
// This is so nasty on so many levels. The original Windows LZ decompressor for the
// Living Books v1 games had knowledge of the underlying RLE8 data. While going
@@ -853,7 +861,7 @@ MohawkSurface *DOSBitmap::decodeImage(Common::SeekableReadStream *stream) {
}
void DOSBitmap::expandMonochromePlane(Graphics::Surface *surface, Common::SeekableReadStream *rawStream) {
- assert(surface->bytesPerPixel == 1);
+ assert(surface->format.bytesPerPixel == 1);
byte *dst = (byte *)surface->pixels;
@@ -879,7 +887,7 @@ void DOSBitmap::expandMonochromePlane(Graphics::Surface *surface, Common::Seekab
*(dst + j * 4 + dstPixel) = (*(dst + j * 4 + dstPixel) >> 1) | (((temp >> srcBit) & 1) << 3)
void DOSBitmap::expandEGAPlanes(Graphics::Surface *surface, Common::SeekableReadStream *rawStream) {
- assert(surface->bytesPerPixel == 1);
+ assert(surface->format.bytesPerPixel == 1);
// Note that the image is in EGA planar form and not just standard 4bpp
// This seems to contradict the PoP specs which seem to do
diff --git a/engines/mohawk/bitmap.h b/engines/mohawk/bitmap.h
index 14b8e75327..ea8a130dfc 100644
--- a/engines/mohawk/bitmap.h
+++ b/engines/mohawk/bitmap.h
@@ -144,6 +144,8 @@ private:
void handleRivenSubcommandStream(byte count, byte *&dst);
};
+#ifdef ENABLE_MYST
+
// Myst uses a different image format than that of other Mohawk games.
// It essentially uses a Windows bitmap with the LZ encoding from the
// Mohawk Bitmap format.
@@ -181,10 +183,12 @@ private:
} _info;
};
-class OldMohawkBitmap : public MohawkBitmap {
+#endif
+
+class LivingBooksBitmap_v1 : public MohawkBitmap {
public:
- OldMohawkBitmap() : MohawkBitmap() {}
- ~OldMohawkBitmap() {}
+ LivingBooksBitmap_v1() : MohawkBitmap() {}
+ ~LivingBooksBitmap_v1() {}
MohawkSurface *decodeImage(Common::SeekableReadStream *stream);
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 64e403092a..93cbe87e55 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -24,19 +24,33 @@
*/
#include "mohawk/console.h"
+#include "mohawk/graphics.h"
+#include "mohawk/livingbooks.h"
+#include "mohawk/sound.h"
+#include "mohawk/video.h"
+
+#include "common/system.h"
+#include "common/textconsole.h"
+
+#ifdef ENABLE_CSTIME
+#include "mohawk/cstime.h"
+#endif
+
+#ifdef ENABLE_MYST
#include "mohawk/myst.h"
#include "mohawk/myst_areas.h"
#include "mohawk/myst_scripts.h"
-#include "mohawk/graphics.h"
+#endif
+
+#ifdef ENABLE_RIVEN
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
-#include "mohawk/livingbooks.h"
-#include "mohawk/cstime.h"
-#include "mohawk/sound.h"
-#include "mohawk/video.h"
+#endif
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));
@@ -307,6 +321,10 @@ bool MystConsole::Cmd_Resources(int argc, const char **argv) {
return true;
}
+#endif // ENABLE_MYST
+
+#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));
@@ -316,7 +334,6 @@ RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) {
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("restart", WRAP_METHOD(RivenConsole, Cmd_Restart));
DCmd_Register("hotspots", WRAP_METHOD(RivenConsole, Cmd_Hotspots));
DCmd_Register("zipMode", WRAP_METHOD(RivenConsole, Cmd_ZipMode));
DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript));
@@ -355,18 +372,17 @@ bool RivenConsole::Cmd_Var(int argc, const char **argv) {
return true;
}
- uint32 *globalVar = _vm->getVar(argv[1]);
-
- if (!globalVar) {
- DebugPrintf("Unknown variable \'%s\'\n", argv[1]);
+ if (!_vm->_vars.contains(argv[1])) {
+ DebugPrintf("Unknown variable '%s'\n", argv[1]);
return true;
}
- if (argc > 2)
- *globalVar = (uint32)atoi(argv[2]);
+ uint32 &var = _vm->_vars[argv[1]];
- DebugPrintf("%s = %d\n", argv[1], *globalVar);
+ if (argc > 2)
+ var = (uint32)atoi(argv[2]);
+ DebugPrintf("%s = %d\n", argv[1], var);
return true;
}
@@ -446,14 +462,6 @@ bool RivenConsole::Cmd_ChangeStack(int argc, const char **argv) {
return false;
}
-bool RivenConsole::Cmd_Restart(int argc, const char **argv) {
- _vm->initVars();
- _vm->changeToStack(aspit);
- _vm->changeToCard(1);
-
- return false;
-}
-
bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) {
DebugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard(), _vm->getHotspotCount());
@@ -473,11 +481,11 @@ bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) {
}
bool RivenConsole::Cmd_ZipMode(int argc, const char **argv) {
- uint32 *zipModeActive = _vm->getVar("azip");
- *zipModeActive = !(*zipModeActive);
+ uint32 &zipModeActive = _vm->_vars["azip"];
+ zipModeActive = !zipModeActive;
DebugPrintf("Zip Mode is ");
- DebugPrintf((*zipModeActive) ? "Enabled" : "Disabled");
+ DebugPrintf(zipModeActive ? "Enabled" : "Disabled");
DebugPrintf("\n");
return true;
}
@@ -558,7 +566,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
// deriven.
debugN("\n\nDumping scripts for %s\'s card %d!\n", argv[1], (uint16)atoi(argv[3]));
debugN("==================================\n\n");
- Common::SeekableReadStream *cardStream = _vm->getResource(MKID_BE('CARD'), (uint16)atoi(argv[3]));
+ Common::SeekableReadStream *cardStream = _vm->getResource(MKTAG('C','A','R','D'), (uint16)atoi(argv[3]));
cardStream->seek(4);
RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false);
for (uint32 i = 0; i < scriptList.size(); i++) {
@@ -571,7 +579,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
debugN("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3]));
debugN("===========================================\n\n");
- Common::SeekableReadStream *hsptStream = _vm->getResource(MKID_BE('HSPT'), (uint16)atoi(argv[3]));
+ Common::SeekableReadStream *hsptStream = _vm->getResource(MKTAG('H','S','P','T'), (uint16)atoi(argv[3]));
uint16 hotspotCount = hsptStream->readUint16BE();
@@ -624,9 +632,9 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
// You'll need to look up the Rebel Tunnel puzzle on your own; the
// solution is constant.
- uint32 teleCombo = *_vm->getVar("tcorrectorder");
- uint32 prisonCombo = *_vm->getVar("pcorrectorder");
- uint32 domeCombo = *_vm->getVar("adomecombo");
+ uint32 teleCombo = _vm->_vars["tcorrectorder"];
+ uint32 prisonCombo = _vm->_vars["pcorrectorder"];
+ uint32 domeCombo = _vm->_vars["adomecombo"];
DebugPrintf("Telescope Combo:\n ");
for (int i = 0; i < 5; i++)
@@ -653,6 +661,8 @@ bool RivenConsole::Cmd_SliderState(int argc, const char **argv) {
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));
@@ -704,6 +714,8 @@ bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) {
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));
@@ -806,4 +818,6 @@ bool CSTimeConsole::Cmd_InvItem(int argc, const char **argv) {
return false;
}
+#endif // ENABLE_CSTIME
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h
index 1dfd0bd318..cb0e8501cd 100644
--- a/engines/mohawk/console.h
+++ b/engines/mohawk/console.h
@@ -30,10 +30,11 @@
namespace Mohawk {
-class MohawkEngine_Myst;
-class MohawkEngine_Riven;
class MohawkEngine_LivingBooks;
-class MohawkEngine_CSTime;
+
+#ifdef ENABLE_MYST
+
+class MohawkEngine_Myst;
class MystConsole : public GUI::Debugger {
public:
@@ -59,6 +60,12 @@ private:
bool Cmd_Resources(int argc, const char **argv);
};
+#endif
+
+#ifdef ENABLE_RIVEN
+
+class MohawkEngine_Riven;
+
class RivenConsole : public GUI::Debugger {
public:
RivenConsole(MohawkEngine_Riven *vm);
@@ -75,7 +82,6 @@ private:
bool Cmd_StopSound(int argc, const char **argv);
bool Cmd_CurStack(int argc, const char **argv);
bool Cmd_ChangeStack(int argc, const char **argv);
- bool Cmd_Restart(int argc, const char **argv);
bool Cmd_Hotspots(int argc, const char **argv);
bool Cmd_ZipMode(int argc, const char **argv);
bool Cmd_RunAllBlocks(int argc, const char **argv);
@@ -86,6 +92,8 @@ private:
bool Cmd_SliderState(int argc, const char **argv);
};
+#endif
+
class LivingBooksConsole : public GUI::Debugger {
public:
LivingBooksConsole(MohawkEngine_LivingBooks *vm);
@@ -100,6 +108,10 @@ private:
bool Cmd_ChangePage(int argc, const char **argv);
};
+#ifdef ENABLE_CSTIME
+
+class MohawkEngine_CSTime;
+
class CSTimeConsole : public GUI::Debugger {
public:
CSTimeConsole(MohawkEngine_CSTime *vm);
@@ -118,6 +130,8 @@ private:
bool Cmd_InvItem(int argc, const char **argv);
};
+#endif
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/cstime.cpp b/engines/mohawk/cstime.cpp
index 955e0e5af6..46faae08f5 100644
--- a/engines/mohawk/cstime.cpp
+++ b/engines/mohawk/cstime.cpp
@@ -30,15 +30,14 @@
#include "mohawk/cstime_view.h"
#include "mohawk/resource.h"
#include "mohawk/cursors.h"
-#include "mohawk/sound.h"
#include "mohawk/video.h"
#include "common/config-manager.h"
+#include "common/error.h"
#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/fs.h"
-
-#include "engines/util.h"
+#include "common/textconsole.h"
namespace Mohawk {
diff --git a/engines/mohawk/cstime_cases.cpp b/engines/mohawk/cstime_cases.cpp
index 408f1c9d9a..c4801f822c 100644
--- a/engines/mohawk/cstime_cases.cpp
+++ b/engines/mohawk/cstime_cases.cpp
@@ -26,6 +26,8 @@
#include "mohawk/cstime_cases.h"
#include "mohawk/cstime_ui.h"
+#include "common/textconsole.h"
+
namespace Mohawk {
CSTimeCase1::CSTimeCase1(MohawkEngine_CSTime *vm) : CSTimeCase(vm, 1) {
diff --git a/engines/mohawk/cstime_game.cpp b/engines/mohawk/cstime_game.cpp
index 5dfc9c4cf6..66dce1da92 100644
--- a/engines/mohawk/cstime_game.cpp
+++ b/engines/mohawk/cstime_game.cpp
@@ -29,6 +29,8 @@
#include "mohawk/resource.h"
#include "mohawk/sound.h"
#include "common/events.h"
+#include "common/system.h"
+#include "common/textconsole.h"
namespace Mohawk {
@@ -470,8 +472,8 @@ void CSTimeConversation::end(bool useLastClicked, bool runEvents) {
_vm->getCase()->getCurrScene()->getChar(_sourceChar)->setupAmbientAnims(true);
}
- CSTimeInterface *interface = _vm->getInterface();
- CSTimeInventoryDisplay *invDisplay = interface->getInventoryDisplay();
+ CSTimeInterface *iface = _vm->getInterface();
+ CSTimeInventoryDisplay *invDisplay = iface->getInventoryDisplay();
if (invDisplay->getState() == 4) {
invDisplay->hide();
invDisplay->setState(0);
@@ -480,8 +482,8 @@ void CSTimeConversation::end(bool useLastClicked, bool runEvents) {
setState((uint)~0);
_currHover = 0xffff;
- interface->clearTextLine();
- interface->clearDialogArea();
+ iface->clearTextLine();
+ iface->clearDialogArea();
invDisplay->show();
// TODO: stupid case 20 stuff
diff --git a/engines/mohawk/cstime_ui.cpp b/engines/mohawk/cstime_ui.cpp
index c95e276b5e..106f7ea319 100644
--- a/engines/mohawk/cstime_ui.cpp
+++ b/engines/mohawk/cstime_ui.cpp
@@ -29,6 +29,9 @@
#include "mohawk/resource.h"
#include "common/algorithm.h" // find
#include "common/events.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "graphics/fontman.h"
namespace Mohawk {
@@ -64,12 +67,15 @@ CSTimeInterface::CSTimeInterface(MohawkEngine_CSTime *vm) : _vm(vm) {
_note = new CSTimeCarmenNote(_vm);
_options = new CSTimeOptions(_vm);
- if (!_normalFont.loadFromFON("EvP14.fon"))
- error("failed to load normal font");
- if (!_dialogFont.loadFromFON("Int1212.fon"))
- error("failed to load dialog font");
- if (!_rolloverFont.loadFromFON("Int1818.fon"))
- error("failed to load rollover font");
+ // The demo uses hardcoded system fonts
+ if (!(_vm->getFeatures() & GF_DEMO)) {
+ if (!_normalFont.loadFromFON("EvP14.fon"))
+ error("failed to load normal font");
+ if (!_dialogFont.loadFromFON("Int1212.fon"))
+ error("failed to load dialog font");
+ if (!_rolloverFont.loadFromFON("Int1818.fon"))
+ error("failed to load rollover font");
+ }
_uiFeature = NULL;
_dialogTextFeature = NULL;
@@ -91,6 +97,30 @@ CSTimeInterface::~CSTimeInterface() {
delete _options;
}
+const Graphics::Font &CSTimeInterface::getNormalFont() const {
+ // HACK: Use a ScummVM GUI font in place of a system one for the demo
+ if (_vm->getFeatures() & GF_DEMO)
+ return *FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
+
+ return _normalFont;
+}
+
+const Graphics::Font &CSTimeInterface::getDialogFont() const {
+ // HACK: Use a ScummVM GUI font in place of a system one for the demo
+ if (_vm->getFeatures() & GF_DEMO)
+ return *FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
+
+ return _dialogFont;
+}
+
+const Graphics::Font &CSTimeInterface::getRolloverFont() const {
+ // HACK: Use a ScummVM GUI font in place of a system one for the demo
+ if (_vm->getFeatures() & GF_DEMO)
+ return *FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
+
+ return _rolloverFont;
+}
+
void CSTimeInterface::cursorInstall() {
_vm->getView()->loadBitmapCursors(200);
}
diff --git a/engines/mohawk/cstime_ui.h b/engines/mohawk/cstime_ui.h
index b849ddbdfb..3ec38492d7 100644
--- a/engines/mohawk/cstime_ui.h
+++ b/engines/mohawk/cstime_ui.h
@@ -233,9 +233,9 @@ public:
const Common::Array<Common::String> &getDialogLines() { return _dialogLines; }
const Common::Array<byte> &getDialogLineColors() { return _dialogLineColors; }
- const Graphics::WinFont &getNormalFont() { return _normalFont; }
- const Graphics::WinFont &getDialogFont() { return _dialogFont; }
- const Graphics::WinFont &getRolloverFont() { return _rolloverFont; }
+ const Graphics::Font &getNormalFont() const;
+ const Graphics::Font &getDialogFont() const;
+ const Graphics::Font &getRolloverFont() const;
Common::Rect _sceneRect, _uiRect;
Common::Rect _dialogTextRect, _bookRect, _noteRect;
diff --git a/engines/mohawk/cstime_view.cpp b/engines/mohawk/cstime_view.cpp
index cad44e3b30..12d641a9ff 100644
--- a/engines/mohawk/cstime_view.cpp
+++ b/engines/mohawk/cstime_view.cpp
@@ -30,6 +30,8 @@
#include "mohawk/cursors.h"
#include "common/events.h"
+#include "common/system.h"
+#include "common/textconsole.h"
namespace Mohawk {
@@ -537,7 +539,7 @@ void CSTimeModule::dialogTextDrawProc(Feature *feature) {
const Common::Array<Common::String> &lines = _vm->getInterface()->getDialogLines();
const Common::Array<byte> &colors = _vm->getInterface()->getDialogLineColors();
const Common::Rect &bounds = feature->_data.bounds;
- const Graphics::WinFont &font = _vm->getInterface()->getDialogFont();
+ const Graphics::Font &font = _vm->getInterface()->getDialogFont();
Graphics::Surface *screen = _vm->_system->lockScreen();
for (uint i = 0; i < lines.size(); i++)
@@ -553,7 +555,7 @@ void CSTimeModule::bubbleTextMoveProc(Feature *feature) {
void CSTimeModule::bubbleTextDrawProc(Feature *feature) {
Common::Rect bounds = feature->_data.bounds;
bounds.grow(-5);
- const Graphics::WinFont &font = _vm->getInterface()->getDialogFont();
+ const Graphics::Font &font = _vm->getInterface()->getDialogFont();
uint height = font.getFontHeight();
Common::Array<Common::String> lines;
diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp
index eb11eb175e..66669e35c9 100644
--- a/engines/mohawk/cursors.cpp
+++ b/engines/mohawk/cursors.cpp
@@ -23,17 +23,21 @@
*
*/
-#include "mohawk/bitmap.h"
#include "mohawk/cursors.h"
+#include "mohawk/mohawk.h"
#include "mohawk/resource.h"
-#include "mohawk/graphics.h"
-#include "mohawk/myst.h"
-#include "mohawk/riven_cursors.h"
#include "common/macresman.h"
-#include "common/ne_exe.h"
#include "common/system.h"
+#include "common/winexe_ne.h"
+#include "common/winexe_pe.h"
#include "graphics/cursorman.h"
+#include "graphics/wincursor.h"
+
+#ifdef ENABLE_MYST
+#include "mohawk/bitmap.h"
+#include "mohawk/myst.h"
+#endif
namespace Mohawk {
@@ -83,15 +87,16 @@ void CursorManager::setCursor(uint16 id) {
setDefaultCursor();
}
-void CursorManager::decodeMacXorCursor(Common::SeekableReadStream *stream, byte *cursor) {
+void CursorManager::setMacXorCursor(Common::SeekableReadStream *stream) {
assert(stream);
- assert(cursor);
+
+ byte cursorBitmap[16 * 16];
// Get black and white data
for (int i = 0; i < 32; i++) {
byte imageByte = stream->readByte();
for (int b = 0; b < 8; b++)
- cursor[i * 8 + b] = (imageByte & (0x80 >> b)) ? 1 : 2;
+ cursorBitmap[i * 8 + b] = (imageByte & (0x80 >> b)) ? 1 : 2;
}
// Apply mask data
@@ -99,30 +104,22 @@ void CursorManager::decodeMacXorCursor(Common::SeekableReadStream *stream, byte
byte imageByte = stream->readByte();
for (int b = 0; b < 8; b++)
if ((imageByte & (0x80 >> b)) == 0)
- cursor[i * 8 + b] = 0;
+ cursorBitmap[i * 8 + b] = 0;
}
-}
-
-void CursorManager::setStandardCursor(Common::SeekableReadStream *stream) {
- // The Broderbund devs decided to rip off the Mac format, it seems.
- // However, they reversed the x/y hotspot. That makes it totally different!!!!
- assert(stream);
- byte cursorBitmap[16 * 16];
- decodeMacXorCursor(stream, cursorBitmap);
uint16 hotspotY = stream->readUint16BE();
uint16 hotspotX = stream->readUint16BE();
CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, 0);
CursorMan.replaceCursorPalette(s_bwPalette, 1, 2);
-
- delete stream;
}
void DefaultCursorManager::setCursor(uint16 id) {
- setStandardCursor(_vm->getResource(_tag, id));
+ setMacXorCursor(_vm->getResource(_tag, id));
}
+#ifdef ENABLE_MYST
+
MystCursorManager::MystCursorManager(MohawkEngine_Myst *vm) : _vm(vm) {
_bmpDecoder = new MystBitmap();
}
@@ -151,7 +148,7 @@ void MystCursorManager::setCursor(uint16 id) {
delete clrcStream;
// Myst ME stores some cursors as 24bpp images instead of 8bpp
- if (surface->bytesPerPixel == 1) {
+ if (surface->format.bytesPerPixel == 1) {
CursorMan.replaceCursor((byte *)surface->pixels, surface->w, surface->h, hotspotX, hotspotY, 0);
CursorMan.replaceCursorPalette(mhkSurface->getPalette(), 0, 256);
} else {
@@ -167,118 +164,7 @@ void MystCursorManager::setDefaultCursor() {
setCursor(kDefaultMystCursor);
}
-void RivenCursorManager::setCursor(uint16 id) {
- // All of Riven's cursors are hardcoded. See riven_cursors.h for these definitions.
-
- switch (id) {
- case 1002:
- // Zip Mode
- CursorMan.replaceCursor(s_zipModeCursor, 16, 16, 8, 8, 0);
- CursorMan.replaceCursorPalette(s_zipModeCursorPalette, 1, ARRAYSIZE(s_zipModeCursorPalette) / 3);
- break;
- case 2003:
- // Hand Over Object
- CursorMan.replaceCursor(s_objectHandCursor, 16, 16, 8, 8, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 2004:
- // Grabbing/Using Object
- CursorMan.replaceCursor(s_grabbingHandCursor, 13, 13, 6, 6, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 3000:
- // Standard Hand
- CursorMan.replaceCursor(s_standardHandCursor, 15, 16, 6, 0, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 3001:
- // Pointing Left
- CursorMan.replaceCursor(s_pointingLeftCursor, 15, 13, 0, 3, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 3002:
- // Pointing Right
- CursorMan.replaceCursor(s_pointingRightCursor, 15, 13, 14, 3, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 3003:
- // Pointing Down (Palm Up)
- CursorMan.replaceCursor(s_pointingDownCursorPalmUp, 13, 16, 3, 15, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 3004:
- // Pointing Up (Palm Up)
- CursorMan.replaceCursor(s_pointingUpCursorPalmUp, 13, 16, 3, 0, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 3005:
- // Pointing Left (Curved)
- CursorMan.replaceCursor(s_pointingLeftCursorBent, 15, 13, 0, 5, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 3006:
- // Pointing Right (Curved)
- CursorMan.replaceCursor(s_pointingRightCursorBent, 15, 13, 14, 5, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 3007:
- // Pointing Down (Palm Down)
- CursorMan.replaceCursor(s_pointingDownCursorPalmDown, 15, 16, 7, 15, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3);
- break;
- case 4001:
- // Red Marble
- CursorMan.replaceCursor(s_redMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_redMarbleCursorPalette, 1, ARRAYSIZE(s_redMarbleCursorPalette) / 3);
- break;
- case 4002:
- // Orange Marble
- CursorMan.replaceCursor(s_orangeMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_orangeMarbleCursorPalette, 1, ARRAYSIZE(s_orangeMarbleCursorPalette) / 3);
- break;
- case 4003:
- // Yellow Marble
- CursorMan.replaceCursor(s_yellowMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_yellowMarbleCursorPalette, 1, ARRAYSIZE(s_yellowMarbleCursorPalette) / 3);
- break;
- case 4004:
- // Green Marble
- CursorMan.replaceCursor(s_greenMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_greenMarbleCursorPalette, 1, ARRAYSIZE(s_greenMarbleCursorPalette) / 3);
- break;
- case 4005:
- // Blue Marble
- CursorMan.replaceCursor(s_blueMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_blueMarbleCursorPalette, 1, ARRAYSIZE(s_blueMarbleCursorPalette) / 3);
- break;
- case 4006:
- // Violet Marble
- CursorMan.replaceCursor(s_violetMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_violetMarbleCursorPalette, 1, ARRAYSIZE(s_violetMarbleCursorPalette) / 3);
- break;
- case 5000:
- // Pellet
- CursorMan.replaceCursor(s_pelletCursor, 8, 8, 4, 4, 0);
- CursorMan.replaceCursorPalette(s_pelletCursorPalette, 1, ARRAYSIZE(s_pelletCursorPalette) / 3);
- break;
- case 9000:
- // Hide Cursor
- CursorMan.showMouse(false);
- break;
- default:
- error("Cursor %d does not exist!", id);
- }
-
- if (id != 9000) // Show Cursor
- CursorMan.showMouse(true);
-
- // Should help in cases where we need to hide the cursor immediately.
- g_system->updateScreen();
-}
-
-void RivenCursorManager::setDefaultCursor() {
- setCursor(kRivenMainCursor);
-}
+#endif
NECursorManager::NECursorManager(const Common::String &appName) {
_exe = new Common::NEResources();
@@ -295,16 +181,14 @@ NECursorManager::~NECursorManager() {
}
void NECursorManager::setCursor(uint16 id) {
- if (!_exe) {
- Common::Array<Common::NECursorGroup> cursors = _exe->getCursors();
-
- for (uint32 i = 0; i < cursors.size(); i++) {
- if (cursors[i].id == id) {
- Common::NECursor *cursor = cursors[i].cursors[0];
- CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), 0);
- CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256);
- return;
- }
+ if (_exe) {
+ Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, id);
+
+ if (cursorGroup) {
+ Graphics::WinCursor *cursor = cursorGroup->cursors[0].cursor;
+ CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor());
+ CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256);
+ return;
}
}
@@ -321,6 +205,8 @@ MacCursorManager::MacCursorManager(const Common::String &appName) {
delete _resFork;
_resFork = 0;
}
+ } else {
+ _resFork = 0;
}
}
@@ -334,22 +220,33 @@ void MacCursorManager::setCursor(uint16 id) {
return;
}
- Common::SeekableReadStream *stream = _resFork->getResource(MKID_BE('CURS'), id);
+ // Try a color cursor first
+ Common::SeekableReadStream *stream = _resFork->getResource(MKTAG('c','r','s','r'), id);
- if (!stream) {
- setDefaultCursor();
+ if (stream) {
+ byte *cursor, *palette;
+ int width, height, hotspotX, hotspotY, keyColor, palSize;
+
+ _resFork->convertCrsrCursor(stream, &cursor, width, height, hotspotX, hotspotY, keyColor, true, &palette, palSize);
+
+ CursorMan.replaceCursor(cursor, width, height, hotspotX, hotspotY, keyColor);
+ CursorMan.replaceCursorPalette(palette, 0, palSize);
+
+ delete[] cursor;
+ delete[] palette;
+ delete stream;
return;
}
- byte cursorBitmap[16 * 16];
- decodeMacXorCursor(stream, cursorBitmap);
- uint16 hotspotX = stream->readUint16BE();
- uint16 hotspotY = stream->readUint16BE();
-
- CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, 0);
- CursorMan.replaceCursorPalette(s_bwPalette, 1, 2);
+ // Fall back to b&w cursors
+ stream = _resFork->getResource(MKTAG('C','U','R','S'), id);
- delete stream;
+ if (stream) {
+ setMacXorCursor(stream);
+ delete stream;
+ } else {
+ setDefaultCursor();
+ }
}
LivingBooksCursorManager_v2::LivingBooksCursorManager_v2() {
@@ -368,10 +265,40 @@ LivingBooksCursorManager_v2::~LivingBooksCursorManager_v2() {
void LivingBooksCursorManager_v2::setCursor(uint16 id) {
if (_sysArchive && _sysArchive->hasResource(ID_TCUR, id)) {
- setStandardCursor(_sysArchive->getResource(ID_TCUR, id));
+ setMacXorCursor(_sysArchive->getResource(ID_TCUR, id));
} else {
// TODO: Handle generated cursors
}
}
+PECursorManager::PECursorManager(const Common::String &appName) {
+ _exe = new Common::PEResources();
+
+ if (!_exe->loadFromEXE(appName)) {
+ // Not all have cursors anyway, so this is not a problem
+ delete _exe;
+ _exe = 0;
+ }
+}
+
+PECursorManager::~PECursorManager() {
+ delete _exe;
+}
+
+void PECursorManager::setCursor(uint16 id) {
+ if (_exe) {
+ Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, id);
+
+ if (cursorGroup) {
+ Graphics::WinCursor *cursor = cursorGroup->cursors[0].cursor;
+ CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor());
+ CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256);
+ return;
+ }
+ }
+
+ // Last resort (not all have cursors)
+ setDefaultCursor();
+}
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/cursors.h b/engines/mohawk/cursors.h
index a542ddb7c3..1fb8b35714 100644
--- a/engines/mohawk/cursors.h
+++ b/engines/mohawk/cursors.h
@@ -29,35 +29,17 @@
#include "common/scummsys.h"
namespace Common {
- class MacResManager;
- class NEResources;
- class SeekableReadStream;
- class String;
+class MacResManager;
+class NEResources;
+class PEResources;
+class SeekableReadStream;
+class String;
}
#include "mohawk/resource.h"
namespace Mohawk {
-// 803-805 are animated, one large bmp which is in chunks - these are NEVER USED
-// Other cursors (200, 300, 400, 500, 600, 700) are not the same in each stack
-enum {
- kDefaultMystCursor = 100, // The default hand
- kWhitePageCursor = 800, // Holding a white page
- kRedPageCursor = 801, // Holding a red page
- kBluePageCursor = 802, // Holding a blue page
- // kDroppingWhitePageAnimCursor = 803,
- // kDroppingRedPageAnimCursor = 804,
- // kDroppingBluePageAnimCursor = 805,
- kNewMatchCursor = 900, // Match that has not yet been lit
- kLitMatchCursor = 901, // Match that's burning
- kDeadMatchCursor = 902, // Match that's been extinguished
- kKeyCursor = 903, // Key in Lighthouse in Stoneship
- kRotateClockwiseCursor = 904, // Rotate gear clockwise (boiler on Myst)
- kRotateCounterClockwiseCursor = 905, // Rotate gear counter clockwise (boiler on Myst)
- kMystZipModeCursor = 999 // Zip Mode cursor
-};
-
enum {
kRivenOpenHandCursor = 2003,
kRivenClosedHandCursor = 2004,
@@ -68,8 +50,6 @@ enum {
class MohawkArchive;
class MohawkEngine;
-class MohawkEngine_Myst;
-class MystBitmap;
class CursorManager {
public:
@@ -80,13 +60,11 @@ public:
virtual void hideCursor();
virtual void setCursor(uint16 id);
virtual void setDefaultCursor();
+ virtual bool hasSource() const { return false; }
protected:
- // Handles the Mac version of the xor/and map cursor
- void decodeMacXorCursor(Common::SeekableReadStream *stream, byte *cursor);
-
- // Set a tCUR resource as the current cursor
- void setStandardCursor(Common::SeekableReadStream *stream);
+ // Set a Mac XOR/AND map cursor to the screen
+ void setMacXorCursor(Common::SeekableReadStream *stream);
};
// The default Mohawk cursor manager
@@ -97,12 +75,37 @@ public:
~DefaultCursorManager() {}
void setCursor(uint16 id);
+ bool hasSource() const { return true; }
private:
MohawkEngine *_vm;
uint32 _tag;
};
+#ifdef ENABLE_MYST
+
+// 803-805 are animated, one large bmp which is in chunks - these are NEVER USED
+// Other cursors (200, 300, 400, 500, 600, 700) are not the same in each stack
+enum {
+ kDefaultMystCursor = 100, // The default hand
+ kWhitePageCursor = 800, // Holding a white page
+ kRedPageCursor = 801, // Holding a red page
+ kBluePageCursor = 802, // Holding a blue page
+ // kDroppingWhitePageAnimCursor = 803,
+ // kDroppingRedPageAnimCursor = 804,
+ // kDroppingBluePageAnimCursor = 805,
+ kNewMatchCursor = 900, // Match that has not yet been lit
+ kLitMatchCursor = 901, // Match that's burning
+ kDeadMatchCursor = 902, // Match that's been extinguished
+ kKeyCursor = 903, // Key in Lighthouse in Stoneship
+ kRotateClockwiseCursor = 904, // Rotate gear clockwise (boiler on Myst)
+ kRotateCounterClockwiseCursor = 905, // Rotate gear counter clockwise (boiler on Myst)
+ kMystZipModeCursor = 999 // Zip Mode cursor
+};
+
+class MohawkEngine_Myst;
+class MystBitmap;
+
// The cursor manager for Myst
// Uses WDIB + CLRC resources
class MystCursorManager : public CursorManager {
@@ -114,31 +117,23 @@ public:
void hideCursor();
void setCursor(uint16 id);
void setDefaultCursor();
+ bool hasSource() const { return true; }
private:
MohawkEngine_Myst *_vm;
MystBitmap *_bmpDecoder;
};
+#endif // ENABLE_MYST
-// The cursor manager for Riven
-// Uses hardcoded cursors
-class RivenCursorManager : public CursorManager {
-public:
- RivenCursorManager() {}
- ~RivenCursorManager() {}
-
- void setCursor(uint16 id);
- void setDefaultCursor();
-};
-
-// The cursor manager for NE exe's
+// The cursor manager for NE EXE's
class NECursorManager : public CursorManager {
public:
NECursorManager(const Common::String &appName);
~NECursorManager();
void setCursor(uint16 id);
+ bool hasSource() const { return _exe != 0; }
private:
Common::NEResources *_exe;
@@ -151,6 +146,7 @@ public:
~MacCursorManager();
void setCursor(uint16 id);
+ bool hasSource() const { return _resFork != 0; }
private:
Common::MacResManager *_resFork;
@@ -164,11 +160,25 @@ public:
~LivingBooksCursorManager_v2();
void setCursor(uint16 id);
+ bool hasSource() const { return _sysArchive != 0; }
private:
MohawkArchive *_sysArchive;
};
+// The cursor manager for PE EXE's
+class PECursorManager : public CursorManager {
+public:
+ PECursorManager(const Common::String &appName);
+ ~PECursorManager();
+
+ void setCursor(uint16 id);
+ bool hasSource() const { return _exe != 0; }
+
+private:
+ Common::PEResources *_exe;
+};
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index f759304f7d..c14d3327d0 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -26,14 +26,23 @@
#include "base/plugins.h"
#include "engines/advancedDetector.h"
-#include "common/config-manager.h"
-#include "common/file.h"
#include "common/savefile.h"
+#include "common/system.h"
+#include "common/textconsole.h"
-#include "mohawk/myst.h"
-#include "mohawk/riven.h"
#include "mohawk/livingbooks.h"
+
+#ifdef ENABLE_CSTIME
#include "mohawk/cstime.h"
+#endif
+
+#ifdef ENABLE_MYST
+#include "mohawk/myst.h"
+#endif
+
+#ifdef ENABLE_RIVEN
+#include "mohawk/riven.h"
+#endif
namespace Mohawk {
@@ -78,6 +87,8 @@ bool MohawkEngine::hasFeature(EngineFeature f) const {
(f == kSupportsRTL);
}
+#ifdef ENABLE_MYST
+
bool MohawkEngine_Myst::hasFeature(EngineFeature f) const {
return
MohawkEngine::hasFeature(f)
@@ -85,6 +96,10 @@ bool MohawkEngine_Myst::hasFeature(EngineFeature f) const {
|| (f == kSupportsSavingDuringRuntime);
}
+#endif
+
+#ifdef ENABLE_RIVEN
+
bool MohawkEngine_Riven::hasFeature(EngineFeature f) const {
return
MohawkEngine::hasFeature(f)
@@ -92,6 +107,8 @@ bool MohawkEngine_Riven::hasFeature(EngineFeature f) const {
|| (f == kSupportsSavingDuringRuntime);
}
+#endif
+
} // End of Namespace Mohawk
static const PlainGameDescriptor mohawkGames[] = {
@@ -104,15 +121,16 @@ static const PlainGameDescriptor mohawkGames[] = {
{"csworld", "Where in the World is Carmen Sandiego?"},
{"csamtrak", "Where in America is Carmen Sandiego? (The Great Amtrak Train Adventure)"},
{"carmentq", "Carmen Sandiego's ThinkQuick Challenge"},
+ {"carmentqc", "Carmen Sandiego's ThinkQuick Challenge Custom Question Creator"},
{"maggiesfa", "Maggie's Farmyard Adventure"},
{"jamesmath", "James Discovers/Explores Math"},
{"treehouse", "The Treehouse"},
{"greeneggs", "Green Eggs and Ham"},
- {"seussabc", "Dr Seuss ABC"},
+ {"seussabc", "Dr Seuss's ABC"},
{"1stdegree", "In the 1st Degree"},
{"csusa", "Where in the USA is Carmen Sandiego?"},
{"tortoise", "Aesop's Fables: The Tortoise and the Hare"},
- {"arthur", "Arthur's Teacher Troubles"},
+ {"arthur", "Arthur's Teacher Trouble"},
{"grandma", "Just Grandma and Me"},
{"ruff", "Ruff's Bone"},
{"newkid", "The New Kid on the Block"},
@@ -123,8 +141,11 @@ static const PlainGameDescriptor mohawkGames[] = {
{"rugrats", "Rugrats Adventure Game"},
{"lbsampler", "Living Books Sampler"},
{"bearfight", "The Berenstain Bears Get in a Fight"},
+ {"beardark", "The Berenstain Bears In The Dark"},
{"arthurcomp", "Arthur's Computer Adventure"},
{"harryhh","Harry and the Haunted House"},
+ {"stellaluna", "Stellaluna"},
+ {"sheila", "Sheila Rae, the Brave"},
{0, 0}
};
@@ -229,11 +250,21 @@ bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
switch (gd->gameType) {
case Mohawk::GType_MYST:
case Mohawk::GType_MAKINGOF:
+#ifdef ENABLE_MYST
*engine = new Mohawk::MohawkEngine_Myst(syst, gd);
break;
+#else
+ warning("Myst support not compiled in");
+ return false;
+#endif
case Mohawk::GType_RIVEN:
+#ifdef ENABLE_RIVEN
*engine = new Mohawk::MohawkEngine_Riven(syst, gd);
break;
+#else
+ warning("Riven support not compiled in");
+ return false;
+#endif
case Mohawk::GType_LIVINGBOOKSV1:
case Mohawk::GType_LIVINGBOOKSV2:
case Mohawk::GType_LIVINGBOOKSV3:
@@ -242,8 +273,13 @@ bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
*engine = new Mohawk::MohawkEngine_LivingBooks(syst, gd);
break;
case Mohawk::GType_CSTIME:
+#ifdef ENABLE_CSTIME
*engine = new Mohawk::MohawkEngine_CSTime(syst, gd);
break;
+#else
+ warning("CSTime support not compiled in");
+ return false;
+#endif
case Mohawk::GType_ZOOMBINI:
case Mohawk::GType_CSWORLD:
case Mohawk::GType_CSAMTRAK:
@@ -251,10 +287,10 @@ bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
case Mohawk::GType_TREEHOUSE:
case Mohawk::GType_1STDEGREE:
case Mohawk::GType_CSUSA:
- error ("Unsupported Mohawk Engine");
- break;
+ warning("Unsupported Mohawk Engine");
+ return false;
default:
- error ("Unknown Mohawk Engine");
+ error("Unknown Mohawk Engine");
}
}
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index a26325be14..36dbcbde7b 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -576,6 +576,23 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
+ // Harry and the Haunted House 1.1
+ // From pacifist
+ {
+ {
+ "harryhh",
+ "",
+ AD_ENTRY1("HARRY.512", "8d786f0998f27e44603a2202d6786c25"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ "HARRY.EXE"
+ },
+
{
{
"carmentq",
@@ -593,6 +610,21 @@ static const MohawkGameDescription gameDescriptions[] = {
{
{
+ "carmentqc",
+ "",
+ AD_ENTRY1("Outline.txt", "6a281eefe72987afb0f8fb6cf84553f5"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV5,
+ 0,
+ 0
+ },
+
+ {
+ {
"maggiesfa",
"",
AD_ENTRY1("Outline", "b7dc6e65fa9e80784a5bb8b557aa37c4"),
@@ -761,6 +793,21 @@ static const MohawkGameDescription gameDescriptions[] = {
{
{
+ "seussabc",
+ "Demo",
+ AD_ENTRY1("BookOutline", "17d72660680ae32cd7c560d0cf04d2ef"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV2,
+ GF_DEMO,
+ 0
+ },
+
+ {
+ {
"1stdegree",
"",
AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"),
@@ -852,6 +899,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"TORTOISE.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "tortoise",
+ "Demo v1.1",
+ AD_ENTRY1("TORTOISE.512", "14400a3358a3f1148e4d4b47bc3523c9"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "TORTOISE.EXE"
+ },
+
{
{
"tortoise",
@@ -912,6 +975,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"ARTHUR.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "arthur",
+ "Demo v1.1",
+ AD_ENTRY1("ARTHUR.512", "dabdd466dea26ab5ecb9415cf73f8601"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "ARTHUR.EXE"
+ },
+
{
{
"arthur",
@@ -942,6 +1021,40 @@ static const MohawkGameDescription gameDescriptions[] = {
"Living Books Player"
},
+ // Just Grandma and Me 2.0
+ // From pacifist
+ {
+ {
+ "grandma",
+ "v2.0",
+ AD_ENTRY1("OUTLINE", "159c18b663c58d1aa17ad5e1ab1f0e12"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ // Just Grandma and Me 1.0
+ // From scoriae
+ {
+ {
+ "grandma",
+ "v1.0",
+ AD_ENTRY1("PAGES.512", "e694ac10f957dd2e20611350bf968da3"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_LB_10,
+ "GRANDMA.EXE"
+ },
+
{
{
"grandma",
@@ -972,6 +1085,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"GRANDMA.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "grandma",
+ "Demo v1.1",
+ AD_ENTRY1("GRANDMA.512", "4f616647245bb4e37e6dab7557dad304"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "GRANDMA.EXE"
+ },
+
{
{
"grandma",
@@ -1002,6 +1131,23 @@ static const MohawkGameDescription gameDescriptions[] = {
"Living Books Player"
},
+ // Ruff's Bone 1.0
+ // From pacifist
+ {
+ {
+ "ruff",
+ "",
+ AD_ENTRY1("RUFF.512", "3dbda0de6f47a64d1714d89f5a5f60d1"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ "RUFF.EXE"
+ },
+
{
{
"ruff",
@@ -1017,6 +1163,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"RUFF.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "ruff",
+ "Demo",
+ AD_ENTRY1("RUFF.512", "07b9d013e2400d61ca268892a76de4d2"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "RUFF.EXE"
+ },
+
{
{
"ruff",
@@ -1062,6 +1224,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"NEWKID.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "newkid",
+ "Demo v1.1",
+ AD_ENTRY1("NEWKID.512", "de576f3481f62e84eda03b4d2307492b"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "NEWKID.EXE"
+ },
+
{
{
"newkid",
@@ -1108,6 +1286,22 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
+ // From zerep in bug #3287894
+ {
+ {
+ "arthurbday",
+ "",
+ AD_ENTRY1("BIRTHDAY.512", "874f80ff363214d63593864e58c4a130"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ "BIRTHDAY.EXE"
+ },
+
{
{
"arthurbday",
@@ -1123,6 +1317,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"BIRTHDAY.EXE"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "arthurbday",
+ "Demo",
+ AD_ENTRY1("BIRTHDAY.512", "2946b1e06f59ea607b8b29dfc6ba8976"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "BIRTHDAY.EXE"
+ },
+
{
{
"arthurbday",
@@ -1168,6 +1378,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"Little Monster at School"
},
+ // From Scarlatti in bug #3275626
+ {
+ {
+ "lilmonster",
+ "Demo",
+ AD_ENTRY1("MONSTER.512", "029e57f1fc8dd1f93f6623a1841f0df2"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "MONSTER.EXE"
+ },
+
{
{
"catinthehat",
@@ -1367,6 +1593,55 @@ static const MohawkGameDescription gameDescriptions[] = {
"Bears Get in a Fight"
},
+ // From bkennimer in bug #3284930
+ {
+ {
+ "beardark",
+ "",
+ AD_ENTRY1("DARK.LB", "81d1e6eaf88d54bd29836a133935c0d4"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ // From bkennimer in bug #3284930
+ // 32-bit version of the previous entry
+ {
+ {
+ "beardark",
+ "",
+ AD_ENTRY1("DARK32.LB", "28abbf5498aeb29e78e5e0dec969ebe2"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
+ // From bkennimer in bug #3284930
+ {
+ {
+ "beardark",
+ "",
+ AD_ENTRY1("BookOutline", "95b2e43778ca9cfaee37bdde843e7681"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
{
{
"arthurcomp",
@@ -1397,6 +1672,40 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
+ // Stellaluna 1.0
+ // From pacifist
+ {
+ {
+ "stellaluna",
+ "",
+ AD_ENTRY1("STELLA.LB", "763bb4a4721aebb5af316ca8e1b478ed"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV2,
+ 0,
+ 0
+ },
+
+ // Sheila Rae the Brave 1.0
+ // From pacifist
+ {
+ {
+ "sheila",
+ "",
+ AD_ENTRY1("SHEILA.LB", "c28a60f615a46384d9a8941fc5c89d63"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV2,
+ 0,
+ 0
+ },
+
{ AD_TABLE_END_MARKER, 0, 0, 0 }
};
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index b5ddc6d233..4c7e52f02f 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -24,14 +24,22 @@
*/
#include "mohawk/mohawk.h"
-#include "mohawk/myst.h"
-#include "mohawk/riven.h"
#include "mohawk/dialogs.h"
#include "gui/gui-manager.h"
-#include "common/savefile.h"
+#include "gui/ThemeEngine.h"
+#include "gui/widget.h"
+#include "common/system.h"
#include "common/translation.h"
+#ifdef ENABLE_MYST
+#include "mohawk/myst.h"
+#endif
+
+#ifdef ENABLE_RIVEN
+#include "mohawk/riven.h"
+#endif
+
namespace Mohawk {
// This used to have GUI::Dialog("MohawkDummyDialog"), but that doesn't work with the gui branch merge :P (Sorry, Tanoku!)
@@ -77,6 +85,8 @@ enum {
kWaterCmd = 'WATR'
};
+#ifdef ENABLE_MYST
+
MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
_zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
_transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
@@ -111,6 +121,10 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
}
}
+#endif
+
+#ifdef ENABLE_RIVEN
+
RivenOptionsDialog::RivenOptionsDialog(MohawkEngine_Riven* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
_zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
_waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~W~ater Effect Enabled"), 0, kWaterCmd);
@@ -125,17 +139,17 @@ RivenOptionsDialog::~RivenOptionsDialog() {
void RivenOptionsDialog::open() {
Dialog::open();
- _zipModeCheckbox->setState(*_vm->getVar("azip") != 0);
- _waterEffectCheckbox->setState(*_vm->getVar("waterenabled") != 0);
+ _zipModeCheckbox->setState(_vm->_vars["azip"] != 0);
+ _waterEffectCheckbox->setState(_vm->_vars["waterenabled"] != 0);
}
void RivenOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kZipCmd:
- *_vm->getVar("azip") = _zipModeCheckbox->getState() ? 1 : 0;
+ _vm->_vars["azip"] = _zipModeCheckbox->getState() ? 1 : 0;
break;
case kWaterCmd:
- *_vm->getVar("waterenabled") = _waterEffectCheckbox->getState() ? 1 : 0;
+ _vm->_vars["waterenabled"] = _waterEffectCheckbox->getState() ? 1 : 0;
break;
case GUI::kCloseCmd:
close();
@@ -145,4 +159,6 @@ void RivenOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, u
}
}
+#endif
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h
index d4e3a3331b..106a1566fc 100644
--- a/engines/mohawk/dialogs.h
+++ b/engines/mohawk/dialogs.h
@@ -38,8 +38,6 @@
namespace Mohawk {
class MohawkEngine;
-class MohawkEngine_Myst;
-class MohawkEngine_Riven;
class InfoDialog : public GUI::Dialog {
protected:
@@ -71,6 +69,10 @@ public:
virtual void handleKeyDown(Common::KeyState state);
};
+#ifdef ENABLE_MYST
+
+class MohawkEngine_Myst;
+
class MystOptionsDialog : public GUI::OptionsDialog {
public:
MystOptionsDialog(MohawkEngine_Myst *vm);
@@ -84,6 +86,12 @@ private:
GUI::CheckboxWidget *_transitionsCheckbox;
};
+#endif
+
+#ifdef ENABLE_RIVEN
+
+class MohawkEngine_Riven;
+
class RivenOptionsDialog : public GUI::OptionsDialog {
public:
RivenOptionsDialog(MohawkEngine_Riven *vm);
@@ -97,6 +105,8 @@ private:
GUI::CheckboxWidget *_waterEffectCheckbox;
};
+#endif
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index 897ca79d0e..a1bcb55f7b 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -25,17 +25,29 @@
#include "mohawk/resource.h"
#include "mohawk/graphics.h"
-#include "mohawk/myst.h"
-#include "mohawk/riven.h"
#include "mohawk/livingbooks.h"
-#include "mohawk/cstime.h"
#include "common/substream.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "engines/util.h"
-#include "graphics/jpeg.h"
+#include "graphics/palette.h"
#include "graphics/primitives.h"
#include "gui/message.h"
+#ifdef ENABLE_CSTIME
+#include "mohawk/cstime.h"
+#endif
+
+#ifdef ENABLE_MYST
+#include "mohawk/myst.h"
+#include "graphics/jpeg.h"
+#endif
+
+#ifdef ENABLE_RIVEN
+#include "mohawk/riven.h"
+#endif
+
namespace Mohawk {
MohawkSurface::MohawkSurface() : _surface(0), _palette(0) {
@@ -61,14 +73,14 @@ MohawkSurface::~MohawkSurface() {
void MohawkSurface::convertToTrueColor() {
assert(_surface);
- if (_surface->bytesPerPixel > 1)
+ if (_surface->format.bytesPerPixel > 1)
return;
assert(_palette);
Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
Graphics::Surface *surface = new Graphics::Surface();
- surface->create(_surface->w, _surface->h, pixelFormat.bytesPerPixel);
+ surface->create(_surface->w, _surface->h, pixelFormat);
for (uint16 i = 0; i < _surface->h; i++) {
for (uint16 j = 0; j < _surface->w; j++) {
@@ -246,6 +258,15 @@ void GraphicsManager::copyAnimImageSectionToScreen(MohawkSurface *image, Common:
getVM()->_system->unlockScreen();
}
+void GraphicsManager::addImageToCache(uint16 id, MohawkSurface *surface) {
+ if (_cache.contains(id))
+ error("Image %d already in cache", id);
+
+ _cache[id] = surface;
+}
+
+#ifdef ENABLE_MYST
+
MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : GraphicsManager(), _vm(vm) {
_bmpDecoder = new MystBitmap();
@@ -274,7 +295,7 @@ MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : GraphicsManager(), _vm(vm) {
// Initialize our buffer
_backBuffer = new Graphics::Surface();
- _backBuffer->create(_vm->_system->getWidth(), _vm->_system->getHeight(), _pixelFormat.bytesPerPixel);
+ _backBuffer->create(_vm->_system->getWidth(), _vm->_system->getHeight(), _pixelFormat);
}
MystGraphics::~MystGraphics() {
@@ -468,7 +489,7 @@ void MystGraphics::copyImageSectionToBackBuffer(uint16 image, Common::Rect src,
debug(3, "\theight: %d", height);
for (uint16 i = 0; i < height; i++)
- memcpy(_backBuffer->getBasePtr(dest.left, i + dest.top), surface->getBasePtr(src.left, top + i), width * surface->bytesPerPixel);
+ memcpy(_backBuffer->getBasePtr(dest.left, i + dest.top), surface->getBasePtr(src.left, top + i), width * surface->format.bytesPerPixel);
}
void MystGraphics::copyImageToScreen(uint16 image, Common::Rect dest) {
@@ -611,6 +632,10 @@ void MystGraphics::drawLine(const Common::Point &p1, const Common::Point &p2, ui
_backBuffer->drawLine(p1.x, p1.y, p2.x, p2.y, color);
}
+#endif // ENABLE_MYST
+
+#ifdef ENABLE_RIVEN
+
RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm) {
_bitmapDecoder = new MohawkBitmap();
@@ -624,12 +649,15 @@ RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm
// The actual game graphics only take up the first 392 rows. The inventory
// occupies the rest of the screen and we don't use the buffer to hold that.
_mainScreen = new Graphics::Surface();
- _mainScreen->create(608, 392, _pixelFormat.bytesPerPixel);
+ _mainScreen->create(608, 392, _pixelFormat);
_updatesEnabled = true;
_scheduledTransition = -1; // no transition
_dirtyScreen = false;
_inventoryDrawn = false;
+
+ _creditsImage = 302;
+ _creditsPos = 0;
}
RivenGraphics::~RivenGraphics() {
@@ -652,7 +680,7 @@ void RivenGraphics::copyImageToScreen(uint16 image, uint32 left, uint32 top, uin
surface->w = 608 - left;
for (uint16 i = 0; i < surface->h; i++)
- memcpy(_mainScreen->getBasePtr(left, i + top), surface->getBasePtr(0, i), surface->w * surface->bytesPerPixel);
+ memcpy(_mainScreen->getBasePtr(left, i + top), surface->getBasePtr(0, i), surface->w * surface->format.bytesPerPixel);
_dirtyScreen = true;
}
@@ -748,7 +776,7 @@ void RivenGraphics::clearWaterEffects() {
bool RivenGraphics::runScheduledWaterEffects() {
// Don't run the effect if it's disabled
- if (*_vm->getVar("waterenabled") == 0)
+ if (_vm->_vars["waterenabled"] == 0)
return false;
Graphics::Surface *screen = NULL;
@@ -840,6 +868,17 @@ void RivenGraphics::runScheduledTransition() {
_scheduledTransition = -1; // Clear scheduled transition
}
+void RivenGraphics::clearMainScreen() {
+ _mainScreen->fillRect(Common::Rect(0, 0, 608, 392), _pixelFormat.RGBToColor(0, 0, 0));
+}
+
+void RivenGraphics::fadeToBlack() {
+ // Self-explanatory
+ scheduleTransition(16);
+ clearMainScreen();
+ runScheduledTransition();
+}
+
void RivenGraphics::showInventory() {
// Don't redraw the inventory
if (_inventoryDrawn)
@@ -864,8 +903,8 @@ void RivenGraphics::showInventory() {
// you get Catherine's journal and the trap book. Near the end,
// you lose the trap book and have just the two journals.
- bool hasCathBook = *_vm->getVar("acathbook") != 0;
- bool hasTrapBook = *_vm->getVar("atrapbook") != 0;
+ bool hasCathBook = _vm->_vars["acathbook"] != 0;
+ bool hasTrapBook = _vm->_vars["atrapbook"] != 0;
if (!hasCathBook) {
drawInventoryImage(101, g_atrusJournalRect1);
@@ -936,7 +975,7 @@ void RivenGraphics::drawImageRect(uint16 id, Common::Rect srcRect, Common::Rect
assert(srcRect.width() == dstRect.width() && srcRect.height() == dstRect.height());
for (uint16 i = 0; i < srcRect.height(); i++)
- memcpy(_mainScreen->getBasePtr(dstRect.left, i + dstRect.top), surface->getBasePtr(srcRect.left, i + srcRect.top), srcRect.width() * surface->bytesPerPixel);
+ memcpy(_mainScreen->getBasePtr(dstRect.left, i + dstRect.top), surface->getBasePtr(srcRect.left, i + srcRect.top), srcRect.width() * surface->format.bytesPerPixel);
_dirtyScreen = true;
}
@@ -955,8 +994,64 @@ void RivenGraphics::drawExtrasImage(uint16 id, Common::Rect dstRect) {
_dirtyScreen = true;
}
+void RivenGraphics::beginCredits() {
+ // Clear the old cache
+ clearCache();
+
+ // Now cache all the credits images
+ for (uint16 i = 302; i <= 320; i++) {
+ MohawkSurface *surface = _bitmapDecoder->decodeImage(_vm->getExtrasResource(ID_TBMP, i));
+ surface->convertToTrueColor();
+ addImageToCache(i, surface);
+ }
+
+ // And clear our screen too
+ clearMainScreen();
+}
+
+void RivenGraphics::updateCredits() {
+ if ((_creditsImage == 303 || _creditsImage == 304) && _creditsPos == 0)
+ fadeToBlack();
+
+ if (_creditsImage < 304) {
+ // For the first two credit images, they are faded from black to the image and then out again
+ scheduleTransition(16);
+
+ Graphics::Surface *frame = findImage(_creditsImage++)->getSurface();
+
+ for (int y = 0; y < frame->h; y++)
+ memcpy(_mainScreen->getBasePtr(124, y), frame->getBasePtr(0, y), frame->pitch);
+
+ runScheduledTransition();
+ } else {
+ // Otheriwse, we're scrolling
+ // Move the screen up one row
+ memmove(_mainScreen->pixels, _mainScreen->getBasePtr(0, 1), _mainScreen->pitch * (_mainScreen->h - 1));
+
+ // Only update as long as we're not before the last frame
+ // Otherwise, we're just moving up a row (which we already did)
+ if (_creditsImage <= 320) {
+ // Copy the next row to the bottom of the screen
+ Graphics::Surface *frame = findImage(_creditsImage)->getSurface();
+ memcpy(_mainScreen->getBasePtr(124, _mainScreen->h - 1), frame->getBasePtr(0, _creditsPos), frame->pitch);
+ _creditsPos++;
+
+ if (_creditsPos == _mainScreen->h) {
+ _creditsImage++;
+ _creditsPos = 0;
+ }
+ }
+
+ // Now flush the new screen
+ _vm->_system->copyRectToScreen((byte *)_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h);
+ _vm->_system->updateScreen();
+ }
+}
+
+#endif // ENABLE_RIVEN
+
LBGraphics::LBGraphics(MohawkEngine_LivingBooks *vm, uint16 width, uint16 height) : GraphicsManager(), _vm(vm) {
- _bmpDecoder = _vm->isPreMohawk() ? new OldMohawkBitmap() : new MohawkBitmap();
+ _bmpDecoder = _vm->isPreMohawk() ? new LivingBooksBitmap_v1() : new MohawkBitmap();
initGraphics(width, height, true);
}
@@ -1023,6 +1118,8 @@ void LBGraphics::setPalette(uint16 id) {
}
}
+#ifdef ENABLE_CSTIME
+
CSTimeGraphics::CSTimeGraphics(MohawkEngine_CSTime *vm) : GraphicsManager(), _vm(vm) {
_bmpDecoder = new MohawkBitmap();
@@ -1055,4 +1152,6 @@ Common::Array<MohawkSurface *> CSTimeGraphics::decodeImages(uint16 id) {
return _bmpDecoder->decodeImages(_vm->getResource(ID_TBMH, id));
}
+#endif
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/graphics.h b/engines/mohawk/graphics.h
index 89189d442a..c7e9b98d49 100644
--- a/engines/mohawk/graphics.h
+++ b/engines/mohawk/graphics.h
@@ -33,26 +33,14 @@
#include "graphics/pict.h"
namespace Graphics {
-
class JPEG;
-
}
namespace Mohawk {
class MohawkEngine;
-class MohawkEngine_Myst;
-class MohawkEngine_Riven;
class MohawkEngine_LivingBooks;
-class MohawkEngine_CSTime;
class MohawkBitmap;
-class MystBitmap;
-
-enum RectState{
- kRectEnabled,
- kRectDisabled,
- kRectUnreachable
-};
class MohawkSurface {
public:
@@ -110,6 +98,7 @@ protected:
virtual Common::Array<MohawkSurface *> decodeImages(uint16 id);
virtual MohawkEngine *getVM() = 0;
+ void addImageToCache(uint16 id, MohawkSurface *surface);
private:
// An image cache that stores images until clearCache() is called
@@ -117,6 +106,17 @@ private:
Common::HashMap<uint16, Common::Array<MohawkSurface*> > _subImageCache;
};
+#ifdef ENABLE_MYST
+
+class MystBitmap;
+class MohawkEngine_Myst;
+
+enum RectState {
+ kRectEnabled,
+ kRectDisabled,
+ kRectUnreachable
+};
+
class MystGraphics : public GraphicsManager {
public:
MystGraphics(MohawkEngine_Myst*);
@@ -161,17 +161,11 @@ private:
Common::Rect _viewport;
};
-struct SFXERecord {
- // Record values
- uint16 frameCount;
- Common::Rect rect;
- uint16 speed;
- Common::Array<Common::SeekableReadStream*> frameScripts;
+#endif // ENABLE_MYST
- // Cur frame
- uint16 curFrame;
- uint32 lastFrameTime;
-};
+#ifdef ENABLE_RIVEN
+
+class MohawkEngine_Riven;
class RivenGraphics : public GraphicsManager {
public:
@@ -195,11 +189,17 @@ public:
// Transitions
void scheduleTransition(uint16 id, Common::Rect rect = Common::Rect(0, 0, 608, 392));
void runScheduledTransition();
+ void fadeToBlack();
// Inventory
void showInventory();
void hideInventory();
+ // Credits
+ void beginCredits();
+ void updateCredits();
+ uint getCurCreditsImage() { return _creditsImage; }
+
protected:
MohawkSurface *decodeImage(uint16 id);
MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
@@ -209,6 +209,17 @@ private:
MohawkBitmap *_bitmapDecoder;
// Water Effects
+ struct SFXERecord {
+ // Record values
+ uint16 frameCount;
+ Common::Rect rect;
+ uint16 speed;
+ Common::Array<Common::SeekableReadStream*> frameScripts;
+
+ // Cur frame
+ uint16 curFrame;
+ uint32 lastFrameTime;
+ };
Common::Array<SFXERecord> _waterEffects;
// Transitions
@@ -224,8 +235,14 @@ private:
Graphics::Surface *_mainScreen;
bool _dirtyScreen;
Graphics::PixelFormat _pixelFormat;
+ void clearMainScreen();
+
+ // Credits
+ uint _creditsImage, _creditsPos;
};
+#endif // ENABLE_RIVEN
+
class LBGraphics : public GraphicsManager {
public:
LBGraphics(MohawkEngine_LivingBooks *vm, uint16 width, uint16 height);
@@ -244,6 +261,10 @@ private:
MohawkEngine_LivingBooks *_vm;
};
+#ifdef ENABLE_CSTIME
+
+class MohawkEngine_CSTime;
+
class CSTimeGraphics : public GraphicsManager {
public:
CSTimeGraphics(MohawkEngine_CSTime *vm);
@@ -261,6 +282,8 @@ private:
MohawkEngine_CSTime *_vm;
};
+#endif
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/installer_archive.cpp b/engines/mohawk/installer_archive.cpp
index 560d99e121..5079375896 100644
--- a/engines/mohawk/installer_archive.cpp
+++ b/engines/mohawk/installer_archive.cpp
@@ -27,8 +27,6 @@
#include "common/dcl.h"
#include "common/debug.h"
-#include "common/substream.h"
-#include "common/util.h"
namespace Mohawk {
@@ -40,11 +38,6 @@ InstallerArchive::~InstallerArchive() {
close();
}
-struct DirectoryEntry {
- uint16 fileCount;
- Common::String name;
-};
-
bool InstallerArchive::open(const Common::String &filename) {
close();
@@ -60,68 +53,55 @@ bool InstallerArchive::open(const Common::String &filename) {
return false;
}
- // Let's move to the directory
+ // Let's pull some relevant data from the header
_stream->seek(41);
- uint32 offset = _stream->readUint32LE();
- _stream->seek(offset);
+ uint32 directoryTableOffset = _stream->readUint32LE();
+ /* uint32 directoryTableSize = */ _stream->readUint32LE();
+ uint16 directoryCount = _stream->readUint16LE();
+ uint32 fileTableOffset = _stream->readUint32LE();
+ /* uint32 fileTableSize = */ _stream->readUint32LE();
+
+ // We need to have at least one directory in order for the archive to be valid
+ if (directoryCount == 0) {
+ close();
+ return false;
+ }
- // Now read in each file from the directory
+ // TODO: Currently, we only support getting files from the first directory
+ // To that end, get the number of files from that entry
+ _stream->seek(directoryTableOffset);
uint16 fileCount = _stream->readUint16LE();
debug(2, "File count = %d", fileCount);
- _stream->skip(9);
-
- Common::Array<DirectoryEntry> directories;
-
- for (uint16 i = 0; i < fileCount;) {
- uint16 dirFileCount = _stream->readUint16LE();
+ // Following the directory table is the file table with files stored recursively
+ // by directory. Since we're only using the first directory, we can just go
+ // right to that one.
+ _stream->seek(fileTableOffset);
- if (dirFileCount == 0) {
- // We've found a file
- FileEntry entry;
+ for (uint16 i = 0; i < fileCount; i++) {
+ FileEntry entry;
- _stream->skip(1); // Unknown
+ _stream->skip(3); // Unknown
- entry.uncompressedSize = _stream->readUint32LE();
- entry.compressedSize = _stream->readUint32LE();
- entry.offset = _stream->readUint32LE();
+ entry.uncompressedSize = _stream->readUint32LE();
+ entry.compressedSize = _stream->readUint32LE();
+ entry.offset = _stream->readUint32LE();
- _stream->skip(14); // Unknown
+ _stream->skip(14); // Unknown
- byte nameLength = _stream->readByte();
- Common::String name;
- while (nameLength--)
- name += _stream->readByte();
+ byte nameLength = _stream->readByte();
+ Common::String name;
+ while (nameLength--)
+ name += _stream->readByte();
- _stream->skip(13); // Unknown
+ _stream->skip(13); // Unknown
- _map[name] = entry;
- i++;
+ _map[name] = entry;
- debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
- entry.offset, entry.compressedSize, entry.uncompressedSize);
- } else {
- // We've found a directory
- DirectoryEntry dirEntry;
-
- dirEntry.fileCount = dirFileCount;
- /* uint16 entrySize = */ _stream->readUint16LE();
-
- uint16 nameLength = _stream->readUint16LE();
- while (nameLength--)
- dirEntry.name += _stream->readByte();
-
- directories.push_back(dirEntry);
-
- _stream->skip(5); // Unknown
-
- debug(3, "Ignoring directory '%s'", dirEntry.name.c_str());
- }
+ debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
+ entry.offset, entry.compressedSize, entry.uncompressedSize);
}
- // TODO: Handle files in directories
- // Per directory found follows DirectoryEntry::fileCount files
-
return true;
}
diff --git a/engines/mohawk/installer_archive.h b/engines/mohawk/installer_archive.h
index 565b363be3..d33fbe5bcd 100644
--- a/engines/mohawk/installer_archive.h
+++ b/engines/mohawk/installer_archive.h
@@ -27,6 +27,8 @@
#include "common/scummsys.h"
#include "common/endian.h"
#include "common/file.h"
+#include "common/hash-str.h"
+#include "common/hashmap.h"
#include "common/str.h"
#ifndef MOHAWK_INSTALLER_ARCHIVE_H
diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp
index 20f7684521..2475965812 100644
--- a/engines/mohawk/livingbooks.cpp
+++ b/engines/mohawk/livingbooks.cpp
@@ -26,16 +26,22 @@
#include "mohawk/livingbooks.h"
#include "mohawk/resource.h"
#include "mohawk/cursors.h"
-#include "mohawk/sound.h"
#include "mohawk/video.h"
+#include "common/config-manager.h"
+#include "common/error.h"
#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/fs.h"
#include "common/archive.h"
+#include "common/textconsole.h"
+
+#include "graphics/palette.h"
#include "engines/util.h"
+#include "gui/message.h"
+
namespace Mohawk {
// read a null-terminated string from a stream
@@ -70,6 +76,48 @@ Common::Rect MohawkEngine_LivingBooks::readRect(Common::SeekableSubReadStreamEnd
return rect;
}
+LBPage::LBPage(MohawkEngine_LivingBooks *vm) : _vm(vm) {
+ _code = NULL;
+ _mhk = NULL;
+
+ _baseId = 0;
+ _cascade = false;
+}
+
+void LBPage::open(MohawkArchive *mhk, uint16 baseId) {
+ _mhk = mhk;
+ _baseId = baseId;
+
+ _vm->addArchive(_mhk);
+ if (_vm->hasResource(ID_BCOD, baseId))
+ _code = new LBCode(_vm, baseId);
+
+ loadBITL(baseId);
+ for (uint i = 0; i < _items.size(); i++)
+ _vm->addItem(_items[i]);
+
+ for (uint32 i = 0; i < _items.size(); i++)
+ _items[i]->init();
+}
+
+void LBPage::itemDestroyed(LBItem *item) {
+ for (uint i = 0; i < _items.size(); i++)
+ if (item == _items[i]) {
+ _items.remove_at(i);
+ return;
+ }
+ error("itemDestroyed didn't find item");
+}
+
+LBPage::~LBPage() {
+ delete _code;
+ _vm->removeItems(_items);
+ for (uint i = 0; i < _items.size(); i++)
+ delete _items[i];
+ _vm->removeArchive(_mhk);
+ delete _mhk;
+}
+
MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) {
_needsUpdate = false;
_needsRedraw = false;
@@ -80,11 +128,11 @@ MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGa
_alreadyShowedIntro = false;
- _code = NULL;
-
_rnd = new Common::RandomSource();
g_eventRec.registerRandomSource(*_rnd, "livingbooks");
+ _page = NULL;
+
const Common::FSNode gameDataDir(ConfMan.get("path"));
// Rugrats
SearchMan.addSubDirectoryMatching(gameDataDir, "program");
@@ -115,6 +163,9 @@ Common::Error MohawkEngine_LivingBooks::run() {
debug("Starting Living Books Title \'%s\'", _title.c_str());
if (!_copyright.empty())
debug("Copyright: %s", _copyright.c_str());
+ debug("This book has %d page(s) in %d language(s).", _numPages, _numLanguages);
+ if (_poetryMode)
+ debug("Running in poetry mode.");
if (!_screenWidth || !_screenHeight)
error("Could not find xRes/yRes variables");
@@ -173,8 +224,7 @@ Common::Error MohawkEngine_LivingBooks::run() {
case Common::KEYCODE_ESCAPE:
if (_curMode == kLBIntroMode)
- if (!loadPage(kLBControlMode, 1, 1))
- loadPage(kLBControlMode, 1, 0);
+ tryLoadPageStart(kLBControlMode, 1);
break;
case Common::KEYCODE_LEFT:
@@ -268,21 +318,18 @@ Common::String MohawkEngine_LivingBooks::stringForMode(LBMode mode) {
void MohawkEngine_LivingBooks::destroyPage() {
_sound->stopSound();
+ _lastSoundOwner = 0;
+ _lastSoundId = 0;
+ _soundLockOwner = 0;
+
_gfx->clearCache();
_video->stopVideos();
_eventQueue.clear();
- delete _code;
- _code = NULL;
-
- for (uint32 i = 0; i < _items.size(); i++)
- delete _items[i];
- _items.clear();
-
- for (uint32 i = 0; i < _mhk.size(); i++)
- delete _mhk[i];
- _mhk.clear();
+ delete _page;
+ assert(_items.empty());
+ _page = NULL;
_notifyEvents.clear();
@@ -300,26 +347,42 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) {
else
base = Common::String::format("Page%d", page);
- Common::String filename;
+ Common::String filename, leftover;
- filename = getFileNameFromConfig(name, base);
+ filename = getFileNameFromConfig(name, base, leftover);
_readOnly = false;
if (filename.empty()) {
- filename = getFileNameFromConfig(name, base + ".r");
+ leftover.clear();
+ filename = getFileNameFromConfig(name, base + ".r", leftover);
_readOnly = true;
}
// TODO: fading between pages
bool fade = false;
- if (filename.hasSuffix(" fade")) {
+ if (leftover.contains("fade")) {
fade = true;
- filename = Common::String(filename.c_str(), filename.size() - 5);
+ }
+ if (leftover.contains("read")) {
+ _readOnly = true;
+ }
+ if (leftover.contains("load")) {
+ // FIXME: don't ignore this
+ warning("ignoring 'load' for filename '%s'", filename.c_str());
+ }
+ if (leftover.contains("cut")) {
+ // FIXME: don't ignore this
+ warning("ignoring 'cut' for filename '%s'", filename.c_str());
+ }
+ if (leftover.contains("killgag")) {
+ // FIXME: don't ignore this
+ warning("ignoring 'killgag' for filename '%s'", filename.c_str());
}
MohawkArchive *pageArchive = createMohawkArchive();
if (!filename.empty() && pageArchive->open(filename)) {
- _mhk.push_back(pageArchive);
+ _page = new LBPage(this);
+ _page->open(pageArchive, 1000);
} else {
delete pageArchive;
debug(2, "Could not find page %d.%d for '%s'", page, subpage, name.c_str());
@@ -337,7 +400,7 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) {
}
}
- debug(1, "Stack Version: %d", getResourceVersion());
+ debug(1, "Page Version: %d", _page->getResourceVersion());
_curMode = mode;
_curPage = page;
@@ -347,13 +410,6 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) {
_gfx->setPalette(1000);
- if (hasResource(ID_BCOD, 1000))
- _code = new LBCode(this);
-
- loadBITL(1000);
- for (uint32 i = 0; i < _items.size(); i++)
- _items[i]->init();
-
_phase = 0;
_introDone = false;
@@ -378,10 +434,6 @@ void MohawkEngine_LivingBooks::updatePage() {
// hard-coded control page startup
LBItem *item;
- item = getItemById(10);
- if (item)
- item->togglePlaying(false);
-
uint16 page = _curPage;
if (getFeatures() & GF_LB_10) {
// Living Books 1.0 had the meanings of these pages reversed
@@ -473,6 +525,12 @@ void MohawkEngine_LivingBooks::updatePage() {
for (uint32 i = 0; i < _items.size(); i++)
_items[i]->startPhase(_phase);
+ if (_curMode == kLBControlMode) {
+ LBItem *item = getItemById(10);
+ if (item)
+ item->togglePlaying(false);
+ }
+
_phase++;
break;
@@ -496,7 +554,9 @@ void MohawkEngine_LivingBooks::updatePage() {
switch (delayedEvent.type) {
case kLBDelayedEventDestroy:
_items.remove_at(i);
+ i--;
delete delayedEvent.item;
+ _page->itemDestroyed(delayedEvent.item);
if (_focus == delayedEvent.item)
_focus = NULL;
break;
@@ -524,6 +584,39 @@ void MohawkEngine_LivingBooks::updatePage() {
}
}
+void MohawkEngine_LivingBooks::addArchive(MohawkArchive *archive) {
+ _mhk.push_back(archive);
+}
+
+void MohawkEngine_LivingBooks::removeArchive(MohawkArchive *archive) {
+ for (uint i = 0; i < _mhk.size(); i++) {
+ if (archive != _mhk[i])
+ continue;
+ _mhk.remove_at(i);
+ return;
+ }
+
+ error("removeArchive didn't find archive");
+}
+
+void MohawkEngine_LivingBooks::addItem(LBItem *item) {
+ _items.push_back(item);
+}
+
+void MohawkEngine_LivingBooks::removeItems(const Common::Array<LBItem *> &items) {
+ for (uint i = 0; i < items.size(); i++) {
+ bool found = false;
+ for (uint16 j = 0; j < _items.size(); j++) {
+ if (items[i] != _items[j])
+ continue;
+ found = true;
+ _items.remove_at(j);
+ break;
+ }
+ assert(found);
+ }
+}
+
LBItem *MohawkEngine_LivingBooks::getItemById(uint16 id) {
for (uint16 i = 0; i < _items.size(); i++)
if (_items[i]->getId() == id)
@@ -532,6 +625,14 @@ LBItem *MohawkEngine_LivingBooks::getItemById(uint16 id) {
return NULL;
}
+LBItem *MohawkEngine_LivingBooks::getItemByName(Common::String name) {
+ for (uint16 i = 0; i < _items.size(); i++)
+ if (_items[i]->getName() == name)
+ return _items[i];
+
+ return NULL;
+}
+
void MohawkEngine_LivingBooks::setFocus(LBItem *focus) {
_focus = focus;
}
@@ -551,12 +652,60 @@ void MohawkEngine_LivingBooks::queueDelayedEvent(DelayedEvent event) {
_eventQueue.push(event);
}
-// Only 1 VSRN resource per stack, Id 1000
-uint16 MohawkEngine_LivingBooks::getResourceVersion() {
- Common::SeekableReadStream *versionStream = getResource(ID_VRSN, 1000);
+bool MohawkEngine_LivingBooks::playSound(LBItem *source, uint16 resourceId) {
+ if (_lastSoundId && !_sound->isPlaying(_lastSoundId))
+ _lastSoundId = 0;
+
+ if (!source->isAmbient() || !_sound->isPlaying()) {
+ if (!_soundLockOwner) {
+ if (_lastSoundId && _lastSoundOwner != source->getId())
+ if (source->getSoundPriority() >= _lastSoundPriority)
+ return false;
+ } else {
+ if (_soundLockOwner != source->getId() && source->getSoundPriority() >= _maxSoundPriority)
+ return false;
+ }
+
+ if (_lastSoundId)
+ _sound->stopSound(_lastSoundId);
+
+ _lastSoundOwner = source->getId();
+ _lastSoundPriority = source->getSoundPriority();
+ }
+ _lastSoundId = resourceId;
+ _sound->playSound(resourceId);
+
+ return true;
+}
+
+void MohawkEngine_LivingBooks::lockSound(LBItem *owner, bool lock) {
+ if (!lock) {
+ _soundLockOwner = 0;
+ return;
+ }
+
+ if (_soundLockOwner || (owner->isAmbient() && _sound->isPlaying()))
+ return;
+
+ if (_lastSoundId && !_sound->isPlaying(_lastSoundId))
+ _lastSoundId = 0;
+
+ _soundLockOwner = owner->getId();
+ _maxSoundPriority = owner->getSoundPriority();
+ if (_lastSoundId && _maxSoundPriority <= _lastSoundPriority) {
+ _sound->stopSound(_lastSoundId);
+ _lastSoundId = 0;
+ }
+}
+
+// Only 1 VSRN resource per page
+uint16 LBPage::getResourceVersion() {
+ Common::SeekableReadStream *versionStream = _vm->getResource(ID_VRSN, _baseId);
+
+ // FIXME: some V2 games have very strange version entries
if (versionStream->size() != 2)
- warning("Version Record size mismatch");
+ debug(1, "Version Record size mismatch");
uint16 version = versionStream->readUint16BE();
@@ -564,40 +713,43 @@ uint16 MohawkEngine_LivingBooks::getResourceVersion() {
return version;
}
-void MohawkEngine_LivingBooks::loadBITL(uint16 resourceId) {
- Common::SeekableSubReadStreamEndian *bitlStream = wrapStreamEndian(ID_BITL, resourceId);
+void LBPage::loadBITL(uint16 resourceId) {
+ Common::SeekableSubReadStreamEndian *bitlStream = _vm->wrapStreamEndian(ID_BITL, resourceId);
while (true) {
- Common::Rect rect = readRect(bitlStream);
+ Common::Rect rect = _vm->readRect(bitlStream);
uint16 type = bitlStream->readUint16();
LBItem *res;
switch (type) {
case kLBPictureItem:
- res = new LBPictureItem(this, rect);
+ res = new LBPictureItem(_vm, this, rect);
break;
case kLBAnimationItem:
- res = new LBAnimationItem(this, rect);
+ res = new LBAnimationItem(_vm, this, rect);
break;
case kLBPaletteItem:
- res = new LBPaletteItem(this, rect);
+ res = new LBPaletteItem(_vm, this, rect);
break;
case kLBGroupItem:
- res = new LBGroupItem(this, rect);
+ res = new LBGroupItem(_vm, this, rect);
break;
case kLBSoundItem:
- res = new LBSoundItem(this, rect);
+ res = new LBSoundItem(_vm, this, rect);
break;
case kLBLiveTextItem:
- res = new LBLiveTextItem(this, rect);
+ res = new LBLiveTextItem(_vm, this, rect);
break;
case kLBMovieItem:
- res = new LBMovieItem(this, rect);
+ res = new LBMovieItem(_vm, this, rect);
+ break;
+ case kLBMiniGameItem:
+ res = new LBMiniGameItem(_vm, this, rect);
break;
default:
warning("Unknown item type %04x", type);
case 3: // often used for buttons
- res = new LBItem(this, rect);
+ res = new LBItem(_vm, this, rect);
break;
}
@@ -615,17 +767,27 @@ Common::SeekableSubReadStreamEndian *MohawkEngine_LivingBooks::wrapStreamEndian(
}
Common::String MohawkEngine_LivingBooks::getStringFromConfig(const Common::String &section, const Common::String &key) {
+ Common::String x, leftover;
+ _bookInfoFile.getKey(key, section, x);
+ Common::String tmp = removeQuotesFromString(x, leftover);
+ if (!leftover.empty())
+ warning("while parsing config key '%s' from section '%s', string '%s' was left after '%s'",
+ key.c_str(), section.c_str(), leftover.c_str(), tmp.c_str());
+ return tmp;
+}
+
+Common::String MohawkEngine_LivingBooks::getStringFromConfig(const Common::String &section, const Common::String &key, Common::String &leftover) {
Common::String x;
_bookInfoFile.getKey(key, section, x);
- return removeQuotesFromString(x);
+ return removeQuotesFromString(x, leftover);
}
int MohawkEngine_LivingBooks::getIntFromConfig(const Common::String &section, const Common::String &key) {
return atoi(getStringFromConfig(section, key).c_str());
}
-Common::String MohawkEngine_LivingBooks::getFileNameFromConfig(const Common::String &section, const Common::String &key) {
- Common::String string = getStringFromConfig(section, key);
+Common::String MohawkEngine_LivingBooks::getFileNameFromConfig(const Common::String &section, const Common::String &key, Common::String &leftover) {
+ Common::String string = getStringFromConfig(section, key, leftover);
Common::String x;
uint32 i = 0;
@@ -640,17 +802,23 @@ Common::String MohawkEngine_LivingBooks::getFileNameFromConfig(const Common::Str
return (getPlatform() == Common::kPlatformMacintosh) ? convertMacFileName(x) : convertWinFileName(x);
}
-Common::String MohawkEngine_LivingBooks::removeQuotesFromString(const Common::String &string) {
- // The last char isn't necessarily a quote, the line could have "fade" in it
- // (which is then handled in loadPage).
+Common::String MohawkEngine_LivingBooks::removeQuotesFromString(const Common::String &string, Common::String &leftover) {
+ if (string.empty())
+ return string;
- // Some versions wrap in quotations, some don't...
- Common::String tmp = string;
- for (uint32 i = 0; i < tmp.size(); i++) {
- if (tmp[i] == '\"') {
- tmp.deleteChar(i);
- i--;
- }
+ char quoteChar = string[0];
+ if (quoteChar != '\"' && quoteChar != '\'')
+ return string;
+
+ Common::String tmp;
+ bool inLeftover = false;
+ for (uint32 i = 1; i < string.size(); i++) {
+ if (inLeftover)
+ leftover += string[i];
+ else if (string[i] == quoteChar)
+ inLeftover = true;
+ else
+ tmp += string[i];
}
return tmp;
@@ -675,6 +843,8 @@ Common::String MohawkEngine_LivingBooks::convertWinFileName(const Common::String
Common::String filename;
for (uint32 i = 0; i < string.size(); i++) {
+ if (i == 0 && (string[i] == '/' || string[i] == '\\')) // ignore slashes at start
+ continue;
if (string[i] == '\\')
filename += '/';
else
@@ -713,20 +883,18 @@ bool MohawkEngine_LivingBooks::tryDefaultPage() {
if (_curMode == kLBCreditsMode || _curMode == kLBPreviewMode) {
// go to options page
if (getFeatures() & GF_LB_10) {
- if (loadPage(kLBControlMode, 2, 0))
+ if (tryLoadPageStart(kLBControlMode, 2))
return true;
} else {
- if (loadPage(kLBControlMode, 3, 0))
+ if (tryLoadPageStart(kLBControlMode, 3))
return true;
}
- } else {
- // go to menu page
- if (loadPage(kLBControlMode, 1, 1))
- return true;
- if (loadPage(kLBControlMode, 1, 0))
- return true;
}
+ // go to menu page
+ if (tryLoadPageStart(kLBControlMode, 1))
+ return true;
+
return false;
}
@@ -760,9 +928,11 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
switch (controlId) {
case 1:
if (getFeatures() & GF_LB_10) {
- loadPage(kLBControlMode, 2, 0);
+ if (!tryLoadPageStart(kLBControlMode, 2))
+ error("couldn't load options page");
} else {
- loadPage(kLBControlMode, 3, 0);
+ if (!tryLoadPageStart(kLBControlMode, 3))
+ error("couldn't load options page");
}
break;
@@ -776,7 +946,7 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
item = getItemById(199 + _curLanguage);
if (item) {
item->setVisible(true);
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
}
break;
@@ -790,15 +960,17 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
item = getItemById(12);
if (item) {
item->setVisible(true);
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
}
break;
case 4:
if (getFeatures() & GF_LB_10) {
- loadPage(kLBControlMode, 3, 0);
+ if (!tryLoadPageStart(kLBControlMode, 3))
+ error("couldn't load quit page");
} else {
- loadPage(kLBControlMode, 2, 0);
+ if (!tryLoadPageStart(kLBControlMode, 2))
+ error("couldn't load quit page");
}
break;
@@ -807,21 +979,22 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
if (item)
item->destroySelf();
item = getItemById(11);
- if (item)
+ if (item) {
item->setVisible(true);
- if (item)
item->togglePlaying(false);
+ }
break;
case 11:
item = getItemById(11);
if (item)
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
break;
case 12:
// start game, in play mode
- loadPage(kLBPlayMode, 1, 0);
+ if (!tryLoadPageStart(kLBPlayMode, 1))
+ error("couldn't start play mode");
break;
default:
@@ -835,7 +1008,8 @@ void MohawkEngine_LivingBooks::handleUIMenuClick(uint controlId) {
_curLanguage = newLanguage;
} else if (controlId >= 200 && controlId < 200 + (uint)_numLanguages) {
// start game, in read mode
- loadPage(kLBReadMode, 1, 0);
+ if (!tryLoadPageStart(kLBReadMode, 1))
+ error("couldn't start read mode");
}
break;
}
@@ -864,7 +1038,6 @@ void MohawkEngine_LivingBooks::handleUIPoetryMenuClick(uint controlId) {
break;
case 7:
- case 0xA:
item = getItemById(10);
if (item)
item->destroySelf();
@@ -874,14 +1047,25 @@ void MohawkEngine_LivingBooks::handleUIPoetryMenuClick(uint controlId) {
item = getItemById(12);
if (item) {
item->setVisible(true);
- item->togglePlaying(controlId == 7);
+ item->togglePlaying(false, true);
+ }
+ break;
+
+ case 0xA:
+ item = getItemById(10);
+ if (item)
+ item->destroySelf();
+ item = getItemById(11);
+ if (item) {
+ item->setVisible(true);
+ item->togglePlaying(false);
}
break;
case 0xB:
- item = getItemById(12);
+ item = getItemById(11);
if (item)
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
break;
case 0xC:
@@ -923,7 +1107,7 @@ void MohawkEngine_LivingBooks::handleUIQuitClick(uint controlId) {
case 11:
item = getItemById(11);
if (item)
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
break;
case 12:
@@ -933,7 +1117,8 @@ void MohawkEngine_LivingBooks::handleUIQuitClick(uint controlId) {
case 13:
// 'no', go back to menu
- loadPage(kLBControlMode, 1, 0);
+ if (!tryLoadPageStart(kLBControlMode, 1))
+ error("couldn't return to menu");
break;
}
}
@@ -949,7 +1134,7 @@ void MohawkEngine_LivingBooks::handleUIOptionsClick(uint controlId) {
item = getItemById(202);
if (item) {
item->setVisible(true);
- item->togglePlaying(true);
+ item->togglePlaying(false, true);
}
break;
@@ -994,11 +1179,13 @@ void MohawkEngine_LivingBooks::handleUIOptionsClick(uint controlId) {
break;
case 4:
- loadPage(kLBCreditsMode, 1, 0);
+ if (!tryLoadPageStart(kLBCreditsMode, 1))
+ error("failed to start credits");
break;
case 5:
- loadPage(kLBPreviewMode, 1, 0);
+ if (!tryLoadPageStart(kLBPreviewMode, 1))
+ error("failed to start preview");
break;
case 202:
@@ -1055,7 +1242,7 @@ void MohawkEngine_LivingBooks::handleNotify(NotifyEvent &event) {
case kLBNotifyGoToControls:
debug(2, "kLBNotifyGoToControls: %d", event.param);
- if (!loadPage(kLBControlMode, 1, 0))
+ if (!tryLoadPageStart(kLBControlMode, 1))
error("couldn't load controls page");
break;
@@ -1085,7 +1272,7 @@ void MohawkEngine_LivingBooks::handleNotify(NotifyEvent &event) {
case kLBNotifyGotoQuit:
debug(2, "kLBNotifyGotoQuit: %d", event.param);
- if (!loadPage(kLBControlMode, 2, 0))
+ if (!tryLoadPageStart(kLBControlMode, 2))
error("couldn't load quit page");
break;
@@ -1119,9 +1306,10 @@ void MohawkEngine_LivingBooks::handleNotify(NotifyEvent &event) {
if (!event.newMode)
event.newMode = _curMode;
if (!loadPage((LBMode)event.newMode, event.newPage, event.newSubpage)) {
- if (event.newSubpage != 0 || !loadPage((LBMode)event.newMode, event.newPage, 1))
- error("kLBNotifyChangeMode failed to move to mode %d, page %d.%d",
- event.newMode, event.newPage, event.newSubpage);
+ if (event.newPage != 0 || !loadPage((LBMode)event.newMode, _curPage, event.newSubpage))
+ if (event.newSubpage != 0 || !loadPage((LBMode)event.newMode, event.newPage, 1))
+ error("kLBNotifyChangeMode failed to move to mode %d, page %d.%d",
+ event.newMode, event.newPage, event.newSubpage);
}
}
break;
@@ -1247,11 +1435,17 @@ NodeState LBAnimationNode::update(bool seeking) {
break;
}
- assert(entry.size == 4);
- uint16 strLen = READ_BE_UINT16(entry.data + 2);
-
- if (strLen)
- error("String length for unnamed wave file");
+ Common::String cue;
+ uint pos = 2;
+ while (pos < entry.size) {
+ char in = entry.data[pos];
+ if (!in)
+ break;
+ pos++;
+ cue += in;
+ }
+ if (pos == entry.size)
+ error("Cue in sound kLBAnimOp wasn't null-terminated");
switch (entry.opcode) {
case kLBAnimOpPlaySound:
@@ -1264,7 +1458,7 @@ NodeState LBAnimationNode::update(bool seeking) {
if (seeking)
break;
debug(4, "b: WaitForSound(%0d)", soundResourceId);
- if (!_parent->soundPlaying(soundResourceId))
+ if (!_parent->soundPlaying(soundResourceId, cue))
break;
_currentEntry--;
return kLBNodeWaiting;
@@ -1597,6 +1791,11 @@ void LBAnimation::seek(uint16 pos) {
_lastTime = 0;
_currentFrame = 0;
+ if (_currentSound != 0xffff) {
+ _vm->_sound->stopSound(_currentSound);
+ _currentSound = 0xffff;
+ }
+
for (uint32 i = 0; i < _nodes.size(); i++)
_nodes[i]->reset();
@@ -1625,11 +1824,27 @@ void LBAnimation::stop() {
void LBAnimation::playSound(uint16 resourceId) {
_currentSound = resourceId;
- _vm->_sound->playSound(_currentSound);
+ _vm->_sound->playSound(_currentSound, Audio::Mixer::kMaxChannelVolume, false, &_cueList);
}
-bool LBAnimation::soundPlaying(uint16 resourceId) {
- return _currentSound == resourceId && _vm->_sound->isPlaying(_currentSound);
+bool LBAnimation::soundPlaying(uint16 resourceId, const Common::String &cue) {
+ if (_currentSound != resourceId)
+ return false;
+ if (!_vm->_sound->isPlaying(_currentSound))
+ return false;
+
+ if (cue.empty())
+ return true;
+
+ uint samples = _vm->_sound->getNumSamplesPlayed(_currentSound);
+ for (uint i = 0; i < _cueList.pointCount; i++) {
+ if (_cueList.points[i].sampleFrame > samples)
+ break;
+ if (_cueList.points[i].name == cue)
+ return false;
+ }
+
+ return true;
}
bool LBAnimation::transparentAt(int x, int y) {
@@ -1662,7 +1877,7 @@ LBScriptEntry::~LBScriptEntry() {
delete subentries[i];
}
-LBItem::LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : _vm(vm), _rect(rect) {
+LBItem::LBItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : _vm(vm), _page(page), _rect(rect) {
_phase = 0;
_loopMode = 0;
@@ -1685,6 +1900,7 @@ LBItem::LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : _vm(vm), _rect
_loops = 0;
_isAmbient = false;
+ _doHitTest = true;
}
LBItem::~LBItem() {
@@ -1785,11 +2001,17 @@ LBScriptEntry *LBItem::parseScriptEntry(uint16 type, uint16 &size, Common::Seeka
debug(4, "%d targets with targeting type %04x", count, targetingType);
// FIXME: targeting by name
+ uint oldAlign = size % 2;
for (uint i = 0; i < count; i++) {
Common::String target = _vm->readString(stream);
warning("ignoring target '%s' in script entry", target.c_str());
size -= target.size() + 1;
}
+
+ if ((uint)(size % 2) != oldAlign) {
+ stream->skip(1);
+ size--;
+ }
}
if (entry->argc) {
@@ -1810,17 +2032,19 @@ LBScriptEntry *LBItem::parseScriptEntry(uint16 type, uint16 &size, Common::Seeka
}
}
- if (type == kLBMsgListScript && entry->opcode == 0xfffb) {
- uint16 u1 = stream->readUint16();
- uint16 u2 = stream->readUint16();
- uint16 u3 = stream->readUint16();
- warning("unknown 0xfffb: %04x, %04x, %04x", u1, u2, u3);
+ if (type == kLBMsgListScript && entry->opcode == kLBOpJumpUnlessExpression) {
+ if (size < 6)
+ error("not enough bytes (%d) in kLBOpJumpUnlessExpression, event 0x%04x", size, entry->event);
+ entry->offset = stream->readUint32();
+ entry->target = stream->readUint16();
+ debug(4, "kLBOpJumpUnlessExpression: offset %08x, target %d", entry->offset, entry->target);
size -= 6;
}
- if (type == kLBMsgListScript && entry->opcode == 0xfffd) {
- uint16 u1 = stream->readUint16();
- uint16 u2 = stream->readUint16();
- warning("unknown 0xfffd: %04x, %04x", u1, u2);
+ if (type == kLBMsgListScript && entry->opcode == kLBOpJumpToExpression) {
+ if (size < 4)
+ error("not enough bytes (%d) in kLBOpJumpToExpression, event 0x%04x", size, entry->event);
+ entry->offset = stream->readUint32();
+ debug(4, "kLBOpJumpToExpression: offset %08x", entry->offset);
size -= 4;
}
@@ -1964,22 +2188,22 @@ void LBItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEnd
debug(2, "kLBSetPlayPhase: %d", _phase);
break;
- case kLBUnknown6F:
+ case kLBSetKeyNotify:
{
+ // FIXME: variable-size notifies, targets
if (size != 18)
error("0x6f had wrong size (%d)", size);
- uint u1 = stream->readUint16();
- uint u2 = stream->readUint16();
uint event = stream->readUint16();
+ LBKey key;
+ stream->read(&key, 4);
uint opcode = stream->readUint16();
uint param = stream->readUint16();
uint u6 = stream->readUint16();
uint u7 = stream->readUint16();
uint u8 = stream->readUint16();
uint u9 = stream->readUint16();
- // FIXME: this is scripting stuff
- warning("0x6f: unknown: item %s, unknowns: %04x, %04x, event %04x, opcode %04x, param %04x, unknowns %04x, %04x, %04x, %04x",
- _desc.c_str(), u1, u2, event, opcode, param, u6, u7, u8, u9);
+ warning("ignoring kLBSetKeyNotify: item %s, key code %02x (modifier mask %d, char %d, repeat %d), event %04x, opcode %04x, param %04x, unknowns %04x, %04x, %04x, %04x",
+ _desc.c_str(), key.code, key.modifiers, key.char_, key.repeats, event, opcode, param, u6, u7, u8, u9);
}
break;
@@ -2013,28 +2237,28 @@ void LBItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEnd
_isAmbient = true;
break;
- case kLBUnknown7D:
+ case kLBSetKeyEvent:
{
+ // FIXME: targets
if (size != 10)
- error("0x7d had wrong size (%d)", size);
- uint u1 = stream->readUint16();
- uint key = stream->readUint16();
+ error("kLBSetKeyEvent had wrong size (%d)", size);
uint u3 = stream->readUint16();
+ LBKey key;
+ stream->read(&key, 4);
uint target = stream->readUint16();
- byte event = stream->readByte();
- byte u4 = stream->readByte();
+ uint16 event = stream->readUint16();
// FIXME: this is scripting stuff: what to run when key is pressed
- warning("0x7d: unknown: item %s, unknown %04x, key %04x, unknown %04x, target %d, event %02x, unknown %02x",
- _desc.c_str(), u1, key, u3, target, event, u4);
+ warning("ignoring kLBSetKeyEvent: item %s, key code %02x (modifier mask %d, char %d, repeat %d) unknown %04x, target %d, event %04x",
+ _desc.c_str(), key.code, key.modifiers, key.char_, key.repeats, u3, target, event);
}
break;
- case kLBUnknown80:
+ case kLBSetHitTest:
{
assert(size == 2);
- uint id = stream->readUint16();
- warning("0x80: unknown: item %s, id %04x", _desc.c_str(), id);
- // FIXME
+ uint val = stream->readUint16();
+ _doHitTest = (bool)val;
+ debug(2, "kLBSetHitTest (on %s): value %04x", _desc.c_str(), val);
}
break;
@@ -2042,9 +2266,9 @@ void LBItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEnd
{
assert(size == 4);
uint offset = stream->readUint32();
- if (!_vm->_code)
+ if (!_page->_code)
error("no BCOD?");
- _vm->_code->runCode(this, offset);
+ _page->_code->runCode(this, offset);
}
break;
@@ -2148,7 +2372,7 @@ bool LBItem::togglePlaying(bool playing, bool restart) {
if (_controlMode >= kLBControlHideMouse) {
debug(2, "Hiding cursor");
_vm->_cursor->hideCursor();
- // TODO: lock sound?
+ _vm->lockSound(this, true);
if (_controlMode >= kLBControlPauseItems) {
debug(2, "Disabling all");
@@ -2186,7 +2410,7 @@ void LBItem::done(bool onlyNotify) {
if (_controlMode >= kLBControlHideMouse) {
debug(2, "Showing cursor");
_vm->_cursor->showCursor();
- // TODO: unlock sound?
+ _vm->lockSound(this, false);
if (_controlMode >= kLBControlPauseItems) {
debug(2, "Enabling all");
@@ -2323,9 +2547,9 @@ void LBItem::runScript(uint event, uint16 data, uint16 from) {
}
}
-void LBItem::runScriptEntry(LBScriptEntry *entry) {
+int LBItem::runScriptEntry(LBScriptEntry *entry) {
if (entry->state == 0xffff)
- return;
+ return 0;
uint start = 0;
uint count = entry->argc;
@@ -2333,7 +2557,7 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
if (!count)
count = 1;
- switch (entry->param) {
+ if (entry->opcode != kLBOpRunSubentries) switch (entry->param) {
case 0xfffe:
// Run once (disable self after run).
entry->state = 0xffff;
@@ -2350,7 +2574,7 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
case 0:
// Disable..
entry->state = 0xffff;
- return;
+ return 0;
case 1:
// Stay at the end.
entry->state = count - 1;
@@ -2388,7 +2612,7 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
debug(2, "Target %04x (%04x) doesn't exist, skipping", targetId, param);
continue;
}
- debug(2, "Target: %04x (%04x) '%s'", targetId, param, _desc.c_str());
+ debug(2, "Target: %04x (%04x) '%s'", targetId, param, target->_desc.c_str());
} else {
target = this;
debug(2, "Self-target on '%s'", _desc.c_str());
@@ -2433,7 +2657,7 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
break;
case kLBOpRewind:
- target->seek(0);
+ target->seek(1);
break;
case kLBOpStop:
@@ -2511,16 +2735,31 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
break;
case kLBOpSendExpression:
- if (!_vm->_code)
+ if (!_page->_code)
error("no BCOD?");
- _vm->_code->runCode(this, entry->offset);
+ _page->_code->runCode(this, entry->offset);
break;
case kLBOpRunSubentries:
for (uint i = 0; i < entry->subentries.size(); i++) {
LBScriptEntry *subentry = entry->subentries[i];
- runScriptEntry(subentry);
+ int e = runScriptEntry(subentry);
+
+ switch (subentry->opcode) {
+ case kLBOpJumpUnlessExpression:
+ debug(2, "JumpUnless got %d (to %d, on %d, of %d)", e, subentry->target, i, entry->subentries.size());
+ if (!e)
+ i = subentry->target - 1;
+ break;
+ case kLBOpBreakExpression:
+ debug(2, "BreakExpression");
+ i = entry->subentries.size();
+ case kLBOpJumpToExpression:
+ debug(2, "JumpToExpression got %d (on %d, of %d)", e, i, entry->subentries.size());
+ i = e - 1;
+ break;
+ }
}
break;
@@ -2528,11 +2767,24 @@ void LBItem::runScriptEntry(LBScriptEntry *entry) {
runCommand(entry->command);
break;
+ case kLBOpJumpUnlessExpression:
+ case kLBOpBreakExpression:
+ case kLBOpJumpToExpression:
+ if (!_page->_code)
+ error("no BCOD?");
+ {
+ LBValue r = _page->_code->runCode(this, entry->offset);
+ // FIXME
+ return r.integer;
+ }
+
default:
error("Unknown script opcode (type 0x%04x, event 0x%04x, opcode 0x%04x, param 0x%04x, target '%s')",
entry->type, entry->event, entry->opcode, entry->param, target->_desc.c_str());
}
}
+
+ return 0;
}
void LBItem::setNextTime(uint16 min, uint16 max) {
@@ -2544,24 +2796,6 @@ void LBItem::setNextTime(uint16 min, uint16 max, uint32 start) {
debug(9, "nextTime is now %d frames away", _nextTime - (uint)(_vm->_system->getMillis() / 16));
}
-bool LBValue::operator==(const LBValue &x) const {
- if (type != x.type) return false;
-
- switch (type) {
- case kLBValueString:
- return string == x.string;
-
- case kLBValueInteger:
- return integer == x.integer;
- default:
- error("Unknown type when testing for equality");
- }
-}
-
-bool LBValue::operator!=(const LBValue &x) const {
- return !(*this == x);
-}
-
enum LBTokenType {
kLBNoToken,
kLBNameToken,
@@ -2815,7 +3049,7 @@ bool LBItem::checkCondition(const Common::String &condition) {
return false; // unreachable
}
-LBSoundItem::LBSoundItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBSoundItem::LBSoundItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBSoundItem");
_running = false;
}
@@ -2847,7 +3081,8 @@ bool LBSoundItem::togglePlaying(bool playing, bool restart) {
return false;
_running = true;
- _vm->_sound->playSound(_resourceId, Audio::Mixer::kMaxChannelVolume, false);
+ debug(4, "sound %d play for item %d (%s)", _resourceId, _itemId, _desc.c_str());
+ _vm->playSound(this, _resourceId);
return true;
}
@@ -2860,7 +3095,7 @@ void LBSoundItem::stop() {
LBItem::stop();
}
-LBGroupItem::LBGroupItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBGroupItem::LBGroupItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBGroupItem");
_starting = false;
}
@@ -2892,6 +3127,16 @@ void LBGroupItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStre
}
}
+void LBGroupItem::destroySelf() {
+ LBItem::destroySelf();
+
+ for (uint i = 0; i < _groupEntries.size(); i++) {
+ LBItem *item = _vm->getItemById(_groupEntries[i].entryId);
+ if (item)
+ item->destroySelf();
+ }
+}
+
void LBGroupItem::setEnabled(bool enabled) {
if (_starting) {
_starting = false;
@@ -2965,7 +3210,7 @@ void LBGroupItem::stop() {
}
}
-LBPaletteItem::LBPaletteItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBPaletteItem::LBPaletteItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBPaletteItem");
_fadeInStart = 0;
@@ -3050,7 +3295,7 @@ void LBPaletteItem::update() {
LBItem::update();
}
-LBLiveTextItem::LBLiveTextItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBLiveTextItem::LBLiveTextItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
_currentPhrase = 0xFFFF;
_currentWord = 0xFFFF;
debug(3, "new LBLiveTextItem");
@@ -3232,7 +3477,7 @@ void LBLiveTextItem::handleMouseDown(Common::Point pos) {
return;
}
_currentWord = i;
- _vm->_sound->playSound(soundId);
+ _vm->playSound(this, soundId);
paletteUpdate(_currentWord, true);
return;
}
@@ -3297,7 +3542,7 @@ void LBLiveTextItem::notify(uint16 data, uint16 from) {
LBItem::notify(data, from);
}
-LBPictureItem::LBPictureItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBPictureItem::LBPictureItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBPictureItem");
}
@@ -3322,6 +3567,9 @@ bool LBPictureItem::contains(Common::Point point) {
if (!LBItem::contains(point))
return false;
+ if (!_doHitTest)
+ return true;
+
// TODO: only check pixels if necessary
return !_vm->_gfx->imageIsTransparentAt(_resourceId, false, point.x - _rect.left, point.y - _rect.top);
}
@@ -3337,7 +3585,7 @@ void LBPictureItem::draw() {
_vm->_gfx->copyAnimImageToScreen(_resourceId, _rect.left, _rect.top);
}
-LBAnimationItem::LBAnimationItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBAnimationItem::LBAnimationItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
_anim = NULL;
_running = false;
debug(3, "new LBAnimationItem");
@@ -3349,26 +3597,32 @@ LBAnimationItem::~LBAnimationItem() {
void LBAnimationItem::setEnabled(bool enabled) {
if (_running) {
- if (enabled && _neverEnabled)
+ if (enabled && _globalEnabled && _neverEnabled)
_anim->start();
else if (!_neverEnabled && !enabled && _enabled && _globalEnabled)
- if (_running) {
- _anim->stop();
- }
+ _anim->stop();
}
return LBItem::setEnabled(enabled);
}
bool LBAnimationItem::contains(Common::Point point) {
- return LBItem::contains(point) && !_anim->transparentAt(point.x, point.y);
+ if (!LBItem::contains(point))
+ return false;
+
+ if (!_doHitTest)
+ return true;
+
+ return !_anim->transparentAt(point.x, point.y);
}
void LBAnimationItem::update() {
if (!_neverEnabled && _enabled && _globalEnabled && _running) {
bool wasDone = _anim->update();
- if (wasDone)
+ if (wasDone) {
+ _running = false;
done(true);
+ }
}
LBItem::update();
@@ -3430,7 +3684,7 @@ void LBAnimationItem::draw() {
_anim->draw();
}
-LBMovieItem::LBMovieItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) {
+LBMovieItem::LBMovieItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
debug(3, "new LBMovieItem");
}
@@ -3459,4 +3713,39 @@ bool LBMovieItem::togglePlaying(bool playing, bool restart) {
return LBItem::togglePlaying(playing, restart);
}
+LBMiniGameItem::LBMiniGameItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {
+ debug(3, "new LBMiniGameItem");
+}
+
+LBMiniGameItem::~LBMiniGameItem() {
+}
+
+bool LBMiniGameItem::togglePlaying(bool playing, bool restart) {
+ // HACK: Since we don't support any of these hardcoded mini games yet,
+ // just skip to the most logical page. For optional minigames, this
+ // will return the player to the previous page. For mandatory minigames,
+ // this will send the player to the next page.
+ // TODO: Document mini games from Arthur's Reading Race
+
+ uint16 destPage;
+
+ // Figure out what minigame we have and bring us back to a page where
+ // the player can continue
+ if (_desc == "Kitch") // Green Eggs and Ham: Kitchen minigame
+ destPage = 4;
+ else if (_desc == "Eggs") // Green Eggs and Ham: Eggs minigame
+ destPage = 5;
+ else if (_desc == "Fall") // Green Eggs and Ham: Fall minigame
+ destPage = 13;
+ else
+ error("Unknown minigame '%s'", _desc.c_str());
+
+ GUI::MessageDialog dialog(Common::String::format("The '%s' minigame is not supported yet.", _desc.c_str()));
+ dialog.runModal();
+
+ _vm->addNotifyEvent(NotifyEvent(kLBNotifyChangePage, destPage));
+
+ return false;
+}
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h
index 186502d532..cd3b206d57 100644
--- a/engines/mohawk/livingbooks.h
+++ b/engines/mohawk/livingbooks.h
@@ -29,6 +29,7 @@
#include "mohawk/mohawk.h"
#include "mohawk/console.h"
#include "mohawk/graphics.h"
+#include "mohawk/sound.h"
#include "common/config-file.h"
#include "common/substream.h"
@@ -42,6 +43,17 @@
namespace Mohawk {
+#define LBKEY_MOD_CTRL 1
+#define LBKEY_MOD_ALT 2
+#define LBKEY_MOD_SHIFT 4
+
+struct LBKey {
+ byte code;
+ byte modifiers;
+ byte char_;
+ byte repeats;
+};
+
enum NodeState {
kLBNodeDone = 0,
kLBNodeRunning = 1,
@@ -88,6 +100,7 @@ enum {
kLBPaletteAItem = 0x44, // unused?
kLBPaletteItem = 0x45,
kLBProxyItem = 0x46,
+ kLBMiniGameItem = 666, // EVIL!!!!
kLBXDataFileItem = 0x3e9,
kLBDiscDectectorItem = 0xfa1
};
@@ -151,7 +164,7 @@ enum {
kLBSetOneShot = 0x6d, // unused?
kLBSetPlayPhase = 0x6e,
// from here, 2.x+
- kLBUnknown6F = 0x6f,
+ kLBSetKeyNotify = 0x6f,
kLBCommand = 0x70,
kLBPaletteAData = 0x71, // unused?
kLBPaletteXData = 0x72,
@@ -165,10 +178,10 @@ enum {
kLBGlobalSetVisible = 0x7a, // unused?
kLBSetAmbient = 0x7b,
kLBUnknown7C = 0x7c, // unused?
- kLBUnknown7D = 0x7d,
+ kLBSetKeyEvent = 0x7d,
kLBUnknown7E = 0x7e, // unused? (rect flag)
kLBSetParent = 0x7f, // unused?
- kLBUnknown80 = 0x80, // unused? TODO: sets +36
+ kLBSetHitTest = 0x80,
// from here, rugrats
kLBUnknown194 = 0x194
};
@@ -204,6 +217,9 @@ enum {
kLBOpScriptEnable = 0x1b,
kLBOpUnknown1C = 0x1c,
kLBOpSendExpression = 0x1d,
+ kLBOpJumpUnlessExpression = 0xfffb,
+ kLBOpBreakExpression = 0xfffc,
+ kLBOpJumpToExpression = 0xfffd,
kLBOpRunSubentries = 0xfffe,
kLBOpRunCommand = 0xffff
};
@@ -221,6 +237,7 @@ enum {
};
class MohawkEngine_LivingBooks;
+class LBPage;
class LBGraphics;
class LBAnimation;
@@ -251,6 +268,8 @@ struct LBScriptEntry {
// kLBOpSendExpression
uint32 offset;
+ // kLBOpJumpUnlessExpression
+ uint16 target;
Common::String command;
Common::Array<Common::String> conditions;
@@ -301,7 +320,7 @@ public:
void stop();
void playSound(uint16 resourceId);
- bool soundPlaying(uint16 resourceId);
+ bool soundPlaying(uint16 resourceId, const Common::String &cue);
bool transparentAt(int x, int y);
@@ -323,7 +342,10 @@ protected:
Common::Array<LBAnimationNode *> _nodes;
uint16 _tempo;
+
uint16 _currentSound;
+ CueList _cueList;
+
uint32 _lastTime, _currentFrame;
bool _running;
@@ -336,7 +358,7 @@ class LBItem {
friend class LBCode;
public:
- LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect);
+ LBItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect);
virtual ~LBItem();
void readFrom(Common::SeekableSubReadStreamEndian *stream);
@@ -364,9 +386,14 @@ public:
virtual void notify(uint16 data, uint16 from); // 0x1A
uint16 getId() { return _itemId; }
+ const Common::String &getName() { return _desc; }
+ const Common::Rect &getRect() { return _rect; }
+ uint16 getSoundPriority() { return _soundMode; }
+ bool isAmbient() { return _isAmbient; }
protected:
MohawkEngine_LivingBooks *_vm;
+ LBPage *_page;
void setNextTime(uint16 min, uint16 max);
void setNextTime(uint16 min, uint16 max, uint32 start);
@@ -387,10 +414,11 @@ protected:
Common::Point _relocPoint;
bool _isAmbient;
+ bool _doHitTest;
Common::Array<LBScriptEntry *> _scriptEntries;
void runScript(uint event, uint16 data = 0, uint16 from = 0);
- void runScriptEntry(LBScriptEntry *entry);
+ int runScriptEntry(LBScriptEntry *entry);
LBValue parseValue(const Common::String &command, uint &pos);
void runCommand(const Common::String &command);
@@ -401,7 +429,7 @@ protected:
class LBSoundItem : public LBItem {
public:
- LBSoundItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBSoundItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
~LBSoundItem();
void update();
@@ -419,10 +447,11 @@ struct GroupEntry {
class LBGroupItem : public LBItem {
public:
- LBGroupItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBGroupItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream);
+ void destroySelf();
void setEnabled(bool enabled);
void setGlobalEnabled(bool enabled);
bool contains(Common::Point point);
@@ -442,7 +471,7 @@ protected:
class LBPaletteItem : public LBItem {
public:
- LBPaletteItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBPaletteItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
~LBPaletteItem();
void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream);
@@ -469,7 +498,7 @@ struct LiveTextPhrase {
class LBLiveTextItem : public LBItem {
public:
- LBLiveTextItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBLiveTextItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream);
@@ -498,7 +527,7 @@ protected:
class LBPictureItem : public LBItem {
public:
- LBPictureItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBPictureItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream);
@@ -509,7 +538,7 @@ public:
class LBAnimationItem : public LBItem {
public:
- LBAnimationItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBAnimationItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
~LBAnimationItem();
void setEnabled(bool enabled);
@@ -530,15 +559,23 @@ protected:
class LBMovieItem : public LBItem {
public:
- LBMovieItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect);
+ LBMovieItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
~LBMovieItem();
void update();
bool togglePlaying(bool playing, bool restart);
};
+class LBMiniGameItem : public LBItem {
+public:
+ LBMiniGameItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect);
+ ~LBMiniGameItem();
+
+ bool togglePlaying(bool playing, bool restart);
+};
+
struct NotifyEvent {
- NotifyEvent(uint t, uint p) : type(t), param(p) { }
+ NotifyEvent(uint t, uint p) : type(t), param(p), newUnknown(0), newMode(0), newPage(0), newSubpage(0) { }
uint type;
uint param;
@@ -561,6 +598,30 @@ struct DelayedEvent {
DelayedEventType type;
};
+class LBPage {
+public:
+ LBPage(MohawkEngine_LivingBooks *vm);
+ ~LBPage();
+
+ void open(MohawkArchive *mhk, uint16 baseId);
+ uint16 getResourceVersion();
+
+ void itemDestroyed(LBItem *item);
+
+ LBCode *_code;
+
+protected:
+ MohawkEngine_LivingBooks *_vm;
+
+ MohawkArchive *_mhk;
+ Common::Array<LBItem *> _items;
+
+ uint16 _baseId;
+ bool _cascade;
+
+ void loadBITL(uint16 resourceId);
+};
+
class MohawkEngine_LivingBooks : public MohawkEngine {
protected:
Common::Error run();
@@ -581,13 +642,22 @@ public:
Common::Rect readRect(Common::SeekableSubReadStreamEndian *stream);
GUI::Debugger *getDebugger() { return _console; }
+ void addArchive(MohawkArchive *archive);
+ void removeArchive(MohawkArchive *Archive);
+ void addItem(LBItem *item);
+ void removeItems(const Common::Array<LBItem *> &items);
+
LBItem *getItemById(uint16 id);
+ LBItem *getItemByName(Common::String name);
void setFocus(LBItem *focus);
void setEnableForAll(bool enable, LBItem *except = 0);
void notifyAll(uint16 data, uint16 from);
void queueDelayedEvent(DelayedEvent event);
+ bool playSound(LBItem *source, uint16 resourceId);
+ void lockSound(LBItem *owner, bool lock);
+
bool isBigEndian() const { return getGameType() != GType_LIVINGBOOKSV1 || getPlatform() == Common::kPlatformMacintosh; }
bool isPreMohawk() const;
@@ -597,11 +667,13 @@ public:
void prevPage();
void nextPage();
- LBCode *_code;
-
// TODO: make private
Common::HashMap<Common::String, LBValue> _variables;
+ // helper functions, also used by LBProxyItem
+ Common::String getFileNameFromConfig(const Common::String &section, const Common::String &key, Common::String &leftover);
+ MohawkArchive *createMohawkArchive() const;
+
private:
LivingBooksConsole *_console;
Common::ConfigFile _bookInfoFile;
@@ -615,6 +687,7 @@ private:
LBMode _curMode;
uint16 _curPage, _curSubPage;
uint16 _phase;
+ LBPage *_page;
Common::Array<LBItem *> _items;
Common::Queue<DelayedEvent> _eventQueue;
LBItem *_focus;
@@ -622,8 +695,11 @@ private:
bool loadPage(LBMode mode, uint page, uint subpage);
void updatePage();
- uint16 getResourceVersion();
- void loadBITL(uint16 resourceId);
+ uint16 _lastSoundOwner, _lastSoundId;
+ uint16 _lastSoundPriority;
+ uint16 _soundLockOwner;
+ uint16 _maxSoundPriority;
+
void loadSHP(uint16 resourceId);
bool tryDefaultPage();
@@ -649,17 +725,14 @@ private:
bool _alreadyShowedIntro;
// String Manipulation Functions
- Common::String removeQuotesFromString(const Common::String &string);
+ Common::String removeQuotesFromString(const Common::String &string, Common::String &leftover);
Common::String convertMacFileName(const Common::String &string);
Common::String convertWinFileName(const Common::String &string);
// Configuration File Functions
Common::String getStringFromConfig(const Common::String &section, const Common::String &key);
+ Common::String getStringFromConfig(const Common::String &section, const Common::String &key, Common::String &leftover);
int getIntFromConfig(const Common::String &section, const Common::String &key);
- Common::String getFileNameFromConfig(const Common::String &section, const Common::String &key);
-
- // Platform/Version functions
- MohawkArchive *createMohawkArchive() const;
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/livingbooks_code.cpp b/engines/mohawk/livingbooks_code.cpp
index a11ac1cfe9..4237c712d9 100644
--- a/engines/mohawk/livingbooks_code.cpp
+++ b/engines/mohawk/livingbooks_code.cpp
@@ -26,20 +26,124 @@
#include "mohawk/livingbooks.h"
#include "mohawk/resource.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+
namespace Mohawk {
-LBCode::LBCode(MohawkEngine_LivingBooks *vm) : _vm(vm) {
- Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, 1000);
+bool LBValue::operator==(const LBValue &x) const {
+ if (type != x.type) {
+ if (isNumeric() && x.isNumeric())
+ return toDouble() == x.toDouble();
+ else
+ return false;
+ }
+
+ switch (type) {
+ case kLBValueString:
+ return string == x.string;
+ case kLBValueInteger:
+ return integer == x.integer;
+ case kLBValueReal:
+ return real == x.real;
+ case kLBValuePoint:
+ return point == x.point;
+ case kLBValueRect:
+ return rect == x.rect;
+ case kLBValueItemPtr:
+ return item == x.item;
+ default:
+ error("Unknown type when testing for equality");
+ }
+}
+
+bool LBValue::operator!=(const LBValue &x) const {
+ return !(*this == x);
+}
+
+bool LBValue::isNumeric() const {
+ if (type == kLBValueInteger || type == kLBValueReal)
+ return true;
+
+ // TODO: string checks
+
+ return false;
+}
+
+bool LBValue::isZero() const {
+ return toInt() == 0; // FIXME
+}
+
+Common::String LBValue::toString() const {
+ switch (type) {
+ case kLBValueString:
+ return string;
+ case kLBValueInteger:
+ return Common::String::format("%d", integer);
+ case kLBValueReal:
+ return Common::String::format("%f", real);
+ default:
+ return string; // FIXME
+ }
+}
+
+int LBValue::toInt() const {
+ return integer; // FIXME
+}
+
+double LBValue::toDouble() const {
+ return real; // FIXME
+}
+
+Common::Point LBValue::toPoint() const {
+ switch (type) {
+ case kLBValueString:
+ // FIXME
+ return Common::Point();
+ case kLBValueInteger:
+ return Common::Point(integer, integer);
+ case kLBValuePoint:
+ return point;
+ default:
+ error("failed to convert to point");
+ }
+}
+
+Common::Rect LBValue::toRect() const {
+ switch (type) {
+ case kLBValueString:
+ // FIXME
+ return Common::Rect();
+ case kLBValueInteger:
+ return Common::Rect(integer, integer, integer, integer);
+ case kLBValueRect:
+ return rect;
+ case kLBValueItemPtr:
+ return item->getRect();
+ default:
+ error("failed to convert to rect");
+ }
+}
+
+LBCode::LBCode(MohawkEngine_LivingBooks *vm, uint16 baseId) : _vm(vm) {
+ Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, baseId);
+
uint32 totalSize = bcodStream->readUint32();
if (totalSize != (uint32)bcodStream->size())
error("BCOD had size %d, but claimed to be of size %d", bcodStream->size(), totalSize);
- size = bcodStream->readUint32();
- if (size + 8 > totalSize)
- error("BCOD code was of size %d, beyond size %d", size, totalSize);
- data = new byte[size];
- bcodStream->read(data, size);
+ _size = bcodStream->readUint32();
+ if (_size + 8 > totalSize)
+ error("BCOD code was of size %d, beyond size %d", _size, totalSize);
+
+ _data = new byte[_size];
+ bcodStream->read(_data, _size);
+
uint16 pos = 0;
while (bcodStream->pos() < bcodStream->size()) {
+ if (bcodStream->pos() + 1 == bcodStream->size()) {
+ warning("ran out of bytes while reading strings");
+ break;
+ }
uint16 unknown = bcodStream->readUint16();
if (unknown != 0) {
warning("unknown was %04x, not zero, while reading strings", unknown);
@@ -48,287 +152,812 @@ LBCode::LBCode(MohawkEngine_LivingBooks *vm) : _vm(vm) {
break;
}
Common::String string = _vm->readString(bcodStream);
- strings[pos] = string;
+ _strings[pos] = string;
debug(2, "read '%s' from BCOD at 0x%04x", string.c_str(), pos);
pos += 2 + string.size() + 1;
}
}
LBCode::~LBCode() {
- delete[] data;
+ delete[] _data;
}
-Common::Array<LBValue> LBCode::readParams(LBItem *src, uint32 &offset) {
- Common::Array<LBValue> params;
+LBValue LBCode::runCode(LBItem *src, uint32 offset) {
+ // TODO: re-entrancy issues?
+ _currSource = src;
+ _currOffset = offset;
- if (offset + 1 >= size)
- error("went off the end of code");
-
- byte numParams = data[offset];
- offset++;
+ return runCode(kTokenEndOfFile);
+}
- if (!numParams) {
- debugN("()\n");
- return params;
+void LBCode::nextToken() {
+ if (_currOffset + 1 >= _size) {
+ // TODO
+ warning("went off the end of code");
+ _currToken = kTokenEndOfFile;
+ _currValue = LBValue();
+ return;
}
- byte nextToken = data[offset];
- offset++;
- if (nextToken != kLBCodeTokenOpenBracket)
- error("missing ( before code parameter list (got %02x)", nextToken);
- debugN("(");
+ _currToken = _data[_currOffset++];
- for (uint i = 0; i < numParams; i++) {
- if (i != 0) {
- nextToken = data[offset];
- offset++;
- if (nextToken != ',')
- error("missing , between code parameters (got %02x)", nextToken);
- debugN(", ");
+ // We slurp any value associated with the parameter here too, to simplify things.
+ switch (_currToken) {
+ case kTokenIdentifier:
+ {
+ uint16 offset = READ_BE_UINT16(_data + _currOffset);
+ // TODO: check string exists
+ _currValue = _strings[offset];
+ _currOffset += 2;
}
+ break;
- nextToken = data[offset];
- offset++;
-
- LBValue nextValue;
-
- switch (nextToken) {
- case kLBCodeTokenLiteral:
- {
- byte literalType = data[offset];
- offset++;
- if (literalType == kLBCodeLiteralInteger) {
- uint16 intValue = READ_BE_UINT16(data + offset);
- offset += 2;
- nextValue.type = kLBValueInteger;
- nextValue.integer = intValue;
- debugN("%d", nextValue.integer);
- } else
- error("unknown literal type %02x in code", literalType);
- }
+ case kTokenLiteral:
+ {
+ byte literalType = _data[_currOffset++];
+ switch (literalType) {
+ case kLBCodeLiteralInteger:
+ _currValue = READ_BE_UINT16(_data + _currOffset);
+ _currOffset += 2;
break;
+ default:
+ error("unknown kTokenLiteral type %02x", literalType);
+ }
+ }
+ break;
- case kLBCodeTokenString:
- {
- uint16 stringOffset = READ_BE_UINT16(data + offset);
- offset += 2;
- // TODO: check string exists
- nextValue.type = kLBValueString;
- nextValue.string = strings[stringOffset];
- debugN("\"%s\"", nextValue.string.c_str());
- }
- break;
+ case kTokenConstMode:
+ case kTokenConstEventId:
+ case 0x5e: // TODO: ??
+ case kTokenKeycode:
+ _currValue = READ_BE_UINT16(_data + _currOffset);
+ _currOffset += 2;
+ break;
- case kLBCodeTokenChar:
- {
- uint16 stringOffset = READ_BE_UINT16(data + offset);
- offset += 2;
- // TODO: check string exists
- nextValue.type = kLBValueString;
- nextValue.string = strings[stringOffset];
- debugN("'%s'", nextValue.string.c_str());
- }
- break;
+ case kTokenGeneralCommand:
+ case kTokenItemCommand:
+ case kTokenNotifyCommand:
+ case kTokenPropListCommand:
+ case kTokenRectCommand:
+ _currValue = _data[_currOffset++];
+ //_currValue = READ_BE_UINT16(_data + _currOffset);
+ //_currOffset += 2;
+ break;
- case kLBCodeTokenLong: // FIXME: wrong?
- {
- uint32 intValue = READ_BE_UINT32(data + offset);
- offset += 4;
- nextValue.type = kLBValueInteger;
- nextValue.integer = intValue;
- debugN("%d", nextValue.integer);
- }
- break;
+ case kTokenString:
+ {
+ uint16 offset = READ_BE_UINT16(_data + _currOffset);
+ // TODO: check string exists
+ _currValue = _strings[offset];
+ _currOffset += 2;
+ }
+ break;
- case 0x31:
- {
- // TODO
- uint16 intValue = READ_BE_UINT16(data + offset);
- offset += 2;
- nextValue.type = kLBValueInteger;
- nextValue.integer = intValue;
- debugN("%d", nextValue.integer);
- }
- break;
+ default:
+ _currValue = LBValue();
+ break;
+ }
+}
- case 0x4d:
- // TODO
- runCodeCommand(src, offset);
- break;
+LBValue LBCode::runCode(byte terminator) {
+ LBValue result;
- case 0x5f:
- // keycode
- nextValue.type = kLBValueInteger;
- nextValue.integer = data[offset];
- debugN("%d", nextValue.integer);
- offset++;
- offset++; // TODO
+ while (true) {
+ nextToken();
+ if (_currToken == kTokenEndOfFile)
break;
+ parseStatement();
+ if (_stack.size())
+ result = _stack.pop();
+ if (_currToken == terminator || _currToken == kTokenEndOfFile)
+ break;
+ if (_currToken != kTokenEndOfStatement && _currToken != kTokenEndOfFile)
+ error("missing EOS (got %02x)", _currToken);
+ debugN("\n");
+ }
- default:
- error("unknown token %02x in code parameter", nextToken);
- }
+ return result;
+}
- params.push_back(nextValue);
+void LBCode::parseStatement() {
+ parseComparisons();
+
+ if (_currToken != kTokenAnd && _currToken != kTokenOr)
+ return;
+ byte op = _currToken;
+ if (op == kTokenAnd)
+ debugN(" && ");
+ else
+ debugN(" || ");
+
+ nextToken();
+ parseComparisons();
+
+ LBValue val2 = _stack.pop();
+ LBValue val1 = _stack.pop();
+ bool result;
+ if (op == kTokenAnd)
+ result = !val1.isZero() && !val2.isZero();
+ else
+ result = !val1.isZero() || !val2.isZero();
+
+ debugN(" [--> %s]", result ? "true" : "false");
+ _stack.push(result);
+}
+
+void LBCode::parseComparisons() {
+ parseConcat();
+
+ if (_currToken != kTokenEquals && _currToken != kTokenLessThan && _currToken != kTokenGreaterThan &&
+ _currToken != kTokenLessThanEq && _currToken != kTokenGreaterThanEq && _currToken != kTokenNotEq)
+ return;
+ byte comparison = _currToken;
+ switch (comparison) {
+ case kTokenEquals:
+ debugN(" == ");
+ break;
+ case kTokenLessThan:
+ debugN(" < ");
+ break;
+ case kTokenGreaterThan:
+ debugN(" > ");
+ break;
+ case kTokenLessThanEq:
+ debugN(" <= ");
+ break;
+ case kTokenGreaterThanEq:
+ debugN(" >= ");
+ break;
+ case kTokenNotEq:
+ debugN(" != ");
+ break;
}
- nextToken = data[offset];
- offset++;
- if (nextToken != kLBCodeTokenCloseBracket)
- error("missing ) after code parameter list (got %02x)", nextToken);
- debugN(")");
+ nextToken();
+ parseConcat();
+
+ if (_stack.size() < 2)
+ error("comparison didn't get enough values");
+ LBValue val2 = _stack.pop();
+ LBValue val1 = _stack.pop();
+ bool result = false;
+ // FIXME: should work for non-integers!!
+ switch (comparison) {
+ case kTokenEquals:
+ result = (val1 == val2);
+ break;
+ case kTokenLessThan:
+ result = (val1.integer < val2.integer);
+ break;
+ case kTokenGreaterThan:
+ result = (val1.integer > val2.integer);
+ break;
+ case kTokenLessThanEq:
+ result = (val1.integer <= val2.integer);
+ break;
+ case kTokenGreaterThanEq:
+ result = (val1.integer >= val2.integer);
+ break;
+ case kTokenNotEq:
+ result = (val1 != val2);
+ break;
+ }
- return params;
+ debugN(" [--> %s]", result ? "true" : "false");
+ _stack.push(result);
}
-void LBCode::runCodeCommand(LBItem *src, uint32 &offset) {
- if (offset + 1 >= size)
- error("went off the end of code");
+void LBCode::parseConcat() {
+ parseArithmetic1();
- byte commandType = data[offset];
- offset++;
+ if (_currToken != kTokenConcat)
+ return;
- switch (commandType) {
- case 0x23:
- {
- debugN("setViewOrigin");
- Common::Array<LBValue> params = readParams(src, offset);
- // TODO
- }
- break;
+ debugN(" & ");
+ nextToken();
+ parseArithmetic1();
- case 0x36:
- {
- debugN("setWorld");
- Common::Array<LBValue> params = readParams(src, offset);
- // TODO
- }
- break;
+ LBValue val2 = _stack.pop();
+ LBValue val1 = _stack.pop();
+ Common::String result = val1.toString() + val2.toString();
+ debugN(" [--> \"%s\"]", result.c_str());
+ _stack.push(result);
+}
+
+void LBCode::parseArithmetic1() {
+ parseArithmetic2();
+
+ if (_currToken != kTokenMinus && _currToken != kTokenPlus)
+ return;
+
+ byte op = _currToken;
+ if (op == kTokenMinus)
+ debugN(" - ");
+ else if (op == kTokenPlus)
+ debugN(" + ");
+
+ nextToken();
+ parseArithmetic2();
+
+ LBValue val2 = _stack.pop();
+ LBValue val1 = _stack.pop();
+ LBValue result;
+ // TODO: cope with non-integers
+ if (op == kTokenMinus)
+ result = val1.toInt() - val2.toInt();
+ else
+ result = val1.toInt() + val2.toInt();
+ _stack.push(result);
+}
+
+void LBCode::parseArithmetic2() {
+ // FIXME: other math operators
+ parseMain();
+}
+
+void LBCode::parseMain() {
+ byte prefix = 0;
+ if (_currToken == kTokenMinus || _currToken == kTokenPlus) {
+ debugN("%s", _currToken == kTokenMinus ? "-" : "+");
+ prefix = _currToken;
+ nextToken();
+ }
- case 0x42:
+ switch (_currToken) {
+ case kTokenIdentifier:
+ assert(_currValue.type == kLBValueString);
{
- debugN("setPlayParams");
- Common::Array<LBValue> params = readParams(src, offset);
- if (params.size() > 8)
- error("too many parameters (%d) to setPlayParams", params.size());
- if (!params.size())
- error("no target for setPlayParams");
- LBItem *target;
- if (params[0].string.equalsIgnoreCase("self")) {
- target = src;
+ Common::String varname = _currValue.string;
+ debugN("%s", varname.c_str());
+ nextToken();
+ if (varname.equalsIgnoreCase("self")) {
+ _stack.push(LBValue(_currSource));
+ if (_currToken == kTokenAssign)
+ error("attempted assignment to self");
+ break;
+ } else if (_currToken == kTokenAssign) {
+ debugN(" = ");
+ nextToken();
+ parseStatement();
+ if (!_stack.size())
+ error("assignment failed");
+ LBValue *val = &_vm->_variables[varname];
+ *val = _stack.pop();
+ _stack.push(*val);
} else {
- error("didn't understand target '%s'", params[0].string.c_str());
+ _stack.push(_vm->_variables[varname]);
}
- // TODO: type-checking
- switch (params.size()) {
- case 8:
- target->_soundMode = params[7].integer;
- case 7:
- target->_controlMode = params[6].integer;
- case 6:
- // TODO: _relocPoint?
- case 5:
- // TODO: _periodMin/Max
- case 4:
- target->_timingMode = params[3].integer;
- case 3:
- // TODO: _delayMin/Max
- case 2:
- target->_loopMode = params[1].integer;
+ // FIXME: pre/postincrement for non-integers
+ if (_currToken == kTokenPlusPlus) {
+ debugN("++");
+ _vm->_variables[varname].integer++;
+ nextToken();
+ } else if (_currToken == kTokenMinusMinus) {
+ debugN("--");
+ _vm->_variables[varname].integer--;
+ nextToken();
}
}
break;
- case 0x50:
- {
- debugN("setKeyEvent");
- Common::Array<LBValue> params = readParams(src, offset);
- if (params.size() != 2)
- error("incorrect number of parameters (%d) to setKeyEvent", params.size());
- // FIXME: params[0] is key, params[1] is opcode id
- }
+ case kTokenLiteral:
+ case kTokenConstMode:
+ case kTokenConstEventId:
+ case 0x5e: // TODO: ??
+ case kTokenKeycode:
+ assert(_currValue.type == kLBValueInteger);
+ debugN("%d", _currValue.integer);
+ _stack.push(_currValue);
+ nextToken();
break;
- case 0x51:
- {
- debugN("setHitTest");
- Common::Array<LBValue> params = readParams(src, offset);
- if (params.size() > 2)
- error("incorrect number of parameters (%d) to setHitTest", params.size());
- // TODO
- }
+ case kTokenString:
+ assert(_currValue.type == kLBValueString);
+ debugN("\"%s\"", _currValue.string.c_str());
+ _stack.push(_currValue);
+ nextToken();
break;
- case 0x52:
- {
- debugN("key");
- Common::Array<LBValue> params = readParams(src, offset);
- // TODO
- }
+ case kTokenTrue:
+ debugN("TRUE");
+ _stack.push(true);
+ nextToken();
+ break;
+ case kTokenFalse:
+ debugN("FALSE");
+ _stack.push(false);
+ nextToken();
break;
- case 0x5E:
- {
- debugN("setPageFade");
- Common::Array<LBValue> params = readParams(src, offset);
- // TODO
- }
+ case kTokenOpenBracket:
+ debugN("(");
+ nextToken();
+ parseStatement();
+ if (_currToken != kTokenCloseBracket)
+ error("no kTokenCloseBracket (%02x), multiple entries?", _currToken);
+ debugN(")");
+ nextToken();
+ break;
+
+ case kTokenNot:
+ debugN("!");
+ nextToken();
+ // not parseStatement, ! takes predecence over logical ops
+ parseComparisons();
+ if (!_stack.size())
+ error("not op failed");
+ _stack.push(_stack.pop().isZero() ? 1 : 0);
+ break;
+
+ case kTokenGeneralCommand:
+ runGeneralCommand();
+ break;
+
+ case kTokenItemCommand:
+ runItemCommand();
+ break;
+
+ case kTokenNotifyCommand:
+ runNotifyCommand();
break;
default:
- error("unknown command %02x in code", commandType);
+ error("unknown token %02x in code", _currToken);
+ }
+
+ if (prefix) {
+ if (!_stack.size())
+ error("+/- prefix failed");
+ LBValue val = _stack.pop();
+ assert(val.isNumeric());
+ // FIXME
+ if (prefix == kTokenMinus)
+ val.integer--;
+ else
+ val.integer++;
+ _stack.push(val);
}
}
-void LBCode::runCodeItemCommand(LBItem *src, uint32 &offset) {
- if (offset + 1 >= size)
+Common::Array<LBValue> LBCode::readParams() {
+ Common::Array<LBValue> params;
+
+ if (_currOffset + 1 >= _size)
error("went off the end of code");
- byte commandType = data[offset];
- offset++;
+ byte numParams = _data[_currOffset++];
- switch (commandType) {
- case 0x1d:
- {
- debugN("setParent");
- Common::Array<LBValue> params = readParams(src, offset);
- if (params.size() > 2)
- error("incorrect number of parameters (%d) to setParent", params.size());
- // TODO
+ if (!numParams) {
+ debugN("()\n");
+ nextToken();
+ return params;
+ }
+
+ nextToken();
+ if (_currToken != kTokenOpenBracket)
+ error("missing ( before code parameter list (got %02x)", _currToken);
+ nextToken();
+ debugN("(");
+
+ for (uint i = 0; i < numParams; i++) {
+ if (i != 0) {
+ if (_currToken != ',')
+ error("missing , between code parameters (got %02x)", _currToken);
+ debugN(", ");
+ nextToken();
}
- break;
- default:
- error("unknown item command %02x in code", commandType);
+ parseStatement();
+ if (!_stack.size())
+ error("stack empty");
+ LBValue nextValue = _stack.pop();
+
+ params.push_back(nextValue);
}
+
+ if (_currToken != kTokenCloseBracket)
+ error("missing ) after code parameter list (got %02x)", _currToken);
+ nextToken();
+ debugN(")");
+
+ return params;
}
-void LBCode::runCodeNotifyCommand(LBItem *src, uint32 &offset) {
- if (offset + 1 >= size)
- error("went off the end of code");
+Common::Rect LBCode::getRectFromParams(const Common::Array<LBValue> &params) {
+ if (params.size() == 0) {
+ assert(_currSource);
+ return _currSource->getRect();
+ } else if (params.size() == 1) {
+ const LBValue &val = params[0];
+ LBItem *item = _vm->getItemByName(val.toString());
+ if (item)
+ return item->getRect();
+ else
+ return val.toRect();
+ } else
+ error("getRectFromParams got called with weird state");
+}
+
+struct CodeCommandInfo {
+ const char *name;
+ typedef void (LBCode::*CommandFunc)(const Common::Array<LBValue> &params);
+ CommandFunc func;
+};
+
+#define NUM_GENERAL_COMMANDS 129
+CodeCommandInfo generalCommandInfo[NUM_GENERAL_COMMANDS] = {
+ { "eval", 0 },
+ { "random", 0 },
+ { "stringLen", 0 },
+ { "substring", 0 },
+ { "max", 0 },
+ { "min", 0 },
+ { "abs", 0 },
+ { "getRect", &LBCode::cmdGetRect }, // also "makeRect"
+ { "makePt", 0 }, // also "makePair"
+ { "topLeft", &LBCode::cmdTopLeft },
+ { "bottomRight", &LBCode::cmdBottomRight },
+ { "mousePos", 0 },
+ { "top", &LBCode::cmdTop },
+ { "left", &LBCode::cmdLeft },
+ { "bottom", &LBCode::cmdBottom },
+ // 0x10
+ { "right", &LBCode::cmdRight },
+ { "xpos", 0 },
+ { "ypos", 0 },
+ { "playFrom", 0 },
+ { "move", 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { "setDragParams", 0 },
+ { "resetDragParams", 0 },
+ { "enableRollover", &LBCode::cmdUnimplemented /* FIXME */ },
+ { "setCursor", 0 },
+ { "width", 0 },
+ { "height", 0 },
+ { "getFrameBounds", 0 }, // also "getFrameRect"
+ { "traceRect", 0 },
+ { "sqrt", 0 },
+ // 0x20
+ { "deleteVar", 0 },
+ { "saveVars", 0 },
+ { "scriptLink", 0 },
+ { "setViewOrigin", &LBCode::cmdUnimplemented },
+ { "rectSect", 0 },
+ { "getViewOrigin", 0 },
+ { "getViewRect", 0 },
+ { "getPage", 0 },
+ { "getWorldRect", 0 },
+ { "isWorldWrap", 0 },
+ { "newList", 0 },
+ { "deleteList", 0 },
+ { "add", 0 },
+ { 0, 0 },
+ { "addAt", 0 },
+ { "getAt", 0 },
+ // 0x30
+ { 0, 0 },
+ { "getIndex", 0 },
+ { "setAt", 0 },
+ { "listLen", 0 },
+ { "deleteAt", 0 },
+ { "clearList", 0 },
+ { "setWorld", 0 },
+ { "setProperty", 0 },
+ { "getProperty", 0 },
+ { "copyList", 0 },
+ { "invoke", 0 },
+ { "exec", 0 },
+ { "return", 0 },
+ { "sendSync", 0 },
+ { "moveViewOrigin", 0 },
+ { "addToGroup", 0 },
+ // 0x40
+ { "removeFromGroup", 0 },
+ { "clearGroup", 0 },
+ { "setPlayParams", &LBCode::cmdSetPlayParams },
+ { "autoEvent", 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { "getID", 0 },
+ { "setCursorPosition", 0 },
+ { "getTime", 0 },
+ { "logWriteLn", 0 },
+ { "logWrite", 0 },
+ { "getLanguage", 0 },
+ { "setLanguage", 0 },
+ { "getSequence", 0 },
+ { "setSequence", 0 },
+ { "getFileSpec", 0 },
+ // 0x50
+ { "setKeyEvent", &LBCode::cmdSetKeyEvent },
+ { "setHitTest", &LBCode::cmdSetHitTest },
+ { "key", &LBCode::cmdKey },
+ { "deleteKeyEvent", 0 },
+ { "setDisplay", &LBCode::cmdUnimplemented },
+ { "getDisplay", 0 },
+ { 0, 0 },
+ { "lbxCreate", 0 },
+ { "lbxFunc", 0 },
+ { "waitCursor", 0 },
+ { "debugBreak", 0 },
+ { "menuItemEnable", 0 },
+ { "showChannel", 0 },
+ { "hideChannel", 0 },
+ { "setPageFade", 0 },
+ { "normalize", 0 },
+ // 0x60 (v5+)
+ { "addEvent", 0 },
+ { "setCueEvent", 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { "getName", 0 },
+ { "getProperties", 0 },
+ { "createItem", 0 },
+ { "setProperties", 0 },
+ { "alert", 0 },
+ { "getUniqueID", 0 },
+ { "isNumeric", 0 },
+ { "setKeyFocus", 0 },
+ { "getKeyFocus", 0 },
+ { "isItem", 0 },
+ { "itemHit", 0 },
+ { "getItem ", 0 },
+ // 0x70
+ { 0, 0 },
+ { "setCascade", 0 },
+ { "getCascade", 0 },
+ { "getRes", 0 },
+ { "setRes", 0 },
+ { "getFilename", 0 },
+ { "resEnumNames", 0 },
+ { "isList", 0 },
+ { "resetRect", 0 },
+ { "setVolume", 0 },
+ { "getVolume", 0 },
+ { "pause", 0 },
+ { "getTextWidth", 0 },
+ { "setItemVolume", 0 },
+ { "setSoundLoop", 0 },
+ // 0x80
+ { "setClipboard", 0 },
+ { "getResDuration", 0 }
+};
+
+void LBCode::runGeneralCommand() {
+ byte commandType = _currValue.integer;
+
+ if (commandType == 0 || commandType > NUM_GENERAL_COMMANDS)
+ error("bad command type 0x%02x in runGeneralCommand", commandType);
+
+ CodeCommandInfo &info = generalCommandInfo[commandType - 1];
+ debugN("%s", info.name);
+ Common::Array<LBValue> params = readParams();
+
+ if (!info.func)
+ error("general command '%s' (0x%02x) unimplemented", info.name, commandType);
+ (this->*(info.func))(params);
+}
+
+void LBCode::cmdUnimplemented(const Common::Array<LBValue> &params) {
+ warning("unimplemented command called");
+}
+
+void LBCode::cmdGetRect(const Common::Array<LBValue> &params) {
+ if (params.size() < 2) {
+ _stack.push(getRectFromParams(params));
+ } else if (params.size() == 2) {
+ Common::Point p1 = params[0].toPoint();
+ Common::Point p2 = params[1].toPoint();
+ _stack.push(Common::Rect(p1.x, p1.y, p2.x, p2.y));
+ } else if (params.size() == 4) {
+ _stack.push(Common::Rect(params[0].toInt(), params[1].toInt(), params[2].toInt(), params[3].toInt()));
+ } else
+ error("incorrect number of parameters (%d) to getRect", params.size());
+}
+
+void LBCode::cmdTopLeft(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to topLeft", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(Common::Point(rect.top, rect.left));
+}
+
+void LBCode::cmdBottomRight(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to bottomRight", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(Common::Point(rect.bottom, rect.right));
+}
+
+void LBCode::cmdTop(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to top", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(rect.top);
+}
+
+void LBCode::cmdLeft(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to left", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(rect.left);
+}
+
+void LBCode::cmdBottom(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to bottom", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(rect.bottom);
+}
+
+void LBCode::cmdRight(const Common::Array<LBValue> &params) {
+ if (params.size() > 1)
+ error("too many parameters (%d) to right", params.size());
+
+ Common::Rect rect = getRectFromParams(params);
+ _stack.push(rect.right);
+}
+
+void LBCode::cmdSetPlayParams(const Common::Array<LBValue> &params) {
+ if (params.size() > 8)
+ error("too many parameters (%d) to setPlayParams", params.size());
+ if (!params.size())
+ error("no target for setPlayParams");
+
+ if (params[0].type != kLBValueItemPtr)
+ error("first param to setPlayParams wasn't item");
+ LBItem *target = params[0].item;
+
+ // TODO: type-checking
+ switch (params.size()) {
+ case 8:
+ target->_soundMode = params[7].integer;
+ case 7:
+ target->_controlMode = params[6].integer;
+ case 6:
+ // TODO: _relocPoint?
+ case 5:
+ // TODO: _periodMin/Max
+ case 4:
+ target->_timingMode = params[3].integer;
+ case 3:
+ // TODO: _delayMin/Max
+ case 2:
+ target->_loopMode = params[1].integer;
+ }
+}
+
+void LBCode::cmdSetKeyEvent(const Common::Array<LBValue> &params) {
+ if (params.size() != 2)
+ error("incorrect number of parameters (%d) to setKeyEvent", params.size());
+
+ // FIXME: params[0] is key, params[1] is opcode id
+ warning("ignoring setKeyEvent");
+}
+
+void LBCode::cmdSetHitTest(const Common::Array<LBValue> &params) {
+ if (params.size() > 2)
+ error("incorrect number of parameters (%d) to setHitTest", params.size());
+ warning("ignoring setHitTest");
+}
+
+void LBCode::cmdKey(const Common::Array<LBValue> &params) {
+ _stack.push(0); // FIXME
+ warning("ignoring Key");
+}
+
+#define NUM_ITEM_COMMANDS 34
+CodeCommandInfo itemCommandInfo[NUM_ITEM_COMMANDS] = {
+ { "clone", 0 },
+ { "destroy", 0 },
+ { "dragBeginFrom", 0 },
+ { "dragEnd", 0 },
+ { "enableLocal", 0 },
+ { "enable", 0 },
+ { "showLocal", 0 },
+ { "show", 0 },
+ { "getFrame", 0 },
+ { "getParent", 0 },
+ { "getPosition" , 0 },
+ { "getText", 0 },
+ { "getZNext", 0 },
+ { "getZPrev", 0 },
+ { "hitTest", 0 },
+ // 0x10
+ { "isAmbient", 0 },
+ { "isEnabled", 0 },
+ { "isMuted", 0 },
+ { "isPlaying", &LBCode::itemIsPlaying },
+ { "isVisible", 0 },
+ { "isLoaded", 0 },
+ { "isDragging", 0 },
+ { "load", 0 },
+ { "moveTo", 0 },
+ { "mute", 0 },
+ { "play", 0 },
+ { "seek", 0 },
+ { "seekToFrame", 0 },
+ { "setParent", &LBCode::itemSetParent },
+ { "setZOrder", 0 },
+ { "setText", 0 },
+ // 0x20
+ { "stop", 0 },
+ { "unload", 0 },
+ { "unloadSync", 0}
+};
+
+void LBCode::runItemCommand() {
+ byte commandType = _currValue.integer;
+
+ if (commandType == 0 || commandType > NUM_ITEM_COMMANDS)
+ error("bad command type 0x%02x in runItemCommand", commandType);
+
+ CodeCommandInfo &info = itemCommandInfo[commandType - 1];
+ debugN("%s", info.name);
+ Common::Array<LBValue> params = readParams();
+
+ if (!info.func)
+ error("item command '%s' (0x%02x) unimplemented", info.name, commandType);
+ (this->*(info.func))(params);
+}
- byte commandType = data[offset];
- offset++;
+void LBCode::itemIsPlaying(const Common::Array<LBValue> &params) {
+ // TODO
+ warning("ignoring isPlaying");
+ _stack.push(0);
+}
+
+void LBCode::itemSetParent(const Common::Array<LBValue> &params) {
+ if (params.size() > 2)
+ error("incorrect number of parameters (%d) to setParent", params.size());
+ // TODO
+ warning("ignoring setParent");
+}
+
+void LBCode::runNotifyCommand() {
+ byte commandType = _currValue.integer;
switch (commandType) {
case kLBNotifyChangePage:
{
debugN("goto");
- Common::Array<LBValue> params = readParams(src, offset);
+ Common::Array<LBValue> params = readParams();
// TODO: type-checking
+ NotifyEvent notifyEvent(kLBNotifyChangePage, 0);
switch (params.size()) {
- case 1:
- _vm->addNotifyEvent(NotifyEvent(kLBNotifyChangePage, params[0].integer));
+ case 4:
+ notifyEvent.type = kLBNotifyChangeMode; // FIXME: type 8?
+ notifyEvent.newUnknown = params[0].integer; // FIXME: this is newLanguage
+ notifyEvent.newMode = params[1].integer;
+ notifyEvent.newPage = params[2].integer;
+ notifyEvent.newSubpage = params[3].integer;
break;
case 2:
- // FIXME
- case 4:
- // FIXME
+ notifyEvent.type = kLBNotifyChangeMode;
+ // FIXME: newPage and newSubpage?
+ error("can't handle goto with 2 params");
+ break;
+
+ case 1:
+ notifyEvent.param = params[0].integer;
+ break;
+
+ case 0:
+ // FIXME: use cur page?
+ error("can't handle goto with 0 params");
+ break;
default:
error("incorrect number of parameters (%d) to goto", params.size());
}
+ _vm->addNotifyEvent(notifyEvent);
}
break;
@@ -336,7 +965,7 @@ void LBCode::runCodeNotifyCommand(LBItem *src, uint32 &offset) {
case kLBNotifyGotoQuit:
{
debugN(commandType == kLBNotifyGoToControls ? "gotocontrol" : "gotoquit");
- Common::Array<LBValue> params = readParams(src, offset);
+ Common::Array<LBValue> params = readParams();
if (params.size() != 0)
error("incorrect number of parameters (%d) to notify", params.size());
_vm->addNotifyEvent(NotifyEvent(commandType, 0));
@@ -346,61 +975,25 @@ void LBCode::runCodeNotifyCommand(LBItem *src, uint32 &offset) {
case kLBNotifyIntroDone:
{
debugN("startphasemain");
- Common::Array<LBValue> params = readParams(src, offset);
+ Common::Array<LBValue> params = readParams();
if (params.size() != 0)
error("incorrect number of parameters (%d) to startphasemain", params.size());
_vm->addNotifyEvent(NotifyEvent(kLBNotifyIntroDone, 1));
}
break;
- default:
- error("unknown notify command %02x in code", commandType);
- }
-}
-
-void LBCode::runCode(LBItem *src, uint32 offset) {
- while (true) {
- if (offset + 1 >= size) {
- warning("went off the end of code");
- return;
- }
-
- byte tokenType = data[offset];
- offset++;
-
- switch (tokenType) {
- case 0x01: // FIXME
- case kLBCodeTokenEndOfFile:
- return;
-
- case 0x4D:
- runCodeCommand(src, offset);
- break;
-
- case 0x4E:
- runCodeItemCommand(src, offset);
- break;
-
- case 0x4F:
- runCodeNotifyCommand(src, offset);
- break;
-
- default:
- debugN("at %04x: %02x ", offset - 1, tokenType);
- for (uint i = 0; i < size; i++)
- debugN("%02x ", data[offset++]);
- debugN("\n");
- error("unknown token %02x in code", tokenType);
+ case kLBNotifyQuit:
+ {
+ debugN("quit");
+ Common::Array<LBValue> params = readParams();
+ if (params.size() != 0)
+ error("incorrect number of parameters (%d) to quit", params.size());
+ _vm->addNotifyEvent(NotifyEvent(kLBNotifyQuit, 0));
}
+ break;
- byte nextToken = data[offset];
- offset++;
- if (nextToken != kLBCodeTokenEndOfStatement)
- warning("missing EndOfStatement after code statement (got %04x)", nextToken);
- if (nextToken == kLBCodeTokenEndOfFile)
- return;
-
- debugN("\n");
+ default:
+ error("unknown notify command %02x in code", commandType);
}
}
diff --git a/engines/mohawk/livingbooks_code.h b/engines/mohawk/livingbooks_code.h
index 7960e79035..cd9ac1004a 100644
--- a/engines/mohawk/livingbooks_code.h
+++ b/engines/mohawk/livingbooks_code.h
@@ -26,6 +26,8 @@
#ifndef MOHAWK_LIVINGBOOKS_CODE_H
#define MOHAWK_LIVINGBOOKS_CODE_H
+#include "common/rect.h"
+#include "common/stack.h"
#include "common/substream.h"
namespace Mohawk {
@@ -35,18 +37,81 @@ class LBItem;
enum LBValueType {
kLBValueString,
- kLBValueInteger
+ kLBValueInteger,
+ kLBValueReal,
+ kLBValuePoint,
+ kLBValueRect,
+ kLBValueItemPtr
};
struct LBValue {
- LBValue() { type = kLBValueInteger; integer = 0; }
+ LBValue() {
+ type = kLBValueInteger;
+ integer = 0;
+ }
+ LBValue(int val) {
+ type = kLBValueInteger;
+ integer = val;
+ }
+ LBValue(const Common::String &str) {
+ type = kLBValueString;
+ string = str;
+ }
+ LBValue(const Common::Point &p) {
+ type = kLBValuePoint;
+ point = p;
+ }
+ LBValue(const Common::Rect &r) {
+ type = kLBValueRect;
+ rect = r;
+ }
+ LBValue(LBItem *itm) {
+ type = kLBValueItemPtr;
+ item = itm;
+ }
+ LBValue(const LBValue &val) {
+ type = val.type;
+ switch (type) {
+ case kLBValueString:
+ string = val.string;
+ break;
+ case kLBValueInteger:
+ integer = val.integer;
+ break;
+ case kLBValueReal:
+ real = val.real;
+ break;
+ case kLBValuePoint:
+ point = val.point;
+ break;
+ case kLBValueRect:
+ rect = val.rect;
+ break;
+ case kLBValueItemPtr:
+ item = val.item;
+ break;
+ }
+ }
LBValueType type;
Common::String string;
int integer;
+ double real;
+ Common::Point point;
+ Common::Rect rect;
+ LBItem *item;
bool operator==(const LBValue &x) const;
bool operator!=(const LBValue &x) const;
+
+ bool isNumeric() const;
+ bool isZero() const;
+
+ Common::String toString() const;
+ int toInt() const;
+ double toDouble() const;
+ Common::Point toPoint() const;
+ Common::Rect toRect() const;
};
enum {
@@ -54,39 +119,119 @@ enum {
};
enum {
- kLBCodeTokenString = 0x1,
- kLBCodeTokenLiteral = 0x5,
- kLBCodeTokenChar = 0x6,
- kLBCodeTokenEndOfStatement = 0x7,
- kLBCodeTokenEndOfFile = 0x8,
- kLBCodeTokenOpenBracket = 0xf,
- kLBCodeTokenCloseBracket = 0x10,
- kLBCodeTokenLong = 0x11,
-
- kLBCodeTokenEquals = 0x22, // TODO: maybe..
- kLBCodeTokenQuote = 0x27, // "'"
- kLBCodeTokenComma = 0x2c // ","
+ kTokenIdentifier = 0x1,
+ kTokenLiteral = 0x5,
+ kTokenString = 0x6,
+ kTokenEndOfStatement = 0x7,
+ kTokenEndOfFile = 0x8,
+ kTokenConcat = 0xb,
+ kTokenSingleQuote = 0xc, // ??
+ kTokenDoubleQuote = 0xd, // ??
+ kTokenMultiply = 0xe,
+ kTokenOpenBracket = 0xf,
+ kTokenCloseBracket = 0x10,
+ kTokenMinus = 0x11,
+ kTokenMinusMinus = 0x12,
+ kTokenPlusEquals = 0x13,
+ kTokenPlus = 0x14,
+ kTokenPlusPlus = 0x15,
+ kTokenEquals = 0x16,
+ kTokenMinusEquals = 0x17,
+ kTokenMultiplyEquals = 0x18,
+ kTokenDivideEquals = 0x19,
+ kTokenListStart = 0x1a,
+ kTokenListEnd = 0x1b,
+ kTokenColon = 0x1c, // ??
+ kTokenLessThan = 0x1d,
+ kTokenGreaterThan = 0x1e,
+ kTokenAndEquals = 0x1f,
+ kTokenDotOperator = 0x20,
+ kTokenDivide = 0x21,
+ kTokenAssign = 0x22,
+ kTokenLessThanEq = 0x23,
+ kTokenGreaterThanEq = 0x24,
+ kTokenNotEq = 0x25,
+ kTokenQuote = 0x27, // ??
+ kTokenAnd = 0x2a,
+ kTokenComma = 0x2c,
+ kTokenConstMode = 0x31,
+ kTokenIntDivide = 0x32,
+ kTokenModulo = 0x34,
+ kTokenNot = 0x35,
+ kTokenOr = 0x37,
+ kTokenTrue = 0x39,
+ kTokenFalse = 0x3a,
+ kTokenConstDataType = 0x3b, // ??
+ kTokenConstItemType = 0x3c, // ??
+ kTokenConstEventId = 0x42,
+ kTokenConstScriptOpcode = 0x43, // ??
+ kTokenConstScriptParam = 0x44, // ??
+ kTokenGeneralCommand = 0x4d,
+ kTokenItemCommand = 0x4e,
+ kTokenNotifyCommand = 0x4f,
+ // 0x5e?!
+ kTokenKeycode = 0x5f,
+
+ // v5 only:
+ kTokenLocal = 0x61,
+ kTokenPropListCommand = 0x70,
+ kTokenRectCommand = 0x71
};
class LBCode {
public:
- LBCode(MohawkEngine_LivingBooks *vm);
+ LBCode(MohawkEngine_LivingBooks *vm, uint16 baseId);
~LBCode();
- void runCode(LBItem *src, uint32 offset);
+ LBValue runCode(LBItem *src, uint32 offset);
protected:
MohawkEngine_LivingBooks *_vm;
- uint32 size;
- byte *data;
+ uint32 _size;
+ byte *_data;
+ Common::HashMap<uint16, Common::String> _strings;
+
+ uint32 _currOffset;
+ LBItem *_currSource;
+
+ Common::Stack<LBValue> _stack;
+ byte _currToken;
+ LBValue _currValue;
- Common::HashMap<uint16, Common::String> strings;
+ void nextToken();
- Common::Array<LBValue> readParams(LBItem *src, uint32 &offset);
- void runCodeCommand(LBItem *src, uint32 &offset);
- void runCodeItemCommand(LBItem *src, uint32 &offset);
- void runCodeNotifyCommand(LBItem *src, uint32 &offset);
+ LBValue runCode(byte terminator);
+ void parseStatement();
+ void parseComparisons();
+ void parseConcat();
+ void parseArithmetic1();
+ void parseArithmetic2();
+ void parseMain();
+
+ Common::Array<LBValue> readParams();
+ Common::Rect getRectFromParams(const Common::Array<LBValue> &params);
+
+ void runGeneralCommand();
+ void runItemCommand();
+ void runNotifyCommand();
+
+public:
+ void cmdUnimplemented(const Common::Array<LBValue> &params);
+ void cmdGetRect(const Common::Array<LBValue> &params);
+ void cmdTopLeft(const Common::Array<LBValue> &params);
+ void cmdBottomRight(const Common::Array<LBValue> &params);
+ void cmdTop(const Common::Array<LBValue> &params);
+ void cmdLeft(const Common::Array<LBValue> &params);
+ void cmdBottom(const Common::Array<LBValue> &params);
+ void cmdRight(const Common::Array<LBValue> &params);
+ void cmdSetPlayParams(const Common::Array<LBValue> &params);
+ void cmdSetKeyEvent(const Common::Array<LBValue> &params);
+ void cmdSetHitTest(const Common::Array<LBValue> &params);
+ void cmdKey(const Common::Array<LBValue> &params);
+
+ void itemSetParent(const Common::Array<LBValue> &params);
+ void itemIsPlaying(const Common::Array<LBValue> &params);
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk
index 8c4453e155..30f1d40fdb 100644
--- a/engines/mohawk/module.mk
+++ b/engines/mohawk/module.mk
@@ -3,11 +3,6 @@ MODULE := engines/mohawk
MODULE_OBJS = \
bitmap.o \
console.o \
- cstime.o \
- cstime_cases.o \
- cstime_game.o \
- cstime_ui.o \
- cstime_view.o \
cursors.o \
detection.o \
dialogs.o \
@@ -16,20 +11,27 @@ MODULE_OBJS = \
livingbooks.o \
livingbooks_code.o \
mohawk.o \
+ resource.o \
+ sound.o \
+ video.o \
+ view.o
+
+ifdef ENABLE_CSTIME
+MODULE_OBJS += \
+ cstime.o \
+ cstime_cases.o \
+ cstime_game.o \
+ cstime_ui.o \
+ cstime_view.o
+endif
+
+ifdef ENABLE_MYST
+MODULE_OBJS += \
myst.o \
myst_areas.o \
myst_scripts.o \
myst_state.o \
- resource.o \
resource_cache.o \
- riven.o \
- riven_external.o \
- riven_saveload.o \
- riven_scripts.o \
- riven_vars.o \
- sound.o \
- video.o \
- view.o \
myst_stacks/channelwood.o \
myst_stacks/credits.o \
myst_stacks/demo.o \
@@ -42,6 +44,16 @@ MODULE_OBJS = \
myst_stacks/selenitic.o \
myst_stacks/slides.o \
myst_stacks/stoneship.o
+endif
+
+ifdef ENABLE_RIVEN
+MODULE_OBJS += \
+ riven.o \
+ riven_external.o \
+ riven_saveload.o \
+ riven_scripts.o \
+ riven_vars.o
+endif
# This module can be built as a plugin
ifeq ($(ENABLE_MOHAWK), DYNAMIC_PLUGIN)
diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp
index a3db630c6a..f63645f1ac 100644
--- a/engines/mohawk/mohawk.cpp
+++ b/engines/mohawk/mohawk.cpp
@@ -24,13 +24,9 @@
*/
#include "common/scummsys.h"
-#include "common/config-manager.h"
-#include "common/file.h"
-#include "common/events.h"
-#include "common/keyboard.h"
-
-#include "base/plugins.h"
-#include "base/version.h"
+#include "common/error.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "mohawk/mohawk.h"
#include "mohawk/cursors.h"
@@ -46,8 +42,8 @@ MohawkEngine::MohawkEngine(OSystem *syst, const MohawkGameDescription *gamedesc)
if (!_mixer->isReady())
error ("Sound initialization failed");
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ // Setup mixer
+ syncSoundSettings();
_sound = 0;
_video = 0;
diff --git a/engines/mohawk/mohawk.h b/engines/mohawk/mohawk.h
index 1bad8a08ce..8a853d151e 100644
--- a/engines/mohawk/mohawk.h
+++ b/engines/mohawk/mohawk.h
@@ -34,7 +34,7 @@
class OSystem;
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
/**
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index f842269893..655a38b578 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -25,7 +25,9 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
+#include "common/system.h"
#include "common/translation.h"
+#include "common/textconsole.h"
#include "mohawk/cursors.h"
#include "mohawk/graphics.h"
@@ -1143,20 +1145,6 @@ void MohawkEngine_Myst::loadResources() {
delete rlstStream;
}
-void MohawkEngine_Myst::runLoadDialog() {
- const Common::String gameId = ConfMan.get("gameid");
-
- const EnginePlugin *plugin = 0;
- EngineMan.findGame(gameId, &plugin);
-
- pauseEngine(true);
- int slot = _loadDialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
- if (slot >= 0) {
- // TODO
- }
- pauseEngine(false);
-}
-
Common::Error MohawkEngine_Myst::loadGameState(int slot) {
if (_gameState->load(_gameState->generateSaveGameList()[slot]))
return Common::kNoError;
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 919509384b..47e8a6562c 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -155,8 +155,6 @@ public:
Common::String wrapMovieFilename(const Common::String &movieName, uint16 stack);
void reloadSaveList();
- void runLoadDialog();
- void runSaveDialog();
void changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound);
void changeToCard(uint16 card, bool updateScreen);
diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp
index 21f6627f60..dc00bff923 100644
--- a/engines/mohawk/myst_areas.cpp
+++ b/engines/mohawk/myst_areas.cpp
@@ -29,6 +29,10 @@
#include "mohawk/sound.h"
#include "mohawk/video.h"
+#include "common/events.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+
namespace Mohawk {
MystResource::MystResource(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) {
diff --git a/engines/mohawk/myst_areas.h b/engines/mohawk/myst_areas.h
index 66430f2068..aa06d1a5b4 100644
--- a/engines/mohawk/myst_areas.h
+++ b/engines/mohawk/myst_areas.h
@@ -233,6 +233,7 @@ public:
void drawFrame(uint16 frame);
bool pullLeverV();
void releaseLeverV();
+ uint16 getNumFrames() { return _numFrames; }
protected:
uint16 _numFrames;
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index 17a2c66091..71c408ed37 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -31,6 +31,8 @@
#include "mohawk/sound.h"
#include "mohawk/video.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "gui/message.h"
namespace Mohawk {
diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp
index 26267cfbda..cba2583a50 100644
--- a/engines/mohawk/myst_stacks/channelwood.cpp
+++ b/engines/mohawk/myst_stacks/channelwood.cpp
@@ -32,7 +32,9 @@
#include "mohawk/video.h"
#include "mohawk/myst_stacks/channelwood.h"
-#include "gui/message.h"
+#include "common/events.h"
+#include "common/system.h"
+#include "common/textconsole.h"
namespace Mohawk {
namespace MystStacks {
diff --git a/engines/mohawk/myst_stacks/credits.cpp b/engines/mohawk/myst_stacks/credits.cpp
index 61772eda4d..bb8397fd09 100644
--- a/engines/mohawk/myst_stacks/credits.cpp
+++ b/engines/mohawk/myst_stacks/credits.cpp
@@ -30,6 +30,7 @@
#include "mohawk/video.h"
#include "mohawk/myst_stacks/credits.h"
+#include "common/system.h"
#include "gui/message.h"
namespace Mohawk {
diff --git a/engines/mohawk/myst_stacks/dni.cpp b/engines/mohawk/myst_stacks/dni.cpp
index ffbf9c991f..e2a11eb94f 100644
--- a/engines/mohawk/myst_stacks/dni.cpp
+++ b/engines/mohawk/myst_stacks/dni.cpp
@@ -31,6 +31,8 @@
#include "mohawk/video.h"
#include "mohawk/myst_stacks/dni.h"
+#include "common/system.h"
+
namespace Mohawk {
namespace MystStacks {
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index 0ae9078974..c5c11026f5 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "mohawk/cursors.h"
#include "mohawk/myst.h"
#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
@@ -31,7 +32,8 @@
#include "mohawk/video.h"
#include "mohawk/myst_stacks/mechanical.h"
-#include "gui/message.h"
+#include "common/events.h"
+#include "common/system.h"
namespace Mohawk {
namespace MystStacks {
@@ -54,9 +56,12 @@ void Mechanical::setupOpcodes() {
OPCODE(100, o_throneEnablePassage);
OPCODE(104, o_snakeBoxTrigger);
OPCODE(105, o_fortressStaircaseMovie);
- OPCODE(121, opcode_121);
- OPCODE(122, opcode_122);
- OPCODE(123, opcode_123);
+ OPCODE(106, o_elevatorRotationStart);
+ OPCODE(107, o_elevatorRotationMove);
+ OPCODE(108, o_elevatorRotationStop);
+ OPCODE(121, o_elevatorWindowMovie);
+ OPCODE(122, o_elevatorGoMiddle);
+ OPCODE(123, o_elevatorTopMovie);
OPCODE(124, opcode_124);
OPCODE(125, o_mystStaircaseMovie);
OPCODE(126, opcode_126);
@@ -72,28 +77,34 @@ void Mechanical::setupOpcodes() {
OPCODE(201, o_fortressStaircase_init);
OPCODE(202, opcode_202);
OPCODE(203, o_snakeBox_init);
- OPCODE(204, opcode_204);
+ OPCODE(204, o_elevatorRotation_init);
OPCODE(205, opcode_205);
OPCODE(206, opcode_206);
OPCODE(209, opcode_209);
// "Exit" Opcodes
- OPCODE(300, opcode_300);
+ OPCODE(300, NOP);
}
#undef OPCODE
void Mechanical::disablePersistentScripts() {
opcode_202_disable();
- opcode_204_disable();
opcode_205_disable();
opcode_206_disable();
opcode_209_disable();
+ _elevatorGoingMiddle = false;
}
void Mechanical::runPersistentScripts() {
opcode_202_run();
- opcode_204_run();
+
+ if (_elevatorRotationLeverMoving)
+ elevatorRotation_run();
+
+ if (_elevatorGoingMiddle)
+ elevatorGoMiddle_run();
+
opcode_205_run();
opcode_206_run();
opcode_209_run();
@@ -131,13 +142,15 @@ uint16 Mechanical::getVar(uint16 var) {
return _state.staircaseState;
case 11: // Fortress Elevator Rotation Position
return _state.elevatorRotation;
-// case 12: // Fortress Elevator Rotation Cog Position
-// return 0;
-// return 1;
-// return 2;
-// return 3;
-// return 4;
-// return 5;
+ case 12: // Fortress Elevator Rotation Cog Position
+ return 5 - (uint16)(_elevatorRotationGearPosition + 0.5) % 6;
+ case 13: // Elevator position
+ return _elevatorPosition;
+ case 14: // Elevator going down when at top
+ if (_elevatorGoingDown && _elevatorTooLate)
+ return 2;
+ else
+ return _elevatorGoingDown;
case 15: // Code Lock Execute Button Script
if (_mystStaircaseState)
return 0;
@@ -184,6 +197,9 @@ void Mechanical::toggleVar(uint16 var) {
case 19: // Code Lock Shape #4 - Right
_state.codeShape[var - 16] = (_state.codeShape[var - 16] + 1) % 10;
break;
+ case 23: // Elevator player is in cabin
+ _elevatorInCabin = false;
+ break;
case 102: // Red page
if (!(_globals.redPagesInBook & 4)) {
if (_globals.heldPage == 9)
@@ -210,6 +226,11 @@ bool Mechanical::setVarValue(uint16 var, uint16 value) {
bool refresh = false;
switch (var) {
+ case 13:
+ _elevatorPosition = value;
+ case 14: // Elevator going down when at top
+ _elevatorGoingDown = value;
+ break;
default:
refresh = MystScriptParser::setVarValue(var, value);
break;
@@ -245,47 +266,165 @@ void Mechanical::o_fortressStaircaseMovie(uint16 op, uint16 var, uint16 argc, ui
_vm->_video->waitUntilMovieEnds(staircase);
}
+void Mechanical::o_elevatorRotationStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator rotation lever start", op);
-void Mechanical::opcode_121(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ lever->drawFrame(0);
- if (argc == 2) {
- uint16 startTime = argv[0];
- uint16 endTime = argv[1];
+ _elevatorRotationLeverMoving = true;
+ _elevatorRotationSpeed = 0;
- warning("TODO: Opcode %d Movie Time Index %d to %d\n", op, startTime, endTime);
- // TODO: Need version of playMovie blocking which allows selection
- // of start and finish points.
- _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("ewindow", kMechanicalStack), 253, 0);
- } else
- unknown(op, var, argc, argv);
+ _vm->_sound->stopBackgroundMyst();
+
+ _vm->_cursor->setCursor(700);
}
-void Mechanical::opcode_122(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- if (argc == 0) {
- // Used on Card 6120 (Elevator)
- // Called when Exit Midde Button Pressed
+void Mechanical::o_elevatorRotationMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator rotation lever move", op);
- // TODO: hcelev? Movie of Elevator?
- } else
- unknown(op, var, argc, argv);
+ const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+
+ // Make the handle follow the mouse
+ int16 maxStep = lever->getNumFrames() - 1;
+ Common::Rect rect = lever->getRect();
+ int16 step = ((rect.bottom - mouse.y) * lever->getNumFrames()) / rect.height();
+ step = CLIP<int16>(step, 0, maxStep);
+
+ _elevatorRotationSpeed = step * 0.1;
+
+ // Draw current frame
+ lever->drawFrame(step);
}
-void Mechanical::opcode_123(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Mechanical::o_elevatorRotationStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator rotation lever stop", op);
- if (argc == 2) {
- // Used on Card 6154
- uint16 start_time = argv[0];
- uint16 end_time = argv[1];
+ const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
- warning("TODO: Opcode %d Movie Time Index %d to %d\n", op, start_time, end_time);
- // TODO: Need version of playMovie blocking which allows selection
- // of start and finish points.
- // TODO: Not 100% sure about movie position
- _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("hcelev", kMechanicalStack), 205, 40);
- } else
- unknown(op, var, argc, argv);
+ // Get current lever frame
+ int16 maxStep = lever->getNumFrames() - 1;
+ Common::Rect rect = lever->getRect();
+ int16 step = ((rect.bottom - mouse.y) * lever->getNumFrames()) / rect.height();
+ step = CLIP<int16>(step, 0, maxStep);
+
+ // Release lever
+ for (int i = step; i >= 0; i--) {
+ lever->drawFrame(i);
+ _vm->_system->delayMillis(10);
+ }
+
+ // Stop persistent script
+ _elevatorRotationLeverMoving = false;
+
+ float speed = _elevatorRotationSpeed * 10;
+
+ if (speed > 0) {
+
+ // Decrease speed
+ while (speed > 2) {
+ speed -= 0.5;
+
+ _elevatorRotationGearPosition += speed * 0.1;
+
+ if (_elevatorRotationGearPosition > 12)
+ break;
+
+ _vm->redrawArea(12);
+ _vm->_system->delayMillis(100);
+ }
+
+ // Increment position
+ _state.elevatorRotation = (_state.elevatorRotation + 1) % 10;
+
+ _vm->_sound->replaceSoundMyst(_elevatorRotationSoundId);
+ _vm->redrawArea(11);
+ }
+
+ _vm->checkCursorHints();
+}
+
+void Mechanical::o_elevatorWindowMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 startTime = argv[0];
+ uint16 endTime = argv[1];
+
+ debugC(kDebugScript, "Opcode %d Movie Time Index %d to %d", op, startTime, endTime);
+
+ VideoHandle window = _vm->_video->playMovie(_vm->wrapMovieFilename("ewindow", kMechanicalStack), 253, 0);
+ _vm->_video->setVideoBounds(window, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600));
+ _vm->_video->waitUntilMovieEnds(window);
+}
+
+void Mechanical::o_elevatorGoMiddle(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator go middle from top", op);
+
+ _elevatorTooLate = false;
+ _elevatorTopCounter = 5;
+ _elevatorGoingMiddle = true;
+ _elevatorInCabin = true;
+ _elevatorNextTime = _vm->_system->getMillis() + 1000;
+}
+
+void Mechanical::elevatorGoMiddle_run() {
+ uint32 time = _vm->_system->getMillis();
+ if (_elevatorNextTime < time) {
+ _elevatorNextTime = time + 1000;
+ _elevatorTopCounter--;
+
+ if (_elevatorTopCounter > 0) {
+ // Draw button pressed
+ if (_elevatorInCabin) {
+ _vm->_gfx->copyImageSectionToScreen(6332, Common::Rect(0, 35, 51, 63), Common::Rect(10, 137, 61, 165));
+ _vm->_system->updateScreen();
+ }
+
+ // Blip
+ _vm->_sound->playSoundBlocking(14120);
+
+ // Restore button
+ if (_elevatorInCabin) {
+ _vm->_gfx->copyBackBufferToScreen(Common::Rect(10, 137, 61, 165));
+ _vm->_system->updateScreen();
+ }
+ } else if (_elevatorInCabin) {
+ _elevatorTooLate = true;
+
+ // Elevator going to middle animation
+ _vm->_cursor->hideCursor();
+ _vm->_sound->playSoundBlocking(11120);
+ _vm->_gfx->copyImageToBackBuffer(6118, Common::Rect(544, 333));
+ _vm->_sound->replaceSoundMyst(12120);
+ _vm->_gfx->runTransition(2, Common::Rect(177, 0, 370, 333), 25, 0);
+ _vm->_sound->playSoundBlocking(13120);
+ _vm->_sound->replaceSoundMyst(8120);
+ _vm->_gfx->copyImageToBackBuffer(6327, Common::Rect(544, 333));
+ _vm->_system->delayMillis(500);
+ _vm->_sound->replaceSoundMyst(9120);
+ static uint16 moviePos[2] = { 3540, 5380 };
+ o_elevatorWindowMovie(121, 0, 2, moviePos);
+ _vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333));
+ _vm->_sound->replaceSoundMyst(10120);
+ _vm->_cursor->showCursor();
+
+ _elevatorGoingMiddle = false;
+ _elevatorPosition = 1;
+
+ _vm->changeToCard(6327, true);
+ }
+ }
+}
+
+void Mechanical::o_elevatorTopMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 startTime = argv[0];
+ uint16 endTime = argv[1];
+
+ debugC(kDebugScript, "Opcode %d Movie Time Index %d to %d", op, startTime, endTime);
+
+ VideoHandle window = _vm->_video->playMovie(_vm->wrapMovieFilename("hcelev", kMechanicalStack), 206, 38);
+ _vm->_video->setVideoBounds(window, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600));
+ _vm->_video->waitUntilMovieEnds(window);
}
void Mechanical::opcode_124(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
@@ -403,36 +542,29 @@ void Mechanical::o_snakeBox_init(uint16 op, uint16 var, uint16 argc, uint16 *arg
_snakeBox = static_cast<MystResourceType6 *>(_invokingResource);
}
-static struct {
- bool enabled;
- uint16 soundId;
-} g_opcode204Parameters;
-
-void Mechanical::opcode_204_run() {
- if (g_opcode204Parameters.enabled) {
- // TODO: Fill in Logic.
- // Var 12 holds Large Cog Position in range 0 to 5
- // - For animation
- // Var 11 holds C position in range 0 to 9
- // - 4 for Correct Answer
- // C Movement Sound
- //_vm->_sound->playSound(g_opcode204Parameters.soundId);
+void Mechanical::elevatorRotation_run() {
+ _vm->redrawArea(12);
+
+ _elevatorRotationGearPosition += _elevatorRotationSpeed;
+
+ if (_elevatorRotationGearPosition > 12) {
+ uint16 position = (uint16)_elevatorRotationGearPosition;
+ _elevatorRotationGearPosition = _elevatorRotationGearPosition - position + position % 6;
+
+ _state.elevatorRotation = (_state.elevatorRotation + 1) % 10;
+
+ _vm->_sound->replaceSoundMyst(_elevatorRotationSoundId);
+ _vm->redrawArea(11);
+ _vm->_system->delayMillis(100);
}
}
-void Mechanical::opcode_204_disable() {
- g_opcode204Parameters.enabled = false;
-}
+void Mechanical::o_elevatorRotation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Elevator rotation init", op);
-void Mechanical::opcode_204(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
-
- // Used for Card 6180 (Lower Elevator Puzzle)
- if (argc == 1) {
- g_opcode204Parameters.soundId = argv[0];
- g_opcode204Parameters.enabled = true;
- } else
- unknown(op, var, argc, argv);
+ _elevatorRotationSoundId = argv[0];
+ _elevatorRotationGearPosition = 0;
+ _elevatorRotationLeverMoving = false;
}
static struct {
@@ -532,11 +664,5 @@ void Mechanical::opcode_209(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
unknown(op, var, argc, argv);
}
-void Mechanical::opcode_300(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- // Used in Card 6156 (Fortress Elevator View)
- varUnusedCheck(op, var);
- // TODO: Fill in Logic. Clearing Variable for View?
-}
-
} // End of namespace MystStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/mechanical.h b/engines/mohawk/myst_stacks/mechanical.h
index 7142425eb4..6a0aa30f5c 100644
--- a/engines/mohawk/myst_stacks/mechanical.h
+++ b/engines/mohawk/myst_stacks/mechanical.h
@@ -54,8 +54,8 @@ private:
void opcode_202_run();
void opcode_202_disable();
- void opcode_204_run();
- void opcode_204_disable();
+ void elevatorRotation_run();
+ void elevatorGoMiddle_run();
void opcode_205_run();
void opcode_205_disable();
void opcode_206_run();
@@ -66,9 +66,12 @@ private:
DECLARE_OPCODE(o_throneEnablePassage);
DECLARE_OPCODE(o_snakeBoxTrigger);
DECLARE_OPCODE(o_fortressStaircaseMovie);
- DECLARE_OPCODE(opcode_121);
- DECLARE_OPCODE(opcode_122);
- DECLARE_OPCODE(opcode_123);
+ DECLARE_OPCODE(o_elevatorRotationStart);
+ DECLARE_OPCODE(o_elevatorRotationMove);
+ DECLARE_OPCODE(o_elevatorRotationStop);
+ DECLARE_OPCODE(o_elevatorWindowMovie);
+ DECLARE_OPCODE(o_elevatorGoMiddle);
+ DECLARE_OPCODE(o_elevatorTopMovie);
DECLARE_OPCODE(opcode_124);
DECLARE_OPCODE(o_mystStaircaseMovie);
DECLARE_OPCODE(opcode_126);
@@ -83,19 +86,31 @@ private:
DECLARE_OPCODE(o_fortressStaircase_init);
DECLARE_OPCODE(opcode_202);
DECLARE_OPCODE(o_snakeBox_init);
- DECLARE_OPCODE(opcode_204);
+ DECLARE_OPCODE(o_elevatorRotation_init);
DECLARE_OPCODE(opcode_205);
DECLARE_OPCODE(opcode_206);
DECLARE_OPCODE(opcode_209);
- DECLARE_OPCODE(opcode_300);
-
MystGameState::Mechanical &_state;
bool _mystStaircaseState; // 76
uint16 _fortressPosition; // 82
+ uint16 _elevatorGoingDown; // 112
+
+ float _elevatorRotationSpeed; // 120
+ float _elevatorRotationGearPosition; // 124
+ uint16 _elevatorRotationSoundId; // 128
+ bool _elevatorRotationLeverMoving; // 184
+
+ bool _elevatorGoingMiddle; // 148
+ bool _elevatorTooLate;
+ uint16 _elevatorPosition; // 104
+ bool _elevatorInCabin; // 108
+ uint16 _elevatorTopCounter;
+ uint32 _elevatorNextTime;
+
uint16 _crystalLit; // 130
MystResourceType6 *_snakeBox; // 156
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index 29048eab39..2b8ef94442 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -33,6 +33,8 @@
#include "mohawk/myst_stacks/myst.h"
#include "common/events.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "gui/message.h"
@@ -50,6 +52,7 @@ Myst::Myst(MohawkEngine_Myst *vm) :
_towerRotationBlinkLabel = false;
_libraryBookcaseChanged = false;
_dockVaultState = 0;
+ _cabinDoorOpened = 0;
_cabinMatchState = 2;
_matchBurning = false;
_tree = 0;
@@ -3132,7 +3135,7 @@ Common::Point Myst::towerRotationMapComputeCoords(const Common::Point &center, u
Common::Point end;
// Polar to rect coords
- double radians = angle * PI / 180.0;
+ double radians = angle * M_PI / 180.0;
end.x = (int16)(center.x + cos(radians) * 310.0);
end.y = (int16)(center.y + sin(radians) * 310.0);
diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp
index dc491c7573..fddf6290fb 100644
--- a/engines/mohawk/myst_stacks/preview.cpp
+++ b/engines/mohawk/myst_stacks/preview.cpp
@@ -30,6 +30,7 @@
#include "mohawk/video.h"
#include "mohawk/myst_stacks/preview.h"
+#include "common/system.h"
#include "gui/message.h"
namespace Mohawk {
diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp
index f485bab2f9..c670cb6a48 100644
--- a/engines/mohawk/myst_stacks/selenitic.cpp
+++ b/engines/mohawk/myst_stacks/selenitic.cpp
@@ -32,6 +32,8 @@
#include "mohawk/video.h"
#include "mohawk/myst_stacks/selenitic.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "gui/message.h"
namespace Mohawk {
@@ -816,7 +818,7 @@ void Selenitic::o_soundLockEndMove(uint16 op, uint16 var, uint16 argc, uint16 *a
debugC(kDebugScript, "Opcode %d: Sound lock end move", op);
MystResourceType10 *slider = soundLockSliderFromVar(var);
- uint16 *value = 0;
+ uint16 *value = &_state.soundLockSliderPositions[0];
switch (var) {
case 20: // Sound lock sliders
@@ -834,6 +836,9 @@ void Selenitic::o_soundLockEndMove(uint16 op, uint16 var, uint16 argc, uint16 *a
case 24:
value = &_state.soundLockSliderPositions[4];
break;
+ default:
+ error("Incorrect var value for Selenitic opcode 114");
+ break;
}
uint16 stepped = 12 * (*value / 12) + 6;
diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp
index e664081c96..4057edd9c9 100644
--- a/engines/mohawk/myst_stacks/slides.cpp
+++ b/engines/mohawk/myst_stacks/slides.cpp
@@ -30,6 +30,7 @@
#include "mohawk/video.h"
#include "mohawk/myst_stacks/slides.h"
+#include "common/system.h"
#include "gui/message.h"
namespace Mohawk {
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index b5b403dad8..07701c273e 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -32,7 +32,9 @@
#include "mohawk/video.h"
#include "mohawk/myst_stacks/stoneship.h"
-#include "gui/message.h"
+#include "common/events.h"
+#include "common/system.h"
+#include "common/textconsole.h"
namespace Mohawk {
namespace MystStacks {
diff --git a/engines/mohawk/myst_state.cpp b/engines/mohawk/myst_state.cpp
index 968bb422be..de71dcf382 100644
--- a/engines/mohawk/myst_state.cpp
+++ b/engines/mohawk/myst_state.cpp
@@ -27,7 +27,9 @@
#include "mohawk/myst.h"
#include "mohawk/myst_state.h"
+#include "common/debug.h"
#include "common/serializer.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Mohawk {
diff --git a/engines/mohawk/myst_state.h b/engines/mohawk/myst_state.h
index a543cb1c4f..074c3e5f10 100644
--- a/engines/mohawk/myst_state.h
+++ b/engines/mohawk/myst_state.h
@@ -31,7 +31,7 @@
#include "common/str.h"
namespace Common {
- class Serializer;
+class Serializer;
}
namespace Mohawk {
diff --git a/engines/mohawk/myst_vars.cpp b/engines/mohawk/myst_vars.cpp
deleted file mode 100644
index f8ea11a1e2..0000000000
--- a/engines/mohawk/myst_vars.cpp
+++ /dev/null
@@ -1,578 +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.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "mohawk/myst.h"
-#include "mohawk/myst_vars.h"
-
-namespace Mohawk {
-
-// The Myst variable system is complex, and the structure is fairly
-// unknown. The idea of this class is to abstract the variable references
-// from the storage structure until the structure is clear enough that
-// the complexity of this abstraction can be removed.
-
-// The exact organization of local/global, persistent/non-persistent
-// age-specific mapping etc. is currently unknown.
-
-MystVarEntry introVars[] = {
- { 0, 7, "Age To Link To" } // 0 to 7
- // 0 = Selenitic
- // 1 = Stoneship
- // 2 = Myst (Library Ceiling)
- // 3 = Mechanical
- // 4 = Channelwood
- // 5 = Myst (Start of Movie - Over Sea)
- // 6 = D'ni
- // 7 = Myst (End of Movie - On Dock)
-};
-
-MystVarEntry seleniticVars[] = {
- { 0, 0, "Sound Pickup At Windy Tunnel" }, // 0 to 1 // TODO: Multiple Uses of Var 0?
- { 1, 0, "Sound Pickup At Volcanic Crack" }, // 0 to 1
- { 2, 0, "Sound Pickup At Clock" }, // 0 to 1
- { 3, 0, "Sound Pickup At Water Pool" }, // 0 to 1
- { 4, 0, "Sound Pickup At Crystal Rocks" }, // 0 to 1
- { 5, 0, "Sound Receiver Doors" }, // 0 to 1
- { 6, 0, "Windy Tunnel Lights" }, // 0 to 1
- { 7, 0, "Maze Runner Porthole View" }, // 0 to 3
- { 8, 0, "Sound Receiver Screen (Control Variable?)" },
- { 9, 0, "Sound Receiver Water Pool Button Selected" },
- { 10, 0, "Sound Receiver Volcanic Crack Button Selected" },
- { 11, 0, "Sound Receiver Clock Button Selected" },
- { 12, 0, "Sound Receiver Crystal Rocks Button Selected" },
- { 13, 0, "Sound Receiver Windy Tunnel Button Selected" },
- { 14, 0, "Sound Receiver LED Digit #0 (Left)" },
- { 15, 0, "Sound Receiver LED Digit #1" },
- { 16, 0, "Sound Receiver LED Digit #2" },
- { 17, 0, "Sound Receiver LED Digit #3 (Right)" },
- { 18, 0, "Sound Receiver Green Arrow - Right" },
- { 19, 0, "Sound Receiver Green Arrow - Left" },
- { 20, 0, "Sound Lock Slider #1 (Left) (Position?)" },
- { 21, 0, "Sound Lock Slider #2 (Position?)" },
- { 22, 0, "Sound Lock Slider #3 (Position?)" },
- { 23, 0, "Sound Lock Slider #4 (Position?)" },
- { 24, 0, "Sound Lock Slider #5 (Right) (Position?)" },
- { 25, 0, "Maze Runner Compass Heading" }, // 0 to 8
- { 26, 0, "Sound Receiver Sum Button Selected" },
- { 27, 0, "Maze Runner Red Warning Light" },
- { 28, 0, "Sound Lock Button State" },
- { 29, 0, "Maze Runner Door Button State" },
- { 30, 0, "Maze Runner Door State" },
- { 31, 0, "Maze Runner Forward Button Lit" }, // 0 to 2
- { 32, 0, "Maze Runner Left & Right Button Lit" }, // 0 to 2
- { 33, 0, "Maze Runner Backtrack Button Lit" }, // 0 to 2
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" } // 0 to 1
-};
-
-MystVarEntry stoneshipVars[] = {
- { 0, 0, "Water Pump Button #3 (Right) / Lighthouse Water Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit
- { 1, 0, "Water Pump Button #2 / Tunnels To Brothers Rooms Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit
- { 2, 0, "Water Pump Button #1 (Left) / Ship Cabin Water Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit
- { 3, 0, "Lighthouse (Water or Chest Floating?)" }, // 0 to 1, Used by Far View
- { 4, 0, "Lighthouse Water/Chest State" }, // 0 to 2 = Water, No Water, Water & Chest Floating
- { 5, 2, "Lighthouse Trapdoor State" }, // 0 to 2 = Closed & Unlocked, Open, Closed & Locked
- { 6, 0, "Lighthouse Chest Valve Position" }, // 0 to 1
- { 7, 0, "Lighthouse Chest Unlocked" }, // 0 to 1
- { 8, 0, "Lighthouse Chest Key Position?" }, // 0 to 2, 2 = Bottom of Lighthouse
-// Var 9 Unused
- { 10, 1, "Lighthouse Chest Full Of Water" }, // 0 to 1
- { 11, 3, "Lighthouse Key State" }, // 0 to 3 = Closed?, Open & No Key, Open & No Key, Open & Key
- { 12, 0, "Lighthouse Trapdoor - Holding Key" }, // 0 to 1
- { 13, 0, "State of Water in Tunnels to Brothers' Rooms" }, // 0 to 2 = Dark & Water, Dark & Drained, Lit & Water
- { 14, 0, "Tunnels to Brothers' Rooms Lit" }, // 0 to 1
- { 15, 0, "Side Door in Tunnels To Brother's Rooms Open" }, // 0 to 1
- { 16, 0, "Underwater Light Lit" }, // 0 to 1
- { 17, 0, "Sirrus' Room Drawer with Drugs Open" }, // 0 to 1
- { 18, 0, "Brother Room Door Open" }, // 0 to 1, Used for Door Slam
- { 19, 0, "Brother Room Door State" }, // 0 to 2 = Closed, Open & Dark, Open & Lit
- { 20, 0, "Ship Cabin Myst Book Present" }, // 0 to 1
- { 21, 0, "Brothers Rooms' Chest Of Drawers Drawer State" }, // 0 to 6 (Card 2197) or 0 to 7 (Card 2004)
- { 22, 0, "Sirrus' Chest of Drawers Drawer #1 (Top) Open" }, // 0 to 1
- { 23, 0, "Sirrus' Chest of Drawers Drawer #2 Open" }, // 0 to 1
- { 24, 0, "Sirrus' Chest of Drawers Drawer #3 Open" }, // 0 to 1
-// Var 25 Unused - Replaced by Var 35.
- { 26, 0, "Sirrus' Chest of Drawers Left Small Drawer Open" }, // 0 to 1
- { 27, 0, "Sirrus' Chest of Drawers Right Small Drawer Open" }, // 0 to 1
- { 28, 0, "Telescope View Position" }, // Range Unknown.. 0 to 360?
- { 29, 0, "Achenar's Room Rose/Skull Hologram Button Lit" }, // 0 to 1
- { 30, 2, "Light State in Tunnel to Compass Rose Room" }, // 0 to 2 = Lit & Underwater Light Lit, Lit, Dark
- { 31, 0, "Lighthouse Lamp Room Battery Pack Indicator Light" }, // 0 to 1
- { 32, 0, "Lighthouse Lamp Room Battery Pack Meter Level" }, // Range Unknown.. // Must be 1 to vertical size of image...
- { 33, 0, "State of Side Door in Tunnels to Compass Rose Room (Power?)" }, // 0 to 2 = Closed (No Power), Closed (Power), Open
- { 34, 1, "Achenar's Room Drawer with Torn Note Closed" }, // 0 to 1
- { 35, 2, "Sirrus' Room Drawer #4 (Bottom) Open and Red Page State" }, // 0 to 2 = Open, Open with Page, Closed
- { 36, 0, "Ship Cabin Door State" }, // 0 to 2 = Closed, Open & Dark, Open & Lit
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" }, // 0 to 1
- { 105, 0, "Ship Cabin Door State" }
-};
-
-MystVarEntry mystVars[] = {
- { 0, 1, "Myst Library Bookcase Closed / Library Exit Open" }, // 0 to 1 // TODO: Multiple Uses of Var 0?
- { 1, 0, "Myst Library Bookcase Open / Library Exit Blocked" }, // 0 to 1
- { 2, 0, "Marker Switch Near Cabin" }, // 0 to 1
- { 3, 0, "Marker Switch Near Clock Tower" }, // 0 to 1
- { 4, 0, "Marker Switch on Dock" }, // 0 to 1
- { 5, 0, "Marker Switch Near Ship Pool" }, // 0 to 1
- { 6, 0, "Marker Switch Near Cogs" }, // 0 to 1
- { 7, 0, "Marker Switch Near Generator Room" }, // 0 to 1
- { 8, 0, "Marker Switch Near Stellar Observatory" }, // 0 to 1
- { 9, 0, "Marker Switch Near Rocket Ship" }, // 0 to 1
- { 10, 0, "Ship Floating State" }, // 0 to 1
- { 11, 0, "Cabin Door Open State" },
- { 12, 0, "Clock Tower Gear Bridge" }, // 0 to 1
- { 13, 0, "Tower Elevator Sound Control" }, // 0 to 1
- { 14, 0, "Tower Solution (Key) Plaque" }, // 0 to 4
- // 0 = None
- // 1 = 59 V
- // 2 = 2:40 2-2-1
- // 3 = October 11, 1984 10:04 AM
- // January 17, 1207 5:46 AM
- // November 23, 9791 6:57 PM
- // 4 = 7, 2, 4
- { 15, 0, "Tower Window (Book) View" }, // 0 to 6
- // 0 = Wall
- // 1 = Rocketship
- // 2 = Cogs Closed
- // 3 = Ship Sunk
- // 4 = Channelwood Tree
- // 5 = Ship Floating
- // 6 = Cogs Open
- { 16, 0, "Tower Window (Book) View From Ladder Top" }, // 0 to 2
- // 0 = Wall
- // 1 = Sky
- // 2 = Sky with Channelwood Tree
- { 17, 0, "Fireplace Grid Row #1 (Top)" }, // Bitfield 0x00 to 0xFF
- { 18, 0, "Fireplace Grid Row #2" }, // Bitfield 0x00 to 0xFF
- { 19, 0, "Fireplace Grid Row #3" }, // Bitfield 0x00 to 0xFF
- { 20, 0, "Fireplace Grid Row #4" }, // Bitfield 0x00 to 0xFF
- { 21, 0, "Fireplace Grid Row #5" }, // Bitfield 0x00 to 0xFF
- { 22, 0, "Fireplace Grid Row #6 (Bottom)" }, // Bitfield 0x00 to 0xFF
- { 23, 0, "Fireplace Pattern Correct" }, // 0 to 1
- { 24, 1, "Fireplace Blue Page Present" }, // 0 to 1
- { 25, 1, "Fireplace Red Page Present" }, // 0 to 1
- { 26, 0, "Ship Puzzle Box Image (Cross)" }, // 0 to 2
- { 27, 0, "Ship Puzzle Box Image (Leaf)" }, // 0 to 2
- { 28, 0, "Ship Puzzle Box Image (Arrow)" }, // 0 to 2
- { 29, 0, "Ship Puzzle Box Image (Eye)" }, // 0 to 2
- { 30, 0, "Ship Puzzle Box Image (Snake)" }, // 0 to 2
- { 31, 0, "Ship Puzzle Box Image (Spider)" }, // 0 to 2
- { 32, 0, "Ship Puzzle Box Image (Anchor)" }, // 0 to 2
- { 33, 0, "Ship Puzzle Box Image (Ostrich)" }, // 0 to 2
- { 34, 2, "Dock Forechamber Imager State" }, // 0 to 2 = Off, Mountain, Water
- { 35, 5, "Dock Forechamber Imager Control Left Digit" }, // 0 to 9
- { 36, 6, "Dock Forechamber Imager Control Right Digit" }, // 0 to 9
- { 37, 0, "Clock Tower Control Wheels Position" }, // 0 to 8
-// Var 38 Unused
-// 39 = TODO: ?
- { 40, 0, "Cog Close/Open State" },
- { 41, 0, "Dock Marker Switch Vault State" }, // 0 to 2 = Closed, Open & Page Taken, Open & Page Present
-// Var 42 Unused
- { 43, 0, "Clock Tower Time" }, // 0 to 143
- { 44, 0, "Rocket Ship Power State" }, // 0 to 2 = None, Insufficient, Correct
- { 45, 1, "Dock Forechamber Imager Water Effect Enabled" }, // 0 to 1
- { 46, 0, "Number Of Pages in Red Book" }, // 0 to 6 = 0-5, Extra
- { 47, 0, "Number Of Pages in Blue Book" }, // 0 to 6 = 0-5, Extra
- { 48, 0, "Marker Switch on Dock - Duplicate of Var #4?" }, // 0 to 2
- { 49, 0, "Generator Running" }, // Boolean used for Sound..
-// 50 = TODO: ?
- { 51, 2, "Forechamber Imager Movie Control Variable" }, // 0 to 4 = Blank, Mountain, Water, Atrus, Marker Switch
- { 52, 0, "Generator Switch #1" },
- { 53, 0, "Generator Switch #2" },
- { 54, 0, "Generator Switch #3" },
- { 55, 0, "Generator Switch #4" },
- { 56, 0, "Generator Switch #5" },
- { 57, 0, "Generator Switch #6" },
- { 58, 0, "Generator Switch #7" },
- { 59, 0, "Generator Switch #8" },
- { 60, 0, "Generator Switch #9" },
- { 61, 0, "Generator Switch #10" },
- { 62, 0, "Generator Power Dial Left LED Digit" }, // 0 to 9
- { 63, 0, "Generator Power Dial Right LED Digit" }, // 0 to 9
- { 64, 0, "Generator Power To Spaceship Dial Left LED Digit" }, // 0 to 9
- { 65, 0, "Generator Power To Spaceship Dial Right LED Digit" }, // 0 to 9
- { 66, 0, "Generator Room Lights On" }, // Boolean
- { 67, 9, "Cabin Safe Lock Number #1 - Left" },
- { 68, 9, "Cabin Safe Lock Number #2" },
- { 69, 9, "Cabin Safe Lock Number #3 - Right" },
- { 70, 0, "Cabin Safe Matchbox State" }, // 0 to 2
- { 71, 1, "Stellar Observatory Lights" },
- { 72, 0, "Channelwood Tree Position" }, // 0 to 12, 4 for Alcove
- { 73, 9, "Stellar Observatory Telescope Control - Month" }, // 0 to 11, Not in order...
- // 0 = OCT, 1 = NOV, 2 = DEC, 3 = JUL, 4 = AUG, 5 = SEP
- // 6 = APR, 7 = MAY, 8 = JUN, 9 = JAN, 10 = FEB, 11 = MAR
- { 74, 10, "Stellar Observatory Telescope Control - Day Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank
- { 75, 1, "Stellar Observatory Telescope Control - Day Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank
- { 76, 10, "Stellar Observatory Telescope Control - Year Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank
- { 77, 10, "Stellar Observatory Telescope Control - Year Digit #2" }, // 0 to 10 = 0 to 9, Blank
- { 78, 10, "Stellar Observatory Telescope Control - Year Digit #3" }, // 0 to 10 = 0 to 9, Blank
- { 79, 0, "Stellar Observatory Telescope Control - Year Digit #4 (Right)" }, // 0 to 10 = 0 to 9, Blank
- { 80, 1, "Stellar Observatory Telescope Control - Hour Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank
- { 81, 2, "Stellar Observatory Telescope Control - Hour Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank
- { 82, 0, "Stellar Observatory Telescope Control - Minute Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank
- { 83, 0, "Stellar Observatory Telescope Control - Minute Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank
-// 84 to 87 = TODO: ?
- { 88, 0, "Stellar Observatory Telescope Control - AM/PM Indicator" }, // 0 = AM, 1 = PM
- { 89, 0, "Stellar Observatory Telescope Control - Slider #1 (Left)" }, // 0 to 2 = Not Present, Dark, Lit
- { 90, 0, "Stellar Observatory Telescope Control - Slider #2" }, // 0 to 2 = Not Present, Dark, Lit
- { 91, 0, "Stellar Observatory Telescope Control - Slider #3" }, // 0 to 2 = Not Present, Dark, Lit
- { 92, 0, "Stellar Observatory Telescope Control - Slider #4 (Right)" }, // 0 to 2 = Not Present, Dark, Lit
- { 93, 0, "Breaker nearest Generator Room Blown" },
- { 94, 0, "Breaker nearest Rocket Ship Blown" },
-// 95 = TODO: ?
- { 96, 0, "Generator Power Dial Needle Position" }, // 0 to 24
- { 97, 0, "Generator Power To Spaceship Dial Needle Position" }, // 0 to 24
- { 98, 0, "Cabin Boiler Pilot Light Lit" },
- { 99, 0, "Cabin Boiler Gas Valve Position" }, // 0 to 5
- { 100, 0, "Red Book Page State" }, // Bitfield
- { 101, 0, "Blue Book Page State" }, // Bitfield
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" }, // 0 to 1
-// 104 = TODO: ?
- { 105, 0, "Clock Tower Door / Ship Box Temp Value" },
- { 106, 0, "Red / Blue Book State" }, // 0 to 4, 0-3 = Books Present 4 = Books Burnt
- { 300, 0, "Rocket Ship Music Puzzle Slider State" }, // 0 to 2 = Not Present, Dark, Lit
- { 301, 0, "Rocket Ship Piano Key Depressed" }, // 0 to 1
- { 302, 0, "Green Book Opened Before Flag" }, // 0 to 1
- { 303, 1, "Myst Library Bookcase Closed / Library Exit Open" },
- { 304, 0, "Myst Library Image Present on Tower Rotation Map" }, // 0 to 1
- { 305, 0, "Cabin Boiler Lit" },
- { 306, 0, "Cabin Boiler Steam Sound Control" }, // 0 to 27
- { 307, 0, "Cabin Boiler Needle Position i.e. Fully Pressurised" }, // 0 to 1
- { 308, 0, "Cabin Safe Handle Position / Matchbox Temp Value" },
- { 309, 0, "Red/Blue/Green Book Open" }, // 0 to 1
- { 310, 0, "Dock Forechamber Imager Control Temp Value?" }
-};
-
-MystVarEntry mechVars[] = {
- { 0, 0, "Achenar's Room Secret Panel State" }, // TODO: Multiple Uses of Var 0?
- { 1, 0, "Sirrus's Room Secret Panel State" },
- { 2, 0, "Achenar's Secret Room Crate Lid Open and Blue Page Present" }, // 0 to 4
- // 0 = Lid Closed, Blue Page Present
- // 1 = Lid Closed, Blue Page Not Present
- // 2 = Lid Open, Blue Page Not Present
- // 3 = Lid Open, Blue Page Present
- { 3, 0, "Achenar's Secret Room Crate Lid Open" }, // 0 to 1
- { 4, 0, "Myst Book Staircase State" },
- { 5, 0, "Fortress Telescope View" },
- { 6, 0, "Large Cog Visible Through Distant Fortress Doorway" }, // 0 to 1
- { 7, 0, "Fortress Elevator Door Rotated to Open" }, // 0 to 1
-// Var 8 Not Used
-// Var 9 Not Used
- { 10, 0, "Fortress Staircase State" }, // 0 to 1
- { 11, 0, "Fortress Elevator Rotation Control - Position Indicator" }, // 0 to 9, 4 = Red Open Position
- { 12, 0, "Fortress Elevator Rotation Control - Top Cog Position" }, // 0 to 5
- { 13, 0, "Fortress Elevator Vertical Position - View" }, // 0 to 2, Used for View Logic on change from Card 6150
- { 14, 0, "Fortress Elevator Vertical Position - Button" }, // 0 to 2, Used for Button Logic on Card 6120
- { 15, 0, "Code Lock State" }, // 0 to 2
- { 16, 0, "Code Lock Shape #1 (Left)" },
- { 17, 0, "Code Lock Shape #2" },
- { 18, 0, "Code Lock Shape #3" },
- { 19, 0, "Code Lock Shape #4 (Right)" },
- { 20, 0, "Red Dodecahedron Lit" },
- { 21, 0, "Green Dodecahedron Lit" },
- { 22, 0, "Yellow Tetrahedron Lit" },
- { 23, 0, "In Elevator" }, // 0 to 1
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" } // 0 to 1
-};
-
-MystVarEntry channelwoodVars[] = {
- { 0, 0, "Multiple Uses..." }, // TODO: Multiple Uses of Var 0?
- { 1, 0, "Water Pump Bridge State" }, // 0 to 1
- { 2, 0, "Lower Walkway to Upper Walkway Elevator State" }, // 0 to 1
- { 3, 0, "Water Flowing (R) to Pump for Upper Walkway to Temple Elevator" }, // 0 to 1
- { 4, 0, "Water Flowing (L, R, R, L, Pipe Extended) to Pump for Book Room Elevator" }, // 0 to 1
- { 5, 0, "Lower Walkway to Upper Walkway Spiral Stair Lower Door Open" }, // 0 to 1
- { 6, 0, "Pipe Bridge Extended" }, // 0 to 1
- { 7, 0, "Bridge Pump Running" }, // 0 to 1
- { 8, 0, "Water Tank Valve State" }, // 0 to 1
- { 9, 0, "First Water Valve State" }, // 0 to 1
- { 10, 0, "Second (L) Water Valve State" }, // 0 to 1
- { 11, 0, "Third (L, R) Water Valve State" }, // 0 to 1
- { 12, 0, "Fourth (L, R, R) Water Valve State" }, // 0 to 1
- { 13, 0, "Fourth (L, R, L) Water Valve State" }, // 0 to 1
- { 14, 0, "Third (L, L) Water Valve State" }, // 0 to 1
- { 15, 0, "Water Flowing (L, R, R, R) to Pump for Lower Walkway to Upper Walkway Elevator" }, // 0 to 1
- { 16, 0, "Lower Walkway to Upper Walkway Spiral Stair Upper Door Open" }, // 0 to 1
- { 17, 0, "Achenar's Holoprojector Selection" }, // 0 to 3
- { 18, 0, "Drawer in Sirrus' Room with Wine Bottles and Torn Note Open" }, // 0 to 1
- { 19, 0, "Water Flowing to First Water Valve" }, // 0 to 1
- { 20, 0, "Water Flowing to Second (L) Water Valve" }, // 0 to 1
- { 21, 0, "Water Flowing to Third (L, R) Water Valve" }, // 0 to 1
- { 22, 0, "Water Flowing to Fourth (L, R, R) Water Valve" }, // 0 to 1
- { 23, 0, "Water Flowing to Fourth (L, R, L) Water Valve" }, // 0 to 1
- { 24, 0, "Water Flowing to Third (L, L) Water Valve" }, // 0 to 1
- { 25, 0, "Water Flowing to Pipe Bridge (L, R, R, L)" }, // 0 to 1
- { 26, 0, "Water Flowing to Pipe At Entry Point (L, R, L, R)" }, // 0 to 1
- { 27, 0, "Water Flowing to Join and Pump Bridge (L, R, L, L)" }, // 0 to 1
- { 28, 0, "Water Flowing to Join and Pump Bridge (L, L, R)" }, // 0 to 1
- { 29, 0, "Water Flowing to Pipe In Water (L, L, L)" }, // 0 to 1
- { 30, 0, "Lower Walkway to Upper Walkway Elevator Door Open" }, // 0 to 1
- { 31, 0, "Water Flowing to Join (L, L, R)" }, // 0 to 2 = Stop Sound, Background, Background with Water Flow
- { 32, 0, "Water Flowing (L, R, R, L, Pipe) State" }, // 0 to 2 = Stop Sound, Background, Background with Water Flow
- { 33, 0, "Lower Walkway to Upper Walkway Spiral Stair Upper Door State" }, // 0 to 2 = Closed, Open, Open but slams behind you.
- { 102, 1, "Red Page in Age" }, // 0 to 1
- { 103, 1, "Blue Page in Age" }, // 0 to 1
- { 105, 0, "Upper Walkway to Temple Elevator Door Open / Temple Iron Door Open" } // 0 to 1, used for slam sound
-};
-
-MystVarEntry dniVars[] = {
- { 0, 0, "Atrus Gone" }, // 0 to 1 // TODO: Multiple Uses of Var 0?
- { 1, 0, "Myst Book State" }, // 0 to 2 = Book Inactive, Book Unlinkable, Book Linkable
- { 2, 0, "Sound Control" }, // 0 to 2 = Win Tune, Lose Tune, Stop Sound
- { 106, 0, "Atrus State Control" } // 0 to 4 = Atrus Writing, Atrus Holding Out Hand, Atrus Gone, Atrus #2, Atrus #2
-};
-
-MystVarEntry creditsVars[] = {
- { 0, 0, "Image Control" }, // 0 to 6
- { 1, 1, "Sound Control" } // 0 to 1 = Win Tune, Lose Tune
-};
-
-MystVar::MystVar(MohawkEngine_Myst *vm) {
- _vm = vm;
-}
-
-MystVar::~MystVar() {
-}
-
-// Only for use by Save/Load, all other code should use getVar()
-uint16 MystVar::saveGetVar(uint16 stack, uint16 v) {
- uint16 value = 0;
- MystVarEntry unknownVar = { v, 0, "Unknown" };
- const char *desc = NULL;
- uint16 i;
-
- switch (stack) {
- case kIntroStack:
- for (i = 0; i < ARRAYSIZE(introVars); i++) {
- if (introVars[i].refNum == v) {
- value = introVars[i].storage;
- desc = introVars[i].description;
- break;
- }
- }
- break;
- case kSeleniticStack:
- for (i = 0; i < ARRAYSIZE(seleniticVars); i++) {
- if (seleniticVars[i].refNum == v) {
- value = seleniticVars[i].storage;
- desc = seleniticVars[i].description;
- break;
- }
- }
- break;
- case kStoneshipStack:
- for (i = 0; i < ARRAYSIZE(stoneshipVars); i++) {
- if (stoneshipVars[i].refNum == v) {
- value = stoneshipVars[i].storage;
- desc = stoneshipVars[i].description;
- break;
- }
- }
- break;
- case kDemoPreviewStack:
- case kMystStack:
- for (i = 0; i < ARRAYSIZE(mystVars); i++) {
- if (mystVars[i].refNum == v) {
- value = mystVars[i].storage;
- desc = mystVars[i].description;
- break;
- }
- }
- break;
- case kMechanicalStack:
- for (i = 0; i < ARRAYSIZE(mechVars); i++) {
- if (mechVars[i].refNum == v) {
- value = mechVars[i].storage;
- desc = mechVars[i].description;
- break;
- }
- }
- break;
- case kChannelwoodStack:
- for (i = 0; i < ARRAYSIZE(channelwoodVars); i++) {
- if (channelwoodVars[i].refNum == v) {
- value = channelwoodVars[i].storage;
- desc = channelwoodVars[i].description;
- break;
- }
- }
- break;
- case kDniStack:
- for (i = 0; i < ARRAYSIZE(dniVars); i++) {
- if (dniVars[i].refNum == v) {
- value = dniVars[i].storage;
- desc = dniVars[i].description;
- break;
- }
- }
- break;
- case kCreditsStack:
- for (i = 0; i < ARRAYSIZE(creditsVars); i++) {
- if (creditsVars[i].refNum == v) {
- value = creditsVars[i].storage;
- desc = creditsVars[i].description;
- break;
- }
- }
- break;
- default:
- break;
- }
-
- if (desc == NULL) {
- for (i = 0; i < _unknown.size(); i++) {
- if (_unknown[i].refNum == v) {
- value = _unknown[i].storage;
- desc = _unknown[i].description;
- break;
- }
- }
-
- if (desc == NULL) {
- warning("MystVar::getVar(%d): Unknown variable reference", v);
- _unknown.push_back(unknownVar);
- desc = _unknown.back().description;
- }
- }
-
- debugC(kDebugVariable, "MystVar::getVar(%d = %s): %d", v, desc, value);
- return value;
-}
-
-// Only for use by Save/Load, all other code should use setVar()
-void MystVar::loadSetVar(uint16 stack, uint16 v, uint16 value) {
- const char *desc = NULL;
- MystVarEntry unknownVar = { v, value, "Unknown" };
- uint16 i;
-
- switch (stack) {
- case kIntroStack:
- for (i = 0; i < ARRAYSIZE(introVars); i++) {
- if (introVars[i].refNum == v) {
- introVars[i].storage = value;
- desc = introVars[i].description;
- break;
- }
- }
- break;
- case kSeleniticStack:
- for (i = 0; i < ARRAYSIZE(seleniticVars); i++) {
- if (seleniticVars[i].refNum == v) {
- seleniticVars[i].storage = value;
- desc = seleniticVars[i].description;
- break;
- }
- }
- break;
- case kStoneshipStack:
- for (i = 0; i < ARRAYSIZE(stoneshipVars); i++) {
- if (stoneshipVars[i].refNum == v) {
- stoneshipVars[i].storage = value;
- desc = stoneshipVars[i].description;
- break;
- }
- }
- break;
- case kDemoPreviewStack:
- case kMystStack:
- for (i = 0; i < ARRAYSIZE(mystVars); i++) {
- if (mystVars[i].refNum == v) {
- mystVars[i].storage = value;
- desc = mystVars[i].description;
- break;
- }
- }
- break;
- case kMechanicalStack:
- for (i = 0; i < ARRAYSIZE(mechVars); i++) {
- if (mechVars[i].refNum == v) {
- mechVars[i].storage = value;
- desc = mechVars[i].description;
- break;
- }
- }
- break;
- case kChannelwoodStack:
- for (i = 0; i < ARRAYSIZE(channelwoodVars); i++) {
- if (channelwoodVars[i].refNum == v) {
- channelwoodVars[i].storage = value;
- desc = channelwoodVars[i].description;
- break;
- }
- }
- break;
- case kDniStack:
- for (i = 0; i < ARRAYSIZE(dniVars); i++) {
- if (dniVars[i].refNum == v) {
- dniVars[i].storage = value;
- desc = dniVars[i].description;
- break;
- }
- }
- break;
- case kCreditsStack:
- for (i = 0; i < ARRAYSIZE(creditsVars); i++) {
- if (creditsVars[i].refNum == v) {
- creditsVars[i].storage = value;
- desc = creditsVars[i].description;
- break;
- }
- }
- break;
- default:
- break;
- }
-
- if (desc == NULL) {
- for (i = 0; i < _unknown.size(); i++) {
- if (_unknown[i].refNum == v) {
- _unknown[i].storage = value;
- desc = _unknown[i].description;
- break;
- }
- }
-
- if (desc == NULL) {
- warning("MystVar::setVar(%d): Unknown variable reference", v);
- _unknown.push_back(unknownVar);
- desc = _unknown.back().description;
- }
- }
-
- debugC(kDebugVariable, "MystVar::setVar(%d = %s): %d", v, desc, value);
-}
-
-uint16 MystVar::getVar(uint16 v) {
- return this->saveGetVar(_vm->getCurStack(), v);
-}
-
-void MystVar::setVar(uint16 v, uint16 value) {
- this->loadSetVar(_vm->getCurStack(), v, value);
-}
-
-} // End of namespace Mohawk
diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp
index de1513b237..62250b75f2 100644
--- a/engines/mohawk/resource.cpp
+++ b/engines/mohawk/resource.cpp
@@ -28,6 +28,7 @@
#include "common/debug.h"
#include "common/substream.h"
#include "common/util.h"
+#include "common/textconsole.h"
namespace Mohawk {
diff --git a/engines/mohawk/resource.h b/engines/mohawk/resource.h
index 18e8f80fb2..07c727951c 100644
--- a/engines/mohawk/resource.h
+++ b/engines/mohawk/resource.h
@@ -34,102 +34,102 @@
namespace Mohawk {
// Main FourCC's
-#define ID_MHWK MKID_BE('MHWK') // Main FourCC
-#define ID_RSRC MKID_BE('RSRC') // Resource Directory Tag
+#define ID_MHWK MKTAG('M','H','W','K') // Main FourCC
+#define ID_RSRC MKTAG('R','S','R','C') // Resource Directory Tag
// Myst Resource FourCC's
-#define ID_CLRC MKID_BE('CLRC') // Cursor Hotspots
-#define ID_EXIT MKID_BE('EXIT') // Card Exit Scripts
-#define ID_HINT MKID_BE('HINT') // Cursor Hints
-#define ID_INIT MKID_BE('INIT') // Card Entrance Scripts
-#define ID_MSND MKID_BE('MSND') // Standard Mohawk Sound
-#define ID_RLST MKID_BE('RLST') // Resource List, Specifies HotSpots
-#define ID_RSFL MKID_BE('RSFL') // ??? (system.dat only)
-#define ID_VIEW MKID_BE('VIEW') // Card Details
-#define ID_WDIB MKID_BE('WDIB') // LZ-Compressed Windows Bitmap
+#define ID_CLRC MKTAG('C','L','R','C') // Cursor Hotspots
+#define ID_EXIT MKTAG('E','X','I','T') // Card Exit Scripts
+#define ID_HINT MKTAG('H','I','N','T') // Cursor Hints
+#define ID_INIT MKTAG('I','N','I','T') // Card Entrance Scripts
+#define ID_MSND MKTAG('M','S','N','D') // Standard Mohawk Sound
+#define ID_RLST MKTAG('R','L','S','T') // Resource List, Specifies HotSpots
+#define ID_RSFL MKTAG('R','S','F','L') // ??? (system.dat only)
+#define ID_VIEW MKTAG('V','I','E','W') // Card Details
+#define ID_WDIB MKTAG('W','D','I','B') // LZ-Compressed Windows Bitmap
// Myst Masterpiece Edition Resource FourCC's (In addition to Myst FourCC's)
-#define ID_HELP MKID_BE('HELP') // Help Chunk
-#define ID_MJMP MKID_BE('MJMP') // MSND Jumps (To reduce MSND duplication)
-#define ID_PICT MKID_BE('PICT') // JPEG/PICT/WDIB Image
+#define ID_HELP MKTAG('H','E','L','P') // Help Chunk
+#define ID_MJMP MKTAG('M','J','M','P') // MSND Jumps (To reduce MSND duplication)
+#define ID_PICT MKTAG('P','I','C','T') // JPEG/PICT/WDIB Image
// Riven Resource FourCC's
-#define ID_BLST MKID_BE('BLST') // Card Hotspot Enabling Lists
-#define ID_CARD MKID_BE('CARD') // Card Scripts
-#define ID_FLST MKID_BE('FLST') // Card SFXE Lists
-#define ID_HSPT MKID_BE('HSPT') // Card Hotspots
-#define ID_MLST MKID_BE('MLST') // Card Movie Lists
-#define ID_NAME MKID_BE('NAME') // Object Names
-#define ID_PLST MKID_BE('PLST') // Card Picture Lists
-#define ID_RMAP MKID_BE('RMAP') // Card Codes
-#define ID_SFXE MKID_BE('SFXE') // Water Effect Animations
-#define ID_SLST MKID_BE('SLST') // Card Ambient Sound Lists
-#define ID_TMOV MKID_BE('tMOV') // QuickTime Movie
+#define ID_BLST MKTAG('B','L','S','T') // Card Hotspot Enabling Lists
+#define ID_CARD MKTAG('C','A','R','D') // Card Scripts
+#define ID_FLST MKTAG('F','L','S','T') // Card SFXE Lists
+#define ID_HSPT MKTAG('H','S','P','T') // Card Hotspots
+#define ID_MLST MKTAG('M','L','S','T') // Card Movie Lists
+#define ID_NAME MKTAG('N','A','M','E') // Object Names
+#define ID_PLST MKTAG('P','L','S','T') // Card Picture Lists
+#define ID_RMAP MKTAG('R','M','A','P') // Card Codes
+#define ID_SFXE MKTAG('S','F','X','E') // Water Effect Animations
+#define ID_SLST MKTAG('S','L','S','T') // Card Ambient Sound Lists
+#define ID_TMOV MKTAG('t','M','O','V') // QuickTime Movie
// Riven Saved Game FourCC's
-#define ID_VARS MKID_BE('VARS') // Variable Values
-#define ID_VERS MKID_BE('VERS') // Version Info
-#define ID_ZIPS MKID_BE('ZIPS') // Zip Mode Status
+#define ID_VARS MKTAG('V','A','R','S') // Variable Values
+#define ID_VERS MKTAG('V','E','R','S') // Version Info
+#define ID_ZIPS MKTAG('Z','I','P','S') // Zip Mode Status
// Zoombini Resource FourCC's
-#define ID_SND MKID_BE('\0SND') // Standard Mohawk Sound
-#define ID_CURS MKID_BE('CURS') // Cursor
-#define ID_SCRB MKID_BE('SCRB') // Feature Script
-#define ID_SCRS MKID_BE('SCRS') // Snoid Script
-#define ID_NODE MKID_BE('NODE') // Walk Node
-#define ID_PATH MKID_BE('PATH') // Walk Path
-#define ID_SHPL MKID_BE('SHPL') // Shape List
+#define ID_SND MKTAG( 0 ,'S','N','D') // Standard Mohawk Sound
+#define ID_CURS MKTAG('C','U','R','S') // Cursor
+#define ID_SCRB MKTAG('S','C','R','B') // Feature Script
+#define ID_SCRS MKTAG('S','C','R','S') // Snoid Script
+#define ID_NODE MKTAG('N','O','D','E') // Walk Node
+#define ID_PATH MKTAG('P','A','T','H') // Walk Path
+#define ID_SHPL MKTAG('S','H','P','L') // Shape List
// Living Books Resource FourCC's
-#define ID_TCUR MKID_BE('tCUR') // Cursor
-#define ID_BITL MKID_BE('BITL') // Book Item List
-#define ID_CTBL MKID_BE('CTBL') // Color Table
-#define ID_SCRP MKID_BE('SCRP') // Script
-#define ID_SPR MKID_BE('SPR#') // Sprite?
-#define ID_VRSN MKID_BE('VRSN') // Version
-#define ID_ANI MKID_BE('ANI ') // Animation
-#define ID_SHP MKID_BE('SHP#') // Shape
-#define ID_WAV MKID_BE('WAV ') // Old Sound Resource
-#define ID_BMAP MKID_BE('BMAP') // Old Mohawk Bitmap
-#define ID_BCOD MKID_BE('BCOD') // Book Code
+#define ID_TCUR MKTAG('t','C','U','R') // Cursor
+#define ID_BITL MKTAG('B','I','T','L') // Book Item List
+#define ID_CTBL MKTAG('C','T','B','L') // Color Table
+#define ID_SCRP MKTAG('S','C','R','P') // Script
+#define ID_SPR MKTAG('S','P','R','#') // Sprite?
+#define ID_VRSN MKTAG('V','R','S','N') // Version
+#define ID_ANI MKTAG('A','N','I',' ') // Animation
+#define ID_SHP MKTAG('S','H','P','#') // Shape
+#define ID_WAV MKTAG('W','A','V',' ') // Old Sound Resource
+#define ID_BMAP MKTAG('B','M','A','P') // Old Mohawk Bitmap
+#define ID_BCOD MKTAG('B','C','O','D') // Book Code
// JamesMath Resource FourCC's
-#define ID_TANM MKID_BE('tANM') // Animation?
-#define ID_TMFO MKID_BE('tMFO') // ???
+#define ID_TANM MKTAG('t','A','N','M') // Animation?
+#define ID_TMFO MKTAG('t','M','F','O') // ???
// CSTime Resource FourCC's
-#define ID_CINF MKID_BE('CINF') // Case Info
-#define ID_CONV MKID_BE('CONV') // Conversation
-#define ID_HOTS MKID_BE('HOTS') // Hotspot
-#define ID_INVO MKID_BE('INVO') // Inventory Object
-#define ID_QARS MKID_BE('QARS') // Question and Responses
-#define ID_SCEN MKID_BE('SCEN') // Scene
-#define ID_STRI MKID_BE('STRI') // String Entry?
+#define ID_CINF MKTAG('C','I','N','F') // Case Info
+#define ID_CONV MKTAG('C','O','N','V') // Conversation
+#define ID_HOTS MKTAG('H','O','T','S') // Hotspot
+#define ID_INVO MKTAG('I','N','V','O') // Inventory Object
+#define ID_QARS MKTAG('Q','A','R','S') // Question and Responses
+#define ID_SCEN MKTAG('S','C','E','N') // Scene
+#define ID_STRI MKTAG('S','T','R','I') // String Entry?
// Mohawk Wave Tags
-#define ID_WAVE MKID_BE('WAVE') // Game Sound (Third Tag)
-#define ID_ADPC MKID_BE('ADPC') // Game Sound Chunk
-#define ID_DATA MKID_BE('Data') // Game Sound Chunk
-#define ID_CUE MKID_BE('Cue#') // Game Sound Chunk
+#define ID_WAVE MKTAG('W','A','V','E') // Game Sound (Third Tag)
+#define ID_ADPC MKTAG('A','D','P','C') // Game Sound Chunk
+#define ID_DATA MKTAG('D','a','t','a') // Game Sound Chunk
+#define ID_CUE MKTAG('C','u','e','#') // Game Sound Chunk
// Mohawk MIDI Tags
-#define ID_MIDI MKID_BE('MIDI') // Game Sound (Third Tag), instead of WAVE
-#define ID_PRG MKID_BE('Prg#') // MIDI Patch
+#define ID_MIDI MKTAG('M','I','D','I') // Game Sound (Third Tag), instead of WAVE
+#define ID_PRG MKTAG('P','r','g','#') // MIDI Patch
// Common Resource FourCC's
-#define ID_TBMP MKID_BE('tBMP') // Standard Mohawk Bitmap
-#define ID_TWAV MKID_BE('tWAV') // Standard Mohawk Sound
-#define ID_TPAL MKID_BE('tPAL') // Standard Mohawk Palette
-#define ID_TCNT MKID_BE('tCNT') // Shape Count (CSWorld, CSAmtrak, JamesMath)
-#define ID_TSCR MKID_BE('tSCR') // Script (CSWorld, CSAmtrak, Treehouse)
-#define ID_STRL MKID_BE('STRL') // String List (Zoombini, CSWorld, CSAmtrak)
-#define ID_TBMH MKID_BE('tBMH') // Standard Mohawk Bitmap
-#define ID_TMID MKID_BE('tMID') // Standard Mohawk MIDI
-#define ID_REGS MKID_BE('REGS') // Registration Data - Shape Offsets (Zoombini, Treehouse)
-#define ID_BYTS MKID_BE('BYTS') // Byte Array? (Used as Database Entry in CSWorld, CSAmtrak)
-#define ID_INTS MKID_BE('INTS') // uint16 Array? (CSWorld, CSAmtrak)
-#define ID_BBOX MKID_BE('BBOX') // Boxes? (CSWorld, CSAmtrak)
-#define ID_SYSX MKID_BE('SYSX') // MIDI Sysex
+#define ID_TBMP MKTAG('t','B','M','P') // Standard Mohawk Bitmap
+#define ID_TWAV MKTAG('t','W','A','V') // Standard Mohawk Sound
+#define ID_TPAL MKTAG('t','P','A','L') // Standard Mohawk Palette
+#define ID_TCNT MKTAG('t','C','N','T') // Shape Count (CSWorld, CSAmtrak, JamesMath)
+#define ID_TSCR MKTAG('t','S','C','R') // Script (CSWorld, CSAmtrak, Treehouse)
+#define ID_STRL MKTAG('S','T','R','L') // String List (Zoombini, CSWorld, CSAmtrak)
+#define ID_TBMH MKTAG('t','B','M','H') // Standard Mohawk Bitmap
+#define ID_TMID MKTAG('t','M','I','D') // Standard Mohawk MIDI
+#define ID_REGS MKTAG('R','E','G','S') // Registration Data - Shape Offsets (Zoombini, Treehouse)
+#define ID_BYTS MKTAG('B','Y','T','S') // Byte Array? (Used as Database Entry in CSWorld, CSAmtrak)
+#define ID_INTS MKTAG('I','N','T','S') // uint16 Array? (CSWorld, CSAmtrak)
+#define ID_BBOX MKTAG('B','B','O','X') // Boxes? (CSWorld, CSAmtrak)
+#define ID_SYSX MKTAG('S','Y','S','X') // MIDI Sysex
struct FileTable {
uint32 offset;
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index abc7f5304e..3d496d0f38 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -57,9 +57,10 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
_gameOver = false;
_activatedSLST = false;
_ignoreNextMouseUp = false;
- _extrasFile = NULL;
+ _extrasFile = 0;
_curStack = aspit;
- _hotspots = NULL;
+ _hotspots = 0;
+ removeTimer();
// NOTE: We can never really support CD swapping. All of the music files
// (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive
@@ -89,7 +90,6 @@ MohawkEngine_Riven::~MohawkEngine_Riven() {
delete _extrasFile;
delete _saveLoad;
delete _scriptMan;
- delete[] _vars;
delete _optionsDialog;
delete _rnd;
delete[] _hotspots;
@@ -120,21 +120,44 @@ Common::Error MohawkEngine_Riven::run() {
_externalScriptHandler = new RivenExternal(this);
_optionsDialog = new RivenOptionsDialog(this);
_scriptMan = new RivenScriptManager(this);
- _cursor = new RivenCursorManager();
_rnd = new Common::RandomSource();
g_eventRec.registerRandomSource(*_rnd, "riven");
+ // Create the cursor manager
+ if (Common::File::exists("rivendmo.exe"))
+ _cursor = new PECursorManager("rivendmo.exe");
+ else if (Common::File::exists("riven.exe"))
+ _cursor = new PECursorManager("riven.exe");
+ else // last resort: try the Mac executable
+ _cursor = new MacCursorManager("Riven");
+
initVars();
+ // We need to have a cursor source, or the game won't work
+ if (!_cursor->hasSource()) {
+ Common::String message = "You're missing a Riven executable. The Windows executable is 'riven.exe' or 'rivendmo.exe'. ";
+ message += "Using the 'arcriven.z' installer file also works. In addition, you can use the Mac 'Riven' executable.";
+ GUIErrorMessage(message);
+ warning("%s", message.c_str());
+ return Common::kNoGameDataFoundError;
+ }
+
// Open extras.mhk for common images
_extrasFile = new MohawkArchive();
- if (!_extrasFile->open("extras.mhk"))
- error("Could not open extras.mhk");
+ // We need extras.mhk for inventory images, marble images, and credits images
+ if (!_extrasFile->open("extras.mhk")) {
+ Common::String message = "You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also works.";
+ GUIErrorMessage(message);
+ warning("%s", message.c_str());
+ return Common::kNoGameDataFoundError;
+ }
// Start at main cursor
_cursor->setCursor(kRivenMainCursor);
+ _cursor->showCursor();
+ _system->updateScreen();
// Let's begin, shall we?
if (getFeatures() & GF_DEMO) {
@@ -147,7 +170,12 @@ Common::Error MohawkEngine_Riven::run() {
Common::StringArray savedGamesList = _saveLoad->generateSaveGameList();
if (gameToLoad > savedGamesList.size())
error ("Could not find saved game");
- _saveLoad->loadGame(savedGamesList[gameToLoad]);
+
+ // Attempt to load the game. On failure, just send us to the main menu.
+ if (!_saveLoad->loadGame(savedGamesList[gameToLoad])) {
+ changeToStack(aspit);
+ changeToCard(1);
+ }
} else {
// Otherwise, start us off at aspit's card 1 (the main menu)
changeToStack(aspit);
@@ -162,12 +190,13 @@ Common::Error MohawkEngine_Riven::run() {
}
void MohawkEngine_Riven::handleEvents() {
- Common::Event event;
-
- // Update background videos and the water effect
+ // Update background running things
+ checkTimer();
bool needsUpdate = _gfx->runScheduledWaterEffects();
needsUpdate |= _video->updateMovies();
+ Common::Event event;
+
while (_eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
@@ -353,6 +382,9 @@ void MohawkEngine_Riven::changeToCard(uint16 dest) {
}
void MohawkEngine_Riven::refreshCard() {
+ // Clear any timer still floating around
+ removeTimer();
+
loadHotspots(_curCard);
_gfx->_updatesEnabled = true;
@@ -370,13 +402,15 @@ void MohawkEngine_Riven::refreshCard() {
if (!_activatedSLST)
_sound->playSLST(1, _curCard);
- if (_showHotspots) {
+ if (_showHotspots)
for (uint16 i = 0; i < _hotspotCount; i++)
_gfx->drawRect(_hotspots[i].rect, _hotspots[i].enabled);
- }
// Now we need to redraw the cursor if necessary and handle mouse over scripts
updateCurrentHotspot();
+
+ // Finally, install any hardcoded timer
+ installCardTimer();
}
void MohawkEngine_Riven::loadCard(uint16 id) {
@@ -455,7 +489,7 @@ void MohawkEngine_Riven::updateZipMode() {
for (uint32 i = 0; i < _hotspotCount; i++) {
if (_hotspots[i].zipModeHotspot) {
- if (*getVar("azip") != 0) {
+ if (_vars["azip"] != 0) {
// Check if a zip mode hotspot is enabled by checking the name/id against the ZIPS records.
Common::String hotspotName = getName(HotspotNames, _hotspots[i].name_resource);
@@ -488,10 +522,12 @@ void MohawkEngine_Riven::checkHotspotChange() {
if (_curHotspot != hotspotIndex) {
_curHotspot = hotspotIndex;
_cursor->setCursor(_hotspots[_curHotspot].mouse_cursor);
+ _system->updateScreen();
}
} else {
_curHotspot = -1;
_cursor->setCursor(kRivenMainCursor);
+ _system->updateScreen();
}
}
@@ -540,13 +576,13 @@ void MohawkEngine_Riven::checkInventoryClick() {
return;
// Set the return stack/card id's.
- *getVar("returnstackid") = _curStack;
- *getVar("returncardid") = _curCard;
+ _vars["returnstackid"] = _curStack;
+ _vars["returncardid"] = _curCard;
// See RivenGraphics::showInventory() for an explanation
// of the variables' meanings.
- bool hasCathBook = *getVar("acathbook") != 0;
- bool hasTrapBook = *getVar("atrapbook") != 0;
+ bool hasCathBook = _vars["acathbook"] != 0;
+ bool hasTrapBook = _vars["atrapbook"] != 0;
// Go to the book if a hotspot contains the mouse
if (!hasCathBook) {
@@ -719,6 +755,88 @@ Common::String MohawkEngine_Riven::getStackName(uint16 stack) const {
return rivenStackNames[stack];
}
+void MohawkEngine_Riven::installTimer(TimerProc proc, uint32 time) {
+ removeTimer();
+ _timerProc = proc;
+ _timerTime = time + getTotalPlayTime();
+}
+
+void MohawkEngine_Riven::checkTimer() {
+ if (!_timerProc)
+ return;
+
+ // NOTE: If the specified timer function is called, it is its job to remove the timer!
+ if (getTotalPlayTime() >= _timerTime) {
+ TimerProc proc = _timerProc;
+ proc(this);
+ }
+}
+
+void MohawkEngine_Riven::removeTimer() {
+ _timerProc = 0;
+ _timerTime = 0;
+}
+
+static void catherineIdleTimer(MohawkEngine_Riven *vm) {
+ uint32 &cathCheck = vm->_vars["pcathcheck"];
+ uint32 &cathState = vm->_vars["acathstate"];
+ uint16 movie;
+
+ // Choose a random movie based on where Catherine is
+ if (cathCheck == 0) {
+ static const int movieList[] = { 5, 6, 7, 8 };
+ cathCheck = 1;
+ movie = movieList[vm->_rnd->getRandomNumber(3)];
+ } else if (cathState == 1) {
+ static const int movieList[] = { 11, 14 };
+ movie = movieList[vm->_rnd->getRandomBit()];
+ } else {
+ static const int movieList[] = { 9, 10, 12, 13 };
+ movie = movieList[vm->_rnd->getRandomNumber(3)];
+ }
+
+ // Update her state if she moves from left/right or right/left, resp.
+ if (movie == 5 || movie == 7 || movie == 11 || movie == 14)
+ cathState = 2;
+ else
+ cathState = 1;
+
+ // Play the movie, blocking
+ vm->_video->activateMLST(movie, vm->getCurCard());
+ vm->_cursor->hideCursor();
+ vm->_video->playMovieBlockingRiven(movie);
+ vm->_cursor->showCursor();
+ vm->_system->updateScreen();
+
+ // Install the next timer for the next video
+ uint32 timeUntilNextMovie = vm->_rnd->getRandomNumber(120) * 1000;
+
+ vm->_vars["pcathtime"] = timeUntilNextMovie + vm->getTotalPlayTime();
+
+ vm->installTimer(&catherineIdleTimer, timeUntilNextMovie);
+}
+
+void MohawkEngine_Riven::installCardTimer() {
+ switch (getCurCardRMAP()) {
+ case 0x3a85: // Top of elevator on prison island
+ // Handle Catherine hardcoded videos
+ installTimer(&catherineIdleTimer, _rnd->getRandomNumberRng(1, 33) * 1000);
+ break;
+ case 0x77d6: // Sunners, top of stairs
+ // TODO: Background Sunner videos
+ break;
+ case 0x79bd: // Sunners, middle of stairs
+ // TODO: Background Sunner videos
+ break;
+ case 0x7beb: // Sunners, bottom of stairs
+ // TODO: Background Sunner videos
+ break;
+ case 0xb6ca: // Sunners, shoreline
+ // TODO: Background Sunner videos
+ break;
+ }
+}
+
bool ZipMode::operator== (const ZipMode &z) const {
return z.name == name && z.id == id;
}
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 60a31736d7..3aba5643db 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -32,7 +32,10 @@
#include "gui/saveload.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
#include "common/random.h"
+#include "common/rect.h"
namespace Mohawk {
@@ -104,6 +107,8 @@ struct ZipMode {
bool operator== (const ZipMode& z) const;
};
+typedef Common::HashMap<Common::String, uint32, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> RivenVariableMap;
+
class MohawkEngine_Riven : public MohawkEngine {
protected:
Common::Error run();
@@ -127,6 +132,8 @@ public:
Common::Error saveGameState(int slot, const char *desc);
bool hasFeature(EngineFeature f) const;
+ typedef void (*TimerProc)(MohawkEngine_Riven *vm);
+
private:
MohawkArchive *_extrasFile; // We need a separate handle for the extra data
RivenConsole *_console;
@@ -149,8 +156,11 @@ private:
void checkHotspotChange();
// Variables
- uint32 *_vars;
- uint32 _varCount;
+ void initVars();
+
+ // Timer
+ TimerProc _timerProc;
+ uint32 _timerTime;
// Miscellaneous
bool _gameOver;
@@ -180,13 +190,9 @@ public:
Common::String getHotspotName(uint16 hotspot);
void updateCurrentHotspot();
- // Variable functions
- void initVars();
- uint32 getVarCount() const { return _varCount; }
- uint32 getGlobalVar(uint32 index);
- Common::String getGlobalVarName(uint32 index);
- uint32 *getLocalVar(uint32 index);
- uint32 *getVar(const Common::String &varName);
+ // Variables
+ RivenVariableMap _vars;
+ uint32 &getStackVar(uint32 index);
// Miscellaneous
void setGameOver() { _gameOver = true; }
@@ -195,6 +201,12 @@ public:
bool _activatedSLST;
void runLoadDialog();
void delayAndUpdate(uint32 ms);
+
+ // Timer
+ void installTimer(TimerProc proc, uint32 time);
+ void installCardTimer();
+ void checkTimer();
+ void removeTimer();
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_cursors.h b/engines/mohawk/riven_cursors.h
deleted file mode 100644
index dadfdf0549..0000000000
--- a/engines/mohawk/riven_cursors.h
+++ /dev/null
@@ -1,670 +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.
- *
- * $URL$
- * $Id$
- *
- */
-
-namespace Mohawk {
-
-//////////////////////////////////////////////
-// Cursors and Cursor Palettes
-//////////////////////////////////////////////
-
-////////////////////////////////////////
-// Zip Mode Cursor (16x16):
-// Shown when a zip mode spot is active
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Yellow (0xDCFF00)
-////////////////////////////////////////
-static const byte s_zipModeCursor[] = {
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 2, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 1, 2, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1, 2, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
-};
-
-
-////////////////////////////////////////
-// Zip Mode Cursor Palette:
-// Palette For The Zip Mode Cursor
-////////////////////////////////////////
-static const byte s_zipModeCursorPalette[] = {
- 0x00, 0x00, 0x00, // Black
- 0xDC, 0xFF, 0x00 // Yellow
-};
-
-
-////////////////////////////////////////
-// Hand Over Object Cursor (16x16):
-// Shown when over a hotspot that's interactive
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_objectHandCursor[] = {
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 0, 1, 2, 3, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 0, 0, 0,
- 0, 0, 1, 2, 3, 1, 1, 4, 3, 1, 2, 3, 1, 0, 1, 0,
- 0, 0, 0, 1, 2, 3, 1, 2, 3, 1, 4, 3, 1, 1, 2, 1,
- 0, 0, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1,
- 0, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2, 3, 1, 2, 3, 1,
- 1, 2, 2, 1, 1, 2, 2, 2, 4, 2, 4, 2, 2, 4, 2, 1,
- 1, 3, 4, 2, 1, 2, 4, 2, 2, 2, 2, 2, 4, 4, 1, 0,
- 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0,
- 0, 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 4, 3, 1, 0,
- 0, 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0,
- 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
- 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Grabbing Hand Cursor (13x13):
-// Shown when interacting with an object
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_grabbingHandCursor[] = {
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 2, 3, 1, 1, 1, 0, 0, 0,
- 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 0,
- 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 1,
- 0, 1, 1, 2, 2, 2, 4, 2, 4, 2, 2, 4, 1,
- 1, 2, 1, 2, 4, 2, 2, 2, 2, 2, 4, 4, 1,
- 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1,
- 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 4, 3, 1,
- 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0,
- 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0,
- 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0,
- 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0,
- 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0
-};
-
-
-////////////////////////////////////////
-// Standard Hand Cursor (15x16):
-// Standard Cursor
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_standardHandCursor[] = {
- 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 3, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 1, 2, 4, 1, 1, 1, 1, 1, 0, 0,
- 1, 4, 2, 1, 0, 1, 2, 4, 1, 4, 1, 4, 1, 1, 1,
- 0, 1, 3, 2, 1, 1, 2, 4, 1, 4, 1, 4, 1, 4, 1,
- 0, 0, 1, 4, 2, 1, 2, 2, 4, 2, 4, 2, 1, 4, 1,
- 0, 0, 1, 4, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1,
- 0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1,
- 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1,
- 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Left Cursor (15x13):
-// Cursor When Over A Hotspot That Allows You To Move Left
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingLeftCursor[] = {
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 1, 1, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1,
- 1, 4, 2, 2, 2, 2, 1, 2, 3, 2, 2, 2, 4, 4, 4,
- 1, 4, 4, 4, 4, 4, 1, 2, 1, 3, 4, 2, 2, 2, 2,
- 0, 1, 1, 1, 1, 1, 1, 2, 1, 3, 3, 4, 2, 2, 2,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 4, 4, 2,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 4, 1, 3, 4, 2, 2,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 4, 2, 2,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 4, 2, 4,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
- 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Right Cursor (15x13):
-// Cursor When Over A Hotspot That Allows You To Move Right
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingRightCursor[] = {
- 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0,
- 1, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0,
- 4, 4, 4, 2, 2, 2, 3, 2, 1, 4, 4, 4, 4, 4, 1,
- 2, 2, 2, 2, 4, 3, 1, 2, 1, 2, 2, 2, 2, 4, 1,
- 2, 2, 2, 4, 3, 3, 1, 2, 1, 1, 1, 1, 1, 1, 0,
- 2, 4, 4, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 2, 2, 4, 3, 1, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 2, 2, 4, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 4, 2, 4, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 1, 4, 4, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Down Cursor (Palm Up)(13x16):
-// Cursor When Over A Hotspot That Allows You To Move Down
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingDownCursorPalmUp[] = {
- 0, 0, 1, 4, 2, 2, 2, 2, 2, 4, 1, 0, 0,
- 0, 0, 1, 4, 2, 2, 4, 2, 2, 2, 4, 1, 0,
- 0, 1, 3, 4, 2, 2, 4, 4, 4, 4, 4, 1, 0,
- 0, 1, 4, 2, 2, 4, 3, 3, 3, 1, 1, 1, 1,
- 1, 2, 2, 2, 4, 3, 3, 1, 1, 2, 1, 2, 1,
- 1, 2, 2, 2, 3, 3, 3, 4, 1, 2, 1, 2, 1,
- 1, 2, 2, 3, 1, 1, 1, 2, 1, 2, 1, 2, 1,
- 1, 3, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1,
- 0, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1,
- 0, 0, 1, 2, 4, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Up Cursor (Palm Up)(13x16):
-// Cursor When Over A Hotspot That Allows You To Move Up
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingUpCursorPalmUp[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 2, 4, 1, 0, 0,
- 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 0,
- 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 3, 1,
- 1, 2, 1, 2, 1, 2, 1, 1, 1, 3, 2, 2, 1,
- 1, 2, 1, 2, 1, 4, 3, 3, 3, 2, 2, 2, 1,
- 1, 2, 1, 2, 1, 1, 3, 3, 4, 2, 2, 2, 1,
- 1, 1, 1, 1, 3, 3, 3, 4, 2, 2, 4, 1, 0,
- 0, 1, 4, 4, 4, 4, 4, 2, 2, 4, 3, 1, 0,
- 0, 1, 4, 2, 2, 2, 4, 2, 2, 4, 1, 0, 0,
- 0, 0, 1, 4, 2, 2, 2, 2, 2, 4, 1, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Left Cursor (Bent)(15x13):
-// Cursor When Over A Hotspot That Allows You To Turn Left 180 Degrees
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingLeftCursorBent[] = {
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 1, 1, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1,
- 1, 3, 2, 4, 4, 2, 1, 2, 3, 3, 2, 2, 4, 4, 4,
- 1, 2, 4, 3, 3, 4, 1, 2, 1, 3, 4, 2, 2, 2, 2,
- 1, 4, 4, 1, 1, 1, 1, 2, 1, 1, 3, 4, 2, 2, 2,
- 1, 1, 1, 0, 0, 1, 1, 1, 1, 3, 3, 3, 4, 4, 2,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 4, 1, 3, 4, 3, 2,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 4, 2, 2,
- 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 4, 2, 4,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
- 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Right Cursor (Bent)(15x13):
-// Cursor When Over A Hotspot That Allows You To Turn Right 180 Degrees
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingRightCursorBent[] = {
- 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0,
- 1, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0,
- 4, 4, 4, 2, 2, 3, 3, 2, 1, 2, 4, 4, 2, 3, 1,
- 2, 2, 2, 2, 4, 3, 1, 2, 1, 4, 3, 3, 4, 2, 1,
- 2, 2, 2, 4, 3, 1, 1, 2, 1, 1, 1, 1, 4, 4, 1,
- 2, 4, 4, 3, 3, 3, 1, 1, 1, 1, 0, 0, 1, 1, 1,
- 2, 3, 4, 3, 1, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 2, 2, 4, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 4, 2, 4, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 1, 4, 4, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Pointing Down Cursor (Palm Down)(15x16):
-// Similar to Standard Cursor
-//
-// 0 = Transparent
-// 1 = Black (0x000000)
-// 2 = Light Peach (0xEDCD96)
-// 3 = Brown (0x8A672F)
-// 4 = Dark Peach (0xE89A62)
-////////////////////////////////////////
-static const byte s_pointingDownCursorPalmDown[] = {
- 0, 1, 3, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 1, 3, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
- 1, 3, 4, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
- 1, 3, 4, 2, 2, 2, 2, 2, 2, 2, 4, 1, 0, 0, 0,
- 1, 3, 2, 3, 2, 2, 2, 2, 2, 1, 2, 4, 1, 0, 0,
- 1, 4, 1, 2, 2, 3, 2, 3, 2, 1, 2, 4, 1, 0, 0,
- 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 1, 2, 3, 1, 0,
- 0, 1, 1, 4, 1, 4, 1, 4, 2, 1, 0, 1, 2, 4, 1,
- 0, 0, 1, 1, 1, 1, 1, 4, 2, 1, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 4, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 4, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 3, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Hand Cursor Palette:
-// Palette For All Hand Cursors
-////////////////////////////////////////
-static const byte s_handCursorPalette[] = {
- 0x00, 0x00, 0x00, // Black
- 0xED, 0xCD, 0x96, // Light Peach
- 0x8A, 0x67, 0x2F, // Brown
- 0xE8, 0x9A, 0x62 // Dark Peach
-};
-
-
-////////////////////////////////////////
-// Pellet Cursor (8x8):
-// Cursor When Using The Pellet In The Frog Trap
-//
-// 0 = Transparent
-// 1 = Light Olive Green (0x5D6730)
-// 2 = Maroon (0x5E3333)
-// 3 = Light Gray (0x555555)
-// 4 = Medium Gray (0x444444)
-// 5 = Dark Gray (0x333333)
-// 6 = Dark Green (0x2D3300)
-// 7 = Darkest Gray (0x222222)
-////////////////////////////////////////
-static const byte s_pelletCursor[] = {
- 0, 0, 1, 1, 2, 3, 0, 0,
- 0, 2, 1, 4, 1, 2, 5, 0,
- 4, 1, 4, 1, 2, 1, 5, 4,
- 4, 2, 1, 2, 1, 1, 2, 6,
- 6, 4, 2, 1, 4, 4, 1, 5,
- 5, 6, 5, 2, 1, 2, 4, 4,
- 0, 7, 5, 5, 4, 2, 5, 0,
- 0, 0, 5, 6, 6, 5, 0, 0
-};
-
-////////////////////////////////////////
-// Pellet Cursor Palette:
-// Palette For The Pellet Cursor
-////////////////////////////////////////
-static const byte s_pelletCursorPalette[] = {
- 0x5D, 0x67, 0x30,
- 0x5E, 0x33, 0x33,
- 0x55, 0x55, 0x55,
- 0x44, 0x44, 0x44,
- 0x33, 0x33, 0x33,
- 0x2D, 0x33, 0x00,
- 0x22, 0x22, 0x22
-};
-
-////////////////////////////////////////
-// Red Marble Cursor (12x12):
-// Cursor When Holding The Red Marble
-////////////////////////////////////////
-static const byte s_redMarbleCursor[] = {
- 0, 0, 0, 0, 1, 2, 2, 2, 0, 0, 0, 0,
- 0, 0, 3, 4, 2, 5, 2, 2, 2, 2, 0, 0,
- 0, 6, 1, 1, 2, 2, 5, 2, 2, 2, 2, 0,
- 0, 6, 3, 4, 5, 2, 2, 7, 8, 5, 2, 0,
- 9, 6, 10,11,2, 2, 2, 12,13,2, 2, 2,
- 14,10,6, 4, 1, 2, 8, 2, 2, 5, 2, 2,
- 15,16,6, 3, 1, 2, 2, 2, 2, 2, 2, 5,
- 17,9,18, 3, 4, 4, 4, 5, 2, 5, 1, 2,
- 0, 16,9, 6, 6, 19,1, 20,1, 4, 11,0,
- 0, 17,15,18,9, 10,6, 10,3, 21,4, 0,
- 0, 0, 18,15,9, 18,6, 22,10,23,0, 0,
- 0, 0, 0, 0, 15,15,16,9, 0, 0, 0, 0
-};
-
-
-////////////////////////////////////////
-// Red Marble Cursor Palette:
-// Palette For The Red Marble Cursor
-////////////////////////////////////////
-static const byte s_redMarbleCursorPalette[] = {
- 0xb8, 0x33, 0x32,
- 0xe5, 0x33, 0x31,
- 0x98, 0x06, 0x00,
- 0xb8, 0x00, 0x34,
- 0xe6, 0x00, 0x34,
- 0x7a, 0x04, 0x00,
- 0xe8, 0x9a, 0x62,
- 0xea, 0x31, 0x67,
- 0x6a, 0x03, 0x00,
- 0x8c, 0x00, 0x35,
- 0xb6, 0x36, 0x00,
- 0xed, 0xcd, 0x96,
- 0xe9, 0x66, 0x65,
- 0x5b, 0x35, 0x00,
- 0x5b, 0x02, 0x00,
- 0x5f, 0x00, 0x35,
- 0x4c, 0x01, 0x00,
- 0x5e, 0x33, 0x33,
- 0x89, 0x05, 0x00,
- 0xb6, 0x08, 0x00,
- 0xa7, 0x07, 0x00,
- 0x88, 0x36, 0x00,
- 0x8b, 0x33, 0x33
-};
-
-////////////////////////////////////////
-// Orange Marble Cursor (12x12):
-// Cursor When Holding The Orange Marble
-////////////////////////////////////////
-static const byte s_orangeMarbleCursor[] = {
- 0, 0, 0, 0, 1, 2, 2, 3, 0, 0, 0, 0,
- 0, 0, 4, 5, 2, 2, 3, 3, 3, 3, 0, 0,
- 0, 6, 7, 4, 2, 1, 2, 2, 3, 3, 3, 0,
- 0, 6, 6, 7, 1, 2, 3, 8, 9, 2, 10,0,
- 11,12,7, 4, 2, 3, 3, 13,9, 2, 2, 1,
- 14,15,6, 4, 2, 16,3, 3, 2, 1, 1, 1,
- 14,14,12,17,4, 2, 2, 1, 2, 1, 2, 1,
- 14,18,12,6, 4, 4, 4, 19,2, 19,20,4,
- 0, 14,14,15,6, 15,6, 4, 4, 4, 4, 0,
- 0, 14,11,14,14,12,12,12,17,6, 17,0,
- 0, 0, 14,14,17,14,17,6, 6, 17,0, 0,
- 0, 0, 0, 0, 14,11,14,11,0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Orange Marble Cursor Palette:
-// Palette For The Orange Marble Cursor
-////////////////////////////////////////
-static const byte s_orangeMarbleCursorPalette[] = {
- 0xe1, 0x9e, 0x00,
- 0xe3, 0x9b, 0x28,
- 0xe2, 0xcf, 0x20,
- 0xb5, 0x6a, 0x00,
- 0xb6, 0x9b, 0x29,
- 0x87, 0x69, 0x00,
- 0xb7, 0x67, 0x2f,
- 0xe9, 0xff, 0x93,
- 0xe1, 0xff, 0x5a,
- 0xe0, 0xd0, 0x00,
- 0x5e, 0x33, 0x33,
- 0x88, 0x36, 0x00,
- 0xf3, 0xff, 0xc9,
- 0x5b, 0x35, 0x00,
- 0x8b, 0x33, 0x33,
- 0xe6, 0xce, 0x5f,
- 0x8a, 0x67, 0x2f,
- 0x5d, 0x67, 0x30,
- 0xe2, 0x6a, 0x00,
- 0xb3, 0x9d, 0x00
-};
-
-////////////////////////////////////////
-// Yellow Marble Cursor (12x12):
-// Cursor When Holding The Yellow Marble
-////////////////////////////////////////
-static const byte s_yellowMarbleCursor[] = {
- 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0,
- 0, 0, 3, 4, 1, 1, 1, 5, 6, 6, 0, 0,
- 0, 3, 3, 7, 1, 1, 1, 1, 2, 1, 6, 0,
- 0, 3, 3, 3, 3, 1, 1, 8, 6, 1, 6, 0,
- 9, 9, 3, 3, 1, 1, 2, 10,8, 1, 1, 2,
- 11,9, 3, 3, 1, 1, 1, 1, 1, 1, 5, 1,
- 9, 9, 12,3, 3, 1, 1, 1, 1, 1, 1, 1,
- 9, 9, 9, 3, 3, 3, 3, 3, 1, 1, 1, 1,
- 0, 11,9, 9, 12,3, 3, 3, 3, 3, 3, 0,
- 0, 9, 9, 13,9, 14,12,3, 3, 3, 3, 0,
- 0, 0, 9, 9, 9, 12,14,3, 13,3, 0, 0,
- 0, 0, 0, 0, 11,9, 11,9, 0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Yellow Marble Cursor Palette:
-// Palette For The Yellow Marble Cursor
-////////////////////////////////////////
-static const byte s_yellowMarbleCursorPalette[] = {
- 0xb3, 0xd0, 0x00,
- 0xb0, 0xff, 0x00,
- 0x86, 0x9c, 0x00,
- 0x87, 0xd0, 0x00,
- 0xe0, 0xd0, 0x00,
- 0xdc, 0xff, 0x00,
- 0xb3, 0x9d, 0x00,
- 0xdc, 0xff, 0x11,
- 0x5a, 0x68, 0x00,
- 0xe1, 0xff, 0x5a,
- 0x5d, 0x67, 0x30,
- 0x87, 0x69, 0x00,
- 0x88, 0x9b, 0x2a,
- 0x5a, 0x9c, 0x00
-};
-
-////////////////////////////////////////
-// Green Marble Cursor (12x12):
-// Cursor When Holding The Green Marble
-////////////////////////////////////////
-static const byte s_greenMarbleCursor[] = {
- 0, 0, 0, 0, 1, 2, 3, 3, 0, 0, 0, 0,
- 0, 0, 4, 5, 2, 1, 2, 3, 6, 6, 0, 0,
- 0, 7, 5, 8, 8, 1, 1, 2, 3, 6, 6, 0,
- 0, 7, 7, 4, 8, 1, 2, 9, 6, 2, 6, 0,
- 10,7, 7, 4, 1, 2, 3, 11,12,2, 2, 3,
- 13,13,7, 4, 1, 2, 3, 2, 1, 2, 2, 3,
- 14,13,7, 7, 5, 1, 1, 8, 2, 1, 1, 2,
- 15,16,13,7, 4, 4, 5, 5, 1, 8, 1, 1,
- 0, 15,13,7, 7, 7, 4, 4, 4, 5, 8, 0,
- 0, 14,16,15,13, 7, 7, 7, 4,17,5, 0,
- 0, 0, 10,16,13,13,13,17,18,17,0, 0,
- 0, 0, 0, 0, 15,10,19,10,0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Green Marble Cursor Palette:
-// Palette For The Green Marble Cursor
-////////////////////////////////////////
-static const byte s_greenMarbleCursorPalette[] = {
- 0x0e, 0xd0, 0x00,
- 0x0f, 0xe1, 0x00,
- 0x10, 0xf2, 0x00,
- 0x0b, 0x9c, 0x00,
- 0x0c, 0xad, 0x00,
- 0x11, 0xff, 0x00,
- 0x09, 0x8a, 0x00,
- 0x0d, 0xbe, 0x00,
- 0x30, 0xff, 0x5a,
- 0x0d, 0x67, 0x30,
- 0x6b, 0xff, 0x92,
- 0x00, 0xff, 0x28,
- 0x08, 0x79, 0x00,
- 0x05, 0x57, 0x00,
- 0x30, 0x67, 0x30,
- 0x06, 0x68, 0x00,
- 0x00, 0x9b, 0x2c,
- 0x2e, 0x9c, 0x00,
- 0x2e, 0x68, 0x00
-};
-
-////////////////////////////////////////
-// Blue Marble Cursor (12x12):
-// Cursor When Holding The Blue Marble
-////////////////////////////////////////
-static const byte s_blueMarbleCursor[] = {
- 0, 0, 0, 0, 1, 2, 3, 3, 0, 0, 0, 0,
- 0, 0, 4, 5, 2, 2, 6, 3, 7, 3, 0, 0,
- 0, 8, 9, 5, 10,11,2, 6, 3, 3, 7, 0,
- 0, 12,13,9, 10,11,6, 14,7, 6, 3, 0,
- 15,8, 4, 13,2, 6, 3, 16,17,6, 6, 3,
- 18,15,19,13,10,7, 3, 6, 2, 2, 6, 7,
- 20,8, 18,4, 21,11,2, 10,6, 2, 2, 2,
- 15,15,18,8, 13,9, 21,5, 11,10,2, 1,
- 0, 8, 15,19,15,13,13,21,21,5, 9, 0,
- 0, 22,20,15, 8,19,15,19,4, 9, 4, 0,
- 0, 0, 15,20,15,15,19,15,9, 15,0, 0,
- 0, 0, 0, 0, 20,15, 8,15,0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Blue Marble Cursor Palette:
-// Palette For The Blue Marble Cursor
-////////////////////////////////////////
-static const byte s_blueMarbleCursorPalette[] = {
- 0x6b, 0x00, 0xd2,
- 0x66, 0x00, 0xe3,
- 0x72, 0x00, 0xff,
- 0x53, 0x2d, 0x9d,
- 0x4e, 0x00, 0xaf,
- 0x6d, 0x00, 0xf5,
- 0x7d, 0x00, 0xff,
- 0x44, 0x00, 0x69,
- 0x56, 0x00, 0x9d,
- 0x56, 0x00, 0xc0,
- 0x5e, 0x00, 0xd2,
- 0x2b, 0x31, 0x68,
- 0x3f, 0x00, 0x8c,
- 0x91, 0x22, 0xff,
- 0x41, 0x31, 0x68,
- 0xd7, 0x95, 0xff,
- 0x77, 0x22, 0xff,
- 0x2f, 0x00, 0x69,
- 0x37, 0x00, 0x7a,
- 0x27, 0x00, 0x58,
- 0x46, 0x00, 0x9d,
- 0x33, 0x33, 0x33
-};
-
-////////////////////////////////////////
-// Violet Marble Cursor (12x12):
-// Cursor When Holding The Violet Marble
-////////////////////////////////////////
-static const byte s_violetMarbleCursor[] = {
- 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0,
- 0, 0, 3, 3, 1, 1, 1, 4, 2, 4, 0, 0,
- 0, 3, 3, 3, 1, 5, 1, 1, 4, 2, 4, 0,
- 0, 3, 3, 3, 3, 1, 1, 6, 4, 1, 2, 0,
- 3, 7, 8, 3, 1, 1, 4, 9, 4, 1, 1, 4,
- 8, 7, 8, 3, 10,4, 1, 1, 1, 1, 4, 1,
- 8, 3, 8, 7, 3, 1, 1, 5, 1, 1, 1, 1,
- 7, 7, 11,3, 3, 3, 3, 3, 1, 3, 1, 1,
- 0, 8, 7, 7, 8, 8, 7, 3, 3, 3, 1, 0,
- 0, 7, 8, 3, 11,7, 3, 11,3, 10,3, 0,
- 0, 0, 8, 7, 3, 3, 7, 3, 3, 3, 0, 0,
- 0, 0, 0, 0, 8, 7, 11,3, 0, 0, 0, 0
-};
-
-////////////////////////////////////////
-// Violet Marble Cursor Palette:
-// Palette For The Violet Marble Cursor
-////////////////////////////////////////
-static const byte s_violetMarbleCursorPalette[] = {
- 0xaa, 0x00, 0xd1,
- 0xd8, 0x00, 0xff,
- 0x76, 0x00, 0x9d,
- 0xb5, 0x00, 0xff,
- 0x87, 0x00, 0xd2,
- 0xd7, 0x22, 0xff,
- 0x68, 0x00, 0x69,
- 0x44, 0x00, 0x69,
- 0xd7, 0x5e, 0xff,
- 0x9c, 0x00, 0x9d,
- 0x56, 0x00, 0x9d
-};
-
-} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 7da5515411..dc0d66f19b 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -32,6 +32,7 @@
#include "gui/message.h"
#include "common/events.h"
+#include "common/system.h"
namespace Mohawk {
@@ -216,20 +217,37 @@ void RivenExternal::runDemoBoundaryDialog() {
dialog.runModal();
}
-void RivenExternal::runEndGame(uint16 video) {
+void RivenExternal::runEndGame(uint16 video, uint32 delay) {
_vm->_sound->stopAllSLST();
_vm->_video->playMovieRiven(video);
- runCredits(video);
+ runCredits(video, delay);
}
-void RivenExternal::runCredits(uint16 video) {
- // TODO: Play until the last frame and then run the credits
+void RivenExternal::runCredits(uint16 video, uint32 delay) {
+ // Initialize our credits state
+ _vm->_cursor->hideCursor();
+ _vm->_gfx->beginCredits();
+ uint nextCreditsFrameStart = 0;
VideoHandle videoHandle = _vm->_video->findVideoHandleRiven(video);
- while (!_vm->_video->endOfVideo(videoHandle) && !_vm->shouldQuit()) {
- if (_vm->_video->updateMovies())
- _vm->_system->updateScreen();
+ while (!_vm->shouldQuit() && _vm->_gfx->getCurCreditsImage() <= 320) {
+ if (_vm->_video->getCurFrame(videoHandle) >= (int32)_vm->_video->getFrameCount(videoHandle) - 1) {
+ if (nextCreditsFrameStart == 0) {
+ // Set us up to start after delay ms
+ nextCreditsFrameStart = _vm->_system->getMillis() + delay;
+ } else if (_vm->_system->getMillis() >= nextCreditsFrameStart) {
+ // the first two frames stay on for 5 seconds
+ // the rest of the scroll updates happen at 30Hz
+ if (_vm->_gfx->getCurCreditsImage() < 304)
+ nextCreditsFrameStart = _vm->_system->getMillis() + 5000;
+ else
+ nextCreditsFrameStart = _vm->_system->getMillis() + 1000 / 30;
+
+ _vm->_gfx->updateCredits();
+ }
+ } else if (_vm->_video->updateMovies())
+ _vm->_system->updateScreen();
Common::Event event;
while (_vm->_system->getEventManager()->pollEvent(event))
@@ -259,7 +277,7 @@ void RivenExternal::runDomeCheck() {
// frame that is the magic one is the one with the golden symbol) but we
// give a 3 frame leeway in either direction.
if (frameCount - curFrame < 3 || curFrame < 3)
- *_vm->getVar("domecheck") = 1;
+ _vm->_vars["domecheck"] = 1;
}
void RivenExternal::resetDomeSliders(uint16 soundId, uint16 startHotspot) {
@@ -297,7 +315,7 @@ void RivenExternal::resetDomeSliders(uint16 soundId, uint16 startHotspot) {
void RivenExternal::checkDomeSliders(uint16 resetSlidersHotspot, uint16 openDomeHotspot) {
// Let's see if we're all matched up...
- if (*_vm->getVar("adomecombo") == _sliderState) {
+ if (_vm->_vars["adomecombo"] == _sliderState) {
// Set the button hotspot to the open dome hotspot
_vm->_hotspots[resetSlidersHotspot].enabled = false;
_vm->_hotspots[openDomeHotspot].enabled = true;
@@ -316,6 +334,7 @@ void RivenExternal::checkSliderCursorChange(uint16 startHotspot) {
_vm->_cursor->setCursor(kRivenOpenHandCursor);
else
_vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
break;
}
}
@@ -341,6 +360,7 @@ void RivenExternal::dragDomeSlider(uint16 soundId, uint16 resetSlidersHotspot, u
// We've clicked down, so show the closed hand cursor
_vm->_cursor->setCursor(kRivenClosedHandCursor);
+ _vm->_system->updateScreen();
bool done = false;
while (!done) {
@@ -427,7 +447,7 @@ void RivenExternal::xasetupcomplete(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->getVar("aatruspage");
+ uint32 &page = _vm->_vars["aatruspage"];
// Set hotspots depending on the page
if (page == 1) {
@@ -446,18 +466,18 @@ void RivenExternal::xaatrusopenbook(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- _vm->changeToStack(*_vm->getVar("returnstackid"));
- _vm->changeToCard(*_vm->getVar("returncardid"));
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
}
void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("aatruspage");
+ uint32 &page = _vm->_vars["aatruspage"];
// Decrement the page if it's not the first page
- if (*page == 1)
+ if (page == 1)
return;
- (*page)--;
+ page--;
// Play the page turning sound
if (_vm->getFeatures() & GF_DEMO)
@@ -472,12 +492,12 @@ void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("aatruspage");
+ uint32 &page = _vm->_vars["aatruspage"];
// Increment the page if it's not the last page
- if (((_vm->getFeatures() & GF_DEMO) && *page == 6) || *page == 10)
+ if (((_vm->getFeatures() & GF_DEMO) && page == 6) || page == 10)
return;
- (*page)++;
+ page++;
// Play the page turning sound
if (_vm->getFeatures() & GF_DEMO)
@@ -492,7 +512,7 @@ void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->getVar("acathpage");
+ uint32 page = _vm->_vars["acathpage"];
// Set hotspots depending on the page
if (page == 1) {
@@ -518,7 +538,7 @@ void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
// Draw the telescope combination
// The images for the numbers are tBMP's 13 through 17.
// The start point is at (156, 247)
- uint32 teleCombo = *_vm->getVar("tcorrectorder");
+ uint32 teleCombo = _vm->_vars["tcorrectorder"];
static const uint16 kNumberWidth = 32;
static const uint16 kNumberHeight = 25;
static const uint16 kDstX = 156;
@@ -535,18 +555,18 @@ void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
void RivenExternal::xacathbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- _vm->changeToStack(*_vm->getVar("returnstackid"));
- _vm->changeToCard(*_vm->getVar("returncardid"));
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
}
void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 *page = _vm->getVar("acathpage");
+ uint32 &page = _vm->_vars["acathpage"];
// Increment the page if it's not the first page
- if (*page == 1)
+ if (page == 1)
return;
- (*page)--;
+ page--;
// Play the page turning sound
_vm->_sound->playSound(5);
@@ -558,12 +578,12 @@ void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 *page = _vm->getVar("acathpage");
+ uint32 &page = _vm->_vars["acathpage"];
// Increment the page if it's not the last page
- if (*page == 49)
+ if (page == 49)
return;
- (*page)++;
+ page++;
// Play the page turning sound
_vm->_sound->playSound(6);
@@ -575,14 +595,14 @@ void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
void RivenExternal::xtrapbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- *_vm->getVar("atrap") = 0;
- _vm->changeToStack(*_vm->getVar("returnstackid"));
- _vm->changeToCard(*_vm->getVar("returncardid"));
+ _vm->_vars["atrap"] = 0;
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
}
void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) {
// Close the trap book
- *_vm->getVar("atrap") = 0;
+ _vm->_vars["atrap"] = 0;
// Play the page turning sound
_vm->_sound->playSound(8);
@@ -592,7 +612,7 @@ void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) {
void RivenExternal::xatrapbookopen(uint16 argc, uint16 *argv) {
// Open the trap book
- *_vm->getVar("atrap") = 1;
+ _vm->_vars["atrap"] = 1;
// Play the page turning sound
_vm->_sound->playSound(9);
@@ -686,7 +706,7 @@ void RivenExternal::xaexittomain(uint16 argc, uint16 *argv) {
void RivenExternal::xblabopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->getVar("blabpage");
+ uint32 page = _vm->_vars["blabpage"];
// Draw the image of the page based on the blabbook variable
_vm->_gfx->drawPLST(page);
@@ -695,7 +715,7 @@ void RivenExternal::xblabopenbook(uint16 argc, uint16 *argv) {
// Draw the dome combination
// The images for the numbers are tBMP's 364 through 368
// The start point is at (240, 82)
- uint32 domeCombo = *_vm->getVar("adomecombo");
+ uint32 domeCombo = _vm->_vars["adomecombo"];
static const uint16 kNumberWidth = 32;
static const uint16 kNumberHeight = 24;
static const uint16 kDstX = 240;
@@ -718,12 +738,12 @@ void RivenExternal::xblabopenbook(uint16 argc, uint16 *argv) {
void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("blabpage");
+ uint32 &page = _vm->_vars["blabpage"];
// Decrement the page if it's not the first page
- if (*page == 1)
+ if (page == 1)
return;
- (*page)--;
+ page--;
// Play the page turning sound
_vm->_sound->playSound(22);
@@ -735,12 +755,12 @@ void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("blabpage");
+ uint32 &page = _vm->_vars["blabpage"];
// Increment the page if it's not the last page
- if (*page == 22)
+ if (page == 22)
return;
- (*page)++;
+ page++;
// Play the page turning sound
_vm->_sound->playSound(23);
@@ -751,21 +771,18 @@ void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
}
void RivenExternal::xsoundplug(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->getVar("bheat");
- uint32 boilerInactive = *_vm->getVar("bcratergg");
-
- if (heat != 0)
+ if (_vm->_vars["bheat"] != 0)
_vm->_sound->playSLST(1, _vm->getCurCard());
- else if (boilerInactive != 0)
+ else if (_vm->_vars["bcratergg"] != 0)
_vm->_sound->playSLST(2, _vm->getCurCard());
else
_vm->_sound->playSLST(3, _vm->getCurCard());
}
void RivenExternal::xbchangeboiler(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->getVar("bheat");
- uint32 water = *_vm->getVar("bblrwtr");
- uint32 platform = *_vm->getVar("bblrgrt");
+ uint32 heat = _vm->_vars["bheat"];
+ uint32 water = _vm->_vars["bblrwtr"];
+ uint32 platform = _vm->_vars["bblrgrt"];
// Stop any background videos
_vm->_video->stopVideos();
@@ -834,11 +851,8 @@ void RivenExternal::xbchangeboiler(uint16 argc, uint16 *argv) {
}
void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->getVar("bheat");
- uint32 platform = *_vm->getVar("bblrgrt");
-
- if (heat) {
- if (platform == 0) {
+ if (_vm->_vars["bheat"] != 0) {
+ if (_vm->_vars["bblrgrt"] == 0) {
_vm->_video->activateMLST(8, _vm->getCurCard());
_vm->_video->playMovieRiven(8);
} else {
@@ -851,17 +865,63 @@ void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) {
}
}
+static void ytramTrapTimer(MohawkEngine_Riven *vm) {
+ // Remove this timer
+ vm->removeTimer();
+
+ // Check if we've caught a Ytram
+ vm->_externalScriptHandler->checkYtramCatch(true);
+}
+
void RivenExternal::xbsettrap(uint16 argc, uint16 *argv) {
- // TODO: Set the Ytram trap
+ // Set the Ytram trap
+
+ // We can catch the Ytram between 10 seconds and 3 minutes from now
+ uint32 timeUntilCatch = _vm->_rnd->getRandomNumberRng(10, 60 * 3) * 1000;
+ _vm->_vars["bytramtime"] = timeUntilCatch + _vm->getTotalPlayTime();
+
+ // And set the timer too
+ _vm->installTimer(&ytramTrapTimer, timeUntilCatch);
+}
+
+void RivenExternal::checkYtramCatch(bool playSound) {
+ // Check if we've caught a Ytram
+
+ uint32 &ytramTime = _vm->_vars["bytramtime"];
+
+ // If the trap still has not gone off, reinstall our timer
+ // This is in case you set the trap, walked away, and returned
+ if (_vm->getTotalPlayTime() < ytramTime) {
+ _vm->installTimer(&ytramTrapTimer, ytramTime - _vm->getTotalPlayTime());
+ return;
+ }
+
+ // Increment the movie per catch (max = 3)
+ uint32 &ytramMovie = _vm->_vars["bytram"];
+ ytramMovie++;
+ if (ytramMovie > 3)
+ ytramMovie = 3;
+
+ // Reset variables
+ _vm->_vars["bytrapped"] = 1;
+ _vm->_vars["bbait"] = 0;
+ _vm->_vars["bytrap"] = 0;
+ ytramTime = 0;
+
+ // Play the capture sound, if requested
+ if (playSound)
+ _vm->_sound->playSound(33);
}
void RivenExternal::xbcheckcatch(uint16 argc, uint16 *argv) {
- // TODO: Check if we've caught a Ytram
+ // Just pass our parameter along...
+ checkYtramCatch(argv[0] != 0);
}
void RivenExternal::xbait(uint16 argc, uint16 *argv) {
// Set the cursor to the pellet
_vm->_cursor->setCursor(kRivenPelletCursor);
+ _vm->_system->updateScreen();
// Loop until the player lets go (or quits)
Common::Event event;
@@ -881,10 +941,11 @@ void RivenExternal::xbait(uint16 argc, uint16 *argv) {
// Set back the cursor
_vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
// Set the bait if we put it on the plate
if (_vm->_hotspots[9].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
- *_vm->getVar("bbait") = 1;
+ _vm->_vars["bbait"] = 1;
_vm->_gfx->drawPLST(4);
_vm->_gfx->updateScreen();
_vm->_hotspots[3].enabled = false; // Disable bait hotspot
@@ -893,14 +954,35 @@ void RivenExternal::xbait(uint16 argc, uint16 *argv) {
}
void RivenExternal::xbfreeytram(uint16 argc, uint16 *argv) {
- // TODO: Play a random Ytram movie
+ // Play a random Ytram movie after freeing it
+ uint16 mlstId;
+
+ switch (_vm->_vars["bytram"]) {
+ case 1:
+ mlstId = 11;
+ break;
+ case 2:
+ mlstId = 12;
+ break;
+ default:
+ mlstId = _vm->_rnd->getRandomNumberRng(13, 15);
+ break;
+ }
+
+ // Activate the MLST and play the video
+ _vm->_video->activateMLST(mlstId, _vm->getCurCard());
+ _vm->_video->playMovieBlockingRiven(11);
+
+ // Now play the second movie
+ _vm->_video->activateMLST(mlstId + 5, _vm->getCurCard());
+ _vm->_video->playMovieBlockingRiven(12);
}
void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) {
// Remove the pellet from the plate and put it in your hand
_vm->_gfx->drawPLST(3);
- _vm->_gfx->updateScreen();
_vm->_cursor->setCursor(kRivenPelletCursor);
+ _vm->_gfx->updateScreen();
// Loop until the player lets go (or quits)
Common::Event event;
@@ -920,16 +1002,17 @@ void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) {
// Set back the cursor
_vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
// Set the bait if we put it on the plate, remove otherwise
if (_vm->_hotspots[9].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
- *_vm->getVar("bbait") = 1;
+ _vm->_vars["bbait"] = 1;
_vm->_gfx->drawPLST(4);
_vm->_gfx->updateScreen();
_vm->_hotspots[3].enabled = false; // Disable bait hotspot
_vm->_hotspots[9].enabled = true; // Enable baitplate hotspot
} else {
- *_vm->getVar("bbait") = 0;
+ _vm->_vars["bbait"] = 0;
_vm->_hotspots[3].enabled = true; // Enable bait hotspot
_vm->_hotspots[9].enabled = false; // Disable baitplate hotspot
}
@@ -963,7 +1046,7 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
Common::Point startPos = _vm->_system->getEventManager()->getMousePos();
// Get the variable for the valve
- uint32 *valve = _vm->getVar("bvalve");
+ uint32 &valve = _vm->_vars["bvalve"];
int changeX = 0;
int changeY = 0;
@@ -985,26 +1068,30 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
break;
case Common::EVENT_LBUTTONUP:
// FIXME: These values for changes in x/y could be tweaked.
- if (*valve == 0 && changeY <= -10) {
- *valve = 1;
+ if (valve == 0 && changeY <= -10) {
+ valve = 1;
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_video->playMovieBlockingRiven(2);
_vm->refreshCard();
- } else if (*valve == 1) {
+ } else if (valve == 1) {
if (changeX >= 0 && changeY >= 10) {
- *valve = 0;
+ valve = 0;
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_video->playMovieBlockingRiven(3);
_vm->refreshCard();
} else if (changeX <= -10 && changeY <= 10) {
- *valve = 2;
+ valve = 2;
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_video->playMovieBlockingRiven(1);
_vm->refreshCard();
}
- } else if (*valve == 2 && changeX >= 10) {
- *valve = 1;
+ } else if (valve == 2 && changeX >= 10) {
+ valve = 1;
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_video->playMovieBlockingRiven(4);
_vm->refreshCard();
}
@@ -1018,27 +1105,27 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
// If we changed state and the new state is that the valve is flowing to
// the boiler, we need to update the boiler state.
- if (*valve == 1) {
- if (*_vm->getVar("bidvlv") == 1) { // Check which way the water is going at the boiler
- if (*_vm->getVar("bblrarm") == 1) {
+ if (valve == 1) {
+ if (_vm->_vars["bidvlv"] == 1) { // Check which way the water is going at the boiler
+ if (_vm->_vars["bblrarm"] == 1) {
// If the pipe is open, make sure the water is drained out
- *_vm->getVar("bheat") = 0;
- *_vm->getVar("bblrwtr") = 0;
+ _vm->_vars["bheat"] = 0;
+ _vm->_vars["bblrwtr"] = 0;
} else {
// If the pipe is closed, fill the boiler again
- *_vm->getVar("bheat") = *_vm->getVar("bblrvalve");
- *_vm->getVar("bblrwtr") = 1;
+ _vm->_vars["bheat"] = _vm->_vars["bblrvalve"];
+ _vm->_vars["bblrwtr"] = 1;
}
} else {
// Have the grating inside the boiler match the switch outside
- *_vm->getVar("bblrgrt") = (*_vm->getVar("bblrsw") == 1) ? 0 : 1;
+ _vm->_vars["bblrgrt"] = (_vm->_vars["bblrsw"] == 1) ? 0 : 1;
}
}
}
void RivenExternal::xbchipper(uint16 argc, uint16 *argv) {
// Why is this an external command....?
- if (*_vm->getVar("bvalve") == 2)
+ if (_vm->_vars["bvalve"] == 2)
_vm->_video->playMovieBlockingRiven(2);
}
@@ -1049,54 +1136,54 @@ void RivenExternal::xbchipper(uint16 argc, uint16 *argv) {
void RivenExternal::lowerPins() {
// Lower the pins
- uint32 *pinUp = _vm->getVar("gpinup");
+ uint32 &pinUp = _vm->_vars["gpinup"];
- if (*pinUp == 0)
+ if (pinUp == 0)
return;
- uint32 *pinPos = _vm->getVar("gpinpos");
- uint32 startTime = (*pinPos - 1) * 600 + 4830;
- *pinUp = 0;
+ uint32 &pinPos = _vm->_vars["gpinpos"];
+ uint32 startTime = (pinPos - 1) * 600 + 4830;
+ pinUp = 0;
// Play the down sound
_vm->_sound->playSound(13);
- uint32 *upMovie = _vm->getVar("gupmoov");
+ uint32 &upMovie = _vm->_vars["gupmoov"];
// Play the video of the pins going down
- VideoHandle handle = _vm->_video->playMovieRiven(*upMovie);
+ VideoHandle handle = _vm->_video->playMovieRiven(upMovie);
assert(handle != NULL_VID_HANDLE);
_vm->_video->setVideoBounds(handle, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 550, 600));
_vm->_video->waitUntilMovieEnds(handle);
- *upMovie = 0;
+ upMovie = 0;
}
void RivenExternal::xgresetpins(uint16 argc, uint16 *argv) {
// As the function name suggests, this resets the pins
lowerPins();
- *_vm->getVar("gupmoov") = 0;
+ _vm->_vars["gupmoov"] = 0;
}
void RivenExternal::xgrotatepins(uint16 argc, uint16 *argv) {
// Rotate the pins, if necessary
- if (*_vm->getVar("gpinup") == 0)
+ if (_vm->_vars["gpinup"] == 0)
return;
- uint32 *pinPos = _vm->getVar("gpinpos");
- uint32 startTime = (*pinPos - 1) * 1200;
+ uint32 &pinPos = _vm->_vars["gpinpos"];
+ uint32 startTime = (pinPos - 1) * 1200;
- if (*pinPos == 4)
- *pinPos = 1;
+ if (pinPos == 4)
+ pinPos = 1;
else
- *pinPos += 1;
+ pinPos++;
// Play the rotating sound
_vm->_sound->playSound(12);
// Play the video of the pins rotating
- VideoHandle handle = _vm->_video->playMovieRiven(*_vm->getVar("gupmoov"));
+ VideoHandle handle = _vm->_video->playMovieRiven(_vm->_vars["gupmoov"]);
assert(handle != NULL_VID_HANDLE);
_vm->_video->setVideoBounds(handle, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 1215, 600));
_vm->_video->waitUntilMovieEnds(handle);
@@ -1115,7 +1202,7 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
mousePos.y /= 11;
// Lastly, adjust it based on the rotational position
- uint32 pinPos = *_vm->getVar("gpinpos");
+ uint32 &pinPos = _vm->_vars["gpinpos"];
switch (pinPos) {
case 1:
mousePos.x = 5 - mousePos.x;
@@ -1139,7 +1226,7 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
}
// Now check to see if this section of the island exists
- uint32 islandIndex = *_vm->getVar("glkbtns") - 1;
+ uint32 islandIndex = _vm->_vars["glkbtns"] - 1;
uint16 imagePos = mousePos.x + mousePos.y;
static const uint16 islandImages[5][11] = {
@@ -1151,7 +1238,7 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
};
// The scripts set gimagemax to hold the max pin array length in islandPins above
- uint32 imageCount = *_vm->getVar("gimagemax");
+ uint32 imageCount = _vm->_vars["gimagemax"];
uint32 image = 0;
for (; image < imageCount; image++)
if (islandImages[islandIndex][image] == imagePos)
@@ -1161,15 +1248,15 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
if (image == imageCount)
return;
- uint32 *pinUp = _vm->getVar("gpinup");
- uint32 *curImage = _vm->getVar("gimagecurr");
+ uint32 &pinUp = _vm->_vars["gpinup"];
+ uint32 &curImage = _vm->_vars["gimagecurr"];
// Lower the pins if they are currently raised
- if (*pinUp == 1) {
+ if (pinUp == 1) {
lowerPins();
// If we just lowered the selected section, don't raise it up again
- if (*curImage == image)
+ if (curImage == image)
return;
}
@@ -1187,9 +1274,9 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
_vm->_video->waitUntilMovieEnds(handle);
// Update the relevant variables
- *_vm->getVar("gupmoov") = pinMovieCodes[imagePos - 1];
- *pinUp = 1;
- *curImage = image;
+ _vm->_vars["gupmoov"] = pinMovieCodes[imagePos - 1];
+ pinUp = 1;
+ curImage = image;
}
void RivenExternal::xgisland25_opencard(uint16 argc, uint16 *argv) {
@@ -1219,19 +1306,20 @@ void RivenExternal::xgisland1490_domecheck(uint16 argc, uint16 *argv) {
void RivenExternal::xgplateau3160_dopools(uint16 argc, uint16 *argv) {
// Play the deactivation of a pool if one is active and a different one is activated
_vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_video->playMovieBlockingRiven(*_vm->getVar("glkbtns") * 2);
+ _vm->_system->updateScreen();
+ _vm->_video->playMovieBlockingRiven(_vm->_vars["glkbtns"] * 2);
}
void RivenExternal::xgwt200_scribetime(uint16 argc, uint16 *argv) {
// Get the current time
- *_vm->getVar("gscribetime") = _vm->_system->getMillis();
+ _vm->_vars["gscribetime"] = _vm->_system->getMillis();
}
void RivenExternal::xgwt900_scribe(uint16 argc, uint16 *argv) {
- uint32 *scribeVar = _vm->getVar("gscribe");
+ uint32 &scribeVar = _vm->_vars["gscribe"];
- if (*scribeVar == 1 && _vm->_system->getMillis() > *_vm->getVar("gscribetime") + 40000)
- *scribeVar = 2;
+ if (scribeVar == 1 && _vm->_system->getMillis() > _vm->_vars["gscribetime"] + 40000)
+ scribeVar = 2;
}
static const uint16 s_viewerTimeIntervals[] = { 0, 816, 1617, 2416, 3216, 4016, 4816, 5616, 6416, 7216, 8016, 8816 };
@@ -1241,9 +1329,9 @@ void RivenExternal::xgrviewer(uint16 argc, uint16 *argv) {
// (It shows the colors of the marbles)
// If the light is on, turn it off
- uint32 *viewerLight = _vm->getVar("grview");
- if (*viewerLight == 1) {
- *viewerLight = 0;
+ uint32 &viewerLight = _vm->_vars["grview"];
+ if (viewerLight == 1) {
+ viewerLight = 0;
_vm->_sound->playSound(27);
_vm->refreshCard();
@@ -1253,17 +1341,17 @@ void RivenExternal::xgrviewer(uint16 argc, uint16 *argv) {
// Calculate how much we're moving
static const uint16 hotspotPositions[] = { 2, 1, 5, 4, 3 };
- uint32 *curPos = _vm->getVar("grviewpos");
- uint32 newPos = *curPos + hotspotPositions[_vm->_curHotspot - 1];
+ uint32 &curPos = _vm->_vars["grviewpos"];
+ uint32 newPos = curPos + hotspotPositions[_vm->_curHotspot - 1];
// Now play the movie
VideoHandle handle = _vm->_video->playMovieRiven(1);
assert(handle != NULL_VID_HANDLE);
- _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[*curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600));
+ _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600));
_vm->_video->waitUntilMovieEnds(handle);
// Set the new position and let the card's scripts take over again
- *curPos = newPos % 6; // Clip it to 0-5
+ curPos = newPos % 6; // Clip it to 0-5
_vm->refreshCard();
}
@@ -1271,25 +1359,25 @@ void RivenExternal::xgplaywhark(uint16 argc, uint16 *argv) {
// The whark response to using the lights
// If we've gotten a visit already since we turned out the light, bail out
- uint32 *wharkState = _vm->getVar("gwharktime");
+ uint32 &wharkState = _vm->_vars["gwharktime"];
- if (*wharkState != 1)
+ if (wharkState != 1)
return;
- *wharkState = 0;
+ wharkState = 0;
// Increase the amount of times the whark has visited
- uint32 *wharkVisits = _vm->getVar("gwhark");
- *wharkVisits += 1;
+ uint32 &wharkVisits = _vm->_vars["gwhark"];
+ wharkVisits++;
// If we're at 5 or more, the whark will no longer visit us :(
- if (*wharkVisits >= 5) {
- *wharkVisits = 5;
+ if (wharkVisits >= 5) {
+ wharkVisits = 5;
return;
}
// Activate the correct video based on the amount of times we've been visited
- switch (*wharkVisits) {
+ switch (wharkVisits) {
case 1:
_vm->_video->activateMLST(3, _vm->getCurCard());
break;
@@ -1322,43 +1410,136 @@ void RivenExternal::xglviewer(uint16 argc, uint16 *argv) {
// Calculate how much we're moving
static const uint16 hotspotPositions[] = { 1, 5, 4, 2, 0, 0, 3 };
- uint32 *curPos = _vm->getVar("glviewpos");
- uint32 newPos = *curPos + hotspotPositions[_vm->_curHotspot - 1];
+ uint32 &curPos = _vm->_vars["glviewpos"];
+ uint32 newPos = curPos + hotspotPositions[_vm->_curHotspot - 1];
// Now play the movie
VideoHandle handle = _vm->_video->playMovieRiven(1);
assert(handle != NULL_VID_HANDLE);
- _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[*curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600));
+ _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600));
_vm->_video->waitUntilMovieEnds(handle);
// Set the new position to the variable
- *curPos = newPos % 6; // Clip it to 0-5
+ curPos = newPos % 6; // Clip it to 0-5
// And update the screen with the new image
- _vm->_gfx->drawPLST(*curPos + 2);
+ _vm->_gfx->drawPLST(curPos + 2);
_vm->_gfx->updateScreen();
}
void RivenExternal::xglview_villageon(uint16 argc, uint16 *argv) {
// Turn on the left viewer to 'village mode'
- *_vm->getVar("glview") = 2;
- _vm->_gfx->drawPLST(*_vm->getVar("glviewpos") + 2);
+ _vm->_vars["glview"] = 2;
+ _vm->_gfx->drawPLST(_vm->_vars["glviewpos"] + 2);
_vm->_gfx->updateScreen();
}
void RivenExternal::xglview_villageoff(uint16 argc, uint16 *argv) {
// Turn off the left viewer when in 'village mode' (why is this external?)
- *_vm->getVar("glview") = 0;
+ _vm->_vars["glview"] = 0;
_vm->_gfx->drawPLST(1);
_vm->_gfx->updateScreen();
}
+static void catherineViewerIdleTimer(MohawkEngine_Riven *vm) {
+ uint32 &cathState = vm->_vars["gcathstate"];
+ uint16 movie;
+
+ // Choose a new movie
+ if (cathState == 1) {
+ static const int movieList[] = { 9, 10, 19, 19, 21, 21 };
+ movie = movieList[vm->_rnd->getRandomNumber(5)];
+ } else if (cathState == 2) {
+ static const int movieList[] = { 18, 20, 22 };
+ movie = movieList[vm->_rnd->getRandomNumber(2)];
+ } else {
+ static const int movieList[] = { 11, 11, 12, 17, 17, 17, 17, 23 };
+ movie = movieList[vm->_rnd->getRandomNumber(7)];
+ }
+
+ // Update Catherine's state
+ if (movie == 10 || movie == 17 || movie == 18 || movie == 20)
+ cathState = 1;
+ else if (movie == 19 || movie == 21 || movie == 23)
+ cathState = 2;
+ else
+ cathState = 3;
+
+ // Begin playing the new movie
+ vm->_video->activateMLST(movie, vm->getCurCard());
+ VideoHandle videoHandle = vm->_video->playMovieRiven(30);
+
+ // Reset the timer
+ vm->installTimer(&catherineViewerIdleTimer, vm->_video->getDuration(videoHandle) + vm->_rnd->getRandomNumber(60) * 1000);
+}
+
void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) {
- // TODO: Activate random background Catherine videos
+ // Activate random background Catherine videos
+
+ // Turn on the left viewer to 'prison mode'
+ _vm->_vars["glview"] = 1;
+
+ // Get basic starting states
+ uint16 cathMovie = _vm->_rnd->getRandomNumberRng(8, 23);
+ uint16 turnOnMovie = 4;
+ uint32 &cathState = _vm->_vars["gcathstate"];
+
+ // Adjust the turn on movie
+ if (cathMovie == 14)
+ turnOnMovie = 6;
+ else if (cathMovie == 15)
+ turnOnMovie = 7;
+
+ // Adjust Catherine's state
+ if (cathMovie == 9 || cathMovie == 11 || cathMovie == 12 || cathMovie == 22)
+ cathState = 3;
+ else if (cathMovie == 19 || cathMovie == 21 || cathMovie == 23 || cathMovie == 14)
+ cathState = 2;
+ else
+ cathState = 1;
+
+ // Turn on the viewer
+ _vm->_cursor->hideCursor();
+ _vm->_video->playMovieBlockingRiven(turnOnMovie);
+ _vm->_cursor->showCursor();
+
+ uint32 timeUntilNextMovie;
+
+ // Begin playing a movie immediately if Catherine is already in the viewer
+ if (cathMovie == 8 || (cathMovie >= 13 && cathMovie <= 16)) {
+ _vm->_video->activateMLST(cathMovie, _vm->getCurCard());
+ VideoHandle videoHandle = _vm->_video->playMovieRiven(30);
+
+ timeUntilNextMovie = _vm->_video->getDuration(videoHandle) + _vm->_rnd->getRandomNumber(60) * 1000;
+ } else {
+ // Otherwise, just redraw the imager
+ timeUntilNextMovie = _vm->_rnd->getRandomNumberRng(10, 20) * 1000;
+ _vm->_gfx->drawPLST(8);
+ _vm->_gfx->updateScreen();
+ }
+
+ // Create the timer for the next video
+ _vm->installTimer(&catherineViewerIdleTimer, timeUntilNextMovie);
}
void RivenExternal::xglview_prisonoff(uint16 argc, uint16 *argv) {
- // TODO: Deactivate random background Catherine videos
+ // Deactivate random background Catherine videos
+
+ // Update the viewer state (now off)
+ _vm->_vars["glview"] = 0;
+
+ // Remove the timer we set in xglview_prisonon()
+ _vm->removeTimer();
+
+ // Play the 'turn off' movie after stopping any videos still playing
+ _vm->_video->stopVideos();
+ _vm->_cursor->hideCursor();
+ _vm->_video->playMovieBlockingRiven(5);
+ _vm->_cursor->showCursor();
+
+ // Redraw the viewer
+ _vm->_gfx->drawPLST(1);
+ _vm->_gfx->updateScreen();
}
// ------------------------------------------------------------------------------------
@@ -1367,9 +1548,9 @@ void RivenExternal::xglview_prisonoff(uint16 argc, uint16 *argv) {
void RivenExternal::xreseticons(uint16 argc, uint16 *argv) {
// Reset the icons when going to Tay (rspit)
- *_vm->getVar("jicons") = 0;
- *_vm->getVar("jiconorder") = 0;
- *_vm->getVar("jrbook") = 0;
+ _vm->_vars["jicons"] = 0;
+ _vm->_vars["jiconorder"] = 0;
+ _vm->_vars["jrbook"] = 0;
}
// Count up how many icons are pressed
@@ -1390,49 +1571,49 @@ static byte countDepressedIcons(uint32 iconOrderVar) {
void RivenExternal::xicon(uint16 argc, uint16 *argv) {
// Set atemp as the status of whether or not the icon can be depressed.
- if (*_vm->getVar("jicons") & (1 << (argv[0] - 1))) {
+ if (_vm->_vars["jicons"] & (1 << (argv[0] - 1))) {
// This icon is depressed. Allow depression only if the last depressed icon was this one.
- if ((*_vm->getVar("jiconorder") & 0x1f) == argv[0])
- *_vm->getVar("atemp") = 1;
+ if ((_vm->_vars["jiconorder"] & 0x1f) == argv[0])
+ _vm->_vars["atemp"] = 1;
else
- *_vm->getVar("atemp") = 2;
+ _vm->_vars["atemp"] = 2;
} else
- *_vm->getVar("atemp") = 0;
+ _vm->_vars["atemp"] = 0;
}
void RivenExternal::xcheckicons(uint16 argc, uint16 *argv) {
// Reset the icons if this is the sixth icon
- uint32 *iconOrderVar = _vm->getVar("jiconorder");
- if (countDepressedIcons(*iconOrderVar) == 5) {
- *iconOrderVar = 0;
- *_vm->getVar("jicons") = 0;
+ uint32 &iconOrderVar = _vm->_vars["jiconorder"];
+ if (countDepressedIcons(iconOrderVar) == 5) {
+ iconOrderVar = 0;
+ _vm->_vars["jicons"] = 0;
_vm->_sound->playSound(46);
}
}
void RivenExternal::xtoggleicon(uint16 argc, uint16 *argv) {
// Get the variables
- uint32 *iconsDepressed = _vm->getVar("jicons");
- uint32 *iconOrderVar = _vm->getVar("jiconorder");
+ uint32 &iconsDepressed = _vm->_vars["jicons"];
+ uint32 &iconOrderVar = _vm->_vars["jiconorder"];
- if (*iconsDepressed & (1 << (argv[0] - 1))) {
+ if (iconsDepressed & (1 << (argv[0] - 1))) {
// The icon is depressed, now unpress it
- *iconsDepressed &= ~(1 << (argv[0] - 1));
- *iconOrderVar >>= 5;
+ iconsDepressed &= ~(1 << (argv[0] - 1));
+ iconOrderVar >>= 5;
} else {
// The icon is not depressed, now depress it
- *iconsDepressed |= 1 << (argv[0] - 1);
- *iconOrderVar = (*iconOrderVar << 5) + argv[0];
+ iconsDepressed |= 1 << (argv[0] - 1);
+ iconOrderVar = (iconOrderVar << 5) + argv[0];
}
// Check if the puzzle is complete now and assign 1 to jrbook if the puzzle is complete.
- if (*iconOrderVar == *_vm->getVar("jiconcorrectorder"))
- *_vm->getVar("jrbook") = 1;
+ if (iconOrderVar == _vm->_vars["jiconcorrectorder"])
+ _vm->_vars["jrbook"] = 1;
}
void RivenExternal::xjtunnel103_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->getVar("jicons");
+ uint32 iconsDepressed = _vm->_vars["jicons"];
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 0))
@@ -1453,7 +1634,7 @@ void RivenExternal::xjtunnel103_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel104_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->getVar("jicons");
+ uint32 iconsDepressed = _vm->_vars["jicons"];
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 9))
@@ -1476,7 +1657,7 @@ void RivenExternal::xjtunnel104_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel105_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->getVar("jicons");
+ uint32 iconsDepressed = _vm->_vars["jicons"];
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 3))
@@ -1497,7 +1678,7 @@ void RivenExternal::xjtunnel105_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel106_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->getVar("jicons");
+ uint32 iconsDepressed = _vm->_vars["jicons"];
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 16))
@@ -1522,17 +1703,18 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
// Run the gallows's carriage
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->_video->playMovieBlockingRiven(1); // Play handle movie
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(1); // Play handle movie
_vm->_gfx->scheduleTransition(15); // Set pan down transition
_vm->changeToCard(_vm->matchRMAPToCard(0x18e77)); // Change to card facing up
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor (again)
- _vm->_video->playMovieBlockingRiven(4); // Play carriage beginning to drop
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(4); // Play carriage beginning to drop
_vm->_gfx->scheduleTransition(14); // Set pan up transition
_vm->changeToCard(_vm->matchRMAPToCard(0x183a9)); // Change to card looking straight again
_vm->_video->playMovieBlockingRiven(2);
- uint32 *gallows = _vm->getVar("jgallows");
- if (*gallows == 1) {
+ if (_vm->_vars["jgallows"] == 1) {
// If the gallows is open, play the up movie and return
_vm->_video->playMovieBlockingRiven(3);
return;
@@ -1560,19 +1742,22 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
}
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->updateScreen(); // Update
if (gotClick) {
_vm->_gfx->scheduleTransition(16); // Schedule dissolve transition
_vm->changeToCard(_vm->matchRMAPToCard(0x18d4d)); // Move forward
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->updateScreen(); // Update
_vm->_system->delayMillis(500); // Delay a half second before changing again
_vm->_gfx->scheduleTransition(12); // Schedule pan left transition
_vm->changeToCard(_vm->matchRMAPToCard(0x18ab5)); // Turn right
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->_video->playMovieBlockingRiven(1); // Play carriage ride movie
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(1); // Play carriage ride movie
_vm->changeToCard(_vm->matchRMAPToCard(0x17167)); // We have arrived at the top
} else
- _vm->_video->playMovieBlockingRiven(3); // Too slow!
+ _vm->_video->playMovieBlockingRiven(3); // Too slow!
}
void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) {
@@ -1603,6 +1788,7 @@ int RivenExternal::jspitElevatorLoop() {
_vm->_cursor->setCursor(kRivenClosedHandCursor);
_vm->_system->updateScreen();
+
for (;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
@@ -1663,11 +1849,11 @@ void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlockingRiven(6);
// If the whark's mouth is open, close it
- uint32 *mouthVar = _vm->getVar("jwmouth");
- if (*mouthVar == 1) {
+ uint32 &mouthVar = _vm->_vars["jwmouth"];
+ if (mouthVar == 1) {
_vm->_video->playMovieBlockingRiven(3);
_vm->_video->playMovieBlockingRiven(8);
- *mouthVar = 0;
+ mouthVar = 0;
}
// Play the elevator video and then change the card
@@ -1682,27 +1868,27 @@ void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
void RivenExternal::xjplaybeetle_550(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_600(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_950(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_1050(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_1450(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time as long as the girl is not present
- *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0 && *_vm->getVar("jgirl") != 1) ? 1 : 0;
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0 && _vm->_vars["jgirl"] != 1) ? 1 : 0;
}
void RivenExternal::xjlagoon700_alert(uint16 argc, uint16 *argv) {
@@ -1715,12 +1901,12 @@ void RivenExternal::xjlagoon800_alert(uint16 argc, uint16 *argv) {
void RivenExternal::xjlagoon1500_alert(uint16 argc, uint16 *argv) {
// Have the sunners move a bit as you get closer ;)
- uint32 *sunners = _vm->getVar("jsunners");
- if (*sunners == 0) {
+ uint32 &sunners = _vm->_vars["jsunners"];
+ if (sunners == 0) {
_vm->_video->playMovieBlockingRiven(3);
- } else if (*sunners == 1) {
+ } else if (sunners == 1) {
_vm->_video->playMovieBlockingRiven(2);
- *sunners = 2;
+ sunners = 2;
}
}
@@ -1750,14 +1936,14 @@ void RivenExternal::xschool280_playwhark(uint16 argc, uint16 *argv) {
uint16 spinMLST, overlayPLST, doomMLST, snackMLST;
// Choose left or right based on jwharkpos (which is set by the scripts)
- if (*_vm->getVar("jwharkpos") == 1) {
- posVar = _vm->getVar("jleftpos");
+ if (_vm->_vars["jwharkpos"] == 1) {
+ posVar = &_vm->_vars["jleftpos"];
spinMLST = 1;
overlayPLST = 12;
doomMLST = 3;
snackMLST = 4;
} else {
- posVar = _vm->getVar("jrightpos");
+ posVar = &_vm->_vars["jrightpos"];
spinMLST = 2;
overlayPLST = 13;
doomMLST = 5;
@@ -1766,6 +1952,7 @@ void RivenExternal::xschool280_playwhark(uint16 argc, uint16 *argv) {
// Hide the cursor
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
// Play the spin movie
_vm->_video->playMovieBlockingRiven(spinMLST);
@@ -1811,26 +1998,27 @@ 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->getVar("returnstackid") == rspit) {
+ if (_vm->_vars["returnstackid"] == rspit) {
_vm->changeToStack(rspit);
_vm->changeToCard(2);
return;
}
// You used the trap book... why? What were you thinking?
- uint32 *gehnState = _vm->getVar("agehn");
+ uint32 gehnState = _vm->_vars["agehn"];
- if (*gehnState == 0) // Gehn who?
- runEndGame(1);
- else if (*gehnState == 4) // You freed him? Are you kidding me?
- runEndGame(2);
- else // You already spoke with Gehn. What were you thinking?
- runEndGame(3);
+ if (gehnState == 0) // Gehn who?
+ runEndGame(1, 9500);
+ else if (gehnState == 4) // You freed him? Are you kidding me?
+ runEndGame(2, 12000);
+ else // You already spoke with Gehn. What were you thinking?
+ runEndGame(3, 8000);
}
void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
// Hide the cursor
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
// Let's hook onto our video
VideoHandle video = _vm->_video->findVideoHandleRiven(argv[0]);
@@ -1873,6 +2061,8 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
_vm->_cursor->setCursor(kRivenOpenHandCursor);
else
_vm->_cursor->setCursor(kRivenMainCursor);
+
+ _vm->_system->updateScreen();
// OK, Gehn has opened the trap book and has asked us to go in. Let's watch
// and see what the player will do...
@@ -1887,7 +2077,7 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
_vm->_cursor->setCursor(kRivenOpenHandCursor);
else
_vm->_cursor->setCursor(kRivenMainCursor);
- updateScreen = false; // Don't update twice, changing the cursor already updates the screen
+ updateScreen = true;
break;
case Common::EVENT_LBUTTONUP:
if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) {
@@ -1899,11 +2089,11 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
_vm->_gfx->updateScreen(); // Update the screen
_vm->_sound->playSound(0); // Play the link sound
_vm->_video->activateMLST(7, _vm->getCurCard()); // Activate Gehn Link Video
- _vm->_video->playMovieBlockingRiven(1); // Play Gehn Link Video
- *_vm->getVar("agehn") = 4; // Set Gehn to the trapped state
- *_vm->getVar("atrapbook") = 1; // We've got the trap book again
+ _vm->_video->playMovieBlockingRiven(1); // Play Gehn Link Video
+ _vm->_vars["agehn"] = 4; // Set Gehn to the trapped state
+ _vm->_vars["atrapbook"] = 1; // We've got the trap book again
_vm->_sound->playSound(0); // Play the link sound again
- _vm->changeToCard(_vm->matchRMAPToCard(0x2885)); // Link out! (TODO: Shouldn't this card change?)
+ _vm->changeToCard(_vm->matchRMAPToCard(0x2885)); // Link out!
return;
}
break;
@@ -1924,13 +2114,14 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
// Hide the cursor again
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
// If there was no click and this is the third time Gehn asks us to
// use the trap book, he will shoot the player. Dead on arrival.
// Run the credits from here.
- if (*_vm->getVar("agehn") == 3) {
+ if (_vm->_vars["agehn"] == 3) {
_vm->_scriptMan->stopAllScripts();
- runCredits(argv[0]);
+ runCredits(argv[0], 5000);
return;
}
@@ -1940,12 +2131,12 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) {
// Close the blank linking book if it's open
- uint32 *book = _vm->getVar("odeskbook");
- if (*book != 1)
+ uint32 &book = _vm->_vars["odeskbook"];
+ if (book != 1)
return;
// Set the variable to be "closed"
- *book = 0;
+ book = 0;
// Play the movie
_vm->_video->playMovieBlockingRiven(1);
@@ -1963,21 +2154,21 @@ void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) {
void RivenExternal::xobedroom5_closedrawer(uint16 argc, uint16 *argv) {
// Close the drawer if open when clicking on the journal.
_vm->_video->playMovieBlockingRiven(2);
- *_vm->getVar("ostanddrawer") = 0;
+ _vm->_vars["ostanddrawer"] = 0;
}
void RivenExternal::xogehnopenbook(uint16 argc, uint16 *argv) {
- _vm->_gfx->drawPLST(*_vm->getVar("ogehnpage"));
+ _vm->_gfx->drawPLST(_vm->_vars["ogehnpage"]);
}
void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("ogehnpage");
+ uint32 &page = _vm->_vars["ogehnpage"];
// Decrement the page if it's not the first page
- if (*page == 1)
+ if (page == 1)
return;
- (*page)--;
+ page--;
// Play the page turning sound
_vm->_sound->playSound(12);
@@ -1989,12 +2180,12 @@ void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->getVar("ogehnpage");
+ uint32 &page = _vm->_vars["ogehnpage"];
// Increment the page if it's not the last page
- if (*page == 13)
+ if (page == 13)
return;
- (*page)++;
+ page++;
// Play the page turning sound
_vm->_sound->playSound(13);
@@ -2012,8 +2203,9 @@ uint16 RivenExternal::getComboDigit(uint32 correctCombo, uint32 digit) {
void RivenExternal::xgwatch(uint16 argc, uint16 *argv) {
// Hide the cursor
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
- uint32 *prisonCombo = _vm->getVar("pcorrectorder");
+ uint32 &prisonCombo = _vm->_vars["pcorrectorder"];
uint32 soundTime = _vm->_system->getMillis() - 500; // Start the first sound instantly
byte curSound = 0;
@@ -2023,7 +2215,7 @@ void RivenExternal::xgwatch(uint16 argc, uint16 *argv) {
if (curSound == 5) // Break out after the last sound is done
break;
- _vm->_sound->playSound(getComboDigit(*prisonCombo, curSound) + 13);
+ _vm->_sound->playSound(getComboDigit(prisonCombo, curSound) + 13);
curSound++;
soundTime = _vm->_system->getMillis();
}
@@ -2055,17 +2247,17 @@ void RivenExternal::xpisland990_elevcombo(uint16 argc, uint16 *argv) {
// It is impossible to get here if Gehn is not trapped. However,
// the original also disallows brute forcing the ending if you have
// not yet trapped Gehn.
- if (*_vm->getVar("agehn") != 4)
+ if (_vm->_vars["agehn"] != 4)
return;
- uint32 *correctDigits = _vm->getVar("pelevcombo");
+ uint32 &correctDigits = _vm->_vars["pelevcombo"];
// pelevcombo keeps count of how many buttons we have pressed in the correct order.
// When pelevcombo is 5, clicking the handle will show the video freeing Catherine.
- if (*correctDigits < 5 && argv[0] == getComboDigit(*_vm->getVar("pcorrectorder"), *correctDigits))
- *correctDigits += 1;
+ if (correctDigits < 5 && argv[0] == getComboDigit(_vm->_vars["pcorrectorder"], correctDigits))
+ correctDigits++;
else
- *correctDigits = 0;
+ correctDigits = 0;
}
void RivenExternal::xpscpbtn(uint16 argc, uint16 *argv) {
@@ -2104,13 +2296,13 @@ void RivenExternal::xrcredittime(uint16 argc, uint16 *argv) {
// For the record, when agehn == 4, Gehn will thank you for
// showing him the rebel age and then leave you to die.
// Otherwise, the rebels burn the book. Epic fail either way.
- runEndGame(1);
+ runEndGame(1, 1500);
}
void RivenExternal::xrshowinventory(uint16 argc, uint16 *argv) {
// Give the trap book and Catherine's journal to the player
- *_vm->getVar("atrapbook") = 1;
- *_vm->getVar("acathbook") = 1;
+ _vm->_vars["atrapbook"] = 1;
+ _vm->_vars["acathbook"] = 1;
_vm->_gfx->showInventory();
}
@@ -2118,8 +2310,53 @@ void RivenExternal::xrhideinventory(uint16 argc, uint16 *argv) {
_vm->_gfx->hideInventory();
}
+static void rebelPrisonWindowTimer(MohawkEngine_Riven *vm) {
+ // Randomize a video out in the middle of Tay
+ uint16 movie = vm->_rnd->getRandomNumberRng(2, 13);
+ vm->_video->activateMLST(movie, vm->getCurCard());
+ VideoHandle handle = vm->_video->playMovieRiven(movie);
+
+ // Ensure the next video starts after this one ends
+ uint32 timeUntilNextVideo = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(38, 58) * 1000;
+
+ // Save the time in case we leave the card and return
+ vm->_vars["rvillagetime"] = timeUntilNextVideo + vm->getTotalPlayTime();
+
+ // Reinstall this timer with the new time
+ vm->installTimer(&rebelPrisonWindowTimer, timeUntilNextVideo);
+}
+
void RivenExternal::xrwindowsetup(uint16 argc, uint16 *argv) {
- // TODO: Randomizing what effect happens when you look out into the middle of Tay (useless! :P)
+ // Randomize what effect happens when you look out into the middle of Tay
+
+ uint32 villageTime = _vm->_vars["rvillagetime"];
+
+ // If we have time leftover from a previous run, set up the timer again
+ if (_vm->getTotalPlayTime() < villageTime) {
+ _vm->installTimer(&rebelPrisonWindowTimer, villageTime - _vm->getTotalPlayTime());
+ return;
+ }
+
+ uint32 timeUntilNextVideo;
+
+ // Randomize the time until the next video
+ if (_vm->_rnd->getRandomNumber(2) == 0 && _vm->_vars["rrichard"] == 0) {
+ // In this case, a rebel is placed on a bridge
+ // The video itself is handled by the scripts later on
+ _vm->_vars["rrebelview"] = 0;
+ timeUntilNextVideo = _vm->_rnd->getRandomNumberRng(38, 58) * 1000;
+ } else {
+ // Otherwise, just a random video from the timer
+ _vm->_vars["rrebelview"] = 1;
+ timeUntilNextVideo = _vm->_rnd->getRandomNumber(20) * 1000;
+ }
+
+ // We don't set rvillagetime here because the scripts later just reset it to 0
+ // Of course, because of this, you can't return to the window twice and expect
+ // the timer to reinstall itself...
+
+ // Install our timer and we're on our way
+ _vm->installTimer(&rebelPrisonWindowTimer, timeUntilNextVideo);
}
// ------------------------------------------------------------------------------------
@@ -2131,48 +2368,45 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlockingRiven(3);
// Don't do anything else if the telescope power is off
- if (*_vm->getVar("ttelevalve") == 0)
+ if (_vm->_vars["ttelevalve"] == 0)
return;
- uint32 *telescopePos = _vm->getVar("ttelescope");
- uint32 *telescopeCover = _vm->getVar("ttelecover");
+ uint32 &telescopePos = _vm->_vars["ttelescope"];
+ uint32 &telescopeCover = _vm->_vars["ttelecover"];
- if (*telescopePos == 1) {
+ if (telescopePos == 1) {
// We're at the bottom, which means one of two things can happen...
- if (*telescopeCover == 1 && *_vm->getVar("ttelepin") == 1) {
+ if (telescopeCover == 1 && _vm->_vars["ttelepin"] == 1) {
// ...if the cover is open and the pin is up, the game is now over.
- if (*_vm->getVar("pcage") == 2) {
+ if (_vm->_vars["pcage"] == 2) {
// The best ending: Catherine is free, Gehn is trapped, Atrus comes to rescue you.
// And now we fall back to Earth... all the way...
- warning("xtexterior300_telescopedown: Good ending");
_vm->_video->activateMLST(8, _vm->getCurCard());
- runEndGame(8);
- } else if (*_vm->getVar("agehn") == 4) {
+ runEndGame(8, 5000);
+ } else if (_vm->_vars["agehn"] == 4) {
// The ok ending: Catherine is still trapped, Gehn is trapped, Atrus comes to rescue you.
// Nice going! Catherine and the islanders are all dead now! Just go back to your home...
- warning("xtexterior300_telescopedown: OK ending");
_vm->_video->activateMLST(9, _vm->getCurCard());
- runEndGame(9);
- } else if (*_vm->getVar("atrapbook") == 1) {
+ runEndGame(9, 5000);
+ } else if (_vm->_vars["atrapbook"] == 1) {
// The bad ending: Catherine is trapped, Gehn is free, Atrus gets shot by Gehn,
// And then you get shot by Cho. Nice going! Catherine and the islanders are dead
// and you have just set Gehn free from Riven, not to mention you're dead.
- warning("xtexterior300_telescopedown: Bad ending");
_vm->_video->activateMLST(10, _vm->getCurCard());
- runEndGame(10);
+ runEndGame(10, 5000);
} else {
// The impossible ending: You don't have Catherine's journal and yet you were somehow
// able to open the hatch on the telescope. The game provides an ending for those who
// cheat, load a saved game with the combo, or just guess the telescope combo. Atrus
// doesn't come and you just fall into the fissure.
- warning("xtexterior300_telescopedown: Wtf ending");
_vm->_video->activateMLST(11, _vm->getCurCard());
- runEndGame(11);
+ runEndGame(11, 5000);
}
} else {
// ...the telescope can't move down anymore.
// Play the sound of not being able to move
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_sound->playSoundBlocking(13);
}
} else {
@@ -2180,14 +2414,14 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) {
// Play a piece of the moving down movie
static const uint32 timeIntervals[] = { 4320, 3440, 2560, 1760, 880, 0 };
- uint16 movieCode = (*telescopeCover) ? 1 : 2;
+ uint16 movieCode = telescopeCover ? 1 : 2;
VideoHandle handle = _vm->_video->playMovieRiven(movieCode);
- _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[*telescopePos], 600), Audio::Timestamp(0, timeIntervals[*telescopePos - 1], 600));
+ _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[telescopePos], 600), Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600));
_vm->_sound->playSound(14); // Play the moving sound
_vm->_video->waitUntilMovieEnds(handle);
// Now move the telescope down a position and refresh
- *telescopePos -= 1;
+ telescopePos--;
_vm->refreshCard();
}
}
@@ -2197,54 +2431,52 @@ void RivenExternal::xtexterior300_telescopeup(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlockingRiven(3);
// Don't do anything else if the telescope power is off
- if (*_vm->getVar("ttelevalve") == 0)
+ if (_vm->_vars["ttelevalve"] == 0)
return;
- uint32 *telescopePos = _vm->getVar("ttelescope");
+ uint32 &telescopePos = _vm->_vars["ttelescope"];
// Check if we can't move up anymore
- if (*telescopePos == 5) {
+ if (telescopePos == 5) {
// Play the sound of not being able to move
_vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
_vm->_sound->playSoundBlocking(13);
return;
}
// Play a piece of the moving up movie
static const uint32 timeIntervals[] = { 0, 800, 1680, 2560, 3440, 4320 };
- uint16 movieCode = (*_vm->getVar("ttelecover")) ? 4 : 5;
+ uint16 movieCode = _vm->_vars["ttelecover"] ? 4 : 5;
VideoHandle handle = _vm->_video->playMovieRiven(movieCode);
- _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[*telescopePos - 1], 600), Audio::Timestamp(0, timeIntervals[*telescopePos], 600));
+ _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600), Audio::Timestamp(0, timeIntervals[telescopePos], 600));
_vm->_sound->playSound(14); // Play the moving sound
_vm->_video->waitUntilMovieEnds(handle);
// Now move the telescope up a position and refresh
- *telescopePos += 1;
+ telescopePos++;
_vm->refreshCard();
}
void RivenExternal::xtisland390_covercombo(uint16 argc, uint16 *argv) {
// Called when clicking the telescope cover buttons. argv[0] is the button number (1...5).
- uint32 *correctDigits = _vm->getVar("tcovercombo");
+ uint32 &correctDigits = _vm->_vars["tcovercombo"];
- if (*correctDigits < 5 && argv[0] == getComboDigit(*_vm->getVar("tcorrectorder"), *correctDigits))
- *correctDigits += 1;
+ if (correctDigits < 5 && argv[0] == getComboDigit(_vm->_vars["tcorrectorder"], correctDigits))
+ correctDigits++;
else
- *correctDigits = 0;
+ correctDigits = 0;
// If we have hit the correct 5 buttons in a row, activate the hotspot to open up the
// telescope cover.
- if (*correctDigits == 5)
- _vm->_hotspots[9].enabled = true;
- else
- _vm->_hotspots[9].enabled = false;
+ _vm->_hotspots[9].enabled = (correctDigits == 5);
}
// Atrus' Journal and Trap Book are added to inventory
void RivenExternal::xtatrusgivesbooks(uint16 argc, uint16 *argv) {
// Give the player Atrus' Journal and the Trap book
- *_vm->getVar("aatrusbook") = 1;
- *_vm->getVar("atrapbook") = 1;
+ _vm->_vars["aatrusbook"] = 1;
+ _vm->_vars["atrapbook"] = 1;
}
// Trap Book is removed from inventory
@@ -2252,7 +2484,7 @@ void RivenExternal::xtchotakesbook(uint16 argc, uint16 *argv) {
// And now Cho takes the trap book. Sure, this isn't strictly
// necessary to add and them remove the trap book... but it
// seems better to do this ;)
- *_vm->getVar("atrapbook") = 0;
+ _vm->_vars["atrapbook"] = 0;
}
void RivenExternal::xthideinventory(uint16 argc, uint16 *argv) {
@@ -2269,20 +2501,20 @@ static const char *s_marbleNames[] = { "tred", "torange", "tyellow", "tgreen", "
// Marble Puzzle helper functions
// The y portion takes the upper 16 bits, while the x portion takes the lower 16 bits
-static void setMarbleX(uint32 *var, byte x) {
- *var = (*var & 0xff00) | (x + 1);
+static void setMarbleX(uint32 &var, byte x) {
+ var = (var & 0xff00) | (x + 1);
}
-static void setMarbleY(uint32 *var, byte y) {
- *var = ((y + 1) << 16) | (*var & 0xff);
+static void setMarbleY(uint32 &var, byte y) {
+ var = ((y + 1) << 16) | (var & 0xff);
}
-static byte getMarbleX(uint32 *var) {
- return (*var & 0xff) - 1;
+static byte getMarbleX(uint32 var) {
+ return (var & 0xff) - 1;
}
-static byte getMarbleY(uint32 *var) { // Give that that Y you old hag! </bad Seinfeld reference>
- return ((*var >> 16) & 0xff) - 1;
+static byte getMarbleY(uint32 var) { // Give that that Y you old hag! </bad Seinfeld reference>
+ return ((var >> 16) & 0xff) - 1;
}
static Common::Rect generateMarbleGridRect(uint16 x, uint16 y) {
@@ -2302,7 +2534,7 @@ void RivenExternal::xt7500_checkmarbles(uint16 argc, uint16 *argv) {
static const uint32 marbleFinalValues[] = { 1114121, 1441798, 0, 65552, 65558, 262146 };
for (uint16 i = 0; i < kMarbleCount; i++)
- if (*_vm->getVar(s_marbleNames[i]) != marbleFinalValues[i]) {
+ if (_vm->_vars[s_marbleNames[i]] != marbleFinalValues[i]) {
valid = false;
break;
}
@@ -2310,24 +2542,24 @@ void RivenExternal::xt7500_checkmarbles(uint16 argc, uint16 *argv) {
// If we have the correct combo, activate the power and reset the marble positions
// Otherwise, make sure the power is off
if (valid) {
- *_vm->getVar("apower") = 1;
+ _vm->_vars["apower"] = 1;
for (uint16 i = 0; i < kMarbleCount; i++)
- *_vm->getVar(s_marbleNames[i]) = 0;
+ _vm->_vars[s_marbleNames[i]] = 0;
} else
- *_vm->getVar("apower") = 0;
+ _vm->_vars["apower"] = 0;
}
void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) {
// Draw the small marbles when we're a step away from the waffle
uint16 baseBitmapId = _vm->findResourceID(ID_TBMP, "*tsmallred");
- bool waffleDown = *_vm->getVar("twaffle") != 0;
+ bool waffleDown = _vm->_vars["twaffle"] != 0;
// Note that each of the small marble images is exactly 4x2
for (uint16 i = 0; i < kMarbleCount; i++) {
- uint32 *var = _vm->getVar(s_marbleNames[i]);
+ uint32 &var = _vm->_vars[s_marbleNames[i]];
- if (*var == 0) {
+ if (var == 0) {
// The marble is still in its initial place
// (Note that this is still drawn even if the waffle is down)
int marbleX = 376 + i * 2;
@@ -2346,9 +2578,9 @@ void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) {
void RivenExternal::setMarbleHotspots() {
// Set the hotspots
for (uint16 i = 0; i < kMarbleCount; i++) {
- uint32 *marblePos = _vm->getVar(s_marbleNames[i]);
+ uint32 &marblePos = _vm->_vars[s_marbleNames[i]];
- if (*marblePos == 0) // In the receptacle
+ if (marblePos == 0) // In the receptacle
_vm->_hotspots[i + 3].rect = _marbleBaseHotspots[i];
else // On the grid
_vm->_hotspots[i + 3].rect = generateMarbleGridRect(getMarbleX(marblePos), getMarbleY(marblePos));
@@ -2363,13 +2595,13 @@ void RivenExternal::xt7800_setup(uint16 argc, uint16 *argv) {
// Move the marble hotspots based on their position variables
setMarbleHotspots();
- *_vm->getVar("themarble") = 0;
+ _vm->_vars["themarble"] = 0;
}
void RivenExternal::drawMarbles() {
for (uint32 i = 0; i < kMarbleCount; i++) {
// Don't draw the marble if we're holding it
- if (*_vm->getVar("themarble") - 1 == i)
+ if (_vm->_vars["themarble"] - 1 == i)
continue;
Common::Rect rect = _vm->_hotspots[i + 3].rect;
@@ -2395,17 +2627,17 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
// Pick up and move a marble
// First, let's figure out what marble we're now holding
- uint32 *marble = _vm->getVar("themarble");
- *marble = 0;
+ uint32 &marble = _vm->_vars["themarble"];
+ marble = 0;
for (uint32 i = 0; i < kMarbleCount; i++)
if (_vm->_hotspots[i + 3].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
- *marble = i + 1;
+ marble = i + 1;
break;
}
// xtakeit() shouldn't be called if we're not on a marble hotspot
- assert(*marble);
+ assert(marble != 0);
// Redraw the background
_vm->_gfx->drawPLST(1);
@@ -2428,7 +2660,7 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
}
// Check if we landed in a valid location and no other marble has that location
- uint32 *marblePos = _vm->getVar(s_marbleNames[*marble - 1]);
+ uint32 &marblePos = _vm->_vars[s_marbleNames[marble - 1]];
bool foundMatch = false;
for (int y = 0; y < 25 && !foundMatch; y++) {
@@ -2443,8 +2675,8 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
// Let's make sure no other marble is in this spot...
for (uint16 i = 0; i < kMarbleCount; i++)
- if (i != *marble - 1 && *_vm->getVar(s_marbleNames[i]) == *marblePos)
- *marblePos = 0;
+ if (i != marble - 1 && _vm->_vars[s_marbleNames[i]] == marblePos)
+ marblePos = 0;
// We have a match
foundMatch = true;
@@ -2454,10 +2686,10 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
// If we still don't have a match, reset it to the original location
if (!foundMatch)
- *marblePos = 0;
+ marblePos = 0;
// Check the new hotspots and refresh everything
- *marble = 0;
+ marble = 0;
setMarbleHotspots();
_vm->updateCurrentHotspot();
_vm->_gfx->updateScreen();
diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h
index 818bc06c54..034cd662f6 100644
--- a/engines/mohawk/riven_external.h
+++ b/engines/mohawk/riven_external.h
@@ -41,6 +41,7 @@ public:
uint16 getComboDigit(uint32 correctCombo, uint32 digit);
uint32 getDomeSliderState() { return _sliderState; }
void setDomeSliderState(uint32 state) { _sliderState = state; }
+ void checkYtramCatch(bool playSound);
private:
MohawkEngine_Riven *_vm;
@@ -61,8 +62,8 @@ private:
// Supplementary Functions
int jspitElevatorLoop();
void runDemoBoundaryDialog();
- void runEndGame(uint16 video);
- void runCredits(uint16 video);
+ void runEndGame(uint16 video, uint32 delay);
+ void runCredits(uint16 video, uint32 delay);
void runDomeCheck();
void runDomeButtonMovie();
void resetDomeSliders(uint16 soundId, uint16 startHotspot);
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index c7b5cd01fd..35ce7aad84 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -165,16 +165,24 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
if (name == "dropLeftStart" || name == "dropRightStart")
continue;
- uint32 *var = _vm->getVar(name);
-
- *var = rawVariables[i];
-
- if (name.equalsIgnoreCase("CurrentStackID"))
+ 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"))
+ else if (name.equalsIgnoreCase("CurrentCardID")) // Store for later
cardID = rawVariables[i];
- else if (name.equalsIgnoreCase("ReturnStackID"))
- *var = mapOldStackIDToNew(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
+ var = 0;
+ else // Otherwise, just store it
+ var = rawVariables[i];
}
_vm->changeToStack(stackID);
@@ -216,14 +224,14 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVERSSection() {
Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() {
Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
- for (uint32 i = 0; i < _vm->getVarCount(); i++) {
+ 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 = _vm->getGlobalVar(i);
- if (_vm->getGlobalVarName(i) == "returnstackid")
+ uint32 variable = it->_value;
+ if (it->_key == "returnstackid")
variable = mapNewStackIDToOld(variable);
stream->writeUint32BE(variable);
@@ -235,19 +243,19 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() {
Common::MemoryWriteStreamDynamic *RivenSaveLoad::genNAMESection() {
Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
- stream->writeUint16BE((uint16)_vm->getVarCount());
+ stream->writeUint16BE(_vm->_vars.size());
uint16 curPos = 0;
- for (uint16 i = 0; i < _vm->getVarCount(); i++) {
+ for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) {
stream->writeUint16BE(curPos);
- curPos += _vm->getGlobalVarName(i).size() + 1;
+ curPos += it->_key.size() + 1;
}
- for (uint16 i = 0; i < _vm->getVarCount(); i++)
+ for (uint16 i = 0; i < _vm->_vars.size(); i++)
stream->writeUint16BE(i);
- for (uint16 i = 0; i < _vm->getVarCount(); i++) {
- stream->write(_vm->getGlobalVarName(i).c_str(), _vm->getGlobalVarName(i).size());
+ for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) {
+ stream->write(it->_key.c_str(), it->_key.size());
stream->writeByte(0);
}
@@ -276,8 +284,8 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
filename += ".rvn";
// Convert class variables to variable numbers
- *_vm->getVar("currentstackid") = mapNewStackIDToOld(_vm->getCurStack());
- *_vm->getVar("currentcardid") = _vm->getCurCard();
+ _vm->_vars["currentstackid"] = mapNewStackIDToOld(_vm->getCurStack());
+ _vm->_vars["currentcardid"] = _vm->getCurCard();
Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
if (!saveFile)
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 5d459354e9..b8f86f993a 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -31,8 +31,9 @@
#include "mohawk/sound.h"
#include "mohawk/video.h"
+#include "common/memstream.h"
#include "common/stream.h"
-#include "graphics/cursorman.h"
+#include "common/system.h"
namespace Mohawk {
@@ -139,7 +140,7 @@ void RivenScript::setupOpcodes() {
// 0x24 (36 decimal)
OPCODE(unk_36), // Unknown
OPCODE(fadeAmbientSounds),
- OPCODE(complexPlayMovie),
+ OPCODE(storeMovieOpcode),
OPCODE(activatePLST),
// 0x28 (40 decimal)
OPCODE(activateSLST),
@@ -260,7 +261,7 @@ void RivenScript::processCommands(bool runCommands) {
// Run the following block if the block's variable is equal to the variable to check against
// Don't run it if the parent block is not executed
// And don't run it if another block has already evaluated to true (needed for the default case)
- runBlock = (*_vm->getLocalVar(var) == checkValue || checkValue == 0xffff) && runCommands && !anotherBlockEvaluated;
+ runBlock = (_vm->getStackVar(var) == checkValue || checkValue == 0xffff) && runCommands && !anotherBlockEvaluated;
processCommands(runBlock);
if (runBlock)
@@ -363,8 +364,7 @@ void RivenScript::playSound(uint16 op, uint16 argc, uint16 *argv) {
// Command 7: set variable value (variable, value)
void RivenScript::setVariable(uint16 op, uint16 argc, uint16 *argv) {
- debug(2, "Setting variable %d to %d", argv[0], argv[1]);
- *_vm->getLocalVar(argv[0]) = argv[1];
+ _vm->getStackVar(argv[0]) = argv[1];
}
// Command 8: conditional branch
@@ -424,6 +424,7 @@ void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) {
void RivenScript::changeCursor(uint16 op, uint16 argc, uint16 *argv) {
debug(2, "Change to cursor %d", argv[0]);
_vm->_cursor->setCursor(argv[0]);
+ _vm->_system->updateScreen();
}
// Command 14: pause script execution (delay in ms, u1)
@@ -470,12 +471,10 @@ void RivenScript::enableScreenUpdate(uint16 op, uint16 argc, uint16 *argv) {
// Command 24: increment variable (variable, value)
void RivenScript::incrementVariable(uint16 op, uint16 argc, uint16 *argv) {
- uint32 *localVar = _vm->getLocalVar(argv[0]);
- *localVar += argv[1];
- debug(2, "Incrementing variable %d by %d, variable now is equal to %d", argv[0], argv[1], *localVar);
+ _vm->getStackVar(argv[0]) += argv[1];
}
-// Command 27: go to stack (stack_name code_hi code_lo)
+// Command 27: go to stack (stack name, code high, code low)
void RivenScript::changeStack(uint16 op, uint16 argc, uint16 *argv) {
Common::String stackName = _vm->getName(StackNames, argv[0]);
int8 index = -1;
@@ -512,9 +511,9 @@ void RivenScript::enableMovie(uint16 op, uint16 argc, uint16 *argv) {
// Command 32: play foreground movie - blocking (movie_id)
void RivenScript::playMovieBlocking(uint16 op, uint16 argc, uint16 *argv) {
- CursorMan.showMouse(false); // Hide the cursor before playing the video
+ _vm->_cursor->hideCursor();
_vm->_video->playMovieBlockingRiven(argv[0]);
- CursorMan.showMouse(true); // Show the cursor again when we're done ;)
+ _vm->_cursor->showCursor();
}
// Command 33: play background movie - nonblocking (movie_id)
@@ -538,18 +537,41 @@ void RivenScript::fadeAmbientSounds(uint16 op, uint16 argc, uint16 *argv) {
_vm->_sound->stopAllSLST(true);
}
-// Command 38: Play a movie with extra parameters (movie id, delay high, delay low, record type, record id)
-void RivenScript::complexPlayMovie(uint16 op, uint16 argc, uint16 *argv) {
- warning("STUB: complexPlayMovie");
- debugN("\tMovie ID = %d\n", argv[0]);
- debugN("\tDelay = %d\n", (argv[1] << 16) + argv[2]);
+// Command 38: Store an opcode for use when playing a movie (movie id, time high, time low, opcode, arguments...)
+void RivenScript::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) {
+ uint32 scriptSize = 6 + (argc - 4) * 2;
- if (argv[3] == 0)
- debugN("\tDraw PLST %d\n", argv[4]);
- else if (argv[3] == 40)
- debugN("\tPlay SLST %d\n", argv[4]);
- else
- error("Unknown complexPlayMovie record type %d", argv[3]);
+ // Create our dummy script
+ byte *scriptBuf = (byte *)malloc(scriptSize);
+ WRITE_BE_UINT16(scriptBuf, 1); // One command
+ WRITE_BE_UINT16(scriptBuf + 2, argv[3]); // One opcode
+ WRITE_BE_UINT16(scriptBuf + 4, argc - 4); // argc - 4 args
+
+ for (int i = 0; i < argc - 4; i++)
+ WRITE_BE_UINT16(scriptBuf + 6 + (i * 2), argv[i + 4]);
+
+ // Build a script out of 'er
+ Common::SeekableReadStream *scriptStream = new Common::MemoryReadStream(scriptBuf, scriptSize, DisposeAfterUse::YES);
+ RivenScript *script = new RivenScript(_vm, scriptStream, kStoredOpcodeScript, getParentStack(), getParentCard());
+
+ uint32 delayTime = (argv[1] << 16) + argv[2];
+
+ if (delayTime > 0) {
+ // Store the script
+ RivenScriptManager::StoredMovieOpcode storedOp;
+ storedOp.script = script;
+ storedOp.time = delayTime + _vm->getTotalPlayTime();
+ storedOp.id = argv[0];
+
+ // TODO: Actually store the movie and call it in our movie loop
+ // For now, just delete the script and move on
+ //_vm->_scriptMan->setStoredMovieOpcode(storedOp);
+ delete script;
+ } else {
+ // Run immediately if we have no delay
+ script->runScript();
+ delete script;
+ }
}
// Command 39: activate PLST record (card picture lists)
@@ -640,11 +662,16 @@ void RivenScript::activateMLST(uint16 op, uint16 argc, uint16 *argv) {
RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) {
_vm = vm;
+ _storedMovieOpcode.script = 0;
+ _storedMovieOpcode.time = 0;
+ _storedMovieOpcode.id = 0;
}
RivenScriptManager::~RivenScriptManager() {
for (uint32 i = 0; i < _currentScripts.size(); i++)
delete _currentScripts[i];
+
+ clearStoredMovieOpcode();
}
RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stream, bool garbageCollect) {
@@ -685,4 +712,33 @@ void RivenScriptManager::unloadUnusedScripts() {
}
}
+void RivenScriptManager::setStoredMovieOpcode(const StoredMovieOpcode &op) {
+ clearStoredMovieOpcode();
+ _storedMovieOpcode.script = op.script;
+ _storedMovieOpcode.id = op.id;
+ _storedMovieOpcode.time = op.time;
+}
+
+void RivenScriptManager::runStoredMovieOpcode(uint16 id) {
+ if (_storedMovieOpcode.script) {
+ if (_storedMovieOpcode.id == id) {
+ // If we've passed the time, run our script
+ if (_vm->getTotalPlayTime() >= _storedMovieOpcode.time) {
+ _storedMovieOpcode.script->runScript();
+ clearStoredMovieOpcode();
+ }
+ } else {
+ // We're on a completely different video, kill off any remaining opcode
+ clearStoredMovieOpcode();
+ }
+ }
+}
+
+void RivenScriptManager::clearStoredMovieOpcode() {
+ delete _storedMovieOpcode.script;
+ _storedMovieOpcode.script = 0;
+ _storedMovieOpcode.time = 0;
+ _storedMovieOpcode.id = 0;
+}
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index 89e5ff0836..2ac805c366 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -28,12 +28,14 @@
#include "common/str-array.h"
#include "common/ptr.h"
+#include "common/textconsole.h"
class MohawkEngine_Riven;
#define DECLARE_OPCODE(x) void x(uint16 op, uint16 argc, uint16 *argv)
namespace Mohawk {
+
// Script Types
enum {
kMouseDownScript = 0,
@@ -46,7 +48,9 @@ enum {
kCardLoadScript = 6,
kCardLeaveScript = 7,
kCardOpenScript = 9,
- kCardUpdateScript = 10
+ kCardUpdateScript = 10,
+
+ kStoredOpcodeScript // This is ScummVM-only to denote the script from a storeMovieOpcode() call
};
class RivenScript;
@@ -114,7 +118,7 @@ private:
DECLARE_OPCODE(stopMovie);
DECLARE_OPCODE(unk_36);
DECLARE_OPCODE(fadeAmbientSounds);
- DECLARE_OPCODE(complexPlayMovie);
+ DECLARE_OPCODE(storeMovieOpcode);
DECLARE_OPCODE(activatePLST);
DECLARE_OPCODE(activateSLST);
DECLARE_OPCODE(activateMLSTAndPlay);
@@ -134,10 +138,22 @@ public:
RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true);
void stopAllScripts();
+ struct StoredMovieOpcode {
+ RivenScript *script;
+ uint32 time;
+ uint16 id;
+ };
+
+ void setStoredMovieOpcode(const StoredMovieOpcode &op);
+ void runStoredMovieOpcode(uint16 id);
+ void clearStoredMovieOpcode();
+
private:
void unloadUnusedScripts();
RivenScriptList _currentScripts;
MohawkEngine_Riven *_vm;
+
+ StoredMovieOpcode _storedMovieOpcode;
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp
index b18a753c31..7f06a67a1d 100644
--- a/engines/mohawk/riven_vars.cpp
+++ b/engines/mohawk/riven_vars.cpp
@@ -270,85 +270,64 @@ static const char *variableNames[] = {
"currentcardid"
};
-uint32 *MohawkEngine_Riven::getLocalVar(uint32 index) {
- return getVar(getName(VariableNames, index));
-}
-
-uint32 MohawkEngine_Riven::getGlobalVar(uint32 index) {
- return _vars[index];
-}
-
-Common::String MohawkEngine_Riven::getGlobalVarName(uint32 index) {
- return variableNames[index];
-}
-
-uint32 *MohawkEngine_Riven::getVar(const Common::String &varName) {
- for (uint32 i = 0; i < _varCount; i++)
- if (varName.equalsIgnoreCase(variableNames[i]))
- return &_vars[i];
-
- error ("Unknown variable: '%s'", varName.c_str());
- return NULL;
+uint32 &MohawkEngine_Riven::getStackVar(uint32 index) {
+ return _vars[getName(VariableNames, index)];
}
void MohawkEngine_Riven::initVars() {
- _varCount = ARRAYSIZE(variableNames);
-
- _vars = new uint32[_varCount];
-
- // Temporary:
- for (uint32 i = 0; i < _varCount; i++)
- _vars[i] = 0;
+ // Most variables just start at 0, it's simpler to do this
+ for (uint32 i = 0; i < ARRAYSIZE(variableNames); i++)
+ _vars[variableNames[i]] = 0;
- // Init Variables to their correct starting state.
- *getVar("ttelescope") = 5;
- *getVar("tgatestate") = 1;
- *getVar("jbridge1") = 1;
- *getVar("jbridge4") = 1;
- *getVar("jgallows") = 1;
- *getVar("jiconcorrectorder") = 12068577;
- *getVar("bblrvalve") = 1;
- *getVar("bblrwtr") = 1;
- *getVar("bfans") = 1;
- *getVar("bytrap") = 2;
- *getVar("aatruspage") = 1;
- *getVar("acathpage") = 1;
- *getVar("bheat") = 1;
- *getVar("waterenabled") = 1;
- *getVar("ogehnpage") = 1;
- *getVar("bblrsw") = 1;
- *getVar("ocage") = 1;
- *getVar("jbeetle") = 1;
- *getVar("tdl") = 1;
- *getVar("bmagcar") = 1;
- *getVar("gnmagcar") = 1;
- *getVar("omusicplayer") = 1;
+ // Initialize the rest of the variables to their proper state
+ _vars["ttelescope"] = 5;
+ _vars["tgatestate"] = 1;
+ _vars["jbridge1"] = 1;
+ _vars["jbridge4"] = 1;
+ _vars["jgallows"] = 1;
+ _vars["jiconcorrectorder"] = 12068577;
+ _vars["bblrvalve"] = 1;
+ _vars["bblrwtr"] = 1;
+ _vars["bfans"] = 1;
+ _vars["bytrap"] = 2;
+ _vars["aatruspage"] = 1;
+ _vars["acathpage"] = 1;
+ _vars["bheat"] = 1;
+ _vars["waterenabled"] = 1;
+ _vars["ogehnpage"] = 1;
+ _vars["bblrsw"] = 1;
+ _vars["ocage"] = 1;
+ _vars["jbeetle"] = 1;
+ _vars["tdl"] = 1;
+ _vars["bmagcar"] = 1;
+ _vars["gnmagcar"] = 1;
+ _vars["omusicplayer"] = 1;
// Randomize the telescope combination
- uint32 *teleCombo = getVar("tcorrectorder");
+ uint32 &teleCombo = _vars["tcorrectorder"];
for (byte i = 0; i < 5; i++) {
- *teleCombo *= 10;
- *teleCombo += _rnd->getRandomNumberRng(1, 5); // 5 buttons
+ teleCombo *= 10;
+ teleCombo += _rnd->getRandomNumberRng(1, 5); // 5 buttons
}
// Randomize the prison combination
- uint32 *prisonCombo = getVar("pcorrectorder");
+ uint32 &prisonCombo = _vars["pcorrectorder"];
for (byte i = 0; i < 5; i++) {
- *prisonCombo *= 10;
- *prisonCombo += _rnd->getRandomNumberRng(1, 3); // 3 buttons/sounds
+ prisonCombo *= 10;
+ prisonCombo += _rnd->getRandomNumberRng(1, 3); // 3 buttons/sounds
}
// Randomize the dome combination -- each bit represents a slider position,
// the highest bit (1 << 24) represents 1, (1 << 23) represents 2, etc.
- uint32 *domeCombo = getVar("adomecombo");
+ uint32 &domeCombo = _vars["adomecombo"];
for (byte bitsSet = 0; bitsSet < 5;) {
uint32 randomBit = 1 << (24 - _rnd->getRandomNumber(24));
// Don't overwrite a bit we already set, and throw out the bottom five bits being set
- if (*domeCombo & randomBit || (*domeCombo | randomBit) == 31)
+ if (domeCombo & randomBit || (domeCombo | randomBit) == 31)
continue;
- *domeCombo |= randomBit;
+ domeCombo |= randomBit;
bitsSet++;
}
}
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index ca642f1376..fba87808d2 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -25,7 +25,10 @@
#include "mohawk/sound.h"
+#include "common/debug.h"
+#include "common/system.h"
#include "common/util.h"
+#include "common/textconsole.h"
#include "audio/musicplugin.h"
#include "audio/audiostream.h"
@@ -90,11 +93,11 @@ Audio::AudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
audStream = makeMohawkWaveStream(_vm->getResource(ID_SND, id));
break;
case GType_LIVINGBOOKSV1:
- audStream = makeOldMohawkWaveStream(_vm->getResource(ID_WAV, id));
+ audStream = makeLivingBooksWaveStream_v1(_vm->getResource(ID_WAV, id));
break;
case GType_LIVINGBOOKSV2:
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
- audStream = makeOldMohawkWaveStream(_vm->getResource(ID_WAV, id));
+ audStream = makeLivingBooksWaveStream_v1(_vm->getResource(ID_WAV, id));
break;
}
// fall through
@@ -479,7 +482,7 @@ Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stre
return Audio::makeRawStream(dataChunk.audioData, dataChunk.sampleRate, flags);
} else if (dataChunk.encoding == kCodecADPCM) {
uint32 blockAlign = dataChunk.channels * dataChunk.bitsPerSample / 8;
- return Audio::makeADPCMStream(dataChunk.audioData, DisposeAfterUse::YES, dataSize, Audio::kADPCMIma, dataChunk.sampleRate, dataChunk.channels, blockAlign);
+ return Audio::makeADPCMStream(dataChunk.audioData, DisposeAfterUse::YES, dataSize, Audio::kADPCMDVI, dataChunk.sampleRate, dataChunk.channels, blockAlign);
} else if (dataChunk.encoding == kCodecMPEG2) {
#ifdef USE_MAD
return Audio::makeMP3Stream(dataChunk.audioData, DisposeAfterUse::YES);
@@ -493,7 +496,7 @@ Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stre
return NULL;
}
-Audio::AudioStream *Sound::makeOldMohawkWaveStream(Common::SeekableReadStream *stream) {
+Audio::AudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
uint16 header = stream->readUint16BE();
uint16 rate = 0;
uint32 size = 0;
@@ -576,6 +579,15 @@ bool Sound::isPlaying(uint16 id) {
return false;
}
+bool Sound::isPlaying() {
+ for (uint32 i = 0; i < _handles.size(); i++)
+ if (_handles[i].type == kUsedHandle)
+ if (_vm->_mixer->isSoundHandleActive(_handles[i].handle))
+ return true;
+
+ return false;
+}
+
uint Sound::getNumSamplesPlayed(uint16 id) {
for (uint32 i = 0; i < _handles.size(); i++)
if (_handles[i].type == kUsedHandle && _handles[i].id == id) {
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 938f15fcb2..702c6f61f3 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -133,6 +133,7 @@ public:
void pauseSound();
void resumeSound();
bool isPlaying(uint16 id);
+ bool isPlaying();
uint getNumSamplesPlayed(uint16 id);
// Myst-specific sound functions
@@ -158,7 +159,7 @@ private:
byte *_midiData;
static Audio::AudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = NULL);
- static Audio::AudioStream *makeOldMohawkWaveStream(Common::SeekableReadStream *stream);
+ static Audio::AudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
void initMidi();
Common::Array<SndHandle> _handles;
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 9bf202083a..8f57d61cc4 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -27,9 +27,16 @@
#include "mohawk/resource.h"
#include "mohawk/video.h"
+#include "common/debug.h"
#include "common/events.h"
+#include "common/textconsole.h"
+#include "common/system.h"
+
+#include "graphics/surface.h"
+
#include "video/qt_decoder.h"
+
namespace Mohawk {
void VideoEntry::clear() {
@@ -219,7 +226,7 @@ bool VideoManager::updateMovies() {
// Convert from 8bpp to the current screen format if necessary
Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();
- if (frame->bytesPerPixel == 1) {
+ if (frame->format.bytesPerPixel == 1) {
if (pixelFormat.bytesPerPixel == 1) {
if (_videoStreams[i]->hasDirtyPalette())
_videoStreams[i]->setSystemPalette();
@@ -228,7 +235,7 @@ bool VideoManager::updateMovies() {
const byte *palette = _videoStreams[i]->getPalette();
assert(palette);
- convertedFrame->create(frame->w, frame->h, pixelFormat.bytesPerPixel);
+ convertedFrame->create(frame->w, frame->h, pixelFormat);
for (uint16 j = 0; j < frame->h; j++) {
for (uint16 k = 0; k < frame->w; k++) {
@@ -490,6 +497,11 @@ uint32 VideoManager::getElapsedTime(VideoHandle handle) {
return _videoStreams[handle]->getElapsedTime();
}
+uint32 VideoManager::getDuration(VideoHandle handle) {
+ assert(handle != NULL_VID_HANDLE);
+ return _videoStreams[handle]->getDuration();
+}
+
bool VideoManager::endOfVideo(VideoHandle handle) {
assert(handle != NULL_VID_HANDLE);
return _videoStreams[handle].endOfVideo();
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index 6b9cfa25d2..e65629a1ec 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -104,6 +104,7 @@ public:
int32 getCurFrame(VideoHandle handle);
uint32 getFrameCount(VideoHandle handle);
uint32 getElapsedTime(VideoHandle handle);
+ uint32 getDuration(VideoHandle videoHandle);
bool endOfVideo(VideoHandle handle);
void setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end);
void seekToTime(VideoHandle handle, Audio::Timestamp time);
diff --git a/engines/mohawk/view.cpp b/engines/mohawk/view.cpp
index 837d386b58..e5a44122ea 100644
--- a/engines/mohawk/view.cpp
+++ b/engines/mohawk/view.cpp
@@ -28,6 +28,8 @@
#include "mohawk/graphics.h"
#include "common/stream.h"
#include "common/system.h"
+#include "common/textconsole.h"
+#include "graphics/palette.h"
namespace Mohawk {
diff --git a/engines/parallaction/balloons.cpp b/engines/parallaction/balloons.cpp
index 527f2d2812..2cf6eebf2a 100644
--- a/engines/parallaction/balloons.cpp
+++ b/engines/parallaction/balloons.cpp
@@ -304,7 +304,7 @@ int BalloonManager_ns::createBalloon(int16 w, int16 h, int16 winding, uint16 bor
int16 real_h = (winding == -1) ? h : h + 9;
balloon->surface = new Graphics::Surface;
- balloon->surface->create(w, real_h, 1);
+ balloon->surface->create(w, real_h, Graphics::PixelFormat::createFormatCLUT8());
balloon->surface->fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR_NS);
Common::Rect r(w, h);
@@ -578,7 +578,7 @@ Graphics::Surface *BalloonManager_br::expandBalloon(Frames *data, int frameNum)
rect.translate(-rect.left, -rect.top);
Graphics::Surface *surf = new Graphics::Surface;
- surf->create(rect.width(), rect.height(), 1);
+ surf->create(rect.width(), rect.height(), Graphics::PixelFormat::createFormatCLUT8());
_vm->_gfx->unpackBlt(rect, data->getData(frameNum), data->getRawSize(frameNum), surf, LAYER_FOREGROUND, 100, BALLOON_TRANSPARENT_COLOR_BR);
@@ -670,7 +670,7 @@ int BalloonManager_br::createBalloon(int16 w, int16 h, uint16 borderThickness) {
Balloon *balloon = &_intBalloons[id];
balloon->surface = new Graphics::Surface;
- balloon->surface->create(w, h, 1);
+ balloon->surface->create(w, h, Graphics::PixelFormat::createFormatCLUT8());
Common::Rect rect(w, h);
balloon->surface->fillRect(rect, 1);
diff --git a/engines/parallaction/callables_br.cpp b/engines/parallaction/callables_br.cpp
index 21703dc1dd..0bc6f6762c 100644
--- a/engines/parallaction/callables_br.cpp
+++ b/engines/parallaction/callables_br.cpp
@@ -25,6 +25,8 @@
#include "parallaction/parallaction.h"
+#include "common/textconsole.h"
+
namespace Parallaction {
void Parallaction_br::_c_null(void*) {
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index f67a77aa21..8e3c2cbeb8 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -28,6 +28,7 @@
#include "common/config-manager.h"
#include "engines/advancedDetector.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "parallaction/parallaction.h"
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index e3d02bac62..944d9f4b55 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -25,6 +25,7 @@
#include "common/events.h"
#include "common/debug-channels.h"
+#include "common/textconsole.h"
#include "parallaction/exec.h"
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp
index 6928c1eefc..d996b72e90 100644
--- a/engines/parallaction/disk.cpp
+++ b/engines/parallaction/disk.cpp
@@ -23,6 +23,9 @@
*
*/
+#include "common/iff_container.h"
+#include "common/textconsole.h"
+
#include "parallaction/disk.h"
#include "parallaction/graphics.h"
@@ -36,7 +39,7 @@ void ILBMLoader::setupBuffer(uint32 w, uint32 h) {
_surf = new Graphics::Surface;
assert(_surf);
}
- _surf->create(w, h, 1);
+ _surf->create(w, h, Graphics::PixelFormat::createFormatCLUT8());
_mode = Graphics::ILBMDecoder::ILBM_UNPACK_PLANES;
_intBuffer = (byte*)_surf->pixels;
break;
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index 8ff0efd3c6..9af189af68 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -29,14 +29,20 @@
#define PATH_LEN 200
#include "common/archive.h"
+#include "common/str.h"
-#include "graphics/surface.h"
#include "graphics/iff.h"
namespace Common {
- class FSDirectory;
+class FSDirectory;
+class ReadStream;
+class SeekableReadStream;
+struct IFFChunk;
}
+namespace Graphics {
+struct Surface;
+}
namespace Parallaction {
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 34b04cd00f..cea4091ee9 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -27,6 +27,7 @@
#include "common/config-manager.h"
#include "common/fs.h"
+#include "common/textconsole.h"
#include "parallaction/parallaction.h"
#include "parallaction/parser.h"
@@ -227,7 +228,7 @@ void DosDisk_br::loadBitmap(Common::SeekableReadStream &stream, Graphics::Surfac
stream.skip(768);
}
- surf.create(width, height, 1);
+ surf.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
stream.read(surf.pixels, width * height);
}
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index 98770b9a6d..e695fa8798 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -27,6 +27,7 @@
#include "common/fs.h"
#include "common/memstream.h"
#include "common/substream.h"
+#include "common/textconsole.h"
#include "parallaction/parser.h"
#include "parallaction/parallaction.h"
@@ -91,7 +92,7 @@ NSArchive::NSArchive(Common::SeekableReadStream *stream, Common::Platform platfo
if (features & GF_DEMO) {
isSmallArchive = stream->size() == SIZEOF_SMALL_ARCHIVE;
} else if (features & GF_LANG_MULT) {
- isSmallArchive = (stream->readUint32BE() != MKID_BE('NDOS'));
+ isSmallArchive = (stream->readUint32BE() != MKTAG('N','D','O','S'));
}
}
@@ -473,7 +474,7 @@ void DosDisk_ns::loadBackground(BackgroundInfo& info, const char *filename) {
}
// read bitmap, mask and path data and extract them into the 3 buffers
- info.bg.create(info.width, info.height, 1);
+ info.bg.create(info.width, info.height, Graphics::PixelFormat::createFormatCLUT8());
createMaskAndPathBuffers(info);
unpackBackground(stream, (byte*)info.bg.pixels, info._mask->data, info._path->data);
@@ -801,7 +802,7 @@ void AmigaDisk_ns::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 b
uint16 planeSize = bytesPerPlane * height;
for (uint32 i = 0; i < numFrames; i++) {
- if (READ_BE_UINT32(src) == MKID_BE('DLTA')) {
+ if (READ_BE_UINT32(src) == MKTAG('D','L','T','A')) {
uint size = READ_BE_UINT32(src + 4);
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index 99aa27b30f..c879745f65 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -27,6 +27,8 @@
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
+#include "common/textconsole.h"
+
namespace Parallaction {
#define INST_ON 1
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index c8a5ee1548..ee357576d2 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -28,6 +28,7 @@
#include "parallaction/parallaction.h"
#include "parallaction/sound.h"
+#include "common/textconsole.h"
namespace Parallaction {
diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp
index 18f469f0a2..a459e6a600 100644
--- a/engines/parallaction/font.cpp
+++ b/engines/parallaction/font.cpp
@@ -25,6 +25,7 @@
#include "common/endian.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "parallaction/parallaction.h"
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index 6c39b2e696..ca99624ecd 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -28,6 +28,7 @@
#include "disk.h"
#include "common/algorithm.h"
+#include "common/textconsole.h"
#include "parallaction/parallaction.h"
namespace Parallaction {
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 35441d7e3e..d33e733677 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -26,6 +26,8 @@
#include "common/system.h"
#include "common/file.h"
+#include "common/textconsole.h"
+#include "graphics/palette.h"
#include "graphics/primitives.h"
#include "engines/util.h"
@@ -521,7 +523,7 @@ void Gfx::invertBackground(const Common::Rect& r) {
void setupLabelSurface(Graphics::Surface &surf, uint w, uint h) {
- surf.create(w, h, 1);
+ surf.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
surf.fillRect(Common::Rect(w,h), LABEL_TRANSPARENT_COLOR);
}
@@ -857,7 +859,7 @@ void Gfx::setBackground(uint type, BackgroundInfo *info) {
int height = CLIP(info->height, (int)_vm->_screenHeight, info->height);
if (width != _backBuffer.w || height != _backBuffer.h) {
- _backBuffer.create(width, height, 1);
+ _backBuffer.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
}
}
diff --git a/engines/parallaction/gui.cpp b/engines/parallaction/gui.cpp
index c4a36e5362..db70ebb432 100644
--- a/engines/parallaction/gui.cpp
+++ b/engines/parallaction/gui.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "parallaction/gui.h"
namespace Parallaction {
diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp
index c80a9940a2..41e3082464 100644
--- a/engines/parallaction/gui_br.cpp
+++ b/engines/parallaction/gui_br.cpp
@@ -24,6 +24,7 @@
*/
#include "common/system.h"
+#include "common/textconsole.h"
#include "parallaction/gui.h"
#include "parallaction/input.h"
@@ -483,7 +484,7 @@ public:
_y = 90;
Graphics::Surface *surf = new Graphics::Surface;
- surf->create(w, 110, 1);
+ surf->create(w, 110, Graphics::PixelFormat::createFormatCLUT8());
surf->fillRect(Common::Rect(0, 0, w, 110), 12);
surf->fillRect(Common::Rect(10, 10, w-10, 100), 15);
diff --git a/engines/parallaction/gui_ns.cpp b/engines/parallaction/gui_ns.cpp
index 51d3ba5799..6b863cc808 100644
--- a/engines/parallaction/gui_ns.cpp
+++ b/engines/parallaction/gui_ns.cpp
@@ -25,6 +25,7 @@
#include "common/system.h"
#include "common/hashmap.h"
+#include "common/textconsole.h"
#include "parallaction/gui.h"
#include "parallaction/input.h"
@@ -474,7 +475,7 @@ class SelectCharacterInputState_NS : public MenuInputState {
public:
SelectCharacterInputState_NS(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("selectcharacter", helper), _vm(vm) {
_keys = (_vm->getPlatform() == Common::kPlatformAmiga && (_vm->getFeatures() & GF_LANG_MULT)) ? _amigaKeys : _pcKeys;
- _block.create(BLOCK_WIDTH, BLOCK_HEIGHT, 1);
+ _block.create(BLOCK_WIDTH, BLOCK_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
_labels[0] = 0;
_labels[1] = 0;
@@ -625,7 +626,7 @@ public:
_vm->_soundManI->stopMusic();
_vm->showSlide("password");
- _emptySlots.create(BLOCK_WIDTH * 8, BLOCK_HEIGHT, 1);
+ _emptySlots.create(BLOCK_WIDTH * 8, BLOCK_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
Common::Rect rect(SLOT_X, SLOT_Y, SLOT_X + BLOCK_WIDTH * 8, SLOT_Y + BLOCK_HEIGHT);
_vm->_gfx->grabBackground(rect, _emptySlots);
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index e508668d80..3a47b14deb 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -25,6 +25,7 @@
#include "common/events.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
#include "parallaction/exec.h"
@@ -486,7 +487,7 @@ void Input::initCursors() {
_donnaCursor = _vm->_disk->loadPointer("pointer3");
Graphics::Surface *surf = new Graphics::Surface;
- surf->create(_mouseComboProps_BR._width, _mouseComboProps_BR._height, 1);
+ surf->create(_mouseComboProps_BR._width, _mouseComboProps_BR._height, Graphics::PixelFormat::createFormatCLUT8());
_comboArrow = new SurfaceToFrames(surf);
// TODO: choose the pointer depending on the active character
@@ -495,12 +496,12 @@ void Input::initCursors() {
} else {
// TODO: Where are the Amiga cursors?
Graphics::Surface *surf1 = new Graphics::Surface;
- surf1->create(_mouseComboProps_BR._width, _mouseComboProps_BR._height, 1);
+ surf1->create(_mouseComboProps_BR._width, _mouseComboProps_BR._height, Graphics::PixelFormat::createFormatCLUT8());
_comboArrow = new SurfaceToFrames(surf1);
// TODO: scale mouse cursor (see staticres.cpp)
Graphics::Surface *surf2 = new Graphics::Surface;
- surf2->create(32, 16, 1);
+ surf2->create(32, 16, Graphics::PixelFormat::createFormatCLUT8());
memcpy(surf2->pixels, _resMouseArrow_BR_Amiga, 32*16);
_mouseArrow = new SurfaceToFrames(surf2);
}
diff --git a/engines/parallaction/inventory.cpp b/engines/parallaction/inventory.cpp
index 5ead55bbef..2412cc6445 100644
--- a/engines/parallaction/inventory.cpp
+++ b/engines/parallaction/inventory.cpp
@@ -26,7 +26,7 @@
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
-
+#include "common/textconsole.h"
namespace Parallaction {
@@ -141,7 +141,7 @@ void Parallaction::closeInventory() {
InventoryRenderer::InventoryRenderer(Parallaction *vm, InventoryProperties *props, Inventory *inv) : _vm(vm), _props(props), _inv(inv) {
- _surf.create(_props->_width, _props->_height, 1);
+ _surf.create(_props->_width, _props->_height, Graphics::PixelFormat::createFormatCLUT8());
}
InventoryRenderer::~InventoryRenderer() {
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
index c345b92ffb..e1306dc956 100644
--- a/engines/parallaction/objects.cpp
+++ b/engines/parallaction/objects.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "parallaction/parallaction.h"
#include "parallaction/objects.h"
#include "parallaction/parser.h"
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index 1113eb5dca..516d465671 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -23,13 +23,10 @@
*
*/
-#include "common/config-manager.h"
#include "common/debug-channels.h"
-#include "common/events.h"
#include "common/EventRecorder.h"
-#include "common/file.h"
-#include "common/util.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "parallaction/exec.h"
#include "parallaction/input.h"
@@ -52,6 +49,8 @@ uint32 _globalFlags = 0;
Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc), _location(getGameType()),
_dialogueMan(0) {
+ // Setup mixer
+ syncSoundSettings();
_vm = this;
DebugMan.addDebugChannel(kDebugDialogue, "dialogue", "Dialogues debug level");
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index a8a57ed2d8..b0b1145d2e 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -32,6 +32,7 @@
#include "common/func.h"
#include "common/random.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "engines/engine.h"
@@ -268,7 +269,7 @@ public:
virtual Common::Error run() {
Common::Error err;
err = init();
- if (err != Common::kNoError)
+ if (err.getCode() != Common::kNoError)
return err;
return go();
}
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 457c421fd7..ca344792cf 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -25,6 +25,7 @@
#include "common/system.h"
#include "common/util.h"
+#include "common/textconsole.h"
#include "parallaction/parallaction.h"
#include "parallaction/exec.h"
@@ -61,9 +62,7 @@ Common::Error Parallaction_br::init() {
_disk = new DosDisk_br(this);
}
_disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters.
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- MidiDriver *driver = MidiDriver::createMidi(dev);
- _soundManI = new DosSoundMan_br(this, driver);
+ _soundManI = new DosSoundMan_br(this);
} else {
_disk = new AmigaDisk_br(this);
_disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters.
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index c3d917a33d..ffc0412b1d 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -25,6 +25,7 @@
#include "common/system.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
#include "parallaction/parallaction.h"
#include "parallaction/exec.h"
@@ -166,9 +167,7 @@ Common::Error Parallaction_ns::init() {
_disk->init();
if (getPlatform() == Common::kPlatformPC) {
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- MidiDriver *driver = MidiDriver::createMidi(dev);
- _soundManI = new DosSoundMan_ns(this, driver);
+ _soundManI = new DosSoundMan_ns(this);
_soundManI->setMusicVolume(ConfMan.getInt("music_volume"));
} else {
_soundManI = new AmigaSoundMan_ns(this);
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp
index c964b74512..a7b926e485 100644
--- a/engines/parallaction/parser.cpp
+++ b/engines/parallaction/parser.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "parallaction/parallaction.h"
#include "parallaction/parser.h"
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index 9748be0526..f8818def9a 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/textconsole.h"
#include "parallaction/parallaction.h"
#include "parallaction/parser.h"
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
index 5053a3d7a5..6c9afe3d85 100644
--- a/engines/parallaction/parser_ns.cpp
+++ b/engines/parallaction/parser_ns.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "parallaction/parallaction.h"
#include "parallaction/parser.h"
#include "parallaction/sound.h"
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index b8116d6bc7..4c77aa3e02 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -25,6 +25,7 @@
#include "common/savefile.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
#include "gui/dialog.h"
#include "gui/saveload.h"
@@ -313,7 +314,7 @@ void SaveLoad_ns::renameOldSavefiles() {
if (_saveFileMan->renameSavefile(oldName, newName)) {
success++;
} else {
- warning("Error %i (%s) occurred while renaming %s to %s", _saveFileMan->getError(),
+ warning("Error %i (%s) occurred while renaming %s to %s", _saveFileMan->getError().getCode(),
_saveFileMan->getErrorDesc().c_str(), oldName.c_str(), newName.c_str());
}
}
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index 7b3eff37cb..455189d1fc 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -140,7 +140,7 @@ class DosSoundMan_ns : public SoundMan_ns {
public:
- DosSoundMan_ns(Parallaction_ns *vm, MidiDriver *midiDriver);
+ DosSoundMan_ns(Parallaction_ns *vm);
~DosSoundMan_ns();
void playMusic();
void stopMusic();
@@ -228,7 +228,7 @@ class DosSoundMan_br : public SoundMan_br {
Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping);
public:
- DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver);
+ DosSoundMan_br(Parallaction_br *vm);
~DosSoundMan_br();
void playMusic();
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index e127cf2838..abfaa4bf5d 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -24,11 +24,12 @@
*/
#include "common/stream.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "audio/mixer.h"
-#include "audio/mididrv.h"
#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
#include "audio/mods/protracker.h"
#include "audio/decoders/raw.h"
@@ -201,122 +202,76 @@ MidiParser *createParser_MSC() {
}
-class MidiPlayer_MSC : public MidiDriver {
+class MidiPlayer_MSC : public Audio::MidiPlayer {
public:
- enum {
- NUM_CHANNELS = 16
- };
-
- MidiPlayer_MSC(MidiDriver *driver);
- ~MidiPlayer_MSC();
+ MidiPlayer_MSC();
void play(Common::SeekableReadStream *stream);
- void stop();
- void pause(bool p);
- void updateTimer();
- void adjustVolume(int diff);
- void setVolume(int volume);
- int getVolume() const { return _masterVolume; }
- void setLooping(bool loop) { _isLooping = loop; }
-
- // MidiDriver interface
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ virtual void pause(bool p);
+ virtual void setVolume(int volume);
+ virtual void onTimer();
-private:
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
- static void timerCallback(void *p);
- void setVolumeInternal(int volume);
- Common::Mutex _mutex;
- MidiDriver *_driver;
- MidiParser *_parser;
- uint8 *_midiData;
- bool _isLooping;
- bool _isPlaying;
+private:
+ void setVolumeInternal(int volume);
bool _paused;
-
- int _masterVolume;
- MidiChannel *_channels[NUM_CHANNELS];
- uint8 _volume[NUM_CHANNELS];
};
-MidiPlayer_MSC::MidiPlayer_MSC(MidiDriver *driver)
- : _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _paused(false), _masterVolume(0) {
- assert(_driver);
- memset(_channels, 0, sizeof(_channels));
- for (int i = 0; i < NUM_CHANNELS; i++) {
- _volume[i] = 127;
- }
+MidiPlayer_MSC::MidiPlayer_MSC()
+ : _paused(false) {
- open();
-}
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
-MidiPlayer_MSC::~MidiPlayer_MSC() {
- close();
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MidiPlayer_MSC::play(Common::SeekableReadStream *stream) {
- if (!stream) {
- stop();
- return;
- }
+ Common::StackLock lock(_mutex);
stop();
+ if (!stream)
+ return;
+
int size = stream->size();
_midiData = (uint8 *)malloc(size);
if (_midiData) {
stream->read(_midiData, size);
delete stream;
- _mutex.lock();
+
+ _parser = createParser_MSC();
_parser->loadMusic(_midiData, size);
_parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
_isLooping = true;
_isPlaying = true;
- _mutex.unlock();
}
}
-void MidiPlayer_MSC::stop() {
- _mutex.lock();
- if (_isPlaying) {
- _isPlaying = false;
- _parser->unloadMusic();
- free(_midiData);
- _midiData = 0;
- }
- _mutex.unlock();
-}
-
void MidiPlayer_MSC::pause(bool p) {
_paused = p;
setVolumeInternal(_paused ? 0 : _masterVolume);
}
-void MidiPlayer_MSC::updateTimer() {
- if (_paused) {
- return;
- }
-
+void MidiPlayer_MSC::onTimer() {
Common::StackLock lock(_mutex);
- if (_isPlaying) {
+
+ if (!_paused && _isPlaying && _parser) {
_parser->onTimer();
}
}
-void MidiPlayer_MSC::adjustVolume(int diff) {
- setVolume(_masterVolume + diff);
-}
-
void MidiPlayer_MSC::setVolume(int volume) {
_masterVolume = CLIP(volume, 0, 255);
setVolumeInternal(_masterVolume);
@@ -324,76 +279,32 @@ void MidiPlayer_MSC::setVolume(int volume) {
void MidiPlayer_MSC::setVolumeInternal(int volume) {
Common::StackLock lock(_mutex);
- for (int i = 0; i < NUM_CHANNELS; ++i) {
- if (_channels[i]) {
- _channels[i]->volume(_volume[i] * volume / 255);
+ for (int i = 0; i < kNumChannels; ++i) {
+ if (_channelsTable[i]) {
+ _channelsTable[i]->volume(_channelsVolume[i] * volume / 255);
}
}
}
-int MidiPlayer_MSC::open() {
- int ret = _driver->open();
- if (ret == 0) {
- _parser = createParser_MSC();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(_driver->getBaseTempo());
- _driver->setTimerCallback(this, &timerCallback);
- }
- return ret;
-}
-
-void MidiPlayer_MSC::close() {
- stop();
- _mutex.lock();
- _driver->setTimerCallback(NULL, NULL);
- _driver->close();
- delete _driver;
- _driver = 0;
- _parser->setMidiDriver(NULL);
- delete _parser;
- _mutex.unlock();
-}
-
void MidiPlayer_MSC::send(uint32 b) {
+ // FIXME/TODO: Unlike Audio::MidiPlayer::send(), this code
+ // does not handle All Note Off. Is this on purpose?
+ // If not, we could simply remove this method, and use the
+ // inherited one.
const byte ch = b & 0x0F;
byte param2 = (b >> 16) & 0xFF;
switch (b & 0xFFF0) {
case 0x07B0: // volume change
- _volume[ch] = param2;
- break;
- }
-
- if (!_channels[ch]) {
- _channels[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- }
- if (_channels[ch]) {
- _channels[ch]->send(b);
- }
-}
-
-void MidiPlayer_MSC::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // end of Track
- if (_isLooping) {
- _parser->jumpToTick(0);
- } else {
- stop();
- }
- break;
- default:
+ _channelsVolume[ch] = param2;
break;
}
-}
-
-void MidiPlayer_MSC::timerCallback(void *p) {
- MidiPlayer_MSC *player = (MidiPlayer_MSC *)p;
- player->updateTimer();
+ sendToChannel(ch, b);
}
-DosSoundMan_br::DosSoundMan_br(Parallaction_br *vm, MidiDriver *driver) : SoundMan_br(vm) {
- _midiPlayer = new MidiPlayer_MSC(driver);
+DosSoundMan_br::DosSoundMan_br(Parallaction_br *vm) : SoundMan_br(vm) {
+ _midiPlayer = new MidiPlayer_MSC();
assert(_midiPlayer);
}
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index 15fdede571..5123695ebc 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -24,11 +24,12 @@
*/
#include "common/file.h"
-
#include "common/stream.h"
+#include "common/textconsole.h"
#include "audio/mixer.h"
#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
#include "audio/mods/protracker.h"
#include "audio/decoders/raw.h"
@@ -38,206 +39,75 @@
namespace Parallaction {
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public Audio::MidiPlayer {
public:
- enum {
- NUM_CHANNELS = 16
- };
-
- MidiPlayer(MidiDriver *driver);
- ~MidiPlayer();
+ MidiPlayer();
void play(Common::SeekableReadStream *stream);
- void stop();
void pause(bool p);
- void updateTimer();
- void adjustVolume(int diff);
- void setVolume(int volume);
- int getVolume() const { return _masterVolume; }
- void setLooping(bool loop) { _isLooping = loop; }
-
- // MidiDriver interface
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ virtual void onTimer();
private:
-
- static void timerCallback(void *p);
-
- MidiDriver *_driver;
- MidiParser *_parser;
- uint8 *_midiData;
- bool _isLooping;
- bool _isPlaying;
bool _paused;
- int _masterVolume;
- MidiChannel *_channelsTable[NUM_CHANNELS];
- uint8 _channelsVolume[NUM_CHANNELS];
- Common::Mutex _mutex;
};
-MidiPlayer::MidiPlayer(MidiDriver *driver)
- : _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _paused(false), _masterVolume(0) {
- assert(_driver);
- memset(_channelsTable, 0, sizeof(_channelsTable));
- for (int i = 0; i < NUM_CHANNELS; i++) {
- _channelsVolume[i] = 127;
- }
+MidiPlayer::MidiPlayer()
+ : _paused(false) {
- open();
-}
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
-MidiPlayer::~MidiPlayer() {
- close();
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
void MidiPlayer::play(Common::SeekableReadStream *stream) {
- if (!stream) {
- stop();
+ Common::StackLock lock(_mutex);
+
+ stop();
+ if (!stream)
return;
- }
int size = stream->size();
-
_midiData = (uint8 *)malloc(size);
if (_midiData) {
stream->read(_midiData, size);
delete stream;
- _mutex.lock();
+
+ _parser = MidiParser::createParser_SMF();
_parser->loadMusic(_midiData, size);
_parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
_isLooping = true;
_isPlaying = true;
- _mutex.unlock();
}
}
-void MidiPlayer::stop() {
- _mutex.lock();
- if (_isPlaying) {
- _isPlaying = false;
- _parser->unloadMusic();
- free(_midiData);
- _midiData = 0;
- }
- _mutex.unlock();
-}
-
void MidiPlayer::pause(bool p) {
_paused = p;
- for (int i = 0; i < NUM_CHANNELS; ++i) {
+ for (int i = 0; i < kNumChannels; ++i) {
if (_channelsTable[i]) {
_channelsTable[i]->volume(_paused ? 0 : _channelsVolume[i] * _masterVolume / 255);
}
}
}
-void MidiPlayer::updateTimer() {
- if (_paused) {
- return;
- }
+void MidiPlayer::onTimer() {
+ Common::StackLock lock(_mutex);
- _mutex.lock();
- if (_isPlaying) {
+ if (!_paused && _isPlaying && _parser) {
_parser->onTimer();
}
- _mutex.unlock();
-}
-
-void MidiPlayer::adjustVolume(int diff) {
- setVolume(_masterVolume + diff);
-}
-
-void MidiPlayer::setVolume(int volume) {
- _masterVolume = CLIP(volume, 0, 255);
- _mutex.lock();
- for (int i = 0; i < NUM_CHANNELS; ++i) {
- if (_channelsTable[i]) {
- _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
- }
- }
- _mutex.unlock();
-}
-
-int MidiPlayer::open() {
- int ret = _driver->open();
- if (ret == 0) {
- _parser = MidiParser::createParser_SMF();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(_driver->getBaseTempo());
- _driver->setTimerCallback(this, &timerCallback);
- }
- return ret;
-}
-
-void MidiPlayer::close() {
- stop();
- _mutex.lock();
- _driver->setTimerCallback(NULL, NULL);
- _driver->close();
- delete _driver;
- _driver = 0;
- _parser->setMidiDriver(NULL);
- delete _parser;
- _mutex.unlock();
-}
-
-void MidiPlayer::send(uint32 b) {
- byte volume, ch = (byte)(b & 0xF);
- switch (b & 0xFFF0) {
- case 0x07B0: // volume change
- volume = (byte)((b >> 16) & 0x7F);
- _channelsVolume[ch] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- break;
- case 0x7BB0: // all notes off
- if (!_channelsTable[ch]) {
- // channel not yet allocated, no need to send the event
- return;
- }
- break;
- }
-
- if (!_channelsTable[ch]) {
- _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- }
- if (_channelsTable[ch]) {
- _channelsTable[ch]->send(b);
- }
-}
-
-void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // end of Track
- if (_isLooping) {
- _parser->jumpToTick(0);
- } else {
- stop();
- }
- break;
- default:
-// warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MidiPlayer::timerCallback(void *p) {
- MidiPlayer *player = (MidiPlayer *)p;
-
- player->updateTimer();
}
-DosSoundMan_ns::DosSoundMan_ns(Parallaction_ns *vm, MidiDriver *midiDriver) : SoundMan_ns(vm), _playing(false) {
- _midiPlayer = new MidiPlayer(midiDriver);
+DosSoundMan_ns::DosSoundMan_ns(Parallaction_ns *vm) : SoundMan_ns(vm), _playing(false) {
+ _midiPlayer = new MidiPlayer();
}
DosSoundMan_ns::~DosSoundMan_ns() {
diff --git a/engines/pegasus/graphics.cpp b/engines/pegasus/graphics.cpp
index de3fe06fcb..2042b8f712 100644
--- a/engines/pegasus/graphics.cpp
+++ b/engines/pegasus/graphics.cpp
@@ -24,6 +24,7 @@
#include "common/endian.h"
#include "common/file.h"
+#include "common/textconsole.h"
#include "engines/util.h"
#include "graphics/cursorman.h"
@@ -63,10 +64,10 @@ Graphics::Surface *GraphicsManager::decodeImage(const Common::String &filename)
Graphics::Surface *image = _pictDecoder->decodeImage(&file, palette);
// For <= 8bpp, we need to convert
- if (image->bytesPerPixel == 1) {
+ if (image->format.bytesPerPixel == 1) {
Graphics::PixelFormat format = _vm->_system->getScreenFormat();
Graphics::Surface *output = new Graphics::Surface();
- output->create(image->w, image->h, format.bytesPerPixel);
+ output->create(image->w, image->h, format);
for (uint16 y = 0; y < image->h; y++) {
for (uint16 x = 0; x < image->w; x++) {
@@ -135,7 +136,7 @@ uint32 GraphicsManager::getColor(byte r, byte g, byte b) {
}
void GraphicsManager::setCursor(uint16 cursor) {
- Common::SeekableReadStream *cicnStream = _vm->_resFork->getResource(MKID_BE('cicn'), cursor);
+ Common::SeekableReadStream *cicnStream = _vm->_resFork->getResource(MKTAG('c', 'i', 'c', 'n'), cursor);
// PixMap section
Graphics::PictDecoder::PixMap pixMap = _pictDecoder->readPixMap(cicnStream);
@@ -181,9 +182,9 @@ void GraphicsManager::setCursor(uint16 cursor) {
Common::SeekableReadStream *cursStream = NULL;
if (cursor >= kMainCursor && cursor <= kGrabbingHand)
- cursStream = _vm->_resFork->getResource(MKID_BE('Curs'), kMainCursor);
+ cursStream = _vm->_resFork->getResource(MKTAG('C', 'u', 'r', 's'), kMainCursor);
else // if (cursor == kTargetingReticle1 || cursor == kTargetingReticle2)
- cursStream = _vm->_resFork->getResource(MKID_BE('Curs'), kTargetingReticle1);
+ cursStream = _vm->_resFork->getResource(MKTAG('C', 'u', 'r', 's'), kTargetingReticle1);
// Go through the stream until we find the right cursor hotspot
uint16 x = 0, y = 0;
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 5f95a584fd..35d1a9f1e6 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -21,7 +21,9 @@
*/
#include "common/config-manager.h"
+#include "common/error.h"
#include "common/events.h"
+#include "common/textconsole.h"
#include "base/plugins.h"
#include "base/version.h"
@@ -131,7 +133,7 @@ Common::Error PegasusEngine::run() {
}
void PegasusEngine::loadItemLocationData() {
- Common::SeekableReadStream *res = _resFork->getResource(MKID_BE('NItm'), 0x80);
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('N', 'I', 't', 'm'), 0x80);
uint16 entryCount = res->readUint16BE();
@@ -206,7 +208,7 @@ void PegasusEngine::changeLocation(TimeZone timeZone) {
void PegasusEngine::loadViews(TimeZone timeZone) {
_currentViews.clear();
- Common::SeekableReadStream *res = _resFork->getResource(MKID_BE('View'), getTimeZoneDesc(timeZone));
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('V', 'i', 'e', 'w'), getTimeZoneDesc(timeZone));
uint32 entryCount = res->readUint32BE();
@@ -226,7 +228,7 @@ void PegasusEngine::loadViews(TimeZone timeZone) {
void PegasusEngine::loadDoors(TimeZone timeZone) {
_currentDoors.clear();
- Common::SeekableReadStream *res = _resFork->getResource(MKID_BE('Door'), getTimeZoneDesc(timeZone));
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('D', 'o', 'o', 'r'), getTimeZoneDesc(timeZone));
uint32 entryCount = res->readUint32BE();
@@ -247,7 +249,7 @@ void PegasusEngine::loadDoors(TimeZone timeZone) {
void PegasusEngine::loadSoundSpots(TimeZone timeZone) {
_currentSoundSpots.clear();
- Common::SeekableReadStream *res = _resFork->getResource(MKID_BE('Spot'), getTimeZoneDesc(timeZone));
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('S', 'p', 'o', 't'), getTimeZoneDesc(timeZone));
uint32 entryCount = res->readUint32BE();
@@ -269,7 +271,7 @@ void PegasusEngine::loadSoundSpots(TimeZone timeZone) {
void PegasusEngine::loadZooms(TimeZone timeZone) {
_currentZooms.clear();
- Common::SeekableReadStream *res = _resFork->getResource(MKID_BE('Zoom'), getTimeZoneDesc(timeZone));
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('Z', 'o', 'o', 'm'), getTimeZoneDesc(timeZone));
uint32 entryCount = res->readUint32BE();
@@ -290,7 +292,7 @@ void PegasusEngine::loadZooms(TimeZone timeZone) {
void PegasusEngine::loadExtras(TimeZone timeZone) {
_currentExtras.clear();
- Common::SeekableReadStream *res = _resFork->getResource(MKID_BE('Xtra'), getTimeZoneDesc(timeZone));
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('X', 't', 'r', 'a'), getTimeZoneDesc(timeZone));
uint32 entryCount = res->readUint32BE();
diff --git a/engines/pegasus/sound.cpp b/engines/pegasus/sound.cpp
index 9ef89ab993..b87bff423a 100644
--- a/engines/pegasus/sound.cpp
+++ b/engines/pegasus/sound.cpp
@@ -23,6 +23,7 @@
#include "pegasus/sound.h"
#include "common/file.h"
+#include "common/textconsole.h"
#include "audio/decoders/aiff.h"
namespace Pegasus {
diff --git a/engines/pegasus/video.cpp b/engines/pegasus/video.cpp
index 6b850db42b..277065b53e 100644
--- a/engines/pegasus/video.cpp
+++ b/engines/pegasus/video.cpp
@@ -24,6 +24,7 @@
#include "pegasus/video.h"
#include "common/events.h"
+#include "common/textconsole.h"
#include "graphics/scaler.h"
#include "video/qt_decoder.h"
@@ -169,7 +170,7 @@ bool VideoManager::updateBackgroundMovies() {
const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
if (frame) {
- if (frame->bytesPerPixel == 1)
+ if (frame->format.bytesPerPixel == 1)
error("Unhandled 8bpp frames"); // Cut out because Pegasus Prime shouldn't need this
// Clip the width/height to make sure we stay on the screen
@@ -182,7 +183,7 @@ bool VideoManager::updateBackgroundMovies() {
_videoStreams[i].x = 0;
_videoStreams[i].y = 0;
Graphics::Surface scaledSurf;
- scaledSurf.create(frame->w * 2, frame->h * 2, frame->bytesPerPixel);
+ scaledSurf.create(frame->w * 2, frame->h * 2, frame->format);
Normal2x((byte *)frame->pixels, frame->pitch, (byte *)scaledSurf.pixels, scaledSurf.pitch, frame->w, frame->h);
_vm->_system->copyRectToScreen((byte*)scaledSurf.pixels, scaledSurf.pitch, _videoStreams[i].x, _videoStreams[i].y, width * 2, height * 2);
scaledSurf.free();
diff --git a/engines/queen/command.cpp b/engines/queen/command.cpp
index 356856e940..87b24735a8 100644
--- a/engines/queen/command.cpp
+++ b/engines/queen/command.cpp
@@ -24,8 +24,6 @@
*/
-#include "common/events.h"
-#include "common/system.h"
#include "queen/command.h"
#include "queen/display.h"
diff --git a/engines/queen/cutaway.cpp b/engines/queen/cutaway.cpp
index 11a8704d60..6fb48c7fb0 100644
--- a/engines/queen/cutaway.cpp
+++ b/engines/queen/cutaway.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/textconsole.h"
#include "queen/cutaway.h"
diff --git a/engines/queen/display.cpp b/engines/queen/display.cpp
index 7b16df52bf..c78fd8ebcc 100644
--- a/engines/queen/display.cpp
+++ b/engines/queen/display.cpp
@@ -29,6 +29,7 @@
#include "common/events.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
#include "queen/display.h"
#include "queen/input.h"
@@ -843,19 +844,19 @@ void Display::decodeLBM(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dst
uint32 size = READ_BE_UINT32(src + 4);
src += 8;
switch (type) {
- case MKID_BE('BMHD'): {
+ case MKTAG('B','M','H','D'): {
*w = READ_BE_UINT16(src + 0);
*h = READ_BE_UINT16(src + 2);
planeCount = src[8];
planePitch = ((*w + 15) >> 4) * 2;
}
break;
- case MKID_BE('CMAP'): {
+ case MKTAG('C','M','A','P'): {
assert(palStart <= palEnd && palEnd <= size / 3);
memcpy(pal, src + palStart * 3, (palEnd - palStart) * 3);
}
break;
- case MKID_BE('BODY'): {
+ case MKTAG('B','O','D','Y'): {
uint32 planarSize = (*h) * planeCount * planePitch;
uint8 *planarBuf = new uint8[planarSize];
uint8 *dstPlanar = planarBuf;
diff --git a/engines/queen/display.h b/engines/queen/display.h
index d3391fc4d3..e7a2ecd4a1 100644
--- a/engines/queen/display.h
+++ b/engines/queen/display.h
@@ -32,8 +32,9 @@
#include "queen/defs.h"
class OSystem;
+
namespace Common {
- struct Rect;
+struct Rect;
}
namespace Queen {
diff --git a/engines/queen/graphics.cpp b/engines/queen/graphics.cpp
index 17e36b1d90..c86f679765 100644
--- a/engines/queen/graphics.cpp
+++ b/engines/queen/graphics.cpp
@@ -34,6 +34,9 @@
#include "queen/resource.h"
#include "queen/sound.h"
+#include "common/debug.h"
+#include "common/textconsole.h"
+
namespace Queen {
void BobSlot::curPos(int16 xx, int16 yy) {
diff --git a/engines/queen/input.cpp b/engines/queen/input.cpp
index 9518388b26..eac855a0cd 100644
--- a/engines/queen/input.cpp
+++ b/engines/queen/input.cpp
@@ -26,6 +26,7 @@
#include "common/events.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "queen/queen.h"
#include "queen/input.h"
diff --git a/engines/queen/journal.cpp b/engines/queen/journal.cpp
index aff24be22e..4200168f07 100644
--- a/engines/queen/journal.cpp
+++ b/engines/queen/journal.cpp
@@ -24,6 +24,7 @@
*/
+#include "common/error.h"
#include "common/events.h"
#include "common/system.h"
#include "queen/journal.h"
diff --git a/engines/queen/logic.cpp b/engines/queen/logic.cpp
index de254300b6..e99a739726 100644
--- a/engines/queen/logic.cpp
+++ b/engines/queen/logic.cpp
@@ -25,8 +25,7 @@
#include "common/config-manager.h"
-#include "common/events.h"
-#include "common/system.h"
+#include "common/textconsole.h"
#include "queen/logic.h"
diff --git a/engines/queen/midiadlib.cpp b/engines/queen/midiadlib.cpp
index c3bc6d1c17..af52f7ed2b 100644
--- a/engines/queen/midiadlib.cpp
+++ b/engines/queen/midiadlib.cpp
@@ -24,14 +24,13 @@
*/
#include "common/endian.h"
+#include "common/textconsole.h"
#include "audio/fmopl.h"
#include "audio/softsynth/emumidi.h"
namespace Queen {
-class AdLibMidiChannel;
-
class AdLibMidiDriver : public MidiDriver_Emulated {
public:
diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp
index 4dc698dac9..58ecfa6d16 100644
--- a/engines/queen/music.cpp
+++ b/engines/queen/music.cpp
@@ -40,9 +40,9 @@ namespace Queen {
extern MidiDriver *C_Player_CreateAdLibMidiDriver(Audio::Mixer *);
MidiMusic::MidiMusic(QueenEngine *vm)
- : _isPlaying(false), _looping(false), _randomLoop(false), _masterVolume(192), _buf(0) {
+ : _isPlaying(false), _isLooping(false), _randomLoop(false), _masterVolume(192), _buf(0) {
- memset(_channel, 0, sizeof(_channel));
+ memset(_channelsTable, 0, sizeof(_channelsTable));
_queuePos = _lastSong = _currentSong = 0;
queueClear();
@@ -78,8 +78,10 @@ MidiMusic::MidiMusic(QueenEngine *vm)
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
}
}
+ assert(_driver);
- _driver->open();
+ int ret = _driver->open();
+ assert(ret == 0);
_driver->setTimerCallback(this, &timerCallback);
if (_nativeMT32)
@@ -116,8 +118,8 @@ void MidiMusic::setVolume(int volume) {
_masterVolume = volume;
for (int i = 0; i < 16; ++i) {
- if (_channel[i])
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
+ if (_channelsTable[i])
+ _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
}
}
@@ -154,7 +156,7 @@ bool MidiMusic::queueSong(uint16 songNum) {
void MidiMusic::queueClear() {
_lastSong = _songQueue[0];
_queuePos = 0;
- _looping = _randomLoop = false;
+ _isLooping = _randomLoop = false;
memset(_songQueue, 0, sizeof(_songQueue));
}
@@ -168,7 +170,7 @@ void MidiMusic::send(uint32 b) {
if ((b & 0xFFF0) == 0x07B0) {
// Adjust volume changes by master volume
byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
+ _channelsVolume[channel] = volume;
volume = volume * _masterVolume / 255;
b = (b & 0xFF00FFFF) | (volume << 16);
} else if ((b & 0xF0) == 0xC0 && !_nativeMT32) {
@@ -176,7 +178,7 @@ void MidiMusic::send(uint32 b) {
} else if ((b & 0xFFF0) == 0x007BB0) {
//Only respond to All Notes Off if this channel
//has currently been allocated
- if (_channel[channel])
+ if (!_channelsTable[channel])
return;
}
@@ -188,17 +190,17 @@ void MidiMusic::send(uint32 b) {
if (channel == 5 && _currentSong == 38)
return;
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ if (!_channelsTable[channel])
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- if (_channel[channel])
- _channel[channel]->send(b);
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
switch (type) {
case 0x2F: // End of Track
- if (_looping || _songQueue[1]) {
+ if (_isLooping || _songQueue[1]) {
playMusic();
} else {
stopMusic();
@@ -216,10 +218,9 @@ void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
}
void MidiMusic::onTimer() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
if (_isPlaying)
_parser->onTimer();
- _mutex.unlock();
}
void MidiMusic::queueTuneList(int16 tuneList) {
@@ -317,11 +318,10 @@ void MidiMusic::playMusic() {
stopMusic();
- _mutex.lock();
+ Common::StackLock lock(_mutex);
_parser->loadMusic(musicPtr, size);
_parser->setTrack(0);
_isPlaying = true;
- _mutex.unlock();
debug(8, "Playing song %d [queue position: %d]", songNum, _queuePos);
queueUpdatePos();
@@ -333,7 +333,7 @@ void MidiMusic::queueUpdatePos() {
} else {
if (_queuePos < (MUSIC_QUEUE_SIZE - 1) && _songQueue[_queuePos + 1])
_queuePos++;
- else if (_looping)
+ else if (_isLooping)
_queuePos = 0;
}
}
@@ -347,14 +347,13 @@ uint8 MidiMusic::randomQueuePos() {
if (!queueSize)
return 0;
- return (uint8) _rnd.getRandomNumber(queueSize - 1) & 0xFF;
+ return (uint8)_rnd.getRandomNumber(queueSize - 1) & 0xFF;
}
void MidiMusic::stopMusic() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
_isPlaying = false;
_parser->unloadMusic();
- _mutex.unlock();
}
uint32 MidiMusic::songOffset(uint16 songNum) const {
diff --git a/engines/queen/music.h b/engines/queen/music.h
index fe45d56fde..3e8fc585ca 100644
--- a/engines/queen/music.h
+++ b/engines/queen/music.h
@@ -39,7 +39,7 @@ struct TuneData;
class QueenEngine;
-class MidiMusic : public MidiDriver {
+class MidiMusic : public MidiDriver_BASE {
public:
MidiMusic(QueenEngine *vm);
~MidiMusic();
@@ -50,25 +50,15 @@ public:
void stopSong() { stopMusic(); }
void playMusic();
void stopMusic();
- void setLoop(bool loop) { _looping = loop; }
+ void setLoop(bool loop) { _isLooping = loop; }
void queueTuneList(int16 tuneList);
bool queueSong(uint16 songNum);
void queueClear();
void toggleVChange();
- //MidiDriver interface implementation
- int open() { return 0; }
- void close() {}
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
protected:
@@ -86,15 +76,15 @@ protected:
MidiDriver *_driver;
MidiParser *_parser;
- MidiChannel *_channel[16];
- byte _channelVolume[16];
+ MidiChannel *_channelsTable[16];
+ byte _channelsVolume[16];
bool _adlib;
bool _nativeMT32;
Common::Mutex _mutex;
Common::RandomSource _rnd;
bool _isPlaying;
- bool _looping;
+ bool _isLooping;
bool _randomLoop;
byte _masterVolume;
uint8 _queuePos;
diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp
index 74bb52f574..0dde5c7b42 100644
--- a/engines/queen/queen.cpp
+++ b/engines/queen/queen.cpp
@@ -32,6 +32,7 @@
#include "common/system.h"
#include "common/events.h"
#include "common/EventRecorder.h"
+#include "common/textconsole.h"
#include "engines/util.h"
@@ -240,14 +241,20 @@ void QueenEngine::checkOptionSettings() {
}
void QueenEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
readOptionSettings();
}
void QueenEngine::readOptionSettings() {
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
_sound->setVolume(ConfMan.getInt("music_volume"));
- _sound->musicToggle(!ConfMan.getBool("music_mute"));
- _sound->sfxToggle(!ConfMan.getBool("sfx_mute"));
- _sound->speechToggle(!ConfMan.getBool("speech_mute"));
+ _sound->musicToggle(!(mute || ConfMan.getBool("music_mute")));
+ _sound->sfxToggle(!(mute || ConfMan.getBool("sfx_mute")));
+ _sound->speechToggle(!(mute || ConfMan.getBool("speech_mute")));
_talkSpeed = (ConfMan.getInt("talkspeed") * (MAX_TEXT_SPEED - MIN_TEXT_SPEED) + 255 / 2) / 255 + MIN_TEXT_SPEED;
_subtitles = ConfMan.getBool("subtitles");
checkOptionSettings();
@@ -397,7 +404,7 @@ Common::InSaveFile *QueenEngine::readGameStateHeader(int slot, GameStateHeader *
char name[20];
makeGameStateName(slot, name);
Common::InSaveFile *file = _saveFileMan->openForLoading(name);
- if (file && file->readUint32BE() == MKID_BE('SCVM')) {
+ if (file && file->readUint32BE() == MKTAG('S','C','V','M')) {
gsh->version = file->readUint32BE();
gsh->flags = file->readUint32BE();
gsh->dataSize = file->readUint32BE();
@@ -470,11 +477,14 @@ Common::Error QueenEngine::run() {
}
_sound = Sound::makeSoundInstance(_mixer, this, _resource->getCompression());
+
_walk = new Walk(this);
//_talkspeedScale = (MAX_TEXT_SPEED - MIN_TEXT_SPEED) / 255.0;
registerDefaultSettings();
- readOptionSettings();
+
+ // Setup mixer
+ syncSoundSettings();
_logic->start();
if (ConfMan.hasKey("save_slot") && canLoadOrSave()) {
diff --git a/engines/queen/queen.h b/engines/queen/queen.h
index 93d705b182..6098a9f5c2 100644
--- a/engines/queen/queen.h
+++ b/engines/queen/queen.h
@@ -30,7 +30,7 @@
#include "common/random.h"
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
#if defined(_WIN32_WCE) && (_WIN32_WCE <= 300)
diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp
index a70d1f1613..62b13e290c 100644
--- a/engines/queen/resource.cpp
+++ b/engines/queen/resource.cpp
@@ -27,6 +27,7 @@
#include "common/endian.h"
#include "common/config-manager.h"
#include "common/substream.h"
+#include "common/textconsole.h"
#include "queen/resource.h"
namespace Queen {
@@ -132,7 +133,7 @@ void Resource::loadTextFile(const char *filename, Common::StringArray &stringLis
bool Resource::detectVersion(DetectedGameVersion *ver, Common::File *f) {
memset(ver, 0, sizeof(DetectedGameVersion));
- if (f->readUint32BE() == MKID_BE('QTBL')) {
+ if (f->readUint32BE() == MKTAG('Q','T','B','L')) {
f->read(ver->str, 6);
f->skip(2);
ver->compression = f->readByte();
@@ -269,7 +270,7 @@ void Resource::seekResourceFile(int num, uint32 offset) {
void Resource::readTableFile(uint8 version, uint32 offset) {
Common::File tableFile;
tableFile.open(_tableFilename);
- if (tableFile.isOpen() && tableFile.readUint32BE() == MKID_BE('QTBL')) {
+ if (tableFile.isOpen() && tableFile.readUint32BE() == MKTAG('Q','T','B','L')) {
uint32 tableVersion = tableFile.readUint32BE();
if (version > tableVersion) {
error("The game you are trying to play requires version %d of queen.tbl, "
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp
index 6eb7362338..afb77f3969 100644
--- a/engines/queen/sound.cpp
+++ b/engines/queen/sound.cpp
@@ -27,6 +27,7 @@
#include "common/config-manager.h"
#include "common/endian.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "queen/sound.h"
#include "queen/input.h"
@@ -192,10 +193,12 @@ Sound *Sound::makeSoundInstance(Audio::Mixer *mixer, QueenEngine *vm, uint8 comp
}
void Sound::setVolume(int vol) {
- _musicVolume = vol;
+ if (ConfMan.hasKey("mute") && ConfMan.getBool("mute"))
+ _musicVolume = 0;
+ else
+ _musicVolume = vol;
+
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _musicVolume);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
}
void Sound::saveState(byte *&ptr) {
diff --git a/engines/queen/sound.h b/engines/queen/sound.h
index cee0463ed1..a89e345791 100644
--- a/engines/queen/sound.h
+++ b/engines/queen/sound.h
@@ -32,7 +32,7 @@
#include "queen/defs.h"
namespace Common {
- class File;
+class File;
}
namespace Queen {
diff --git a/engines/queen/talk.cpp b/engines/queen/talk.cpp
index 106b0d6123..18c712b799 100644
--- a/engines/queen/talk.cpp
+++ b/engines/queen/talk.cpp
@@ -24,9 +24,8 @@
*/
-#include "common/events.h"
-#include "common/system.h"
#include "common/rect.h"
+#include "common/textconsole.h"
#include "queen/talk.h"
diff --git a/engines/queen/walk.cpp b/engines/queen/walk.cpp
index 7765828bd7..a778ea5b05 100644
--- a/engines/queen/walk.cpp
+++ b/engines/queen/walk.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/textconsole.h"
#include "queen/walk.h"
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index e43f1ee5c7..b1bcc99295 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -264,7 +264,7 @@ SaveStateDescriptor SagaMetaEngine::querySaveMetaInfos(const char *target, int s
if (version < 4)
warning("This savegame is not endian-safe. There may be problems");
- if (type != MKID_BE('SAGA')) {
+ if (type != MKTAG('S','A','G','A')) {
error("SagaEngine::load wrong save game format");
}
@@ -372,12 +372,13 @@ Common::Error SagaEngine::saveGameState(int slot, const char *desc) {
}
bool SagaEngine::canLoadGameStateCurrently() {
- return !_scene->isInIntro();
+ return !_scene->isInIntro() &&
+ (_interface->getMode() == kPanelMain || _interface->getMode() == kPanelChapterSelection);
}
bool SagaEngine::canSaveGameStateCurrently() {
return !_scene->isInIntro() &&
- (_interface->getMode() == kPanelMain || _interface->getMode() == kPanelChapterSelection);
+ (_interface->getMode() == kPanelMain || _interface->getMode() == kPanelChapterSelection);
}
} // End of namespace Saga
diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp
index 01e74d2984..2434f7aad8 100644
--- a/engines/saga/font.cpp
+++ b/engines/saga/font.cpp
@@ -434,7 +434,6 @@ int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags
int textWidth;
int textLength;
int fitWidth;
- const char *startPointer;
const char *searchPointer;
const char *measurePointer;
const char *foundPointer;
@@ -465,7 +464,6 @@ int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags
len_total = 0;
wc = 0;
- startPointer = text;
measurePointer = text;
searchPointer = text;
endPointer = text + textLength;
@@ -498,7 +496,6 @@ int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags
len_total = 0;
wc = 0;
measurePointer = searchPointer;
- startPointer = searchPointer;
} else {
// Word will fit ok
w_total += w;
diff --git a/engines/saga/gfx.cpp b/engines/saga/gfx.cpp
index 5fc2082178..4930718b67 100644
--- a/engines/saga/gfx.cpp
+++ b/engines/saga/gfx.cpp
@@ -34,6 +34,7 @@
#include "common/system.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
#include "engines/util.h"
namespace Saga {
@@ -46,7 +47,7 @@ Gfx::Gfx(SagaEngine *vm, OSystem *system, int width, int height) : _vm(vm), _sys
debug(5, "Init screen %dx%d", width, height);
// Convert surface data to R surface data
- _backBuffer.create(width, height, 1);
+ _backBuffer.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
// Start with the cursor shown. It will be hidden before the intro, if
// there is an intro. (With boot params, there may not be.)
diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h
index 33fac10c63..56d9104371 100644
--- a/engines/saga/gfx.h
+++ b/engines/saga/gfx.h
@@ -28,6 +28,7 @@
#ifndef SAGA_GFX_H
#define SAGA_GFX_H
+#include "common/rect.h"
#include "graphics/surface.h"
namespace Saga {
diff --git a/engines/saga/image.cpp b/engines/saga/image.cpp
index 87d9e514c8..ac9fe94f2f 100644
--- a/engines/saga/image.cpp
+++ b/engines/saga/image.cpp
@@ -322,7 +322,6 @@ void SagaEngine::unbankBGImage(byte *dst_buf, const byte *src_buf, int columns,
int rowjump_src;
int rowjump_dest;
const byte *src_p;
- byte *dst_p;
const byte *srcptr1, *srcptr2, *srcptr3, *srcptr4;
byte *dstptr1, *dstptr2, *dstptr3, *dstptr4;
@@ -332,7 +331,6 @@ void SagaEngine::unbankBGImage(byte *dst_buf, const byte *src_buf, int columns,
assert(scanlines > 0);
src_p = src_buf;
- dst_p = dst_buf + columns;
srcptr1 = src_p;
srcptr2 = src_p + 1;
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 5a3b229c9d..c3773b2cb2 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -1379,9 +1379,7 @@ void Interface::setSave(PanelButton *panelButton) {
fileName = _vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
_vm->save(fileName, _textInputString);
}
- _vm->getTimerManager()->removeTimerProc(&saveReminderCallback);
- _vm->getTimerManager()->installTimerProc(&saveReminderCallback, TIMETOSAVE, this);
- setSaveReminderState(1);
+ resetSaveReminder();
_textInput = false;
setMode(kPanelOption);
@@ -1393,6 +1391,12 @@ void Interface::setSave(PanelButton *panelButton) {
}
}
+void Interface::resetSaveReminder() {
+ _vm->getTimerManager()->removeTimerProc(&saveReminderCallback);
+ _vm->getTimerManager()->installTimerProc(&saveReminderCallback, TIMETOSAVE, this);
+ setSaveReminderState(1);
+}
+
void Interface::handleOptionUpdate(const Point& mousePoint) {
int16 mouseY;
Rect rect;
@@ -2794,7 +2798,7 @@ void Interface::keyBoss() {
Rect rect;
ByteArray image;
int imageWidth, imageHeight;
- const byte *pal;
+ //const byte *pal;
PalEntry cPal[PAL_ENTRIES];
_vm->_gfx->showCursor(false);
@@ -2814,7 +2818,7 @@ void Interface::keyBoss() {
rect.setHeight(imageHeight);
_vm->_gfx->getCurrentPal(_mapSavedPal);
- pal = _vm->getImagePal(resourceData);
+ //pal = _vm->getImagePal(resourceData);
cPal[0].red = 0;
cPal[0].green = 0;
diff --git a/engines/saga/interface.h b/engines/saga/interface.h
index b9a96653a7..09631bf0e8 100644
--- a/engines/saga/interface.h
+++ b/engines/saga/interface.h
@@ -288,6 +288,8 @@ public:
int32 getProtectHash() { return _protectHash; }
+ void resetSaveReminder();
+
private:
void handleMainUpdate(const Point& mousePoint); // main panel update
void handleMainClick(const Point& mousePoint); // main panel click
diff --git a/engines/saga/introproc_saga2.cpp b/engines/saga/introproc_saga2.cpp
index 5ae80b14c9..7f04474c61 100644
--- a/engines/saga/introproc_saga2.cpp
+++ b/engines/saga/introproc_saga2.cpp
@@ -31,7 +31,10 @@
#include "saga/scene.h"
#include "saga/gfx.h"
-#include "audio/mixer.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
#include "video/smk_decoder.h"
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index dd3034cdb9..eb0a911555 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -44,85 +44,88 @@ namespace Saga {
#define MUSIC_SUNSPOT 26
MusicDriver::MusicDriver() : _isGM(false) {
- memset(_channel, 0, sizeof(_channel));
- _masterVolume = 0;
- _nativeMT32 = ConfMan.getBool("native_mt32");
+
+ MidiPlayer::createDriver();
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _driver = MidiDriver::createMidi(dev);
_driverType = MidiDriver::getMusicType(dev);
- if (isMT32())
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- this->open();
-}
+ int retValue = _driver->open();
+ if (retValue == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
-MusicDriver::~MusicDriver() {
- this->close();
- delete _driver;
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
-int MusicDriver::open() {
- int retValue = _driver->open();
- if (retValue)
- return retValue;
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
+void MusicDriver::send(uint32 b) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ // Remap MT32 instruments to General Midi
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+ Audio::MidiPlayer::send(b);
+}
- return 0;
+void MusicDriver::metaEvent(byte type, byte *data, uint16 length) {
+ // TODO: Seems SAGA does not want / need to handle end-of-track events?
}
-void MusicDriver::setVolume(int volume) {
- volume = CLIP(volume, 0, 255);
+void MusicDriver::play(SagaEngine *vm, ByteArray *buffer, bool loop) {
+ if (buffer->size() < 4) {
+ error("Music::play() wrong music resource size");
+ }
- if (_masterVolume == volume)
- return;
+ // Check if the game is using XMIDI or SMF music
+ if (vm->getGameId() == GID_IHNM && vm->isMacResources()) {
+ // Just set an XMIDI parser for Mac IHNM for now
+ _parser = MidiParser::createParser_XMIDI();
+ } else {
+ if (!memcmp(buffer->getBuffer(), "FORM", 4)) {
+ _parser = MidiParser::createParser_XMIDI();
+ // ITE had MT32 mapped instruments
+ _isGM = (vm->getGameId() != GID_ITE);
+ } else {
+ _parser = MidiParser::createParser_SMF();
+ // ITE with standalone MIDI files is General MIDI
+ _isGM = (vm->getGameId() == GID_ITE);
+ }
+ }
+
+ if (!_parser->loadMusic(buffer->getBuffer(), buffer->size()))
+ error("Music::play() wrong music resource");
- _masterVolume = volume;
+ _parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+ _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+ _parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
- Common::StackLock lock(_mutex);
+ // Handle music looping
+ _parser->property(MidiParser::mpAutoLoop, loop);
+// _isLooping = loop;
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
- }
- }
+ _isPlaying = true;
}
-void MusicDriver::send(uint32 b) {
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0 && !_isGM && !isMT32()) {
- // Remap MT32 instruments to General Midi
- b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
- } else if ((b & 0xFFF0) == 0x007BB0) {
- // Only respond to All Notes Off if this channel
- // has currently been allocated
- if (!_channel[channel])
- return;
- }
+void MusicDriver::pause() {
+ _isPlaying = false;
+}
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- else
- _channel[channel]->send(b);
+void MusicDriver::resume() {
+ _isPlaying = true;
}
+
Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
_currentVolume = 0;
_currentMusicBuffer = NULL;
- _driver = new MusicDriver();
+ _player = new MusicDriver();
_digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE);
- if (!_driver->isAdlib())
+ if (!_player->isAdlib())
_musicContext = _vm->_resource->getContext(GAME_MUSICFILE_GM);
else
_musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM);
@@ -159,55 +162,19 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
}
}
- // Check if the game is using XMIDI or SMF music
- if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
- // Just set an XMIDI parser for Mac IHNM for now
- _parser = MidiParser::createParser_XMIDI();
- } else {
- ByteArray resourceData;
- int resourceId = (_vm->getGameId() == GID_ITE ? 9 : 0);
- _vm->_resource->loadResource(_musicContext, resourceId, resourceData);
- if (resourceData.size() < 4) {
- error("Music::Music Unable to load midi resource data");
- }
- if (!memcmp(resourceData.getBuffer(), "FORM", 4)) {
- _parser = MidiParser::createParser_XMIDI();
- // ITE had MT32 mapped instruments
- _driver->setGM(_vm->getGameId() != GID_ITE);
- } else {
- _parser = MidiParser::createParser_SMF();
- // ITE with standalone MIDI files is General MIDI
- _driver->setGM(_vm->getGameId() == GID_ITE);
- }
- }
-
- _parser->setMidiDriver(_driver);
- _parser->setTimerRate(_driver->getBaseTempo());
- _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
- _parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
-
_digitalMusic = false;
}
Music::~Music() {
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
_mixer->stopHandle(_musicHandle);
- _driver->setTimerCallback(NULL, NULL);
- delete _driver;
- _parser->setMidiDriver(NULL);
- delete _parser;
+ delete _player;
}
void Music::musicVolumeGaugeCallback(void *refCon) {
((Music *)refCon)->musicVolumeGauge();
}
-void Music::onTimer(void *refCon) {
- Music *music = (Music *)refCon;
- Common::StackLock lock(music->_driver->_mutex);
- music->_parser->onTimer();
-}
-
void Music::musicVolumeGauge() {
int volume;
@@ -223,7 +190,7 @@ void Music::musicVolumeGauge() {
volume = 1;
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
- _driver->setVolume(volume);
+ _player->setVolume(volume);
if (_currentVolumePercent == 100) {
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
@@ -239,8 +206,11 @@ void Music::setVolume(int volume, int time) {
volume = 255;
if (time == 1) {
+ if (ConfMan.hasKey("mute") && ConfMan.getBool("mute"))
+ volume = 0;
+
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
- _driver->setVolume(volume);
+ _player->setVolume(volume);
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
_currentVolume = volume;
return;
@@ -250,7 +220,7 @@ void Music::setVolume(int volume, int time) {
}
bool Music::isPlaying() {
- return _mixer->isSoundHandleActive(_musicHandle) || _parser->isPlaying();
+ return _mixer->isSoundHandleActive(_musicHandle) || _player->isPlaying();
}
void Music::play(uint32 resourceId, MusicFlags flags) {
@@ -265,7 +235,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
_trackNumber = resourceId;
_mixer->stopHandle(_musicHandle);
- _parser->unloadMusic();
+ _player->stop();
int realTrackNumber;
@@ -395,33 +365,20 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
_vm->_resource->loadResource(_musicContext, resourceId, *_currentMusicBuffer);
}
- if (_currentMusicBuffer->size() < 4) {
- error("Music::play() wrong music resource size");
- }
-
- if (!_parser->loadMusic(_currentMusicBuffer->getBuffer(), _currentMusicBuffer->size()))
- error("Music::play() wrong music resource");
-
- _parser->setTrack(0);
- _driver->setTimerCallback(this, &onTimer);
-
+ _player->play(_vm, _currentMusicBuffer, (flags & MUSIC_LOOP));
setVolume(_vm->_musicVolume);
-
- // Handle music looping
- _parser->property(MidiParser::mpAutoLoop, (flags & MUSIC_LOOP) ? 1 : 0);
}
void Music::pause() {
- _driver->setTimerCallback(NULL, NULL);
+ _player->pause();
}
void Music::resume() {
- _driver->setTimerCallback(this, &onTimer);
+ _player->resume();
}
void Music::stop() {
- _driver->setTimerCallback(NULL, NULL);
- _parser->unloadMusic();
+ _player->stop();
}
} // End of namespace Saga
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 7d599d91c2..465d61e366 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -28,7 +28,7 @@
#ifndef SAGA_MUSIC_H
#define SAGA_MUSIC_H
-#include "audio/mididrv.h"
+#include "audio/midiplayer.h"
#include "audio/midiparser.h"
#include "audio/mixer.h"
#include "audio/decoders/mp3.h"
@@ -44,50 +44,26 @@ enum MusicFlags {
MUSIC_DEFAULT = 0xffff
};
-class MusicDriver : public MidiDriver {
+class MusicDriver : public Audio::MidiPlayer {
public:
MusicDriver();
- ~MusicDriver();
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
+ void play(SagaEngine *vm, ByteArray *buffer, bool loop);
+ virtual void pause();
+ virtual void resume();
- bool isAdlib() { return _driverType == MT_ADLIB; }
- bool isMT32() { return _driverType == MT_MT32 || _nativeMT32; }
- void setGM(bool isGM) { _isGM = isGM; }
+ bool isAdlib() const { return _driverType == MT_ADLIB; }
- //MidiDriver interface implementation
- int open();
- void close() { _driver->close(); }
- void send(uint32 b);
+ // FIXME
+ bool isPlaying() const { return _parser && _parser->isPlaying(); }
- void metaEvent(byte type, byte *data, uint16 length) {}
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _driver->setTimerCallback(timerParam, timerProc); }
- uint32 getBaseTempo() { return _driver->getBaseTempo(); }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- Common::Mutex _mutex;
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
protected:
-
- static void onTimer(void *data);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
MusicType _driverType;
- byte _channelVolume[16];
bool _isGM;
- bool _nativeMT32;
-
- byte _masterVolume;
-
- byte *_musicData;
- uint16 *_buf;
- size_t _musicDataSize;
};
class Music {
@@ -112,7 +88,7 @@ private:
SagaEngine *_vm;
Audio::Mixer *_mixer;
- MusicDriver *_driver;
+ MusicDriver *_player;
Audio::SoundHandle _musicHandle;
uint32 _trackNumber;
@@ -123,7 +99,6 @@ private:
ResourceContext *_musicContext;
ResourceContext *_digitalMusicContext;
- MidiParser *_parser;
static void musicVolumeGaugeCallback(void *refCon);
diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp
index dc9334b037..837a9e5879 100644
--- a/engines/saga/render.cpp
+++ b/engines/saga/render.cpp
@@ -56,7 +56,7 @@ Render::Render(SagaEngine *vm, OSystem *system) {
_vm->getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this);
#endif
- _backGroundSurface.create(_vm->getDisplayInfo().width, _vm->getDisplayInfo().height, 1);
+ _backGroundSurface.create(_vm->getDisplayInfo().width, _vm->getDisplayInfo().height, Graphics::PixelFormat::createFormatCLUT8());
_flags = 0;
diff --git a/engines/saga/resource_hrs.cpp b/engines/saga/resource_hrs.cpp
index 2ec2099c8d..21cf0ef4c1 100644
--- a/engines/saga/resource_hrs.cpp
+++ b/engines/saga/resource_hrs.cpp
@@ -62,7 +62,7 @@ bool ResourceContext_HRS::loadResV2(uint32 contextSize) {
readElement(_file, origin);
// Check if the file is valid
- if (origin.id != MKID_BE('HRES')) { // header
+ if (origin.id != MKTAG('H','R','E','S')) { // header
return false;
}
diff --git a/engines/saga/resource_rsc.cpp b/engines/saga/resource_rsc.cpp
index 42c4dc05e8..089757ca27 100644
--- a/engines/saga/resource_rsc.cpp
+++ b/engines/saga/resource_rsc.cpp
@@ -30,7 +30,7 @@
namespace Saga {
-#define ID_MIDI MKID_BE('Midi')
+#define ID_MIDI MKTAG('M','i','d','i')
bool ResourceContext_RSC::loadMacMIDI() {
// Sanity check
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 2e34b49dc5..62493f5eac 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -625,6 +625,8 @@ GUI::Debugger *SagaEngine::getDebugger() {
}
void SagaEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
_subtitlesEnabled = ConfMan.getBool("subtitles");
_readingSpeed = getTalkspeed();
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 52c4b824e7..4df44a2e18 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -31,6 +31,7 @@
#include "common/array.h"
#include "common/random.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "audio/mididrv.h"
#include "saga/gfx.h"
diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp
index c5388d6878..27300377e9 100644
--- a/engines/saga/saveload.cpp
+++ b/engines/saga/saveload.cpp
@@ -23,10 +23,8 @@
*
*/
-#include "common/config-manager.h"
#include "common/savefile.h"
#include "common/system.h"
-#include "common/file.h"
#include "graphics/thumbnail.h"
#include "saga/saga.h"
@@ -151,7 +149,7 @@ void SagaEngine::fillSaveList() {
_saveHeader.version = in->readUint32LE();
in->read(_saveHeader.name, sizeof(_saveHeader.name));
- if (_saveHeader.type != MKID_BE('SAGA')) {
+ if (_saveHeader.type != MKTAG('S','A','G','A')) {
warning("SagaEngine::load wrong save %s format", name);
i++;
continue;
@@ -175,7 +173,7 @@ void SagaEngine::save(const char *fileName, const char *saveName) {
return;
}
- _saveHeader.type = MKID_BE('SAGA');
+ _saveHeader.type = MKTAG('S','A','G','A');
_saveHeader.size = 0;
_saveHeader.version = CURRENT_SAGA_VER;
// Note that IHNM has a smaller save title size than ITE
@@ -256,6 +254,8 @@ void SagaEngine::save(const char *fileName, const char *saveName) {
warning("Can't write file '%s'. (Disk full?)", fileName);
delete out;
+
+ _interface->resetSaveReminder();
}
void SagaEngine::load(const char *fileName) {
@@ -287,7 +287,7 @@ void SagaEngine::load(const char *fileName) {
if (_saveHeader.version < 4)
warning("This savegame is not endian-safe. There may be problems");
- if (_saveHeader.type != MKID_BE('SAGA')) {
+ if (_saveHeader.type != MKTAG('S','A','G','A')) {
error("SagaEngine::load wrong save game format");
}
diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 3ae2f19e1b..bd1d6e5d84 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -160,7 +160,7 @@ SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) {
}
// Script export segment (lookup table)
- uint32 saga2ExportSegId = MKID_BE('_EXP');
+ uint32 saga2ExportSegId = MKTAG('_','E','X','P');
int32 entryNum = _scriptContext->getEntryNum(saga2ExportSegId);
if (entryNum < 0)
error("Unable to locate the script's export segment");
@@ -176,7 +176,7 @@ SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) {
// Script data segment
/*
- uint32 saga2DataSegId = MKID_BE('__DA');
+ uint32 saga2DataSegId = MKTAG('_','_','D','A');
entryNum = _scriptContext->getEntryNum(saga2DataSegId);
if (entryNum < 0)
error("Unable to locate the script's data segment");
diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp
index 685cb26aa7..8f0baa9d53 100644
--- a/engines/saga/shorten.cpp
+++ b/engines/saga/shorten.cpp
@@ -24,6 +24,7 @@
*/
#include "common/scummsys.h"
+#include "common/textconsole.h"
#include "saga/shorten.h"
@@ -34,10 +35,8 @@
// FIXME: This doesn't work yet correctly
-#include "common/endian.h"
#include "common/util.h"
-#include "audio/mixer.h"
#include "audio/decoders/raw.h"
namespace Saga {
diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp
index 07e8487ee4..8ffce4e6cd 100644
--- a/engines/saga/sound.cpp
+++ b/engines/saga/sound.cpp
@@ -175,8 +175,12 @@ void Sound::stopAll() {
}
void Sound::setVolume() {
- _vm->_soundVolume = ConfMan.getInt("sfx_volume");
- _vm->_speechVolume = ConfMan.getInt("speech_volume");
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _vm->_soundVolume = mute ? 0 : ConfMan.getInt("sfx_volume");
+ _vm->_speechVolume = mute ? 0 : ConfMan.getInt("speech_volume");
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _vm->_soundVolume);
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _vm->_speechVolume);
}
diff --git a/engines/savestate.cpp b/engines/savestate.cpp
index 368f59ef51..bed19ba3e5 100644
--- a/engines/savestate.cpp
+++ b/engines/savestate.cpp
@@ -25,6 +25,7 @@
#include "engines/savestate.h"
#include "graphics/surface.h"
+#include "common/textconsole.h"
void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) {
if (_thumbnail.get() == t)
diff --git a/engines/savestate.h b/engines/savestate.h
index 37f2b9bdd4..9b64a96aee 100644
--- a/engines/savestate.h
+++ b/engines/savestate.h
@@ -32,7 +32,7 @@
namespace Graphics {
- struct Surface;
+struct Surface;
}
/**
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index d77ac858c8..60bd129efc 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -40,12 +40,16 @@
#include "sci/sound/music.h"
#include "sci/sound/drivers/mididriver.h"
#include "sci/sound/drivers/map-mt32-to-gm.h"
+#include "sci/graphics/animate.h"
+#include "sci/graphics/cache.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/paint.h"
#include "sci/graphics/paint16.h"
#include "sci/graphics/paint32.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/ports.h"
+#include "sci/graphics/view.h"
#include "sci/parser/vocabulary.h"
@@ -123,6 +127,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
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
// Segments
DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable));
DCmd_Register("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias
@@ -354,6 +362,8 @@ bool Console::cmdHelp(int argc, const char **argv) {
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_object_list / al - Shows the current list of objects in kAnimate's draw list\n");
DebugPrintf("\n");
DebugPrintf("Segments:\n");
DebugPrintf(" segment_table / segtable - Lists all segments\n");
@@ -432,7 +442,7 @@ ResourceType parseResourceType(const char *resid) {
}
bool Console::cmdGetVersion(int argc, const char **argv) {
- const char *viewTypeDesc[] = { "Unknown", "EGA", "VGA", "VGA SCI1.1", "Amiga" };
+ const char *viewTypeDesc[] = { "Unknown", "EGA", "Amiga ECS 32 colors", "Amiga AGA 64 colors", "VGA", "VGA SCI1.1" };
bool hasVocab997 = g_sci->getResMan()->testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS)) ? true : false;
Common::String gameVersion = "N/A";
@@ -623,7 +633,7 @@ 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->restAdjust);
+ 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",
@@ -1434,7 +1444,7 @@ bool Console::cmdSaid(int argc, const char **argv) {
_engine->getVocabulary()->dumpParseTree();
_engine->getVocabulary()->parserIsValid = true;
- int ret = said(_engine->_gamestate, (byte*)spec, true);
+ int ret = said((byte*)spec, true);
DebugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match"));
}
@@ -1503,7 +1513,14 @@ bool Console::cmdDrawCel(int argc, const char **argv) {
uint16 loopNo = atoi(argv[2]);
uint16 celNo = atoi(argv[3]);
- _engine->_gfxPaint->kernelDrawCel(resourceId, loopNo, celNo, 50, 50, 0, 0, false, NULL_REG);
+ if (_engine->_gfxPaint16) {
+ _engine->_gfxPaint16->kernelDrawCel(resourceId, loopNo, celNo, 50, 50, 0, 0, 128, 128, false, NULL_REG);
+ } else {
+ GfxView *view = _engine->_gfxCache->getView(resourceId);
+ Common::Rect celRect(50, 50, 50 + view->getWidth(loopNo, celNo), 50 + view->getHeight(loopNo, celNo));
+ view->draw(celRect, celRect, celRect, loopNo, celNo, 255, 0, false);
+ _engine->_gfxScreen->copyRectToScreen(celRect);
+ }
return true;
}
@@ -1567,6 +1584,22 @@ bool Console::cmdPlayVideo(int argc, const char **argv) {
}
}
+bool Console::cmdAnimateList(int argc, const char **argv) {
+ if (_engine->_gfxAnimate) {
+ DebugPrintf("Animate list:\n");
+ _engine->_gfxAnimate->printAnimateList(this);
+ }
+ return true;
+}
+
+bool Console::cmdWindowList(int argc, const char **argv) {
+ if (_engine->_gfxPorts) {
+ DebugPrintf("Window list:\n");
+ _engine->_gfxPorts->printWindowList(this);
+ }
+ return true;
+
+}
bool Console::cmdParseGrammar(int argc, const char **argv) {
DebugPrintf("Parse grammar, in strict GNF:\n");
@@ -1701,9 +1734,7 @@ bool Console::segmentInfo(int nr) {
for (uint i = 0; i < ct->_table.size(); i++)
if (ct->isValidEntry(i)) {
- reg_t objpos;
- objpos.offset = i;
- objpos.segment = nr;
+ reg_t objpos = make_reg(nr, i);
DebugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos));
// Object header
const Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos());
@@ -2189,7 +2220,7 @@ bool Console::cmdStack(int argc, const char **argv) {
return true;
}
- ExecStack &xs = _engine->_gamestate->_executionStack.back();
+ const ExecStack &xs = _engine->_gamestate->_executionStack.back();
int nr = atoi(argv[1]);
for (int i = nr; i > 0; i--) {
@@ -2438,12 +2469,12 @@ bool Console::cmdScriptSteps(int argc, const char **argv) {
bool Console::cmdBacktrace(int argc, const char **argv) {
DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase);
- Common::List<ExecStack>::iterator iter;
+ Common::List<ExecStack>::const_iterator iter;
uint i = 0;
for (iter = _engine->_gamestate->_executionStack.begin();
iter != _engine->_gamestate->_executionStack.end(); ++iter, ++i) {
- ExecStack &call = *iter;
+ const ExecStack &call = *iter;
const char *objname = _engine->_gamestate->_segMan->getObjectName(call.sendp);
int paramc, totalparamc;
@@ -2607,7 +2638,7 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
const Object *obj = _engine->_gamestate->_segMan->getObject(objAddr);
int selectorId = _engine->getKernel()->findSelector(argv[2]);
- reg_t addr;
+ reg_t addr = NULL_REG;
if (!obj) {
DebugPrintf("Not an object.");
@@ -2626,13 +2657,22 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
for (int i = 3; i < argc; i++) {
if (!scumm_stricmp(argv[i], "bwt"))
- printBytecode = true;
- else if (!scumm_stricmp(argv[i], "bc"))
printBWTag = true;
+ else if (!scumm_stricmp(argv[i], "bc"))
+ printBytecode = true;
}
+ reg_t farthestTarget = addr;
do {
+ reg_t prevAddr = addr;
+ reg_t jumpTarget;
+ if (isJumpOpcode(_engine->_gamestate, addr, jumpTarget)) {
+ if (jumpTarget > farthestTarget)
+ farthestTarget = jumpTarget;
+ }
addr = disassemble(_engine->_gamestate, addr, printBWTag, printBytecode);
+ if (addr.isNull() && prevAddr < farthestTarget)
+ addr = prevAddr + 1; // skip past the ret
} while (addr.offset > 0);
return true;
@@ -2699,26 +2739,30 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
int scriptSegment;
Script *script;
- SegManager *segMan = _engine->getEngineState()->_segMan;
+ // Create a custom segment manager here, so that the game's segment
+ // manager won't be affected by loading and unloading scripts here.
+ SegManager *customSegMan = new SegManager(_engine->getResMan());
while (itr != resources->end()) {
- if (_engine->getGameId() == GID_KQ5 && itr->getNumber() == 980) {
- // Ignore script 980 in KQ5. Seems to be a leftover, as it
- // uses a superclass from script 988, which doesn't exist
+ // Ignore specific leftover scripts, which require other non-existing scripts
+ if ((_engine->getGameId() == GID_HOYLE3 && itr->getNumber() == 995) ||
+ (_engine->getGameId() == GID_KQ5 && itr->getNumber() == 980) ||
+ (_engine->getGameId() == GID_SLATER && itr->getNumber() == 947) ||
+ (_engine->getGameId() == GID_MOTHERGOOSE256 && itr->getNumber() == 980)) {
itr++;
continue;
}
// Load script
- scriptSegment = segMan->instantiateScript(itr->getNumber());
- script = segMan->getScript(scriptSegment);
+ scriptSegment = customSegMan->instantiateScript(itr->getNumber());
+ script = customSegMan->getScript(scriptSegment);
// Iterate through all the script's objects
ObjMap::iterator it;
const ObjMap::iterator end = script->_objects.end();
for (it = script->_objects.begin(); it != end; ++it) {
- const Object *obj = segMan->getObject(it->_value.getPos());
- const char *objName = segMan->getObjectName(it->_value.getPos());
+ const Object *obj = customSegMan->getObject(it->_value.getPos());
+ const char *objName = customSegMan->getObjectName(it->_value.getPos());
// Now dissassemble each method of the script object
for (uint16 i = 0; i < obj->getMethodCount(); i++) {
@@ -2761,10 +2805,12 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
} // for (uint16 i = 0; i < obj->getMethodCount(); i++)
} // for (it = script->_objects.begin(); it != end; ++it)
- segMan->uninstantiateScript(itr->getNumber());
+ customSegMan->uninstantiateScript(itr->getNumber());
++itr;
}
+ delete customSegMan;
+
delete resources;
}
@@ -3108,10 +3154,9 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) {
}
bool Console::cmdBreakpointFunction(int argc, const char **argv) {
- // TODO/FIXME: Why does this accept 2 parameters (the high and the low part of the address)?"
if (argc != 3) {
DebugPrintf("Sets a breakpoint on the execution of the specified exported function.\n");
- DebugPrintf("Usage: %s <addr1> <addr2>\n", argv[0]);
+ DebugPrintf("Usage: %s <script number> <export number\n", argv[0]);
return true;
}
@@ -3120,6 +3165,7 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) {
A breakpoint set on an invalid method name will just never trigger. */
Breakpoint bp;
bp.type = BREAK_EXPORT;
+ // script number, export number
bp.address = (atoi(argv[1]) << 16 | atoi(argv[2]));
_debugState._breakpoints.push_back(bp);
@@ -3758,11 +3804,16 @@ int Console::printObject(reg_t pos) {
return 0;
}
+static void printChar(byte c) {
+ if (c < 32 || c >= 127)
+ c = '.';
+ debugN("%c", c);
+}
+
void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startOffset, bool isArray) {
// reg_t version of Common::hexdump
assert(1 <= regsPerLine && regsPerLine <= 8);
int i;
- byte c;
int offset = startOffset;
while (len >= regsPerLine) {
debugN("%06x: ", offset);
@@ -3771,14 +3822,13 @@ void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startO
}
debugN(" |");
for (i = 0; i < regsPerLine; i++) {
- c = data[i].toUint16() & 0xff;
- if (c < 32 || c >= 127)
- c = '.';
- debugN("%c", c);
- c = data[i].toUint16() >> 8;
- if (c < 32 || c >= 127)
- c = '.';
- debugN("%c", c);
+ if (g_sci->isBE()) {
+ printChar(data[i].toUint16() >> 8);
+ printChar(data[i].toUint16() & 0xff);
+ } else {
+ printChar(data[i].toUint16() & 0xff);
+ printChar(data[i].toUint16() >> 8);
+ }
}
debugN("|\n");
data += regsPerLine;
@@ -3798,14 +3848,13 @@ void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startO
}
debugN(" |");
for (i = 0; i < len; i++) {
- c = data[i].toUint16() & 0xff;
- if (c < 32 || c >= 127)
- c = '.';
- debugN("%c", c);
- c = data[i].toUint16() >> 8;
- if (c < 32 || c >= 127)
- c = '.';
- debugN("%c", c);
+ if (g_sci->isBE()) {
+ printChar(data[i].toUint16() >> 8);
+ printChar(data[i].toUint16() & 0xff);
+ } else {
+ printChar(data[i].toUint16() & 0xff);
+ printChar(data[i].toUint16() >> 8);
+ }
}
for (; i < regsPerLine; i++)
debugN(" ");
diff --git a/engines/sci/console.h b/engines/sci/console.h
index b0a1de6ebd..93ccc45503 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -37,6 +37,7 @@ class SciEngine;
struct List;
reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode);
+bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpOffset);
class Console : public GUI::Debugger {
public:
@@ -94,6 +95,8 @@ private:
bool cmdUndither(int argc, const char **argv);
bool cmdPicVisualize(int argc, const char **argv);
bool cmdPlayVideo(int argc, const char **argv);
+ bool cmdAnimateList(int argc, const char **argv);
+ bool cmdWindowList(int argc, const char **argv);
// Segments
bool cmdPrintSegmentTable(int argc, const char **argv);
bool cmdSegmentInfo(int argc, const char **argv);
diff --git a/engines/sci/debug.h b/engines/sci/debug.h
index d9959f0b7f..8ddbbd0d45 100644
--- a/engines/sci/debug.h
+++ b/engines/sci/debug.h
@@ -34,18 +34,18 @@ namespace Sci {
// These types are used both as identifiers and as elements of bitfields
enum BreakpointType {
/**
- * Break when selector is executed. data contains (char *) selector name
+ * Break when a selector is executed. Data contains (char *) selector name
* (in the format Object::Method)
*/
- BREAK_SELECTOREXEC = 1 << 0, // break when selector gets executed
- BREAK_SELECTORREAD = 1 << 1, // break when selector gets executed
- BREAK_SELECTORWRITE = 1 << 2, // break when selector gets executed
+ BREAK_SELECTOREXEC = 1 << 0, // break when a function selector is executed
+ BREAK_SELECTORREAD = 1 << 1, // break when a variable selector is read
+ BREAK_SELECTORWRITE = 1 << 2, // break when a variable selector is written
/**
- * Break when an exported function is called. data contains
+ * Break when an exported function is called. Data contains
* script_no << 16 | export_no.
*/
- BREAK_EXPORT = 1 << 3
+ BREAK_EXPORT = 1 << 3
};
struct Breakpoint {
diff --git a/engines/sci/decompressor.cpp b/engines/sci/decompressor.cpp
index 73d4ed4198..c122fceeb0 100644
--- a/engines/sci/decompressor.cpp
+++ b/engines/sci/decompressor.cpp
@@ -28,9 +28,8 @@
#include "common/dcl.h"
#include "common/util.h"
#include "common/endian.h"
-#include "common/debug.h"
-#include "common/debug-channels.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "sci/decompressor.h"
#include "sci/sci.h"
diff --git a/engines/sci/decompressor.h b/engines/sci/decompressor.h
index 88e24fcc47..8b6f955ddb 100644
--- a/engines/sci/decompressor.h
+++ b/engines/sci/decompressor.h
@@ -28,7 +28,9 @@
#include "common/scummsys.h"
-namespace Common { class ReadStream; }
+namespace Common {
+class ReadStream;
+}
namespace Sci {
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index c7ef720e1f..829831d3a6 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -622,6 +622,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ // Gabriel Knight - English DOS Floppy
+ // SCI interpreter version 2.000.000, VERSION file reports "1.0\nGabriel Knight\n11/22/10:33 pm\n\x1A"
+ {"gk1", "", {
+ {"resource.map", 0, "ef41df08cf2c1f680216cdbeed0f8311", 10783},
+ {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
// Gabriel Knight - German DOS Floppy (supplied my markcoolio in bug report #2723775)
// SCI interpreter version 2.000.000
{"gk1", "", {
@@ -1608,7 +1616,13 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Larry 1 VGA Remake - English Amiga (from www.back2roots.org)
+#if 0
+ // The resource.002 file, contained in disk 3, is broken in this version
+ // (it contains a large chunk of zeroes and several broken resources,
+ // e.g. pic 250 and views 250 and 251).
+ // Thus this detection entry isn't accurate.
+
+ // Larry 1 Remake - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.004.024"
// SCI interpreter version 1.000.784
{"lsl1sci", "SCI", {
@@ -1619,6 +1633,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251},
AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH },
+#endif
// Larry 1 VGA Remake - English DOS (from spookypeanut)
// Executable scanning reports "1.000.577", VERSION file reports "2.1"
@@ -1992,31 +2007,31 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Larry 6 - English/German/French DOS CD - LORES
+ // Larry 6 - English/German/French DOS CD - LOWRES
// SCI interpreter version 1.001.115
{"lsl6", "", {
{"resource.map", 0, "0b91234b7112782962cb480b7791b6e2", 7263},
{"resource.000", 0, "57d5fe8bb9e044158514476ea7678eb0", 5754790},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
- // Larry 6 - German DOS CD - LORES (provided by richiefs in bug report #2670691)
+ // Larry 6 - German DOS CD - LOWRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 1.001.115
{"lsl6", "", {
{"resource.map", 0, "bafe85f32738854135991d4324ad147e", 7268},
{"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5773160},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE },
+ Common::DE_DEU, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
- // Larry 6 - French DOS CD - LORES (provided by richiefs in bug report #2670691)
+ // Larry 6 - French DOS CD - LOWRES (provided by richiefs in bug report #2670691)
// SCI interpreter version 1.001.115
{"lsl6", "", {
{"resource.map", 0, "97797ea775baaf18a1907d357d3c0ea6", 7268},
{"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5776092},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE },
+ Common::FR_FRA, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
- // Larry 6 - Spanish DOS - LORES (from the Leisure Suit Larry Collection)
+ // Larry 6 - Spanish DOS - LOWRES (from the Leisure Suit Larry Collection)
// Executable scanning reports "1.001.113", VERSION file reports "1.000, 11.06.93, FIVE PATCHES ADDED TO DISK 6 ON 11-18-93"
{"lsl6", "", {
{"resource.map", 0, "633bf8f42170b6271019917c8009989b", 6943},
@@ -2588,13 +2603,13 @@ static const struct ADGameDescription SciGameDescriptions[] = {
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
#ifdef ENABLE_SCI32
- // Police Quest 4 - English DOS (from the Police Quest Collection)
+ // Police Quest 4 - English DOS CD (from the Police Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.100.000"
- {"pq4", "", {
+ {"pq4", "CD", {
{"resource.map", 0, "379dfe80ed6bd16c47e4b950c4722eac", 11374},
{"resource.000", 0, "fd316a09b628b7032248139003369022", 18841068},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
// Police Quest 4 - English DOS
// SCI interpreter version 2.000.000 (a guess?)
@@ -2628,6 +2643,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
+ // Police Quest: SWAT - English DOS (from GOG.com)
+ // Executable scanning reports "2.100.002", VERSION file reports "1.0c"
+ {"pqswat", "", {
+ {"resmap.000", 0, "1c2563fee189885e29d9348f37306d94", 12175},
+ {"ressci.000", 0, "b2e1826ca81ce2e7e764587f5a14eee9", 127149181},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE },
+
// Police Quest: SWAT - English Windows (from the Police Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.0c"
// Original DOS/Windows release VERSION file reports "1.000" is the same
@@ -2641,7 +2664,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.004", 0, "4228038906f041623e65789500b22285", 6835},
{"ressci.004", 0, "b7e619e6ecf62fe65d5116a3a422e5f0", 46223872},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH },
+ Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE },
#endif // ENABLE_SCI32
// Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by merkur in bug report #2718784)
@@ -2656,6 +2679,17 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ // Quest for Glory 1 / Hero's Quest - English DOS 3.5" Floppy (supplied by alonzotg in bug report #3206006)
+ {"qfg1", "", {
+ {"resource.map", 0, "85512508ed4e4ef1e3b309adabceeda9", 6486},
+ {"resource.000", 0, "481b034132106390cb5160fe61dd5f58", 80334},
+ {"resource.001", 0, "4d67acf52833ff45c7f753d6663532e8", 462729},
+ {"resource.002", 0, "439ba9b6dde216e6eb97ef3a9830fbe4", 647244},
+ {"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203},
+ {"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+
// Quest for Glory 1 / Hero's Quest - English DOS 5.25" Floppy (supplied by markcoolio in bug report #2723843)
// Executable scanning reports "0.000.566"
{"qfg1", "", {
@@ -2709,7 +2743,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes english language)
+ // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language)
// Executable scanning reports "S.old.201"
{"qfg1", "8 Colors", {
{"resource.map", 0, "5cbeb95dd2a4b7cb242b415cc6ec1c47", 6444},
@@ -2719,7 +2753,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO_NOSPEECH },
- // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes english language)
+ // Quest for Glory 1 - Japanese PC-98 5.25" Floppy (also includes English language)
// Executable scanning reports "S.old.201"
{"qfg1", "16 Colors", {
{"resource.map", 0, "3ecaba33bf77cb434067a0b8aee15097", 6444},
@@ -2959,13 +2993,13 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH },
- // Quest for Glory 4 - English DOS/Windows (from jvprat)
+ // Quest for Glory 4 CD - English DOS/Windows (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
- {"qfg4", "", {
+ {"qfg4", "CD", {
{"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246},
{"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO_NONE },
// RAMA - English DOS/Windows Demo
// Executable scanning reports "2.100.002", VERSION file reports "000.000.008"
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 206624f87e..964097f57d 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -285,20 +285,16 @@ SciVersion GameFeatures::detectLofsType() {
}
// Find a function of the "Game" object (which is the game super class) which invokes lofsa/lofss
- reg_t gameSuperClass = g_sci->getGameSuperClassAddress();
+ const Object *gameObject = _segMan->getObject(g_sci->getGameObject());
+ const Object *gameSuperObject = _segMan->getObject(gameObject->getSuperClassSelector());
bool found = false;
- if (!gameSuperClass.isNull()) {
- Common::String gameSuperClassName = _segMan->getObjectName(gameSuperClass);
- const Object *gameSuperObject = _segMan->getObject(gameSuperClass);
+ if (gameSuperObject) {
+ Common::String gameSuperClassName = _segMan->getObjectName(gameObject->getSuperClassSelector());
- if (gameSuperObject) {
- for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
- found = autoDetectLofsType(gameSuperClassName, m);
- if (found)
- break;
- }
- } else {
- warning("detectLofsType(): Could not get superclass object");
+ for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
+ found = autoDetectLofsType(gameSuperClassName, m);
+ if (found)
+ break;
}
} else {
warning("detectLofsType(): Could not find superclass of game object");
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp
index 7692613ee5..e395eeab94 100644
--- a/engines/sci/engine/gc.cpp
+++ b/engines/sci/engine/gc.cpp
@@ -25,33 +25,47 @@
#include "sci/engine/gc.h"
#include "common/array.h"
+#include "sci/graphics/ports.h"
namespace Sci {
//#define GC_DEBUG_CODE
-struct WorklistManager {
- Common::Array<reg_t> _worklist;
- AddrSet _map; // used for 2 contains() calls, inside push() and run_gc()
+#ifdef GC_DEBUG_CODE
+const char *segmentTypeNames[] = {
+ "invalid", // 0
+ "script", // 1
+ "clones", // 2
+ "locals", // 3
+ "stack", // 4
+ "obsolete", // 5: obsolete system strings
+ "lists", // 6
+ "nodes", // 7
+ "hunk", // 8
+ "dynmem", // 9
+ "obsolete", // 10: obsolete string fragments
+ "array", // 11: SCI32 arrays
+ "string" // 12: SCI32 strings
+};
+#endif
- void push(reg_t reg) {
- if (!reg.segment) // No numbers
- return;
+void WorklistManager::push(reg_t reg) {
+ if (!reg.segment) // No numbers
+ return;
- debugC(kDebugLevelGC, "[GC] Adding %04x:%04x", PRINT_REG(reg));
+ debugC(kDebugLevelGC, "[GC] Adding %04x:%04x", PRINT_REG(reg));
- if (_map.contains(reg))
- return; // already dealt with it
+ if (_map.contains(reg))
+ return; // already dealt with it
- _map.setVal(reg, true);
- _worklist.push_back(reg);
- }
+ _map.setVal(reg, true);
+ _worklist.push_back(reg);
+}
- void pushArray(const Common::Array<reg_t> &tmp) {
- for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
- push(*it);
- }
-};
+void WorklistManager::pushArray(const Common::Array<reg_t> &tmp) {
+ for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+ push(*it);
+}
static AddrSet *normalizeAddresses(SegManager *segMan, const AddrSet &nonnormal_map) {
AddrSet *normal_map = new AddrSet();
@@ -95,7 +109,7 @@ AddrSet *findAllActiveReferences(EngineState *s) {
// Initialize value stack
// We do this one by hand since the stack doesn't know the current execution stack
- Common::List<ExecStack>::iterator iter = s->_executionStack.reverse_begin();
+ Common::List<ExecStack>::const_iterator iter = s->_executionStack.reverse_begin();
// Skip fake kernel stack frame if it's on top
if ((*iter).type == EXEC_STACK_TYPE_KERNEL)
@@ -103,9 +117,9 @@ AddrSet *findAllActiveReferences(EngineState *s) {
assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL));
- ExecStack &xs = *iter;
+ const StackPtr sp = iter->sp;
- for (reg_t *pos = s->stack_base; pos < xs.sp; pos++)
+ for (reg_t *pos = s->stack_base; pos < sp; pos++)
wm.push(*pos);
debugC(kDebugLevelGC, "[GC] -- Finished adding value stack");
@@ -113,7 +127,7 @@ AddrSet *findAllActiveReferences(EngineState *s) {
// Init: Execution Stack
for (iter = s->_executionStack.begin();
iter != s->_executionStack.end(); ++iter) {
- ExecStack &es = *iter;
+ const ExecStack &es = *iter;
if (es.type != EXEC_STACK_TYPE_KERNEL) {
wm.push(es.objp);
@@ -143,6 +157,9 @@ AddrSet *findAllActiveReferences(EngineState *s) {
processWorkList(s->_segMan, wm, heap);
+ if (g_sci->_gfxPorts)
+ g_sci->_gfxPorts->processEngineHunkList(wm);
+
return normalizeAddresses(s->_segMan, wm._map);
}
@@ -170,7 +187,7 @@ void run_gc(EngineState *s) {
if (mobj != NULL) {
#ifdef GC_DEBUG_CODE
const SegmentType type = mobj->getType();
- segnames[type] = SegmentObj::getSegmentTypeName(type);
+ segnames[type] = segmentTypeNames[type];
#endif
// Get a list of all deallocatable objects in this segment,
diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h
index f4318a1453..48e1c6b482 100644
--- a/engines/sci/engine/gc.h
+++ b/engines/sci/engine/gc.h
@@ -58,6 +58,15 @@ AddrSet *findAllActiveReferences(EngineState *s);
*/
void run_gc(EngineState *s);
+struct WorklistManager {
+ Common::Array<reg_t> _worklist;
+ AddrSet _map; // used for 2 contains() calls, inside push() and run_gc()
+
+ void push(reg_t reg);
+ void pushArray(const Common::Array<reg_t> &tmp);
+};
+
+
} // End of namespace Sci
#endif // SCI_ENGINE_GC_H
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 202fc40ba4..9a55ef630b 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -255,6 +255,11 @@ private:
Common::StringArray checkStaticSelectorNames();
/**
+ * Automatically find specific selectors
+ */
+ void findSpecificSelectors(Common::StringArray &selectorNames);
+
+ /**
* Maps special selectors.
*/
void mapSelectors();
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 71892a8bea..16d56d10a8 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -56,7 +56,7 @@ struct SciKernelMapSubEntry {
#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE
#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01
-#define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE
+#define SIG_SCI1 SCI_VERSION_1_EGA_ONLY, SCI_VERSION_1_LATE
#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1
#define SIG_SINCE_SCI11 SCI_VERSION_1_1, SCI_VERSION_NONE
#define SIG_SCI21 SCI_VERSION_2_1, SCI_VERSION_3
@@ -348,7 +348,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, kFindKey_workarounds },
{ MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL },
{ MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL },
- { MAP_CALL(Format), SIG_EVERYWHERE, "r(.*)", NULL, NULL },
+ { MAP_CALL(Format), SIG_EVERYWHERE, "r[ri](.*)", NULL, NULL },
{ MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL },
{ MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiii", NULL, kGetAngle_workarounds },
{ MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL },
@@ -434,7 +434,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL },
{ MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(StrAt), SIG_EVERYWHERE, "ri(i)", NULL, kStrAt_workarounds },
- { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, kStrCat_workarounds },
+ { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL },
{ MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL },
{ MAP_CALL(StrCpy), SIG_EVERYWHERE, "r[r0](i)", NULL, NULL },
{ MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL },
@@ -490,6 +490,12 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL },
{ MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "l[o0]", NULL, NULL },
{ "OnMe", kIsOnMe, SIG_EVERYWHERE, "iioi", NULL, NULL },
+ // Purge is used by the memory manager in SSCI to ensure that X number of bytes (the so called "unmovable
+ // memory") are available when the current room changes. This is similar to the SCI0-SCI1.1 FlushResources
+ // call, with the added functionality of ensuring that a specific amount of memory is available. We have
+ // our own memory manager and garbage collector, thus we simply call FlushResources, which in turn invokes
+ // our garbage collector (i.e. the SCI0-SCI1.1 semantics).
+ { "Purge", kFlushResources, SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(SetShowStyle), SIG_EVERYWHERE, "ioiiiii([ri])(i)", NULL, NULL },
{ MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL },
@@ -508,12 +514,6 @@ static SciKernelMapEntry s_kernelMap[] = {
// MakeSaveCatName - used in the Save/Load dialog of GK1CD (SRDialog, script 64990)
// MakeSaveFileName - used in the Save/Load dialog of GK1CD (SRDialog, script 64990)
- // SCI2 empty functions
-
- // Purge is used by the memory manager in SSCI to ensure that X number of bytes (the so called "unmovable
- // memory") are available. We have our own memory manager and garbage collector, thus we ignore this call.
- { MAP_EMPTY(Purge), SIG_EVERYWHERE, "i", NULL, NULL },
-
// Unused / debug SCI2 unused functions, always mapped to kDummy
{ MAP_DUMMY(InspectObject), SIG_EVERYWHERE, "(.*)", NULL, NULL },
// Profiler (same as SCI0-SCI1.1)
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index e5a9931605..725b78341b 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -35,6 +35,7 @@
#include "sci/event.h"
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/cursor.h"
+#include "sci/graphics/maciconbar.h"
namespace Sci {
@@ -46,17 +47,25 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->_segMan;
Common::Point mousePos;
- // Limit the mouse cursor position, if necessary
- g_sci->_gfxCursor->refreshPosition();
- mousePos = g_sci->_gfxCursor->getPosition();
-#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1)
- g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
-#endif
+ // For Mac games with an icon bar, handle possible icon bar events first
+ if (g_sci->hasMacIconBar()) {
+ reg_t iconObj = g_sci->_gfxMacIconBar->handleEvents();
+ if (!iconObj.isNull())
+ invokeSelector(s, iconObj, SELECTOR(select), argc, argv, 0, NULL);
+ }
// If there's a simkey pending, and the game wants a keyboard event, use the
// simkey instead of a normal event
if (g_debug_simulated_key && (mask & SCI_EVENT_KEYBOARD)) {
+ // In case we use a simulated event we query the current mouse position
+ mousePos = g_sci->_gfxCursor->getPosition();
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2_1)
+ g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
+#endif
+ // Limit the mouse cursor position, if necessary
+ g_sci->_gfxCursor->refreshPosition();
+
writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD); // Keyboard event
writeSelectorValue(segMan, obj, SELECTOR(message), g_debug_simulated_key);
writeSelectorValue(segMan, obj, SELECTOR(modifiers), SCI_KEYMOD_NUMLOCK); // Numlock on
@@ -68,6 +77,15 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
curEvent = g_sci->getEventManager()->getSciEvent(mask);
+ // For a real event we use its associated mouse position
+ mousePos = curEvent.mousePos;
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2_1)
+ g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
+#endif
+ // Limit the mouse cursor position, if necessary
+ g_sci->_gfxCursor->refreshPosition();
+
if (g_sci->getVocabulary())
g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event
@@ -135,7 +153,11 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
break;
default:
- s->r_acc = NULL_REG; // Unknown or no event
+ // Return a null event
+ writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_NONE);
+ writeSelectorValue(segMan, obj, SELECTOR(message), 0);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
+ s->r_acc = NULL_REG;
}
if ((s->r_acc.offset) && (g_sci->_debugState.stopOnEvent)) {
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index f6dec5da64..0e2f64257a 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -28,6 +28,7 @@
#include "common/file.h"
#include "common/str.h"
#include "common/savefile.h"
+#include "common/system.h"
#include "common/translation.h"
#include "gui/saveload.h"
@@ -253,6 +254,7 @@ reg_t kFGets(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelFile, "kFGets(%d, %d)", handle, maxsize);
int readBytes = fgets_wrapper(s, buf, maxsize, handle);
s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize);
+ delete[] buf;
return readBytes ? argv[0] : NULL_REG;
}
@@ -1155,15 +1157,14 @@ reg_t kCD(EngineState *s, int argc, reg_t *argv) {
reg_t kSave(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
- case 0: // Called by kq7 when starting chapters
+ case 0:
return kSaveGame(s, argc - 1,argv + 1);
- case 2: // GetSaveDir
- // Yay! Reusing the old kernel function!
+ case 1:
+ return kRestoreGame(s, argc - 1,argv + 1);
+ case 2:
return kGetSaveDir(s, argc - 1, argv + 1);
case 5:
- // TODO
- // 3 parameters: game ID, a string and an array
- return s->r_acc;
+ return kGetSaveFiles(s, argc - 1, argv + 1);
case 8:
// TODO
// This is a timer callback, with 1 parameter: the timer object
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 8730724d68..c7a2a26c3d 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -58,6 +58,17 @@
namespace Sci {
+static int16 adjustGraphColor(int16 color) {
+ // WORKAROUND: SCI1 EGA and Amiga games can set invalid colors (above 0 - 15).
+ // Colors above 15 are all white in SCI1 EGA games, which is why this was never
+ // observed. We clip them all to (0, 15) instead, as colors above 15 are used
+ // for the undithering algorithm in EGA games - bug #3048908.
+ if (getSciVersion() >= SCI_VERSION_1_EARLY && g_sci->getResMan()->getViewType() == kViewEga)
+ return color & 0x0F; // 0 - 15
+ else
+ return color;
+}
+
void showScummVMDialog(const Common::String &message) {
GUI::MessageDialog dialog(message, "OK");
dialog.runModal();
@@ -242,23 +253,14 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
}
reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isAmiga32color())
- return make_reg(0, 32);
- return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256);
+ return make_reg(0, g_sci->_gfxPalette->getTotalColorCount());
}
reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv) {
- int16 color = argv[4].toSint16();
+ int16 color = adjustGraphColor(argv[4].toSint16());
int16 priority = (argc > 5) ? argv[5].toSint16() : -1;
int16 control = (argc > 6) ? argv[6].toSint16() : -1;
- // WORKAROUND: SCI1 EGA games can set invalid colors (above 0 - 15).
- // Colors above 15 are all white in SCI1 EGA games, which is why this was never
- // observed. We clip them all to (0, 15) instead, as colors above 15 are used
- // for the undithering algorithm in EGA games - bug #3048908.
- if (g_sci->getResMan()->getViewType() == kViewEga && getSciVersion() >= SCI_VERSION_1_EARLY)
- color &= 0x0F;
-
g_sci->_gfxPaint16->kernelGraphDrawLine(getGraphPoint(argv), getGraphPoint(argv + 2), color, priority, control);
return s->r_acc;
}
@@ -290,17 +292,10 @@ reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv) {
reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv) {
Common::Rect rect = getGraphRect(argv);
int16 colorMask = argv[4].toUint16();
- int16 color = argv[5].toSint16();
+ int16 color = adjustGraphColor(argv[5].toSint16());
int16 priority = argv[6].toSint16(); // yes, we may read from stack sometimes here
int16 control = argv[7].toSint16(); // sierra did the same
- // WORKAROUND: SCI1 EGA games can set invalid colors (above 0 - 15).
- // Colors above 15 are all white in SCI1 EGA games, which is why this was never
- // observed. We clip them all to (0, 15) instead, as colors above 15 are used
- // for the undithering algorithm in EGA games - bug #3048908.
- if (g_sci->getResMan()->getViewType() == kViewEga && getSciVersion() >= SCI_VERSION_1_EARLY)
- color &= 0x0F;
-
g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control);
return s->r_acc;
}
@@ -364,6 +359,7 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
if (!g_sci->_gfxText16) {
// TODO: Implement this
textWidth = 0; textHeight = 0;
+ warning("TODO: implement kTextSize for SCI32");
} else
#endif
g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
@@ -553,8 +549,6 @@ reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-// we are called on EGA/amiga games as well, this doesnt make sense.
-// doing this would actually break the system EGA/amiga palette
reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
if (!s)
return make_reg(0, getSciVersion());
@@ -562,86 +556,85 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
}
reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- GuiResourceId resourceId = argv[0].toUint16();
- bool force = false;
- if (argc == 2)
- force = argv[1].toUint16() == 2 ? true : false;
- g_sci->_gfxPalette->kernelSetFromResource(resourceId, force);
- }
+ GuiResourceId resourceId = argv[0].toUint16();
+ bool force = false;
+ if (argc == 2)
+ force = argv[1].toUint16() == 2 ? true : false;
+
+ // Non-VGA games don't use palette resources.
+ // This has been changed to 64 colors because Longbow Amiga does have
+ // one palette (palette 999).
+ if (g_sci->_gfxPalette->getTotalColorCount() < 64)
+ return s->r_acc;
+
+ g_sci->_gfxPalette->kernelSetFromResource(resourceId, force);
return s->r_acc;
}
reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 flags = argv[2].toUint16();
- g_sci->_gfxPalette->kernelSetFlag(fromColor, toColor, flags);
- }
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 flags = argv[2].toUint16();
+ g_sci->_gfxPalette->kernelSetFlag(fromColor, toColor, flags);
return s->r_acc;
}
reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 flags = argv[2].toUint16();
- g_sci->_gfxPalette->kernelUnsetFlag(fromColor, toColor, flags);
- }
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 flags = argv[2].toUint16();
+ g_sci->_gfxPalette->kernelUnsetFlag(fromColor, toColor, flags);
return s->r_acc;
}
reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
- uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
- uint16 intensity = argv[2].toUint16();
- bool setPalette = (argc < 4) ? true : (argv[3].isNull()) ? true : false;
+ uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
+ uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
+ uint16 intensity = argv[2].toUint16();
+ bool setPalette = (argc < 4) ? true : (argv[3].isNull()) ? true : false;
- g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette);
- }
+ // Palette intensity in non-VGA SCI1 games has been removed
+ if (g_sci->_gfxPalette->getTotalColorCount() < 256)
+ return s->r_acc;
+
+ g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette);
return s->r_acc;
}
reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- uint16 r = argv[0].toUint16();
- uint16 g = argv[1].toUint16();
- uint16 b = argv[2].toUint16();
- return make_reg(0, g_sci->_gfxPalette->kernelFindColor(r, g, b));
- }
- return NULL_REG;
+ uint16 r = argv[0].toUint16();
+ uint16 g = argv[1].toUint16();
+ uint16 b = argv[2].toUint16();
+ return make_reg(0, g_sci->_gfxPalette->kernelFindColor(r, g, b));
}
reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- int16 argNr;
- bool paletteChanged = false;
- for (argNr = 0; argNr < argc; argNr += 3) {
- uint16 fromColor = argv[argNr].toUint16();
- uint16 toColor = argv[argNr + 1].toUint16();
- int16 speed = argv[argNr + 2].toSint16();
- if (g_sci->_gfxPalette->kernelAnimate(fromColor, toColor, speed))
- paletteChanged = true;
- }
- if (paletteChanged)
- g_sci->_gfxPalette->kernelAnimateSet();
+ int16 argNr;
+ bool paletteChanged = false;
+
+ // Palette animation in non-VGA SCI1 games has been removed
+ if (g_sci->_gfxPalette->getTotalColorCount() < 256)
+ return s->r_acc;
+
+ for (argNr = 0; argNr < argc; argNr += 3) {
+ uint16 fromColor = argv[argNr].toUint16();
+ uint16 toColor = argv[argNr + 1].toUint16();
+ int16 speed = argv[argNr + 2].toSint16();
+ if (g_sci->_gfxPalette->kernelAnimate(fromColor, toColor, speed))
+ paletteChanged = true;
}
+ if (paletteChanged)
+ g_sci->_gfxPalette->kernelAnimateSet();
+
return s->r_acc;
}
reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- return g_sci->_gfxPalette->kernelSave();
- }
- return NULL_REG;
+ return g_sci->_gfxPalette->kernelSave();
}
reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->getResMan()->isVGA()) {
- g_sci->_gfxPalette->kernelRestore(argv[0]);
- }
+ g_sci->_gfxPalette->kernelRestore(argv[0]);
return argv[0];
}
@@ -1082,22 +1075,11 @@ reg_t kNewWindow(EngineState *s, int argc, reg_t *argv) {
int argextra = argc >= 13 ? 4 : 0; // Triggers in PQ3 and SCI1.1 games, argc 13 for DOS argc 15 for mac
int style = argv[5 + argextra].toSint16();
int priority = (argc > 6 + argextra) ? argv[6 + argextra].toSint16() : -1;
- int colorPen = (argc > 7 + argextra) ? argv[7 + argextra].toSint16() : 0;
- int colorBack = (argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255;
+ int colorPen = adjustGraphColor((argc > 7 + argextra) ? argv[7 + argextra].toSint16() : 0);
+ int colorBack = adjustGraphColor((argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255);
- // WORKAROUND: SCI1 EGA games can set invalid colors (above 0 - 15).
- // Colors above 15 are all white in SCI1 EGA games, which is why this was never
- // observed. We clip them all to (0, 15) instead, as colors above 15 are used
- // for the undithering algorithm in EGA games - bug #3048908.
- if (g_sci->getResMan()->getViewType() == kViewEga && getSciVersion() >= SCI_VERSION_1_EARLY) {
- colorPen &= 0x0F;
- colorBack &= 0x0F;
- }
-
- // const char *title = argv[4 + argextra].segment ? kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL;
- if (argc>=13) {
+ if (argc >= 13)
rect2 = Common::Rect (argv[5].toSint16(), argv[4].toSint16(), argv[7].toSint16(), argv[6].toSint16());
- }
Common::String title;
if (argv[4 + argextra].segment) {
@@ -1201,14 +1183,12 @@ reg_t kShow(EngineState *s, int argc, reg_t *argv) {
}
reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
- // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now
- kStub(s, argc, argv);
-
uint16 operation = argv[0].toUint16();
switch (operation) {
- case 0: { // Initialize remapping to base. 0 turns remapping off.
- //int16 unk1 = (argc >= 2) ? argv[1].toSint16() : 0;
+ case 0: { // Set remapping to base. 0 turns remapping off.
+ int16 base = (argc >= 2) ? argv[1].toSint16() : 0;
+ warning("kRemapColors: Set remapping to base %d", base);
}
break;
case 1: { // unknown
@@ -1218,18 +1198,32 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
//int16 unk3 = argv[3].toSint16();
//uint16 unk4 = argv[4].toUint16();
//uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0;
+ kStub(s, argc, argv);
}
break;
case 2: { // remap by percent
- //int16 unk1 = argv[1].toSint16();
- //uint16 percent = argv[2].toUint16();
- //uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0;
+ // This adjusts the alpha value of a specific color, and it operates on
+ // an RGBA palette. Since we're operating on an RGB palette, we just
+ // modify the color intensity instead
+ // TODO: From what I understand, palette remapping should be placed
+ // separately, so that it can be reset by case 0 above. Thus, we
+ // should adjust the functionality of the Palette class accordingly.
+ int16 color = argv[1].toSint16();
+ if (color >= 10)
+ color -= 10;
+ uint16 percent = argv[2].toUint16(); // 0 - 100
+ if (argc >= 4)
+ warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16());
+ g_sci->_gfxPalette->kernelSetIntensity(color, 255, percent, false);
}
break;
case 3: { // remap to gray
- //int16 unk1 = argv[1].toSint16();
- //int16 percent = argv[2].toSint16(); // 0 - 100
- //uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0;
+ // NOTE: This adjusts the alpha value of a specific color, and it operates on
+ // an RGBA palette
+ int16 color = argv[1].toSint16(); // this is subtracted from a maximum color value, and can be offset by 10
+ int16 percent = argv[2].toSint16(); // 0 - 100
+ uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0;
+ warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3);
}
break;
case 4: { // unknown
@@ -1237,11 +1231,13 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
//uint16 unk2 = argv[2].toUint16();
//uint16 unk3 = argv[3].toUint16();
//uint16 unk4 = (argc >= 5) ? argv[4].toUint16() : 0;
+ kStub(s, argc, argv);
}
break;
case 5: { // increment color
//int16 unk1 = argv[1].toSint16();
//uint16 unk2 = argv[2].toUint16();
+ kStub(s, argc, argv);
}
break;
default:
diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp
index f90a5b4353..9baf9f5a54 100644
--- a/engines/sci/engine/kmath.cpp
+++ b/engines/sci/engine/kmath.cpp
@@ -117,7 +117,7 @@ reg_t kGetDistance(EngineState *s, int argc, reg_t *argv) {
int xdiff = (argc > 3) ? argv[3].toSint16() : 0;
int ydiff = (argc > 2) ? argv[2].toSint16() : 0;
int angle = (argc > 5) ? argv[5].toSint16() : 0;
- int xrel = (int)(((float) argv[1].toSint16() - xdiff) / cos(angle * PI / 180.0)); // This works because cos(0)==1
+ int xrel = (int)(((float) argv[1].toSint16() - xdiff) / cos(angle * M_PI / 180.0)); // This works because cos(0)==1
int yrel = argv[0].toSint16() - ydiff;
return make_reg(0, (int16)sqrt((float) xrel*xrel + yrel*yrel));
}
@@ -126,20 +126,20 @@ reg_t kTimesSin(EngineState *s, int argc, reg_t *argv) {
int angle = argv[0].toSint16();
int factor = argv[1].toSint16();
- return make_reg(0, (int16)(factor * sin(angle * PI / 180.0)));
+ return make_reg(0, (int16)(factor * sin(angle * M_PI / 180.0)));
}
reg_t kTimesCos(EngineState *s, int argc, reg_t *argv) {
int angle = argv[0].toSint16();
int factor = argv[1].toSint16();
- return make_reg(0, (int16)(factor * cos(angle * PI / 180.0)));
+ return make_reg(0, (int16)(factor * cos(angle * M_PI / 180.0)));
}
reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) {
int angle = argv[0].toSint16();
int value = argv[1].toSint16();
- double cosval = cos(angle * PI / 180.0);
+ double cosval = cos(angle * M_PI / 180.0);
if ((cosval < 0.0001) && (cosval > -0.0001)) {
error("kCosDiv: Attempted division by zero");
@@ -151,7 +151,7 @@ reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) {
reg_t kSinDiv(EngineState *s, int argc, reg_t *argv) {
int angle = argv[0].toSint16();
int value = argv[1].toSint16();
- double sinval = sin(angle * PI / 180.0);
+ double sinval = sin(angle * M_PI / 180.0);
if ((sinval < 0.0001) && (sinval > -0.0001)) {
error("kSinDiv: Attempted division by zero");
@@ -169,7 +169,7 @@ reg_t kTimesTan(EngineState *s, int argc, reg_t *argv) {
error("kTimesTan: Attempted tan(pi/2)");
return SIGNAL_REG;
} else
- return make_reg(0, (int16) - (tan(param * PI / 180.0) * scale));
+ return make_reg(0, (int16) - (tan(param * M_PI / 180.0) * scale));
}
reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) {
@@ -180,7 +180,7 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) {
error("kTimesCot: Attempted tan(pi/2)");
return SIGNAL_REG;
} else
- return make_reg(0, (int16)(tan(param * PI / 180.0) * scale));
+ return make_reg(0, (int16)(tan(param * M_PI / 180.0) * scale));
}
#ifdef ENABLE_SCI32
diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp
index 428c27ca73..3986966a71 100644
--- a/engines/sci/engine/kmenu.cpp
+++ b/engines/sci/engine/kmenu.cpp
@@ -29,6 +29,7 @@
#include "sci/engine/kernel.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/menu.h"
+#include "sci/graphics/screen.h"
namespace Sci {
@@ -71,7 +72,7 @@ reg_t kDrawStatus(EngineState *s, int argc, reg_t *argv) {
reg_t textReference = argv[0];
Common::String text;
int16 colorPen = (argc > 1) ? argv[1].toSint16() : 0;
- int16 colorBack = (argc > 2) ? argv[2].toSint16() : g_sci->getResMan()->isVGA() ? 255 : 15;
+ int16 colorBack = (argc > 2) ? argv[2].toSint16() : g_sci->_gfxScreen->getColorWhite();
if (!textReference.isNull()) {
// Sometimes this is called without giving text, if thats the case dont process it.
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index 6d7c4580e6..80425224bf 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -151,8 +151,13 @@ reg_t kMemorySegment(EngineState *s, int argc, reg_t *argv) {
if (!size)
size = s->_segMan->strlen(argv[1]) + 1;
- if (size > EngineState::kMemorySegmentMax)
- size = EngineState::kMemorySegmentMax;
+ if (size > EngineState::kMemorySegmentMax) {
+ // This was set to cut the block to 256 bytes. This should be an
+ // error, as we won't restore the full block that the game scripts
+ // request, thus error out instead.
+ //size = EngineState::kMemorySegmentMax;
+ error("kMemorySegment: Requested to save more than 256 bytes (%d)", size);
+ }
s->_memorySegmentSize = size;
@@ -298,12 +303,9 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
error("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1]));
return s->r_acc;
}
- if (ref.isRaw) {
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- return make_reg(0, (int16)READ_BE_UINT16(ref.raw)); // Amiga versions are BE
- else
- return make_reg(0, (int16)READ_LE_UINT16(ref.raw));
- } else {
+ if (ref.isRaw)
+ return make_reg(0, (int16)READ_SCIENDIAN_UINT16(ref.raw));
+ else {
if (ref.skipByte)
error("Attempt to peek memory at odd offset %04X:%04X", PRINT_REG(argv[1]));
return *(ref.reg);
@@ -323,10 +325,7 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
error("Attempt to poke memory reference %04x:%04x to %04x:%04x", PRINT_REG(argv[2]), PRINT_REG(argv[1]));
return s->r_acc;
}
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- WRITE_BE_UINT16(ref.raw, argv[2].offset); // Amiga versions are BE
- else
- WRITE_LE_UINT16(ref.raw, argv[2].offset);
+ WRITE_SCIENDIAN_UINT16(ref.raw, argv[2].offset); // Amiga versions are BE
} else {
if (ref.skipByte)
error("Attempt to poke memory at odd offset %04X:%04X", PRINT_REG(argv[1]));
@@ -365,23 +364,22 @@ reg_t kIconBar(EngineState *s, int argc, reg_t *argv) {
case 0: // InitIconBar
for (int i = 0; i < argv[1].toUint16(); i++)
g_sci->_gfxMacIconBar->addIcon(argv[i + 2]);
-
- // TODO: Should return icon bar handle
- // Said handle is then used by DisposeIconBar
break;
case 1: // DisposeIconBar
warning("kIconBar(Dispose)");
break;
- case 2: // EnableIconBar (0xffff = all)
- debug(0, "kIconBar(Enable, %d)", argv[1].toUint16());
- g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toUint16(), true);
+ case 2: // EnableIconBar (-1 = all)
+ debug(0, "kIconBar(Enable, %i)", argv[1].toSint16());
+ g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toSint16(), true);
break;
- case 3: // DisableIconBar (0xffff = all)
- debug(0, "kIconBar(Disable, %d)", argv[1].toUint16());
- g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toUint16(), false);
+ case 3: // DisableIconBar (-1 = all)
+ debug(0, "kIconBar(Disable, %i)", argv[1].toSint16());
+ g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toSint16(), false);
break;
case 4: // SetIconBarIcon
- warning("kIconBar(SetIcon, %d, %d)", argv[1].toUint16(), argv[2].toUint16());
+ debug(0, "kIconBar(SetIcon, %d, %d)", argv[1].toUint16(), argv[2].toUint16());
+ if (argv[2].toSint16() == -1)
+ g_sci->_gfxMacIconBar->setInventoryIcon(argv[2].toSint16());
break;
default:
error("Unknown kIconBar(%d)", argv[0].toUint16());
@@ -413,7 +411,8 @@ reg_t kMacPlatform(EngineState *s, int argc, reg_t *argv) {
return kIconBar(s, argc - 1, argv + 1);
case 7: // Unknown, but always return -1
return SIGNAL_REG;
- case 1: // Unknown, calls QuickDraw region functions (KQ5, QFG1VGA)
+ case 1: // Unknown, calls QuickDraw region functions (KQ5, QFG1VGA, Dr. Brain 1)
+ break; // removed warning, as it produces a lot of spam in the console
case 2: // Unknown, "UseNextWaitEvent" (Various)
case 3: // Unknown, "ProcessOpenDocuments" (Various)
case 5: // Unknown, plays a sound (KQ7)
@@ -503,7 +502,7 @@ reg_t kStub(EngineState *s, int argc, reg_t *argv) {
Kernel *kernel = g_sci->getKernel();
int kernelCallNr = -1;
- Common::List<ExecStack>::iterator callIterator = s->_executionStack.end();
+ Common::List<ExecStack>::const_iterator callIterator = s->_executionStack.end();
if (callIterator != s->_executionStack.begin()) {
callIterator--;
ExecStack lastCall = *callIterator;
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp
index 3c516f63f2..f4392df8f2 100644
--- a/engines/sci/engine/kmovement.cpp
+++ b/engines/sci/engine/kmovement.cpp
@@ -128,7 +128,7 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelBresen, "c: %d, tmp: %d", c, tmp);
// Compute x step
- if (tmp != 0)
+ if (tmp != 0 && dx != 0)
vx = (int16)((float)(dx * sqrt(gy / (2.0 * tmp))));
else
vx = 0;
@@ -166,17 +166,6 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-// TODO/FIXME: There is a notable regression with the new kInitBresed/kDoBresen
-// functions below in a death scene of LB1 - the shower scene, room 215 (bug
-// #3122075). There is a hack to get around this bug by modifying the actor's
-// position for that scene in kScriptID. The actual bug should be found, but
-// since only this death scene has an issue, it's not really worth the effort.
-// The new kInitBresen/kDoBresen functions have been enabled in r52467. The
-// old ones are based on observations, so there are many differences in the
-// way that they behave. Check the hack in kScriptID for more info. Note that
-// the actual issue might not be with kInitBresen/kDoBresen, and there might
-// be another underlying problem here.
-
reg_t kInitBresen(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->_segMan;
reg_t mover = argv[0];
@@ -275,7 +264,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
bool completed = false;
bool handleMoveCount = g_sci->_features->handleMoveCount();
- if (getSciVersion() >= SCI_VERSION_1_EGA) {
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) {
uint client_signal = readSelectorValue(segMan, client, SELECTOR(signal));
writeSelectorValue(segMan, client, SELECTOR(signal), client_signal & ~kSignalHitObstacle);
}
@@ -292,8 +281,6 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
mover_moveCnt = 0;
int16 client_x = readSelectorValue(segMan, client, SELECTOR(x));
int16 client_y = readSelectorValue(segMan, client, SELECTOR(y));
- int16 client_org_x = client_x;
- int16 client_org_y = client_y;
int16 mover_x = readSelectorValue(segMan, mover, SELECTOR(x));
int16 mover_y = readSelectorValue(segMan, mover, SELECTOR(y));
int16 mover_xAxis = readSelectorValue(segMan, mover, SELECTOR(b_xAxis));
@@ -307,12 +294,19 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
int16 mover_org_i2 = mover_i2;
int16 mover_org_di = mover_di;
- if ((getSciVersion() >= SCI_VERSION_1_EGA)) {
+ if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) {
// save current position into mover
writeSelectorValue(segMan, mover, SELECTOR(xLast), client_x);
writeSelectorValue(segMan, mover, SELECTOR(yLast), client_y);
}
- // sierra sci saves full client selector variables here
+
+ // Store backups of all client selector variables. We will restore them
+ // in case of a collision.
+ Object* clientObject = segMan->getObject(client);
+ uint clientVarNum = clientObject->getVarCount();
+ reg_t* clientBackup = new reg_t[clientVarNum];
+ for (uint i = 0; i < clientVarNum; ++i)
+ clientBackup[i] = clientObject->getVariable(i);
if (mover_xAxis) {
if (ABS(mover_x - client_x) < ABS(mover_dx))
@@ -360,9 +354,10 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
}
if (collision) {
- // sierra restores full client variables here, seems that restoring x/y is enough
- writeSelectorValue(segMan, client, SELECTOR(x), client_org_x);
- writeSelectorValue(segMan, client, SELECTOR(y), client_org_y);
+ // We restore the backup of the client variables
+ for (uint i = 0; i < clientVarNum; ++i)
+ clientObject->getVariableRef(i) = clientBackup[i];
+
mover_i1 = mover_org_i1;
mover_i2 = mover_org_i2;
mover_di = mover_org_di;
@@ -370,30 +365,29 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
uint16 client_signal = readSelectorValue(segMan, client, SELECTOR(signal));
writeSelectorValue(segMan, client, SELECTOR(signal), client_signal | kSignalHitObstacle);
}
+ delete[] clientBackup;
+
writeSelectorValue(segMan, mover, SELECTOR(b_i1), mover_i1);
writeSelectorValue(segMan, mover, SELECTOR(b_i2), mover_i2);
writeSelectorValue(segMan, mover, SELECTOR(b_di), mover_di);
- if ((getSciVersion() >= SCI_VERSION_1_EGA)) {
- // this calling code here was right before the last return in
- // sci1ega and got changed to this position since sci1early
- // this was an uninitialized issue in sierra sci
- if ((handleMoveCount) && (getSciVersion() >= SCI_VERSION_1_EARLY))
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) {
+ // In sci1egaonly this block of code was outside of the main if,
+ // but client_x/client_y aren't set there, so it was an
+ // uninitialized read in SSCI. (This issue was fixed in sci1early.)
+ if (handleMoveCount)
writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt);
// We need to compare directly in here, complete may have happened during
// the current move
if ((client_x == mover_x) && (client_y == mover_y))
invokeSelector(s, mover, SELECTOR(moveDone), argc, argv);
- if (getSciVersion() >= SCI_VERSION_1_EARLY)
- return s->r_acc;
+ return s->r_acc;
}
}
- if (handleMoveCount) {
- if (getSciVersion() <= SCI_VERSION_1_EGA)
- writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt);
- else
- writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), client_moveSpeed);
- }
+
+ if (handleMoveCount)
+ writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt);
+
return s->r_acc;
}
@@ -575,8 +569,8 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelBresen, " avoider %04x:%04x", PRINT_REG(avoider));
for (moves = 0; moves < 8; moves++) {
- int move_x = (int)(sin(angle * PI / 180.0) * (xstep));
- int move_y = (int)(-cos(angle * PI / 180.0) * (ystep));
+ int move_x = (int)(sin(angle * M_PI / 180.0) * (xstep));
+ int move_y = (int)(-cos(angle * M_PI / 180.0) * (ystep));
writeSelectorValue(segMan, client, SELECTOR(x), oldx + move_x);
writeSelectorValue(segMan, client, SELECTOR(y), oldy + move_y);
diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp
index e8f8ee7152..09cf7744b2 100644
--- a/engines/sci/engine/kparse.cpp
+++ b/engines/sci/engine/kparse.cpp
@@ -70,7 +70,7 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
}
- new_lastmatch = said(s, said_block, debug_parser);
+ new_lastmatch = said(said_block, debug_parser);
if (new_lastmatch != SAID_NO_MATCH) { /* Build and possibly display a parse tree */
#ifdef DEBUG_PARSER
@@ -169,7 +169,7 @@ reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) {
Vocabulary *voc = g_sci->getVocabulary();
// Only SCI0-SCI1 EGA games had a parser. In newer versions, this is a stub
- if (getSciVersion() > SCI_VERSION_1_EGA)
+ if (getSciVersion() > SCI_VERSION_1_EGA_ONLY)
return s->r_acc;
voc->clearSynonyms();
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index cb70cf91e0..7786f9b093 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -264,9 +264,9 @@ struct PathfindingState {
static Common::Point readPoint(SegmentRef list_r, int offset) {
Common::Point point;
- if (list_r.isRaw) {
- point.x = (int16)READ_LE_UINT16(list_r.raw + offset * POLY_POINT_SIZE);
- point.y = (int16)READ_LE_UINT16(list_r.raw + offset * POLY_POINT_SIZE + 2);
+ if (list_r.isRaw) { // dynmem blocks are raw
+ point.x = (int16)READ_SCIENDIAN_UINT16(list_r.raw + offset * POLY_POINT_SIZE);
+ point.y = (int16)READ_SCIENDIAN_UINT16(list_r.raw + offset * POLY_POINT_SIZE + 2);
} else {
point.x = list_r.reg[offset * 2].toUint16();
point.y = list_r.reg[offset * 2 + 1].toUint16();
@@ -275,9 +275,9 @@ static Common::Point readPoint(SegmentRef list_r, int offset) {
}
static void writePoint(SegmentRef ref, int offset, const Common::Point &point) {
- if (ref.isRaw) {
- WRITE_LE_UINT16(ref.raw + offset * POLY_POINT_SIZE, point.x);
- WRITE_LE_UINT16(ref.raw + offset * POLY_POINT_SIZE + 2, point.y);
+ if (ref.isRaw) { // dynmem blocks are raw
+ WRITE_SCIENDIAN_UINT16(ref.raw + offset * POLY_POINT_SIZE, point.x);
+ WRITE_SCIENDIAN_UINT16(ref.raw + offset * POLY_POINT_SIZE + 2, point.y);
} else {
ref.reg[offset * 2] = make_reg(0, point.x);
ref.reg[offset * 2 + 1] = make_reg(0, point.y);
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index 810e8a13ee..b9baa3540a 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -56,14 +56,6 @@ reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) {
ResourceType restype = g_sci->getResMan()->convertResType(argv[0].toUint16());
reg_t resnr = argv[1];
- // WORKAROUND for a broken script in room 320 in Castle of Dr. Brain.
- // Script 377 tries to free the hunk memory allocated for the saved area
- // (underbits) beneath the pop up window, which results in having the
- // window stay on screen even when it's closed. Ignore this request here.
- if (restype == kResourceTypeMemory && g_sci->getGameId() == GID_CASTLEBRAIN &&
- s->currentRoomNumber() == 320)
- return s->r_acc;
-
if (restype == kResourceTypeMemory)
s->_segMan->freeHunkEntry(resnr);
}
@@ -257,33 +249,9 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) {
// is used for timing during the intro, and in the problematic version it's
// initialized to 0, whereas it's 6 in other versions. Thus, we assign it
// to 6 here, fixing the speed of the introduction. Refer to bug #3102071.
- if (g_sci->getGameId() == GID_PQ2 && script == 200) {
- if (s->variables[VAR_GLOBAL][3].isNull()) {
- warning("Fixing speed in the intro of PQ2, version 1.002.011");
- s->variables[VAR_GLOBAL][3] = make_reg(0, 6);
- }
- }
-
- // HACK: Prevent the murderer from getting stuck behind the door in
- // Colonel's Bequest, room 215. A temporary fix for bug #3122075.
- // TODO/FIXME: Add a proper fix for this. There is a regression in this
- // scene with the new kInitBresen and kDoBresen functions (r52467). Using
- // just the "old" kInitBresen works. This hack is added for now because the
- // two functions are quite complex. The "old" versions were created based
- // on observations, and not on the interpreter itself, thus they have a lot
- // of differences in the way they behave and set variables to the mover object.
- // Since this is just a death scene where Laura is supposed to die anyway,
- // figuring out the exact cause of this is just not worth the effort.
- // Differences between the new and the old kInitBresen to the MoveTo object:
- // dy: 1 (new) - 2 (old)
- // b-i1: 20 (new) - 12 (old)
- // b-di: 65526 (new) - 65516 (old)
- // Performing the changes above to MoveTo (0017:033a) allows the killer to
- // move. Note that the actual issue might not be with kInitBresen/kDoBresen,
- // and there might be another underlying problem here.
- if (g_sci->getGameId() == GID_LAURABOW && script == 215) {
- warning("Moving actor position for the shower scene of Colonel's Bequest");
- writeSelectorValue(s->_segMan, s->_segMan->findObjectByName("killer"), SELECTOR(x), 6);
+ if (g_sci->getGameId() == GID_PQ2 && script == 200 &&
+ s->variables[VAR_GLOBAL][3].isNull()) {
+ s->variables[VAR_GLOBAL][3] = make_reg(0, 6);
}
return make_reg(scriptSeg, address);
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 911713d0bd..7fb6ac296e 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -32,6 +32,7 @@
#include "sci/sound/soundcmd.h"
#include "audio/mixer.h"
+#include "common/system.h"
namespace Sci {
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 5c6ef06910..e79af70158 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -113,7 +113,7 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) {
reg_t &tmp = dest_r.reg[offset / 2];
bool oddOffset = offset & 1;
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
+ if (g_sci->isBE())
oddOffset = !oddOffset;
if (!oddOffset) {
@@ -159,17 +159,9 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) {
source++;
}
while (*source) {
- if ((*source < '0') || (*source > '9')) {
- // Sierra's atoi stopped processing at anything which is not
- // a digit. Sometimes the input has a trailing space, that's
- // fine (example: lsl3)
- if (*source != ' ') {
- // TODO: this happens in lsl5 right in the intro -> we get '1' '3' 0xCD 0xCD 0xCD 0xCD 0xCD
- // find out why this happens and fix it
- warning("Invalid character in kReadNumber input");
- }
+ if ((*source < '0') || (*source > '9'))
+ // Stop if we encounter anything other than a digit (like atoi)
break;
- }
result *= 10;
result += *source - 0x30;
source++;
@@ -183,7 +175,7 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) {
#define ALIGN_NONE 0
#define ALIGN_RIGHT 1
#define ALIGN_LEFT -1
-#define ALIGN_CENTRE 2
+#define ALIGN_CENTER 2
/* Format(targ_address, textresnr, index_inside_res, ...)
** or
@@ -198,7 +190,6 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
char targetbuf[4096];
char *target = targetbuf;
reg_t position = argv[1]; /* source */
- int index = argv[2].toUint16();
int mode = 0;
int paramindex = 0; /* Next parameter to evaluate */
char xfer;
@@ -209,9 +200,16 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
if (position.segment)
startarg = 2;
- else
+ else {
+ // WORKAROUND: QFG1 VGA Mac calls this without the first parameter (dest). It then
+ // treats the source as the dest and overwrites the source string with an empty string.
+ if (argc < 3)
+ return NULL_REG;
+
startarg = 3; /* First parameter to use for formatting */
+ }
+ int index = (startarg == 3) ? argv[2].toUint16() : 0;
Common::String source_str = g_sci->getKernel()->lookupText(position, index);
const char* source = source_str.c_str();
@@ -248,7 +246,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
if (xfer == '0')
fillchar = '0';
else if (xfer == '=')
- align = ALIGN_CENTRE;
+ align = ALIGN_CENTER;
else if (isdigit(xfer) || (xfer == '-'))
source--; // Go to start of length argument
@@ -260,7 +258,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
if (str_leng < 0) {
align = ALIGN_LEFT;
str_leng = -str_leng;
- } else if (align != ALIGN_CENTRE)
+ } else if (align != ALIGN_CENTER)
align = ALIGN_RIGHT;
xfer = *source++;
@@ -300,7 +298,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
*target++ = ' '; /* Format into the text */
break;
- case ALIGN_CENTRE: {
+ case ALIGN_CENTER: {
int half_extralen = extralen >> 1;
while (half_extralen-- > 0)
*target++ = ' '; /* Format into the text */
@@ -317,7 +315,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
switch (align) {
- case ALIGN_CENTRE: {
+ case ALIGN_CENTER: {
int half_extralen;
align = 0;
half_extralen = extralen - (extralen >> 1);
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index 6a411d8e23..a8d4437148 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -29,7 +29,14 @@
#include "sci/graphics/cursor.h"
#include "sci/graphics/palette.h"
#include "sci/graphics/screen.h"
-#include "graphics/cursorman.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+#include "video/video_decoder.h"
#include "video/avi_decoder.h"
#include "video/qt_decoder.h"
#include "sci/video/seq_decoder.h"
diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp
index bc79e30129..267ba35e3c 100644
--- a/engines/sci/engine/object.cpp
+++ b/engines/sci/engine/object.cpp
@@ -172,11 +172,73 @@ bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClas
const Object *baseObj = segMan->getObject(getSpeciesSelector());
if (baseObj) {
- _variables.resize(baseObj->getVarCount());
+ uint originalVarCount = _variables.size();
+
+ if (_variables.size() != baseObj->getVarCount())
+ _variables.resize(baseObj->getVarCount());
// Copy base from species class, as we need its selector IDs
_baseObj = baseObj->_baseObj;
if (doInitSuperClass)
initSuperClass(segMan, addr);
+
+ if (_variables.size() != originalVarCount) {
+ // These objects are probably broken.
+ // An example is 'witchCage' in script 200 in KQ5 (#3034714),
+ // but also 'girl' in script 216 and 'door' in script 22.
+ // In LSL3 a number of sound objects trigger this right away.
+ // SQ4-floppy's bug #3037938 also seems related.
+
+ // The effect is that a number of its method selectors may be
+ // treated as variable selectors, causing unpredictable effects.
+ int objScript = segMan->getScript(_pos.segment)->getScriptNumber();
+
+ // We have to do a little bit of work to get the name of the object
+ // before any relocations are done.
+ reg_t nameReg = getNameSelector();
+ const char *name;
+ if (nameReg.isNull()) {
+ name = "<no name>";
+ } else {
+ nameReg.segment = _pos.segment;
+ name = segMan->derefString(nameReg);
+ if (!name)
+ name = "<invalid name>";
+ }
+
+ warning("Object %04x:%04x (name %s, script %d) varnum doesn't "
+ "match baseObj's: obj %d, base %d", PRINT_REG(_pos),
+ name, objScript, originalVarCount, baseObj->getVarCount());
+
+#if 0
+ // We enumerate the methods selectors which could be hidden here
+ if (getSciVersion() <= SCI_VERSION_2_1) {
+ const SegmentRef objRef = segMan->dereference(baseObj->_pos);
+ assert(objRef.isRaw);
+ uint segBound = objRef.maxSize/2 - baseObj->getVarCount();
+ const byte* buf = (const byte *)baseObj->_baseVars;
+ if (!buf) {
+ // While loading this may happen due to objects being loaded
+ // out of order, and we can't proceed then, unfortunately.
+ segBound = 0;
+ }
+ for (uint i = baseObj->getVarCount();
+ i < originalVarCount && i < segBound; ++i) {
+ uint16 slc = READ_SCI11ENDIAN_UINT16(buf + 2*i);
+ // Skip any numbers which happen to be varselectors too
+ bool found = false;
+ for (uint j = 0; j < baseObj->getVarCount() && !found; ++j)
+ found = READ_SCI11ENDIAN_UINT16(buf + 2*j) == slc;
+ if (found) continue;
+ // Skip any selectors which aren't method selectors,
+ // so couldn't be mistaken for varselectors
+ if (lookupSelector(segMan, _pos, slc, 0, 0) != kSelectorMethod) continue;
+ warning(" Possibly affected selector: %02x (%s)", slc,
+ g_sci->getKernel()->getSelectorName(slc).c_str());
+ }
+ }
+#endif
+ }
+
return true;
}
diff --git a/engines/sci/engine/object.h b/engines/sci/engine/object.h
index 81d5b2c983..8ae06f2707 100644
--- a/engines/sci/engine/object.h
+++ b/engines/sci/engine/object.h
@@ -28,6 +28,7 @@
#include "common/array.h"
#include "common/serializer.h"
+#include "common/textconsole.h"
#include "sci/sci.h" // for the SCI versions
#include "sci/engine/vm_types.h" // for reg_t
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index ab355cebb4..43d00ebc15 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -328,14 +328,14 @@ void Object::saveLoadWithSerializer(Common::Serializer &s) {
}
template <>
-void syncWithSerializer(Common::Serializer &s, Table<Clone>::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<Clone>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
syncWithSerializer<Object>(s, obj);
}
template <>
-void syncWithSerializer(Common::Serializer &s, Table<List>::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<List>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
syncWithSerializer(s, obj.first);
@@ -343,7 +343,7 @@ void syncWithSerializer(Common::Serializer &s, Table<List>::Entry &obj) {
}
template <>
-void syncWithSerializer(Common::Serializer &s, Table<Node>::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<Node>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
syncWithSerializer(s, obj.pred);
@@ -354,7 +354,7 @@ void syncWithSerializer(Common::Serializer &s, Table<Node>::Entry &obj) {
#ifdef ENABLE_SCI32
template <>
-void syncWithSerializer(Common::Serializer &s, Table<SciArray<reg_t> >::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<SciArray<reg_t> >::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
byte type = 0;
@@ -390,7 +390,7 @@ void syncWithSerializer(Common::Serializer &s, Table<SciArray<reg_t> >::Entry &o
}
template <>
-void syncWithSerializer(Common::Serializer &s, Table<SciString>::Entry &obj) {
+void syncWithSerializer(Common::Serializer &s, SegmentObjTable<SciString>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
uint32 size = 0;
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 6719b73aa5..25bf91c3ad 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -70,7 +70,7 @@ void Script::init(int script_nr, ResourceManager *resMan) {
Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
if (!script)
- error("Script %d not found\n", script_nr);
+ error("Script %d not found", script_nr);
_localsOffset = 0;
_localsBlock = NULL;
@@ -129,6 +129,17 @@ void Script::load(ResourceManager *resMan) {
Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0);
assert(script != 0);
+ uint extraLocalsWorkaround = 0;
+ if (g_sci->getGameId() == GID_FANMADE && _nr == 1 && script->size == 11140) {
+ // WORKAROUND: Script 1 in Ocean Battle doesn't have enough locals to
+ // fit the string showing how many shots are left (a nasty script bug,
+ // corrupting heap memory). We add 10 more locals so that it has enough
+ // space to use as the target for its kFormat operation. Fixes bug
+ // #3059871.
+ extraLocalsWorkaround = 10;
+ }
+ _bufSize += extraLocalsWorkaround * 2;
+
_buf = (byte *)malloc(_bufSize);
assert(_buf);
@@ -187,6 +198,9 @@ void Script::load(ResourceManager *resMan) {
_localsOffset = 24 + _numExports * 2;
}
+ // WORKAROUND: Increase locals, if needed (check above)
+ _localsCount += extraLocalsWorkaround;
+
if (getSciVersion() == SCI_VERSION_0_EARLY) {
// SCI0 early
// Old script block. There won't be a localvar block in this case.
@@ -202,7 +216,7 @@ void Script::load(ResourceManager *resMan) {
if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) {
error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize);
- _localsCount = (_bufSize - _localsOffset) >> 1;
+ //_localsCount = (_bufSize - _localsOffset) >> 1;
}
}
}
@@ -243,9 +257,8 @@ Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) {
if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit)
obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET)
- VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n");
-
- VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n");
+ if (obj_pos.offset >= _bufSize)
+ error("Attempt to initialize object beyond end of script");
// Get the object at the specified position and init it. This will
// automatically "allocate" space for it in the _objects map if necessary.
@@ -313,8 +326,9 @@ void Script::relocateSci0Sci21(reg_t block) {
heapOffset = _scriptSize;
}
- VERIFY(block.offset < (uint16)heapSize && READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset < (uint16)heapSize,
- "Relocation block outside of script\n");
+ if (block.offset >= (uint16)heapSize ||
+ READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset >= (uint16)heapSize)
+ error("Relocation block outside of script");
int count = READ_SCI11ENDIAN_UINT16(heap + block.offset);
int exportIndex = 0;
@@ -404,7 +418,8 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) {
offset = relocateOffsetSci3(pubfunct * 2 + 22);
}
- VERIFY(offset < _bufSize, "invalid export function pointer");
+ if (offset >= _bufSize)
+ error("Invalid export function pointer");
// Check if the offset found points to a second export table (e.g. script 912
// in Camelot and script 306 in KQ4). Such offsets are usually small (i.e. < 10),
@@ -418,7 +433,8 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) {
if (secondExportTable) {
secondExportTable += 3; // skip header plus 2 bytes (secondExportTable is a uint16 pointer)
offset = READ_SCI11ENDIAN_UINT16(secondExportTable + pubfunct);
- VERIFY(offset < _bufSize, "invalid export function pointer");
+ if (offset >= _bufSize)
+ error("Invalid export function pointer");
}
}
@@ -595,7 +611,7 @@ void Script::initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId) {
// #3150767.
// Same happens with script 764, it seems to
// contain junk towards its end.
- _objects.erase(addr.toUint16() + (getSciVersion() < SCI_VERSION_1_1) ? 8 : 0);
+ _objects.erase(addr.toUint16() - SCRIPT_OBJECT_MAGIC_OFFSET);
} else {
error("Failed to locate base object for object at %04X:%04X", PRINT_REG(addr));
}
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index f3b6ff8a46..06540e6f43 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -60,55 +60,6 @@ struct SciScriptSignature {
// - if not EOS, an adjust offset and the actual bytes
// - rinse and repeat
-#if 0
-
-// ===========================================================================
-// Castle of Dr. Brain
-// cipher::init (script 391) is called on room 380 init. This resets the word
-// cipher puzzle. The puzzle sadly operates on some hep strings, which aren't
-// saved in our sci. So saving/restoring in this room will break the puzzle
-// Because of this issue, we just init the puzzle each time it's accessed.
-// this is not 100% sierra behaviour, in fact we will actually reset the puzzle
-// during each access which makes it impossible to cheat.
-const byte castlebrainSignatureCipherPuzzle[] = {
- 22,
- 0x35, 0x00, // ldi 00
- 0xa3, 0x26, // sal local[26]
- 0xa3, 0x25, // sal local[25]
- 0x35, 0x00, // ldi 00
- 0xa3, 0x2a, // sal local[2a] (local is not used)
- 0xa3, 0x29, // sal local[29] (local is not used)
- 0x35, 0xff, // ldi ff
- 0xa3, 0x2c, // sal local[2c]
- 0xa3, 0x2b, // sal local[2b]
- 0x35, 0x00, // ldi 00
- 0x65, 0x16, // aTop highlightedIcon
- 0
-};
-
-const uint16 castlebrainPatchCipherPuzzle[] = {
- 0x39, 0x6b, // pushi 6b (selector init)
- 0x76, // push0
- 0x55, 0x04, // self 04
- 0x35, 0x00, // ldi 00
- 0xa3, 0x25, // sal local[25]
- 0xa3, 0x26, // sal local[26]
- 0xa3, 0x29, // sal local[29]
- 0x65, 0x16, // aTop highlightedIcon
- 0x34, 0xff, 0xff, // ldi ffff
- 0xa3, 0x2b, // sal local[2b]
- 0xa3, 0x2c, // sal local[2c]
- PATCH_END
-};
-
-// script, description, magic DWORD, adjust
-const SciScriptSignature castlebrainSignatures[] = {
- { 391, "cipher puzzle save/restore break", 1, PATCH_MAGICDWORD(0xa3, 0x26, 0xa3, 0x25), -2, castlebrainSignatureCipherPuzzle, castlebrainPatchCipherPuzzle },
- SCI_SIGNATUREENTRY_TERMINATOR
-};
-
-#endif
-
// ===========================================================================
// stayAndHelp::changeState (0) is called when ego swims to the left or right
// boundaries of room 660. Normally a textbox is supposed to get on screen
@@ -497,74 +448,6 @@ const SciScriptSignature gk1Signatures[] = {
SCI_SIGNATUREENTRY_TERMINATOR
};
-#if 0
-
-// ===========================================================================
-// this here gets called on entry and when going out of game windows
-// uEvt::port will not get changed after kDisposeWindow but a bit later, so
-// we would get an invalid port handle to a kSetPort call. We just patch in
-// resetting of the port selector. We destroy the stop/fade code in there,
-// it seems it isn't used at all in the game.
-const byte hoyle4SignaturePortFix[] = {
- 28,
- 0x39, 0x09, // pushi 09
- 0x89, 0x0b, // lsg 0b
- 0x39, 0x64, // pushi 64
- 0x38, 0xc8, 0x00, // pushi 00c8
- 0x38, 0x2c, 0x01, // pushi 012c
- 0x38, 0x90, 0x01, // pushi 0190
- 0x38, 0xf4, 0x01, // pushi 01f4
- 0x38, 0x58, 0x02, // pushi 0258
- 0x38, 0xbc, 0x02, // pushi 02bc
- 0x38, 0x20, 0x03, // pushi 0320
- 0x46, // calle [xxxx] [xxxx] [xx]
- +5, 43, // [skip 5 bytes]
- 0x30, 0x27, 0x00, // bnt 0027 -> end of routine
- 0x87, 0x00, // lap 00
- 0x30, 0x19, 0x00, // bnt 0019 -> fade out
- 0x87, 0x01, // lap 01
- 0x30, 0x14, 0x00, // bnt 0014 -> fade out
- 0x38, 0xa7, 0x00, // pushi 00a7
- 0x76, // push0
- 0x80, 0x29, 0x01, // lag 0129
- 0x4a, 0x04, // send 04 - call song::stop
- 0x39, 0x27, // pushi 27
- 0x78, // push1
- 0x8f, 0x01, // lsp 01
- 0x51, 0x54, // class 54
- 0x4a, 0x06, // send 06 - call PlaySong::play
- 0x33, 0x09, // jmp 09 -> end of routine
- 0x38, 0xaa, 0x00, // pushi 00aa
- 0x76, // push0
- 0x80, 0x29, 0x01, // lag 0129
- 0x4a, 0x04, // send 04
- 0x48, // ret
- 0
-};
-
-const uint16 hoyle4PatchPortFix[] = {
- PATCH_ADDTOOFFSET | +33,
- 0x38, 0x31, 0x01, // pushi 0131 (selector curEvent)
- 0x76, // push0
- 0x80, 0x50, 0x00, // lag 0050 (global var 80h, "User")
- 0x4a, 0x04, // send 04 - read User::curEvent
-
- 0x38, 0x93, 0x00, // pushi 0093 (selector port)
- 0x78, // push1
- 0x76, // push0
- 0x4a, 0x06, // send 06 - write 0 to that object::port
- 0x48, // ret
- PATCH_END
-};
-
-// script, description, magic DWORD, adjust
-const SciScriptSignature hoyle4Signatures[] = {
- { 0, "port fix when disposing windows", PATCH_MAGICDWORD(0x64, 0x38, 0xC8, 0x00), -5, hoyle4SignaturePortFix, hoyle4PatchPortFix },
- { 0, NULL, 0, 0, NULL, NULL }
-};
-
-#endif
-
// ===========================================================================
// at least during harpy scene export 29 of script 0 is called in kq5cd and
// has an issue for those calls, where temp 3 won't get inititialized, but
@@ -615,9 +498,121 @@ const uint16 kq5PatchCdHarpyVolume[] = {
PATCH_END
};
+// This is a heap patch, and it modifies the properties of an object, instead
+// of patching script code.
+//
+// The witchCage object in script 200 is broken and claims to have 12
+// variables instead of the 8 it should have because it is a Cage.
+// Additionally its top,left,bottom,right properties are set to 0 rather
+// than the right values. We fix the object by setting the right values.
+// If they are all zero, this causes an impossible position check in
+// witch::cantBeHere and an infinite loop when entering room 22 (bug #3034714).
+//
+// This bug is accidentally not triggered in SSCI because the invalid number
+// of variables effectively hides witchCage::doit, causing this position check
+// to be bypassed entirely.
+// See also the warning+comment in Object::initBaseObject
+const byte kq5SignatureWitchCageInit[] = {
+ 16,
+ 0x00, 0x00, // top
+ 0x00, 0x00, // left
+ 0x00, 0x00, // bottom
+ 0x00, 0x00, // right
+ 0x00, 0x00, // extra property #1
+ 0x7a, 0x00, // extra property #2
+ 0xc8, 0x00, // extra property #3
+ 0xa3, 0x00, // extra property #4
+ 0
+};
+
+const uint16 kq5PatchWitchCageInit[] = {
+ 0x00, 0x00, // top
+ 0x7a, 0x00, // left
+ 0xc8, 0x00, // bottom
+ 0xa3, 0x00, // right
+ PATCH_END
+};
+
// script, description, magic DWORD, adjust
const SciScriptSignature kq5Signatures[] = {
{ 0, "CD: harpy volume change", 1, PATCH_MAGICDWORD(0x80, 0x91, 0x01, 0x18), 0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
+ { 200, "CD: witch cage init", 1, PATCH_MAGICDWORD(0x7a, 0x00, 0xc8, 0x00), -10, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
+// When giving the milk bottle to one of the babies in the garden in KQ6 (room
+// 480), script 481 starts a looping baby cry sound. However, that particular
+// script also has an overriden check method (cryMusic::check). This method
+// explicitly restarts the sound, even if it's set to be looped, thus the same
+// sound is played twice, squelching all other sounds. We just rip the
+// unnecessary cryMusic::check method out, thereby stopping the sound from
+// constantly restarting (since it's being looped anyway), thus the normal
+// game speech can work while the baby cry sound is heard. Fixes bug #3034579.
+const byte kq6SignatureDuplicateBabyCry[] = {
+ 10,
+ 0x83, 0x00, // lal 00
+ 0x31, 0x1e, // bnt 1e [07f4]
+ 0x78, // push1
+ 0x39, 0x04, // pushi 04
+ 0x43, 0x75, 0x02, // callk DoAudio[75] 02
+ 0
+};
+
+const uint16 kq6PatchDuplicateBabyCry[] = {
+ 0x48, // ret
+ PATCH_END
+};
+
+// script, description, magic DWORD, adjust
+const SciScriptSignature kq6Signatures[] = {
+ { 481, "duplicate baby cry", 1, PATCH_MAGICDWORD(0x83, 0x00, 0x31, 0x1e), 0, kq6SignatureDuplicateBabyCry, kq6PatchDuplicateBabyCry },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
+// Script 210 in the German version of Longbow handles the case where Robin
+// hands out the scroll to Marion and then types his name using the hand code.
+// The German version script contains a typo (probably a copy/paste error),
+// and the function that is used to show each letter is called twice. The
+// second time that the function is called, the second parameter passed to
+// the function is undefined, thus kStrCat() that is called inside the function
+// reads a random pointer and crashes. We patch all of the 5 function calls
+// (one for each letter typed from "R", "O", "B", "I", "N") so that they are
+// the same as the English version. Fixes bug #3048054.
+const byte longbowSignatureShowHandCode[] = {
+ 3,
+ 0x78, // push1
+ 0x78, // push1
+ 0x72, // lofsa
+ +2, 2, // skip 2 bytes, offset of lofsa (the letter typed)
+ 0x36, // push
+ 0x40, // call
+ +2, 3, // skip 2 bytes, offset of call
+ 0x02, // perform the call above with 2 parameters
+ 0x36, // push
+ 0x40, // call
+ +2, 8, // skip 2 bytes, offset of call
+ 0x02, // perform the call above with 2 parameters
+ 0x38, 0x1c, 0x01, // pushi 011c (setMotion)
+ 0x39, 0x04, // pushi 04 (x)
+ 0x51, 0x1e, // class MoveTo
+ 0
+};
+
+const uint16 longbowPatchShowHandCode[] = {
+ 0x39, 0x01, // pushi 1 (combine the two push1's in one, like in the English version)
+ PATCH_ADDTOOFFSET | +3, // leave the lofsa call untouched
+ // The following will remove the duplicate call
+ 0x32, 0x02, 0x00, // jmp 02 - skip 2 bytes (the remainder of the first call)
+ 0x48, // ret (dummy, should never be reached)
+ 0x48, // ret (dummy, should never be reached)
+ PATCH_END
+};
+
+// script, description, magic DWORD, adjust
+const SciScriptSignature longbowSignatures[] = {
+ { 210, "hand code crash", 5, PATCH_MAGICDWORD(0x02, 0x38, 0x1c, 0x01), -14, longbowSignatureShowHandCode, longbowPatchShowHandCode },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -673,7 +668,7 @@ const SciScriptSignature larry6Signatures[] = {
};
// ===========================================================================
-// rm560::doit was supposed to close the painting, when heimlich enters the
+// rm560::doit was supposed to close the painting, when Heimlich enters the
// room. The code is buggy, so it actually closes the painting, when heimlich
// is not in the room. We fix that.
const byte laurabow2SignaturePaintingClosing[] = {
@@ -796,44 +791,10 @@ const uint16 qfg1vgaPatchFightEvents[] = {
PATCH_END
};
-// When QFG1VGA and QFG3 dispose of a child window. For example, when choosing
-// a spell (parent window), if the spell can't be casted, a subsequent window
-// opens, notifying that it can't be casted. When showing the child window, the
-// scripts restore the area below the parent window, draw the child window, and
-// then attempt to redraw the parent window, which leads to the background
-// picture (which has just been restored) overwriting the child window. It
-// appers that kGraph(redrawBox) is different in QFG1VGA and QFG3. However, we
-// can just remove the window redraw and update calls when the window is
-// supposed to be disposed, and the window is disposed of correctly. Fixes bug
-// #3053093.
-const byte qfg1vgaWindowDispose[] = {
- 17,
- 0x39, 0x05, // pushi 05
- 0x39, 0x0d, // pushi 0d
- 0x67, 0x2e, // pTos 2e
- 0x67, 0x30, // pTos 30
- 0x67, 0x32, // pTos 32
- 0x67, 0x34, // pTos 34
- 0x43, 0x6c, 0x0a, // callk kGraph 10
- 0x39, 0x06, // pushi 06
- 0
-};
-
-const uint16 qfg1vgaPatchWindowDispose[] = {
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x33, 0x3e, // jmp 0x3e (skip 62 bytes - this skips the subsequent 2 kGraph(update) calls, before kDisposeWindow is invoked)
- PATCH_END
-};
-
// script, description, magic DWORD, adjust
const SciScriptSignature qfg1vgaSignatures[] = {
{ 215, "fight event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
{ 216, "weapon master event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
- { 559, "window dispose", 1, PATCH_MAGICDWORD(0x39, 0x05, 0x39, 0x0d), 0, qfg1vgaWindowDispose, qfg1vgaPatchWindowDispose },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -897,37 +858,6 @@ const uint16 qfg3PatchImportDialog[] = {
PATCH_END
};
-// When QFG1VGA and QFG3 dispose of a child window. For example, when choosing
-// a spell (parent window), if the spell can't be casted, a subsequent window
-// opens, notifying that it can't be casted. When showing the child window, the
-// scripts restore the area below the parent window, draw the child window, and
-// then attempt to redraw the parent window, which leads to the background
-// picture (which has just been restored) overwriting the child window. It
-// appers that kGraph(redrawBox) is different in QFG1VGA and QFG3. However, we
-// can just remove the window redraw and update calls when the window is
-// supposed to be disposed, and the window is disposed of correctly. Fixes bug
-// #3053093.
-const byte qfg3WindowDispose[] = {
- 15,
- 0x39, 0x05, // pushi 05
- 0x39, 0x0d, // pushi 0d
- 0x67, 0x2e, // pTos 2e
- 0x67, 0x30, // pTos 30
- 0x67, 0x32, // pTos 32
- 0x67, 0x34, // pTos 34
- 0x43, 0x6c, 0x0a, // callk kGraph 10
- 0
-};
-
-const uint16 qfg3PatchWindowDispose[] = {
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- 0x34, 0x00, 0x00, // ldi 0000 (dummy)
- PATCH_END
-};
-
// Script 23 in QFG3 has a typo/bug which makes it loop endlessly and
// read garbage. Fixes bug #3040722.
const byte qfg3DialogCrash[] = {
@@ -944,10 +874,50 @@ const uint16 qfg3PatchDialogCrash[] = {
PATCH_END
};
+// Part of script 47 that handles the barter icon checks for the wrong local.
+// The local is supposed to contain the value returned by a previous kDisplay
+// call, but since the wrong one is checked, it contains junk instead. We
+// remove that check here (this doesn't affect the game at all). This occurs
+// when attempting to purchase something from a vendor and the barter button is
+// available (e.g. when buying the robe or meat from the associated vendors).
+// Fixes bug #3292251.
+const byte qfg3BarterCrash[] = {
+ 22,
+ 0x83, 0x10, // lal 10 ---> BUG! Wrong local
+ 0x30, 0x11, 0x00, // bnt 0011 ---> the accumulator will now contain garbage, so this check fails
+ 0x35, 0x00, // ldi 00
+ 0xa5, 0x00, // sat 00
+ 0x39, 0x03, // pushi 03
+ 0x5b, 0x04, 0x00, // lea 04 00
+ 0x36, // push
+ 0x39, 0x6c, // pushi 6c
+ 0x8b, 0x10, // lsl 10 ---> local 10 contains garbage, so the call below will fail
+ 0x43, 0x1b, 0x06 // callk Display[1b] 06
+};
+
+// Same as above, but for local 0x11
+const byte qfg3BarterCrash2[] = {
+ 18,
+ 0x83, 0x11, // lal 11 ---> BUG! Wrong local
+ 0x30, 0x0d, 0x00, // bnt 000d ---> the accumulator will now contain garbage, so this check fails
+ 0x39, 0x03, // pushi 03
+ 0x5b, 0x04, 0x00, // lea 04 00
+ 0x36, // push
+ 0x39, 0x6c, // pushi 6c
+ 0x8b, 0x11, // lsl 11 ---> local 11 contains garbage, so the call below will fail
+ 0x43, 0x1b, 0x06 // callk Display[1b] 06
+};
+
+const uint16 qfg3PatchBarterCrash[] = {
+ 0x35, 0x00, // ldi 00 ---> the accumulator will always be zero, so the problematic code won't run
+ PATCH_END
+};
+
// script, description, magic DWORD, adjust
const SciScriptSignature qfg3Signatures[] = {
- { 22, "window dispose", 1, PATCH_MAGICDWORD(0x39, 0x05, 0x39, 0x0d), 0, qfg3WindowDispose, qfg3PatchWindowDispose },
{ 23, "dialog crash", 1, PATCH_MAGICDWORD(0xe7, 0x03, 0x22, 0x33), -1, qfg3DialogCrash, qfg3PatchDialogCrash },
+ { 47, "barter crash", 1, PATCH_MAGICDWORD(0x83, 0x10, 0x30, 0x11), 0, qfg3BarterCrash, qfg3PatchBarterCrash },
+ { 47, "barter crash 2", 1, PATCH_MAGICDWORD(0x83, 0x11, 0x30, 0x0d), 0, qfg3BarterCrash2, qfg3PatchBarterCrash },
{ 944, "import dialog continuous calls", 1, PATCH_MAGICDWORD(0x2a, 0x31, 0x0b, 0x7a), -1, qfg3SignatureImportDialog, qfg3PatchImportDialog },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -1065,54 +1035,52 @@ const SciScriptSignature sq4Signatures[] = {
SCI_SIGNATUREENTRY_TERMINATOR
};
-// ===========================================================================
-// It seems to scripts warp ego outside the screen somehow (or maybe kDoBresen?)
-// ego::mover is set to 0 and rm119::doit will crash in that case. This here
-// fixes part of the problem and actually checks ego::mover to be 0 and skips
-// TODO: this should get further investigated by waltervn and maybe properly
-// patched. For now ego will shortly disappear and reappear a bit after
-// this isn't good, but sierra sci also "crashed" (endless looped) so this
-// is at least better than the original code
-const byte sq5SignatureScrubbing[] = {
- 19,
- 0x18, // not
- 0x31, 0x37, // bnt 37
- 0x78, // push1 (selector x)
+const byte sq1vgaSignatureEgoShowsCard[] = {
+ 25,
+ 0x38, 0x46, 0x02, // push 0x246 (set up send frame to set timesShownID)
+ 0x78, // push1
+ 0x38, 0x46, 0x02, // push 0x246 (set up send frame to get timesShownID)
0x76, // push0
- 0x39, 0x38, // pushi 38 (selector mover)
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x04, // send 0x04 (get timesShownID)
+ 0x36, // push
+ 0x35, 0x01, // ldi 1
+ 0x02, // add
+ 0x36, // push
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x06, // send 0x06 (set timesShownID)
+ 0x36, // push (wrong, acc clobbered by class, above)
+ 0x35, 0x03, // ldi 0x03
+ 0x22, // lt?
+ 0};
+
+// Note that this script patch is merely a reordering of the
+// instructions in the original script.
+const uint16 sq1vgaPatchEgoShowsCard[] = {
+ 0x38, 0x46, 0x02, // push 0x246 (set up send frame to get timesShownID)
0x76, // push0
- 0x81, 0x00, // lag 00
- 0x4a, 0x04, // send 04 - read ego::mover
- 0x4a, 0x04, // send 04 - read ego::mover::x
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x04, // send 0x04 (get timesShownID)
0x36, // push
- 0x34, 0xa0, 0x00, // ldi 00a0
- 0x1c, // ne?
- 0
-};
+ 0x35, 0x01, // ldi 1
+ 0x02, // add
+ 0x36, // push (this push corresponds to the wrong one above)
+ 0x38, 0x46, 0x02, // push 0x246 (set up send frame to set timesShownID)
+ 0x78, // push1
+ 0x36, // push
+ 0x51, 0x7c, // class DeltaurRegion
+ 0x4a, 0x06, // send 0x06 (set timesShownID)
+ 0x35, 0x03, // ldi 0x03
+ 0x22, // lt?
+ PATCH_END};
-const uint16 sq5PatchScrubbing[] = {
- 0x18, // not
- 0x31, 0x37, // bnt 37
-// 0x2f, 0x38, // bt 37 (would save another byte, isn't needed
- 0x39, 0x38, // pushi 38 (selector mover)
- 0x76, // push0
- 0x81, 0x00, // lag 00
- 0x4a, 0x04, // send 04 - read ego::mover
- 0x31, 0x2e, // bnt 2e (jump if ego::mover is 0)
- 0x78, // push1 (selector x)
- 0x76, // push0
- 0x4a, 0x04, // send 04 - read ego::mover::x
- 0x39, 0xa0, // pushi a0 (saving 2 bytes)
- 0x1c, // ne?
- PATCH_END
-};
// script, description, magic DWORD, adjust
-const SciScriptSignature sq5Signatures[] = {
- { 119, "scrubbing send crash", 1, PATCH_MAGICDWORD(0x18, 0x31, 0x37, 0x78), 0, sq5SignatureScrubbing, sq5PatchScrubbing },
- SCI_SIGNATUREENTRY_TERMINATOR
-};
+const SciScriptSignature sq1vgaSignatures[] = {
+ { 58, "Sarien armory droid zapping ego first time", 1, PATCH_MAGICDWORD( 0x72, 0x88, 0x15, 0x36 ), -70,
+ sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard },
+ SCI_SIGNATUREENTRY_TERMINATOR};
// will actually patch previously found signature area
void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset) {
@@ -1206,12 +1174,6 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr
void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
const SciScriptSignature *signatureTable = NULL;
switch (g_sci->getGameId()) {
- // Dr. Brain now works because we properly maintain the state of the string heap in savegames
-#if 0
- case GID_CASTLEBRAIN:
- signatureTable = castlebrainSignatures;
- break;
-#endif
case GID_ECOQUEST:
signatureTable = ecoquest1Signatures;
break;
@@ -1227,18 +1189,18 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
case GID_GK1:
signatureTable = gk1Signatures;
break;
- // hoyle4 now works due to workaround inside GfxPorts
-#if 0
- case GID_HOYLE4:
- signatureTable = hoyle4Signatures;
- break;
-#endif
case GID_KQ5:
signatureTable = kq5Signatures;
break;
+ case GID_KQ6:
+ signatureTable = kq6Signatures;
+ break;
case GID_LAURABOW2:
signatureTable = laurabow2Signatures;
break;
+ case GID_LONGBOW:
+ signatureTable = longbowSignatures;
+ break;
case GID_LSL6:
signatureTable = larry6Signatures;
break;
@@ -1254,12 +1216,12 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
case GID_QFG3:
signatureTable = qfg3Signatures;
break;
+ case GID_SQ1:
+ signatureTable = sq1vgaSignatures;
+ break;
case GID_SQ4:
signatureTable = sq4Signatures;
break;
- case GID_SQ5:
- signatureTable = sq5Signatures;
- break;
default:
break;
}
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 184f81bb99..596494d61b 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -208,12 +208,12 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode
if (pos == s->xs->addr.pc) { // Extra information if debugging the current opcode
if (opcode == op_callk) {
- int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjust);
+ int stackframe = (scr[pos.offset + 2] >> 1) + (s->r_rest);
int argc = ((s->xs->sp)[- stackframe - 1]).offset;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
if (!oldScriptHeader)
- argc += (s->restAdjust);
+ argc += (s->r_rest);
debugN(" Kernel params: (");
@@ -224,7 +224,7 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode
}
debugN(")\n");
} else if ((opcode == op_send) || (opcode == op_self)) {
- int restmod = s->restAdjust;
+ int restmod = s->r_rest;
int stackframe = (scr[pos.offset + 1] >> 1) + restmod;
reg_t *sb = s->xs->sp;
uint16 selector;
@@ -281,6 +281,34 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode
return retval;
}
+bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) {
+ SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT);
+ if (!mobj)
+ return false;
+ Script *script_entity = (Script *)mobj;
+
+ const byte *scr = script_entity->getBuf();
+ int scr_size = script_entity->getBufSize();
+
+ if (pos.offset >= scr_size)
+ return false;
+
+ int16 opparams[4];
+ byte opsize;
+ int bytecount = readPMachineInstruction(scr + pos.offset, opsize, opparams);
+ const byte opcode = opsize >> 1;
+
+ switch (opcode) {
+ case op_bt:
+ case op_bnt:
+ case op_jmp:
+ jumpTarget = pos + bytecount + opparams[0];
+ return true;
+ default:
+ return false;
+ }
+}
+
void SciEngine::scriptDebug() {
EngineState *s = _gamestate;
@@ -542,4 +570,187 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
debugN("Script ends without terminator\n");
}
+bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) {
+ Common::String methodName = _gamestate->_segMan->getObjectName(send_obj);
+ methodName += ("::" + getKernel()->getSelectorName(selector));
+
+ 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));
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
+ if (_debugState._activeBreakpointTypes & BREAK_EXPORT) {
+ uint32 bpaddress = (script << 16 | 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);
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType) {
+ int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes;
+ const char *objectName = segMan->getObjectName(send_obj);
+ const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str();
+ Console *con = g_sci->getSciDebugger();
+
+#ifdef VM_DEBUG_SEND
+ debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),
+ s->_segMan->getObjectName(send_obj), selector,
+ g_sci->getKernel()->getSelectorName(selector).c_str());
+#endif // VM_DEBUG_SEND
+
+ switch (selectorType) {
+ case kSelectorNone:
+ break;
+ case kSelectorVariable:
+#ifdef VM_DEBUG_SEND
+ if (argc)
+ debugN("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1]));
+ else
+ debugN("Varselector: Read\n");
+#endif // VM_DEBUG_SEND
+
+ // argc == 0: read selector
+ // argc == 1: write selector
+ // argc can be bigger than 1 in some cases, because of a script bug.
+ // Usually, these aren't fatal.
+ if ((activeBreakpointTypes & BREAK_SELECTORREAD) ||
+ (activeBreakpointTypes & BREAK_SELECTORWRITE) ||
+ argc > 1) {
+
+ 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",
+ 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",
+ objectName, selectorName,
+ PRINT_REG(selectorValue), PRINT_REG(argp[1]));
+ }
+
+ if (argc > 1)
+ debug(kDebugLevelScripts, "Write to selector (%s:%s): change %04x:%04x to %04x:%04x, argc == %d\n",
+ objectName, selectorName,
+ PRINT_REG(selectorValue), PRINT_REG(argp[1]), argc);
+ }
+ break;
+ case kSelectorMethod:
+#ifndef VM_DEBUG_SEND
+ if (activeBreakpointTypes & BREAK_SELECTOREXEC) {
+ if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) {
+#else
+ if (true) {
+ if (true) {
+#endif
+ con->DebugPrintf("%s::%s(", objectName, selectorName);
+ for (int i = 0; i < argc; i++) {
+ con->DebugPrintf("%04x:%04x", PRINT_REG(argp[i+1]));
+ if (i + 1 < argc)
+ con->DebugPrintf(", ");
+ }
+ con->DebugPrintf(") at %04x:%04x\n", PRINT_REG(funcp));
+ }
+ }
+ break;
+ } // switch
+}
+
+void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result) {
+ Kernel *kernel = g_sci->getKernel();
+ if (!kernelSubCall) {
+ debugN("k%s: ", kernelCall->name);
+ } else {
+ int callNameLen = strlen(kernelCall->name);
+ if (strncmp(kernelCall->name, kernelSubCall->name, callNameLen) == 0) {
+ const char *subCallName = kernelSubCall->name + callNameLen;
+ debugN("k%s(%s): ", kernelCall->name, subCallName);
+ } else {
+ debugN("k%s(%s): ", kernelCall->name, kernelSubCall->name);
+ }
+ }
+ for (int parmNr = 0; parmNr < argc; parmNr++) {
+ if (parmNr)
+ debugN(", ");
+ uint16 regType = kernel->findRegType(argv[parmNr]);
+ if (regType & SIG_TYPE_NULL)
+ debugN("0");
+ else if (regType & SIG_TYPE_UNINITIALIZED)
+ debugN("UNINIT");
+ else if (regType & SIG_IS_INVALID)
+ debugN("INVALID");
+ else if (regType & SIG_TYPE_INTEGER)
+ debugN("%d", argv[parmNr].offset);
+ else {
+ debugN("%04x:%04x", PRINT_REG(argv[parmNr]));
+ switch (regType) {
+ case SIG_TYPE_OBJECT:
+ debugN(" (%s)", s->_segMan->getObjectName(argv[parmNr]));
+ break;
+ case SIG_TYPE_REFERENCE:
+ {
+ SegmentObj *mobj = s->_segMan->getSegmentObj(argv[parmNr].segment);
+ switch (mobj->getType()) {
+ case SEG_TYPE_HUNK:
+ {
+ HunkTable *ht = (HunkTable*)mobj;
+ int index = argv[parmNr].offset;
+ if (ht->isValidEntry(index)) {
+ // NOTE: This ", deleted" isn't as useful as it could
+ // be because it prints the status _after_ the kernel
+ // call.
+ debugN(" ('%s' hunk%s)", ht->_table[index].type, ht->_table[index].mem ? "" : ", deleted");
+ } else
+ debugN(" (INVALID hunk ref)");
+ break;
+ }
+ default:
+ // TODO: Any other segment types which could
+ // use special handling?
+
+ if (kernelCall->function == kSaid) {
+ SegmentRef saidSpec = s->_segMan->dereference(argv[parmNr]);
+ if (saidSpec.isRaw) {
+ debugN(" ('");
+ g_sci->getVocabulary()->debugDecipherSaidBlock(saidSpec.raw);
+ debugN("')");
+ } else {
+ debugN(" (non-raw said-spec)");
+ }
+ } else {
+ debugN(" ('%s')", s->_segMan->getString(argv[parmNr]).c_str());
+ }
+ break;
+ }
+ }
+ default:
+ break;
+ }
+ }
+ }
+ if (result.isPointer())
+ debugN(" = %04x:%04x\n", PRINT_REG(result));
+ else
+ debugN(" = %d\n", result.offset);
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index ffc81f0fde..0dc245a991 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -63,7 +63,7 @@ void SegManager::resetSegMan() {
// Free memory
for (uint i = 0; i < _heap.size(); i++) {
if (_heap[i])
- deallocate(i, false);
+ deallocate(i);
}
_heap.clear();
@@ -151,16 +151,17 @@ Script *SegManager::allocateScript(int script_nr, SegmentId *segid) {
return (Script *)mem;
}
-void SegManager::deallocate(SegmentId seg, bool recursive) {
- VERIFY(check(seg), "invalid seg id");
+void SegManager::deallocate(SegmentId seg) {
+ if (!check(seg))
+ error("SegManager::deallocate(): invalid segment ID");
SegmentObj *mobj = _heap[seg];
if (mobj->getType() == SEG_TYPE_SCRIPT) {
Script *scr = (Script *)mobj;
_scriptSegMap.erase(scr->getScriptNumber());
- if (recursive && scr->_localsSegment)
- deallocate(scr->_localsSegment, recursive);
+ if (scr->_localsSegment)
+ deallocate(scr->_localsSegment);
}
delete mobj;
@@ -176,8 +177,7 @@ bool SegManager::isHeapObject(reg_t pos) const {
}
void SegManager::deallocateScript(int script_nr) {
- SegmentId seg = getScriptSegment(script_nr);
- deallocate(seg, true);
+ deallocate(getScriptSegment(script_nr));
}
Script *SegManager::getScript(const SegmentId seg) {
@@ -360,9 +360,8 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr) {
if (scr->_localsSegment) {
locals = (LocalVariables *)_heap[scr->_localsSegment];
- VERIFY(locals != NULL, "Re-used locals segment was NULL'd out");
- VERIFY(locals->getType() == SEG_TYPE_LOCALS, "Re-used locals segment did not consist of local variables");
- VERIFY(locals->script_id == scr->getScriptNumber(), "Re-used locals segment belonged to other script");
+ if (!locals || locals->getType() != SEG_TYPE_LOCALS || locals->script_id != scr->getScriptNumber())
+ error("Invalid script locals segment while allocating locals");
} else
locals = (LocalVariables *)allocSegment(new LocalVariables(), &scr->_localsSegment);
@@ -403,7 +402,7 @@ void SegManager::freeHunkEntry(reg_t addr) {
return;
}
- ht->freeEntry(addr.offset);
+ ht->freeEntryContents(addr.offset);
}
reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) {
@@ -602,13 +601,13 @@ static inline char getChar(const SegmentRef &ref, uint offset) {
warning("Attempt to read character from non-raw data");
bool oddOffset = offset & 1;
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- oddOffset = !oddOffset; // Amiga versions are BE
+ if (g_sci->isBE())
+ oddOffset = !oddOffset;
return (oddOffset ? val.offset >> 8 : val.offset & 0xff);
}
-static inline void setChar(const SegmentRef &ref, uint offset, char value) {
+static inline void setChar(const SegmentRef &ref, uint offset, byte value) {
if (ref.skipByte)
offset++;
@@ -617,8 +616,8 @@ static inline void setChar(const SegmentRef &ref, uint offset, char value) {
val->segment = 0;
bool oddOffset = offset & 1;
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- oddOffset = !oddOffset; // Amiga versions are BE
+ if (g_sci->isBE())
+ oddOffset = !oddOffset;
if (oddOffset)
val->offset = (val->offset & 0x00ff) | (value << 8);
@@ -864,7 +863,7 @@ bool SegManager::freeDynmem(reg_t addr) {
if (addr.segment < 1 || addr.segment >= _heap.size() || !_heap[addr.segment] || _heap[addr.segment]->getType() != SEG_TYPE_DYNMEM)
return false; // error
- deallocate(addr.segment, true);
+ deallocate(addr.segment);
return true; // OK
}
@@ -1022,7 +1021,7 @@ void SegManager::uninstantiateScript(int script_nr) {
SegmentId segmentId = getScriptSegment(script_nr);
Script *scr = getScriptIfLoaded(segmentId);
- if (!scr) { // Is it already unloaded?
+ if (!scr || scr->isMarkedAsDeleted()) { // Is it already unloaded?
//warning("unloading script 0x%x requested although not loaded", script_nr);
// This is perfectly valid SCI behaviour
return;
@@ -1079,15 +1078,7 @@ void SegManager::uninstantiateScriptSci0(int script_nr) {
if (scr->getLockers())
scr->decrementLockers(); // Decrease lockers if this is us ourselves
} else {
- if (g_sci->getGameId() == GID_HOYLE3 && (superclass_script == 0 || superclass_script >= 990)) {
- // HACK for Hoyle 3: when exiting Checkers or Pachisi, scripts 0, 999 and some others
- // are deleted but are never instantiated again. We ignore deletion of these scripts
- // here for Hoyle 3 - bug #3038837
- // TODO/FIXME: find out why this happens, seems like there is a problem with the object
- // lock code
- } else {
- uninstantiateScript(superclass_script);
- }
+ uninstantiateScript(superclass_script);
}
// Recurse to assure that the superclass lockers number gets decreased
}
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index 61fa2e2245..d402afbf1a 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -36,15 +36,6 @@
namespace Sci {
/**
- * Verify the the given condition is true, output the message if condition is false, and exit.
- * @param cond condition to be verified
- * @param msg the message to be printed if condition fails
- */
-#define VERIFY( cond, msg ) if (!(cond)) {\
- error("%s, line, %d, %s", __FILE__, __LINE__, msg); \
- }
-
-/**
* Parameters for getScriptSegment().
*/
enum ScriptLoadType {
@@ -477,7 +468,7 @@ private:
private:
SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid);
- void deallocate(SegmentId seg, bool recursive);
+ void deallocate(SegmentId seg);
void createClassTable();
SegmentId findFreeSegment() const;
diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp
index 05d914cffb..2bb77c707a 100644
--- a/engines/sci/engine/segment.cpp
+++ b/engines/sci/engine/segment.cpp
@@ -39,7 +39,6 @@ namespace Sci {
//#define GC_DEBUG // Debug garbage collection
//#define GC_DEBUG_VERBOSE // Debug garbage verbosely
-
SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
SegmentObj *mem = 0;
switch (type) {
@@ -85,116 +84,12 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
return mem;
}
-const char *SegmentObj::getSegmentTypeName(SegmentType type) {
- switch (type) {
- case SEG_TYPE_SCRIPT:
- return "script";
- break;
- case SEG_TYPE_CLONES:
- return "clones";
- break;
- case SEG_TYPE_LOCALS:
- return "locals";
- break;
- case SEG_TYPE_STACK:
- return "stack";
- break;
- case SEG_TYPE_HUNK:
- return "hunk";
- break;
- case SEG_TYPE_LISTS:
- return "lists";
- break;
- case SEG_TYPE_NODES:
- return "nodes";
- break;
- case SEG_TYPE_DYNMEM:
- return "dynmem";
- break;
-#ifdef ENABLE_SCI32
- case SEG_TYPE_ARRAY:
- return "array";
- break;
- case SEG_TYPE_STRING:
- return "string";
- break;
-#endif
- default:
- error("Unknown SegmentObj type %d", type);
- break;
- }
- return NULL;
-}
-
SegmentRef SegmentObj::dereference(reg_t pointer) {
error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",
PRINT_REG(pointer));
return SegmentRef();
}
-
-bool LocalVariables::isValidOffset(uint16 offset) const {
- return offset < _locals.size() * 2;
-}
-
-SegmentRef LocalVariables::dereference(reg_t pointer) {
- SegmentRef ret;
- ret.isRaw = false; // reg_t based data!
- ret.maxSize = (_locals.size() - pointer.offset / 2) * 2;
-
- if (pointer.offset & 1) {
- ret.maxSize -= 1;
- ret.skipByte = true;
- }
-
- if (ret.maxSize > 0) {
- ret.reg = &_locals[pointer.offset / 2];
- } else {
- if ((g_sci->getEngineState()->currentRoomNumber() == 660 || g_sci->getEngineState()->currentRoomNumber() == 660)
- && g_sci->getGameId() == GID_LAURABOW2) {
- // Happens in two places during the intro of LB2CD, both from kMemory(peek):
- // - room 160: Heap 160 has 83 local variables (0-82), and the game
- // asks for variables at indices 83 - 90 too.
- // - room 220: Heap 220 has 114 local variables (0-113), and the
- // game asks for variables at indices 114-120 too.
- } else {
- error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer));
- }
- ret.reg = 0;
- }
- return ret;
-}
-
-bool DataStack::isValidOffset(uint16 offset) const {
- return offset < _capacity * 2;
-}
-
-SegmentRef DataStack::dereference(reg_t pointer) {
- SegmentRef ret;
- ret.isRaw = false; // reg_t based data!
- ret.maxSize = (_capacity - pointer.offset / 2) * 2;
-
- if (pointer.offset & 1) {
- ret.maxSize -= 1;
- ret.skipByte = true;
- }
-
- ret.reg = &_entries[pointer.offset / 2];
- return ret;
-}
-
-bool DynMem::isValidOffset(uint16 offset) const {
- return offset < _size;
-}
-
-SegmentRef DynMem::dereference(reg_t pointer) {
- SegmentRef ret;
- ret.isRaw = true;
- ret.maxSize = _size - pointer.offset;
- ret.raw = _buf + pointer.offset;
- return ret;
-}
-
//-------------------- clones --------------------
Common::Array<reg_t> CloneTable::listAllOutgoingReferences(reg_t addr) const {
@@ -220,8 +115,6 @@ Common::Array<reg_t> CloneTable::listAllOutgoingReferences(reg_t addr) const {
void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) {
#ifdef GC_DEBUG
- // assert(addr.segment == _segId);
-
Object *victim_obj = &(_table[addr.offset]);
if (!(victim_obj->_flags & OBJECT_FLAG_FREED))
@@ -229,30 +122,54 @@ void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) {
#ifdef GC_DEBUG_VERBOSE
else
warning("[GC-DEBUG] Clone %04x:%04x: Freeing", PRINT_REG(addr));
+
+ warning("[GC] Clone had pos %04x:%04x", PRINT_REG(victim_obj->pos));
#endif
#endif
- /*
- warning("[GC] Clone %04x:%04x: Freeing", PRINT_REG(addr));
- warning("[GC] Clone had pos %04x:%04x", PRINT_REG(victim_obj->pos));
- */
+
freeEntry(addr.offset);
}
//-------------------- locals --------------------
+
+SegmentRef LocalVariables::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = false; // reg_t based data!
+ ret.maxSize = (_locals.size() - pointer.offset / 2) * 2;
+
+ if (pointer.offset & 1) {
+ ret.maxSize -= 1;
+ ret.skipByte = true;
+ }
+
+ if (ret.maxSize > 0) {
+ ret.reg = &_locals[pointer.offset / 2];
+ } else {
+ if ((g_sci->getEngineState()->currentRoomNumber() == 660 || g_sci->getEngineState()->currentRoomNumber() == 660)
+ && g_sci->getGameId() == GID_LAURABOW2) {
+ // Happens in two places during the intro of LB2CD, both from kMemory(peek):
+ // - room 160: Heap 160 has 83 local variables (0-82), and the game
+ // asks for variables at indices 83 - 90 too.
+ // - room 220: Heap 220 has 114 local variables (0-113), and the
+ // game asks for variables at indices 114-120 too.
+ } else {
+ error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer));
+ }
+ ret.reg = 0;
+ }
+ return ret;
+}
+
reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) const {
// Reference the owning script
SegmentId owner_seg = segMan->getScriptSegment(script_id);
-
assert(owner_seg > 0);
-
return make_reg(owner_seg, 0);
}
Common::Array<reg_t> LocalVariables::listAllOutgoingReferences(reg_t addr) const {
Common::Array<reg_t> tmp;
-// assert(addr.segment == _segId);
-
for (uint i = 0; i < _locals.size(); i++)
tmp.push_back(_locals[i]);
@@ -261,9 +178,19 @@ Common::Array<reg_t> LocalVariables::listAllOutgoingReferences(reg_t addr) const
//-------------------- stack --------------------
-reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) const {
- addr.offset = 0;
- return addr;
+
+SegmentRef DataStack::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = false; // reg_t based data!
+ ret.maxSize = (_capacity - pointer.offset / 2) * 2;
+
+ if (pointer.offset & 1) {
+ ret.maxSize -= 1;
+ ret.skipByte = true;
+ }
+
+ ret.reg = &_entries[pointer.offset / 2];
+ return ret;
}
Common::Array<reg_t> DataStack::listAllOutgoingReferences(reg_t object) const {
@@ -274,11 +201,7 @@ Common::Array<reg_t> DataStack::listAllOutgoingReferences(reg_t object) const {
return tmp;
}
-
//-------------------- lists --------------------
-void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
- freeEntry(sub_addr.offset);
-}
Common::Array<reg_t> ListTable::listAllOutgoingReferences(reg_t addr) const {
Common::Array<reg_t> tmp;
@@ -296,11 +219,7 @@ Common::Array<reg_t> ListTable::listAllOutgoingReferences(reg_t addr) const {
return tmp;
}
-
//-------------------- nodes --------------------
-void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
- freeEntry(sub_addr.offset);
-}
Common::Array<reg_t> NodeTable::listAllOutgoingReferences(reg_t addr) const {
Common::Array<reg_t> tmp;
@@ -321,14 +240,12 @@ Common::Array<reg_t> NodeTable::listAllOutgoingReferences(reg_t addr) const {
//-------------------- dynamic memory --------------------
-reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) const {
- addr.offset = 0;
- return addr;
-}
-
-Common::Array<reg_t> DynMem::listAllDeallocatable(SegmentId segId) const {
- const reg_t r = make_reg(segId, 0);
- return Common::Array<reg_t>(&r, 1);
+SegmentRef DynMem::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = true;
+ ret.maxSize = _size - pointer.offset;
+ ret.raw = _buf + pointer.offset;
+ return ret;
}
#ifdef ENABLE_SCI32
@@ -393,11 +310,6 @@ SegmentRef StringTable::dereference(reg_t pointer) {
return ret;
}
-void StringTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
- _table[sub_addr.offset].destroy();
- freeEntry(sub_addr.offset);
-}
-
#endif
} // End of namespace Sci
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 9aaa3a4b08..947953e8c3 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -84,7 +84,6 @@ struct SegmentObj : public Common::Serializable {
public:
static SegmentObj *createSegmentObj(SegmentType type);
- static const char *getSegmentTypeName(SegmentType type);
public:
SegmentObj(SegmentType type) : _type(type) {}
@@ -150,11 +149,11 @@ struct LocalVariables : public SegmentObj {
Common::Array<reg_t> _locals;
public:
- LocalVariables(): SegmentObj(SEG_TYPE_LOCALS) {
- script_id = 0;
- }
+ LocalVariables(): SegmentObj(SEG_TYPE_LOCALS), script_id(0) { }
- virtual bool isValidOffset(uint16 offset) const;
+ virtual bool isValidOffset(uint16 offset) const {
+ return offset < _locals.size() * 2;
+ }
virtual SegmentRef dereference(reg_t pointer);
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
@@ -168,18 +167,19 @@ struct DataStack : SegmentObj {
reg_t *_entries;
public:
- DataStack() : SegmentObj(SEG_TYPE_STACK) {
- _capacity = 0;
- _entries = NULL;
- }
+ DataStack() : SegmentObj(SEG_TYPE_STACK), _capacity(0), _entries(NULL) { }
~DataStack() {
free(_entries);
_entries = NULL;
}
- virtual bool isValidOffset(uint16 offset) const;
+ virtual bool isValidOffset(uint16 offset) const {
+ return offset < _capacity * 2;
+ }
virtual SegmentRef dereference(reg_t pointer);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const {
+ return make_reg(addr.segment, 0);
+ }
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
@@ -211,7 +211,7 @@ struct Hunk {
};
template<typename T>
-struct Table : public SegmentObj {
+struct SegmentObjTable : public SegmentObj {
typedef T value_type;
struct Entry : public T {
int next_free; /* Only used for free entries */
@@ -225,7 +225,7 @@ struct Table : public SegmentObj {
Common::Array<Entry> _table;
public:
- Table(SegmentType type) : SegmentObj(type) {
+ SegmentObjTable(SegmentType type) : SegmentObj(type) {
initTable();
}
@@ -279,8 +279,8 @@ public:
/* CloneTable */
-struct CloneTable : public Table<Clone> {
- CloneTable() : Table<Clone>(SEG_TYPE_CLONES) {}
+struct CloneTable : public SegmentObjTable<Clone> {
+ CloneTable() : SegmentObjTable<Clone>(SEG_TYPE_CLONES) {}
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
@@ -290,10 +290,12 @@ struct CloneTable : public Table<Clone> {
/* NodeTable */
-struct NodeTable : public Table<Node> {
- NodeTable() : Table<Node>(SEG_TYPE_NODES) {}
+struct NodeTable : public SegmentObjTable<Node> {
+ NodeTable() : SegmentObjTable<Node>(SEG_TYPE_NODES) {}
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+ }
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
@@ -301,10 +303,12 @@ struct NodeTable : public Table<Node> {
/* ListTable */
-struct ListTable : public Table<List> {
- ListTable() : Table<List>(SEG_TYPE_LISTS) {}
+struct ListTable : public SegmentObjTable<List> {
+ ListTable() : SegmentObjTable<List>(SEG_TYPE_LISTS) {}
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+ }
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
@@ -312,18 +316,29 @@ struct ListTable : public Table<List> {
/* HunkTable */
-struct HunkTable : public Table<Hunk> {
- HunkTable() : Table<Hunk>(SEG_TYPE_HUNK) {}
-
- virtual void freeEntry(int idx) {
- Table<Hunk>::freeEntry(idx);
+struct HunkTable : public SegmentObjTable<Hunk> {
+ HunkTable() : SegmentObjTable<Hunk>(SEG_TYPE_HUNK) {}
+ virtual ~HunkTable() {
+ for (uint i = 0; i < _table.size(); i++) {
+ if (isValidEntry(i))
+ freeEntryContents(i);
+ }
+ }
- if (!_table[idx].mem)
- warning("Attempt to free an already freed hunk");
+ void freeEntryContents(int idx) {
free(_table[idx].mem);
_table[idx].mem = 0;
}
+ virtual void freeEntry(int idx) {
+ SegmentObjTable<Hunk>::freeEntry(idx);
+ freeEntryContents(idx);
+ }
+
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+ }
+
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -341,10 +356,17 @@ public:
_buf = NULL;
}
- virtual bool isValidOffset(uint16 offset) const;
+ virtual bool isValidOffset(uint16 offset) const {
+ return offset < _size;
+ }
virtual SegmentRef dereference(reg_t pointer);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
- virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const;
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const {
+ return make_reg(addr.segment, 0);
+ }
+ virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const {
+ const reg_t r = make_reg(segId, 0);
+ return Common::Array<reg_t>(&r, 1);
+ }
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -354,12 +376,7 @@ public:
template <typename T>
class SciArray {
public:
- SciArray() {
- _type = -1;
- _data = NULL;
- _size = 0;
- _actualSize = 0;
- }
+ SciArray() : _type(-1), _data(NULL), _size(0), _actualSize(0) { }
SciArray(const SciArray<T> &array) {
_type = array._type;
@@ -474,8 +491,8 @@ public:
void fromString(const Common::String &string);
};
-struct ArrayTable : public Table<SciArray<reg_t> > {
- ArrayTable() : Table<SciArray<reg_t> >(SEG_TYPE_ARRAY) {}
+struct ArrayTable : public SegmentObjTable<SciArray<reg_t> > {
+ ArrayTable() : SegmentObjTable<SciArray<reg_t> >(SEG_TYPE_ARRAY) {}
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
@@ -484,10 +501,13 @@ struct ArrayTable : public Table<SciArray<reg_t> > {
SegmentRef dereference(reg_t pointer);
};
-struct StringTable : public Table<SciString> {
- StringTable() : Table<SciString>(SEG_TYPE_STRING) {}
+struct StringTable : public SegmentObjTable<SciString> {
+ StringTable() : SegmentObjTable<SciString>(SEG_TYPE_STRING) {}
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ _table[sub_addr.offset].destroy();
+ freeEntry(sub_addr.offset);
+ }
void saveLoadWithSerializer(Common::Serializer &ser);
SegmentRef dereference(reg_t pointer);
diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp
index 798dbf529c..957a836e3e 100644
--- a/engines/sci/engine/selector.cpp
+++ b/engines/sci/engine/selector.cpp
@@ -165,6 +165,7 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(vanishingX);
FIND_SELECTOR(vanishingY);
FIND_SELECTOR(iconIndex);
+ FIND_SELECTOR(select);
#ifdef ENABLE_SCI32
FIND_SELECTOR(data);
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index 6038ad0c36..8a47984204 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -130,6 +130,7 @@ struct SelectorCache {
// SCI1.1 Mac icon bar selectors
Selector iconIndex; ///< Used to index icon bar objects
+ Selector select;
#ifdef ENABLE_SCI32
Selector data; // Used by Array()/String()
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 12795adeb1..f9d6c70389 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -94,10 +94,9 @@ void EngineState::reset(bool isRestoring) {
stack_base = 0;
stack_top = 0;
- restAdjust = 0;
-
r_acc = NULL_REG;
r_prev = NULL_REG;
+ r_rest = 0;
lastWaitTime = 0;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index bba34b6b48..cd6d56500a 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -32,8 +32,8 @@
#include "common/str-array.h"
namespace Common {
- class SeekableReadStream;
- class WriteStream;
+class SeekableReadStream;
+class WriteStream;
}
#include "sci/sci.h"
@@ -79,10 +79,6 @@ private:
};
enum {
- MAX_SAVE_DIR_SIZE = MAXPATHLEN
-};
-
-enum {
MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */
};
@@ -187,9 +183,10 @@ public:
int executionStackBase;
bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */
+ // Registers
reg_t r_acc; /**< Accumulator */
- int16 restAdjust; /**< current &rest register */
reg_t r_prev; /**< previous comparison result */
+ int16 r_rest; /**< current &rest register */
StackPtr stack_base; /**< Pointer to the least stack element */
StackPtr stack_top; /**< First invalid stack element */
@@ -230,7 +227,7 @@ public:
enum {
kMemorySegmentMax = 256
};
- uint _memorySegmentSize;
+ uint16 _memorySegmentSize;
byte _memorySegment[kMemorySegmentMax];
VideoState _videoState;
diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp
index 4bb61a0658..23241de330 100644
--- a/engines/sci/engine/static_selectors.cpp
+++ b/engines/sci/engine/static_selectors.cpp
@@ -28,6 +28,7 @@
#include "sci/engine/kernel.h"
#include "sci/engine/seg_manager.h"
+#include "sci/engine/vm.h"
namespace Sci {
@@ -118,6 +119,33 @@ static const SelectorRemap sciSelectorRemap[] = {
{ SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 }
};
+struct ClassReference {
+ int script;
+ const char *className;
+ const char *selectorName;
+ SelectorType selectorType;
+ uint selectorOffset;
+};
+
+// For variable selectors, we ignore the global selectors and start off from
+// the object's selectors (i.e. from the name selector onwards). Thus, the
+// following are not taken into consideration when calculating the indices of
+// variable selectors in this array:
+// SCI0 - SCI1: species, superClass, -info-
+// SCI1.1: -objID-, -size-, -propDict-, -methDict-, -classScript-, -script-,
+// -super-, -info-
+static const ClassReference classReferences[] = {
+ { 0, "Character", "say", kSelectorMethod, 5 }, // Crazy Nick's Soft Picks
+ { 928, "Narrator", "say", kSelectorMethod, 4 },
+ { 928, "Narrator", "startText", kSelectorMethod, 5 },
+ { 929, "Sync", "syncTime", kSelectorVariable, 1 },
+ { 929, "Sync", "syncCue", kSelectorVariable, 2 },
+ { 981, "SysWindow", "open", kSelectorMethod, 1 },
+ { 999, "Script", "init", kSelectorMethod, 0 },
+ { 999, "Script", "dispose", kSelectorMethod, 2 },
+ { 999, "Script", "changeState", kSelectorMethod, 3 }
+};
+
Common::StringArray Kernel::checkStaticSelectorNames() {
Common::StringArray names;
const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0;
@@ -158,133 +186,115 @@ Common::StringArray Kernel::checkStaticSelectorNames() {
names[i] = sci11Selectors[i - count - countSci1];
}
- // Now, we need to find out selectors which keep changing place...
- // We do that by dissecting game objects, and looking for selectors at
- // specified locations.
+ findSpecificSelectors(names);
- // We need to initialize script 0 here, to make sure that it's always
- // located at segment 1.
- _segMan->instantiateScript(0);
-
- // The Actor class contains the init, xLast and yLast selectors, which
- // we reference directly. It's always in script 998, so we need to
- // explicitly load it here.
- if (_resMan->testResource(ResourceId(kResourceTypeScript, 998))) {
- _segMan->instantiateScript(998);
-
- const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor"));
-
- if (actorClass) {
- // The init selector is always the first function
- int initSelectorPos = actorClass->getFuncSelector(0);
+#ifdef ENABLE_SCI32
+ } else {
+ // SCI2+
+ for (int i = 0; i < count; i++)
+ names[i] = sci2Selectors[i];
+#endif
+ }
- if (names.size() < (uint32)initSelectorPos + 2)
- names.resize((uint32)initSelectorPos + 2);
+ for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) {
+ if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) {
+ const uint32 slot = selectorRemap->slot;
+ if (slot >= names.size())
+ names.resize(slot + 1);
+ names[slot] = selectorRemap->name;
+ }
+ }
- names[initSelectorPos] = "init";
- // dispose comes right after init
- names[initSelectorPos + 1] = "dispose";
+ return names;
+}
- if ((getSciVersion() >= SCI_VERSION_1_EGA)) {
- // Find the xLast and yLast selectors, used in kDoBresen
+void Kernel::findSpecificSelectors(Common::StringArray &selectorNames) {
+ // Now, we need to find out selectors which keep changing place...
+ // We do that by dissecting game objects, and looking for selectors at
+ // specified locations.
- // xLast and yLast always come between illegalBits and xStep
- int illegalBitsSelectorPos = actorClass->locateVarSelector(_segMan, 15 + offset); // illegalBits
- int xStepSelectorPos = actorClass->locateVarSelector(_segMan, 51 + offset); // xStep
- if (xStepSelectorPos - illegalBitsSelectorPos != 3) {
- error("illegalBits and xStep selectors aren't found in "
- "known locations. illegalBits = %d, xStep = %d",
- illegalBitsSelectorPos, xStepSelectorPos);
- }
+ // We need to initialize script 0 here, to make sure that it's always
+ // located at segment 1.
+ _segMan->instantiateScript(0);
- int xLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 1);
- int yLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 2);
+ // The Actor class contains the init, xLast and yLast selectors, which
+ // we reference directly. It's always in script 998, so we need to
+ // explicitly load it here.
+ if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) {
+ if (_resMan->testResource(ResourceId(kResourceTypeScript, 998))) {
+ _segMan->instantiateScript(998);
- if (names.size() < (uint32)yLastSelectorPos + 1)
- names.resize((uint32)yLastSelectorPos + 1);
+ const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor"));
- names[xLastSelectorPos] = "xLast";
- names[yLastSelectorPos] = "yLast";
- } // if ((getSciVersion() >= SCI_VERSION_1_EGA))
+ if (actorClass) {
+ // Find the xLast and yLast selectors, used in kDoBresen
+
+ const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0;
+ // xLast and yLast always come between illegalBits and xStep
+ int illegalBitsSelectorPos = actorClass->locateVarSelector(_segMan, 15 + offset); // illegalBits
+ int xStepSelectorPos = actorClass->locateVarSelector(_segMan, 51 + offset); // xStep
+ if (xStepSelectorPos - illegalBitsSelectorPos != 3) {
+ error("illegalBits and xStep selectors aren't found in "
+ "known locations. illegalBits = %d, xStep = %d",
+ illegalBitsSelectorPos, xStepSelectorPos);
+ }
+
+ int xLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 1);
+ int yLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 2);
+
+ if (selectorNames.size() < (uint32)yLastSelectorPos + 1)
+ selectorNames.resize((uint32)yLastSelectorPos + 1);
+
+ selectorNames[xLastSelectorPos] = "xLast";
+ selectorNames[yLastSelectorPos] = "yLast";
} // if (actorClass)
_segMan->uninstantiateScript(998);
} // if (_resMan->testResource(ResourceId(kResourceTypeScript, 998)))
+ } // if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY))
+
+ // Find selectors from specific classes
+
+ for (int i = 0; i < ARRAYSIZE(classReferences); i++) {
+ if (!_resMan->testResource(ResourceId(kResourceTypeScript, classReferences[i].script)))
+ continue;
- if (_resMan->testResource(ResourceId(kResourceTypeScript, 981))) {
- // The SysWindow class contains the open selectors, which we
- // reference directly. It's always in script 981, so we need to
- // explicitly load it here
- _segMan->instantiateScript(981);
+ _segMan->instantiateScript(classReferences[i].script);
- const Object *sysWindowClass = _segMan->getObject(_segMan->findObjectByName("SysWindow"));
+ const Object *targetClass = _segMan->getObject(_segMan->findObjectByName(classReferences[i].className));
+ int targetSelectorPos = 0;
+ uint selectorOffset = classReferences[i].selectorOffset;
- if (sysWindowClass) {
- if (sysWindowClass->getMethodCount() < 2)
- error("The SysWindow class has less than 2 methods");
+ if (targetClass) {
+ if (classReferences[i].selectorType == kSelectorMethod) {
+ if (targetClass->getMethodCount() < selectorOffset + 1)
+ error("The %s class has less than %d methods (%d)",
+ classReferences[i].className, selectorOffset + 1,
+ targetClass->getMethodCount());
- // The open selector is always the second function
- int openSelectorPos = sysWindowClass->getFuncSelector(1);
+ targetSelectorPos = targetClass->getFuncSelector(selectorOffset);
+ } else {
+ // Add the global selectors to the selector ID
+ selectorOffset += (getSciVersion() <= SCI_VERSION_1_LATE) ? 3 : 8;
- if (names.size() < (uint32)openSelectorPos + 1)
- names.resize((uint32)openSelectorPos + 1);
+ if (targetClass->getVarCount() < selectorOffset + 1)
+ error("The %s class has less than %d variables (%d)",
+ classReferences[i].className, selectorOffset + 1,
+ targetClass->getVarCount());
- names[openSelectorPos] = "open";
+ targetSelectorPos = targetClass->getVarSelector(selectorOffset);
}
- _segMan->uninstantiateScript(981);
- } // if (_resMan->testResource(ResourceId(kResourceTypeScript, 981)))
-
- if (g_sci->getGameId() == GID_HOYLE4) {
- // The demo of Hoyle 4 is one of the few demos with lip syncing and no selector vocabulary.
- // This needs two selectors, "syncTime" and "syncCue", which keep changing positions in each
- // game. Usually, games with speech and lip sync have a selector vocabulary, so we don't need
- // to set these two selectors, but we need for Hoyle...
- if (names.size() < 276)
- names.resize(276);
-
- names[274] = "syncTime";
- names[275] = "syncCue";
- } else if (g_sci->getGameId() == GID_PEPPER) {
- // Same as above for the non-interactive demo of Pepper
- if (names.size() < 539)
- names.resize(539);
-
- names[263] = "syncTime";
- names[264] = "syncCue";
- names[538] = "startText";
- } else if (g_sci->getGameId() == GID_LAURABOW2) {
- // The floppy of version needs the changeState selector set to match up with the
- // CD version's workarounds.
- if (names.size() < 251)
- names.resize(251);
-
- names[144] = "changeState";
- } else if (g_sci->getGameId() == GID_CNICK_KQ) {
- if (names.size() < 447)
- names.resize(447);
-
- names[446] = "say";
- }
+ if (selectorNames.size() < (uint32)targetSelectorPos + 1)
+ selectorNames.resize((uint32)targetSelectorPos + 1);
-#ifdef ENABLE_SCI32
- } else {
- // SCI2+
- for (int i = 0; i < count; i++)
- names[i] = sci2Selectors[i];
-#endif
- }
- for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) {
- if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) {
- const uint32 slot = selectorRemap->slot;
- if (slot >= names.size())
- names.resize(slot + 1);
- names[slot] = selectorRemap->name;
+ selectorNames[targetSelectorPos] = classReferences[i].selectorName;
}
}
- return names;
+ // Reset the segment manager
+ _segMan->resetSegMan();
}
} // End of namespace Sci
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index a70ff5ab72..b441815014 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -25,8 +25,6 @@
#include "common/debug.h"
#include "common/debug-channels.h"
-#include "common/stack.h"
-#include "common/config-manager.h"
#include "sci/sci.h"
#include "sci/console.h"
@@ -47,51 +45,10 @@ const reg_t NULL_REG = {0, 0};
const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET};
const reg_t TRUE_REG = {0, 1};
//#define VM_DEBUG_SEND
-
-#define SCI_XS_CALLEE_LOCALS ((SegmentId)-1)
-
-/**
- * Adds an entry to the top of the execution stack.
- *
- * @param[in] s The state with which to execute
- * @param[in] pc The initial program counter
- * @param[in] sp The initial stack pointer
- * @param[in] objp Pointer to the beginning of the current object
- * @param[in] argc Number of parameters to call with
- * @param[in] argp Heap pointer to the first parameter
- * @param[in] selector The selector by which it was called or
- * NULL_SELECTOR if n.a. For debugging.
- * @param[in] exportId The exportId by which it was called or
- * -1 if n.a. For debugging.
- * @param[in] sendp Pointer to the object which the message was
- * sent to. Equal to objp for anything but super.
- * @param[in] origin Number of the execution stack element this
- * entry was created by (usually the current TOS
- * number, except for multiple sends).
- * @param[in] local_segment The segment to use for local variables,
- * or SCI_XS_CALLEE_LOCALS to use obj's segment.
- * @return A pointer to the new exec stack TOS entry
- */
-static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp,
- reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, int localCallOffset,
- reg_t sendp, int origin, SegmentId local_segment);
-
-/**
- * Adds one varselector access to the execution stack.
- * This function is called from send_selector only.
- * @param[in] s The EngineState to use
- * @param[in] objp Pointer to the object owning the selector
- * @param[in] argc 1 for writing, 0 for reading
- * @param[in] argp Pointer to the address of the data to write -2
- * @param[in] selector Selector name
- * @param[in] address Heap address of the selector
- * @param[in] origin Stack frame which the access originated from
- * @return Pointer to the new exec-TOS element
- */
-static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc,
- StackPtr argp, Selector selector, const ObjVarRef& address,
- int origin);
-
+// Enable the define below to have the VM abort on cases where a conditional
+// statement is followed by an unconditional jump (which will most likely lead
+// to an infinite loop). Aids in detecting script bugs such as #3040722.
+//#define ABORT_ON_INFINITE_LOOP
// validation functionality
@@ -114,8 +71,8 @@ static reg_t &validate_property(EngineState *s, Object *obj, int index) {
if (index < 0 || (uint)index >= obj->getVarCount()) {
// This is same way sierra does it and there are some games, that contain such scripts like
// iceman script 998 (fred::canBeHere, executed right at the start)
- debugC(kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!",
- index, obj->getVarCount());
+ debugC(kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested from object %04x:%04x (%s)",
+ index, obj->getVarCount(), PRINT_REG(obj->getPos()), s->_segMan->getObjectName(obj->getPos()));
return dummyReg;
}
@@ -125,10 +82,9 @@ static reg_t &validate_property(EngineState *s, Object *obj, int index) {
static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) {
if (sp >= s->stack_base && sp < s->stack_top)
return sp;
-
+ else
error("[VM] Stack index %d out of valid range [%d..%d]",
(int)(sp - s->stack_base), 0, (int)(s->stack_top - s->stack_base - 1));
- return 0;
}
static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index) {
@@ -163,9 +119,9 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in
extern const char *opcodeNames[]; // from scriptdebug.cpp
-static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t default_value) {
- if (validate_variable(r, stack_base, type, max, index)) {
- if (r[index].segment == 0xffff) {
+static reg_t read_var(EngineState *s, int type, int index) {
+ if (validate_variable(s->variables[type], s->stack_base, type, s->variablesMax[type], index)) {
+ if (s->variables[type][index].segment == 0xffff) {
switch (type) {
case VAR_TEMP: {
// Uninitialized read on a temp
@@ -179,7 +135,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr,
g_sci->getEngineState()->currentRoomNumber(), originReply.localCallOffset);
- r[index] = NULL_REG;
+ s->variables[type][index] = NULL_REG;
break;
#else
error("Uninitialized read for temp %d from method %s::%s (script %d, room %d, localCall %x)",
@@ -188,7 +144,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
#endif
}
assert(solution.type == WORKAROUND_FAKE);
- r[index] = make_reg(0, solution.value);
+ s->variables[type][index] = make_reg(0, solution.value);
break;
}
case VAR_PARAM:
@@ -200,13 +156,13 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
break;
}
}
- return r[index];
+ return s->variables[type][index];
} else
- return default_value;
+ return s->r_acc;
}
-static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t value, SegManager *segMan, Kernel *kernel) {
- if (validate_variable(r, stack_base, type, max, index)) {
+static void write_var(EngineState *s, int type, int index, reg_t value) {
+ if (validate_variable(s->variables[type], s->stack_base, type, s->variablesMax[type], index)) {
// WORKAROUND: This code is needed to work around a probable script bug, or a
// limitation of the original SCI engine, which can be observed in LSL5.
@@ -226,12 +182,12 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
// done, ego's movement will not be updated properly, so the result is
// unpredictable (for example in LSL5, Patti spins around instead of walking).
if (index == 0 && type == VAR_GLOBAL && getSciVersion() > SCI_VERSION_0_EARLY) { // global 0 is ego
- reg_t stopGroopPos = segMan->findObjectByName("stopGroop");
+ reg_t stopGroopPos = s->_segMan->findObjectByName("stopGroop");
if (!stopGroopPos.isNull()) { // does the game have a stopGroop object?
// Find the "client" member variable of the stopGroop object, and update it
ObjVarRef varp;
- if (lookupSelector(segMan, stopGroopPos, SELECTOR(client), &varp, NULL) == kSelectorVariable) {
- reg_t *clientVar = varp.getPointer(segMan);
+ if (lookupSelector(s->_segMan, stopGroopPos, SELECTOR(client), &varp, NULL) == kSelectorVariable) {
+ reg_t *clientVar = varp.getPointer(s->_segMan);
*clientVar = value;
}
}
@@ -244,7 +200,7 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
if (type == VAR_TEMP && value.segment == 0xffff)
value.segment = 0;
- r[index] = value;
+ s->variables[type][index] = value;
// If the game is trying to change its speech/subtitle settings, apply the ScummVM audio
// options first, if they haven't been applied yet
@@ -255,10 +211,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
}
}
-#define READ_VAR(type, index) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, s->r_acc)
-#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, value, s->_segMan, g_sci->getKernel())
-#define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value));
-
// Operating on the stack
// 16 bit:
#define PUSH(v) PUSH32(make_reg(0, v))
@@ -266,26 +218,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
#define PUSH32(a) (*(validate_stack_addr(s, (s->xs->sp)++)) = (a))
#define POP32() (*(validate_stack_addr(s, --(s->xs->sp))))
-bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
- if (_debugState._activeBreakpointTypes & BREAK_EXPORT) {
- uint32 bpaddress;
-
- bpaddress = (script << 16 | 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);
- _debugState.debugging = true;
- _debugState.breakpointWasHit = true;
- return true;
- }
- }
- }
-
- return false;
-}
-
ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) {
int seg = s->_segMan->getScriptSegment(script);
Script *scr = s->_segMan->getScriptIfLoaded(seg);
@@ -315,10 +247,13 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
// Check if a breakpoint is set on this method
g_sci->checkExportBreakpoint(script, pubfunct);
- return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg);
+ ExecStack xstack(calling_obj, calling_obj, sp, argc, argp,
+ seg, make_reg(seg, temp), -1, pubfunct, -1,
+ s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL);
+ s->_executionStack.push_back(xstack);
+ return &(s->_executionStack.back());
}
-
static void _exec_varselectors(EngineState *s) {
// Executes all varselector read/write ops on the TOS
while (!s->_executionStack.empty() && s->_executionStack.back().type == EXEC_STACK_TYPE_VARSELECTOR) {
@@ -338,52 +273,22 @@ static void _exec_varselectors(EngineState *s) {
}
}
-/** This struct is used to buffer the list of send calls in send_selector() */
-struct CallsStruct {
- reg_t addr_func;
- reg_t varp_objp;
- union {
- reg_t func;
- ObjVarRef var;
- } address;
- StackPtr argp;
- int argc;
- Selector selector;
- StackPtr sp; /**< Stack pointer */
- int type; /**< Same as ExecStack.type */
-};
-
-bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) {
- Common::String methodName = _gamestate->_segMan->getObjectName(send_obj);
- methodName += ("::" + getKernel()->getSelectorName(selector));
-
- 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));
- _debugState.debugging = true;
- _debugState.breakpointWasHit = true;
- return true;
- }
- }
- return false;
-}
+// from scriptdebug.cpp
+extern void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType);
ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) {
-// send_obj and work_obj are equal for anything but 'super'
-// Returns a pointer to the TOS exec_stack element
+ // send_obj and work_obj are equal for anything but 'super'
+ // Returns a pointer to the TOS exec_stack element
assert(s);
reg_t funcp;
- int selector;
+ Selector selector;
int argc;
- int origin = s->_executionStack.size()-1; // Origin: Used for debugging
- // We return a pointer to the new active ExecStack
-
- // The selector calls we catch are stored below:
- Common::Stack<CallsStruct> sendCalls;
-
+ int origin = s->_executionStack.size() - 1; // Origin: Used for debugging
int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes;
+ ObjVarRef varp;
+
+ Common::List<ExecStack>::iterator prevElementIterator = s->_executionStack.end();
while (framesize > 0) {
selector = argp->requireUint16();
@@ -393,263 +298,57 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
if (argc > 0x800) // More arguments than the stack could possibly accomodate for
error("send_selector(): More than 0x800 arguments to function call");
-#ifdef VM_DEBUG_SEND
- debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),
- s->_segMan->getObjectName(send_obj), selector,
- g_sci->getKernel()->getSelectorName(selector).c_str());
-#endif // VM_DEBUG_SEND
-
- ObjVarRef varp;
- switch (lookupSelector(s->_segMan, send_obj, selector, &varp, &funcp)) {
- case kSelectorNone:
+ SelectorType selectorType = lookupSelector(s->_segMan, send_obj, selector, &varp, &funcp);
+ if (selectorType == kSelectorNone)
error("Send to invalid selector 0x%x of object at %04x:%04x", 0xffff & selector, PRINT_REG(send_obj));
- break;
- case kSelectorVariable:
-
-#ifdef VM_DEBUG_SEND
- if (argc)
- debugN("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1]));
- else
- debugN("Varselector: Read\n");
-#endif // VM_DEBUG_SEND
-
- // argc == 0: read selector
- // argc != 0: write selector
- if (!argc) {
- // read selector
- if (activeBreakpointTypes & BREAK_SELECTORREAD) {
- if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector))
- debug("[read selector]\n");
- }
- } else {
- // write selector
- if (activeBreakpointTypes & BREAK_SELECTORWRITE) {
- if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) {
- reg_t oldReg = *varp.getPointer(s->_segMan);
- reg_t newReg = argp[1];
- warning("[write to selector (%s:%s): change %04x:%04x to %04x:%04x]\n",
- s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str(),
- PRINT_REG(oldReg), PRINT_REG(newReg));
- }
- }
- }
-
- if (argc > 1) {
- // argc can indeed be bigger than 1 in some cases, and it's usually the
- // result of a script bug. Usually these aren't fatal.
-
- const char *objectName = s->_segMan->getObjectName(send_obj);
-
- reg_t oldReg = *varp.getPointer(s->_segMan);
- reg_t newReg = argp[1];
- const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str();
- debug(2, "send_selector(): argc = %d while modifying variable selector "
- "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x",
- argc, selector, selectorName, PRINT_REG(send_obj),
- objectName, PRINT_REG(oldReg), PRINT_REG(newReg));
- }
-
- {
- CallsStruct call;
- call.address.var = varp; // register the call
- call.argp = argp;
- call.argc = argc;
- call.selector = selector;
- call.type = EXEC_STACK_TYPE_VARSELECTOR; // Register as a varselector
- sendCalls.push(call);
- }
+ ExecStackType stackType = EXEC_STACK_TYPE_VARSELECTOR;
+ StackPtr curSP = NULL;
+ reg_t curFP = NULL_REG;
+ if (selectorType == kSelectorMethod) {
+ stackType = EXEC_STACK_TYPE_CALL;
+ curSP = sp;
+ curFP = funcp;
+ sp = CALL_SP_CARRY; // Destroy sp, as it will be carried over
+ }
- break;
+ if (activeBreakpointTypes || DebugMan.isDebugChannelEnabled(kDebugLevelScripts))
+ debugSelectorCall(send_obj, selector, argc, argp, varp, funcp, s->_segMan, selectorType);
- case kSelectorMethod:
-
-#ifndef VM_DEBUG_SEND
- if (activeBreakpointTypes & BREAK_SELECTOREXEC) {
- if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) {
- debugN("[execute selector]");
-
- int displaySize = 0;
- for (int argNr = 1; argNr <= argc; argNr++) {
- if (argNr == 1)
- debugN(" - ");
- reg_t curParam = argp[argNr];
- if (curParam.isPointer()) {
- debugN("[%04x:%04x] ", PRINT_REG(curParam));
- displaySize += 12;
- } else {
- debugN("[%04x] ", curParam.offset);
- displaySize += 7;
- }
- if (displaySize > 50) {
- if (argNr < argc)
- debugN("...");
- break;
- }
- }
- debugN("\n");
- }
- }
-#else // VM_DEBUG_SEND
- if (activeBreakpointTypes & BREAK_SELECTOREXEC)
- g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector);
- debugN("Funcselector(");
- for (int i = 0; i < argc; i++) {
- debugN("%04x:%04x", PRINT_REG(argp[i+1]));
- if (i + 1 < argc)
- debugN(", ");
- }
- debugN(") at %04x:%04x\n", PRINT_REG(funcp));
-#endif // VM_DEBUG_SEND
+ ExecStack xstack(work_obj, send_obj, curSP, argc, argp,
+ 0xFFFF, curFP, selector, -1, -1,
+ origin, stackType);
- {
- CallsStruct call;
- call.address.func = funcp; // register call
- call.argp = argp;
- call.argc = argc;
- call.selector = selector;
- call.type = EXEC_STACK_TYPE_CALL;
- call.sp = sp;
- sp = CALL_SP_CARRY; // Destroy sp, as it will be carried over
- sendCalls.push(call);
- }
+ if (selectorType == kSelectorVariable)
+ xstack.addr.varp = varp;
- break;
- } // switch (lookupSelector())
+ // The new stack entries should be put on the stack in reverse order
+ // so that the first one is executed first
+ s->_executionStack.insert(prevElementIterator, xstack);
+ // Decrement the stack end pointer so that it points to our recently
+ // added element, so that the next insert() places it before this one.
+ --prevElementIterator;
framesize -= (2 + argc);
argp += argc + 1;
- }
-
- // Iterate over all registered calls in the reverse order. This way, the first call is
- // placed on the TOS; as soon as it returns, it will cause the second call to be executed.
- while (!sendCalls.empty()) {
- CallsStruct call = sendCalls.pop();
- if (call.type == EXEC_STACK_TYPE_VARSELECTOR) // Write/read variable?
- add_exec_stack_varselector(s->_executionStack, work_obj, call.argc, call.argp,
- call.selector, call.address.var, origin);
- else
- add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj,
- call.argc, call.argp,
- call.selector, -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS);
- }
+ } // while (framesize > 0)
_exec_varselectors(s);
return s->_executionStack.empty() ? NULL : &(s->_executionStack.back());
}
-static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) {
- ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, -1, objp, origin, SCI_XS_CALLEE_LOCALS);
- // Store selector address in sp
-
- xstack->addr.varp = address;
- xstack->type = EXEC_STACK_TYPE_VARSELECTOR;
-
- return xstack;
-}
-
-static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc,
- StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId _localsSegment) {
- // Returns new TOS element for the execution stack
- // _localsSegment may be -1 if derived from the called object
-
- //debug("Exec stack: [%d/%d], origin %d, at %p", s->execution_stack_pos, s->_executionStack.size(), origin, s->execution_stack);
-
- ExecStack xstack;
-
- xstack.objp = objp;
- if (_localsSegment != SCI_XS_CALLEE_LOCALS)
- xstack.local_segment = _localsSegment;
- else
- xstack.local_segment = pc.segment;
-
- xstack.sendp = sendp;
- xstack.addr.pc = pc;
- xstack.fp = xstack.sp = sp;
- xstack.argc = argc;
-
- xstack.variables_argp = argp; // Parameters
-
- *argp = make_reg(0, argc); // SCI code relies on the zeroeth argument to equal argc
-
- // Additional debug information
- xstack.debugSelector = selector;
- xstack.debugExportId = exportId;
- xstack.debugLocalCallOffset = localCallOffset;
- xstack.debugOrigin = origin;
-
- xstack.type = EXEC_STACK_TYPE_CALL; // Normal call
-
- execStack.push_back(xstack);
- return &(execStack.back());
-}
-
static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc, reg_t *argv) {
// Add stack frame to indicate we're executing a callk.
// This is useful in debugger backtraces if this
// kernel function calls a script itself.
- ExecStack *xstack;
- xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG,
- s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
- xstack->debugSelector = kernelCallNr;
- xstack->type = EXEC_STACK_TYPE_KERNEL;
+ ExecStack xstack(NULL_REG, NULL_REG, NULL, argc, argv - 1, 0xFFFF, NULL_REG,
+ kernelCallNr, -1, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_KERNEL);
+ s->_executionStack.push_back(xstack);
}
-static void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result) {
- Kernel *kernel = g_sci->getKernel();
- if (!kernelSubCall) {
- debugN("k%s: ", kernelCall->name);
- } else {
- int callNameLen = strlen(kernelCall->name);
- if (strncmp(kernelCall->name, kernelSubCall->name, callNameLen) == 0) {
- const char *subCallName = kernelSubCall->name + callNameLen;
- debugN("k%s(%s): ", kernelCall->name, subCallName);
- } else {
- debugN("k%s(%s): ", kernelCall->name, kernelSubCall->name);
- }
- }
- for (int parmNr = 0; parmNr < argc; parmNr++) {
- if (parmNr)
- debugN(", ");
- uint16 regType = kernel->findRegType(argv[parmNr]);
- if (regType & SIG_TYPE_NULL)
- debugN("0");
- else if (regType & SIG_TYPE_UNINITIALIZED)
- debugN("UNINIT");
- else if (regType & SIG_IS_INVALID)
- debugN("INVALID");
- else if (regType & SIG_TYPE_INTEGER)
- debugN("%d", argv[parmNr].offset);
- else {
- debugN("%04x:%04x", PRINT_REG(argv[parmNr]));
- switch (regType) {
- case SIG_TYPE_OBJECT:
- debugN(" (%s)", s->_segMan->getObjectName(argv[parmNr]));
- break;
- case SIG_TYPE_REFERENCE:
- if (kernelCall->function == kSaid) {
- SegmentRef saidSpec = s->_segMan->dereference(argv[parmNr]);
- if (saidSpec.isRaw) {
- debugN(" ('");
- g_sci->getVocabulary()->debugDecipherSaidBlock(saidSpec.raw);
- debugN("')");
- } else {
- debugN(" (non-raw said-spec)");
- }
- } else {
- debugN(" ('%s')", s->_segMan->getString(argv[parmNr]).c_str());
- }
- default:
- break;
- }
- }
- }
- if (result.isPointer())
- debugN(" = %04x:%04x\n", PRINT_REG(result));
- else
- debugN(" = %d\n", result.offset);
-}
+// from scriptdebug.cpp
+extern void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *kernelSubCall, EngineState *s, int argc, reg_t *argv, reg_t result);
static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
Kernel *kernel = g_sci->getKernel();
@@ -851,7 +550,7 @@ void run_vm(EngineState *s) {
StackPtr s_temp; // Temporary stack pointer
int16 opparams[4]; // opcode parameters
- s->restAdjust = 0; // &rest adjusts the parameter count by this value
+ s->r_rest = 0; // &rest adjusts the parameter count by this value
// Current execution data:
s->xs = &(s->_executionStack.back());
ExecStack *xs_new = NULL;
@@ -871,6 +570,10 @@ void run_vm(EngineState *s) {
s->_executionStackPosChanged = true; // Force initialization
+#ifdef ABORT_ON_INFINITE_LOOP
+ byte prevOpcode = 0xFF;
+#endif
+
while (1) {
int var_type; // See description below
int var_number;
@@ -935,7 +638,22 @@ void run_vm(EngineState *s) {
byte extOpcode;
s->xs->addr.pc.offset += readPMachineInstruction(scr->getBuf() + s->xs->addr.pc.offset, extOpcode, opparams);
const byte opcode = extOpcode >> 1;
- //debug("%s: %d, %d, %d, %d, acc = %04x:%04x", opcodeNames[opcode], opparams[0], opparams[1], opparams[2], opparams[3], PRINT_REG(s->r_acc));
+ //debug("%s: %d, %d, %d, %d, acc = %04x:%04x, script %d, local script %d", opcodeNames[opcode], opparams[0], opparams[1], opparams[2], opparams[3], PRINT_REG(s->r_acc), scr->getScriptNumber(), local_script->getScriptNumber());
+
+#ifdef ABORT_ON_INFINITE_LOOP
+ if (prevOpcode != 0xFF) {
+ if (prevOpcode == op_eq_ || prevOpcode == op_ne_ ||
+ prevOpcode == op_gt_ || prevOpcode == op_ge_ ||
+ prevOpcode == op_lt_ || prevOpcode == op_le_ ||
+ prevOpcode == op_ugt_ || prevOpcode == op_uge_ ||
+ prevOpcode == op_ult_ || prevOpcode == op_ule_) {
+ if (opcode == op_jmp)
+ error("Infinite loop detected in script %d", scr->getScriptNumber());
+ }
+ }
+
+ prevOpcode = opcode;
+#endif
switch (opcode) {
@@ -1105,19 +823,22 @@ void run_vm(EngineState *s) {
case op_call: { // 0x20 (32)
// Call a script subroutine
int argc = (opparams[1] >> 1) // Given as offset, but we need count
- + 1 + s->restAdjust;
+ + 1 + s->r_rest;
StackPtr call_base = s->xs->sp - argc;
- s->xs->sp[1].offset += s->restAdjust;
+ s->xs->sp[1].offset += s->r_rest;
uint16 localCallOffset = s->xs->addr.pc.offset + opparams[0];
- xs_new = add_exec_stack_entry(s->_executionStack, make_reg(s->xs->addr.pc.segment,
- localCallOffset),
- s->xs->sp, s->xs->objp,
- (call_base->requireUint16()) + s->restAdjust,
- call_base, NULL_SELECTOR, -1, localCallOffset, s->xs->objp,
- s->_executionStack.size()-1, s->xs->local_segment);
- s->restAdjust = 0; // Used up the &rest adjustment
+ ExecStack xstack(s->xs->objp, s->xs->objp, s->xs->sp,
+ (call_base->requireUint16()) + s->r_rest, call_base,
+ s->xs->local_segment, make_reg(s->xs->addr.pc.segment, localCallOffset),
+ NULL_SELECTOR, -1, localCallOffset, s->_executionStack.size() - 1,
+ EXEC_STACK_TYPE_CALL);
+
+ s->_executionStack.push_back(xstack);
+ xs_new = &(s->_executionStack.back());
+
+ s->r_rest = 0; // Used up the &rest adjustment
s->xs->sp = call_base;
s->_executionStackPosChanged = true;
@@ -1136,17 +857,17 @@ void run_vm(EngineState *s) {
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
if (!oldScriptHeader)
- s->xs->sp -= s->restAdjust;
+ s->xs->sp -= s->r_rest;
int argc = s->xs->sp[0].requireUint16();
if (!oldScriptHeader)
- argc += s->restAdjust;
+ argc += s->r_rest;
callKernelFunc(s, opparams[0], argc);
if (!oldScriptHeader)
- s->restAdjust = 0;
+ s->r_rest = 0;
// Calculate xs again: The kernel function might
// have spawned a new VM
@@ -1163,28 +884,28 @@ void run_vm(EngineState *s) {
case op_callb: // 0x22 (34)
// Call base script
- temp = ((opparams[1] >> 1) + s->restAdjust + 1);
+ temp = ((opparams[1] >> 1) + s->r_rest + 1);
s_temp = s->xs->sp;
s->xs->sp -= temp;
- s->xs->sp[0].offset += s->restAdjust;
+ s->xs->sp[0].offset += s->r_rest;
xs_new = execute_method(s, 0, opparams[0], s_temp, s->xs->objp,
s->xs->sp[0].offset, s->xs->sp);
- s->restAdjust = 0; // Used up the &rest adjustment
+ s->r_rest = 0; // Used up the &rest adjustment
if (xs_new) // in case of error, keep old stack
s->_executionStackPosChanged = true;
break;
case op_calle: // 0x23 (35)
// Call external script
- temp = ((opparams[2] >> 1) + s->restAdjust + 1);
+ temp = ((opparams[2] >> 1) + s->r_rest + 1);
s_temp = s->xs->sp;
s->xs->sp -= temp;
- s->xs->sp[0].offset += s->restAdjust;
+ s->xs->sp[0].offset += s->r_rest;
xs_new = execute_method(s, opparams[0], opparams[1], s_temp, s->xs->objp,
s->xs->sp[0].offset, s->xs->sp);
- s->restAdjust = 0; // Used up the &rest adjustment
+ s->r_rest = 0; // Used up the &rest adjustment
if (xs_new) // in case of error, keep old stack
s->_executionStackPosChanged = true;
@@ -1236,16 +957,16 @@ void run_vm(EngineState *s) {
case op_send: // 0x25 (37)
// Send for one or more selectors
s_temp = s->xs->sp;
- s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
+ s->xs->sp -= ((opparams[0] >> 1) + s->r_rest); // Adjust stack
- s->xs->sp[1].offset += s->restAdjust;
+ s->xs->sp[1].offset += s->r_rest;
xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp,
- (int)(opparams[0] >> 1) + (uint16)s->restAdjust, s->xs->sp);
+ (int)(opparams[0] >> 1) + (uint16)s->r_rest, s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjust = 0;
+ s->r_rest = 0;
break;
@@ -1279,17 +1000,17 @@ void run_vm(EngineState *s) {
case op_self: // 0x2a (42)
// Send to self
s_temp = s->xs->sp;
- s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
+ s->xs->sp -= ((opparams[0] >> 1) + s->r_rest); // Adjust stack
- s->xs->sp[1].offset += s->restAdjust;
+ s->xs->sp[1].offset += s->r_rest;
xs_new = send_selector(s, s->xs->objp, s->xs->objp,
- s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjust,
+ s_temp, (int)(opparams[0] >> 1) + (uint16)s->r_rest,
s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjust = 0;
+ s->r_rest = 0;
break;
case op_super: // 0x2b (43)
@@ -1300,17 +1021,17 @@ void run_vm(EngineState *s) {
error("[VM]: Invalid superclass in object");
else {
s_temp = s->xs->sp;
- s->xs->sp -= ((opparams[1] >> 1) + s->restAdjust); // Adjust stack
+ s->xs->sp -= ((opparams[1] >> 1) + s->r_rest); // Adjust stack
- s->xs->sp[1].offset += s->restAdjust;
+ s->xs->sp[1].offset += s->r_rest;
xs_new = send_selector(s, r_temp, s->xs->objp, s_temp,
- (int)(opparams[1] >> 1) + (uint16)s->restAdjust,
+ (int)(opparams[1] >> 1) + (uint16)s->r_rest,
s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjust = 0;
+ s->r_rest = 0;
}
break;
@@ -1318,7 +1039,7 @@ void run_vm(EngineState *s) {
case op_rest: // 0x2c (44)
// Pushes all or part of the parameter variable list on the stack
temp = (uint16) opparams[0]; // First argument
- s->restAdjust = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
+ s->r_rest = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
for (; temp <= s->xs->argc; temp++)
PUSH32(s->xs->variables_argp[temp]);
@@ -1476,7 +1197,7 @@ void run_vm(EngineState *s) {
// an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + (opcode >= op_lagi ? s->r_acc.requireSint16() : 0);
- s->r_acc = READ_VAR(var_type, var_number);
+ s->r_acc = read_var(s, var_type, var_number);
break;
case op_lsg: // 0x44 (68)
@@ -1492,7 +1213,7 @@ void run_vm(EngineState *s) {
// an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + (opcode >= op_lsgi ? s->r_acc.requireSint16() : 0);
- PUSH32(READ_VAR(var_type, var_number));
+ PUSH32(read_var(s, var_type, var_number));
break;
case op_sag: // 0x50 (80)
@@ -1510,7 +1231,7 @@ void run_vm(EngineState *s) {
var_number = opparams[0] + (opcode >= op_sagi ? s->r_acc.requireSint16() : 0);
if (opcode >= op_sagi) // load the actual value to store in the accumulator
s->r_acc = POP32();
- WRITE_VAR(var_type, var_number, s->r_acc);
+ write_var(s, var_type, var_number, s->r_acc);
break;
case op_ssg: // 0x54 (84)
@@ -1526,7 +1247,7 @@ void run_vm(EngineState *s) {
// an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + (opcode >= op_ssgi ? s->r_acc.requireSint16() : 0);
- WRITE_VAR(var_type, var_number, POP32());
+ write_var(s, var_type, var_number, POP32());
break;
case op_plusag: // 0x60 (96)
@@ -1543,8 +1264,8 @@ void run_vm(EngineState *s) {
// an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + (opcode >= op_plusagi ? s->r_acc.requireSint16() : 0);
- s->r_acc = READ_VAR(var_type, var_number) + 1;
- WRITE_VAR(var_type, var_number, s->r_acc);
+ s->r_acc = read_var(s, var_type, var_number) + 1;
+ write_var(s, var_type, var_number, s->r_acc);
break;
case op_plussg: // 0x64 (100)
@@ -1561,9 +1282,9 @@ void run_vm(EngineState *s) {
// an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + (opcode >= op_plussgi ? s->r_acc.requireSint16() : 0);
- r_temp = READ_VAR(var_type, var_number) + 1;
+ r_temp = read_var(s, var_type, var_number) + 1;
PUSH32(r_temp);
- WRITE_VAR(var_type, var_number, r_temp);
+ write_var(s, var_type, var_number, r_temp);
break;
case op_minusag: // 0x70 (112)
@@ -1580,8 +1301,8 @@ void run_vm(EngineState *s) {
// an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + (opcode >= op_minusagi ? s->r_acc.requireSint16() : 0);
- s->r_acc = READ_VAR(var_type, var_number) - 1;
- WRITE_VAR(var_type, var_number, s->r_acc);
+ s->r_acc = read_var(s, var_type, var_number) - 1;
+ write_var(s, var_type, var_number, s->r_acc);
break;
case op_minussg: // 0x74 (116)
@@ -1598,9 +1319,9 @@ void run_vm(EngineState *s) {
// an additional index
var_type = opcode & 0x3; // Gets the variable type: g, l, t or p
var_number = opparams[0] + (opcode >= op_minussgi ? s->r_acc.requireSint16() : 0);
- r_temp = READ_VAR(var_type, var_number) - 1;
+ r_temp = read_var(s, var_type, var_number) - 1;
PUSH32(r_temp);
- WRITE_VAR(var_type, var_number, r_temp);
+ write_var(s, var_type, var_number, r_temp);
break;
default:
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index ee22e03310..5947579aa3 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -92,9 +92,10 @@ struct ExecStack {
StackPtr fp; // Frame pointer
StackPtr sp; // Stack pointer
- int argc;
+ int argc;
StackPtr variables_argp; // Argument pointer
+
SegmentId local_segment; // local variables etc
Selector debugSelector; // The selector which was used to call or -1 if not applicable
@@ -104,6 +105,29 @@ struct ExecStack {
ExecStackType type;
reg_t* getVarPointer(SegManager *segMan) const;
+
+ ExecStack(reg_t objp_, reg_t sendp_, StackPtr sp_, int argc_, StackPtr argp_,
+ SegmentId localsSegment_, reg_t pc_, Selector debugSelector_,
+ int debugExportId_, int debugLocalCallOffset_, int debugOrigin_,
+ ExecStackType type_) {
+ objp = objp_;
+ sendp = sendp_;
+ // varp is set separately for varselector calls
+ addr.pc = pc_;
+ fp = sp = sp_;
+ argc = argc_;
+ variables_argp = argp_;
+ *variables_argp = make_reg(0, argc); // The first argument is argc
+ if (localsSegment_ != 0xFFFF)
+ local_segment = localsSegment_;
+ else
+ local_segment = pc_.segment;
+ debugSelector = debugSelector_;
+ debugExportId = debugExportId_;
+ debugLocalCallOffset = debugLocalCallOffset_;
+ debugOrigin = debugOrigin_;
+ type = type_;
+ }
};
enum {
@@ -115,7 +139,7 @@ enum {
/** Number of kernel calls in between gcs; should be < 50000 */
enum {
- GC_INTERVAL = 32768
+ GC_INTERVAL = 0x8000
};
// Opcode formats
diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp
index dea4d63bf0..e606fa1f86 100644
--- a/engines/sci/engine/vm_types.cpp
+++ b/engines/sci/engine/vm_types.cpp
@@ -31,13 +31,11 @@
namespace Sci {
-extern const char *opcodeNames[]; // from scriptdebug.cpp
-
reg_t reg_t::lookForWorkaround(const reg_t right) const {
SciTrackOriginReply originReply;
SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, arithmeticWorkarounds, &originReply);
if (solution.type == WORKAROUND_NONE)
- error("arithmetic operation on non-integer (%04x:%04x, %04x:%04x) from method %s::%s (script %d, room %d, localCall %x)",
+ error("Invalid arithmetic operation (params: %04x:%04x and %04x:%04x) from method %s::%s (script %d, room %d, localCall %x)",
PRINT_REG(*this), PRINT_REG(right), originReply.objectName.c_str(),
originReply.methodName.c_str(), originReply.scriptNr, g_sci->getEngineState()->currentRoomNumber(),
originReply.localCallOffset);
@@ -46,7 +44,7 @@ reg_t reg_t::lookForWorkaround(const reg_t right) const {
}
reg_t reg_t::operator+(const reg_t right) const {
- if (isPointer() && isInitialized()) {
+ if (isPointer() && right.isNumber()) {
// Pointer arithmetics. Only some pointer types make sense here
SegmentObj *mobj = g_sci->getEngineState()->_segMan->getSegmentObj(segment);
@@ -58,29 +56,18 @@ reg_t reg_t::operator+(const reg_t right) const {
case SEG_TYPE_SCRIPT:
case SEG_TYPE_STACK:
case SEG_TYPE_DYNMEM:
- // Make sure that we are adding an offset to the pointer
- if (right.isPointer())
- return lookForWorkaround(right);
return make_reg(segment, offset + right.toSint16());
default:
return lookForWorkaround(right);
}
- } else if (isNumber() && isInitialized() && right.isPointer()) {
+ } else if (isNumber() && right.isPointer()) {
// Adding a pointer to a number, flip the order
return right + *this;
+ } else if (isNumber() && right.isNumber()) {
+ // Normal arithmetics
+ return make_reg(0, toSint16() + right.toSint16());
} else {
- // Normal arithmetics. Make sure we're adding a number
- if (right.isPointer())
- return lookForWorkaround(right);
- // If the current variable is uninitialized, it'll be set
- // to zero in order to perform the operation. Such a case
- // happens in SQ1, room 28, when throwing the water at Orat.
- if (!isInitialized())
- return make_reg(0, right.toSint16());
- else if (!right.isInitialized())
- return *this;
- else
- return make_reg(0, toSint16() + right.toSint16());
+ return lookForWorkaround(right);
}
}
@@ -97,24 +84,19 @@ reg_t reg_t::operator-(const reg_t right) const {
reg_t reg_t::operator*(const reg_t right) const {
if (isNumber() && right.isNumber())
return make_reg(0, toSint16() * right.toSint16());
- else if (!isInitialized() || !right.isInitialized())
- return NULL_REG; // unitialized variables - always return 0
else
return lookForWorkaround(right);
}
reg_t reg_t::operator/(const reg_t right) const {
- if (isNumber() && right.isNumber()) {
- if (right.isNull())
- return NULL_REG; // division by zero
- else
- return make_reg(0, toSint16() / right.toSint16());
- } else
+ if (isNumber() && right.isNumber() && !right.isNull())
+ return make_reg(0, toSint16() / right.toSint16());
+ else
return lookForWorkaround(right);
}
reg_t reg_t::operator%(const reg_t right) const {
- if (isNumber() && right.isNumber()) {
+ if (isNumber() && right.isNumber() && !right.isNull()) {
// Support for negative numbers was added in Iceman, and perhaps in
// SCI0 0.000.685 and later. Theoretically, this wasn't really used
// in SCI0, so the result is probably unpredictable. Such a case
@@ -125,7 +107,7 @@ reg_t reg_t::operator%(const reg_t right) const {
warning("Modulo of a negative number has been requested for SCI0. This *could* lead to issues");
int16 value = toSint16();
int16 modulo = ABS(right.toSint16());
- int16 result = (modulo != 0 ? value % modulo : 0);
+ int16 result = value % modulo;
if (result < 0)
result += modulo;
return make_reg(0, result);
@@ -159,6 +141,8 @@ uint16 reg_t::requireUint16() const {
if (isNumber())
return toUint16();
else
+ // The right parameter is NULL_REG because
+ // we're not comparing *this with anything here.
return lookForWorkaround(NULL_REG).toUint16();
}
@@ -166,6 +150,8 @@ int16 reg_t::requireSint16() const {
if (isNumber())
return toSint16();
else
+ // The right parameter is NULL_REG because
+ // we're not comparing *this with anything here.
return lookForWorkaround(NULL_REG).toSint16();
}
@@ -190,76 +176,51 @@ reg_t reg_t::operator^(const reg_t right) const {
return lookForWorkaround(right);
}
-bool reg_t::operator>(const reg_t right) const {
- if (isNumber() && right.isNumber())
- return toSint16() > right.toSint16();
- else if (isPointer() && segment == right.segment)
- return toUint16() > right.toUint16(); // pointer comparison
- else if (pointerComparisonWithInteger(right))
- return true;
- else if (right.pointerComparisonWithInteger(*this))
- return false;
- else
- return lookForWorkaround(right).toSint16();
-}
-
-bool reg_t::operator<(const reg_t right) const {
- if (isNumber() && right.isNumber())
- return toSint16() < right.toSint16();
- else if (isPointer() && segment == right.segment)
- return toUint16() < right.toUint16(); // pointer comparison
- else if (pointerComparisonWithInteger(right))
- return false;
- else if (right.pointerComparisonWithInteger(*this))
- return true;
- else
- return lookForWorkaround(right).toSint16();
-}
-
-bool reg_t::gtU(const reg_t right) const {
- if (isNumber() && right.isNumber())
- return toUint16() > right.toUint16();
- else if (isPointer() && segment == right.segment)
- return toUint16() > right.toUint16(); // pointer comparison
- else if (pointerComparisonWithInteger(right))
- return true;
- else if (right.pointerComparisonWithInteger(*this))
- return false;
- else
- return lookForWorkaround(right).toSint16();
-}
-
-bool reg_t::ltU(const reg_t right) const {
- if (isNumber() && right.isNumber())
- return toUint16() < right.toUint16();
- else if (isPointer() && segment == right.segment)
- return toUint16() < right.toUint16(); // pointer comparison
- else if (pointerComparisonWithInteger(right))
- return false;
- else if (right.pointerComparisonWithInteger(*this))
- return true;
- else
+int reg_t::cmp(const reg_t right, bool treatAsUnsigned) const {
+ if (segment == right.segment) { // can compare things in the same segment
+ if (treatAsUnsigned || !isNumber())
+ return toUint16() - right.toUint16();
+ else
+ return toSint16() - right.toSint16();
+ } else if (pointerComparisonWithInteger(right)) {
+ return 1;
+ } else if (right.pointerComparisonWithInteger(*this)) {
+ return -1;
+ } else
return lookForWorkaround(right).toSint16();
}
bool reg_t::pointerComparisonWithInteger(const reg_t right) const {
- // SCI0 - SCI1.1 scripts use this to check whether a parameter is a pointer
- // or a far text reference. It is used e.g. by the standard library Print
- // function to distinguish two ways of calling it:
+ // This function handles the case where a script tries to compare a pointer
+ // to a number. Normally, we would not want to allow that. However, SCI0 -
+ // SCI1.1 scripts do this in order to distinguish references to
+ // external resources (which are numbers) from pointers. In
+ // our SCI implementation, such a check may seem pointless, as
+ // one can simply use the segment value to achieve this goal.
+ // But Sierra's SCI did not have the notion of segment IDs, so
+ // both pointer and numbers were simple integers.
+ //
+ // But for some things, scripts had (and have) to distinguish between
+ // numbers and pointers. Lacking the segment information, Sierra's
+ // developers resorted to a hack: If an integer is smaller than a certain
+ // bound, it can be assumed to be a number, otherwise it is assumed to be a
+ // pointer. This allowed them to implement polymorphic functions, such as
+ // the Print function, which can be called in two different ways, with a
+ // pointer or a far text reference:
//
// (Print "foo") // Pointer to a string
// (Print 420 5) // Reference to the fifth message in text resource 420
// It works because in those games, the maximum resource number is 999,
// so any parameter value above that threshold must be a pointer.
// PQ2 japanese compares pointers to 2000 to find out if its a pointer
- // or a resource ID.
- // There are cases where game scripts check for arbitrary numbers against
- // pointers, e.g.:
+ // or a resource ID. Thus, we check for all integers <= 2000.
+ //
+ // Some examples where game scripts check for arbitrary numbers against
+ // pointers:
// Hoyle 3, Pachisi, when any opponent is about to talk
// SQ1, room 28, when throwing water at the Orat
// SQ1, room 58, when giving the ID card to the robot
- // QFG3, room 440, when talking to Uhura
- // Thus we check for all integers <= 2000
+ // SQ4 CD, at the first game screen, when the narrator is about to speak
return (isPointer() && right.isNumber() && right.offset <= 2000 && getSciVersion() <= SCI_VERSION_1_1);
}
diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h
index ac23bbe7dc..b927df339e 100644
--- a/engines/sci/engine/vm_types.h
+++ b/engines/sci/engine/vm_types.h
@@ -37,20 +37,20 @@ struct reg_t {
SegmentId segment;
uint16 offset;
- bool isNull() const {
- return !(offset || segment);
+ inline bool isNull() const {
+ return (offset | segment) == 0;
}
- uint16 toUint16() const {
+ inline uint16 toUint16() const {
return offset;
}
- int16 toSint16() const {
- return (int16) offset;
+ inline int16 toSint16() const {
+ return (int16)offset;
}
bool isNumber() const {
- return !segment;
+ return segment == 0;
}
bool isPointer() const {
@@ -60,7 +60,7 @@ struct reg_t {
uint16 requireUint16() const;
int16 requireSint16() const;
- bool isInitialized() const {
+ inline bool isInitialized() const {
return segment != 0xFFFF;
}
@@ -73,35 +73,39 @@ struct reg_t {
return (offset != x.offset) || (segment != x.segment);
}
- bool operator>(const reg_t right) const;
+ bool operator>(const reg_t right) const {
+ return cmp(right, false) > 0;
+ }
+
bool operator>=(const reg_t right) const {
- if (*this == right)
- return true;
- return *this > right;
+ return cmp(right, false) >= 0;
+ }
+
+ bool operator<(const reg_t right) const {
+ return cmp(right, false) < 0;
}
- bool operator<(const reg_t right) const;
+
bool operator<=(const reg_t right) const {
- if (*this == right)
- return true;
- return *this < right;
+ return cmp(right, false) <= 0;
}
// Same as the normal operators, but perform unsigned
// integer checking
- bool gtU(const reg_t right) const;
+ bool gtU(const reg_t right) const {
+ return cmp(right, true) > 0;
+ }
+
bool geU(const reg_t right) const {
- if (*this == right)
- return true;
- return gtU(right);
+ return cmp(right, true) >= 0;
}
- bool ltU(const reg_t right) const;
- bool leU(const reg_t right) const {
- if (*this == right)
- return true;
- return ltU(right);
+
+ bool ltU(const reg_t right) const {
+ return cmp(right, true) < 0;
}
- bool pointerComparisonWithInteger(const reg_t right) const;
+ bool leU(const reg_t right) const {
+ return cmp(right, true) <= 0;
+ }
// Arithmetic operators
reg_t operator+(const reg_t right) const;
@@ -125,7 +129,17 @@ struct reg_t {
reg_t operator|(const reg_t right) const;
reg_t operator^(const reg_t right) const;
+private:
+ /**
+ * Compares two reg_t's.
+ * Returns:
+ * - a positive number if *this > right
+ * - 0 if *this == right
+ * - a negative number if *this < right
+ */
+ int cmp(const reg_t right, bool treatAsUnsigned) const;
reg_t lookForWorkaround(const reg_t right) const;
+ bool pointerComparisonWithInteger(const reg_t right) const;
};
static inline reg_t make_reg(SegmentId segment, uint16 offset) {
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 64cbc5ec90..20d6cd0dd0 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -36,16 +36,15 @@ namespace Sci {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry arithmeticWorkarounds[] = {
{ GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #3044734
- { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #3034464
+ { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #3034464
{ GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #3038913
{ GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl
- { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version)
- { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #3038228
+ { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version)
+ { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #3038228
{ 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_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 #3039879
- // TODO: The SQ5 workaround below may no longer be necessary
- { GID_SQ5, 200, 939, 0, "Osc", "cycleDone", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_dpToa: when going back to bridge the crew is goofing off, we get an object as cycle count
+ { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -75,6 +74,11 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_HOYLE4, -1, 0, 0, NULL, "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when selecting "Control" from the menu (temp vars 0-3) - bug #3039294
{ GID_HOYLE4, 910, 18, 0, NULL, "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // during tutorial - bug #3042756
{ GID_HOYLE4, 910, 910, 0, NULL, "setup", -1, 3, { WORKAROUND_FAKE, 0 } }, // when selecting "Tutorial" from the main menu - bug #3039294
+ { GID_HOYLE4, 700, 718, 0, "compete_tree", "doit", -1, 75, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge - bug #3292332
+ { GID_HOYLE4, 700, 716, 0, "other1_tree", "doit", -1, 46, { WORKAROUND_FAKE, 0 } }, // sometimes when placing a bid in bridge
+ { GID_HOYLE4, 700, 700, 1, "BridgeHand", "calcQTS", -1, 3, { WORKAROUND_FAKE, 0 } }, // sometimes when placing a bid in bridge
+ { GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts
+ { GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #3292334
{ GID_ISLANDBRAIN, 100, 937, 0, "IconBar", "dispatchEvent", -1, 58, { WORKAROUND_FAKE, 0 } }, // when using ENTER at the startup menu - bug #3045225
{ 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
@@ -92,7 +96,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_KQ6, 520, 520, 0, "rm520", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle
{ GID_KQ6, -1, 903, 0, "controlWin", "open", -1, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc)
{ GID_KQ6, -1, 907, 0, "tomato", "doVerb", -1, 2, { WORKAROUND_FAKE, 0 } }, // when looking at the rotten tomato in the inventory - bug #3059544
- { GID_KQ7, 30, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key
+ { GID_KQ7, -1, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key
{ GID_LAURABOW, 37, 0, 0, "CB1", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs (bug #3037694)
{ GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up (initial bug #3034985)
{ GID_LAURABOW2, -1, 24, 0, "gcWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu
@@ -115,11 +119,13 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_LSL6HIRES, -1, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // during the game
{ GID_MOTHERGOOSE256, -1, 0, 0, "MG", "doit", -1, 5, { WORKAROUND_FAKE, 0 } }, // SCI1.1: When moving the cursor all the way to the left during the game (bug #3043955)
{ GID_MOTHERGOOSE256, -1, 992, 0, "AIPath", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // Happens in the demo and full version. In the demo, it happens when walking two screens from mother goose's house to the north. In the full version, it happens in rooms 7 and 23 - bug #3049146
+ { GID_MOTHERGOOSE256, 90, 90, 0, "introScript", "changeState", -1, 65, { WORKAROUND_FAKE, 0 } }, // SCI1(CD): At the very end, after the game is completed and restarted - bug #3268076
{ GID_MOTHERGOOSE256, 94, 94, 0, "sunrise", "changeState", -1, 367, { WORKAROUND_FAKE, 0 } }, // At the very end, after the game is completed - bug #3051163
{ GID_MOTHERGOOSEHIRES,-1,64950, 1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // right when clicking on a child at the start and probably also later
{ GID_MOTHERGOOSEHIRES,-1,64950, 1, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // see above
{ GID_PEPPER, -1, 894, 0, "Package", "doVerb", -1, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #3040012
{ GID_PEPPER, 150, 928, 0, "Narrator", "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper
+ { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning
{ GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbd0, 0, { WORKAROUND_FAKE, 0 } }, // hq1: going to the brigands hideout
{ GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbe4, 0, { WORKAROUND_FAKE, 0 } }, // qfg1: going to the brigands hideout
{ GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #3053268
@@ -131,6 +137,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_QFG2, 260, 260, 0, "abdulS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #3039891, temps 1 and 2
{ GID_QFG2, 260, 260, 0, "jabbarS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #3040469, temps 1 and 2
{ GID_QFG2, 500, 500, 0, "lightNextCandleS", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // Inside the last room, while Ad Avis performs the ritual to summon the genie - bug #3148418
+ { GID_QFG2, -1, 700, 0, NULL, "showSign", -1, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #3272735, #3275413
{ GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #3049435
{ GID_QFG3, 140, 140, 0, "rm140", "init", 0x1008, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #3040460
{ GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #3036390, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #3039774, temp 1)
@@ -141,7 +148,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_QFG3, 851, 32, -1, "ProjObj", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // near the end, when throwing the spear of death, bug #3050122
{ GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen
{ GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu
- { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happen sometimes in fights
+ { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happens sometimes in fight scenes
{ GID_RAMA, 12, 64950, -1, "InterfaceFeature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts
{ GID_RAMA, 12, 64950, -1, "hiliteOptText", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts
{ GID_RAMA, 12, 64950, -1, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts
@@ -249,6 +256,7 @@ const SciWorkaroundEntry kGetAngle_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kFindKey_workarounds[] = {
{ GID_ECOQUEST2, 100, 999, 0, "myList", "contains", -1, 0, { WORKAROUND_FAKE, 0 } }, // When Noah Greene gives Adam the Ecorder, and just before the game gives a demonstration, a null reference to a list is passed - bug #3035186
+ { GID_HOYLE4, 300, 999, 0, "Piles", "contains", -1, 0, { WORKAROUND_FAKE, 0 } }, // When passing the three cards in Hearts, a null reference to a list is passed - bug #3292333
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -273,10 +281,6 @@ const SciWorkaroundEntry kGraphSaveBox_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = {
- { GID_LSL6, -1, 85, 0, "rScroller", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring (sometimes), same as the one below
- { GID_LSL6, -1, 85, 0, "lScroller", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring (sometimes), same as the one below
- { GID_LSL6, -1, 86, 0, "LL6Inv", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time
- // ^^ TODO: check, if this is really a script error or an issue with our restore code
{ GID_LSL6, -1, 86, 0, "LL6Inv", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens during the game, gets called with 1 extra parameter
{ GID_SQ5, 850, 850, 0, NULL, "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens while playing Battle Cruiser (invalid segment) - bug #3056811
SCI_WORKAROUNDENTRY_TERMINATOR
@@ -316,7 +320,7 @@ const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = {
const SciWorkaroundEntry kGraphUpdateBox_workarounds[] = {
{ GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function
{ GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
- { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
+ { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #3038077
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -330,7 +334,7 @@ const SciWorkaroundEntry kIsObject_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kMemory_workarounds[] = {
- { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train, talking to Mr. Augustini, etc. - bug #3034490
+ { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train (room 160), talking to Mr. Augustini, etc. - bug #3034490
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -361,7 +365,7 @@ const SciWorkaroundEntry kSetCursor_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kSetPort_workarounds[] = {
{ GID_LSL6, 740, 740, 0, "rm740", "drawPic", -1, 0, { WORKAROUND_IGNORE, 0 } }, // ending scene, is called with additional 3 (!) parameters
- { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, bug #3040844
+ { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, gets called with 4 parameters (bug #3040844)
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -373,12 +377,6 @@ const SciWorkaroundEntry kStrAt_workarounds[] = {
};
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
-const SciWorkaroundEntry kStrCat_workarounds[] = {
- { GID_LONGBOW, 210, 210, 0, "giveScroll", "changeState",0x3294, 0, { WORKAROUND_FAKE, 0 } }, // German version, when handing the scroll with the druid hand code to Marion - bug #3048054
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kStrLen_workarounds[] = {
{ GID_QFG2, 210, 2, 0, "", "export 21", 0xdeb, 0, { WORKAROUND_FAKE, 0 } }, // When saying something incorrect at the WIT, an integer is passed instead of a reference - bug #3100292
SCI_WORKAROUNDENTRY_TERMINATOR
@@ -386,23 +384,13 @@ const SciWorkaroundEntry kStrLen_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kUnLoad_workarounds[] = {
- { GID_CAMELOT, 921, 921, 1, "Script", "changeState", 0x36, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: While showing Camelot (and other places), the reference is invalid - bug #3035000
- { GID_CAMELOT, 921, 921, 1, "Script", "init", 0x36, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When being attacked by the boar (and other places), the reference is invalid - bug #3035000
- { GID_CASTLEBRAIN, 320, 377, 0, "SWord", "upDate", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after solving the cross-word-puzzle, trying to unload invalid reference
- { GID_CASTLEBRAIN, 320, 377, 0, "theWord", "show", -1, 0, { WORKAROUND_IGNORE, 0 } }, // 2nd word puzzle, when exiting before solving, trying to unload invalid reference - bug #3034473
- { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after talking to the dolphin the first time
- { GID_ECOQUEST, 380, 69, 0, "lookAtBlackBoard", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room - bug #3098353
- { GID_LAURABOW2, 1, 1, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902
- { GID_LAURABOW2, 2, 2, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902
- { GID_LAURABOW2, 4, 4, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: inside the museum, a 3rd parameter is passed by accident - bug #3034902
- { GID_LAURABOW2, 6, 6, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the murder, a 3rd parameter is passed by accident - bug #3034902
- { GID_LAURABOW2, 7, 7, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the logo is shown, a 3rd parameter is passed by accident - bug #3034902
+ { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // CD version: after talking to the dolphin the first time, a 3rd parameter is passed by accident
+ { GID_ECOQUEST, 380, 69, 0, "lookAtBlackBoard", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room, a 3rd parameter is passed by accident - bug #3098353
+ { GID_LAURABOW2, -1, 1, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902
{ GID_LSL6, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident
{ GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident
{ GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident
- { GID_PQ3, 877, 998, 0, "View", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when getting run over on the freeway, the reference is invalid
{ GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error
- { GID_SQ3, 2, 998, 0, "View", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // clicking the mouse button during the intro, after the escape pod gets pulled into the garbage freighter, the reference is invalid - bug #3050856
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -416,14 +404,14 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun
return sci3IgnoreForNow;
}
- EngineState *state = g_sci->getEngineState();
+ const EngineState *state = g_sci->getEngineState();
ExecStack *lastCall = state->xs;
- Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment);
- int curScriptNr = local_script->getScriptNumber();
+ const Script *localScript = state->_segMan->getScriptIfLoaded(lastCall->local_segment);
+ int curScriptNr = localScript->getScriptNumber();
if (lastCall->debugLocalCallOffset != -1) {
// if lastcall was actually a local call search back for a real call
- Common::List<ExecStack>::iterator callIterator = state->_executionStack.end();
+ Common::List<ExecStack>::const_iterator callIterator = state->_executionStack.end();
while (callIterator != state->_executionStack.begin()) {
callIterator--;
ExecStack loopCall = *callIterator;
diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h
index 7ab73cdff2..c7721aa787 100644
--- a/engines/sci/engine/workarounds.h
+++ b/engines/sci/engine/workarounds.h
@@ -95,7 +95,6 @@ extern const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[];
extern const SciWorkaroundEntry kSetCursor_workarounds[];
extern const SciWorkaroundEntry kSetPort_workarounds[];
extern const SciWorkaroundEntry kStrAt_workarounds[];
-extern const SciWorkaroundEntry kStrCat_workarounds[];
extern const SciWorkaroundEntry kStrLen_workarounds[];
extern const SciWorkaroundEntry kUnLoad_workarounds[];
diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp
index d607a5314f..6b5ea64fc4 100644
--- a/engines/sci/event.cpp
+++ b/engines/sci/event.cpp
@@ -32,15 +32,10 @@
#include "sci/console.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
+#include "sci/graphics/screen.h"
namespace Sci {
-EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended), _modifierStates(0) {
-}
-
-EventManager::~EventManager() {
-}
-
struct ScancodeRow {
int offset;
const char *keys;
@@ -52,27 +47,6 @@ const ScancodeRow s_scancodeRows[] = {
{ 0x2c, "ZXCVBNM,./" }
};
-static int altify(int ch) {
- // Calculates a PC keyboard scancode from a character */
- int row;
- int c = toupper((char)ch);
-
- for (row = 0; row < ARRAYSIZE(s_scancodeRows); row++) {
- const char *keys = s_scancodeRows[row].keys;
- int offset = s_scancodeRows[row].offset;
-
- while (*keys) {
- if (*keys == c)
- return offset << 8;
-
- offset++;
- keys++;
- }
- }
-
- return ch;
-}
-
const byte codepagemap_88591toDOS[0x80] = {
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x8x
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x9x
@@ -120,147 +94,182 @@ const SciKeyConversion keyMappings[] = {
{ Common::KEYCODE_KP_DIVIDE , '/' , '/' },
};
+struct MouseEventConversion {
+ Common::EventType commonType;
+ short sciType;
+ short data;
+};
+
+const MouseEventConversion mouseEventMappings[] = {
+ { Common::EVENT_LBUTTONDOWN, SCI_EVENT_MOUSE_PRESS, 1 },
+ { Common::EVENT_RBUTTONDOWN, SCI_EVENT_MOUSE_PRESS, 2 },
+ { Common::EVENT_MBUTTONDOWN, SCI_EVENT_MOUSE_PRESS, 3 },
+ { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 1 },
+ { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 2 },
+ { Common::EVENT_LBUTTONUP, SCI_EVENT_MOUSE_RELEASE, 3 }
+};
+
+EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended) {
+}
+
+EventManager::~EventManager() {
+}
+
+static int altify(int ch) {
+ // Calculates a PC keyboard scancode from a character */
+ int row;
+ int c = toupper((char)ch);
+
+ for (row = 0; row < ARRAYSIZE(s_scancodeRows); row++) {
+ const char *keys = s_scancodeRows[row].keys;
+ int offset = s_scancodeRows[row].offset;
+
+ while (*keys) {
+ if (*keys == c)
+ return offset << 8;
+
+ offset++;
+ keys++;
+ }
+ }
+
+ return ch;
+}
+
SciEvent EventManager::getScummVMEvent() {
- SciEvent input = { SCI_EVENT_NONE, 0, 0, 0 };
+ SciEvent input = { SCI_EVENT_NONE, 0, 0, 0, Common::Point(0, 0) };
+ SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, 0, Common::Point(0, 0) };
Common::EventManager *em = g_system->getEventManager();
Common::Event ev;
bool found = em->pollEvent(ev);
- Common::Point p = ev.mouse;
// Don't generate events for mouse movement
- while (found && ev.type == Common::EVENT_MOUSEMOVE) {
+ while (found && ev.type == Common::EVENT_MOUSEMOVE)
found = em->pollEvent(ev);
+
+ // Save the mouse position
+ //
+ // We call getMousePos of the event manager here, since we also want to
+ // store the mouse position in case of keyboard events, which do not feature
+ // any mouse position information itself.
+ // This should be safe, since the mouse position in the event manager should
+ // only be updated when a mouse related event has been taken from the queue
+ // via pollEvent.
+ // We also adjust the position based on the scaling of the screen.
+ Common::Point mousePos = em->getMousePos();
+ g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);
+
+ noEvent.mousePos = input.mousePos = mousePos;
+
+ if (!found || ev.type == Common::EVENT_MOUSEMOVE)
+ return noEvent;
+
+ if (ev.type == Common::EVENT_QUIT) {
+ input.type = SCI_EVENT_QUIT;
+ return input;
}
- if (found && ev.type != Common::EVENT_MOUSEMOVE) {
- int modifiers = em->getModifierState();
- bool numlockOn = (ev.kbd.flags & Common::KBD_NUM);
-
- // We add the modifier key status to buckybits
- //TODO: SCI_EVM_INSERT
-
- input.modifiers =
- ((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
- ((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
- ((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0) |
- ((ev.kbd.flags & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) |
- ((ev.kbd.flags & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) |
- _modifierStates;
-
- switch (ev.type) {
- // Keyboard events
- case Common::EVENT_KEYDOWN:
- input.data = ev.kbd.keycode;
- input.character = ev.kbd.ascii;
-
- // Debug console
- if (ev.kbd.hasFlags(Common::KBD_CTRL) && ev.kbd.keycode == Common::KEYCODE_d) {
- // Open debug console
- Console *con = g_sci->getSciDebugger();
- con->attach();
-
- // Clear keyboard event
- input.type = SCI_EVENT_NONE;
- input.character = 0;
- input.data = 0;
- input.modifiers = 0;
-
- return input;
- }
+ // Handle mouse events
+ for (int i = 0; i < ARRAYSIZE(mouseEventMappings); i++) {
+ if (mouseEventMappings[i].commonType == ev.type) {
+ input.type = mouseEventMappings[i].sciType;
+ input.data = mouseEventMappings[i].data;
+ return input;
+ }
+ }
- if (!(input.data & 0xFF00)) {
- // Directly accept most common keys without conversion
- input.type = SCI_EVENT_KEYBOARD;
- if ((input.character >= 0x80) && (input.character <= 0xFF)) {
- // If there is no extended font, we will just clear the current event
- // Sierra SCI actually accepted those characters, but didn't display them inside textedit-controls
- // because the characters were missing inside the font(s)
- // We filter them out for non-multilingual games because of that
- if (!_fontIsExtended) {
- input.type = SCI_EVENT_NONE;
- input.character = 0;
- input.data = 0;
- input.modifiers = 0;
- return input;
- }
- // We get a 8859-1 character, we need dos (cp850/437) character for multilingual sci01 games
- input.character = codepagemap_88591toDOS[input.character & 0x7f];
- }
- if (input.data == Common::KEYCODE_TAB) {
- // Tab
- input.type = SCI_EVENT_KEYBOARD;
- input.data = SCI_KEY_TAB;
- if (input.modifiers & (SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT))
- input.character = SCI_KEY_SHIFT_TAB;
- else
- input.character = SCI_KEY_TAB;
- }
- if (input.data == Common::KEYCODE_DELETE) {
- // Delete key
- input.type = SCI_EVENT_KEYBOARD;
- input.data = input.character = SCI_KEY_DELETE;
- }
- } else if ((input.data >= Common::KEYCODE_F1) && input.data <= Common::KEYCODE_F10) {
- // F1-F10
- input.type = SCI_EVENT_KEYBOARD;
- // SCI_K_F1 == 59 << 8
- // SCI_K_SHIFT_F1 == 84 << 8
- input.data = SCI_KEY_F1 + ((input.data - Common::KEYCODE_F1)<<8);
- if (input.modifiers & (SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT))
- input.character = input.data + 0x1900;
- else
- input.character = input.data;
- } else {
- // Special keys that need conversion
- input.type = SCI_EVENT_KEYBOARD;
- for (int i = 0; i < ARRAYSIZE(keyMappings); i++) {
- if (keyMappings[i].scummVMKey == ev.kbd.keycode) {
- input.data = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff;
- break;
- }
- }
- input.character = input.data;
- }
- break;
+ // If we reached here, make sure that it's a keydown event
+ if (ev.type != Common::EVENT_KEYDOWN)
+ return noEvent;
- // Mouse events
- case Common::EVENT_LBUTTONDOWN:
- input.type = SCI_EVENT_MOUSE_PRESS;
- input.data = 1;
- break;
- case Common::EVENT_RBUTTONDOWN:
- input.type = SCI_EVENT_MOUSE_PRESS;
- input.data = 2;
- break;
- case Common::EVENT_MBUTTONDOWN:
- input.type = SCI_EVENT_MOUSE_PRESS;
- input.data = 3;
- break;
- case Common::EVENT_LBUTTONUP:
- input.type = SCI_EVENT_MOUSE_RELEASE;
- input.data = 1;
- break;
- case Common::EVENT_RBUTTONUP:
- input.type = SCI_EVENT_MOUSE_RELEASE;
- input.data = 2;
- break;
- case Common::EVENT_MBUTTONUP:
- input.type = SCI_EVENT_MOUSE_RELEASE;
- input.data = 3;
- break;
-
- // Misc events
- case Common::EVENT_QUIT:
- input.type = SCI_EVENT_QUIT;
- break;
+ // Check for Control-D (debug console)
+ if (ev.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_SHIFT) && ev.kbd.keycode == Common::KEYCODE_d) {
+ // Open debug console
+ Console *con = g_sci->getSciDebugger();
+ con->attach();
+ return noEvent;
+ }
- default:
- break;
+ // Process keyboard events
+
+ int modifiers = em->getModifierState();
+ bool numlockOn = (ev.kbd.flags & Common::KBD_NUM);
+
+ input.data = ev.kbd.keycode;
+ input.character = ev.kbd.ascii;
+ input.type = SCI_EVENT_KEYBOARD;
+
+ input.modifiers =
+ ((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
+ ((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
+ ((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0);
+
+ // Caps lock and Scroll lock have been removed, cause we already handle upper
+ // case keys ad Scroll lock doesn't seem to be used anywhere
+ //((ev.kbd.flags & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) |
+ //((ev.kbd.flags & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) |
+
+ if (!(input.data & 0xFF00)) {
+ // Directly accept most common keys without conversion
+ if ((input.character >= 0x80) && (input.character <= 0xFF)) {
+ // If there is no extended font, we will just clear the
+ // current event.
+ // Sierra SCI actually accepted those characters, but
+ // didn't display them inside text edit controls because
+ // the characters were missing inside the font(s).
+ // We filter them out for non-multilingual games because
+ // of that.
+ if (!_fontIsExtended)
+ return noEvent;
+ // Convert 8859-1 characters to DOS (cp850/437) for
+ // multilingual SCI01 games
+ input.character = codepagemap_88591toDOS[input.character & 0x7f];
+ }
+ if (input.data == Common::KEYCODE_TAB) {
+ input.character = input.data = SCI_KEY_TAB;
+ if (modifiers & Common::KBD_SHIFT)
+ input.character = SCI_KEY_SHIFT_TAB;
+ }
+ if (input.data == Common::KEYCODE_DELETE)
+ input.data = input.character = SCI_KEY_DELETE;
+ } else if ((input.data >= Common::KEYCODE_F1) && input.data <= Common::KEYCODE_F10) {
+ // SCI_K_F1 == 59 << 8
+ // SCI_K_SHIFT_F1 == 84 << 8
+ input.character = input.data = SCI_KEY_F1 + ((input.data - Common::KEYCODE_F1)<<8);
+ if (modifiers & Common::KBD_SHIFT)
+ input.character = input.data + 0x1900;
+ } else {
+ // Special keys that need conversion
+ for (int i = 0; i < ARRAYSIZE(keyMappings); i++) {
+ if (keyMappings[i].scummVMKey == ev.kbd.keycode) {
+ input.character = input.data = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff;
+ break;
+ }
}
}
+
+ // When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give
+ // us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway
+ // we support the other case as well
+ if ((modifiers & Common::KBD_SHIFT) && input.character > 0 && input.character < 27)
+ input.character += 96; // 0x01 -> 'a'
+
+ if (getSciVersion() <= SCI_VERSION_1_MIDDLE) {
+ // TODO: find out if altify is also not needed for sci1late+, couldnt find any game that uses those keys
+ // Scancodify if appropriate
+ if (modifiers & Common::KBD_ALT)
+ input.character = altify(input.character);
+ else if ((modifiers & Common::KBD_CTRL) && input.character > 0 && input.character < 27)
+ input.character += 96; // 0x01 -> 'a'
+ }
+ // If no actual key was pressed (e.g. if only a modifier key was pressed),
+ // ignore the event
+ if (!input.character)
+ return noEvent;
+
return input;
}
@@ -282,8 +291,7 @@ void EventManager::updateScreen() {
}
SciEvent EventManager::getSciEvent(unsigned int mask) {
- //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 };
- SciEvent event = { 0, 0, 0, 0 };
+ SciEvent event = { 0, 0, 0, 0, Common::Point(0, 0) };
EventManager::updateScreen();
@@ -304,9 +312,8 @@ SciEvent EventManager::getSciEvent(unsigned int mask) {
event = *iter;
// If not peeking at the queue, remove the event
- if (!(mask & SCI_EVENT_PEEK)) {
+ if (!(mask & SCI_EVENT_PEEK))
_events.erase(iter);
- }
} else {
// No event found: we must return a SCI_EVT_NONE event.
@@ -314,29 +321,6 @@ SciEvent EventManager::getSciEvent(unsigned int mask) {
// there is no need to change it.
}
- if (event.type == SCI_EVENT_KEYBOARD) {
- // Do we still have to translate the key?
-
- // When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give
- // us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway
- // we support the other case as well
- if (event.modifiers & SCI_KEYMOD_ALT) {
- if (event.character < 27)
- event.character += 96; // 0x01 -> 'a'
- }
-
- if (getSciVersion() <= SCI_VERSION_1_MIDDLE) {
- // TODO: find out if altify is also not needed for sci1late+, couldnt find any game that uses those keys
- // Scancodify if appropriate
- if (event.modifiers & SCI_KEYMOD_ALT) {
- event.character = altify(event.character);
- } else if (event.modifiers & SCI_KEYMOD_CTRL) {
- if (event.character < 27)
- event.character += 96; // 0x01 -> 'a'
- }
- }
- }
-
return event;
}
diff --git a/engines/sci/event.h b/engines/sci/event.h
index 7c83476294..be0322f2a4 100644
--- a/engines/sci/event.h
+++ b/engines/sci/event.h
@@ -27,6 +27,7 @@
#define SCI_EVENT_H
#include "common/list.h"
+#include "common/rect.h"
namespace Sci {
@@ -46,6 +47,13 @@ struct SciEvent {
* PC keyboard scancodes.
*/
short character;
+
+ /**
+ * The mouse position at the time the event was created.
+ *
+ * These are display coordinates!
+ */
+ Common::Point mousePos;
};
/*Values for type*/
@@ -56,11 +64,8 @@ struct SciEvent {
#define SCI_EVENT_DIRECTION (1<<6)
#define SCI_EVENT_SAID (1<<7)
/*Fake values for other events*/
-#define SCI_EVENT_ERROR (1<<10)
#define SCI_EVENT_QUIT (1<<11)
#define SCI_EVENT_PEEK (1<<15)
-/* The QUIT event may be used to signal an external 'quit' command being
-** issued to the gfx driver. */
#define SCI_EVENT_ANY 0x7fff
/* Keycodes of special keys: */
@@ -121,7 +126,6 @@ private:
SciEvent getScummVMEvent();
const bool _fontIsExtended;
- int _modifierStates;
Common::List<SciEvent> _events;
};
diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp
index 2e5e94c52a..d8f3fa09b0 100644
--- a/engines/sci/graphics/animate.cpp
+++ b/engines/sci/graphics/animate.cpp
@@ -27,6 +27,7 @@
#include "common/stack.h"
#include "graphics/primitives.h"
+#include "sci/console.h"
#include "sci/sci.h"
#include "sci/event.h"
#include "sci/engine/kernel.h"
@@ -191,11 +192,88 @@ void GfxAnimate::makeSortedList(List *list) {
Common::sort(_list.begin(), _list.end(), sortHelper);
}
-void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view) {
- reg_t curObject = entry->object;
+void GfxAnimate::fill(byte &old_picNotValid) {
+ GfxView *view = NULL;
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
+
+ for (it = _list.begin(); it != end; ++it) {
+ // Get the corresponding view
+ view = _cache->getView(it->viewId);
+
+ adjustInvalidCels(view, it);
+ processViewScaling(view, it);
+ setNsRect(view, it);
+
+ //warning("%s view %d, loop %d, cel %d, signal %x", _s->_segMan->getObjectName(curObject), it->viewId, it->loopNo, it->celNo, it->signal);
+
+ // Calculate current priority according to y-coordinate
+ if (!(it->signal & kSignalFixedPriority)) {
+ it->priority = _ports->kernelCoordinateToPriority(it->y);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(priority), it->priority);
+ }
+
+ if (it->signal & kSignalNoUpdate) {
+ if ((it->signal & (kSignalForceUpdate | kSignalViewUpdated))
+ || (it->signal & kSignalHidden && !(it->signal & kSignalRemoveView))
+ || (!(it->signal & kSignalHidden) && it->signal & kSignalRemoveView)
+ || (it->signal & kSignalAlwaysUpdate))
+ old_picNotValid++;
+ it->signal &= ~kSignalStopUpdate;
+ } else {
+ if ((it->signal & kSignalStopUpdate) || (it->signal & kSignalAlwaysUpdate))
+ old_picNotValid++;
+ it->signal &= ~kSignalForceUpdate;
+ }
+ }
+}
+
+void GfxAnimate::adjustInvalidCels(GfxView *view, AnimateList::iterator it) {
+ // adjust loop and cel, if any of those is invalid
+ // this seems to be completely crazy code
+ // sierra sci checked signed int16 to be above or equal the counts and reseted to 0 in those cases
+ // later during view processing those are compared unsigned again and then set to maximum count - 1
+ // Games rely on this behaviour. For example laura bow 1 has a knight standing around in room 37
+ // which has cel set to 3. This cel does not exist and the actual knight is 0
+ // In kq5 on the other hand during the intro, when the trunk is opened, cel is set to some real
+ // high number, which is negative when considered signed. This actually requires to get fixed to
+ // maximum cel, otherwise the trunk would be closed.
+ int16 viewLoopCount = view->getLoopCount();
+ if (it->loopNo >= viewLoopCount) {
+ it->loopNo = 0;
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(loop), it->loopNo);
+ } else if (it->loopNo < 0) {
+ it->loopNo = viewLoopCount - 1;
+ // not setting selector is right, sierra sci didn't do it during view processing as well
+ }
+ int16 viewCelCount = view->getCelCount(it->loopNo);
+ if (it->celNo >= viewCelCount) {
+ it->celNo = 0;
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(cel), it->celNo);
+ } else if (it->celNo < 0) {
+ it->celNo = viewCelCount - 1;
+ }
+}
+
+void GfxAnimate::processViewScaling(GfxView *view, AnimateList::iterator it) {
+ if (!view->isScaleable()) {
+ // Laura Bow 2 (especially floppy) depends on this, some views are not supposed to be scaleable
+ // this "feature" was removed in later versions of SCI1.1
+ it->scaleSignal = 0;
+ it->scaleY = it->scaleX = 128;
+ } else {
+ // Process global scaling, if needed
+ if (it->scaleSignal & kScaleSignalDoScaling) {
+ if (it->scaleSignal & kScaleSignalGlobalScaling) {
+ applyGlobalScaling(it, view);
+ }
+ }
+ }
+}
+void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view) {
// Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
- int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale));
+ int16 maxScale = readSelectorValue(_s->_segMan, entry->object, SELECTOR(maxScale));
int16 celHeight = view->getHeight(entry->loopNo, entry->celNo);
int16 maxCelHeight = (maxScale * celHeight) >> 7;
reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object
@@ -215,120 +293,43 @@ void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view)
entry->scaleX = entry->scaleY;
// and set objects scale selectors
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), entry->scaleX);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), entry->scaleY);
+ writeSelectorValue(_s->_segMan, entry->object, SELECTOR(scaleX), entry->scaleX);
+ writeSelectorValue(_s->_segMan, entry->object, SELECTOR(scaleY), entry->scaleY);
}
-void GfxAnimate::fill(byte &old_picNotValid) {
- reg_t curObject;
- uint16 signal;
- GfxView *view = NULL;
- AnimateList::iterator it;
- const AnimateList::iterator end = _list.end();
-
- for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- // Get the corresponding view
- view = _cache->getView(it->viewId);
-
- // adjust loop and cel, if any of those is invalid
- // this seems to be completely crazy code
- // sierra sci checked signed int16 to be above or equal the counts and reseted to 0 in those cases
- // later during view processing those are compared unsigned again and then set to maximum count - 1
- // Games rely on this behaviour. For example laura bow 1 has a knight standing around in room 37
- // which has cel set to 3. This cel does not exist and the actual knight is 0
- // In kq5 on the other hand during the intro, when the trunk is opened, cel is set to some real
- // high number, which is negative when considered signed. This actually requires to get fixed to
- // maximum cel, otherwise the trunk would be closed.
- int16 viewLoopCount = view->getLoopCount();
- if (it->loopNo >= viewLoopCount) {
- it->loopNo = 0;
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), it->loopNo);
- } else if (it->loopNo < 0) {
- it->loopNo = viewLoopCount - 1;
- // not setting selector is right, sierra sci didn't do it during view processing as well
- }
- int16 viewCelCount = view->getCelCount(it->loopNo);
- if (it->celNo >= viewCelCount) {
- it->celNo = 0;
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), it->celNo);
- } else if (it->celNo < 0) {
- it->celNo = viewCelCount - 1;
- }
-
- if (!view->isScaleable()) {
- // Laura Bow 2 (especially floppy) depends on this, some views are not supposed to be scaleable
- // this "feature" was removed in later versions of SCI1.1
- it->scaleSignal = 0;
- it->scaleY = it->scaleX = 128;
- } else {
- // Process global scaling, if needed
- if (it->scaleSignal & kScaleSignalDoScaling) {
- if (it->scaleSignal & kScaleSignalGlobalScaling) {
- applyGlobalScaling(it, view);
- }
- }
- }
-
- //warning("%s view %d, loop %d, cel %d, signal %x", _s->_segMan->getObjectName(curObject), it->viewId, it->loopNo, it->celNo, it->signal);
+void GfxAnimate::setNsRect(GfxView *view, AnimateList::iterator it) {
+ bool shouldSetNsRect = true;
- bool setNsRect = true;
-
- // Create rect according to coordinates and given cel
- if (it->scaleSignal & kScaleSignalDoScaling) {
- view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect);
- // when being scaled, only set nsRect, if object will get drawn
- if ((signal & kSignalHidden) && !(signal & kSignalAlwaysUpdate))
- setNsRect = false;
+ // Create rect according to coordinates and given cel
+ if (it->scaleSignal & kScaleSignalDoScaling) {
+ view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect);
+ // when being scaled, only set nsRect, if object will get drawn
+ if ((it->signal & kSignalHidden) && !(it->signal & kSignalAlwaysUpdate))
+ shouldSetNsRect = false;
+ } else {
+ // This special handling is not included in the other SCI1.1 interpreters and MUST NOT be
+ // checked in those cases, otherwise we will break games (e.g. EcoQuest 2, room 200)
+ if ((g_sci->getGameId() == GID_HOYLE4) && (it->scaleSignal & kScaleSignalHoyle4SpecialHandling)) {
+ it->celRect.left = readSelectorValue(_s->_segMan, it->object, SELECTOR(nsLeft));
+ it->celRect.top = readSelectorValue(_s->_segMan, it->object, SELECTOR(nsTop));
+ it->celRect.right = readSelectorValue(_s->_segMan, it->object, SELECTOR(nsRight));
+ it->celRect.bottom = readSelectorValue(_s->_segMan, it->object, SELECTOR(nsBottom));
+ view->getCelSpecialHoyle4Rect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
+ shouldSetNsRect = false;
} else {
- // This special handling is not included in the other SCI1.1 interpreters and MUST NOT be
- // checked in those cases, otherwise we will break games (e.g. EcoQuest 2, room 200)
- if ((g_sci->getGameId() == GID_HOYLE4) && (it->scaleSignal & kScaleSignalHoyle4SpecialHandling)) {
- it->celRect.left = readSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft));
- it->celRect.top = readSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop));
- it->celRect.right = readSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight));
- it->celRect.bottom = readSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom));
- view->getCelSpecialHoyle4Rect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
- setNsRect = false;
- } else {
- view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
- }
- }
-
- if (setNsRect) {
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), it->celRect.left);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), it->celRect.top);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), it->celRect.right);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom), it->celRect.bottom);
- }
-
- // Calculate current priority according to y-coordinate
- if (!(signal & kSignalFixedPriority)) {
- it->priority = _ports->kernelCoordinateToPriority(it->y);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), it->priority);
+ view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
}
+ }
- if (signal & kSignalNoUpdate) {
- if (signal & (kSignalForceUpdate | kSignalViewUpdated)
- || (signal & kSignalHidden && !(signal & kSignalRemoveView))
- || (!(signal & kSignalHidden) && signal & kSignalRemoveView)
- || (signal & kSignalAlwaysUpdate))
- old_picNotValid++;
- signal &= ~kSignalStopUpdate;
- } else {
- if (signal & kSignalStopUpdate || signal & kSignalAlwaysUpdate)
- old_picNotValid++;
- signal &= ~kSignalForceUpdate;
- }
- it->signal = signal;
+ if (shouldSetNsRect) {
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(nsLeft), it->celRect.left);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(nsTop), it->celRect.top);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(nsRight), it->celRect.right);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(nsBottom), it->celRect.bottom);
}
}
void GfxAnimate::update() {
- reg_t curObject;
- uint16 signal;
reg_t bitsHandle;
Common::Rect rect;
AnimateList::iterator it;
@@ -336,81 +337,66 @@ void GfxAnimate::update() {
// Remove all no-update cels, if requested
for (it = _list.reverse_begin(); it != end; --it) {
- curObject = it->object;
- signal = it->signal;
-
- if (signal & kSignalNoUpdate) {
- if (!(signal & kSignalRemoveView)) {
- bitsHandle = readSelector(_s->_segMan, curObject, SELECTOR(underBits));
+ if (it->signal & kSignalNoUpdate) {
+ if (!(it->signal & kSignalRemoveView)) {
+ bitsHandle = readSelector(_s->_segMan, it->object, SELECTOR(underBits));
if (_screen->_picNotValid != 1) {
_paint16->bitsRestore(bitsHandle);
it->showBitsFlag = true;
} else {
_paint16->bitsFree(bitsHandle);
}
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(underBits), 0);
}
- signal &= ~kSignalForceUpdate;
- if (signal & kSignalViewUpdated)
- signal &= ~(kSignalViewUpdated | kSignalNoUpdate);
- } else if (signal & kSignalStopUpdate) {
- signal &= ~kSignalStopUpdate;
- signal |= kSignalNoUpdate;
+ it->signal &= ~kSignalForceUpdate;
+ if (it->signal & kSignalViewUpdated)
+ it->signal &= ~(kSignalViewUpdated | kSignalNoUpdate);
+ } else if (it->signal & kSignalStopUpdate) {
+ it->signal &= ~kSignalStopUpdate;
+ it->signal |= kSignalNoUpdate;
}
- it->signal = signal;
}
// Draw always-update cels
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (signal & kSignalAlwaysUpdate) {
+ if (it->signal & kSignalAlwaysUpdate) {
// draw corresponding cel
_paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
it->showBitsFlag = true;
- signal &= ~(kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate);
- if ((signal & kSignalIgnoreActor) == 0) {
+ it->signal &= ~(kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate);
+ if (!(it->signal & kSignalIgnoreActor)) {
rect = it->celRect;
rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1);
_paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
}
- it->signal = signal;
}
}
// Saving background for all NoUpdate-cels
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (signal & kSignalNoUpdate) {
- if (signal & kSignalHidden) {
- signal |= kSignalRemoveView;
+ if (it->signal & kSignalNoUpdate) {
+ if (it->signal & kSignalHidden) {
+ it->signal |= kSignalRemoveView;
} else {
- signal &= ~kSignalRemoveView;
- if (signal & kSignalIgnoreActor)
+ it->signal &= ~kSignalRemoveView;
+ if (it->signal & kSignalIgnoreActor)
bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY);
else
bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL);
- writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle);
+ writeSelector(_s->_segMan, it->object, SELECTOR(underBits), bitsHandle);
}
- it->signal = signal;
}
}
// Draw NoUpdate cels
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (signal & kSignalNoUpdate && !(signal & kSignalHidden)) {
+ if (it->signal & kSignalNoUpdate && !(it->signal & kSignalHidden)) {
// draw corresponding cel
_paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
it->showBitsFlag = true;
- if (!(signal & kSignalIgnoreActor)) {
+ if (!(it->signal & kSignalIgnoreActor)) {
rect = it->celRect;
rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1);
_paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
@@ -420,30 +406,23 @@ void GfxAnimate::update() {
}
void GfxAnimate::drawCels() {
- reg_t curObject;
- uint16 signal;
reg_t bitsHandle;
AnimateList::iterator it;
const AnimateList::iterator end = _list.end();
_lastCastData.clear();
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (!(signal & (kSignalNoUpdate | kSignalHidden | kSignalAlwaysUpdate))) {
+ if (!(it->signal & (kSignalNoUpdate | kSignalHidden | kSignalAlwaysUpdate))) {
// Save background
bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL);
- writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle);
+ writeSelector(_s->_segMan, it->object, SELECTOR(underBits), bitsHandle);
// draw corresponding cel
_paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
it->showBitsFlag = true;
- if (signal & kSignalRemoveView) {
- signal &= ~kSignalRemoveView;
- }
- it->signal = signal;
+ if (it->signal & kSignalRemoveView)
+ it->signal &= ~kSignalRemoveView;
// Remember that entry in lastCast
_lastCastData.push_back(*it);
@@ -452,23 +431,18 @@ void GfxAnimate::drawCels() {
}
void GfxAnimate::updateScreen(byte oldPicNotValid) {
- reg_t curObject;
- uint16 signal;
AnimateList::iterator it;
const AnimateList::iterator end = _list.end();
Common::Rect lsRect;
Common::Rect workerRect;
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
- if (it->showBitsFlag || !(signal & (kSignalRemoveView | kSignalNoUpdate) ||
- (!(signal & kSignalRemoveView) && (signal & kSignalNoUpdate) && oldPicNotValid))) {
- lsRect.left = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft));
- lsRect.top = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop));
- lsRect.right = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight));
- lsRect.bottom = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom));
+ if (it->showBitsFlag || !(it->signal & (kSignalRemoveView | kSignalNoUpdate) ||
+ (!(it->signal & kSignalRemoveView) && (it->signal & kSignalNoUpdate) && oldPicNotValid))) {
+ lsRect.left = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsLeft));
+ lsRect.top = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsTop));
+ lsRect.right = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsRight));
+ lsRect.bottom = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsBottom));
workerRect = lsRect;
workerRect.clip(it->celRect);
@@ -480,17 +454,16 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) {
_paint16->bitsShow(lsRect);
workerRect = it->celRect;
}
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), it->celRect.left);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), it->celRect.top);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), it->celRect.right);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), it->celRect.bottom);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsLeft), it->celRect.left);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsTop), it->celRect.top);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsRight), it->celRect.right);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsBottom), it->celRect.bottom);
// may get used for debugging
//_paint16->frameRect(workerRect);
_paint16->bitsShow(workerRect);
- if (signal & kSignalHidden) {
+ if (it->signal & kSignalHidden)
it->signal |= kSignalRemoveView;
- }
}
}
// use this for debug purposes
@@ -498,37 +471,30 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) {
}
void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) {
- reg_t curObject;
- uint16 signal;
AnimateList::iterator it;
const AnimateList::iterator end = _list.end();
-
// This has to be done in a separate loop. At least in sq1 some .dispose
// modifies FIXEDLOOP flag in signal for another object. In that case we
// would overwrite the new signal with our version of the old signal.
for (it = _list.begin(); it != end; ++it) {
- curObject = it->object;
- signal = it->signal;
-
// Finally update signal
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(signal), signal);
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(signal), it->signal);
}
for (it = _list.reverse_begin(); it != end; --it) {
- curObject = it->object;
// We read out signal here again, this is not by accident but to ensure
// that we got an up-to-date signal
- signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal));
+ it->signal = readSelectorValue(_s->_segMan, it->object, SELECTOR(signal));
- if ((signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) {
- _paint16->bitsRestore(readSelector(_s->_segMan, curObject, SELECTOR(underBits)));
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0);
+ if ((it->signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) {
+ _paint16->bitsRestore(readSelector(_s->_segMan, it->object, SELECTOR(underBits)));
+ writeSelectorValue(_s->_segMan, it->object, SELECTOR(underBits), 0);
}
- if (signal & kSignalDisposeMe) {
+ if (it->signal & kSignalDisposeMe) {
// Call .delete_ method of that object
- invokeSelector(_s, curObject, SELECTOR(delete_), argc, argv, 0);
+ invokeSelector(_s, it->object, SELECTOR(delete_), argc, argv, 0);
}
}
}
@@ -591,7 +557,7 @@ void GfxAnimate::addToPicDrawCels() {
// draw corresponding cel
_paint16->drawCel(view, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
- if ((it->signal & kSignalIgnoreActor) == 0) {
+ if (!(it->signal & kSignalIgnoreActor)) {
it->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, it->celRect.top, it->celRect.bottom - 1);
_paint16->fillRect(it->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
}
@@ -665,10 +631,10 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
// beginUpdate()/endUpdate() were introduced SCI1.
// Calling those for SCI0 will work most of the time but breaks minor
// stuff like percentage bar of qfg1ega at the character skill screen.
- if (getSciVersion() >= SCI_VERSION_1_EGA)
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
_ports->beginUpdate(_ports->_picWind);
update();
- if (getSciVersion() >= SCI_VERSION_1_EGA)
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
_ports->endUpdate(_ports->_picWind);
}
@@ -687,6 +653,10 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
_ports->setPort(oldPort);
// Now trigger speed throttler
+ throttleSpeed();
+}
+
+void GfxAnimate::throttleSpeed() {
switch (_lastCastData.size()) {
case 0:
// No entries drawn -> no speed throttler triggering
@@ -759,4 +729,21 @@ void GfxAnimate::kernelAddToPicView(GuiResourceId viewId, int16 loopNo, int16 ce
addToPicSetPicNotValid();
}
+void GfxAnimate::printAnimateList(Console *con) {
+ AnimateList::iterator it;
+ const AnimateList::iterator end = _list.end();
+
+ for (it = _list.begin(); it != end; ++it) {
+ Script *scr = _s->_segMan->getScriptIfLoaded(it->object.segment);
+ int16 scriptNo = scr ? scr->getScriptNumber() : -1;
+
+ 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,
+ it->x, it->y, it->scaleX, it->scaleY, it->scaleSignal,
+ it->z, it->priority, it->showBitsFlag, it->signal);
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h
index 44ffdd53af..b2aadcbead 100644
--- a/engines/sci/graphics/animate.h
+++ b/engines/sci/graphics/animate.h
@@ -77,6 +77,7 @@ struct AnimateEntry {
typedef Common::List<AnimateEntry> AnimateList;
typedef Common::Array<AnimateEntry> AnimateArray;
+class Console;
class GfxCache;
class GfxCursor;
class GfxPorts;
@@ -105,6 +106,7 @@ public:
void reAnimate(Common::Rect rect);
void addToPicDrawCels();
void addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control);
+ void printAnimateList(Console *con);
virtual void kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv);
virtual void kernelAddToPicList(reg_t listReference, int argc, reg_t *argv);
@@ -115,6 +117,10 @@ private:
void addToPicSetPicNotValid();
void animateShowPic();
+ void throttleSpeed();
+ void adjustInvalidCels(GfxView *view, AnimateList::iterator it);
+ void processViewScaling(GfxView *view, AnimateList::iterator it);
+ void setNsRect(GfxView *view, AnimateList::iterator it);
EngineState *_s;
GfxCache *_cache;
diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp
index 5f6aef0153..db926f2962 100644
--- a/engines/sci/graphics/compare.cpp
+++ b/engines/sci/graphics/compare.cpp
@@ -81,23 +81,14 @@ reg_t GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect &
curObject = curNode->value;
if (curObject != checkObject) {
signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
- if ((signal & (kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate)) == 0) {
+ if (!(signal & (kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate))) {
curRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
curRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
curRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
curRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
// Check if curRect is within checkRect
- // TODO: This check is slightly odd, because it means that a rect is not contained
- // in itself. It may very well be that the original SCI engine did it just
- // this way, so it should not be changed lightly. However, somebody should
- // confirm whether the original engine really did it this way. Then, update
- // this comment accordingly, and, if necessary, fix the code.
- if (curRect.right > checkRect.left &&
- curRect.left < checkRect.right &&
- curRect.bottom > checkRect.top &&
- curRect.top < checkRect.bottom) {
+ if (checkRect.contains(curRect))
return curObject;
- }
}
}
curAddress = curNode->succ;
@@ -134,7 +125,7 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
#ifdef ENABLE_SCI32
if (view->isSci2Hires())
- _screen->adjustToUpscaledCoordinates(y, x);
+ view->adjustToUpscaledCoordinates(y, x);
else if (getSciVersion() == SCI_VERSION_2_1)
_coordAdjuster->fromScriptToDisplay(y, x);
#endif
@@ -143,8 +134,8 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
#ifdef ENABLE_SCI32
if (view->isSci2Hires()) {
- _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
- _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
+ view->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
+ view->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
} else if (getSciVersion() == SCI_VERSION_2_1) {
_coordAdjuster->fromDisplayToScript(celRect.top, celRect.left);
_coordAdjuster->fromDisplayToScript(celRect.bottom, celRect.right);
@@ -232,13 +223,13 @@ void GfxCompare::kernelBaseSetter(reg_t object) {
celRect.bottom = readSelectorValue(_segMan, object, SELECTOR(nsBottom));
} else {
if (tmpView->isSci2Hires())
- _screen->adjustToUpscaledCoordinates(y, x);
+ tmpView->adjustToUpscaledCoordinates(y, x);
tmpView->getCelRect(loopNo, celNo, x, y, z, celRect);
if (tmpView->isSci2Hires()) {
- _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
- _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
+ tmpView->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
+ tmpView->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
}
}
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp
index b085654d02..3b95a5c955 100644
--- a/engines/sci/graphics/cursor.cpp
+++ b/engines/sci/graphics/cursor.cpp
@@ -26,6 +26,7 @@
#include "common/config-manager.h"
#include "common/events.h"
#include "common/macresman.h"
+#include "common/memstream.h"
#include "common/system.h"
#include "common/util.h"
#include "graphics/cursorman.h"
@@ -38,6 +39,7 @@
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/view.h"
#include "sci/graphics/cursor.h"
+#include "sci/graphics/maciconbar.h"
namespace Sci {
@@ -434,9 +436,17 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
if (_macCursorRemap.empty()) {
// QFG1/Freddy/Hoyle4 use a straight viewNum->cursor ID mapping
- // KQ6 seems to use this mapping for its cursors
- if (g_sci->getGameId() == GID_KQ6)
- viewNum = loopNum * 1000 + celNum;
+ // KQ6 uses this mapping for its cursors
+ if (g_sci->getGameId() == GID_KQ6) {
+ if (viewNum == 990) // Inventory Cursors
+ viewNum = loopNum * 16 + celNum + 2000;
+ else if (viewNum == 998) // Regular Cursors
+ viewNum = celNum + 1000;
+ else // Unknown cursor, ignored
+ return;
+ }
+ if (g_sci->hasMacIconBar())
+ g_sci->_gfxMacIconBar->setInventoryIcon(viewNum);
} else {
// If we do have the list, we'll be using a remap based on what the
// scripts have given us.
@@ -485,8 +495,8 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
cursorBitmap[i * 8 + b] = 0; // Doesn't matter, just is transparent
}
- uint16 hotspotX = READ_BE_UINT16(data);
- uint16 hotspotY = READ_BE_UINT16(data + 2);
+ uint16 hotspotY = READ_BE_UINT16(data);
+ uint16 hotspotX = READ_BE_UINT16(data + 2);
static const byte cursorPalette[] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff };
@@ -498,11 +508,12 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
// Mac crsr cursor
byte *cursorBitmap, *palette;
int width, height, hotspotX, hotspotY, palSize, keycolor;
- Common::MacResManager::convertCrsrCursor(resource->data, resource->size, &cursorBitmap, &width, &height, &hotspotX, &hotspotY, &keycolor, true, &palette, &palSize);
+ Common::MemoryReadStream resStream(resource->data, resource->size);
+ Common::MacResManager::convertCrsrCursor(&resStream, &cursorBitmap, width, height, hotspotX, hotspotY, keycolor, true, &palette, palSize);
CursorMan.replaceCursor(cursorBitmap, width, height, hotspotX, hotspotY, keycolor);
CursorMan.replaceCursorPalette(palette, 0, palSize);
- free(cursorBitmap);
- free(palette);
+ delete[] cursorBitmap;
+ delete[] palette;
}
kernelShow();
diff --git a/engines/sci/graphics/fontsjis.h b/engines/sci/graphics/fontsjis.h
index 684e6cac5e..5538b5c2c5 100644
--- a/engines/sci/graphics/fontsjis.h
+++ b/engines/sci/graphics/fontsjis.h
@@ -29,7 +29,7 @@
#include "sci/graphics/helpers.h"
namespace Graphics {
- class FontSJIS;
+class FontSJIS;
}
namespace Sci {
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index ab4a2c9c1a..7fafe843fd 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -23,9 +23,15 @@
*
*/
-#include "common/util.h"
-#include "common/stack.h"
-#include "graphics/primitives.h"
+#include "common/algorithm.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/list_intern.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "engines/engine.h"
+#include "graphics/surface.h"
#include "sci/sci.h"
#include "sci/engine/kernel.h"
@@ -83,10 +89,12 @@ void GfxFrameout::kernelAddPlane(reg_t object) {
}
newPlane.object = object;
- newPlane.pictureId = 0xFFFF;
newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority));
newPlane.lastPriority = 0xFFFF; // hidden
newPlane.planeOffsetX = 0;
+ newPlane.pictureId = 0xFFFF;
+ newPlane.planePictureMirrored = false;
+ newPlane.planeBack = 0;
_planes.push_back(newPlane);
kernelUpdatePlane(object);
@@ -123,7 +131,10 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) {
if (it->planeRect.left < 0) {
it->planeOffsetX = -it->planeRect.left;
it->planeRect.left = 0;
+ } else {
+ it->planeOffsetX = 0;
}
+
if (it->planeRect.top < 0)
it->planeRect.top = 0;
// We get bad plane-bottom in sq6
@@ -337,6 +348,8 @@ static int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font) {
maxChars = curCharCount; // return count up to (but not including) breaking space
break;
}
+ if (width + font->getCharWidth(curChar) > maxWidth)
+ break;
width += font->getCharWidth(curChar);
curCharCount++;
}
@@ -485,8 +498,8 @@ void GfxFrameout::kernelFrameout() {
if (view->isSci2Hires()) {
int16 dummyX = 0;
- _screen->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
- _screen->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
+ view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
+ view->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
} else if (getSciVersion() == SCI_VERSION_2_1) {
itemEntry->y = (itemEntry->y * _screen->getHeight()) / scriptsRunningHeight;
itemEntry->x = (itemEntry->x * _screen->getWidth()) / scriptsRunningWidth;
@@ -503,8 +516,8 @@ void GfxFrameout::kernelFrameout() {
itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom)) + 1;
itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight)) + 1;
if (view->isSci2Hires()) {
- _screen->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
- _screen->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
+ view->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
+ view->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
}
itemEntry->celRect.translate(itemEntry->x, itemEntry->y);
// TODO: maybe we should clip the cels rect with this, i'm not sure
@@ -520,8 +533,8 @@ void GfxFrameout::kernelFrameout() {
nsRect.translate(it->planeOffsetX, 0);
if (view->isSci2Hires()) {
- _screen->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
- _screen->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
+ view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
+ view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
} else if (getSciVersion() == SCI_VERSION_2_1) {
nsRect.top = (nsRect.top * scriptsRunningHeight) / _screen->getHeight();
nsRect.left = (nsRect.left * scriptsRunningWidth) / _screen->getWidth();
@@ -592,9 +605,9 @@ void GfxFrameout::kernelFrameout() {
const char *txt = text.c_str();
// HACK. The plane sometimes doesn't contain the correct width. This
// hack breaks the dialog options when speaking with Grace, but it's
- // the best we got up to now.
- // TODO: Remove this, and figure out why the plane in question isn't
- // initialized correctly (its width is 0).
+ // the best we got up to now. This happens because of the unimplemented
+ // kTextWidth function in SCI32.
+ // TODO: Remove this once kTextWidth has been implemented.
uint16 w = it->planeRect.width() >= 20 ? it->planeRect.width() : _screen->getWidth() - 10;
int16 charCount;
diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h
index f6cb214a2b..343f3c7e6e 100644
--- a/engines/sci/graphics/helpers.h
+++ b/engines/sci/graphics/helpers.h
@@ -45,6 +45,10 @@ typedef int GuiResourceId; // is a resource-number and -1 means no parameter giv
typedef int16 TextAlignment;
+#define PORTS_FIRSTWINDOWID 2
+#define PORTS_FIRSTSCRIPTWINDOWID 3
+
+
struct Port {
uint16 id;
int16 top, left;
@@ -62,6 +66,8 @@ struct Port {
fontHeight(0), fontId(0), greyedOutput(false),
penClr(0), backClr(0xFF), penMode(0), counterTillFree(0) {
}
+
+ bool isWindow() const { return id >= PORTS_FIRSTWINDOWID && id != 0xFFFF; }
};
struct Window : public Port, public Common::Serializable {
@@ -132,12 +138,14 @@ struct PalSchedule {
uint32 schedule;
};
+// Game view types, sorted by the number of colors
enum ViewType {
- kViewUnknown,
- kViewEga,
- kViewVga,
- kViewVga11,
- kViewAmiga
+ kViewUnknown, // uninitialized, or non-SCI
+ kViewEga, // EGA SCI0/SCI1 and Amiga SCI0/SCI1 ECS 16 colors
+ kViewAmiga, // Amiga SCI1 ECS 32 colors
+ kViewAmiga64, // Amiga SCI1 AGA 64 colors (i.e. Longbow)
+ kViewVga, // VGA SCI1 256 colors
+ kViewVga11 // VGA SCI1.1 and newer 256 colors
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index ea44db654b..6cf4f269a7 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -27,6 +27,7 @@
#include "sci/engine/kernel.h"
#include "sci/engine/selector.h"
#include "sci/engine/state.h"
+#include "sci/event.h"
#include "sci/graphics/maciconbar.h"
#include "sci/graphics/palette.h"
#include "sci/graphics/screen.h"
@@ -40,9 +41,22 @@ namespace Sci {
GfxMacIconBar::GfxMacIconBar() {
_lastX = 0;
+
+ if (g_sci->getGameId() == GID_FREDDYPHARKAS)
+ _inventoryIndex = 5;
+ else
+ _inventoryIndex = 4;
+
+ _inventoryIcon = 0;
+ _allDisabled = true;
}
GfxMacIconBar::~GfxMacIconBar() {
+ if (_inventoryIcon) {
+ _inventoryIcon->free();
+ delete _inventoryIcon;
+ }
+
for (uint32 i = 0; i < _iconBarItems.size(); i++) {
if (_iconBarItems[i].nonSelectedImage) {
_iconBarItems[i].nonSelectedImage->free();
@@ -62,7 +76,12 @@ void GfxMacIconBar::addIcon(reg_t obj) {
item.object = obj;
item.nonSelectedImage = createImage(iconIndex, false);
- item.selectedImage = createImage(iconIndex, true);
+
+ if (iconIndex != _inventoryIndex)
+ item.selectedImage = createImage(iconIndex, true);
+ else
+ item.selectedImage = 0;
+
item.enabled = true;
// Start after the main viewing window and add a two pixel buffer
@@ -82,17 +101,33 @@ void GfxMacIconBar::drawIcons() {
// Draw the icons to the bottom of the screen
for (uint32 i = 0; i < _iconBarItems.size(); i++)
- redrawIcon(i);
+ drawIcon(i, false);
}
-void GfxMacIconBar::redrawIcon(uint16 iconIndex) {
+void GfxMacIconBar::drawIcon(uint16 iconIndex, bool selected) {
if (iconIndex >= _iconBarItems.size())
return;
- if (_iconBarItems[iconIndex].enabled)
- drawEnabledImage(_iconBarItems[iconIndex].nonSelectedImage, _iconBarItems[iconIndex].rect);
- else
- drawDisabledImage(_iconBarItems[iconIndex].nonSelectedImage, _iconBarItems[iconIndex].rect);
+ Common::Rect rect = _iconBarItems[iconIndex].rect;
+
+ if (isIconEnabled(iconIndex)) {
+ if (selected)
+ drawEnabledImage(_iconBarItems[iconIndex].selectedImage, rect);
+ else
+ drawEnabledImage(_iconBarItems[iconIndex].nonSelectedImage, rect);
+ } else
+ drawDisabledImage(_iconBarItems[iconIndex].nonSelectedImage, rect);
+
+ if ((iconIndex == _inventoryIndex) && _inventoryIcon) {
+ Common::Rect invRect = Common::Rect(0, 0, _inventoryIcon->w, _inventoryIcon->h);
+ invRect.moveTo(rect.left, rect.top);
+ invRect.translate((rect.width() - invRect.width()) / 2, (rect.height() - invRect.height()) / 2);
+
+ if (isIconEnabled(iconIndex))
+ drawEnabledImage(_inventoryIcon, invRect);
+ else
+ drawDisabledImage(_inventoryIcon, invRect);
+ }
}
void GfxMacIconBar::drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect) {
@@ -110,10 +145,12 @@ void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::
newSurf.copyFrom(*surface);
for (int i = 0; i < newSurf.h; i++) {
- int startX = rect.left & 3;
+ // Start at the next four byte boundary
+ int startX = 3 - ((rect.left + 3) & 3);
+ // Start odd rows at two bytes past that (also properly aligned)
if ((i + rect.top) & 1)
- startX += 2;
+ startX = (startX + 2) & 3;
for (int j = startX; j < newSurf.w; j += 4)
*((byte *)newSurf.getBasePtr(j, i)) = 0;
@@ -126,30 +163,49 @@ void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::
void GfxMacIconBar::drawSelectedImage(uint16 iconIndex) {
assert(iconIndex <= _iconBarItems.size());
- // TODO
+ drawEnabledImage(_iconBarItems[iconIndex].selectedImage, _iconBarItems[iconIndex].rect);
}
bool GfxMacIconBar::isIconEnabled(uint16 iconIndex) const {
if (iconIndex >= _iconBarItems.size())
return false;
- return _iconBarItems[iconIndex].enabled;
+ return !_allDisabled && _iconBarItems[iconIndex].enabled;
}
-void GfxMacIconBar::setIconEnabled(uint16 iconIndex, bool enabled) {
- if (iconIndex == 0xffff) {
- for (uint32 i = 0; i < _iconBarItems.size(); i++)
- _iconBarItems[i].enabled = enabled;
- } else if (iconIndex < _iconBarItems.size()) {
+void GfxMacIconBar::setIconEnabled(int16 iconIndex, bool enabled) {
+ if (iconIndex < 0)
+ _allDisabled = !enabled;
+ else if (iconIndex < (int)_iconBarItems.size()) {
_iconBarItems[iconIndex].enabled = enabled;
}
}
-Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected) {
- Graphics::PictDecoder pictDecoder(Graphics::PixelFormat::createFormatCLUT8());
- ResourceType type = isSelected ? kResourceTypeMacIconBarPictS : kResourceTypeMacIconBarPictN;
+void GfxMacIconBar::setInventoryIcon(int16 icon) {
+ Graphics::Surface *surface = 0;
+
+ if (icon >= 0)
+ surface = loadPict(ResourceId(kResourceTypeMacPict, icon));
+
+ if (_inventoryIcon) {
+ // Free old inventory icon if we're removing the inventory icon
+ // or setting a new one.
+ if ((icon < 0) || surface) {
+ _inventoryIcon->free();
+ delete _inventoryIcon;
+ _inventoryIcon = 0;
+ }
+ }
- Resource *res = g_sci->getResMan()->findResource(ResourceId(type, iconIndex + 1), false);
+ if (surface)
+ _inventoryIcon = surface;
+
+ drawIcon(_inventoryIndex, false);
+}
+
+Graphics::Surface *GfxMacIconBar::loadPict(ResourceId id) {
+ Graphics::PictDecoder pictDecoder(Graphics::PixelFormat::createFormatCLUT8());
+ Resource *res = g_sci->getResMan()->findResource(id, false);
if (!res || res->size == 0)
return 0;
@@ -163,6 +219,11 @@ Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected)
return surface;
}
+Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected) {
+ ResourceType type = isSelected ? kResourceTypeMacIconBarPictS : kResourceTypeMacIconBarPictN;
+ return loadPict(ResourceId(type, iconIndex + 1));
+}
+
void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
byte *pixels = (byte *)surf->pixels;
@@ -178,4 +239,59 @@ void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
}
}
+bool GfxMacIconBar::pointOnIcon(uint32 iconIndex, Common::Point point) {
+ return _iconBarItems[iconIndex].rect.contains(point);
+}
+
+reg_t GfxMacIconBar::handleEvents() {
+ // Peek event queue for a mouse button press
+ EventManager *evtMgr = g_sci->getEventManager();
+ SciEvent evt = evtMgr->getSciEvent(SCI_EVENT_MOUSE_PRESS | SCI_EVENT_PEEK);
+
+ // No mouse press found
+ if (evt.type == SCI_EVENT_NONE)
+ return NULL_REG;
+
+ // If the mouse is not over the icon bar, return
+ if (evt.mousePos.y < g_sci->_gfxScreen->getHeight())
+ return NULL_REG;
+
+ // Remove event from queue
+ evtMgr->getSciEvent(SCI_EVENT_MOUSE_PRESS);
+
+ // Mouse press on the icon bar, check the icon rectangles
+ uint iconNr;
+ for (iconNr = 0; iconNr < _iconBarItems.size(); iconNr++) {
+ if (pointOnIcon(iconNr, evt.mousePos) && isIconEnabled(iconNr))
+ break;
+ }
+
+ // Mouse press not on an icon
+ if (iconNr == _iconBarItems.size())
+ return NULL_REG;
+
+ drawIcon(iconNr, true);
+ bool isSelected = true;
+
+ // Wait for mouse release
+ while (evt.type != SCI_EVENT_MOUSE_RELEASE) {
+ // Mimic behavior of SSCI when moving mouse with button held down
+ if (isSelected != pointOnIcon(iconNr, evt.mousePos)) {
+ isSelected = !isSelected;
+ drawIcon(iconNr, isSelected);
+ }
+
+ evt = evtMgr->getSciEvent(SCI_EVENT_MOUSE_RELEASE);
+ g_system->delayMillis(10);
+ }
+
+ drawIcon(iconNr, false);
+
+ // If user moved away from the icon, we do nothing
+ if (pointOnIcon(iconNr, evt.mousePos))
+ return _iconBarItems[iconNr].object;
+
+ return NULL_REG;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/maciconbar.h b/engines/sci/graphics/maciconbar.h
index 0db9454eb7..72609d19ab 100644
--- a/engines/sci/graphics/maciconbar.h
+++ b/engines/sci/graphics/maciconbar.h
@@ -31,7 +31,7 @@
#include "sci/engine/vm.h"
namespace Graphics {
- struct Surface;
+struct Surface;
}
namespace Sci {
@@ -43,10 +43,9 @@ public:
void addIcon(reg_t obj);
void drawIcons();
- void redrawIcon(uint16 index);
- void drawSelectedImage(uint16 index);
- bool isIconEnabled(uint16 index) const;
- void setIconEnabled(uint16 index, bool enabled);
+ void setIconEnabled(int16 index, bool enabled);
+ void setInventoryIcon(int16 icon);
+ reg_t handleEvents();
private:
struct IconBarItem {
@@ -59,12 +58,20 @@ private:
Common::Array<IconBarItem> _iconBarItems;
uint32 _lastX;
+ uint16 _inventoryIndex;
+ Graphics::Surface *_inventoryIcon;
+ bool _allDisabled;
+ Graphics::Surface *loadPict(ResourceId id);
Graphics::Surface *createImage(uint32 iconIndex, bool isSelected);
void remapColors(Graphics::Surface *surf, byte *palette);
+ void drawIcon(uint16 index, bool selected);
+ void drawSelectedImage(uint16 index);
+ bool isIconEnabled(uint16 index) const;
void drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect);
void drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect);
+ bool pointOnIcon(uint32 iconIndex, Common::Point point);
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp
index 3b9119c52f..50ba77e832 100644
--- a/engines/sci/graphics/menu.cpp
+++ b/engines/sci/graphics/menu.cpp
@@ -399,12 +399,10 @@ void GfxMenu::calculateMenuAndItemWidth() {
reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
int16 eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type));
int16 keyPress, keyModifier;
- Common::Point mousePosition;
GuiMenuItemList::iterator itemIterator = _itemList.begin();
GuiMenuItemList::iterator itemEnd = _itemList.end();
GuiMenuItemEntry *itemEntry = NULL;
bool forceClaimed = false;
- EngineState *s;
switch (eventType) {
case SCI_EVENT_KEYBOARD:
@@ -438,8 +436,6 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
break;
case SCI_EVENT_SAID:
- // HACK: should be removed as soon as said() is cleaned up
- s = g_sci->getEngineState();
while (itemIterator != itemEnd) {
itemEntry = *itemIterator;
@@ -451,7 +447,7 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
continue;
}
- if (said(s, saidSpec, 0) != SAID_NO_MATCH)
+ if (said(saidSpec, 0) != SAID_NO_MATCH)
break;
}
itemIterator++;
@@ -460,15 +456,17 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
itemEntry = NULL;
break;
- case SCI_EVENT_MOUSE_PRESS:
- mousePosition = _cursor->getPosition();
+ case SCI_EVENT_MOUSE_PRESS: {
+ Common::Point mousePosition;
+ mousePosition.x = readSelectorValue(_segMan, eventObject, SELECTOR(x));
+ mousePosition.y = readSelectorValue(_segMan, eventObject, SELECTOR(y));
if (mousePosition.y < 10) {
interactiveStart(pauseSound);
itemEntry = interactiveWithMouse();
interactiveEnd(pauseSound);
forceClaimed = true;
}
- break;
+ } break;
}
if (!_menuSaveHandle.isNull()) {
@@ -718,7 +716,6 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
uint16 newItemId = _curItemId;
GuiMenuItemEntry *curItemEntry = findItem(_curMenuId, _curItemId);
GuiMenuItemEntry *newItemEntry = curItemEntry;
- Common::Point mousePosition;
// We don't 100% follow Sierra here: we select last item instead of
// selecting first item of first menu every time. Also sierra sci didn't
@@ -796,9 +793,9 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
}
break;
- case SCI_EVENT_MOUSE_PRESS:
- mousePosition = _cursor->getPosition();
- if (_cursor->getPosition().y < 10) {
+ case SCI_EVENT_MOUSE_PRESS: {
+ Common::Point mousePosition = curEvent.mousePos;
+ if (mousePosition.y < 10) {
// Somewhere on the menubar
newMenuId = mouseFindMenuSelection(mousePosition);
if (newMenuId) {
@@ -827,7 +824,8 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() {
}
newItemId = curItemEntry->id;
}
- break;
+ } break;
+
case SCI_EVENT_NONE:
g_sci->sleep(2500 / 1000);
break;
@@ -843,7 +841,6 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() {
SciEvent curEvent;
uint16 newMenuId = 0, newItemId = 0;
uint16 curMenuId = 0, curItemId = 0;
- Common::Point mousePosition = _cursor->getPosition();
bool firstMenuChange = true;
GuiMenuItemEntry *curItemEntry = NULL;
@@ -874,7 +871,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() {
}
// Find out where mouse is currently pointing to
- mousePosition = _cursor->getPosition();
+ Common::Point mousePosition = curEvent.mousePos;
if (mousePosition.y < 10) {
// Somewhere on the menubar
newMenuId = mouseFindMenuSelection(mousePosition);
@@ -914,6 +911,13 @@ void GfxMenu::kernelDrawStatus(const char *text, int16 colorPen, int16 colorBack
_ports->moveTo(0, 1);
_text16->DrawStatus(text);
_paint16->bitsShow(_ports->_menuBarRect);
+ // Also draw the line under the status bar. Normally, this is never drawn,
+ // but we need it to be drawn because Dr. Brain 1 Mac draws over it when
+ // it displays the icon bar. SSCI used negative rectangles to erase the
+ // area after drawing the icon bar, but this is a much cleaner way of
+ // achieving the same effect.
+ _paint16->fillRect(_ports->_menuLine, 1, 0);
+ _paint16->bitsShow(_ports->_menuLine);
_ports->setPort(oldPort);
}
diff --git a/engines/sci/graphics/paint.cpp b/engines/sci/graphics/paint.cpp
index 50b0534ba7..27a0bdfc44 100644
--- a/engines/sci/graphics/paint.cpp
+++ b/engines/sci/graphics/paint.cpp
@@ -23,8 +23,6 @@
*
*/
-#include "common/util.h"
-#include "common/stack.h"
#include "graphics/primitives.h"
#include "sci/sci.h"
@@ -43,9 +41,6 @@ GfxPaint::~GfxPaint() {
void GfxPaint::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) {
}
-void GfxPaint::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) {
-}
-
void GfxPaint::kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) {
}
diff --git a/engines/sci/graphics/paint.h b/engines/sci/graphics/paint.h
index 994bc4e5e9..a79e8993c2 100644
--- a/engines/sci/graphics/paint.h
+++ b/engines/sci/graphics/paint.h
@@ -36,7 +36,6 @@ public:
virtual ~GfxPaint();
virtual void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo);
- virtual void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle);
virtual void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control);
};
diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp
index 935dd4e62e..5172f7cdc0 100644
--- a/engines/sci/graphics/paint16.cpp
+++ b/engines/sci/graphics/paint16.cpp
@@ -23,11 +23,6 @@
*
*/
-#include "common/util.h"
-#include "common/stack.h"
-#include "common/system.h"
-#include "graphics/primitives.h"
-
#include "sci/sci.h"
#include "sci/engine/features.h"
#include "sci/engine/state.h"
@@ -159,8 +154,8 @@ void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 c
// adjust curPort to upscaled hires
clipRect = celRect;
curPortRect = _ports->_curPort->rect;
- _screen->adjustToUpscaledCoordinates(curPortRect.top, curPortRect.left);
- _screen->adjustToUpscaledCoordinates(curPortRect.bottom, curPortRect.right);
+ view->adjustToUpscaledCoordinates(curPortRect.top, curPortRect.left);
+ view->adjustToUpscaledCoordinates(curPortRect.bottom, curPortRect.right);
curPortRect.bottom++;
curPortRect.right++;
clipRect.clip(curPortRect);
@@ -170,7 +165,7 @@ void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 c
clipRectTranslated = clipRect;
if (!upscaledHiresHack) {
curPortPos.x = _ports->_curPort->left; curPortPos.y = _ports->_curPort->top;
- _screen->adjustToUpscaledCoordinates(curPortPos.y, curPortPos.x);
+ view->adjustToUpscaledCoordinates(curPortPos.y, curPortPos.x);
clipRectTranslated.top += curPortPos.y; clipRectTranslated.bottom += curPortPos.y;
clipRectTranslated.left += curPortPos.x; clipRectTranslated.right += curPortPos.x;
}
@@ -302,6 +297,11 @@ void GfxPaint16::bitsShow(const Common::Rect &rect) {
return;
_ports->offsetRect(workerRect);
+
+ // We adjust the left/right coordinates to even coordinates
+ workerRect.left &= 0xFFFE; // round down
+ workerRect.right = (workerRect.right + 1) & 0xFFFE; // round up
+
_screen->copyRectToScreen(workerRect);
}
@@ -360,7 +360,7 @@ void GfxPaint16::bitsRestore(reg_t memoryHandle) {
if (memoryPtr) {
_screen->bitsRestore(memoryPtr);
- _segMan->freeHunkEntry(memoryHandle);
+ bitsFree(memoryHandle);
}
}
}
@@ -472,6 +472,7 @@ void GfxPaint16::kernelGraphRedrawBox(Common::Rect rect) {
#define SCI_DISPLAY_RESTOREUNDER 108
#define SCI_DISPLAY_DUMMY1 114 // used in longbow demo/qfg1 ega demo, not supported in sierra sci - no parameters
#define SCI_DISPLAY_DUMMY2 115 // used in longbow demo, not supported in sierra sci - has 1 parameter
+#define SCI_DISPLAY_DUMMY3 117 // used in qfg1 ega demo, not supported in sierra sci - no parameters
#define SCI_DISPLAY_DONTSHOWBITS 121
reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
@@ -532,20 +533,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
case SCI_DISPLAY_RESTOREUNDER:
bitsGetRect(argv[0], &rect);
rect.translate(-_ports->getPort()->left, -_ports->getPort()->top);
- if (g_sci->getGameId() == GID_PQ3 && g_sci->getEngineState()->currentRoomNumber() == 29) {
- // WORKAROUND: PQ3 calls this without calling the associated
- // kDisplay(SCI_DISPLAY_SAVEUNDER) call before. Theoretically,
- // this would result in no rect getting restored. However, we
- // still maintain a pointer from the previous room, resulting
- // in invalidated content being restored on screen, and causing
- // graphics glitches. Thus, we simply don't restore a rect in
- // that room. The correct fix for this would be to erase hunk
- // pointers when changing rooms, but this will suffice for now,
- // as restoring from a totally invalid pointer is very rare.
- // Fixes bug #3037945.
- } else {
- bitsRestore(argv[0]);
- }
+ bitsRestore(argv[0]);
kernelGraphRedrawBox(rect);
// finishing loop
argc = 0;
@@ -555,9 +543,10 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
break;
// 2 Dummy functions, longbow-demo is using those several times but sierra sci doesn't support them at all
- // The Quest for Glory 1 EGA demo also calls kDisplay(114)
+ // The Quest for Glory 1 EGA demo also calls kDisplay(114) and kDisplay(117)
case SCI_DISPLAY_DUMMY1:
case SCI_DISPLAY_DUMMY2:
+ case SCI_DISPLAY_DUMMY3:
if (!g_sci->isDemo() || (g_sci->getGameId() != GID_LONGBOW && g_sci->getGameId() != GID_QFG1))
error("Unknown kDisplay argument %d", displayArg.offset);
if (displayArg.offset == SCI_DISPLAY_DUMMY2) {
@@ -581,7 +570,10 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
// now drawing the text
_text16->Size(rect, text, -1, width);
rect.moveTo(_ports->getPort()->curLeft, _ports->getPort()->curTop);
- if (getSciVersion() >= SCI_VERSION_1_LATE) {
+ // Note: This code has been found in SCI1 middle and newer games. It was
+ // previously only for SCI1 late and newer, but the LSL1 interpreter contains
+ // this code.
+ if (getSciVersion() >= SCI_VERSION_1_MIDDLE) {
int16 leftPos = rect.right <= _screen->getWidth() ? 0 : _screen->getWidth() - rect.right;
int16 topPos = rect.bottom <= _screen->getHeight() ? 0 : _screen->getHeight() - rect.bottom;
_ports->move(leftPos, topPos);
diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h
index 4f709fd7c6..69ddf09ea6 100644
--- a/engines/sci/graphics/paint16.h
+++ b/engines/sci/graphics/paint16.h
@@ -36,7 +36,6 @@ class GfxPorts;
class GfxScreen;
class GfxPalette;
class Font;
-class SciGuiPicture;
class GfxView;
/**
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp
index aa3bf8dfb3..f277436631 100644
--- a/engines/sci/graphics/paint32.cpp
+++ b/engines/sci/graphics/paint32.cpp
@@ -23,11 +23,6 @@
*
*/
-#include "common/util.h"
-#include "common/stack.h"
-
-#include "graphics/primitives.h"
-
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
@@ -65,17 +60,6 @@ void GfxPaint32::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, b
delete picture;
}
-// This is "hacked" together, because its only used by debug command
-void GfxPaint32::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) {
- GfxView *view = _cache->getView(viewId);
- Common::Rect celRect(50, 50, 50, 50);
- Common::Rect translatedRect;
- celRect.bottom += view->getHeight(loopNo, celNo);
- celRect.right += view->getWidth(loopNo, celNo);
- view->draw(celRect, celRect, celRect, loopNo, celNo, 255, 0, false);
- _screen->copyRectToScreen(celRect);
-}
-
void GfxPaint32::kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) {
_screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control);
}
diff --git a/engines/sci/graphics/paint32.h b/engines/sci/graphics/paint32.h
index 3fa9d11d9b..e412bdf1c4 100644
--- a/engines/sci/graphics/paint32.h
+++ b/engines/sci/graphics/paint32.h
@@ -45,7 +45,6 @@ public:
void fillRect(Common::Rect rect, byte color);
void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo);
- void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle);
void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control);
private:
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index 534890315c..42551e9369 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -28,6 +28,8 @@
#include "common/util.h"
#include "common/system.h"
+#include "graphics/palette.h"
+
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/graphics/cache.h"
@@ -76,6 +78,24 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMergi
#ifdef ENABLE_SCI32
_clutTable = 0;
#endif
+
+ switch (_resMan->getViewType()) {
+ case kViewEga:
+ _totalScreenColors = 16;
+ break;
+ case kViewAmiga:
+ _totalScreenColors = 32;
+ break;
+ case kViewAmiga64:
+ _totalScreenColors = 64;
+ break;
+ case kViewVga:
+ case kViewVga11:
+ _totalScreenColors = 256;
+ break;
+ default:
+ error("GfxPalette: Unknown view type");
+ }
}
GfxPalette::~GfxPalette() {
@@ -97,7 +117,7 @@ bool GfxPalette::isMerging() {
void GfxPalette::setDefault() {
if (_resMan->getViewType() == kViewEga)
setEGA();
- else if (_resMan->isAmiga32color())
+ else if (_resMan->getViewType() == kViewAmiga)
setAmiga();
else
kernelSetFromResource(999, true);
@@ -418,10 +438,6 @@ void GfxPalette::getSys(Palette *pal) {
}
void GfxPalette::setOnScreen() {
- // We dont change palette at all times for amiga
- if (_resMan->isAmiga32color())
- return;
-
copySysPaletteToScreen();
}
@@ -847,24 +863,28 @@ void GfxPalette::palVaryProcess(int signal, bool setPalette) {
}
}
+static inline uint getMacColorDiff(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) {
+ // Use the difference of the top 4 bits and add together the differences
+ return ABS((r2 & 0xf0) - (r1 & 0xf0)) + ABS((g2 & 0xf0) - (g1 & 0xf0)) + ABS((b2 & 0xf0) - (b1 & 0xf0));
+}
+
byte GfxPalette::findMacIconBarColor(byte r, byte g, byte b) {
// Find the best color for use with the Mac icon bar
+ // Check white, then the palette colors, and then black
- // For black, always use 0
- if (r == 0 && g == 0 && b == 0)
- return 0;
+ // Try white first
+ byte found = 0xff;
+ uint diff = getMacColorDiff(r, g, b, 0xff, 0xff, 0xff);
- byte found = 0xFF;
- uint diff = 0xFFFFFFFF;
+ if (diff == 0)
+ return found;
+ // Go through the main colors of the CLUT
for (uint16 i = 1; i < 255; i++) {
- int dr = _macClut[i * 3 ] - r;
- int dg = _macClut[i * 3 + 1] - g;
- int db = _macClut[i * 3 + 2] - b;
+ if (!colorIsFromMacClut(i))
+ continue;
- // Use the largest difference. This is what the Mac Palette Manager does.
- uint cdiff = MAX<int>(ABS(dr), ABS(dg));
- cdiff = MAX<int>(cdiff, ABS(db));
+ uint cdiff = getMacColorDiff(r, g, b, _macClut[i * 3], _macClut[i * 3 + 1], _macClut[i * 3 + 2]);
if (cdiff == 0)
return i;
@@ -874,6 +894,10 @@ byte GfxPalette::findMacIconBarColor(byte r, byte g, byte b) {
}
}
+ // Also check black here
+ if (getMacColorDiff(r, g, b, 0, 0, 0) < diff)
+ return 0;
+
return found;
}
@@ -881,7 +905,7 @@ void GfxPalette::loadMacIconBarPalette() {
if (!g_sci->hasMacIconBar())
return;
- Common::SeekableReadStream *clutStream = g_sci->getMacExecutable()->getResource(MKID_BE('clut'), 150);
+ Common::SeekableReadStream *clutStream = g_sci->getMacExecutable()->getResource(MKTAG('c','l','u','t'), 150);
if (!clutStream)
error("Could not find clut 150 for the Mac icon bar");
@@ -889,7 +913,9 @@ void GfxPalette::loadMacIconBarPalette() {
clutStream->readUint32BE(); // seed
clutStream->readUint16BE(); // flags
uint16 colorCount = clutStream->readUint16BE() + 1;
- _macClut = new byte[colorCount * 3];
+ assert(colorCount == 256);
+
+ _macClut = new byte[256 * 3];
for (uint16 i = 0; i < colorCount; i++) {
clutStream->readUint16BE();
@@ -898,6 +924,19 @@ void GfxPalette::loadMacIconBarPalette() {
_macClut[i * 3 + 2] = clutStream->readUint16BE() >> 8;
}
+ // Adjust bounds on the KQ6 palette
+ // We don't use all of it for the icon bar
+ if (g_sci->getGameId() == GID_KQ6)
+ memset(_macClut + 32 * 3, 0, (256 - 32) * 3);
+
+ // Force black/white
+ _macClut[0x00 * 3 ] = 0;
+ _macClut[0x00 * 3 + 1] = 0;
+ _macClut[0x00 * 3 + 2] = 0;
+ _macClut[0xff * 3 ] = 0xff;
+ _macClut[0xff * 3 + 1] = 0xff;
+ _macClut[0xff * 3 + 2] = 0xff;
+
delete clutStream;
}
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 317401ac1f..d2e5151d6a 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -54,6 +54,7 @@ public:
bool merge(Palette *pFrom, bool force, bool forceRealMerge);
uint16 matchColor(byte r, byte g, byte b);
void getSys(Palette *pal);
+ uint16 getTotalColorCount() const { return _totalScreenColors; }
void setOnScreen();
void copySysPaletteToScreen();
@@ -123,6 +124,7 @@ private:
uint16 _palVaryTicks;
int _palVaryPaused;
int _palVarySignal;
+ uint16 _totalScreenColors;
void loadMacIconBarPalette();
byte *_macClut;
diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index 7e71c1a258..82aae5399f 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -36,6 +36,8 @@
namespace Sci {
+//#define DEBUG_PICTURE_DRAW
+
GfxPicture::GfxPicture(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPorts *ports, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize)
: _resMan(resMan), _coordAdjuster(coordAdjuster), _ports(ports), _screen(screen), _palette(palette), _resourceId(resourceId), _EGAdrawingVisualize(EGAdrawingVisualize) {
assert(resourceId != -1);
@@ -222,19 +224,20 @@ void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictu
}
#endif
+extern void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCount, int rlePos, int literalPos, ViewType viewType, uint16 width, bool isMacSci11ViewData);
+
void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX) {
byte *celBitmap = NULL;
byte *ptr = NULL;
byte *headerPtr = inbuffer + headerPos;
byte *rlePtr = inbuffer + rlePos;
- byte *literalPtr = inbuffer + literalPos;
int16 displaceX, displaceY;
byte priority = _addToFlag ? _priority : 0;
byte clearColor;
bool compression = true;
- byte curByte, runLength;
+ byte curByte;
int16 y, lastY, x, leftX, rightX;
- int pixelNr, pixelCount;
+ int pixelCount;
uint16 width, height;
#ifdef ENABLE_SCI32
@@ -245,12 +248,11 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
height = READ_LE_UINT16(headerPtr + 2);
displaceX = (signed char)headerPtr[4];
displaceY = (unsigned char)headerPtr[5];
- if (_resourceType == SCI_PICTURE_TYPE_SCI11) {
+ if (_resourceType == SCI_PICTURE_TYPE_SCI11)
// SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
clearColor = _screen->getColorWhite();
- } else {
+ else
clearColor = headerPtr[6];
- }
#ifdef ENABLE_SCI32
} else {
width = READ_SCI11ENDIAN_UINT16(headerPtr + 0);
@@ -266,90 +268,37 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
if (displaceX || displaceY)
error("unsupported embedded cel-data in picture");
+ // We will unpack cel-data into a temporary buffer and then plot it to screen
+ // That needs to be done cause a mirrored picture may be requested
pixelCount = width * height;
celBitmap = new byte[pixelCount];
if (!celBitmap)
error("Unable to allocate temporary memory for picture drawing");
- if (compression) {
- // We will unpack cel-data into a temporary buffer and then plot it to screen
- // That needs to be done cause a mirrored picture may be requested
- memset(celBitmap, clearColor, pixelCount);
- pixelNr = 0;
- ptr = celBitmap;
- if (literalPos == 0) {
- // decompression for data that has only one stream (vecor embedded view data)
- switch (_resMan->getViewType()) {
- case kViewEga:
- while (pixelNr < pixelCount) {
- curByte = *rlePtr++;
- runLength = curByte >> 4;
- memset(ptr + pixelNr, curByte & 0x0F, MIN<uint16>(runLength, pixelCount - pixelNr));
- pixelNr += runLength;
- }
- break;
- case kViewVga:
- case kViewVga11:
- while (pixelNr < pixelCount) {
- curByte = *rlePtr++;
- runLength = curByte & 0x3F;
- switch (curByte & 0xC0) {
- case 0: // copy bytes as-is
- while (runLength-- && pixelNr < pixelCount)
- ptr[pixelNr++] = *rlePtr++;
- break;
- case 0x80: // fill with color
- memset(ptr + pixelNr, *rlePtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
- pixelNr += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNr += runLength;
- break;
- }
- }
- break;
- case kViewAmiga:
- while (pixelNr < pixelCount) {
- curByte = *rlePtr++;
- if (curByte & 0x07) { // fill with color
- runLength = curByte & 0x07;
- curByte = curByte >> 3;
- while (runLength-- && pixelNr < pixelCount) {
- ptr[pixelNr++] = curByte;
- }
- } else { // fill with transparent
- runLength = curByte >> 3;
- pixelNr += runLength;
- }
- }
- break;
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
+ // See GfxView::unpackCel() for why this black/white swap is done
+ // This picture swap is only needed in SCI32, not SCI1.1
+ if (clearColor == 0)
+ clearColor = 0xff;
+ else if (clearColor == 0xff)
+ clearColor = 0;
+ }
- default:
- error("Unsupported picture viewtype");
- }
- } else {
- // decompression for data that has two separate streams (probably SCI 1.1 picture)
- while (pixelNr < pixelCount) {
- curByte = *rlePtr++;
- runLength = curByte & 0x3F;
- switch (curByte & 0xC0) {
- case 0: // copy bytes as-is
- while (runLength-- && pixelNr < pixelCount)
- ptr[pixelNr++] = *literalPtr++;
- break;
- case 0x80: // fill with color
- memset(ptr + pixelNr, *literalPtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
- pixelNr += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNr += runLength;
- break;
- }
- }
- }
- } else {
+ if (compression)
+ unpackCelData(inbuffer, celBitmap, clearColor, pixelCount, rlePos, literalPos, _resMan->getViewType(), width, false);
+ else
// No compression (some SCI32 pictures)
memcpy(celBitmap, rlePtr, pixelCount);
+
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
+ // See GfxView::unpackCel() for why this black/white swap is done
+ // This picture swap is only needed in SCI32, not SCI1.1
+ for (int i = 0; i < pixelCount; i++) {
+ if (celBitmap[i] == 0)
+ celBitmap[i] = 0xff;
+ else if (celBitmap[i] == 0xff)
+ celBitmap[i] = 0;
+ }
}
Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
@@ -377,10 +326,11 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
sourcePixelSkipPerRow = width - (rightX - leftX);
// Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen
- // but white and that wont matter because the screen is supposed to be already white. It seems that most (if not all)
- // SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
- // the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra
- if (!_addToFlag)
+ // but white and that won't matter because the screen is supposed to be already white. It seems that most (if not all)
+ // SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
+ // the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra.
+ // SCI32 doesn't use _addToFlag at all.
+ if (!_addToFlag && _resourceType != SCI_PICTURE_TYPE_SCI32)
clearColor = _screen->getColorWhite();
byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY;
@@ -443,6 +393,7 @@ enum {
PIC_OP_OPX = 0xfe,
PIC_OP_TERMINATE = 0xff
};
+
#define PIC_OP_FIRST PIC_OP_SET_COLOR
enum {
@@ -465,6 +416,47 @@ enum {
PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT = 4
};
+#ifdef DEBUG_PICTURE_DRAW
+const char *picOpcodeNames[] = {
+ "Set color",
+ "Disable visual",
+ "Set priority",
+ "Disable priority",
+ "Short patterns",
+ "Medium lines",
+ "Long lines",
+ "Short lines",
+ "Fill",
+ "Set pattern",
+ "Absolute pattern",
+ "Set control",
+ "Disable control",
+ "Medium patterns",
+ "Extended opcode",
+ "Terminate"
+};
+
+const char *picExOpcodeNamesEGA[] = {
+ "Set palette entries",
+ "Set palette",
+ "Mono0",
+ "Mono1",
+ "Mono2",
+ "Mono3",
+ "Mono4",
+ "Embedded view",
+ "Set priority table"
+};
+
+const char *picExOpcodeNamesVGA[] = {
+ "Set palette entries",
+ "Embedded view",
+ "Set palette",
+ "Set priority table (eqdist)",
+ "Set priority table (explicit)"
+};
+#endif
+
#define PIC_EGAPALETTE_COUNT 4
#define PIC_EGAPALETTE_SIZE 40
#define PIC_EGAPALETTE_TOTALSIZE PIC_EGAPALETTE_COUNT*PIC_EGAPALETTE_SIZE
@@ -543,7 +535,9 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
// Drawing
while (curPos < dataSize) {
- //warning("%X at %d", data[curPos], curPos);
+#ifdef DEBUG_PICTURE_DRAW
+ debug("Picture op: %X (%s) at %d", data[curPos], picOpcodeNames[data[curPos] - 0xF0], curPos);
+#endif
switch (pic_op = data[curPos++]) {
case PIC_OP_SET_COLOR:
pic_color = data[curPos++];
@@ -681,6 +675,9 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
case PIC_OP_OPX: // Extended functions
if (isEGA) {
+#ifdef DEBUG_PICTURE_DRAW
+ debug("* Picture ex op: %X (%s) at %d", data[curPos], picExOpcodeNamesEGA[data[curPos]], curPos);
+#endif
switch (pic_op = data[curPos++]) {
case PIC_OPX_EGA_SET_PALETTE_ENTRIES:
while (vectorIsNonOpcode(data[curPos])) {
@@ -726,6 +723,9 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
error("Unsupported sci1 extended pic-operation %X", pic_op);
}
} else {
+#ifdef DEBUG_PICTURE_DRAW
+ debug("* Picture ex op: %X (%s) at %d", data[curPos], picExOpcodeNamesVGA[data[curPos]], curPos);
+#endif
switch (pic_op = data[curPos++]) {
case PIC_OPX_VGA_SET_PALETTE_ENTRIES:
while (vectorIsNonOpcode(data[curPos])) {
@@ -733,7 +733,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
}
break;
case PIC_OPX_VGA_SET_PALETTE:
- if (_resMan->isAmiga32color()) {
+ if (_resMan->getViewType() == kViewAmiga || _resMan->getViewType() == kViewAmiga64) {
if ((data[curPos] == 0x00) && (data[curPos + 1] == 0x01) && ((data[curPos + 32] & 0xF0) != 0xF0)) {
// Left-Over VGA palette, we simply ignore it
curPos += 256 + 4 + 1024;
@@ -780,7 +780,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
case GID_SQ3:
switch (_resourceId) {
case 154: // SQ3: intro, ship gets sucked in
- _screen->ditherForceMemorial(0xD0);
+ _screen->ditherForceDitheredColor(0xD0);
break;
default:
break;
@@ -866,6 +866,8 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
byte matchedMask, matchMask;
int16 w, e, a_set, b_set;
+ bool isEGA = (_resMan->getViewType() == kViewEga);
+
p.x = x + curPort->left;
p.y = y + curPort->top;
stack.push(p);
@@ -874,6 +876,18 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
byte searchPriority = _screen->getPriority(p.x, p.y);
byte searchControl = _screen->getControl(p.x, p.y);
+ if (isEGA) {
+ // In EGA games a pixel in the framebuffer is only 4 bits. We store
+ // a full byte per pixel to allow undithering, but when comparing
+ // pixels for flood-fill purposes, we should only compare the
+ // visible color of a pixel.
+
+ if ((x ^ y) & 1)
+ searchColor = (searchColor ^ (searchColor >> 4)) & 0x0F;
+ else
+ searchColor = searchColor & 0x0F;
+ }
+
// This logic was taken directly from sierra sci, floodfill will get aborted on various occations
if (screenMask & GFX_SCREEN_MASK_VISUAL) {
if ((color == _screen->getColorWhite()) || (searchColor != _screen->getColorWhite()))
@@ -913,20 +927,20 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
int b = curPort->rect.bottom + curPort->top - 1;
while (stack.size()) {
p = stack.pop();
- if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl)) == 0) // already filled
+ if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)) == 0) // already filled
continue;
_screen->putPixel(p.x, p.y, screenMask, color, priority, control);
w = p.x;
e = p.x;
// moving west and east pointers as long as there is a matching color to fill
- while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl)))
+ while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
_screen->putPixel(--w, p.y, screenMask, color, priority, control);
- while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl)))
+ while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
_screen->putPixel(++e, p.y, screenMask, color, priority, control);
// checking lines above and below for possible flood targets
a_set = b_set = 0;
while (w <= e) {
- if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl))) { // one line above
+ if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line above
if (a_set == 0) {
p1.x = w;
p1.y = p.y - 1;
@@ -936,7 +950,7 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
} else
a_set = 0;
- if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl))) { // one line below
+ if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line below
if (b_set == 0) {
p1.x = w;
p1.y = p.y + 1;
diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp
index 6e9df2f019..3f9ebaa07a 100644
--- a/engines/sci/graphics/portrait.cpp
+++ b/engines/sci/graphics/portrait.cpp
@@ -24,9 +24,7 @@
*/
#include "common/archive.h"
-#include "common/util.h"
-#include "common/stack.h"
-#include "graphics/primitives.h"
+#include "common/system.h"
#include "sci/sci.h"
#include "sci/event.h"
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index 57c76126c0..cc206bd5b9 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -25,8 +25,10 @@
#include "common/util.h"
+#include "sci/console.h"
#include "sci/sci.h"
#include "sci/engine/features.h"
+#include "sci/engine/gc.h"
#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
@@ -246,8 +248,10 @@ void GfxPorts::beginUpdate(Window *wnd) {
PortList::iterator it = _windowList.reverse_begin();
const PortList::iterator end = Common::find(_windowList.begin(), _windowList.end(), wnd);
while (it != end) {
- // FIXME: We also store Port objects in the window list.
- // We should add a check that we really only pass windows here...
+ // We also store Port objects in the window list, but they
+ // shouldn't be encountered during this iteration.
+ assert((*it)->isWindow());
+
updateWindow((Window *)*it);
--it;
}
@@ -263,11 +267,16 @@ void GfxPorts::endUpdate(Window *wnd) {
assert(it != end);
while (++it != end) {
- // FIXME: We also store Port objects in the window list.
- // We should add a check that we really only pass windows here...
+ // We also store Port objects in the window list, but they
+ // shouldn't be encountered during this iteration.
+ assert((*it)->isWindow());
+
updateWindow((Window *)*it);
}
+ if (getSciVersion() < SCI_VERSION_1_EGA_ONLY)
+ g_sci->_gfxPaint16->kernelGraphRedrawBox(_curPort->rect);
+
setPort(oldPort);
}
@@ -300,7 +309,14 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor
}
_windowsById[id] = pwnd;
- if (style & SCI_WINDOWMGR_STYLE_TOPMOST)
+
+ // KQ1sci, KQ4, iceman, QfG2 always add windows to the back of the list.
+ // KQ5CD checks style.
+ // Hoyle3-demo also always adds to the back (#3036763).
+ bool forceToBack = (getSciVersion() <= SCI_VERSION_1_EGA_ONLY) ||
+ (g_sci->getGameId() == GID_HOYLE3 && g_sci->isDemo());
+
+ if (!forceToBack && (style & SCI_WINDOWMGR_STYLE_TOPMOST))
_windowList.push_front(pwnd);
else
_windowList.push_back(pwnd);
@@ -311,7 +327,7 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor
// bit of the left dimension in their interpreter. It seems Sierra did it
// for EGA byte alignment (EGA uses 1 byte for 2 pixels) and left it in
// their interpreter even in the newer VGA games.
- r.left = r.left & 0x7FFE;
+ r.left = r.left & 0xFFFE;
if (r.width() > _screen->getWidth()) {
// We get invalid dimensions at least at the end of sq3 (script bug!).
@@ -347,25 +363,50 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor
}
pwnd->dims = r;
- const Common::Rect *wmprect = &_wmgrPort->rect;
+
+ // Clip window, if needed
+ Common::Rect wmprect = _wmgrPort->rect;
+ // Handle a special case for Dr. Brain 1 Mac. When hovering the mouse cursor
+ // over the status line on top, the game scripts try to draw the game's icon
+ // bar above the current port, by specifying a negative window top, so that
+ // the end result will be drawn 10 pixels above the current port. This is a
+ // hack by Sierra, and is only limited to user style windows. Normally, we
+ // should not clip, same as what Sierra does. However, this will result in
+ // having invalid rectangles with negative coordinates. For this reason, we
+ // adjust the containing rectangle instead.
+ if (pwnd->dims.top < 0 && g_sci->getPlatform() == Common::kPlatformMacintosh &&
+ (style & SCI_WINDOWMGR_STYLE_USER) && _wmgrPort->top + pwnd->dims.top >= 0) {
+ // Offset the final rect top by the requested pixels
+ wmprect.top += pwnd->dims.top;
+ }
+
int16 oldtop = pwnd->dims.top;
int16 oldleft = pwnd->dims.left;
- if (wmprect->top > pwnd->dims.top)
- pwnd->dims.moveTo(pwnd->dims.left, wmprect->top);
- if (wmprect->bottom < pwnd->dims.bottom)
- pwnd->dims.moveTo(pwnd->dims.left, wmprect->bottom - pwnd->dims.bottom + pwnd->dims.top);
+ if (wmprect.top > pwnd->dims.top)
+ pwnd->dims.moveTo(pwnd->dims.left, wmprect.top);
- if (wmprect->right < pwnd->dims.right)
- pwnd->dims.moveTo(wmprect->right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top);
+ if (wmprect.bottom < pwnd->dims.bottom)
+ pwnd->dims.moveTo(pwnd->dims.left, wmprect.bottom - pwnd->dims.bottom + pwnd->dims.top);
- if (wmprect->left > pwnd->dims.left)
- pwnd->dims.moveTo(wmprect->left, pwnd->dims.top);
+ if (wmprect.right < pwnd->dims.right)
+ pwnd->dims.moveTo(wmprect.right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top);
+
+ if (wmprect.left > pwnd->dims.left)
+ pwnd->dims.moveTo(wmprect.left, pwnd->dims.top);
pwnd->rect.moveTo(pwnd->rect.left + pwnd->dims.left - oldleft, pwnd->rect.top + pwnd->dims.top - oldtop);
+
if (restoreRect == 0)
pwnd->restoreRect = pwnd->dims;
+ if (pwnd->restoreRect.top < 0 && g_sci->getPlatform() == Common::kPlatformMacintosh &&
+ (style & SCI_WINDOWMGR_STYLE_USER) && _wmgrPort->top + pwnd->restoreRect.top >= 0) {
+ // Special case for Dr. Brain 1 Mac (check above), applied to the
+ // restore rectangle.
+ pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.top);
+ }
+
if (draw)
drawWindow(pwnd);
setPort((Port *)pwnd);
@@ -668,4 +709,26 @@ int16 GfxPorts::kernelPriorityToCoordinate(byte priority) {
return _priorityBottom;
}
+void GfxPorts::processEngineHunkList(WorklistManager &wm) {
+ for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) {
+ if ((*it)->isWindow()) {
+ Window *wnd = ((Window *)*it);
+ wm.push(wnd->hSaved1);
+ wm.push(wnd->hSaved2);
+ }
+ }
+}
+
+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",
+ 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);
+ }
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h
index 21c6d31ebd..31ed671daf 100644
--- a/engines/sci/graphics/ports.h
+++ b/engines/sci/graphics/ports.h
@@ -32,13 +32,10 @@
namespace Sci {
-class SciGui;
class GfxPaint16;
class GfxScreen;
class GfxText16;
-
-#define PORTS_FIRSTWINDOWID 2
-#define PORTS_FIRSTSCRIPTWINDOWID 3
+struct WorklistManager;
// window styles
enum {
@@ -49,6 +46,9 @@ enum {
SCI_WINDOWMGR_STYLE_USER = (1 << 7)
};
+typedef Common::List<Port *> PortList;
+typedef Common::Array<Port *> PortArray;
+
/**
* Ports class, includes all port managment for SCI0->SCI1.1 games. Ports are some sort of windows in SCI
* this class also handles adjusting coordinates to a specific port
@@ -103,6 +103,8 @@ public:
void kernelGraphAdjustPriority(int top, int bottom);
byte kernelCoordinateToPriority(int16 y);
int16 kernelPriorityToCoordinate(byte priority);
+ void processEngineHunkList(WorklistManager &wm);
+ void printWindowList(Console *con);
Port *_wmgrPort;
Window *_picWind;
@@ -116,7 +118,11 @@ public:
virtual void saveLoadWithSerializer(Common::Serializer &ser);
private:
- typedef Common::List<Port *> PortList;
+ /** The list of open 'windows' (and ports), in visual order. */
+ PortList _windowList;
+
+ /** The list of all open 'windows' (and ports), ordered by their id. */
+ PortArray _windowsById;
SegManager *_segMan;
GfxPaint16 *_paint16;
@@ -130,12 +136,6 @@ private:
// counts windows that got disposed but are not freed yet
uint16 _freeCounter;
- /** The list of open 'windows' (and ports), in visual order. */
- PortList _windowList;
-
- /** The list of all open 'windows' (and ports), ordered by their id. */
- Common::Array<Port *> _windowsById;
-
Common::Rect _bounds;
// Priority Bands related variables
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index b019853a2b..f619780c7c 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -32,6 +32,7 @@
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/graphics/screen.h"
+#include "sci/graphics/view.h"
namespace Sci {
@@ -113,7 +114,7 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_unditherState = true;
_fontIsUpscaled = false;
- if (_resMan->isVGA() || (_resMan->isAmiga32color())) {
+ if (_resMan->getViewType() != kViewEga) {
// It is not 100% accurate to set white to be 255 for Amiga 32-color
// games. But 255 is defined as white in our SCI at all times, so it
// doesn't matter.
@@ -156,12 +157,14 @@ void GfxScreen::copyToScreen() {
}
void GfxScreen::copyFromScreen(byte *buffer) {
+ // TODO this ignores the pitch
Graphics::Surface *screen = g_system->lockScreen();
memcpy(buffer, screen->pixels, _displayPixels);
g_system->unlockScreen();
}
void GfxScreen::kernelSyncWithFramebuffer() {
+ // TODO this ignores the pitch
Graphics::Surface *screen = g_system->lockScreen();
memcpy(_displayScreen, screen->pixels, _displayPixels);
g_system->unlockScreen();
@@ -353,12 +356,29 @@ byte GfxScreen::getControl(int x, int y) {
return _controlScreen[y * _width + x];
}
-byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con) {
+byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) {
int offset = y * _width + x;
byte match = 0;
- if ((screenMask & GFX_SCREEN_MASK_VISUAL) && *(_visualScreen + offset) == t_color)
- match |= GFX_SCREEN_MASK_VISUAL;
+ if (screenMask & GFX_SCREEN_MASK_VISUAL) {
+ if (!isEGA) {
+ if (*(_visualScreen + offset) == t_color)
+ match |= GFX_SCREEN_MASK_VISUAL;
+ } else {
+ // In EGA games a pixel in the framebuffer is only 4 bits. We store
+ // a full byte per pixel to allow undithering, but when comparing
+ // pixels for flood-fill purposes, we should only compare the
+ // visible color of a pixel.
+
+ byte c = *(_visualScreen + offset);
+ if ((x ^ y) & 1)
+ c = (c ^ (c >> 4)) & 0x0F;
+ else
+ c = c & 0x0F;
+ if (c == t_color)
+ match |= GFX_SCREEN_MASK_VISUAL;
+ }
+ }
if ((screenMask & GFX_SCREEN_MASK_PRIORITY) && *(_priorityScreen + offset) == t_pri)
match |= GFX_SCREEN_MASK_PRIORITY;
if ((screenMask & GFX_SCREEN_MASK_CONTROL) && *(_controlScreen + offset) == t_con)
@@ -565,7 +585,7 @@ void GfxScreen::dither(bool addToFlag) {
}
} else {
if (!addToFlag)
- memset(&_unditherMemorial, 0, sizeof(_unditherMemorial));
+ memset(&_ditheredPicColors, 0, sizeof(_ditheredPicColors));
// Do dithering on visual screen and put decoded but undithered byte onto display-screen
for (y = 0; y < _height; y++) {
for (x = 0; x < _width; x++) {
@@ -573,7 +593,7 @@ void GfxScreen::dither(bool addToFlag) {
if (color & 0xF0) {
color ^= color << 4;
// remember dither combination for cel-undithering
- _unditherMemorial[color]++;
+ _ditheredPicColors[color]++;
// if decoded color wants do dither with black on left side, we turn it around
// otherwise the normal ega color would get used for display
if (color & 0xF0) {
@@ -600,18 +620,17 @@ void GfxScreen::dither(bool addToFlag) {
}
}
-// Force a color combination into memorial
-void GfxScreen::ditherForceMemorial(byte color) {
- _unditherMemorial[color] = 256;
+void GfxScreen::ditherForceDitheredColor(byte color) {
+ _ditheredPicColors[color] = 256;
}
void GfxScreen::debugUnditherSetState(bool flag) {
_unditherState = flag;
}
-int16 *GfxScreen::unditherGetMemorial() {
+int16 *GfxScreen::unditherGetDitheredBgColors() {
if (_unditherState)
- return (int16 *)&_unditherMemorial;
+ return (int16 *)&_ditheredPicColors;
else
return NULL;
}
@@ -676,12 +695,39 @@ void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHei
}
}
-void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x) {
+struct UpScaledAdjust {
+ GfxScreenUpscaledMode gameHiresMode;
+ Sci32ViewNativeResolution viewNativeRes;
+ int numerator;
+ int denominator;
+};
+
+static const UpScaledAdjust s_upscaledAdjustTable[] = {
+ { GFX_SCREEN_UPSCALED_640x480, SCI_VIEW_NATIVERES_640x400, 5, 6 }
+};
+
+void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewNativeRes) {
x *= 2;
y = _upscaledMapping[y];
+
+ for (int i = 0; i < ARRAYSIZE(s_upscaledAdjustTable); i++) {
+ if (s_upscaledAdjustTable[i].gameHiresMode == _upscaledHires &&
+ s_upscaledAdjustTable[i].viewNativeRes == viewNativeRes) {
+ y = (y * s_upscaledAdjustTable[i].numerator) / s_upscaledAdjustTable[i].denominator;
+ break;
+ }
+ }
}
-void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x) {
+void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewNativeRes) {
+ for (int i = 0; i < ARRAYSIZE(s_upscaledAdjustTable); i++) {
+ if (s_upscaledAdjustTable[i].gameHiresMode == _upscaledHires &&
+ s_upscaledAdjustTable[i].viewNativeRes == viewNativeRes) {
+ y = (y * s_upscaledAdjustTable[i].denominator) / s_upscaledAdjustTable[i].numerator;
+ break;
+ }
+ }
+
switch (_upscaledHires) {
case GFX_SCREEN_UPSCALED_640x400:
x /= 2;
@@ -725,6 +771,7 @@ uint16 GfxScreen::getLowResScreenHeight() {
case GID_FREDDYPHARKAS:
case GID_KQ5:
case GID_KQ6:
+ case GID_SQ1:
return 190;
default:
break;
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index fc1f38ed41..89ad52e0ac 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -28,6 +28,7 @@
#include "sci/sci.h"
#include "sci/graphics/helpers.h"
+#include "sci/graphics/view.h"
#include "graphics/sjis.h"
@@ -51,7 +52,7 @@ enum GfxScreenMasks {
};
enum {
- SCI_SCREEN_UNDITHERMEMORIAL_SIZE = 256
+ DITHERED_BG_COLORS_SIZE = 256
};
/**
@@ -89,17 +90,20 @@ public:
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);
}
- int getUpscaledHires() const {
+
+ GfxScreenUpscaledMode getUpscaledHires() const {
return _upscaledHires;
}
+
bool getUnditherState() const {
return _unditherState;
}
+
void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color);
byte getVisual(int x, int y);
byte getPriority(int x, int y);
byte getControl(int x, int y);
- byte isFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con);
+ byte isFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con, bool isEGA);
int bitsGetDataSize(Common::Rect rect, byte mask);
void bitsSave(Common::Rect rect, byte mask, byte *memoryPtr);
@@ -108,13 +112,15 @@ public:
void scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight, byte bytesPerPixel = 1);
- void adjustToUpscaledCoordinates(int16 &y, int16 &x);
- void adjustBackUpscaledCoordinates(int16 &y, int16 &x);
+ void adjustToUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewScalingType = SCI_VIEW_NATIVERES_NONE);
+ void adjustBackUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewScalingType = SCI_VIEW_NATIVERES_NONE);
void dither(bool addToFlag);
- void ditherForceMemorial(byte color);
+
+ // Force a color combination as a dithered color
+ void ditherForceDitheredColor(byte color);
void debugUnditherSetState(bool flag);
- int16 *unditherGetMemorial();
+ int16 *unditherGetDitheredBgColors();
void debugShowMap(int mapNo);
@@ -146,7 +152,7 @@ private:
void setVerticalShakePos(uint16 shakePos);
bool _unditherState;
- int16 _unditherMemorial[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
+ int16 _ditheredPicColors[DITHERED_BG_COLORS_SIZE];
// These screens have the real resolution of the game engine (320x200 for
// SCI0/SCI1/SCI11 games, 640x480 for SCI2 games). SCI0 games will be
@@ -172,7 +178,7 @@ private:
// This variable defines, if upscaled hires is active and what upscaled mode
// is used.
- int _upscaledHires;
+ GfxScreenUpscaledMode _upscaledHires;
// This here holds a translation for vertical coordinates between native
// (visual) and actual (display) screen.
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index 21605ccb8e..6269a58492 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -204,19 +204,24 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF
maxChars = curCharCount; // return count up to (but not including) breaking space
break;
}
+ // Sometimes this can go off the screen, like for example bug #3040161.
+ // However, we only perform this for non-Japanese games, as these require
+ // special handling, done after this loop.
+ if (width + _font->getCharWidth(curChar) > maxWidth && g_sci->getLanguage() != Common::JA_JPN)
+ break;
width += _font->getCharWidth(curChar);
curCharCount++;
}
+
+ // Text without spaces, probably Kanji/Japanese
if (maxChars == 0) {
- // Text w/o space, supposingly kanji
maxChars = curCharCount;
uint16 nextChar;
// We remove the last char only, if maxWidth was actually equal width
// before adding the last char. Otherwise we won't get the same cutting
- // as in sierra pc98 sci. Note: changing the while() instead will NOT
- // WORK. it would break all sorts of regular sci games.
+ // as in sierra pc98 sci.
if (maxWidth == (width - _font->getCharWidth(curChar))) {
maxChars--;
if (curChar > 0xFF)
diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp
index e025a2f9ab..dde1be13ab 100644
--- a/engines/sci/graphics/transitions.cpp
+++ b/engines/sci/graphics/transitions.cpp
@@ -24,9 +24,8 @@
*/
#include "common/events.h"
-#include "common/util.h"
-#include "common/stack.h"
#include "common/system.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "sci/sci.h"
@@ -39,8 +38,8 @@ namespace Sci {
//#define DISABLE_TRANSITIONS // uncomment to disable room transitions (for development only! helps in testing games quickly)
-GfxTransitions::GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA)
- : _screen(screen), _palette(palette), _isVGA(isVGA) {
+GfxTransitions::GfxTransitions(GfxScreen *screen, GfxPalette *palette)
+ : _screen(screen), _palette(palette) {
init();
}
@@ -124,6 +123,7 @@ void GfxTransitions::setup(int16 number, bool blackoutFlag) {
_number = SCI_TRANSITIONS_NONE;
#endif
_blackoutFlag = blackoutFlag;
+ debugC(kDebugLevelGraphics, "Transition %d, blackout %d", number, blackoutFlag);
}
}
@@ -271,7 +271,7 @@ void GfxTransitions::doTransition(int16 number, bool blackoutFlag) {
}
void GfxTransitions::setNewPalette(bool blackoutFlag) {
- if (!blackoutFlag && _isVGA)
+ if (!blackoutFlag)
_palette->setOnScreen();
}
@@ -462,7 +462,6 @@ void GfxTransitions::scrollCopyOldToScreen(Common::Rect screenRect, int16 x, int
// Scroll old screen (up/down/left/right) and insert new screen that way - works
// on _picRect area only.
void GfxTransitions::scroll(int16 number) {
- int16 screenWidth, screenHeight;
int16 stepNr = 0;
Common::Rect oldMoveRect = _picRect;
Common::Rect oldScreenRect = _picRect;
@@ -471,7 +470,6 @@ void GfxTransitions::scroll(int16 number) {
uint32 msecCount = 0;
_screen->copyFromScreen(_oldScreen);
- screenWidth = _screen->getDisplayWidth(); screenHeight = _screen->getDisplayHeight();
switch (number) {
case SCI_TRANSITIONS_SCROLL_LEFT:
@@ -515,7 +513,7 @@ void GfxTransitions::scroll(int16 number) {
newScreenRect.bottom = newScreenRect.top;
newMoveRect.top = newMoveRect.bottom;
while (oldMoveRect.top < oldMoveRect.bottom) {
- oldMoveRect.top++; oldScreenRect.top++;
+ oldMoveRect.top++; oldScreenRect.top++;
newScreenRect.bottom++; newMoveRect.top--;
msecCount += 5;
diff --git a/engines/sci/graphics/transitions.h b/engines/sci/graphics/transitions.h
index 674b7a8173..a8f0ca6f07 100644
--- a/engines/sci/graphics/transitions.h
+++ b/engines/sci/graphics/transitions.h
@@ -65,7 +65,7 @@ class Screen;
*/
class GfxTransitions {
public:
- GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA);
+ GfxTransitions(GfxScreen *screen, GfxPalette *palette);
~GfxTransitions();
void setup(int16 number, bool blackoutFlag);
@@ -97,7 +97,6 @@ private:
GfxScreen *_screen;
GfxPalette *_palette;
- bool _isVGA;
const GfxTransitionTranslateEntry *_translationTable;
int16 _number;
bool _blackoutFlag;
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index 3c1f417740..f31cbacb22 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -83,7 +83,7 @@ void GfxView::initData(GuiResourceId resourceId) {
_loopCount = 0;
_embeddedPal = false;
_EGAmapping = NULL;
- _isSci2Hires = false;
+ _sci2ScaleRes = SCI_VIEW_NATIVERES_NONE;
_isScaleable = true;
// we adjust inside getCelRect for SCI0EARLY (that version didn't have the +1 when calculating bottom)
@@ -104,9 +104,10 @@ void GfxView::initData(GuiResourceId resourceId) {
}
switch (curViewType) {
- case kViewEga: // View-format SCI0 (and Amiga 16 colors)
+ case kViewEga: // SCI0 (and Amiga 16 colors)
isEGA = true;
- case kViewAmiga: // View-format Amiga (32 colors)
+ case kViewAmiga: // Amiga ECS (32 colors)
+ case kViewAmiga64: // Amiga AGA (64 colors)
case kViewVga: // View-format SCI1
// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
@@ -132,7 +133,7 @@ void GfxView::initData(GuiResourceId resourceId) {
// SCI1 VGA conversion games (which will get detected as SCI1EARLY/MIDDLE/LATE) have some views
// with broken mapping tables. I guess those games won't use the mapping, so I rather disable it
// for them
- if (getSciVersion() == SCI_VERSION_1_EGA) {
+ if (getSciVersion() == SCI_VERSION_1_EGA_ONLY) {
_EGAmapping = &_resourceData[palOffset];
for (EGAmapNr = 0; EGAmapNr < SCI_VIEW_EGAMAPPING_COUNT; EGAmapNr++) {
if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE) != 0)
@@ -201,8 +202,15 @@ void GfxView::initData(GuiResourceId resourceId) {
assert(headerSize >= 16);
_loopCount = _resourceData[2];
assert(_loopCount);
- _isSci2Hires = _resourceData[5] == 1 ? true : false;
palOffset = READ_SCI11ENDIAN_UINT32(_resourceData + 8);
+
+ // For SCI32, this is a scale flag
+ if (getSciVersion() >= SCI_VERSION_2) {
+ _sci2ScaleRes = (Sci32ViewNativeResolution)_resourceData[5];
+ if (_screen->getUpscaledHires() == GFX_SCREEN_UPSCALED_DISABLED)
+ _sci2ScaleRes = SCI_VIEW_NATIVERES_NONE;
+ }
+
// flags is actually a bit-mask
// it seems it was only used for some early sci1.1 games (or even just laura bow 2)
// later interpreters dont support it at all anymore
@@ -282,10 +290,10 @@ void GfxView::initData(GuiResourceId resourceId) {
}
#ifdef ENABLE_SCI32
// adjust width/height returned to scripts
- if (_isSci2Hires) {
+ if (_sci2ScaleRes != SCI_VIEW_NATIVERES_NONE) {
for (loopNo = 0; loopNo < _loopCount; loopNo++)
for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++)
- _screen->adjustBackUpscaledCoordinates(_loop[loopNo].cel[celNo].scriptWidth, _loop[loopNo].cel[celNo].scriptHeight);
+ _screen->adjustBackUpscaledCoordinates(_loop[loopNo].cel[celNo].scriptWidth, _loop[loopNo].cel[celNo].scriptHeight, _sci2ScaleRes);
} else if (getSciVersion() == SCI_VERSION_2_1) {
for (loopNo = 0; loopNo < _loopCount; loopNo++)
for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++)
@@ -329,7 +337,7 @@ Palette *GfxView::getPalette() {
}
bool GfxView::isSci2Hires() {
- return _isSci2Hires;
+ return _sci2ScaleRes > SCI_VIEW_NATIVERES_320x200;
}
bool GfxView::isScaleable() {
@@ -370,22 +378,157 @@ void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int1
outRect.top = outRect.bottom - scaledHeight;
}
+void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCount, int rlePos, int literalPos, ViewType viewType, uint16 width, bool isMacSci11ViewData) {
+ byte *outPtr = celBitmap;
+ byte curByte, runLength;
+ byte *rlePtr = inBuffer + rlePos;
+ // The existence of a literal position pointer signifies data with two
+ // separate streams, most likely a SCI1.1 view
+ byte *literalPtr = inBuffer + literalPos;
+ int pixelNr = 0;
+
+ memset(celBitmap, clearColor, pixelCount);
+
+ // View unpacking:
+ //
+ // EGA:
+ // Each byte is like XXXXYYYY (XXXX: 0 - 15, YYYY: 0 - 15)
+ // Set the next XXXX pixels to YYYY
+ //
+ // Amiga:
+ // Each byte is like XXXXXYYY (XXXXX: 0 - 31, YYY: 0 - 7)
+ // - Case A: YYY != 0
+ // Set the next YYY pixels to XXXXX
+ // - Case B: YYY == 0
+ // Skip the next XXXXX pixels (i.e. transparency)
+ //
+ // Amiga 64:
+ // Each byte is like XXYYYYYY (XX: 0 - 3, YYYYYY: 0 - 63)
+ // - Case A: XX != 0
+ // Set the next XX pixels to YYYYYY
+ // - Case B: XX == 0
+ // Skip the next YYYYYY pixels (i.e. transparency)
+ //
+ // VGA:
+ // Each byte is like XXYYYYYY (YYYYY: 0 - 63)
+ // - Case A: XX == 00 (binary)
+ // Copy next YYYYYY bytes as-is
+ // - Case B: XX == 01 (binary)
+ // Same as above, copy YYYYYY + 64 bytes as-is
+ // - Case C: XX == 10 (binary)
+ // Set the next YYYYY pixels to the next byte value
+ // - Case D: XX == 11 (binary)
+ // Skip the next YYYYY pixels (i.e. transparency)
+
+ if (literalPos && isMacSci11ViewData) {
+ // KQ6/Freddy Pharkas use byte lengths, all others use uint16
+ // The SCI devs must have realized that a max of 255 pixels wide
+ // was not very good for 320 or 640 width games.
+ bool hasByteLengths = (g_sci->getGameId() == GID_KQ6 || g_sci->getGameId() == GID_FREDDYPHARKAS);
+
+ // compression for SCI1.1+ Mac
+ while (pixelNr < pixelCount) {
+ uint32 pixelLine = pixelNr;
+
+ if (hasByteLengths) {
+ pixelNr += *rlePtr++;
+ runLength = *rlePtr++;
+ } else {
+ pixelNr += READ_BE_UINT16(rlePtr);
+ runLength = READ_BE_UINT16(rlePtr + 2);
+ rlePtr += 4;
+ }
+
+ while (runLength-- && pixelNr < pixelCount)
+ outPtr[pixelNr++] = *literalPtr++;
+
+ pixelNr = pixelLine + width;
+ }
+ return;
+ }
+
+ switch (viewType) {
+ case kViewEga:
+ while (pixelNr < pixelCount) {
+ curByte = *rlePtr++;
+ runLength = curByte >> 4;
+ memset(outPtr + pixelNr, curByte & 0x0F, MIN<uint16>(runLength, pixelCount - pixelNr));
+ pixelNr += runLength;
+ }
+ break;
+ case kViewAmiga:
+ while (pixelNr < pixelCount) {
+ curByte = *rlePtr++;
+ if (curByte & 0x07) { // fill with color
+ runLength = curByte & 0x07;
+ curByte = curByte >> 3;
+ memset(outPtr + pixelNr, curByte, MIN<uint16>(runLength, pixelCount - pixelNr));
+ } else { // skip the next pixels (transparency)
+ runLength = curByte >> 3;
+ }
+ pixelNr += runLength;
+ }
+ break;
+ case kViewAmiga64:
+ while (pixelNr < pixelCount) {
+ curByte = *rlePtr++;
+ if (curByte & 0xC0) { // fill with color
+ runLength = curByte >> 6;
+ memset(outPtr + pixelNr, curByte & 0x3F, MIN<uint16>(runLength, pixelCount - pixelNr));
+ } else { // skip the next pixels (transparency)
+ runLength = curByte & 0x3F;
+ }
+ pixelNr += runLength;
+ }
+ break;
+ case kViewVga:
+ case kViewVga11:
+ // If we have no RLE data, the image is just uncompressed
+ if (rlePos == 0) {
+ memcpy(outPtr, literalPtr, pixelCount);
+ break;
+ }
+
+ while (pixelNr < pixelCount) {
+ curByte = *rlePtr++;
+ runLength = curByte & 0x3F;
+
+ switch (curByte & 0xC0) {
+ case 0x40: // copy bytes as is (In copy case, runLength can go up to 127 i.e. pixel & 0x40). Fixes bug #3135872.
+ runLength += 64;
+ case 0x00: // copy bytes as-is
+ if (!literalPos) {
+ memcpy(outPtr + pixelNr, rlePtr, MIN<uint16>(runLength, pixelCount - pixelNr));
+ rlePtr += runLength;
+ } else {
+ memcpy(outPtr + pixelNr, literalPtr, MIN<uint16>(runLength, pixelCount - pixelNr));
+ literalPtr += runLength;
+ }
+ break;
+ case 0x80: // fill with color
+ if (!literalPos)
+ memset(outPtr + pixelNr, *rlePtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
+ else
+ memset(outPtr + pixelNr, *literalPtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
+ break;
+ case 0xC0: // skip the next pixels (transparency)
+ break;
+ }
+
+ pixelNr += runLength;
+ }
+ break;
+ default:
+ error("Unsupported picture viewtype");
+ }
+}
+
void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount) {
const CelInfo *celInfo = getCelInfo(loopNo, celNo);
- byte *rlePtr;
- byte *literalPtr;
- uint32 pixelNo = 0, runLength;
- byte pixel;
if (celInfo->offsetEGA) {
// decompression for EGA views
- literalPtr = _resourceData + _loop[loopNo].cel[celNo].offsetEGA;
- while (pixelNo < pixelCount) {
- pixel = *literalPtr++;
- runLength = pixel >> 4;
- memset(outPtr + pixelNo, pixel & 0x0F, MIN<uint32>(runLength, pixelCount - pixelNo));
- pixelNo += runLength;
- }
+ unpackCelData(_resourceData, outPtr, 0, pixelCount, celInfo->offsetEGA, 0, _resMan->getViewType(), celInfo->width, false);
} else {
// We fill the buffer with transparent pixels, so that we can later skip
// over pixels to automatically have them transparent
@@ -408,100 +551,8 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou
clearColor = 0;
}
- memset(outPtr, clearColor, pixelCount);
-
- rlePtr = _resourceData + celInfo->offsetRLE;
- if (!celInfo->offsetLiteral) { // no additional literal data
- if (_resMan->isAmiga32color()) {
- // decompression for amiga views
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- if (pixel & 0x07) { // fill with color
- runLength = pixel & 0x07;
- pixel = pixel >> 3;
- while (runLength-- && pixelNo < pixelCount) {
- outPtr[pixelNo++] = pixel;
- }
- } else { // fill with transparent
- runLength = pixel >> 3;
- pixelNo += runLength;
- }
- }
- } else {
- // decompression for data that has just one combined stream
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- runLength = pixel & 0x3F;
- switch (pixel & 0xC0) {
- case 0x40: // copy bytes as is (In copy case, runLength can go upto 127 i.e. pixel & 0x40)
- runLength += 64;
- case 0x00: // copy bytes as-is
- while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *rlePtr++;
- break;
- case 0x80: // fill with color
- memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
- pixelNo += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNo += runLength;
- break;
- }
- }
- }
- } else {
- literalPtr = _resourceData + celInfo->offsetLiteral;
- if (celInfo->offsetRLE) {
- if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() == SCI_VERSION_1_1) {
- // KQ6/Freddy Pharkas use byte lengths, all others use uint16
- // The SCI devs must have realized that a max of 255 pixels wide
- // was not very good for 320 or 640 width games.
- bool hasByteLengths = (g_sci->getGameId() == GID_KQ6 || g_sci->getGameId() == GID_FREDDYPHARKAS);
-
- // compression for SCI1.1+ Mac
- while (pixelNo < pixelCount) {
- uint32 pixelLine = pixelNo;
-
- if (hasByteLengths) {
- pixelNo += *rlePtr++;
- runLength = *rlePtr++;
- } else {
- pixelNo += READ_BE_UINT16(rlePtr);
- runLength = READ_BE_UINT16(rlePtr + 2);
- rlePtr += 4;
- }
-
- while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *literalPtr++;
-
- pixelNo = pixelLine + celInfo->width;
- }
- } else {
- // decompression for data that has separate rle and literal streams
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- runLength = pixel & 0x3F;
- switch (pixel & 0xC0) {
- case 0: // copy bytes as-is
- while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *literalPtr++;
- break;
- case 0x80: // fill with color
- memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
- pixelNo += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNo += runLength;
- break;
- }
- }
- }
- } else {
- // literal stream only, so no compression
- memcpy(outPtr, literalPtr, pixelCount);
- pixelNo = pixelCount;
- }
- }
+ bool isMacSci11ViewData = g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() == SCI_VERSION_1_1;
+ unpackCelData(_resourceData, outPtr, clearColor, pixelCount, celInfo->offsetRLE, celInfo->offsetLiteral, _resMan->getViewType(), celInfo->width, isMacSci11ViewData);
// Swap 0 and 0xff pixels for Mac SCI1.1+ games (see above)
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) {
@@ -531,9 +582,8 @@ const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
// unpack the actual cel bitmap data
unpackCel(loopNo, celNo, pBitmap, pixelCount);
- if (!_resMan->isVGA()) {
+ if (_resMan->getViewType() == kViewEga)
unditherBitmap(pBitmap, width, height, _loop[loopNo].cel[celNo].clearKey);
- }
// mirroring the cel if needed
if (_loop[loopNo].mirrorFlag) {
@@ -549,19 +599,15 @@ const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
* cel if the dithering in here matches dithering used by the current picture.
*/
void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte clearKey) {
- int16 *unditherMemorial = _screen->unditherGetMemorial();
-
- // It makes no sense to go further, if no memorial data from current picture
- // is available
- if (!unditherMemorial)
- return;
+ int16 *ditheredPicColors = _screen->unditherGetDitheredBgColors();
- // Makes no sense to process bitmaps that are 3 pixels wide or less
- if (width <= 3)
+ // It makes no sense to go further, if there isn't any dithered color data
+ // available for the current picture
+ if (!ditheredPicColors)
return;
- // We need at least 2 pixel lines
- if (height < 2)
+ // We need at least a 4x2 bitmap for this algorithm to work
+ if (width < 4 || height < 2)
return;
// If EGA mapping is used for this view, dont do undithering as well
@@ -569,13 +615,13 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
return;
// Walk through the bitmap and remember all combinations of colors
- int16 bitmapMemorial[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
+ int16 ditheredBitmapColors[DITHERED_BG_COLORS_SIZE];
byte *curPtr;
byte color1, color2;
byte nextColor1, nextColor2;
int16 y, x;
- memset(&bitmapMemorial, 0, sizeof(bitmapMemorial));
+ memset(&ditheredBitmapColors, 0, sizeof(ditheredBitmapColors));
// Count all seemingly dithered pixel-combinations as soon as at least 4
// pixels are adjacent and check pixels in the following line as well to
@@ -594,17 +640,17 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
nextColor1 = (nextColor1 >> 4) | (nextColor2 << 4);
nextColor2 = (nextColor2 >> 4) | *nextPtr++ << 4;
if ((color1 == color2) && (color1 == nextColor1) && (color1 == nextColor2))
- bitmapMemorial[color1]++;
+ ditheredBitmapColors[color1]++;
}
}
- // Now compare both memorial tables to find out matching
- // dithering-combinations
- bool unditherTable[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
+ // Now compare both dither color tables to find out matching dithered color
+ // combinations
+ bool unditherTable[DITHERED_BG_COLORS_SIZE];
byte color, unditherCount = 0;
memset(&unditherTable, false, sizeof(unditherTable));
for (color = 0; color < 255; color++) {
- if ((bitmapMemorial[color] > 5) && (unditherMemorial[color] > 200)) {
+ if ((ditheredBitmapColors[color] > 5) && (ditheredPicColors[color] > 200)) {
// match found, check if colorKey is contained -> if so, we ignore
// of course
color1 = color & 0x0F; color2 = color >> 4;
@@ -676,6 +722,8 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const
// get drawn onto lowres screen.
// FIXME(?): we can't read priority directly with the
// hires coordinates. May not be needed at all in kq6
+ // FIXME: Handle proper aspect ratio. Some GK1 hires images
+ // are in 640x400 instead of 640x480
_screen->putPixelOnDisplay(x2, y2, palette->mapping[color]);
}
}
@@ -783,4 +831,12 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect,
}
}
+void GfxView::adjustToUpscaledCoordinates(int16 &y, int16 &x) {
+ _screen->adjustToUpscaledCoordinates(y, x, _sci2ScaleRes);
+}
+
+void GfxView::adjustBackUpscaledCoordinates(int16 &y, int16 &x) {
+ _screen->adjustBackUpscaledCoordinates(y, x, _sci2ScaleRes);
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h
index f785e3c475..36914f916c 100644
--- a/engines/sci/graphics/view.h
+++ b/engines/sci/graphics/view.h
@@ -28,6 +28,13 @@
namespace Sci {
+enum Sci32ViewNativeResolution {
+ SCI_VIEW_NATIVERES_NONE = -1,
+ SCI_VIEW_NATIVERES_320x200 = 0,
+ SCI_VIEW_NATIVERES_640x480 = 1,
+ SCI_VIEW_NATIVERES_640x400 = 2
+};
+
struct CelInfo {
int16 width, height;
int16 scriptWidth, scriptHeight;
@@ -78,6 +85,9 @@ public:
bool isScaleable();
bool isSci2Hires();
+ void adjustToUpscaledCoordinates(int16 &y, int16 &x);
+ void adjustBackUpscaledCoordinates(int16 &y, int16 &x);
+
private:
void initData(GuiResourceId resourceId);
void unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount);
@@ -98,8 +108,8 @@ private:
bool _embeddedPal;
Palette _viewPalette;
- // set for SCI2 views in gk1/windows, means that views are hires and should be handled accordingly
- bool _isSci2Hires;
+ // specifies scaling resolution for SCI2 views (see gk1/windows, Wolfgang in room 720)
+ Sci32ViewNativeResolution _sci2ScaleRes;
byte *_EGAmapping;
diff --git a/engines/sci/parser/grammar.cpp b/engines/sci/parser/grammar.cpp
index 8a6cd2dd4d..b330a432e3 100644
--- a/engines/sci/parser/grammar.cpp
+++ b/engines/sci/parser/grammar.cpp
@@ -31,6 +31,7 @@
#include "sci/parser/vocabulary.h"
#include "sci/console.h"
#include "common/array.h"
+#include "common/textconsole.h"
namespace Sci {
@@ -380,7 +381,7 @@ static ParseRuleList *_vocab_clone_rule_list_by_id(ParseRuleList *list, int id)
ParseRuleList *Vocabulary::buildGNF(bool verbose) {
int iterations = 0;
- int last_termrules, termrules = 0;
+ int termrules = 0;
int ntrules_nr;
ParseRuleList *ntlist = NULL;
ParseRuleList *tlist, *new_tlist;
@@ -405,7 +406,6 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) {
do {
ParseRuleList *new_new_tlist = NULL;
ParseRuleList *ntseeker, *tseeker;
- last_termrules = termrules;
ntseeker = ntlist;
while (ntseeker) {
diff --git a/engines/sci/parser/said.cpp b/engines/sci/parser/said.cpp
index e9c6d9847f..666a235cf9 100644
--- a/engines/sci/parser/said.cpp
+++ b/engines/sci/parser/said.cpp
@@ -1020,7 +1020,7 @@ static int augment_parse_nodes(ParseTreeNode *parseT, ParseTreeNode *saidT) {
/**** Main code ****/
/*******************/
-int said(EngineState *s, const byte *spec, bool verbose) {
+int said(const byte *spec, bool verbose) {
int retval;
Vocabulary *voc = g_sci->getVocabulary();
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index 8d59df5d58..25043401cc 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -63,7 +63,7 @@ Vocabulary::Vocabulary(ResourceManager *resMan, bool foreign) : _resMan(resMan),
_resourceIdBranches += 10;
}
- if (getSciVersion() <= SCI_VERSION_1_EGA && loadParserWords()) {
+ if (getSciVersion() <= SCI_VERSION_1_EGA_ONLY && loadParserWords()) {
loadSuffixes();
if (loadBranches())
// Now build a GNF grammar out of this
diff --git a/engines/sci/parser/vocabulary.h b/engines/sci/parser/vocabulary.h
index 3d644d88f7..6d3e0b301e 100644
--- a/engines/sci/parser/vocabulary.h
+++ b/engines/sci/parser/vocabulary.h
@@ -383,12 +383,11 @@ void vocab_dump_parse_tree(const char *tree_name, ParseTreeNode *nodes);
/**
* Builds a parse tree from a spec and compares it to a parse tree.
- * @param s The affected state
* @param spec Pointer to the spec to build
* @param verbose Whether to display the parse tree after building it
* @return 1 on a match, 0 otherwise
*/
-int said(EngineState *s, const byte *spec, bool verbose);
+int said(const byte *spec, bool verbose);
} // End of namespace Sci
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index a16f7126c3..a48ae0fad7 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -28,6 +28,7 @@
#include "common/file.h"
#include "common/fs.h"
#include "common/macresman.h"
+#include "common/textconsole.h"
#include "sci/resource.h"
#include "sci/resource_intern.h"
@@ -67,7 +68,7 @@ const char *getSciVersionDesc(SciVersion version) {
return "Late SCI0";
case SCI_VERSION_01:
return "SCI01";
- case SCI_VERSION_1_EGA:
+ case SCI_VERSION_1_EGA_ONLY:
return "SCI1 EGA";
case SCI_VERSION_1_EARLY:
return "Early SCI1";
@@ -948,15 +949,18 @@ void ResourceManager::init(bool initFromFallbackDetector) {
case kViewEga:
debugC(1, kDebugLevelResMan, "resMan: Detected EGA graphic resources");
break;
+ case kViewAmiga:
+ debugC(1, kDebugLevelResMan, "resMan: Detected Amiga ECS graphic resources");
+ break;
+ case kViewAmiga64:
+ debugC(1, kDebugLevelResMan, "resMan: Detected Amiga AGA graphic resources");
+ break;
case kViewVga:
debugC(1, kDebugLevelResMan, "resMan: Detected VGA graphic resources");
break;
case kViewVga11:
debugC(1, kDebugLevelResMan, "resMan: Detected SCI1.1 VGA graphic resources");
break;
- case kViewAmiga:
- debugC(1, kDebugLevelResMan, "resMan: Detected Amiga graphic resources");
- break;
default:
#ifdef ENABLE_SCI32
error("resMan: Couldn't determine view type");
@@ -1272,7 +1276,7 @@ ResVersion ResourceManager::detectVolVersion() {
// SCI32 volume format: {bResType wResNumber dwPacked dwUnpacked wCompression} = 13 bytes
// Try to parse volume with SCI0 scheme to see if it make sense
// Checking 1MB of data should be enough to determine the version
- uint16 resId, wCompression;
+ uint16 wCompression;
uint32 dwPacked, dwUnpacked;
ResVersion curVersion = kResVersionSci0Sci1Early;
bool failed = false;
@@ -1282,7 +1286,7 @@ ResVersion ResourceManager::detectVolVersion() {
while (!fileStream->eos() && fileStream->pos() < 0x100000) {
if (curVersion > kResVersionSci0Sci1Early)
fileStream->readByte();
- resId = fileStream->readUint16LE();
+ fileStream->skip(2); // resId
dwPacked = (curVersion < kResVersionSci2) ? fileStream->readUint16LE() : fileStream->readUint32LE();
dwUnpacked = (curVersion < kResVersionSci2) ? fileStream->readUint16LE() : fileStream->readUint32LE();
@@ -1485,7 +1489,7 @@ void ResourceManager::readResourcePatchesBase36() {
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
uint32 tag = stream->readUint32BE();
- if (tag == MKID_BE('RIFF') || tag == MKID_BE('FORM')) {
+ if (tag == MKTAG('R','I','F','F') || tag == MKTAG('F','O','R','M')) {
delete stream;
processWavePatch(resource36, name);
continue;
@@ -1494,7 +1498,7 @@ void ResourceManager::readResourcePatchesBase36() {
// Check for SOL as well
tag = (tag << 16) | stream->readUint16BE();
- if (tag != MKID_BE('SOL\0')) {
+ if (tag != MKTAG('S','O','L',0)) {
delete stream;
continue;
}
@@ -1535,10 +1539,18 @@ void ResourceManager::readResourcePatches() {
mask += s_resourceTypeSuffixes[i];
SearchMan.listMatchingMembers(files, mask);
- if (i == kResourceTypeScript && files.size() == 0) {
- // SCI3 (we can't use getSciVersion() at this point)
- mask = "*.csc";
- SearchMan.listMatchingMembers(files, mask);
+ if (i == kResourceTypeView) {
+ SearchMan.listMatchingMembers(files, "*.v16"); // EGA SCI1 view patches
+ SearchMan.listMatchingMembers(files, "*.v32"); // Amiga SCI1 view patches
+ SearchMan.listMatchingMembers(files, "*.v64"); // Amiga AGA SCI1 (i.e. Longbow) view patches
+ } else if (i == kResourceTypePic) {
+ SearchMan.listMatchingMembers(files, "*.p16"); // EGA SCI1 picture patches
+ SearchMan.listMatchingMembers(files, "*.p32"); // Amiga SCI1 picture patches
+ SearchMan.listMatchingMembers(files, "*.p64"); // Amiga AGA SCI1 (i.e. Longbow) picture patches
+ } else if (i == kResourceTypeScript) {
+ if (files.size() == 0)
+ // SCI3 (we can't use getSciVersion() at this point)
+ SearchMan.listMatchingMembers(files, "*.csc");
}
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
@@ -1735,25 +1747,25 @@ struct MacResTag {
};
static const MacResTag macResTagMap[] = {
- { MKID_BE('V56 '), kResourceTypeView },
- { MKID_BE('P56 '), kResourceTypePic },
- { MKID_BE('SCR '), kResourceTypeScript },
- { MKID_BE('TEX '), kResourceTypeText },
- { MKID_BE('SND '), kResourceTypeSound },
- { MKID_BE('VOC '), kResourceTypeVocab },
- { MKID_BE('FON '), kResourceTypeFont },
- { MKID_BE('CURS'), kResourceTypeCursor },
- { MKID_BE('crsr'), kResourceTypeCursor },
- { MKID_BE('Pat '), kResourceTypePatch },
- { MKID_BE('PAL '), kResourceTypePalette },
- { MKID_BE('snd '), kResourceTypeAudio },
- { MKID_BE('MSG '), kResourceTypeMessage },
- { MKID_BE('HEP '), kResourceTypeHeap },
- { MKID_BE('IBIN'), kResourceTypeMacIconBarPictN },
- { MKID_BE('IBIS'), kResourceTypeMacIconBarPictS },
- { MKID_BE('PICT'), kResourceTypeMacPict },
- { MKID_BE('SYN '), kResourceTypeSync },
- { MKID_BE('SYNC'), kResourceTypeSync }
+ { MKTAG('V','5','6',' '), kResourceTypeView },
+ { MKTAG('P','5','6',' '), kResourceTypePic },
+ { MKTAG('S','C','R',' '), kResourceTypeScript },
+ { MKTAG('T','E','X',' '), kResourceTypeText },
+ { MKTAG('S','N','D',' '), kResourceTypeSound },
+ { MKTAG('V','O','C',' '), kResourceTypeVocab },
+ { MKTAG('F','O','N',' '), kResourceTypeFont },
+ { MKTAG('C','U','R','S'), kResourceTypeCursor },
+ { MKTAG('c','r','s','r'), kResourceTypeCursor },
+ { MKTAG('P','a','t',' '), kResourceTypePatch },
+ { MKTAG('P','A','L',' '), kResourceTypePalette },
+ { MKTAG('s','n','d',' '), kResourceTypeAudio },
+ { MKTAG('M','S','G',' '), kResourceTypeMessage },
+ { MKTAG('H','E','P',' '), kResourceTypeHeap },
+ { MKTAG('I','B','I','N'), kResourceTypeMacIconBarPictN },
+ { MKTAG('I','B','I','S'), kResourceTypeMacIconBarPictS },
+ { MKTAG('P','I','C','T'), kResourceTypeMacPict },
+ { MKTAG('S','Y','N',' '), kResourceTypeSync },
+ { MKTAG('S','Y','N','C'), kResourceTypeSync }
};
static Common::Array<uint32> resTypeToMacTags(ResourceType type) {
@@ -2049,7 +2061,13 @@ ViewType ResourceManager::detectViewType() {
switch (res->data[1]) {
case 128:
- // If the 2nd byte is 128, it's a VGA game
+ // If the 2nd byte is 128, it's a VGA game.
+ // However, Longbow Amiga (AGA, 64 colors), also sets this byte
+ // to 128, but it's a mixed VGA/Amiga format. Detect this from
+ // the platform here.
+ if (g_sci && g_sci->getPlatform() == Common::kPlatformAmiga)
+ return kViewAmiga64;
+
return kViewVga;
case 0:
// EGA or Amiga, try to read as Amiga view
@@ -2127,9 +2145,9 @@ void ResourceManager::detectSciVersion() {
if (viewCompression != kCompLZW) {
// If it's a different compression type from kCompLZW, the game is probably
- // SCI_VERSION_1_EGA or later. If the views are uncompressed, it is
+ // SCI_VERSION_1_EGA_ONLY or later. If the views are uncompressed, it is
// likely not an early disk game.
- s_sciVersion = SCI_VERSION_1_EGA;
+ s_sciVersion = SCI_VERSION_1_EGA_ONLY;
oldDecompressors = false;
}
@@ -2243,9 +2261,9 @@ void ResourceManager::detectSciVersion() {
return;
}
- // New decompressors. It's either SCI_VERSION_1_EGA or SCI_VERSION_1_EARLY.
+ // New decompressors. It's either SCI_VERSION_1_EGA_ONLY or SCI_VERSION_1_EARLY.
if (hasSci1Voc900()) {
- s_sciVersion = SCI_VERSION_1_EGA;
+ s_sciVersion = SCI_VERSION_1_EGA_ONLY;
return;
}
@@ -2255,6 +2273,12 @@ void ResourceManager::detectSciVersion() {
case kResVersionSci1Middle:
case kResVersionKQ5FMT:
s_sciVersion = SCI_VERSION_1_MIDDLE;
+ // Amiga SCI1 middle games are actually SCI1 late
+ if (_viewType == kViewAmiga || _viewType == kViewAmiga64)
+ s_sciVersion = SCI_VERSION_1_LATE;
+ // Same goes for Mac SCI1 middle games
+ if (g_sci && g_sci->getPlatform() == Common::kPlatformMacintosh)
+ s_sciVersion = SCI_VERSION_1_LATE;
return;
case kResVersionSci1Late:
if (_volVersion == kResVersionSci11) {
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 76b5a421ee..e941f666d9 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -331,8 +331,6 @@ public:
int getAudioLanguage() const;
void changeAudioDirectory(Common::String path);
bool isGMTrackIncluded();
- bool isVGA() const { return (_viewType == kViewVga) || (_viewType == kViewVga11); }
- bool isAmiga32color() const { return _viewType == kViewAmiga; }
bool isSci11Mac() const { return _volVersion == kResVersionSci11Mac; }
ViewType getViewType() const { return _viewType; }
const char *getMapVersionDesc() const { return versionDescription(_mapVersion); }
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 386bfb37f5..1e0b9c0ddf 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -27,6 +27,7 @@
#include "common/archive.h"
#include "common/file.h"
+#include "common/textconsole.h"
#include "sci/resource.h"
#include "sci/resource_intern.h"
@@ -53,9 +54,9 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, co
fileStream->seek(0, SEEK_SET);
uint32 compressionType = fileStream->readUint32BE();
switch (compressionType) {
- case MKID_BE('MP3 '):
- case MKID_BE('OGG '):
- case MKID_BE('FLAC'):
+ case MKTAG('M','P','3',' '):
+ case MKTAG('O','G','G',' '):
+ case MKTAG('F','L','A','C'):
// Detected a compressed audio volume
_audioCompressionType = compressionType;
// Now read the whole offset mapping table for later usage
@@ -91,7 +92,7 @@ bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) {
bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) {
// Check for WAVE files here
uint32 riffTag = file->readUint32BE();
- if (riffTag == MKID_BE('RIFF')) {
+ if (riffTag == MKTAG('R','I','F','F')) {
_headerSize = 0;
size = file->readUint32LE() + 8;
file->seek(-8, SEEK_CUR);
diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h
index 98cca6283c..969e250e62 100644
--- a/engines/sci/resource_intern.h
+++ b/engines/sci/resource_intern.h
@@ -29,7 +29,7 @@
#include "sci/resource.h"
namespace Common {
- class MacResManager;
+class MacResManager;
}
namespace Sci {
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 7147b17b82..85c2eced19 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -213,7 +213,6 @@ Common::Error SciEngine::run() {
// Add the after market GM patches for the specified game, if they exist
_resMan->addNewGMPatch(_gameId);
_gameObjectAddress = _resMan->findGameObject();
- _gameSuperClassAddress = NULL_REG;
SegManager *segMan = new SegManager(_resMan);
@@ -227,7 +226,7 @@ Common::Error SciEngine::run() {
_features = new GameFeatures(segMan, _kernel);
// Only SCI0, SCI01 and SCI1 EGA games used a parser
- _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan, false) : NULL;
+ _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA_ONLY) ? new Vocabulary(_resMan, false) : NULL;
// Also, XMAS1990 apparently had a parser too. Refer to http://forums.scummvm.org/viewtopic.php?t=9135
if (getGameId() == GID_CHRISTMAS1990)
_vocabulary = new Vocabulary(_resMan, false);
@@ -250,7 +249,6 @@ Common::Error SciEngine::run() {
warning("Could not get game object, aborting...");
return Common::kUnknownError;
}
- _gameSuperClassAddress = gameObject->getSuperClassSelector();
script_adjust_opcode_formats();
@@ -267,8 +265,6 @@ Common::Error SciEngine::run() {
// Initialize all graphics related subsystems
initGraphics();
- debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
-
// Patch in our save/restore code, so that dialogs are replaced
patchGameSaveRestore();
setLauncherLanguage();
@@ -427,34 +423,66 @@ static byte patchGameRestoreSave[] = {
0x76, // push0
0x38, 0xff, 0xff, // pushi -1
0x76, // push0
- 0x43, 0xff, 0x06, // call kRestoreGame/kSaveGame (will get fixed directly)
+ 0x43, 0xff, 0x06, // callk kRestoreGame/kSaveGame (will get changed afterwards)
+ 0x48, // ret
+};
+
+// SCI2 version: Same as above, but the second parameter to callk is a word
+static byte patchGameRestoreSaveSci2[] = {
+ 0x39, 0x03, // pushi 03
+ 0x76, // push0
+ 0x38, 0xff, 0xff, // pushi -1
+ 0x76, // push0
+ 0x43, 0xff, 0x06, 0x00, // callk kRestoreGame/kSaveGame (will get changed afterwards)
+ 0x48, // ret
+};
+
+// SCI21 version: Same as above, but the second parameter to callk is a word
+static byte patchGameRestoreSaveSci21[] = {
+ 0x39, 0x04, // pushi 04
+ 0x76, // push0 // 0: save, 1: restore (will get changed afterwards)
+ 0x76, // push0
+ 0x38, 0xff, 0xff, // pushi -1
+ 0x76, // push0
+ 0x43, 0xff, 0x08, 0x00, // callk kSave (will get changed afterwards)
0x48, // ret
};
+static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) {
+ Script *script = segMan->getScript(methodAddress.segment);
+ byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.offset));
+ if (getSciVersion() <= SCI_VERSION_1_1)
+ memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
+ else // SCI2+
+ memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2));
+ patchPtr[8] = id;
+}
+
+static void patchGameSaveRestoreCodeSci21(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) {
+ Script *script = segMan->getScript(methodAddress.segment);
+ byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.offset));
+ memcpy(patchPtr, patchGameRestoreSaveSci21, sizeof(patchGameRestoreSaveSci21));
+ if (doRestore)
+ patchPtr[2] = 0x78; // push1
+ patchPtr[9] = id;
+}
+
void SciEngine::patchGameSaveRestore() {
SegManager *segMan = _gamestate->_segMan;
const Object *gameObject = segMan->getObject(_gameObjectAddress);
- const uint16 gameMethodCount = gameObject->getMethodCount();
- const Object *gameSuperObject = segMan->getObject(_gameSuperClassAddress);
+ const Object *gameSuperObject = segMan->getObject(gameObject->getSuperClassSelector());
if (!gameSuperObject)
gameSuperObject = gameObject; // happens in KQ5CD, when loading saved games before r54510
- const uint16 gameSuperMethodCount = gameSuperObject->getMethodCount();
- reg_t methodAddress;
- const uint16 kernelCount = _kernel->getKernelNamesSize();
- const byte *scriptRestorePtr = NULL;
byte kernelIdRestore = 0;
- const byte *scriptSavePtr = NULL;
byte kernelIdSave = 0;
- // this feature is currently not supported on SCI32
- if (getSciVersion() >= SCI_VERSION_2)
- return;
-
switch (_gameId) {
- case GID_MOTHERGOOSE256: // mother goose saves/restores directly and has no save/restore dialogs
- 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_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_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
return;
default:
break;
@@ -463,61 +491,53 @@ void SciEngine::patchGameSaveRestore() {
if (ConfMan.getBool("sci_originalsaveload"))
return;
- for (uint16 kernelNr = 0; kernelNr < kernelCount; kernelNr++) {
+ uint16 kernelNamesSize = _kernel->getKernelNamesSize();
+ for (uint16 kernelNr = 0; kernelNr < kernelNamesSize; kernelNr++) {
Common::String kernelName = _kernel->getKernelName(kernelNr);
if (kernelName == "RestoreGame")
kernelIdRestore = kernelNr;
if (kernelName == "SaveGame")
kernelIdSave = kernelNr;
+ if (kernelName == "Save")
+ kernelIdSave = kernelIdRestore = kernelNr;
}
- // Search for gameobject-superclass ::restore
- for (uint16 methodNr = 0; methodNr < gameSuperMethodCount; methodNr++) {
+ // Search for gameobject superclass ::restore
+ uint16 gameSuperObjectMethodCount = gameSuperObject->getMethodCount();
+ for (uint16 methodNr = 0; methodNr < gameSuperObjectMethodCount; methodNr++) {
uint16 selectorId = gameSuperObject->getFuncSelector(methodNr);
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "restore") {
- methodAddress = gameSuperObject->getFunction(methodNr);
- Script *script = segMan->getScript(methodAddress.segment);
- scriptRestorePtr = script->getBuf(methodAddress.offset);
+ if (kernelIdSave != kernelIdRestore)
+ patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore);
+ else
+ patchGameSaveRestoreCodeSci21(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore, true);
}
- if (methodName == "save") {
- methodAddress = gameSuperObject->getFunction(methodNr);
- Script *script = segMan->getScript(methodAddress.segment);
- scriptSavePtr = script->getBuf(methodAddress.offset);
+ else if (methodName == "save") {
+ if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog
+ if (kernelIdSave != kernelIdRestore)
+ patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave);
+ else
+ patchGameSaveRestoreCodeSci21(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave, false);
+ }
}
}
- // Search for gameobject ::save, if there is one patch that one instead
- for (uint16 methodNr = 0; methodNr < gameMethodCount; methodNr++) {
+ // Search for gameobject ::save, if there is one patch that one too
+ uint16 gameObjectMethodCount = gameObject->getMethodCount();
+ for (uint16 methodNr = 0; methodNr < gameObjectMethodCount; methodNr++) {
uint16 selectorId = gameObject->getFuncSelector(methodNr);
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "save") {
- methodAddress = gameObject->getFunction(methodNr);
- Script *script = segMan->getScript(methodAddress.segment);
- scriptSavePtr = script->getBuf(methodAddress.offset);
+ if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog
+ if (kernelIdSave != kernelIdRestore)
+ patchGameSaveRestoreCode(segMan, gameObject->getFunction(methodNr), kernelIdSave);
+ else
+ patchGameSaveRestoreCodeSci21(segMan, gameObject->getFunction(methodNr), kernelIdSave, false);
+ }
break;
}
}
-
- switch (_gameId) {
- case GID_FAIRYTALES: // fairy tales automatically saves w/o dialog
- scriptSavePtr = NULL;
- default:
- break;
- }
-
- if (scriptRestorePtr) {
- // Now patch in our code
- byte *patchPtr = const_cast<byte *>(scriptRestorePtr);
- memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
- patchPtr[8] = kernelIdRestore;
- }
- if (scriptSavePtr) {
- // Now patch in our code
- byte *patchPtr = const_cast<byte *>(scriptSavePtr);
- memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
- patchPtr[8] = kernelIdSave;
- }
}
bool SciEngine::initGame() {
@@ -555,9 +575,8 @@ bool SciEngine::initGame() {
}
// Reset parser
- if (_vocabulary) {
+ if (_vocabulary)
_vocabulary->reset();
- }
_gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis();
@@ -623,7 +642,7 @@ void SciEngine::initGraphics() {
_gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts);
_gfxCursor->init(_gfxCoordAdjuster, _eventMan);
_gfxCompare = new GfxCompare(_gamestate->_segMan, _kernel, _gfxCache, _gfxScreen, _gfxCoordAdjuster);
- _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, _resMan->isVGA());
+ _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette);
_gfxPaint16 = new GfxPaint16(_resMan, _gamestate->_segMan, _kernel, _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio);
_gfxPaint = _gfxPaint16;
_gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions);
@@ -758,6 +777,16 @@ bool SciEngine::isCD() const {
return _gameDescription->flags & ADGF_CD;
}
+bool SciEngine::isBE() const{
+ switch(_gameDescription->platform) {
+ case Common::kPlatformAmiga:
+ case Common::kPlatformMacintosh:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool SciEngine::hasMacIconBar() const {
return _resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1 &&
(getGameId() == GID_KQ6 || getGameId() == GID_FREDDYPHARKAS);
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index b3e398325f..cd50b2402c 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -77,7 +77,6 @@ class GfxText16;
class GfxTransitions;
#ifdef ENABLE_SCI32
-class SciGui32;
class RobotDecoder;
class GfxFrameout;
#endif
@@ -180,20 +179,24 @@ enum SciGameId {
GID_FANMADE // FIXME: Do we really need/want this?
};
-/** SCI versions */
+/**
+ * SCI versions
+ * For more information, check here:
+ * http://wiki.scummvm.org/index.php/Sierra_Game_Versions#SCI_Games
+ */
enum SciVersion {
SCI_VERSION_NONE,
- SCI_VERSION_0_EARLY, // Early KQ4, 1988 xmas card
+ SCI_VERSION_0_EARLY, // KQ4 early, LSL2 early, XMAS card 1988
SCI_VERSION_0_LATE, // KQ4, LSL2, LSL3, SQ3 etc
SCI_VERSION_01, // KQ1 and multilingual games (S.old.*)
- SCI_VERSION_1_EGA, // EGA with parser, QFG2
- SCI_VERSION_1_EARLY, // KQ5. (EGA/VGA)
- SCI_VERSION_1_MIDDLE, // LSL1, JONESCD. (EGA?/VGA)
- SCI_VERSION_1_LATE, // ECO1, LSL5. (EGA/VGA)
- SCI_VERSION_1_1, // KQ6, ECO2
- SCI_VERSION_2, // GK1, PQ4 (Floppy), QFG4 (Floppy)
- SCI_VERSION_2_1, // GK2, KQ7, SQ6, Torin
- SCI_VERSION_3 // LSL7, RAMA, Lighthouse
+ SCI_VERSION_1_EGA_ONLY, // SCI 1 EGA with parser (i.e. QFG2 only)
+ SCI_VERSION_1_EARLY, // KQ5 floppy, SQ4 floppy, XMAS card 1990, Fairy tales, Jones floppy
+ SCI_VERSION_1_MIDDLE, // LSL1, Jones CD
+ SCI_VERSION_1_LATE, // Dr. Brain 1, EcoQuest 1, Longbow, PQ3, SQ1, LSL5, KQ5 CD
+ SCI_VERSION_1_1, // Dr. Brain 2, EcoQuest 1 CD, EcoQuest 2, KQ6, QFG3, SQ4CD, XMAS 1992 and many more
+ SCI_VERSION_2, // GK1, PQ4 floppy, QFG4 floppy
+ SCI_VERSION_2_1, // GK2, KQ7, LSL6 hires, MUMG Deluxe, Phantasmagoria 1, PQ4CD, PQ:SWAT, QFG4CD, Shivers 1, SQ6, Torin
+ SCI_VERSION_3 // LSL7, Lighthouse, RAMA, Phantasmagoria 2
};
/** Supported languages */
@@ -234,6 +237,10 @@ public:
Common::Platform getPlatform() const;
bool isDemo() const;
bool isCD() const;
+
+ /** Returns true if the game's original platform is big-endian. */
+ bool isBE() const;
+
bool hasMacIconBar() const;
inline ResourceManager *getResMan() const { return _resMan; }
@@ -242,7 +249,6 @@ public:
inline Vocabulary *getVocabulary() const { return _vocabulary; }
inline EventManager *getEventManager() const { return _eventMan; }
inline reg_t getGameObject() const { return _gameObjectAddress; }
- inline reg_t getGameSuperClassAddress() const { return _gameSuperClassAddress; }
Common::RandomSource &getRNG() { return _rng; }
@@ -371,7 +377,6 @@ private:
int16 _vocabularyLanguage;
EventManager *_eventMan;
reg_t _gameObjectAddress; /**< Pointer to the game object */
- reg_t _gameSuperClassAddress; // Address of the super class of the game object
Console *_console;
Common::RandomSource _rng;
Common::MacResManager _macExecutable;
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp
index 73f471b247..53311b4252 100644
--- a/engines/sci/sound/audio.cpp
+++ b/engines/sci/sound/audio.cpp
@@ -195,7 +195,7 @@ static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSiz
uint32 tag = audioStream->readUint32BE();
- if (tag != MKID_BE('SOL\0')) {
+ if (tag != MKTAG('S','O','L',0)) {
warning("No 'SOL' FourCC found");
return false;
}
@@ -290,17 +290,17 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
Common::SeekableReadStream *compressedStream = new Common::MemoryReadStream(compressedData, audioRes->size, DisposeAfterUse::YES);
switch (audioCompressionType) {
- case MKID_BE('MP3 '):
+ case MKTAG('M','P','3',' '):
#ifdef USE_MAD
audioSeekStream = Audio::makeMP3Stream(compressedStream, DisposeAfterUse::YES);
#endif
break;
- case MKID_BE('OGG '):
+ case MKTAG('O','G','G',' '):
#ifdef USE_VORBIS
audioSeekStream = Audio::makeVorbisStream(compressedStream, DisposeAfterUse::YES);
#endif
break;
- case MKID_BE('FLAC'):
+ case MKTAG('F','L','A','C'):
#ifdef USE_FLAC
audioSeekStream = Audio::makeFLACStream(compressedStream, DisposeAfterUse::YES);
#endif
@@ -319,7 +319,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
data = readSOLAudio(&dataStream, size, audioFlags, flags);
}
- } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('RIFF')) {
+ } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKTAG('R','I','F','F')) {
// WAVE detected
Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
@@ -331,7 +331,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
waveStream->seek(0, SEEK_SET);
audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES);
- } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('FORM')) {
+ } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKTAG('F','O','R','M')) {
// AIFF detected
Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO);
diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp
index 057b7c177f..f00c99d5b5 100644
--- a/engines/sci/sound/drivers/adlib.cpp
+++ b/engines/sci/sound/drivers/adlib.cpp
@@ -26,6 +26,8 @@
#include "sci/sci.h"
#include "common/file.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "audio/fmopl.h"
#include "audio/softsynth/emumidi.h"
@@ -55,7 +57,7 @@ public:
virtual ~MidiDriver_AdLib() { }
// MidiDriver
- int open(bool isSCI0);
+ int openAdLib(bool isSCI0);
void close();
void send(uint32 b);
MidiChannel *allocateChannel() { return NULL; }
@@ -215,7 +217,7 @@ static const int ym3812_note[13] = {
0x2ae
};
-int MidiDriver_AdLib::open(bool isSCI0) {
+int MidiDriver_AdLib::openAdLib(bool isSCI0) {
int rate = _mixer->getOutputRate();
_stereo = STEREO;
@@ -273,10 +275,6 @@ void MidiDriver_AdLib::send(uint32 b) {
case 0x90:
noteOn(channel, op1, op2);
break;
- case 0xe0:
- _channels[channel].pitchWheel = (op1 & 0x7f) | ((op2 & 0x7f) << 7);
- renewNotes(channel, true);
- break;
case 0xb0:
switch (op1) {
case 0x07:
@@ -321,7 +319,9 @@ void MidiDriver_AdLib::send(uint32 b) {
case 0xa0: // Polyphonic key pressure (aftertouch)
case 0xd0: // Channel pressure (aftertouch)
break;
- case 0xf0: // SysEx, ignore it
+ case 0xe0:
+ _channels[channel].pitchWheel = (op1 & 0x7f) | ((op2 & 0x7f) << 7);
+ renewNotes(channel, true);
break;
default:
warning("ADLIB: Unknown event %02x", command);
@@ -828,7 +828,7 @@ int MidiPlayer_AdLib::open(ResourceManager *resMan) {
return -1;
}
- return static_cast<MidiDriver_AdLib *>(_driver)->open(_version <= SCI_VERSION_0_LATE);
+ return static_cast<MidiDriver_AdLib *>(_driver)->openAdLib(_version <= SCI_VERSION_0_LATE);
}
void MidiPlayer_AdLib::close() {
diff --git a/engines/sci/sound/drivers/amigamac.cpp b/engines/sci/sound/drivers/amigamac.cpp
index 0ec4c283f7..7ee8d21f86 100644
--- a/engines/sci/sound/drivers/amigamac.cpp
+++ b/engines/sci/sound/drivers/amigamac.cpp
@@ -30,11 +30,13 @@
#include "common/file.h"
#include "common/frac.h"
#include "common/memstream.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Sci {
-/* #define DEBUG */
+//#define DEBUG
class MidiDriver_AmigaMac : public MidiDriver_Emulated {
public:
@@ -132,6 +134,7 @@ private:
};
bool _isSci1;
+ bool _isSci1Early; // KQ1 Amiga, patch 5
bool _playSwitch;
int _masterVolume;
int _frequency;
@@ -289,9 +292,9 @@ void MidiDriver_AmigaMac::playInstrument(int16 *dest, Voice *channel, int count)
void MidiDriver_AmigaMac::changeInstrument(int channel, int instrument) {
#ifdef DEBUG
if (_bank.instruments[instrument][0])
- debugN("[sfx:seq:amiga] Setting channel %i to \"%s\" (%i)\n", channel, _bank.instruments[instrument]->name, instrument);
+ debugN("Amiga/Mac driver: Setting channel %i to \"%s\" (%i)\n", channel, _bank.instruments[instrument].name, instrument);
else
- warning("[sfx:seq:amiga] instrument %i does not exist (channel %i)", instrument, channel);
+ warning("Amiga/Mac driver: instrument %i does not exist (channel %i)", instrument, channel);
#endif
_channels[channel].instrument = instrument;
}
@@ -326,7 +329,7 @@ void MidiDriver_AmigaMac::stopNote(int ch, int note) {
if (channel == kChannels) {
#ifdef DEBUG
- warning("[sfx:seq:amiga] cannot stop note %i on channel %i", note, ch);
+ warning("Amiga/Mac driver: cannot stop note %i on channel %i", note, ch);
#endif
return;
}
@@ -366,7 +369,7 @@ void MidiDriver_AmigaMac::setOutputFrac(int voice) {
fnote += instrument->transpose;
if (fnote < 0 || fnote > 127) {
- warning("[sfx:seq:amiga] illegal note %i", fnote);
+ warning("Amiga/Mac driver: illegal note %i", fnote);
return;
}
} else
@@ -403,14 +406,14 @@ void MidiDriver_AmigaMac::startNote(int ch, int note, int velocity) {
int channel;
if (_channels[ch].instrument < 0 || _channels[ch].instrument > 255) {
- warning("[sfx:seq:amiga] invalid instrument %i on channel %i", _channels[ch].instrument, ch);
+ warning("Amiga/Mac driver: invalid instrument %i on channel %i", _channels[ch].instrument, ch);
return;
}
InstrumentSample *instrument = findInstrument(_channels[ch].instrument, note);
if (!instrument) {
- warning("[sfx:seq:amiga] instrument %i does not exist", _channels[ch].instrument);
+ warning("Amiga/Mac driver: instrument %i does not exist", _channels[ch].instrument);
return;
}
@@ -419,7 +422,7 @@ void MidiDriver_AmigaMac::startNote(int ch, int note, int velocity) {
break;
if (channel == kChannels) {
- warning("[sfx:seq:amiga] could not find a free channel");
+ warning("Amiga/Mac driver: could not find a free channel");
return;
}
@@ -447,14 +450,14 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C
byte header[61];
if (file.read(header, 61) < 61) {
- warning("[sfx:seq:amiga] failed to read instrument header");
+ warning("Amiga/Mac driver: failed to read instrument header");
return NULL;
}
int seg_size[3];
- seg_size[0] = READ_BE_UINT16(header + 35) * 2;
- seg_size[1] = READ_BE_UINT16(header + 41) * 2;
- seg_size[2] = READ_BE_UINT16(header + 47) * 2;
+ seg_size[0] = (int16)READ_BE_UINT16(header + 35) * 2;
+ seg_size[1] = (int16)READ_BE_UINT16(header + 41) * 2;
+ seg_size[2] = (int16)READ_BE_UINT16(header + 47) * 2;
InstrumentSample *instrument = new InstrumentSample;
@@ -489,18 +492,18 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C
instrument->name[29] = 0;
#ifdef DEBUG
- debugN("[sfx:seq:amiga] Reading instrument %i: \"%s\" (%i bytes)\n",
+ debugN("Amiga/Mac driver: Reading instrument %i: \"%s\" (%i bytes)\n",
*id, instrument->name, size);
debugN(" Mode: %02x\n", instrument->mode);
debugN(" Looping: %s\n", instrument->mode & kModeLoop ? "on" : "off");
debugN(" Pitch changes: %s\n", instrument->mode & kModePitch ? "on" : "off");
debugN(" Segment sizes: %i %i %i\n", seg_size[0], seg_size[1], seg_size[2]);
- debugN(" Segment offsets: 0 %i %i\n", loop_offset, read_int32(header + 43));
+ debugN(" Segment offsets: 0 %i %i\n", loop_offset, (int32)READ_BE_UINT32(header + 43));
#endif
instrument->samples = (int8 *) malloc(size + 1);
if (file.read(instrument->samples, size) < (unsigned int)size) {
- warning("[sfx:seq:amiga] failed to read instrument samples");
+ warning("Amiga/Mac driver: failed to read instrument samples");
free(instrument->samples);
delete instrument;
return NULL;
@@ -512,14 +515,14 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C
if (instrument->mode & kModeLoop) {
if (loop_offset + seg_size[1] > size) {
#ifdef DEBUG
- warning("[sfx:seq:amiga] looping samples extend %i bytes past end of sample block",
+ warning("Amiga/Mac driver: looping samples extend %i bytes past end of sample block",
loop_offset + seg_size[1] - size);
#endif
seg_size[1] = size - loop_offset;
}
if (seg_size[1] < 0) {
- warning("[sfx:seq:amiga] invalid looping point");
+ warning("Amiga/Mac driver: invalid looping point");
free(instrument->samples);
delete instrument;
return NULL;
@@ -557,6 +560,7 @@ uint32 MidiDriver_AmigaMac::property(int prop, uint32 param) {
int MidiDriver_AmigaMac::open() {
_isSci1 = false;
+ _isSci1Early = false;
for (int i = 0; i < 48; i++)
_freqTable[i] = pow(2, i / (double)48);
@@ -589,9 +593,15 @@ int MidiDriver_AmigaMac::open() {
} else {
ResourceManager *resMan = g_sci->getResMan();
- Resource *resource = resMan->findResource(ResourceId(kResourceTypePatch, 7), false);
+ Resource *resource = resMan->findResource(ResourceId(kResourceTypePatch, 7), false); // Mac
if (!resource)
- resource = resMan->findResource(ResourceId(kResourceTypePatch, 9), false);
+ resource = resMan->findResource(ResourceId(kResourceTypePatch, 9), false); // Amiga
+
+ if (!resource) {
+ resource = resMan->findResource(ResourceId(kResourceTypePatch, 5), false); // KQ1 Amiga
+ if (resource)
+ _isSci1Early = true;
+ }
// If we have a patch by this point, it's SCI1
if (resource)
@@ -666,26 +676,42 @@ void MidiDriver_AmigaMac::send(uint32 b) {
case 0x07:
_channels[channel].volume = op2;
break;
- case 0x0a:
+ case 0x0a: // pan
+ // TODO
+#ifdef DEBUG
+ warning("Amiga/Mac driver: ignoring pan 0x%02x event for channel %i", op2, channel);
+#endif
+ break;
+ case 0x40: // hold
+ // TODO
#ifdef DEBUG
- warning("[sfx:seq:amiga] ignoring pan 0x%02x event for channel %i", op2, channel);
+ warning("Amiga/Mac driver: ignoring hold 0x%02x event for channel %i", op2, channel);
#endif
break;
+ case 0x4b: // voice mapping
+ break;
+ case 0x4e: // velocity
+ break;
case 0x7b:
stopChannel(channel);
break;
default:
- warning("[sfx:seq:amiga] unknown control event 0x%02x", op1);
+ //warning("Amiga/Mac driver: unknown control event 0x%02x", op1);
+ break;
}
break;
case 0xc0:
changeInstrument(channel, op1);
break;
+ // The original MIDI driver from sierra ignores aftertouch completely, so should we
+ case 0xa0: // Polyphonic key pressure (aftertouch)
+ case 0xd0: // Channel pressure (aftertouch)
+ break;
case 0xe0:
pitchWheel(channel, (op2 << 7) | op1);
break;
default:
- warning("[sfx:seq:amiga] unknown event %02x", command);
+ warning("Amiga/Mac driver: unknown event %02x", command);
}
}
@@ -738,7 +764,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) {
byte header[40];
if (file.read(header, 40) < 40) {
- warning("[sfx:seq:amiga] failed to read header of file bank.001");
+ warning("Amiga/Mac driver: failed to read header of file bank.001");
return false;
}
@@ -746,7 +772,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) {
strncpy(_bank.name, (char *) header + 8, 29);
_bank.name[29] = 0;
#ifdef DEBUG
- debugN("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
+ debugN("Amiga/Mac driver: Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
#endif
for (uint i = 0; i < _bank.size; i++) {
@@ -754,12 +780,12 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) {
InstrumentSample *instrument = readInstrumentSCI0(file, &id);
if (!instrument) {
- warning("[sfx:seq:amiga] failed to read bank.001");
+ warning("Amiga/Mac driver: failed to read bank.001");
return false;
}
if (id < 0 || id > 255) {
- warning("[sfx:seq:amiga] Error: instrument ID out of bounds");
+ warning("Amiga/Mac driver: Error: instrument ID out of bounds");
return false;
}
@@ -777,7 +803,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil
byte header[40];
if (file.read(header, 40) < 40) {
- warning("[sfx:seq:amiga] failed to read header of file patch.200");
+ warning("Amiga/Mac driver: failed to read header of file patch.200");
return false;
}
@@ -785,7 +811,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil
strncpy(_bank.name, (char *) header + 8, 29);
_bank.name[29] = 0;
#ifdef DEBUG
- debugN("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
+ debugN("Amiga/Mac driver: Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
#endif
Common::Array<uint32> instrumentOffsets;
@@ -848,7 +874,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil
instrument->samples = (int8 *)malloc(size + 1);
if (file.read(instrument->samples, size) < size) {
- warning("[sfx:seq:amiga] failed to read instrument sample");
+ warning("Amiga/Mac driver: failed to read instrument sample");
free(instrument->samples);
delete instrument;
continue;
@@ -880,6 +906,9 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil
bool MidiDriver_AmigaMac::loadInstrumentsSCI1(Common::SeekableReadStream &file) {
_bank.size = 128;
+ if (_isSci1Early)
+ file.skip(4); // TODO: What is this offset for?
+
Common::Array<uint32> instrumentOffsets;
instrumentOffsets.resize(_bank.size);
_bank.instruments.resize(_bank.size);
@@ -892,11 +921,17 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI1(Common::SeekableReadStream &file)
if (instrumentOffsets[i] == 0)
continue;
- file.seek(instrumentOffsets[i]);
+ file.seek(instrumentOffsets[i] + (_isSci1Early ? 4 : 0));
// Read in the instrument name
file.read(_bank.instruments[i].name, 10); // last two bytes are always 0
+ // TODO: Finish off support of SCI1 early patches (patch.005 - KQ1 Amiga)
+ if (_isSci1Early) {
+ warning("Music patch 5 isn't supported yet - ignoring instrument %d", i);
+ continue;
+ }
+
for (uint32 j = 0; ; j++) {
InstrumentSample *sample = new InstrumentSample;
memset(sample, 0, sizeof(InstrumentSample));
diff --git a/engines/sci/sound/drivers/cms.cpp b/engines/sci/sound/drivers/cms.cpp
index ff38e1c554..47c59a1e3d 100644
--- a/engines/sci/sound/drivers/cms.cpp
+++ b/engines/sci/sound/drivers/cms.cpp
@@ -29,6 +29,8 @@
#include "audio/softsynth/cms.h"
#include "audio/mixer.h"
+#include "common/system.h"
+
#include "sci/resource.h"
namespace Sci {
@@ -785,7 +787,7 @@ public:
int open(ResourceManager *resMan) {
if (_driver)
- return MERR_ALREADY_OPEN;
+ return MidiDriver::MERR_ALREADY_OPEN;
_driver = new MidiDriver_CMS(g_system->getMixer(), resMan);
int driverRetVal = _driver->open();
diff --git a/engines/sci/sound/drivers/fb01.cpp b/engines/sci/sound/drivers/fb01.cpp
index ce48b7f1f8..f217738bb2 100644
--- a/engines/sci/sound/drivers/fb01.cpp
+++ b/engines/sci/sound/drivers/fb01.cpp
@@ -30,6 +30,7 @@
#include "common/file.h"
#include "common/system.h"
+#include "common/textconsole.h"
namespace Sci {
@@ -129,7 +130,7 @@ private:
MidiPlayer_Fb01::MidiPlayer_Fb01(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _timerParam(NULL), _timerProc(NULL) {
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI);
- _driver = createMidi(dev);
+ _driver = MidiDriver::createMidi(dev);
_sysExBuf[0] = 0x43;
_sysExBuf[1] = 0x75;
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index 08e93d3213..f36aac3a2a 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -28,9 +28,9 @@
#include "common/config-manager.h"
#include "common/file.h"
#include "common/memstream.h"
+#include "common/system.h"
#include "audio/fmopl.h"
-#include "audio/softsynth/emumidi.h"
#include "sci/resource.h"
#include "sci/engine/features.h"
@@ -104,7 +104,7 @@ private:
uint8 volume;
Channel() : mappedPatch(MIDI_UNMAPPED), patch(MIDI_UNMAPPED), velocityMapIdx(0), playing(false),
- keyShift(0), volAdjust(0), pan(0x80), hold(0), volume(0x7f) { }
+ keyShift(0), volAdjust(0), pan(0x40), hold(0), volume(0x7f) { }
};
bool _isMt32;
@@ -132,7 +132,7 @@ private:
MidiPlayer_Midi::MidiPlayer_Midi(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _isMt32(false), _hasReverb(false), _useMT32Track(true) {
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI);
- _driver = createMidi(dev);
+ _driver = MidiDriver::createMidi(dev);
if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32"))
_isMt32 = true;
@@ -248,11 +248,17 @@ void MidiPlayer_Midi::controlChange(int channel, int control, int value) {
_channels[channel].hold = value;
break;
+ case 0x4b: // voice mapping
+ break;
+ case 0x4e: // velocity
+ break;
case 0x7b:
if (!_channels[channel].playing)
return;
_channels[channel].playing = false;
+ default:
+ break;
}
_driver->send(0xb0 | channel, control, value);
@@ -387,7 +393,7 @@ int MidiPlayer_Midi::getVolume() {
void MidiPlayer_Midi::setReverb(int8 reverb) {
assert(reverb < kReverbConfigNr);
-
+
if (_hasReverb && (_reverb != reverb))
sendMt32SysEx(0x100001, _reverbConfig[reverb], 3, true);
@@ -604,41 +610,83 @@ void MidiPlayer_Midi::readMt32DrvData() {
if (f.open("MT32.DRV")) {
int size = f.size();
- assert(size >= 166);
-
- // Send before-SysEx text
- f.seek(0x59);
+ // Skip before-SysEx text
+ if (size == 1773 || size == 1759 || size == 1747) // XMAS88 / KQ4 early (0.000.253 / 0.000.274)
+ f.seek(0x59);
+ else if (size == 2771) // LSL2 early
+ f.seek(0x29);
+ else
+ error("Unknown MT32.DRV size (%d)", size);
// Skip 2 extra 0 bytes in some drivers
if (f.readUint16LE() != 0)
f.seek(-2, SEEK_CUR);
+ // Send before-SysEx text
sendMt32SysEx(0x200000, static_cast<Common::SeekableReadStream *>(&f), 20);
- // Send after-SysEx text (SSCI sends this before every song)
- sendMt32SysEx(0x200000, static_cast<Common::SeekableReadStream *>(&f), 20);
+ if (size != 2271) {
+ // Send after-SysEx text (SSCI sends this before every song).
+ // There aren't any SysEx calls in old drivers, so this can
+ // be sent right after the before-SysEx text.
+ sendMt32SysEx(0x200000, static_cast<Common::SeekableReadStream *>(&f), 20);
+ } else {
+ // Skip the after-SysEx text in the newer patch version, we'll send
+ // it after the SysEx messages are sent.
+ f.skip(20);
+ }
- // Save goodbye message
+ // Save goodbye message. This isn't a C string, so it may not be
+ // nul-terminated.
f.read(_goodbyeMsg, 20);
// Set volume
byte volume = CLIP<uint16>(f.readUint16LE(), 0, 100);
setMt32Volume(volume);
- byte reverbSysEx[13];
- // This old driver should have a full reverb SysEx
- if ((f.read(reverbSysEx, 13) != 13) || (reverbSysEx[0] != 0xf0) || (reverbSysEx[12] != 0xf7))
- error("Error reading MT32.DRV");
+ if (size == 2771) {
+ // MT32.DRV in LSL2 early contains more data, like a normal patch
+ byte reverb = f.readByte();
- // Send reverb SysEx
- sysEx(reverbSysEx + 1, 11);
- _hasReverb = false;
+ _hasReverb = true;
- f.seek(0x29);
+ // Skip reverb SysEx message
+ f.skip(11);
- // Read AdLib->MT-32 patch map
- for (int i = 0; i < 48; i++) {
- _patchMap[i] = f.readByte();
+ // Read reverb data (stored vertically - patch #3117434)
+ for (int j = 0; j < 3; ++j) {
+ for (int i = 0; i < kReverbConfigNr; i++) {
+ _reverbConfig[i][j] = f.readByte();
+ }
+ }
+
+ f.skip(2235); // skip driver code
+
+ // Patches 1-48
+ sendMt32SysEx(0x50000, static_cast<Common::SeekableReadStream *>(&f), 256);
+ sendMt32SysEx(0x50200, static_cast<Common::SeekableReadStream *>(&f), 128);
+
+ setReverb(reverb);
+
+ // Send the after-SysEx text
+ f.seek(0x3d);
+ sendMt32SysEx(0x200000, static_cast<Common::SeekableReadStream *>(&f), 20);
+ } else {
+ byte reverbSysEx[13];
+ // This old driver should have a full reverb SysEx
+ if ((f.read(reverbSysEx, 13) != 13) || (reverbSysEx[0] != 0xf0) || (reverbSysEx[12] != 0xf7))
+ error("Error reading MT32.DRV");
+
+ // Send reverb SysEx
+ sysEx(reverbSysEx + 1, 11);
+ _hasReverb = false;
+
+ f.seek(0x29);
+
+ // Read AdLib->MT-32 patch map
+ for (int i = 0; i < 48; i++) {
+ _patchMap[i] = f.readByte();
+ }
}
f.close();
@@ -697,7 +745,7 @@ uint8 MidiPlayer_Midi::getGmInstrument(const Mt32ToGmMap &Mt32Ins) {
void MidiPlayer_Midi::mapMt32ToGm(byte *data, size_t size) {
// FIXME: Clean this up
int memtimbres, patches;
- uint8 group, number, keyshift, finetune, bender_range;
+ uint8 group, number, keyshift, /*finetune,*/ bender_range;
uint8 *patchpointer;
uint32 pos;
int i;
@@ -736,7 +784,7 @@ void MidiPlayer_Midi::mapMt32ToGm(byte *data, size_t size) {
group = *patchpointer;
number = *(patchpointer + 1);
keyshift = *(patchpointer + 2);
- finetune = *(patchpointer + 3);
+ //finetune = *(patchpointer + 3);
bender_range = *(patchpointer + 4);
debugCN(kDebugLevelSound, " [%03d] ", i);
@@ -913,7 +961,7 @@ int MidiPlayer_Midi::open(ResourceManager *resMan) {
// TODO: The MT-32 <-> GM mapping hasn't been worked on for SCI1 games. Throw
// a warning to the user
- if (getSciVersion() >= SCI_VERSION_1_EGA)
+ 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 "
diff --git a/engines/sci/sound/drivers/mididriver.h b/engines/sci/sound/drivers/mididriver.h
index f745d62716..2038725dbe 100644
--- a/engines/sci/sound/drivers/mididriver.h
+++ b/engines/sci/sound/drivers/mididriver.h
@@ -76,7 +76,7 @@ enum {
#define SCI_MIDI_CONTROLLER(status) ((status & 0xF0) == 0xB0)
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public MidiDriver_BASE {
protected:
MidiDriver *_driver;
int8 _reverb;
@@ -91,10 +91,8 @@ public:
virtual int open(ResourceManager *resMan) { return _driver->open(); }
virtual void close() { _driver->close(); }
virtual void send(uint32 b) { _driver->send(b); }
- uint32 getBaseTempo() { return _driver->getBaseTempo(); }
+ virtual uint32 getBaseTempo() { return _driver->getBaseTempo(); }
virtual bool hasRhythmChannel() const = 0;
- MidiChannel *allocateChannel() { return _driver->allocateChannel(); }
- MidiChannel *getPercussionChannel() { return _driver->getPercussionChannel(); }
virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { _driver->setTimerCallback(timer_param, timer_proc); }
virtual byte getPlayId() const = 0;
diff --git a/engines/sci/sound/drivers/pcjr.cpp b/engines/sci/sound/drivers/pcjr.cpp
index 063332577e..4b1efb3c87 100644
--- a/engines/sci/sound/drivers/pcjr.cpp
+++ b/engines/sci/sound/drivers/pcjr.cpp
@@ -27,6 +27,9 @@
#include "audio/softsynth/emumidi.h"
+#include "common/debug.h"
+#include "common/system.h"
+
namespace Sci {
#define VOLUME_SHIFT 3
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index f0963e7d64..c7743ac587 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -75,7 +75,7 @@ void SciMusic::init() {
deviceFlags |= MDT_PREFER_GM;
// Currently our CMS implementation only supports SCI1(.1)
- if (getSciVersion() >= SCI_VERSION_1_EGA && getSciVersion() <= SCI_VERSION_1_1)
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY && getSciVersion() <= SCI_VERSION_1_1)
deviceFlags |= MDT_CMS;
uint32 dev = MidiDriver::detectDevice(deviceFlags);
@@ -303,7 +303,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
pSnd->hCurrentAud = Audio::SoundHandle();
} else {
// play MIDI track
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->soundType = Audio::Mixer::kMusicSoundType;
if (pSnd->pMidiParser == NULL) {
pSnd->pMidiParser = new MidiParser_SCI(_soundVersion, this);
@@ -318,10 +318,22 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel());
pSnd->pMidiParser->mainThreadBegin();
+ // loadMusic() below calls jumpToTick.
+ // Disable sound looping and hold before jumpToTick is called,
+ // otherwise the song may keep looping forever when it ends in
+ // jumpToTick (e.g. LSL3, when going left from room 210).
+ uint16 prevLoop = pSnd->loop;
+ int16 prevHold = pSnd->hold;
+ pSnd->loop = 0;
+ pSnd->hold = -1;
+
pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
pSnd->reverb = pSnd->pMidiParser->getSongReverb();
+
+ // Restore looping and hold
+ pSnd->loop = prevLoop;
+ pSnd->hold = prevHold;
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
}
}
@@ -428,26 +440,52 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
}
} else {
if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
+
+ if (pSnd->status != kSoundPaused) {
+ // Stop any in progress music fading, as that will reset the
+ // volume of the sound channels that the faded song occupies..
+ // Fixes bug #3266480 and partially fixes bug #3041738.
+ for (uint i = 0; i < playListCount; i++) {
+ // Is another MIDI song being faded? If yes, stop it
+ // immediately instead
+ if (_playList[i]->fadeStep && _playList[i]->pMidiParser) {
+ _playList[i]->status = kSoundStopped;
+ if (_soundVersion <= SCI_VERSION_0_LATE)
+ _playList[i]->isQueued = false;
+ _playList[i]->pMidiParser->stop();
+ freeChannels(_playList[i]);
+ _playList[i]->fadeStep = 0;
+ }
+ }
+ }
+
pSnd->pMidiParser->tryToOwnChannels();
if (pSnd->status != kSoundPaused)
pSnd->pMidiParser->sendInitCommands();
pSnd->pMidiParser->setVolume(pSnd->volume);
- if (pSnd->status == kSoundStopped) {
+
+ // Disable sound looping and hold before jumpToTick is called,
+ // otherwise the song may keep looping forever when it ends in jumpToTick.
+ // This is needed when loading saved games, or when a game
+ // stops the same sound twice (e.g. LSL3 Amiga, going left from
+ // room 210 to talk with Kalalau). Fixes bugs #3083151 and #3106107.
+ uint16 prevLoop = pSnd->loop;
+ int16 prevHold = pSnd->hold;
+ pSnd->loop = 0;
+ pSnd->hold = -1;
+
+ if (pSnd->status == kSoundStopped)
pSnd->pMidiParser->jumpToTick(0);
- } else {
- // Disable sound looping before fast forwarding to the last position,
- // when loading a saved game. Fixes bug #3083151.
- uint16 prevLoop = pSnd->loop;
- pSnd->loop = 0;
+ else
// Fast forward to the last position and perform associated events when loading
pSnd->pMidiParser->jumpToTick(pSnd->ticker, true, true, true);
- // Restore looping
- pSnd->loop = prevLoop;
- }
+
+ // Restore looping and hold
+ pSnd->loop = prevLoop;
+ pSnd->hold = prevHold;
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
}
@@ -463,7 +501,7 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
_pMixer->stopHandle(pSnd->hCurrentAud);
if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
// We shouldn't call stop in case it's paused, otherwise we would send
// allNotesOff() again
@@ -471,7 +509,6 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
pSnd->pMidiParser->stop();
freeChannels(pSnd);
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
pSnd->fadeStep = 0; // end fading, if fading was in progress
@@ -483,11 +520,10 @@ void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
// we simply ignore volume changes for samples, because sierra sci also
// doesn't support volume for samples via kDoSound
} else if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->setVolume(volume);
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
}
@@ -509,13 +545,12 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
pSnd->status = kSoundStopped;
if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->unloadMusic();
pSnd->pMidiParser->mainThreadEnd();
delete pSnd->pMidiParser;
pSnd->pMidiParser = NULL;
- _mutex.unlock();
}
if (pSnd->pStreamAud) {
@@ -526,7 +561,7 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
pSnd->pLoopStream = 0;
}
- _mutex.lock();
+ Common::StackLock lock(_mutex);
uint sz = _playList.size(), i;
// Remove sound from playlist
for (i = 0; i < sz; i++) {
@@ -537,7 +572,6 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
break;
}
}
- _mutex.unlock();
}
void SciMusic::soundPause(MusicEntry *pSnd) {
@@ -560,12 +594,11 @@ void SciMusic::soundPause(MusicEntry *pSnd) {
_pMixer->pauseHandle(pSnd->hCurrentAud, true);
} else {
if (pSnd->pMidiParser) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->pause();
freeChannels(pSnd);
pSnd->pMidiParser->mainThreadEnd();
- _mutex.unlock();
}
}
}
@@ -630,9 +663,11 @@ void SciMusic::printPlayList(Console *con) {
for (uint32 i = 0; i < _playList.size(); i++) {
MusicEntry *song = _playList[i];
- con->DebugPrintf("%d: %04x:%04x, resource id: %d, status: %s, %s type\n", i,
- PRINT_REG(song->soundObj), song->resourceId,
- musicStatus[song->status], song->pMidiParser ? "MIDI" : "digital audio");
+ 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],
+ song->pMidiParser ? "MIDI" : "digital audio");
}
}
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 45a3e09453..a2b09eab4c 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -345,7 +345,25 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) {
musicSlot->fadeStep = volume > musicSlot->fadeTo ? -5 : 5;
musicSlot->fadeTickerStep = argv[2].toUint16() * 16667 / _music->soundGetTempo();
musicSlot->fadeTicker = 0;
- musicSlot->stopAfterFading = (argc == 5) ? (argv[4].toUint16() != 0) : false;
+
+ if (argc == 5) {
+ // TODO: We currently treat this argument as a boolean, but may
+ // have to handle different non-zero values differently. (e.g.,
+ // some KQ6 scripts pass 3 here)
+ musicSlot->stopAfterFading = (argv[4].toUint16() != 0);
+ } else {
+ musicSlot->stopAfterFading = false;
+ }
+
+ // WORKAROUND/HACK: In the labyrinth in KQ6, when falling in the pit and
+ // lighting the lantern, the game scripts perform a fade in of the game
+ // music, but set it to stop after fading. Remove that flag here. This is
+ // marked as both a workaround and a hack because this issue could be a
+ // problem with our fading code and an incorrect handling of that
+ // parameter, or a script bug in that scene. Fixes bug #3267956.
+ if (g_sci->getGameId() == GID_KQ6 && g_sci->getEngineState()->currentRoomNumber() == 406 &&
+ musicSlot->resourceId == 400)
+ musicSlot->stopAfterFading = false;
break;
default:
@@ -445,8 +463,16 @@ void SoundCommandParser::processUpdateCues(reg_t obj) {
if (musicSlot->fadeCompleted) {
musicSlot->fadeCompleted = false;
- // We need signal for sci0 at least in iceman as well (room 14, fireworks)
- writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ // We need signal for sci0 at least in iceman as well (room 14,
+ // fireworks).
+ // It is also needed in other games, e.g. LSL6 when talking to the
+ // receptionist (bug #3192166).
+ if (g_sci->getGameId() == GID_LONGBOW && g_sci->getEngineState()->currentRoomNumber() == 95) {
+ // HACK: Don't set a signal here in the intro of Longbow, as that makes some dialog
+ // boxes disappear too soon (bug #3044844).
+ } else {
+ writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
+ }
if (_soundVersion <= SCI_VERSION_0_LATE) {
processStopSound(obj, false);
} else {
diff --git a/engines/sci/util.cpp b/engines/sci/util.cpp
index f6a2465682..f346adddeb 100644
--- a/engines/sci/util.cpp
+++ b/engines/sci/util.cpp
@@ -30,25 +30,39 @@
namespace Sci {
+uint16 READ_SCIENDIAN_UINT16(const void *ptr) {
+ if (g_sci->isBE())
+ return READ_BE_UINT16(ptr);
+ else
+ return READ_LE_UINT16(ptr);
+}
+
+void WRITE_SCIENDIAN_UINT16(void *ptr, uint16 val) {
+ if (g_sci->isBE())
+ WRITE_BE_UINT16(ptr, val);
+ else
+ WRITE_LE_UINT16(ptr, val);
+}
+
uint16 READ_SCI11ENDIAN_UINT16(const void *ptr) {
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1)
return READ_BE_UINT16(ptr);
-
- return READ_LE_UINT16(ptr);
+ else
+ return READ_LE_UINT16(ptr);
}
uint16 READ_SCI32ENDIAN_UINT16(const void *ptr) {
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1)
return READ_BE_UINT16(ptr);
-
- return READ_LE_UINT16(ptr);
+ else
+ return READ_LE_UINT16(ptr);
}
uint32 READ_SCI11ENDIAN_UINT32(const void *ptr) {
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1)
return READ_BE_UINT32(ptr);
-
- return READ_LE_UINT32(ptr);
+ else
+ return READ_LE_UINT32(ptr);
}
void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val) {
diff --git a/engines/sci/util.h b/engines/sci/util.h
index d9ced5c9f6..7a2abb1873 100644
--- a/engines/sci/util.h
+++ b/engines/sci/util.h
@@ -30,6 +30,11 @@
namespace Sci {
+// Wrappers for reading/writing 16-bit values in the endianness
+// of the original game platform.
+uint16 READ_SCIENDIAN_UINT16(const void *ptr);
+void WRITE_SCIENDIAN_UINT16(void *ptr, uint16 val);
+
// Wrappers for reading integer values for SCI1.1+.
// Mac versions have big endian data for some fields.
uint16 READ_SCI11ENDIAN_UINT16(const void *ptr);
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index bf52de67d5..debc75dffd 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -23,11 +23,10 @@
*
*/
-#include "common/debug.h"
-#include "common/endian.h"
#include "common/archive.h"
#include "common/stream.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "graphics/surface.h"
@@ -126,7 +125,7 @@ bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) {
readPaletteChunk(_header.paletteDataSize);
readFrameSizesChunk();
calculateVideoDimensions();
- _surface->create(_width, _height, 1);
+ _surface->create(_width, _height, Graphics::PixelFormat::createFormatCLUT8());
return true;
}
@@ -251,6 +250,11 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() {
_fileStream->skip(4); // unknown, almost always 0
uint16 frameX = _fileStream->readUint16();
uint16 frameY = _fileStream->readUint16();
+ // TODO: In v4 robot files, frameX and frameY have a different meaning.
+ // Set them both to 0 for v4 for now, so that robots in PQ:SWAT show up
+ // correctly.
+ if (_header.version == 4)
+ frameX = frameY = 0;
uint16 compressedSize = _fileStream->readUint16();
uint16 frameFragments = _fileStream->readUint16();
_fileStream->skip(4); // unknown
diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h
index 52bf0bad07..aeb638e019 100644
--- a/engines/sci/video/robot_decoder.h
+++ b/engines/sci/video/robot_decoder.h
@@ -32,6 +32,7 @@
#include "common/substream.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
+#include "graphics/pixelformat.h"
#include "video/video_decoder.h"
namespace Sci {
diff --git a/engines/sci/video/seq_decoder.cpp b/engines/sci/video/seq_decoder.cpp
index 0e69a9a352..7168496893 100644
--- a/engines/sci/video/seq_decoder.cpp
+++ b/engines/sci/video/seq_decoder.cpp
@@ -23,12 +23,10 @@
*
*/
-#include "common/debug.h"
#include "common/endian.h"
-#include "common/archive.h"
#include "common/stream.h"
#include "common/system.h"
-#include "common/util.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
@@ -61,7 +59,7 @@ bool SeqDecoder::loadStream(Common::SeekableReadStream *stream) {
_fileStream = stream;
_surface = new Graphics::Surface();
- _surface->create(SEQ_SCREEN_WIDTH, SEQ_SCREEN_HEIGHT, 1);
+ _surface->create(SEQ_SCREEN_WIDTH, SEQ_SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
_frameCount = _fileStream->readUint16LE();
diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h
index 70aaa661ae..70d3985ec5 100644
--- a/engines/sci/video/seq_decoder.h
+++ b/engines/sci/video/seq_decoder.h
@@ -26,8 +26,18 @@
#ifndef SCI_VIDEO_SEQ_DECODER_H
#define SCI_VIDEO_SEQ_DECODER_H
+#include "common/rational.h"
+#include "graphics/pixelformat.h"
#include "video/video_decoder.h"
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
namespace Sci {
/**
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 5906545917..13581c4b45 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -26,6 +26,7 @@
#include "common/system.h" // for setFocusRectangle/clearFocusRectangle
#include "scumm/scumm.h"
#include "scumm/actor.h"
+#include "scumm/actor_he.h"
#include "scumm/akos.h"
#include "scumm/boxes.h"
#include "scumm/charset.h"
@@ -75,7 +76,7 @@ void ActorHE::initActor(int mode) {
if (_vm->_game.heversion >= 61)
_flip = 0;
- _clipOverride = _vm->_actorClipOverride;
+ _clipOverride = ((ScummEngine_v60he *)_vm)->_actorClipOverride;
_auxBlock.reset();
}
@@ -241,7 +242,7 @@ void Actor::setActorWalkSpeed(uint newSpeedX, uint newSpeedY) {
int getAngleFromPos(int x, int y, bool useATAN) {
if (useATAN) {
double temp = atan2((double)x, (double)-y);
- return normalizeAngle((int)(temp * 180 / PI));
+ return normalizeAngle((int)(temp * 180 / M_PI));
} else {
if (ABS(y) * 2 < ABS(x)) {
if (x > 0)
@@ -1852,8 +1853,8 @@ void Actor::animateLimb(int limb, int f) {
byte *akos = _vm->getResourceAddress(rtCostume, _costume);
assert(akos);
- aksq = _vm->findResourceData(MKID_BE('AKSQ'), akos);
- akfo = _vm->findResourceData(MKID_BE('AKFO'), akos);
+ aksq = _vm->findResourceData(MKTAG('A','K','S','Q'), akos);
+ akfo = _vm->findResourceData(MKTAG('A','K','F','O'), akos);
size = _vm->getResourceDataSize(akfo) / 2;
@@ -2373,7 +2374,7 @@ void Actor::remapActorPaletteColor(int color, int new_color) {
return;
}
- akpl = _vm->findResourceData(MKID_BE('AKPL'), akos);
+ akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos);
if (!akpl) {
debugC(DEBUG_ACTORS, "Actor::remapActorPaletteColor: Can't remap actor %d, costume %d doesn't contain an AKPL block", _number, _costume);
return;
@@ -2408,7 +2409,7 @@ void Actor::remapActorPalette(int r_fact, int g_fact, int b_fact, int threshold)
return;
}
- akpl = _vm->findResourceData(MKID_BE('AKPL'), akos);
+ akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos);
if (!akpl) {
debugC(DEBUG_ACTORS, "Actor::remapActorPalette: Can't remap actor %d, costume %d doesn't contain an AKPL block", _number, _costume);
return;
@@ -2417,7 +2418,7 @@ void Actor::remapActorPalette(int r_fact, int g_fact, int b_fact, int threshold)
// Get the number palette entries
akpl_size = _vm->getResourceDataSize(akpl);
- rgbs = _vm->findResourceData(MKID_BE('RGBS'), akos);
+ rgbs = _vm->findResourceData(MKTAG('R','G','B','S'), akos);
if (!rgbs) {
debugC(DEBUG_ACTORS, "Actor::remapActorPalette: Can't remap actor %d costume %d doesn't contain an RGB block", _number, _costume);
@@ -2534,19 +2535,19 @@ void ScummEngine_v71he::postProcessAuxQueue() {
if (_game.heversion >= 72)
dy -= a->getElevation();
- const uint8 *akax = findResource(MKID_BE('AKAX'), cost);
+ const uint8 *akax = findResource(MKTAG('A','K','A','X'), cost);
assert(akax);
const uint8 *auxd = findPalInPals(akax, ae->subIndex) - _resourceHeaderSize;
assert(auxd);
- const uint8 *frel = findResourceData(MKID_BE('FREL'), auxd);
+ const uint8 *frel = findResourceData(MKTAG('F','R','E','L'), auxd);
if (frel) {
error("unhandled FREL block");
}
- const uint8 *disp = findResourceData(MKID_BE('DISP'), auxd);
+ const uint8 *disp = findResourceData(MKTAG('D','I','S','P'), auxd);
if (disp) {
error("unhandled DISP block");
}
- const uint8 *axfd = findResourceData(MKID_BE('AXFD'), auxd);
+ const uint8 *axfd = findResourceData(MKTAG('A','X','F','D'), auxd);
assert(axfd);
uint16 comp = READ_LE_UINT16(axfd);
@@ -2566,7 +2567,7 @@ void ScummEngine_v71he::postProcessAuxQueue() {
error("unimplemented compression type %d", comp);
}
}
- const uint8 *axur = findResourceData(MKID_BE('AXUR'), auxd);
+ const uint8 *axur = findResourceData(MKTAG('A','X','U','R'), auxd);
if (axur) {
uint16 n = READ_LE_UINT16(axur); axur += 2;
while (n--) {
@@ -2578,7 +2579,7 @@ void ScummEngine_v71he::postProcessAuxQueue() {
axur += 8;
}
}
- const uint8 *axer = findResourceData(MKID_BE('AXER'), auxd);
+ const uint8 *axer = findResourceData(MKTAG('A','X','E','R'), auxd);
if (axer) {
a->_auxBlock.visible = true;
a->_auxBlock.r.left = (int16)READ_LE_UINT16(axer + 0) + dx;
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index 98854ec5ba..8e699b5a49 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -34,7 +34,6 @@
namespace Scumm {
-
enum {
V12_X_MULTIPLIER = 8,
V12_Y_MULTIPLIER = 2,
@@ -315,46 +314,6 @@ protected:
bool findPathTowards(byte box, byte box2, byte box3, Common::Point &foundPath);
};
-class ActorHE : public Actor {
-public:
- ActorHE(ScummEngine *scumm, int id) : Actor(scumm, id) {}
-
- virtual void initActor(int mode);
-
- virtual void hideActor();
-
- void drawActorToBackBuf(int x, int y);
-
- void setHEFlag(int bit, int set);
-
- void setUserCondition(int slot, int set);
- bool isUserConditionSet(int slot) const;
-
- void setTalkCondition(int slot);
- bool isTalkConditionSet(int slot) const;
-
-public:
- /** This rect is used to clip actor drawing. */
- Common::Rect _clipOverride;
-
- bool _heNoTalkAnimation;
- bool _heTalking;
- byte _heFlags;
-
- AuxBlock _auxBlock;
-
- struct {
- int16 posX;
- int16 posY;
- int16 color;
- byte sentence[128];
- } _heTalkQueue[16];
-
-
- virtual void prepareDrawActorCostume(BaseCostumeRenderer *bcr);
- virtual void setActorCostume(int c);
-};
-
class Actor_v3 : public Actor {
public:
Actor_v3(ScummEngine *scumm, int id) : Actor(scumm, id) {}
diff --git a/engines/scumm/actor_he.h b/engines/scumm/actor_he.h
new file mode 100644
index 0000000000..bb7bbb6487
--- /dev/null
+++ b/engines/scumm/actor_he.h
@@ -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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+
+#ifndef SCUMM_ACTOR_HE_H
+#define SCUMM_ACTOR_HE_H
+
+#include "scumm/actor.h"
+
+namespace Scumm {
+
+struct AuxBlock {
+ bool visible;
+ Common::Rect r;
+
+ void reset() {
+ visible = false;
+ r.left = r.top = 0;
+ r.right = r.bottom = -1;
+ }
+};
+
+struct AuxEntry {
+ int actorNum;
+ int subIndex;
+};
+
+class ActorHE : public Actor {
+public:
+ ActorHE(ScummEngine *scumm, int id) : Actor(scumm, id) {}
+
+ virtual void initActor(int mode);
+
+ virtual void hideActor();
+
+ void drawActorToBackBuf(int x, int y);
+
+ void setHEFlag(int bit, int set);
+
+ void setUserCondition(int slot, int set);
+ bool isUserConditionSet(int slot) const;
+
+ void setTalkCondition(int slot);
+ bool isTalkConditionSet(int slot) const;
+
+public:
+ /** This rect is used to clip actor drawing. */
+ Common::Rect _clipOverride;
+
+ bool _heNoTalkAnimation;
+ bool _heTalking;
+ byte _heFlags;
+
+ AuxBlock _auxBlock;
+
+ struct {
+ int16 posX;
+ int16 posY;
+ int16 color;
+ byte sentence[128];
+ } _heTalkQueue[16];
+
+
+ virtual void prepareDrawActorCostume(BaseCostumeRenderer *bcr);
+ virtual void setActorCostume(int c);
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 354a1d4491..8acbb8058e 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -146,7 +146,7 @@ void AkosCostumeLoader::loadCostume(int id) {
bool AkosCostumeLoader::hasManyDirections() {
const AkosHeader *akhd;
- akhd = (const AkosHeader *)_vm->findResourceData(MKID_BE('AKHD'), _akos);
+ akhd = (const AkosHeader *)_vm->findResourceData(MKTAG('A','K','H','D'), _akos);
return (akhd->flags & 2) != 0;
}
@@ -170,12 +170,12 @@ void AkosCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) {
else
anim = newDirToOldDir(a->getFacing()) + frame * 4;
- akhd = (const AkosHeader *)_vm->findResourceData(MKID_BE('AKHD'), _akos);
+ akhd = (const AkosHeader *)_vm->findResourceData(MKTAG('A','K','H','D'), _akos);
if (anim >= READ_LE_UINT16(&akhd->num_anims))
return;
- r = _vm->findResourceData(MKID_BE('AKCH'), _akos);
+ r = _vm->findResourceData(MKTAG('A','K','C','H'), _akos);
assert(r);
offs = READ_LE_UINT16(r + anim * sizeof(uint16));
@@ -183,8 +183,8 @@ void AkosCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) {
return;
r += offs;
- const uint8 *akstPtr = _vm->findResourceData(MKID_BE('AKST'), _akos);
- const uint8 *aksfPtr = _vm->findResourceData(MKID_BE('AKSF'), _akos);
+ const uint8 *akstPtr = _vm->findResourceData(MKTAG('A','K','S','T'), _akos);
+ const uint8 *aksfPtr = _vm->findResourceData(MKTAG('A','K','S','F'), _akos);
i = 0;
mask = READ_LE_UINT16(r); r += 2;
@@ -341,21 +341,21 @@ void AkosRenderer::setCostume(int costume, int shadow) {
const byte *akos = _vm->getResourceAddress(rtCostume, costume);
assert(akos);
- akhd = (const AkosHeader *) _vm->findResourceData(MKID_BE('AKHD'), akos);
- akof = (const AkosOffset *) _vm->findResourceData(MKID_BE('AKOF'), akos);
- akci = _vm->findResourceData(MKID_BE('AKCI'), akos);
- aksq = _vm->findResourceData(MKID_BE('AKSQ'), akos);
- akcd = _vm->findResourceData(MKID_BE('AKCD'), akos);
- akpl = _vm->findResourceData(MKID_BE('AKPL'), akos);
+ akhd = (const AkosHeader *) _vm->findResourceData(MKTAG('A','K','H','D'), akos);
+ akof = (const AkosOffset *) _vm->findResourceData(MKTAG('A','K','O','F'), akos);
+ akci = _vm->findResourceData(MKTAG('A','K','C','I'), akos);
+ aksq = _vm->findResourceData(MKTAG('A','K','S','Q'), akos);
+ akcd = _vm->findResourceData(MKTAG('A','K','C','D'), akos);
+ akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos);
_codec = READ_LE_UINT16(&akhd->codec);
- akct = _vm->findResourceData(MKID_BE('AKCT'), akos);
- rgbs = _vm->findResourceData(MKID_BE('RGBS'), akos);
+ akct = _vm->findResourceData(MKTAG('A','K','C','T'), akos);
+ rgbs = _vm->findResourceData(MKTAG('R','G','B','S'), akos);
xmap = 0;
if (shadow) {
const uint8 *xmapPtr = _vm->getResourceAddress(rtImage, shadow);
assert(xmapPtr);
- xmap = _vm->findResourceData(MKID_BE('XMAP'), xmapPtr);
+ xmap = _vm->findResourceData(MKTAG('X','M','A','P'), xmapPtr);
assert(xmap);
}
}
@@ -1384,8 +1384,8 @@ bool ScummEngine_v6::akos_increaseAnims(const byte *akos, Actor *a) {
uint size;
bool result;
- aksq = findResourceData(MKID_BE('AKSQ'), akos);
- akfo = findResourceData(MKID_BE('AKFO'), akos);
+ aksq = findResourceData(MKTAG('A','K','S','Q'), akos);
+ akfo = findResourceData(MKTAG('A','K','F','O'), akos);
size = getResourceDataSize(akfo) / 2;
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 861e448221..9fb76d9d63 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -401,7 +401,7 @@ int CharsetRendererClassic::getCharWidth(uint16 chr) {
spacing++;
}
}
-
+
} else if (chr >= 0x80) {
return _vm->_2byteWidth / 2;
}
@@ -618,11 +618,12 @@ int CharsetRendererV3::getCharWidth(uint16 chr) {
spacing = 4;
} else if (chr & 0x80) {
spacing = _vm->_2byteWidth / 2;
- }
+ }
}
- if (!spacing)
+ if (!spacing) {
spacing = *(_widthTable + chr);
+ }
return spacing;
}
@@ -777,7 +778,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
(ignoreCharsetMask || !vs->hasTwoBuffers)) {
dst = vs->getPixels(_left, drawTop);
if (charPtr)
- drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->bytesPerPixel);
+ drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->format.bytesPerPixel);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
else if (_vm->_cjkFont)
_vm->_cjkFont->drawChar(vs, chr, _left, drawTop, _color, _shadowColor);
@@ -785,7 +786,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
} else {
dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier);
if (charPtr)
- drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight, _vm->_textSurface.bytesPerPixel, (_vm->_textSurfaceMultiplier == 2 && !is2byte));
+ drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight, _vm->_textSurface.format.bytesPerPixel, (_vm->_textSurfaceMultiplier == 2 && !is2byte));
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
else if (_vm->_cjkFont)
_vm->_cjkFont->drawChar(_vm->_textSurface, chr, _left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier, _color, _shadowColor);
@@ -834,7 +835,7 @@ void CharsetRendererV3::drawChar(int chr, Graphics::Surface &s, int x, int y) {
height = 8;
}
dst = (byte *)s.pixels + y * s.pitch + x;
- drawBits1(s, dst, charPtr, y, width, height, s.bytesPerPixel);
+ drawBits1(s, dst, charPtr, y, width, height, s.format.bytesPerPixel);
}
void CharsetRenderer::translateColor() {
@@ -857,17 +858,17 @@ void CharsetRenderer::processTownsCharsetColors(uint8 bytesPerPixel) {
if (_vm->_game.platform == Common::kPlatformFMTowns) {
for (int i = 0; i < (1 << bytesPerPixel); i++) {
uint8 c = _vm->_charsetColorMap[i];
-
+
if (c > 16) {
uint8 t = (_vm->_currentPalette[c * 3] < 32) ? 4 : 12;
t |= ((_vm->_currentPalette[c * 3 + 1] < 32) ? 2 : 10);
t |= ((_vm->_currentPalette[c * 3 + 1] < 32) ? 1 : 9);
c = t;
}
-
+
if (c == 0)
c = _vm->_townsOverrideShadowColor;
-
+
c = ((c & 0x0f) << 4) | (c & 0x0f);
_vm->_townsCharsetColorMap[i] = c;
}
@@ -920,12 +921,12 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
noSjis = true;
}
}
-
+
if (useTownsFontRomCharacter(chr) && !noSjis) {
charPtr = 0;
_vm->_cjkChar = chr;
enableShadow(true);
-
+
width = getCharWidth(chr);
// For whatever reason MI1 uses a different font width
// for alignment calculation and for drawing when
@@ -947,7 +948,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
height++;
}
} else
-#endif
+#endif
{
uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
assert(charOffs < 0x14000);
@@ -1096,7 +1097,7 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
} else
#endif
if (is2byte) {
- drawBits1(dstSurface, dstPtr, charPtr, drawTop, origWidth, origHeight, dstSurface.bytesPerPixel);
+ drawBits1(dstSurface, dstPtr, charPtr, drawTop, origWidth, origHeight, dstSurface.format.bytesPerPixel);
} else {
drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight, _vm->_textSurfaceMultiplier == 2);
}
@@ -1173,7 +1174,7 @@ void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int
dst = (byte *)s.pixels + y * s.pitch + x;
if (is2byte) {
- drawBits1(s, dst, charPtr, y, width, height, s.bytesPerPixel);
+ drawBits1(s, dst, charPtr, y, width, height, s.format.bytesPerPixel);
} else {
drawBitsN(s, dst, charPtr, *_fontPtr, y, width, height);
}
@@ -1259,14 +1260,14 @@ void CharsetRendererCommon::drawBits1(const Graphics::Surface &s, byte *dst, con
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
byte *dst3 = dst2;
byte *dst4 = dst2;
- if (scale2x) {
+ if (scale2x) {
dst3 = dst2 + s.pitch;
dst4 = dst3 + s.pitch;
pitch <<= 1;
}
if (_vm->_game.platform == Common::kPlatformFMTowns && _vm->_game.version == 5)
col = _vm->_townsCharsetColorMap[1];
-#endif
+#endif
for (y = 0; y < height && y + drawTop < s.h; y++) {
for (x = 0; x < width; x++) {
@@ -1287,19 +1288,19 @@ void CharsetRendererCommon::drawBits1(const Graphics::Surface &s, byte *dst, con
if (scale2x) {
dst[2] = dst[3] = dst2[2] = dst2[3] = _shadowColor;
dst3[0] = dst4[0] = dst3[1] = dst4[1] = _shadowColor;
- } else
+ } else
#endif
{
dst[1] = dst2[0] = _shadowColor;
if (_shadowMode != kFMTOWNSShadowMode)
dst2[1] = _shadowColor;
- }
+ }
}
dst[0] = col;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (scale2x)
- dst[1] = dst2[0] = dst2[1] = col;
+ dst[1] = dst2[0] = dst2[1] = col;
#endif
}
}
@@ -1317,7 +1318,7 @@ void CharsetRendererCommon::drawBits1(const Graphics::Surface &s, byte *dst, con
dst += pitch;
dst2 += pitch;
-#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
+#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
dst3 += pitch;
dst4 += pitch;
#endif
@@ -1519,10 +1520,10 @@ void CharsetRendererNES::printChar(int chr, bool ignoreCharsetMask) {
if (ignoreCharsetMask || !vs->hasTwoBuffers) {
dst = vs->getPixels(_left, drawTop);
- drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->bytesPerPixel);
+ drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->format.bytesPerPixel);
} else {
dst = (byte *)_vm->_textSurface.pixels + _top * _vm->_textSurface.pitch + _left;
- drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight, _vm->_textSurface.bytesPerPixel);
+ drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight, _vm->_textSurface.format.bytesPerPixel);
}
if (_str.left > _left)
@@ -1552,7 +1553,7 @@ void CharsetRendererNES::drawChar(int chr, Graphics::Surface &s, int x, int y) {
height = 8;
dst = (byte *)s.pixels + y * s.pitch + x;
- drawBits1(s, dst, charPtr, y, width, height, s.bytesPerPixel);
+ drawBits1(s, dst, charPtr, y, width, height, s.format.bytesPerPixel);
}
void CharsetRendererNES::drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height, uint8 bitDepth, bool scalex) {
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index cd366fcfd4..d0a3ec6e11 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -419,6 +419,11 @@ void ClassicCostumeRenderer::procC64(Codec1 &v1, int actor) {
#undef MASK_AT
#ifdef USE_ARM_COSTUME_ASM
+
+#ifndef IPHONE
+#define ClassicProc3RendererShadowARM _ClassicProc3RendererShadowARM
+#endif
+
extern "C" int ClassicProc3RendererShadowARM(int _scaleY,
ClassicCostumeRenderer::Codec1 *v1,
Graphics::Surface *_out,
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index f49635d10f..820605924c 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -240,7 +240,7 @@ void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) {
room = getObjectRoom(img);
findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room);
- imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), foir.obim);
+ imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), foir.obim);
if (_game.version == 8) {
setCursorHotspot(READ_LE_UINT32(&imhd->v8.hotspot[0].x),
@@ -270,7 +270,7 @@ void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) {
if (size > sizeof(_grabbedCursor))
error("setCursorFromImg: Cursor image too large");
- bomp = findResource(MKID_BE('BOMP'), dataptr);
+ bomp = findResource(MKTAG('B','O','M','P'), dataptr);
}
if (bomp != NULL)
@@ -385,7 +385,7 @@ void ScummEngine_v5::redefineBuiltinCursorFromChar(int index, int chr) {
s.pitch = s.w;
// s.h = 17 for FM-TOWNS Loom Japanese. Fixes bug #1166917
assert(s.w <= 16 && s.h <= 17);
- s.bytesPerPixel = 1;
+ s.format = Graphics::PixelFormat::createFormatCLUT8();
_charset->drawChar(chr, s, 0, 0);
diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp
index cf0ee0fa0a..4c1942b865 100644
--- a/engines/scumm/debugger.cpp
+++ b/engines/scumm/debugger.cpp
@@ -23,7 +23,6 @@
*
*/
-#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/file.h"
#include "common/str.h"
@@ -479,7 +478,7 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) {
//is BgNeedsRedraw enough?
_vm->_bgNeedsRedraw = true;
} else {
- DebugPrintf("object command 'state' requires a parameter\n");
+ 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));
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 2a6de98dee..51b46b033c 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -23,6 +23,9 @@
*
*/
+// FIXME: Avoid using printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
+
#include "base/plugins.h"
#include "common/archive.h"
@@ -77,8 +80,6 @@ Common::String ScummEngine::generateFilename(const int room) const {
snprintf(buf, sizeof(buf), "disk%02d.lec", diskNumber);
}
} else {
- char id = 0;
-
switch (_filenamePattern.genMethod) {
case kGenDiskNum:
snprintf(buf, sizeof(buf), _filenamePattern.pattern, diskNumber);
@@ -88,59 +89,6 @@ Common::String ScummEngine::generateFilename(const int room) const {
snprintf(buf, sizeof(buf), _filenamePattern.pattern, room);
break;
- case kGenHEMac:
- case kGenHEMacNoParens:
- case kGenHEPC:
- if (room < 0) {
- id = '0' - room;
- } else if (_game.heversion >= 98) {
- int disk = 0;
- if (_heV7DiskOffsets)
- disk = _heV7DiskOffsets[room];
-
- switch (disk) {
- case 2:
- id = 'b';
- // Special cases for Blue's games, which share common (b) files
- if (_game.id == GID_BIRTHDAY && !(_game.features & GF_DEMO))
- strcpy(buf, "Blue'sBirthday.(b)");
- else if (_game.id == GID_TREASUREHUNT)
- strcpy(buf, "Blue'sTreasureHunt.(b)");
- else
- snprintf(buf, sizeof(buf), "%s.(b)", _filenamePattern.pattern);
- break;
- case 1:
- id = 'a';
- snprintf(buf, sizeof(buf), "%s.(a)", _filenamePattern.pattern);
- break;
- default:
- id = '0';
- snprintf(buf, sizeof(buf), "%s.he0", _filenamePattern.pattern);
- }
- } else if (_game.heversion >= 70) {
- id = (room == 0) ? '0' : '1';
- } else {
- id = diskNumber + '0';
- }
-
- if (_filenamePattern.genMethod == kGenHEPC) {
- // For HE >= 98, we already called snprintf above.
- if (_game.heversion < 98 || room < 0)
- snprintf(buf, sizeof(buf), "%s.he%c", _filenamePattern.pattern, id);
- } else {
- if (id == '3') { // special case for cursors
- // For mac they're stored in game binary
- strncpy(buf, _filenamePattern.pattern, sizeof(buf));
- } else {
- if (_filenamePattern.genMethod == kGenHEMac)
- snprintf(buf, sizeof(buf), "%s (%c)", _filenamePattern.pattern, id);
- else
- snprintf(buf, sizeof(buf), "%s %c", _filenamePattern.pattern, id);
- }
- }
-
- break;
-
case kGenUnchanged:
strncpy(buf, _filenamePattern.pattern, sizeof(buf));
break;
@@ -153,6 +101,109 @@ Common::String ScummEngine::generateFilename(const int room) const {
return buf;
}
+Common::String ScummEngine_v60he::generateFilename(const int room) const {
+ char buf[128];
+ char id = 0;
+
+ switch (_filenamePattern.genMethod) {
+ case kGenHEMac:
+ case kGenHEMacNoParens:
+ case kGenHEPC:
+ if (room < 0) {
+ id = '0' - room;
+ } else {
+ const int diskNumber = (room > 0) ? _res->roomno[rtRoom][room] : 0;
+ id = diskNumber + '0';
+ }
+
+ if (_filenamePattern.genMethod == kGenHEPC) {
+ snprintf(buf, sizeof(buf), "%s.he%c", _filenamePattern.pattern, id);
+ } else {
+ if (id == '3') { // special case for cursors
+ // For mac they're stored in game binary
+ strncpy(buf, _filenamePattern.pattern, sizeof(buf));
+ } else {
+ if (_filenamePattern.genMethod == kGenHEMac)
+ snprintf(buf, sizeof(buf), "%s (%c)", _filenamePattern.pattern, id);
+ else
+ snprintf(buf, sizeof(buf), "%s %c", _filenamePattern.pattern, id);
+ }
+ }
+
+ break;
+
+ default:
+ // Fallback to parent method
+ return ScummEngine::generateFilename(room);
+ }
+
+ return buf;
+}
+
+Common::String ScummEngine_v70he::generateFilename(const int room) const {
+ char buf[128];
+ char id = 0;
+
+ switch (_filenamePattern.genMethod) {
+ case kGenHEMac:
+ case kGenHEMacNoParens:
+ case kGenHEPC:
+ if (_game.heversion >= 98 && room >= 0) {
+ int disk = 0;
+ if (_heV7DiskOffsets)
+ disk = _heV7DiskOffsets[room];
+
+ switch (disk) {
+ case 2:
+ id = 'b';
+ // Special cases for Blue's games, which share common (b) files
+ if (_game.id == GID_BIRTHDAY && !(_game.features & GF_DEMO))
+ strcpy(buf, "Blue'sBirthday.(b)");
+ else if (_game.id == GID_TREASUREHUNT)
+ strcpy(buf, "Blue'sTreasureHunt.(b)");
+ else
+ snprintf(buf, sizeof(buf), "%s.(b)", _filenamePattern.pattern);
+ break;
+ case 1:
+ id = 'a';
+ snprintf(buf, sizeof(buf), "%s.(a)", _filenamePattern.pattern);
+ break;
+ default:
+ id = '0';
+ snprintf(buf, sizeof(buf), "%s.he0", _filenamePattern.pattern);
+ }
+ } else if (room < 0) {
+ id = '0' - room;
+ } else {
+ id = (room == 0) ? '0' : '1';
+ }
+
+ if (_filenamePattern.genMethod == kGenHEPC) {
+ // For HE >= 98, we already called snprintf above.
+ if (_game.heversion < 98 || room < 0)
+ snprintf(buf, sizeof(buf), "%s.he%c", _filenamePattern.pattern, id);
+ } else {
+ if (id == '3') { // special case for cursors
+ // For mac they're stored in game binary
+ strncpy(buf, _filenamePattern.pattern, sizeof(buf));
+ } else {
+ if (_filenamePattern.genMethod == kGenHEMac)
+ snprintf(buf, sizeof(buf), "%s (%c)", _filenamePattern.pattern, id);
+ else
+ snprintf(buf, sizeof(buf), "%s %c", _filenamePattern.pattern, id);
+ }
+ }
+
+ break;
+
+ default:
+ // Fallback to parent method
+ return ScummEngine_v60he::generateFilename(room);
+ }
+
+ return buf;
+}
+
static Common::String generateFilenameForDetection(const char *pattern, FilenameGenMethod genMethod) {
char buf[128];
@@ -946,7 +997,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
Common::FSList fslist;
Common::FSNode dir(ConfMan.get("path"));
if (!dir.isDirectory())
- return Common::kInvalidPathError;
+ return Common::kPathNotDirectory;
if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly))
return Common::kNoGameDataFoundError;
@@ -1083,6 +1134,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
break;
case 62:
case 61:
+ case 60:
*engine = new ScummEngine_v60he(syst, res);
break;
default:
@@ -1186,7 +1238,7 @@ SaveStateDescriptor ScummMetaEngine::querySaveMetaInfos(const char *target, int
desc.setDeletableFlag(true);
desc.setThumbnail(thumbnail);
- InfoStuff infos;
+ SaveStateMetaInfos infos;
memset(&infos, 0, sizeof(infos));
if (ScummEngine::loadInfosFromSlot(target, slot, &infos)) {
int day = (infos.date >> 24) & 0xFF;
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index a5542ca868..952abdb39a 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -372,7 +372,7 @@ static const GameSettings gameVariantsTable[] = {
{"arttime", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
{"baseball2001", 0, 0, GID_BASEBALL2001, 6, 99, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
{"readtime", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
- {"SoccerMLS", 0, 0, GID_SOCCER, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
+ {"SoccerMLS", 0, 0, GID_SOCCERMLS, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
{"spyozon", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
{"freddicove", "", 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
@@ -386,7 +386,7 @@ static const GameSettings gameVariantsTable[] = {
{"Baseball2003", 0, 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
{"basketball", 0, 0, GID_BASKETBALL, 6, 100, MDT_NONE, GF_USE_KEY| GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
{"football2002", 0, 0, GID_FOOTBALL, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
- {"Soccer2004", 0, 0, GID_SOCCER, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
+ {"Soccer2004", 0, 0, GID_SOCCER2004, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
// U32 code required, for testing only
{"moonbase", 0, 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
@@ -483,6 +483,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
#ifdef ENABLE_SCUMM_7_8
{ "dig", "dig.la%d", kGenDiskNum, UNK_LANG, UNK, 0 },
+ { "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.h b/engines/scumm/dialogs.h
index 0e6e18905f..40e549471b 100644
--- a/engines/scumm/dialogs.h
+++ b/engines/scumm/dialogs.h
@@ -33,8 +33,8 @@
#include "scumm/detection.h"
namespace GUI {
- class ListWidget;
- class CommandSender;
+class ListWidget;
+class CommandSender;
}
diff --git a/engines/scumm/file_nes.cpp b/engines/scumm/file_nes.cpp
index d9d84f04ff..47704d6eaf 100644
--- a/engines/scumm/file_nes.cpp
+++ b/engines/scumm/file_nes.cpp
@@ -28,6 +28,7 @@
#include "common/endian.h"
#include "common/md5.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
namespace Scumm {
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index 9efddc6ad2..e7abd5610e 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -36,6 +36,12 @@
#include "scumm/util.h"
#ifdef USE_ARM_GFX_ASM
+
+#ifndef IPHONE
+#define asmDrawStripToScreen _asmDrawStripToScreen
+#define asmCopy8Col _asmCopy8Col
+#endif
+
extern "C" void asmDrawStripToScreen(int height, int width, void const* text, void const* src, byte* dst,
int vsPitch, int vmScreenWidth, int textSurfacePitch);
extern "C" void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height, uint8 bitDepth);
@@ -283,7 +289,7 @@ void Gdi::loadTiles(byte *roomptr) {
#ifdef USE_RGB_COLOR
void GdiPCEngine::loadTiles(byte *roomptr) {
- decodePCEngineTileData(_vm->findResourceData(MKID_BE('TILE'), roomptr));
+ decodePCEngineTileData(_vm->findResourceData(MKTAG('T','I','L','E'), roomptr));
}
#endif
@@ -385,8 +391,11 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int
vs->hasTwoBuffers = twobufs;
vs->xstart = 0;
vs->backBuf = NULL;
- vs->bytesPerPixel = (_game.features & GF_16BIT_COLOR) ? 2 : 1;
- vs->pitch = width * vs->bytesPerPixel;
+ if (_game.features & GF_16BIT_COLOR)
+ vs->format = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ else
+ vs->format = Graphics::PixelFormat::createFormatCLUT8();
+ vs->pitch = width * vs->format.bytesPerPixel;
if (_game.version >= 7) {
// Increase the pitch by one; needed to accomodate the extra screen
@@ -622,7 +631,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
int m = _textSurfaceMultiplier;
int vsPitch;
int pitch = vs->pitch;
- vsPitch = vs->pitch - width * vs->bytesPerPixel;
+ vsPitch = vs->pitch - width * vs->format.bytesPerPixel;
if (_game.version < 7) {
@@ -667,7 +676,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
} else {
WRITE_UINT16(dstPtr, _16BitPalette[tmp]); dstPtr += 2;
}
- srcPtr += vs->bytesPerPixel;
+ srcPtr += vs->format.bytesPerPixel;
}
srcPtr += vsPitch;
textPtr += _textSurface.pitch - width * m;
@@ -706,7 +715,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
}
#endif
src = _compositeBuf;
- pitch = width * vs->bytesPerPixel;
+ pitch = width * vs->format.bytesPerPixel;
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height);
@@ -858,7 +867,7 @@ void ScummEngine::initBGBuffers(int height) {
_gdi->_numZBuffer = 2;
} else if (_game.features & GF_SMALL_HEADER) {
int off;
- ptr = findResourceData(MKID_BE('SMAP'), room);
+ ptr = findResourceData(MKTAG('S','M','A','P'), room);
_gdi->_numZBuffer = 0;
if (_game.features & GF_16COLOR)
@@ -873,13 +882,13 @@ void ScummEngine::initBGBuffers(int height) {
}
} else if (_game.version == 8) {
// in V8 there is no RMIH and num z buffers is in RMHD
- ptr = findResource(MKID_BE('RMHD'), room);
+ ptr = findResource(MKTAG('R','M','H','D'), room);
_gdi->_numZBuffer = READ_LE_UINT32(ptr + 24) + 1;
} else if (_game.heversion >= 70) {
- ptr = findResource(MKID_BE('RMIH'), room);
+ ptr = findResource(MKTAG('R','M','I','H'), room);
_gdi->_numZBuffer = READ_LE_UINT16(ptr + 8) + 1;
} else {
- ptr = findResource(MKID_BE('RMIH'), findResource(MKID_BE('RMIM'), room));
+ ptr = findResource(MKTAG('R','M','I','H'), findResource(MKTAG('R','M','I','M'), room));
_gdi->_numZBuffer = READ_LE_UINT16(ptr + 8) + 1;
}
assert(_gdi->_numZBuffer >= 1 && _gdi->_numZBuffer <= 8);
@@ -1036,17 +1045,17 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
return;
if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) {
- blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height, vs->bytesPerPixel);
+ blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height, vs->format.bytesPerPixel);
if (vs->number == kMainVirtScreen && _charset->_hasMask) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
byte *mask = (byte *)_textSurface.getBasePtr(rect.left * _textSurfaceMultiplier, (rect.top + vs->topline) * _textSurfaceMultiplier);
- fill(mask, _textSurface.pitch, 0, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
+ fill(mask, _textSurface.pitch, 0, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
} else
#endif
{
byte *mask = (byte *)_textSurface.getBasePtr(rect.left, rect.top - _screenTop);
- fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
+ fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
}
}
} else {
@@ -1054,14 +1063,14 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
if (_game.platform == Common::kPlatformFMTowns) {
backColor |= (backColor << 4);
byte *mask = (byte *)_textSurface.getBasePtr(rect.left * _textSurfaceMultiplier, (rect.top + vs->topline) * _textSurfaceMultiplier);
- fill(mask, _textSurface.pitch, backColor, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
+ fill(mask, _textSurface.pitch, backColor, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
}
#endif
if (_game.features & GF_16BIT_COLOR)
- fill(screenBuf, vs->pitch, _16BitPalette[backColor], width, height, vs->bytesPerPixel);
+ fill(screenBuf, vs->pitch, _16BitPalette[backColor], width, height, vs->format.bytesPerPixel);
else
- fill(screenBuf, vs->pitch, backColor, width, height, vs->bytesPerPixel);
+ fill(screenBuf, vs->pitch, backColor, width, height, vs->format.bytesPerPixel);
}
}
@@ -1090,7 +1099,7 @@ void ScummEngine::restoreCharsetBg() {
if (vs->number != kMainVirtScreen) {
// Restore from back buffer
const byte *backBuf = vs->getBackPixels(0, 0);
- blit(screenBuf, vs->pitch, backBuf, vs->pitch, vs->w, vs->h, vs->bytesPerPixel);
+ blit(screenBuf, vs->pitch, backBuf, vs->pitch, vs->w, vs->h, vs->format.bytesPerPixel);
}
} else {
// Clear area
@@ -1118,7 +1127,7 @@ void ScummEngine::clearTextSurface() {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_game.platform == Common::kPlatformFMTowns ? 0 :
#endif
- CHARSET_MASK_TRANSPARENCY, _textSurface.w, _textSurface.h, _textSurface.bytesPerPixel);
+ CHARSET_MASK_TRANSPARENCY, _textSurface.w, _textSurface.h, _textSurface.format.bytesPerPixel);
}
byte *ScummEngine::getMaskBuffer(int x, int y, int z) {
@@ -1283,66 +1292,64 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
- if (color == 254) {
- color = color;
+ if (color == 254)
towns_setupPalCycleField(x, y, x2, y2);
- }
} else
#endif
{
if (vs->number != kMainVirtScreen)
error("can only copy bg to main window");
- blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);
+ blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
if (_charset->_hasMask) {
byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier);
- fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
+ fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
}
}
} else if (_game.heversion >= 72) {
// Flags are used for different methods in HE games
uint32 flags = color;
if ((flags & 0x2000) || (flags & 0x4000000)) {
- blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);
+ blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
} else if ((flags & 0x4000) || (flags & 0x2000000)) {
- blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->bytesPerPixel);
+ blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
} else if ((flags & 0x8000) || (flags & 0x1000000)) {
flags &= (flags & 0x1000000) ? 0xFFFFFF : 0x7FFF;
- fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
- fill(bgbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
+ fill(backbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
+ fill(bgbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
} else {
- fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
+ fill(backbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
}
} else if (_game.heversion >= 60) {
// Flags are used for different methods in HE games
uint16 flags = color;
if (flags & 0x2000) {
- blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);
+ blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
} else if (flags & 0x4000) {
- blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->bytesPerPixel);
+ blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
} else if (flags & 0x8000) {
flags &= 0x7FFF;
- fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
- fill(bgbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
+ fill(backbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
+ fill(bgbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
} else {
- fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
+ fill(backbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
}
} else {
if (_game.features & GF_16BIT_COLOR) {
- fill(backbuff, vs->pitch, _16BitPalette[color], width, height, vs->bytesPerPixel);
+ fill(backbuff, vs->pitch, _16BitPalette[color], width, height, vs->format.bytesPerPixel);
} else {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
color = ((color & 0x0f) << 4) | (color & 0x0f);
byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop + vs->topline) * _textSurfaceMultiplier);
- fill(mask, _textSurface.pitch, color, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
+ fill(mask, _textSurface.pitch, color, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
if (_game.id == GID_MONKEY2 || _game.id == GID_INDY4 || ((_game.id == GID_INDY3 || _game.id == GID_ZAK) && vs->number != kTextVirtScreen) || (_game.id == GID_LOOM && vs->number == kMainVirtScreen))
return;
}
#endif
- fill(backbuff, vs->pitch, color, width, height, vs->bytesPerPixel);
+ fill(backbuff, vs->pitch, color, width, height, vs->format.bytesPerPixel);
}
}
}
@@ -1381,7 +1388,7 @@ void ScummEngine_v5::drawFlashlight() {
_flashlight.y, _flashlight.y + _flashlight.h, USAGE_BIT_DIRTY);
if (_flashlight.buffer) {
- fill(_flashlight.buffer, vs->pitch, 0, _flashlight.w, _flashlight.h, vs->bytesPerPixel);
+ fill(_flashlight.buffer, vs->pitch, 0, _flashlight.w, _flashlight.h, vs->format.bytesPerPixel);
}
_flashlight.isDrawn = false;
}
@@ -1428,20 +1435,20 @@ void ScummEngine_v5::drawFlashlight() {
_flashlight.buffer = vs->getPixels(_flashlight.x, _flashlight.y);
bgbak = vs->getBackPixels(_flashlight.x, _flashlight.y);
- blit(_flashlight.buffer, vs->pitch, bgbak, vs->pitch, _flashlight.w, _flashlight.h, vs->bytesPerPixel);
+ blit(_flashlight.buffer, vs->pitch, bgbak, vs->pitch, _flashlight.w, _flashlight.h, vs->format.bytesPerPixel);
// Round the corners. To do so, we simply hard-code a set of nicely
// rounded corners.
static const int corner_data[] = { 8, 6, 4, 3, 2, 2, 1, 1 };
int minrow = 0;
- int maxcol = (_flashlight.w - 1) * vs->bytesPerPixel;
+ int maxcol = (_flashlight.w - 1) * vs->format.bytesPerPixel;
int maxrow = (_flashlight.h - 1) * vs->pitch;
for (i = 0; i < 8; i++, minrow += vs->pitch, maxrow -= vs->pitch) {
int d = corner_data[i];
for (j = 0; j < d; j++) {
- if (vs->bytesPerPixel == 2) {
+ if (vs->format.bytesPerPixel == 2) {
WRITE_UINT16(&_flashlight.buffer[minrow + 2 * j], 0);
WRITE_UINT16(&_flashlight.buffer[minrow + maxcol - 2 * j], 0);
WRITE_UINT16(&_flashlight.buffer[maxrow + 2 * j], 0);
@@ -1649,9 +1656,9 @@ int Gdi::getZPlanes(const byte *ptr, const byte *zplane_list[9], bool bmapImage)
if ((_vm->_game.features & GF_SMALL_HEADER) || _vm->_game.version == 8)
zplane_list[0] = ptr;
else if (bmapImage)
- zplane_list[0] = _vm->findResource(MKID_BE('BMAP'), ptr);
+ zplane_list[0] = _vm->findResource(MKTAG('B','M','A','P'), ptr);
else
- zplane_list[0] = _vm->findResource(MKID_BE('SMAP'), ptr);
+ zplane_list[0] = _vm->findResource(MKTAG('S','M','A','P'), ptr);
if (_zbufferDisabled)
numzbuf = 0;
@@ -1694,11 +1701,11 @@ int Gdi::getZPlanes(const byte *ptr, const byte *zplane_list[9], bool bmapImage)
}
} else {
const uint32 zplane_tags[] = {
- MKID_BE('ZP00'),
- MKID_BE('ZP01'),
- MKID_BE('ZP02'),
- MKID_BE('ZP03'),
- MKID_BE('ZP04')
+ MKTAG('Z','P','0','0'),
+ MKTAG('Z','P','0','1'),
+ MKTAG('Z','P','0','2'),
+ MKTAG('Z','P','0','3'),
+ MKTAG('Z','P','0','4')
};
for (i = 1; i < numzbuf; i++) {
@@ -1735,7 +1742,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
// Skip to the BSTR->WRAP->OFFS chunk
smap_ptr = ptr + 24;
} else {
- smap_ptr = _vm->findResource(MKID_BE('SMAP'), ptr);
+ smap_ptr = _vm->findResource(MKTAG('S','M','A','P'), ptr);
assert(smap_ptr);
}
@@ -1743,7 +1750,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
const byte *tmsk_ptr = NULL;
if (_vm->_game.heversion >= 72) {
- tmsk_ptr = _vm->findResource(MKID_BE('TMSK'), ptr);
+ tmsk_ptr = _vm->findResource(MKTAG('T','M','S','K'), ptr);
}
if (y + height > vs->h) {
@@ -1757,7 +1764,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
}
#endif
- _vertStripNextInc = height * vs->pitch - 1 * vs->bytesPerPixel;
+ _vertStripNextInc = height * vs->pitch - 1 * vs->format.bytesPerPixel;
_objectMode = (flag & dbObjectMode) == dbObjectMode;
prepareDrawBitmap(ptr, vs, x, y, width, height, stripnr, numstrip);
@@ -1790,9 +1797,9 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
// In the case of a double buffered virtual screen, we draw to
// the backbuffer, otherwise to the primary surface memory.
if (vs->hasTwoBuffers)
- dstPtr = vs->backBuf + y * vs->pitch + (x * 8 * vs->bytesPerPixel);
+ dstPtr = vs->backBuf + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel);
else
- dstPtr = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->bytesPerPixel);
+ dstPtr = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel);
transpStrip = drawStrip(dstPtr, vs, x, y, width, height, stripnr, smap_ptr);
@@ -1801,11 +1808,11 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
transpStrip = true;
if (vs->hasTwoBuffers) {
- byte *frontBuf = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->bytesPerPixel);
+ byte *frontBuf = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel);
if (lightsOn)
- copy8Col(frontBuf, vs->pitch, dstPtr, height, vs->bytesPerPixel);
+ copy8Col(frontBuf, vs->pitch, dstPtr, height, vs->format.bytesPerPixel);
else
- clear8Col(frontBuf, vs->pitch, height, vs->bytesPerPixel);
+ clear8Col(frontBuf, vs->pitch, height, vs->format.bytesPerPixel);
}
decodeMask(x, y, width, height, stripnr, numzbuf, zplane_list, transpStrip, flag, tmsk_ptr);
@@ -2013,7 +2020,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) {
byte *mask_ptr;
const byte *zplane_list[9];
- const byte *bmap_ptr = _vm->findResourceData(MKID_BE('BMAP'), ptr);
+ const byte *bmap_ptr = _vm->findResourceData(MKTAG('B','M','A','P'), ptr);
assert(bmap_ptr);
byte code = *bmap_ptr++;
@@ -2041,7 +2048,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) {
drawStripHE(dst, vs->pitch, bmap_ptr, vs->w, vs->h, true);
break;
case 150:
- fill(dst, vs->pitch, *bmap_ptr, vs->w, vs->h, vs->bytesPerPixel);
+ fill(dst, vs->pitch, *bmap_ptr, vs->w, vs->h, vs->format.bytesPerPixel);
break;
default:
// Alternative russian freddi3 uses badly formatted bitmaps
@@ -2093,7 +2100,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) {
}
void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y, int w, int h) {
- const byte *bmap_ptr = _vm->findResourceData(MKID_BE('BMAP'), ptr);
+ const byte *bmap_ptr = _vm->findResourceData(MKTAG('B','M','A','P'), ptr);
assert(bmap_ptr);
byte code = *bmap_ptr++;
@@ -2152,7 +2159,7 @@ void ScummEngine_v70he::restoreBackgroundHE(Common::Rect rect, int dirtybit) {
assert(rw <= _screenWidth && rw > 0);
assert(rh <= _screenHeight && rh > 0);
- blit(dst, _virtscr[kMainVirtScreen].pitch, src, _virtscr[kMainVirtScreen].pitch, rw, rh, vs->bytesPerPixel);
+ blit(dst, _virtscr[kMainVirtScreen].pitch, src, _virtscr[kMainVirtScreen].pitch, rw, rh, vs->format.bytesPerPixel);
markRectAsDirty(kMainVirtScreen, rect, dirtybit);
}
#endif
@@ -2182,15 +2189,15 @@ void Gdi::resetBackground(int top, int bottom, int strip) {
if (bottom > vs->bdirty[strip])
vs->bdirty[strip] = bottom;
- bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->bytesPerPixel;
- backbuff_ptr = (byte *)vs->pixels + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->bytesPerPixel;
+ bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->format.bytesPerPixel;
+ backbuff_ptr = (byte *)vs->pixels + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->format.bytesPerPixel;
numLinesToProcess = bottom - top;
if (numLinesToProcess) {
if (_vm->isLightOn()) {
- copy8Col(backbuff_ptr, vs->pitch, bgbak_ptr, numLinesToProcess, vs->bytesPerPixel);
+ copy8Col(backbuff_ptr, vs->pitch, bgbak_ptr, numLinesToProcess, vs->format.bytesPerPixel);
} else {
- clear8Col(backbuff_ptr, vs->pitch, numLinesToProcess, vs->bytesPerPixel);
+ clear8Col(backbuff_ptr, vs->pitch, numLinesToProcess, vs->format.bytesPerPixel);
}
}
}
@@ -2830,10 +2837,10 @@ void GdiPCEngine::decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint
void GdiPCEngine::decodePCEngineGfx(const byte *room) {
uint16* stripOffsets;
- decodePCEngineTileData(_vm->findResourceData(MKID_BE('TILE'), room));
- decodePCEngineMaskData(_vm->findResourceData(MKID_BE('ZP00'), room));
+ decodePCEngineTileData(_vm->findResourceData(MKTAG('T','I','L','E'), room));
+ decodePCEngineMaskData(_vm->findResourceData(MKTAG('Z','P','0','0'), room));
- const byte* smap_ptr = _vm->findResourceData(MKID_BE('IM00'), room);
+ const byte* smap_ptr = _vm->findResourceData(MKTAG('I','M','0','0'), room);
smap_ptr++; // roomID
int numStrips = *smap_ptr++;
int numRows = *smap_ptr++;
diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h
index c6062ef9be..3f69d75efd 100644
--- a/engines/scumm/gfx.h
+++ b/engines/scumm/gfx.h
@@ -158,11 +158,11 @@ struct VirtScreen : Graphics::Surface {
}
byte *getPixels(int x, int y) const {
- return (byte *)pixels + y * pitch + (xstart + x) * bytesPerPixel;
+ return (byte *)pixels + y * pitch + (xstart + x) * format.bytesPerPixel;
}
byte *getBackPixels(int x, int y) const {
- return (byte *)backBuf + y * pitch + (xstart + x) * bytesPerPixel;
+ return (byte *)backBuf + y * pitch + (xstart + x) * format.bytesPerPixel;
}
};
diff --git a/engines/scumm/gfxARM.s b/engines/scumm/gfxARM.s
index 34de954a17..9f7c2949b3 100644
--- a/engines/scumm/gfxARM.s
+++ b/engines/scumm/gfxARM.s
@@ -25,8 +25,8 @@
.text
- .global asmDrawStripToScreen
- .global asmCopy8Col
+ .global _asmDrawStripToScreen
+ .global _asmCopy8Col
@ ARM implementation of asmDrawStripToScreen.
@
@@ -44,7 +44,7 @@
@ In addition, we assume that text, src and dst are all word (4 byte)
@ aligned. This is the same assumption that the old 'inline' version
@ made.
-asmDrawStripToScreen:
+_asmDrawStripToScreen:
@ r0 = height
@ r1 = width
@ r2 = text
@@ -125,7 +125,7 @@ end:
@ In addition, we assume that src and dst are both word (4 byte)
@ aligned. This is the same assumption that the old 'inline' version
@ made.
-asmCopy8Col:
+_asmCopy8Col:
@ r0 = dst
@ r1 = dstPitch
@ r2 = src
diff --git a/engines/scumm/gfx_towns.cpp b/engines/scumm/gfx_towns.cpp
index abf2da63a6..78c7ef23f1 100644
--- a/engines/scumm/gfx_towns.cpp
+++ b/engines/scumm/gfx_towns.cpp
@@ -48,7 +48,7 @@ void ScummEngine::towns_drawStripToScreen(VirtScreen *vs, int dstX, int dstY, in
int dp1 = _townsScreen->getLayerPitch(0) - width * _townsScreen->getLayerBpp(0);
int dp2 = _townsScreen->getLayerPitch(1) - width * m * _townsScreen->getLayerBpp(1);
- int sp1 = vs->pitch - (width * vs->bytesPerPixel);
+ int sp1 = vs->pitch - (width * vs->format.bytesPerPixel);
int sp2 = _textSurface.pitch - width * m;
if (vs->number == kMainVirtScreen || _game.id == GID_INDY3 || _game.id == GID_ZAK) {
diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp
index 7840b9df20..e3e25c161c 100644
--- a/engines/scumm/he/animation_he.cpp
+++ b/engines/scumm/he/animation_he.cpp
@@ -112,7 +112,7 @@ void MoviePlayer::handleNextFrame() {
if (_flags & 2) {
uint8 *dstPtr = _vm->getResourceAddress(rtImage, _wizResNum);
assert(dstPtr);
- uint8 *dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
+ uint8 *dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0);
assert(dst);
copyFrameToBuffer(dst, kDstResource, 0, 0, _vm->_screenWidth * _vm->_bytesPerPixel);
} else if (_flags & 1) {
diff --git a/engines/scumm/he/cup_player_he.cpp b/engines/scumm/he/cup_player_he.cpp
index 79bb47aafc..5cd75a5c62 100644
--- a/engines/scumm/he/cup_player_he.cpp
+++ b/engines/scumm/he/cup_player_he.cpp
@@ -30,6 +30,7 @@
#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "audio/decoders/raw.h"
+#include "graphics/palette.h"
#include "scumm/scumm.h"
#include "scumm/util.h"
#include "scumm/he/intern_he.h"
@@ -47,7 +48,7 @@ bool CUP_Player::open(const char *filename) {
if (_fileStream.open(filename)) {
uint32 tag = _fileStream.readUint32BE();
_fileStream.readUint32BE();
- if (tag == MKID_BE('BEAN')) {
+ if (tag == MKTAG('B','E','A','N')) {
_playbackRate = kDefaultPlaybackRate;
_width = kDefaultVideoWidth;
_height = kDefaultVideoHeight;
@@ -168,7 +169,7 @@ void CUP_Player::updateSfx() {
assert(sfxIndex >= 0 && sfxIndex < _sfxCount);
uint32 offset = READ_LE_UINT32(_sfxBuffer + sfxIndex * 4) - 8;
uint8 *soundData = _sfxBuffer + offset;
- if (READ_BE_UINT32(soundData) == MKID_BE('DATA')) {
+ if (READ_BE_UINT32(soundData) == MKTAG('D','A','T','A')) {
uint32 soundSize = READ_BE_UINT32(soundData + 4);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &sfxChannel->handle,
Audio::makeLoopingAudioStream(
@@ -208,19 +209,19 @@ bool CUP_Player::parseNextHeaderTag(Common::SeekableReadStream &dataStream) {
uint32 next = dataStream.pos() + size;
debug(1, "New header tag %s %d dataSize %d", tag2str(tag), size, _dataSize);
switch (tag) {
- case MKID_BE('HEAD'):
+ case MKTAG('H','E','A','D'):
handleHEAD(dataStream, size);
break;
- case MKID_BE('SFXB'):
+ case MKTAG('S','F','X','B'):
handleSFXB(dataStream, size);
break;
- case MKID_BE('RGBS'):
+ case MKTAG('R','G','B','S'):
handleRGBS(dataStream, size);
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
_dataSize = size;
return false;
- case MKID_BE('GFXB'):
+ case MKTAG('G','F','X','B'):
// this is never triggered
default:
warning("Unhandled tag %s", tag2str(tag));
@@ -236,34 +237,34 @@ bool CUP_Player::parseNextBlockTag(Common::SeekableReadStream &dataStream) {
uint32 next = dataStream.pos() + size;
debug(1, "New block tag %s %d dataSize %d", tag2str(tag), size, _dataSize);
switch (tag) {
- case MKID_BE('FRAM'):
+ case MKTAG('F','R','A','M'):
handleFRAM(dataStream, size);
break;
- case MKID_BE('LZSS'):
+ case MKTAG('L','Z','S','S'):
if (handleLZSS(dataStream, size) && _outLzssBufSize != 0) {
Common::MemoryReadStream memoryStream(_outLzssBufData, _outLzssBufSize);
parseNextBlockTag(memoryStream);
}
break;
- case MKID_BE('RATE'):
+ case MKTAG('R','A','T','E'):
handleRATE(dataStream, size);
break;
- case MKID_BE('RGBS'):
+ case MKTAG('R','G','B','S'):
handleRGBS(dataStream, size);
break;
- case MKID_BE('SNDE'):
+ case MKTAG('S','N','D','E'):
handleSNDE(dataStream, size);
break;
- case MKID_BE('TOIL'):
+ case MKTAG('T','O','I','L'):
handleTOIL(dataStream, size);
break;
- case MKID_BE('SRLE'):
+ case MKTAG('S','R','L','E'):
handleSRLE(dataStream, size);
break;
- case MKID_BE('BLOK'):
+ case MKTAG('B','L','O','K'):
_dataSize -= size + 8;
return false;
- case MKID_BE('WRLE'):
+ case MKTAG('W','R','L','E'):
// this is never triggered
default:
warning("Unhandled tag %s", tag2str(tag));
@@ -283,10 +284,10 @@ void CUP_Player::handleSFXB(Common::SeekableReadStream &dataStream, uint32 dataS
if (dataSize > 16) { // WRAP and OFFS chunks
uint32 tag = dataStream.readUint32BE();
uint32 size = dataStream.readUint32BE();
- if (tag == MKID_BE('WRAP')) {
+ if (tag == MKTAG('W','R','A','P')) {
tag = dataStream.readUint32BE();
size = dataStream.readUint32BE();
- if (tag == MKID_BE('OFFS')) {
+ if (tag == MKTAG('O','F','F','S')) {
_sfxCount = (size - 8) / 4;
_sfxBuffer = (uint8 *)malloc(dataSize - 16);
if (_sfxBuffer) {
@@ -439,12 +440,12 @@ static void decodeLZSS(uint8 *dst, const uint8 *src1, const uint8 *src2, const u
bool CUP_Player::handleLZSS(Common::SeekableReadStream &dataStream, uint32 dataSize) {
uint32 tag = dataStream.readUint32BE();
uint32 size = dataStream.readUint32BE();
- if (tag == MKID_BE('LZHD')) {
+ if (tag == MKTAG('L','Z','H','D')) {
uint32 compressionType = dataStream.readUint32LE();
uint32 compressionSize = dataStream.readUint32LE();
tag = dataStream.readUint32BE();
size = dataStream.readUint32BE();
- if (tag == MKID_BE('DATA') && compressionType == 0x2000) {
+ if (tag == MKTAG('D','A','T','A') && compressionType == 0x2000) {
if (_inLzssBufSize < size - 16) {
free(_inLzssBufData);
_inLzssBufSize = size - 16;
diff --git a/engines/scumm/he/floodfill_he.cpp b/engines/scumm/he/floodfill_he.cpp
index 491b91c17e..026a848828 100644
--- a/engines/scumm/he/floodfill_he.cpp
+++ b/engines/scumm/he/floodfill_he.cpp
@@ -240,7 +240,7 @@ void Wiz::fillWizFlood(const WizParameters *params) {
if (params->processFlags & kWPFNewState) {
state = params->img.state;
}
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
@@ -258,7 +258,7 @@ void Wiz::fillWizFlood(const WizParameters *params) {
color = params->fillColor;
}
if (imageRect.contains(px, py)) {
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
FloodFillState *ffs = new FloodFillState;
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 5b59558dd7..830e940322 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -31,6 +31,7 @@
#include "scumm/he/floodfill_he.h"
#include "scumm/he/wiz_he.h"
#endif
+#include "scumm/actor_he.h" // For AuxBlock & AuxEntry
namespace Common {
class SeekableReadStream;
@@ -55,7 +56,10 @@ public:
Common::SeekableReadStream *_hInFileTable[17];
Common::WriteStream *_hOutFileTable[17];
+ Common::Rect _actorClipOverride; // HE specific
+
int _heTimers[16];
+
int getHETimer(int timer);
void setHETimer(int timer);
@@ -63,6 +67,8 @@ public:
ScummEngine_v60he(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v60he();
+ virtual Common::String generateFilename(const int room) const;
+
virtual void resetScumm();
protected:
@@ -107,7 +113,9 @@ class ScummEngine_v70he : public ScummEngine_v60he {
protected:
ResExtractor *_resExtractor;
+ byte *_heV7DiskOffsets;
byte *_heV7RoomOffsets;
+ uint32 *_heV7RoomIntOffsets;
int32 _heSndSoundId, _heSndOffset, _heSndChannel, _heSndFlags, _heSndSoundFreq;
@@ -118,9 +126,14 @@ public:
ScummEngine_v70he(OSystem *syst, const DetectorResult &dr);
~ScummEngine_v70he();
+ virtual Common::String generateFilename(const int room) const;
+
void restoreBackgroundHE(Common::Rect rect, int dirtybit = 0);
protected:
+ virtual void allocateArrays();
+ virtual int readResTypeList(int id);
+ virtual uint32 getResourceRoomOffset(int type, int idx);
virtual void setupOpcodes();
virtual void setupScummVars();
diff --git a/engines/scumm/he/logic_he.cpp b/engines/scumm/he/logic_he.cpp
index ed92c33105..297c2992db 100644
--- a/engines/scumm/he/logic_he.cpp
+++ b/engines/scumm/he/logic_he.cpp
@@ -160,8 +160,8 @@ int32 LogicHErace::dispatch(int op, int numArgs, int32 *args) {
return res;
}
-#define RAD2DEG (180 / PI)
-#define DEG2RAD (PI / 180)
+#define RAD2DEG (180 / M_PI)
+#define DEG2RAD (M_PI / 180)
int32 LogicHErace::op_1003(int32 *args) {
int value = args[2] ? args[2] : 1;
@@ -457,7 +457,7 @@ void LogicHEfunshop::op_1004(int32 *args) {
sq = sqrt(data[i + 1] * data[i + 1] + data[i] * data[i]);
if (at <= 0)
- at += 2 * PI;
+ at += 2 * M_PI;
data[i] = cos(at + a1) * sq;
data[i + 1] = sin(at + a1) * sq;
@@ -823,8 +823,18 @@ int LogicHEsoccer::versionID() {
}
LogicHEsoccer::LogicHEsoccer(ScummEngine_v90he *vm) : LogicHE(vm) {
- // Originally it used 0x1b0d bytes
_userDataD = (double *)calloc(1732, sizeof(double));
+ _intArray1 = 0;
+ _intArray2 = 0;
+ _intArraysAllocated = false;
+ _array1013 = 0;
+ _array1013Allocated = false;
+}
+
+LogicHEsoccer::~LogicHEsoccer() {
+ free(_userDataD);
+ op_1020(); // clear int arrays
+ delete[] _array1013;
}
int32 LogicHEsoccer::dispatch(int op, int numArgs, int32 *args) {
@@ -843,6 +853,37 @@ int32 LogicHEsoccer::dispatch(int op, int numArgs, int32 *args) {
res = op_1004(args);
break;
+ case 1006:
+ res = op_1006(args[0], args[1], args[2], args[3]);
+ break;
+
+ case 1011:
+ // args[4] is ignored!
+ // soccer passes the argument, but then ends up not using it
+ // Makes sense that they removed it for soccermls
+ res = op_1011(args[0], args[1], args[2], args[3], args[5]);
+ break;
+
+ case 1012:
+ res = op_1012(args);
+ break;
+
+ case 1013:
+ res = op_1013(args[0], args[1], args[2]);
+ break;
+
+ case 1019:
+ res = op_1019(args);
+ break;
+
+ case 1020:
+ res = op_1020();
+ break;
+
+ case 1021:
+ res = op_1021(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ break;
+
case 8221968:
// Someone had a fun and used his birthday as opcode number
res = getFromArray(args[0], args[1], args[2]);
@@ -856,6 +897,32 @@ int32 LogicHEsoccer::dispatch(int op, int numArgs, int32 *args) {
return res;
}
+void LogicHEsoccer::beforeBootScript() {
+ if (_intArraysAllocated)
+ op_1020();
+
+ _userDataD[530] = 0;
+}
+
+void LogicHEsoccer::initOnce() {
+ // The original sets some paths here that we don't need to worry about
+ _array1013Allocated = false;
+ _userDataD[530] = 0;
+}
+
+int LogicHEsoccer::startOfFrame() {
+ // This variable is some sort of flag that activates this mode
+ int res = (int)_userDataD[530];
+
+ // _userDataD[535] is not used!
+ // soccer passes the argument, but then ends up not using it
+ // Makes sense that they removed it for soccermls
+ if (res)
+ res = op_1011((int)_userDataD[531], (int)_userDataD[532], (int)_userDataD[533], (int)_userDataD[534], (int)_userDataD[536]);
+
+ return res;
+}
+
int LogicHEsoccer::op_1001(int32 *args) {
return (int)(args[0] * sin((float)args[1]));
}
@@ -901,16 +968,16 @@ int LogicHEsoccer::op_1004(int32 *args) {
return 1;
}
-int LogicHEsoccer::op_1006(int32 *args) {
- double a1 = args[1] * 0.01;
- double a2 = args[2] * 0.01;
- double a3 = args[3] * 0.01;
+int LogicHEsoccer::op_1006(int32 a1, int32 a2, int32 a3, int32 a4) {
+ double v1 = a1 * 0.01;
+ double v2 = a2 * 0.01;
+ double v3 = a3 * 0.01;
double var108, var109;
- _userDataD[529] = args[4];
+ _userDataD[529] = a4;
- var108 = atan2(a1, a3) * _userDataD[523] - args[4];
- var109 = _userDataD[526] - _userDataD[528] + (_userDataD[521] - atan2(_userDataD[524] - a2, a3)) * _userDataD[522];
+ var108 = atan2(v1, v3) * _userDataD[523] - a4;
+ var109 = _userDataD[526] - _userDataD[528] + (_userDataD[521] - atan2(_userDataD[524] - v2, v3)) * _userDataD[522];
writeScummVar(108, (int32)var108);
writeScummVar(109, (int32)var109);
@@ -919,37 +986,358 @@ int LogicHEsoccer::op_1006(int32 *args) {
}
int LogicHEsoccer::op_1007(int32 *args) {
- // TODO: Used when the HE logo is shown
+ // Used when the HE logo is shown
+ // This initializes the _userDataD fields that are used in op_1006/op_1011
+
+ _intArraysAllocated = false;
+ double v14 = (double)args[0] * 0.01;
+ double v13 = (double)args[2] * 0.01;
+ _userDataD[524] = v14;
+ double v12 = atan2(v13, v14);
+ _userDataD[520] = v12;
+ double v15 = atan2(v13 - (double)args[4] * 0.01, (double)args[3] * 0.01);
+ double v19 = v15 * 2.0;
+ double v17 = atan2(v13 - (double)args[4] * 0.01, v14);
+ _userDataD[519] = v19;
+ _userDataD[521] = v17;
+ _userDataD[525] = (v17 - v12) * 2.0;
+ _userDataD[527] = (double)args[5];
+ _userDataD[526] = (double)args[6];
+ _userDataD[528] = (double)args[7];
+ _userDataD[522] = _userDataD[526] / _userDataD[525];
+ _userDataD[523] = _userDataD[527] / _userDataD[519];
+ _userDataD[518] = v13;
+
+ // Clear both byte arrays
+ memset(_byteArray1, 0, 4096);
+ memset(_byteArray2, 0, 585);
+
+ if (_array1013Allocated == 0 )
+ op_1013(4, args[8], args[9]);
return 1;
}
+// Returns the square root of the sum of the squares of the arguments
+static inline double sqrtSquare(double a1, double a2, double a3) {
+ return sqrt(a1 * a1 + a2 * a2 + a3 * a3);
+}
+
int LogicHEsoccer::op_1008(int32 *args) {
// TODO: Used during a match (kicking?)
return 1;
}
+int LogicHEsoccer::op_1011(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5) {
+ // This is called on each frame by startOfFrame() if activated by op_1012.
+ // This seems to do player placement!
+
+ float v28 = 0.0;
+
+ for (int i = 0; i < 18; i++) {
+ // These seem to be some sort of percent? of angles?
+ int v32 = getFromArray(a1, i, 0);
+ int v6 = getFromArray(a1, i, 1);
+ int v30 = getFromArray(a1, i, 2);
+
+ float v29 = (double)v32 / 100.0;
+ v28 = (double)v6 / 100.0;
+ float v31 = (double)v30 / 100.0;
+
+ if (i < 13) {
+ int v25 = ((v32 + 2760) / 500 >= 0) ? ((v32 + 2750) / 500) : 0;
+ int v24 = 10;
+
+ if (v25 <= 10) {
+ int v23 = 0;
+ if ((v32 + 2750) / 500 >= 0)
+ v23 = (v32 + 2750) / 500;
+
+ v24 = v23;
+ }
+
+ int v22 = 0;
+ if ((9219 - v30) / 500 >= 0)
+ v22 = (9219 - v30) / 500;
+
+ int v21 = 6;
+ if (v22 <= 6) {
+ int v20 = 0;
+ if ((9219 - v30) / 500 >= 0)
+ v20 = (9219 - v30) / 500;
+ v21 = v20;
+ }
+
+ if (a5)
+ putInArray(a5, 0, i, v24 + 11 * v21);
+ }
+
+ float v7 = atan2(_userDataD[524] - v28, (double)v31);
+ int v8 = (int)(_userDataD[526] - (_userDataD[521] - v7) * _userDataD[522] + 300.0);
+
+ double v9 = atan2(_userDataD[523], (double)v31);
+ // x/y position?
+ putInArray(a2, i, 0, (int32)(v29 * v9 + 640.0));
+ putInArray(a2, i, 1, v8);
+
+ double v10 = atan2(_userDataD[524], (double)v31);
+ int v12 = (int)(_userDataD[526] - (_userDataD[521] - (float)v10) * _userDataD[522] + 300.0);
+ double v13 = _userDataD[523];
+
+ v29 = atan2(v29, v31);
+ // x/y position?
+ putInArray(a2, i + 22, 0, (int32)(v29 * v13 + 640.0));
+ putInArray(a2, i + 22, 1, v12);
+ }
+
+ // soccer only uses one array here
+ // soccermls/soccer2004 use four
+ int start = (_vm->_game.id == GID_SOCCER) ? 19 : 18;
+ int end = (_vm->_game.id == GID_SOCCER) ? 19 : 21;
+
+ for (int i = start; i <= end; i++) {
+ int v14 = getFromArray(a2, i, 0);
+ int v15 = getFromArray(a2, i, 1);
+
+ // This retains v28 from (i == 17)?
+ float v16 = _userDataD[524] - v28;
+ float v17 = v16 / tan((_userDataD[528] + v15 - _userDataD[526]) / (_userDataD[522] + _userDataD[521]));
+ double v18 = tan((double)(v14 - 640) / _userDataD[523]) * v17;
+ putInArray(a1, i, 0, (int)(v18 * 100.0));
+ putInArray(a1, i, 2, (int)(v17 * 100.0));
+ }
+
+ op_1011_sub(a1, a3, a4, a4);
+
+ return 1;
+}
+
+static inline int distance(int a1, int a2, int a3, int a4) {
+ return (int)sqrt((double)((a4 - a3) * (a4 - a3) + (a2 - a1) * (a2 - a1)));
+}
+
+void LogicHEsoccer::op_1011_sub(int32 a1, int32 a2, int32 a3, int32 a4) {
+ // As you can guess, this is called from op_1011
+ // This seems to be checking distances between the players and the ball
+ // and which distance is the shortest.
+
+ int v6[13];
+ int v7[13];
+ int v8[13];
+ int v18[195];
+
+ for (int i = 0; i < 13; i++) {
+ v6[i] = 0;
+ v7[i] = getFromArray(a1, i, 0);
+ v8[i] = getFromArray(a1, i, 2);
+ }
+
+ // 12 here, 13 up there
+ // Probably 12 for players, 13 for players+ball
+ for (int i = 0; i < 12; i++) {
+ int v22 = a4;
+ for (int j = i + 1; j < 13; j++) {
+ v18[i * 15 + j] = distance(v7[i], v7[j], v8[i], v8[j]);
+ putInArray(a2, i, j, v18[i * 15 + j]);
+ putInArray(a2, j, i, v18[i * 15 + j]);
+ if (v18[i * 15 + j] < v22) {
+ v22 = v18[i * 15 + j];
+ v6[i] = j + 1;
+ v6[j] = i + 1;
+ }
+ }
+ }
+
+ int v13 = getFromArray(a1, 18, 0);
+ int v14 = getFromArray(a1, 18, 2);
+ int v15 = getFromArray(a1, 19, 0);
+ int v16 = getFromArray(a1, 19, 2);
+ int v19[15];
+ int v20[15];
+
+ if (_vm->_game.id == GID_SOCCER) {
+ // soccer gets to be different
+ for (int i = 0; i < 13; i++)
+ v20[i] = distance(v13, v7[i], v14, v8[i]);
+
+ for (int i = 0; i < 13; i++)
+ v19[i] = distance(v15, v7[i], v16, v8[i]);
+ } else {
+ // soccermls and soccer2004 use two other arrays here
+ int v9 = getFromArray(a1, 20, 0);
+ int v10 = getFromArray(a1, 20, 2);
+ int v11 = getFromArray(a1, 21, 0);
+ int v12 = getFromArray(a1, 21, 2);
+
+ for (int i = 0; i < 6; i++) {
+ v20[i] = distance(v9, v7[i], v10, v8[i]);
+ v19[i] = distance(v13, v7[i], v14, v8[i]);
+ }
+
+ for (int i = 6; i < 13; i++) {
+ v20[i] = distance(v11, v7[i], v12, v8[i]);
+ v19[i] = distance(v15, v7[i], v16, v8[i]);
+ }
+ }
+
+ for (int i = 0; i < 13; i++) {
+ putInArray(a2, 14, i, v20[i]);
+ putInArray(a2, i, 14, v20[i]);
+ putInArray(a2, 13, i, v19[i]);
+ putInArray(a2, i, 13, v19[i]);
+ putInArray(a3, 0, i, v6[i]);
+ }
+}
+
int LogicHEsoccer::op_1012(int32 *args) {
- // TODO: Used after op_1019
+ // Used after op_1019
+ // This function activates startOfFrame() to call op_1011
+ // (Possibly field parameters?)
+
+ _userDataD[530] = (args[0] != 0) ? 1 : 0;
+ _userDataD[531] = args[1];
+ _userDataD[532] = args[2];
+ _userDataD[533] = args[3];
+ _userDataD[534] = args[4];
+ _userDataD[535] = args[5]; // unused!!!
+ _userDataD[536] = args[6];
+
+ return 1;
+}
+
+// Some strange power operation, ignores negative exponents
+static inline double u32Pow(float a1, int a2) {
+ if (a2 < 0)
+ return 0.0;
+
+ float v4 = 1.0;
+
+ for (int i = 1; i <= a2; i++)
+ v4 *= a1;
+
+ return v4;
+}
+
+int LogicHEsoccer::op_sub5(int a1, int a2, int a3) {
+ byte *v9 = _array1013 + 44 * a2;
+
+ *((uint32 *)v9 + 4) = a3;
+ *((uint32 *)v9) = a2;
+
+ if (a1 > 2) {
+ // Casual observation: 585 is also the size of _byteArray2
+ *((uint32 *)v9 + 40) = 8 * a2 - 585;
+ for (int i = 0; i < 8; i++)
+ *((uint32 *)v9 + 4 * i + 8) = 0xffffffff;
+ } else {
+ for (int i = 0; i < 8; i++)
+ *((uint32 *)v9 + 4 * i + 8) = op_sub5(a1 + 1, i + 8 * a2 + 1, a2);
+ }
+
+ return a2;
+}
+
+int LogicHEsoccer::op_1013(int32 a1, int32 a2, int32 a3) {
+ // Creates _array1013 for *some* purpose
+ // _array1013Temp is used again op_1014 for some reason...
+ // Seems to be used in op_1015
+
+ int v4 = (int)((1.0 - u32Pow(8.0, 4)) / -7.0);
+
+ _array1013 = new byte[v4 * 44];
+ memset(_array1013, 0, v4 * 44);
+ _array1013Allocated = true;
+ memset(_array1013Temp, 0, 44);
+
+ for (int i = 0; i < 8; i++)
+ _array1013Temp[i + 2] = op_sub5(1, i + 1, 0);
+
+ // Yes, this is not endian-safe, but should not matter since we're
+ // not saving/loading the data anywhere
+ memcpy(_array1013, _array1013Temp, 44);
return 1;
}
-int LogicHEsoccer::op_1014(int32 *args) {
+int LogicHEsoccer::op_1014(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5, int32 a6, int32 a7, int32 a8, int32 a9, int32 a10, int32 a11, int32 a12, int32 a13, int32 a14) {
// TODO: Used many times during a match
+ // And called from op_1008!
return 1;
}
int LogicHEsoccer::op_1019(int32 *args) {
- // TODO: Used at the beginning of a match
+ // Used at the beginning of a match
+ // Initializes some arrays. Player positions?
+
+ // These two arrays are used in op_1014 and op_1015
+ for (int i = 0; i < 4096; i++)
+ _byteArray1[i] = getFromArray(args[1], 0, i);
+
+ for (int i = 0; i < 585; i++)
+ _byteArray2[i] = getFromArray(args[0], 0, i);
+
+ // Deallocate the two integer arrays
+ if (_intArraysAllocated)
+ op_1020();
+
+ // Reallocate them
+ _intArray1 = new uint32[1008];
+ _intArray2 = new uint32[168];
+ _intArraysAllocated = true;
+
+ memset(_intArray1, 0, 4 * 4);
+ memset(_intArray2, 0, 24 * 4);
+
+ // These two arrays are used in op_1015
+ for (int i = 0; i < 42; i++) {
+ for (int j = 0; j < 24; j++)
+ _intArray1[j + 24 * i] = getFromArray(args[3], 0, j + 24 * i);
+
+ for (int j = 0; j < 4; j++)
+ _intArray2[j + 4 * i] = getFromArray(args[2], 0, j + 4 * i);
+ }
+
+ return 1;
+}
+
+int LogicHEsoccer::op_1020() {
+ // Deallocate integer arrays
+ // The arrays can be allocated in op_1015 or op_1019
+
+ delete[] _intArray1; _intArray1 = 0;
+ delete[] _intArray2; _intArray2 = 0;
+ _intArraysAllocated = false;
return 1;
}
-int LogicHEsoccer::op_1021(int32 *args) {
- // TODO: Used during a match (ball movement?)
+int LogicHEsoccer::op_1021(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5, int32 a6, int32 a7) {
+ // Used during a match (ball movement?)
+ // Also called from op_1008
+
+ int v10;
+ if (a4 && a5)
+ v10 = (int)(((double)a2 - (double)a5 * (double)a1 / (double)a4) * -1.0 * (double)a4 / (double)a5);
+ else
+ v10 = a1;
+
+ int v9;
+ if (a6 && a5)
+ v9 = (int)(((double)a2 - (double)a5 * (double)a3 / (double)a6) * -1.0 * (double)a6 / (double)a5);
+ else
+ v9 = a3;
+
+ // The final argument chooses whether to store the results for op_1008 or
+ // store them in SCUMM variables.
+ if (a7) {
+ _var1021[0] = v10;
+ _var1021[1] = v9;
+ } else {
+ writeScummVar(108, v10);
+ writeScummVar(109, v9);
+ }
return 1;
}
diff --git a/engines/scumm/he/logic_he.h b/engines/scumm/he/logic_he.h
index ab952abd5e..d097d37e75 100644
--- a/engines/scumm/he/logic_he.h
+++ b/engines/scumm/he/logic_he.h
@@ -41,9 +41,9 @@ public:
int getFromArray(int arg0, int idx2, int idx1);
void putInArray(int arg0, int idx2, int idx1, int val);
- void beforeBootScript() {}
- void initOnce() {}
- void startOfFrame() {}
+ virtual void beforeBootScript() {}
+ virtual void initOnce() {}
+ virtual int startOfFrame() { return 1; }
void endOfFrame() {}
void processKeyStroke(int keyPressed) {}
@@ -115,22 +115,52 @@ private:
public:
LogicHEsoccer(ScummEngine_v90he *vm);
+ ~LogicHEsoccer();
int versionID();
int32 dispatch(int op, int numArgs, int32 *args);
+ void beforeBootScript();
+ void initOnce();
+ int startOfFrame();
+
private:
int op_1001(int32 *args);
int op_1002(int32 *args);
int op_1003(int32 *args);
int op_1004(int32 *args);
- int op_1006(int32 *args);
+ int op_1006(int32 a1, int32 a2, int32 a3, int32 a4);
int op_1007(int32 *args);
int op_1008(int32 *args);
+ int op_1011(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5);
int op_1012(int32 *args);
- int op_1014(int32 *args);
+ int op_1013(int32 a1, int32 a2, int32 a3);
+ int op_1014(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5, int32 a6, int32 a7, int32 a8, int32 a9, int32 a10, int32 a11, int32 a12, int32 a13, int32 a14);
int op_1019(int32 *args);
- int op_1021(int32 *args);
+ int op_1020();
+ int op_1021(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5, int32 a6, int32 a7);
+
+ // Two integer arrays are used between some functions
+ // Originally, these pointers were in _userData, but we keep them separate
+ // Also, doing it that would break things on non 32-bit systems...
+ bool _intArraysAllocated;
+ uint32 *_intArray1, *_intArray2;
+
+ // op_1007 allocates some arrays
+ // they're then filled by op_1019
+ byte _byteArray1[4096], _byteArray2[585];
+
+ // op_1011 has a subfunction
+ void op_1011_sub(int32 a1, int32 a2, int32 a3, int32 a4);
+
+ // op_1013 creates some array, purpose unknown
+ bool _array1013Allocated;
+ byte *_array1013;
+ uint32 _array1013Temp[11];
+ int op_sub5(int a1, int a2, int a3);
+
+ // op_1021 can (optionally) set two variables for use in op_1008
+ uint32 _var1021[2];
};
class LogicHEbaseball2001 : public LogicHE {
diff --git a/engines/scumm/he/palette_he.cpp b/engines/scumm/he/palette_he.cpp
index b42d6e97e2..49e43a040b 100644
--- a/engines/scumm/he/palette_he.cpp
+++ b/engines/scumm/he/palette_he.cpp
@@ -26,6 +26,7 @@
#ifdef ENABLE_HE
#include "common/system.h"
+#include "graphics/palette.h"
#include "scumm/scumm.h"
#include "scumm/he/intern_he.h"
#include "scumm/resource.h"
@@ -192,7 +193,7 @@ void ScummEngine_v90he::setHEPaletteFromCostume(int palSlot, int resId) {
assertRange(1, palSlot, _numPalettes, "palette");
const uint8 *data = getResourceAddress(rtCostume, resId);
assert(data);
- const uint8 *rgbs = findResourceData(MKID_BE('RGBS'), data);
+ const uint8 *rgbs = findResourceData(MKTAG('R','G','B','S'), data);
assert(rgbs);
setHEPaletteFromPtr(palSlot, rgbs);
}
@@ -202,7 +203,7 @@ void ScummEngine_v90he::setHEPaletteFromImage(int palSlot, int resId, int state)
assertRange(1, palSlot, _numPalettes, "palette");
uint8 *data = getResourceAddress(rtImage, resId);
assert(data);
- const uint8 *rgbs = findWrappedBlock(MKID_BE('RGBS'), data, state, 0);
+ const uint8 *rgbs = findWrappedBlock(MKTAG('R','G','B','S'), data, state, 0);
if (rgbs)
setHEPaletteFromPtr(palSlot, rgbs);
}
@@ -212,7 +213,7 @@ void ScummEngine_v90he::setHEPaletteFromRoom(int palSlot, int resId, int state)
assertRange(1, palSlot, _numPalettes, "palette");
const uint8 *data = getResourceAddress(rtRoom, resId);
assert(data);
- const uint8 *pals = findResourceData(MKID_BE('PALS'), data);
+ const uint8 *pals = findResourceData(MKTAG('P','A','L','S'), data);
assert(pals);
const uint8 *rgbs = findPalInPals(pals, state);
assert(rgbs);
diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp
index 72e7052034..ecb094f29b 100644
--- a/engines/scumm/he/resource_he.cpp
+++ b/engines/scumm/he/resource_he.cpp
@@ -4,10 +4,6 @@
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
- * Parts of this code are heavily based on:
- * icoutils - A set of programs dealing with MS Windows icons and cursors.
- * Copyright (C) 1998-2001 Oskar Liljeblad
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -36,6 +32,7 @@
#include "audio/decoders/wave.h"
#include "graphics/cursorman.h"
+#include "graphics/wincursor.h"
#include "common/archive.h"
#include "common/memstream.h"
@@ -43,14 +40,6 @@
namespace Scumm {
-#if defined(SCUMM_LITTLE_ENDIAN)
-#define LE16(x)
-#define LE32(x)
-#elif defined(SCUMM_BIG_ENDIAN)
-#define LE16(x) ((x) = TO_LE_16(x))
-#define LE32(x) ((x) = TO_LE_32(x))
-#endif
-
ResExtractor::ResExtractor(ScummEngine_v70he *scumm)
: _vm(scumm) {
@@ -65,1092 +54,112 @@ ResExtractor::~ResExtractor() {
free(cc->palette);
}
}
+
memset(_cursorCache, 0, sizeof(_cursorCache));
}
ResExtractor::CachedCursor *ResExtractor::findCachedCursor(int id) {
- for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
- CachedCursor *cc = &_cursorCache[i];
- if (cc->valid && cc->id == id) {
- return cc;
- }
- }
+ for (int i = 0; i < MAX_CACHED_CURSORS; ++i)
+ if (_cursorCache[i].valid && _cursorCache[i].id == id)
+ return &_cursorCache[i];
+
return NULL;
}
ResExtractor::CachedCursor *ResExtractor::getCachedCursorSlot() {
- uint32 min_last_used = 0;
+ uint32 minLastUsed = 0;
CachedCursor *r = NULL;
+
for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
CachedCursor *cc = &_cursorCache[i];
- if (!cc->valid) {
+ if (!cc->valid)
return cc;
- } else {
- if (min_last_used == 0 || cc->last_used < min_last_used) {
- min_last_used = cc->last_used;
- r = cc;
- }
+
+ if (minLastUsed == 0 || cc->lastUsed < minLastUsed) {
+ minLastUsed = cc->lastUsed;
+ r = cc;
}
}
+
assert(r);
- free(r->bitmap);
- free(r->palette);
+ delete[] r->bitmap;
+ delete[] r->palette;
memset(r, 0, sizeof(CachedCursor));
return r;
}
void ResExtractor::setCursor(int id) {
- byte *cursorRes = 0;
- int cursorsize;
- int keycolor = 0;
CachedCursor *cc = findCachedCursor(id);
+
if (cc != NULL) {
debug(7, "Found cursor %d in cache slot %lu", id, (long)(cc - _cursorCache));
} else {
cc = getCachedCursorSlot();
assert(cc && !cc->valid);
- cursorsize = extractResource(id, &cursorRes);
- convertIcons(cursorRes, cursorsize, &cc->bitmap, &cc->w, &cc->h, &cc->hotspot_x, &cc->hotspot_y, &keycolor, &cc->palette, &cc->palSize);
+
+ if (!extractResource(id, cc))
+ error("Could not extract cursor %d", id);
+
debug(7, "Adding cursor %d to cache slot %lu", id, (long)(cc - _cursorCache));
- free(cursorRes);
+
cc->valid = true;
cc->id = id;
- cc->last_used = g_system->getMillis();
+ cc->lastUsed = g_system->getMillis();
}
if (cc->palette)
CursorMan.replaceCursorPalette(cc->palette, 0, cc->palSize);
- _vm->setCursorHotspot(cc->hotspot_x, cc->hotspot_y);
- _vm->setCursorFromBuffer(cc->bitmap, cc->w, cc->h, cc->w);
+ _vm->setCursorHotspot(cc->hotspotX, cc->hotspotY);
+ _vm->setCursorFromBuffer(cc->bitmap, cc->width, cc->height, cc->width);
}
-/*
- * Static variables
- */
-const char *res_types[] = {
- /* 0x01: */
- "cursor", "bitmap", "icon", "menu", "dialog", "string",
- "fontdir", "font", "accelerator", "rcdata", "messagelist",
- "group_cursor", NULL, "group_icon", NULL,
- /* the following are not defined in winbase.h, but found in wrc. */
- /* 0x10: */
- "version", "dlginclude", NULL, "plugplay", "vxd",
- "anicursor", "aniicon"
-};
-#define RES_TYPE_COUNT (sizeof(res_types)/sizeof(char *))
-
Win32ResExtractor::Win32ResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) {
}
-int Win32ResExtractor::extractResource(int resId, byte **data) {
- char buf[20];
-
- snprintf(buf, sizeof(buf), "%d", resId);
-
- return extractResource_("group_cursor", buf, data);
-}
-
-int Win32ResExtractor::extractResource_(const char *resType, char *resName, byte **data) {
- char *arg_language = NULL;
- const char *arg_type = resType;
- char *arg_name = resName;
- int ressize = 0;
-
- _arg_raw = false;
-
- /* translate --type option from resource type string to integer */
- arg_type = res_type_string_to_id(arg_type);
-
- WinLibrary fi;
-
- /* initiate stuff */
- fi.memory = NULL;
- fi.file = NULL;
-
+bool Win32ResExtractor::extractResource(int id, CachedCursor *cc) {
if (_fileName.empty()) { // We are running for the first time
_fileName = _vm->generateFilename(-3);
- }
-
- /* get file size */
- fi.file = SearchMan.createReadStreamForMember(_fileName);
- if (!fi.file) {
- error("Cannot open file %s", _fileName.c_str());
- }
-
- fi.total_size = fi.file->size();
- if (fi.total_size == -1) {
- error("Cannot get size of file %s", _fileName.c_str());
- goto cleanup;
- }
- if (fi.total_size == 0) {
- error("%s: file has a size of 0", _fileName.c_str());
- goto cleanup;
- }
-
- /* read all of file */
- fi.memory = (byte *)malloc(fi.total_size);
- if (fi.file->read(fi.memory, fi.total_size) == 0) {
- error("Cannot read from file %s", _fileName.c_str());
- goto cleanup;
- }
-
- /* identify file and find resource table */
- if (!read_library(&fi)) {
- /* error reported by read_library */
- goto cleanup;
- }
-
- /* errors will be printed by the callback */
- ressize = do_resources(&fi, arg_type, arg_name, arg_language, data);
-
- /* free stuff and close file */
- cleanup:
- delete fi.file;
- free(fi.memory);
-
- return ressize;
-}
-
-
-/**
- * Translate a numeric resource type to it's corresponding string type.
- * (For informative-ness.)
- */
-const char *Win32ResExtractor::res_type_id_to_string(int id) {
- if (id == 241)
- return "toolbar";
- if (id > 0 && id <= (int)RES_TYPE_COUNT)
- return res_types[id-1];
- return NULL;
-}
-
-/**
- * Translate a resource type string to integer.
- * (Used to convert the --type option.)
- */
-const char *Win32ResExtractor::res_type_string_to_id(const char *type) {
- static const char *res_type_ids[] = {
- "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-10",
- "-11", "-12", NULL, "-14", NULL, "-16", "-17", NULL, "-19",
- "-20", "-21", "-22"
- };
- int c;
-
- if (type == NULL)
- return NULL;
-
- for (c = 0; c < (int)RES_TYPE_COUNT; c++) {
- if (res_types[c] != NULL && !scumm_stricmp(type, res_types[c]))
- return res_type_ids[c];
- }
-
- return type;
-}
-
-/**
- * Return the resource id quoted if it is a string, otherwise (i.e. if
- * it is numeric) just return it.
- */
-Common::String Win32ResExtractor::WinResource::getQuotedResourceId() const {
- if (numeric_id || id[0] == '\0')
- return id;
- return '"' + Common::String(id) + '"';
-}
-
-int Win32ResExtractor::extract_resources(WinLibrary *fi, WinResource *wr,
- WinResource *type_wr, WinResource *name_wr,
- WinResource *lang_wr, byte **data) {
- int size;
- bool free_it;
- const char *type;
- int32 id;
-
- if (*data) {
- error("Win32ResExtractor::extract_resources() more than one cursor");
- return 0;
- }
-
- *data = extract_resource(fi, wr, &size, &free_it, type_wr->id, (lang_wr == NULL ? NULL : lang_wr->id), _arg_raw);
-
- if (data == NULL) {
- error("Win32ResExtractor::extract_resources() problem with resource extraction");
- return 0;
- }
-
- /* get named resource type if possible */
- type = NULL;
- if ((id = strtol(type_wr->id, 0, 10)) != 0)
- type = res_type_id_to_string(id);
-
- if (lang_wr != NULL && lang_wr->id[0] != '\0') {
- debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s language: %s [size=%d]",
- name_wr->getQuotedResourceId().c_str(), lang_wr->getQuotedResourceId().c_str(), size);
- } else {
- debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s [size=%d]",
- name_wr->getQuotedResourceId().c_str(), size);
- }
- return size;
-}
-
-/**
- * Extract a resource, returning pointer to data.
- */
-byte *Win32ResExtractor::extract_resource(WinLibrary *fi, WinResource *wr, int *size,
- bool *free_it, char *type, char *lang, bool raw) {
- char *str;
- int32 intval;
-
- /* just return pointer to data if raw */
- if (raw) {
- *free_it = false;
- /* get_resource_entry will print possible error */
- return get_resource_entry(fi, wr, size);
- }
-
- /* find out how to extract */
- str = type;
- if (str != NULL && (intval = strtol(STRIP_RES_ID_FORMAT(str), 0, 10))) {
- if (intval == (int)RT_GROUP_ICON) {
- *free_it = true;
- return extract_group_icon_cursor_resource(fi, wr, lang, size, true);
- }
- if (intval == (int)RT_GROUP_CURSOR) {
- *free_it = true;
- return extract_group_icon_cursor_resource(fi, wr, lang, size, false);
- }
- }
-
- return NULL;
-}
-
-/**
- * Create a complete RT_GROUP_ICON resource, that can be written to
- * an `.ico' file without modifications. Returns an allocated
- * memory block that should be freed with free() once used.
- *
- * `root' is the offset in file that specifies the resource.
- * `base' is the offset that string pointers are calculated from.
- * `ressize' should point to an integer variable where the size of
- * the returned memory block will be placed.
- * `is_icon' indicates whether resource to be extracted is icon
- * or cursor group.
- */
-byte *Win32ResExtractor::extract_group_icon_cursor_resource(WinLibrary *fi, WinResource *wr, char *lang,
- int *ressize, bool is_icon) {
- Win32CursorIconDir *icondir;
- Win32CursorIconFileDir *fileicondir;
- byte *memory;
- int c, offset, skipped;
- int size;
-
- /* get resource data and size */
- icondir = (Win32CursorIconDir *)get_resource_entry(fi, wr, &size);
- if (icondir == NULL) {
- /* get_resource_entry will print error */
- return NULL;
- }
-
- /* calculate total size of output file */
- RETURN_IF_BAD_POINTER(NULL, icondir->count);
- skipped = 0;
- for (c = 0; c < FROM_LE_16(icondir->count); c++) {
- int level;
- int iconsize;
- char name[14];
- WinResource *fwr;
-
- RETURN_IF_BAD_POINTER(NULL, icondir->entries[c]);
- /*debug("%d. bytes_in_res=%d width=%d height=%d planes=%d bit_count=%d", c,
- FROM_LE_32(icondir->entries[c].bytes_in_res),
- (is_icon ? icondir->entries[c].res_info.icon.width : FROM_LE_16(icondir->entries[c].res_info.cursor.width)),
- (is_icon ? icondir->entries[c].res_info.icon.height : FROM_LE_16(icondir->entries[c].res_info.cursor.height)),
- FROM_LE_16(icondir->entries[c].plane_count),
- FROM_LE_16(icondir->entries[c].bit_count));*/
-
- /* find the corresponding icon resource */
- snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(icondir->entries[c].res_id));
- fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level);
- if (fwr == NULL) {
- error("%s: could not find `%s' in `%s' resource.",
- _fileName.c_str(), &name[1], (is_icon ? "group_icon" : "group_cursor"));
- return NULL;
- }
-
- if (get_resource_entry(fi, fwr, &iconsize) != NULL) {
- if (iconsize == 0) {
- debugC(DEBUG_RESOURCE, "%s: icon resource `%s' is empty, skipping", _fileName.c_str(), name);
- skipped++;
- continue;
- }
- if ((uint32)iconsize != FROM_LE_32(icondir->entries[c].bytes_in_res)) {
- debugC(DEBUG_RESOURCE, "%s: mismatch of size in icon resource `%s' and group (%d != %d)",
- _fileName.c_str(), name, iconsize, FROM_LE_32(icondir->entries[c].bytes_in_res));
- }
- size += iconsize; /* size += FROM_LE_32(icondir->entries[c].bytes_in_res); */
- /* cursor resources have two additional WORDs that contain
- * hotspot info */
- if (!is_icon)
- size -= sizeof(uint16)*2;
- }
- }
- offset = sizeof(Win32CursorIconFileDir) + (FROM_LE_16(icondir->count)-skipped) * sizeof(Win32CursorIconFileDirEntry);
- size += offset;
- *ressize = size;
-
- /* allocate that much memory */
- memory = (byte *)malloc(size);
- fileicondir = (Win32CursorIconFileDir *)memory;
-
- /* transfer Win32CursorIconDir structure members */
- fileicondir->reserved = icondir->reserved;
- fileicondir->type = icondir->type;
- fileicondir->count = TO_LE_16(FROM_LE_16(icondir->count) - skipped);
-
- /* transfer each cursor/icon: Win32CursorIconDirEntry and data */
- skipped = 0;
- for (c = 0; c < FROM_LE_16(icondir->count); c++) {
- int level;
- char name[14];
- WinResource *fwr;
- byte *data;
-
- /* find the corresponding icon resource */
- snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(icondir->entries[c].res_id));
- fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level);
- if (fwr == NULL) {
- error("%s: could not find `%s' in `%s' resource.",
- _fileName.c_str(), &name[1], (is_icon ? "group_icon" : "group_cursor"));
- return NULL;
- }
-
- /* get data and size of that resource */
- data = (byte *)get_resource_entry(fi, fwr, &size);
- if (data == NULL) {
- /* get_resource_entry has printed error */
- return NULL;
- }
- if (size == 0) {
- skipped++;
- continue;
- }
-
- /* copy ICONDIRENTRY (not including last dwImageOffset) */
- memcpy(&fileicondir->entries[c-skipped], &icondir->entries[c],
- sizeof(Win32CursorIconFileDirEntry)-sizeof(uint32));
-
- /* special treatment for cursors */
- if (!is_icon) {
- fileicondir->entries[c-skipped].width = icondir->entries[c].res_info.cursor.width;
- fileicondir->entries[c-skipped].height = TO_LE_16(FROM_LE_16(icondir->entries[c].res_info.cursor.height) / 2);
- fileicondir->entries[c-skipped].color_count = 0;
- fileicondir->entries[c-skipped].reserved = 0;
- }
-
- /* set image offset and increase it */
- fileicondir->entries[c-skipped].dib_offset = TO_LE_32(offset);
-
- /* transfer resource into file memory */
- if (is_icon) {
- memcpy(&memory[offset], data, FROM_LE_32(icondir->entries[c].bytes_in_res));
- } else {
- fileicondir->entries[c-skipped].hotspot_x = ((uint16 *) data)[0];
- fileicondir->entries[c-skipped].hotspot_y = ((uint16 *) data)[1];
- memcpy(&memory[offset], data+sizeof(uint16)*2,
- FROM_LE_32(icondir->entries[c].bytes_in_res)-sizeof(uint16)*2);
- offset -= sizeof(uint16)*2;
- }
-
- /* increase the offset pointer */
- offset += FROM_LE_32(icondir->entries[c].bytes_in_res);
+ if (!_exe.loadFromEXE(_fileName))
+ error("Cannot open file %s", _fileName.c_str());
}
- return memory;
-}
-
-/**
- * Check if a chunk of data (determined by offset and size)
- * is within the bounds of the WinLibrary file.
- * Usually not called directly.
- */
-bool Win32ResExtractor::check_offset(byte *memory, int total_size, const char *name, void *offset, int size) {
- int need_size = (int)((byte *)offset - memory + size);
-
- debugC(DEBUG_RESOURCE, "check_offset: size=%x vs %x offset=%x size=%x",
- need_size, total_size, (uint)((byte *)offset - memory), size);
+ Graphics::WinCursorGroup *group = Graphics::WinCursorGroup::createCursorGroup(_exe, id);
- if (need_size < 0 || need_size > total_size) {
- error("%s: premature end", name);
+ if (!group)
return false;
- }
-
- return true;
-}
-
-
-/**
- * Do something for each resource matching type, name and lang.
- */
-int Win32ResExtractor::do_resources(WinLibrary *fi, const char *type, char *name, char *lang, byte **data) {
- WinResource *type_wr;
- WinResource *name_wr;
- WinResource *lang_wr;
- int size;
-
- type_wr = (WinResource *)calloc(3, sizeof(WinResource));
- name_wr = type_wr + 1;
- lang_wr = type_wr + 2;
-
- size = do_resources_recurs(fi, NULL, type_wr, name_wr, lang_wr, type, name, lang, data);
-
- free(type_wr);
-
- return size;
-}
-
-/* what is each entry in this directory level for? type, name or language? */
-#define WINRESOURCE_BY_LEVEL(x) ((x)==0 ? type_wr : ((x)==1 ? name_wr : lang_wr))
-
-/* does the id of this entry match the specified id? */
-#define LEVEL_MATCHES(x) (x == NULL || x ## _wr->id[0] == '\0' || compare_resource_id(x ## _wr, x))
-int Win32ResExtractor::do_resources_recurs(WinLibrary *fi, WinResource *base,
- WinResource *type_wr, WinResource *name_wr, WinResource *lang_wr,
- const char *type, char *name, char *lang, byte **data) {
- int c, rescnt;
- WinResource *wr;
- uint32 size = 0;
+ Graphics::WinCursor *cursor = group->cursors[0].cursor;
- /* get a list of all resources at this level */
- wr = list_resources(fi, base, &rescnt);
- if (wr == NULL) {
- return size;
- }
-
- /* process each resource listed */
- for (c = 0; c < rescnt; c++) {
- /* (over)write the corresponding WinResource holder with the current */
- memcpy(WINRESOURCE_BY_LEVEL(wr[c].level), wr+c, sizeof(WinResource));
-
- /* go deeper unless there is something that does NOT match */
- if (LEVEL_MATCHES(type) && LEVEL_MATCHES(name) && LEVEL_MATCHES(lang)) {
- if (wr->is_directory)
- size = do_resources_recurs(fi, wr+c, type_wr, name_wr, lang_wr, type, name, lang, data);
- else
- size = extract_resources(fi, wr+c, type_wr, name_wr, lang_wr, data);
- }
- }
-
- /* since we're moving back one level after this, unset the
- * WinResource holder used on this level */
- memset(WINRESOURCE_BY_LEVEL(wr[0].level), 0, sizeof(WinResource));
-
- return size;
-}
-
-bool Win32ResExtractor::compare_resource_id(WinResource *wr, const char *id) {
- if (wr->numeric_id) {
- int32 cmp1, cmp2;
- if (id[0] == '+')
- return false;
- if (id[0] == '-')
- id++;
- cmp1 = strtol(wr->id, 0, 10);
- cmp2 = strtol(id, 0, 10);
- if (!cmp1 || !cmp2 || cmp1 != cmp2)
- return false;
- } else {
- if (id[0] == '-')
- return false;
- if (id[0] == '+')
- id++;
- if (strcmp(wr->id, id))
- return false;
- }
+ cc->bitmap = new byte[cursor->getWidth() * cursor->getHeight()];
+ cc->width = cursor->getWidth();
+ cc->height = cursor->getHeight();
+ cc->hotspotX = cursor->getHotspotX();
+ cc->hotspotY = cursor->getHotspotY();
- return true;
-}
+ // Convert from the paletted format to the SCUMM palette
+ const byte *srcBitmap = cursor->getSurface();
-bool Win32ResExtractor::decode_pe_resource_id(WinLibrary *fi, WinResource *wr, uint32 value) {
- if (value & IMAGE_RESOURCE_NAME_IS_STRING) { /* numeric id */
- int c, len;
- uint16 *mem = (uint16 *)
- (fi->first_resource + (value & ~IMAGE_RESOURCE_NAME_IS_STRING));
-
- /* copy each char of the string, and terminate it */
- RETURN_IF_BAD_POINTER(false, *mem);
- len = FROM_LE_16(mem[0]);
- RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(uint16) * len);
-
- len = MIN(FROM_LE_16(mem[0]), (uint16)WINRES_ID_MAXLEN);
- for (c = 0; c < len; c++)
- wr->id[c] = FROM_LE_16(mem[c+1]) & 0x00FF;
- wr->id[len] = '\0';
- wr->numeric_id = false;
- } else { /* Unicode string id */
- /* translate id into a string */
- snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value);
- wr->numeric_id = true;
+ for (int i = 0; i < cursor->getWidth() * cursor->getHeight(); i++) {
+ if (srcBitmap[i] == cursor->getKeyColor()) // Transparent
+ cc->bitmap[i] = 255;
+ else if (srcBitmap[i] == 0) // Black
+ cc->bitmap[i] = 253;
+ else // White
+ cc->bitmap[i] = 254;
}
+ delete group;
return true;
}
-byte *Win32ResExtractor::get_resource_entry(WinLibrary *fi, WinResource *wr, int *size) {
- byte *result;
-
- Win32ImageResourceDataEntry *dataent;
-
- dataent = (Win32ImageResourceDataEntry *) wr->children;
- RETURN_IF_BAD_POINTER(NULL, *dataent);
- *size = FROM_LE_32(dataent->size);
-
- result = fi->memory + FROM_LE_32(dataent->offset_to_data);
-
- RETURN_IF_BAD_OFFSET(NULL, result, *size);
-
- return result;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::list_pe_resources(WinLibrary *fi, Win32ImageResourceDirectory *pe_res, int level, int *count) {
- WinResource *wr;
- int c, rescnt;
- Win32ImageResourceDirectoryEntry *dirent
- = (Win32ImageResourceDirectoryEntry *)(pe_res + 1);
-
- /* count number of `type' resources */
- RETURN_IF_BAD_POINTER(NULL, *dirent);
- rescnt = FROM_LE_16(pe_res->number_of_named_entries) + FROM_LE_16(pe_res->number_of_id_entries);
- *count = rescnt;
-
- /* allocate WinResource's */
- wr = (WinResource *)malloc(sizeof(WinResource) * rescnt);
-
- /* fill in the WinResource's */
- for (c = 0; c < rescnt; c++) {
- RETURN_IF_BAD_POINTER(NULL, dirent[c]);
- wr[c].this_ = pe_res;
- wr[c].level = level;
- wr[c].is_directory = ((FROM_LE_32(dirent[c].offset_to_data) & IMAGE_RESOURCE_DATA_IS_DIRECTORY) != 0);
- wr[c].children = fi->first_resource + (FROM_LE_32(dirent[c].offset_to_data) & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY);
-
- /* fill in wr->id, wr->numeric_id */
- if (!decode_pe_resource_id(fi, wr + c, FROM_LE_32(dirent[c].name))) {
- free(wr);
- return NULL;
- }
- }
-
- return wr;
-}
-
-
-/**
- * Return an array of WinResource's in the current
- * resource level specified by _res->
- */
-Win32ResExtractor::WinResource *Win32ResExtractor::list_resources(WinLibrary *fi, WinResource *res, int *count) {
- if (res != NULL && !res->is_directory)
- return NULL;
-
- return list_pe_resources(fi, (Win32ImageResourceDirectory *)
- (res == NULL ? fi->first_resource : res->children),
- (res == NULL ? 0 : res->level+1),
- count);
-}
-
-/**
- * Read header and get resource directory offset in a Windows library
- * (AKA module).
- */
-bool Win32ResExtractor::read_library(WinLibrary *fi) {
- /* check for DOS header signature `MZ' */
- RETURN_IF_BAD_POINTER(false, MZ_HEADER(fi->memory)->magic);
- if (FROM_LE_16(MZ_HEADER(fi->memory)->magic) == IMAGE_DOS_SIGNATURE) {
- DOSImageHeader *mz_header = MZ_HEADER(fi->memory);
-
- RETURN_IF_BAD_POINTER(false, mz_header->lfanew);
-
- // Apply endian fix (currently only lfanew is used from the DOSImageHeader,
- // so we don't bother to 'fix' the rest).
- LE32(mz_header->lfanew);
-
- if (mz_header->lfanew < sizeof(DOSImageHeader)) {
- error("%s: not a Windows library", _fileName.c_str());
- return false;
- }
- }
-
- /* check for NT header signature `PE' */
- RETURN_IF_BAD_POINTER(false, PE_HEADER(fi->memory)->signature);
- if (FROM_LE_32(PE_HEADER(fi->memory)->signature) == IMAGE_NT_SIGNATURE) {
- Win32ImageNTHeaders *pe_header;
- int d;
-
- // Fix image header endianess
- fix_win32_image_header_endian(PE_HEADER(fi->memory));
-
- /* allocate new memory */
- fi->total_size = calc_vma_size(fi);
- if (fi->total_size == 0) {
- /* calc_vma_size has reported error */
- return false;
- }
- byte *ptr = (byte *)realloc(fi->memory, fi->total_size);
- assert(ptr);
- fi->memory = ptr;
-
- /* relocate memory, start from last section */
- pe_header = PE_HEADER(fi->memory);
- RETURN_IF_BAD_POINTER(false, pe_header->file_header.number_of_sections);
-
- /* we don't need to do OFFSET checking for the sections.
- * calc_vma_size has already done that */
- for (d = pe_header->file_header.number_of_sections - 1; d >= 0; d--) {
- Win32ImageSectionHeader *pe_sec = PE_SECTIONS(fi->memory) + d;
-
- if (pe_sec->characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- continue;
-
- //if (pe_sec->virtual_address + pe_sec->size_of_raw_data > fi->total_size)
-
- RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->virtual_address, pe_sec->size_of_raw_data);
- RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->pointer_to_raw_data, pe_sec->size_of_raw_data);
- if (FROM_LE_32(pe_sec->virtual_address) != pe_sec->pointer_to_raw_data) {
- memmove(fi->memory + pe_sec->virtual_address,
- fi->memory + pe_sec->pointer_to_raw_data,
- pe_sec->size_of_raw_data);
- }
- }
-
- /* find resource directory */
- RETURN_IF_BAD_POINTER(false, pe_header->optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
- Win32ImageDataDirectory *dir = pe_header->optional_header.data_directory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
- if (dir->size == 0) {
- error("%s: file contains no resources", _fileName.c_str());
- return false;
- }
-
- fix_win32_image_data_directory(dir);
-
- fi->first_resource = fi->memory + dir->virtual_address;
- return true;
- }
-
- /* other (unknown) header signature was found */
- error("%s: not a Windows library", _fileName.c_str());
- return false;
-}
-
-/**
- * Calculate the total amount of memory needed for a 32-bit Windows
- * module. Returns -1 if file was too small.
- */
-int Win32ResExtractor::calc_vma_size(WinLibrary *fi) {
- Win32ImageSectionHeader *seg;
- int c, segcount, size;
-
- size = 0;
- RETURN_IF_BAD_POINTER(-1, PE_HEADER(fi->memory)->file_header.number_of_sections);
- segcount = PE_HEADER(fi->memory)->file_header.number_of_sections;
-
- /* If there are no segments, just process file like it is.
- * This is (probably) not the right thing to do, but problems
- * will be delt with later anyway.
- */
- if (segcount == 0)
- return fi->total_size;
-
- seg = PE_SECTIONS(fi->memory);
- RETURN_IF_BAD_POINTER(-1, *seg);
- for (c = 0; c < segcount; c++) {
- RETURN_IF_BAD_POINTER(0, *seg);
- fix_win32_image_section_header(seg);
-
- size = MAX((uint32)size, seg->virtual_address + seg->size_of_raw_data);
- /* I have no idea what misc.virtual_size is for... */
- size = MAX((uint32)size, seg->virtual_address + seg->misc.virtual_size);
- seg++;
- }
-
- return size;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::find_with_resource_array(WinLibrary *fi, WinResource *wr, const char *id) {
- int c, rescnt;
- WinResource *return_wr;
-
- wr = list_resources(fi, wr, &rescnt);
- if (wr == NULL)
- return NULL;
-
- for (c = 0; c < rescnt; c++) {
- if (compare_resource_id(&wr[c], id)) {
- /* duplicate WinResource and return it */
- return_wr = (WinResource *)malloc(sizeof(WinResource));
- memcpy(return_wr, &wr[c], sizeof(WinResource));
-
- /* free old WinResource */
- free(wr);
- return return_wr;
- }
- }
-
- return NULL;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::find_resource(WinLibrary *fi, const char *type, const char *name, const char *language, int *level) {
- WinResource *wr;
-
- *level = 0;
- if (type == NULL)
- return NULL;
- wr = find_with_resource_array(fi, NULL, type);
- if (wr == NULL || !wr->is_directory)
- return wr;
-
- *level = 1;
- if (name == NULL)
- return wr;
- wr = find_with_resource_array(fi, wr, name);
- if (wr == NULL || !wr->is_directory)
- return wr;
-
- *level = 2;
- if (language == NULL)
- return wr;
- wr = find_with_resource_array(fi, wr, language);
- return wr;
-}
-
-#define ROW_BYTES(bits) ((((bits) + 31) >> 5) << 2)
-
-
-int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **pal, int *palSize) {
- Win32CursorIconFileDir dir;
- Win32CursorIconFileDirEntry *entries = NULL;
- uint32 offset;
- uint32 c, d;
- int completed;
- int matched = 0;
- Common::MemoryReadStream *in = new Common::MemoryReadStream(data, datasize);
-
- if (!in->read(&dir, sizeof(Win32CursorIconFileDir)- sizeof(Win32CursorIconFileDirEntry)))
- goto cleanup;
- fix_win32_cursor_icon_file_dir_endian(&dir);
-
- if (dir.reserved != 0) {
- error("not an icon or cursor file (reserved non-zero)");
- goto cleanup;
- }
- if (dir.type != 1 && dir.type != 2) {
- error("not an icon or cursor file (wrong type)");
- goto cleanup;
- }
-
- entries = (Win32CursorIconFileDirEntry *)malloc(dir.count * sizeof(Win32CursorIconFileDirEntry));
- for (c = 0; c < dir.count; c++) {
- if (!in->read(&entries[c], sizeof(Win32CursorIconFileDirEntry)))
- goto cleanup;
- fix_win32_cursor_icon_file_dir_entry_endian(&entries[c]);
- if (entries[c].reserved != 0)
- error("reserved is not zero");
- }
-
- offset = sizeof(Win32CursorIconFileDir) + (dir.count - 1) * (sizeof(Win32CursorIconFileDirEntry));
-
- for (completed = 0; completed < dir.count; ) {
- uint32 min_offset = 0x7fffffff;
- int previous = completed;
-
- for (c = 0; c < dir.count; c++) {
- if (entries[c].dib_offset == offset) {
- Win32BitmapInfoHeader bitmap;
- Win32RGBQuad *palette = NULL;
- uint32 palette_count = 0;
- uint32 image_size, mask_size;
- uint32 width, height;
- byte *image_data = NULL, *mask_data = NULL;
- byte *row = NULL;
-
- if (!in->read(&bitmap, sizeof(Win32BitmapInfoHeader)))
- goto local_cleanup;
-
- fix_win32_bitmap_info_header_endian(&bitmap);
- if (bitmap.size < sizeof(Win32BitmapInfoHeader)) {
- error("bitmap header is too short");
- goto local_cleanup;
- }
- if (bitmap.compression != 0) {
- error("compressed image data not supported");
- goto local_cleanup;
- }
- if (bitmap.x_pels_per_meter != 0)
- error("x_pels_per_meter field in bitmap should be zero");
- if (bitmap.y_pels_per_meter != 0)
- error("y_pels_per_meter field in bitmap should be zero");
- if (bitmap.clr_important != 0)
- error("clr_important field in bitmap should be zero");
- if (bitmap.planes != 1)
- error("planes field in bitmap should be one");
- if (bitmap.size != sizeof(Win32BitmapInfoHeader)) {
- uint32 skip = bitmap.size - sizeof(Win32BitmapInfoHeader);
- error("skipping %d bytes of extended bitmap header", skip);
- in->seek(skip, SEEK_CUR);
- }
- offset += bitmap.size;
-
- if (bitmap.clr_used != 0 || bitmap.bit_count < 24) {
- palette_count = (bitmap.clr_used != 0 ? bitmap.clr_used : 1 << bitmap.bit_count);
- palette = (Win32RGBQuad *)malloc(sizeof(Win32RGBQuad) * palette_count);
- if (!in->read(palette, sizeof(Win32RGBQuad) * palette_count))
- goto local_cleanup;
- offset += sizeof(Win32RGBQuad) * palette_count;
- }
-
- width = bitmap.width;
- height = ABS(bitmap.height)/2;
-
- image_size = height * ROW_BYTES(width * bitmap.bit_count);
- mask_size = height * ROW_BYTES(width);
-
- if (entries[c].dib_size != bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad))
- debugC(DEBUG_RESOURCE, "incorrect total size of bitmap (%d specified; %d real)",
- entries[c].dib_size,
- (int)(bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad))
- );
-
- image_data = (byte *)malloc(image_size);
- if (!in->read(image_data, image_size))
- goto local_cleanup;
-
- mask_data = (byte *)malloc(mask_size);
- if (!in->read(mask_data, mask_size))
- goto local_cleanup;
-
- offset += image_size;
- offset += mask_size;
- completed++;
- matched++;
-
- *hotspot_x = entries[c].hotspot_x;
- *hotspot_y = entries[c].hotspot_y;
- *w = width;
- *h = height;
- *keycolor = 0;
- *cursor = (byte *)malloc(width * height);
-
- row = (byte *)malloc(width * 4);
-
- for (d = 0; d < height; d++) {
- uint32 x;
- uint32 y = (bitmap.height < 0 ? d : height - d - 1);
- uint32 imod = y * (image_size / height) * 8 / bitmap.bit_count;
- uint32 mmod = y * (mask_size / height) * 8;
-
- for (x = 0; x < width; x++) {
-
- uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count);
-
- // We set up cursor palette for default cursor, so use it
- if (!simple_vec(mask_data, x + mmod, 1)) {
- if (color) {
- cursor[0][width * d + x] = 254; // white
- } else {
- cursor[0][width * d + x] = 253; // black
- }
- } else {
- cursor[0][width * d + x] = 255; // transparent
- }
- /*
-
- if (bitmap.bit_count <= 16) {
- if (color >= palette_count) {
- error("color out of range in image data");
- goto local_cleanup;
- }
- row[4*x+0] = palette[color].red;
- row[4*x+1] = palette[color].green;
- row[4*x+2] = palette[color].blue;
-
- } else {
- row[4*x+0] = (color >> 16) & 0xFF;
- row[4*x+1] = (color >> 8) & 0xFF;
- row[4*x+2] = (color >> 0) & 0xFF;
- }
- if (bitmap.bit_count == 32)
- row[4*x+3] = (color >> 24) & 0xFF;
- else
- row[4*x+3] = simple_vec(mask_data, x + mmod, 1) ? 0 : 0xFF;
- */
- }
-
- }
-
- free(row);
- free(palette);
- if (image_data != NULL) {
- free(image_data);
- free(mask_data);
- }
- continue;
-
- local_cleanup:
-
- free(row);
- free(palette);
- if (image_data != NULL) {
- free(image_data);
- free(mask_data);
- }
- goto cleanup;
- } else {
- if (entries[c].dib_offset > offset)
- min_offset = MIN(min_offset, entries[c].dib_offset);
- }
- }
-
- if (previous == completed) {
- if (min_offset < offset) {
- error("offset of bitmap header incorrect (too low)");
- goto cleanup;
- }
- assert(min_offset != 0x7fffffff);
- debugC(DEBUG_RESOURCE, "skipping %d bytes of garbage at %d", min_offset-offset, offset);
- in->seek(min_offset - offset, SEEK_CUR);
- offset = min_offset;
- }
- }
-
- free(entries);
- return matched;
-
-cleanup:
-
- free(entries);
- return -1;
-}
-
-uint32 Win32ResExtractor::simple_vec(byte *data, uint32 ofs, byte size) {
- switch (size) {
- case 1:
- return (data[ofs/8] >> (7 - ofs%8)) & 1;
- case 2:
- return (data[ofs/4] >> ((3 - ofs%4) << 1)) & 3;
- case 4:
- return (data[ofs/2] >> ((1 - ofs%2) << 2)) & 15;
- case 8:
- return data[ofs];
- case 16:
- return data[2*ofs] | data[2*ofs+1] << 8;
- case 24:
- return data[3*ofs] | data[3*ofs+1] << 8 | data[3*ofs+2] << 16;
- case 32:
- return data[4*ofs] | data[4*ofs+1] << 8 | data[4*ofs+2] << 16 | data[4*ofs+3] << 24;
- }
-
- return 0;
-}
-
-void Win32ResExtractor::fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj) {
- LE16(obj->reserved);
- LE16(obj->type);
- LE16(obj->count);
-}
-
-void Win32ResExtractor::fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj) {
- LE32(obj->size);
- LE32(obj->width);
- LE32(obj->height);
- LE16(obj->planes);
- LE16(obj->bit_count);
- LE32(obj->compression);
- LE32(obj->size_image);
- LE32(obj->x_pels_per_meter);
- LE32(obj->y_pels_per_meter);
- LE32(obj->clr_used);
- LE32(obj->clr_important);
-}
-
-void Win32ResExtractor::fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj) {
- LE16(obj->hotspot_x);
- LE16(obj->hotspot_y);
- LE32(obj->dib_size);
- LE32(obj->dib_offset);
-}
-
-void Win32ResExtractor::fix_win32_image_section_header(Win32ImageSectionHeader *obj) {
- LE32(obj->misc.physical_address);
- LE32(obj->virtual_address);
- LE32(obj->size_of_raw_data);
- LE32(obj->pointer_to_raw_data);
- LE32(obj->pointer_to_relocations);
- LE32(obj->pointer_to_linenumbers);
- LE16(obj->number_of_relocations);
- LE16(obj->number_of_linenumbers);
- LE32(obj->characteristics);
-}
-
-/* fix_win32_image_header_endian:
- * NOTE: This assumes that the optional header is always available.
- */
-void Win32ResExtractor::fix_win32_image_header_endian(Win32ImageNTHeaders *obj) {
- LE32(obj->signature);
- LE16(obj->file_header.machine);
- LE16(obj->file_header.number_of_sections);
- LE32(obj->file_header.time_date_stamp);
- LE32(obj->file_header.pointer_to_symbol_table);
- LE32(obj->file_header.number_of_symbols);
- LE16(obj->file_header.size_of_optional_header);
- LE16(obj->file_header.characteristics);
-
- // FIXME: Does this assert ever trigger? If so, we should modify this function
- // to properly deal with it.
- assert(obj->file_header.size_of_optional_header >= sizeof(obj->optional_header));
- LE16(obj->optional_header.magic);
- LE32(obj->optional_header.size_of_code);
- LE32(obj->optional_header.size_of_initialized_data);
- LE32(obj->optional_header.size_of_uninitialized_data);
- LE32(obj->optional_header.address_of_entry_point);
- LE32(obj->optional_header.base_of_code);
- LE32(obj->optional_header.base_of_data);
- LE32(obj->optional_header.image_base);
- LE32(obj->optional_header.section_alignment);
- LE32(obj->optional_header.file_alignment);
- LE16(obj->optional_header.major_operating_system_version);
- LE16(obj->optional_header.minor_operating_system_version);
- LE16(obj->optional_header.major_image_version);
- LE16(obj->optional_header.minor_image_version);
- LE16(obj->optional_header.major_subsystem_version);
- LE16(obj->optional_header.minor_subsystem_version);
- LE32(obj->optional_header.win32_version_value);
- LE32(obj->optional_header.size_of_image);
- LE32(obj->optional_header.size_of_headers);
- LE32(obj->optional_header.checksum);
- LE16(obj->optional_header.subsystem);
- LE16(obj->optional_header.dll_characteristics);
- LE32(obj->optional_header.size_of_stack_reserve);
- LE32(obj->optional_header.size_of_stack_commit);
- LE32(obj->optional_header.size_of_heap_reserve);
- LE32(obj->optional_header.size_of_heap_commit);
- LE32(obj->optional_header.loader_flags);
- LE32(obj->optional_header.number_of_rva_and_sizes);
-}
-
-void Win32ResExtractor::fix_win32_image_data_directory(Win32ImageDataDirectory *obj) {
- LE32(obj->virtual_address);
- LE32(obj->size);
-}
-
-
MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) {
_resMgr = NULL;
}
-int MacResExtractor::extractResource(int id, byte **buf) {
+bool MacResExtractor::extractResource(int id, CachedCursor *cc) {
// Create the MacResManager if not created already
if (_resMgr == NULL) {
_resMgr = new Common::MacResManager();
@@ -1158,25 +167,18 @@ int MacResExtractor::extractResource(int id, byte **buf) {
error("Cannot open file %s", _fileName.c_str());
}
- Common::SeekableReadStream *dataStream = _resMgr->getResource('crsr', 1000 + id);
+ Common::SeekableReadStream *dataStream = _resMgr->getResource('crsr', id + 1000);
if (!dataStream)
- error("There is no cursor ID #%d", 1000 + id);
-
- uint32 size = dataStream->size();
- *buf = (byte *)malloc(size);
- dataStream->read(*buf, size);
- delete dataStream;
+ return false;
- return size;
-}
+ int keyColor; // HACK: key color is ignored
+ _resMgr->convertCrsrCursor(dataStream, &cc->bitmap, cc->width, cc->height, cc->hotspotX, cc->hotspotY,
+ keyColor, _vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette),
+ &cc->palette, cc->palSize);
-int MacResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize) {
-
- _resMgr->convertCrsrCursor(data, datasize, cursor, w, h, hotspot_x, hotspot_y, keycolor,
- _vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette), palette, palSize);
- return 1;
+ delete dataStream;
+ return true;
}
void ScummEngine_v70he::readRoomsOffsets() {
@@ -1330,7 +332,7 @@ int ScummEngine_v72he::getSoundResourceSize(int id) {
if (!ptr)
return 0;
- if (READ_BE_UINT32(ptr) == MKID_BE('RIFF')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F')) {
byte flags;
int rate;
@@ -1342,11 +344,11 @@ int ScummEngine_v72he::getSoundResourceSize(int id) {
}
} else {
ptr += 8 + READ_BE_UINT32(ptr + 12);
- if (READ_BE_UINT32(ptr) == MKID_BE('SBNG')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('S','B','N','G')) {
ptr += READ_BE_UINT32(ptr + 4);
}
- assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT'));
+ assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T'));
size = READ_BE_UINT32(ptr + 4) - 8;
}
}
diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h
index 6b4c3fe493..5d7c70db76 100644
--- a/engines/scumm/he/resource_he.h
+++ b/engines/scumm/he/resource_he.h
@@ -4,10 +4,6 @@
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
- * Parts of this code are heavily based on:
- * icoutils - A set of programs dealing with MS Windows icons and cursors.
- * Copyright (C) 1998-2001 Oskar Liljeblad
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -31,89 +27,10 @@
#define SCUMM_HE_RESOURCE_HE_H
#include "common/macresman.h"
+#include "common/winexe_pe.h"
namespace Scumm {
-#define WINRES_ID_MAXLEN (256)
-
-/*
- * Definitions
- */
-
-#define MZ_HEADER(x) ((DOSImageHeader *)(x))
-
-#define STRIP_RES_ID_FORMAT(x) (x != NULL && (x[0] == '-' || x[0] == '+') ? ++x : x)
-
-#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
-#define IMAGE_SIZEOF_SHORT_NAME 8
-
-#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000
-#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000
-
-#define PE_HEADER(module) \
- ((Win32ImageNTHeaders*)((byte *)(module) + \
- (((DOSImageHeader*)(module))->lfanew)))
-
-#define PE_SECTIONS(module) \
- ((Win32ImageSectionHeader *)((byte *) &PE_HEADER(module)->optional_header + \
- PE_HEADER(module)->file_header.size_of_optional_header))
-
-#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
-#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
-
-/* The following symbols below and another group a few lines below are defined in
- * the windows header, at least in wince and most likely in plain win32 as well.
- * Defining them out silences a redefinition warning in gcc.
- * If the same problem arises in win32 builds as well, please replace
- * _WIN32_WCE with _WIN32 which is also defined in the wince platform.
- */
-#ifndef _WIN32_WCE
-#define IMAGE_SCN_CNT_CODE 0x00000020
-#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
-#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
-#endif
-
-// Only IMAGE_DIRECTORY_ENTRY_RESOURCE is used:
-#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
-#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
-#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
-#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
-#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
-#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
-#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
-#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
-#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* (MIPS GP) */
-#define IMAGE_DIRECTORY_ENTRY_TLS 9
-#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
-#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
-#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
-#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
-#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
-
-#ifndef _WIN32_WCE
-// Only RT_GROUP_CURSOR and RT_GROUP_ICON are used
-#define RT_CURSOR 1
-#define RT_BITMAP 2
-#define RT_ICON 3
-#define RT_MENU 4
-#define RT_DIALOG 5
-#define RT_STRING 6
-#define RT_FONTDIR 7
-#define RT_FONT 8
-#define RT_ACCELERATOR 9
-#define RT_RCDATA 10
-#define RT_MESSAGELIST 11
-#define RT_GROUP_CURSOR 12
-#define RT_GROUP_ICON 14
-#endif
-
-#define RETURN_IF_BAD_POINTER(r, x) \
- if (!check_offset(fi->memory, fi->total_size, _fileName.c_str(), &(x), sizeof(x))) \
- return (r);
-#define RETURN_IF_BAD_OFFSET(r, x, s) \
- if (!check_offset(fi->memory, fi->total_size, _fileName.c_str(), x, s)) \
- return (r);
-
class ScummEngine_v70he;
class ResExtractor {
@@ -123,312 +40,54 @@ public:
void setCursor(int id);
- virtual int extractResource(int id, byte **buf) { return 0; }
- virtual int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor,
- byte **palette, int *palSize) { return 0; }
-
- enum {
- MAX_CACHED_CURSORS = 10
- };
-
+protected:
struct CachedCursor {
bool valid;
int id;
byte *bitmap;
- int w, h;
- int hotspot_x, hotspot_y;
- uint32 last_used;
+ int width, height;
+ int hotspotX, hotspotY;
+ uint32 lastUsed;
byte *palette;
int palSize;
};
+ Common::String _fileName;
ScummEngine_v70he *_vm;
+ virtual bool extractResource(int id, CachedCursor *cc) = 0;
+
+private:
+ enum {
+ MAX_CACHED_CURSORS = 10
+ };
+
ResExtractor::CachedCursor *findCachedCursor(int id);
ResExtractor::CachedCursor *getCachedCursorSlot();
-
- bool _arg_raw;
- Common::String _fileName;
+
CachedCursor _cursorCache[MAX_CACHED_CURSORS];
};
class Win32ResExtractor : public ResExtractor {
- public:
+public:
Win32ResExtractor(ScummEngine_v70he *scumm);
~Win32ResExtractor() {}
- int extractResource(int id, byte **data);
- void setCursor(int id);
- int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize);
- private:
- int extractResource_(const char *resType, char *resName, byte **data);
-/*
- * Structures
- */
-
-#include "common/pack-start.h" // START STRUCT PACKING
-
- struct WinLibrary {
- Common::SeekableReadStream *file;
- byte *memory;
- byte *first_resource;
- int total_size;
- } PACKED_STRUCT;
-
- struct WinResource {
- char id[256];
- void *this_;
- void *children;
- int level;
- bool numeric_id;
- bool is_directory;
-
- Common::String getQuotedResourceId() const;
- } PACKED_STRUCT;
-
-
- struct Win32IconResDir {
- byte width;
- byte height;
- byte color_count;
- byte reserved;
- } PACKED_STRUCT;
-
- struct Win32CursorDir {
- uint16 width;
- uint16 height;
- } PACKED_STRUCT;
-
- struct Win32CursorIconDirEntry {
- union {
- Win32IconResDir icon;
- Win32CursorDir cursor;
- } res_info;
- uint16 plane_count;
- uint16 bit_count;
- uint32 bytes_in_res;
- uint16 res_id;
- } PACKED_STRUCT;
-
- struct Win32CursorIconDir {
- uint16 reserved;
- uint16 type;
- uint16 count;
- Win32CursorIconDirEntry entries[1];
- } PACKED_STRUCT;
-
- struct Win32CursorIconFileDirEntry {
- byte width;
- byte height;
- byte color_count;
- byte reserved;
- uint16 hotspot_x;
- uint16 hotspot_y;
- uint32 dib_size;
- uint32 dib_offset;
- } PACKED_STRUCT;
-
- struct Win32CursorIconFileDir {
- uint16 reserved;
- uint16 type;
- uint16 count;
- Win32CursorIconFileDirEntry entries[1];
- } PACKED_STRUCT;
-
- struct Win32BitmapInfoHeader {
- uint32 size;
- int32 width;
- int32 height;
- uint16 planes;
- uint16 bit_count;
- uint32 compression;
- uint32 size_image;
- int32 x_pels_per_meter;
- int32 y_pels_per_meter;
- uint32 clr_used;
- uint32 clr_important;
- } PACKED_STRUCT;
-
- struct Win32RGBQuad {
- byte blue;
- byte green;
- byte red;
- byte reserved;
- } PACKED_STRUCT;
-
- struct Win32ImageResourceDirectoryEntry {
- uint32 name;
- uint32 offset_to_data;
- } PACKED_STRUCT;
-
- struct Win16NETypeInfo {
- uint16 type_id;
- uint16 count;
- uint32 resloader; // FARPROC16 - smaller? uint16?
- } PACKED_STRUCT;
-
- struct DOSImageHeader {
- uint16 magic;
- uint16 cblp;
- uint16 cp;
- uint16 crlc;
- uint16 cparhdr;
- uint16 minalloc;
- uint16 maxalloc;
- uint16 ss;
- uint16 sp;
- uint16 csum;
- uint16 ip;
- uint16 cs;
- uint16 lfarlc;
- uint16 ovno;
- uint16 res[4];
- uint16 oemid;
- uint16 oeminfo;
- uint16 res2[10];
- uint32 lfanew;
- } PACKED_STRUCT;
-
- struct Win32ImageFileHeader {
- uint16 machine;
- uint16 number_of_sections;
- uint32 time_date_stamp;
- uint32 pointer_to_symbol_table;
- uint32 number_of_symbols;
- uint16 size_of_optional_header;
- uint16 characteristics;
- } PACKED_STRUCT;
-
- struct Win32ImageDataDirectory {
- uint32 virtual_address;
- uint32 size;
- } PACKED_STRUCT;
-
- struct Win32ImageOptionalHeader {
- uint16 magic;
- byte major_linker_version;
- byte minor_linker_version;
- uint32 size_of_code;
- uint32 size_of_initialized_data;
- uint32 size_of_uninitialized_data;
- uint32 address_of_entry_point;
- uint32 base_of_code;
- uint32 base_of_data;
- uint32 image_base;
- uint32 section_alignment;
- uint32 file_alignment;
- uint16 major_operating_system_version;
- uint16 minor_operating_system_version;
- uint16 major_image_version;
- uint16 minor_image_version;
- uint16 major_subsystem_version;
- uint16 minor_subsystem_version;
- uint32 win32_version_value;
- uint32 size_of_image;
- uint32 size_of_headers;
- uint32 checksum;
- uint16 subsystem;
- uint16 dll_characteristics;
- uint32 size_of_stack_reserve;
- uint32 size_of_stack_commit;
- uint32 size_of_heap_reserve;
- uint32 size_of_heap_commit;
- uint32 loader_flags;
- uint32 number_of_rva_and_sizes;
- Win32ImageDataDirectory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
- } PACKED_STRUCT;
-
- struct Win32ImageNTHeaders {
- uint32 signature;
- Win32ImageFileHeader file_header;
- Win32ImageOptionalHeader optional_header;
- } PACKED_STRUCT;
-
- struct Win32ImageSectionHeader {
- byte name[IMAGE_SIZEOF_SHORT_NAME];
- union {
- uint32 physical_address;
- uint32 virtual_size;
- } misc;
- uint32 virtual_address;
- uint32 size_of_raw_data;
- uint32 pointer_to_raw_data;
- uint32 pointer_to_relocations;
- uint32 pointer_to_linenumbers;
- uint16 number_of_relocations;
- uint16 number_of_linenumbers;
- uint32 characteristics;
- } PACKED_STRUCT;
-
- struct Win32ImageResourceDataEntry {
- uint32 offset_to_data;
- uint32 size;
- uint32 code_page;
- uint32 resource_handle;
- } PACKED_STRUCT;
-
- struct Win32ImageResourceDirectory {
- uint32 characteristics;
- uint32 time_date_stamp;
- uint16 major_version;
- uint16 minor_version;
- uint16 number_of_named_entries;
- uint16 number_of_id_entries;
- } PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
-/*
- * Function Prototypes
- */
-
- WinResource *list_resources(WinLibrary *, WinResource *, int *);
- bool read_library(WinLibrary *);
- WinResource *find_resource(WinLibrary *, const char *, const char *, const char *, int *);
- byte *get_resource_entry(WinLibrary *, WinResource *, int *);
- int do_resources(WinLibrary *, const char *, char *, char *, byte **);
- bool compare_resource_id(WinResource *, const char *);
- const char *res_type_string_to_id(const char *);
-
- const char *res_type_id_to_string(int);
- char *get_destination_name(WinLibrary *, char *, char *, char *);
-
- byte *extract_resource(WinLibrary *, WinResource *, int *, bool *, char *, char *, bool);
- int extract_resources(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, byte **);
- byte *extract_group_icon_cursor_resource(WinLibrary *, WinResource *, char *, int *, bool);
-
- bool decode_pe_resource_id(WinLibrary *, WinResource *, uint32);
- WinResource *list_pe_resources(WinLibrary *, Win32ImageResourceDirectory *, int, int *);
- int calc_vma_size(WinLibrary *);
- int do_resources_recurs(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, const char *, char *, char *, byte **);
- WinResource *find_with_resource_array(WinLibrary *, WinResource *, const char *);
-
- bool check_offset(byte *, int, const char *, void *, int);
-
- uint32 simple_vec(byte *data, uint32 ofs, byte size);
+private:
+ Common::PEResources _exe;
- void fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj);
- void fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj);
- void fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj);
- void fix_win32_image_section_header(Win32ImageSectionHeader *obj);
- void fix_win32_image_header_endian(Win32ImageNTHeaders *obj);
- void fix_win32_image_data_directory(Win32ImageDataDirectory *obj);
+ bool extractResource(int id, CachedCursor *cc);
};
class MacResExtractor : public ResExtractor {
-
public:
MacResExtractor(ScummEngine_v70he *scumm);
- ~MacResExtractor() { }
+ ~MacResExtractor() {}
private:
Common::MacResManager *_resMgr;
- int extractResource(int id, byte **buf);
- int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize);
+ bool extractResource(int id, CachedCursor *cc);
};
} // End of namespace Scumm
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index ca4a65ac74..69063a1837 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -2999,7 +2999,7 @@ void ScummEngine_v100he::decodeParseString(int m, int n) {
case 78:
{
byte *dataPtr = getResourceAddress(rtTalkie, pop());
- byte *text = findWrappedBlock(MKID_BE('TEXT'), dataPtr, 0, 0);
+ byte *text = findWrappedBlock(MKTAG('T','E','X','T'), dataPtr, 0, 0);
size = getResourceDataSize(text);
memcpy(name, text, size);
printString(m, name);
diff --git a/engines/scumm/he/script_v60he.cpp b/engines/scumm/he/script_v60he.cpp
index 9d62a31f6d..7ecabd55e1 100644
--- a/engines/scumm/he/script_v60he.cpp
+++ b/engines/scumm/he/script_v60he.cpp
@@ -741,10 +741,14 @@ void ScummEngine_v60he::o60_openFile() {
void ScummEngine_v60he::o60_closeFile() {
int slot = pop();
if (0 <= slot && slot < 17) {
- delete _hInFileTable[slot];
- delete _hOutFileTable[slot];
+ if (_hOutFileTable[slot]) {
+ _hOutFileTable[slot]->finalize();
+ delete _hOutFileTable[slot];
+ _hOutFileTable[slot] = 0;
+ }
+
+ delete _hInFileTable[slot];
_hInFileTable[slot] = 0;
- _hOutFileTable[slot] = 0;
}
}
diff --git a/engines/scumm/he/script_v71he.cpp b/engines/scumm/he/script_v71he.cpp
index 46a8868949..a800a7d85c 100644
--- a/engines/scumm/he/script_v71he.cpp
+++ b/engines/scumm/he/script_v71he.cpp
@@ -88,15 +88,15 @@ byte *ScummEngine_v71he::heFindResource(uint32 tag, byte *searchin) {
}
byte *ScummEngine_v71he::findWrappedBlock(uint32 tag, byte *ptr, int state, bool errorFlag) {
- if (READ_BE_UINT32(ptr) == MKID_BE('MULT')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('M','U','L','T')) {
byte *offs, *wrap;
uint32 size;
- wrap = heFindResource(MKID_BE('WRAP'), ptr);
+ wrap = heFindResource(MKTAG('W','R','A','P'), ptr);
if (wrap == NULL)
return NULL;
- offs = heFindResourceData(MKID_BE('OFFS'), wrap);
+ offs = heFindResourceData(MKTAG('O','F','F','S'), wrap);
if (offs == NULL)
return NULL;
@@ -109,7 +109,7 @@ byte *ScummEngine_v71he::findWrappedBlock(uint32 tag, byte *ptr, int state, bool
if (offs)
return offs;
- offs = heFindResourceData(MKID_BE('DEFA'), ptr);
+ offs = heFindResourceData(MKTAG('D','E','F','A'), ptr);
if (offs == NULL)
return NULL;
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index 32c15abcba..17bd29d826 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -1408,18 +1408,49 @@ void ScummEngine_v72he::o72_openFile() {
if (slot != -1) {
switch (mode) {
- case 1:
+ case 1: // Read mode
if (!_saveFileMan->listSavefiles(filename).empty()) {
_hInFileTable[slot] = _saveFileMan->openForLoading(filename);
} else {
_hInFileTable[slot] = SearchMan.createReadStreamForMember(filename);
}
break;
- case 2:
+ case 2: // Write mode
if (!strchr(filename, '/')) {
_hOutFileTable[slot] = _saveFileMan->openForSaving(filename);
}
break;
+ case 6: { // Append mode
+ if (strchr(filename, '/'))
+ break;
+
+ // First check if the file already exists
+ Common::InSaveFile *initialState = 0;
+ if (!_saveFileMan->listSavefiles(filename).empty())
+ initialState = _saveFileMan->openForLoading(filename);
+ else
+ initialState = SearchMan.createReadStreamForMember(filename);
+
+ // Read in the data from the initial file
+ uint32 initialSize = 0;
+ byte *initialData = 0;
+ if (initialState) {
+ initialSize = initialState->size();
+ initialData = new byte[initialSize];
+ initialState->read(initialData, initialSize);
+ delete initialState;
+ }
+
+ // Attempt to open a save file
+ _hOutFileTable[slot] = _saveFileMan->openForSaving(filename);
+
+ // Begin us off with the data from the previous file
+ if (_hOutFileTable[slot] && initialData) {
+ _hOutFileTable[slot]->write(initialData, initialSize);
+ delete[] initialData;
+ }
+
+ } break;
default:
error("o72_openFile(): wrong open file mode %d", mode);
}
@@ -2008,7 +2039,7 @@ void ScummEngine_v72he::decodeParseString(int m, int n) {
case 0xE1:
{
byte *dataPtr = getResourceAddress(rtTalkie, pop());
- byte *text = findWrappedBlock(MKID_BE('TEXT'), dataPtr, 0, 0);
+ byte *text = findWrappedBlock(MKTAG('T','E','X','T'), dataPtr, 0, 0);
size = getResourceDataSize(text);
memcpy(name, text, size);
printString(m, name);
diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp
index 841eba960d..1a38a99f17 100644
--- a/engines/scumm/he/script_v90he.cpp
+++ b/engines/scumm/he/script_v90he.cpp
@@ -351,12 +351,12 @@ void ScummEngine_v90he::o90_max() {
}
void ScummEngine_v90he::o90_sin() {
- double a = pop() * PI / 180.;
+ double a = pop() * M_PI / 180.;
push((int)(sin(a) * 100000));
}
void ScummEngine_v90he::o90_cos() {
- double a = pop() * PI / 180.;
+ double a = pop() * M_PI / 180.;
push((int)(cos(a) * 100000));
}
@@ -372,7 +372,7 @@ void ScummEngine_v90he::o90_sqrt() {
void ScummEngine_v90he::o90_atan2() {
int y = pop();
int x = pop();
- int a = (int)(atan2((double)y, (double)x) * 180. / PI);
+ int a = (int)(atan2((double)y, (double)x) * 180. / M_PI);
if (a < 0) {
a += 360;
}
@@ -384,7 +384,7 @@ void ScummEngine_v90he::o90_getSegmentAngle() {
int x1 = pop();
int dy = y1 - pop();
int dx = x1 - pop();
- int a = (int)(atan2((double)dy, (double)dx) * 180. / PI);
+ int a = (int)(atan2((double)dy, (double)dx) * 180. / M_PI);
if (a < 0) {
a += 360;
}
@@ -2292,13 +2292,13 @@ void ScummEngine_v90he::o90_kernelGetFunctions() {
switch (args[0]) {
case 1001:
{
- double b = args[1] * PI / 180.;
+ double b = args[1] * M_PI / 180.;
push((int)(sin(b) * 100000));
}
break;
case 1002:
{
- double b = args[1] * PI / 180.;
+ double b = args[1] * M_PI / 180.;
push((int)(cos(b) * 100000));
}
break;
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index 4770f28cbc..4fd7caebf5 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -499,11 +499,11 @@ byte *findSoundTag(uint32 tag, byte *ptr) {
byte *endPtr;
uint32 offset, size;
- if (READ_BE_UINT32(ptr) == MKID_BE('WSOU')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) {
ptr += 8;
}
- if (READ_BE_UINT32(ptr) != MKID_BE('RIFF'))
+ if (READ_BE_UINT32(ptr) != MKTAG('R','I','F','F'))
return NULL;
endPtr = (ptr + 12);
@@ -591,14 +591,14 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
}
// Support for sound in later HE games
- if (READ_BE_UINT32(ptr) == MKID_BE('RIFF') || READ_BE_UINT32(ptr) == MKID_BE('WSOU')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F') || READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) {
uint16 compType;
int blockAlign;
int codeOffs = -1;
priority = (soundID > _vm->_numSounds) ? 255 : *(ptr + 18);
- byte *sbngPtr = findSoundTag(MKID_BE('SBNG'), ptr);
+ byte *sbngPtr = findSoundTag(MKTAG('S','B','N','G'), ptr);
if (sbngPtr != NULL) {
codeOffs = sbngPtr - ptr + 8;
}
@@ -611,7 +611,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
return;
}
- if (READ_BE_UINT32(ptr) == MKID_BE('WSOU'))
+ if (READ_BE_UINT32(ptr) == MKTAG('W','S','O','U'))
ptr += 8;
size = READ_LE_UINT32(ptr + 4);
@@ -675,7 +675,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
Audio::makeLoopingAudioStream(stream, (heFlags & 1) ? 0 : 1), soundID);
}
// Support for sound in Humongous Entertainment games
- else if (READ_BE_UINT32(ptr) == MKID_BE('DIGI') || READ_BE_UINT32(ptr) == MKID_BE('TALK')) {
+ else if (READ_BE_UINT32(ptr) == MKTAG('D','I','G','I') || READ_BE_UINT32(ptr) == MKTAG('T','A','L','K')) {
byte *sndPtr = ptr;
int codeOffs = -1;
@@ -693,12 +693,12 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
return;
}
- if (READ_BE_UINT32(ptr) == MKID_BE('SBNG')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('S','B','N','G')) {
codeOffs = ptr - sndPtr + 8;
ptr += READ_BE_UINT32(ptr + 4);
}
- assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT'));
+ assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T'));
size = READ_BE_UINT32(ptr + 4) - 8;
if (heOffset < 0 || heOffset > size) {
// Occurs when making fireworks in puttmoon
@@ -734,14 +734,14 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
Audio::makeLoopingAudioStream(stream, (heFlags & 1) ? 0 : 1), soundID);
}
// Support for PCM music in 3DO versions of Humongous Entertainment games
- else if (READ_BE_UINT32(ptr) == MKID_BE('MRAW')) {
+ else if (READ_BE_UINT32(ptr) == MKTAG('M','R','A','W')) {
priority = *(ptr + 18);
rate = READ_LE_UINT16(ptr + 22);
// Skip DIGI (8) and HSHD (24) blocks
ptr += 32;
- assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT'));
+ assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T'));
size = READ_BE_UINT32(ptr + 4) - 8;
byte *sound = (byte *)malloc(size);
@@ -753,7 +753,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
stream = Audio::makeRawStream(sound, size, rate, 0);
_mixer->playStream(Audio::Mixer::kMusicSoundType, NULL, stream, soundID);
}
- else if (READ_BE_UINT32(ptr) == MKID_BE('MIDI')) {
+ else if (READ_BE_UINT32(ptr) == MKTAG('M','I','D','I')) {
if (_vm->_imuse) {
// This is used in the DOS version of Fatty Bear's
// Birthday Surprise to change the note on the piano
@@ -833,9 +833,9 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) {
chan = i;
}
- if (!findSoundTag(MKID_BE('data'), snd1Ptr)) {
- sbng1Ptr = heFindResource(MKID_BE('SBNG'), snd1Ptr);
- sbng2Ptr = heFindResource(MKID_BE('SBNG'), snd2Ptr);
+ if (!findSoundTag(MKTAG('d','a','t','a'), snd1Ptr)) {
+ sbng1Ptr = heFindResource(MKTAG('S','B','N','G'), snd1Ptr);
+ sbng2Ptr = heFindResource(MKTAG('S','B','N','G'), snd2Ptr);
}
if (sbng1Ptr != NULL && sbng2Ptr != NULL) {
@@ -879,10 +879,10 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) {
}
}
- if (findSoundTag(MKID_BE('data'), snd1Ptr)) {
- sdat1Ptr = findSoundTag(MKID_BE('data'), snd1Ptr);
+ if (findSoundTag(MKTAG('d','a','t','a'), snd1Ptr)) {
+ sdat1Ptr = findSoundTag(MKTAG('d','a','t','a'), snd1Ptr);
assert(sdat1Ptr);
- sdat2Ptr = findSoundTag(MKID_BE('data'), snd2Ptr);
+ sdat2Ptr = findSoundTag(MKTAG('d','a','t','a'), snd2Ptr);
assert(sdat2Ptr);
if (!_sndDataSize)
@@ -890,9 +890,9 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) {
sdat2size = READ_LE_UINT32(sdat2Ptr + 4) - 8;
} else {
- sdat1Ptr = heFindResource(MKID_BE('SDAT'), snd1Ptr);
+ sdat1Ptr = heFindResource(MKTAG('S','D','A','T'), snd1Ptr);
assert(sdat1Ptr);
- sdat2Ptr = heFindResource(MKID_BE('SDAT'), snd2Ptr);
+ sdat2Ptr = heFindResource(MKTAG('S','D','A','T'), snd2Ptr);
assert(sdat2Ptr);
_sndDataSize = READ_BE_UINT32(sdat1Ptr + 4) - 8;
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
index 5f751d8285..c66eed6ae6 100644
--- a/engines/scumm/he/sprite_he.cpp
+++ b/engines/scumm/he/sprite_he.cpp
@@ -46,7 +46,7 @@ Sprite::~Sprite() {
}
void ScummEngine_v90he::allocateArrays() {
- ScummEngine::allocateArrays();
+ ScummEngine_v70he::allocateArrays();
_sprite->allocTables(_numSprites, MAX(64, _numSprites / 4), 64);
}
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index c7e6a56083..16cbadd65b 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -111,7 +111,7 @@ void Wiz::polygonStore(int id, bool flag, int vert1x, int vert1y, int vert2x, in
}
void Wiz::polygonRotatePoints(Common::Point *pts, int num, int angle) {
- double alpha = angle * PI / 180.;
+ double alpha = angle * M_PI / 180.;
double cos_alpha = cos(alpha);
double sin_alpha = sin(alpha);
@@ -1445,21 +1445,21 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
if (shadow) {
dataPtr = _vm->getResourceAddress(rtImage, shadow);
assert(dataPtr);
- xmapPtr = _vm->findResourceData(MKID_BE('XMAP'), dataPtr);
+ xmapPtr = _vm->findResourceData(MKTAG('X','M','A','P'), dataPtr);
assert(xmapPtr);
}
dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
uint32 comp = READ_LE_UINT32(wizh + 0x0);
uint32 width = READ_LE_UINT32(wizh + 0x4);
uint32 height = READ_LE_UINT32(wizh + 0x8);
debug(3, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height);
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
uint8 *mask = NULL;
@@ -1467,28 +1467,28 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
uint8 *maskPtr = _vm->getResourceAddress(rtImage, maskNum);
assert(maskPtr);
- wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), maskPtr, maskState, 0);
+ wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), maskPtr, maskState, 0);
assert(wizh);
assert(comp == 2 && READ_LE_UINT32(wizh + 0x0) == 1);
width = READ_LE_UINT32(wizh + 0x4);
height = READ_LE_UINT32(wizh + 0x8);
- mask = _vm->findWrappedBlock(MKID_BE('WIZD'), maskPtr, maskState, 0);
+ mask = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), maskPtr, maskState, 0);
assert(mask);
}
if (flags & kWIFHasPalette) {
- uint8 *pal = _vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0);
+ uint8 *pal = _vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0);
assert(pal);
_vm->setPaletteFromPtr(pal, 256);
}
uint8 *rmap = NULL;
if (flags & kWIFRemapPalette) {
- rmap = _vm->findWrappedBlock(MKID_BE('RMAP'), dataPtr, state, 0);
+ rmap = _vm->findWrappedBlock(MKTAG('R','M','A','P'), dataPtr, state, 0);
assert(rmap);
if (_vm->_game.heversion <= 80 || READ_BE_UINT32(rmap) != 0x01234567) {
- uint8 *rgbs = _vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0);
+ uint8 *rgbs = _vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0);
assert(rgbs);
_vm->remapHEPalette(rgbs, rmap + 4);
}
@@ -1526,7 +1526,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
if (dstResNum) {
uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum);
assert(dstPtr);
- dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
+ dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0);
assert(dst);
getWizImageDim(dstResNum, 0, cw, ch);
dstPitch = cw * _vm->_bytesPerPixel;
@@ -1567,7 +1567,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
int transColor = -1;
if (_vm->VAR_WIZ_TCOLOR != 0xFF) {
- uint8 *trns = _vm->findWrappedBlock(MKID_BE('TRNS'), dataPtr, state, 0);
+ uint8 *trns = _vm->findWrappedBlock(MKTAG('T','R','N','S'), dataPtr, state, 0);
transColor = (trns == NULL) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : -1;
}
@@ -1817,7 +1817,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
assert(_vm->_bytesPerPixel == 1);
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- srcWizBuf = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ srcWizBuf = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(srcWizBuf);
freeBuffer = false;
}
@@ -1827,7 +1827,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
} else {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- srcWizBuf = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ srcWizBuf = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(srcWizBuf);
freeBuffer = false;
}
@@ -1842,7 +1842,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
if (dstResNum) {
uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum);
assert(dstPtr);
- dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
+ dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0);
assert(dst);
getWizImageDim(dstResNum, 0, dstw, dsth);
dstpitch = dstw * _vm->_bytesPerPixel;
@@ -2185,7 +2185,7 @@ void Wiz::fillWizRect(const WizParameters *params) {
}
uint8 *dataPtr = _vm->getResourceAddress(rtImage, params->img.resNum);
if (dataPtr) {
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
@@ -2210,7 +2210,7 @@ void Wiz::fillWizRect(const WizParameters *params) {
}
if (areaRect.intersects(imageRect)) {
areaRect.clip(imageRect);
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
int dx = areaRect.width();
int dy = areaRect.height();
@@ -2256,7 +2256,7 @@ void Wiz::fillWizLine(const WizParameters *params) {
}
uint8 *dataPtr = _vm->getResourceAddress(rtImage, params->img.resNum);
if (dataPtr) {
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
@@ -2274,7 +2274,7 @@ void Wiz::fillWizLine(const WizParameters *params) {
if (params->processFlags & kWPFFillColor) {
color = params->fillColor;
}
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
int x1 = params->box2.left;
int y1 = params->box2.top;
@@ -2309,7 +2309,7 @@ void Wiz::fillWizPixel(const WizParameters *params) {
if (params->processFlags & kWPFNewState) {
state = params->img.state;
}
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
@@ -2327,7 +2327,7 @@ void Wiz::fillWizPixel(const WizParameters *params) {
color = params->fillColor;
}
if (imageRect.contains(px, py)) {
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
assert(wizd);
*(wizd + py * w + px) = color;
}
@@ -2342,7 +2342,7 @@ void Wiz::remapWizImagePal(const WizParameters *params) {
const uint8 *index = params->remapIndex;
uint8 *iwiz = _vm->getResourceAddress(rtImage, params->img.resNum);
assert(iwiz);
- uint8 *rmap = _vm->findWrappedBlock(MKID_BE('RMAP'), iwiz, st, 0);
+ uint8 *rmap = _vm->findWrappedBlock(MKTAG('R','M','A','P'), iwiz, st, 0);
assert(rmap);
WRITE_BE_UINT32(rmap, 0x01234567);
while (num--) {
@@ -2380,7 +2380,7 @@ void Wiz::processWizImage(const WizParameters *params) {
if (f) {
uint32 id = f->readUint32BE();
- if (id == MKID_BE('AWIZ') || id == MKID_BE('MULT')) {
+ if (id == MKTAG('A','W','I','Z') || id == MKTAG('M','U','L','T')) {
uint32 size = f->readUint32BE();
f->seek(0, SEEK_SET);
byte *p = _vm->_res->createResource(rtImage, params->img.resNum, size);
@@ -2510,7 +2510,7 @@ void Wiz::processWizImage(const WizParameters *params) {
void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
w = READ_LE_UINT32(wizh + 0x4);
h = READ_LE_UINT32(wizh + 0x8);
@@ -2519,7 +2519,7 @@ void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) {
void Wiz::getWizImageSpot(int resId, int state, int32 &x, int32 &y) {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resId);
assert(dataPtr);
- uint8 *spotPtr = _vm->findWrappedBlock(MKID_BE('SPOT'), dataPtr, state, 0);
+ uint8 *spotPtr = _vm->findWrappedBlock(MKTAG('S','P','O','T'), dataPtr, state, 0);
if (spotPtr) {
x = READ_LE_UINT32(spotPtr + 0);
y = READ_LE_UINT32(spotPtr + 4);
@@ -2537,17 +2537,17 @@ int Wiz::getWizImageData(int resNum, int state, int type) {
switch (type) {
case 0:
- wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0);
+ wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
return READ_LE_UINT32(wizh + 0x0);
case 1:
- return (_vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0) != NULL) ? 1 : 0;
+ return (_vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0) != NULL) ? 1 : 0;
case 2:
- return (_vm->findWrappedBlock(MKID_BE('RMAP'), dataPtr, state, 0) != NULL) ? 1 : 0;
+ return (_vm->findWrappedBlock(MKTAG('R','M','A','P'), dataPtr, state, 0) != NULL) ? 1 : 0;
case 3:
- return (_vm->findWrappedBlock(MKID_BE('TRNS'), dataPtr, state, 0) != NULL) ? 1 : 0;
+ return (_vm->findWrappedBlock(MKTAG('T','R','N','S'), dataPtr, state, 0) != NULL) ? 1 : 0;
case 4:
- return (_vm->findWrappedBlock(MKID_BE('XMAP'), dataPtr, state, 0) != NULL) ? 1 : 0;
+ return (_vm->findWrappedBlock(MKTAG('X','M','A','P'), dataPtr, state, 0) != NULL) ? 1 : 0;
default:
error("getWizImageData: Unknown type %d", type);
}
@@ -2556,14 +2556,14 @@ int Wiz::getWizImageData(int resNum, int state, int type) {
int Wiz::getWizImageStates(int resNum) {
const uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
- if (READ_BE_UINT32(dataPtr) == MKID_BE('MULT')) {
+ if (READ_BE_UINT32(dataPtr) == MKTAG('M','U','L','T')) {
const byte *offs, *wrap;
- wrap = _vm->findResource(MKID_BE('WRAP'), dataPtr);
+ wrap = _vm->findResource(MKTAG('W','R','A','P'), dataPtr);
if (wrap == NULL)
return 1;
- offs = _vm->findResourceData(MKID_BE('OFFS'), wrap);
+ offs = _vm->findResourceData(MKTAG('O','F','F','S'), wrap);
if (offs == NULL)
return 1;
@@ -2577,12 +2577,12 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags
int ret = 0;
uint8 *data = _vm->getResourceAddress(rtImage, resNum);
assert(data);
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), data, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
int h = READ_LE_UINT32(wizh + 0x8);
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), data, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0);
assert(wizd);
if (x >= 0 && x < w && y >= 0 && y < h) {
if (flags & kWIFFlipX) {
@@ -2627,12 +2627,12 @@ uint16 Wiz::getWizPixelColor(int resNum, int state, int x, int y) {
uint16 color = 0;
uint8 *data = _vm->getResourceAddress(rtImage, resNum);
assert(data);
- uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), data, state, 0);
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
int h = READ_LE_UINT32(wizh + 0x8);
- uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), data, state, 0);
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0);
assert(wizd);
switch (c) {
case 0:
@@ -2671,13 +2671,13 @@ int ScummEngine_v90he::computeWizHistogram(int resNum, int state, int x, int y,
Common::Rect rCapt(x, y, w + 1, h + 1);
uint8 *data = getResourceAddress(rtImage, resNum);
assert(data);
- uint8 *wizh = findWrappedBlock(MKID_BE('WIZH'), data, state, 0);
+ uint8 *wizh = findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
w = READ_LE_UINT32(wizh + 0x4);
h = READ_LE_UINT32(wizh + 0x8);
Common::Rect rWiz(w, h);
- uint8 *wizd = findWrappedBlock(MKID_BE('WIZD'), data, state, 0);
+ uint8 *wizd = findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0);
assert(wizd);
if (rCapt.intersects(rWiz)) {
rCapt.clip(rWiz);
diff --git a/engines/scumm/help.cpp b/engines/scumm/help.cpp
index 3738ebc2e5..a3bb85ab42 100644
--- a/engines/scumm/help.cpp
+++ b/engines/scumm/help.cpp
@@ -79,14 +79,14 @@ void ScummHelp::updateStrings(byte gameId, byte version, Common::Platform platfo
ADD_BIND(".", _("Skip line of text"));
ADD_BIND(_("Esc"), _("Skip cutscene"));
ADD_BIND(_("Space"), _("Pause game"));
- ADD_BIND(_("Ctrl 0-9"), _("Load game state 1-10"));
- ADD_BIND(_("Alt 0-9"), _("Save game state 1-10"));
+ ADD_BIND(String(_("Ctrl")) + " 0-9", _("Load game state 1-10"));
+ ADD_BIND(String(_("Alt")) + " 0-9", _("Save game state 1-10"));
#ifdef MACOSX
ADD_BIND("Cmd q", _("Quit"));
#else
- ADD_BIND(_("Alt x, Ctrl z"), _("Quit"));
+ ADD_BIND(String(_("Alt")) + " x, " + _("Ctrl") + " z", _("Quit"));
#endif
- ADD_BIND(_("Alt Enter"), _("Toggle fullscreen"));
+ ADD_BIND(String(_("Alt")) + " " + _("Enter"), _("Toggle fullscreen"));
ADD_BIND("[, ]", _("Music volume up / down"));
ADD_BIND("-, +", _("Text speed slower / faster"));
ADD_BIND(_("Enter"), _("Simulate left mouse button"));
@@ -95,14 +95,14 @@ void ScummHelp::updateStrings(byte gameId, byte version, Common::Platform platfo
case 2:
title = _("Special keyboard commands:");
ADD_BIND("~, #", _("Show / Hide console"));
- ADD_BIND(_("Ctrl d"), _("Start the debugger"));
- ADD_BIND(_("Ctrl s"), _("Show memory consumption"));
- ADD_BIND(_("Ctrl f"), _("Run in fast mode (*)"));
- ADD_BIND(_("Ctrl g"), _("Run in really fast mode (*)"));
- ADD_BIND(_("Ctrl m"), _("Toggle mouse capture"));
- ADD_BIND(_("Ctrl Alt 1-8"), _("Switch between graphics filters"));
- ADD_BIND(_("Ctrl Alt +, -"), _("Increase / Decrease scale factor"));
- ADD_BIND(_("Ctrl Alt a"), _("Toggle aspect-ratio correction"));
+ ADD_BIND(String(_("Ctrl")) + " d", _("Start the debugger"));
+ ADD_BIND(String(_("Ctrl")) + " s", _("Show memory consumption"));
+ ADD_BIND(String(_("Ctrl")) + " f", _("Run in fast mode (*)"));
+ ADD_BIND(String(_("Ctrl")) + " g", _("Run in really fast mode (*)"));
+ ADD_BIND(String(_("Ctrl")) + " m", _("Toggle mouse capture"));
+ ADD_BIND(String(_("Ctrl")) + " " + _("Alt") + " 1-8", _("Switch between graphics filters"));
+ ADD_BIND(String(_("Ctrl")) + " " + _("Alt") + " +, -", _("Increase / Decrease scale factor"));
+ ADD_BIND(String(_("Ctrl")) + " " + _("Alt") + " a", _("Toggle aspect-ratio correction"));
ADD_LINE;
ADD_LINE;
// FIXME: This should use word-wrapping, and should not assume
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index 4db40e6247..07fd99c809 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -57,7 +57,6 @@ _initialized(false),
_tempoFactor(0),
_player_limit(ARRAYSIZE(_players)),
_recycle_players(false),
-_direct_passthrough(false),
_queue_end(0),
_queue_pos(0),
_queue_sound(0),
@@ -151,22 +150,22 @@ bool IMuseInternal::isMT32(int sound) {
tag = READ_BE_UINT32(ptr + 4);
switch (tag) {
- case MKID_BE('ADL '):
- case MKID_BE('ASFX'): // Special AD class for old AdLib sound effects
- case MKID_BE('SPK '):
+ case MKTAG('A','D','L',' '):
+ case MKTAG('A','S','F','X'): // Special AD class for old AdLib sound effects
+ case MKTAG('S','P','K',' '):
return false;
- case MKID_BE('AMI '):
- case MKID_BE('ROL '):
+ case MKTAG('A','M','I',' '):
+ case MKTAG('R','O','L',' '):
return true;
- case MKID_BE('MAC '): // Occurs in the Mac version of FOA and MI2
+ case MKTAG('M','A','C',' '): // Occurs in the Mac version of FOA and MI2
return true;
- case MKID_BE('GMD '):
+ case MKTAG('G','M','D',' '):
return false;
- case MKID_BE('MIDI'): // Occurs in Sam & Max
+ case MKTAG('M','I','D','I'): // Occurs in Sam & Max
// HE games use Roland music
if (ptr[12] == 'H' && ptr[13] == 'S')
return true;
@@ -198,20 +197,20 @@ bool IMuseInternal::isMIDI(int sound) {
tag = READ_BE_UINT32(ptr + 4);
switch (tag) {
- case MKID_BE('ADL '):
- case MKID_BE('ASFX'): // Special AD class for old AdLib sound effects
- case MKID_BE('SPK '):
+ case MKTAG('A','D','L',' '):
+ case MKTAG('A','S','F','X'): // Special AD class for old AdLib sound effects
+ case MKTAG('S','P','K',' '):
return false;
- case MKID_BE('AMI '):
- case MKID_BE('ROL '):
+ case MKTAG('A','M','I',' '):
+ case MKTAG('R','O','L',' '):
return true;
- case MKID_BE('MAC '): // Occurs in the Mac version of FOA and MI2
+ case MKTAG('M','A','C',' '): // Occurs in the Mac version of FOA and MI2
return true;
- case MKID_BE('GMD '):
- case MKID_BE('MIDI'): // Occurs in Sam & Max
+ case MKTAG('G','M','D',' '):
+ case MKTAG('M','I','D','I'): // Occurs in Sam & Max
return true;
}
@@ -472,10 +471,6 @@ uint32 IMuseInternal::property(int prop, uint32 value) {
_recycle_players = (value != 0);
break;
- case IMuse::PROP_DIRECT_PASSTHROUGH:
- _direct_passthrough = (value != 0);
- break;
-
case IMuse::PROP_GAME_ID:
_game_id = value;
break;
@@ -636,7 +631,7 @@ bool IMuseInternal::startSound_internal(int sound, int offset) {
player->clear();
player->setOffsetNote(offset);
- return player->startSound(sound, driver, _direct_passthrough);
+ return player->startSound(sound, driver);
}
int IMuseInternal::stopSound_internal(int sound) {
diff --git a/engines/scumm/imuse/imuse.h b/engines/scumm/imuse/imuse.h
index d7ce2b7bdd..1e3b0fd756 100644
--- a/engines/scumm/imuse/imuse.h
+++ b/engines/scumm/imuse/imuse.h
@@ -58,7 +58,6 @@ public:
PROP_GS,
PROP_LIMIT_PLAYERS,
PROP_RECYCLE_PLAYERS,
- PROP_DIRECT_PASSTHROUGH,
PROP_GAME_ID
};
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index 0014480894..7d46650d2e 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -155,7 +155,7 @@ struct CommandQueue {
//
//////////////////////////////////////////////////
-class Player : public MidiDriver {
+class Player : public MidiDriver_BASE {
/*
* External SysEx handler functions shall each be defined in
* a separate file. This header file shall be included at the
@@ -174,7 +174,6 @@ protected:
protected:
MidiDriver *_midi;
MidiParser *_parser;
- bool _passThrough; // Only respond to EOT, all else direct to MidiDriver
Part *_parts;
bool _active;
@@ -278,21 +277,14 @@ public:
void setSpeed(byte speed);
int setTranspose(byte relative, int b);
int setVolume(byte vol);
- bool startSound(int sound, MidiDriver *midi, bool passThrough);
+ bool startSound(int sound, MidiDriver *midi);
int getMusicTimer() const;
public:
// MidiDriver interface
- int open() { return 0; }
- void close() { }
void send(uint32 b);
- const char *getErrorName(int error_code) { return "Unknown"; }
void sysEx(const byte *msg, uint16 length);
void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timer_param, void(*timer_proc)(void *)) { }
- uint32 getBaseTempo();
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
};
@@ -424,7 +416,6 @@ protected:
int _player_limit; // Limits how many simultaneous music tracks are played
bool _recycle_players; // Can we stop a player in order to start another one?
- bool _direct_passthrough; // Pass data direct to MidiDriver (no interactivity)
uint _queue_end, _queue_pos, _queue_sound;
byte _queue_adding;
diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp
index 40889ec24f..487429c294 100644
--- a/engines/scumm/imuse/imuse_part.cpp
+++ b/engines/scumm/imuse/imuse_part.cpp
@@ -25,6 +25,8 @@
+#include "common/debug.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "scumm/imuse/imuse_internal.h"
#include "scumm/saveload.h"
diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp
index ac2b2d4203..4d185d94d7 100644
--- a/engines/scumm/imuse/imuse_player.cpp
+++ b/engines/scumm/imuse/imuse_player.cpp
@@ -61,7 +61,6 @@ uint16 Player::_active_notes[128];
Player::Player() :
_midi(NULL),
_parser(NULL),
- _passThrough(0),
_parts(NULL),
_active(false),
_scanning(false),
@@ -93,7 +92,7 @@ Player::~Player() {
}
}
-bool Player::startSound(int sound, MidiDriver *midi, bool passThrough) {
+bool Player::startSound(int sound, MidiDriver *midi) {
void *ptr;
int i;
@@ -119,7 +118,6 @@ bool Player::startSound(int sound, MidiDriver *midi, bool passThrough) {
_pan = 0;
_transpose = 0;
_detune = 0;
- _passThrough = passThrough;
for (i = 0; i < ARRAYSIZE(_parameterFaders); ++i)
_parameterFaders[i].init();
@@ -227,11 +225,6 @@ void Player::setSpeed(byte speed) {
}
void Player::send(uint32 b) {
- if (_passThrough) {
- _midi->send(b);
- return;
- }
-
byte cmd = (byte)(b & 0xF0);
byte chan = (byte)(b & 0x0F);
byte param1 = (byte)((b >> 8) & 0xFF);
@@ -348,11 +341,6 @@ void Player::sysEx(const byte *p, uint16 len) {
byte buf[128];
Part *part;
- if (_passThrough) {
- _midi->sysEx(p, len);
- return;
- }
-
// Check SysEx manufacturer.
a = *p++;
--len;
@@ -998,10 +986,6 @@ void Player::fixAfterLoad() {
}
}
-uint32 Player::getBaseTempo() {
- return (_midi ? _midi->getBaseTempo() : 0);
-}
-
void Player::metaEvent(byte type, byte *msg, uint16 len) {
if (type == 0x2F)
clear();
diff --git a/engines/scumm/imuse/sysex_scumm.cpp b/engines/scumm/imuse/sysex_scumm.cpp
index c96b2f757b..78028c6056 100644
--- a/engines/scumm/imuse/sysex_scumm.cpp
+++ b/engines/scumm/imuse/sysex_scumm.cpp
@@ -24,6 +24,7 @@
#include "common/endian.h"
+#include "common/textconsole.h"
#include "common/util.h"
/*
diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index 516a0497fa..3831689def 100644
--- a/engines/scumm/imuse_digi/dimuse.cpp
+++ b/engines/scumm/imuse_digi/dimuse.cpp
@@ -31,6 +31,7 @@
#include "scumm/sound.h"
#include "scumm/imuse_digi/dimuse.h"
#include "scumm/imuse_digi/dimuse_bndmgr.h"
+#include "scumm/imuse_digi/dimuse_codecs.h"
#include "scumm/imuse_digi/dimuse_track.h"
#include "audio/audiostream.h"
diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h
index 236edb5a89..1e96aa8827 100644
--- a/engines/scumm/imuse_digi/dimuse.h
+++ b/engines/scumm/imuse_digi/dimuse.h
@@ -26,6 +26,8 @@
#define SCUMM_IMUSE_DIGI_H
#include "common/scummsys.h"
+#include "common/mutex.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "scumm/imuse_digi/dimuse.h"
diff --git a/engines/scumm/imuse_digi/dimuse_bndmgr.cpp b/engines/scumm/imuse_digi/dimuse_bndmgr.cpp
index f10f17f3d8..cb894d77cc 100644
--- a/engines/scumm/imuse_digi/dimuse_bndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_bndmgr.cpp
@@ -28,6 +28,7 @@
#include "scumm/util.h"
#include "scumm/file.h"
#include "scumm/imuse_digi/dimuse_bndmgr.h"
+#include "scumm/imuse_digi/dimuse_codecs.h"
namespace Scumm {
@@ -92,7 +93,7 @@ int BundleDirCache::matchFile(const char *filename) {
error("BundleDirCache::matchFileFile() Can't find free slot for file bundle dir cache");
tag = file.readUint32BE();
- if (tag == MKID_BE('LB23'))
+ if (tag == MKTAG('L','B','2','3'))
_budleDirCache[freeSlot].isCompressed = true;
offset = file.readUint32BE();
@@ -112,7 +113,7 @@ int BundleDirCache::matchFile(const char *filename) {
int32 z = 0;
int32 z2;
- if (tag == MKID_BE('LB23')) {
+ if (tag == MKTAG('L','B','2','3')) {
file.read(_budleDirCache[freeSlot].bundleTable[i].filename, 24);
} else {
for (z2 = 0; z2 < 8; z2++)
@@ -224,7 +225,7 @@ bool BundleMgr::loadCompTable(int32 index) {
assert(_numCompItems > 0);
_file->seek(8, SEEK_CUR);
- if (tag != MKID_BE('COMP')) {
+ if (tag != MKTAG('C','O','M','P')) {
error("BundleMgr::loadCompTable() Compressed sound %d (%s:%d) invalid (%s)", index, _file->getName(), _bundleTable[index].offset, tag2str(tag));
return false;
}
diff --git a/engines/scumm/imuse_digi/dimuse_bndmgr.h b/engines/scumm/imuse_digi/dimuse_bndmgr.h
index a78697a854..bed1ac6549 100644
--- a/engines/scumm/imuse_digi/dimuse_bndmgr.h
+++ b/engines/scumm/imuse_digi/dimuse_bndmgr.h
@@ -107,14 +107,6 @@ public:
int32 decompressSampleByCurIndex(int32 offset, int32 size, byte **compFinal, int headerSize, bool headerOutside);
};
-namespace BundleCodecs {
-
-uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size);
-void initializeImcTables();
-int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize);
-
-} // End of namespace BundleCodecs
-
} // End of namespace Scumm
#endif
diff --git a/engines/scumm/imuse_digi/dimuse_codecs.cpp b/engines/scumm/imuse_digi/dimuse_codecs.cpp
index 3f7c341701..c78e313fc2 100644
--- a/engines/scumm/imuse_digi/dimuse_codecs.cpp
+++ b/engines/scumm/imuse_digi/dimuse_codecs.cpp
@@ -25,6 +25,9 @@
#include "common/scummsys.h"
#include "common/endian.h"
#include "common/util.h"
+#include "scumm/imuse_digi/dimuse_codecs.h"
+
+#include "audio/decoders/adpcm_intern.h"
namespace Scumm {
@@ -59,23 +62,10 @@ uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size) {
* varies the size of each "packet" between 2 and 7 bits.
*/
-static byte _imcTableEntryBitCount[89];
-
-static const int16 imcTable[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14,
- 16, 17, 19, 21, 23, 25, 28, 31,
- 34, 37, 41, 45, 50, 55, 60, 66,
- 73, 80, 88, 97, 107, 118, 130, 143,
- 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658,
- 724, 796, 876, 963, 1060, 1166, 1282, 1411,
- 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
- 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
- 7132, 7845, 8630, 9493,10442,11487,12635,13899,
- 15289,16818,18500,20350,22385,24623,27086,29794,
- 32767
-};
+static byte *_destImcTable = NULL;
+static uint32 *_destImcTable2 = NULL;
+// This table is the "big brother" of Audio::ADPCMStream::_stepAdjustTable.
static const byte imxOtherTable[6][64] = {
{
0xFF,
@@ -116,23 +106,47 @@ static const byte imxOtherTable[6][64] = {
}
};
+void releaseImcTables() {
+ free(_destImcTable);
+ free(_destImcTable2);
+}
+
void initializeImcTables() {
int pos;
- for (pos = 0; pos < ARRAYSIZE(imcTable); ++pos) {
- byte put = 0;
- int32 tableValue = ((imcTable[pos] * 4) / 7) / 2;
+ if (!_destImcTable) _destImcTable = (byte *)calloc(89, sizeof(byte));
+ if (!_destImcTable2) _destImcTable2 = (uint32 *)calloc(89 * 64, sizeof(uint32));
+
+ for (pos = 0; pos <= 88; ++pos) {
+ byte put = 1;
+ int32 tableValue = ((Audio::Ima_ADPCMStream::_imaTable[pos] * 4) / 7) / 2;
while (tableValue != 0) {
tableValue /= 2;
put++;
}
- if (put < 2) {
- put = 2;
+ if (put < 3) {
+ put = 3;
+ }
+ if (put > 8) {
+ put = 8;
}
- if (put > 7) {
- put = 7;
+ _destImcTable[pos] = put - 1;
+ }
+
+ for (int n = 0; n < 64; n++) {
+ for (pos = 0; pos <= 88; ++pos) {
+ int32 count = 32;
+ int32 put = 0;
+ int32 tableValue = Audio::Ima_ADPCMStream::_imaTable[pos];
+ do {
+ if ((count & n) != 0) {
+ put += tableValue;
+ }
+ count /= 2;
+ tableValue /= 2;
+ } while (count != 0);
+ _destImcTable2[n + pos * 64] = put;
}
- _imcTableEntryBitCount[pos] = put;
}
}
@@ -183,8 +197,128 @@ static int32 compDecode(byte *src, byte *dst) {
}
#undef NextBit
+int32 decompressADPCM(byte *compInput, byte *compOutput, int channels) {
+ byte *src;
+
+ // Decoder for the the IMA ADPCM variants used in COMI.
+ // Contrary to regular IMA ADPCM, this codec uses a variable
+ // bitsize for the encoded data.
+
+ const int MAX_CHANNELS = 2;
+ int32 outputSamplesLeft;
+ int32 destPos;
+ int16 firstWord;
+ byte initialTablePos[MAX_CHANNELS] = {0, 0};
+ int32 initialimcTableEntry[MAX_CHANNELS] = {7, 7};
+ int32 initialOutputWord[MAX_CHANNELS] = {0, 0};
+ int32 totalBitOffset, curTablePos, outputWord;
+ byte *dst;
+ int i;
+
+ // We only support mono and stereo
+ assert(channels == 1 || channels == 2);
+
+ src = compInput;
+ dst = compOutput;
+ outputSamplesLeft = 0x1000;
+
+ // Every data packet contains 0x2000 bytes of audio data
+ // when extracted. In order to encode bigger data sets,
+ // one has to split the data into multiple blocks.
+ //
+ // Every block starts with a 2 byte word. If that word is
+ // non-zero, it indicates the size of a block of raw audio
+ // data (not encoded) following it. That data we simply copy
+ // to the output buffer and then proceed by decoding the
+ // remaining data.
+ //
+ // If on the other hand the word is zero, then what follows
+ // are 7*channels bytes containing seed data for the decoder.
+ firstWord = READ_BE_UINT16(src);
+ src += 2;
+ if (firstWord != 0) {
+ // Copy raw data
+ memcpy(dst, src, firstWord);
+ dst += firstWord;
+ src += firstWord;
+ assert((firstWord & 1) == 0);
+ outputSamplesLeft -= firstWord / 2;
+ } else {
+ // Read the seed values for the decoder.
+ for (i = 0; i < channels; i++) {
+ initialTablePos[i] = *src;
+ src += 1;
+ initialimcTableEntry[i] = READ_BE_UINT32(src);
+ src += 4;
+ initialOutputWord[i] = READ_BE_UINT32(src);
+ src += 4;
+ }
+ }
+
+ totalBitOffset = 0;
+ // The channels are encoded separately.
+ for (int chan = 0; chan < channels; chan++) {
+ // Read initial state (this makes it possible for the data stream
+ // to be split & spread across multiple data chunks.
+ curTablePos = initialTablePos[chan];
+ //imcTableEntry = initialimcTableEntry[chan];
+ outputWord = initialOutputWord[chan];
+
+ // We need to interleave the channels in the output; we achieve
+ // that by using a variables dest offset:
+ destPos = chan * 2;
+
+ const int bound = (channels == 1)
+ ? outputSamplesLeft
+ : ((chan == 0)
+ ? (outputSamplesLeft+1) / 2
+ : outputSamplesLeft / 2);
+ for (i = 0; i < bound; ++i) {
+ // Determine the size (in bits) of the next data packet
+ const int32 curTableEntryBitCount = _destImcTable[curTablePos];
+ assert(2 <= curTableEntryBitCount && curTableEntryBitCount <= 7);
+
+ // Read the next data packet
+ const byte *readPos = src + (totalBitOffset >> 3);
+ const uint16 readWord = (uint16)(READ_BE_UINT16(readPos) << (totalBitOffset & 7));
+ const byte packet = (byte)(readWord >> (16 - curTableEntryBitCount));
+
+ // Advance read position to the next data packet
+ totalBitOffset += curTableEntryBitCount;
+
+ // Decode the data packet into a delta value for the output signal.
+ const byte signBitMask = (1 << (curTableEntryBitCount - 1));
+ const byte dataBitMask = (signBitMask - 1);
+ const byte data = (packet & dataBitMask);
+
+ const int32 tmpA = (data << (7 - curTableEntryBitCount));
+ const int32 imcTableEntry = Audio::Ima_ADPCMStream::_imaTable[curTablePos] >> (curTableEntryBitCount - 1);
+ int32 delta = imcTableEntry + _destImcTable2[tmpA + (curTablePos * 64)];
+
+ // The topmost bit in the data packet tells is a sign bit
+ if ((packet & signBitMask) != 0) {
+ delta = -delta;
+ }
+
+ // Accumulate the delta onto the output data
+ outputWord += delta;
+
+ // Clip outputWord to 16 bit signed, and write it into the destination stream
+ outputWord = CLIP<int32>(outputWord, -0x8000, 0x7fff);
+ WRITE_BE_UINT16(dst + destPos, outputWord);
+ destPos += channels << 1;
+
+ // Adjust the curTablePos
+ curTablePos += (int8)imxOtherTable[curTableEntryBitCount - 2][data];
+ curTablePos = CLIP<int32>(curTablePos, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1);
+ }
+ }
+
+ return 0x2000;
+}
+
int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize) {
- int32 outputSize, channels;
+ int32 outputSize;
int32 offset1, offset2, offset3, length, k, c, s, j, r, t, z;
byte *src, *t_table, *p, *ptr;
byte t_tmp1, t_tmp2;
@@ -506,132 +640,7 @@ int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inpu
case 13:
case 15:
- if (codec == 13) {
- channels = 1;
- } else {
- channels = 2;
- }
-
- {
- // Decoder for the the IMA ADPCM variants used in COMI.
- // Contrary to regular IMA ADPCM, this codec uses a variable
- // bitsize for the encoded data.
-
- const int MAX_CHANNELS = 2;
- int32 outputSamplesLeft;
- int32 destPos;
- int16 firstWord;
- byte initialTablePos[MAX_CHANNELS] = {0, 0};
- int32 initialimcTableEntry[MAX_CHANNELS] = {7, 7};
- int32 initialOutputWord[MAX_CHANNELS] = {0, 0};
- int32 totalBitOffset, curTablePos, outputWord;
- byte *dst;
- int i;
-
- // We only support mono and stereo
- assert(channels == 1 || channels == 2);
-
- src = compInput;
- dst = compOutput;
- outputSize = 0x2000;
- outputSamplesLeft = 0x1000;
-
- // Every data packet contains 0x2000 bytes of audio data
- // when extracted. In order to encode bigger data sets,
- // one has to split the data into multiple blocks.
- //
- // Every block starts with a 2 byte word. If that word is
- // non-zero, it indicates the size of a block of raw audio
- // data (not encoded) following it. That data we simply copy
- // to the output buffer and the proceed by decoding the
- // remaining data.
- //
- // If on the other hand the word is zero, then what follows
- // are 7*channels bytes containing seed data for the decoder.
- firstWord = READ_BE_UINT16(src);
- src += 2;
- if (firstWord != 0) {
- // Copy raw data
- memcpy(dst, src, firstWord);
- dst += firstWord;
- src += firstWord;
- assert((firstWord & 1) == 0);
- outputSamplesLeft -= firstWord / 2;
- } else {
- // Read the seed values for the decoder.
- for (i = 0; i < channels; i++) {
- initialTablePos[i] = *src;
- src += 1;
- initialimcTableEntry[i] = READ_BE_UINT32(src);
- src += 4;
- initialOutputWord[i] = READ_BE_UINT32(src);
- src += 4;
- }
- }
-
- totalBitOffset = 0;
- // The channels are encoded separately.
- for (int chan = 0; chan < channels; chan++) {
- // Read initial state (this makes it possible for the data stream
- // to be split & spread across multiple data chunks.
- curTablePos = initialTablePos[chan];
- //imcTableEntry = initialimcTableEntry[chan];
- outputWord = initialOutputWord[chan];
-
- // We need to interleave the channels in the output; we achieve
- // that by using a variables dest offset:
- destPos = chan * 2;
-
- const int bound = (channels == 1)
- ? outputSamplesLeft
- : ((chan == 0)
- ? (outputSamplesLeft+1) / 2
- : outputSamplesLeft / 2);
- for (i = 0; i < bound; ++i) {
- // Determine the size (in bits) of the next data packet
- const int32 curTableEntryBitCount = _imcTableEntryBitCount[curTablePos];
- assert(2 <= curTableEntryBitCount && curTableEntryBitCount <= 7);
-
- // Read the next data packet
- const byte *readPos = src + (totalBitOffset >> 3);
- const uint16 readWord = (uint16)(READ_BE_UINT16(readPos) << (totalBitOffset & 7));
- const byte packet = (byte)(readWord >> (16 - curTableEntryBitCount));
-
- // Advance read position to the next data packet
- totalBitOffset += curTableEntryBitCount;
-
- // Decode the data packet into a delta value for the output signal.
- const byte signBitMask = (1 << (curTableEntryBitCount - 1));
- const byte dataBitMask = (signBitMask - 1);
- const byte data = (packet & dataBitMask);
-
- int32 delta = imcTable[curTablePos] * (2 * data + 1) >> (curTableEntryBitCount - 1);
-
- // The topmost bit in the data packet tells is a sign bit
- if ((packet & signBitMask) != 0) {
- delta = -delta;
- }
-
- // Accumulate the delta onto the output data
- outputWord += delta;
-
- // Clip outputWord to 16 bit signed, and write it into the destination stream
- if (outputWord > 0x7fff)
- outputWord = 0x7fff;
- if (outputWord < -0x8000)
- outputWord = -0x8000;
- WRITE_BE_UINT16(dst + destPos, outputWord);
- destPos += channels << 1;
-
- // Adjust the curTablePos
- curTablePos += (int8)imxOtherTable[curTableEntryBitCount - 2][data];
- if (curTablePos < 0)
- curTablePos = 0;
- else if (curTablePos >= ARRAYSIZE(imcTable))
- curTablePos = ARRAYSIZE(imcTable) - 1;
- }
- }
- }
+ outputSize = decompressADPCM(compInput, compOutput, (codec == 13) ? 1 : 2);
break;
default:
diff --git a/engines/mohawk/myst_vars.h b/engines/scumm/imuse_digi/dimuse_codecs.h
index 065d8df2cb..71fd24c3ac 100644
--- a/engines/mohawk/myst_vars.h
+++ b/engines/scumm/imuse_digi/dimuse_codecs.h
@@ -8,53 +8,37 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
- *
*/
-#include "mohawk/myst.h"
-
-#ifndef MYST_VARS_H
-#define MYST_VARS_H
-
-namespace Mohawk {
+#ifndef SCUMM_IMUSE_DIGI_CODECS_H
+#define SCUMM_IMUSE_DIGI_CODECS_H
-struct MystVarEntry {
- uint16 refNum;
- uint16 storage; // Used for Initial Value setting
- const char *description;
-};
+#include "common/scummsys.h"
-class MystVar {
-public:
- MystVar(MohawkEngine_Myst *vm);
- ~MystVar();
+namespace Scumm {
- // Only for use by Save/Load
- // All other code should use getVar() / setVar()
- void loadSetVar(uint16 stack, uint16 v, uint16 value);
- uint16 saveGetVar(uint16 stack, uint16 v);
+namespace BundleCodecs {
- uint16 getVar(uint16 v);
- void setVar(uint16 v, uint16 value);
+uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size);
+int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize);
-private:
- MohawkEngine_Myst *_vm;
+void initializeImcTables();
+void releaseImcTables();
- Common::Array<MystVarEntry> _unknown;
-};
+} // End of namespace BundleCodecs
-} // End of namespace Mohawk
+} // End of namespace Scumm
#endif
diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
index 00074a951a..2cd90c4f2b 100644
--- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -34,8 +34,9 @@
#include "scumm/scumm.h"
#include "scumm/util.h"
#include "scumm/imuse_digi/dimuse.h"
-#include "scumm/imuse_digi/dimuse_sndmgr.h"
#include "scumm/imuse_digi/dimuse_bndmgr.h"
+#include "scumm/imuse_digi/dimuse_codecs.h"
+#include "scumm/imuse_digi/dimuse_sndmgr.h"
namespace Scumm {
@@ -56,6 +57,7 @@ ImuseDigiSndMgr::~ImuseDigiSndMgr() {
}
delete _cacheBundleDir;
+ BundleCodecs::releaseImcTables();
}
void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs, int &numMarkers) {
@@ -65,32 +67,32 @@ void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, i
do {
tag = READ_BE_UINT32(ptr); ptr += 4;
switch (tag) {
- case MKID_BE('STOP'):
- case MKID_BE('FRMT'):
- case MKID_BE('DATA'):
+ case MKTAG('S','T','O','P'):
+ case MKTAG('F','R','M','T'):
+ case MKTAG('D','A','T','A'):
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
if (!scumm_stricmp((const char *)(ptr + 8), "exit"))
numMarkers++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('REGN'):
+ case MKTAG('R','E','G','N'):
numRegions++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('JUMP'):
+ case MKTAG('J','U','M','P'):
numJumps++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('SYNC'):
+ case MKTAG('S','Y','N','C'):
numSyncs++;
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
default:
error("ImuseDigiSndMgr::countElements() Unknown sfx header '%s'", tag2str(tag));
}
- } while (tag != MKID_BE('DATA'));
+ } while (tag != MKTAG('D','A','T','A'));
}
void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, SoundDesc *sound, int32 offset, int32 size) {
@@ -98,7 +100,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, Sou
file->seek(offset, SEEK_SET);
uint32 tag = file->readUint32BE();
- assert(tag == MKID_BE('RMAP'));
+ assert(tag == MKTAG('R','M','A','P'));
int32 version = file->readUint32BE();
if (version != 3) {
if (version == 2) {
@@ -153,7 +155,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, Sou
}
void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
- if (READ_BE_UINT32(ptr) == MKID_BE('Crea')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('C','r','e','a')) {
bool quit = false;
int len;
@@ -222,7 +224,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
}
offset += len;
}
- } else if (READ_BE_UINT32(ptr) == MKID_BE('iMUS')) {
+ } else if (READ_BE_UINT32(ptr) == MKTAG('i','M','U','S')) {
uint32 tag;
int32 size = 0;
byte *s_ptr = ptr;
@@ -250,13 +252,13 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
do {
tag = READ_BE_UINT32(ptr); ptr += 4;
switch (tag) {
- case MKID_BE('FRMT'):
+ case MKTAG('F','R','M','T'):
ptr += 12;
sound->bits = READ_BE_UINT32(ptr); ptr += 4;
sound->freq = READ_BE_UINT32(ptr); ptr += 4;
sound->channels = READ_BE_UINT32(ptr); ptr += 4;
break;
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
if (!scumm_stricmp((const char *)(ptr + 8), "exit")) {
sound->marker[curIndexMarker].pos = READ_BE_UINT32(ptr + 4);
sound->marker[curIndexMarker].length = strlen((const char *)(ptr + 8)) + 1;
@@ -267,16 +269,16 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
}
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('STOP'):
+ case MKTAG('S','T','O','P'):
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
- case MKID_BE('REGN'):
+ case MKTAG('R','E','G','N'):
ptr += 4;
sound->region[curIndexRegion].offset = READ_BE_UINT32(ptr); ptr += 4;
sound->region[curIndexRegion].length = READ_BE_UINT32(ptr); ptr += 4;
curIndexRegion++;
break;
- case MKID_BE('JUMP'):
+ case MKTAG('J','U','M','P'):
ptr += 4;
sound->jump[curIndexJump].offset = READ_BE_UINT32(ptr); ptr += 4;
sound->jump[curIndexJump].dest = READ_BE_UINT32(ptr); ptr += 4;
@@ -284,7 +286,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
sound->jump[curIndexJump].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
curIndexJump++;
break;
- case MKID_BE('SYNC'):
+ case MKTAG('S','Y','N','C'):
size = READ_BE_UINT32(ptr); ptr += 4;
sound->sync[curIndexSync].size = size;
sound->sync[curIndexSync].ptr = new byte[size];
@@ -293,13 +295,13 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
curIndexSync++;
ptr += size;
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
ptr += 4;
break;
default:
error("ImuseDigiSndMgr::prepareSound(%d/%s) Unknown sfx header '%s'", sound->soundId, sound->name, tag2str(tag));
}
- } while (tag != MKID_BE('DATA'));
+ } while (tag != MKTAG('D','A','T','A'));
sound->offsetData = ptr - s_ptr;
} else {
error("ImuseDigiSndMgr::prepareSound(): Unknown sound format");
diff --git a/engines/scumm/insane/insane.cpp b/engines/scumm/insane/insane.cpp
index f2e50382b3..a82c0ae408 100644
--- a/engines/scumm/insane/insane.cpp
+++ b/engines/scumm/insane/insane.cpp
@@ -1413,7 +1413,7 @@ int32 Insane::smush_setupSanWithFlu(const char *filename, int32 setupsan2, int32
_smush_setupsan1 = setupsan1;
/* skip FLUP marker */
- if (READ_BE_UINT32(fluPtr) == MKID_BE('FLUP'))
+ if (READ_BE_UINT32(fluPtr) == MKTAG('F','L','U','P'))
tmp += 8;
_smush_setupsan2 = setupsan2;
diff --git a/engines/scumm/insane/insane_iact.cpp b/engines/scumm/insane/insane_iact.cpp
index 942256b1a4..265931ecc2 100644
--- a/engines/scumm/insane/insane_iact.cpp
+++ b/engines/scumm/insane/insane_iact.cpp
@@ -62,7 +62,7 @@ void Insane::procIACT(byte *renderBitmap, int32 codecparam, int32 setupsan12,
void Insane::iactScene1(byte *renderBitmap, int32 codecparam, int32 setupsan12,
int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
int16 par1, int16 par2, int16 par3, int16 par4) {
- int16 par5, par6, par7, par9, par11, par13, tmp;
+ int16 par5, par6, par7, par9, par11, par13;
switch (par1) {
case 2: // PATCH
@@ -99,15 +99,15 @@ void Insane::iactScene1(byte *renderBitmap, int32 codecparam, int32 setupsan12,
if (par2 != 13)
break;
- tmp = b.readUint16LE(); // +8
- tmp = b.readUint16LE(); // +10
- par7 = b.readUint16LE(); // +12 dx
- tmp = b.readUint16LE(); // +14
- par9 = b.readUint16LE(); // +16 bx
- tmp = b.readUint16LE(); // +18
- par11 = b.readUint16LE(); // +20 cx
- tmp = b.readUint16LE(); // +22
- par13 = b.readUint16LE(); // +24 ax
+ b.readUint16LE(); // +8
+ b.readUint16LE(); // +10
+ par7 = b.readUint16LE(); // +12 dx
+ b.readUint16LE(); // +14
+ par9 = b.readUint16LE(); // +16 bx
+ b.readUint16LE(); // +18
+ par11 = b.readUint16LE(); // +20 cx
+ b.readUint16LE(); // +22
+ par13 = b.readUint16LE(); // +24 ax
if (par13 > _actor[0].x || par11 < _actor[0].x) {
_tiresRustle = true;
diff --git a/engines/scumm/midiparser_ro.cpp b/engines/scumm/midiparser_ro.cpp
index e737d747ac..be77e4fd66 100644
--- a/engines/scumm/midiparser_ro.cpp
+++ b/engines/scumm/midiparser_ro.cpp
@@ -26,6 +26,7 @@
#include "audio/midiparser.h"
#include "audio/mididrv.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Scumm {
diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp
index d56017c6f5..7f250e45e0 100644
--- a/engines/scumm/nut_renderer.cpp
+++ b/engines/scumm/nut_renderer.cpp
@@ -95,7 +95,7 @@ void NutRenderer::loadFont(const char *filename) {
}
uint32 tag = file.readUint32BE();
- if (tag != MKID_BE('ANIM')) {
+ if (tag != MKTAG('A','N','I','M')) {
error("NutRenderer::loadFont() there is no ANIM chunk in font header");
}
@@ -104,7 +104,7 @@ void NutRenderer::loadFont(const char *filename) {
file.read(dataSrc, length);
file.close();
- if (READ_BE_UINT32(dataSrc) != MKID_BE('AHDR')) {
+ if (READ_BE_UINT32(dataSrc) != MKTAG('A','H','D','R')) {
error("NutRenderer::loadFont() there is no AHDR chunk in font header");
}
@@ -142,12 +142,12 @@ void NutRenderer::loadFont(const char *filename) {
offset = 0;
for (l = 0; l < _numChars; l++) {
offset += READ_BE_UINT32(dataSrc + offset + 4) + 8;
- if (READ_BE_UINT32(dataSrc + offset) != MKID_BE('FRME')) {
+ if (READ_BE_UINT32(dataSrc + offset) != MKTAG('F','R','M','E')) {
error("NutRenderer::loadFont(%s) there is no FRME chunk %d (offset %x)", filename, l, offset);
break;
}
offset += 8;
- if (READ_BE_UINT32(dataSrc + offset) != MKID_BE('FOBJ')) {
+ if (READ_BE_UINT32(dataSrc + offset) != MKTAG('F','O','B','J')) {
error("NutRenderer::loadFont(%s) there is no FOBJ chunk in FRME chunk %d (offset %x)", filename, l, offset);
break;
}
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index c44043ca81..c2547f74f4 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -416,7 +416,7 @@ void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) {
debug(0, "getObjectXYPos: Can't find object %d", object);
return;
}
- imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), ptr);
+ imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), ptr);
assert(imhd);
if (_game.version == 8) {
switch (FROM_LE_32(imhd->v8.version)) {
@@ -655,7 +655,7 @@ void ScummEngine::drawObject(int obj, int arg) {
flags |= Gdi::dbDrawMaskOnAll;
#ifdef ENABLE_HE
- if (_game.heversion >= 70 && findResource(MKID_BE('SMAP'), ptr) == NULL)
+ if (_game.heversion >= 70 && findResource(MKTAG('S','M','A','P'), ptr) == NULL)
_gdi->drawBMAPObject(ptr, &_virtscr[kMainVirtScreen], obj, od.x_pos, od.y_pos, od.width, od.height);
else
#endif
@@ -762,12 +762,12 @@ void ScummEngine::resetRoomObjects() {
for (i = 0; i < _numObjectsInRoom; i++) {
od = &_objs[findLocalObjectSlot()];
- ptr = obcds.findNext(MKID_BE('OBCD'));
+ ptr = obcds.findNext(MKTAG('O','B','C','D'));
if (ptr == NULL)
error("Room %d missing object code block(s)", _roomResource);
od->OBCDoffset = ptr - rootptr;
- cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), ptr);
+ cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), ptr);
if (_game.version >= 7)
od->obj_nr = READ_LE_UINT16(&(cdhd->v7.obj_id));
@@ -779,7 +779,7 @@ void ScummEngine::resetRoomObjects() {
if (_dumpScripts) {
char buf[32];
sprintf(buf, "roomobj-%d-", _roomResource);
- ptr = findResource(MKID_BE('VERB'), ptr);
+ ptr = findResource(MKTAG('V','E','R','B'), ptr);
dumpResource(buf, od->obj_nr, ptr);
}
@@ -788,7 +788,7 @@ void ScummEngine::resetRoomObjects() {
searchptr = room;
ResourceIterator obims(room, false);
for (i = 0; i < _numObjectsInRoom; i++) {
- ptr = obims.findNext(MKID_BE('OBIM'));
+ ptr = obims.findNext(MKTAG('O','B','I','M'));
if (ptr == NULL)
error("Room %d missing image blocks(s)", _roomResource);
@@ -870,7 +870,7 @@ void ScummEngine_v4::resetRoomObjects() {
for (i = 0; i < _numObjectsInRoom; i++) {
od = &_objs[findLocalObjectSlot()];
- ptr = obcds.findNext(MKID_BE('OBCD'));
+ ptr = obcds.findNext(MKTAG('O','B','C','D'));
if (ptr == NULL)
error("Room %d missing object code block(s)", _roomResource);
@@ -887,7 +887,7 @@ void ScummEngine_v4::resetRoomObjects() {
for (i = 0; i < _numObjectsInRoom; i++) {
// In the PC Engine version of Loom, there aren't image blocks
// for all objects.
- ptr = obims.findNext(MKID_BE('OBIM'));
+ ptr = obims.findNext(MKTAG('O','B','I','M'));
if (ptr == NULL)
break;
@@ -991,11 +991,11 @@ void ScummEngine::resetRoomObject(ObjectData *od, const byte *room, const byte *
searchptr = room;
}
- cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), searchptr + od->OBCDoffset);
+ cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), searchptr + od->OBCDoffset);
if (cdhd == NULL)
error("Room %d missing CDHD blocks(s)", _roomResource);
if (od->OBIMoffset)
- imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), room + od->OBIMoffset);
+ imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), room + od->OBIMoffset);
od->flags = Gdi::dbAllowMaskOr;
@@ -1194,7 +1194,7 @@ const byte *ScummEngine::getObjOrActorName(int obj) {
return (objptr + offset);
}
- return findResourceData(MKID_BE('OBNA'), objptr);
+ return findResourceData(MKTAG('O','B','N','A'), objptr);
}
void ScummEngine::setObjectName(int obj) {
@@ -1278,7 +1278,7 @@ const byte *ScummEngine::getOBIMFromObjectData(const ObjectData &od) {
if (od.fl_object_index) {
ptr = getResourceAddress(rtFlObject, od.fl_object_index);
- ptr = findResource(MKID_BE('OBIM'), ptr);
+ ptr = findResource(MKTAG('O','B','I','M'), ptr);
} else {
ptr = getResourceAddress(rtRoom, _roomResource);
if (ptr)
@@ -1288,23 +1288,23 @@ const byte *ScummEngine::getOBIMFromObjectData(const ObjectData &od) {
}
static const uint32 IMxx_tags[] = {
- MKID_BE('IM00'),
- MKID_BE('IM01'),
- MKID_BE('IM02'),
- MKID_BE('IM03'),
- MKID_BE('IM04'),
- MKID_BE('IM05'),
- MKID_BE('IM06'),
- MKID_BE('IM07'),
- MKID_BE('IM08'),
- MKID_BE('IM09'),
- MKID_BE('IM0A'),
- MKID_BE('IM0B'),
- MKID_BE('IM0C'),
- MKID_BE('IM0D'),
- MKID_BE('IM0E'),
- MKID_BE('IM0F'),
- MKID_BE('IM10')
+ MKTAG('I','M','0','0'),
+ MKTAG('I','M','0','1'),
+ MKTAG('I','M','0','2'),
+ MKTAG('I','M','0','3'),
+ MKTAG('I','M','0','4'),
+ MKTAG('I','M','0','5'),
+ MKTAG('I','M','0','6'),
+ MKTAG('I','M','0','7'),
+ MKTAG('I','M','0','8'),
+ MKTAG('I','M','0','9'),
+ MKTAG('I','M','0','A'),
+ MKTAG('I','M','0','B'),
+ MKTAG('I','M','0','C'),
+ MKTAG('I','M','0','D'),
+ MKTAG('I','M','0','E'),
+ MKTAG('I','M','0','F'),
+ MKTAG('I','M','1','0')
};
const byte *ScummEngine::getObjectImage(const byte *ptr, int state) {
@@ -1317,15 +1317,15 @@ const byte *ScummEngine::getObjectImage(const byte *ptr, int state) {
// The OBIM contains an IMAG, which in turn contains a WRAP, which contains
// an OFFS chunk and multiple BOMP/SMAP chunks. To find the right BOMP/SMAP,
// we use the offsets in the OFFS chunk,
- ptr = findResource(MKID_BE('IMAG'), ptr);
+ ptr = findResource(MKTAG('I','M','A','G'), ptr);
if (!ptr)
return 0;
- ptr = findResource(MKID_BE('WRAP'), ptr);
+ ptr = findResource(MKTAG('W','R','A','P'), ptr);
if (!ptr)
return 0;
- ptr = findResource(MKID_BE('OFFS'), ptr);
+ ptr = findResource(MKTAG('O','F','F','S'), ptr);
if (!ptr)
return 0;
@@ -1348,7 +1348,7 @@ int ScummEngine::getObjectImageCount(int object) {
return 0;
ptr = getOBIMFromObjectData(_objs[objnum]);
- imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), ptr);
+ imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), ptr);
if (!imhd)
return 0;
@@ -1365,7 +1365,7 @@ int ScummEngine::getObjectImageCount(int object) {
int ScummEngine_v8::getObjectIdFromOBIM(const byte *obim) {
// In V8, IMHD has no obj_id, but rather a name string. We map the name
// back to an object id using a table derived from the DOBJ resource.
- const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim);
+ const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim);
ObjectNameId *found = (ObjectNameId *)bsearch(imhd->v8.name, _objectIDMap, _objectIDMapSize,
sizeof(ObjectNameId), (int (*)(const void*, const void*))strcmp);
assert(found);
@@ -1373,7 +1373,7 @@ int ScummEngine_v8::getObjectIdFromOBIM(const byte *obim) {
}
int ScummEngine_v7::getObjectIdFromOBIM(const byte *obim) {
- const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim);
+ const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim);
return READ_LE_UINT16(&imhd->v7.obj_id);
}
#endif
@@ -1382,7 +1382,7 @@ int ScummEngine::getObjectIdFromOBIM(const byte *obim) {
if (_game.features & GF_SMALL_HEADER)
return READ_LE_UINT16(obim + 6);
- const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim);
+ const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim);
return READ_LE_UINT16(&imhd->old.obj_id);
}
@@ -1400,7 +1400,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
if (findWhat & foCodeHeader) {
fo->obcd = obcdptr = getOBCDFromObject(id);
assert(obcdptr);
- fo->cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), obcdptr);
+ fo->cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), obcdptr);
}
if (findWhat & foImageHeader) {
fo->obim = obimptr = getOBIMFromObjectData(_objs[id2]);
@@ -1416,7 +1416,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
if (_game.features & GF_OLD_BUNDLE) {
numobj = roomptr[20];
} else {
- const RoomHeader *roomhdr = (const RoomHeader *)findResourceData(MKID_BE('RMHD'), roomptr);
+ const RoomHeader *roomhdr = (const RoomHeader *)findResourceData(MKTAG('R','M','H','D'), roomptr);
if (_game.version == 8)
numobj = READ_LE_UINT32(&(roomhdr->v8.numObjects));
@@ -1467,10 +1467,10 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
assert(searchptr);
ResourceIterator obcds(searchptr, (_game.features & GF_SMALL_HEADER) != 0);
for (i = 0; i < numobj; i++) {
- obcdptr = obcds.findNext(MKID_BE('OBCD'));
+ obcdptr = obcds.findNext(MKTAG('O','B','C','D'));
if (obcdptr == NULL)
error("findObjectInRoom: Not enough code blocks in room %d", room);
- cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), obcdptr);
+ cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), obcdptr);
if (_game.features & GF_SMALL_HEADER)
id2 = READ_LE_UINT16(obcdptr + 6);
@@ -1495,7 +1495,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
if (findWhat & foImageHeader) {
ResourceIterator obims(roomptr, (_game.features & GF_SMALL_HEADER) != 0);
for (i = 0; i < numobj; i++) {
- obimptr = obims.findNext(MKID_BE('OBIM'));
+ obimptr = obims.findNext(MKTAG('O','B','I','M'));
if (obimptr == NULL)
error("findObjectInRoom: Not enough image blocks in room %d", room);
obim_id = getObjectIdFromOBIM(obimptr);
@@ -1699,7 +1699,7 @@ void ScummEngine_v6::drawBlastObject(BlastObject *eo) {
if (!img)
img = getObjectImage(ptr, 1); // Backward compatibility with samnmax blast objects
assert(img);
- bomp = findResourceData(MKID_BE('BOMP'), img);
+ bomp = findResourceData(MKTAG('B','O','M','P'), img);
}
if (!bomp)
@@ -1843,7 +1843,7 @@ void ScummEngine::loadFlObject(uint object, uint room) {
char buf[32];
const byte *ptr = foir.obcd;
sprintf(buf, "roomobj-%d-", room);
- ptr = findResource(MKID_BE('VERB'), ptr);
+ ptr = findResource(MKTAG('V','E','R','B'), ptr);
dumpResource(buf, object, ptr);
}
@@ -1869,7 +1869,7 @@ void ScummEngine::loadFlObject(uint object, uint room) {
assert(flob);
// Copy object code + object image to floating object
- WRITE_UINT32(flob, MKID_BE('FLOB'));
+ WRITE_UINT32(flob, MKTAG('F','L','O','B'));
WRITE_BE_UINT32(flob + 4, flob_size);
memcpy(flob + 8, foir.obcd, obcd_size);
memcpy(flob + 8 + obcd_size, foir.obim, obim_size);
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 18784151b7..b0786c924d 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -23,8 +23,11 @@
*/
#include "common/system.h"
+#include "common/textconsole.h"
#include "common/util.h"
+#include "graphics/palette.h"
+
#include "scumm/resource.h"
#include "scumm/scumm.h"
#include "scumm/scumm_v6.h"
@@ -1029,7 +1032,7 @@ void ScummEngine::setCurrentPalette(int palindex) {
void ScummEngine::setRoomPalette(int palindex, int room) {
const byte *roomptr = getResourceAddress(rtRoom, room);
assert(roomptr);
- const byte *pals = findResource(MKID_BE('PALS'), roomptr);
+ const byte *pals = findResource(MKTAG('P','A','L','S'), roomptr);
assert(pals);
const byte *rgbs = findPalInPals(pals, palindex);
assert(rgbs);
@@ -1040,11 +1043,11 @@ const byte *ScummEngine::findPalInPals(const byte *pal, int idx) {
const byte *offs;
uint32 size;
- pal = findResource(MKID_BE('WRAP'), pal);
+ pal = findResource(MKTAG('W','R','A','P'), pal);
if (pal == NULL)
return NULL;
- offs = findResourceData(MKID_BE('OFFS'), pal);
+ offs = findResourceData(MKTAG('O','F','F','S'), pal);
if (offs == NULL)
return NULL;
diff --git a/engines/scumm/player_mod.h b/engines/scumm/player_mod.h
index 67d1bb4cbf..3f97c4cab9 100644
--- a/engines/scumm/player_mod.h
+++ b/engines/scumm/player_mod.h
@@ -31,7 +31,7 @@
#include "audio/mixer.h"
namespace Audio {
- class RateConverter;
+class RateConverter;
}
namespace Scumm {
diff --git a/engines/scumm/player_nes.h b/engines/scumm/player_nes.h
index 5f6e8f2d8d..402eea7bf8 100644
--- a/engines/scumm/player_nes.h
+++ b/engines/scumm/player_nes.h
@@ -35,7 +35,7 @@ namespace Scumm {
class ScummEngine;
namespace APUe {
- class APU;
+class APU;
}
static const int MAXVOLUME = 0x7F;
diff --git a/engines/scumm/player_pce.cpp b/engines/scumm/player_pce.cpp
index 4236fb2d6b..46d976773d 100644
--- a/engines/scumm/player_pce.cpp
+++ b/engines/scumm/player_pce.cpp
@@ -515,7 +515,7 @@ int Player_PCE::readBuffer(int16 *buffer, const int numSamples) {
int sampleCopyCnt;
int samplesLeft = numSamples;
- _mutex.lock();
+ Common::StackLock lock(_mutex);
while (true) {
// copy samples to output buffer
@@ -543,8 +543,6 @@ int Player_PCE::readBuffer(int16 *buffer, const int numSamples) {
_sampleBufferCnt * sizeof(int16));
}
- _mutex.unlock();
-
return numSamples;
}
diff --git a/engines/scumm/player_pce.h b/engines/scumm/player_pce.h
index 3f5033f724..42153e8abc 100644
--- a/engines/scumm/player_pce.h
+++ b/engines/scumm/player_pce.h
@@ -27,6 +27,7 @@
#define SCUMM_PLAYER_PCE_H
#include "common/scummsys.h"
+#include "common/mutex.h"
#include "scumm/music.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
diff --git a/engines/scumm/player_sid.cpp b/engines/scumm/player_sid.cpp
index 34654a68c5..11468f3097 100644
--- a/engines/scumm/player_sid.cpp
+++ b/engines/scumm/player_sid.cpp
@@ -1287,7 +1287,7 @@ uint8 *Player_SID::getResource(int resID) {
int Player_SID::readBuffer(int16 *buffer, const int numSamples) {
int samplesLeft = numSamples;
- _mutex.lock();
+ Common::StackLock lock(_mutex);
while (samplesLeft > 0) {
// update SID status after each frame
@@ -1296,13 +1296,11 @@ int Player_SID::readBuffer(int16 *buffer, const int numSamples) {
_cpuCyclesLeft = timingProps[_videoSystem].cyclesPerFrame;
}
// fetch samples
- int sampleCount = _sid->clock(_cpuCyclesLeft, (short*)buffer, samplesLeft);
+ int sampleCount = _sid->updateClock(_cpuCyclesLeft, (short*)buffer, samplesLeft);
samplesLeft -= sampleCount;
buffer += sampleCount;
}
- _mutex.unlock();
-
return numSamples;
}
@@ -1337,7 +1335,7 @@ void Player_SID::startSound(int nr) {
// prio 7 is never used in any sound file use this byte for auto-detection.
bool isMusic = (data[4] == 0x07);
- _mutex.lock();
+ Common::StackLock lock(_mutex);
if (isMusic) {
initMusic(nr);
@@ -1345,29 +1343,25 @@ void Player_SID::startSound(int nr) {
stopSound_intern(nr);
initSound(nr);
}
-
- _mutex.unlock();
}
void Player_SID::stopSound(int nr) {
if (nr == -1)
return;
- _mutex.lock();
+ Common::StackLock lock(_mutex);
stopSound_intern(nr);
- _mutex.unlock();
}
void Player_SID::stopAllSounds() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
stopAllSounds_intern();
- _mutex.unlock();
}
int Player_SID::getSoundStatus(int nr) const {
int result = 0;
- //_mutex.lock();
+ //Common::StackLock lock(_mutex);
if (resID_song == nr && isMusicPlaying) {
result = 1;
@@ -1379,8 +1373,6 @@ int Player_SID::getSoundStatus(int nr) const {
}
}
- //_mutex.unlock();
-
return result;
}
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp
index 06f97fd671..8922ff1730 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/player_towns.cpp
@@ -622,7 +622,7 @@ int Player_Towns_v2::getSoundStatus(int sound) const {
void Player_Towns_v2::startSound(int sound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
- if (READ_BE_UINT32(ptr) == MKID_BE('TOWS')) {
+ if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) {
_soundOverride[sound].type = 7;
uint8 velo = _soundOverride[sound].velo ? _soundOverride[sound].velo - 1: (ptr[10] + ptr[11] + 1) >> 1;
uint8 pan = _soundOverride[sound].pan ? _soundOverride[sound].pan - 1 : 64;
@@ -630,7 +630,7 @@ void Player_Towns_v2::startSound(int sound) {
_soundOverride[sound].velo = _soundOverride[sound].pan = 0;
playPcmTrack(sound, ptr + 8, velo, pan, ptr[52], pri);
- } else if (READ_BE_UINT32(ptr) == MKID_BE('SBL ')) {
+ } else if (READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) {
_soundOverride[sound].type = 5;
playVocTrack(ptr + 27);
@@ -680,7 +680,7 @@ int32 Player_Towns_v2::doCommand(int numargs, int args[]) {
case 258:
if (_soundOverride[args[1]].type == 0) {
ptr = _vm->getResourceAddress(rtSound, args[1]);
- if (READ_BE_UINT32(ptr) == MKID_BE('TOWS'))
+ if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S'))
_soundOverride[args[1]].type = 7;
}
if (_soundOverride[args[1]].type == 7) {
@@ -692,7 +692,7 @@ int32 Player_Towns_v2::doCommand(int numargs, int args[]) {
case 259:
if (_soundOverride[args[1]].type == 0) {
ptr = _vm->getResourceAddress(rtSound, args[1]);
- if (READ_BE_UINT32(ptr) == MKID_BE('TOWS'))
+ if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S'))
_soundOverride[args[1]].type = 7;
}
if (_soundOverride[args[1]].type == 7) {
diff --git a/engines/scumm/player_v4a.h b/engines/scumm/player_v4a.h
index 108dbcf317..458a39b5fe 100644
--- a/engines/scumm/player_v4a.h
+++ b/engines/scumm/player_v4a.h
@@ -27,6 +27,7 @@
#define SCUMM_PLAYER_V4A_H
#include "common/scummsys.h"
+#include "common/util.h"
#include "scumm/music.h"
#include "audio/mixer.h"
#include "audio/mods/tfmx.h"
diff --git a/engines/scumm/proc3ARM.s b/engines/scumm/proc3ARM.s
index 8b3e31f5f8..5acfa86c29 100644
--- a/engines/scumm/proc3ARM.s
+++ b/engines/scumm/proc3ARM.s
@@ -25,40 +25,40 @@
.text
- .global ClassicProc3RendererShadowARM
+ .global _ClassicProc3RendererShadowARM
-.equ _scaleIndexY , 112
-.equ _numStrips , 108
-.equ _palette , 104
-.equ _shadow_table , 100
-.equ _scaleIndexX , 96
-.equ _scaleX , 92
-.equ _height , 88
-.equ store_r14 , 84
-.equ store_r11 , 80
-.equ store_r10 , 76
-.equ store_r9 , 72
-.equ store_r8 , 68
-.equ store_r7 , 64
-.equ store_r6 , 60
-.equ store_r5 , 56
-.equ store_r4 , 52
-.equ src , 48
-.equ height , 44
-.equ len , 40
-.equ v1_shr , 36
-.equ v1_skip_width , 32
-.equ v1_destptr , 28
-.equ v1_scaleXstep , 24
-.equ v1_mask_ptr , 20
-.equ v1_y , 16
-.equ v1_scaletable , 12
-.equ pitch , 8
-.equ scaleIdxXPtr , 4
-.equ scaleIdxYPtr , 0
+.set _scaleIndexY , 112
+.set _numStrips , 108
+.set _palette , 104
+.set _shadow_table , 100
+.set _scaleIndexX , 96
+.set _scaleX , 92
+.set _height , 88
+.set store_r14 , 84
+.set store_r11 , 80
+.set store_r10 , 76
+.set store_r9 , 72
+.set store_r8 , 68
+.set store_r7 , 64
+.set store_r6 , 60
+.set store_r5 , 56
+.set store_r4 , 52
+.set src , 48
+.set height , 44
+.set len , 40
+.set v1_shr , 36
+.set v1_skip_width , 32
+.set v1_destptr , 28
+.set v1_scaleXstep , 24
+.set v1_mask_ptr , 20
+.set v1_y , 16
+.set v1_scaletable , 12
+.set pitch , 8
+.set scaleIdxXPtr , 4
+.set scaleIdxYPtr , 0
-.equ space , 48
+.set space , 48
@ r0 = _scaleY
@ r1 = v1
@@ -71,7 +71,7 @@
@ <> = _palette
@ <> = _numstrips
@ <> = _scaleIndexY
-ClassicProc3RendererShadowARM:
+_ClassicProc3RendererShadowARM:
@ shadow20 = false
@ shadowed = true
@ unscaled = false
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index 5aae59d987..c872a83d14 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -167,8 +167,6 @@ void ScummEngine::deleteRoomOffsets() {
/** Read room offsets */
void ScummEngine::readRoomsOffsets() {
- int num, room;
-
debug(9, "readRoomOffsets()");
if (_game.features & GF_SMALL_HEADER) {
@@ -177,13 +175,12 @@ void ScummEngine::readRoomsOffsets() {
_fileHandle->seek(16, SEEK_SET);
}
- num = _fileHandle->readByte();
+ int num = _fileHandle->readByte();
while (num--) {
- room = _fileHandle->readByte();
+ int room = _fileHandle->readByte();
+ int offset = _fileHandle->readUint32LE();
if (_res->roomoffs[rtRoom][room] != RES_INVALID_OFFSET) {
- _res->roomoffs[rtRoom][room] = _fileHandle->readUint32LE();
- } else {
- _fileHandle->readUint32LE();
+ _res->roomoffs[rtRoom][room] = offset;
}
}
}
@@ -262,26 +259,26 @@ void ScummEngine::readIndexFile() {
if (_fileHandle->eos() || _fileHandle->err())
break;
switch (blocktype) {
- case MKID_BE('DOBJ'):
+ case MKTAG('D','O','B','J'):
_numGlobalObjects = _fileHandle->readUint16LE();
itemsize -= 2;
break;
- case MKID_BE('DROO'):
+ case MKTAG('D','R','O','O'):
_numRooms = _fileHandle->readUint16LE();
itemsize -= 2;
break;
- case MKID_BE('DSCR'):
+ case MKTAG('D','S','C','R'):
_numScripts = _fileHandle->readUint16LE();
itemsize -= 2;
break;
- case MKID_BE('DCOS'):
+ case MKTAG('D','C','O','S'):
_numCostumes = _fileHandle->readUint16LE();
itemsize -= 2;
break;
- case MKID_BE('DSOU'):
+ case MKTAG('D','S','O','U'):
_numSounds = _fileHandle->readUint16LE();
itemsize -= 2;
break;
@@ -354,7 +351,7 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) {
int num;
char *ptr;
switch (blocktype) {
- case MKID_BE('ANAM'): // Used by: The Dig, FT
+ case MKTAG('A','N','A','M'): // Used by: The Dig, FT
debug(9, "found ANAM block, reading audio names");
num = _fileHandle->readUint16LE();
ptr = (char*)malloc(num * 9);
@@ -362,7 +359,7 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) {
_imuseDigital->setAudioNames(num, ptr);
break;
- case MKID_BE('DRSC'): // Used by: COMI
+ case MKTAG('D','R','S','C'): // Used by: COMI
readResTypeList(rtRoomScripts);
break;
@@ -375,37 +372,37 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) {
void ScummEngine_v70he::readIndexBlock(uint32 blocktype, uint32 itemsize) {
int i;
switch (blocktype) {
- case MKID_BE('DIRI'):
+ case MKTAG('D','I','R','I'):
readResTypeList(rtRoomImage);
break;
- case MKID_BE('DIRM'):
+ case MKTAG('D','I','R','M'):
readResTypeList(rtImage);
break;
- case MKID_BE('DIRT'):
+ case MKTAG('D','I','R','T'):
readResTypeList(rtTalkie);
break;
- case MKID_BE('DLFL'):
+ case MKTAG('D','L','F','L'):
i = _fileHandle->readUint16LE();
_fileHandle->seek(-2, SEEK_CUR);
_heV7RoomOffsets = (byte *)calloc(2 + (i * 4), 1);
_fileHandle->read(_heV7RoomOffsets, (2 + (i * 4)) );
break;
- case MKID_BE('DISK'):
+ case MKTAG('D','I','S','K'):
i = _fileHandle->readUint16LE();
_heV7DiskOffsets = (byte *)calloc(i, 1);
_fileHandle->read(_heV7DiskOffsets, i);
break;
- case MKID_BE('SVER'):
+ case MKTAG('S','V','E','R'):
// Index version number
_fileHandle->seek(itemsize - 8, SEEK_CUR);
break;
- case MKID_BE('INIB'):
+ case MKTAG('I','N','I','B'):
_fileHandle->seek(itemsize - 8, SEEK_CUR);
debug(2, "INIB index block not yet handled, skipping");
break;
@@ -418,17 +415,17 @@ void ScummEngine_v70he::readIndexBlock(uint32 blocktype, uint32 itemsize) {
void ScummEngine::readIndexBlock(uint32 blocktype, uint32 itemsize) {
int i;
switch (blocktype) {
- case MKID_BE('DCHR'):
- case MKID_BE('DIRF'):
+ case MKTAG('D','C','H','R'):
+ case MKTAG('D','I','R','F'):
readResTypeList(rtCharset);
break;
- case MKID_BE('DOBJ'):
+ case MKTAG('D','O','B','J'):
debug(9, "found DOBJ block, reading object table");
readGlobalObjects();
break;
- case MKID_BE('RNAM'):
+ case MKTAG('R','N','A','M'):
// Names of rooms. Maybe we should put them into a table, for use by the debugger?
if (_game.heversion >= 80) {
for (int room; (room = _fileHandle->readUint16LE()); ) {
@@ -452,32 +449,32 @@ void ScummEngine::readIndexBlock(uint32 blocktype, uint32 itemsize) {
}
break;
- case MKID_BE('DROO'):
- case MKID_BE('DIRR'):
+ case MKTAG('D','R','O','O'):
+ case MKTAG('D','I','R','R'):
readResTypeList(rtRoom);
break;
- case MKID_BE('DSCR'):
- case MKID_BE('DIRS'):
+ case MKTAG('D','S','C','R'):
+ case MKTAG('D','I','R','S'):
readResTypeList(rtScript);
break;
- case MKID_BE('DCOS'):
- case MKID_BE('DIRC'):
+ case MKTAG('D','C','O','S'):
+ case MKTAG('D','I','R','C'):
readResTypeList(rtCostume);
break;
- case MKID_BE('MAXS'):
+ case MKTAG('M','A','X','S'):
readMAXS(itemsize);
allocateArrays();
break;
- case MKID_BE('DIRN'):
- case MKID_BE('DSOU'):
+ case MKTAG('D','I','R','N'):
+ case MKTAG('D','S','O','U'):
readResTypeList(rtSound);
break;
- case MKID_BE('AARY'):
+ case MKTAG('A','A','R','Y'):
readArrayFromIndexFile();
break;
@@ -491,7 +488,7 @@ void ScummEngine::readArrayFromIndexFile() {
error("readArrayFromIndexFile() not supported in pre-V6 games");
}
-void ScummEngine::readResTypeList(int id) {
+int ScummEngine::readResTypeList(int id) {
int num;
int i;
@@ -511,16 +508,27 @@ void ScummEngine::readResTypeList(int id) {
}
for (i = 0; i < num; i++) {
_res->roomoffs[id][i] = _fileHandle->readUint32LE();
-
- if (id == rtRoom && _game.heversion >= 70)
- _heV7RoomIntOffsets[i] = _res->roomoffs[id][i];
}
- if (_game.heversion >= 70) {
+ return num;
+}
+
+int ScummEngine_v70he::readResTypeList(int id) {
+ int num;
+ int i;
+
+ num = ScummEngine::readResTypeList(id);
+
+ if (id == rtRoom)
for (i = 0; i < num; i++) {
- _res->globsize[id][i] = _fileHandle->readUint32LE();
+ _heV7RoomIntOffsets[i] = _res->roomoffs[rtRoom][i];
}
+
+ for (i = 0; i < num; i++) {
+ _res->globsize[id][i] = _fileHandle->readUint32LE();
}
+
+ return num;
}
void ResourceManager::allocResTypeData(int id, uint32 tag, int num_, const char *name_, int mode_) {
@@ -635,18 +643,9 @@ int ScummEngine::loadResource(int type, int idx) {
if (roomNr == 0)
roomNr = _roomResource;
- if (type == rtRoom) {
- if (_game.version == 8)
- fileOffs = 8;
- else if (_game.heversion >= 70)
- fileOffs = _heV7RoomIntOffsets[idx];
- else
- fileOffs = 0;
- } else {
- fileOffs = _res->roomoffs[type][idx];
- if (fileOffs == RES_INVALID_OFFSET)
- return 0;
- }
+ fileOffs = getResourceRoomOffset(type, idx);
+ if (fileOffs == RES_INVALID_OFFSET)
+ return 0;
openRoom(roomNr);
@@ -691,13 +690,11 @@ int ScummEngine::loadResource(int type, int idx) {
dumpResource("script-", idx, getResourceAddress(rtScript, idx));
}
- if (!_fileHandle->err() && !_fileHandle->eos()) {
- return 1;
+ if (_fileHandle->err() || _fileHandle->eos()) {
+ error("Cannot read resource");
}
- _res->nukeResource(type, idx);
-
- error("Cannot read resource");
+ return 1;
}
int ScummEngine::getResourceRoomNr(int type, int idx) {
@@ -706,6 +703,20 @@ int ScummEngine::getResourceRoomNr(int type, int idx) {
return _res->roomno[type][idx];
}
+uint32 ScummEngine::getResourceRoomOffset(int type, int idx) {
+ if (type == rtRoom) {
+ return (_game.version == 8) ? 8 : 0;
+ }
+ return _res->roomoffs[type][idx];
+}
+
+uint32 ScummEngine_v70he::getResourceRoomOffset(int type, int idx) {
+ if (type == rtRoom) {
+ return _heV7RoomIntOffsets[idx];
+ }
+ return _res->roomoffs[type][idx];
+}
+
int ScummEngine::getResourceSize(int type, int idx) {
byte *ptr = getResourceAddress(type, idx);
assert(ptr);
@@ -1276,14 +1287,14 @@ void ScummEngine::allocateArrays() {
_arraySlot = (byte *)calloc(_numArray, 1);
}
- _res->allocResTypeData(rtCostume, (_game.features & GF_NEW_COSTUMES) ? MKID_BE('AKOS') : MKID_BE('COST'),
+ _res->allocResTypeData(rtCostume, (_game.features & GF_NEW_COSTUMES) ? MKTAG('A','K','O','S') : MKTAG('C','O','S','T'),
_numCostumes, "costume", 1);
- _res->allocResTypeData(rtRoom, MKID_BE('ROOM'), _numRooms, "room", 1);
- _res->allocResTypeData(rtRoomImage, MKID_BE('RMIM'), _numRooms, "room image", 1);
- _res->allocResTypeData(rtRoomScripts, MKID_BE('RMSC'), _numRooms, "room script", 1);
- _res->allocResTypeData(rtSound, MKID_BE('SOUN'), _numSounds, "sound", 2);
- _res->allocResTypeData(rtScript, MKID_BE('SCRP'), _numScripts, "script", 1);
- _res->allocResTypeData(rtCharset, MKID_BE('CHAR'), _numCharsets, "charset", 1);
+ _res->allocResTypeData(rtRoom, MKTAG('R','O','O','M'), _numRooms, "room", 1);
+ _res->allocResTypeData(rtRoomImage, MKTAG('R','M','I','M'), _numRooms, "room image", 1);
+ _res->allocResTypeData(rtRoomScripts, MKTAG('R','M','S','C'), _numRooms, "room script", 1);
+ _res->allocResTypeData(rtSound, MKTAG('S','O','U','N'), _numSounds, "sound", 2);
+ _res->allocResTypeData(rtScript, MKTAG('S','C','R','P'), _numScripts, "script", 1);
+ _res->allocResTypeData(rtCharset, MKTAG('C','H','A','R'), _numCharsets, "charset", 1);
_res->allocResTypeData(rtObjectName, 0, _numNewNames, "new name", 0);
_res->allocResTypeData(rtInventory, 0, _numInventory, "inventory", 0);
_res->allocResTypeData(rtTemp, 0, 10, "temp", 0);
@@ -1293,15 +1304,18 @@ void ScummEngine::allocateArrays() {
_res->allocResTypeData(rtString, 0, _numArray, "array", 0);
_res->allocResTypeData(rtFlObject, 0, _numFlObject, "flobject", 0);
_res->allocResTypeData(rtMatrix, 0, 10, "boxes", 0);
- _res->allocResTypeData(rtImage, MKID_BE('AWIZ'), _numImages, "images", 1);
- _res->allocResTypeData(rtTalkie, MKID_BE('TLKE'), _numTalkies, "talkie", 1);
+ _res->allocResTypeData(rtImage, MKTAG('A','W','I','Z'), _numImages, "images", 1);
+ _res->allocResTypeData(rtTalkie, MKTAG('T','L','K','E'), _numTalkies, "talkie", 1);
+}
- if (_game.heversion >= 70) {
- _res->allocResTypeData(rtSpoolBuffer, 0, 9, "spool buffer", 1);
- _heV7RoomIntOffsets = (uint32 *)calloc(_numRooms, sizeof(uint32));
- }
+void ScummEngine_v70he::allocateArrays() {
+ ScummEngine::allocateArrays();
+
+ _res->allocResTypeData(rtSpoolBuffer, 0, 9, "spool buffer", 1);
+ _heV7RoomIntOffsets = (uint32 *)calloc(_numRooms, sizeof(uint32));
}
+
void ScummEngine::dumpResource(const char *tag, int idx, const byte *ptr, int length) {
char buf[256];
Common::DumpFile out;
@@ -1450,35 +1464,35 @@ const byte *findResourceSmall(uint32 tag, const byte *searchin) {
uint16 newTag2Old(uint32 newTag) {
switch (newTag) {
- case (MKID_BE('RMHD')):
+ case (MKTAG('R','M','H','D')):
return (0x4448); // HD
- case (MKID_BE('IM00')):
+ case (MKTAG('I','M','0','0')):
return (0x4D42); // BM
- case (MKID_BE('EXCD')):
+ case (MKTAG('E','X','C','D')):
return (0x5845); // EX
- case (MKID_BE('ENCD')):
+ case (MKTAG('E','N','C','D')):
return (0x4E45); // EN
- case (MKID_BE('SCAL')):
+ case (MKTAG('S','C','A','L')):
return (0x4153); // SA
- case (MKID_BE('LSCR')):
+ case (MKTAG('L','S','C','R')):
return (0x534C); // LS
- case (MKID_BE('OBCD')):
+ case (MKTAG('O','B','C','D')):
return (0x434F); // OC
- case (MKID_BE('OBIM')):
+ case (MKTAG('O','B','I','M')):
return (0x494F); // OI
- case (MKID_BE('SMAP')):
+ case (MKTAG('S','M','A','P')):
return (0x4D42); // BM
- case (MKID_BE('CLUT')):
+ case (MKTAG('C','L','U','T')):
return (0x4150); // PA
- case (MKID_BE('BOXD')):
+ case (MKTAG('B','O','X','D')):
return (0x5842); // BX
- case (MKID_BE('CYCL')):
+ case (MKTAG('C','Y','C','L')):
return (0x4343); // CC
- case (MKID_BE('EPAL')):
+ case (MKTAG('E','P','A','L')):
return (0x5053); // SP
- case (MKID_BE('TILE')):
+ case (MKTAG('T','I','L','E')):
return (0x4C54); // TL
- case (MKID_BE('ZP00')):
+ case (MKTAG('Z','P','0','0')):
return (0x505A); // ZP
default:
return (0);
diff --git a/engines/scumm/resource_v3.cpp b/engines/scumm/resource_v3.cpp
index 0728395055..5f23720ce9 100644
--- a/engines/scumm/resource_v3.cpp
+++ b/engines/scumm/resource_v3.cpp
@@ -32,7 +32,7 @@ namespace Scumm {
extern const char *resTypeFromId(int id);
-void ScummEngine_v3old::readResTypeList(int id) {
+int ScummEngine_v3old::readResTypeList(int id) {
int num;
int i;
@@ -57,6 +57,8 @@ void ScummEngine_v3old::readResTypeList(int id) {
if (_res->roomoffs[id][i] == 0xFFFF)
_res->roomoffs[id][i] = (uint32)RES_INVALID_OFFSET;
}
+
+ return num;
}
void ScummEngine_v3old::readIndexFile() {
diff --git a/engines/scumm/resource_v4.cpp b/engines/scumm/resource_v4.cpp
index 808fcbd73e..b1d98494d4 100644
--- a/engines/scumm/resource_v4.cpp
+++ b/engines/scumm/resource_v4.cpp
@@ -33,7 +33,7 @@ namespace Scumm {
extern const char *resTypeFromId(int id);
-void ScummEngine_v4::readResTypeList(int id) {
+int ScummEngine_v4::readResTypeList(int id) {
int num;
int i;
@@ -49,6 +49,8 @@ void ScummEngine_v4::readResTypeList(int id) {
_res->roomno[id][i] = _fileHandle->readByte();
_res->roomoffs[id][i] = _fileHandle->readUint32LE();
}
+
+ return num;
}
void ScummEngine_v4::readIndexFile() {
diff --git a/engines/scumm/room.cpp b/engines/scumm/room.cpp
index 02b2482e40..06fa0f2c39 100644
--- a/engines/scumm/room.cpp
+++ b/engines/scumm/room.cpp
@@ -264,7 +264,7 @@ void ScummEngine::setupRoomSubBlocks() {
//
// Determine the room dimensions (width/height)
//
- rmhd = (const RoomHeader *)findResourceData(MKID_BE('RMHD'), roomptr);
+ rmhd = (const RoomHeader *)findResourceData(MKTAG('R','M','H','D'), roomptr);
if (_game.version == 8) {
_roomWidth = READ_LE_UINT32(&(rmhd->v8.width));
@@ -286,18 +286,18 @@ void ScummEngine::setupRoomSubBlocks() {
if (_game.version == 8) {
_IM00_offs = getObjectImage(roomptr, 1) - roomptr;
} else if (_game.features & GF_SMALL_HEADER) {
- _IM00_offs = findResourceData(MKID_BE('IM00'), roomptr) - roomptr;
+ _IM00_offs = findResourceData(MKTAG('I','M','0','0'), roomptr) - roomptr;
} else if (_game.heversion >= 70) {
byte *roomImagePtr = getResourceAddress(rtRoomImage, _roomResource);
- _IM00_offs = findResource(MKID_BE('IM00'), roomImagePtr) - roomImagePtr;
+ _IM00_offs = findResource(MKTAG('I','M','0','0'), roomImagePtr) - roomImagePtr;
} else {
- _IM00_offs = findResource(MKID_BE('IM00'), findResource(MKID_BE('RMIM'), roomptr)) - roomptr;
+ _IM00_offs = findResource(MKTAG('I','M','0','0'), findResource(MKTAG('R','M','I','M'), roomptr)) - roomptr;
}
//
// Look for an exit script
//
- ptr = findResourceData(MKID_BE('EXCD'), roomResPtr);
+ ptr = findResourceData(MKTAG('E','X','C','D'), roomResPtr);
if (ptr)
_EXCD_offs = ptr - roomResPtr;
if (_dumpScripts && _EXCD_offs)
@@ -306,7 +306,7 @@ void ScummEngine::setupRoomSubBlocks() {
//
// Look for an entry script
//
- ptr = findResourceData(MKID_BE('ENCD'), roomResPtr);
+ ptr = findResourceData(MKTAG('E','N','C','D'), roomResPtr);
if (ptr)
_ENCD_offs = ptr - roomResPtr;
if (_dumpScripts && _ENCD_offs)
@@ -326,7 +326,7 @@ void ScummEngine::setupRoomSubBlocks() {
if (_game.features & GF_SMALL_HEADER) {
ResourceIterator localScriptIterator(searchptr, true);
- while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
+ while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
id = ptr[0];
@@ -341,7 +341,7 @@ void ScummEngine::setupRoomSubBlocks() {
}
} else if (_game.heversion >= 90) {
ResourceIterator localScriptIterator2(searchptr, false);
- while ((ptr = localScriptIterator2.findNext(MKID_BE('LSC2'))) != NULL) {
+ while ((ptr = localScriptIterator2.findNext(MKTAG('L','S','C','2'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
@@ -359,7 +359,7 @@ void ScummEngine::setupRoomSubBlocks() {
}
ResourceIterator localScriptIterator(searchptr, false);
- while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
+ while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
@@ -376,7 +376,7 @@ void ScummEngine::setupRoomSubBlocks() {
} else {
ResourceIterator localScriptIterator(searchptr, false);
- while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
+ while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
@@ -403,18 +403,18 @@ void ScummEngine::setupRoomSubBlocks() {
}
// Locate the EGA palette (currently unused).
- ptr = findResourceData(MKID_BE('EPAL'), roomptr);
+ ptr = findResourceData(MKTAG('E','P','A','L'), roomptr);
if (ptr)
_EPAL_offs = ptr - roomptr;
// Locate the standard room palette (for V3-V5 games).
- ptr = findResourceData(MKID_BE('CLUT'), roomptr);
+ ptr = findResourceData(MKTAG('C','L','U','T'), roomptr);
if (ptr)
_CLUT_offs = ptr - roomptr;
// Locate the standard room palettes (for V6+ games).
if (_game.version >= 6) {
- ptr = findResource(MKID_BE('PALS'), roomptr);
+ ptr = findResource(MKTAG('P','A','L','S'), roomptr);
if (ptr) {
_PALS_offs = ptr - roomptr;
}
@@ -425,7 +425,7 @@ void ScummEngine::setupRoomSubBlocks() {
if (_game.version == 8)
trans = (byte)READ_LE_UINT32(&(rmhd->v8.transparency));
else {
- ptr = findResourceData(MKID_BE('TRNS'), roomptr);
+ ptr = findResourceData(MKTAG('T','R','N','S'), roomptr);
if (ptr)
trans = ptr[0];
else
@@ -434,7 +434,7 @@ void ScummEngine::setupRoomSubBlocks() {
// Actor Palette in HE 70 games
if (_game.heversion == 70) {
- ptr = findResourceData(MKID_BE('REMP'), roomptr);
+ ptr = findResourceData(MKTAG('R','E','M','P'), roomptr);
if (ptr) {
for (i = 0; i < 256; i++)
_HEV7ActorPalette[i] = *ptr++;
@@ -485,7 +485,7 @@ void ScummEngine::resetRoomSubBlocks() {
_res->nukeResource(rtMatrix, 1);
_res->nukeResource(rtMatrix, 2);
if (_game.features & GF_SMALL_HEADER) {
- ptr = findResourceData(MKID_BE('BOXD'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','D'), roomptr);
if (ptr) {
byte numOfBoxes = *ptr;
int size;
@@ -506,21 +506,21 @@ void ScummEngine::resetRoomSubBlocks() {
}
} else {
- ptr = findResourceData(MKID_BE('BOXD'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','D'), roomptr);
if (ptr) {
int size = getResourceDataSize(ptr);
_res->createResource(rtMatrix, 2, size);
roomptr = getResourceAddress(rtRoom, _roomResource);
- ptr = findResourceData(MKID_BE('BOXD'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','D'), roomptr);
memcpy(getResourceAddress(rtMatrix, 2), ptr, size);
}
- ptr = findResourceData(MKID_BE('BOXM'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','M'), roomptr);
if (ptr) {
int size = getResourceDataSize(ptr);
_res->createResource(rtMatrix, 1, size);
roomptr = getResourceAddress(rtRoom, _roomResource);
- ptr = findResourceData(MKID_BE('BOXM'), roomptr);
+ ptr = findResourceData(MKTAG('B','O','X','M'), roomptr);
memcpy(getResourceAddress(rtMatrix, 1), ptr, size);
}
}
@@ -531,7 +531,7 @@ void ScummEngine::resetRoomSubBlocks() {
for (i = 1; i < _res->num[rtScaleTable]; i++)
_res->nukeResource(rtScaleTable, i);
- ptr = findResourceData(MKID_BE('SCAL'), roomptr);
+ ptr = findResourceData(MKTAG('S','C','A','L'), roomptr);
if (ptr) {
int s1, s2, y1, y2;
if (_game.version == 8) {
@@ -558,7 +558,7 @@ void ScummEngine::resetRoomSubBlocks() {
// Color cycling
// HE 7.0 games load resources but don't use them.
if (_game.version >= 4 && _game.heversion <= 62) {
- ptr = findResourceData(MKID_BE('CYCL'), roomptr);
+ ptr = findResourceData(MKTAG('C','Y','C','L'), roomptr);
if (ptr) {
initCycl(ptr);
}
@@ -567,7 +567,7 @@ void ScummEngine::resetRoomSubBlocks() {
#ifdef ENABLE_HE
// Polygons in HE 80+ games
if (_game.heversion >= 80) {
- ptr = findResourceData(MKID_BE('POLD'), roomptr);
+ ptr = findResourceData(MKTAG('P','O','L','D'), roomptr);
if (ptr) {
((ScummEngine_v71he *)this)->_wiz->polygonLoad(ptr);
}
@@ -581,7 +581,7 @@ void ScummEngine::resetRoomSubBlocks() {
void ScummEngine_v3old::setupRoomSubBlocks() {
const byte *ptr;
- byte *roomptr, *searchptr = 0;
+ byte *roomptr;
const RoomHeader *rmhd;
_ENCD_offs = 0;
@@ -669,7 +669,6 @@ void ScummEngine_v3old::setupRoomSubBlocks() {
// Determine the room script base address
roomptr = getResourceAddress(rtRoom, _roomResource);
- searchptr = roomptr;
memset(_localScriptOffsets, 0, sizeof(_localScriptOffsets));
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index bdae4c5f6a..3bfe51a77b 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -154,7 +154,7 @@ void ScummEngine::requestLoad(int slot) {
}
static bool saveSaveGameHeader(Common::OutSaveFile *out, SaveGameHeader &hdr) {
- hdr.type = MKID_BE('SCVM');
+ hdr.type = MKTAG('S','C','V','M');
hdr.size = 0;
hdr.ver = CURRENT_VER;
@@ -308,7 +308,7 @@ static bool loadSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &h
hdr.size = in->readUint32LE();
hdr.ver = in->readUint32LE();
in->read(hdr.name, sizeof(hdr.name));
- return !in->err() && hdr.type == MKID_BE('SCVM');
+ return !in->err() && hdr.type == MKTAG('S','C','V','M');
}
bool ScummEngine::loadState(int slot, bool compat) {
@@ -373,7 +373,7 @@ bool ScummEngine::loadState(int slot, bool compat) {
// Since version 56 we save additional information about the creation of
// the save game and the save time.
if (hdr.ver >= VER(56)) {
- InfoStuff infos;
+ SaveStateMetaInfos infos;
if (!loadInfos(in, &infos)) {
warning("Info section could not be found");
delete in;
@@ -703,7 +703,7 @@ Graphics::Surface *ScummEngine::loadThumbnailFromSlot(const char *target, int sl
return thumb;
}
-bool ScummEngine::loadInfosFromSlot(const char *target, int slot, InfoStuff *stuff) {
+bool ScummEngine::loadInfosFromSlot(const char *target, int slot, SaveStateMetaInfos *stuff) {
Common::SeekableReadStream *in;
SaveGameHeader hdr;
@@ -741,12 +741,12 @@ bool ScummEngine::loadInfosFromSlot(const char *target, int slot, InfoStuff *stu
return true;
}
-bool ScummEngine::loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff) {
- memset(stuff, 0, sizeof(InfoStuff));
+bool ScummEngine::loadInfos(Common::SeekableReadStream *file, SaveStateMetaInfos *stuff) {
+ memset(stuff, 0, sizeof(SaveStateMetaInfos));
SaveInfoSection section;
section.type = file->readUint32BE();
- if (section.type != MKID_BE('INFO')) {
+ if (section.type != MKTAG('I','N','F','O')) {
return false;
}
@@ -793,7 +793,7 @@ bool ScummEngine::loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff)
void ScummEngine::saveInfos(Common::WriteStream* file) {
SaveInfoSection section;
- section.type = MKID_BE('INFO');
+ section.type = MKTAG('I','N','F','O');
section.version = INFOSECTION_VERSION;
section.size = SaveInfoSectionSize;
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index 91e780bcd1..eead241b90 100644
--- a/engines/scumm/saveload.h
+++ b/engines/scumm/saveload.h
@@ -30,8 +30,8 @@
#include <stddef.h> // for ptrdiff_t
namespace Common {
- class SeekableReadStream;
- class WriteStream;
+class SeekableReadStream;
+class WriteStream;
}
namespace Scumm {
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index eac2061560..9e02f126cd 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -174,7 +174,7 @@ int ScummEngine::getVerbEntrypoint(int obj, int entry) {
else if (_game.features & GF_SMALL_HEADER)
verbptr = objptr + 19;
else
- verbptr = findResource(MKID_BE('VERB'), objptr);
+ verbptr = findResource(MKTAG('V','E','R','B'), objptr);
assert(verbptr);
@@ -261,8 +261,7 @@ void ScummEngine::stopScript(int script) {
/* Stop an object script 'script'*/
void ScummEngine::stopObjectScript(int script) {
ScriptSlot *ss;
- NestedScript *nest;
- int i, num;
+ int i;
if (script == 0)
return;
@@ -282,19 +281,14 @@ void ScummEngine::stopObjectScript(int script) {
}
}
- nest = vm.nest;
- num = vm.numNestedScripts;
-
- while (num > 0) {
- if (nest->number == script &&
- (nest->where == WIO_ROOM || nest->where == WIO_INVENTORY || nest->where == WIO_FLOBJECT)) {
- nukeArrays(nest->slot);
- nest->number = 0xFF;
- nest->slot = 0xFF;
- nest->where = 0xFF;
+ for (i = 0; i < vm.numNestedScripts; ++i) {
+ if (vm.nest[i].number == script &&
+ (vm.nest[i].where == WIO_ROOM || vm.nest[i].where == WIO_INVENTORY || vm.nest[i].where == WIO_FLOBJECT)) {
+ nukeArrays(vm.nest[i].slot);
+ vm.nest[i].number = 0xFF;
+ vm.nest[i].slot = 0xFF;
+ vm.nest[i].where = 0xFF;
}
- nest++;
- num--;
}
}
@@ -319,6 +313,9 @@ void ScummEngine::runScriptNested(int script) {
updateScriptPtr();
+ if (vm.numNestedScripts >= kMaxScriptNesting)
+ error("Too many nested scripts");
+
nest = &vm.nest[vm.numNestedScripts];
if (_currentScript == 0xFF) {
@@ -334,9 +331,6 @@ void ScummEngine::runScriptNested(int script) {
vm.numNestedScripts++;
- if (vm.numNestedScripts > ARRAYSIZE(vm.nest))
- error("Too many nested scripts");
-
_currentScript = script;
getScriptBaseAddress();
resetScriptPointer();
@@ -927,7 +921,7 @@ void ScummEngine::runExitScript() {
// be limiting ourselves to strictly reading the size from the header?
if (_game.id == GID_INDY3 && !(_game.features & GF_OLD_BUNDLE)) {
byte *roomptr = getResourceAddress(rtRoom, _roomResource);
- const byte *excd = findResourceData(MKID_BE('EXCD'), roomptr) - _resourceHeaderSize;
+ const byte *excd = findResourceData(MKTAG('E','X','C','D'), roomptr) - _resourceHeaderSize;
if (!excd || (getResourceDataSize(excd) < 1)) {
debug(2, "Exit-%d is empty", _roomResource);
return;
@@ -1283,7 +1277,8 @@ void ScummEngine::beginCutscene(int *args) {
int scr = _currentScript;
vm.slot[scr].cutsceneOverride++;
- if (++vm.cutSceneStackPointer > ARRAYSIZE(vm.cutSceneData))
+ ++vm.cutSceneStackPointer;
+ if (vm.cutSceneStackPointer >= kMaxCutsceneNum)
error("Cutscene stack overflow");
vm.cutSceneData[vm.cutSceneStackPointer] = args[0];
@@ -1313,6 +1308,9 @@ void ScummEngine::endCutscene() {
vm.cutSceneScript[vm.cutSceneStackPointer] = 0;
vm.cutScenePtr[vm.cutSceneStackPointer] = 0;
+
+ if (0 == vm.cutSceneStackPointer)
+ error("Cutscene stack underflow");
vm.cutSceneStackPointer--;
if (VAR(VAR_CUTSCENE_END_SCRIPT))
@@ -1321,7 +1319,7 @@ void ScummEngine::endCutscene() {
void ScummEngine::abortCutscene() {
const int idx = vm.cutSceneStackPointer;
- assert(0 <= idx && idx < 5);
+ assert(0 <= idx && idx < kMaxCutsceneNum);
uint32 offs = vm.cutScenePtr[idx];
if (offs) {
@@ -1340,7 +1338,7 @@ void ScummEngine::abortCutscene() {
void ScummEngine::beginOverride() {
const int idx = vm.cutSceneStackPointer;
- assert(0 <= idx && idx < 5);
+ assert(0 <= idx && idx < kMaxCutsceneNum);
vm.cutScenePtr[idx] = _scriptPointer - _scriptOrgPointer;
vm.cutSceneScript[idx] = _currentScript;
@@ -1357,7 +1355,7 @@ void ScummEngine::beginOverride() {
void ScummEngine::endOverride() {
const int idx = vm.cutSceneStackPointer;
- assert(0 <= idx && idx < 5);
+ assert(0 <= idx && idx < kMaxCutsceneNum);
vm.cutScenePtr[idx] = 0;
vm.cutSceneScript[idx] = 0;
diff --git a/engines/scumm/script.h b/engines/scumm/script.h
index dbfa2630e5..39d5d802b4 100644
--- a/engines/scumm/script.h
+++ b/engines/scumm/script.h
@@ -98,16 +98,29 @@ struct NestedScript {
uint8 slot;
};
+enum {
+ /**
+ * The maximal number of cutscenes that can be active
+ * in parallel (i.e. nested).
+ */
+ kMaxCutsceneNum = 5,
+
+ /**
+ * The maximal 'nesting' level for scripts.
+ */
+ kMaxScriptNesting = 15
+};
+
struct VirtualMachineState {
- uint32 cutScenePtr[5];
- byte cutSceneScript[5];
- int16 cutSceneData[5];
+ uint32 cutScenePtr[kMaxCutsceneNum];
+ byte cutSceneScript[kMaxCutsceneNum];
+ int16 cutSceneData[kMaxCutsceneNum];
int16 cutSceneScriptIndex;
byte cutSceneStackPointer;
ScriptSlot slot[NUM_SCRIPT_SLOT];
int32 localvar[NUM_SCRIPT_SLOT][26];
- NestedScript nest[15];
+ NestedScript nest[kMaxScriptNesting];
byte numNestedScripts;
};
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 9e245aa168..ee790f7876 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -530,11 +530,20 @@ void ScummEngine_v5::o5_actorOps() {
void ScummEngine_v5::o5_setClass() {
int obj = getVarOrDirectWord(PARAM_1);
- int newClass;
+ int cls;
while ((_opcode = fetchScriptByte()) != 0xFF) {
- newClass = getVarOrDirectWord(PARAM_1);
- if (newClass == 0) {
+ cls = getVarOrDirectWord(PARAM_1);
+
+ // WORKAROUND bug #1668393: Due to a script bug, the wrong opcode is
+ // used to test and set the state of various objects (e.g. the inside
+ // door (object 465) of the of the Hostel on Mars), when opening the
+ // Hostel door from the outside.
+ if (_game.id == GID_ZAK && _game.platform == Common::kPlatformFMTowns &&
+ vm.slot[_currentScript].number == 205 && _currentRoom == 185 &&
+ (cls == 0 || cls == 1)) {
+ putState(obj, cls);
+ } else if (cls == 0) {
// Class '0' means: clean all class data
_classData[obj] = 0;
if ((_game.features & GF_SMALL_HEADER) && obj <= _numActors) {
@@ -543,7 +552,7 @@ void ScummEngine_v5::o5_setClass() {
a->_forceClip = 0;
}
} else
- putClass(obj, newClass, (newClass & 0x80) ? true : false);
+ putClass(obj, cls, (cls & 0x80) ? true : false);
}
}
@@ -1148,9 +1157,10 @@ void ScummEngine_v5::o5_ifClassOfIs() {
while ((_opcode = fetchScriptByte()) != 0xFF) {
cls = getVarOrDirectWord(PARAM_1);
- // WORKAROUND bug #1668393: Due to a script bug, the wrong opcode is used
- // to check the state of the inside door (object 465) of the Hostel on Mars,
- // when opening the Hostel door from the outside.
+ // WORKAROUND bug #1668393: Due to a script bug, the wrong opcode is
+ // used to test and set the state of various objects (e.g. the inside
+ // door (object 465) of the of the Hostel on Mars), when opening the
+ // Hostel door from the outside.
if (_game.id == GID_ZAK && _game.platform == Common::kPlatformFMTowns &&
vm.slot[_currentScript].number == 205 && _currentRoom == 185 &&
obj == 465 && cls == 0) {
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index 30187937f3..b2df1d0baa 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -1228,11 +1228,11 @@ void ScummEngine_v6::o6_animateActor() {
}
void ScummEngine_v6::o6_doSentence() {
- int verb, objectA, objectB, dummy = 0;
+ int verb, objectA, objectB;
objectB = pop();
if (_game.version < 8)
- dummy = pop(); // dummy pop (in Sam&Max, seems to be always 0 or 130)
+ pop(); // dummy pop (in Sam&Max, seems to be always 0 or 130)
objectA = pop();
verb = pop();
@@ -3014,7 +3014,7 @@ void ScummEngine_v6::o6_setBoxSet() {
ResourceIterator boxds(room, false);
for (i = 0; i < arg; i++)
- boxd = boxds.findNext(MKID_BE('BOXD'));
+ boxd = boxds.findNext(MKTAG('B','O','X','D'));
if (!boxd)
error("ScummEngine_v6::o6_setBoxSet: Can't find dboxes for set %d", arg);
@@ -3027,7 +3027,7 @@ void ScummEngine_v6::o6_setBoxSet() {
ResourceIterator boxms(room, false);
for (i = 0; i < arg; i++)
- boxm = boxms.findNext(MKID_BE('BOXM'));
+ boxm = boxms.findNext(MKTAG('B','O','X','M'));
if (!boxm)
error("ScummEngine_v6::o6_setBoxSet: Can't find mboxes for set %d", arg);
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 40eeba3663..8f555818f4 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 Mon Oct 18 00:42:16 2010
+ This file was generated by the md5table tool on Sun Apr 17 10:46:26 2011
DO NOT EDIT MANUALLY!
*/
@@ -206,6 +206,7 @@ static const MD5Table md5table[] = {
{ "4c4820518e16e1a0e3616a3b021a04f3", "catalog", "HE CUP", "Preview", 10927456, Common::DE_DEU, Common::kPlatformUnknown },
{ "4cb9c3618f71668f8e4346c8f323fa82", "monkey2", "", "", 10700, Common::EN_ANY, Common::kPlatformMacintosh },
{ "4ce2d5b355964bbcb5e5ce73236ef868", "freddicove", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows },
+ { "4cfd3fda4a4e6e64a1fc488eba973b7a", "fbpack", "", "", -1, Common::EN_ANY, Common::kPlatformPC },
{ "4d34042713958b971cb139fba4658586", "atlantis", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns },
{ "4dbff3787aedcd96b0b325f2d92d7ad9", "maze", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "4dc780f1bc587a193ce8a97652791438", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformAmiga },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index c2556d6467..f43aed53f7 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -201,8 +201,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_bootParam = 0;
_dumpScripts = false;
_debugMode = 0;
- _heV7DiskOffsets = NULL;
- _heV7RoomIntOffsets = NULL;
_objectOwnerTable = NULL;
_objectRoomTable = NULL;
_objectStateTable = NULL;
@@ -320,11 +318,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_V1TalkingActor = 0;
_NESStartStrip = 0;
- _actorClipOverride.top = 0;
- _actorClipOverride.bottom = 480;
- _actorClipOverride.left = 0;
- _actorClipOverride.right = 640;
-
_skipDrawObject = 0;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
@@ -767,6 +760,12 @@ ScummEngine_v60he::ScummEngine_v60he(OSystem *syst, const DetectorResult &dr)
: ScummEngine_v6(syst, dr) {
memset(_hInFileTable, 0, sizeof(_hInFileTable));
memset(_hOutFileTable, 0, sizeof(_hOutFileTable));
+
+ _actorClipOverride.top = 0;
+ _actorClipOverride.bottom = 480;
+ _actorClipOverride.left = 0;
+ _actorClipOverride.right = 640;
+
memset(_heTimers, 0, sizeof(_heTimers));
if (_game.heversion >= 61)
@@ -787,7 +786,9 @@ ScummEngine_v70he::ScummEngine_v70he(OSystem *syst, const DetectorResult &dr)
else
_resExtractor = new Win32ResExtractor(this);
+ _heV7DiskOffsets = NULL;
_heV7RoomOffsets = NULL;
+ _heV7RoomIntOffsets = NULL;
_heSndSoundId = 0;
_heSndOffset = 0;
@@ -804,8 +805,8 @@ ScummEngine_v70he::ScummEngine_v70he(OSystem *syst, const DetectorResult &dr)
ScummEngine_v70he::~ScummEngine_v70he() {
delete _resExtractor;
free(_heV7DiskOffsets);
- free(_heV7RoomIntOffsets);
free(_heV7RoomOffsets);
+ free(_heV7RoomIntOffsets);
free(_storedFlObjects);
}
@@ -1161,7 +1162,7 @@ Common::Error ScummEngine::init() {
warning("Starting game without the required 16bit color support.\nYou may experience color glitches");
initGraphics(screenWidth, screenHeight, (screenWidth > 320));
} else {
- error("16bit color support is required for this game");
+ return Common::Error(Common::kUnsupportedColorMode, "16bit color support is required for this game");
}
#endif
} else {
@@ -1221,7 +1222,7 @@ void ScummEngine::setupScumm() {
setupCharsetRenderer();
// Create and clear the text surface
- _textSurface.create(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, 1);
+ _textSurface.create(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, Graphics::PixelFormat::createFormatCLUT8());
clearTextSurface();
// Create the costume renderer
@@ -1576,7 +1577,7 @@ void ScummEngine_v3::resetScumm() {
// Load tile set and palette for the distaff
byte *roomptr = getResourceAddress(rtRoom, 90);
assert(roomptr);
- const byte *palPtr = findResourceData(MKID_BE('CLUT'), roomptr);
+ const byte *palPtr = findResourceData(MKTAG('C','L','U','T'), roomptr);
assert(palPtr - 4);
setPCEPaletteFromPtr(palPtr);
_gdi->_distaff = true;
@@ -1647,6 +1648,8 @@ void ScummEngine_v90he::resetScumm() {
break;
case GID_SOCCER:
+ case GID_SOCCERMLS:
+ case GID_SOCCER2004:
_logicHE = new LogicHEsoccer(this);
break;
@@ -1858,27 +1861,25 @@ void ScummEngine::setupMusic(int midi) {
if (ConfMan.hasKey("tempo"))
_imuse->property(IMuse::PROP_TEMPO_BASE, ConfMan.getInt("tempo"));
// YM2162 driver can't handle midi->getPercussionChannel(), NULL shouldn't init MT-32/GM/GS
- if (/*(midi != MDT_TOWNS) && (*/midi != MDT_NONE/*)*/) {
+ if (midi != MDT_NONE) {
_imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32);
if (MidiDriver::getMusicType(dev) != MT_MT32) // MT-32 Emulation shouldn't be GM/GS initialized
_imuse->property(IMuse::PROP_GS, _enable_gs);
}
- if (_game.heversion >= 60 /*|| midi == MDT_TOWNS*/) {
+ if (_game.heversion >= 60) {
_imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1);
_imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1);
}
- /*if (midi == MDT_TOWNS)
- _imuse->property(IMuse::PROP_DIRECT_PASSTHROUGH, 1);*/
}
}
}
void ScummEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
// Sync the engine with the config manager
int soundVolumeMusic = ConfMan.getInt("music_volume");
int soundVolumeSfx = ConfMan.getInt("sfx_volume");
- int soundVolumeSpeech = ConfMan.getInt("speech_volume");
bool mute = false;
@@ -1886,7 +1887,7 @@ void ScummEngine::syncSoundSettings() {
mute = ConfMan.getBool("mute");
if (mute)
- soundVolumeMusic = soundVolumeSfx = soundVolumeSpeech = 0;
+ soundVolumeMusic = soundVolumeSfx = 0;
}
if (_musicEngine) {
@@ -1897,10 +1898,6 @@ void ScummEngine::syncSoundSettings() {
_townsPlayer->setSfxVolume(soundVolumeSfx);
}
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSfx);
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech);
-
if (ConfMan.getBool("speech_mute"))
_voiceMode = 2;
else
@@ -2499,7 +2496,7 @@ void ScummEngine_v90he::runBootscript() {
void ScummEngine::startManiac() {
debug(0, "stub startManiac()");
- displayMessage(0, "Usually, Maniac Mansion would start now. But ScummVM doesn't do that yet. To play it, go to 'Add Game' in the ScummVM start menu and select the 'Maniac' directory inside the Tentacle game directory.");
+ displayMessage(0, "%s", _("Usually, Maniac Mansion would start now. But ScummVM doesn't do that yet. To play it, go to 'Add Game' in the ScummVM start menu and select the 'Maniac' directory inside the Tentacle game directory."));
}
#pragma mark -
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 587d1be776..62c6c70e5a 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -35,6 +35,7 @@
#include "common/random.h"
#include "common/rect.h"
#include "common/str.h"
+#include "common/textconsole.h"
#include "graphics/surface.h"
#include "graphics/sjis.h"
@@ -56,12 +57,12 @@
#endif
namespace GUI {
- class Dialog;
+class Dialog;
}
using GUI::Dialog;
namespace Common {
- class SeekableReadStream;
- class WriteStream;
+class SeekableReadStream;
+class WriteStream;
}
/**
@@ -253,6 +254,8 @@ enum ScummGameId {
GID_FUNSHOP, // Used for all three funshops
GID_FOOTBALL,
GID_SOCCER,
+ GID_SOCCERMLS,
+ GID_SOCCER2004,
GID_BASEBALL2001,
GID_BASKETBALL,
GID_MOONBASE,
@@ -308,24 +311,7 @@ enum WhereIsObject {
WIO_FLOBJECT = 4
};
-struct AuxBlock {
- bool visible;
- Common::Rect r;
-
- void reset() {
- visible = false;
- r.left = r.top = 0;
- r.right = r.bottom = -1;
- }
-};
-
-struct AuxEntry {
- int actorNum;
- int subIndex;
-};
-
-// TODO: Rename InfoStuff to something more descriptive
-struct InfoStuff {
+struct SaveStateMetaInfos {
uint32 date;
uint16 time;
uint32 playtime;
@@ -480,7 +466,7 @@ public:
virtual Common::Error run() {
Common::Error err;
err = init();
- if (err != Common::kNoError)
+ if (err.getCode() != Common::kNoError)
return err;
return go();
}
@@ -630,7 +616,7 @@ public:
FilenamePattern _filenamePattern;
- Common::String generateFilename(const int room) const;
+ virtual Common::String generateFilename(const int room) const;
protected:
Common::KeyState _keyPressed;
@@ -694,11 +680,11 @@ public:
}
static Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot);
- static bool loadInfosFromSlot(const char *target, int slot, InfoStuff *stuff);
+ static bool loadInfosFromSlot(const char *target, int slot, SaveStateMetaInfos *stuff);
protected:
void saveInfos(Common::WriteStream* file);
- static bool loadInfos(Common::SeekableReadStream *file, InfoStuff *stuff);
+ static bool loadInfos(Common::SeekableReadStream *file, SaveStateMetaInfos *stuff);
protected:
/* Script VM - should be in Script class */
@@ -790,8 +776,6 @@ public:
protected:
int _resourceHeaderSize;
byte _resourceMapper[128];
- byte *_heV7DiskOffsets;
- uint32 *_heV7RoomIntOffsets;
const byte *_resourceLastSearchBuf; // FIXME: need to put it to savefile?
uint32 _resourceLastSearchSize; // FIXME: need to put it to savefile?
@@ -804,11 +788,13 @@ protected:
bool openResourceFile(const Common::String &filename, byte encByte); // TODO: Use Common::String
void loadPtrToResource(int type, int i, const byte *ptr);
- virtual void readResTypeList(int id);
+ virtual int readResTypeList(int id);
// void allocResTypeData(int id, uint32 tag, int num, const char *name, int mode);
// byte *createResource(int type, int index, uint32 size);
int loadResource(int type, int i);
// void nukeResource(int type, int i);
+ int getResourceRoomNr(int type, int idx);
+ virtual uint32 getResourceRoomOffset(int type, int idx);
int getResourceSize(int type, int idx);
public:
@@ -816,7 +802,6 @@ public:
virtual byte *getStringAddress(int i);
byte *getStringAddressVar(int i);
void ensureResourceLoaded(int type, int i);
- int getResourceRoomNr(int type, int index);
protected:
int readSoundResource(int index);
@@ -972,8 +957,6 @@ public:
// Generic costume code
bool isCostumeInUse(int i) const;
- Common::Rect _actorClipOverride; // HE specific
-
protected:
/* Should be in Graphics class? */
uint16 _screenB, _screenH;
diff --git a/engines/scumm/scumm_v3.h b/engines/scumm/scumm_v3.h
index abe75cd64d..6e8d593a35 100644
--- a/engines/scumm/scumm_v3.h
+++ b/engines/scumm/scumm_v3.h
@@ -62,7 +62,7 @@ public:
ScummEngine_v3old(OSystem *syst, const DetectorResult &dr);
protected:
- virtual void readResTypeList(int id);
+ virtual int readResTypeList(int id);
virtual void readIndexFile();
virtual void setupRoomSubBlocks();
virtual void resetRoomSubBlocks();
diff --git a/engines/scumm/scumm_v4.h b/engines/scumm/scumm_v4.h
index be3f6cb47e..653cfc228e 100644
--- a/engines/scumm/scumm_v4.h
+++ b/engines/scumm/scumm_v4.h
@@ -59,7 +59,7 @@ protected:
virtual void scummLoop_handleSaveLoad();
- virtual void readResTypeList(int id);
+ virtual int readResTypeList(int id);
virtual void readIndexFile();
virtual void loadCharset(int no);
virtual void resetRoomObjects();
diff --git a/engines/scumm/smush/channel.cpp b/engines/scumm/smush/channel.cpp
index 4389890994..95b7653262 100644
--- a/engines/scumm/smush/channel.cpp
+++ b/engines/scumm/smush/channel.cpp
@@ -24,6 +24,8 @@
*/
+#include "common/textconsole.h"
+
#include "scumm/smush/channel.h"
namespace Scumm {
diff --git a/engines/scumm/smush/channel.h b/engines/scumm/smush/channel.h
index c35ac0ac00..717a294d96 100644
--- a/engines/scumm/smush/channel.h
+++ b/engines/scumm/smush/channel.h
@@ -29,7 +29,7 @@
#include "common/util.h"
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Scumm {
diff --git a/engines/scumm/smush/codec37.cpp b/engines/scumm/smush/codec37.cpp
index 658d67c1b4..9dbbc6816f 100644
--- a/engines/scumm/smush/codec37.cpp
+++ b/engines/scumm/smush/codec37.cpp
@@ -25,6 +25,7 @@
#include "common/endian.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "scumm/bomp.h"
#include "scumm/smush/codec37.h"
diff --git a/engines/scumm/smush/codec47.cpp b/engines/scumm/smush/codec47.cpp
index 333fdabccf..47286ba4fc 100644
--- a/engines/scumm/smush/codec47.cpp
+++ b/engines/scumm/smush/codec47.cpp
@@ -25,6 +25,7 @@
#include "common/endian.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "scumm/bomp.h"
#include "scumm/smush/codec47.h"
@@ -342,11 +343,9 @@ void Codec47Decoder::makeTables47(int width) {
#ifdef USE_ARM_SMUSH_ASM
-extern "C" {
#ifndef IPHONE
#define ARM_Smush_decode2 _ARM_Smush_decode2
#endif
-}
extern "C" void ARM_Smush_decode2( byte *dst,
const byte *src,
diff --git a/engines/scumm/smush/imuse_channel.cpp b/engines/scumm/smush/imuse_channel.cpp
index a838fdba56..32fa99a870 100644
--- a/engines/scumm/smush/imuse_channel.cpp
+++ b/engines/scumm/smush/imuse_channel.cpp
@@ -29,6 +29,7 @@
#include "scumm/scumm.h" // For DEBUG_SMUSH
#include "scumm/util.h"
#include "scumm/smush/channel.h"
+#include "scumm/imuse_digi/dimuse_codecs.h" // for decode12BitsSample
namespace Scumm {
@@ -64,7 +65,7 @@ bool ImuseChannel::appendData(Common::SeekableReadStream &b, int32 size) {
assert(size > 8);
uint32 imus_type = b.readUint32BE();
/*uint32 imus_size =*/ b.readUint32BE();
- if (imus_type != MKID_BE('iMUS'))
+ if (imus_type != MKTAG('i','M','U','S'))
error("Invalid Chunk for imuse_channel");
size -= 8;
_tbufferSize = size;
@@ -115,7 +116,7 @@ bool ImuseChannel::handleMap(byte *data) {
size -= 8;
switch (subType) {
- case MKID_BE('FRMT'):
+ case MKTAG('F','R','M','T'):
if (subSize != 20)
error("invalid size for FRMT Chunk");
//uint32 imuse_start = READ_BE_UINT32(data);
@@ -125,14 +126,14 @@ bool ImuseChannel::handleMap(byte *data) {
_channels = READ_BE_UINT32(data+16);
assert(_channels == 1 || _channels == 2);
break;
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
// Ignore this
break;
- case MKID_BE('REGN'):
+ case MKTAG('R','E','G','N'):
if (subSize != 8)
error("invalid size for REGN Chunk");
break;
- case MKID_BE('STOP'):
+ case MKTAG('S','T','O','P'):
if (subSize != 4)
error("invalid size for STOP Chunk");
break;
@@ -171,28 +172,10 @@ void ImuseChannel::decode() {
}
}
- // FIXME: Code duplication! See decode12BitsSample() in imuse_digi/dimuse_codecs.cpp
-
- int loop_size = _sbufferSize / 3;
- int new_size = loop_size * 4;
- byte *keep, *decoded;
- uint32 value;
- keep = decoded = (byte *)malloc(new_size);
- assert(keep);
- unsigned char * source = _sbuffer;
-
- while (loop_size--) {
- byte v1 = *source++;
- byte v2 = *source++;
- byte v3 = *source++;
- value = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000;
- WRITE_BE_UINT16(decoded, value); decoded += 2;
- value = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000;
- WRITE_BE_UINT16(decoded, value); decoded += 2;
- }
+ byte *keep;
+ _sbufferSize = BundleCodecs::decode12BitsSample(_sbuffer, &keep, _sbufferSize);
free(_sbuffer);
_sbuffer = (byte *)keep;
- _sbufferSize = new_size;
}
bool ImuseChannel::handleSubTags(int32 &offset) {
@@ -201,13 +184,13 @@ bool ImuseChannel::handleSubTags(int32 &offset) {
uint32 size = READ_BE_UINT32(_tbuffer + offset + 4);
uint32 available_size = _tbufferSize - offset;
switch (type) {
- case MKID_BE('MAP '):
+ case MKTAG('M','A','P',' '):
_inData = false;
if (available_size >= (size + 8)) {
handleMap((byte *)_tbuffer + offset);
}
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
_inData = true;
_dataSize = size;
offset += 8;
diff --git a/engines/scumm/smush/saud_channel.cpp b/engines/scumm/smush/saud_channel.cpp
index 94df70633f..f730acf804 100644
--- a/engines/scumm/smush/saud_channel.cpp
+++ b/engines/scumm/smush/saud_channel.cpp
@@ -26,6 +26,7 @@
#include "common/endian.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "scumm/util.h"
#include "scumm/smush/channel.h"
@@ -50,7 +51,7 @@ bool SaudChannel::handleSubTags(int32 &offset) {
uint32 available_size = _tbufferSize - offset;
switch (type) {
- case MKID_BE('STRK'):
+ case MKTAG('S','T','R','K'):
_inData = false;
if (available_size >= (size + 8)) {
int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4);
@@ -60,14 +61,14 @@ bool SaudChannel::handleSubTags(int32 &offset) {
} else
return false;
break;
- case MKID_BE('SMRK'):
+ case MKTAG('S','M','R','K'):
_inData = false;
if (available_size >= (size + 8))
_markReached = true;
else
return false;
break;
- case MKID_BE('SHDR'):
+ case MKTAG('S','H','D','R'):
_inData = false;
if (available_size >= (size + 8)) {
int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4);
@@ -76,7 +77,7 @@ bool SaudChannel::handleSubTags(int32 &offset) {
} else
return false;
break;
- case MKID_BE('SDAT'):
+ case MKTAG('S','D','A','T'):
_inData = true;
_dataSize = size;
offset += 8;
@@ -123,7 +124,7 @@ bool SaudChannel::appendData(Common::SeekableReadStream &b, int32 size) {
assert(size > 8);
uint32 saud_type = b.readUint32BE();
/*uint32 saud_size =*/ b.readUint32BE();
- if (saud_type != MKID_BE('SAUD'))
+ if (saud_type != MKTAG('S','A','U','D'))
error("Invalid Chunk for SaudChannel : %X", saud_type);
size -= 8;
_dataSize = -2;
diff --git a/engines/scumm/smush/smush_mixer.h b/engines/scumm/smush/smush_mixer.h
index c7a7354511..3d62fdc722 100644
--- a/engines/scumm/smush/smush_mixer.h
+++ b/engines/scumm/smush/smush_mixer.h
@@ -27,6 +27,8 @@
#define SCUMM_SMUSH_MIXER_H
+#include "audio/mixer.h"
+#include "common/mutex.h"
#include "scumm/sound.h"
namespace Scumm {
diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp
index fe2b9d99ff..2e39558372 100644
--- a/engines/scumm/smush/smush_player.cpp
+++ b/engines/scumm/smush/smush_player.cpp
@@ -31,6 +31,7 @@
#include "common/util.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
#include "scumm/bomp.h"
#include "scumm/file.h"
@@ -190,7 +191,7 @@ static StringResource *getStrings(ScummEngine *vm, const char *file, bool is_enc
theFile.read(filebuffer, length);
filebuffer[length] = 0;
- if (is_encoded && READ_BE_UINT32(filebuffer) == MKID_BE('ETRS')) {
+ if (is_encoded && READ_BE_UINT32(filebuffer) == MKTAG('E','T','R','S')) {
assert(length > ETRS_HEADER_LENGTH);
length -= ETRS_HEADER_LENGTH;
for (int i = 0; i < length; ++i) {
@@ -507,7 +508,7 @@ void SmushPlayer::handleTextResource(uint32 subType, int32 subSize, Common::Seek
const char *str;
char *string = NULL, *string2 = NULL;
- if (subType == MKID_BE('TEXT')) {
+ if (subType == MKTAG('T','E','X','T')) {
string = (char *)malloc(subSize - 16);
str = string;
b.read(string, subSize - 16);
@@ -845,40 +846,40 @@ void SmushPlayer::handleFrame(int32 frameSize, Common::SeekableReadStream &b) {
const int32 subSize = b.readUint32BE();
const int32 subOffset = b.pos();
switch (subType) {
- case MKID_BE('NPAL'):
+ case MKTAG('N','P','A','L'):
handleNewPalette(subSize, b);
break;
- case MKID_BE('FOBJ'):
+ case MKTAG('F','O','B','J'):
handleFrameObject(subSize, b);
break;
#ifdef USE_ZLIB
- case MKID_BE('ZFOB'):
+ case MKTAG('Z','F','O','B'):
handleZlibFrameObject(subSize, b);
break;
#endif
- case MKID_BE('PSAD'):
+ case MKTAG('P','S','A','D'):
if (!_compressedFileMode)
handleSoundFrame(subSize, b);
break;
- case MKID_BE('TRES'):
+ case MKTAG('T','R','E','S'):
handleTextResource(subType, subSize, b);
break;
- case MKID_BE('XPAL'):
+ case MKTAG('X','P','A','L'):
handleDeltaPalette(subSize, b);
break;
- case MKID_BE('IACT'):
+ case MKTAG('I','A','C','T'):
handleIACT(subSize, b);
break;
- case MKID_BE('STOR'):
+ case MKTAG('S','T','O','R'):
handleStore(subSize, b);
break;
- case MKID_BE('FTCH'):
+ case MKTAG('F','T','C','H'):
handleFetch(subSize, b);
break;
- case MKID_BE('SKIP'):
+ case MKTAG('S','K','I','P'):
_vm->_insane->procSKIP(subSize, b);
break;
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
handleTextResource(subType, subSize, b);
break;
default:
@@ -990,7 +991,7 @@ void SmushPlayer::parseNextFrame() {
const uint32 subType = _base->readUint32BE();
const int32 subSize = _base->readUint32BE();
const int32 subOffset = _base->pos();
- assert(subType == MKID_BE('AHDR'));
+ assert(subType == MKTAG('A','H','D','R'));
handleAnimHeader(subSize, *_base);
_base->seek(subOffset + subSize, SEEK_SET);
@@ -1029,10 +1030,10 @@ void SmushPlayer::parseNextFrame() {
debug(3, "Chunk: %s at %x", tag2str(subType), subOffset);
switch (subType) {
- case MKID_BE('AHDR'): // FT INSANE may seek file to the beginning
+ case MKTAG('A','H','D','R'): // FT INSANE may seek file to the beginning
handleAnimHeader(subSize, *_base);
break;
- case MKID_BE('FRME'):
+ case MKTAG('F','R','M','E'):
handleFrame(subSize, *_base);
break;
default:
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index cff1618c18..a38119584f 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -195,8 +195,7 @@ void Sound::playSound(int soundID) {
return;
}
- debugC(DEBUG_SOUND, "playSound #%d (room %d)", soundID,
- _vm->getResourceRoomNr(rtSound, soundID));
+ debugC(DEBUG_SOUND, "playSound #%d", soundID);
ptr = _vm->getResourceAddress(rtSound, soundID);
@@ -207,7 +206,7 @@ void Sound::playSound(int soundID) {
// Support for SFX in Monkey Island 1, Mac version
// This is rather hackish right now, but works OK. SFX are not sounding
// 100% correct, though, not sure right now what is causing this.
- else if (READ_BE_UINT32(ptr) == MKID_BE('Mac1')) {
+ else if (READ_BE_UINT32(ptr) == MKTAG('M','a','c','1')) {
// Read info from the header
size = READ_BE_UINT32(ptr+0x60);
rate = READ_BE_UINT16(ptr+0x64);
@@ -246,7 +245,7 @@ void Sound::playSound(int soundID) {
_mixer->playStream(Audio::Mixer::kSFXSoundType, NULL, stream, soundID);
}
// Support for sampled sound effects in Monkey Island 1 and 2
- else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKID_BE('SBL ')) {
+ else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) {
debugC(DEBUG_SOUND, "Using SBL sound effect");
// SBL resources essentially contain VOC sound data.
@@ -317,7 +316,7 @@ void Sound::playSound(int soundID) {
stream = Audio::makeRawStream(sound, size, rate, Audio::FLAG_UNSIGNED);
_mixer->playStream(Audio::Mixer::kSFXSoundType, NULL, stream, soundID);
}
- else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKID_BE('SOUN')) {
+ else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKTAG('S','O','U','N')) {
if (_vm->_game.version != 3)
ptr += 2;
@@ -416,7 +415,7 @@ void Sound::playSound(int soundID) {
// Rather it seems that starting a new music is supposed to
// automatically stop the old song.
if (_vm->_imuse) {
- if (READ_BE_UINT32(ptr) != MKID_BE('ASFX'))
+ if (READ_BE_UINT32(ptr) != MKTAG('A','S','F','X'))
_vm->_imuse->stopAllSounds();
}
}
@@ -528,6 +527,10 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
sprintf(filename, "audio/%s.%d/%d.voc", roomname, offset, b);
_vm->openFile(*_sfxFile, filename);
if (!_sfxFile->isOpen()) {
+ sprintf(filename, "audio/%s_%d/%d.voc", roomname, offset, b);
+ _vm->openFile(*_sfxFile, filename);
+ }
+ if (!_sfxFile->isOpen()) {
sprintf(filename, "%d.%d.voc", offset, b);
_vm->openFile(*_sfxFile, filename);
}
@@ -1091,15 +1094,15 @@ int ScummEngine::readSoundResource(int idx) {
debugC(DEBUG_RESOURCE, " basetag: %s, total_size=%d", tag2str(basetag), total_size);
switch (basetag) {
- case MKID_BE('MIDI'):
- case MKID_BE('iMUS'):
+ case MKTAG('M','I','D','I'):
+ case MKTAG('i','M','U','S'):
if (_musicType != MDT_PCSPK && _musicType != MDT_PCJR) {
_fileHandle->seek(-8, SEEK_CUR);
_fileHandle->read(_res->createResource(rtSound, idx, total_size + 8), total_size + 8);
return 1;
}
break;
- case MKID_BE('SOU '):
+ case MKTAG('S','O','U',' '):
best_pri = -1;
while (pos < total_size) {
tag = _fileHandle->readUint32BE();
@@ -1109,32 +1112,32 @@ int ScummEngine::readSoundResource(int idx) {
pri = -1;
switch (tag) {
- case MKID_BE('TOWS'):
+ case MKTAG('T','O','W','S'):
pri = 16;
break;
- case MKID_BE('SBL '):
+ case MKTAG('S','B','L',' '):
pri = 15;
break;
- case MKID_BE('ADL '):
+ case MKTAG('A','D','L',' '):
pri = 1;
if (_musicType == MDT_ADLIB)
pri = 10;
break;
- case MKID_BE('AMI '):
+ case MKTAG('A','M','I',' '):
pri = 3;
break;
- case MKID_BE('ROL '):
+ case MKTAG('R','O','L',' '):
pri = 3;
if (_native_mt32)
pri = 5;
break;
- case MKID_BE('GMD '):
+ case MKTAG('G','M','D',' '):
pri = 4;
break;
- case MKID_BE('MAC '): // Occurs in Mac MI2, FOA
+ case MKTAG('M','A','C',' '): // Occurs in Mac MI2, FOA
pri = 2;
break;
- case MKID_BE('SPK '):
+ case MKTAG('S','P','K',' '):
pri = -1;
// if (_musicType == MDT_PCSPK || _musicType == MDT_PCJR)
// pri = 11;
@@ -1164,7 +1167,7 @@ int ScummEngine::readSoundResource(int idx) {
return 1;
}
break;
- case MKID_BE('Mac0'):
+ case MKTAG('M','a','c','0'):
_fileHandle->seek(-12, SEEK_CUR);
total_size = _fileHandle->readUint32BE() - 8;
ptr = (byte *)calloc(total_size, 1);
@@ -1174,11 +1177,11 @@ int ScummEngine::readSoundResource(int idx) {
free(ptr);
return 1;
- case MKID_BE('Mac1'):
- case MKID_BE('RIFF'):
- case MKID_BE('TALK'):
- case MKID_BE('DIGI'):
- case MKID_BE('Crea'):
+ case MKTAG('M','a','c','1'):
+ case MKTAG('R','I','F','F'):
+ case MKTAG('T','A','L','K'):
+ case MKTAG('D','I','G','I'):
+ case MKTAG('C','r','e','a'):
case 0x460e200d: // WORKAROUND bug # 1311447
_fileHandle->seek(-12, SEEK_CUR);
total_size = _fileHandle->readUint32BE();
@@ -1187,7 +1190,7 @@ int ScummEngine::readSoundResource(int idx) {
//dumpResource("sound-", idx, ptr);
return 1;
- case MKID_BE('HSHD'):
+ case MKTAG('H','S','H','D'):
// HE sound type without SOUN header
_fileHandle->seek(-16, SEEK_CUR);
total_size = max_total_size + 8;
@@ -1196,7 +1199,7 @@ int ScummEngine::readSoundResource(int idx) {
//dumpResource("sound-", idx, ptr);
return 1;
- case MKID_BE('FMUS'): {
+ case MKTAG('F','M','U','S'): {
// Used in 3DO version of puttputt joins the parade and probably others
// Specifies a separate file to be used for music from what I gather.
int tmpsize;
@@ -1223,7 +1226,7 @@ int ScummEngine::readSoundResource(int idx) {
if (!dmuFile.open(buffer)) {
error("Can't open music file %s", buffer);
- _res->roomoffs[rtSound][idx] = (uint32)RES_INVALID_OFFSET;
+ _res->roomoffs[rtSound][idx] = RES_INVALID_OFFSET;
return 0;
}
dmuFile.seek(4, SEEK_SET);
@@ -1247,7 +1250,7 @@ int ScummEngine::readSoundResource(int idx) {
}
error("Unrecognized base tag 0x%08x in sound %d", basetag, idx);
}
- _res->roomoffs[rtSound][idx] = (uint32)RES_INVALID_OFFSET;
+ _res->roomoffs[rtSound][idx] = RES_INVALID_OFFSET;
return 0;
}
@@ -1407,20 +1410,20 @@ static byte *writeVLQ(byte *ptr, int value) {
static byte Mac0ToGMInstrument(uint32 type, int &transpose) {
transpose = 0;
switch (type) {
- case MKID_BE('MARI'): return 12;
- case MKID_BE('PLUC'): return 45;
- case MKID_BE('HARM'): return 22;
- case MKID_BE('PIPE'): return 19;
- case MKID_BE('TROM'): transpose = -12; return 57;
- case MKID_BE('STRI'): return 48;
- case MKID_BE('HORN'): return 60;
- case MKID_BE('VIBE'): return 11;
- case MKID_BE('SHAK'): return 77;
- case MKID_BE('PANP'): return 75;
- case MKID_BE('WHIS'): return 76;
- case MKID_BE('ORGA'): return 17;
- case MKID_BE('BONG'): return 115;
- case MKID_BE('BASS'): transpose = -24; return 35;
+ case MKTAG('M','A','R','I'): return 12;
+ case MKTAG('P','L','U','C'): return 45;
+ case MKTAG('H','A','R','M'): return 22;
+ case MKTAG('P','I','P','E'): return 19;
+ case MKTAG('T','R','O','M'): transpose = -12; return 57;
+ case MKTAG('S','T','R','I'): return 48;
+ case MKTAG('H','O','R','N'): return 60;
+ case MKTAG('V','I','B','E'): return 11;
+ case MKTAG('S','H','A','K'): return 77;
+ case MKTAG('P','A','N','P'): return 75;
+ case MKTAG('W','H','I','S'): return 76;
+ case MKTAG('O','R','G','A'): return 17;
+ case MKTAG('B','O','N','G'): return 115;
+ case MKTAG('B','A','S','S'): transpose = -24; return 35;
default:
error("Unknown Mac0 instrument %s found", tag2str(type));
}
@@ -1505,13 +1508,13 @@ static void convertMac0Resource(ResourceManager *res, int idx, byte *src_ptr, in
// Parse the three channels
for (i = 0; i < 3; i++) {
- assert(READ_BE_UINT32(src_ptr) == MKID_BE('Chan'));
+ assert(READ_BE_UINT32(src_ptr) == MKTAG('C','h','a','n'));
len = READ_BE_UINT32(src_ptr + 4);
track_len[i] = len - 24;
track_instr[i] = Mac0ToGMInstrument(READ_BE_UINT32(src_ptr + 8), track_transpose[i]);
track_data[i] = src_ptr + 12;
src_ptr += len;
- looped = (READ_BE_UINT32(src_ptr - 8) == MKID_BE('Loop'));
+ looped = (READ_BE_UINT32(src_ptr - 8) == MKTAG('L','o','o','p'));
// For each note event, we need up to 6 bytes for the
// Note On (3 VLQ, 3 event), and 6 bytes for the Note
@@ -2122,7 +2125,7 @@ int ScummEngine::readSoundResourceSmallHeader(int idx) {
_fileHandle->read(_res->createResource(rtSound, idx, ro_size - 4), ro_size - 4);
return 1;
}
- _res->roomoffs[rtSound][idx] = (uint32)RES_INVALID_OFFSET;
+ _res->roomoffs[rtSound][idx] = RES_INVALID_OFFSET;
return 0;
}
diff --git a/engines/scumm/util.cpp b/engines/scumm/util.cpp
index ccd0230efa..5c3e4c9d0c 100644
--- a/engines/scumm/util.cpp
+++ b/engines/scumm/util.cpp
@@ -25,6 +25,7 @@
#include "scumm/util.h"
#include "common/util.h"
+#include "common/textconsole.h"
namespace Scumm {
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index e8f75dd901..6d5eb3fad7 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -1499,7 +1499,7 @@ void ScummEngine::drawVerbBitmap(int verb, int x, int y) {
}
imptr = getObjectImage(obim, 1);
} else {
- const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim);
+ const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim);
if (_game.version >= 7) {
imgw = READ_LE_UINT16(&imhd->v7.width) / 8;
imgh = READ_LE_UINT16(&imhd->v7.height) / 8;
diff --git a/engines/sky/autoroute.cpp b/engines/sky/autoroute.cpp
index dae4b94291..d6974837c6 100644
--- a/engines/sky/autoroute.cpp
+++ b/engines/sky/autoroute.cpp
@@ -25,6 +25,7 @@
#include "common/endian.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "sky/autoroute.h"
diff --git a/engines/sky/compact.cpp b/engines/sky/compact.cpp
index 78884e96dc..672fb38ca9 100644
--- a/engines/sky/compact.cpp
+++ b/engines/sky/compact.cpp
@@ -24,9 +24,10 @@
*/
+#include "common/debug.h"
#include "common/endian.h"
-#include "common/util.h"
#include "common/file.h"
+#include "common/textconsole.h"
#include "sky/compact.h"
#include "gui/message.h"
#include <stddef.h> // for ptrdiff_t
@@ -85,7 +86,7 @@ static const uint32 compactOffsets[] = {
MK16(Compact, alt),
MK16(Compact, request),
MK16(Compact, spWidth_xx),
- MK16(Compact, spColour),
+ MK16(Compact, spColor),
MK16(Compact, spTextId),
MK16(Compact, spTime),
MK16(Compact, arAnimIndex),
diff --git a/engines/sky/compact.h b/engines/sky/compact.h
index cd80d5cfbe..4861273146 100644
--- a/engines/sky/compact.h
+++ b/engines/sky/compact.h
@@ -31,7 +31,7 @@
#include "sky/skydefs.h"
namespace Common {
- class File;
+class File;
}
enum CptIds {
diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp
index 7b59fa2726..f31f0f6ba9 100644
--- a/engines/sky/control.cpp
+++ b/engines/sky/control.cpp
@@ -26,11 +26,10 @@
#include "common/endian.h"
#include "common/config-manager.h"
-#include "common/file.h"
#include "common/events.h"
#include "common/system.h"
#include "common/savefile.h"
-#include "common/util.h"
+#include "common/textconsole.h"
#include "gui/message.h"
#include "sky/compact.h"
@@ -115,7 +114,7 @@ void TextResource::flushForRedraw() {
}
void TextResource::drawToScreen(bool doMask) {
- doMask = true;
+ (void)doMask;
uint16 cnty, cntx, cpWidth, cpHeight;
if ((_oldX == _x) && (_oldY == _y) && (_spriteData))
return;
@@ -1275,7 +1274,7 @@ void Control::importOldCompact(Compact* destCpt, uint8 **srcPos, uint16 numElems
LODSW(*srcPos, destCpt->alt);
LODSW(*srcPos, destCpt->request);
LODSW(*srcPos, destCpt->spWidth_xx);
- LODSW(*srcPos, destCpt->spColour);
+ LODSW(*srcPos, destCpt->spColor);
LODSW(*srcPos, destCpt->spTextId);
LODSW(*srcPos, destCpt->spTime);
LODSW(*srcPos, destCpt->arAnimIndex);
diff --git a/engines/sky/control.h b/engines/sky/control.h
index a0024ce73b..e4428c1876 100644
--- a/engines/sky/control.h
+++ b/engines/sky/control.h
@@ -33,7 +33,7 @@
class OSystem;
namespace Common {
- class SaveFileManager;
+class SaveFileManager;
}
namespace Sky {
diff --git a/engines/sky/debug.cpp b/engines/sky/debug.cpp
index 2839665ff8..df55966a9a 100644
--- a/engines/sky/debug.cpp
+++ b/engines/sky/debug.cpp
@@ -24,7 +24,7 @@
*/
-#include "common/endian.h"
+#include "common/debug.h"
#include "common/util.h"
#include "sky/debug.h"
diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp
index e72875fa4e..6871fc9604 100644
--- a/engines/sky/detection.cpp
+++ b/engines/sky/detection.cpp
@@ -34,6 +34,7 @@
#include "common/file.h"
#include "common/fs.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "engines/metaengine.h"
diff --git a/engines/sky/disk.cpp b/engines/sky/disk.cpp
index 5ad0c3eb19..3795c4166d 100644
--- a/engines/sky/disk.cpp
+++ b/engines/sky/disk.cpp
@@ -24,12 +24,12 @@
*/
+#include "common/debug.h"
+#include "common/textconsole.h"
#include "common/endian.h"
#include "common/file.h"
-#include "common/util.h"
#include "sky/disk.h"
-#include "sky/rnc_deco.h"
#include "sky/sky.h"
#include "sky/struc.h"
diff --git a/engines/sky/disk.h b/engines/sky/disk.h
index 3338cce385..0cdcbb4d0f 100644
--- a/engines/sky/disk.h
+++ b/engines/sky/disk.h
@@ -28,13 +28,12 @@
#include "common/scummsys.h"
-#include "common/str.h"
#include "sky/rnc_deco.h"
#define MAX_FILES_IN_LIST 60
namespace Common {
- class File;
+class File;
}
namespace Sky {
diff --git a/engines/sky/intro.cpp b/engines/sky/intro.cpp
index cf1910c5b1..506a6699c1 100644
--- a/engines/sky/intro.cpp
+++ b/engines/sky/intro.cpp
@@ -28,6 +28,7 @@
#include "common/util.h"
#include "common/events.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "sky/disk.h"
#include "sky/intro.h"
diff --git a/engines/sky/logic.cpp b/engines/sky/logic.cpp
index 1c1e2c9682..f9ebd0fb64 100644
--- a/engines/sky/logic.cpp
+++ b/engines/sky/logic.cpp
@@ -25,9 +25,8 @@
#include "common/endian.h"
#include "common/rect.h"
-#include "common/events.h"
#include "common/EventRecorder.h"
-#include "common/system.h"
+#include "common/textconsole.h"
#include "sky/autoroute.h"
#include "sky/compact.h"
@@ -1823,7 +1822,7 @@ bool Logic::fnHighlight(uint32 itemNo, uint32 pen, uint32 c) {
pen += 241;
Compact *textCompact = _skyCompact->fetchCpt(itemNo);
uint8 *sprData = (uint8 *)SkyEngine::fetchItem(textCompact->flag);
- _skyText->changeTextSpriteColour(sprData, (uint8)pen);
+ _skyText->changeTextSpriteColor(sprData, (uint8)pen);
return true;
}
@@ -2547,7 +2546,7 @@ void Logic::stdSpeak(Compact *target, uint32 textNum, uint32 animNum, uint32 bas
// form the text sprite, if player wants subtitles or
// if we couldn't find the speech file
DisplayedText textInfo;
- textInfo = _skyText->lowTextManager(textNum, FIXED_TEXT_WIDTH, 0, (uint8)target->spColour, true);
+ textInfo = _skyText->lowTextManager(textNum, FIXED_TEXT_WIDTH, 0, (uint8)target->spColor, true);
Compact *textCompact = _skyCompact->fetchCpt(textInfo.compactNum);
target->spTextId = textInfo.compactNum; //So we know what text to kill
byte *textGfx = textInfo.textData;
diff --git a/engines/sky/mouse.cpp b/engines/sky/mouse.cpp
index ca0ebcc19c..611010fa46 100644
--- a/engines/sky/mouse.cpp
+++ b/engines/sky/mouse.cpp
@@ -26,6 +26,7 @@
#include "common/events.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
#include "sky/disk.h"
#include "sky/logic.h"
diff --git a/engines/sky/music/adlibchannel.cpp b/engines/sky/music/adlibchannel.cpp
index e9c20de8c7..9b3c4338ab 100644
--- a/engines/sky/music/adlibchannel.cpp
+++ b/engines/sky/music/adlibchannel.cpp
@@ -25,6 +25,7 @@
#include "common/endian.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "sky/music/adlibchannel.h"
#include "sky/sky.h"
diff --git a/engines/sky/music/gmchannel.cpp b/engines/sky/music/gmchannel.cpp
index 3852a69068..be0afa8894 100644
--- a/engines/sky/music/gmchannel.cpp
+++ b/engines/sky/music/gmchannel.cpp
@@ -25,6 +25,7 @@
#include "gmchannel.h"
#include "common/util.h"
+#include "common/textconsole.h"
#include "audio/mididrv.h"
namespace Sky {
diff --git a/engines/sky/music/gmmusic.cpp b/engines/sky/music/gmmusic.cpp
index 22964f3f56..6a8529f287 100644
--- a/engines/sky/music/gmmusic.cpp
+++ b/engines/sky/music/gmmusic.cpp
@@ -28,6 +28,7 @@
#include "sky/sky.h"
#include "common/util.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "audio/mididrv.h"
namespace Sky {
@@ -53,8 +54,8 @@ GmMusic::~GmMusic() {
stopMusic();
// Send All Sound Off and All Notes Off (for external synths)
for (int i = 0; i < 16; i++) {
- _midiDrv->send ((120 << 8) | 0xB0 | i);
- _midiDrv->send ((123 << 8) | 0xB0 | i);
+ _midiDrv->send((120 << 8) | 0xB0 | i);
+ _midiDrv->send((123 << 8) | 0xB0 | i);
}
_midiDrv->close();
delete _midiDrv;
diff --git a/engines/sky/music/mt32music.cpp b/engines/sky/music/mt32music.cpp
index 51df95e451..4f47e511c7 100644
--- a/engines/sky/music/mt32music.cpp
+++ b/engines/sky/music/mt32music.cpp
@@ -28,6 +28,7 @@
#include "common/util.h"
#include "common/system.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "audio/mididrv.h"
namespace Sky {
diff --git a/engines/sky/music/musicbase.cpp b/engines/sky/music/musicbase.cpp
index 0d3cb65e1b..748637f9d0 100644
--- a/engines/sky/music/musicbase.cpp
+++ b/engines/sky/music/musicbase.cpp
@@ -27,6 +27,7 @@
#include "sky/disk.h"
#include "common/util.h"
#include "common/endian.h"
+#include "common/textconsole.h"
namespace Sky {
@@ -44,7 +45,7 @@ MusicBase::~MusicBase() {
}
void MusicBase::loadSection(uint8 pSection) {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
if (_currentMusic)
stopMusicInternal();
free(_musicData);
@@ -58,7 +59,6 @@ void MusicBase::loadSection(uint8 pSection) {
_numberOfChannels = _currentMusic = 0;
setupPointers();
startDriver();
- _mutex.unlock();
}
bool MusicBase::musicIsPlaying() {
@@ -69,9 +69,8 @@ bool MusicBase::musicIsPlaying() {
}
void MusicBase::stopMusic() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
stopMusicInternal();
- _mutex.unlock();
}
void MusicBase::stopMusicInternal() {
@@ -113,7 +112,7 @@ void MusicBase::loadNewMusic() {
}
void MusicBase::pollMusic() {
- _mutex.lock();
+ Common::StackLock lock(_mutex);
uint8 newTempo;
if (_onNextPoll.musicToProcess != _currentMusic)
loadNewMusic();
@@ -127,7 +126,6 @@ void MusicBase::pollMusic() {
updateTempo();
}
}
- _mutex.unlock();
_aktTime &= 0xFFFF;
}
diff --git a/engines/sky/screen.cpp b/engines/sky/screen.cpp
index a77017de38..a209571b37 100644
--- a/engines/sky/screen.cpp
+++ b/engines/sky/screen.cpp
@@ -27,6 +27,9 @@
#include "common/endian.h"
#include "common/events.h"
#include "common/system.h"
+#include "common/textconsole.h"
+
+#include "graphics/palette.h"
#include "sky/disk.h"
#include "sky/logic.h"
@@ -38,7 +41,7 @@
namespace Sky {
-uint8 Screen::_top16Colours[16*3] = {
+uint8 Screen::_top16Colors[16*3] = {
0, 0, 0,
38, 38, 38,
63, 63, 63,
@@ -63,7 +66,7 @@ Screen::Screen(OSystem *pSystem, Disk *pDisk, SkyCompact *skyCompact) {
_skyCompact = skyCompact;
int i;
- uint8 tmpPal[VGA_COLOURS * 3];
+ uint8 tmpPal[VGA_COLORS * 3];
_gameGrid = (uint8 *)malloc(GRID_X * GRID_Y * 2);
forceRefresh();
@@ -72,17 +75,17 @@ Screen::Screen(OSystem *pSystem, Disk *pDisk, SkyCompact *skyCompact) {
_scrollScreen = NULL;
//blank the first 240 colors of the palette
- memset(tmpPal, 0, GAME_COLOURS * 3);
+ memset(tmpPal, 0, GAME_COLORS * 3);
//set the remaining colors
- for (i = 0; i < (VGA_COLOURS-GAME_COLOURS); i++) {
- tmpPal[3 * GAME_COLOURS + i * 3 + 0] = (_top16Colours[i * 3 + 0] << 2) + (_top16Colours[i * 3 + 0] >> 4);
- tmpPal[3 * GAME_COLOURS + i * 3 + 1] = (_top16Colours[i * 3 + 1] << 2) + (_top16Colours[i * 3 + 1] >> 4);
- tmpPal[3 * GAME_COLOURS + i * 3 + 2] = (_top16Colours[i * 3 + 2] << 2) + (_top16Colours[i * 3 + 2] >> 4);
+ for (i = 0; i < (VGA_COLORS-GAME_COLORS); i++) {
+ tmpPal[3 * GAME_COLORS + i * 3 + 0] = (_top16Colors[i * 3 + 0] << 2) + (_top16Colors[i * 3 + 0] >> 4);
+ tmpPal[3 * GAME_COLORS + i * 3 + 1] = (_top16Colors[i * 3 + 1] << 2) + (_top16Colors[i * 3 + 1] >> 4);
+ tmpPal[3 * GAME_COLORS + i * 3 + 2] = (_top16Colors[i * 3 + 2] << 2) + (_top16Colors[i * 3 + 2] >> 4);
}
//set the palette
- _system->getPaletteManager()->setPalette(tmpPal, 0, VGA_COLOURS);
+ _system->getPaletteManager()->setPalette(tmpPal, 0, VGA_COLORS);
_currentPalette = 0;
_seqInfo.nextFrame = _seqInfo.framesLeft = 0;
@@ -109,32 +112,32 @@ void Screen::setFocusRectangle(const Common::Rect& rect) {
//set a new palette, pal is a pointer to dos vga rgb components 0..63
void Screen::setPalette(uint8 *pal) {
convertPalette(pal, _palette);
- _system->getPaletteManager()->setPalette(_palette, 0, GAME_COLOURS);
+ _system->getPaletteManager()->setPalette(_palette, 0, GAME_COLORS);
_system->updateScreen();
}
void Screen::setPaletteEndian(uint8 *pal) {
#ifdef SCUMM_BIG_ENDIAN
- uint8 endPalette[VGA_COLOURS * 3];
- for (uint16 cnt = 0; cnt < VGA_COLOURS * 3; cnt++)
+ uint8 endPalette[VGA_COLORS * 3];
+ for (uint16 cnt = 0; cnt < VGA_COLORS * 3; cnt++)
endPalette[cnt] = pal[cnt ^ 1];
convertPalette(endPalette, _palette);
#else
convertPalette(pal, _palette);
#endif
- _system->getPaletteManager()->setPalette(_palette, 0, GAME_COLOURS);
+ _system->getPaletteManager()->setPalette(_palette, 0, GAME_COLORS);
_system->updateScreen();
}
void Screen::halvePalette() {
- uint8 halfPalette[VGA_COLOURS * 3];
+ uint8 halfPalette[VGA_COLORS * 3];
- for (uint8 cnt = 0; cnt < GAME_COLOURS; cnt++) {
+ for (uint8 cnt = 0; cnt < GAME_COLORS; cnt++) {
halfPalette[cnt * 3 + 0] = _palette[cnt * 3 + 0] >> 1;
halfPalette[cnt * 3 + 1] = _palette[cnt * 3 + 1] >> 1;
halfPalette[cnt * 3 + 2] = _palette[cnt * 3 + 2] >> 1;
}
- _system->getPaletteManager()->setPalette(halfPalette, 0, GAME_COLOURS);
+ _system->getPaletteManager()->setPalette(halfPalette, 0, GAME_COLORS);
}
void Screen::setPalette(uint16 fileNum) {
@@ -168,7 +171,7 @@ void Screen::showScreen(uint8 *pScreen) {
void Screen::convertPalette(uint8 *inPal, uint8* outPal) {
int i;
- for (i = 0; i < VGA_COLOURS; i++) {
+ for (i = 0; i < VGA_COLORS; i++) {
outPal[3 * i + 0] = (inPal[3 * i + 0] << 2) + (inPal[3 * i + 0] >> 4);
outPal[3 * i + 1] = (inPal[3 * i + 1] << 2) + (inPal[3 * i + 1] >> 4);
outPal[3 * i + 2] = (inPal[3 * i + 2] << 2) + (inPal[3 * i + 2] >> 4);
@@ -247,8 +250,8 @@ void Screen::fnFadeDown(uint32 scroll) {
uint32 delayTime = _system->getMillis();
for (uint8 cnt = 0; cnt < 32; cnt++) {
delayTime += 20;
- palette_fadedown_helper(_palette, GAME_COLOURS);
- _system->getPaletteManager()->setPalette(_palette, 0, GAME_COLOURS);
+ palette_fadedown_helper(_palette, GAME_COLORS);
+ _system->getPaletteManager()->setPalette(_palette, 0, GAME_COLORS);
_system->updateScreen();
int32 waitTime = (int32)delayTime - _system->getMillis();
if (waitTime < 0)
@@ -296,7 +299,7 @@ void Screen::paletteFadeUp(uint16 fileNr) {
}
void Screen::paletteFadeUp(uint8 *pal) {
- byte tmpPal[VGA_COLOURS * 3];
+ byte tmpPal[VGA_COLORS * 3];
convertPalette(pal, tmpPal);
@@ -304,13 +307,13 @@ void Screen::paletteFadeUp(uint8 *pal) {
for (uint8 cnt = 1; cnt <= 32; cnt++) {
delayTime += 20;
- for (uint8 colCnt = 0; colCnt < GAME_COLOURS; colCnt++) {
+ for (uint8 colCnt = 0; colCnt < GAME_COLORS; colCnt++) {
_palette[colCnt * 3 + 0] = (tmpPal[colCnt * 3 + 0] * cnt) >> 5;
_palette[colCnt * 3 + 1] = (tmpPal[colCnt * 3 + 1] * cnt) >> 5;
_palette[colCnt * 3 + 2] = (tmpPal[colCnt * 3 + 2] * cnt) >> 5;
}
- _system->getPaletteManager()->setPalette(_palette, 0, GAME_COLOURS);
+ _system->getPaletteManager()->setPalette(_palette, 0, GAME_COLORS);
_system->updateScreen();
int32 waitTime = (int32)delayTime - _system->getMillis();
@@ -331,8 +334,8 @@ void Screen::fnFadeUp(uint32 palNum, uint32 scroll) {
if (palette == NULL)
error("Screen::fnFadeUp: can't fetch compact %X", palNum);
#ifdef SCUMM_BIG_ENDIAN
- byte tmpPal[VGA_COLOURS * 3];
- for (uint16 cnt = 0; cnt < VGA_COLOURS * 3; cnt++)
+ byte tmpPal[VGA_COLORS * 3];
+ for (uint16 cnt = 0; cnt < VGA_COLORS * 3; cnt++)
tmpPal[cnt] = palette[cnt ^ 1];
paletteFadeUp(tmpPal);
#else
diff --git a/engines/sky/screen.h b/engines/sky/screen.h
index 69a9a2fc8f..5e226c49ed 100644
--- a/engines/sky/screen.h
+++ b/engines/sky/screen.h
@@ -31,8 +31,9 @@
#include "sky/skydefs.h"
class OSystem;
+
namespace Common {
- struct Rect;
+struct Rect;
}
namespace Sky {
@@ -44,8 +45,8 @@ struct Compact;
struct DataFileHeader;
#define SCROLL_JUMP 16
-#define VGA_COLOURS 256
-#define GAME_COLOURS 240
+#define VGA_COLORS 256
+#define GAME_COLORS 240
#define FORE 1
#define BACK 0
@@ -100,8 +101,8 @@ private:
OSystem *_system;
Disk *_skyDisk;
SkyCompact *_skyCompact;
- static uint8 _top16Colours[16 * 3];
- uint8 _palette[VGA_COLOURS * 3];
+ static uint8 _top16Colors[16 * 3];
+ uint8 _palette[VGA_COLORS * 3];
uint32 _currentPalette;
uint8 _seqGrid[20 * 12];
diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp
index c42bb6301e..f10ec1083a 100644
--- a/engines/sky/sky.cpp
+++ b/engines/sky/sky.cpp
@@ -25,6 +25,7 @@
#include "common/config-manager.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "sky/control.h"
#include "sky/debug.h"
@@ -100,6 +101,22 @@ SkyEngine::~SkyEngine() {
free(_itemList[i]);
}
+void SkyEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ if (ConfMan.getBool("sfx_mute"))
+ SkyEngine::_systemVars.systemFlags |= SF_FX_OFF;
+
+ if (ConfMan.getBool("music_mute"))
+ SkyEngine::_systemVars.systemFlags |= SF_MUS_OFF;
+
+ _skyMusic->setVolume(mute ? 0: ConfMan.getInt("music_volume") >> 1);
+}
+
GUI::Debugger *SkyEngine::getDebugger() {
return _debugger;
}
@@ -242,16 +259,6 @@ Common::Error SkyEngine::go() {
Common::Error SkyEngine::init() {
initGraphics(320, 200, false);
- if (ConfMan.getBool("sfx_mute")) {
- SkyEngine::_systemVars.systemFlags |= SF_FX_OFF;
- }
- if (ConfMan.getBool("music_mute")) {
- SkyEngine::_systemVars.systemFlags |= SF_MUS_OFF;
- }
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
-
_skyDisk = new Disk();
_skySound = new Sound(_mixer, _skyDisk, Audio::Mixer::kMaxChannelVolume);
@@ -346,7 +353,8 @@ Common::Error SkyEngine::init() {
}
}
- _skyMusic->setVolume(ConfMan.getInt("music_volume") >> 1);
+ // Setup mixer
+ syncSoundSettings();
_debugger = new Debugger(_skyLogic, _skyMouse, _skyScreen, _skyCompact);
return Common::kNoError;
diff --git a/engines/sky/sky.h b/engines/sky/sky.h
index 29e7c9ab42..58ac3ed26e 100644
--- a/engines/sky/sky.h
+++ b/engines/sky/sky.h
@@ -27,7 +27,8 @@
#define SKY_H
-#include "common/events.h"
+#include "common/error.h"
+#include "common/keyboard.h"
#include "engines/engine.h"
/**
@@ -52,7 +53,6 @@ struct SystemVars {
bool paused;
};
-struct Compact;
class Sound;
class Disk;
class Text;
@@ -84,6 +84,8 @@ public:
SkyEngine(OSystem *syst);
virtual ~SkyEngine();
+ virtual void syncSoundSettings();
+
static bool isDemo();
static bool isCDVersion();
@@ -104,7 +106,7 @@ protected:
virtual Common::Error run() {
Common::Error err;
err = init();
- if (err != Common::kNoError)
+ if (err.getCode() != Common::kNoError)
return err;
return go();
}
diff --git a/engines/sky/skydefs.h b/engines/sky/skydefs.h
index f68c0f826b..e3f3f3101f 100644
--- a/engines/sky/skydefs.h
+++ b/engines/sky/skydefs.h
@@ -92,7 +92,7 @@ namespace Sky {
#define C_BASE_MODE 0
#define C_BASE_MODE56 56
#define C_ACTION_MODE 4
-#define C_SP_COLOUR 90
+#define C_SP_COLOR 90
#define C_MEGA_SET 112
#define C_GRID_WIDTH 114
#define C_ANIM_UP 122
@@ -141,7 +141,7 @@ namespace Sky {
#define L_WAIT_SYNC 15
#define L_SIMPLE_MOD 16
-// characters with own colour set
+// characters with own color set
#define SP_COL_FOSTER 194
#define SP_COL_JOEY 216
#define SP_COL_JOBS 209
diff --git a/engines/sky/sound.cpp b/engines/sky/sound.cpp
index 3d247ed334..7191f6cd00 100644
--- a/engines/sky/sound.cpp
+++ b/engines/sky/sound.cpp
@@ -24,7 +24,9 @@
*/
+#include "common/debug.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "sky/disk.h"
#include "sky/logic.h"
diff --git a/engines/sky/struc.h b/engines/sky/struc.h
index 295e31d9b0..987f074ed1 100644
--- a/engines/sky/struc.h
+++ b/engines/sky/struc.h
@@ -37,9 +37,9 @@ struct DisplayedText {
#include "common/pack-start.h" // START STRUCT PACKING
struct DataFileHeader {
- uint16 flag; // bit 0: set for colour data, clear for not
+ uint16 flag; // bit 0: set for color data, clear for not
// bit 1: set for compressed, clear for uncompressed
- // bit 2: set for 32 colours, clear for 16 colours
+ // bit 2: set for 32 colors, clear for 16 colors
uint16 s_x;
uint16 s_y;
uint16 s_width;
@@ -139,7 +139,7 @@ struct Compact {
uint16 request; // 42
uint16 spWidth_xx; // 43
- uint16 spColour; // 44
+ uint16 spColor; // 44
uint16 spTextId; // 45
uint16 spTime; // 46
diff --git a/engines/sky/text.cpp b/engines/sky/text.cpp
index 73c376dbbe..2464d93581 100644
--- a/engines/sky/text.cpp
+++ b/engines/sky/text.cpp
@@ -24,7 +24,9 @@
*/
+#include "common/debug.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "sky/disk.h"
#include "sky/logic.h"
@@ -231,13 +233,13 @@ char Text::getTextChar(uint8 **data, uint32 *bitPos) {
}
}
-DisplayedText Text::displayText(uint32 textNum, uint8 *dest, bool centre, uint16 pixelWidth, uint8 color) {
+DisplayedText Text::displayText(uint32 textNum, uint8 *dest, bool center, uint16 pixelWidth, uint8 color) {
//Render text into buffer *dest
getText(textNum);
- return displayText(_textBuffer, dest, centre, pixelWidth, color);
+ return displayText(_textBuffer, dest, center, pixelWidth, color);
}
-DisplayedText Text::displayText(char *textPtr, uint8 *dest, bool centre, uint16 pixelWidth, uint8 color) {
+DisplayedText Text::displayText(char *textPtr, uint8 *dest, bool center, uint16 pixelWidth, uint8 color) {
//Render text pointed to by *textPtr in buffer *dest
uint32 centerTable[10];
uint16 lineWidth = 0;
@@ -319,7 +321,7 @@ DisplayedText Text::displayText(char *textPtr, uint8 *dest, bool centre, uint16
uint32 *centerTblPtr = centerTable;
do {
- if (centre) {
+ if (center) {
uint32 width = (pixelWidth - *centerTblPtr) >> 1;
centerTblPtr++;
curDest += width;
@@ -379,9 +381,9 @@ void Text::makeGameCharacter(uint8 textChar, uint8 *charSetPtr, uint8 *&dest, ui
dest = startPos + charWidth + _dtCharSpacing * 2 - 1;
}
-DisplayedText Text::lowTextManager(uint32 textNum, uint16 width, uint16 logicNum, uint8 color, bool centre) {
+DisplayedText Text::lowTextManager(uint32 textNum, uint16 width, uint16 logicNum, uint8 color, bool center) {
getText(textNum);
- DisplayedText textInfo = displayText(_textBuffer, NULL, centre, width, color);
+ DisplayedText textInfo = displayText(_textBuffer, NULL, center, width, color);
uint32 compactNum = FIRST_TEXT_COMPACT;
Compact *cpt = _skyCompact->fetchCpt(compactNum);
@@ -405,7 +407,7 @@ DisplayedText Text::lowTextManager(uint32 textNum, uint16 width, uint16 logicNum
return textInfo;
}
-void Text::changeTextSpriteColour(uint8 *sprData, uint8 newCol) {
+void Text::changeTextSpriteColor(uint8 *sprData, uint8 newCol) {
DataFileHeader *header = (DataFileHeader *)sprData;
sprData += sizeof(DataFileHeader);
for (uint16 cnt = 0; cnt < header->s_sp_size; cnt++)
diff --git a/engines/sky/text.h b/engines/sky/text.h
index 890cfb2e47..06aabf5094 100644
--- a/engines/sky/text.h
+++ b/engines/sky/text.h
@@ -52,14 +52,14 @@ class Text {
public:
Text(Disk *skyDisk, SkyCompact *skyCompact);
~Text();
- struct DisplayedText displayText(uint32 textNum, uint8 *dest, bool centre, uint16 pixelWidth, uint8 color);
- struct DisplayedText displayText(char *textPtr, uint8 *dest, bool centre, uint16 pixelWidth, uint8 color);
- struct DisplayedText lowTextManager(uint32 textNum, uint16 width, uint16 logicNum, uint8 color, bool centre);
+ struct DisplayedText displayText(uint32 textNum, uint8 *dest, bool center, uint16 pixelWidth, uint8 color);
+ struct DisplayedText displayText(char *textPtr, uint8 *dest, bool center, uint16 pixelWidth, uint8 color);
+ struct DisplayedText lowTextManager(uint32 textNum, uint16 width, uint16 logicNum, uint8 color, bool center);
void fnSetFont(uint32 fontNr);
void fnTextModule(uint32 textInfoId, uint32 textNo);
void fnPointerText(uint32 pointedId, uint16 mouseX, uint16 mouseY);
void logicCursor(Compact *textCompact, uint16 mouseX, uint16 mouseY);
- void changeTextSpriteColour(uint8 *sprData, uint8 newCol);
+ void changeTextSpriteColor(uint8 *sprData, uint8 newCol);
uint32 giveCurrentCharSet();
uint32 _numLetters; //no of chars in message
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 60176be1a9..7c17befcff 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -24,15 +24,16 @@
*/
#include "common/file.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/textconsole.h"
#include "sword1/sword1.h"
#include "sword1/animation.h"
#include "sword1/text.h"
-#include "audio/decoders/vorbis.h"
-#include "common/config-manager.h"
-#include "common/endian.h"
#include "common/str.h"
#include "common/system.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "gui/message.h"
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index d4f6bfd1fe..d8ddd53e2e 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -29,7 +29,9 @@
#include "common/events.h"
#include "common/system.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
+#include "graphics/palette.h"
#include "graphics/thumbnail.h"
#include "gui/message.h"
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index a6ccb09a04..db910f521f 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -33,7 +33,7 @@
class OSystem;
namespace Common {
- class SaveFileManager;
+class SaveFileManager;
}
namespace Sword1 {
@@ -44,7 +44,7 @@ class Mouse;
class Music;
class Sound;
-#define SAVEGAME_HEADER MKID_BE('BS_1')
+#define SAVEGAME_HEADER MKTAG('B','S','_','1')
#define SAVEGAME_VERSION 2
#define MAX_BUTTONS 16
diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp
index 855c7d1f83..fa8277033c 100644
--- a/engines/sword1/detection.cpp
+++ b/engines/sword1/detection.cpp
@@ -27,8 +27,6 @@
#include "sword1/control.h"
#include "base/plugins.h"
-#include "common/config-manager.h"
-#include "common/file.h"
#include "common/fs.h"
#include "common/savefile.h"
#include "common/system.h"
diff --git a/engines/sword1/eventman.cpp b/engines/sword1/eventman.cpp
index 55a438f506..9200e6a229 100644
--- a/engines/sword1/eventman.cpp
+++ b/engines/sword1/eventman.cpp
@@ -26,6 +26,7 @@
#include "sword1/eventman.h"
#include "sword1/sworddefs.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Sword1 {
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index ef54167d41..3da3c457d0 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -25,9 +25,8 @@
#include "common/endian.h"
#include "common/util.h"
-#include "common/system.h"
-#include "common/events.h"
#include "common/EventRecorder.h"
+#include "common/textconsole.h"
#include "sword1/logic.h"
#include "sword1/text.h"
diff --git a/engines/sword1/memman.cpp b/engines/sword1/memman.cpp
index b08631dfc8..f315895eb0 100644
--- a/engines/sword1/memman.cpp
+++ b/engines/sword1/memman.cpp
@@ -25,6 +25,7 @@
#include "sword1/memman.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Sword1 {
diff --git a/engines/sword1/menu.cpp b/engines/sword1/menu.cpp
index 34f6daf276..582bea82f8 100644
--- a/engines/sword1/menu.cpp
+++ b/engines/sword1/menu.cpp
@@ -309,7 +309,7 @@ void Menu::buildMenu() {
if (Logic::_scriptVars[MENU_LOOKING] || _subjectBarStatus == MENU_OPEN) { // either we're in the chooser or we're doing a 'LOOK AT'
if ((!objHeld) || (objHeld == _menuList[menuSlot]))
_objects[menuSlot]->setSelect(true);
- } else if (Logic::_scriptVars[SECOND_ITEM]) { // clicked luggage onto 2nd icon - we need to colour-highlight the 2 relevant icons & grey out the rest
+ } else if (Logic::_scriptVars[SECOND_ITEM]) { // clicked luggage onto 2nd icon - we need to color-highlight the 2 relevant icons & grey out the rest
if ((_menuList[menuSlot] == objHeld) || (_menuList[menuSlot] == Logic::_scriptVars[SECOND_ITEM]))
_objects[menuSlot]->setSelect(true);
} else { // this object is selected - ie. GREYED OUT
diff --git a/engines/sword1/mouse.cpp b/engines/sword1/mouse.cpp
index 751b27efc0..87e476e504 100644
--- a/engines/sword1/mouse.cpp
+++ b/engines/sword1/mouse.cpp
@@ -197,6 +197,7 @@ void Mouse::createPointer(uint32 ptrId, uint32 luggageId) {
free(_currentPtr);
_currentPtr = NULL;
}
+
if (ptrId) {
MousePtr *lugg = NULL;
MousePtr *ptr = (MousePtr*)_resMan->openFetchRes(ptrId);
@@ -284,6 +285,7 @@ void Mouse::createPointer(uint32 ptrId, uint32 luggageId) {
void Mouse::setPointer(uint32 resId, uint32 rate) {
_currentPtrId = resId;
_frame = 0;
+ _activeFrame = -1;
createPointer(resId, _currentLuggageId);
@@ -298,15 +300,24 @@ void Mouse::setPointer(uint32 resId, uint32 rate) {
void Mouse::setLuggage(uint32 resId, uint32 rate) {
_currentLuggageId = resId;
_frame = 0;
+ _activeFrame = -1;
+
createPointer(_currentPtrId, resId);
}
void Mouse::animate() {
if ((Logic::_scriptVars[MOUSE_STATUS] == 1) || (_mouseOverride && _currentPtr)) {
_frame = (_frame + 1) % _currentPtr->numFrames;
+
+ if (_activeFrame == _frame)
+ return;
+
uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr);
ptrData += _frame * _currentPtr->sizeX * _currentPtr->sizeY;
+
CursorMan.replaceCursor(ptrData, _currentPtr->sizeX, _currentPtr->sizeY, _currentPtr->hotSpotX, _currentPtr->hotSpotY, 255);
+
+ _activeFrame = _frame;
}
}
diff --git a/engines/sword1/mouse.h b/engines/sword1/mouse.h
index 50b7431c48..3a7ea747fb 100644
--- a/engines/sword1/mouse.h
+++ b/engines/sword1/mouse.h
@@ -27,6 +27,7 @@
#define SWORD1_MOUSE_H
#include "common/scummsys.h"
+#include "common/rect.h"
#include "sword1/sworddefs.h"
#include "sword1/object.h"
@@ -99,8 +100,9 @@ private:
ObjectMan *_objMan;
Common::Point _mouse;
- uint32 _currentPtrId, _currentLuggageId, _frame;
+ uint32 _currentPtrId, _currentLuggageId;
MousePtr *_currentPtr;
+ int _frame, _activeFrame;
uint16 _numObjs;
uint16 _lastState, _state;
uint32 _getOff;
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
index 2b81ae1eb4..49f9f7271b 100644
--- a/engines/sword1/music.cpp
+++ b/engines/sword1/music.cpp
@@ -24,10 +24,9 @@
*/
-#include "common/endian.h"
#include "common/file.h"
#include "common/util.h"
-#include "common/system.h"
+#include "common/textconsole.h"
#include "sword1/sword1.h"
#include "sword1/music.h"
diff --git a/engines/sword1/objectman.cpp b/engines/sword1/objectman.cpp
index 9ac2c7a255..dde1498591 100644
--- a/engines/sword1/objectman.cpp
+++ b/engines/sword1/objectman.cpp
@@ -24,6 +24,7 @@
*/
+#include "common/textconsole.h"
#include "common/util.h"
#include "sword1/objectman.h"
diff --git a/engines/sword1/resman.cpp b/engines/sword1/resman.cpp
index 2bad8a79a7..f7b9eb8908 100644
--- a/engines/sword1/resman.cpp
+++ b/engines/sword1/resman.cpp
@@ -24,19 +24,14 @@
*/
-#include "common/config-manager.h"
-#include "common/util.h"
-#include "common/str.h"
-
-#include "engines/engine.h"
+#include "common/debug.h"
+#include "common/textconsole.h"
#include "sword1/memman.h"
#include "sword1/resman.h"
-#include "sword1/sworddefs.h"
#include "sword1/swordres.h"
#include "gui/message.h"
-#include "gui/gui-manager.h"
namespace Sword1 {
void guiFatalError(char *msg) {
diff --git a/engines/sword1/router.cpp b/engines/sword1/router.cpp
index 9ff5ae0c8e..3694ed2459 100644
--- a/engines/sword1/router.cpp
+++ b/engines/sword1/router.cpp
@@ -24,6 +24,7 @@
*/
#include "common/debug.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "sword1/router.h"
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 24fd5b502f..de96f6e7b4 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -25,8 +25,11 @@
#include "common/system.h"
+#include "common/textconsole.h"
#include "common/util.h"
+#include "graphics/palette.h"
+
#include "sword1/screen.h"
#include "sword1/logic.h"
#include "sword1/sworddefs.h"
@@ -899,7 +902,7 @@ uint8* Screen::psxShrinkedBackgroundToIndexed(uint8 *psxBackground, uint32 bakXr
uint8 *fullres_buffer = (uint8 *)malloc(bakXres * (yresInTiles + 1) * 32);
memset(fullres_buffer, 0, bakXres * (yresInTiles + 1) * 32);
- bool isCompressed = (READ_LE_UINT32(psxBackground) == MKID_BE('COMP'));
+ bool isCompressed = (READ_LE_UINT32(psxBackground) == MKTAG('C','O','M','P'));
totTiles -= xresInTiles;
psxBackground += 4; //We skip the id tag
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index f8219eb21a..c970e72748 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -27,10 +27,9 @@
#include "common/endian.h"
#include "common/util.h"
-#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/memstream.h"
-#include "common/system.h"
+#include "common/textconsole.h"
#include "sword1/sound.h"
#include "sword1/resman.h"
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index ae96132241..b6fcd6706f 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -34,7 +34,7 @@
#include "audio/mixer.h"
namespace Audio {
- class Mixer;
+class Mixer;
}
namespace Sword1 {
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 537720401d..3b3eaaf8b9 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -37,6 +37,7 @@
#include "sword1/control.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
#include "engines/util.h"
@@ -170,6 +171,8 @@ void SwordEngine::reinitialize() {
}
void SwordEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
uint musicVol = ConfMan.getInt("music_volume");
uint sfxVol = ConfMan.getInt("sfx_volume");
uint speechVol = ConfMan.getInt("speech_volume");
@@ -228,9 +231,6 @@ void SwordEngine::syncSoundSettings() {
_sound->setSpeechVol(speechVolL, speechVolR);
_sound->setSfxVol(sfxVolL, sfxVolR);
}
-
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : ConfMan.getInt("speech_volume"));
}
void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index 592d2da6f4..dbb683cd74 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -27,7 +27,9 @@
#define SWORD1_H
#include "engines/engine.h"
-#include "common/events.h"
+#include "common/error.h"
+#include "common/keyboard.h"
+#include "common/rect.h"
#include "common/util.h"
#include "sword1/sworddefs.h"
#include "sword1/console.h"
@@ -100,7 +102,7 @@ protected:
virtual Common::Error run() {
Common::Error err;
err = init();
- if (err != Common::kNoError)
+ if (err.getCode() != Common::kNoError)
return err;
return go();
}
diff --git a/engines/sword1/text.cpp b/engines/sword1/text.cpp
index ef3e07fe74..7c65533067 100644
--- a/engines/sword1/text.cpp
+++ b/engines/sword1/text.cpp
@@ -24,8 +24,7 @@
*/
-#include "common/endian.h"
-#include "common/util.h"
+#include "common/textconsole.h"
#include "sword1/text.h"
#include "sword1/resman.h"
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 3c506c0dae..a5a2499b01 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -26,7 +26,9 @@
*/
#include "common/file.h"
+#include "common/mutex.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -110,7 +112,7 @@ void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadI
terminated = !playVideo();
- closeTextObject(_currentMovieText, NULL);
+ closeTextObject(_currentMovieText, NULL, 0);
if (terminated) {
_snd->stopHandle(*_bgSoundHandle);
@@ -165,7 +167,7 @@ void MoviePlayer::openTextObject(uint32 index) {
}
}
-void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
+void MoviePlayer::closeTextObject(uint32 index, byte *screen, uint16 pitch) {
if (index < _numMovieTexts) {
MovieText *text = &_movieTexts[index];
@@ -182,20 +184,21 @@ void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
int frameHeight = _decoder->getHeight();
int frameX = (_system->getWidth() - frameWidth) / 2;
int frameY = (_system->getHeight() - frameHeight) / 2;
+ byte black = findBlackPalIndex();
- byte *dst = screen + _textY * _system->getWidth();
+ byte *dst = screen + _textY * pitch;
for (int y = 0; y < text->_textSprite.h; y++) {
if (_textY + y < frameY || _textY + y >= frameY + frameHeight) {
- memset(dst + _textX, findBlackPalIndex(), text->_textSprite.w);
+ memset(dst + _textX, black, text->_textSprite.w);
} else {
if (frameX > _textX)
- memset(dst + _textX, findBlackPalIndex(), frameX - _textX);
+ memset(dst + _textX, black, frameX - _textX);
if (frameX + frameWidth < _textX + text->_textSprite.w)
- memset(dst + frameX + frameWidth, findBlackPalIndex(), _textX + text->_textSprite.w - (frameX + frameWidth));
+ memset(dst + frameX + frameWidth, black, _textX + text->_textSprite.w - (frameX + frameWidth));
}
- dst += _system->getWidth();
+ dst += pitch;
}
}
@@ -205,7 +208,7 @@ void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
}
}
-void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
+void MoviePlayer::drawTextObject(uint32 index, byte *screen, uint16 pitch) {
MovieText *text = &_movieTexts[index];
byte white = findWhitePalIndex();
@@ -217,14 +220,15 @@ void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
uint16 height = text->_textSprite.h;
// Resize text sprites for PSX version
+ byte *psxSpriteBuffer = 0;
if (Sword2Engine::isPsx()) {
height *= 2;
- byte *buffer = (byte *)malloc(width * height);
- Screen::resizePsxSprite(buffer, src, width, height);
- src = buffer;
+ psxSpriteBuffer = (byte *)malloc(width * height);
+ Screen::resizePsxSprite(psxSpriteBuffer, src, width, height);
+ src = psxSpriteBuffer;
}
- byte *dst = screen + _textY * RENDERWIDE + _textX;
+ byte *dst = screen + _textY * pitch + _textX;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
@@ -234,12 +238,16 @@ void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
dst[x] = white;
}
src += width;
- dst += RENDERWIDE;
+ dst += pitch;
}
+
+ // Free buffer used to resize psx sprite
+ if (Sword2Engine::isPsx())
+ free(psxSpriteBuffer);
}
}
-void MoviePlayer::performPostProcessing(byte *screen) {
+void MoviePlayer::performPostProcessing(byte *screen, uint16 pitch) {
MovieText *text;
int frame = _decoder->getCurFrame();
@@ -261,9 +269,9 @@ void MoviePlayer::performPostProcessing(byte *screen) {
_vm->_sound->playCompSpeech(text->_speechId, 16, 0);
}
if (frame < text->_endFrame) {
- drawTextObject(_currentMovieText, screen);
+ drawTextObject(_currentMovieText, screen, pitch);
} else {
- closeTextObject(_currentMovieText, screen);
+ closeTextObject(_currentMovieText, screen, pitch);
_currentMovieText++;
}
}
@@ -313,7 +321,7 @@ bool MoviePlayer::playVideo() {
}
Graphics::Surface *screen = _vm->_system->lockScreen();
- performPostProcessing((byte *)screen->pixels);
+ performPostProcessing((byte *)screen->pixels, screen->pitch);
_vm->_system->unlockScreen();
_vm->_system->updateScreen();
}
diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h
index 550ac0fac4..afe7dfcc68 100644
--- a/engines/sword2/animation.h
+++ b/engines/sword2/animation.h
@@ -96,12 +96,12 @@ protected:
uint32 _leadOut;
int _leadOutFrame;
- void performPostProcessing(byte *screen);
+ void performPostProcessing(byte *screen, uint16 pitch);
bool playVideo();
void openTextObject(uint32 index);
- void closeTextObject(uint32 index, byte *screen);
- void drawTextObject(uint32 index, byte *screen);
+ void closeTextObject(uint32 index, byte *screen, uint16 pitch);
+ void drawTextObject(uint32 index, byte *screen, uint16 pitch);
byte findBlackPalIndex();
byte findWhitePalIndex();
diff --git a/engines/sword2/controls.cpp b/engines/sword2/controls.cpp
index c55cc72493..4332f2811c 100644
--- a/engines/sword2/controls.cpp
+++ b/engines/sword2/controls.cpp
@@ -26,9 +26,7 @@
*/
-#include "common/events.h"
#include "common/rect.h"
-#include "common/config-manager.h"
#include "common/system.h"
#include "sword2/sword2.h"
@@ -465,7 +463,7 @@ void Widget::createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc)
break;
case RLE16:
spriteType |= RDSPR_RLE256;
- // Points to just after last cdt_entry, i.e. start of colour
+ // Points to just after last cdt_entry, i.e. start of color
// table
colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size()
+ anim_head.noAnimFrames * CdtEntry::size();
diff --git a/engines/sword2/events.cpp b/engines/sword2/events.cpp
index f0e0e567a4..24101e271c 100644
--- a/engines/sword2/events.cpp
+++ b/engines/sword2/events.cpp
@@ -26,6 +26,7 @@
*/
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
diff --git a/engines/sword2/function.cpp b/engines/sword2/function.cpp
index 5e570fbaad..e0990ea120 100644
--- a/engines/sword2/function.cpp
+++ b/engines/sword2/function.cpp
@@ -28,6 +28,7 @@
#include "common/system.h"
#include "common/file.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -1859,15 +1860,15 @@ int32 Logic::fnSetScrollRightMouse(int32 *params) {
return IR_CONT;
}
-int32 Logic::fnColour(int32 *params) {
- // set border colour - useful during script development
- // eg. set to colour during a timer situation, then black when timed
+int32 Logic::fnColor(int32 *params) {
+ // set border color - useful during script development
+ // eg. set to color during a timer situation, then black when timed
// out
- // params 0: colour (see defines above)
+ // params 0: color (see defines above)
#ifdef SWORD2_DEBUG
- // what colour?
+ // what color?
switch (params[0]) {
case BLACK:
_vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
@@ -1905,14 +1906,14 @@ static const uint8 blue[3] = { 0, 0, 255 };
#endif
int32 Logic::fnFlash(int32 *params) {
- // flash colour 0 (ie. border) - useful during script development
+ // flash color 0 (ie. border) - useful during script development
// eg. fnFlash(BLUE) where a text line is missed; RED when some code
// missing, etc
- // params: 0 colour to flash
+ // params: 0 color to flash
#ifdef SWORD2_DEBUG
- // what colour?
+ // what color?
switch (params[0]) {
case WHITE:
_vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
diff --git a/engines/sword2/header.h b/engines/sword2/header.h
index 3f64152bb9..ed63c806bc 100644
--- a/engines/sword2/header.h
+++ b/engines/sword2/header.h
@@ -114,7 +114,7 @@ enum {
// standard file header
// animation header
// a string of CDT entries (one per frame of the anim)
-// a 16-byte colour table ONLY if (runTimeComp==RLE16)
+// a 16-byte color table ONLY if (runTimeComp==RLE16)
// a string of groups of (frame header + frame data)
// Animation Header
@@ -147,11 +147,11 @@ struct AnimHeader {
enum {
NONE = 0, // No frame compression
- RLE256 = 1, // James's RLE for 256-colour sprites
- RLE16 = 2 // James's RLE for 16- or 17-colour sprites
- // (raw blocks have max 16 colours for 2 pixels
+ RLE256 = 1, // James's RLE for 256-color sprites
+ RLE16 = 2 // James's RLE for 16- or 17-color sprites
+ // (raw blocks have max 16 colors for 2 pixels
// per byte, so '0's are encoded only as FLAT
- // for 17-colour sprites eg. George's mega-set)
+ // for 17-color sprites eg. George's mega-set)
};
// CDT Entry
diff --git a/engines/sword2/icons.cpp b/engines/sword2/icons.cpp
index b115eb373b..8336178ae5 100644
--- a/engines/sword2/icons.cpp
+++ b/engines/sword2/icons.cpp
@@ -157,33 +157,33 @@ void Mouse::buildMenu() {
byte *icon = NULL;
if (res) {
- bool icon_coloured;
+ bool icon_colored;
uint32 object_held = _vm->_logic->readVar(OBJECT_HELD);
uint32 combine_base = _vm->_logic->readVar(COMBINE_BASE);
if (_examiningMenuIcon) {
// When examining an object, that object is
- // coloured. The rest are greyed out.
- icon_coloured = (res == object_held);
+ // colored. The rest are greyed out.
+ icon_colored = (res == object_held);
} else if (combine_base) {
// When combining two menu object (i.e. using
- // one on another), both are coloured. The rest
+ // one on another), both are colored. The rest
// are greyed out.
- icon_coloured = (res == object_held || combine_base);
+ icon_colored = (res == object_held || combine_base);
} else {
// If an object is selected but we are not yet
// doing anything with it, the selected object
- // is greyed out. The rest are coloured.
- icon_coloured = (res != object_held);
+ // is greyed out. The rest are colored.
+ icon_colored = (res != object_held);
}
icon = _vm->_resman->openResource(res) + ResHeader::size();
- // The coloured icon is stored directly after the
+ // The colored icon is stored directly after the
// greyed out one.
- if (icon_coloured)
+ if (icon_colored)
icon += (menuIconWidth * RDMENU_ICONDEEP);
}
@@ -216,7 +216,7 @@ void Mouse::buildSystemMenu() {
else
menuIconWidth = RDMENU_ICONWIDE;
- // Build them all high in full colour - when one is clicked on all the
+ // Build them all high in full color - when one is clicked on all the
// rest will grey out.
for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
diff --git a/engines/sword2/interpreter.cpp b/engines/sword2/interpreter.cpp
index a51ce5702c..a3804366d4 100644
--- a/engines/sword2/interpreter.cpp
+++ b/engines/sword2/interpreter.cpp
@@ -28,6 +28,7 @@
#include "common/util.h"
#include "common/stack.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/header.h"
@@ -147,7 +148,7 @@ void Logic::setupOpcodes() {
OPCODE(fnSetScrollLeftMouse),
OPCODE(fnSetScrollRightMouse),
/* 4C */
- OPCODE(fnColour),
+ OPCODE(fnColor),
OPCODE(fnFlash),
OPCODE(fnPreFetch),
OPCODE(fnGetPlayerSaveData),
diff --git a/engines/sword2/layers.cpp b/engines/sword2/layers.cpp
index d97b1395d5..47cc3ec232 100644
--- a/engines/sword2/layers.cpp
+++ b/engines/sword2/layers.cpp
@@ -35,6 +35,7 @@
#include "common/rect.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -166,7 +167,7 @@ void Screen::initBackground(int32 res, int32 new_palette) {
spriteInfo.type = 0;
spriteInfo.blend = 0;
spriteInfo.data = _vm->fetchShadingMask(file);
- spriteInfo.colourTable = 0;
+ spriteInfo.colorTable = 0;
if (openLightMask(&spriteInfo) != RD_OK)
error("Could not open light mask");
diff --git a/engines/sword2/logic.cpp b/engines/sword2/logic.cpp
index 511561c55a..c27bd76ff4 100644
--- a/engines/sword2/logic.cpp
+++ b/engines/sword2/logic.cpp
@@ -26,6 +26,7 @@
*/
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
diff --git a/engines/sword2/logic.h b/engines/sword2/logic.h
index 793f87d037..e40a12bba3 100644
--- a/engines/sword2/logic.h
+++ b/engines/sword2/logic.h
@@ -260,7 +260,7 @@ public:
int32 fnStandAtAnim(int32 *params);
int32 fnSetScrollLeftMouse(int32 *params);
int32 fnSetScrollRightMouse(int32 *params);
- int32 fnColour(int32 *params);
+ int32 fnColor(int32 *params);
int32 fnFlash(int32 *params);
int32 fnPreFetch(int32 *params);
int32 fnGetPlayerSaveData(int32 *params);
diff --git a/engines/sword2/maketext.cpp b/engines/sword2/maketext.cpp
index 84a2fccedd..fda30981c8 100644
--- a/engines/sword2/maketext.cpp
+++ b/engines/sword2/maketext.cpp
@@ -27,17 +27,17 @@
// MAKETEXT - Constructs a single-frame text sprite: returns a handle to a
// FLOATING memory block containing the sprite, given a
-// null-terminated string, max width allowed, pen colour and
+// null-terminated string, max width allowed, pen color and
// pointer to required character set.
//
// NB 1) The routine does not create a standard file header or
// an anim header for the text sprite - the data simply begins
// with the frame header.
//
-// NB 2) If pen colour is zero, it copies the characters into
-// the sprite without remapping the colours.
-// ie. It can handle both the standard 2-colour font for speech
-// and any multicoloured fonts for control panels, etc.
+// NB 2) If pen color is zero, it copies the characters into
+// the sprite without remapping the colors.
+// ie. It can handle both the standard 2-color font for speech
+// and any multicolored fonts for control panels, etc.
//
// Based on textsprt.c as used for Broken Sword 1, but updated
// for new system by JEL on 9oct96 and updated again (for font
@@ -45,6 +45,7 @@
#include "common/system.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -58,10 +59,10 @@ namespace Sword2 {
#define MAX_LINES 30 // max character lines in output sprite
-#define BORDER_COL 200 // source colour for character border (only
- // needed for remapping colours)
+#define BORDER_COL 200 // source color for character border (only
+ // needed for remapping colors)
-#define LETTER_COL 193 // source colour for bulk of character ( " )
+#define LETTER_COL 193 // source color for bulk of character ( " )
#define LETTER_COL_PSX1 33
#define LETTER_COL_PSX2 34
#define SPACE ' '
@@ -76,9 +77,9 @@ namespace Sword2 {
*
* @param sentence pointer to a null-terminated string
* @param maxWidth the maximum allowed text sprite width in pixels
- * @param pen the text colour, or zero to use the source colours
+ * @param pen the text color, or zero to use the source colors
* @param fontRes the font resource id
- * @param border the border colour; black by default
+ * @param border the border color; black by default
* @return a handle to a floating memory block containing the text sprite
* @note The sentence must contain no leading, trailing or extra spaces.
* Out-of-range characters in the string are replaced by a special
@@ -200,7 +201,7 @@ uint16 FontRenderer::analyseSentence(byte *sentence, uint16 maxWidth, uint32 fon
*
* @param sentence pointer to a null-terminated string
* @param fontRes the font resource id
- * @param pen the text colour, or zero to use the source colours
+ * @param pen the text color, or zero to use the source colors
* @param line array of LineInfo structures, created by analyseSentence()
* @param noOfLines the number of lines, i.e. the number of elements in 'line'
* @return a handle to a floating memory block containing the text sprite
@@ -448,7 +449,7 @@ byte *FontRenderer::findChar(byte ch, byte *charSet) {
* @param spritePtr pointer to the sprite buffer
* @param spriteWidth the width of the character
* @param pen If zero, copy the data directly. Otherwise remap the
- * sprite's colours from BORDER_COL to _borderPen and from
+ * sprite's colors from BORDER_COL to _borderPen and from
* LETTER_COL to pen.
*/
@@ -464,7 +465,7 @@ void FontRenderer::copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth,
byte *dest = rowPtr;
if (pen) {
- // Use the specified colours
+ // Use the specified colors
for (uint j = 0; j < frame.width; j++) {
switch (*source++) {
case 0:
@@ -489,7 +490,7 @@ void FontRenderer::copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth,
}
} else {
// Pen is zero, so just copy character sprites
- // directly into text sprite without remapping colours.
+ // directly into text sprite without remapping colors.
// Apparently overlapping is never considered here?
memcpy(dest, source, frame.width);
source += frame.width;
@@ -528,13 +529,13 @@ uint32 FontRenderer::buildNewBloc(byte *ascii, int16 x, int16 y, uint16 width, u
frame_head.read(_blocList[i].text_mem);
switch (justification) {
- case POSITION_AT_CENTRE_OF_BASE:
+ case POSITION_AT_CENTER_OF_BASE:
// This one is always used for SPEECH TEXT; possibly
// also for pointer text
x -= (frame_head.width / 2);
y -= frame_head.height;
break;
- case POSITION_AT_CENTRE_OF_TOP:
+ case POSITION_AT_CENTER_OF_TOP:
x -= (frame_head.width / 2);
break;
case POSITION_AT_LEFT_OF_TOP:
@@ -550,10 +551,10 @@ uint32 FontRenderer::buildNewBloc(byte *ascii, int16 x, int16 y, uint16 width, u
x -= frame_head.width;
y -= frame_head.height;
break;
- case POSITION_AT_LEFT_OF_CENTRE:
+ case POSITION_AT_LEFT_OF_CENTER:
y -= (frame_head.height / 2);
break;
- case POSITION_AT_RIGHT_OF_CENTRE:
+ case POSITION_AT_RIGHT_OF_CENTER:
x -= frame_head.width;
y -= (frame_head.height) / 2;
break;
@@ -613,7 +614,7 @@ void FontRenderer::printTextBlocs() {
spriteInfo.type = _blocList[i].type;
spriteInfo.blend = 0;
spriteInfo.data = _blocList[i].text_mem + FrameHeader::size();
- spriteInfo.colourTable = 0;
+ spriteInfo.colorTable = 0;
spriteInfo.isText = true;
uint32 rv = _vm->_screen->drawSprite(&spriteInfo);
diff --git a/engines/sword2/maketext.h b/engines/sword2/maketext.h
index 63b65a32b1..52740d9de9 100644
--- a/engines/sword2/maketext.h
+++ b/engines/sword2/maketext.h
@@ -32,7 +32,7 @@
namespace Sword2 {
-// Output colour for character border - should be be black but note that we
+// Output color for character border - should be be black but note that we
// have to use a different pen number during sequences
#define BORDER_PEN 194
@@ -47,14 +47,14 @@ enum {
NO_JUSTIFICATION = 0,
// These all force text inside the screen edge margin when necessary
- POSITION_AT_CENTRE_OF_BASE = 1,
- POSITION_AT_CENTRE_OF_TOP = 2,
+ POSITION_AT_CENTER_OF_BASE = 1,
+ POSITION_AT_CENTER_OF_TOP = 2,
POSITION_AT_LEFT_OF_TOP = 3,
POSITION_AT_RIGHT_OF_TOP = 4,
POSITION_AT_LEFT_OF_BASE = 5,
POSITION_AT_RIGHT_OF_BASE = 6,
- POSITION_AT_LEFT_OF_CENTRE = 7,
- POSITION_AT_RIGHT_OF_CENTRE = 8
+ POSITION_AT_LEFT_OF_CENTER = 7,
+ POSITION_AT_RIGHT_OF_CENTER = 8
};
enum {
@@ -92,7 +92,7 @@ private:
// for overlap
int8 _charSpacing; // no. of pixels to separate characters along
// each line - negative for overlap
- uint8 _borderPen; // output pen colour of character borders
+ uint8 _borderPen; // output pen color of character borders
uint16 analyseSentence(byte *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line);
byte *buildTextSprite(byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines);
diff --git a/engines/sword2/memory.cpp b/engines/sword2/memory.cpp
index cd36f9a19b..2b3784164e 100644
--- a/engines/sword2/memory.cpp
+++ b/engines/sword2/memory.cpp
@@ -48,6 +48,7 @@
//
// The number zero is used to represent the NULL pointer.
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/memory.h"
diff --git a/engines/sword2/mouse.cpp b/engines/sword2/mouse.cpp
index c8e9387cb7..3a26ab17b7 100644
--- a/engines/sword2/mouse.cpp
+++ b/engines/sword2/mouse.cpp
@@ -29,6 +29,7 @@
#include "common/system.h"
#include "common/events.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "graphics/cursorman.h"
@@ -1270,8 +1271,8 @@ void Mouse::createPointerText(uint32 text_id, uint32 pointer_res) {
// Above right
justification = POSITION_AT_LEFT_OF_BASE;
} else {
- // Above centre
- justification = POSITION_AT_CENTRE_OF_BASE;
+ // Above center
+ justification = POSITION_AT_CENTER_OF_BASE;
}
} else if (yOffset > 0) {
// Below pointer
@@ -1282,20 +1283,20 @@ void Mouse::createPointerText(uint32 text_id, uint32 pointer_res) {
// Below right
justification = POSITION_AT_LEFT_OF_TOP;
} else {
- // Below centre
- justification = POSITION_AT_CENTRE_OF_TOP;
+ // Below center
+ justification = POSITION_AT_CENTER_OF_TOP;
}
} else {
// Same y-coord as pointer
if (xOffset < 0) {
- // Centre left
- justification = POSITION_AT_RIGHT_OF_CENTRE;
+ // Center left
+ justification = POSITION_AT_RIGHT_OF_CENTER;
} else if (xOffset > 0) {
- // Centre right
- justification = POSITION_AT_LEFT_OF_CENTRE;
+ // Center right
+ justification = POSITION_AT_LEFT_OF_CENTER;
} else {
- // Centre centre - shouldn't happen anyway!
- justification = POSITION_AT_LEFT_OF_CENTRE;
+ // Center center - shouldn't happen anyway!
+ justification = POSITION_AT_LEFT_OF_CENTER;
}
}
@@ -1433,7 +1434,7 @@ void Mouse::refreshInventory() {
// Can reset this now
_vm->_logic->writeVar(COMBINE_BASE, 0);
- // Cause 'object_held' icon to be greyed. The rest are coloured.
+ // Cause 'object_held' icon to be greyed. The rest are colored.
_examiningMenuIcon = true;
buildMenu();
_examiningMenuIcon = false;
diff --git a/engines/sword2/music.cpp b/engines/sword2/music.cpp
index aa91843432..233d9369d2 100644
--- a/engines/sword2/music.cpp
+++ b/engines/sword2/music.cpp
@@ -36,6 +36,7 @@
#include "common/memstream.h"
#include "common/substream.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "audio/decoders/mp3.h"
#include "audio/decoders/vorbis.h"
diff --git a/engines/sword2/object.h b/engines/sword2/object.h
index 53819c08cc..94a968e58d 100644
--- a/engines/sword2/object.h
+++ b/engines/sword2/object.h
@@ -139,7 +139,7 @@ public:
// speech structure - contains fields used by speech scripts & text output
class ObjectSpeech {
- // int32 pen; // colour to use for body of characters
+ // int32 pen; // color to use for body of characters
// int32 width; // max width of text sprite
// int32 command; // speech script command id
// int32 ins1; // speech script instruction parameters
diff --git a/engines/sword2/palette.cpp b/engines/sword2/palette.cpp
index b348fd6bb5..a52160db25 100644
--- a/engines/sword2/palette.cpp
+++ b/engines/sword2/palette.cpp
@@ -27,6 +27,9 @@
#include "common/system.h"
+#include "common/textconsole.h"
+
+#include "graphics/palette.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -107,8 +110,8 @@ void Screen::setFullPalette(int32 palRes) {
pal += ResHeader::size();
- // always set colour 0 to black because most background screen
- // palettes have a bright colour 0 although it should come out
+ // always set color 0 to black because most background screen
+ // palettes have a bright color 0 although it should come out
// as black in the game!
_palette[0] = 0;
@@ -144,11 +147,11 @@ void Screen::setFullPalette(int32 palRes) {
}
/**
- * Matches a colour triplet to a palette index.
- * @param r red colour component
- * @param g green colour component
- * @param b blue colour component
- * @return the palette index of the closest matching colour in the palette
+ * Matches a color triplet to a palette index.
+ * @param r red color component
+ * @param g green color component
+ * @param b blue color component
+ * @return the palette index of the closest matching color in the palette
*/
// FIXME: This used to be inlined - probably a good idea - but the
@@ -160,16 +163,16 @@ uint8 Screen::quickMatch(uint8 r, uint8 g, uint8 b) {
/**
* Sets the palette.
- * @param startEntry the first colour entry to set
- * @param noEntries the number of colour entries to set
- * @param colourTable the new colour entries
+ * @param startEntry the first color entry to set
+ * @param noEntries the number of color entries to set
+ * @param colorTable the new color entries
* @param fadeNow whether to perform the change immediately or delayed
*/
-void Screen::setPalette(int16 startEntry, int16 noEntries, byte *colourTable, uint8 fadeNow) {
+void Screen::setPalette(int16 startEntry, int16 noEntries, byte *colorTable, uint8 fadeNow) {
assert(noEntries > 0);
- memmove(&_palette[3 * startEntry], colourTable, noEntries * 3);
+ memmove(&_palette[3 * startEntry], colorTable, noEntries * 3);
if (fadeNow == RDPAL_INSTANT) {
setSystemPalette(_palette, startEntry, noEntries);
diff --git a/engines/sword2/protocol.cpp b/engines/sword2/protocol.cpp
index ef2c622287..3d16e4ea4c 100644
--- a/engines/sword2/protocol.cpp
+++ b/engines/sword2/protocol.cpp
@@ -52,8 +52,8 @@ void Sword2Engine::fetchPalette(byte *screenFile, byte *palBuffer) {
palette = screenFile + ResHeader::size() + mscreenHeader.palette;
}
- // Always set colour 0 to black, because while most background screen
- // palettes have a bright colour 0 it should come out as black in the
+ // Always set color 0 to black, because while most background screen
+ // palettes have a bright color 0 it should come out as black in the
// game.
palBuffer[0] = 0;
diff --git a/engines/sword2/render.cpp b/engines/sword2/render.cpp
index a71d503d95..a47f8abe0d 100644
--- a/engines/sword2/render.cpp
+++ b/engines/sword2/render.cpp
@@ -234,24 +234,24 @@ void Screen::scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16
* used for debugging.
* @param x x-coordinate of the point
* @param y y-coordinate of the point
- * @param colour colour of the point
+ * @param color color of the point
*/
-void Screen::plotPoint(int x, int y, uint8 colour) {
+void Screen::plotPoint(int x, int y, uint8 color) {
byte *buf = _buffer + MENUDEEP * RENDERWIDE;
x -= _scrollX;
y -= _scrollY;
if (x >= 0 && x < RENDERWIDE && y >= 0 && y < RENDERDEEP) {
- buf[y * RENDERWIDE + x] = colour;
+ buf[y * RENDERWIDE + x] = color;
markAsDirty(x, y + MENUDEEP, x, y + MENUDEEP);
}
}
-static void plot(int x, int y, int colour, void *data) {
+static void plot(int x, int y, int color, void *data) {
Screen *screen = (Screen *)data;
- screen->plotPoint(x, y, (uint8) colour);
+ screen->plotPoint(x, y, (uint8) color);
}
/**
@@ -260,11 +260,11 @@ static void plot(int x, int y, int colour, void *data) {
* @param y0 y-coordinate of the start point
* @param x1 x-coordinate of the end point
* @param y1 y-coordinate of the end point
- * @param colour colour of the line
+ * @param color color of the line
*/
-void Screen::drawLine(int x0, int y0, int x1, int y1, uint8 colour) {
- Graphics::drawLine(x0, y0, x1, y1, colour, &plot, this);
+void Screen::drawLine(int x0, int y0, int x1, int y1, uint8 color) {
+ Graphics::drawLine(x0, y0, x1, y1, color, &plot, this);
}
/**
diff --git a/engines/sword2/resman.cpp b/engines/sword2/resman.cpp
index fa9c396ef3..36280cfda2 100644
--- a/engines/sword2/resman.cpp
+++ b/engines/sword2/resman.cpp
@@ -28,6 +28,7 @@
#include "common/file.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
diff --git a/engines/sword2/resman.h b/engines/sword2/resman.h
index dcc79927ea..75748e1568 100644
--- a/engines/sword2/resman.h
+++ b/engines/sword2/resman.h
@@ -29,7 +29,7 @@
#define SWORD2_RESMAN_H
namespace Common {
- class File;
+class File;
}
#define MAX_MEM_CACHE (8 * 1024 * 1024) // we keep up to 8 megs of resource data files in memory
diff --git a/engines/sword2/router.cpp b/engines/sword2/router.cpp
index 1548536ccb..c2b4d2e67f 100644
--- a/engines/sword2/router.cpp
+++ b/engines/sword2/router.cpp
@@ -27,6 +27,7 @@
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -2344,9 +2345,9 @@ void Router::plotWalkGrid() {
plotCross(_node[i].x, _node[i].y, 184);
}
-void Router::plotCross(int16 x, int16 y, uint8 colour) {
- _vm->_screen->drawLine(x - 1, y - 1, x + 1, y + 1, colour);
- _vm->_screen->drawLine(x + 1, y - 1, x - 1, y + 1, colour);
+void Router::plotCross(int16 x, int16 y, uint8 color) {
+ _vm->_screen->drawLine(x - 1, y - 1, x + 1, y + 1, color);
+ _vm->_screen->drawLine(x + 1, y - 1, x - 1, y + 1, color);
}
void Router::loadWalkGrid() {
diff --git a/engines/sword2/router.h b/engines/sword2/router.h
index f556850797..1ad3dd74c4 100644
--- a/engines/sword2/router.h
+++ b/engines/sword2/router.h
@@ -193,7 +193,7 @@ private:
int32 solidWalkAnimator(WalkData *walkAnim);
#endif
- void plotCross(int16 x, int16 y, uint8 colour);
+ void plotCross(int16 x, int16 y, uint8 color);
public:
Router(Sword2Engine *vm) : _vm(vm), _diagonalx(0), _diagonaly(0) {
diff --git a/engines/sword2/saveload.cpp b/engines/sword2/saveload.cpp
index fab360a8ac..94ef8975b4 100644
--- a/engines/sword2/saveload.cpp
+++ b/engines/sword2/saveload.cpp
@@ -37,6 +37,7 @@
#include "common/memstream.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
diff --git a/engines/sword2/screen.cpp b/engines/sword2/screen.cpp
index 8c2db79297..a83e581fd4 100644
--- a/engines/sword2/screen.cpp
+++ b/engines/sword2/screen.cpp
@@ -32,6 +32,7 @@
#include "common/system.h"
#include "common/events.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -253,7 +254,7 @@ void Screen::updateDisplay(bool redrawScene) {
}
/**
- * Fill the screen buffer with palette colour zero. Note that it does not
+ * Fill the screen buffer with palette color zero. Note that it does not
* touch the menu areas of the screen.
*/
@@ -392,7 +393,7 @@ void Screen::displayMsg(byte *text, int time) {
spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
spriteInfo.blend = 0;
spriteInfo.data = text_spr + FrameHeader::size();
- spriteInfo.colourTable = 0;
+ spriteInfo.colorTable = 0;
spriteInfo.isText = true;
uint32 rv = drawSprite(&spriteInfo);
@@ -530,7 +531,7 @@ void Screen::processLayer(byte *file, uint32 layer_number) {
}
spriteInfo.blend = 0;
- spriteInfo.colourTable = 0;
+ spriteInfo.colorTable = 0;
// check for largest layer for debug info
@@ -572,7 +573,7 @@ void Screen::processImage(BuildUnit *build_unit) {
cdt_entry.read(_vm->fetchCdtEntry(file, build_unit->anim_pc));
frame_head.read(frame);
- // so that 0-colour is transparent
+ // so that 0-color is transparent
uint32 spriteType = RDSPR_TRANS;
if (anim_head.blend)
@@ -606,7 +607,7 @@ void Screen::processImage(BuildUnit *build_unit) {
case RLE16:
spriteType |= RDSPR_RLE16;
// points to just after last cdt_entry, ie.
- // start of colour table
+ // start of color table
colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size() + anim_head.noAnimFrames * CdtEntry::size();
if (Sword2Engine::isPsx())
colTablePtr++; // There is one additional byte to skip before the table in psx version
@@ -632,7 +633,7 @@ void Screen::processImage(BuildUnit *build_unit) {
spriteInfo.blend = anim_head.blend;
// points to just after frame header, ie. start of sprite data
spriteInfo.data = frame + FrameHeader::size();
- spriteInfo.colourTable = colTablePtr;
+ spriteInfo.colorTable = colTablePtr;
spriteInfo.isText = false;
// check for largest layer for debug info
@@ -895,7 +896,7 @@ void Screen::rollCredits() {
// palette 3 * 256 bytes
// data width * height bytes
//
- // Note that the maximum colour component in the palette is 0x3F.
+ // Note that the maximum color component in the palette is 0x3F.
// This is the same resolution as the _paletteMatch table. I doubt
// that this is a coincidence, but let's use the image palette
// directly anyway, just to be safe.
@@ -1261,7 +1262,7 @@ void Screen::splashScreen() {
barSprite.scaledHeight = 0;
barSprite.type = RDSPR_RLE256FAST | RDSPR_TRANS;
barSprite.blend = 0;
- barSprite.colourTable = 0;
+ barSprite.colorTable = 0;
barSprite.data = frame + FrameHeader::size();
barSprite.isText = false;
diff --git a/engines/sword2/screen.h b/engines/sword2/screen.h
index 46eb53d0db..9ef4f28049 100644
--- a/engines/sword2/screen.h
+++ b/engines/sword2/screen.h
@@ -172,7 +172,7 @@ struct SpriteInfo {
uint16 type; // mask containing 'RDSPR_' bits specifying compression type, flip, transparency, etc
uint16 blend; // holds the blending values.
byte *data; // pointer to the sprite data
- byte *colourTable; // pointer to 16-byte colour table, only applicable to 16-col compression type
+ byte *colorTable; // pointer to 16-byte color table, only applicable to 16-col compression type
bool isText; // It is a engine-generated sprite containing text
};
@@ -442,8 +442,8 @@ public:
void buildDisplay();
- void plotPoint(int x, int y, uint8 colour);
- void drawLine(int x0, int y0, int x1, int y1, uint8 colour);
+ void plotPoint(int x, int y, uint8 color);
+ void drawLine(int x0, int y0, int x1, int y1, uint8 color);
void rollCredits();
void splashScreen();
diff --git a/engines/sword2/scroll.cpp b/engines/sword2/scroll.cpp
index eb080eb4b3..11ba546cf3 100644
--- a/engines/sword2/scroll.cpp
+++ b/engines/sword2/scroll.cpp
@@ -73,7 +73,7 @@ void Screen::setScrolling() {
return;
}
- // George's offset from the centre - the desired position for him
+ // George's offset from the center - the desired position for him
int16 offset_x = _thisScreen.player_feet_x - _thisScreen.feet_x;
int16 offset_y = _thisScreen.player_feet_y - _thisScreen.feet_y;
diff --git a/engines/sword2/sound.cpp b/engines/sword2/sound.cpp
index 261c8293bd..3cf8523113 100644
--- a/engines/sword2/sound.cpp
+++ b/engines/sword2/sound.cpp
@@ -39,6 +39,7 @@
#include "common/file.h"
#include "common/memstream.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
diff --git a/engines/sword2/sound.h b/engines/sword2/sound.h
index 2c4c8364c7..c37e006b76 100644
--- a/engines/sword2/sound.h
+++ b/engines/sword2/sound.h
@@ -39,6 +39,7 @@
#define SWORD2_SOUND_H
#include "common/file.h"
+#include "common/mutex.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
diff --git a/engines/sword2/speech.cpp b/engines/sword2/speech.cpp
index a0ddc333c2..ec8e198377 100644
--- a/engines/sword2/speech.cpp
+++ b/engines/sword2/speech.cpp
@@ -27,6 +27,7 @@
#include "common/file.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -104,16 +105,16 @@ void Logic::locateTalker(int32 *params) {
uint16 scale = obMega.calcScale();
- // Calc suitable centre point above the head, based on scaled
+ // Calc suitable center point above the head, based on scaled
// height
- // just use 'feet_x' as centre
+ // just use 'feet_x' as center
_textX = obMega.getFeetX();
// Add scaled y-offset to feet_y coord to get top of sprite
_textY = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
} else {
- // It's a non-scaling anim - calc suitable centre point above
+ // It's a non-scaling anim - calc suitable center point above
// the head, based on scaled width
// x-coord + half of width
@@ -185,7 +186,7 @@ void Logic::formText(int32 *params) {
text + 2, _textX, _textY,
textWidth, obSpeech.getPen(),
RDSPR_TRANS | RDSPR_DISPLAYALIGN,
- _vm->_speechFontId, POSITION_AT_CENTRE_OF_BASE);
+ _vm->_speechFontId, POSITION_AT_CENTER_OF_BASE);
_vm->_resman->closeResource(text_res);
diff --git a/engines/sword2/sprite.cpp b/engines/sword2/sprite.cpp
index 255176292a..9a25812178 100644
--- a/engines/sword2/sprite.cpp
+++ b/engines/sword2/sprite.cpp
@@ -51,7 +51,7 @@ void Screen::mirrorSprite(byte *dst, byte *src, int16 w, int16 h) {
}
/**
- * This function takes a compressed frame of a sprite with up to 256 colours
+ * This function takes a compressed frame of a sprite with up to 256 colors
* and decompresses it.
* @param dst destination buffer
* @param src source buffer
@@ -82,7 +82,7 @@ int32 Screen::decompressRLE256(byte *dst, byte *src, int32 decompSize) {
break;
}
- // set the next 'headerByte' pixels to the next colour
+ // set the next 'headerByte' pixels to the next color
// at 'source'
memset(dst, *src, headerByte);
@@ -90,7 +90,7 @@ int32 Screen::decompressRLE256(byte *dst, byte *src, int32 decompSize) {
// block
dst += headerByte;
- // increment source pointer to just after this colour
+ // increment source pointer to just after this color
src++;
// if we've decompressed all of the data
@@ -135,7 +135,7 @@ int32 Screen::decompressRLE256(byte *dst, byte *src, int32 decompSize) {
}
/**
- * Unwinds a run of 16-colour data into 256-colour palette data.
+ * Unwinds a run of 16-color data into 256-color palette data.
*/
void Screen::unwindRaw16(byte *dst, byte *src, uint16 blockSize, byte *colTable) {
@@ -143,11 +143,11 @@ void Screen::unwindRaw16(byte *dst, byte *src, uint16 blockSize, byte *colTable)
while (blockSize > 1) {
if (Sword2Engine::isPsx()) {
- // 1st colour = number in table at position given by upper
+ // 1st color = number in table at position given by upper
// nibble of source byte
*dst++ = colTable[(*src) & 0x0f];
- // 2nd colour = number in table at position given by lower
+ // 2nd color = number in table at position given by lower
// nibble of source byte
*dst++ = colTable[(*src) >> 4];
} else {
@@ -165,19 +165,19 @@ void Screen::unwindRaw16(byte *dst, byte *src, uint16 blockSize, byte *colTable)
// if there's a final odd pixel
if (blockSize) {
- // colour = number in table at position given by upper nibble
+ // color = number in table at position given by upper nibble
// of source byte
*dst++ = colTable[(*src) >> 4];
}
}
/**
- * This function takes a compressed frame of a sprite (with up to 16 colours)
+ * This function takes a compressed frame of a sprite (with up to 16 colors)
* and decompresses it.
* @param dst destination buffer
* @param src source buffer
* @param decompSize the expected size of the uncompressed sprite
- * @param colTable mapping from the 16 encoded colours to the current palette
+ * @param colTable mapping from the 16 encoded colors to the current palette
*/
int32 Screen::decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable) {
@@ -199,14 +199,14 @@ int32 Screen::decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colT
}
// set the next 'headerByte' pixels to the next
- // colour at 'source'
+ // color at 'source'
memset(dst, *src, headerByte);
// increment destination pointer to just after this
// block
dst += headerByte;
- // increment source pointer to just after this colour
+ // increment source pointer to just after this color
src++;
// if we've decompressed all of the data
@@ -470,13 +470,13 @@ void Screen::deleteSurface(byte *surface) {
* RDSPR_DISPLAYALIGN The sprite is drawn relative to the top left corner
* of the screen
* RDSPR_FLIP The sprite is mirrored
- * RDSPR_TRANS The sprite has a transparent colour zero
+ * RDSPR_TRANS The sprite has a transparent color zero
* RDSPR_BLEND The sprite is translucent
* RDSPR_SHADOW The sprite is affected by the light mask. (Scaled
* sprites always are.)
* RDSPR_NOCOMPRESSION The sprite data is not compressed
- * RDSPR_RLE16 The sprite data is a 16-colour compressed sprite
- * RDSPR_RLE256 The sprite data is a 256-colour compressed sprite
+ * RDSPR_RLE16 The sprite data is a 16-color compressed sprite
+ * RDSPR_RLE256 The sprite data is a 256-color compressed sprite
* @param s all the information needed to draw the sprite
* @warning Sprites will only be drawn onto the background, not over menubar
* areas.
@@ -538,7 +538,7 @@ int32 Screen::drawSprite(SpriteInfo *s) {
byte *tempBuf2 = (byte *)malloc(s->w * s->h * 10);
memset(tempBuf2, 0, s->w * s->h * 2);
- unwindRaw16(tempBuf2, tempBuf, (s->w * (s->h / 2)), s->colourTable);
+ unwindRaw16(tempBuf2, tempBuf, (s->w * (s->h / 2)), s->colorTable);
sprite = (byte *)malloc(s->w * s->h);
if (!sprite) {
@@ -557,7 +557,7 @@ int32 Screen::drawSprite(SpriteInfo *s) {
if (!sprite)
return RDERR_OUTOFMEMORY;
- if (decompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) {
+ if (decompressRLE16(sprite, s->data, s->w * s->h, s->colorTable)) {
free(sprite);
return RDERR_DECOMPRESSION;
}
diff --git a/engines/sword2/startup.cpp b/engines/sword2/startup.cpp
index e4572d3c1a..ea1751eb5f 100644
--- a/engines/sword2/startup.cpp
+++ b/engines/sword2/startup.cpp
@@ -27,6 +27,7 @@
#include "common/file.h"
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index 9c67fcdf25..58f3547ff7 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -34,6 +34,7 @@
#include "common/EventRecorder.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "engines/metaengine.h"
#include "engines/util.h"
@@ -319,11 +320,10 @@ void Sword2Engine::registerDefaultSettings() {
}
void Sword2Engine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
bool mute = ConfMan.getBool("mute");
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, mute ? 0 : ConfMan.getInt("music_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : ConfMan.getInt("sfx_volume"));
setSubtitles(ConfMan.getBool("subtitles"));
// Our own settings dialog can mute the music, speech and sound effects
diff --git a/engines/sword2/sync.cpp b/engines/sword2/sync.cpp
index 1adc652b75..ee4c6b2238 100644
--- a/engines/sword2/sync.cpp
+++ b/engines/sword2/sync.cpp
@@ -26,6 +26,7 @@
*/
+#include "common/textconsole.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
diff --git a/engines/sword25/detection.cpp b/engines/sword25/detection.cpp
index 3900df2fcf..fe24675f8a 100644
--- a/engines/sword25/detection.cpp
+++ b/engines/sword25/detection.cpp
@@ -24,8 +24,6 @@
*/
#include "base/plugins.h"
-#include "common/savefile.h"
-#include "common/system.h"
#include "engines/advancedDetector.h"
#include "sword25/sword25.h"
diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp
index 177bd38303..975f08be22 100644
--- a/engines/sword25/fmv/movieplayer.cpp
+++ b/engines/sword25/fmv/movieplayer.cpp
@@ -32,13 +32,17 @@
*
*/
+#include "common/debug.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "common/util.h"
+
#include "sword25/sword25.h" // for kDebugScript
#include "sword25/fmv/movieplayer.h"
#include "sword25/gfx/graphicengine.h"
#include "sword25/gfx/panel.h"
#include "sword25/kernel/kernel.h"
#include "sword25/package/packagemanager.h"
-#include "sword25/sfx/soundengine.h"
namespace Sword25 {
@@ -121,7 +125,7 @@ void MoviePlayer::update() {
const Graphics::Surface *s = _decoder.decodeNextFrame();
if (s) {
// Transfer the next frame
- assert(s->bytesPerPixel == 4);
+ assert(s->format.bytesPerPixel == 4);
#ifdef THEORA_INDIRECT_RENDERING
byte *frameData = (byte *)s->getBasePtr(0, 0);
diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp
index e9901c04b0..86236fbd21 100644
--- a/engines/sword25/fmv/theora_decoder.cpp
+++ b/engines/sword25/fmv/theora_decoder.cpp
@@ -41,6 +41,7 @@
#ifdef USE_THEORADEC
#include "common/system.h"
+#include "common/textconsole.h"
#include "graphics/conversion.h"
#include "audio/decoders/raw.h"
#include "sword25/kernel/common.h"
@@ -289,7 +290,7 @@ bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
_surface = new Graphics::Surface();
- _surface->create(_theoraInfo.frame_width, _theoraInfo.frame_height, 4);
+ _surface->create(_theoraInfo.frame_width, _theoraInfo.frame_height, g_system->getScreenFormat());
return true;
}
diff --git a/engines/sword25/fmv/theora_decoder.h b/engines/sword25/fmv/theora_decoder.h
index a753bc58ac..4ed2af5f98 100644
--- a/engines/sword25/fmv/theora_decoder.h
+++ b/engines/sword25/fmv/theora_decoder.h
@@ -30,9 +30,12 @@
#ifdef USE_THEORADEC
+#include "common/rational.h"
#include "video/video_decoder.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
#include <theora/theoradec.h>
#include <vorbis/codec.h>
diff --git a/engines/sword25/gfx/graphicengine.cpp b/engines/sword25/gfx/graphicengine.cpp
index 5fefcec420..8bdf2a4a6e 100644
--- a/engines/sword25/gfx/graphicengine.cpp
+++ b/engines/sword25/gfx/graphicengine.cpp
@@ -112,8 +112,10 @@ bool GraphicEngine::init(int width, int height, int bitDepth, int backbufferCoun
_screenRect.right = _width;
_screenRect.bottom = _height;
- _backSurface.create(width, height, 4);
- _frameBuffer.create(width, height, 4);
+ const Graphics::PixelFormat format = g_system->getScreenFormat();
+
+ _backSurface.create(width, height, format);
+ _frameBuffer.create(width, height, format);
// Standardmäßig ist Vsync an.
setVsync(true);
@@ -206,6 +208,7 @@ bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) {
for (int i = rect.top; i < rect.bottom; i++) {
out = outo;
for (int j = rect.left; j < rect.right; j++) {
+#if defined(SCUMM_LITTLE_ENDIAN)
*out += (byte)(((cb - *out) * ca) >> 8);
out++;
*out += (byte)(((cg - *out) * ca) >> 8);
@@ -214,6 +217,16 @@ bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) {
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++;
+#endif
}
outo += _backSurface.pitch;
diff --git a/engines/sword25/gfx/graphicengine_script.cpp b/engines/sword25/gfx/graphicengine_script.cpp
index d67d0038c3..d8daaab32c 100644
--- a/engines/sword25/gfx/graphicengine_script.cpp
+++ b/engines/sword25/gfx/graphicengine_script.cpp
@@ -81,26 +81,6 @@ static ActionCallback *actionCallbackPtr = 0; // FIXME: should be turned into Gr
#define ANIMATION_TEMPLATE_CLASS_NAME "Gfx.AnimationTemplate"
static const char *GFX_LIBRARY_NAME = "Gfx";
-// Wie luaL_checkudata, nur ohne dass kein Fehler erzeugt wird.
-static void *my_checkudata(lua_State *L, int ud, const char *tname) {
- int top = lua_gettop(L);
-
- void *p = lua_touserdata(L, ud);
- if (p != NULL) { /* value is a userdata? */
- if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
- // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
- LuaBindhelper::getMetatable(L, tname);
- if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
- lua_settop(L, top);
- return p;
- }
- }
- }
-
- lua_settop(L, top);
- return NULL;
-}
-
static void newUintUserData(lua_State *L, uint value) {
void *userData = lua_newuserdata(L, sizeof(value));
memcpy(userData, &value, sizeof(value));
@@ -108,8 +88,8 @@ static void newUintUserData(lua_State *L, uint value) {
static AnimationTemplate *checkAnimationTemplate(lua_State *L, int idx = 1) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.AnimationTemplate
- uint animationTemplateHandle;
- if ((animationTemplateHandle = *reinterpret_cast<uint *>(my_checkudata(L, idx, ANIMATION_TEMPLATE_CLASS_NAME))) != 0) {
+ uint animationTemplateHandle = *reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, idx, ANIMATION_TEMPLATE_CLASS_NAME));
+ if (animationTemplateHandle != 0) {
AnimationTemplate *animationTemplatePtr = AnimationTemplateRegistry::instance().resolveHandle(animationTemplateHandle);
if (!animationTemplatePtr)
luaL_error(L, "The animation template with the handle %d does no longer exist.", animationTemplateHandle);
@@ -370,10 +350,10 @@ static const luaL_reg GFX_FUNCTIONS[] = {
static RenderObjectPtr<RenderObject> checkRenderObject(lua_State *L, bool errorIfRemoved = true) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable einer Klasse haben, die von Gfx.RenderObject "erbt".
uint *userDataPtr;
- if ((userDataPtr = (uint *) my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0 ||
- (userDataPtr = (uint *) my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0 ||
- (userDataPtr = (uint *) my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0 ||
- (userDataPtr = (uint *) my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0 ||
+ (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0 ||
+ (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0 ||
+ (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
if (roPtr.isValid())
return roPtr;
@@ -600,11 +580,11 @@ static const luaL_reg RENDEROBJECT_METHODS[] = {
static RenderObjectPtr<Panel> checkPanel(lua_State *L) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Panel
uint *userDataPtr;
- if ((userDataPtr = (uint *)my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
- if (roPtr.isValid()) {
+ if (roPtr.isValid())
return roPtr->toPanel();
- } else
+ else
luaL_error(L, "The panel with the handle %d does no longer exist.", *userDataPtr);
} else {
luaL_argcheck(L, 0, 1, "'" PANEL_CLASS_NAME "' expected");
@@ -645,11 +625,11 @@ static const luaL_reg PANEL_METHODS[] = {
static RenderObjectPtr<Bitmap> checkBitmap(lua_State *L) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Bitmap
uint *userDataPtr;
- if ((userDataPtr = (uint *)my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
- if (roPtr.isValid()) {
+ if (roPtr.isValid())
return roPtr->toBitmap();
- } else
+ else
luaL_error(L, "The bitmap with the handle %d does no longer exist.", *userDataPtr);
} else {
luaL_argcheck(L, 0, 1, "'" BITMAP_CLASS_NAME "' expected");
@@ -790,13 +770,12 @@ static const luaL_reg BITMAP_METHODS[] = {
static RenderObjectPtr<Animation> checkAnimation(lua_State *L) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Animation
uint *userDataPtr;
- if ((userDataPtr = (uint *)my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
if (roPtr.isValid())
return roPtr->toAnimation();
- else {
+ else
luaL_error(L, "The animation with the handle %d does no longer exist.", *userDataPtr);
- }
} else {
luaL_argcheck(L, 0, 1, "'" ANIMATION_CLASS_NAME "' expected");
}
@@ -1064,7 +1043,7 @@ static const luaL_reg ANIMATION_METHODS[] = {
static RenderObjectPtr<Text> checkText(lua_State *L) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Text
uint *userDataPtr;
- if ((userDataPtr = (uint *)my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) {
+ if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) {
RenderObjectPtr<RenderObject> roPtr(*userDataPtr);
if (roPtr.isValid())
return roPtr->toText();
diff --git a/engines/sword25/gfx/image/art.cpp b/engines/sword25/gfx/image/art.cpp
index d30460901d..69f9425a53 100644
--- a/engines/sword25/gfx/image/art.cpp
+++ b/engines/sword25/gfx/image/art.cpp
@@ -1041,7 +1041,7 @@ static void art_pri_free(ArtPriQ *pq) {
free(pq);
}
-static art_boolean art_pri_empty(ArtPriQ *pq) {
+static bool art_pri_empty(ArtPriQ *pq) {
return pq->n_items == 0;
}
@@ -1122,7 +1122,7 @@ static int art_svp_writer_rewind_add_segment(ArtSvpWriter *self, int wind_left,
ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
ArtSVP *svp;
ArtSVPSeg *seg;
- art_boolean left_filled = 0, right_filled = 0;
+ bool left_filled = 0, right_filled = 0;
int wind_right = wind_left + delta_wind;
int seg_num;
const int init_n_points_max = 4;
@@ -1459,7 +1459,7 @@ static ArtActiveSeg *art_svp_intersect_add_point(ArtIntersectCtx *ctx, double x,
ArtActiveSeg *seg, ArtBreakFlags break_flags) {
ArtActiveSeg *left, *right;
double x_min = x, x_max = x;
- art_boolean left_live, right_live;
+ bool left_live, right_live;
double d;
double new_x;
ArtActiveSeg *test, *result = NULL;
@@ -1490,9 +1490,9 @@ static ArtActiveSeg *art_svp_intersect_add_point(ArtIntersectCtx *ctx, double x,
left = left->left;
left_live = (left != NULL);
} else
- left_live = ART_FALSE;
+ left_live = false;
} else
- left_live = ART_FALSE;
+ left_live = false;
} else if (right_live) {
if (x >= right->x[(right->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] &&
/* It may be that one of these conjuncts turns out to be always
@@ -1510,9 +1510,9 @@ static ArtActiveSeg *art_svp_intersect_add_point(ArtIntersectCtx *ctx, double x,
right = right->right;
right_live = (right != NULL);
} else
- right_live = ART_FALSE;
+ right_live = false;
} else
- right_live = ART_FALSE;
+ right_live = false;
}
}
@@ -1571,7 +1571,7 @@ static void art_svp_intersect_swap_active(ArtIntersectCtx *ctx,
* Return value: True if the intersection took place at the current
* scan line, indicating further iteration is needed.
**/
-static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
+static bool art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
ArtActiveSeg *left_seg, ArtActiveSeg *right_seg,
ArtBreakFlags break_flags) {
double left_x0, left_y0, left_x1;
@@ -1597,17 +1597,17 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if (left_x1 <
right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] ||
left_y1 == right_seg->y0)
- return ART_FALSE;
+ return false;
d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
if (d < -EPSILON_A)
- return ART_FALSE;
+ return false;
else if (d < EPSILON_A) {
/* I'm unsure about the break flags here. */
double right_x1 = art_svp_intersect_break(ctx, right_seg,
left_x1, left_y1,
ART_BREAK_RIGHT);
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
} else if (left_y1 > right_y1) {
/* Test right (x1, y1) against left segment */
@@ -1615,27 +1615,27 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] ||
right_y1 == left_seg->y0)
- return ART_FALSE;
+ return false;
d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c;
if (d > EPSILON_A)
- return ART_FALSE;
+ return false;
else if (d > -EPSILON_A) {
/* See above regarding break flags. */
left_x1 = art_svp_intersect_break(ctx, left_seg,
right_x1, right_y1,
ART_BREAK_LEFT);
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
} else { /* left_y1 == right_y1 */
left_x1 = left_seg->x[1];
double right_x1 = right_seg->x[1];
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
art_svp_intersect_swap_active(ctx, left_seg, right_seg);
- return ART_TRUE;
+ return true;
}
if (left_y1 < right_y1) {
@@ -1645,16 +1645,16 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if (left_x1 <
right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] ||
left_y1 == right_seg->y0)
- return ART_FALSE;
+ return false;
d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
if (d < -EPSILON_A)
- return ART_FALSE;
+ return false;
else if (d < EPSILON_A) {
double right_x1 = art_svp_intersect_break(ctx, right_seg,
left_x1, left_y1,
ART_BREAK_RIGHT);
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
} else if (left_y1 > right_y1) {
/* Test right (x1, y1) against left segment */
@@ -1662,23 +1662,23 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] ||
right_y1 == left_seg->y0)
- return ART_FALSE;
+ return false;
d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c;
if (d > EPSILON_A)
- return ART_FALSE;
+ return false;
else if (d > -EPSILON_A) {
left_x1 = art_svp_intersect_break(ctx, left_seg,
right_x1, right_y1,
ART_BREAK_LEFT);
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
} else { /* left_y1 == right_y1 */
left_x1 = left_seg->x[1];
double right_x1 = right_seg->x[1];
if (left_x1 <= right_x1)
- return ART_FALSE;
+ return false;
}
/* The segments cross. Find the intersection point. */
@@ -1748,7 +1748,7 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
winner->horiz_delta_wind -= loser->delta_wind;
art_svp_intersect_swap_active(ctx, left_seg, right_seg);
- return ART_TRUE;
+ return true;
}
} else if (y == right_seg->y0) {
art_svp_intersect_push_pt(ctx, left_seg, x, y);
@@ -1764,7 +1764,7 @@ static art_boolean art_svp_intersect_test_cross(ArtIntersectCtx *ctx,
if ((break_flags & ART_BREAK_RIGHT) && right_seg->right != NULL)
art_svp_intersect_add_point(ctx, x, y, right_seg->right, break_flags);
}
- return ART_FALSE;
+ return false;
}
/**
@@ -1885,7 +1885,7 @@ static void art_svp_intersect_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg,
if (x0 > x1) {
ArtActiveSeg *left;
- art_boolean first = ART_TRUE;
+ bool first = true;
for (left = seg->left; left != NULL; left = seg->left) {
int left_bneg = left->flags & ART_ACTIVE_FLAGS_BNEG;
@@ -1902,12 +1902,12 @@ static void art_svp_intersect_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg,
if (first && left->right != NULL) {
art_svp_intersect_test_cross(ctx, left, left->right,
ART_BREAK_RIGHT);
- first = ART_FALSE;
+ first = false;
}
}
} else {
ArtActiveSeg *right;
- art_boolean first = ART_TRUE;
+ bool first = true;
for (right = seg->right; right != NULL; right = seg->right) {
int right_bneg = right->flags & ART_ACTIVE_FLAGS_BNEG;
@@ -1925,7 +1925,7 @@ static void art_svp_intersect_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg,
if (first && right->left != NULL) {
art_svp_intersect_test_cross(ctx, right->left, right,
ART_BREAK_RIGHT);
- first = ART_FALSE;
+ first = false;
}
}
}
@@ -2231,7 +2231,7 @@ void art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out) {
typedef double artfloat;
-struct _ArtSVPRenderAAIter {
+struct ArtSVPRenderAAIter {
const ArtSVP *svp;
int x0, x1;
int y;
diff --git a/engines/sword25/gfx/image/art.h b/engines/sword25/gfx/image/art.h
index 90baa770cf..fe3bbd4982 100644
--- a/engines/sword25/gfx/image/art.h
+++ b/engines/sword25/gfx/image/art.h
@@ -42,10 +42,6 @@
namespace Sword25 {
-typedef byte art_u8;
-typedef uint16 art_u16;
-typedef uint32 art_u32;
-
/* These aren't, strictly speaking, configuration macros, but they're
damn handy to have around, and may be worth playing with for
debugging. */
@@ -55,95 +51,55 @@ typedef uint32 art_u32;
/* This one must be used carefully - in particular, p and max should
be variables. They can also be pstruct->el lvalues. */
-#define art_expand(p, type, max) do { if(max) { p = art_renew (p, type, max <<= 1); } else { max = 1; p = art_new(type, 1); } } while (0)
-
-typedef int art_boolean;
-#define ART_FALSE 0
-#define ART_TRUE 1
-
-/* define pi */
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif /* M_PI */
-
-#ifndef M_SQRT2
-#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
-#endif /* M_SQRT2 */
-
-/* Provide macros to feature the GCC function attribute.
- */
-#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
-#define ART_GNUC_PRINTF( format_idx, arg_idx ) \
- __attribute__((__format__ (__printf__, format_idx, arg_idx)))
-#define ART_GNUC_NORETURN \
- __attribute__((__noreturn__))
-#else /* !__GNUC__ */
-#define ART_GNUC_PRINTF( format_idx, arg_idx )
-#define ART_GNUC_NORETURN
-#endif /* !__GNUC__ */
-
-void ART_GNUC_NORETURN
-art_die(const char *fmt, ...) ART_GNUC_PRINTF(1, 2);
-
-void
-art_warn(const char *fmt, ...) ART_GNUC_PRINTF(1, 2);
-
-typedef struct _ArtDRect ArtDRect;
-typedef struct _ArtIRect ArtIRect;
-
-struct _ArtDRect {
+#define art_expand(p, type, max) \
+ do { \
+ if(max) {\
+ p = art_renew(p, type, max <<= 1); \
+ } else { \
+ max = 1; \
+ p = art_new(type, 1); \
+ } \
+ } while (0)
+
+struct ArtDRect {
/*< public >*/
double x0, y0, x1, y1;
};
-struct _ArtIRect {
- /*< public >*/
- int x0, y0, x1, y1;
-};
-
-typedef struct _ArtPoint ArtPoint;
-
-struct _ArtPoint {
+struct ArtPoint {
/*< public >*/
double x, y;
};
/* Basic data structures and constructors for sorted vector paths */
-typedef struct _ArtSVP ArtSVP;
-typedef struct _ArtSVPSeg ArtSVPSeg;
-
-struct _ArtSVPSeg {
+struct ArtSVPSeg {
int n_points;
int dir; /* == 0 for "up", 1 for "down" */
ArtDRect bbox;
ArtPoint *points;
};
-struct _ArtSVP {
+struct ArtSVP {
int n_segs;
ArtSVPSeg segs[1];
};
-void
-art_svp_free(ArtSVP *svp);
+void art_svp_free(ArtSVP *svp);
-int
-art_svp_seg_compare(const void *s1, const void *s2);
+int art_svp_seg_compare(const void *s1, const void *s2);
/* Basic data structures and constructors for bezier paths */
-typedef enum {
+enum ArtPathcode {
ART_MOVETO,
ART_MOVETO_OPEN,
ART_CURVETO,
ART_LINETO,
ART_END
-} ArtPathcode;
-
-typedef struct _ArtBpath ArtBpath;
+};
-struct _ArtBpath {
+struct ArtBpath {
/*< public >*/
ArtPathcode code;
double x1;
@@ -156,10 +112,8 @@ struct _ArtBpath {
/* Basic data structures and constructors for simple vector paths */
-typedef struct _ArtVpath ArtVpath;
-
/* CURVETO is not allowed! */
-struct _ArtVpath {
+struct ArtVpath {
ArtPathcode code;
double x;
double y;
@@ -167,8 +121,7 @@ struct _ArtVpath {
/* Some of the functions need to go into their own modules */
-void
-art_vpath_add_point(ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
+void art_vpath_add_point(ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
ArtPathcode code, double x, double y);
ArtVpath *art_bez_path_to_vec(const ArtBpath *bez, double flatness);
@@ -177,57 +130,49 @@ ArtVpath *art_bez_path_to_vec(const ArtBpath *bez, double flatness);
#ifndef ART_WIND_RULE_DEFINED
#define ART_WIND_RULE_DEFINED
-typedef enum {
+enum ArtWindRule {
ART_WIND_RULE_NONZERO,
ART_WIND_RULE_INTERSECT,
ART_WIND_RULE_ODDEVEN,
ART_WIND_RULE_POSITIVE
-} ArtWindRule;
+};
#endif
-typedef struct _ArtSvpWriter ArtSvpWriter;
-
-struct _ArtSvpWriter {
+struct ArtSvpWriter {
int (*add_segment)(ArtSvpWriter *self, int wind_left, int delta_wind,
double x, double y);
void (*add_point)(ArtSvpWriter *self, int seg_id, double x, double y);
void (*close_segment)(ArtSvpWriter *self, int seg_id);
};
-ArtSvpWriter *
-art_svp_writer_rewind_new(ArtWindRule rule);
+ArtSvpWriter *art_svp_writer_rewind_new(ArtWindRule rule);
-ArtSVP *
-art_svp_writer_rewind_reap(ArtSvpWriter *self);
+ArtSVP *art_svp_writer_rewind_reap(ArtSvpWriter *self);
-int
-art_svp_seg_compare(const void *s1, const void *s2);
+int art_svp_seg_compare(const void *s1, const void *s2);
-void
-art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out);
+void art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out);
/* Sort vector paths into sorted vector paths. */
-ArtSVP *
-art_svp_from_vpath(ArtVpath *vpath);
+ArtSVP *art_svp_from_vpath(ArtVpath *vpath);
/* Sort vector paths into sorted vector paths. */
-typedef enum {
+enum ArtPathStrokeJoinType {
ART_PATH_STROKE_JOIN_MITER,
ART_PATH_STROKE_JOIN_ROUND,
ART_PATH_STROKE_JOIN_BEVEL
-} ArtPathStrokeJoinType;
+};
-typedef enum {
+enum ArtPathStrokeCapType {
ART_PATH_STROKE_CAP_BUTT,
ART_PATH_STROKE_CAP_ROUND,
ART_PATH_STROKE_CAP_SQUARE
-} ArtPathStrokeCapType;
+};
-ArtSVP *
-art_svp_vpath_stroke(ArtVpath *vpath,
+ArtSVP *art_svp_vpath_stroke(ArtVpath *vpath,
ArtPathStrokeJoinType join,
ArtPathStrokeCapType cap,
double line_width,
@@ -235,8 +180,7 @@ art_svp_vpath_stroke(ArtVpath *vpath,
double flatness);
/* This version may have winding numbers exceeding 1. */
-ArtVpath *
-art_svp_vpath_stroke_raw(ArtVpath *vpath,
+ArtVpath *art_svp_vpath_stroke_raw(ArtVpath *vpath,
ArtPathStrokeJoinType join,
ArtPathStrokeCapType cap,
double line_width,
@@ -246,27 +190,22 @@ art_svp_vpath_stroke_raw(ArtVpath *vpath,
/* The spiffy antialiased renderer for sorted vector paths. */
-typedef struct _ArtSVPRenderAAStep ArtSVPRenderAAStep;
-typedef struct _ArtSVPRenderAAIter ArtSVPRenderAAIter;
-
-struct _ArtSVPRenderAAStep {
+struct ArtSVPRenderAAStep {
int x;
int delta; /* stored with 16 fractional bits */
};
-ArtSVPRenderAAIter *
-art_svp_render_aa_iter(const ArtSVP *svp,
+struct ArtSVPRenderAAIter;
+
+ArtSVPRenderAAIter *art_svp_render_aa_iter(const ArtSVP *svp,
int x0, int y0, int x1, int y1);
-void
-art_svp_render_aa_iter_step(ArtSVPRenderAAIter *iter, int *p_start,
+void art_svp_render_aa_iter_step(ArtSVPRenderAAIter *iter, int *p_start,
ArtSVPRenderAAStep **p_steps, int *p_n_steps);
-void
-art_svp_render_aa_iter_done(ArtSVPRenderAAIter *iter);
+void art_svp_render_aa_iter_done(ArtSVPRenderAAIter *iter);
-void
-art_svp_render_aa(const ArtSVP *svp,
+void art_svp_render_aa(const ArtSVP *svp,
int x0, int y0, int x1, int y1,
void (*callback)(void *callback_data,
int y,
diff --git a/engines/sword25/gfx/image/image.h b/engines/sword25/gfx/image/image.h
index 5ac6d1ac25..7029402c4a 100644
--- a/engines/sword25/gfx/image/image.h
+++ b/engines/sword25/gfx/image/image.h
@@ -55,75 +55,72 @@ public:
// Enums
/**
- @brief Die möglichen Flippingparameter für die Blit-Methode.
+ @brief The possible flipping parameters for the blit methode.
*/
enum FLIP_FLAGS {
- /// Das Bild wird nicht gespiegelt.
+ /// The image will not be flipped.
FLIP_NONE = 0,
- /// Das Bild wird an der horizontalen Achse gespiegelt.
+ /// The image will be flipped at the horizontal axis.
FLIP_H = 1,
- /// Das Bild wird an der vertikalen Achse gespiegelt.
+ /// The image will be flipped at the vertical axis.
FLIP_V = 2,
- /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt.
+ /// The image will be flipped at the horizontal and vertical axis.
FLIP_HV = FLIP_H | FLIP_V,
- /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt.
+ /// The image will be flipped at the horizontal and vertical axis.
FLIP_VH = FLIP_H | FLIP_V
};
//@{
- /** @name Accessor-Methoden */
+ /** @name Accessor methods */
/**
- @brief Gibt die Breite des Bildes in Pixeln zurück
+ @brief Returns the width of the image in pixels
*/
virtual int getWidth() const = 0;
/**
- @brief Gibt die Höhe des Bildes in Pixeln zurück
+ @brief Returns the height of the image in pixels
*/
virtual int getHeight() const = 0;
/**
- @brief Gibt das Farbformat des Bildes zurück
+ @brief Returns the color format of the image
*/
virtual GraphicEngine::COLOR_FORMATS getColorFormat() const = 0;
//@}
//@{
- /** @name Render-Methoden */
+ /** @name Render methodes */
/**
- @brief Rendert das Bild in den Framebuffer.
- @param pDest ein Pointer auf das Zielbild. In den meisten Fällen ist dies der Framebuffer.
- @param PosX die Position auf der X-Achse im Zielbild in Pixeln, an der das Bild gerendert werden soll.<br>
- Der Standardwert ist 0.
- @param PosY die Position auf der Y-Achse im Zielbild in Pixeln, an der das Bild gerendert werden soll.<br>
- Der Standardwert ist 0.
- @param Flipping gibt an, wie das Bild gespiegelt werden soll.<br>
- Der Standardwert ist BS_Image::FLIP_NONE (keine Spiegelung)
- @param pSrcPartRect Pointer auf ein Common::Rect, welches den Ausschnitt des Quellbildes spezifiziert, der gerendert
- werden soll oder NULL, falls das gesamte Bild gerendert werden soll.<br>
- Dieser Ausschnitt bezieht sich auf das ungespiegelte und unskalierte Bild.<br>
- Der Standardwert ist NULL.
- @param Color ein ARGB Farbwert, der die Parameter für die Farbmodulation und fürs Alphablending festlegt.<br>
- Die Alpha-Komponente der Farbe bestimmt den Alphablending Parameter (0 = keine Deckung, 255 = volle Deckung).<br>
- Die Farbkomponenten geben die Farbe für die Farbmodulation an.<br>
- Der Standardwert is BS_ARGB(255, 255, 255, 255) (volle Deckung, keine Farbmodulation).
- Zum Erzeugen des Farbwertes können die Makros BS_RGB und BS_ARGB benutzt werden.
- @param Width gibt die Ausgabebreite des Bildausschnittes an.
- Falls diese von der Breite des Bildausschnittes abweicht wird
- das Bild entsprechend Skaliert.<br>
- Der Wert -1 gibt an, dass das Bild nicht Skaliert werden soll.<br>
- Der Standardwert ist -1.
- @param Width gibt die Ausgabehöhe des Bildausschnittes an.
- Falls diese von der Höhe des Bildauschnittes abweicht, wird
- das Bild entsprechend Skaliert.<br>
- Der Wert -1 gibt an, dass das Bild nicht Skaliert werden soll.<br>
- Der Standardwert ist -1.
- @return Gibt false zurück, falls das Rendern fehlgeschlagen ist.
- @remark Er werden nicht alle Blitting-Operationen von allen BS_Image-Klassen unterstützt.<br>
- Mehr Informationen gibt es in der Klassenbeschreibung von BS_Image und durch folgende Methoden:
+ @brief renders the image in the framebuffer
+ @param pDest a pointer to the target image. In most cases this is the framebuffer.
+ @param PosX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.<br>
+ 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 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.
+ @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 Width 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.
+ @remark Not all blitting operations of all BS_Image classes are supported.<br>
+ More information can be find in the class description of BS_Image and the following methodes:
- IsBlitTarget()
- IsScalingAllowed()
- IsFillingAllowed()
@@ -138,79 +135,74 @@ public:
int width = -1, int height = -1) = 0;
/**
- @brief Füllt einen Rechteckigen Bereich des Bildes mit einer Farbe.
- @param pFillRect Pointer auf ein Common::Rect, welches den Ausschnitt des Bildes spezifiziert, der gefüllt
- werden soll oder NULL, falls das gesamte Bild gefüllt werden soll.<br>
- Der Standardwert ist NULL.
- @param Color der 32 Bit Farbwert mit dem der Bildbereich gefüllt werden soll.
- @remark Es ist möglich über die Methode transparente Rechtecke darzustellen, indem man eine Farbe mit einem Alphawert ungleich
- 255 angibt.
- @remark Unabhängig vom Farbformat des Bildes muss ein 32 Bit Farbwert angegeben werden. Zur Erzeugung, können die Makros
- BS_RGB und BS_ARGB benutzt werden.
- @remark Falls das Rechteck nicht völlig innerhalb des Bildschirms ist, wird es automatisch zurechtgestutzt.
+ @brief fills a rectangular section of the image with a color.
+ @param pFillRect Pointer on Common::Rect which specifies the section of the image which is supposed to be filled. If the whole image has to be filled this value is NULL.<br>
+ The default value is NULL.
+ @param Color the 32 Bit color value for filling the image section.
+ @remark It is possible to create transparent rectangulars by using a color with alpha value not equal to 255.
+ @remark Independent from the color format of the image, it must be given a 32 bit color value. The macros BS_RGB and BS_ARGB can be used for the creation of the color value.
+ @remark If the rectangular is not completely inside the screen area, it will be automatically trimmed.
*/
virtual bool fill(const Common::Rect *pFillRect = 0, uint color = BS_RGB(0, 0, 0)) = 0;
/**
- @brief Füllt den Inhalt des Bildes mit Pixeldaten.
- @param Pixeldata ein Vector der die Pixeldaten enthält. Sie müssen in dem Farbformat des Bildes vorliegen und es müssen genügend Daten
- vorhanden sein, um das ganze Bild zu füllen.
- @param Offset der Offset in Byte im Pixeldata-Vector an dem sich der erste zu schreibende Pixel befindet.<br>
- Der Standardwert ist 0.
- @param Stride der Abstand in Byte zwischen dem Zeilenende und dem Beginn einer neuen Zeile im Pixeldata-Vector.<br>
- Der Standardwert ist 0.
- @return Gibt false zurück, falls der Aufruf fehlgeschlagen ist.
- @remark Ein Aufruf dieser Methode ist nur erlaubt, wenn IsSetContentAllowed() true zurückgibt.
+ @brief Fills the content of the image with pixel data.
+ @param Pixeldata a vector which cotains the pixel data. They must be present in the color format of the image and there must be enough data available for filling the whole image.
+ @param Offset the offset in Byte in Pixeldata-Vector on which the first pixel to write is located.<br>
+ The default value is 0.
+ @param Stride the distance in Byte between the end of line and the beginning of a new line in Pixeldata-Vector.<br>
+ The default value is 0.
+ @return returns false, if the call failed.
+ @remark A call of this methode is only allowd if IsSetContentAllowed() returns true.
*/
virtual bool setContent(const byte *pixeldata, uint size, uint offset, uint stride) = 0;
/**
- @brief Liest einen Pixel des Bildes.
- @param X die X-Koordinate des Pixels.
- @param Y die Y-Koordinate des Pixels
- @return Gibt den 32-Bit Farbwert des Pixels an der übergebenen Koordinate zurück.
- @remark Diese Methode sollte auf keine Fall benutzt werden um größere Teile des Bildes zu lesen, da sie sehr langsam ist. Sie ist
- eher dafür gedacht einzelne Pixel des Bildes auszulesen.
+ @brief Reads out a pixel of the image.
+ @param X the X-coordinate of the pixel.
+ @param Y the y-coordinate of the pixel.
+ @return Returns the 32-bit color value of the pixel at the given position.
+ @remark This methode should not be used in no way to read out bigger parts of the image because the method is very slow. The method is rather intended for reading out single pixels of the image..
*/
virtual uint getPixel(int x, int y) = 0;
//@{
- /** @name Auskunfts-Methoden */
+ /** @name Information methodes */
/**
- @brief Überprüft, ob an dem BS_Image Blit() aufgerufen werden darf.
- @return Gibt false zurück, falls ein Blit()-Aufruf an diesem Objekt nicht gestattet ist.
+ @brief Checks, if it is allowed to call BS_Image Blit().
+ @return Returns false, if a Blit() call is not allowed at this object.
*/
virtual bool isBlitSource() const = 0;
/**
- @brief Überprüft, ob das BS_Image ein Zielbild für einen Blit-Aufruf sein kann.
- @return Gibt false zurück, falls ein Blit-Aufruf mit diesem Objekt als Ziel nicht gestattet ist.
+ @brief Checks, if the BS_Image can be a target image for a Blit call.
+ @return Returns false, if a Blit() call with this object as an target is not allowed.
*/
virtual bool isBlitTarget() const = 0;
/**
- @brief Gibt true zurück, falls das BS_Image bei einem Aufruf von Blit() skaliert dargestellt werden kann.
+ @brief Returns true, if the BS_Image is allowed to be scaled by a Blit() call.
*/
virtual bool isScalingAllowed() const = 0;
/**
- @brief Gibt true zurück, wenn das BS_Image mit einem Aufruf von Fill() gefüllt werden kann.
+ @brief Returns true, if the BS_Image is allowed to be filled by a Fill() call.
*/
virtual bool isFillingAllowed() const = 0;
/**
- @brief Gibt true zurück, wenn das BS_Image bei einem Aufruf von Blit() mit einem Alphawert dargestellt werden kann.
+ @brief Returns true, if the BS_Image is allowed to be displayed with an alpha value.
*/
virtual bool isAlphaAllowed() const = 0;
/**
- @brief Gibt true zurück, wenn das BS_Image bei einem Aufruf von Blit() mit Farbmodulation dargestellt werden kann.
+ @brief Return true, if the BS_Image is allowed to be displayed with color modulation by a Blit() call
*/
virtual bool isColorModulationAllowed() const = 0;
/**
- @brief Gibt true zurück, wenn der Inhalt des BS_Image durch eine Aufruf von SetContent() ausgetauscht werden kann.
+ @brief Returns true, if the content of the BS_Image is allowed to be replaced by call of SetContent().
*/
virtual bool isSetContentAllowed() const = 0;
diff --git a/engines/sword25/gfx/image/pngloader.cpp b/engines/sword25/gfx/image/pngloader.cpp
index f54b45254b..f6c00b6968 100644
--- a/engines/sword25/gfx/image/pngloader.cpp
+++ b/engines/sword25/gfx/image/pngloader.cpp
@@ -84,7 +84,7 @@ static uint findEmbeddedPNG(const byte *fileDataPtr, uint fileSize) {
Common::MemoryReadStream stream(fileDataPtr, fileSize);
stream.seek(0, SEEK_SET);
- // Headerinformationen der Spielstandes einlesen.
+ // Read header information of savegame
uint compressedGamedataSize;
loadString(stream); // Marker
loadString(stream); // Version
@@ -124,7 +124,7 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc
error("png_check_sig failed");
}
- // Die beiden PNG Strukturen erstellen
+ // Create both PNG structures
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
error("Could not create libpng read struct.");
@@ -135,31 +135,31 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc
error("Could not create libpng info struct.");
}
- // Alternative Lesefunktion benutzen
+ // Use alternative reading function
const byte **ref = &fileDataPtr;
png_set_read_fn(png_ptr, (void *)ref, png_user_read_data);
- // PNG Header einlesen
+ // Read PNG header
png_read_info(png_ptr, info_ptr);
- // PNG Informationen auslesen
+ // Read out PNG informations
png_uint_32 w, h;
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL);
width = w;
height = h;
- // Pitch des Ausgabebildes berechnen
+ // Calculate pitch of output image
pitch = GraphicEngine::calcPitch(GraphicEngine::CF_ARGB32, width);
- // Speicher für die endgültigen Bilddaten reservieren
- // Dieses geschieht vor dem reservieren von Speicher für temporäre Bilddaten um die Fragmentierung des Speichers gering zu halten
+ // Allocate memory for the final image data.
+ // To keep memory framentation low this happens before allocating memory for temporary image data.
uncompressedDataPtr = new byte[pitch * height];
if (!uncompressedDataPtr) {
error("Could not allocate memory for output image.");
}
- // Bilder jeglicher Farbformate werden zunächst in ARGB Bilder umgewandelt
+ // Images of all color formates will be transformed into ARGB images
if (bitDepth == 16)
png_set_strip_16(png_ptr);
if (colorType == PNG_COLOR_TYPE_PALETTE)
@@ -177,7 +177,7 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc
if (colorType != PNG_COLOR_TYPE_RGB_ALPHA)
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
- // Nachdem die Transformationen registriert wurden, werden die Bilddaten erneut eingelesen
+ // After the transformations have been registered, the image data is read again.
png_read_update_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL);
width = w;
@@ -218,7 +218,7 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc
Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO);
Graphics::PNG *png = new Graphics::PNG();
if (!png->read(fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done
- error("Error while reading PNG image");
+ error("Error while reading PNG image");
Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
Graphics::Surface *pngSurface = png->getSurface(format);
@@ -251,7 +251,7 @@ bool PNGLoader::doImageProperties(const byte *fileDataPtr, uint fileSize, int &w
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
- // Die beiden PNG Strukturen erstellen
+ // Create both PNG structures
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
error("Could not create libpng read struct.");
@@ -262,14 +262,14 @@ bool PNGLoader::doImageProperties(const byte *fileDataPtr, uint fileSize, int &w
error("Could not create libpng info struct.");
}
- // Alternative Lesefunktion benutzen
+ // Use alternative reading function
const byte **ref = &fileDataPtr;
png_set_read_fn(png_ptr, (void *)ref, png_user_read_data);
- // PNG Header einlesen
+ // Read PNG Header
png_read_info(png_ptr, info_ptr);
- // PNG Informationen auslesen
+ // Read out PNG informations
int bitDepth;
int colorType;
png_uint_32 w, h;
@@ -278,7 +278,7 @@ bool PNGLoader::doImageProperties(const byte *fileDataPtr, uint fileSize, int &w
width = w;
height = h;
- // Die Strukturen freigeben
+ // Destroy libpng structures
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
#else
// We don't need to read the image properties here...
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index 0d2ffb5aee..806d9b27ad 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -59,7 +59,7 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
_backSurface = Kernel::getInstance()->getGfx()->getSurface();
- // Datei laden
+ // Load file
byte *pFileData;
uint fileSize;
pFileData = pPackage->getFile(filename, &fileSize);
@@ -68,7 +68,7 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
return;
}
- // Bildeigenschaften bestimmen
+ // Determine image properties
int pitch;
if (!PNGLoader::imageProperties(pFileData, fileSize, _width, _height)) {
error("Could not read image properties.");
@@ -76,14 +76,14 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
return;
}
- // Das Bild dekomprimieren
+ // Uncompress the image
if (!PNGLoader::decodeImage(pFileData, fileSize, _data, _width, _height, pitch)) {
error("Could not decode image.");
delete[] pFileData;
return;
}
- // Dateidaten freigeben
+ // Cleanup FileData
delete[] pFileData;
_doCleanup = true;
@@ -134,7 +134,7 @@ bool RenderedImage::fill(const Common::Rect *pFillRect, uint color) {
// -----------------------------------------------------------------------------
bool RenderedImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) {
- // Überprüfen, ob PixelData ausreichend viele Pixel enthält um ein Bild der Größe Width * Height zu erzeugen
+ // 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);
return false;
@@ -187,7 +187,8 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
// Create an encapsulating surface for the data
Graphics::Surface srcImage;
- srcImage.bytesPerPixel = 4;
+ // TODO: Is the data really in the screen format?
+ srcImage.format = g_system->getScreenFormat();
srcImage.pitch = _width * 4;
srcImage.w = _width;
srcImage.h = _height;
@@ -198,11 +199,11 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
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,
+ 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,
+ 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);
}
@@ -267,10 +268,11 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
out = outo;
in = ino;
for (int j = 0; j < img->w; j++) {
- int b = in[0];
- int g = in[1];
- int r = in[2];
- int a = in[3];
+ uint32 pix = *(uint32 *)in;
+ int b = (pix >> 0) & 0xff;
+ int g = (pix >> 8) & 0xff;
+ int r = (pix >> 16) & 0xff;
+ int a = (pix >> 24) & 0xff;
in += inStep;
if (ca != 255) {
@@ -282,6 +284,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
out += 4;
break;
case 255: // Full opacity
+#if defined(SCUMM_LITTLE_ENDIAN)
if (cb != 255)
*out++ = (b * cb) >> 8;
else
@@ -298,9 +301,28 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
*out++ = r;
*out++ = a;
+#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
break;
default: // alpha blending
+#if defined(SCUMM_LITTLE_ENDIAN)
if (cb != 255)
*out += ((b - *out) * a * cb) >> 16;
else
@@ -318,13 +340,32 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
out++;
*out = 255;
out++;
+#else
+ *out = 255;
+ out++;
+ if (cr != 255)
+ *out += ((r - *out) * a * cr) >> 16;
+ else
+ *out += ((r - *out) * a) >> 8;
+ out++;
+ if (cg != 255)
+ *out += ((g - *out) * a * cg) >> 16;
+ else
+ *out += ((g - *out) * a) >> 8;
+ out++;
+ if (cb != 255)
+ *out += ((b - *out) * a * cb) >> 16;
+ else
+ *out += ((b - *out) * a) >> 8;
+ out++;
+#endif
}
}
outo += _backSurface->pitch;
ino += inoStep;
}
- g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY,
+ g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY,
img->w, img->h);
}
@@ -369,7 +410,7 @@ void RenderedImage::copyDirectly(int posX, int posY) {
*/
Graphics::Surface *RenderedImage::scale(const Graphics::Surface &srcImage, int xSize, int ySize) {
Graphics::Surface *s = new Graphics::Surface();
- s->create(xSize, ySize, srcImage.bytesPerPixel);
+ s->create(xSize, ySize, srcImage.format);
int *horizUsage = scaleLine(xSize, srcImage.w);
int *vertUsage = scaleLine(ySize, srcImage.h);
@@ -380,8 +421,8 @@ Graphics::Surface *RenderedImage::scale(const Graphics::Surface &srcImage, int x
byte *destP = (byte *)s->getBasePtr(0, yp);
for (int xp = 0; xp < xSize; ++xp) {
- const byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.bytesPerPixel);
- for (int byteCtr = 0; byteCtr < srcImage.bytesPerPixel; ++byteCtr) {
+ const byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.format.bytesPerPixel);
+ for (int byteCtr = 0; byteCtr < srcImage.format.bytesPerPixel; ++byteCtr) {
*destP++ = *tempSrcP++;
}
}
@@ -413,7 +454,7 @@ int *RenderedImage::scaleLine(int size, int srcSize) {
distCtr -= 100;
}
}
-
+
return v;
}
diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h
index 0375c7acbe..e3f23747da 100644
--- a/engines/sword25/gfx/image/renderedimage.h
+++ b/engines/sword25/gfx/image/renderedimage.h
@@ -50,12 +50,12 @@ public:
RenderedImage(const Common::String &filename, bool &result);
/**
- @brief Erzeugt ein leeres BS_RenderedImage
+ @brief Creates an empty BS_RenderedImage
- @param Width die Breite des zu erzeugenden Bildes.
- @param Height die Höhe des zu erzeugenden Bildes
- @param Result gibt dem Aufrufer bekannt, ob der Konstruktor erfolgreich ausgeführt wurde. Wenn es nach dem Aufruf false enthalten sollte,
- dürfen keine Methoden am Objekt aufgerufen werden und das Objekt ist sofort zu zerstören.
+ @param Width The width of the image to be created.
+ @param Height The height of the image to be created
+ @param Result Informs the caller, whether the constructor is executed successfully. If it contains false
+ after the call, do not call methods on the object and destroy the object immediately.
*/
RenderedImage(uint width, uint height, bool &result);
RenderedImage();
@@ -84,25 +84,25 @@ public:
void replaceContent(byte *pixeldata, int width, int height);
virtual uint getPixel(int x, int y);
- virtual bool isBlitSource() const {
+ virtual bool isBlitSource() const {
return true;
}
- virtual bool isBlitTarget() const {
+ virtual bool isBlitTarget() const {
return false;
}
- virtual bool isScalingAllowed() const {
+ virtual bool isScalingAllowed() const {
return true;
}
- virtual bool isFillingAllowed() const {
+ virtual bool isFillingAllowed() const {
return false;
}
- virtual bool isAlphaAllowed() const {
+ virtual bool isAlphaAllowed() const {
return true;
}
- virtual bool isColorModulationAllowed() const {
+ virtual bool isColorModulationAllowed() const {
return true;
}
- virtual bool isSetContentAllowed() const {
+ virtual bool isSetContentAllowed() const {
return true;
}
diff --git a/engines/sword25/gfx/image/swimage.cpp b/engines/sword25/gfx/image/swimage.cpp
index ff06491b36..3b9b939eb3 100644
--- a/engines/sword25/gfx/image/swimage.cpp
+++ b/engines/sword25/gfx/image/swimage.cpp
@@ -47,7 +47,7 @@ SWImage::SWImage(const Common::String &filename, bool &result) :
PackageManager *pPackage = Kernel::getInstance()->getPackage();
assert(pPackage);
- // Datei laden
+ // Load file
byte *pFileData;
uint fileSize;
pFileData = pPackage->getFile(filename, &fileSize);
@@ -56,21 +56,21 @@ SWImage::SWImage(const Common::String &filename, bool &result) :
return;
}
- // Bildeigenschaften bestimmen
+ // Determine image properties
int pitch;
if (!PNGLoader::imageProperties(pFileData, fileSize, _width, _height)) {
error("Could not read image properties.");
return;
}
- // Das Bild dekomprimieren
+ // Uncompress the image
byte *pUncompressedData;
if (!PNGLoader::decodeImage(pFileData, fileSize, pUncompressedData, _width, _height, pitch)) {
error("Could not decode image.");
return;
}
- // Dateidaten freigeben
+ // Cleanup FileData
delete[] pFileData;
_imageDataPtr = (uint *)pUncompressedData;
diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp
index 094e6a59a8..241e80bad3 100644
--- a/engines/sword25/gfx/image/vectorimage.cpp
+++ b/engines/sword25/gfx/image/vectorimage.cpp
@@ -47,15 +47,15 @@ namespace Sword25 {
#define BEZSMOOTHNESS 0.5
// -----------------------------------------------------------------------------
-// SWF Datentypen
+// SWF datatype
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
-// Bitstream Hilfsklasse
+// Bitstream helper class
// -----------------------------------------------------------------------------
-// Das Parsen von SWF-Dateien erfordert sowohl bitweises Auslesen als auch an
-// Bytegrenzen ausgerichtetes Lesen.
-// Diese Klasse ist speziell dafür ausgestattet.
+// The parsing of SWF files requires both bitwise readout and on Byte boundaries
+// oriented reading.
+// This class is specially equipped for this.
// -----------------------------------------------------------------------------
class VectorImage::SWFBitStream {
@@ -85,10 +85,10 @@ public:
}
inline int32 getSignedBits(uint bitCount) {
- // Bits einlesen
+ // readout bits
uint32 temp = getBits(bitCount);
- // Falls das Sign-Bit gesetzt ist, den Rest des Rückgabewertes mit 1-Bits auffüllen (Sign Extension)
+ // If the sign-bit is set, fill the rest of the return value with 1-bit (sign extension)
if (temp & 1 << (bitCount - 1))
return (0xffffffff << bitCount) | temp;
else
@@ -151,28 +151,28 @@ private:
// -----------------------------------------------------------------------------
-// Konstanten und Hilfsfunktionen
+// Constants and utility functions
// -----------------------------------------------------------------------------
namespace {
// -----------------------------------------------------------------------------
-// Konstanten
+// Constants
// -----------------------------------------------------------------------------
-const uint32 MAX_ACCEPTED_FLASH_VERSION = 3; // Die höchste Flash-Dateiversion, die vom Lader akzeptiert wird
+const uint32 MAX_ACCEPTED_FLASH_VERSION = 3; // The maximum flash file version that is accepted by the loader
// -----------------------------------------------------------------------------
-// Konvertiert SWF-Rechteckdaten in einem Bitstrom in Common::Rect-Objekte
+// Converts SWF rectangle data in a bit stream in Common::Rect objects
// -----------------------------------------------------------------------------
Common::Rect flashRectToBSRect(VectorImage::SWFBitStream &bs) {
bs.flushByte();
- // Feststellen mit wie vielen Bits die einzelnen Komponenten kodiert sind
+ // Determines how many bits of the single components are encoded
uint32 bitsPerValue = bs.getBits(5);
- // Die einzelnen Komponenten einlesen
+ // Readout the single components
int32 xMin = bs.getSignedBits(bitsPerValue);
int32 xMax = bs.getSignedBits(bitsPerValue);
int32 yMin = bs.getSignedBits(bitsPerValue);
@@ -182,7 +182,7 @@ Common::Rect flashRectToBSRect(VectorImage::SWFBitStream &bs) {
}
// -----------------------------------------------------------------------------
-// Berechnet die Bounding-Box eines BS_VectorImageElement
+// Calculate the bounding box of a BS_VectorImageElement
// -----------------------------------------------------------------------------
Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) {
@@ -214,17 +214,17 @@ Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement)
// -----------------------------------------------------------------------------
-// Konstruktion
+// Construction
// -----------------------------------------------------------------------------
VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, const Common::String &fname) : _pixelData(0), _fname(fname) {
success = false;
- // Bitstream-Objekt erzeugen
- // Im Folgenden werden die Dateidaten aus diesem ausgelesen.
+ // Create bitstream object
+ // In the following the file data will be readout of the bitstream object.
SWFBitStream bs(pFileData, fileSize);
- // SWF-Signatur überprüfen
+ // Check SWF signature
uint32 signature[3];
signature[0] = bs.getByte();
signature[1] = bs.getByte();
@@ -236,37 +236,37 @@ VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, co
return;
}
- // Versionsangabe überprüfen
+ // Check the version
uint32 version = bs.getByte();
if (version > MAX_ACCEPTED_FLASH_VERSION) {
error("File is of version %d. Highest accepted version is %d.", version, MAX_ACCEPTED_FLASH_VERSION);
return;
}
- // Dateigröße auslesen und mit der tatsächlichen Größe vergleichen
+ // Readout filesize and compare with the actual size
uint32 storedFileSize = bs.getUInt32();
if (storedFileSize != fileSize) {
error("File is not a valid SWF-file");
return;
}
- // SWF-Maße auslesen
+ // readout SWF size
Common::Rect movieRect = flashRectToBSRect(bs);
- // Framerate und Frameanzahl auslesen
+ // Get frame rate and frame count
/* uint32 frameRate = */
bs.getUInt16();
/* uint32 frameCount = */
bs.getUInt16();
- // Tags parsen
- // Da wir uns nur für das erste DefineShape-Tag interessieren
+ // Parse tags
+ // Because we are only interested in the first DifneShape-Tag...
bool keepParsing = true;
while (keepParsing) {
- // Tags beginnen immer an Bytegrenzen
+ // Tags always begin on byte boundaries
bs.flushByte();
- // Tagtyp und Länge auslesen
+ // Readout tag type and length
uint16 tagTypeAndLength = bs.getUInt16();
uint32 tagType = tagTypeAndLength >> 6;
uint32 tagLength = tagTypeAndLength & 0x3f;
@@ -286,13 +286,13 @@ VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, co
success = parseDefineShape(3, bs);
return;
default:
- // Unbekannte Tags ignorieren
+ // Ignore unknown tags
bs.skipBytes(tagLength);
}
}
- // Die Ausführung darf nicht an dieser Stelle ankommen: Entweder es wird ein Shape gefunden, dann wird die Funktion mit vorher verlassen, oder
- // es wird keines gefunden, dann tritt eine Exception auf sobald über das Ende der Datei hinaus gelesen wird.
+ // The execution must not arrive at this point: Either a shape is found, then the function will be leaved before, or it is found none, then
+ // an exception occurs as soon as it is read beyond of the end of file.
assert(false);
}
@@ -336,13 +336,13 @@ ArtBpath *VectorImage::storeBez(ArtBpath *bez, int lineStyle, int fillStyle0, in
bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
/*uint32 shapeID = */bs.getUInt16();
- // Bounding Box auslesen
+ // readout bounding box
_boundingBox = flashRectToBSRect(bs);
- // Erstes Image-Element erzeugen
+ // create first image element
_elements.resize(1);
- // Styles einlesen
+ // read styles
uint numFillBits;
uint numLineBits;
if (!parseStyles(shapeType, bs, numFillBits, numLineBits))
@@ -352,7 +352,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
uint fillStyle0 = 0;
uint fillStyle1 = 0;
- // Shaperecord parsen
+ // parse shaperecord
// ------------------
double curX = 0;
@@ -367,7 +367,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
// Non-Edge Record
if (typeFlag == 0) {
- // Feststellen welche Parameter gesetzt werden
+ // Determines which parameters are set
uint32 stateNewStyles = bs.getBits(1);
uint32 stateLineStyle = bs.getBits(1);
uint32 stateFillStyle1 = bs.getBits(1);
@@ -378,10 +378,10 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
uint prevFillStyle0 = fillStyle0;
uint prevFillStyle1 = fillStyle1;
- // End der Shape-Definition erreicht?
+ // End of the shape definition is reached?
if (!stateNewStyles && !stateLineStyle && !stateFillStyle0 && !stateFillStyle1 && !stateMoveTo) {
endOfShapeDiscovered = true;
- // Parameter dekodieren
+ // Decode parameters
} else {
if (stateMoveTo) {
uint32 moveToBits = bs.getBits(5);
@@ -410,7 +410,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
numLineBits = 0;
}
- // Ein neuen Pfad erzeugen, es sei denn, es wurden nur neue Styles definiert
+ // Create a new path, unless there were only defined new styles
if (stateLineStyle || stateFillStyle0 || stateFillStyle1 || stateMoveTo) {
// Store previous curve if any
if (bezNodes) {
@@ -426,15 +426,15 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
}
if (stateNewStyles) {
- // An dieser Stelle werden in Flash die alten Style-Definitionen verworfen und mit den neuen überschrieben.
- // Es wird ein neues Element begonnen.
+ // The old style definitions will be discarded and overwritten with the new at this point in Flash.
+ // A new element will be started with a new element.
_elements.resize(_elements.size() + 1);
if (!parseStyles(shapeType, bs, numFillBits, numLineBits))
return false;
}
}
} else {
- // Edge Record
+ // Edge record
uint32 edgeFlag = bs.getBits(1);
uint32 numBits = bs.getBits(4) + 2;
@@ -499,7 +499,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
free(bez);
- // Bounding-Boxes der einzelnen Elemente berechnen
+ // Calculate the bounding boxes of each element
Common::Array<VectorImageElement>::iterator it = _elements.begin();
for (; it != _elements.end(); ++it)
it->_boundingBox = CalculateBoundingBox(*it);
@@ -513,16 +513,16 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBits, uint &numLineBits) {
bs.flushByte();
- // Fillstyles parsen
+ // Parse fill styles
// -----------------
- // Anzahl an Fillstyles bestimmen
+ // Determine number of fill styles
uint fillStyleCount = bs.getByte();
if (fillStyleCount == 0xff)
fillStyleCount = bs.getUInt16();
- // Alle Fillstyles einlesen, falls ein Fillstyle mit Typ != 0 gefunden wird, wird das Parsen abgebrochen.
- // Es wird nur "solid fill" (Typ 0) unterstützt.
+ // Readout all fill styles. If a fill style with Typ != 0 is found, the parsing is aborted.
+ // Only "solid fill" (Typ 0) is supported.
_elements.back()._fillStyles.reserve(fillStyleCount);
for (uint i = 0; i < fillStyleCount; ++i) {
byte type = bs.getByte();
@@ -543,15 +543,15 @@ bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBit
_elements.back()._fillStyles.push_back(color);
}
- // Linestyles parsen
+ // Line styles parsen
// -----------------
- // Anzahl an Linestyles bestimmen
+ // Determine number of line styles
uint lineStyleCount = bs.getByte();
if (lineStyleCount == 0xff)
lineStyleCount = bs.getUInt16();
- // Alle Linestyles einlesen
+ // Readout all line styles
_elements.back()._lineStyles.reserve(lineStyleCount);
for (uint i = 0; i < lineStyleCount; ++i) {
double width = bs.getUInt16();
@@ -569,7 +569,7 @@ bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBit
_elements.back()._lineStyles.push_back(VectorImageElement::LineStyleType(width, color));
}
- // Bitbreite für die folgenden Styleindizes auslesen
+ // Readout the bit width for the following style indices
numFillBits = bs.getBits(4);
numLineBits = bs.getBits(4);
@@ -608,11 +608,11 @@ bool VectorImage::blit(int posX, int posY,
static int oldWidth = -2;
static int oldHeight = -2;
- // Falls Breite oder Höhe 0 sind, muss nichts dargestellt werden.
+ // If width or height to 0, nothing needs to be shown.
if (width == 0 || height == 0)
return true;
- // Feststellen, ob das alte Bild im Cache nicht wiederbenutzt werden kann und neu Berechnet werden muss
+ // Determine if the old image in the cache can not be reused and must be recalculated
if (!(oldThis == this && oldWidth == width && oldHeight == height)) {
render(width, height);
diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp
index 7587aab4e5..99a47015fb 100644
--- a/engines/sword25/gfx/image/vectorimagerenderer.cpp
+++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp
@@ -48,7 +48,7 @@
namespace Sword25 {
-void art_rgb_fill_run1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n) {
+void art_rgb_fill_run1(byte *buf, byte r, byte g, byte b, int n) {
int i;
if (r == g && g == b && r == 255) {
@@ -62,11 +62,12 @@ void art_rgb_fill_run1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n) {
}
}
-void art_rgb_run_alpha1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n) {
+void art_rgb_run_alpha1(byte *buf, byte r, byte g, byte b, int alpha, int n) {
int i;
int v;
for (i = 0; i < n; i++) {
+#if defined(SCUMM_LITTLE_ENDIAN)
v = *buf;
*buf++ = v + (((b - v) * alpha + 0x80) >> 8);
v = *buf;
@@ -75,6 +76,16 @@ void art_rgb_run_alpha1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, in
*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);
+#endif
}
}
@@ -82,8 +93,8 @@ typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
struct _ArtRgbSVPAlphaData {
int alphatab[256];
- art_u8 r, g, b, alpha;
- art_u8 *buf;
+ byte r, g, b, alpha;
+ byte *buf;
int rowstride;
int x0, x1;
};
@@ -91,12 +102,12 @@ struct _ArtRgbSVPAlphaData {
static void art_rgb_svp_alpha_callback1(void *callback_data, int y,
int start, ArtSVPRenderAAStep *steps, int n_steps) {
ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
- art_u8 *linebuf;
+ byte *linebuf;
int run_x0, run_x1;
- art_u32 running_sum = start;
+ uint32 running_sum = start;
int x0, x1;
int k;
- art_u8 r, g, b;
+ byte r, g, b;
int *alphatab;
int alpha;
@@ -146,12 +157,12 @@ static void art_rgb_svp_alpha_opaque_callback1(void *callback_data, int y,
int start,
ArtSVPRenderAAStep *steps, int n_steps) {
ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
- art_u8 *linebuf;
+ byte *linebuf;
int run_x0, run_x1;
- art_u32 running_sum = start;
+ uint32 running_sum = start;
int x0, x1;
int k;
- art_u8 r, g, b;
+ byte r, g, b;
int *alphatab;
int alpha;
@@ -216,7 +227,7 @@ static void art_rgb_svp_alpha_opaque_callback1(void *callback_data, int y,
void art_rgb_svp_alpha1(const ArtSVP *svp,
int x0, int y0, int x1, int y1,
uint32 color,
- art_u8 *buf, int rowstride) {
+ byte *buf, int rowstride) {
ArtRgbSVPAlphaData data;
byte r, g, b, alpha;
int i;
@@ -320,7 +331,7 @@ ArtVpath *art_vpath_reverse_free(ArtVpath *a) {
return dest;
}
-void drawBez(ArtBpath *bez1, ArtBpath *bez2, art_u8 *buffer, int width, int height, int deltaX, int deltaY, double scaleX, double scaleY, double penWidth, unsigned int color) {
+void drawBez(ArtBpath *bez1, ArtBpath *bez2, byte *buffer, int width, int height, int deltaX, int deltaY, double scaleX, double scaleY, double penWidth, unsigned int color) {
ArtVpath *vec = NULL;
ArtVpath *vec1 = NULL;
ArtVpath *vec2 = NULL;
diff --git a/engines/sword25/gfx/screenshot.cpp b/engines/sword25/gfx/screenshot.cpp
index 35e94976eb..6ea2b574d6 100644
--- a/engines/sword25/gfx/screenshot.cpp
+++ b/engines/sword25/gfx/screenshot.cpp
@@ -36,6 +36,7 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/memstream.h"
+#include "common/textconsole.h"
#include "sword25/gfx/screenshot.h"
#include "sword25/kernel/filesystemutil.h"
#include <png.h>
@@ -127,14 +128,14 @@ Common::SeekableReadStream *Screenshot::createThumbnail(Graphics::Surface *data)
// generates a pixel of the target image. Finally, the result as a PNG file is stored as a file.
// The source image must be 800x600.
- if (data->w != 800 || data->h != 600 || data->bytesPerPixel != 4) {
+ if (data->w != 800 || data->h != 600 || data->format.bytesPerPixel != 4) {
error("The sreenshot dimensions have to be 800x600 in order to be saved as a thumbnail.");
return false;
}
// Buffer for the output thumbnail
Graphics::Surface thumbnail;
- thumbnail.create(200, 125, 4);
+ thumbnail.create(200, 125, g_system->getScreenFormat());
// Über das Zielbild iterieren und einen Pixel zur Zeit berechnen.
uint x, y;
diff --git a/engines/sword25/gfx/text.cpp b/engines/sword25/gfx/text.cpp
index bbfc3804a3..b1c1708565 100644
--- a/engines/sword25/gfx/text.cpp
+++ b/engines/sword25/gfx/text.cpp
@@ -173,10 +173,8 @@ bool Text::doRender() {
Common::Rect curRect = fontPtr->getCharacterRect((byte)(*iter).text[i]);
Common::Rect renderRect(curX, curY, curX + curRect.width(), curY + curRect.height());
- int renderX = curX + (renderRect.left - renderRect.left);
- int renderY = curY + (renderRect.top - renderRect.top);
renderRect.translate(curRect.left - curX, curRect.top - curY);
- result = charMapPtr->blit(renderX, renderY, Image::FLIP_NONE, &renderRect, _modulationColor);
+ result = charMapPtr->blit(curX, curY, Image::FLIP_NONE, &renderRect, _modulationColor);
if (!result)
break;
diff --git a/engines/sword25/kernel/filesystemutil.cpp b/engines/sword25/kernel/filesystemutil.cpp
index b4d4b25f8d..e5ec6c15db 100644
--- a/engines/sword25/kernel/filesystemutil.cpp
+++ b/engines/sword25/kernel/filesystemutil.cpp
@@ -34,8 +34,7 @@
#include "common/config-manager.h"
#include "common/fs.h"
-#include "common/savefile.h"
-#include "common/system.h"
+#include "common/textconsole.h"
#include "sword25/kernel/filesystemutil.h"
#include "sword25/kernel/persistenceservice.h"
diff --git a/engines/sword25/kernel/inputpersistenceblock.cpp b/engines/sword25/kernel/inputpersistenceblock.cpp
index f3aebef203..26c924dc82 100644
--- a/engines/sword25/kernel/inputpersistenceblock.cpp
+++ b/engines/sword25/kernel/inputpersistenceblock.cpp
@@ -32,6 +32,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "sword25/kernel/inputpersistenceblock.h"
namespace Sword25 {
diff --git a/engines/sword25/kernel/kernel.cpp b/engines/sword25/kernel/kernel.cpp
index 6b99b0a115..99fec52040 100644
--- a/engines/sword25/kernel/kernel.cpp
+++ b/engines/sword25/kernel/kernel.cpp
@@ -95,10 +95,8 @@ Kernel::Kernel() :
_geometry = new Geometry(this);
assert(_geometry);
-#ifdef USE_THEORADEC
_fmv = new MoviePlayer(this);
assert(_fmv);
-#endif
_initSuccess = true;
}
@@ -121,10 +119,8 @@ Kernel::~Kernel() {
delete _geometry;
_geometry = 0;
-#ifdef USE_THEORADEC
delete _fmv;
_fmv = 0;
-#endif
delete _script;
_script = 0;
diff --git a/engines/sword25/kernel/kernel.h b/engines/sword25/kernel/kernel.h
index 9e7ee0fdd9..3abf43d239 100644
--- a/engines/sword25/kernel/kernel.h
+++ b/engines/sword25/kernel/kernel.h
@@ -48,6 +48,7 @@
#include "common/scummsys.h"
#include "common/random.h"
#include "common/stack.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "engines/engine.h"
diff --git a/engines/sword25/kernel/objectregistry.h b/engines/sword25/kernel/objectregistry.h
index 8d0f4a314b..69d961ae91 100644
--- a/engines/sword25/kernel/objectregistry.h
+++ b/engines/sword25/kernel/objectregistry.h
@@ -37,6 +37,7 @@
#include "common/func.h"
#include "common/hashmap.h"
+#include "common/textconsole.h"
#include "sword25/kernel/common.h"
namespace Sword25 {
diff --git a/engines/sword25/kernel/persistenceservice.cpp b/engines/sword25/kernel/persistenceservice.cpp
index be66b6abf0..506eef3c57 100644
--- a/engines/sword25/kernel/persistenceservice.cpp
+++ b/engines/sword25/kernel/persistenceservice.cpp
@@ -32,6 +32,9 @@
*
*/
+// Disable symbol overrides so that we can use zlib.h
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
#include "common/fs.h"
#include "common/savefile.h"
#include "sword25/kernel/kernel.h"
diff --git a/engines/sword25/math/geometry_script.cpp b/engines/sword25/math/geometry_script.cpp
index 6562a0f0a5..4b5e0550fe 100644
--- a/engines/sword25/math/geometry_script.cpp
+++ b/engines/sword25/math/geometry_script.cpp
@@ -51,27 +51,6 @@ namespace Sword25 {
#define REGION_CLASS_NAME "Geo.Region"
#define WALKREGION_CLASS_NAME "Geo.WalkRegion"
-// How luaL_checkudata, only without that no error is generated.
-static void *my_checkudata(lua_State *L, int ud, const char *tname) {
- int top = lua_gettop(L);
-
- void *p = lua_touserdata(L, ud);
- if (p != NULL) { /* value is a userdata? */
- if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
- // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
- LuaBindhelper::getMetatable(L, tname);
- /* does it have the correct mt? */
- if (lua_rawequal(L, -1, -2)) {
- lua_settop(L, top);
- return p;
- }
- }
- }
-
- lua_settop(L, top);
- return NULL;
-}
-
static void newUintUserData(lua_State *L, uint value) {
void *userData = lua_newuserdata(L, sizeof(value));
memcpy(userData, &value, sizeof(value));
@@ -276,9 +255,9 @@ static const luaL_reg GEO_FUNCTIONS[] = {
static Region *checkRegion(lua_State *L) {
// The first parameter must be of type 'userdata', and the Metatable class Geo.Region or Geo.WalkRegion
- uint *regionHandlePtr;
- if ((regionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, REGION_CLASS_NAME))) != 0 ||
- (regionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
+ uint *regionHandlePtr = reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, REGION_CLASS_NAME));
+ if (regionHandlePtr != 0 ||
+ (regionHandlePtr = reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
return RegionRegistry::instance().resolveHandle(*regionHandlePtr);
} else {
luaL_argcheck(L, 0, 1, "'" REGION_CLASS_NAME "' expected");
@@ -398,7 +377,7 @@ static const luaL_reg REGION_METHODS[] = {
static WalkRegion *checkWalkRegion(lua_State *L) {
// The first parameter must be of type 'userdate', and the Metatable class Geo.WalkRegion
uint regionHandle;
- if ((regionHandle = *reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
+ if ((regionHandle = *reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
return reinterpret_cast<WalkRegion *>(RegionRegistry::instance().resolveHandle(regionHandle));
} else {
luaL_argcheck(L, 0, 1, "'" WALKREGION_CLASS_NAME "' expected");
diff --git a/engines/sword25/script/luabindhelper.cpp b/engines/sword25/script/luabindhelper.cpp
index 5ff9708b95..03a1802a04 100644
--- a/engines/sword25/script/luabindhelper.cpp
+++ b/engines/sword25/script/luabindhelper.cpp
@@ -303,6 +303,27 @@ bool LuaBindhelper::getMetatable(lua_State *L, const Common::String &tableName)
return true;
}
+// Like luaL_checkudata, only without that no error is generated.
+void *LuaBindhelper::my_checkudata(lua_State *L, int ud, const char *tname) {
+ int top = lua_gettop(L);
+
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
+ LuaBindhelper::getMetatable(L, tname);
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_settop(L, top);
+ return p;
+ }
+ }
+ }
+
+ lua_settop(L, top);
+ return NULL;
+}
+
+
bool LuaBindhelper::createTable(lua_State *L, const Common::String &tableName) {
const char *partBegin = tableName.c_str();
diff --git a/engines/sword25/script/luabindhelper.h b/engines/sword25/script/luabindhelper.h
index dc45104d53..94f52743f3 100644
--- a/engines/sword25/script/luabindhelper.h
+++ b/engines/sword25/script/luabindhelper.h
@@ -110,6 +110,8 @@ public:
static bool getMetatable(lua_State *L, const Common::String &tableName);
+ static void *my_checkudata(lua_State *L, int ud, const char *tname);
+
private:
static bool createTable(lua_State *L, const Common::String &tableName);
};
diff --git a/engines/sword25/script/luacallback.cpp b/engines/sword25/script/luacallback.cpp
index 137e37bf8d..809676796e 100644
--- a/engines/sword25/script/luacallback.cpp
+++ b/engines/sword25/script/luacallback.cpp
@@ -32,6 +32,8 @@
*
*/
+#include "common/textconsole.h"
+
#include "sword25/script/luacallback.h"
#include "sword25/script/luabindhelper.h"
diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp
index 03cdaf82b7..08f0f5b4ae 100644
--- a/engines/sword25/sfx/soundengine.cpp
+++ b/engines/sword25/sfx/soundengine.cpp
@@ -39,6 +39,8 @@
#include "audio/decoders/vorbis.h"
+#include "common/system.h"
+
namespace Sword25 {
class SoundResource : public Resource {
diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp
index 55b9aa340d..38c1c89109 100644
--- a/engines/sword25/sword25.cpp
+++ b/engines/sword25/sword25.cpp
@@ -34,10 +34,18 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
+#include "common/algorithm.h"
+#include "common/array.h"
+#include "common/error.h"
+#include "common/fs.h"
+#include "common/singleton.h"
+#include "common/str-array.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "engines/util.h"
#include "sword25/sword25.h"
-#include "sword25/kernel/filesystemutil.h"
#include "sword25/kernel/kernel.h"
#include "sword25/kernel/persistenceservice.h"
#include "sword25/package/packagemanager.h"
@@ -56,6 +64,8 @@ const char *const DEFAULT_SCRIPT_FILE = "/system/boot.lua";
Sword25Engine::Sword25Engine(OSystem *syst, const ADGameDescription *gameDesc):
Engine(syst),
_gameDescription(gameDesc) {
+ // Setup mixer
+ syncSoundSettings();
DebugMan.addDebugChannel(kDebugScript, "Script", "Script debug level");
DebugMan.addDebugChannel(kDebugScript, "Scripts", "Script debug level");
@@ -71,10 +81,10 @@ Sword25Engine::~Sword25Engine() {
Common::Error Sword25Engine::run() {
// Engine initialisation
- Common::Error errorCode = appStart();
- if (errorCode != Common::kNoError) {
+ Common::Error error = appStart();
+ if (error.getCode() != Common::kNoError) {
appEnd();
- return errorCode;
+ return error;
}
// Run the game
diff --git a/engines/sword25/sword25.h b/engines/sword25/sword25.h
index 9e9679526b..5bd27b311f 100644
--- a/engines/sword25/sword25.h
+++ b/engines/sword25/sword25.h
@@ -27,12 +27,18 @@
#define SWORD25_H
#include "common/scummsys.h"
-#include "common/str-array.h"
-#include "common/util.h"
#include "engines/engine.h"
#include "sword25/console.h"
+namespace Common {
+class Error;
+}
+
+namespace GUI {
+class Debugger;
+}
+
struct ADGameDescription;
/**
diff --git a/engines/sword25/util/lua/lmathlib.cpp b/engines/sword25/util/lua/lmathlib.cpp
index ed50539f1f..7e64d75789 100644
--- a/engines/sword25/util/lua/lmathlib.cpp
+++ b/engines/sword25/util/lua/lmathlib.cpp
@@ -6,6 +6,11 @@
#include <stdlib.h>
+// MSVC does not define M_PI, M_SQRT2 and other math defines by default.
+// _USE_MATH_DEFINES must be defined in order to have these defined, thus
+// we enable it here. For more information, check:
+// http://msdn.microsoft.com/en-us/library/4hwaceh6(v=VS.100).aspx
+#define _USE_MATH_DEFINES
#include <math.h>
#define lmathlib_c
@@ -16,12 +21,7 @@
#include "lauxlib.h"
#include "lualib.h"
-
-#undef PI
-#define PI (3.14159265358979323846)
-#define RADIANS_PER_DEGREE (PI/180.0)
-
-
+#define RADIANS_PER_DEGREE (M_PI/180.0)
static int math_abs (lua_State *L) {
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
@@ -250,7 +250,7 @@ static const luaL_Reg mathlib[] = {
*/
LUALIB_API int luaopen_math (lua_State *L) {
luaL_register(L, LUA_MATHLIBNAME, mathlib);
- lua_pushnumber(L, PI);
+ lua_pushnumber(L, M_PI);
lua_setfield(L, -2, "pi");
#if defined(MACOSX) && defined(__GNUC__) && ! defined( __XLC__ )
// WORKAROUND for a bug in the Mac OS X 10.2.8 SDK. It defines
diff --git a/engines/sword25/util/pluto/Makefile b/engines/sword25/util/pluto/Makefile
deleted file mode 100644
index 611ecc83d2..0000000000
--- a/engines/sword25/util/pluto/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-LDLIBS= -lm -ldl -llua
-LDFLAGS = -rdynamic # -L../lua-5.1.3/src
-# CFLAGS= -g3 -Wall -fprofile-arcs -ftest-coverage
-CFLAGS= -g3 -Wall -ansi -pedantic
-
-LIBTOOL=libtool --tag=CC
-
-default: pluto.so pptest puptest
-
-%.lo: %.c
- $(LIBTOOL) --mode=compile cc $(CFLAGS) -c $<
-
-pluto.so: pluto.lo pdep.lo lzio.lo
- $(LIBTOOL) --mode=link cc -rpath /usr/local/lib/lua/5.1 -o libpluto.la $^
- mv .libs/libpluto.so.0.0.0 $@
-
-test: pptest puptest pptest.lua puptest.lua pluto.so
- ./pptest
- ./puptest
-
-pptest: pptest.o
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-puptest: puptest.o
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-clean:
- -rm -r *.so *.la *.lo .libs *.a *.o *.bb *.bbg *.da *.gcov pptest puptest test.plh
-
diff --git a/engines/sword25/util/pluto/pdep/lauxlib.h b/engines/sword25/util/pluto/pdep/lauxlib.h
deleted file mode 100644
index d58f290527..0000000000
--- a/engines/sword25/util/pluto/pdep/lauxlib.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-** $Id$
-** Auxiliary functions for building Lua libraries
-** See Copyright Notice in lua.h
-*/
-
-
-#ifndef lauxlib_h
-#define lauxlib_h
-
-
-#include <stddef.h>
-#include <stdio.h>
-
-#include "lua.h"
-
-
-#if defined(LUA_COMPAT_GETN)
-LUALIB_API int (luaL_getn) (lua_State *L, int t);
-LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
-#else
-#define luaL_getn(L,i) ((int)lua_objlen(L, i))
-#define luaL_setn(L,i,j) ((void)0) /* no op! */
-#endif
-
-#if defined(LUA_COMPAT_OPENLIB)
-#define luaI_openlib luaL_openlib
-#endif
-
-
-/* extra error code for `luaL_load' */
-#define LUA_ERRFILE (LUA_ERRERR+1)
-
-
-typedef struct luaL_Reg {
- const char *name;
- lua_CFunction func;
-} luaL_Reg;
-
-
-
-LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
- const luaL_Reg *l, int nup);
-LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
- const luaL_Reg *l);
-LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
-LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
-LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
-LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
-LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
- size_t *l);
-LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
- const char *def, size_t *l);
-LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
-LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
-
-LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
-LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
- lua_Integer def);
-
-LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
-LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
-LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
-
-LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
-LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
-
-LUALIB_API void (luaL_where) (lua_State *L, int lvl);
-LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
-
-LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
- const char *const lst[]);
-
-LUALIB_API int (luaL_ref) (lua_State *L, int t);
-LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
-
-LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
-LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
- const char *name);
-LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
-
-LUALIB_API lua_State *(luaL_newstate) (void);
-
-
-LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
- const char *r);
-
-LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
- const char *fname, int szhint);
-
-
-
-
-/*
-** ===============================================================
-** some useful macros
-** ===============================================================
-*/
-
-#define luaL_argcheck(L, cond,numarg,extramsg) \
- ((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
-#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
-#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
-#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
-#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
-#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
-#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
-
-#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
-
-#define luaL_dofile(L, fn) \
- (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
-
-#define luaL_dostring(L, s) \
- (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
-
-#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
-
-#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
-
-/*
-** {======================================================
-** Generic Buffer manipulation
-** =======================================================
-*/
-
-
-
-typedef struct luaL_Buffer {
- char *p; /* current position in buffer */
- int lvl; /* number of strings in the stack (level) */
- lua_State *L;
- char buffer[LUAL_BUFFERSIZE];
-} luaL_Buffer;
-
-#define luaL_addchar(B,c) \
- ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
- (*(B)->p++ = (char)(c)))
-
-/* compatibility only */
-#define luaL_putchar(B,c) luaL_addchar(B,c)
-
-#define luaL_addsize(B,n) ((B)->p += (n))
-
-LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
-LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
-LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
-LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
-LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
-LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
-
-
-/* }====================================================== */
-
-
-/* compatibility with ref system */
-
-/* pre-defined references */
-#define LUA_NOREF (-2)
-#define LUA_REFNIL (-1)
-
-#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
- (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
-
-#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
-
-#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
-
-
-#define luaL_reg luaL_Reg
-
-#endif
-
-
diff --git a/engines/sword25/util/pluto/pdep/ldo.h b/engines/sword25/util/pluto/pdep/ldo.h
deleted file mode 100644
index 4c97134805..0000000000
--- a/engines/sword25/util/pluto/pdep/ldo.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-** $Id$
-** Stack and Call structure of Lua
-** See Copyright Notice in lua.h
-*/
-
-#ifndef ldo_h
-#define ldo_h
-
-
-#include "lobject.h"
-#include "lstate.h"
-#include "lzio.h"
-
-
-#define luaD_checkstack(L,n) \
- if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
- luaD_growstack(L, n); \
- else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
-
-
-#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
-
-#define savestack(L,p) ((char *)(p) - (char *)L->stack)
-#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
-
-#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
-#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
-
-
-/* results from luaD_precall */
-#define PCRLUA 0 /* initiated a call to a Lua function */
-#define PCRC 1 /* did a call to a C function */
-#define PCRYIELD 2 /* C funtion yielded */
-
-
-/* type of protected functions, to be ran by `runprotected' */
-typedef void (*Pfunc) (lua_State *L, void *ud);
-
-LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
-LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);
-LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
-LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
-LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
- ptrdiff_t oldtop, ptrdiff_t ef);
-LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
-LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
-LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
-LUAI_FUNC void luaD_growstack (lua_State *L, int n);
-
-LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
-LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
-
-LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
-
-#endif
-
diff --git a/engines/sword25/util/pluto/pdep/lfunc.h b/engines/sword25/util/pluto/pdep/lfunc.h
deleted file mode 100644
index 4c2b7fd138..0000000000
--- a/engines/sword25/util/pluto/pdep/lfunc.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-** $Id$
-** Auxiliary functions to manipulate prototypes and closures
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lfunc_h
-#define lfunc_h
-
-
-#include "lobject.h"
-
-
-#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
- cast(int, sizeof(TValue)*((n)-1)))
-
-#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
- cast(int, sizeof(TValue *)*((n)-1)))
-
-
-LUAI_FUNC Proto *luaF_newproto (lua_State *L);
-LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
-LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
-LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
-LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
-LUAI_FUNC void luaF_close (lua_State *L, StkId level);
-LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
-LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);
-LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
-LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
- int pc);
-
-
-#endif
diff --git a/engines/sword25/util/pluto/pdep/lgc.h b/engines/sword25/util/pluto/pdep/lgc.h
deleted file mode 100644
index 5123ccb479..0000000000
--- a/engines/sword25/util/pluto/pdep/lgc.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-** $Id$
-** Garbage Collector
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lgc_h
-#define lgc_h
-
-
-#include "lobject.h"
-
-
-/*
-** Possible states of the Garbage Collector
-*/
-#define GCSpause 0
-#define GCSpropagate 1
-#define GCSsweepstring 2
-#define GCSsweep 3
-#define GCSfinalize 4
-
-
-/*
-** some userful bit tricks
-*/
-#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
-#define setbits(x,m) ((x) |= (m))
-#define testbits(x,m) ((x) & (m))
-#define bitmask(b) (1<<(b))
-#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
-#define l_setbit(x,b) setbits(x, bitmask(b))
-#define resetbit(x,b) resetbits(x, bitmask(b))
-#define testbit(x,b) testbits(x, bitmask(b))
-#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
-#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
-#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2)))
-
-
-
-/*
-** Layout for bit use in `marked' field:
-** bit 0 - object is white (type 0)
-** bit 1 - object is white (type 1)
-** bit 2 - object is black
-** bit 3 - for userdata: has been finalized
-** bit 3 - for tables: has weak keys
-** bit 4 - for tables: has weak values
-** bit 5 - object is fixed (should not be collected)
-** bit 6 - object is "super" fixed (only the main thread)
-*/
-
-
-#define WHITE0BIT 0
-#define WHITE1BIT 1
-#define BLACKBIT 2
-#define FINALIZEDBIT 3
-#define KEYWEAKBIT 3
-#define VALUEWEAKBIT 4
-#define FIXEDBIT 5
-#define SFIXEDBIT 6
-#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
-
-
-#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
-#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
-#define isgray(x) (!isblack(x) && !iswhite(x))
-
-#define otherwhite(g) (g->currentwhite ^ WHITEBITS)
-#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS)
-
-#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
-#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
-
-#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
-
-#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
-
-
-#define luaC_checkGC(L) { \
- condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
- if (G(L)->totalbytes >= G(L)->GCthreshold) \
- luaC_step(L); }
-
-
-#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
- luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
-
-#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \
- luaC_barrierback(L,t); }
-
-#define luaC_objbarrier(L,p,o) \
- { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
- luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
-
-#define luaC_objbarriert(L,t,o) \
- { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
-
-LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
-LUAI_FUNC void luaC_callGCTM (lua_State *L);
-LUAI_FUNC void luaC_freeall (lua_State *L);
-LUAI_FUNC void luaC_step (lua_State *L);
-LUAI_FUNC void luaC_fullgc (lua_State *L);
-LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
-LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
-LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
-LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);
-
-
-#endif
diff --git a/engines/sword25/util/pluto/pdep/llimits.h b/engines/sword25/util/pluto/pdep/llimits.h
deleted file mode 100644
index a31ad160ad..0000000000
--- a/engines/sword25/util/pluto/pdep/llimits.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-** $Id$
-** Limits, basic types, and some other `installation-dependent' definitions
-** See Copyright Notice in lua.h
-*/
-
-#ifndef llimits_h
-#define llimits_h
-
-
-#include <limits.h>
-#include <stddef.h>
-
-
-#include "lua.h"
-
-
-typedef LUAI_UINT32 lu_int32;
-
-typedef LUAI_UMEM lu_mem;
-
-typedef LUAI_MEM l_mem;
-
-
-
-/* chars used as small naturals (so that `char' is reserved for characters) */
-typedef unsigned char lu_byte;
-
-
-#define MAX_SIZET ((size_t)(~(size_t)0)-2)
-
-#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2)
-
-
-#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */
-
-/*
-** conversion of pointer to integer
-** this is for hashing only; there is no problem if the integer
-** cannot hold the whole pointer value
-*/
-#define IntPoint(p) ((unsigned int)(lu_mem)(p))
-
-
-
-/* type to ensure maximum alignment */
-typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
-
-
-/* result of a `usual argument conversion' over lua_Number */
-typedef LUAI_UACNUMBER l_uacNumber;
-
-
-/* internal assertions for in-house debugging */
-#ifdef lua_assert
-
-#define check_exp(c,e) (lua_assert(c), (e))
-#define api_check(l,e) lua_assert(e)
-
-#else
-
-#define lua_assert(c) ((void)0)
-#define check_exp(c,e) (e)
-#define api_check luai_apicheck
-
-#endif
-
-
-#ifndef UNUSED
-#define UNUSED(x) ((void)(x)) /* to avoid warnings */
-#endif
-
-
-#ifndef cast
-#define cast(t, exp) ((t)(exp))
-#endif
-
-#define cast_byte(i) cast(lu_byte, (i))
-#define cast_num(i) cast(lua_Number, (i))
-#define cast_int(i) cast(int, (i))
-
-
-
-/*
-** type for virtual-machine instructions
-** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
-*/
-typedef lu_int32 Instruction;
-
-
-
-/* maximum stack for a Lua function */
-#define MAXSTACK 250
-
-
-
-/* minimum size for the string table (must be power of 2) */
-#ifndef MINSTRTABSIZE
-#define MINSTRTABSIZE 32
-#endif
-
-
-/* minimum size for string buffer */
-#ifndef LUA_MINBUFFER
-#define LUA_MINBUFFER 32
-#endif
-
-
-#ifndef lua_lock
-#define lua_lock(L) ((void) 0)
-#define lua_unlock(L) ((void) 0)
-#endif
-
-#ifndef luai_threadyield
-#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
-#endif
-
-
-/*
-** macro to control inclusion of some hard tests on stack reallocation
-*/
-#ifndef HARDSTACKTESTS
-#define condhardstacktests(x) ((void)0)
-#else
-#define condhardstacktests(x) x
-#endif
-
-#endif
diff --git a/engines/sword25/util/pluto/pdep/lobject.h b/engines/sword25/util/pluto/pdep/lobject.h
deleted file mode 100644
index 35aaed028a..0000000000
--- a/engines/sword25/util/pluto/pdep/lobject.h
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
-** $Id$
-** Type definitions for Lua objects
-** See Copyright Notice in lua.h
-*/
-
-
-#ifndef lobject_h
-#define lobject_h
-
-
-#include <stdarg.h>
-
-
-#include "llimits.h"
-#include "lua.h"
-
-
-/* tags for values visible from Lua */
-#define LAST_TAG LUA_TTHREAD
-
-#define NUM_TAGS (LAST_TAG+1)
-
-
-/*
-** Extra tags for non-values
-*/
-#define LUA_TPROTO (LAST_TAG+1)
-#define LUA_TUPVAL (LAST_TAG+2)
-#define LUA_TDEADKEY (LAST_TAG+3)
-
-
-/*
-** Union of all collectable objects
-*/
-typedef union GCObject GCObject;
-
-
-/*
-** Common Header for all collectable objects (in macro form, to be
-** included in other objects)
-*/
-#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
-
-
-/*
-** Common header in struct form
-*/
-typedef struct GCheader {
- CommonHeader;
-} GCheader;
-
-
-
-
-/*
-** Union of all Lua values
-*/
-typedef union {
- GCObject *gc;
- void *p;
- lua_Number n;
- int b;
-} Value;
-
-
-/*
-** Tagged Values
-*/
-
-#define TValuefields Value value; int tt
-
-typedef struct lua_TValue {
- TValuefields;
-} TValue;
-
-
-/* Macros to test type */
-#define ttisnil(o) (ttype(o) == LUA_TNIL)
-#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
-#define ttisstring(o) (ttype(o) == LUA_TSTRING)
-#define ttistable(o) (ttype(o) == LUA_TTABLE)
-#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
-#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
-#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
-#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
-#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
-
-/* Macros to access values */
-#define ttype(o) ((o)->tt)
-#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
-#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
-#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
-#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
-#define tsvalue(o) (&rawtsvalue(o)->tsv)
-#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
-#define uvalue(o) (&rawuvalue(o)->uv)
-#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
-#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
-#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
-#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
-
-#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
-
-/*
-** for internal debug only
-*/
-#define checkconsistency(obj) \
- lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
-
-#define checkliveness(g,obj) \
- lua_assert(!iscollectable(obj) || \
- ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
-
-
-/* Macros to set values */
-#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
-
-#define setnvalue(obj,x) \
- { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
-
-#define setpvalue(obj,x) \
- { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
-
-#define setbvalue(obj,x) \
- { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }
-
-#define setsvalue(L,obj,x) \
- { TValue *i_o=(obj); \
- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
- checkliveness(G(L),i_o); }
-
-#define setuvalue(L,obj,x) \
- { TValue *i_o=(obj); \
- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
- checkliveness(G(L),i_o); }
-
-#define setthvalue(L,obj,x) \
- { TValue *i_o=(obj); \
- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
- checkliveness(G(L),i_o); }
-
-#define setclvalue(L,obj,x) \
- { TValue *i_o=(obj); \
- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
- checkliveness(G(L),i_o); }
-
-#define sethvalue(L,obj,x) \
- { TValue *i_o=(obj); \
- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
- checkliveness(G(L),i_o); }
-
-#define setptvalue(L,obj,x) \
- { TValue *i_o=(obj); \
- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
- checkliveness(G(L),i_o); }
-
-
-
-
-#define setobj(L,obj1,obj2) \
- { const TValue *o2=(obj2); TValue *o1=(obj1); \
- o1->value = o2->value; o1->tt=o2->tt; \
- checkliveness(G(L),o1); }
-
-
-/*
-** different types of sets, according to destination
-*/
-
-/* from stack to (same) stack */
-#define setobjs2s setobj
-/* to stack (not from same stack) */
-#define setobj2s setobj
-#define setsvalue2s setsvalue
-#define sethvalue2s sethvalue
-#define setptvalue2s setptvalue
-/* from table to same table */
-#define setobjt2t setobj
-/* to table */
-#define setobj2t setobj
-/* to new object */
-#define setobj2n setobj
-#define setsvalue2n setsvalue
-
-#define setttype(obj, tt) (ttype(obj) = (tt))
-
-
-#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
-
-
-
-typedef TValue *StkId; /* index to stack elements */
-
-
-/*
-** String headers for string table
-*/
-typedef union TString {
- L_Umaxalign dummy; /* ensures maximum alignment for strings */
- struct {
- CommonHeader;
- lu_byte reserved;
- unsigned int hash;
- size_t len;
- } tsv;
-} TString;
-
-
-#define getstr(ts) cast(const char *, (ts) + 1)
-#define svalue(o) getstr(tsvalue(o))
-
-
-
-typedef union Udata {
- L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
- struct {
- CommonHeader;
- struct Table *metatable;
- struct Table *env;
- size_t len;
- } uv;
-} Udata;
-
-
-
-
-/*
-** Function Prototypes
-*/
-typedef struct Proto {
- CommonHeader;
- TValue *k; /* constants used by the function */
- Instruction *code;
- struct Proto **p; /* functions defined inside the function */
- int *lineinfo; /* map from opcodes to source lines */
- struct LocVar *locvars; /* information about local variables */
- TString **upvalues; /* upvalue names */
- TString *source;
- int sizeupvalues;
- int sizek; /* size of `k' */
- int sizecode;
- int sizelineinfo;
- int sizep; /* size of `p' */
- int sizelocvars;
- int linedefined;
- int lastlinedefined;
- GCObject *gclist;
- lu_byte nups; /* number of upvalues */
- lu_byte numparams;
- lu_byte is_vararg;
- lu_byte maxstacksize;
-} Proto;
-
-
-/* masks for new-style vararg */
-#define VARARG_HASARG 1
-#define VARARG_ISVARARG 2
-#define VARARG_NEEDSARG 4
-
-
-typedef struct LocVar {
- TString *varname;
- int startpc; /* first point where variable is active */
- int endpc; /* first point where variable is dead */
-} LocVar;
-
-
-
-/*
-** Upvalues
-*/
-
-typedef struct UpVal {
- CommonHeader;
- TValue *v; /* points to stack or to its own value */
- union {
- TValue value; /* the value (when closed) */
- struct { /* double linked list (when open) */
- struct UpVal *prev;
- struct UpVal *next;
- } l;
- } u;
-} UpVal;
-
-
-/*
-** Closures
-*/
-
-#define ClosureHeader \
- CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
- struct Table *env
-
-typedef struct CClosure {
- ClosureHeader;
- lua_CFunction f;
- TValue upvalue[1];
-} CClosure;
-
-
-typedef struct LClosure {
- ClosureHeader;
- struct Proto *p;
- UpVal *upvals[1];
-} LClosure;
-
-
-typedef union Closure {
- CClosure c;
- LClosure l;
-} Closure;
-
-
-#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
-#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
-
-
-/*
-** Tables
-*/
-
-typedef union TKey {
- struct {
- TValuefields;
- struct Node *next; /* for chaining */
- } nk;
- TValue tvk;
-} TKey;
-
-
-typedef struct Node {
- TValue i_val;
- TKey i_key;
-} Node;
-
-
-typedef struct Table {
- CommonHeader;
- lu_byte flags; /* 1<<p means tagmethod(p) is not present */
- lu_byte lsizenode; /* log2 of size of `node' array */
- struct Table *metatable;
- TValue *array; /* array part */
- Node *node;
- Node *lastfree; /* any free position is before this position */
- GCObject *gclist;
- int sizearray; /* size of `array' array */
-} Table;
-
-
-
-/*
-** `module' operation for hashing (size is always a power of 2)
-*/
-#define lmod(s,size) \
- (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
-
-
-#define twoto(x) (1<<(x))
-#define sizenode(t) (twoto((t)->lsizenode))
-
-
-#define luaO_nilobject (&luaO_nilobject_)
-
-LUAI_DATA const TValue luaO_nilobject_;
-
-#define ceillog2(x) (luaO_log2((x)-1) + 1)
-
-LUAI_FUNC int luaO_log2 (unsigned int x);
-LUAI_FUNC int luaO_int2fb (unsigned int x);
-LUAI_FUNC int luaO_fb2int (int x);
-LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
-LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
-LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
- va_list argp);
-LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
-LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
-
-
-#endif
-
diff --git a/engines/sword25/util/pluto/pdep/lopcodes.h b/engines/sword25/util/pluto/pdep/lopcodes.h
deleted file mode 100644
index e1aed0f637..0000000000
--- a/engines/sword25/util/pluto/pdep/lopcodes.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
-** $Id$
-** Opcodes for Lua virtual machine
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lopcodes_h
-#define lopcodes_h
-
-#include "llimits.h"
-
-
-/*===========================================================================
- We assume that instructions are unsigned numbers.
- All instructions have an opcode in the first 6 bits.
- Instructions can have the following fields:
- `A' : 8 bits
- `B' : 9 bits
- `C' : 9 bits
- `Bx' : 18 bits (`B' and `C' together)
- `sBx' : signed Bx
-
- A signed argument is represented in excess K; that is, the number
- value is the unsigned value minus K. K is exactly the maximum value
- for that argument (so that -max is represented by 0, and +max is
- represented by 2*max), which is half the maximum for the corresponding
- unsigned argument.
-===========================================================================*/
-
-
-enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
-
-
-/*
-** size and position of opcode arguments.
-*/
-#define SIZE_C 9
-#define SIZE_B 9
-#define SIZE_Bx (SIZE_C + SIZE_B)
-#define SIZE_A 8
-
-#define SIZE_OP 6
-
-#define POS_OP 0
-#define POS_A (POS_OP + SIZE_OP)
-#define POS_C (POS_A + SIZE_A)
-#define POS_B (POS_C + SIZE_C)
-#define POS_Bx POS_C
-
-
-/*
-** limits for opcode arguments.
-** we use (signed) int to manipulate most arguments,
-** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
-*/
-#if SIZE_Bx < LUAI_BITSINT-1
-#define MAXARG_Bx ((1<<SIZE_Bx)-1)
-#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
-#else
-#define MAXARG_Bx MAX_INT
-#define MAXARG_sBx MAX_INT
-#endif
-
-
-#define MAXARG_A ((1<<SIZE_A)-1)
-#define MAXARG_B ((1<<SIZE_B)-1)
-#define MAXARG_C ((1<<SIZE_C)-1)
-
-
-/* creates a mask with `n' 1 bits at position `p' */
-#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p)
-
-/* creates a mask with `n' 0 bits at position `p' */
-#define MASK0(n,p) (~MASK1(n,p))
-
-/*
-** the following macros help to manipulate instructions
-*/
-
-#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
-#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
- ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
-
-#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
-#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
- ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
-
-#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
-#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
- ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
-
-#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
-#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
- ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
-
-#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
-#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
- ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
-
-#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
-#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
-
-
-#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \
- | (cast(Instruction, a)<<POS_A) \
- | (cast(Instruction, b)<<POS_B) \
- | (cast(Instruction, c)<<POS_C))
-
-#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
- | (cast(Instruction, a)<<POS_A) \
- | (cast(Instruction, bc)<<POS_Bx))
-
-
-/*
-** Macros to operate RK indices
-*/
-
-/* this bit 1 means constant (0 means register) */
-#define BITRK (1 << (SIZE_B - 1))
-
-/* test whether value is a constant */
-#define ISK(x) ((x) & BITRK)
-
-/* gets the index of the constant */
-#define INDEXK(r) ((int)(r) & ~BITRK)
-
-#define MAXINDEXRK (BITRK - 1)
-
-/* code a constant index as a RK value */
-#define RKASK(x) ((x) | BITRK)
-
-
-/*
-** invalid register that fits in 8 bits
-*/
-#define NO_REG MAXARG_A
-
-
-/*
-** R(x) - register
-** Kst(x) - constant (in constant table)
-** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
-*/
-
-
-/*
-** grep "ORDER OP" if you change these enums
-*/
-
-typedef enum {
-/*----------------------------------------------------------------------
-name args description
-------------------------------------------------------------------------*/
-OP_MOVE,/* A B R(A) := R(B) */
-OP_LOADK,/* A Bx R(A) := Kst(Bx) */
-OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
-OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
-OP_GETUPVAL,/* A B R(A) := UpValue[B] */
-
-OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
-OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
-
-OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
-OP_SETUPVAL,/* A B UpValue[B] := R(A) */
-OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
-
-OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
-
-OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
-
-OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
-OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
-OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
-OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
-OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
-OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
-OP_UNM,/* A B R(A) := -R(B) */
-OP_NOT,/* A B R(A) := not R(B) */
-OP_LEN,/* A B R(A) := length of R(B) */
-
-OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
-
-OP_JMP,/* sBx pc+=sBx */
-
-OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
-OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
-OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
-
-OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
-OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
-
-OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
-OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
-OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
-
-OP_FORLOOP,/* A sBx R(A)+=R(A+2);
- if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
-OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
-
-OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
- if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
-OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
-
-OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
-OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
-
-OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
-} OpCode;
-
-
-#define NUM_OPCODES (cast(int, OP_VARARG) + 1)
-
-
-
-/*===========================================================================
- Notes:
- (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
- and can be 0: OP_CALL then sets `top' to last_result+1, so
- next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
-
- (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
- set top (like in OP_CALL with C == 0).
-
- (*) In OP_RETURN, if (B == 0) then return up to `top'
-
- (*) In OP_SETLIST, if (B == 0) then B = `top';
- if (C == 0) then next `instruction' is real C
-
- (*) For comparisons, A specifies what condition the test should accept
- (true or false).
-
- (*) All `skips' (pc++) assume that next instruction is a jump
-===========================================================================*/
-
-
-/*
-** masks for instruction properties. The format is:
-** bits 0-1: op mode
-** bits 2-3: C arg mode
-** bits 4-5: B arg mode
-** bit 6: instruction set register A
-** bit 7: operator is a test
-*/
-
-enum OpArgMask {
- OpArgN, /* argument is not used */
- OpArgU, /* argument is used */
- OpArgR, /* argument is a register or a jump offset */
- OpArgK /* argument is a constant or register/constant */
-};
-
-LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
-
-#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
-#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
-#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
-#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
-#define testTMode(m) (luaP_opmodes[m] & (1 << 7))
-
-
-LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
-
-
-/* number of list items to accumulate before a SETLIST instruction */
-#define LFIELDS_PER_FLUSH 50
-
-
-#endif
diff --git a/engines/sword25/util/pluto/pdep/lstate.h b/engines/sword25/util/pluto/pdep/lstate.h
deleted file mode 100644
index 94a6249461..0000000000
--- a/engines/sword25/util/pluto/pdep/lstate.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
-** $Id$
-** Global State
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lstate_h
-#define lstate_h
-
-#include "lua.h"
-
-#include "lobject.h"
-#include "ltm.h"
-#include "lzio.h"
-
-
-
-struct lua_longjmp; /* defined in ldo.c */
-
-
-/* table of globals */
-#define gt(L) (&L->l_gt)
-
-/* registry */
-#define registry(L) (&G(L)->l_registry)
-
-
-/* extra stack space to handle TM calls and some other extras */
-#define EXTRA_STACK 5
-
-
-#define BASIC_CI_SIZE 8
-
-#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
-
-
-
-typedef struct stringtable {
- GCObject **hash;
- lu_int32 nuse; /* number of elements */
- int size;
-} stringtable;
-
-
-/*
-** informations about a call
-*/
-typedef struct CallInfo {
- StkId base; /* base for this function */
- StkId func; /* function index in the stack */
- StkId top; /* top for this function */
- const Instruction *savedpc;
- int nresults; /* expected number of results from this function */
- int tailcalls; /* number of tail calls lost under this entry */
-} CallInfo;
-
-
-
-#define curr_func(L) (clvalue(L->ci->func))
-#define ci_func(ci) (clvalue((ci)->func))
-#define f_isLua(ci) (!ci_func(ci)->c.isC)
-#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
-
-
-/*
-** `global state', shared by all threads of this state
-*/
-typedef struct global_State {
- stringtable strt; /* hash table for strings */
- lua_Alloc frealloc; /* function to reallocate memory */
- void *ud; /* auxiliary data to `frealloc' */
- lu_byte currentwhite;
- lu_byte gcstate; /* state of garbage collector */
- int sweepstrgc; /* position of sweep in `strt' */
- GCObject *rootgc; /* list of all collectable objects */
- GCObject **sweepgc; /* position of sweep in `rootgc' */
- GCObject *gray; /* list of gray objects */
- GCObject *grayagain; /* list of objects to be traversed atomically */
- GCObject *weak; /* list of weak tables (to be cleared) */
- GCObject *tmudata; /* last element of list of userdata to be GC */
- Mbuffer buff; /* temporary buffer for string concatentation */
- lu_mem GCthreshold;
- lu_mem totalbytes; /* number of bytes currently allocated */
- lu_mem estimate; /* an estimate of number of bytes actually in use */
- lu_mem gcdept; /* how much GC is `behind schedule' */
- int gcpause; /* size of pause between successive GCs */
- int gcstepmul; /* GC `granularity' */
- lua_CFunction panic; /* to be called in unprotected errors */
- TValue l_registry;
- struct lua_State *mainthread;
- UpVal uvhead; /* head of double-linked list of all open upvalues */
- struct Table *mt[NUM_TAGS]; /* metatables for basic types */
- TString *tmname[TM_N]; /* array with tag-method names */
-} global_State;
-
-
-/*
-** `per thread' state
-*/
-struct lua_State {
- CommonHeader;
- lu_byte status;
- StkId top; /* first free slot in the stack */
- StkId base; /* base of current function */
- global_State *l_G;
- CallInfo *ci; /* call info for current function */
- const Instruction *savedpc; /* `savedpc' of current function */
- StkId stack_last; /* last free slot in the stack */
- StkId stack; /* stack base */
- CallInfo *end_ci; /* points after end of ci array*/
- CallInfo *base_ci; /* array of CallInfo's */
- int stacksize;
- int size_ci; /* size of array `base_ci' */
- unsigned short nCcalls; /* number of nested C calls */
- unsigned short baseCcalls; /* nested C calls when resuming coroutine */
- lu_byte hookmask;
- lu_byte allowhook;
- int basehookcount;
- int hookcount;
- lua_Hook hook;
- TValue l_gt; /* table of globals */
- TValue env; /* temporary place for environments */
- GCObject *openupval; /* list of open upvalues in this stack */
- GCObject *gclist;
- struct lua_longjmp *errorJmp; /* current error recover point */
- ptrdiff_t errfunc; /* current error handling function (stack index) */
-};
-
-
-#define G(L) (L->l_G)
-
-
-/*
-** Union of all collectable objects
-*/
-union GCObject {
- GCheader gch;
- union TString ts;
- union Udata u;
- union Closure cl;
- struct Table h;
- struct Proto p;
- struct UpVal uv;
- struct lua_State th; /* thread */
-};
-
-
-/* macros to convert a GCObject into a specific value */
-#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
-#define gco2ts(o) (&rawgco2ts(o)->tsv)
-#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
-#define gco2u(o) (&rawgco2u(o)->uv)
-#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
-#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
-#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
-#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
-#define ngcotouv(o) \
- check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
-#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
-
-/* macro to convert any Lua object into a GCObject */
-#define obj2gco(v) (cast(GCObject *, (v)))
-
-
-LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
-LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
-
-#endif
-
diff --git a/engines/sword25/util/pluto/pdep/lstring.h b/engines/sword25/util/pluto/pdep/lstring.h
deleted file mode 100644
index c88e4c12a9..0000000000
--- a/engines/sword25/util/pluto/pdep/lstring.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-** $Id$
-** String table (keep all strings handled by Lua)
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lstring_h
-#define lstring_h
-
-
-#include "lgc.h"
-#include "lobject.h"
-#include "lstate.h"
-
-
-#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
-
-#define sizeudata(u) (sizeof(union Udata)+(u)->len)
-
-#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
-#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
- (sizeof(s)/sizeof(char))-1))
-
-#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
-
-LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
-LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
-LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
-
-
-#endif
diff --git a/engines/sword25/util/pluto/pdep/ltm.h b/engines/sword25/util/pluto/pdep/ltm.h
deleted file mode 100644
index 1b89683ef3..0000000000
--- a/engines/sword25/util/pluto/pdep/ltm.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-** $Id$
-** Tag methods
-** See Copyright Notice in lua.h
-*/
-
-#ifndef ltm_h
-#define ltm_h
-
-
-#include "lobject.h"
-
-
-/*
-* WARNING: if you change the order of this enumeration,
-* grep "ORDER TM"
-*/
-typedef enum {
- TM_INDEX,
- TM_NEWINDEX,
- TM_GC,
- TM_MODE,
- TM_EQ, /* last tag method with `fast' access */
- TM_ADD,
- TM_SUB,
- TM_MUL,
- TM_DIV,
- TM_MOD,
- TM_POW,
- TM_UNM,
- TM_LEN,
- TM_LT,
- TM_LE,
- TM_CONCAT,
- TM_CALL,
- TM_N /* number of elements in the enum */
-} TMS;
-
-
-
-#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
- ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
-
-#define fasttm(l,et,e) gfasttm(G(l), et, e)
-
-LUAI_DATA const char *const luaT_typenames[];
-
-
-LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
-LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
- TMS event);
-LUAI_FUNC void luaT_init (lua_State *L);
-
-#endif
diff --git a/engines/sword25/util/pluto/pdep/lua.h b/engines/sword25/util/pluto/pdep/lua.h
deleted file mode 100644
index 68dd887f0f..0000000000
--- a/engines/sword25/util/pluto/pdep/lua.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
-** $Id$
-** Lua - An Extensible Extension Language
-** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
-** See Copyright Notice at the end of this file
-*/
-
-
-#ifndef lua_h
-#define lua_h
-
-#include <stdarg.h>
-#include <stddef.h>
-
-
-#include "sword25/util/lua/luaconf.h"
-
-
-#define LUA_VERSION "Lua 5.1"
-#define LUA_RELEASE "Lua 5.1.3"
-#define LUA_VERSION_NUM 501
-#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
-#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
-
-
-/* mark for precompiled code (`<esc>Lua') */
-#define LUA_SIGNATURE "\033Lua"
-
-/* option for multiple returns in `lua_pcall' and `lua_call' */
-#define LUA_MULTRET (-1)
-
-
-/*
-** pseudo-indices
-*/
-#define LUA_REGISTRYINDEX (-10000)
-#define LUA_ENVIRONINDEX (-10001)
-#define LUA_GLOBALSINDEX (-10002)
-#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
-
-
-/* thread status; 0 is OK */
-#define LUA_YIELD 1
-#define LUA_ERRRUN 2
-#define LUA_ERRSYNTAX 3
-#define LUA_ERRMEM 4
-#define LUA_ERRERR 5
-
-
-typedef struct lua_State lua_State;
-
-typedef int (*lua_CFunction) (lua_State *L);
-
-
-/*
-** functions that read/write blocks when loading/dumping Lua chunks
-*/
-typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
-
-typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
-
-
-/*
-** prototype for memory-allocation functions
-*/
-typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
-
-
-/*
-** basic types
-*/
-#define LUA_TNONE (-1)
-
-#define LUA_TNIL 0
-#define LUA_TBOOLEAN 1
-#define LUA_TLIGHTUSERDATA 2
-#define LUA_TNUMBER 3
-#define LUA_TSTRING 4
-#define LUA_TTABLE 5
-#define LUA_TFUNCTION 6
-#define LUA_TUSERDATA 7
-#define LUA_TTHREAD 8
-
-
-
-/* minimum Lua stack available to a C function */
-#define LUA_MINSTACK 20
-
-
-/*
-** generic extra include file
-*/
-#if defined(LUA_USER_H)
-#include LUA_USER_H
-#endif
-
-
-/* type of numbers in Lua */
-typedef LUA_NUMBER lua_Number;
-
-
-/* type for integer functions */
-typedef LUA_INTEGER lua_Integer;
-
-
-
-/*
-** state manipulation
-*/
-LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
-LUA_API void (lua_close) (lua_State *L);
-LUA_API lua_State *(lua_newthread) (lua_State *L);
-
-LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
-
-
-/*
-** basic stack manipulation
-*/
-LUA_API int (lua_gettop) (lua_State *L);
-LUA_API void (lua_settop) (lua_State *L, int idx);
-LUA_API void (lua_pushvalue) (lua_State *L, int idx);
-LUA_API void (lua_remove) (lua_State *L, int idx);
-LUA_API void (lua_insert) (lua_State *L, int idx);
-LUA_API void (lua_replace) (lua_State *L, int idx);
-LUA_API int (lua_checkstack) (lua_State *L, int sz);
-
-LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
-
-
-/*
-** access functions (stack -> C)
-*/
-
-LUA_API int (lua_isnumber) (lua_State *L, int idx);
-LUA_API int (lua_isstring) (lua_State *L, int idx);
-LUA_API int (lua_iscfunction) (lua_State *L, int idx);
-LUA_API int (lua_isuserdata) (lua_State *L, int idx);
-LUA_API int (lua_type) (lua_State *L, int idx);
-LUA_API const char *(lua_typename) (lua_State *L, int tp);
-
-LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
-LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
-LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
-
-LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
-LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
-LUA_API int (lua_toboolean) (lua_State *L, int idx);
-LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
-LUA_API size_t (lua_objlen) (lua_State *L, int idx);
-LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
-LUA_API void *(lua_touserdata) (lua_State *L, int idx);
-LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
-LUA_API const void *(lua_topointer) (lua_State *L, int idx);
-
-
-/*
-** push functions (C -> stack)
-*/
-LUA_API void (lua_pushnil) (lua_State *L);
-LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
-LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
-LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
-LUA_API void (lua_pushstring) (lua_State *L, const char *s);
-LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
- va_list argp);
-LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
-LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
-LUA_API void (lua_pushboolean) (lua_State *L, int b);
-LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
-LUA_API int (lua_pushthread) (lua_State *L);
-
-
-/*
-** get functions (Lua -> stack)
-*/
-LUA_API void (lua_gettable) (lua_State *L, int idx);
-LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
-LUA_API void (lua_rawget) (lua_State *L, int idx);
-LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
-LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
-LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
-LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
-LUA_API void (lua_getfenv) (lua_State *L, int idx);
-
-
-/*
-** set functions (stack -> Lua)
-*/
-LUA_API void (lua_settable) (lua_State *L, int idx);
-LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
-LUA_API void (lua_rawset) (lua_State *L, int idx);
-LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
-LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
-LUA_API int (lua_setfenv) (lua_State *L, int idx);
-
-
-/*
-** `load' and `call' functions (load and run Lua code)
-*/
-LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
-LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
-LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
-LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
- const char *chunkname);
-
-LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
-
-
-/*
-** coroutine functions
-*/
-LUA_API int (lua_yield) (lua_State *L, int nresults);
-LUA_API int (lua_resume) (lua_State *L, int narg);
-LUA_API int (lua_status) (lua_State *L);
-
-/*
-** garbage-collection function and options
-*/
-
-#define LUA_GCSTOP 0
-#define LUA_GCRESTART 1
-#define LUA_GCCOLLECT 2
-#define LUA_GCCOUNT 3
-#define LUA_GCCOUNTB 4
-#define LUA_GCSTEP 5
-#define LUA_GCSETPAUSE 6
-#define LUA_GCSETSTEPMUL 7
-
-LUA_API int (lua_gc) (lua_State *L, int what, int data);
-
-
-/*
-** miscellaneous functions
-*/
-
-LUA_API int (lua_error) (lua_State *L);
-
-LUA_API int (lua_next) (lua_State *L, int idx);
-
-LUA_API void (lua_concat) (lua_State *L, int n);
-
-LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
-LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
-
-
-
-/*
-** ===============================================================
-** some useful macros
-** ===============================================================
-*/
-
-#define lua_pop(L,n) lua_settop(L, -(n)-1)
-
-#define lua_newtable(L) lua_createtable(L, 0, 0)
-
-#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
-
-#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
-
-#define lua_strlen(L,i) lua_objlen(L, (i))
-
-#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
-#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
-#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
-#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
-#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
-#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
-#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
-#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
-
-#define lua_pushliteral(L, s) \
- lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
-
-#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
-#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
-
-#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
-
-
-
-/*
-** compatibility macros and functions
-*/
-
-#define lua_open() luaL_newstate()
-
-#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
-
-#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
-
-#define lua_Chunkreader lua_Reader
-#define lua_Chunkwriter lua_Writer
-
-
-/* hack */
-LUA_API void lua_setlevel (lua_State *from, lua_State *to);
-
-
-/*
-** {======================================================================
-** Debug API
-** =======================================================================
-*/
-
-
-/*
-** Event codes
-*/
-#define LUA_HOOKCALL 0
-#define LUA_HOOKRET 1
-#define LUA_HOOKLINE 2
-#define LUA_HOOKCOUNT 3
-#define LUA_HOOKTAILRET 4
-
-
-/*
-** Event masks
-*/
-#define LUA_MASKCALL (1 << LUA_HOOKCALL)
-#define LUA_MASKRET (1 << LUA_HOOKRET)
-#define LUA_MASKLINE (1 << LUA_HOOKLINE)
-#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
-
-typedef struct lua_Debug lua_Debug; /* activation record */
-
-
-/* Functions to be called by the debuger in specific events */
-typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
-
-
-LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
-LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
-LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
-LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
-LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
-LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
-
-LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
-LUA_API lua_Hook lua_gethook (lua_State *L);
-LUA_API int lua_gethookmask (lua_State *L);
-LUA_API int lua_gethookcount (lua_State *L);
-
-
-struct lua_Debug {
- int event;
- const char *name; /* (n) */
- const char *namewhat; /* (n) `global', `local', `field', `method' */
- const char *what; /* (S) `Lua', `C', `main', `tail' */
- const char *source; /* (S) */
- int currentline; /* (l) */
- int nups; /* (u) number of upvalues */
- int linedefined; /* (S) */
- int lastlinedefined; /* (S) */
- char short_src[LUA_IDSIZE]; /* (S) */
- /* private part */
- int i_ci; /* active function */
-};
-
-/* }====================================================================== */
-
-
-/******************************************************************************
-* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining
-* a copy of this software and associated documentation files (the
-* "Software"), to deal in the Software without restriction, including
-* without limitation the rights to use, copy, modify, merge, publish,
-* distribute, sublicense, and/or sell copies of the Software, and to
-* permit persons to whom the Software is furnished to do so, subject to
-* the following conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-******************************************************************************/
-
-
-#endif
diff --git a/engines/sword25/util/pluto/pdep/lzio.h b/engines/sword25/util/pluto/pdep/lzio.h
index 2f167d7d58..2e37f8d202 100644
--- a/engines/sword25/util/pluto/pdep/lzio.h
+++ b/engines/sword25/util/pluto/pdep/lzio.h
@@ -8,7 +8,7 @@
#ifndef lzio_h
#define lzio_h
-#include "lua.h"
+#include "sword25/util/lua/lua.h"
#define EOZ (-1) /* end of stream */
diff --git a/engines/sword25/util/pluto/pdep/pdep.h b/engines/sword25/util/pluto/pdep/pdep.h
index c26f4566c5..664fc812b5 100644
--- a/engines/sword25/util/pluto/pdep/pdep.h
+++ b/engines/sword25/util/pluto/pdep/pdep.h
@@ -1,16 +1,17 @@
#ifndef PDEP_H
#define PDEP_H
-#include "lua.h"
-#include "ldo.h"
-#include "lfunc.h"
-#include "lgc.h"
-#include "llimits.h"
-#include "lobject.h"
-#include "lopcodes.h"
-#include "lstate.h"
-#include "lstring.h"
-#include "lauxlib.h"
+#include "sword25/util/lua/lua.h"
+#include "sword25/util/pluto/pdep/lzio.h"
+#include "sword25/util/lua/ldo.h"
+#include "sword25/util/lua/lfunc.h"
+#include "sword25/util/lua/lgc.h"
+#include "sword25/util/lua/llimits.h"
+#include "sword25/util/lua/lobject.h"
+#include "sword25/util/lua/lopcodes.h"
+#include "sword25/util/lua/lstate.h"
+#include "sword25/util/lua/lstring.h"
+#include "sword25/util/lua/lauxlib.h"
#define pdep_reallocv(L,b,on,n,e) \
diff --git a/engines/sword25/util/pluto/pptest.cpp b/engines/sword25/util/pluto/pptest.cpp
deleted file mode 100644
index 1bfecf2b75..0000000000
--- a/engines/sword25/util/pluto/pptest.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/* $Id$ */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "lua.h"
-#include "lualib.h"
-#include "lauxlib.h"
-
-static int LUAF_createludata(lua_State *L)
-{
- lua_pushlightuserdata(L, (void*)321);
- return 1;
-}
-
-/* A userdata that may be literally persisted */
-static int LUAF_boxinteger(lua_State *L)
-{
- /* num */
- int* ptr = lua_newuserdata(L, sizeof(int));
- /* num udata */
- *ptr = luaL_checkint(L, 1);
- lua_newtable(L);
- /* num udata mt */
- lua_pushstring(L, "__persist");
- /* num udata mt "__persist" */
- lua_pushboolean(L, 1);
- /* num udata mt "__persist" true */
- lua_rawset(L, 3);
- /* num udata mt */
- lua_setmetatable(L, 2);
- /* num udata */
- return 1;
-}
-
-static int LUAF_boxboolean(lua_State *L)
-{
- /* bool */
- char* ptr = lua_newuserdata(L, sizeof(char));
- /* bool udata */
- *ptr = lua_toboolean(L, 1);
- lua_newtable(L);
- /* num udata mt */
- lua_pushstring(L, "__persist");
- /* num udata mt "__persist" */
- lua_getglobal(L, "booleanpersist");
- /* num udata mt "__persist" booleanpersist */
- lua_rawset(L, 3);
- /* num udata mt */
- lua_setmetatable(L, 2);
- /* num udata */
- return 1;
-}
-
-static int LUAF_unboxboolean(lua_State *L)
-{
- /* udata */
- lua_pushboolean(L, *(char*)lua_touserdata(L, 1));
- /* udata bool */
- return 1;
-}
-
-static int LUAF_onerror(lua_State *L)
-{
-
- const char* str = 0;
- if(lua_gettop(L) != 0)
- {
- str = lua_tostring(L, -1);
- printf("%s\n",str);
- }
- return 0;
-}
-
-int main()
-{
- lua_State* L = lua_open();
-
- luaL_openlibs(L);
- lua_settop(L, 0);
-
- lua_register(L, "createludata", LUAF_createludata);
- lua_register(L, "boxinteger", LUAF_boxinteger);
- lua_register(L, "boxboolean", LUAF_boxboolean);
- lua_register(L, "unboxboolean", LUAF_unboxboolean);
- lua_register(L, "onerror", LUAF_onerror);
-
- lua_pushcfunction(L, LUAF_onerror);
- luaL_loadfile(L, "pptest.lua");
- lua_pcall(L,0,0,1);
-
- lua_close(L);
-
- return 0;
-}
diff --git a/engines/sword25/util/pluto/pptest.lua b/engines/sword25/util/pluto/pptest.lua
deleted file mode 100644
index 144da3ee80..0000000000
--- a/engines/sword25/util/pluto/pptest.lua
+++ /dev/null
@@ -1,168 +0,0 @@
--- $Id$
-
-require "pluto"
-
-permtable = { 1234 }
-
-perms = { [coroutine.yield] = 1, [permtable] = 2 }
-
-twithmt = {}
-setmetatable( twithmt, { __call = function() return 21 end } )
-
-function testfenv()
- return abc
-end
-
-setfenv(testfenv, { abc = 456 })
-
-function fa(i)
- local ia = i + 1
- return fb(ia)
-end
-
-function fb(i)
- local ib = i + 1
- ib = ib + fc(ib)
- return ib
-end
-
-function fc(i)
- local ic = i + 1
- coroutine.yield()
- return ic*2
-end
-
-function func()
- return 4
-end
-
-thr = coroutine.create(fa)
-coroutine.resume(thr, 2)
-
-testtbl = { a = 2, [2] = 4 }
-
-function funcreturningclosure(n)
- return function()
- return n
- end
-end
-
-function nestedfunc(n)
- return (function(m) return m+2 end)(n+3)
-end
-
-testloopa = {}
-testloopb = { testloopa = testloopa }
-testloopa.testloopb = testloopb
-
-sharedref = {}
-refa = {sharedref = sharedref}
-refb = {sharedref = sharedref}
-
-sptable = { a = 3 }
-
-setmetatable(sptable, {
- __persist = function(tbl)
- local a = tbl.a
- return function()
- return { a = a+3 }
- end
- end
-})
-
-literaludata = boxinteger(71)
-
-function booleanpersist(udata)
- local b = unboxboolean(udata)
- return function()
- return boxboolean(b)
- end
-end
-
-function makecounter()
- local a = 0
- return {
- inc = function() a = a + 1 end,
- cur = function() return a end
- }
-end
-
-function uvinthreadfunc()
- local a = 1
- local b = function()
- a = a+1
- coroutine.yield()
- a = a+1
- end
- a = a+1
- b()
- a = a+1
- return a
-end
-
-uvinthread = coroutine.create(uvinthreadfunc)
-coroutine.resume(uvinthread)
-
-niinmt = { a = 3 }
-setmetatable(niinmt, {__newindex = function(key, val) end })
-
-
-
-
-local function GenerateObjects()
- local Table = {}
-
- function Table:Func()
- return { Table, self }
- end
-
- function uvcycle()
- return Table:Func()
- end
-end
-
-GenerateObjects()
-
-
-
-function debuginfo(foo)
- foo = foo + foo
- return debug.getlocal(1,1)
-end
-
-rootobj = {
- testfalse = false,
- testtrue = true,
- testseven = 7,
- testfoobar = "foobar",
- testfuncreturnsfour = func,
- testnil = nil,
- testthread = thr,
- testperm = permtable,
- testmt = twithmt,
- testtbl = testtbl,
- testfenv = testfenv,
- testclosure = funcreturningclosure(11),
- testnilclosure = funcreturningclosure(nil),
- testnest = nestedfunc,
- testludata = createludata(),
- testlooptable = testloopa,
- testsharedrefa = refa,
- testsharedrefb = refb,
- testsptable = sptable,
- testliteraludata = literaludata,
- testspudata1 = boxboolean(true),
- testspudata2 = boxboolean(false),
- testsharedupval = makecounter(),
- testuvinthread = uvinthread,
- testniinmt = niinmt,
- testuvcycle = uvcycle,
- testdebuginfo = debuginfo
-}
-
-buf = pluto.persist(perms, rootobj)
-
-onerror()
-outfile = io.open("test.plh", "wb")
-outfile:write(buf)
-outfile:close()
diff --git a/engines/sword25/util/pluto/puptest.cpp b/engines/sword25/util/pluto/puptest.cpp
deleted file mode 100644
index e9aa7ea305..0000000000
--- a/engines/sword25/util/pluto/puptest.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/* $Id$ */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "lua.h"
-#include "lualib.h"
-#include "lauxlib.h"
-
-static int LUAF_checkludata(lua_State *L)
-{
- lua_pushboolean(L, lua_touserdata(L, -1) == (void*)321);
- return 1;
-}
-
-static int LUAF_unboxinteger(lua_State *L)
-{
- lua_pushnumber(L, *((int*)lua_touserdata(L, -1)));
- return 1;
-}
-
-static int LUAF_unboxboolean(lua_State *L)
-{
- /* udata */
- lua_pushboolean(L, *(char*)lua_touserdata(L, 1));
- /* udata bool */
- return 1;
-}
-
-static int LUAF_boxboolean(lua_State *L)
-{
- /* bool */
- char* ptr = lua_newuserdata(L, sizeof(char));
- /* bool udata */
- *ptr = lua_toboolean(L, 1);
- lua_newtable(L);
- /* num udata mt */
- lua_pushstring(L, "__persist");
- /* num udata mt "__persist" */
- lua_getglobal(L, "booleanpersist");
- /* num udata mt "__persist" booleanpersist */
- lua_rawset(L, 3);
- /* num udata mt */
- lua_setmetatable(L, 2);
- /* num udata */
- return 1;
-}
-
-static int LUAF_onerror(lua_State *L)
-{
-
- const char* str = 0;
- if(lua_gettop(L) != 0)
- {
- str = lua_tostring(L, -1);
- printf("%s\n",str);
- }
- return 0;
-}
-
-int main()
-{
- lua_State* L = lua_open();
-
- luaL_openlibs(L);
- lua_settop(L, 0);
-
- lua_register(L, "checkludata", LUAF_checkludata);
- lua_register(L, "unboxinteger", LUAF_unboxinteger);
- lua_register(L, "boxboolean", LUAF_boxboolean);
- lua_register(L, "unboxboolean", LUAF_unboxboolean);
- lua_register(L, "onerror", LUAF_onerror);
-
- lua_pushcfunction(L, LUAF_onerror);
- luaL_loadfile(L, "puptest.lua");
- lua_pcall(L,0,0,1);
-
- lua_close(L);
-
- return 0;
-}
diff --git a/engines/sword25/util/pluto/puptest.lua b/engines/sword25/util/pluto/puptest.lua
deleted file mode 100644
index e5ccdd64bd..0000000000
--- a/engines/sword25/util/pluto/puptest.lua
+++ /dev/null
@@ -1,93 +0,0 @@
--- $Id$
-
-require "pluto"
-
-permtable = { 1234 }
-
-perms = { [1] = coroutine.yield, [2] = permtable }
-
-function testcounter(counter)
- local a = counter.cur()
- counter.inc()
- return counter.cur() == a+1
-end
-
-function testuvinthread(func)
- local success, result = coroutine.resume(func)
- return success and result == 5
-end
-
-
-function test(rootobj)
- local passed = 0
- local total = 0
- local dotest = function(name,cond)
- total = total+1
- if cond then
- print(name, " PASSED")
- passed = passed + 1
- else
- print(name, "* FAILED")
- end
- end
-
-
- dotest("Boolean FALSE ", rootobj.testfalse == false)
- dotest("Boolean TRUE ", rootobj.testtrue == true)
- dotest("Number 7 ", rootobj.testseven == 7)
- dotest("String 'foobar' ", rootobj.testfoobar == "foobar")
- dotest("Func returning 4 ", rootobj.testfuncreturnsfour() == 4)
- dotest("Nil value ", rootobj.testnil == nil)
- dotest("Thread resume ", coroutine.resume(rootobj.testthread) == true,14)
- dotest("Table ", rootobj.testtbl.a == 2 and rootobj.testtbl[2] == 4);
- dotest("Permanent table ", rootobj.testperm == permtable)
- dotest("Table metatable ", rootobj.testmt() == 21)
- dotest("Function env ", rootobj.testfenv() == 456)
- dotest("Lua closure ", rootobj.testclosure() == 11)
- dotest("Nil in closure ", rootobj.testnilclosure() == nil)
- dotest("Nested func ", rootobj.testnest(1) == 6)
- dotest("Light userdata ", checkludata(rootobj.testludata))
- dotest("Looped tables ",
- rootobj.testlooptable.testloopb.testloopa ==
- rootobj.testlooptable)
- dotest("Shared reference ", rootobj.testsharedrefa.sharedref ==
- rootobj.testsharedrefb.sharedref)
- dotest("Identical tables ", rootobj.testsharedrefa ~=
- rootobj.testsharedrefb)
- dotest("Table special persist", rootobj.testsptable.a == 6)
- dotest("Udata literal persist",
- unboxinteger(rootobj.testliteraludata) == 71)
- dotest("Udata special persist",
- unboxboolean(rootobj.testspudata1) == true and
- unboxboolean(rootobj.testspudata2) == false)
- dotest("Shared upvalues ",
- testcounter(rootobj.testsharedupval))
- dotest("Open upvalues ",
- testuvinthread(rootobj.testuvinthread))
- dotest("Upvalue cycles ",
- rootobj.testuvcycle()[1] == rootobj.testuvcycle()[2])
- dotest("__newindex metamethod", rootobj.testniinmt.a == 3)
- dotest("Debug info ", (rootobj.testdebuginfo(2)) == "foo")
- print()
- if passed == total then
- print("All tests passed.")
- else
- print(passed .. "/" .. total .. " tests passed.")
- end
-end
-
-infile, err = io.open("test.plh", "rb")
-if infile == nil then
- error("While opening: " .. (err or "no error"))
-end
-
-buf, err = infile:read("*a")
-if buf == nil then
- error("While reading: " .. (err or "no error"))
-end
-
-infile:close()
-
-rootobj = pluto.unpersist(perms, buf)
-
-test(rootobj)
diff --git a/engines/teenagent/actor.cpp b/engines/teenagent/actor.cpp
index 1620aa700c..9dd30f43c3 100644
--- a/engines/teenagent/actor.cpp
+++ b/engines/teenagent/actor.cpp
@@ -27,6 +27,7 @@
#include "teenagent/resources.h"
#include "common/random.h"
+#include "common/textconsole.h"
namespace TeenAgent {
diff --git a/engines/teenagent/animation.cpp b/engines/teenagent/animation.cpp
index 56812001e8..623966f265 100644
--- a/engines/teenagent/animation.cpp
+++ b/engines/teenagent/animation.cpp
@@ -24,6 +24,7 @@
#include "teenagent/animation.h"
#include "common/endian.h"
+#include "common/textconsole.h"
namespace TeenAgent {
diff --git a/engines/teenagent/callbacks.cpp b/engines/teenagent/callbacks.cpp
index d0662a73d6..f4be917eac 100644
--- a/engines/teenagent/callbacks.cpp
+++ b/engines/teenagent/callbacks.cpp
@@ -27,6 +27,8 @@
#include "teenagent/resources.h"
#include "teenagent/dialog.h"
+#include "common/textconsole.h"
+
namespace TeenAgent {
#define CHECK_FLAG(addr, v) (res->dseg.get_byte(addr) == (v))
diff --git a/engines/teenagent/console.h b/engines/teenagent/console.h
index 2aba99428b..d6c24d4d8f 100644
--- a/engines/teenagent/console.h
+++ b/engines/teenagent/console.h
@@ -22,8 +22,8 @@
* $Id$
*/
-#ifndef TEENAGENT_DIALOG_H
-#define TEENAGENT_DIALOG_H
+#ifndef TEENAGENT_CONSOLE_H
+#define TEENAGENT_CONSOLE_H
#include "gui/debugger.h"
diff --git a/engines/teenagent/font.cpp b/engines/teenagent/font.cpp
index 7d252f59e8..2d98ae9de7 100644
--- a/engines/teenagent/font.cpp
+++ b/engines/teenagent/font.cpp
@@ -24,8 +24,12 @@
#include "teenagent/font.h"
#include "teenagent/pack.h"
+#include "common/debug.h"
+#include "common/endian.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "common/ptr.h"
+#include "graphics/surface.h"
namespace TeenAgent {
diff --git a/engines/teenagent/font.h b/engines/teenagent/font.h
index e08a3513af..29a8121435 100644
--- a/engines/teenagent/font.h
+++ b/engines/teenagent/font.h
@@ -25,6 +25,7 @@
#ifndef TEENAGENT_FONT_H
#define TEENAGENT_FONT_H
+#include "common/str.h"
#include "graphics/surface.h"
namespace TeenAgent {
diff --git a/engines/teenagent/inventory.cpp b/engines/teenagent/inventory.cpp
index bc4ac24da4..4d18d68502 100644
--- a/engines/teenagent/inventory.cpp
+++ b/engines/teenagent/inventory.cpp
@@ -24,6 +24,7 @@
#include "common/memstream.h"
#include "common/ptr.h"
+#include "common/textconsole.h"
#include "teenagent/inventory.h"
#include "teenagent/resources.h"
diff --git a/engines/teenagent/music.cpp b/engines/teenagent/music.cpp
index 395b2546b9..f0be5165f6 100644
--- a/engines/teenagent/music.cpp
+++ b/engines/teenagent/music.cpp
@@ -25,7 +25,9 @@
#include "teenagent/music.h"
#include "teenagent/resources.h"
+#include "common/debug.h"
#include "common/ptr.h"
+#include "common/textconsole.h"
namespace TeenAgent {
diff --git a/engines/teenagent/resources.cpp b/engines/teenagent/resources.cpp
index 9fe889fa41..69908239ab 100644
--- a/engines/teenagent/resources.cpp
+++ b/engines/teenagent/resources.cpp
@@ -24,6 +24,7 @@
#include "teenagent/resources.h"
#include "teenagent/teenagent.h"
+#include "common/textconsole.h"
#include "common/zlib.h"
namespace TeenAgent {
diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp
index f9756b5b91..ee431b2ab5 100644
--- a/engines/teenagent/scene.cpp
+++ b/engines/teenagent/scene.cpp
@@ -26,6 +26,9 @@
#include "common/debug.h"
#include "common/algorithm.h"
#include "common/ptr.h"
+#include "common/textconsole.h"
+
+#include "graphics/palette.h"
#include "teenagent/scene.h"
#include "teenagent/resources.h"
@@ -379,7 +382,7 @@ void Scene::init(int id, const Common::Point &pos) {
custom_animation[i].free();
if (background.pixels == NULL)
- background.create(320, 200, 1);
+ background.create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
warp(pos);
diff --git a/engines/teenagent/scene.h b/engines/teenagent/scene.h
index 2dc5bc9c83..28def3a064 100644
--- a/engines/teenagent/scene.h
+++ b/engines/teenagent/scene.h
@@ -35,6 +35,10 @@
#include "common/array.h"
#include "common/list.h"
+namespace Common {
+struct Event;
+}
+
namespace TeenAgent {
class TeenAgentEngine;
diff --git a/engines/teenagent/segment.cpp b/engines/teenagent/segment.cpp
index 7ba680907b..829c84765d 100644
--- a/engines/teenagent/segment.cpp
+++ b/engines/teenagent/segment.cpp
@@ -23,6 +23,7 @@
*/
#include "teenagent/segment.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace TeenAgent {
diff --git a/engines/teenagent/surface.cpp b/engines/teenagent/surface.cpp
index 96672ca1b3..545b0f75f0 100644
--- a/engines/teenagent/surface.cpp
+++ b/engines/teenagent/surface.cpp
@@ -61,7 +61,7 @@ void Surface::load(Common::SeekableReadStream *stream, Type type) {
}
//debug(0, "creating surface %ux%u -> %u,%u", w_, h_, x, y);
- create(w_, h_, 1);
+ create(w_, h_, Graphics::PixelFormat::createFormatCLUT8());
stream->read(pixels, w_ * h_);
}
diff --git a/engines/teenagent/surface.h b/engines/teenagent/surface.h
index b44fd3c21a..82c13c84bd 100644
--- a/engines/teenagent/surface.h
+++ b/engines/teenagent/surface.h
@@ -25,8 +25,12 @@
#ifndef TEENAGENT_SURFACE_H
#define TEENAGENT_SURFACE_H
+#include "common/rect.h"
#include "graphics/surface.h"
-#include "common/stream.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
namespace TeenAgent {
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
index e66de70079..ec1e945f8d 100644
--- a/engines/teenagent/teenagent.cpp
+++ b/engines/teenagent/teenagent.cpp
@@ -27,6 +27,7 @@
#include "common/events.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "backends/audiocd/audiocd.h"
@@ -37,6 +38,7 @@
#include "audio/decoders/raw.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
#include "graphics/thumbnail.h"
#include "teenagent/console.h"
diff --git a/engines/testbed/detection.cpp b/engines/testbed/detection.cpp
index 734ed0c22a..b08cca291a 100644
--- a/engines/testbed/detection.cpp
+++ b/engines/testbed/detection.cpp
@@ -23,10 +23,8 @@
*
*/
-#include "common/config-manager.h"
#include "engines/advancedDetector.h"
#include "common/system.h"
-#include "common/fs.h"
#include "base/plugins.h"
diff --git a/engines/testbed/events.cpp b/engines/testbed/events.cpp
index b0a930172d..37b0a7ead4 100644
--- a/engines/testbed/events.cpp
+++ b/engines/testbed/events.cpp
@@ -24,10 +24,17 @@
#include "common/events.h"
#include "common/keyboard.h"
+#include "common/rect.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "common/util.h"
#include "engines/engine.h"
#include "graphics/cursorman.h"
+#include "graphics/font.h"
+#include "graphics/fontman.h"
+#include "graphics/surface.h"
#include "testbed/events.h"
#include "testbed/graphics.h"
diff --git a/engines/testbed/graphics.cpp b/engines/testbed/graphics.cpp
index a0e2754fe4..c8558e30f4 100644
--- a/engines/testbed/graphics.cpp
+++ b/engines/testbed/graphics.cpp
@@ -33,6 +33,7 @@
#include "graphics/cursorman.h"
#include "graphics/fontman.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "graphics/VectorRendererSpec.h"
@@ -229,16 +230,16 @@ void rotatePalette(byte *palette, int size) {
// Rotate the colors starting from address palette "size" times
// take a temporary palette color
- byte tColor[4] = {0};
+ byte tColor[3] = {0};
// save first color in it.
- memcpy(tColor, &palette[0], 4 * sizeof(byte));
+ memcpy(tColor, &palette[0], 3 * sizeof(byte));
// Move each color upward by 1
for (int i = 0; i < size - 1; i++) {
- memcpy(&palette[i * 4], &palette[(i + 1) * 4], 4 * sizeof(byte));
+ memcpy(&palette[i * 3], &palette[(i + 1) * 3], 3 * sizeof(byte));
}
// Assign last color to tcolor
- memcpy(&palette[(size - 1) * 4], tColor, 4 * sizeof(byte));
+ memcpy(&palette[(size - 1) * 3], tColor, 3 * sizeof(byte));
}
/**
@@ -360,7 +361,7 @@ void GFXtests::drawEllipse(int cx, int cy, int a, int b) {
// Illuminate the points lying on ellipse
- for (theta = 0; theta <= PI / 2; theta += PI / 360) {
+ for (theta = 0; theta <= M_PI / 2; theta += M_PI / 360) {
x = (int)(b * sin(theta) + 0.5);
y = (int)(a * cos(theta) + 0.5);
@@ -606,7 +607,7 @@ TestExitStatus GFXtests::mouseMovements() {
Common::String info = "Testing Automated Mouse movements.\n"
"You should expect cursor hotspot(top-left corner) to automatically move from (0, 0) to (100, 100).\n"
- "There we have a rectangle drawn, finally the cursor would lie centred in that rectangle.";
+ "There we have a rectangle drawn, finally the cursor would lie centered in that rectangle.";
if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Skipping test : Mouse Movements\n");
@@ -637,7 +638,7 @@ TestExitStatus GFXtests::mouseMovements() {
g_system->delayMillis(1500);
CursorMan.showMouse(false);
- if (Testsuite::handleInteractiveInput("Was the cursor centred in the rectangle at (100, 100)?", "Yes", "No", kOptionRight)) {
+ if (Testsuite::handleInteractiveInput("Was the cursor centered in the rectangle at (100, 100)?", "Yes", "No", kOptionRight)) {
return kTestFailed;
}
@@ -654,7 +655,7 @@ TestExitStatus GFXtests::copyRectToScreen() {
Testsuite::clearScreen();
Common::String info = "Testing Blitting a Bitmap to screen.\n"
- "You should expect to see a 20x40 yellow horizontal rectangle centred at the screen.";
+ "You should expect to see a 20x40 yellow horizontal rectangle centered at the screen.";
if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Skipping test : Blitting Bitmap\n");
@@ -1113,7 +1114,7 @@ TestExitStatus GFXtests::pixelFormats() {
Graphics::Surface *screen = g_system->lockScreen();
- // Draw 6 rectangles centred at (50, 160), piled over one another
+ // Draw 6 rectangles centered at (50, 160), piled over one another
// each with color in colors[]
for (int i = 0; i < 6; i++) {
screen->fillRect(Common::Rect::center(160, 20 + i * 10, 100, 10), colors[i]);
diff --git a/engines/testbed/midi.cpp b/engines/testbed/midi.cpp
index 673f5d8547..7ec24aa670 100644
--- a/engines/testbed/midi.cpp
+++ b/engines/testbed/midi.cpp
@@ -96,7 +96,7 @@ TestExitStatus MidiTests::playMidiMusic() {
int errCode = driver->open();
if (errCode) {
- Common::String errMsg = driver->getErrorName(errCode);
+ Common::String errMsg = MidiDriver::getErrorName(errCode);
Testsuite::writeOnScreen(errMsg, Common::Point(0, 100));
Testsuite::logPrintf("Error! %s", errMsg.c_str());
return kTestFailed;
diff --git a/engines/testbed/savegame.cpp b/engines/testbed/savegame.cpp
index b91d9fc47c..0ffd3672fa 100644
--- a/engines/testbed/savegame.cpp
+++ b/engines/testbed/savegame.cpp
@@ -138,9 +138,9 @@ TestExitStatus SaveGametests::testListingSavefile() {
Common::Error error = saveFileMan->getError();
- if (error != Common::kNoError) {
+ if (error.getCode() != Common::kNoError) {
// Abort. Some Error in writing files
- Testsuite::logDetailedPrintf("Error while creating savefiles: %s\n", Common::errorToString(error));
+ Testsuite::logDetailedPrintf("Error while creating savefiles: %s\n", error.getDesc().c_str());
return kTestFailed;
}
@@ -177,7 +177,7 @@ TestExitStatus SaveGametests::testErrorMessages() {
readAndVerifyData("tBedSomeNonExistentSaveFile.0", "File doesn't exists!");
Common::Error error = saveFileMan->getError();
- if (error == Common::kNoError) {
+ if (error.getCode() == Common::kNoError) {
// blunder! how come?
Testsuite::logDetailedPrintf("SaveFileMan.getError() failed\n");
return kTestFailed;
diff --git a/engines/testbed/sound.cpp b/engines/testbed/sound.cpp
index 76f9e850c0..dca116368e 100644
--- a/engines/testbed/sound.cpp
+++ b/engines/testbed/sound.cpp
@@ -26,6 +26,8 @@
#include "backends/audiocd/audiocd.h"
+#include "common/config-manager.h"
+
#include "testbed/sound.h"
namespace Testbed {
diff --git a/engines/testbed/testbed.cpp b/engines/testbed/testbed.cpp
index 1ceecb8ebf..179be2bb8b 100644
--- a/engines/testbed/testbed.cpp
+++ b/engines/testbed/testbed.cpp
@@ -24,7 +24,12 @@
#include "common/debug-channels.h"
#include "common/scummsys.h"
-#include "common/system.h"
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/error.h"
+#include "common/fs.h"
+#include "common/rect.h"
+#include "common/str.h"
#include "engines/util.h"
diff --git a/engines/testbed/testbed.h b/engines/testbed/testbed.h
index e0feb52ff5..ca803a4cec 100644
--- a/engines/testbed/testbed.h
+++ b/engines/testbed/testbed.h
@@ -25,9 +25,9 @@
#ifndef TESTBED_H
#define TESTBED_H
-#include "engines/engine.h"
+#include "common/array.h"
-#include "gui/options.h"
+#include "engines/engine.h"
#include "testbed/config.h"
#include "testbed/testsuite.h"
diff --git a/engines/testbed/testsuite.h b/engines/testbed/testsuite.h
index a738f40764..94b3d70fd4 100644
--- a/engines/testbed/testsuite.h
+++ b/engines/testbed/testsuite.h
@@ -25,9 +25,12 @@
#ifndef TESTBED_TESTSUITE_H
#define TESTBED_TESTSUITE_H
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/scummsys.h"
#include "common/system.h"
#include "common/str.h"
-#include "common/array.h"
+#include "graphics/font.h"
#include "graphics/fontman.h"
diff --git a/engines/tinsel/actors.cpp b/engines/tinsel/actors.cpp
index 7a1f9fbf55..9ec253e512 100644
--- a/engines/tinsel/actors.cpp
+++ b/engines/tinsel/actors.cpp
@@ -44,6 +44,7 @@
#include "tinsel/tinsel.h"
#include "tinsel/token.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Tinsel {
@@ -108,7 +109,7 @@ struct ACTORINFO {
bool bEscOn;
int escEvent;
- COLORREF textColour; // Text colour
+ COLORREF textColor; // Text color
SCNHANDLE playFilm; // revert to this after talks
SCNHANDLE talkFilm; // this be deleted in the future!
@@ -140,7 +141,7 @@ typedef TAGACTOR *PTAGACTOR;
static ACTORINFO *actorInfo = NULL;
-static COLORREF defaultColour = 0; // Text colour
+static COLORREF defaultColor = 0; // Text color
static bool bActorsOn = false;
@@ -479,13 +480,13 @@ void DropActors() {
for (int i = 0; i < NumActors; i++) {
if (TinselV2) {
- // Save text colour
- COLORREF tColour = actorInfo[i].textColour;
+ // Save text color
+ COLORREF tColor = actorInfo[i].textColor;
memset(&actorInfo[i], 0, sizeof(ACTORINFO));
- // Restor text colour
- actorInfo[i].textColour = tColour;
+ // Restor text color
+ actorInfo[i].textColor = tColor;
// Clear extra arrays
memset(zFactors, 0, NumActors);
@@ -1278,7 +1279,7 @@ void SetMoverZ(PMOVER pMover, int y, int32 zFactor) {
/**
* Stores actor's attributes.
- * Currently only the speech colours.
+ * Currently only the speech colors.
*/
void storeActorAttr(int ano, int r1, int g1, int b1) {
assert((ano > 0 && ano <= NumActors) || ano == -1); // illegal actor number
@@ -1288,36 +1289,36 @@ void storeActorAttr(int ano, int r1, int g1, int b1) {
if (b1 > MAX_INTENSITY) b1 = MAX_INTENSITY; // }
if (ano == -1)
- defaultColour = TINSEL_RGB(r1, g1, b1);
+ defaultColor = TINSEL_RGB(r1, g1, b1);
else
- actorInfo[ano - 1].textColour = TINSEL_RGB(r1, g1, b1);
+ actorInfo[ano - 1].textColor = TINSEL_RGB(r1, g1, b1);
}
/**
- * Called from ActorRGB() - Stores actor's speech colour.
+ * Called from ActorRGB() - Stores actor's speech color.
*/
-void SetActorRGB(int ano, COLORREF colour) {
+void SetActorRGB(int ano, COLORREF color) {
assert(ano >= 0 && ano <= NumActors);
if (ano)
- actorInfo[ano - 1].textColour = TO_LE_32(colour);
+ actorInfo[ano - 1].textColor = TO_LE_32(color);
else
- defaultColour = TO_LE_32(colour);
+ defaultColor = TO_LE_32(color);
}
/**
- * Get the actor's stored speech colour.
+ * Get the actor's stored speech color.
* @param ano Actor Id
*/
COLORREF GetActorRGB(int ano) {
// Not used in JAPAN version
assert((ano >= -1) && (ano <= NumActors)); // illegal actor number
- if ((ano == -1) || !actorInfo[ano - 1].textColour)
- return defaultColour;
+ if ((ano == -1) || !actorInfo[ano - 1].textColor)
+ return defaultColor;
else
- return actorInfo[ano - 1].textColour;
+ return actorInfo[ano - 1].textColor;
}
/**
diff --git a/engines/tinsel/actors.h b/engines/tinsel/actors.h
index fbad5d9955..2be42b00e6 100644
--- a/engines/tinsel/actors.h
+++ b/engines/tinsel/actors.h
@@ -109,7 +109,7 @@ void ActorEvent(int ano, TINSEL_EVENT event, PLR_EVENT be);
void storeActorAttr(int ano, int r1, int g1, int b1);
COLORREF GetActorRGB(int ano);
-void SetActorRGB(int ano, COLORREF colour);
+void SetActorRGB(int ano, COLORREF color);
void SetActorZfactor(int ano, uint32 zFactor);
uint32 GetActorZfactor(int ano);
diff --git a/engines/tinsel/adpcm.cpp b/engines/tinsel/adpcm.cpp
new file mode 100644
index 0000000000..530395d754
--- /dev/null
+++ b/engines/tinsel/adpcm.cpp
@@ -0,0 +1,171 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stream.h"
+#include "common/util.h"
+
+#include "tinsel/adpcm.h"
+
+namespace Tinsel {
+
+static const double TinselFilterTable[4][2] = {
+ {0, 0 },
+ {0.9375, 0},
+ {1.796875, -0.8125},
+ {1.53125, -0.859375}
+};
+
+void Tinsel_ADPCMStream::readBufferTinselHeader() {
+ uint8 start = _stream->readByte();
+ uint8 filterVal = (start & 0xC0) >> 6;
+
+ if ((start & 0x20) != 0) {
+ //Lower 6 bit are negative
+
+ // Negate
+ start = ~(start | 0xC0) + 1;
+
+ _status.predictor = (unsigned long long int)1 << start;
+ } else {
+ // Lower 6 bit are positive
+
+ // Truncate
+ start &= 0x1F;
+
+ _status.predictor = ((double) 1.0) / ((unsigned long long int)1 << start);
+ }
+
+ _status.K0 = TinselFilterTable[filterVal][0];
+ _status.K1 = TinselFilterTable[filterVal][1];
+}
+
+int16 Tinsel_ADPCMStream::decodeTinsel(int16 code, double eVal) {
+ double sample;
+
+ sample = (double) code;
+ sample *= eVal * _status.predictor;
+ sample += (_status.d0 * _status.K0) + (_status.d1 * _status.K1);
+
+ _status.d1 = _status.d0;
+ _status.d0 = sample;
+
+ return (int16) CLIP<double>(sample, -32768.0, 32767.0);
+}
+
+int Tinsel4_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
+ int samples;
+ uint16 data;
+ const double eVal = 1.142822265;
+
+ samples = 0;
+
+ assert(numSamples % 2 == 0);
+
+ while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
+ if (_blockPos[0] == _blockAlign) {
+ readBufferTinselHeader();
+ _blockPos[0] = 0;
+ }
+
+ for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2, _blockPos[0]++) {
+ // Read 1 byte = 8 bits = two 4 bit blocks
+ data = _stream->readByte();
+ buffer[samples] = decodeTinsel((data << 8) & 0xF000, eVal);
+ buffer[samples+1] = decodeTinsel((data << 12) & 0xF000, eVal);
+ }
+ }
+
+ return samples;
+}
+
+int Tinsel6_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
+ int samples;
+ const double eVal = 1.032226562;
+
+ samples = 0;
+
+ while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
+ if (_blockPos[0] == _blockAlign) {
+ readBufferTinselHeader();
+ _blockPos[0] = 0;
+ _chunkPos = 0;
+ }
+
+ for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples++, _chunkPos = (_chunkPos + 1) % 4) {
+
+ switch (_chunkPos) {
+ case 0:
+ _chunkData = _stream->readByte();
+ buffer[samples] = decodeTinsel((_chunkData << 8) & 0xFC00, eVal);
+ break;
+ case 1:
+ _chunkData = (_chunkData << 8) | (_stream->readByte());
+ buffer[samples] = decodeTinsel((_chunkData << 6) & 0xFC00, eVal);
+ _blockPos[0]++;
+ break;
+ case 2:
+ _chunkData = (_chunkData << 8) | (_stream->readByte());
+ buffer[samples] = decodeTinsel((_chunkData << 4) & 0xFC00, eVal);
+ _blockPos[0]++;
+ break;
+ case 3:
+ _chunkData = (_chunkData << 8);
+ buffer[samples] = decodeTinsel((_chunkData << 2) & 0xFC00, eVal);
+ _blockPos[0]++;
+ break;
+ }
+
+ }
+
+ }
+
+ return samples;
+}
+
+int Tinsel8_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
+ int samples;
+ byte data;
+ const double eVal = 1.007843258;
+
+ samples = 0;
+
+ while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
+ if (_blockPos[0] == _blockAlign) {
+ readBufferTinselHeader();
+ _blockPos[0] = 0;
+ }
+
+ for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples++, _blockPos[0]++) {
+ // Read 1 byte = 8 bits = one 8 bit block
+ data = _stream->readByte();
+ buffer[samples] = decodeTinsel(data << 8, eVal);
+ }
+ }
+
+ return samples;
+}
+
+
+} // End of namespace Tinsel
diff --git a/engines/tinsel/adpcm.h b/engines/tinsel/adpcm.h
new file mode 100644
index 0000000000..79d537eef6
--- /dev/null
+++ b/engines/tinsel/adpcm.h
@@ -0,0 +1,105 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TINSEL_ADPCM_H
+#define TINSEL_ADPCM_H
+
+#include "audio/decoders/adpcm_intern.h"
+
+namespace Tinsel {
+
+class Tinsel_ADPCMStream : public Audio::ADPCMStream {
+protected:
+ struct {
+ // Tinsel
+ double predictor;
+ double K0, K1;
+ double d0, d1;
+ } _status;
+
+ void reset() {
+ ADPCMStream::reset();
+ memset(&_status, 0, sizeof(_status));
+ }
+
+ int16 decodeTinsel(int16, double);
+ void readBufferTinselHeader();
+
+public:
+ Tinsel_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+
+ if (blockAlign == 0)
+ error("Tinsel_ADPCMStream(): blockAlign isn't specified");
+
+ if (channels != 1)
+ error("Tinsel_ADPCMStream(): Tinsel ADPCM only supports mono");
+
+ memset(&_status, 0, sizeof(_status));
+ }
+
+};
+
+class Tinsel4_ADPCMStream : public Tinsel_ADPCMStream {
+public:
+ Tinsel4_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+};
+
+class Tinsel6_ADPCMStream : public Tinsel_ADPCMStream {
+protected:
+ uint8 _chunkPos;
+ uint16 _chunkData;
+
+ void reset() {
+ ADPCMStream::reset();
+ _chunkPos = 0;
+ _chunkData = 0;
+ }
+
+public:
+ Tinsel6_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+ _chunkPos = 0;
+ _chunkData = 0;
+ }
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+};
+
+class Tinsel8_ADPCMStream : public Tinsel_ADPCMStream {
+public:
+ Tinsel8_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+};
+
+
+} // End of namespace Tinsel
+
+#endif
diff --git a/engines/tinsel/anim.cpp b/engines/tinsel/anim.cpp
index 37d8de925e..61c8b67624 100644
--- a/engines/tinsel/anim.cpp
+++ b/engines/tinsel/anim.cpp
@@ -31,6 +31,7 @@
#include "tinsel/sched.h"
#include "tinsel/tinsel.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Tinsel {
diff --git a/engines/tinsel/background.cpp b/engines/tinsel/background.cpp
index 560216aadb..dfff093c09 100644
--- a/engines/tinsel/background.cpp
+++ b/engines/tinsel/background.cpp
@@ -39,9 +39,6 @@ namespace Tinsel {
// current background
const BACKGND *pCurBgnd = NULL;
-// FIXME: Not yet used
-static bool bEntireRedraw;
-
/**
* Called to initialise a background.
* @param pBgnd Pointer to data struct for current background
@@ -54,8 +51,8 @@ void InitBackground(const BACKGND *pBgnd) {
// set current background
pCurBgnd = pBgnd;
- // init background sky colour
- SetBgndColour(pBgnd->rgbSkyColour);
+ // init background sky color
+ SetBgndColor(pBgnd->rgbSkyColor);
// start of playfield array
pPlayfield = pBgnd->fieldArray;
@@ -130,11 +127,11 @@ void PlayfieldGetPos(int which, int *pXpos, int *pYpos) {
}
/**
- * Returns the x position of the centre of the specified playfield
+ * Returns the x position of the center of the specified playfield
* @param which Which playfield
*/
-int PlayfieldGetCentreX(int which) {
+int PlayfieldGetCenterX(int which) {
PLAYFIELD *pPlayfield; // pointer to relavent playfield
// make sure there is a background
@@ -257,9 +254,4 @@ void DrawBackgnd() {
ResetClipRect();
}
-void ForceEntireRedraw() {
- bEntireRedraw = true;
-}
-
-
} // End of namespace Tinsel
diff --git a/engines/tinsel/background.h b/engines/tinsel/background.h
index 81b490488e..06789e50bf 100644
--- a/engines/tinsel/background.h
+++ b/engines/tinsel/background.h
@@ -60,7 +60,7 @@ struct PLAYFIELD {
/** multi-playfield background structure - a backgnd is a container of playfields */
struct BACKGND {
- COLORREF rgbSkyColour; ///< background sky colour
+ COLORREF rgbSkyColor; ///< background sky color
Common::Point ptInitWorld; ///< initial world position
Common::Rect rcScrollLimits; ///< scroll limits
int refreshRate; ///< background update process refresh rate
@@ -93,7 +93,7 @@ void PlayfieldGetPos( // Returns the xy position of the specified playfield in
int *pXpos, // returns current x position
int *pYpos); // returns current y position
-int PlayfieldGetCentreX( // Returns the xy position of the specified playfield in the current background
+int PlayfieldGetCenterX( // Returns the xy position of the specified playfield in the current background
int which); // which playfield
OBJECT *GetPlayfieldList( // Returns the display list for the specified playfield
@@ -110,8 +110,6 @@ OBJECT *GetBgObject();
SCNHANDLE BgPal();
-void ForceEntireRedraw();
-
int BgWidth();
int BgHeight();
diff --git a/engines/tinsel/bg.cpp b/engines/tinsel/bg.cpp
index 68653b16f4..0e67c3a06e 100644
--- a/engines/tinsel/bg.cpp
+++ b/engines/tinsel/bg.cpp
@@ -40,6 +40,7 @@
#include "tinsel/tinlib.h" // For Control()
#include "tinsel/tinsel.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Tinsel {
@@ -158,7 +159,7 @@ static void BGmainProcess(CORO_PARAM, const void *param) {
FadeInFast(NULL);
bDoFadeIn = false;
} else if (TinselV2)
- PokeInTagColour();
+ PokeInTagColor();
for (;;) {
for (int i = 0; i < bgReels; i++) {
diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp
index 3f56288aca..793febdc21 100644
--- a/engines/tinsel/bmv.cpp
+++ b/engines/tinsel/bmv.cpp
@@ -44,6 +44,8 @@
#include "audio/decoders/raw.h"
+#include "common/textconsole.h"
+
namespace Tinsel {
//----------------- LOCAL DEFINES ----------------------------
@@ -81,7 +83,7 @@ namespace Tinsel {
#define BIT0 0x01
#define CD_XSCR 0x04 // Screen has a scroll offset
-#define CD_CMAP 0x08 // Colour map is included
+#define CD_CMAP 0x08 // Color map is included
#define CD_CMND 0x10 // Command is included
#define CD_AUDIO 0x20 // Audio data is included
#define CD_EXTEND 0x40 // Extended modes "A"-"z"
@@ -350,7 +352,7 @@ BMVPlayer::BMVPlayer() {
memset(texts, 0, sizeof(texts));
- talkColour = 0;
+ talkColor = 0;
bigProblemCount = 0;
bIsText = 0;
movieTick = 0;
@@ -382,8 +384,8 @@ void BMVPlayer::MoviePalette(int paletteOffset) {
UpdateDACqueue(1, 255, &moviePal[1]);
// Don't clobber talk
- if (talkColour != 0)
- SetTextPal(talkColour);
+ if (talkColor != 0)
+ SetTextPal(talkColor);
}
void BMVPlayer::InitialiseMovieSound() {
@@ -490,7 +492,7 @@ void BMVPlayer::BmvDrawText(bool bDraw) {
|-------------------------------------------------------|
\*-----------------------------------------------------*/
-void BMVPlayer::MovieText(CORO_PARAM, int stringId, int x, int y, int fontId, COLORREF *pTalkColour, int duration) {
+void BMVPlayer::MovieText(CORO_PARAM, int stringId, int x, int y, int fontId, COLORREF *pTalkColor, int duration) {
SCNHANDLE hFont;
int index;
@@ -502,8 +504,8 @@ void BMVPlayer::MovieText(CORO_PARAM, int stringId, int x, int y, int fontId, CO
} else {
// It's a 'talk'
- if (pTalkColour != NULL)
- SetTextPal(*pTalkColour);
+ if (pTalkColor != NULL)
+ SetTextPal(*pTalkColor);
hFont = GetTalkFontHandle();
index = 1;
}
@@ -519,7 +521,7 @@ void BMVPlayer::MovieText(CORO_PARAM, int stringId, int x, int y, int fontId, CO
0,
x, y,
hFont,
- TXT_CENTRE, 0);
+ TXT_CENTER, 0);
KeepOnScreen(texts[index].pText, &x, &y);
}
@@ -541,13 +543,13 @@ int BMVPlayer::MovieCommand(char cmd, int commandOffset) {
} else {
if (_vm->_config->_useSubtitles) {
TALK_CMD *pCmd = (TALK_CMD *)(bigBuffer + commandOffset);
- talkColour = TINSEL_RGB(pCmd->r, pCmd->g, pCmd->b);
+ talkColor = TINSEL_RGB(pCmd->r, pCmd->g, pCmd->b);
MovieText(nullContext, (int16)READ_LE_UINT16(&pCmd->stringId),
(int16)READ_LE_UINT16(&pCmd->x),
(int16)READ_LE_UINT16(&pCmd->y),
0,
- &talkColour,
+ &talkColor,
pCmd->duration);
}
return sz_CMD_TALK_pkt;
@@ -693,7 +695,7 @@ void BMVPlayer::InitialiseBMV() {
bFileEnd = false;
blobsInBuffer = 0;
memset(texts, 0, sizeof(texts));
- talkColour = 0;
+ talkColor = 0;
bigProblemCount = 0;
movieTick = 0;
@@ -1025,7 +1027,6 @@ bool BMVPlayer::DoSoundFrame() {
void BMVPlayer::CopyMovieToScreen() {
// Not if not up and running yet!
if (!screenBuffer || (currentFrame == 0)) {
- ForceEntireRedraw();
DrawBackgnd();
return;
}
@@ -1046,21 +1047,6 @@ void BMVPlayer::CopyMovieToScreen() {
}
/**
- * LookAtBuffers
- */
-void BMVPlayer::LookAtBuffers() {
- // FIXME: What's the point of this function???
- // Maybe to ensure the relevant data is loaded into cache by the CPU?
- static int junk; // FIXME: Avoid non-const global vars
- int i;
-
- if (bigBuffer) {
- for (i = 0; i < NUM_SLOTS; i++)
- junk += bigBuffer[i*SLOT_SIZE];
- }
-}
-
-/**
* Handles playback of any active movie. Called from the foreground 24 times a second.
*/
void BMVPlayer::FettleBMV() {
@@ -1078,8 +1064,6 @@ void BMVPlayer::FettleBMV() {
return;
}
- LookAtBuffers();
-
if (!stream.isOpen()) {
int i;
diff --git a/engines/tinsel/bmv.h b/engines/tinsel/bmv.h
index 2644504cab..d90d68fc13 100644
--- a/engines/tinsel/bmv.h
+++ b/engines/tinsel/bmv.h
@@ -96,7 +96,7 @@ class BMVPlayer {
int dieFrame;
} texts[2];
- COLORREF talkColour;
+ COLORREF talkColor;
int bigProblemCount;
@@ -143,7 +143,7 @@ private:
void MovieAudio(int audioOffset, int blobs);
void FettleMovieText();
void BmvDrawText(bool bDraw);
- void MovieText(CORO_PARAM, int stringId, int x, int y, int fontId, COLORREF *pTalkColour, int duration);
+ void MovieText(CORO_PARAM, int stringId, int x, int y, int fontId, COLORREF *pTalkColor, int duration);
int MovieCommand(char cmd, int commandOffset);
int FollowingPacket(int thisPacket, bool bReallyImportant);
void LoadSlots(int number);
@@ -151,7 +151,6 @@ private:
bool MaintainBuffer();
bool DoBMVFrame();
bool DoSoundFrame();
- void LookAtBuffers();
};
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 22e8806e7e..70bf398baf 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -280,11 +280,9 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList &
ADGameDescList matched;
int maxFilesMatched = 0;
- bool gotAnyMatchesWithAllFiles = false;
// MD5 based matching
- uint i;
- for (i = 0, g = &Tinsel::gameDescriptions[0]; g->desc.gameid != 0; ++g) {
+ for (g = &Tinsel::gameDescriptions[0]; g->desc.gameid != 0; ++g) {
if (strcmp(g->desc.gameid, "dw2") != 0)
continue;
@@ -327,9 +325,6 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList &
}
}
- if (allFilesPresent)
- gotAnyMatchesWithAllFiles = true;
-
if (!fileMissing) {
// Count the number of matching files. Then, only keep those
// entries which match a maximal amount of files.
diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp
index 73cad7a68f..281dd2da55 100644
--- a/engines/tinsel/dialogs.cpp
+++ b/engines/tinsel/dialogs.cpp
@@ -62,6 +62,8 @@
#include "tinsel/tinsel.h" // For engine access
#include "tinsel/token.h"
+#include "common/textconsole.h"
+
namespace Tinsel {
//----------------- EXTERNAL GLOBAL DATA --------------------
@@ -259,7 +261,7 @@ enum PARTS_INDEX {
#define MD_XLBUTR (TinselV2 ? 26 : 10)
#define MD_XRBUTL (TinselV2 ? 173 : 105)
#define MD_XRBUTR (TinselV2 ? 195 : 114)
-#define ROTX1 60 // Rotate button's offsets from the centre
+#define ROTX1 60 // Rotate button's offsets from the center
// Number of objects that makes up an empty window
#define MAX_WCOMP 21 // 4 corners + (3+3) sides + (2+2) extra sides
@@ -449,7 +451,7 @@ static bool bMoveOnUnHide; // Set before start of conversation
//----- Data pertinant to configure (incl. load/save game) -----
-#define COL_MAINBOX TBLUE1 // Base blue colour
+#define COL_MAINBOX TBLUE1 // Base blue color
#define COL_BOX TBLUE1
#define COL_HILIGHT TBLUE4
@@ -1639,7 +1641,7 @@ static void Select(int i, bool force) {
switch (cd.box[i].boxType) {
case RGROUP:
iconArray[HL2] = RectangleObject(BgPal(),
- (TinselV2 ? HighlightColour() : COL_HILIGHT), cd.box[i].w, cd.box[i].h);
+ (TinselV2 ? HighlightColor() : COL_HILIGHT), cd.box[i].w, cd.box[i].h);
MultiInsertObject(GetPlayfieldList(FIELD_STATUS), iconArray[HL2]);
MultiSetAniXY(iconArray[HL2],
InvD[ino].inventoryX + cd.box[i].xpos,
@@ -2239,7 +2241,7 @@ static int WhichMenuBox(int curX, int curY, bool bSlides) {
/***/
/**************************************************************************/
-#define ROTX1 60 // Rotate button's offsets from the centre
+#define ROTX1 60 // Rotate button's offsets from the center
/**
* InvBoxes
@@ -2277,7 +2279,7 @@ static void InvBoxes(bool InBody, int curX, int curY) {
cd.box[cd.pointBox].boxType == AATBUT ||
cd.box[cd.pointBox].boxType == AABUT) {
iconArray[HL1] = RectangleObject(BgPal(),
- (TinselV2 ? HighlightColour() : COL_HILIGHT),
+ (TinselV2 ? HighlightColor() : COL_HILIGHT),
cd.box[cd.pointBox].w, cd.box[cd.pointBox].h);
MultiInsertObject(GetPlayfieldList(FIELD_STATUS), iconArray[HL1]);
MultiSetAniXY(iconArray[HL1],
@@ -2638,14 +2640,14 @@ static void AddBackground(OBJECT **rect, OBJECT **title, int extraH, int extraV,
LoadStringRes(InvD[ino].hInvTitle, TextBufferAddr(), TBUFSZ);
*title = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(), 0,
InvD[ino].inventoryX + width/2, InvD[ino].inventoryY + M_TOFF,
- GetTagFontHandle(), TXT_CENTRE);
+ GetTagFontHandle(), TXT_CENTER);
assert(*title); // Inventory title string produced NULL text
MultiSetZPosition(*title, Z_INV_HTEXT);
} else if (textFrom == FROM_STRING && cd.ixHeading != NO_HEADING) {
LoadStringRes(configStrings[cd.ixHeading], TextBufferAddr(), TBUFSZ);
*title = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(), 0,
InvD[ino].inventoryX + width/2, InvD[ino].inventoryY + M_TOFF,
- GetTagFontHandle(), TXT_CENTRE);
+ GetTagFontHandle(), TXT_CENTER);
assert(*title); // Inventory title string produced NULL text
MultiSetZPosition(*title, Z_INV_HTEXT);
}
@@ -2669,7 +2671,7 @@ static void AddTitle(POBJECT *title, int extraH) {
LoadStringRes(InvD[ino].hInvTitle, TextBufferAddr(), TBUFSZ);
*title = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(), 0,
InvD[ino].inventoryX + (width/2)+NM_BG_POS_X, InvD[ino].inventoryY + NM_TOFF,
- GetTagFontHandle(), TXT_CENTRE, 0);
+ GetTagFontHandle(), TXT_CENTER, 0);
assert(*title);
MultiSetZPosition(*title, Z_INV_HTEXT);
}
@@ -2736,7 +2738,7 @@ static void AddBox(int *pi, const int i) {
break;
// Give us a box
- iconArray[*pi] = RectangleObject(BgPal(), TinselV2 ? BoxColour() : COL_BOX,
+ iconArray[*pi] = RectangleObject(BgPal(), TinselV2 ? BoxColor() : COL_BOX,
cd.box[i].w, cd.box[i].h);
MultiInsertObject(GetPlayfieldList(FIELD_STATUS), iconArray[*pi]);
MultiSetAniXY(iconArray[*pi], x, y);
@@ -2758,9 +2760,9 @@ static void AddBox(int *pi, const int i) {
iconArray[*pi] = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), cd.box[i].boxText, 0,
#ifdef JAPAN
// Note: it never seems to go here!
- x + cd.box[i].w/2, y+2, GetTagFontHandle(), TXT_CENTRE);
+ x + cd.box[i].w/2, y+2, GetTagFontHandle(), TXT_CENTER);
#else
- x + cd.box[i].w / 2, y + TYOFF, GetTagFontHandle(), TXT_CENTRE);
+ x + cd.box[i].w / 2, y + TYOFF, GetTagFontHandle(), TXT_CENTER);
#endif
}
@@ -2787,9 +2789,9 @@ static void AddBox(int *pi, const int i) {
iconArray[*pi] = ObjectTextOut(GetPlayfieldList(FIELD_STATUS),
TextBufferAddr(), 0,
#ifdef JAPAN
- x + cd.box[i].w/2, y+2, GetTagFontHandle(), TXT_CENTRE);
+ x + cd.box[i].w/2, y+2, GetTagFontHandle(), TXT_CENTER);
#else
- x + cd.box[i].w / 2, y + TYOFF, GetTagFontHandle(), TXT_CENTRE);
+ x + cd.box[i].w / 2, y + TYOFF, GetTagFontHandle(), TXT_CENTER);
#endif
MultiSetZPosition(iconArray[*pi], Z_INV_ITEXT);
*pi += 1;
@@ -2870,7 +2872,7 @@ static void AddBox(int *pi, const int i) {
if (cd.box[i].boxType == TOGGLE2) {
iconArray[*pi] = ObjectTextOut(GetPlayfieldList(FIELD_STATUS),
TextBufferAddr(), 0, x + cd.box[i].w / 2, y + TOG2_YOFF,
- GetTagFontHandle(), TXT_CENTRE, 0);
+ GetTagFontHandle(), TXT_CENTER, 0);
} else {
iconArray[*pi] = ObjectTextOut(GetPlayfieldList(FIELD_STATUS),
TextBufferAddr(), 0, x + MDTEXT_XOFF, y + MDTEXT_YOFF,
@@ -2934,7 +2936,7 @@ static void AddBox(int *pi, const int i) {
LoadStringRes(SysString(cd.box[i].ixText), TextBufferAddr(), TBUFSZ);
iconArray[*pi] = ObjectTextOut(GetPlayfieldList(FIELD_STATUS),
TextBufferAddr(), 0, x + cd.box[i].w / 2, y + TOG2_YOFF,
- GetTagFontHandle(), TXT_CENTRE, 0);
+ GetTagFontHandle(), TXT_CENTER, 0);
MultiSetZPosition(iconArray[*pi], Z_INV_ITEXT);
*pi += 1;
}
@@ -2945,7 +2947,7 @@ static void AddBox(int *pi, const int i) {
LoadStringRes(LanguageDesc(displayedLanguage), TextBufferAddr(), TBUFSZ);
iconArray[*pi] = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(), 0,
- x + cd.box[i].w / 2, y + ROT_YOFF, GetTagFontHandle(), TXT_CENTRE, 0);
+ x + cd.box[i].w / 2, y + ROT_YOFF, GetTagFontHandle(), TXT_CENTER, 0);
MultiSetZPosition(iconArray[*pi], Z_INV_ITEXT);
*pi += 1;
@@ -3683,15 +3685,15 @@ extern void HideConversation(bool bHide) {
/*
* First time, position it appropriately
*/
- int left, centre;
+ int left, center;
int x, y, deltay;
// Only do it once per conversation
bMoveOnUnHide = false;
- // Current centre of the window
+ // Current center of the window
left = MultiLeftmost(RectObject);
- centre = (MultiRightmost(RectObject) + left) / 2;
+ center = (MultiRightmost(RectObject) + left) / 2;
// Get the x-offset for the conversation window
if (thisConvActor) {
@@ -3731,12 +3733,12 @@ extern void HideConversation(bool bHide) {
// Move it all
for (i = 0; objArray[i] && i < MAX_WCOMP; i++) {
- MultiMoveRelXY(objArray[i], x - centre, deltay);
+ MultiMoveRelXY(objArray[i], x - center, deltay);
}
for (i = 0; iconArray[i] && i < MAX_ICONS; i++) {
- MultiMoveRelXY(iconArray[i], x - centre, deltay);
+ MultiMoveRelXY(iconArray[i], x - center, deltay);
}
- InvD[INV_CONV].inventoryX += x - centre;
+ InvD[INV_CONV].inventoryX += x - center;
/*
* Now positioned as worked out
diff --git a/engines/tinsel/dialogs.h b/engines/tinsel/dialogs.h
index a256ed73e8..f81a59a0b7 100644
--- a/engines/tinsel/dialogs.h
+++ b/engines/tinsel/dialogs.h
@@ -32,7 +32,7 @@
#include "tinsel/events.h" // for PLR_EVENT, PLR_EVENT
namespace Common {
- class Serializer;
+class Serializer;
}
namespace Tinsel {
diff --git a/engines/tinsel/drives.cpp b/engines/tinsel/drives.cpp
index 6e30caf006..d252e45cf5 100644
--- a/engines/tinsel/drives.cpp
+++ b/engines/tinsel/drives.cpp
@@ -24,9 +24,7 @@
* CD/drive handling functions
*/
-#include "common/config-manager.h"
-#include "common/substream.h"
-#include "gui/message.h"
+#include "common/textconsole.h"
#include "tinsel/drives.h"
#include "tinsel/scene.h"
#include "tinsel/tinsel.h"
@@ -38,7 +36,6 @@ namespace Tinsel {
// FIXME: Avoid non-const global vars
char currentCD = '1';
-static uint32 cdFlags[] = { fCd1, fCd2, fCd3, fCd4, fCd5, fCd6, fCd7, fCd8 };
static bool bChangingCD = false;
static char nextCD = '\0';
@@ -75,6 +72,8 @@ int GetCurrentCD() {
return (currentCD - '1' + 1);
}
+static const uint32 cdFlags[] = { fCd1, fCd2, fCd3, fCd4, fCd5, fCd6, fCd7, fCd8 };
+
void SetCD(int flags) {
if (flags & cdFlags[currentCD - '1'])
return;
diff --git a/engines/tinsel/dw.h b/engines/tinsel/dw.h
index 8bd7ca1a4e..aed4c50408 100644
--- a/engines/tinsel/dw.h
+++ b/engines/tinsel/dw.h
@@ -42,8 +42,6 @@ typedef int HPOLYGON;
#define LF_CHAR '\x0a' // line feed
// file names
-#define SAMPLE_FILE "english.smp" // all samples
-#define SAMPLE_INDEX "english.idx" // sample index filename
#define MIDI_FILE "midi.dat" // all MIDI sequences
#define INDEX_FILENAME "index" // name of index file
#define PSX_INDEX_FILENAME "index.dat" // name of index file in psx version
diff --git a/engines/tinsel/faders.cpp b/engines/tinsel/faders.cpp
index a82285b12f..99a8b9ff14 100644
--- a/engines/tinsel/faders.cpp
+++ b/engines/tinsel/faders.cpp
@@ -37,7 +37,7 @@ namespace Tinsel {
/** structure used by the "FadeProcess" process */
struct FADE {
- const long *pColourMultTable; // list of fixed point colour multipliers - terminated with negative entry
+ const long *pColorMultTable; // list of fixed point color multipliers - terminated with negative entry
PALQ *pPalQ; // palette queue entry to fade
};
@@ -46,42 +46,42 @@ struct FADE {
//const long fadein[] = {0, 0x1000, 0x3000, 0x5000, 0x7000, 0x9000, 0xb000, 0xd000, 0x10000L, -1};
/**
- * Scale 'colour' by the fixed point colour multiplier 'colourMult'
- * @param colour Colour to scale
- * @param colourMult Fixed point multiplier
+ * Scale 'color' by the fixed point color multiplier 'colorMult'
+ * @param color Color to scale
+ * @param colorMult Fixed point multiplier
*/
-static COLORREF ScaleColour(COLORREF colour, uint32 colourMult) {
+static COLORREF ScaleColor(COLORREF color, uint32 colorMult) {
// apply multiplier to RGB components
- uint32 red = ((TINSEL_GetRValue(colour) * colourMult) << 8) >> 24;
- uint32 green = ((TINSEL_GetGValue(colour) * colourMult) << 8) >> 24;
- uint32 blue = ((TINSEL_GetBValue(colour) * colourMult) << 8) >> 24;
+ uint32 red = ((TINSEL_GetRValue(color) * colorMult) << 8) >> 24;
+ uint32 green = ((TINSEL_GetGValue(color) * colorMult) << 8) >> 24;
+ uint32 blue = ((TINSEL_GetBValue(color) * colorMult) << 8) >> 24;
- // return new colour
+ // return new color
return TINSEL_RGB(red, green, blue);
}
/**
- * Applies the fixed point multiplier 'mult' to all colours in
- * 'pOrig' to produce 'pNew'. Each colour in the palette will be
+ * Applies the fixed point multiplier 'mult' to all colors in
+ * 'pOrig' to produce 'pNew'. Each color in the palette will be
* multiplied by 'mult'.
* @param pNew Pointer to new palette
* @param pOrig Pointer to original palette
- * @param numColours Number of colours in the above palettes
+ * @param numColors Number of colors in the above palettes
* @param mult Fixed point multiplier
*/
-static void FadePalette(COLORREF *pNew, COLORREF *pOrig, int numColours, uint32 mult) {
- for (int i = 0; i < numColours; i++, pNew++, pOrig++) {
+static void FadePalette(COLORREF *pNew, COLORREF *pOrig, int numColors, uint32 mult) {
+ for (int i = 0; i < numColors; i++, pNew++, pOrig++) {
if (!TinselV2)
// apply multiplier to RGB components
- *pNew = ScaleColour(*pOrig, mult);
- else if (i == (TalkColour() - 1)) {
- *pNew = GetTalkColourRef();
- *pNew = ScaleColour(*pNew, mult);
- } else if (SysVar(SV_TAGCOLOUR) && i == (SysVar(SV_TAGCOLOUR) - 1)) {
+ *pNew = ScaleColor(*pOrig, mult);
+ else if (i == (TalkColor() - 1)) {
+ *pNew = GetTalkColorRef();
+ *pNew = ScaleColor(*pNew, mult);
+ } else if (SysVar(SV_TAGCOLOR) && i == (SysVar(SV_TAGCOLOR) - 1)) {
*pNew = GetTagColorRef();
- *pNew = ScaleColour(*pNew, mult);
+ *pNew = ScaleColor(*pNew, mult);
} else {
- *pNew = ScaleColour(*pOrig, mult);
+ *pNew = ScaleColor(*pOrig, mult);
}
}
}
@@ -94,8 +94,8 @@ static void FadePalette(COLORREF *pNew, COLORREF *pOrig, int numColours, uint32
static void FadeProcess(CORO_PARAM, const void *param) {
// COROUTINE
CORO_BEGIN_CONTEXT;
- COLORREF fadeRGB[MAX_COLOURS]; // local copy of palette
- const long *pColMult; // pointer to colour multiplier table
+ COLORREF fadeRGB[MAX_COLORS]; // local copy of palette
+ const long *pColMult; // pointer to color multiplier table
PALETTE *pPalette; // pointer to palette
CORO_END_CONTEXT(_ctx);
@@ -111,19 +111,19 @@ static void FadeProcess(CORO_PARAM, const void *param) {
// get pointer to palette - reduce pointer indirection a bit
_ctx->pPalette = (PALETTE *)LockMem(pFade->pPalQ->hPal);
- for (_ctx->pColMult = pFade->pColourMultTable; *_ctx->pColMult >= 0; _ctx->pColMult++) {
+ for (_ctx->pColMult = pFade->pColorMultTable; *_ctx->pColMult >= 0; _ctx->pColMult++) {
// go through all multipliers in table - until a negative entry
// fade palette using next multiplier
if (TinselV2)
FadePalette(_ctx->fadeRGB, pFade->pPalQ->palRGB,
- pFade->pPalQ->numColours, (uint32) *_ctx->pColMult);
+ pFade->pPalQ->numColors, (uint32) *_ctx->pColMult);
else
FadePalette(_ctx->fadeRGB, _ctx->pPalette->palRGB,
- FROM_LE_32(_ctx->pPalette->numColours), (uint32) *_ctx->pColMult);
+ FROM_LE_32(_ctx->pPalette->numColors), (uint32) *_ctx->pColMult);
// send new palette to video DAC
- UpdateDACqueue(pFade->pPalQ->posInDAC, FROM_LE_32(_ctx->pPalette->numColours), _ctx->fadeRGB);
+ UpdateDACqueue(pFade->pPalQ->posInDAC, FROM_LE_32(_ctx->pPalette->numColors), _ctx->fadeRGB);
// allow time for video DAC to be updated
CORO_SLEEP(1);
@@ -139,7 +139,7 @@ static void FadeProcess(CORO_PARAM, const void *param) {
/**
* Generic palette fader/unfader. Creates a 'FadeProcess' process
* for each palette that is to fade.
- * @param multTable Fixed point colour multiplier table
+ * @param multTable Fixed point color multiplier table
* @param noFadeTable List of palettes not to fade
*/
static void Fader(const long multTable[], SCNHANDLE noFadeTable[]) {
@@ -175,7 +175,7 @@ static void Fader(const long multTable[], SCNHANDLE noFadeTable[]) {
FADE fade;
// fill in FADE struct
- fade.pColourMultTable = multTable;
+ fade.pColorMultTable = multTable;
fade.pPalQ = pPal;
// create a fader process for this palette
@@ -210,7 +210,7 @@ void FadeOutFast(SCNHANDLE noFadeTable[]) {
}
/**
- * Fades a list of palettes from black to their current colours.
+ * Fades a list of palettes from black to their current colors.
* 'noFadeTable' is a NULL terminated list of palettes not to fade.
*/
void FadeInMedium(SCNHANDLE noFadeTable[]) {
@@ -223,7 +223,7 @@ void FadeInMedium(SCNHANDLE noFadeTable[]) {
}
/**
- * Fades a list of palettes from black to their current colours.
+ * Fades a list of palettes from black to their current colors.
* @param noFadeTable A NULL terminated list of palettes not to fade.
*/
void FadeInFast(SCNHANDLE noFadeTable[]) {
@@ -234,10 +234,10 @@ void FadeInFast(SCNHANDLE noFadeTable[]) {
Fader(fadein, noFadeTable);
}
-void PokeInTagColour() {
- if (SysVar(SV_TAGCOLOUR)) {
+void PokeInTagColor() {
+ if (SysVar(SV_TAGCOLOR)) {
const COLORREF c = GetActorRGB(-1);
- UpdateDACqueue(SysVar(SV_TAGCOLOUR), c);
+ UpdateDACqueue(SysVar(SV_TAGCOLOR), c);
}
}
diff --git a/engines/tinsel/faders.h b/engines/tinsel/faders.h
index e77bff2661..b30a26d893 100644
--- a/engines/tinsel/faders.h
+++ b/engines/tinsel/faders.h
@@ -50,7 +50,7 @@ void FadeOutMedium(SCNHANDLE noFadeTable[]);
void FadeOutFast(SCNHANDLE noFadeTable[]);
void FadeInMedium(SCNHANDLE noFadeTable[]);
void FadeInFast(SCNHANDLE noFadeTable[]);
-void PokeInTagColour();
+void PokeInTagColor();
} // End of namespace Tinsel
diff --git a/engines/tinsel/font.cpp b/engines/tinsel/font.cpp
index 4c76d12400..f57a6d5d54 100644
--- a/engines/tinsel/font.cpp
+++ b/engines/tinsel/font.cpp
@@ -118,10 +118,10 @@ void FettleFontPal(SCNHANDLE fontPal) {
else
pImg->hImgPal = 0;
- if (TinselV2 && SysVar(SV_TAGCOLOUR)) {
+ if (TinselV2 && SysVar(SV_TAGCOLOR)) {
const COLORREF c = GetActorRGB(-1);
SetTagColorRef(c);
- UpdateDACqueue(SysVar(SV_TAGCOLOUR), c);
+ UpdateDACqueue(SysVar(SV_TAGCOLOR), c);
}
}
diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp
index aefc6e6144..bdcd3207f9 100644
--- a/engines/tinsel/graphics.cpp
+++ b/engines/tinsel/graphics.cpp
@@ -32,6 +32,8 @@
#include "tinsel/tinsel.h"
#include "tinsel/scn.h"
+#include "common/textconsole.h"
+
namespace Tinsel {
//----------------- LOCAL DEFINES --------------------
@@ -41,7 +43,7 @@ namespace Tinsel {
#define CHAR_WIDTH 4
#define CHAR_HEIGHT 4
-extern uint8 transPalette[MAX_COLOURS];
+extern uint8 transPalette[MAX_COLORS];
//----------------- SUPPORT FUNCTIONS ---------------------
@@ -175,14 +177,14 @@ static void t0WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply
x += clipAmount;
if (repeatFlag) {
- // Repeat of a given colour
- uint8 colour = (numBytes >> 8) & 0xff;
+ // Repeat of a given color
+ uint8 color = (numBytes >> 8) & 0xff;
int runLength = (numBytes & 0xff) - clipAmount;
int rptLength = MAX(MIN(runLength, pObj->width - rightClip - x), 0);
if (yClip == 0) {
- if (colour != 0)
- memset(tempDest, colour, rptLength);
+ if (color != 0)
+ memset(tempDest, color, rptLength);
tempDest += rptLength;
}
@@ -470,18 +472,18 @@ static void t2WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply
x+= clipAmount;
int runLength = numBytes - clipAmount;
- uint8 colour = *srcP++;
+ uint8 color = *srcP++;
- if ((yClip == 0) && (runLength > 0) && (colour != 0)) {
+ if ((yClip == 0) && (runLength > 0) && (color != 0)) {
runLength = MIN(runLength, pObj->width - rightClip - x);
if (runLength > 0) {
// Non-transparent run length
- colour += pObj->constant;
+ color += pObj->constant;
if (horizFlipped)
- Common::set_to(tempP - runLength + 1, tempP + 1, colour);
+ Common::set_to(tempP - runLength + 1, tempP + 1, color);
else
- Common::set_to(tempP, tempP + runLength, colour);
+ Common::set_to(tempP, tempP + runLength, color);
}
}
@@ -521,7 +523,7 @@ static void t2WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply
}
/**
- * Fill the destination area with a constant colour
+ * Fill the destination area with a constant color
*/
static void WrtConst(DRAWOBJECT *pObj, uint8 *destP, bool applyClipping) {
if (applyClipping) {
@@ -595,11 +597,11 @@ static void WrtAll(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool applyClippi
*/
static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP,
bool applyClipping, bool horizFlipped, int packingType) {
- uint8 numColours = 0;
- uint8 *colourTable = NULL;
+ uint8 numColors = 0;
+ uint8 *colorTable = NULL;
int topClip = 0;
int xOffset = 0;
- int numBytes, colour;
+ int numBytes, color;
int v;
if (_vm->getLanguage() == Common::RU_RUS) {
@@ -625,10 +627,10 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP,
}
if (packingType == 3) {
- // Variable colours
- numColours = *srcP++;
- colourTable = srcP;
- srcP += numColours;
+ // Variable colors
+ numColors = *srcP++;
+ colorTable = srcP;
+ srcP += numColors;
}
for (int y = 0; y < pObj->height; ++y) {
@@ -646,7 +648,7 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP,
int x = 0;
while (x < pObj->width) {
- // Get next run size and colour to use
+ // Get next run size and color to use
for (;;) {
if (xOffset > 0) {
x += xOffset;
@@ -663,9 +665,9 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP,
v = *srcP++;
numBytes = v & 0xf; // No. bytes 1-15
if (packingType == 3)
- colour = colourTable[v >> 4];
+ color = colorTable[v >> 4];
else
- colour = pObj->baseCol + (v >> 4);
+ color = pObj->baseCol + (v >> 4);
if (numBytes != 0)
break;
@@ -693,7 +695,7 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP,
while (numBytes-- > 0) {
if ((topClip == 0) && (x < (pObj->width - rightClip))) {
- *tempP = colour;
+ *tempP = color;
if (horizFlipped) --tempP; else ++tempP;
}
++x;
@@ -830,7 +832,7 @@ void DrawObject(DRAWOBJECT *pObj) {
int packType = pObj->flags >> 14;
if (packType == 0) {
- // No colour packing
+ // No color packing
switch (typeId) {
case 0x01:
case 0x11:
@@ -865,7 +867,7 @@ void DrawObject(DRAWOBJECT *pObj) {
} else {
// 1 = 16 from 240
// 2 = 16 from 224
- // 3 = variable colour
+ // 3 = variable color
if (packType == 1) pObj->baseCol = 0xF0;
else if (packType == 2) pObj->baseCol = 0xE0;
diff --git a/engines/tinsel/graphics.h b/engines/tinsel/graphics.h
index 8b8bb6488d..de16082441 100644
--- a/engines/tinsel/graphics.h
+++ b/engines/tinsel/graphics.h
@@ -43,7 +43,7 @@ struct DRAWOBJECT {
int transOffset; // transparent character offset
int flags; // object flags - see above for list
PALQ *pPal; // objects palette Q position
- int constant; // which colour in palette for monochrome objects
+ int constant; // which color in palette for monochrome objects
int width; // width of object
int height; // height of object
SCNHANDLE hBits; // image bitmap handle
diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp
index a48fd2ca1f..6f5f92c969 100644
--- a/engines/tinsel/handle.cpp
+++ b/engines/tinsel/handle.cpp
@@ -27,6 +27,7 @@
#define BODGE
#include "common/file.h"
+#include "common/textconsole.h"
#include "tinsel/drives.h"
#include "tinsel/dw.h"
@@ -65,8 +66,6 @@ enum {
fLoaded = 0x20000000L ///< set when file data has been loaded
};
#define FSIZE_MASK 0x00FFFFFFL ///< mask to isolate the filesize
-#define MALLOC_MASK 0xFF000000L ///< mask to isolate the memory allocation flags
-//#define HANDLEMASK 0xFF800000L ///< get handle of address
//----------------- LOCAL GLOBAL DATA --------------------
@@ -80,7 +79,6 @@ static uint numHandles = 0;
static uint32 cdPlayHandle = (uint32)-1;
-static int cdPlayFileNum, cdPlaySceneNum;
static SCNHANDLE cdBaseHandle = 0, cdTopHandle = 0;
static Common::File *cdGraphStream = 0;
@@ -235,7 +233,7 @@ void LoadCDGraphData(MEMHANDLE *pH) {
// clear the loading flag
// pH->filesize &= ~fLoading;
- if (bytes != ((cdTopHandle-cdBaseHandle) & OFFSETMASK))
+ if (bytes != ((cdTopHandle - cdBaseHandle) & OFFSETMASK))
// file is corrupt
error(FILE_READ_ERROR, "CD play file");
}
@@ -248,7 +246,7 @@ void LoadCDGraphData(MEMHANDLE *pH) {
* @param next Handle of end of range + 1
*/
void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) {
- if (cdPlayFileNum == cdPlaySceneNum && start == cdBaseHandle)
+ if (start == cdBaseHandle)
return;
OpenCDGraphFile();
@@ -264,7 +262,6 @@ void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) {
}
void SetCdPlaySceneDetails(int fileNum, const char *fileName) {
- cdPlaySceneNum = fileNum;
strcpy(szCdPlayFile, fileName);
}
diff --git a/engines/tinsel/mareels.cpp b/engines/tinsel/mareels.cpp
index cf28749e76..5d9672972a 100644
--- a/engines/tinsel/mareels.cpp
+++ b/engines/tinsel/mareels.cpp
@@ -28,6 +28,7 @@
#include "tinsel/pcode.h" // For D_UP, D_DOWN
#include "tinsel/rince.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Tinsel {
diff --git a/engines/tinsel/module.mk b/engines/tinsel/module.mk
index 2778cec3df..2ab94b830a 100644
--- a/engines/tinsel/module.mk
+++ b/engines/tinsel/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/tinsel
MODULE_OBJS := \
actors.o \
+ adpcm.o \
anim.o \
background.o \
bg.o \
diff --git a/engines/tinsel/move.cpp b/engines/tinsel/move.cpp
index 5b9e650689..5fc555f9b0 100644
--- a/engines/tinsel/move.cpp
+++ b/engines/tinsel/move.cpp
@@ -584,7 +584,7 @@ static void SetMoverUltDest(PMOVER pActor, int x, int y) {
* If in a neighbouring path to the final destination, if the target path
* is a follow nodes path, head for the end node, otherwise head straight
* for the target.
- * Otherwise, head towards the pseudo-centre or end node of the first
+ * Otherwise, head towards the pseudo-center or end node of the first
* en-route path.
*/
static void SetMoverIntDest(PMOVER pMover, int x, int y) {
@@ -636,7 +636,7 @@ static void SetMoverIntDest(PMOVER pMover, int x, int y) {
} else if (hIpath != NOPOLY) {
/* Head for an en-route path */
if (PolySubtype(hIpath) != NODE) {
- /* En-route path is normal - head for pseudo centre. */
+ /* En-route path is normal - head for pseudo center. */
if (CanGetThere(pMover, x, y) == GT_OK) {
pMover->ItargetX = x;
pMover->ItargetY = y;
@@ -644,8 +644,8 @@ static void SetMoverIntDest(PMOVER pMover, int x, int y) {
// make damn sure that Itarget is in hIpath
pMover->hIpath = InPolygon(x, y, PATH);
} else {
- pMover->ItargetX = PolyCentreX(hIpath);
- pMover->ItargetY = PolyCentreY(hIpath);
+ pMover->ItargetX = PolyCenterX(hIpath);
+ pMover->ItargetY = PolyCenterY(hIpath);
if (TinselV2)
// make damn sure that Itarget is in hIpath
pMover->hIpath = InPolygon(pMover->ItargetX, pMover->ItargetY, PATH);
@@ -943,12 +943,12 @@ static void SetNextDest(PMOVER pMover) {
assert(hPath == pMover->hIpath);
if (pMover->InDifficulty == NO_PROB) {
- x = PolyCentreX(hPath);
- y = PolyCentreY(hPath);
+ x = PolyCenterX(hPath);
+ y = PolyCenterY(hPath);
SetMoverDest(pMover, x, y);
- pMover->InDifficulty = TRY_CENTRE;
+ pMover->InDifficulty = TRY_CENTER;
pMover->over = false;
- } else if (pMover->InDifficulty == TRY_CENTRE) {
+ } else if (pMover->InDifficulty == TRY_CENTER) {
NearestCorner(&x, &y, pMover->hCpath, pMover->hIpath);
SetMoverDest(pMover, x, y);
pMover->InDifficulty = TRY_CORNER;
@@ -986,7 +986,7 @@ static void SetNextDest(PMOVER pMover) {
!IsAdjacentPath(pMover->hCpath, pMover->hIpath)) {
/*----------------------------------------------------------
If just entering a follow nodes polygon, go to first node.|
- Else if just going to pass through, go to pseudo-centre. |
+ Else if just going to pass through, go to pseudo-center. |
----------------------------------------------------------*/
if (PolySubtype(hPath) == NODE && pMover->hFnpath != hPath && pMover->npstatus != LEAVING) {
int node = NearestEndNode(hPath, x, y);
@@ -995,7 +995,7 @@ static void SetNextDest(PMOVER pMover) {
pMover->over = true;
} else if (!IsInPolygon(pMover->ItargetX, pMover->ItargetY, hPath) &&
!IsInPolygon(pMover->ItargetX, pMover->ItargetY, pMover->hCpath)) {
- SetMoverDest(pMover, PolyCentreX(hPath), PolyCentreY(hPath));
+ SetMoverDest(pMover, PolyCenterX(hPath), PolyCenterY(hPath));
pMover->over = true;
} else {
SetMoverDest(pMover, pMover->ItargetX, pMover->ItargetY);
@@ -1258,8 +1258,8 @@ static void SetOffWithinNodePath(PMOVER pMover, HPOLYGON StartPath, HPOLYGON Des
endnode = NearestEndNode(StartPath, targetX, targetY);
} else {
if (PolySubtype(hIpath) != NODE) {
- x = PolyCentreX(hIpath);
- y = PolyCentreY(hIpath);
+ x = PolyCenterX(hIpath);
+ y = PolyCenterY(hIpath);
endnode = NearestEndNode(StartPath, x, y);
} else {
endnode = NearEndNode(StartPath, hIpath);
@@ -1278,7 +1278,7 @@ static void SetOffWithinNodePath(PMOVER pMover, HPOLYGON StartPath, HPOLYGON Des
{
// could go for its end node if it's an NPATH
// but we probably will when we hit it anyway!
- SetMoverDest(pMover, PolyCentreX(hIpath), PolyCentreY(hIpath));
+ SetMoverDest(pMover, PolyCenterX(hIpath), PolyCenterY(hIpath));
}
}
} else
@@ -1500,7 +1500,7 @@ static void EnteringNewPath(PMOVER pMover, HPOLYGON hPath, int x, int y) {
assert(hIpath != NOPOLY); // No path on the way
if (PolySubtype(hIpath) != NODE) {
- lastnode = NearestEndNode(hPath, PolyCentreX(hIpath), PolyCentreY(hIpath));
+ lastnode = NearestEndNode(hPath, PolyCenterX(hIpath), PolyCenterY(hIpath));
} else {
lastnode = NearEndNode(hPath, hIpath);
}
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index 29d4dbc92d..12bcff829b 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -38,6 +38,7 @@
#include "common/file.h"
#include "common/memstream.h"
+#include "tinsel/adpcm.h"
#include "tinsel/config.h"
#include "tinsel/sound.h"
#include "tinsel/music.h"
@@ -65,10 +66,6 @@ struct SOUND_BUFFER {
// FIXME: Avoid non-const global vars
-// get set when music driver is installed
-//static MDI_DRIVER *mDriver;
-//static HSEQUENCE mSeqHandle;
-
// MIDI buffer
static SOUND_BUFFER midiBuffer = { 0, 0 };
@@ -115,26 +112,6 @@ static const int enhancedAudioSCNVersion[] = {
97, 98, 99, 99 // 151-154
};
-// TODO. This mapping is wrong
-static const int enhancedAudioSCNVersionALT[] = {
- 301, 302, 2, 1, 1, 301, 302, 3, 3, 4, // 1-10
- 4, 5, 6, 1, 7, 8, 9, 10, 8, 11, // 11-20
- 11, 12, 13, 13, 13, 13, 13, 14, 13, 13, // 21-30
- 15, 16, 17, 15, 18, 19, 20, 338, 21, 21, // 31-40
- 341, 342, 22, 22, 23, 24, 25, 26, 27, 28, // 41-50
- 29, 30, 31, 32, 33, 34, 35, 35, 36, 37, // 51-60
- 38, 39, 39, 39, 39, 40, 39, 41, 41, 42, // 61-70
- 43, 42, 44, 45, 41, 46, 48, 47, 48, 49, // 71-80
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, // 81-90
- 60, 61, 62, 63, 61, 64, 65, 66, 67, 68, // 91-100
- 69, 70, 68, 71, 72, 73, 74, 75, 12, 76, // 101-110
- 77, 78, 79, 80, 4, 4, 82, 83, 77, 4, // 111-120
- 84, 85, 86, 3124, 88, 89, 90, 88, 2, 2, // 121-130
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 131-140
- 3142, 91, 92, 93, 94, 94, 95, 96, 52, 4, // 141-150
- 97, 98, 99 // 151-153
-};
-
int GetTrackNumber(SCNHANDLE hMidi) {
for (int i = 0; i < ARRAYSIZE(midiOffsets); i++)
if (midiOffsets[i] == hMidi)
@@ -172,18 +149,18 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) {
// the index and length of the last tune loaded
static uint32 dwLastMidiIndex = 0; // FIXME: Avoid non-const global vars
- //static uint32 dwLastSeqLen;
-
uint32 dwSeqLen = 0; // length of the sequence
// Support for external music from the music enhancement project
if (_vm->getFeatures() & GF_ENHANCED_AUDIO_SUPPORT) {
int trackNumber = GetTrackNumber(dwFileOffset);
+ // Track 8 has been removed in the German CD re-release "Neon Edition"
+ if ((_vm->getFeatures() & GF_ALT_MIDI) && trackNumber >= 8)
+ trackNumber++;
+
int track = 0;
if (trackNumber >= 0) {
- if (_vm->getFeatures() & GF_ALT_MIDI)
- track = enhancedAudioSCNVersionALT[trackNumber];
- else if (_vm->getFeatures() & GF_SCNFILES)
+ if (_vm->getFeatures() & GF_SCNFILES)
track = enhancedAudioSCNVersion[trackNumber];
else
track = enhancedAudioGRAVersion[trackNumber];
@@ -404,112 +381,43 @@ void DeleteMidiBuffer() {
midiBuffer.pDat = NULL;
}
-MidiMusicPlayer::MidiMusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false) {
- memset(_channel, 0, sizeof(_channel));
- memset(_channelVolume, 0, sizeof(_channelVolume));
- _masterVolume = 0;
- this->open();
- _xmidiParser = MidiParser::createParser_XMIDI();
-}
-
-MidiMusicPlayer::~MidiMusicPlayer() {
- _driver->setTimerCallback(NULL, NULL);
- stop();
- this->close();
- _xmidiParser->setMidiDriver(NULL);
- delete _xmidiParser;
-}
-
-void MidiMusicPlayer::setVolume(int volume) {
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
-
- if (_masterVolume == volume)
- return;
+MidiMusicPlayer::MidiMusicPlayer() {
+ MidiPlayer::createDriver();
- _masterVolume = volume;
-
- Common::StackLock lock(_mutex);
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
- for (int i = 0; i < 16; ++i) {
- if (_channel[i]) {
- _channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
- }
+ _driver->setTimerCallback(this, &timerCallback);
}
}
-int MidiMusicPlayer::open() {
- // Don't ever call open without first setting the output driver!
- if (!_driver)
- return 255;
-
- int ret = _driver->open();
- if (ret)
- return ret;
-
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
+void MidiMusicPlayer::setVolume(int volume) {
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
-void MidiMusicPlayer::close() {
- stop();
- if (_driver)
- _driver->close();
- _driver = 0;
+ Audio::MidiPlayer::setVolume(volume);
}
void MidiMusicPlayer::send(uint32 b) {
- byte channel = (byte)(b & 0x0F);
- if ((b & 0xFFF0) == 0x07B0) {
- // Adjust volume changes by master volume
- byte volume = (byte)((b >> 16) & 0x7F);
- _channelVolume[channel] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xFFF0) == 0x007BB0) {
- // Only respond to All Notes Off if this channel
- // has currently been allocated
- if (!_channel[b & 0x0F])
- return;
- }
-
- if (!_channel[channel])
- _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
-
- if (_channel[channel]) {
- _channel[channel]->send(b);
+ Audio::MidiPlayer::send(b);
+ byte channel = (byte)(b & 0x0F);
+ if (_channelsTable[channel]) {
if ((b & 0xFFF0) == 0x0079B0) {
// We've just Reset All Controllers, so we need to
// re-adjust the volume. Otherwise, volume is reset to
// default whenever the music changes.
- _channel[channel]->send(0x000007B0 | (((_channelVolume[channel] * _masterVolume) / 255) << 16) | channel);
+ _channelsTable[channel]->send(0x000007B0 | (((_channelsVolume[channel] * _masterVolume) / 255) << 16) | channel);
}
}
}
-void MidiMusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // End of Track
- if (_looping)
- _parser->jumpToTick(0);
- else
- stop();
- break;
- default:
- //warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MidiMusicPlayer::onTimer(void *refCon) {
- MidiMusicPlayer *music = (MidiMusicPlayer *)refCon;
- Common::StackLock lock(music->_mutex);
-
- if (music->_isPlaying)
- music->_parser->onTimer();
-}
-
void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) {
+ Common::StackLock lock(_mutex);
+
if (_isPlaying)
return;
@@ -527,8 +435,8 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) {
// Load XMID resource data
- if (_xmidiParser->loadMusic(midiData, size)) {
- MidiParser *parser = _xmidiParser;
+ MidiParser *parser = MidiParser::createParser_XMIDI();
+ if (parser->loadMusic(midiData, size)) {
parser->setTrack(0);
parser->setMidiDriver(this);
parser->setTimerRate(getBaseTempo());
@@ -537,18 +445,10 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) {
_parser = parser;
- _looping = loop;
+ _isLooping = loop;
_isPlaying = true;
- }
-}
-
-void MidiMusicPlayer::stop() {
- Common::StackLock lock(_mutex);
-
- _isPlaying = false;
- if (_parser) {
- _parser->unloadMusic();
- _parser = NULL;
+ } else {
+ delete parser;
}
}
@@ -566,7 +466,6 @@ PCMMusicPlayer::PCMMusicPlayer() {
_silenceSamples = 0;
_curChunk = 0;
- _fileName = 0;
_state = S_IDLE;
_mState = S_IDLE;
_scriptNum = -1;
@@ -589,15 +488,13 @@ PCMMusicPlayer::PCMMusicPlayer() {
PCMMusicPlayer::~PCMMusicPlayer() {
_vm->_mixer->stopHandle(_handle);
-
- delete[] _fileName;
}
void PCMMusicPlayer::startPlay(int id) {
- if (!_fileName)
+ if (_filename.empty())
return;
- debugC(DEBUG_DETAILED, kTinselDebugMusic, "Playing PCM music %s, index %d", _fileName, id);
+ debugC(DEBUG_DETAILED, kTinselDebugMusic, "Playing PCM music %s, index %d", _filename.c_str(), id);
Common::StackLock slock(_mutex);
@@ -712,8 +609,7 @@ void PCMMusicPlayer::setMusicSceneDetails(SCNHANDLE hScript,
_hScript = hScript;
_hSegment = hSegment;
- _fileName = new char[strlen(fileName) + 1];
- strcpy(_fileName, fileName);
+ _filename = fileName;
// Start scene with music not dimmed
_dimmed = false;
@@ -869,19 +765,19 @@ bool PCMMusicPlayer::getNextChunk() {
sampleLength = FROM_LE_32(musicSegments[snum].sampleLength);
sampleCLength = (((sampleLength + 63) & ~63)*33)/64;
- if (!file.open(_fileName))
- error(CANNOT_FIND_FILE, _fileName);
+ if (!file.open(_filename))
+ error(CANNOT_FIND_FILE, _filename.c_str());
file.seek(sampleOffset);
if (file.eos() || file.err() || (uint32)file.pos() != sampleOffset)
- error(FILE_IS_CORRUPT, _fileName);
+ error(FILE_IS_CORRUPT, _filename.c_str());
buffer = (byte *) malloc(sampleCLength);
assert(buffer);
// read all of the sample
if (file.read(buffer, sampleCLength) != sampleCLength)
- error(FILE_IS_CORRUPT, _fileName);
+ error(FILE_IS_CORRUPT, _filename.c_str());
debugC(DEBUG_DETAILED, kTinselDebugMusic, "Creating ADPCM music chunk with size %d, "
"offset %d (script %d.%d)", sampleCLength, sampleOffset,
@@ -890,8 +786,8 @@ bool PCMMusicPlayer::getNextChunk() {
sampleStream = new Common::MemoryReadStream(buffer, sampleCLength, DisposeAfterUse::YES);
delete _curChunk;
- _curChunk = makeADPCMStream(sampleStream, DisposeAfterUse::YES, sampleCLength,
- Audio::kADPCMTinsel8, 22050, 1, 32);
+ _curChunk = new Tinsel8_ADPCMStream(sampleStream, DisposeAfterUse::YES, sampleCLength,
+ 22050, 1, 32);
_state = S_MID;
return true;
diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h
index e2a3b4c2c1..9003e60078 100644
--- a/engines/tinsel/music.h
+++ b/engines/tinsel/music.h
@@ -28,12 +28,13 @@
#ifndef TINSEL_MUSIC_H
#define TINSEL_MUSIC_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "common/mutex.h"
+class MidiParser;
+
namespace Tinsel {
bool PlayMidiSequence( // Plays the specified MIDI sequence through the sound driver
@@ -60,57 +61,24 @@ SCNHANDLE GetTrackOffset(int trackNumber);
void dumpMusic();
-class MidiMusicPlayer : public MidiDriver {
+class MidiMusicPlayer : public Audio::MidiPlayer {
public:
- MidiMusicPlayer(MidiDriver *driver);
- ~MidiMusicPlayer();
-
- bool isPlaying() { return _isPlaying; }
- void setPlaying(bool playing) { _isPlaying = playing; }
+ MidiMusicPlayer();
- void setVolume(int volume);
- int getVolume() { return _masterVolume; }
+ virtual void setVolume(int volume);
void playXMIDI(byte *midiData, uint32 size, bool loop);
- void stop();
+// void stop();
void pause();
void resume();
- void setLoop(bool loop) { _looping = loop; }
- //MidiDriver interface implementation
- int open();
- void close();
- void send(uint32 b);
-
- void metaEvent(byte type, byte *data, uint16 length);
-
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
// The original sets the "sequence timing" to 109 Hz, whatever that
// means. The default is 120.
-
uint32 getBaseTempo() { return _driver ? (109 * _driver->getBaseTempo()) / 120 : 0; }
-
- //Channel allocation functions
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
- MidiParser *_parser;
- Common::Mutex _mutex;
-
-protected:
-
- static void onTimer(void *data);
-
- MidiChannel *_channel[16];
- MidiDriver *_driver;
- MidiParser *_xmidiParser;
- byte _channelVolume[16];
-
- bool _isPlaying;
- bool _looping;
- byte _masterVolume;
};
class PCMMusicPlayer : public Audio::AudioStream {
@@ -180,7 +148,7 @@ protected:
int32 _scriptIndex;
SCNHANDLE _hScript;
SCNHANDLE _hSegment;
- char *_fileName;
+ Common::String _filename;
uint8 _volume;
diff --git a/engines/tinsel/object.cpp b/engines/tinsel/object.cpp
index bf31cdfa25..ad02a614a5 100644
--- a/engines/tinsel/object.cpp
+++ b/engines/tinsel/object.cpp
@@ -32,6 +32,8 @@
#include "tinsel/text.h"
#include "tinsel/tinsel.h"
+#include "common/textconsole.h"
+
#define OID_EFFECTS 0x2000 // generic special effects object id
namespace Tinsel {
@@ -482,11 +484,11 @@ void AnimateObject(OBJECT *pAniObj, SCNHANDLE hNewImg) {
* Creates a rectangle object of the given dimensions and returns
* a pointer to the object.
* @param hPal Palette for the rectangle object
- * @param colour Which colour offset from the above palette
+ * @param color Which color offset from the above palette
* @param width Width of rectangle
* @param height Height of rectangle
*/
-OBJECT *RectangleObject(SCNHANDLE hPal, int colour, int width, int height) {
+OBJECT *RectangleObject(SCNHANDLE hPal, int color, int width, int height) {
// template for initialising the rectangle object
static const OBJ_INIT rectObj = {0, DMA_CONST, OID_EFFECTS, 0, 0, 0};
PALQ *pPalQ; // palette queue pointer
@@ -503,8 +505,8 @@ OBJECT *RectangleObject(SCNHANDLE hPal, int colour, int width, int height) {
// assign palette to object
pRect->pPal = pPalQ;
- // set colour in the palette
- pRect->constant = colour;
+ // set color in the palette
+ pRect->constant = color;
// set rectangle width
pRect->width = width;
diff --git a/engines/tinsel/object.h b/engines/tinsel/object.h
index a000dee72c..9f10c06cd2 100644
--- a/engines/tinsel/object.h
+++ b/engines/tinsel/object.h
@@ -87,7 +87,7 @@ struct OBJECT {
Common::Rect rcPrev; ///< previous screen coordinates of object bounding rectangle
int flags; ///< object flags - see above for list
PALQ *pPal; ///< objects palette Q position
- int constant; ///< which colour in palette for monochrome objects
+ int constant; ///< which color in palette for monochrome objects
int width; ///< width of object
int height; ///< height of object
SCNHANDLE hBits; ///< image bitmap handle
@@ -184,7 +184,7 @@ void HideObject( // Hides a object by giving it a "NullImage" image pointer
OBJECT *RectangleObject( // create a rectangle object of the given dimensions
SCNHANDLE hPal, // palette for the rectangle object
- int colour, // which colour offset from the above palette
+ int color, // which color offset from the above palette
int width, // width of rectangle
int height); // height of rectangle
diff --git a/engines/tinsel/palette.cpp b/engines/tinsel/palette.cpp
index a0ceec54eb..0877337603 100644
--- a/engines/tinsel/palette.cpp
+++ b/engines/tinsel/palette.cpp
@@ -32,6 +32,8 @@
#include "tinsel/tinsel.h"
#include "common/system.h"
+#include "common/textconsole.h"
+#include "graphics/palette.h"
namespace Tinsel {
@@ -41,12 +43,12 @@ namespace Tinsel {
struct VIDEO_DAC_Q {
union {
SCNHANDLE hRGBarray; ///< handle of palette or
- COLORREF *pRGBarray; ///< list of palette colours
+ COLORREF *pRGBarray; ///< list of palette colors
COLORREF singleRGB;
} pal;
bool bHandle; ///< when set - use handle of palette
int destDACindex; ///< start index of palette in video DAC
- int numColours; ///< number of colours in "hRGBarray"
+ int numColors; ///< number of colors in "hRGBarray"
};
@@ -67,13 +69,13 @@ static VIDEO_DAC_Q vidDACdata[VDACQLENGTH];
/** video DAC transfer Q head pointer */
static VIDEO_DAC_Q *pDAChead;
-/** colour index of the 4 colours used for the translucent palette */
+/** color index of the 4 colors used for the translucent palette */
#define COL_HILIGHT TBLUE1
/** the translucent palette lookup table */
-uint8 transPalette[MAX_COLOURS]; // used in graphics.cpp
+uint8 transPalette[MAX_COLORS]; // used in graphics.cpp
-uint8 ghostPalette[MAX_COLOURS];
+uint8 ghostPalette[MAX_COLORS];
static int translucentIndex = 228;
@@ -111,7 +113,7 @@ void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) {
}
// Check for correspondent color
- for (uint i = 0; (i < FROM_LE_32(pal->numColours)) && !colorFound; i++) {
+ for (uint i = 0; (i < FROM_LE_32(pal->numColors)) && !colorFound; i++) {
// get R G B values in the same way as psx format converters
uint16 psxEquivalent = TINSEL_PSX_RGB(TINSEL_GetRValue(pal->palRGB[i]) >> 3, TINSEL_GetGValue(pal->palRGB[i]) >> 3, TINSEL_GetBValue(pal->palRGB[i]) >> 3);
@@ -138,15 +140,15 @@ void PalettesToVideoDAC() {
// while Q is not empty
while (pDAChead != pDACtail) {
const PALETTE *pPalette; // pointer to hardware palette
- const COLORREF *pColours; // pointer to list of RGB triples
+ const COLORREF *pColors; // pointer to list of RGB triples
#ifdef DEBUG
// make sure palette does not overlap
- assert(pDACtail->destDACindex + pDACtail->numColours <= MAX_COLOURS);
+ assert(pDACtail->destDACindex + pDACtail->numColors <= MAX_COLORS);
#else
// make sure palette does not overlap
- if (pDACtail->destDACindex + pDACtail->numColours > MAX_COLOURS)
- pDACtail->numColours = MAX_COLOURS - pDACtail->destDACindex;
+ if (pDACtail->destDACindex + pDACtail->numColors > MAX_COLORS)
+ pDACtail->numColors = MAX_COLORS - pDACtail->destDACindex;
#endif
if (pDACtail->bHandle) {
@@ -156,23 +158,23 @@ void PalettesToVideoDAC() {
pPalette = (const PALETTE *)LockMem(pDACtail->pal.hRGBarray);
// get RGB pointer
- pColours = pPalette->palRGB;
- } else if (pDACtail->numColours == 1) {
+ pColors = pPalette->palRGB;
+ } else if (pDACtail->numColors == 1) {
// we are using a single color palette
- pColours = &pDACtail->pal.singleRGB;
+ pColors = &pDACtail->pal.singleRGB;
} else {
// we are using a palette pointer
- pColours = pDACtail->pal.pRGBarray;
+ pColors = pDACtail->pal.pRGBarray;
}
- for (int i = 0; i < pDACtail->numColours; ++i) {
- pal[i * 3 + 0] = TINSEL_GetRValue(pColours[i]);
- pal[i * 3 + 1] = TINSEL_GetGValue(pColours[i]);
- pal[i * 3 + 2] = TINSEL_GetBValue(pColours[i]);
+ for (int i = 0; i < pDACtail->numColors; ++i) {
+ pal[i * 3 + 0] = TINSEL_GetRValue(pColors[i]);
+ pal[i * 3 + 1] = TINSEL_GetGValue(pColors[i]);
+ pal[i * 3 + 2] = TINSEL_GetBValue(pColors[i]);
}
// update the system palette
- g_system->getPaletteManager()->setPalette(pal, pDACtail->destDACindex, pDACtail->numColours);
+ g_system->getPaletteManager()->setPalette(pal, pDACtail->destDACindex, pDACtail->numColors);
// update tail pointer
pDACtail++;
@@ -216,15 +218,15 @@ void PaletteStats() {
/**
* Places a palette in the video DAC queue.
* @param posInDAC Position in video DAC
- * @param numColours Number of colours in palette
+ * @param numColors Number of colors in palette
* @param hPalette Handle to palette
*/
-void UpdateDACqueueHandle(int posInDAC, int numColours, SCNHANDLE hPalette) {
+void UpdateDACqueueHandle(int posInDAC, int numColors, SCNHANDLE hPalette) {
// check Q overflow
assert(pDAChead < vidDACdata + VDACQLENGTH);
pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
- pDAChead->numColours = numColours; // set number of colours
+ pDAChead->numColors = numColors; // set number of colors
pDAChead->pal.hRGBarray = hPalette; // set handle of palette
pDAChead->bHandle = true; // we are using a palette handle
@@ -240,19 +242,19 @@ void UpdateDACqueueHandle(int posInDAC, int numColours, SCNHANDLE hPalette) {
/**
* Places a palette in the video DAC queue.
* @param posInDAC Position in video DAC
- * @param numColours Number of colours in palette
- * @param pColours List of RGB triples
+ * @param numColors Number of colors in palette
+ * @param pColors List of RGB triples
*/
-void UpdateDACqueue(int posInDAC, int numColours, COLORREF *pColours) {
+void UpdateDACqueue(int posInDAC, int numColors, COLORREF *pColors) {
// check Q overflow
assert(pDAChead < vidDACdata + NUM_PALETTES);
pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
- pDAChead->numColours = numColours; // set number of colours
- if (numColours == 1)
- pDAChead->pal.singleRGB = *pColours; // set single color of which the "palette" consists
+ pDAChead->numColors = numColors; // set number of colors
+ if (numColors == 1)
+ pDAChead->pal.singleRGB = *pColors; // set single color of which the "palette" consists
else
- pDAChead->pal.pRGBarray = pColours; // set addr of palette
+ pDAChead->pal.pRGBarray = pColors; // set addr of palette
pDAChead->bHandle = false; // we are not using a palette handle
// update head pointer
@@ -275,7 +277,7 @@ void UpdateDACqueue(int posInDAC, COLORREF color) {
assert(pDAChead < vidDACdata + NUM_PALETTES);
pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
- pDAChead->numColours = 1; // set number of colours
+ pDAChead->numColors = 1; // set number of colors
pDAChead->pal.singleRGB = color; // set single color of which the "palette" consists
pDAChead->bHandle = false; // we are not using a palette handle
@@ -294,7 +296,7 @@ void UpdateDACqueue(int posInDAC, COLORREF color) {
*/
PALQ *AllocPalette(SCNHANDLE hNewPal) {
PALQ *pPrev, *p; // walks palAllocData
- int iDAC; // colour index in video DAC
+ int iDAC; // color index in video DAC
PALQ *pNxtPal; // next PALQ struct in palette allocator
PALETTE *pNewPal;
@@ -311,7 +313,7 @@ PALQ *AllocPalette(SCNHANDLE hNewPal) {
}
// search all structs in palette allocator - find a free slot
- iDAC = FGND_DAC_INDEX; // init DAC index to first available foreground colour
+ iDAC = FGND_DAC_INDEX; // init DAC index to first available foreground color
for (p = palAllocData; p < palAllocData + NUM_PALETTES; p++) {
if (p->hPal == 0) {
@@ -319,11 +321,11 @@ PALQ *AllocPalette(SCNHANDLE hNewPal) {
p->objCount = 1; // init number of objects using palette
p->posInDAC = iDAC; // set palettes start pos in video DAC
p->hPal = hNewPal; // set hardware palette data
- p->numColours = FROM_LE_32(pNewPal->numColours); // set number of colours in palette
+ p->numColors = FROM_LE_32(pNewPal->numColors); // set number of colors in palette
if (TinselV2)
- // Copy all the colours
- memcpy(p->palRGB, pNewPal->palRGB, p->numColours * sizeof(COLORREF));
+ // Copy all the colors
+ memcpy(p->palRGB, pNewPal->palRGB, p->numColors * sizeof(COLORREF));
#ifdef DEBUG
// one more palette in use
@@ -333,30 +335,30 @@ PALQ *AllocPalette(SCNHANDLE hNewPal) {
// Q the change to the video DAC
if (TinselV2)
- UpdateDACqueue(p->posInDAC, p->numColours, p->palRGB);
+ UpdateDACqueue(p->posInDAC, p->numColors, p->palRGB);
else
- UpdateDACqueueHandle(p->posInDAC, p->numColours, p->hPal);
+ UpdateDACqueueHandle(p->posInDAC, p->numColors, p->hPal);
// move all palettes after this one down (if necessary)
for (pPrev = p, pNxtPal = pPrev + 1; pNxtPal < palAllocData + NUM_PALETTES; pNxtPal++) {
if (pNxtPal->hPal != 0) {
// palette slot is in use
- if (pNxtPal->posInDAC >= pPrev->posInDAC + pPrev->numColours)
+ if (pNxtPal->posInDAC >= pPrev->posInDAC + pPrev->numColors)
// no need to move palettes down
break;
// move palette down - indicate change
pNxtPal->posInDAC = (pPrev->posInDAC
- + pPrev->numColours) | PALETTE_MOVED;
+ + pPrev->numColors) | PALETTE_MOVED;
// Q the palette change in position to the video DAC
if (!TinselV2)
UpdateDACqueueHandle(pNxtPal->posInDAC,
- pNxtPal->numColours,
+ pNxtPal->numColors,
pNxtPal->hPal);
else if (!pNxtPal->bFading)
UpdateDACqueue(pNxtPal->posInDAC,
- pNxtPal->numColours,
+ pNxtPal->numColors,
pNxtPal->palRGB);
// update previous palette to current palette
@@ -369,7 +371,7 @@ PALQ *AllocPalette(SCNHANDLE hNewPal) {
}
// set new DAC index
- iDAC = p->posInDAC + p->numColours;
+ iDAC = p->posInDAC + p->numColors;
}
// no free palettes
@@ -431,43 +433,43 @@ void SwapPalette(PALQ *pPalQ, SCNHANDLE hNewPal) {
// validate palette Q pointer
assert(pPalQ >= palAllocData && pPalQ <= palAllocData + NUM_PALETTES - 1);
- if (pPalQ->numColours >= (int)FROM_LE_32(pNewPal->numColours)) {
+ if (pPalQ->numColors >= (int)FROM_LE_32(pNewPal->numColors)) {
// new palette will fit the slot
// install new palette
pPalQ->hPal = hNewPal;
if (TinselV2) {
- pPalQ->numColours = FROM_LE_32(pNewPal->numColours);
+ pPalQ->numColors = FROM_LE_32(pNewPal->numColors);
- // Copy all the colours
- memcpy(pPalQ->palRGB, pNewPal->palRGB, FROM_LE_32(pNewPal->numColours) * sizeof(COLORREF));
+ // Copy all the colors
+ memcpy(pPalQ->palRGB, pNewPal->palRGB, FROM_LE_32(pNewPal->numColors) * sizeof(COLORREF));
if (!pPalQ->bFading)
// Q the change to the video DAC
- UpdateDACqueue(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColours), pPalQ->palRGB);
+ UpdateDACqueue(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColors), pPalQ->palRGB);
} else {
// Q the change to the video DAC
- UpdateDACqueueHandle(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColours), hNewPal);
+ UpdateDACqueueHandle(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColors), hNewPal);
}
} else {
- // # colours are different - will have to update all following palette entries
+ // # colors are different - will have to update all following palette entries
assert(!TinselV2); // Fatal error for Tinsel 2
PALQ *pNxtPalQ; // next palette queue position
for (pNxtPalQ = pPalQ + 1; pNxtPalQ < palAllocData + NUM_PALETTES; pNxtPalQ++) {
- if (pNxtPalQ->posInDAC >= pPalQ->posInDAC + pPalQ->numColours)
+ if (pNxtPalQ->posInDAC >= pPalQ->posInDAC + pPalQ->numColors)
// no need to move palettes down
break;
// move palette down
pNxtPalQ->posInDAC = (pPalQ->posInDAC
- + pPalQ->numColours) | PALETTE_MOVED;
+ + pPalQ->numColors) | PALETTE_MOVED;
// Q the palette change in position to the video DAC
UpdateDACqueueHandle(pNxtPalQ->posInDAC,
- pNxtPalQ->numColours,
+ pNxtPalQ->numColors,
pNxtPalQ->hPal);
// update previous palette to current palette
@@ -501,12 +503,12 @@ PALQ *GetNextPalette(PALQ *pStrtPal) {
}
/**
- * Sets the current background colour.
- * @param colour Colour to set the background to
+ * Sets the current background color.
+ * @param color Color to set the background to
*/
-void SetBgndColour(COLORREF colour) {
- // update background colour struct by queuing the change to the video DAC
- UpdateDACqueue(BGND_DAC_INDEX, colour);
+void SetBgndColor(COLORREF color) {
+ // update background color struct by queuing the change to the video DAC
+ UpdateDACqueue(BGND_DAC_INDEX, color);
}
/**
@@ -544,23 +546,23 @@ void CreateTranslucentPalette(SCNHANDLE hPalette) {
// get a pointer to the palette
PALETTE *pPal = (PALETTE *)LockMem(hPalette);
- // leave background colour alone
+ // leave background color alone
transPalette[0] = 0;
- for (uint i = 0; i < FROM_LE_32(pPal->numColours); i++) {
- // get the RGB colour model values
+ for (uint i = 0; i < FROM_LE_32(pPal->numColors); i++) {
+ // get the RGB color model values
uint8 red = TINSEL_GetRValue(pPal->palRGB[i]);
uint8 green = TINSEL_GetGValue(pPal->palRGB[i]);
uint8 blue = TINSEL_GetBValue(pPal->palRGB[i]);
- // calculate the Value field of the HSV colour model
+ // calculate the Value field of the HSV color model
unsigned val = (red > green) ? red : green;
val = (val > blue) ? val : blue;
- // map the Value field to one of the 4 colours reserved for the translucent palette
+ // map the Value field to one of the 4 colors reserved for the translucent palette
val /= 63;
transPalette[i + 1] = (uint8)((val == 0) ? 0 : val +
- (TinselV2 ? TranslucentColour() : COL_HILIGHT) - 1);
+ (TinselV2 ? TranslucentColor() : COL_HILIGHT) - 1);
}
}
@@ -572,20 +574,20 @@ void CreateGhostPalette(SCNHANDLE hPalette) {
PALETTE *pPal = (PALETTE *)LockMem(hPalette);
int i;
- // leave background colour alone
+ // leave background color alone
ghostPalette[0] = 0;
- for (i = 0; i < (int)FROM_LE_32(pPal->numColours); i++) {
- // get the RGB colour model values
+ for (i = 0; i < (int)FROM_LE_32(pPal->numColors); i++) {
+ // get the RGB color model values
uint8 red = TINSEL_GetRValue(pPal->palRGB[i]);
uint8 green = TINSEL_GetGValue(pPal->palRGB[i]);
uint8 blue = TINSEL_GetBValue(pPal->palRGB[i]);
- // calculate the Value field of the HSV colour model
+ // calculate the Value field of the HSV color model
unsigned val = (red > green) ? red : green;
val = (val > blue) ? val : blue;
- // map the Value field to one of the 4 colours reserved for the translucent palette
+ // map the Value field to one of the 4 colors reserved for the translucent palette
val /= 64;
assert(/*val >= 0 &&*/ val <= 3);
ghostPalette[i + 1] = (uint8)(val + SysVar(ISV_GHOST_BASE));
@@ -594,25 +596,25 @@ void CreateGhostPalette(SCNHANDLE hPalette) {
/**
- * Returns an adjusted colour RGB
- * @param colour Colour to scale
+ * Returns an adjusted color RGB
+ * @param color Color to scale
*/
-static COLORREF DimColour(COLORREF colour, int factor) {
+static COLORREF DimColor(COLORREF color, int factor) {
uint32 red, green, blue;
if (factor == 10) {
// No change
- return colour;
+ return color;
} else if (factor == 0) {
// No brightness
return 0;
} else {
// apply multiplier to RGB components
- red = TINSEL_GetRValue(colour) * factor / 10;
- green = TINSEL_GetGValue(colour) * factor / 10;
- blue = TINSEL_GetBValue(colour) * factor / 10;
+ red = TINSEL_GetRValue(color) * factor / 10;
+ green = TINSEL_GetGValue(color) * factor / 10;
+ blue = TINSEL_GetBValue(color) * factor / 10;
- // return new colour
+ // return new color
return TINSEL_RGB(red, green, blue);
}
}
@@ -620,10 +622,10 @@ static COLORREF DimColour(COLORREF colour, int factor) {
/**
* DimPartPalette
*/
-void DimPartPalette(SCNHANDLE hDimPal, int startColour, int length, int brightness) {
+void DimPartPalette(SCNHANDLE hDimPal, int startColor, int length, int brightness) {
PALQ *pPalQ;
PALETTE *pDimPal;
- int iColour;
+ int iColor;
pPalQ = FindPalette(hDimPal);
assert(pPalQ);
@@ -631,42 +633,42 @@ void DimPartPalette(SCNHANDLE hDimPal, int startColour, int length, int brightne
// get pointer to dim palette
pDimPal = (PALETTE *)LockMem(hDimPal);
- // Adjust for the fact that palettes don't contain colour 0
- startColour -= 1;
+ // Adjust for the fact that palettes don't contain color 0
+ startColor -= 1;
// Check some other things
- if (startColour + length > pPalQ->numColours)
- error("DimPartPalette(): colour overrun");
+ if (startColor + length > pPalQ->numColors)
+ error("DimPartPalette(): color overrun");
- for (iColour = startColour; iColour < startColour + length; iColour++) {
- pPalQ->palRGB[iColour] = DimColour(pDimPal->palRGB[iColour], brightness);
+ for (iColor = startColor; iColor < startColor + length; iColor++) {
+ pPalQ->palRGB[iColor] = DimColor(pDimPal->palRGB[iColor], brightness);
}
if (!pPalQ->bFading) {
// Q the change to the video DAC
- UpdateDACqueue(pPalQ->posInDAC + startColour, length, &pPalQ->palRGB[startColour]);
+ UpdateDACqueue(pPalQ->posInDAC + startColor, length, &pPalQ->palRGB[startColor]);
}
}
-int TranslucentColour() {
+int TranslucentColor() {
return translucentIndex;
}
-int HighlightColour() {
+int HighlightColor() {
UpdateDACqueue(talkIndex, (COLORREF)SysVar(SYS_HighlightRGB));
return talkIndex;
}
-int TalkColour() {
+int TalkColor() {
return TinselV2 ? talkIndex : TALKFONT_COL;
}
-void SetTalkColourRef(COLORREF colRef) {
+void SetTalkColorRef(COLORREF colRef) {
talkColRef = colRef;
}
-COLORREF GetTalkColourRef() {
+COLORREF GetTalkColorRef() {
return talkColRef;
}
diff --git a/engines/tinsel/palette.h b/engines/tinsel/palette.h
index 9743ee53aa..694eff504d 100644
--- a/engines/tinsel/palette.h
+++ b/engines/tinsel/palette.h
@@ -42,14 +42,14 @@ typedef uint32 COLORREF;
#define TINSEL_PSX_RGB(r,g,b) ((uint16)(((uint8)(r))|((uint16)(g)<<5)|(((uint16)(b))<<10)))
enum {
- MAX_COLOURS = 256, ///< maximum number of colours - for VGA 256
+ MAX_COLORS = 256, ///< maximum number of colors - for VGA 256
BITS_PER_PIXEL = 8, ///< number of bits per pixel for VGA 256
MAX_INTENSITY = 255, ///< the biggest value R, G or B can have
NUM_PALETTES = 32, ///< number of palettes
// Discworld has some fixed apportioned bits in the palette.
- BGND_DAC_INDEX = 0, ///< index of background colour in Video DAC
- FGND_DAC_INDEX = 1, ///< index of first foreground colour in Video DAC
+ BGND_DAC_INDEX = 0, ///< index of background color in Video DAC
+ FGND_DAC_INDEX = 1, ///< index of first foreground color in Video DAC
TBLUE1 = 228, ///< Blue used in translucent rectangles
TBLUE2 = 229, ///< Blue used in translucent rectangles
TBLUE3 = 230, ///< Blue used in translucent rectangles
@@ -57,7 +57,7 @@ enum {
TALKFONT_COL = 233
};
-// some common colours
+// some common colors
#define BLACK (TINSEL_RGB(0, 0, 0))
#define WHITE (TINSEL_RGB(MAX_INTENSITY, MAX_INTENSITY, MAX_INTENSITY))
@@ -73,8 +73,8 @@ enum {
/** hardware palette structure */
struct PALETTE {
- int32 numColours; ///< number of colours in the palette
- COLORREF palRGB[MAX_COLOURS]; ///< actual palette colours
+ int32 numColors; ///< number of colors in the palette
+ COLORREF palRGB[MAX_COLORS]; ///< actual palette colors
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
@@ -85,10 +85,10 @@ struct PALQ {
SCNHANDLE hPal; ///< handle to palette data struct
int objCount; ///< number of objects using this palette
int posInDAC; ///< palette position in the video DAC
- int numColours; ///< number of colours in the palette
+ int numColors; ///< number of colors in the palette
// Discworld 2 fields
bool bFading; // Whether or not fading
- COLORREF palRGB[MAX_COLOURS]; // actual palette colours
+ COLORREF palRGB[MAX_COLORS]; // actual palette colors
};
#define PALETTE_MOVED 0x8000 // when this bit is set in the "posInDAC"
@@ -114,13 +114,13 @@ void PalettesToVideoDAC(); // Update the video DAC with palettes currently the t
void UpdateDACqueueHandle(
int posInDAC, // position in video DAC
- int numColours, // number of colours in palette
+ int numColors, // number of colors in palette
SCNHANDLE hPalette); // handle to palette
void UpdateDACqueue( // places a palette in the video DAC queue
int posInDAC, // position in video DAC
- int numColours, // number of colours in palette
- COLORREF *pColours); // list of RGB tripples
+ int numColors, // number of colors in palette
+ COLORREF *pColors); // list of RGB tripples
void UpdateDACqueue(int posInDAC, COLORREF color);
@@ -140,10 +140,10 @@ void SwapPalette( // swaps palettes at the specified palette queue position
PALQ *GetNextPalette( // returns the next palette in the queue
PALQ *pStrtPal); // queue position to start from - when NULL will start from beginning of queue
-COLORREF GetBgndColour(); // returns current background colour
+COLORREF GetBgndColor(); // returns current background color
-void SetBgndColour( // sets current background colour
- COLORREF colour); // colour to set the background to
+void SetBgndColor( // sets current background color
+ COLORREF color); // color to set the background to
void FadingPalette(PALQ *pPalQ, bool bFading);
@@ -155,22 +155,22 @@ void NoFadingPalettes(); // All fading processes have just been killed
void DimPartPalette(
SCNHANDLE hPal,
- int startColour,
+ int startColor,
int length,
int brightness); // 0 = black, 10 == 100%
-int TranslucentColour();
+int TranslucentColor();
-#define BoxColour TranslucentColour
+#define BoxColor TranslucentColor
-int HighlightColour();
+int HighlightColor();
-int TalkColour();
+int TalkColor();
-void SetTalkColourRef(COLORREF colRef);
+void SetTalkColorRef(COLORREF colRef);
-COLORREF GetTalkColourRef();
+COLORREF GetTalkColorRef();
void SetTagColorRef(COLORREF colRef);
diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp
index ccd86d7ed7..a1cc02a832 100644
--- a/engines/tinsel/pcode.cpp
+++ b/engines/tinsel/pcode.cpp
@@ -36,6 +36,7 @@
#include "tinsel/tinlib.h" // Library routines
#include "tinsel/tinsel.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Tinsel {
diff --git a/engines/tinsel/pcode.h b/engines/tinsel/pcode.h
index f3690e9257..f31f2eb5c6 100644
--- a/engines/tinsel/pcode.h
+++ b/engines/tinsel/pcode.h
@@ -31,7 +31,7 @@
#include "tinsel/sched.h" // for PROCESS
namespace Common {
- class Serializer;
+class Serializer;
}
namespace Tinsel {
diff --git a/engines/tinsel/pdisplay.cpp b/engines/tinsel/pdisplay.cpp
index 38748b703b..5022f4757a 100644
--- a/engines/tinsel/pdisplay.cpp
+++ b/engines/tinsel/pdisplay.cpp
@@ -44,6 +44,8 @@
#include "tinsel/text.h"
#include "tinsel/tinsel.h"
+#include "common/textconsole.h"
+
namespace Tinsel {
//----------------- EXTERNAL GLOBAL DATA --------------------
@@ -59,8 +61,8 @@ extern int newestString; // The overrun counter, in STRRES.C
#define LPOSX 295 // X-co-ord of lead actor's position display
#define CPOSX 24 // X-co-ord of cursor's position display
-#define OPOSX SCRN_CENTRE_X // X-co-ord of overrun counter's display
-#define SPOSX SCRN_CENTRE_X // X-co-ord of string numbner's display
+#define OPOSX SCRN_CENTER_X // X-co-ord of overrun counter's display
+#define SPOSX SCRN_CENTER_X // X-co-ord of string numbner's display
#define POSY 0 // Y-co-ord of these position displays
@@ -158,7 +160,7 @@ void CursorPositionProcess(CORO_PARAM, const void *) {
// New text objects
sprintf(PositionString, "%d %d", aniX + Loffset, aniY + Toffset);
_ctx->cpText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), PositionString,
- 0, CPOSX, POSY, GetTagFontHandle(), TXT_CENTRE);
+ 0, CPOSX, POSY, GetTagFontHandle(), TXT_CENTER);
if (DispPath) {
HPOLYGON hp = InPolygon(aniX + Loffset, aniY + Toffset, PATH);
if (hp == NOPOLY)
@@ -190,7 +192,7 @@ void CursorPositionProcess(CORO_PARAM, const void *) {
sprintf(PositionString, "%d", Overrun);
_ctx->opText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), PositionString,
- 0, OPOSX, POSY, GetTagFontHandle(), TXT_CENTRE);
+ 0, OPOSX, POSY, GetTagFontHandle(), TXT_CENTER);
// update previous value
_ctx->prevOver = Overrun;
@@ -216,7 +218,7 @@ void CursorPositionProcess(CORO_PARAM, const void *) {
// create new text object list
sprintf(PositionString, "%d %d", aniX, aniY);
_ctx->rpText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), PositionString,
- 0, LPOSX, POSY, GetTagFontHandle(), TXT_CENTRE);
+ 0, LPOSX, POSY, GetTagFontHandle(), TXT_CENTER);
// update previous position
_ctx->prevlX = aniX;
@@ -235,7 +237,7 @@ void CursorPositionProcess(CORO_PARAM, const void *) {
sprintf(PositionString, "String: %d", newestString);
_ctx->spText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), PositionString,
- 0, SPOSX, POSY+10, GetTalkFontHandle(), TXT_CENTRE);
+ 0, SPOSX, POSY+10, GetTalkFontHandle(), TXT_CENTER);
// update previous value
_ctx->prevString = newestString;
@@ -411,7 +413,7 @@ static bool ActorTag(int curX, int curY, HotSpotTag *pTag, OBJECT **ppText) {
// May have buggered cursor
EndCursorFollowed();
*ppText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), tagBuffer,
- 0, tagX, tagY, GetTagFontHandle(), TXT_CENTRE, 0);
+ 0, tagX, tagY, GetTagFontHandle(), TXT_CENTER, 0);
assert(*ppText);
MultiSetZPosition(*ppText, Z_TAG_TEXT);
} else
@@ -456,7 +458,7 @@ static bool ActorTag(int curX, int curY, HotSpotTag *pTag, OBJECT **ppText) {
PlayfieldGetPos(FIELD_WORLD, &tagX, &tagY);
LoadStringRes(GetActorTag(ano), TextBufferAddr(), TBUFSZ);
*ppText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
- 0, xtext - tagX, ytext - tagY, GetTagFontHandle(), TXT_CENTRE);
+ 0, xtext - tagX, ytext - tagY, GetTagFontHandle(), TXT_CENTER);
assert(*ppText); // Actor tag string produced NULL text
MultiSetZPosition(*ppText, Z_TAG_TEXT);
} else {
@@ -561,7 +563,7 @@ static bool PolyTag(HotSpotTag *pTag, OBJECT **ppText) {
*ppText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS),
TextBufferAddr(), 0, tagx - Loffset, tagy - Toffset,
- GetTagFontHandle(), TXT_CENTRE, 0);
+ GetTagFontHandle(), TXT_CENTER, 0);
} else if (TinselV2) {
// Bugger cursor
const char *tagPtr = TextBufferAddr();
@@ -570,12 +572,12 @@ static bool PolyTag(HotSpotTag *pTag, OBJECT **ppText) {
GetCursorXYNoWait(&curX, &curY, false);
*ppText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
- 0, curX, curY, GetTagFontHandle(), TXT_CENTRE, 0);
+ 0, curX, curY, GetTagFontHandle(), TXT_CENTER, 0);
} else {
// Handle displaying the tag text on-screen
*ppText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
0, tagx - Loffset, tagy - Toffset,
- GetTagFontHandle(), TXT_CENTRE);
+ GetTagFontHandle(), TXT_CENTER);
assert(*ppText); // Polygon tag string produced NULL text
}
diff --git a/engines/tinsel/pid.h b/engines/tinsel/pid.h
index 786ccc6327..d6f87bdf98 100644
--- a/engines/tinsel/pid.h
+++ b/engines/tinsel/pid.h
@@ -32,11 +32,11 @@ namespace Tinsel {
#define PID_DESTROY 0x8000 // process id of any process that is to be destroyed between scenes
#define PID_EFFECTS (0x0010 | PID_DESTROY) // generic special effects process id
-#define PID_FLASH (PID_EFFECTS + 1) // flash colour process
-#define PID_CYCLE (PID_EFFECTS + 2) // cycle colour range process
+#define PID_FLASH (PID_EFFECTS + 1) // flash color process
+#define PID_CYCLE (PID_EFFECTS + 2) // cycle color range process
#define PID_MORPH (PID_EFFECTS + 3) // morph process
#define PID_FADER (PID_EFFECTS + 4) // fader process
-#define PID_FADE_BGND (PID_EFFECTS + 5) // fade background colour process
+#define PID_FADE_BGND (PID_EFFECTS + 5) // fade background color process
#define PID_BACKGND (0x0020 | PID_DESTROY) // background update process id
diff --git a/engines/tinsel/polygons.cpp b/engines/tinsel/polygons.cpp
index 1620881b01..f49dddeef4 100644
--- a/engines/tinsel/polygons.cpp
+++ b/engines/tinsel/polygons.cpp
@@ -34,6 +34,7 @@
#include "tinsel/tinsel.h"
#include "tinsel/token.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Tinsel {
@@ -98,10 +99,10 @@ struct POLYGON {
/*
* Internal derived data for speed and conveniance
- * set up by PseudoCentre()
+ * set up by PseudoCenter()
*/
- int pcentrex; // Pseudo-centre
- int pcentrey; //
+ int pcenterx; // Pseudo-center
+ int pcentery; //
/**
* List of adjacent polygons. For Path polygons only.
@@ -1624,34 +1625,34 @@ static PPOLYGON CommonInits(PTYPE polyType, int pno, const Poly &ptp, bool bRest
}
/**
- * Calculate a point approximating to the centre of a polygon.
+ * Calculate a point approximating to the center of a polygon.
* Not very sophisticated.
*/
-static void PseudoCentre(POLYGON *p) {
- p->pcentrex = (p->cx[0] + p->cx[1] + p->cx[2] + p->cx[3])/4;
- p->pcentrey = (p->cy[0] + p->cy[1] + p->cy[2] + p->cy[3])/4;
+static void PseudoCenter(POLYGON *p) {
+ p->pcenterx = (p->cx[0] + p->cx[1] + p->cx[2] + p->cx[3])/4;
+ p->pcentery = (p->cy[0] + p->cy[1] + p->cy[2] + p->cy[3])/4;
- if (!IsInPolygon(p->pcentrex, p->pcentrey, PolygonIndex(p))) {
+ if (!IsInPolygon(p->pcenterx, p->pcentery, PolygonIndex(p))) {
int i, top = 0, bot = 0;
for (i = p->ptop; i <= p->pbottom; i++) {
- if (IsInPolygon(p->pcentrex, i, PolygonIndex(p))) {
+ if (IsInPolygon(p->pcenterx, i, PolygonIndex(p))) {
top = i;
break;
}
}
for (i = p->pbottom; i >= p->ptop; i--) {
- if (IsInPolygon(p->pcentrex, i, PolygonIndex(p))) {
+ if (IsInPolygon(p->pcenterx, i, PolygonIndex(p))) {
bot = i;
break;
}
}
- p->pcentrex = (top+bot)/2;
+ p->pcenterx = (top+bot)/2;
}
#ifdef DEBUG
- // assert(IsInPolygon(p->pcentrex, p->pcentrey, PolygonIndex(p))); // Pseudo-centre is not in path
- if (!IsInPolygon(p->pcentrex, p->pcentrey, PolygonIndex(p))) {
- sprintf(TextBufferAddr(), "Pseudo-centre is not in path (starting (%d, %d)) - polygon reversed?",
+ // assert(IsInPolygon(p->pcenterx, p->pcentery, PolygonIndex(p))); // Pseudo-center is not in path
+ if (!IsInPolygon(p->pcenterx, p->pcentery, PolygonIndex(p))) {
+ sprintf(TextBufferAddr(), "Pseudo-center is not in path (starting (%d, %d)) - polygon reversed?",
p->cx[0], p->cy[0]);
error(TextBufferAddr());
}
@@ -1673,7 +1674,7 @@ static void InitPath(const Poly &ptp, bool NodePath, int pno, bool bRestart) {
p->subtype = NodePath ? NODE : NORMAL;
- PseudoCentre(p);
+ PseudoCenter(p);
}
@@ -1918,16 +1919,16 @@ int PolySubtype(HPOLYGON hp) {
return Polys[hp]->subtype;
}
-int PolyCentreX(HPOLYGON hp) {
+int PolyCenterX(HPOLYGON hp) {
CHECK_HP(hp, "Out of range polygon handle (27)");
- return Polys[hp]->pcentrex;
+ return Polys[hp]->pcenterx;
}
-int PolyCentreY(HPOLYGON hp) {
+int PolyCenterY(HPOLYGON hp) {
CHECK_HP(hp, "Out of range polygon handle (28)");
- return Polys[hp]->pcentrey;
+ return Polys[hp]->pcentery;
}
int PolyCornerX(HPOLYGON hp, int n) {
diff --git a/engines/tinsel/polygons.h b/engines/tinsel/polygons.h
index 4be1dabf98..cf8f9e98c2 100644
--- a/engines/tinsel/polygons.h
+++ b/engines/tinsel/polygons.h
@@ -127,8 +127,8 @@ void RestorePolygonStuff(POLY_VOLATILE *sps);
PTYPE PolyType(HPOLYGON hp); // ->type
int PolySubtype(HPOLYGON hp); // ->subtype
-int PolyCentreX(HPOLYGON hp); // ->pcentrex
-int PolyCentreY(HPOLYGON hp); // ->pcentrey
+int PolyCenterX(HPOLYGON hp); // ->pcenterx
+int PolyCenterY(HPOLYGON hp); // ->pcentery
int PolyCornerX(HPOLYGON hp, int n); // ->cx[n]
int PolyCornerY(HPOLYGON hp, int n); // ->cy[n]
PSTATE PolyPointState(HPOLYGON hp); // ->pointState
diff --git a/engines/tinsel/rince.cpp b/engines/tinsel/rince.cpp
index 6ea1dd7464..38ac0a2ce6 100644
--- a/engines/tinsel/rince.cpp
+++ b/engines/tinsel/rince.cpp
@@ -47,6 +47,7 @@
#include "tinsel/tinsel.h"
#include "tinsel/token.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Tinsel {
@@ -60,8 +61,8 @@ static MOVER Movers[MAX_MOVERS]; // FIXME: Avoid non-const global vars
/**
* Called from ActorPalette(), normally once just after the beginning of time.
*/
-void StoreMoverPalette(PMOVER pMover, int startColour, int length) {
- pMover->startColour = startColour;
+void StoreMoverPalette(PMOVER pMover, int startColor, int length) {
+ pMover->startColor = startColor;
pMover->paletteLength = length;
}
@@ -88,7 +89,7 @@ static void CheckBrightness(PMOVER pMover) {
pMover->brightness--; // ramp down
DimPartPalette(BgPal(),
- pMover->startColour,
+ pMover->startColor,
pMover->paletteLength,
pMover->brightness);
}
@@ -107,7 +108,7 @@ void MoverBrightness(PMOVER pMover, int brightness) {
assert(BgPal());
// Do it all immediately
- DimPartPalette(BgPal(), pMover->startColour, pMover->paletteLength, brightness);
+ DimPartPalette(BgPal(), pMover->startColor, pMover->paletteLength, brightness);
// The actor is probably hidden at this point,
pMover->brightness = brightness;
@@ -924,7 +925,7 @@ void SaveMovers(SAVED_MOVER *sMoverInfo) {
if (TinselV2) {
sMoverInfo[i].bHidden = Movers[i].bHidden;
sMoverInfo[i].brightness = Movers[i].brightness;
- sMoverInfo[i].startColour = Movers[i].startColour;
+ sMoverInfo[i].startColor = Movers[i].startColor;
sMoverInfo[i].paletteLength = Movers[i].paletteLength;
}
diff --git a/engines/tinsel/rince.h b/engines/tinsel/rince.h
index 57eac00fa4..5d09a1e945 100644
--- a/engines/tinsel/rince.h
+++ b/engines/tinsel/rince.h
@@ -38,7 +38,7 @@ struct PROCESS;
enum NPS {NOT_IN, GOING_UP, GOING_DOWN, LEAVING, ENTERING};
-enum IND {NO_PROB, TRY_CENTRE, TRY_CORNER, TRY_NEXTCORNER};
+enum IND {NO_PROB, TRY_CENTER, TRY_CORNER, TRY_NEXTCORNER};
enum DIRECTION { LEFTREEL, RIGHTREEL, FORWARD, AWAY };
@@ -119,7 +119,7 @@ struct MOVER {
int32 zOverride;
bool bHidden;
int brightness; // Current brightness
- int startColour;
+ int startColor;
int paletteLength;
HPOLYGON hRpath; // Recent path
};
@@ -140,7 +140,7 @@ void MoverProcessCreate(int X, int Y, int id, PMOVER pMover);
enum AR_FUNCTION { AR_NORMAL, AR_PUSHREEL, AR_POPREEL, AR_WALKREEL };
-void StoreMoverPalette(PMOVER pMover, int startColour, int length);
+void StoreMoverPalette(PMOVER pMover, int startColor, int length);
void MoverBrightness(PMOVER pMover, int brightness);
@@ -204,7 +204,7 @@ struct SAVED_MOVER {
bool bActive;
bool bHidden;
int brightness;
- int startColour;
+ int startColor;
int paletteLength;
};
diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp
index c965666e84..b6935d41ab 100644
--- a/engines/tinsel/saveload.cpp
+++ b/engines/tinsel/saveload.cpp
@@ -36,6 +36,7 @@
#include "common/serializer.h"
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "gui/message.h"
@@ -77,9 +78,6 @@ SRSTATE SRstate = SR_IDLE;
// in DOS_DW.C
extern void syncSCdata(Common::Serializer &s);
-// in DOS_MAIN.C
-//char HardDriveLetter();
-
// in PCODE.C
extern void syncGlobInfo(Common::Serializer &s);
@@ -186,7 +184,7 @@ static void syncSavedMover(Common::Serializer &s, SAVED_MOVER &sm) {
s.syncAsByte(sm.bHidden);
s.syncAsSint32LE(sm.brightness);
- s.syncAsSint32LE(sm.startColour);
+ s.syncAsSint32LE(sm.startColor);
s.syncAsSint32LE(sm.paletteLength);
}
}
@@ -283,32 +281,6 @@ static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd) {
}
}
-
-/**
- * Called when saving a game to a new file.
- * Generates a new, unique, filename.
- */
-static char *NewName() {
- static char result[FNAMELEN]; // FIXME: Avoid non-const global vars
- int i;
- int ano = 1; // Allocated number
-
- while (1) {
- Common::String fname = _vm->getSavegameFilename(ano);
- strcpy(result, fname.c_str());
-
- for (i = 0; i < numSfiles; i++)
- if (!strcmp(savedFiles[i].name, result))
- break;
-
- if (i == numSfiles)
- break;
- ano++;
- }
-
- return result;
-}
-
/**
* Compare two TimeDate structs to see which one was earlier.
* Returns 0 if they are equal, a negative value if a is lower / first, and
@@ -498,19 +470,37 @@ static bool DoRestore() {
*/
static void DoSave() {
Common::OutSaveFile *f;
- const char *fname;
+ char tmpName[FNAMELEN];
// Next getList() must do its stuff again
NeedLoad = true;
- if (SaveSceneName == NULL)
- SaveSceneName = NewName();
+ if (SaveSceneName == NULL) {
+ // Generate a new unique save name
+ int i;
+ int ano = 1; // Allocated number
+
+ while (1) {
+ Common::String fname = _vm->getSavegameFilename(ano);
+ strcpy(tmpName, fname.c_str());
+
+ for (i = 0; i < numSfiles; i++)
+ if (!strcmp(savedFiles[i].name, tmpName))
+ break;
+
+ if (i == numSfiles)
+ break;
+ ano++;
+ }
+
+ SaveSceneName = tmpName;
+ }
+
+
if (SaveSceneDesc[0] == 0)
SaveSceneDesc = "unnamed";
- fname = SaveSceneName;
-
- f = _vm->getSaveFileMan()->openForSaving(fname);
+ f = _vm->getSaveFileMan()->openForSaving(SaveSceneName);
Common::Serializer s(0, f);
if (f == NULL)
@@ -537,12 +527,14 @@ static void DoSave() {
f->finalize();
delete f;
+ SaveSceneName = NULL; // Invalidate save name
return;
save_failure:
if (f) {
delete f;
- _vm->getSaveFileMan()->removeSavefile(fname);
+ _vm->getSaveFileMan()->removeSavefile(SaveSceneName);
+ SaveSceneName = NULL; // Invalidate save name
}
GUI::MessageDialog dialog("Failed to save game state to file.");
dialog.runModal();
diff --git a/engines/tinsel/savescn.cpp b/engines/tinsel/savescn.cpp
index a3fe393b79..aa359d281f 100644
--- a/engines/tinsel/savescn.cpp
+++ b/engines/tinsel/savescn.cpp
@@ -48,6 +48,8 @@
#include "tinsel/tinlib.h"
#include "tinsel/token.h"
+#include "common/textconsole.h"
+
namespace Tinsel {
//----------------- EXTERN FUNCTIONS --------------------
@@ -226,7 +228,7 @@ static void SortMAProcess(CORO_PARAM, const void *) {
}
ActorPalette(rsd->SavedMoverInfo[_ctx->i].actorID,
- rsd->SavedMoverInfo[_ctx->i].startColour, rsd->SavedMoverInfo[_ctx->i].paletteLength);
+ rsd->SavedMoverInfo[_ctx->i].startColor, rsd->SavedMoverInfo[_ctx->i].paletteLength);
if (rsd->SavedMoverInfo[_ctx->i].brightness != BOGUS_BRIGHTNESS)
ActorBrightness(rsd->SavedMoverInfo[_ctx->i].actorID, rsd->SavedMoverInfo[_ctx->i].brightness);
diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp
index 8f0f4771e3..b82bac32cc 100644
--- a/engines/tinsel/scene.cpp
+++ b/engines/tinsel/scene.cpp
@@ -51,6 +51,7 @@
#include "tinsel/sysvar.h"
#include "tinsel/token.h"
+#include "common/textconsole.h"
namespace Tinsel {
@@ -112,15 +113,11 @@ struct ENTRANCE_STRUC {
static bool ShowPosition = false; // Set when showpos() has been called
#endif
-SCNHANDLE newestScene = 0;
-
int sceneCtr = 0;
static int initialMyEscape;
static SCNHANDLE SceneHandle = 0; // Current scene handle - stored in case of Save_Scene()
-static bool bWatchingOut = false;
-
SCENE_STRUC tempStruc;
struct TP_INIT {
@@ -180,9 +177,6 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) {
_ctx->myEscape);
CORO_INVOKE_1(Interpret, _ctx->pic);
- if (_ctx->pInit->event == CLOSEDOWN || _ctx->pInit->event == LEAVE_T2)
- bWatchingOut = false;
-
CORO_END_CODE;
}
@@ -193,9 +187,6 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) {
void SendSceneTinselProcess(TINSEL_EVENT event) {
SCENE_STRUC *ss;
- if (event == CLOSEDOWN || event == LEAVE_T2)
- bWatchingOut = true;
-
if (SceneHandle != (SCNHANDLE)NULL) {
ss = (SCENE_STRUC *) FindChunk(SceneHandle, CHUNK_SCENE);
@@ -206,11 +197,8 @@ void SendSceneTinselProcess(TINSEL_EVENT event) {
init.hTinselCode = ss->hSceneScript;
g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init));
- } else if (event == CLOSEDOWN)
- bWatchingOut = false;
+ }
}
- else if (event == CLOSEDOWN)
- bWatchingOut = false;
}
@@ -249,9 +237,6 @@ static void LoadScene(SCNHANDLE scene, int entry) {
assert(ss != NULL);
if (TinselV2) {
- // Handle to scene description
- newestScene = FROM_LE_32(ss->hSceneDesc);
-
// Music stuff
char *cptr = (char *)FindChunk(scene, CHUNK_MUSIC_FILENAME);
assert(cptr);
@@ -397,7 +382,7 @@ void PrimeBackground() {
// structure for background
static const BACKGND backgnd = {
- BLACK, // sky colour
+ BLACK, // sky color
Common::Point(0, 0), // initial world pos
Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), // scroll limits
0, // no background update process
diff --git a/engines/tinsel/sched.cpp b/engines/tinsel/sched.cpp
index 427e28826f..37c04abd22 100644
--- a/engines/tinsel/sched.cpp
+++ b/engines/tinsel/sched.cpp
@@ -30,6 +30,7 @@
#include "tinsel/polygons.h"
#include "tinsel/sched.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Tinsel {
diff --git a/engines/tinsel/scn.cpp b/engines/tinsel/scn.cpp
index 17ae7c8687..20d75b6b93 100644
--- a/engines/tinsel/scn.cpp
+++ b/engines/tinsel/scn.cpp
@@ -24,9 +24,6 @@
* A (some would say very) small collection of utility functions.
*/
-#include "common/endian.h"
-#include "common/util.h"
-
#include "tinsel/dw.h"
#include "tinsel/film.h"
#include "tinsel/handle.h"
diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp
index 5fc2820986..ec42ca5da4 100644
--- a/engines/tinsel/sound.cpp
+++ b/engines/tinsel/sound.cpp
@@ -26,6 +26,7 @@
#include "tinsel/sound.h"
+#include "tinsel/adpcm.h"
#include "tinsel/dw.h"
#include "tinsel/config.h"
#include "tinsel/music.h"
@@ -34,9 +35,7 @@
#include "tinsel/sysvar.h"
#include "tinsel/background.h"
-#include "common/config-manager.h"
#include "common/endian.h"
-#include "common/file.h"
#include "common/memstream.h"
#include "common/system.h"
@@ -130,13 +129,9 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound
error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage));
// FIXME: Should set this in a different place ;)
- bool mute = false;
- if (ConfMan.hasKey("mute"))
- mute = ConfMan.getBool("mute");
-
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : _vm->_config->_soundVolume);
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _vm->_config->_soundVolume);
//_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic);
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : _vm->_config->_voiceVolume);
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _vm->_config->_voiceVolume);
Audio::AudioStream *sampleStream = 0;
@@ -319,18 +314,14 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p
#endif
break;
default:
- sampleStream = Audio::makeADPCMStream(compressedStream, DisposeAfterUse::YES, sampleLen, Audio::kADPCMTinsel6, 22050, 1, 24);
+ sampleStream = new Tinsel6_ADPCMStream(compressedStream, DisposeAfterUse::YES, sampleLen, 22050, 1, 24);
break;
}
// FIXME: Should set this in a different place ;)
- bool mute = false;
- if (ConfMan.hasKey("mute"))
- mute = ConfMan.getBool("mute");
-
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : _vm->_config->_soundVolume);
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _vm->_config->_soundVolume);
//_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic);
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : _vm->_config->_voiceVolume);
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _vm->_config->_voiceVolume);
curChan->sampleNum = id;
curChan->subSample = sub;
@@ -363,8 +354,8 @@ bool SoundManager::offscreenChecks(int x, int &y) {
if (x == -1)
return true;
- // convert x to offset from screen centre
- x -= PlayfieldGetCentreX(FIELD_WORLD);
+ // convert x to offset from screen center
+ x -= PlayfieldGetCenterX(FIELD_WORLD);
if (x < -SCREEN_WIDTH || x > SCREEN_WIDTH) {
// A long way offscreen, ignore it
@@ -384,7 +375,7 @@ int8 SoundManager::getPan(int x) {
if (x == -1)
return 0;
- x -= PlayfieldGetCentreX(FIELD_WORLD);
+ x -= PlayfieldGetCenterX(FIELD_WORLD);
if (x == 0)
return 0;
@@ -530,17 +521,17 @@ void SoundManager::openSampleFiles() {
// Detect format of soundfile by looking at 1st sample-index
switch (TO_BE_32(_sampleIndex[0])) {
- case MKID_BE('MP3 '):
+ case MKTAG('M','P','3',' '):
debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected MP3 sound-data");
_soundMode = kMP3Mode;
break;
- case MKID_BE('OGG '):
+ case MKTAG('O','G','G',' '):
debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected OGG sound-data");
_soundMode = kVorbisMode;
break;
- case MKID_BE('FLAC'):
+ case MKTAG('F','L','A','C'):
debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected FLAC sound-data");
_soundMode = kFLACMode;
break;
diff --git a/engines/tinsel/strres.cpp b/engines/tinsel/strres.cpp
index aa303a5391..2dc0e833d1 100644
--- a/engines/tinsel/strres.cpp
+++ b/engines/tinsel/strres.cpp
@@ -31,6 +31,7 @@
#include "tinsel/scn.h"
#include "common/file.h"
#include "common/endian.h"
+#include "common/textconsole.h"
#include "gui/message.h"
diff --git a/engines/tinsel/sysvar.cpp b/engines/tinsel/sysvar.cpp
index 7003d34feb..ad795fd219 100644
--- a/engines/tinsel/sysvar.cpp
+++ b/engines/tinsel/sysvar.cpp
@@ -31,6 +31,8 @@
#include "tinsel/sysvar.h"
#include "tinsel/tinsel.h"
+#include "common/textconsole.h"
+
namespace Tinsel {
// Return for SYS_Platform
@@ -77,7 +79,7 @@ static int systemVars[SV_TOPVALID] = {
2, // Speech Delay
2, // Music dim factor
- 0, // if set, default actor's text colour gets poked in here
+ 0, // if set, default actor's text color gets poked in here
0, // user 1
0, // user 2
@@ -103,7 +105,7 @@ static int systemVars[SV_TOPVALID] = {
0, // ISV_GHOST_ACTOR
0, // ISV_GHOST_BASE
- 0 // ISV_GHOST_COLOUR
+ 0 // ISV_GHOST_COLOR
};
static SCNHANDLE systemStrings[SS_MAX_VALID]; // FIXME: Avoid non-const global vars
diff --git a/engines/tinsel/sysvar.h b/engines/tinsel/sysvar.h
index e407e6ffa3..4cdb1364b4 100644
--- a/engines/tinsel/sysvar.h
+++ b/engines/tinsel/sysvar.h
@@ -60,7 +60,7 @@ typedef enum { SV_DEFAULT_INV,
SV_SPEECHDELAY, // Delay 'twixt text/animation and sample
SV_MUSICDIMFACTOR, // dimVolume = volume - volume/SV_MDF
- SV_TAGCOLOUR, // if set, default actor's text colour gets poked in here
+ SV_TAGCOLOR, // if set, default actor's text color gets poked in here
SV_USER1,
SV_USER2,
@@ -85,7 +85,7 @@ typedef enum { SV_DEFAULT_INV,
ISV_NO_BLOCKING,
ISV_GHOST_ACTOR,
ISV_GHOST_BASE,
- ISV_GHOST_COLOUR,
+ ISV_GHOST_COLOR,
SV_TOPVALID } SYSVARS;
diff --git a/engines/tinsel/text.cpp b/engines/tinsel/text.cpp
index d2939281eb..3652d6ed3e 100644
--- a/engines/tinsel/text.cpp
+++ b/engines/tinsel/text.cpp
@@ -78,8 +78,8 @@ int StringLengthPix(char *szStr, const FONT *pFont) {
* @param mode Mode flags for the string
*/
int JustifyText(char *szStr, int xPos, const FONT *pFont, int mode) {
- if (mode & TXT_CENTRE) {
- // centre justify the text
+ if (mode & TXT_CENTER) {
+ // center justify the text
// adjust x positioning by half the length of line in pixels
xPos -= StringLengthPix(szStr, pFont) / 2;
@@ -100,14 +100,14 @@ int JustifyText(char *szStr, int xPos, const FONT *pFont, int mode) {
* of the list is returned.
* @param pList Object list to add text to
* @param szStr String to output
- * @param colour Colour for monochrome text
+ * @param color Color for monochrome text
* @param xPos X position of string
* @param yPos Y position of string
* @param hFont Which font to use
* @param mode Mode flags for the string
* @param sleepTime Sleep time between each character (if non-zero)
*/
-OBJECT *ObjectTextOut(OBJECT *pList, char *szStr, int colour,
+OBJECT *ObjectTextOut(OBJECT *pList, char *szStr, int color,
int xPos, int yPos, SCNHANDLE hFont, int mode, int sleepTime) {
int xJustify; // x position of text after justification
int yOffset; // offset to next line of text
@@ -183,8 +183,8 @@ OBJECT *ObjectTextOut(OBJECT *pList, char *szStr, int colour,
if (mode & TXT_ABSOLUTE)
pChar->flags |= DMA_ABS;
- // set characters colour - only effective for mono fonts
- pChar->constant = colour;
+ // set characters color - only effective for mono fonts
+ pChar->constant = color;
// get Y animation offset
GetAniOffset(hImg, pChar->flags, &aniX, &aniY);
diff --git a/engines/tinsel/text.h b/engines/tinsel/text.h
index a849e286ec..ea804f58d7 100644
--- a/engines/tinsel/text.h
+++ b/engines/tinsel/text.h
@@ -34,7 +34,7 @@ namespace Tinsel {
/** text mode flags - defaults to left justify */
enum {
- TXT_CENTRE = 0x0001, ///< centre justify text
+ TXT_CENTER = 0x0001, ///< center justify text
TXT_RIGHT = 0x0002, ///< right justify text
TXT_SHADOW = 0x0004, ///< shadow each character
TXT_ABSOLUTE = 0x0008 ///< position of text is absolute (only for object text)
@@ -72,7 +72,7 @@ struct FONT {
struct TEXTOUT {
OBJECT *pList; ///< object list to add text to
char *szStr; ///< string to output
- int colour; ///< colour for monochrome text
+ int color; ///< color for monochrome text
int xPos; ///< x position of string
int yPos; ///< y position of string
SCNHANDLE hFont; ///< which font to use
@@ -91,14 +91,14 @@ struct TEXTOUT {
* of the list is returned.
* @param pList object list to add text to
* @param szStr string to output
- * @param colour colour for monochrome text
+ * @param color color for monochrome text
* @param xPos x position of string
* @param yPos y position of string
* @param hFont which font to use
* @param mode mode flags for the string
* @param sleepTime Sleep time between each character (if non-zero)
*/
-OBJECT *ObjectTextOut(OBJECT *pList, char *szStr, int colour,
+OBJECT *ObjectTextOut(OBJECT *pList, char *szStr, int color,
int xPos, int yPos, SCNHANDLE hFont, int mode, int sleepTime = 0);
OBJECT *ObjectTextOutIndirect( // output a string of text
diff --git a/engines/tinsel/timers.cpp b/engines/tinsel/timers.cpp
index 5f15cd9d3b..c1a4cd0ff5 100644
--- a/engines/tinsel/timers.cpp
+++ b/engines/tinsel/timers.cpp
@@ -31,7 +31,7 @@
#include "tinsel/timers.h"
#include "tinsel/dw.h"
#include "common/serializer.h"
-
+#include "common/textconsole.h"
#include "common/system.h"
namespace Tinsel {
diff --git a/engines/tinsel/timers.h b/engines/tinsel/timers.h
index 022604b662..1456d9a1d5 100644
--- a/engines/tinsel/timers.h
+++ b/engines/tinsel/timers.h
@@ -31,7 +31,7 @@
#include "tinsel/dw.h"
namespace Common {
- class Serializer;
+class Serializer;
}
namespace Tinsel {
diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp
index 40418dcc43..afd409ce27 100644
--- a/engines/tinsel/tinlib.cpp
+++ b/engines/tinsel/tinlib.cpp
@@ -70,6 +70,7 @@
#include "tinsel/tinsel.h"
#include "tinsel/token.h"
+#include "common/textconsole.h"
namespace Tinsel {
@@ -84,7 +85,7 @@ extern bool bNoPause;
// In DOS_MAIN.C
// TODO/FIXME: From dos_main.c: "Only used on PSX so far"
-int clRunMode = 0;
+//int clRunMode = 0;
//----------------- EXTERNAL FUNCTIONS ---------------------
@@ -426,11 +427,11 @@ static void ScrollMonitorProcess(CORO_PARAM, const void *param) {
/**
* NOT A LIBRARY FUNCTION
*
- * Poke supplied colour into the DAC queue.
+ * Poke supplied color into the DAC queue.
*/
void SetTextPal(COLORREF col) {
- SetTalkColourRef(col);
- UpdateDACqueue(TalkColour(), col);
+ SetTalkColorRef(col);
+ UpdateDACqueue(TalkColor(), col);
}
/**
@@ -522,7 +523,7 @@ void TinGetVersion(WHICH_VER which, char *buffer, int length) {
/**
* Set actor's attributes.
- * - currently only the text colour.
+ * - currently only the text color.
*/
static void ActorAttr(int actor, int r1, int g1, int b1) {
storeActorAttr(actor, r1, g1, b1);
@@ -553,11 +554,11 @@ static int ActorDirection(int actor) {
/**
* Set actor's palette details for path brightnesses
*/
-void ActorPalette(int actor, int startColour, int length) {
+void ActorPalette(int actor, int startColor, int length) {
PMOVER pMover = GetMover(actor);
assert(pMover);
- StoreMoverPalette(pMover, startColour, length);
+ StoreMoverPalette(pMover, startColor, length);
}
/**
@@ -568,10 +569,10 @@ static void ActorPriority(int actor, int zFactor) {
}
/**
- * Set actor's text colour.
+ * Set actor's text color.
*/
-static void ActorRGB(int actor, COLORREF colour) {
- SetActorRGB(actor, colour);
+static void ActorRGB(int actor, COLORREF color) {
+ SetActorRGB(actor, color);
}
/**
@@ -1196,9 +1197,9 @@ static int GetInvLimit(int invno) {
/**
* Ghost
*/
-static void Ghost(int actor, int tColour, int tPalOffset) {
+static void Ghost(int actor, int tColor, int tPalOffset) {
SetSysVar(ISV_GHOST_ACTOR, actor);
- SetSysVar(ISV_GHOST_COLOUR, tColour);
+ SetSysVar(ISV_GHOST_COLOR, tColor);
SetSysVar(ISV_GHOST_BASE, tPalOffset);
CreateGhostPalette(BgPal());
}
@@ -1952,7 +1953,7 @@ static void Print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, bool bSust
PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset);
_ctx->pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS),
TextBufferAddr(), 0, x - Loffset, y - Toffset, GetTagFontHandle(),
- TXT_CENTRE, 0);
+ TXT_CENTER, 0);
assert(_ctx->pText);
// Adjust x, y, or z if necessary
@@ -1965,7 +1966,7 @@ static void Print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, bool bSust
PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset);
_ctx->pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
0, x - Loffset, y - Toffset,
- TinselV2 ? GetTagFontHandle() : GetTalkFontHandle(), TXT_CENTRE);
+ TinselV2 ? GetTagFontHandle() : GetTalkFontHandle(), TXT_CENTER);
assert(_ctx->pText); // string produced NULL text
if (IsTopWindow())
MultiSetZPosition(_ctx->pText, Z_TOPW_TEXT);
@@ -2128,7 +2129,7 @@ static void PrintObj(CORO_PARAM, const SCNHANDLE hText, const INV_OBJECT *pinvo,
LoadStringRes(hText, TextBufferAddr(), TBUFSZ);
_ctx->pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
- 0, _ctx->textx, _ctx->texty, GetTagFontHandle(), TXT_CENTRE);
+ 0, _ctx->textx, _ctx->texty, GetTagFontHandle(), TXT_CENTER);
assert(_ctx->pText); // PrintObj() string produced NULL text
MultiSetZPosition(_ctx->pText, Z_INV_ITEXT);
@@ -2181,7 +2182,7 @@ static void PrintObj(CORO_PARAM, const SCNHANDLE hText, const INV_OBJECT *pinvo,
LoadStringRes(hText, TextBufferAddr(), TBUFSZ);
_ctx->pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS),
TextBufferAddr(), 0, _ctx->textx, _ctx->texty, GetTagFontHandle(),
- TXT_CENTRE, 0);
+ TXT_CENTER, 0);
assert(_ctx->pText);
KeepOnScreen(_ctx->pText, &_ctx->textx, &_ctx->texty);
@@ -2297,7 +2298,7 @@ static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *
// Re-display in the same place
LoadStringRes(text, TextBufferAddr(), TBUFSZ);
pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
- 0, textx, texty, GetTagFontHandle(), TXT_CENTRE);
+ 0, textx, texty, GetTagFontHandle(), TXT_CENTER);
assert(pText); // PrintObj() string produced NULL text
MultiSetZPosition(pText, Z_INV_ITEXT);
}
@@ -2490,7 +2491,7 @@ void ResumeLastGame() {
* Returns the current run mode
*/
static int RunMode() {
- return clRunMode;
+ return 0; //clRunMode;
}
/**
@@ -3367,7 +3368,7 @@ static void TalkOrSay(CORO_PARAM, SPEECH_TYPE speechType, SCNHANDLE hText, int x
_ctx->pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS),
TextBufferAddr(), 0, _ctx->x - _ctx->Loffset, _ctx->y - _ctx->Toffset,
- GetTalkFontHandle(), TXT_CENTRE);
+ GetTalkFontHandle(), TXT_CENTER);
assert(_ctx->pText); // talk() string produced NULL text;
if (IsTopWindow())
@@ -3595,12 +3596,12 @@ static void TalkPaletteIndex(unsigned index) {
/**
* Set talk font's palette entry.
*/
-static void TalkRGB(COLORREF colour, int myescEvent) {
+static void TalkRGB(COLORREF color, int myescEvent) {
// Don't do it if it's not wanted
if (myescEvent && myescEvent != GetEscEvents())
return;
- SetTextPal(colour);
+ SetTextPal(color);
}
/**
diff --git a/engines/tinsel/tinlib.h b/engines/tinsel/tinlib.h
index 11e59f380d..7bd2a19d55 100644
--- a/engines/tinsel/tinlib.h
+++ b/engines/tinsel/tinlib.h
@@ -48,7 +48,7 @@ void TinGetVersion(WHICH_VER which, char *buffer, int length);
// Library functions in TINLIB.C
void ActorBrightness(int actor, int brightness);
-void ActorPalette(int actor, int startColour, int length);
+void ActorPalette(int actor, int startColor, int length);
void Control(int param);
void HookScene(SCNHANDLE scene, int entrance, int transition);
void NewScene(CORO_PARAM, SCNHANDLE scene, int entrance, int transition);
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 23335539d1..20d4f1d31a 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -29,22 +29,14 @@
#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/keyboard.h"
-#include "common/file.h"
#include "common/fs.h"
-#include "common/savefile.h"
#include "common/config-manager.h"
#include "common/serializer.h"
-#include "common/stream.h"
#include "backends/audiocd/audiocd.h"
#include "engines/util.h"
-#include "graphics/cursorman.h"
-
-#include "base/plugins.h"
-#include "base/version.h"
-
#include "tinsel/actors.h"
#include "tinsel/background.h"
#include "tinsel/bmv.h"
@@ -218,14 +210,17 @@ void KeyboardProcess(CORO_PARAM, const void *) {
continue;
#endif
+ case Common::KEYCODE_1:
case Common::KEYCODE_F1:
// Options dialog
ProcessKeyEvent(PLR_MENU);
continue;
+ case Common::KEYCODE_5:
case Common::KEYCODE_F5:
// Save game
ProcessKeyEvent(PLR_SAVE);
continue;
+ case Common::KEYCODE_7:
case Common::KEYCODE_F7:
// Load game
ProcessKeyEvent(PLR_LOAD);
@@ -856,25 +851,8 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
if (cd_num >= 0)
_system->getAudioCDManager()->openCD(cd_num);
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB);
-
- _driver = MidiDriver::createMidi(dev);
- if (native_mt32)
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
- _midiMusic = new MidiMusicPlayer(_driver);
+ _midiMusic = new MidiMusicPlayer();
_pcmMusic = new PCMMusicPlayer();
- //_midiMusic->setNativeMT32(native_mt32);
- //_midiMusic->setAdLib(adlib);
-
- if (native_mt32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
-
- _musicVolume = ConfMan.getInt("music_volume");
_sound = new SoundManager(this);
@@ -896,7 +874,6 @@ TinselEngine::~TinselEngine() {
delete _midiMusic;
delete _pcmMusic;
delete _console;
- delete _driver;
_screenSurface.free();
FreeSaveScenes();
FreeTextBuffer();
@@ -926,10 +903,10 @@ Common::Error TinselEngine::run() {
#else
initGraphics(640, 432, true);
#endif
- _screenSurface.create(640, 432, 1);
+ _screenSurface.create(640, 432, Graphics::PixelFormat::createFormatCLUT8());
} else {
initGraphics(320, 200, false);
- _screenSurface.create(320, 200, 1);
+ _screenSurface.create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
}
g_eventRec.registerRandomSource(_random, "tinsel");
@@ -987,7 +964,7 @@ Common::Error TinselEngine::run() {
// errors when loading the save state.
if (ConfMan.hasKey("save_slot")) {
- if (loadGameState(ConfMan.getInt("save_slot")) == Common::kNoError)
+ if (loadGameState(ConfMan.getInt("save_slot")).getCode() == Common::kNoError)
loadingFromGMM = true;
}
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index 009f6fe26d..35ea43074c 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -125,8 +125,8 @@ typedef bool (*KEYFPTR)(const Common::KeyState &);
#define SCREEN_WIDTH (_vm->screen().w) // PC screen dimensions
#define SCREEN_HEIGHT (_vm->screen().h)
-#define SCRN_CENTRE_X ((SCREEN_WIDTH - 1) / 2) // screen centre x
-#define SCRN_CENTRE_Y ((SCREEN_HEIGHT - 1) / 2) // screen centre y
+#define SCRN_CENTER_X ((SCREEN_WIDTH - 1) / 2) // screen center x
+#define SCRN_CENTER_Y ((SCREEN_HEIGHT - 1) / 2) // screen center y
#define UNUSED_LINES 48
#define EXTRA_UNUSED_LINES 3
//#define SCREEN_BOX_HEIGHT1 (SCREEN_HEIGHT - UNUSED_LINES)
@@ -219,9 +219,6 @@ public:
RectList _clipRects;
private:
- //MidiMusicPlayer *_midiMusic;
- int _musicVolume;
-
void NextGameCycle();
void CreateConstProcesses();
void RestartGame();
diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp
index 2e63d89f37..856acbd986 100644
--- a/engines/toon/anim.cpp
+++ b/engines/toon/anim.cpp
@@ -23,6 +23,9 @@
*
*/
+#include "common/debug.h"
+#include "common/rect.h"
+
#include "toon/anim.h"
#include "toon/toon.h"
#include "toon/tools.h"
@@ -99,7 +102,7 @@ bool Animation::loadAnimation(Common::String file) {
_frames[e]._data = new uint8[decompressedSize];
if (compressedSize < decompressedSize) {
decompressLZSS(imageData, _frames[e]._data, decompressedSize);
- } else {
+ } else {
memcpy(_frames[e]._data, imageData, compressedSize);
}
}
@@ -151,6 +154,8 @@ void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int32 xx, int
int32 offsX = 0;
int32 offsY = 0;
+ _vm->addDirtyRect(xx + _x1 + _frames[frame]._x1, yy + _y1 + _frames[frame]._y1, xx + rectX + _x1 + _frames[frame]._x1 , yy + rectY + _y1 + _frames[frame]._y1);
+
if (xx + _x1 + _frames[frame]._x1 < 0) {
offsX = -(xx + _x1 + _frames[frame]._x1);
}
@@ -212,14 +217,14 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram
int32 finalWidth = rectX * scale / 1024;
int32 finalHeight = rectY * scale / 1024;
- // compute final x1,y1,x2,y2
+ // compute final x1, y1, x2, y2
int32 xx1 = xx + _x1 + _frames[frame]._x1 * scale / 1024;
int32 yy1 = yy + _y1 + _frames[frame]._y1 * scale / 1024;
int32 xx2 = xx1 + finalWidth;
int32 yy2 = yy1 + finalHeight;
int32 w = _frames[frame]._x2 - _frames[frame]._x1;
-// Strangerke - Commented (not used)
-// int32 h = _frames[frame]._y2 - _frames[frame]._y1;
+
+ _vm->addDirtyRect(xx1, yy1, xx2, yy2);
int32 destPitch = surface.pitch;
int32 destPitchMask = mask->getWidth();
@@ -442,7 +447,6 @@ AnimationInstance::AnimationInstance(ToonEngine *vm, AnimationInstanceType type)
_layerZ = 0;
}
-
void AnimationInstance::render() {
debugC(5, kDebugAnim, "render()");
if (_visible && _animation) {
@@ -574,7 +578,7 @@ void AnimationInstance::getRect(int32 *x1, int32 *y1, int32 *x2, int32 *y2) cons
int32 finalWidth = rectX * _scale / 1024;
int32 finalHeight = rectY * _scale / 1024;
- // compute final x1,y1,x2,y2
+ // compute final x1, y1, x2, y2
*x1 = _x + _animation->_x1 + _animation->_frames[_currentFrame]._x1 * _scale / 1024;
*y1 = _y + _animation->_y1 + _animation->_frames[_currentFrame]._y1 * _scale / 1024;
*x2 = *x1 + finalWidth;
@@ -604,7 +608,7 @@ void AnimationInstance::setZ(int32 z, bool relative) {
void AnimationInstance::setLayerZ(int32 z) {
_layerZ = z;
- if (_vm->getAnimationManager()->hasInstance(this))
+ if (_vm->getAnimationManager()->hasInstance(this))
_vm->getAnimationManager()->updateInstance(this);
}
@@ -665,8 +669,6 @@ void AnimationInstance::load(Common::ReadStream *stream) {
_useMask = stream->readSint32LE();
}
-
-
void AnimationInstance::setLooping(bool enable) {
debugC(6, kDebugAnim, "setLooping(%d)", (enable) ? 1 : 0);
_looping = enable;
@@ -682,7 +684,7 @@ AnimationManager::AnimationManager(ToonEngine *vm) : _vm(vm) {
bool AnimationManager::hasInstance(AnimationInstance* instance) {
for (uint32 i = 0; i < _instances.size(); i++) {
- if(_instances[i] == instance)
+ if(_instances[i] == instance)
return true;
}
return false;
@@ -698,12 +700,12 @@ void AnimationManager::addInstance(AnimationInstance *instance) {
// if the instance already exists, we skip the add
for (uint32 i = 0; i < _instances.size(); i++) {
- if(_instances[i] == instance)
+ if(_instances[i] == instance)
return;
}
-
+
int found = -1;
-
+
// here we now do an ordered insert (closer to the original game)
for (uint32 i = 0; i < _instances.size(); i++) {
if (_instances[i]->getLayerZ() >= instance->getLayerZ()) {
@@ -717,7 +719,6 @@ void AnimationManager::addInstance(AnimationInstance *instance) {
} else {
_instances.insert_at(found, instance);
}
-
}
void AnimationManager::removeInstance(AnimationInstance *instance) {
diff --git a/engines/toon/anim.h b/engines/toon/anim.h
index d7f64ab687..dfb6842b0e 100644
--- a/engines/toon/anim.h
+++ b/engines/toon/anim.h
@@ -161,7 +161,7 @@ public:
AnimationInstance *createNewInstance(AnimationInstanceType type);
void addInstance(AnimationInstance *instance);
void removeInstance(AnimationInstance *instance);
- void updateInstance(AnimationInstance* instance);
+ void updateInstance(AnimationInstance* instance);
void removeAllInstances(AnimationInstanceType type);
void render();
void update(int32 timeIncrement);
diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp
index e5e5b85832..026450d3c9 100644
--- a/engines/toon/audio.cpp
+++ b/engines/toon/audio.cpp
@@ -23,32 +23,20 @@
*
*/
+#include "common/debug.h"
+
#include "toon/audio.h"
#include "common/memstream.h"
#include "common/substream.h"
+#include "audio/decoders/adpcm_intern.h"
namespace Toon {
-static int ADPCM_index[8] = {
- -1, -1, -1, -1, 2 , 4 , 6 , 8
-};
-static int ADPCM_table[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
- 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
- 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
- 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
- 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
- 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
-};
-
AudioManager::AudioManager(ToonEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
for (int32 i = 0; i < 16; i++)
_channels[i] = NULL;
- for (int32 i = 0; i < 4; i++)
+ for (int32 i = 0; i < 4; i++)
_audioPacks[i] = NULL;
for (int32 i = 0; i < 4; i++) {
@@ -63,6 +51,8 @@ AudioManager::AudioManager(ToonEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixe
_voiceMuted = false;
_musicMuted = false;
_sfxMuted = false;
+
+ _currentMusicChannel = 0;
}
AudioManager::~AudioManager(void) {
@@ -113,24 +103,23 @@ void AudioManager::playMusic(Common::String dir, Common::String music) {
return;
// see what channel to take
- if (_channels[0] && _channels[0]->isPlaying() && _channels[1] && _channels[1]->isPlaying()) {
- // take the one that is fading
- if (_channels[0]->isFading()) {
- _channels[0]->stop(false);
- _channels[1]->stop(true);
- _currentMusicChannel = 0;
- } else {
- _channels[1]->stop(false);
- _channels[0]->stop(true);
- _currentMusicChannel = 1;
+ // if the current channel didn't really start. reuse this one
+ if (_channels[_currentMusicChannel] && _channels[_currentMusicChannel]->isPlaying()) {
+ if (_channels[_currentMusicChannel]->getPlayedSampleCount() < 500) {
+ _channels[_currentMusicChannel]->stop(false);
+ _currentMusicChannel = 1 - _currentMusicChannel;
+ }
+ else
+ {
+ _channels[_currentMusicChannel]->stop(true);
}
- } else if (_channels[0] && _channels[0]->isPlaying()) {
- _channels[0]->stop(true);
- _currentMusicChannel = 1;
- } else {
- if (_channels[1] && _channels[1]->isPlaying())
- _channels[1]->stop(true);
- _currentMusicChannel = 0;
+ }
+ // go to the next channel
+ _currentMusicChannel = 1 - _currentMusicChannel;
+
+ // if it's already playing.. stop it quickly (no fade)
+ if (_channels[_currentMusicChannel] && _channels[_currentMusicChannel]->isPlaying()) {
+ _channels[_currentMusicChannel]->stop(false);
}
// no need to delete instance here it will automatically deleted by the mixer is done with it
@@ -208,7 +197,6 @@ void AudioManager::stopCurrentVoice() {
_channels[2]->stop(false);
}
-
void AudioManager::closeAudioPack(int32 id) {
delete _audioPacks[id];
_audioPacks[id] = NULL;
@@ -261,6 +249,7 @@ AudioStreamInstance::AudioStreamInstance(AudioManager *man, Audio::Mixer *mixer,
_looping = looping;
_musicAttenuation = 1000;
_deleteFileStream = deleteFileStreamAtEnd;
+ _playedSamples = 0;
// preload one packet
if (_totalSize > 0) {
@@ -286,7 +275,7 @@ AudioStreamInstance::~AudioStreamInstance() {
int AudioStreamInstance::readBuffer(int16 *buffer, const int numSamples) {
debugC(5, kDebugAudio, "readBuffer(buffer, %d)", numSamples);
- if(_stopped)
+ if(_stopped)
return 0;
handleFade(numSamples);
@@ -309,6 +298,8 @@ int AudioStreamInstance::readBuffer(int16 *buffer, const int numSamples) {
_bufferOffset += leftSamples;
}
+ _playedSamples += numSamples;
+
return numSamples;
}
@@ -369,7 +360,7 @@ void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize
int32 v31 = v30 & 0x8;
int32 v32 = v30 & 0x7;
- int32 v33 = ADPCM_table[v19];
+ int32 v33 = Audio::Ima_ADPCMStream::_imaTable[v19];
int32 v34 = v33 >> 3;
if (v32 & 4)
v34 += v33;
@@ -380,12 +371,8 @@ void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize
if (v32 & 1)
v34 += v33 >> 2;
- v19 += ADPCM_index[v32];
- if (v19 < 0)
- v19 = 0;
-
- if (v19 > 88)
- v19 = 88;
+ v19 += Audio::ADPCMStream::_stepAdjustTable[v32];
+ v19 = CLIP<int32>(v19, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1);
if (v31)
v18 -= v34;
@@ -423,7 +410,7 @@ void AudioStreamInstance::handleFade(int32 numSamples) {
debugC(5, kDebugAudio, "handleFade(%d)", numSamples);
// Fading enabled only for music
- if (_soundType != Audio::Mixer::kMusicSoundType)
+ if (_soundType != Audio::Mixer::kMusicSoundType)
return;
int32 finalVolume = _volume;
@@ -457,7 +444,7 @@ void AudioStreamInstance::handleFade(int32 numSamples) {
_musicAttenuation = 250;
} else {
_musicAttenuation += numSamples >> 5;
- if (_musicAttenuation > 1000)
+ if (_musicAttenuation > 1000)
_musicAttenuation = 1000;
}
@@ -468,9 +455,11 @@ void AudioStreamInstance::stop(bool fade /*= false*/) {
debugC(1, kDebugAudio, "stop(%d)", (fade) ? 1 : 0);
if (fade) {
- _fadingIn = false;
- _fadingOut = true;
- _fadeTime = 0;
+ if (!_fadingOut) {
+ _fadingIn = false;
+ _fadingOut = true;
+ _fadeTime = 0;
+ }
} else {
stopNow();
}
@@ -551,7 +540,7 @@ void AudioManager::startAmbientSFX(int32 id, int32 delay, int32 mode, int32 volu
}
}
- if (found < 0)
+ if (found < 0)
return;
_ambientSFXs[found]._lastTimer = _vm->getOldMilli() - 1;
@@ -610,13 +599,14 @@ void AudioManager::killAllAmbientSFX()
void AudioManager::updateAmbientSFX()
{
- if (_vm->getMoviePlayer()->isPlaying()) return;
+ if (_vm->getMoviePlayer()->isPlaying())
+ return;
for (int32 i = 0; i < 4; i++) {
AudioAmbientSFX* ambient = &_ambientSFXs[i];
if (ambient->_enabled && (ambient->_channel < 0 || !(_channels[ambient->_channel] && _channels[ambient->_channel]->isPlaying()))) {
if(ambient->_mode == 1) {
- if (_vm->randRange(0, 32767) < ambient->_delay) {
+ if (_vm->randRange(0, 32767) < ambient->_delay) {
ambient->_channel = playSFX(ambient->_id, ambient->_volume, false);
}
} else {
@@ -629,6 +619,5 @@ void AudioManager::updateAmbientSFX()
}
}
-
} // End of namespace Toon
diff --git a/engines/toon/audio.h b/engines/toon/audio.h
index 7c1eedfee9..5feae9c5a1 100644
--- a/engines/toon/audio.h
+++ b/engines/toon/audio.h
@@ -52,6 +52,10 @@ public:
return _fadingIn || _fadingOut;
}
+ int32 getPlayedSampleCount() {
+ return _playedSamples;
+ }
+
void setVolume(int32 volume);
protected:
int readBuffer(int16 *buffer, const int numSamples);
@@ -93,6 +97,7 @@ protected:
int32 _volume;
int32 _musicAttenuation;
bool _deleteFileStream;
+ int32 _playedSamples;
};
class AudioStreamPackage {
@@ -133,14 +138,14 @@ public:
void playVoice(int32 id, bool genericVoice);
int32 playSFX(int32 id, int volume, bool genericSFX);
void stopCurrentVoice();
- void stopAllSfxs();
+ void stopAllSfxs();
void setMusicVolume(int32 volume);
void stopMusic();
void muteVoice(bool mute);
void muteMusic(bool mute);
void muteSfx(bool mute);
bool isVoiceMuted() { return _voiceMuted; }
- bool isMusicMuted() { return _musicMuted; }
+ bool isMusicMuted() { return _musicMuted; }
bool isSfxMuted() { return _sfxMuted; }
void startAmbientSFX(int32 id, int32 delay, int32 mode, int32 volume);
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index f1f246e549..29a61ffd78 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -23,6 +23,9 @@
*
*/
+#include "common/debug.h"
+#include "common/system.h"
+
#include "toon/character.h"
#include "toon/drew.h"
#include "toon/flux.h"
@@ -64,6 +67,7 @@ Character::Character(ToonEngine *vm) : _vm(vm) {
_lastWalkTime = 0;
_numPixelToWalk = 0;
_nextIdleTime = _vm->getSystem()->getMillis() + (_vm->randRange(0, 600) + 300) * _vm->getTickLength();
+ _lineToSayId = 0;
}
Character::~Character(void) {
@@ -104,7 +108,7 @@ void Character::setFacing(int32 facing) {
_lastWalkTime = _vm->getSystem()->getMillis();
if ((_facing - facing + 8) % 8 > (facing - _facing + 8) % 8)
dir = 1;
- else
+ else
dir = -1;
while (_facing != facing) {
@@ -125,14 +129,13 @@ void Character::setFacing(int32 facing) {
if (_currentPathNode == 0)
playStandingAnim();
else
- playWalkAnim(0,0);
+ playWalkAnim(0, 0);
_vm->doFrame();
};
_flags &= ~2;
}
-
_facing = facing;
}
@@ -140,7 +143,7 @@ void Character::forcePosition(int32 x, int32 y) {
debugC(5, kDebugCharacter, "forcePosition(%d, %d)", x, y);
- setPosition(x,y);
+ setPosition(x, y);
_finalX = x;
_finalY = y;
}
@@ -166,8 +169,9 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) {
_vm->getPathFinding()->resetBlockingRects();
- if (_id == 1) {
- int32 sizeX = MAX<int32>(5, 40 * _vm->getDrew()->getScale() / 1024);
+ // don't allow flux to go at the same position as drew
+ if (_id == 1 ) {
+ int32 sizeX = MAX<int32>(5, 30 * _vm->getDrew()->getScale() / 1024);
int32 sizeY = MAX<int32>(2, 20 * _vm->getDrew()->getScale() / 1024);
_vm->getPathFinding()->addBlockingEllipse(_vm->getDrew()->getFinalX(), _vm->getDrew()->getFinalY(), sizeX, sizeY);
}
@@ -176,7 +180,6 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) {
if (_x == _finalX && _y == _finalY)
return true;
-
if (_vm->getPathFinding()->findPath(_x, _y, _finalX, _finalY)) {
int32 localFinalX = _finalX;
@@ -191,7 +194,7 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) {
_currentPathNodeCount = _vm->getPathFinding()->getPathNodeCount();
_currentPathNode = 0;
stopSpecialAnim();
-
+
_lastWalkTime = _vm->getSystem()->getMillis();
_numPixelToWalk = 0;
@@ -327,11 +330,6 @@ void Character::updateTimers(int32 relativeAdd) {
void Character::stopSpecialAnim() {
debugC(4, kDebugCharacter, "stopSpecialAnim()");
-// Strangerke - Commented (not used)
-#if 0
- if (_animSpecialId != _animSpecialDefaultId)
- delete anim;
-#endif
if (_animScriptId != -1)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = false;
@@ -388,7 +386,6 @@ void Character::update(int32 timeIncrement) {
if ((_flags & 4) == 0)
return;
-
if (_animScriptId != -1) {
_animationInstance = _vm->getSceneAnimation(this->)
#endif
@@ -423,19 +420,9 @@ void Character::update(int32 timeIncrement) {
return;
}
-// Strangerke - Commented (not used)
-#if 0
- if (_animFlags & 8) {
- if (anim->_flags7 == 0xff && anim->_flags9 == 0xff) {
- // start voice
- }
- }
-#endif
-
if (_animScriptId != -1)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = true;
-
-
+
// TODO setup backup //
_animFlags |= 0x10;
@@ -494,17 +481,6 @@ void Character::update(int32 timeIncrement) {
}
} else {
nextFrame = currentFrame + 1;
-// Strangerke - Commented (not used)
-#if 0
- if (!_vm->getAudioManager()->voiceStillPlaying()) {
- if (_animFlags & 8) {
- if ((anim->_flags9 == 0xff && nextFrame == anim->_flags6) ||
- (anim->_flags9 != 0xff && nextFrame >= anim->_flags9)) {
- // start really talking
- }
- }
- }
-#endif
if (nextFrame == anim->_flags7 + 1 && (_animFlags & 0x40) == 0) {
if (anim->_flags8 != 1 && (_vm->randRange(0, 1) || anim->_flags8 == 2)) {
_animFlags |= 0x20;
@@ -525,7 +501,6 @@ void Character::update(int32 timeIncrement) {
//label78
-
#if 0
if (_id == 0)
debug(" drew animation name %s / flag %d / frame %d", _specialAnim->_name, _animFlags, nextFrame);
@@ -611,7 +586,6 @@ int32 Character::getScale() {
}
void Character::playWalkAnim(int32 startFrame, int32 endFrame) {
-
}
void Character::setId(int32 id) {
@@ -677,7 +651,6 @@ int32 Character::getAnimScript() {
}
void Character::playTalkAnim() {
-
}
void Character::stopWalk() {
@@ -1046,7 +1019,6 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) {
*strchr(animName, '?') = '0' + facing;
strcat(animName, ".CAF");
-
if (_animScriptId != -1 && (flags & 8) == 0)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = true;
@@ -1068,11 +1040,9 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) {
}
}
-
if (_sceneAnimationId > -1)
setAnimationInstance(_vm->getSceneAnimation(_sceneAnimationId)->_animInstance);
-
_animFlags |= flags;
delete _specialAnim;
diff --git a/engines/toon/character.h b/engines/toon/character.h
index d4079d82ef..e870d81813 100644
--- a/engines/toon/character.h
+++ b/engines/toon/character.h
@@ -49,7 +49,6 @@ struct SpecialCharacterAnimation {
byte _flags9; // 25
};
-
class Character {
public:
Character(ToonEngine *vm);
@@ -106,7 +105,6 @@ public:
int32 getFacingFromDirection(int32 dx, int32 dy);
static const SpecialCharacterAnimation *getSpecialAnimation(int32 characterId, int32 animationId);
-
protected:
ToonEngine *_vm;
diff --git a/engines/toon/conversation.cpp b/engines/toon/conversation.cpp
index 4678ccc1c8..fc846288ef 100644
--- a/engines/toon/conversation.cpp
+++ b/engines/toon/conversation.cpp
@@ -45,5 +45,4 @@ void Conversation::load(Common::ReadStream *stream, int16 *conversationDataBase)
}
}
-
}
diff --git a/engines/toon/conversation.h b/engines/toon/conversation.h
index 784c681055..0380210e02 100644
--- a/engines/toon/conversation.h
+++ b/engines/toon/conversation.h
@@ -33,10 +33,10 @@ namespace Toon {
class Conversation {
public:
- int32 _enable; // 00
+ int32 _enable; // 00
struct ConvState {
- int32 _data2; // 04
+ int32 _data2; // 04
int16 _data3; // 08
void *_data4; // 10
} state[10];
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index f8c4c08ce6..ef023564bc 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -91,6 +91,15 @@ static const ADGameDescription gameDescriptions[] = {
},
Common::DE_DEU, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE
},
+ {
+ "toon", "",
+ {
+ {"local.pak", 0, "8ef3368078b9ea70b305c04db826feea", 2680573},
+ {"generic.svl", 0, "5c42724bb93b360dca7044d6b7ef26e5", 7739319},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE
+ },
AD_TABLE_END_MARKER
};
diff --git a/engines/toon/drew.cpp b/engines/toon/drew.cpp
index eefb4b8efa..77333c4a9f 100644
--- a/engines/toon/drew.cpp
+++ b/engines/toon/drew.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/drew.h"
namespace Toon {
@@ -111,11 +113,10 @@ void CharacterDrew::update(int32 timeIncrement) {
_scale = _currentScale;
} else if (_currentScale < _scale) {
_scale -= timeIncrement * 2;
- if (_scale < _currentScale)
+ if (_scale < _currentScale)
_scale = _currentScale;
}
setPosition(_x, _y);
-
}
int32 CharacterDrew::getRandomIdleAnim() {
diff --git a/engines/toon/drew.h b/engines/toon/drew.h
index d8091f2225..f248e4aa51 100644
--- a/engines/toon/drew.h
+++ b/engines/toon/drew.h
@@ -28,7 +28,6 @@
#include "toon/character.h"
-
namespace Toon {
class ToonEngine;
@@ -46,7 +45,6 @@ public:
int32 getRandomIdleAnim();
protected:
int32 _currentScale;
-
};
} // End of namespace Toon
diff --git a/engines/toon/flux.cpp b/engines/toon/flux.cpp
index 2b5551732b..833fdbf5ce 100644
--- a/engines/toon/flux.cpp
+++ b/engines/toon/flux.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/flux.h"
namespace Toon {
@@ -96,7 +98,7 @@ int32 CharacterFlux::fixFacingForAnimation(int32 originalFacing, int32 animation
if (!facingMask)
break;
}
-
+
return finalFacing;
}
diff --git a/engines/toon/flux.h b/engines/toon/flux.h
index a90853cb02..136dedd415 100644
--- a/engines/toon/flux.h
+++ b/engines/toon/flux.h
@@ -26,7 +26,6 @@
#ifndef TOON_FLUX_H
#define TOON_FLUX_H
-
#include "toon/character.h"
class ToonEngine;
diff --git a/engines/toon/font.cpp b/engines/toon/font.cpp
index 8455ca7b61..9367d79036 100644
--- a/engines/toon/font.cpp
+++ b/engines/toon/font.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/font.h"
namespace Toon {
@@ -81,6 +83,8 @@ void FontRenderer::renderText(int32 x, int32 y, Common::String origText, int32 m
x -= xx / 2;
}
+ _vm->addDirtyRect(x, y, x + xx + 2, y + yy);
+
int32 curX = x;
int32 curY = y;
int32 height = 0;
@@ -212,7 +216,7 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
curChar = textToFont(curChar);
int width = _currentFont->getFrameWidth(curChar);
- curWidth += width - 2;
+ curWidth += MAX<int32>(width - 2, 0);
it++;
curLetterNr++;
}
@@ -263,8 +267,8 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
if (x - 30 - maxWidth / 2 < 0)
x = maxWidth / 2 + 30;
- if (x + 30 + (maxWidth / 2) > 640)
- x = 640 - (maxWidth / 2) - 30;
+ if (x + 30 + (maxWidth / 2) > TOON_SCREEN_WIDTH)
+ x = TOON_SCREEN_WIDTH - (maxWidth / 2) - 30;
// we have good coordinates now, we can render the multi line
int32 curX = x;
@@ -273,10 +277,12 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
for (int32 i = 0; i < numLines; i++) {
const byte *line = lines[i];
curX = x - lineSize[i] / 2;
+ _vm->addDirtyRect(curX + _vm->state()->_currentScrollValue, curY, curX + lineSize[i] + _vm->state()->_currentScrollValue + 2, curY + height);
+
while (*line) {
byte curChar = textToFont(*line);
if (curChar != 32) _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX + _vm->state()->_currentScrollValue, curY, _currentFontColor);
- curX = curX + _currentFont->getFrameWidth(curChar) - 2;
+ curX = curX + MAX<int32>(_currentFont->getFrameWidth(curChar) - 2, 0);
//height = MAX(height, _currentFont->getFrameHeight(curChar));
line++;
}
diff --git a/engines/toon/hotspot.cpp b/engines/toon/hotspot.cpp
index 687ea6ee83..1c1e23e39e 100644
--- a/engines/toon/hotspot.cpp
+++ b/engines/toon/hotspot.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/hotspot.h"
#include "toon/tools.h"
@@ -78,8 +80,6 @@ int32 Hotspots::Find(int32 x, int32 y) {
debugC(6, kDebugHotspot, "Find(%d, %d)", x, y);
int32 priority = -1;
-// Strangerke - Commented (not used)
-// bool found = false;
int32 foundId = -1;
int32 testId = -1;
@@ -91,8 +91,6 @@ int32 Hotspots::Find(int32 x, int32 y) {
testId = i;
if (_items[testId].getPriority() > priority) {
-// Strangerke - Commented (not used)
-// found = true;
foundId = testId;
priority = _items[testId].getPriority();
}
@@ -128,10 +126,10 @@ bool Hotspots::LoadRif(Common::String rifName, Common::String additionalRifName)
// RIFs are compressed in RNC1
RncDecoder decoder;
- decoder.unpackM1(rifData, _items);
+ decoder.unpackM1(rifData, size, _items);
if (rifsize2) {
RncDecoder decoder2;
- decoder2.unpackM1(rifData2 , _items + (rifsize >> 9));
+ decoder2.unpackM1(rifData2 , size2, _items + (rifsize >> 9));
for (int32 i = 0; i < (rifsize2 >> 9); i++) {
HotspotData *hot = _items + (rifsize >> 9) + i;
hot->setData(0, hot->getX1() + 1280);
diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp
index c6b57d96e2..64b80c29b3 100644
--- a/engines/toon/movie.cpp
+++ b/engines/toon/movie.cpp
@@ -23,7 +23,16 @@
*
*/
+#include "common/debug.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+
+#include "toon/audio.h"
#include "toon/movie.h"
+#include "toon/toon.h"
namespace Toon {
@@ -38,8 +47,8 @@ void ToonstruckSmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, ui
Video::SmackerDecoder::handleAudioTrack(track, chunkSize, unpackedSize);
}
-bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename, int forcedflags) {
- debugC(1, kDebugMovie, "loadFile(%s, %d)", filename.c_str(), forcedflags);
+bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename) {
+ debugC(1, kDebugMovie, "loadFile(%s)", filename.c_str());
_lowRes = false;
@@ -50,14 +59,12 @@ bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename, int forc
delete _surface;
}
_surface = new Graphics::Surface();
- _surface->create(640, 400, 1);
+ _surface->create(640, 400, Graphics::PixelFormat::createFormatCLUT8());
_header.flags = 4;
}
return true;
}
-
-
return false;
}
@@ -88,7 +95,7 @@ void Movie::play(Common::String video, int32 flags) {
_playing = true;
if (flags & 1)
_vm->getAudioManager()->setMusicVolume(0);
- _decoder->loadFile(video.c_str(), flags);
+ _decoder->loadFile(video.c_str());
playVideo(isFirstIntroVideo);
_vm->flushPalette(false);
if (flags & 1)
@@ -107,9 +114,9 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
if (_decoder->isLowRes()) {
// handle manually 2x scaling here
Graphics::Surface* surf = _vm->getSystem()->lockScreen();
- for (int y = 0; y < frame->h/2; y++) {
- memcpy(surf->getBasePtr(0, y*2+0), frame->getBasePtr(0, y), frame->pitch);
- memcpy(surf->getBasePtr(0, y*2+1), frame->getBasePtr(0, y), frame->pitch);
+ for (int y = 0; y < frame->h / 2; y++) {
+ memcpy(surf->getBasePtr(0, y * 2 + 0), frame->getBasePtr(0, y), frame->pitch);
+ memcpy(surf->getBasePtr(0, y * 2 + 1), frame->getBasePtr(0, y), frame->pitch);
}
_vm->getSystem()->unlockScreen();
} else {
@@ -135,11 +142,13 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
Common::Event event;
while (_vm->getSystem()->getEventManager()->pollEvent(event))
if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ _vm->dirtyAllScreen();
return false;
}
_vm->getSystem()->delayMillis(10);
}
+ _vm->dirtyAllScreen();
return !_vm->shouldQuit();
}
diff --git a/engines/toon/movie.h b/engines/toon/movie.h
index 2a9173850f..bed2ceceae 100644
--- a/engines/toon/movie.h
+++ b/engines/toon/movie.h
@@ -36,7 +36,7 @@ public:
ToonstruckSmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
virtual ~ToonstruckSmackerDecoder() {}
void handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize);
- bool loadFile(const Common::String &filename, int forcedflags);
+ bool loadFile(const Common::String &filename);
bool isLowRes() { return _lowRes; }
protected:
bool _lowRes;
diff --git a/engines/toon/path.cpp b/engines/toon/path.cpp
index 3f948679f4..26355863f6 100644
--- a/engines/toon/path.cpp
+++ b/engines/toon/path.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/path.h"
namespace Toon {
@@ -186,7 +188,7 @@ int32 PathFinding::findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32
for (int y = 0; y < _height; y++) {
for (int x = 0; x < _width; x++) {
- if (isWalkable(x, y) && isLikelyWalkable(x,y)) {
+ if (isWalkable(x, y) && isLikelyWalkable(x, y)) {
int32 ndist = (x - xx) * (x - xx) + (y - yy) * (y - yy);
int32 ndist2 = (x - origX) * (x - origX) + (y - origY) * (y - origY);
if (currentFound < 0 || ndist < dist || (ndist == dist && ndist2 < dist2)) {
@@ -283,8 +285,8 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) {
}
// first test direct line
- if (lineIsWalkable(x,y,destx,desty)) {
- walkLine(x,y,destx,desty);
+ if (lineIsWalkable(x, y, destx, desty)) {
+ walkLine(x, y, destx, desty);
return true;
}
@@ -317,7 +319,7 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) {
int32 curPNode = px + py * _width;
if (isWalkable(px, py)) { // walkable ?
- int sum = sq[curNode] + wei * (1 + (isLikelyWalkable(px,py) ? 5 : 0));
+ int sum = sq[curNode] + wei * (1 + (isLikelyWalkable(px, py) ? 5 : 0));
if (sq[curPNode] > sum || !sq[curPNode]) {
int newWeight = abs(destx - px) + abs(desty - py);
sq[curPNode] = sum;
@@ -407,7 +409,11 @@ void PathFinding::init(Picture *mask) {
_height = mask->getHeight();
_currentMask = mask;
_heap->unload();
- _heap->init(_width * _height);
+ // In order to reduce memory fragmentation on small devices, we use the maximum
+ // possible size here which is TOON_BACKBUFFER_WIDTH. Even though this is
+ // 1280 as opposed to the possible 640, it actually helps memory allocation on
+ // those devices.
+ _heap->init(TOON_BACKBUFFER_WIDTH * _height); // should really be _width
delete[] _gridTemp;
_gridTemp = new int32[_width*_height];
}
@@ -438,7 +444,6 @@ void PathFinding::addBlockingEllipse(int32 x1, int32 y1, int32 w, int32 h) {
_numBlockingRects++;
}
-
int32 PathFinding::getPathNodeCount() const {
return _gridPathCount;
}
diff --git a/engines/toon/path.h b/engines/toon/path.h
index a2b1b7bf92..03d2b188e5 100644
--- a/engines/toon/path.h
+++ b/engines/toon/path.h
@@ -91,7 +91,6 @@ protected:
int32 _gridPathCount;
ToonEngine *_vm;
-
};
} // End of namespace Toon
diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index 18e6a8cf7f..ce28f9c68b 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -23,16 +23,18 @@
*
*/
-
#include "toon/picture.h"
#include "toon/tools.h"
+
+#include "common/debug.h"
+#include "common/rect.h"
#include "common/stack.h"
namespace Toon {
bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
debugC(1, kDebugPicture, "loadPicture(%s, %d)", file.c_str(), (totalPalette) ? 1 : 0);
-
+
uint32 size = 0;
uint8 *fileData = _vm->resources()->getFileData(file, &size);
if (!fileData)
@@ -49,12 +51,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
decompressLZSS(fileData + 8, _data, dstsize);
// size can only be 640x400 or 1280x400
- if (dstsize > 640 * 400 + 768)
- _width = 1280;
+ if (dstsize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
// do we have a palette ?
_paletteEntries = (dstsize & 0x7ff) / 3;
@@ -69,7 +71,7 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
}
case kCompSPCN: {
uint32 decSize = READ_LE_UINT32(fileData + 10);
- _data = new uint8[decSize+100];
+ _data = new uint8[decSize + 100];
_paletteEntries = READ_LE_UINT16(fileData + 14) / 3;
if (_paletteEntries) {
@@ -79,12 +81,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
}
// size can only be 640x400 or 1280x400
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
// decompress the picture into our buffer
decompressSPCN(fileData + 16 + _paletteEntries * 3, _data, decSize);
@@ -98,15 +100,15 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
_data = new uint8[decSize];
- rnc.unpackM1(fileData, _data);
+ rnc.unpackM1(fileData, size, _data);
// size can only be 640x400 or 1280x400
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
return true;
}
case kCompRNC2: {
@@ -119,12 +121,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
decSize = rnc.unpackM2(fileData, _data);
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
return true;
}
}
@@ -187,6 +189,41 @@ void Picture::drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, i
}
}
+void Picture::drawWithRectList(Graphics::Surface& surface, int32 x, int32 y, int32 dx, int32 dy, Common::Array<Common::Rect>& rectArray) {
+
+ int32 rx = MIN(_width, surface.w - x);
+ int32 ry = MIN(_height, surface.h - y);
+
+ if (rx < 0 || ry < 0)
+ return;
+
+ int32 destPitch = surface.pitch;
+ int32 srcPitch = _width;
+
+ for (uint32 i = 0; i < rectArray.size(); i++) {
+
+ Common::Rect rect = rectArray[i];
+
+ int32 fillRx = MIN<int32>(rx, rect.right - rect.left);
+ int32 fillRy = MIN<int32>(ry, rect.bottom - rect.top);
+
+ uint8 *c = _data + _width * (dy + rect.top) + (dx + rect.left);
+ uint8 *curRow = (uint8 *)surface.pixels + (y + rect.top) * destPitch + (x + rect.left);
+
+ for (int32 yy = 0; yy < fillRy; yy++) {
+ uint8 *curSrc = c;
+ uint8 *cur = curRow;
+ for (int32 xx = 0; xx < fillRx; xx++) {
+ *cur = *curSrc;
+ curSrc++;
+ cur++;
+ }
+ curRow += destPitch;
+ c += srcPitch;
+ }
+ }
+}
+
void Picture::draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy) {
debugC(6, kDebugPicture, "draw(surface, %d, %d, %d, %d)", x, y, dx, dy);
@@ -279,7 +316,6 @@ void Picture::drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable
else
t = adx;
-
int32 cdx = (dx << 16) / t;
int32 cdy = (dy << 16) / t;
@@ -289,15 +325,15 @@ void Picture::drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable
int32 rx = bx >> 16;
int32 ry = by >> 16;
- if( rx >= 0 && rx < _width-1 && ry >= 0 && ry < _height) { // sanity check: some lines in the game
+ if( rx >= 0 && rx < _width-1 && ry >= 0 && ry < _height) { // sanity check: some lines in the game
// were drawing outside the screen causing corruption
if (!walkable) {
_data[_width * ry + rx] &= 0xe0;
- _data[_width * ry + rx+1] &= 0xe0;
+ _data[_width * ry + rx + 1] &= 0xe0;
} else {
int32 v = _data[_width * (by >> 16) + rx - 1];
_data[_width * ry + rx] = v;
- _data[_width * ry + rx+1] = v;
+ _data[_width * ry + rx + 1] = v;
}
}
diff --git a/engines/toon/picture.h b/engines/toon/picture.h
index 1b0fd7f550..6aca408364 100644
--- a/engines/toon/picture.h
+++ b/engines/toon/picture.h
@@ -44,6 +44,7 @@ public:
bool loadPicture(Common::String file, bool totalPalette = false);
void setupPalette();
void draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
+ void drawWithRectList(Graphics::Surface& surface, int32 x, int32 y, int32 dx, int32 dy, Common::Array<Common::Rect>& rectArray);
void drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
void drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable);
void floodFillNotWalkableOnMask(int32 x, int32 y);
diff --git a/engines/toon/resource.cpp b/engines/toon/resource.cpp
index 61e3ffb111..f9f65b423b 100644
--- a/engines/toon/resource.cpp
+++ b/engines/toon/resource.cpp
@@ -24,18 +24,26 @@
*/
#include "toon/resource.h"
+#include "common/debug.h"
#include "common/file.h"
#include "common/memstream.h"
#include "common/substream.h"
#include "toon/toon.h"
-
namespace Toon {
-Resources::Resources(ToonEngine *vm) : _vm(vm) {
+Resources::Resources(ToonEngine *vm) : _vm(vm), _cacheSize(0) {
+ _resourceCache.clear();
}
Resources::~Resources() {
+
+ while (!_resourceCache.empty()) {
+ CacheEntry *temp = _resourceCache.back();
+ _resourceCache.pop_back();
+ delete temp;
+ }
+
while(!_pakFiles.empty()) {
PakFile *temp = _pakFiles.back();
_pakFiles.pop_back();
@@ -45,8 +53,73 @@ Resources::~Resources() {
purgeFileData();
}
-void Resources::openPackage(Common::String fileName, bool preloadEntirePackage) {
- debugC(1, kDebugResource, "openPackage(%s, %d)", fileName.c_str(), (preloadEntirePackage) ? 1 : 0);
+void Resources::removePackageFromCache(Common::String packName) {
+ // I'm not sure what's a good strategy here. It seems unnecessary to
+ // actually remove the cached resources, because the player may be
+ // wandering back and forth between rooms. So for now, do nothing.
+}
+
+bool Resources::getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData) {
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data && (*entry)->_fileName.compareToIgnoreCase(fileName) == 0) {
+ debugC(5, kDebugResource, "getFromCache(%s) - Got %d bytes from %s", fileName.c_str(), (*entry)->_size, (*entry)->_packName.c_str());
+ (*entry)->_age = 0;
+ *fileSize = (*entry)->_size;
+ *fileData = (*entry)->_data;
+ return true;
+ }
+ }
+ return false;
+}
+
+void Resources::addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData) {
+ debugC(5, kDebugResource, "addToCache(%s, %s, %d) - Total Size: %d", packName.c_str(), fileName.c_str(), fileSize, _cacheSize + fileSize);
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data) {
+ (*entry)->_age++;
+ }
+ }
+ _cacheSize += fileSize;
+
+ while (_cacheSize > MAX_CACHE_SIZE) {
+ CacheEntry *bestEntry = 0;
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data) {
+ if (!bestEntry || ((*entry)->_age >= bestEntry->_age && (*entry)->_size >= bestEntry->_size)) {
+ bestEntry = *entry;
+ }
+ }
+ }
+ if (!bestEntry)
+ break;
+
+ free(bestEntry->_data);
+ bestEntry->_data = 0;
+ _cacheSize -= bestEntry->_size;
+ debugC(5, kDebugResource, "Freed %s (%s) to reclaim %d bytes", bestEntry->_fileName.c_str(), bestEntry->_packName.c_str(), bestEntry->_size);
+ }
+
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if (!(*entry)->_data) {
+ (*entry)->_packName = packName;
+ (*entry)->_fileName = fileName;
+ (*entry)->_age = 0;
+ (*entry)->_size = fileSize;
+ (*entry)->_data = fileData;
+ return;
+ }
+ }
+
+ CacheEntry *entry = new CacheEntry();
+ entry->_packName = packName;
+ entry->_fileName = fileName;
+ entry->_size = fileSize;
+ entry->_data = fileData;
+ _resourceCache.push_back(entry);
+}
+
+void Resources::openPackage(Common::String fileName) {
+ debugC(1, kDebugResource, "openPackage(%s)", fileName.c_str());
Common::File file;
bool opened = file.open(fileName);
@@ -55,15 +128,16 @@ void Resources::openPackage(Common::String fileName, bool preloadEntirePackage)
return;
PakFile *pakFile = new PakFile();
- pakFile->open(&file, fileName, preloadEntirePackage);
+ pakFile->open(&file, fileName);
- if (preloadEntirePackage)
- file.close();
+ file.close();
_pakFiles.push_back(pakFile);
}
void Resources::closePackage(Common::String fileName) {
+
+ removePackageFromCache(fileName);
for (uint32 i = 0; i < _pakFiles.size(); i++) {
if (_pakFiles[i]->getPackName() == fileName) {
delete _pakFiles[i];
@@ -91,13 +165,21 @@ uint8 *Resources::getFileData(Common::String fileName, uint32 *fileSize) {
_allocatedFileData.push_back(memory);
return memory;
} else {
+
+ uint32 locFileSize = 0;
+ uint8 *locFileData = 0;
+
+ if (getFromCache(fileName, &locFileSize, &locFileData)) {
+ *fileSize = locFileSize;
+ return locFileData;
+ }
+
for (uint32 i = 0; i < _pakFiles.size(); i++) {
- uint32 locFileSize = 0;
- uint8 *locFileData = 0;
locFileData = _pakFiles[i]->getFileData(fileName, &locFileSize);
if (locFileData) {
*fileSize = locFileSize;
+ addToCache(_pakFiles[i]->getPackName(), fileName, locFileSize, locFileData);
return locFileData;
}
}
@@ -136,25 +218,16 @@ void Resources::purgeFileData() {
}
_allocatedFileData.clear();
}
+
Common::SeekableReadStream *PakFile::createReadStream(Common::String fileName) {
debugC(1, kDebugResource, "createReadStream(%s)", fileName.c_str());
- int32 offset = 0;
- int32 size = 0;
- for (uint32 i = 0; i < _numFiles; i++) {
- if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
- size = _files[i]._size;
- offset = _files[i]._offset;
- break;
- }
- }
- if (!size)
- return 0;
-
- if (_fileHandle)
- return new Common::SeekableSubReadStream(_fileHandle, offset, offset + size);
+ uint32 fileSize = 0;
+ uint8 *buffer = getFileData(fileName, &fileSize);
+ if (buffer)
+ return new Common::MemoryReadStream(buffer, fileSize, DisposeAfterUse::YES);
else
- return new Common::MemoryReadStream(_buffer + offset, size);
+ return 0;
}
uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
@@ -162,16 +235,26 @@ uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
for (uint32 i = 0; i < _numFiles; i++) {
if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
- *fileSize = _files[i]._size;
- return _buffer + _files[i]._offset;
+ Common::File file;
+ if (file.open(_packName)) {
+ *fileSize = _files[i]._size;
+ file.seek(_files[i]._offset);
+
+ // Use malloc() because that's what MemoryReadStream
+ // uses to dispose of the memory when it's done.
+ uint8 *buffer = (uint8 *)malloc(*fileSize);
+ file.read(buffer, *fileSize);
+ file.close();
+ return buffer;
+ }
}
}
return 0;
}
-void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage) {
- debugC(1, kDebugResource, "open(rs, %d)", (preloadEntirePackage) ? 1 : 0);
+void PakFile::open(Common::SeekableReadStream *rs, Common::String packName) {
+ debugC(1, kDebugResource, "open(rs)");
char buffer[64];
int32 currentPos = 0;
@@ -199,30 +282,12 @@ void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool
_numFiles++;
_files.push_back(newFile);
}
-
- if (preloadEntirePackage) {
- _bufferSize = rs->size();
- delete[] _buffer;
- _buffer = new uint8[_bufferSize];
- rs->seek(0);
- rs->read(_buffer, _bufferSize);
- }
}
void PakFile::close() {
- delete[] _buffer;
-
- if (_fileHandle) {
- _fileHandle->close();
- delete _fileHandle;
- }
}
PakFile::PakFile() {
- _bufferSize = 0;
- _buffer = NULL;
-
- _fileHandle = NULL;
}
PakFile::~PakFile() {
diff --git a/engines/toon/resource.h b/engines/toon/resource.h
index e117c8e259..d6ed29b81b 100644
--- a/engines/toon/resource.h
+++ b/engines/toon/resource.h
@@ -31,6 +31,8 @@
#include "common/file.h"
#include "common/stream.h"
+#define MAX_CACHE_SIZE (4 * 1024 * 1024)
+
namespace Toon {
class PakFile {
@@ -38,7 +40,7 @@ public:
PakFile();
~PakFile();
- void open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage);
+ void open(Common::SeekableReadStream *rs, Common::String packName);
uint8 *getFileData(Common::String fileName, uint32 *fileSize);
Common::String getPackName() { return _packName; }
Common::SeekableReadStream *createReadStream(Common::String fileName);
@@ -52,9 +54,6 @@ protected:
};
Common::String _packName;
- uint8 *_buffer;
- int32 _bufferSize;
-
uint32 _numFiles;
Common::Array<File> _files;
Common::File *_fileHandle;
@@ -62,11 +61,25 @@ protected:
class ToonEngine;
+class CacheEntry {
+public:
+ CacheEntry() : _age(0), _size(0), _data(0) {}
+ ~CacheEntry() {
+ free(_data);
+ }
+
+ Common::String _packName;
+ Common::String _fileName;
+ uint32 _age;
+ uint32 _size;
+ uint8 *_data;
+};
+
class Resources {
public:
Resources(ToonEngine *vm);
~Resources();
- void openPackage(Common::String file, bool preloadEntirePackage);
+ void openPackage(Common::String file);
void closePackage(Common::String fileName);
Common::SeekableReadStream *openFile(Common::String file);
uint8 *getFileData(Common::String fileName, uint32 *fileSize); // this memory must be copied to your own structures!
@@ -76,6 +89,12 @@ protected:
ToonEngine *_vm;
Common::Array<uint8 *> _allocatedFileData;
Common::Array<PakFile *> _pakFiles;
+ uint32 _cacheSize;
+ Common::Array<CacheEntry *> _resourceCache;
+
+ void removePackageFromCache(Common::String packName);
+ bool getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData);
+ void addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData);
};
} // End of namespace Toon
diff --git a/engines/toon/script.cpp b/engines/toon/script.cpp
index 3cd56761f6..8703666781 100644
--- a/engines/toon/script.cpp
+++ b/engines/toon/script.cpp
@@ -23,11 +23,9 @@
*
*/
-
+#include "common/debug.h"
#include "common/endian.h"
#include "common/stream.h"
-#include "common/util.h"
-#include "common/system.h"
#include "toon/toon.h"
#include "toon/script.h"
@@ -71,7 +69,7 @@ EMCInterpreter::~EMCInterpreter() {
bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
switch (chunk._type) {
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
delete[] _scriptData->text;
_scriptData->text = new byte[chunk._size];
assert(_scriptData->text);
@@ -79,7 +77,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
error("Couldn't read TEXT chunk from file '%s'", _filename);
break;
- case MKID_BE('ORDR'):
+ case MKTAG('O','R','D','R'):
delete[] _scriptData->ordr;
_scriptData->ordr = new uint16[chunk._size >> 1];
assert(_scriptData->ordr);
@@ -90,7 +88,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
_scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]);
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
delete[] _scriptData->data;
_scriptData->data = new uint16[chunk._size >> 1];
assert(_scriptData->data);
@@ -177,7 +175,7 @@ bool EMCInterpreter::start(EMCState *script, int function) {
if (functionOffset == 0xFFFF)
return false;
- script->ip = &script->dataPtr->data[functionOffset+1];
+ script->ip = &script->dataPtr->data[functionOffset + 1];
return true;
}
diff --git a/engines/toon/script.h b/engines/toon/script.h
index 6c46238238..b6d28e1171 100644
--- a/engines/toon/script.h
+++ b/engines/toon/script.h
@@ -31,7 +31,6 @@
#include "common/func.h"
#include "common/iff_container.h"
-
// Based on Kyra script interpretor
namespace Toon {
@@ -88,9 +87,9 @@ public:
// Both lead to some problems in our IFF parser, either reading after the end
// of file or producing a "Chunk overread" error message. To work around this
// we need to adjust the size field properly.
- if (_formType == MKID_BE('EMC2'))
+ if (_formType == MKTAG('E','M','C','2'))
_formChunk.size -= 8;
- else if (_formType == MKID_BE('AVFS'))
+ else if (_formType == MKTAG('A','V','F','S'))
_formChunk.size += 4;
}
};
diff --git a/engines/toon/script_func.cpp b/engines/toon/script_func.cpp
index adf3a1c9cc..8f75097bd4 100644
--- a/engines/toon/script_func.cpp
+++ b/engines/toon/script_func.cpp
@@ -23,6 +23,9 @@
*
*/
+#include "common/debug.h"
+#include "common/system.h"
+
#include "toon/script_func.h"
#include "toon/script.h"
#include "toon/state.h"
@@ -265,7 +268,6 @@ int32 ScriptFunc::sys_Cmd_Draw_Actor_Standing(EMCState *state) {
arg1 = 1;
}
-
if (arg2 > -1)
_vm->getDrew()->forceFacing(arg2);
@@ -461,7 +463,7 @@ int32 ScriptFunc::sys_Cmd_Actor_Talks(EMCState *state) {
}
int32 ScriptFunc::sys_Cmd_Say_Lines(EMCState *state) {
-
+
// WORKAROUND: In the scene 4 (Castle), if you click twice on the closed door, Drew disappears
// the script makes him disappear for the custom animation and not reappear.
if (_vm->state()->_currentScene == 4 && stackPos(1) == 562) {
@@ -491,11 +493,11 @@ int32 ScriptFunc::sys_Cmd_Empty_Inventory(EMCState *state) {
int32 ScriptFunc::sys_Cmd_Set_Anim_Scale_Size(EMCState *state) {
int32 animID = stackPos(0);
int32 scale = stackPos(1);
-
+
SceneAnimation *sceneAnim = _vm->getSceneAnimation(animID);
if (sceneAnim) {
sceneAnim->_animInstance->setUseMask(true);
- sceneAnim->_animInstance->setScale(scale,true);
+ sceneAnim->_animInstance->setScale(scale, true);
}
return 0;
}
@@ -939,8 +941,6 @@ int32 ScriptFunc::sys_Cmd_Init_Scene_Anim(EMCState *state) {
sceneAnim->_animInstance->setAnimationRange(stackPos(11), stackPos(11));
sceneAnim->_animInstance->setFrame(stackPos(11));
-
-
debugC(0, 0xfff, "Init Anim %s %d %d %d %d %d %d %d %d %d %d %d %d %d\n", GetText(12, state), stackPos(0), stackPos(1), stackPos(2), stackPos(3),
stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9), stackPos(10), stackPos(11), stackPos(12));
@@ -950,7 +950,7 @@ int32 ScriptFunc::sys_Cmd_Init_Scene_Anim(EMCState *state) {
int32 layerZ = stackPos(3);
if (dx == -2)
- sceneAnim->_animInstance->moveRelative(640, 0, 0);
+ sceneAnim->_animInstance->moveRelative(TOON_SCREEN_WIDTH, 0, 0);
else if (dx < 0) {
dx = sceneAnim->_animation->_x1;
}
@@ -1028,7 +1028,7 @@ int32 ScriptFunc::sys_Cmd_Draw_Scene_Anim_WSA_Frame(EMCState *state) {
else if (animId == 20 || animId == 15 || animId == 21 || animId == 16 || animId == 17 || animId == 18)
_vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 1);
else if (animId == 9) {
- _vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 6);
+ _vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 3);
}
}
@@ -1091,13 +1091,13 @@ int32 ScriptFunc::sys_Cmd_Proceed_To_Next_Chapter(EMCState *state) {
}
int32 ScriptFunc::sys_Cmd_Play_Sfx_Plus(EMCState *state) {
- //debugC(0,0xfff, "playSfx ( %d , %d, %d, %d, %d )", stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ //debugC(0, 0xfff, "playSfx ( %d , %d, %d, %d, %d )", stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
_vm->playSFX(stackPos(0), stackPos(1));
return 0;
}
int32 ScriptFunc::sys_Cmd_Play_Sfx(EMCState *state) {
- //debugC(0,0xfff, "playSfx ( %d , %d)", stackPos(0), stackPos(1));
+ //debugC(0, 0xfff, "playSfx ( %d , %d)", stackPos(0), stackPos(1));
_vm->playSFX(stackPos(0), stackPos(1));
return 0;
}
diff --git a/engines/toon/state.cpp b/engines/toon/state.cpp
index f676a65025..af37ea9e68 100644
--- a/engines/toon/state.cpp
+++ b/engines/toon/state.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/state.h"
#include "toon/toon.h"
@@ -119,7 +121,6 @@ State::State(void) {
}
State::~State(void) {
-
}
int32 State::getGameFlag(int32 flagId) {
diff --git a/engines/toon/state.h b/engines/toon/state.h
index d31ff4f3c2..63505fd5fb 100644
--- a/engines/toon/state.h
+++ b/engines/toon/state.h
@@ -81,7 +81,6 @@ public:
int32 _nextSpecialEnterX;
int32 _nextSpecialEnterY;
-
bool _timerEnabled[2];
int32 _timerTimeout[2];
int32 _timerDelay[2];
@@ -94,7 +93,6 @@ public:
void loadConversations(Common::ReadStream *stream);
void saveConversations(Common::WriteStream *stream);
-
};
} // End of namespace Toon
diff --git a/engines/toon/text.cpp b/engines/toon/text.cpp
index f0d17dd34e..94a3ea5aa7 100644
--- a/engines/toon/text.cpp
+++ b/engines/toon/text.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/text.h"
namespace Toon {
diff --git a/engines/toon/tools.cpp b/engines/toon/tools.cpp
index a03a2d57ce..ff72e69543 100644
--- a/engines/toon/tools.cpp
+++ b/engines/toon/tools.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/tools.h"
#include "toon/toon.h"
@@ -125,7 +127,6 @@ uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize) {
return (dstp - dst);
}
-
//return codes
#define NOT_PACKED 0
#define PACKED_CRC -1
@@ -201,7 +202,16 @@ uint16 RncDecoder::inputBits(uint8 amount) {
newBitBuffl >>= newBitCount;
newBitBuffl |= remBits;
_srcPtr += 2;
- newBitBuffh = READ_LE_UINT16(_srcPtr);
+
+ // added some more check here to prevent reading in the buffer
+ // if there are no bytes anymore.
+ _inputByteLeft -= 2;
+ if (_inputByteLeft <= 0)
+ newBitBuffh = 0;
+ else if (_inputByteLeft == 1)
+ newBitBuffh = *_srcPtr;
+ else
+ newBitBuffh = READ_LE_UINT16(_srcPtr);
amount -= newBitCount;
newBitCount = 16 - amount;
}
@@ -284,7 +294,7 @@ int RncDecoder::getbit() {
return temp;
}
-int32 RncDecoder::unpackM1(const void *input, void *output) {
+int32 RncDecoder::unpackM1(const void *input, uint16 inputSize, void *output) {
debugC(1, kDebugTools, "unpackM1(input, output)");
uint8 *outputLow, *outputHigh;
@@ -297,6 +307,7 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
uint16 crcPacked = 0;
+ _inputByteLeft = inputSize;
_bitBuffl = 0;
_bitBuffh = 0;
_bitCount = 0;
@@ -339,9 +350,12 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
_srcPtr = (_dstPtr - packLen);
}
+ _inputByteLeft -= HEADER_LEN;
+
_dstPtr = (uint8 *)output;
_bitCount = 0;
+
_bitBuffl = READ_LE_UINT16(_srcPtr);
inputBits(2);
@@ -360,8 +374,22 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
memcpy(_dstPtr, _srcPtr, inputLength); //memcpy is allowed here
_dstPtr += inputLength;
_srcPtr += inputLength;
- uint16 a = READ_LE_UINT16(_srcPtr);
- uint16 b = READ_LE_UINT16(_srcPtr + 2);
+ _inputByteLeft -= inputLength;
+ uint16 a;
+ if (_inputByteLeft <= 0)
+ a = 0;
+ else if (_inputByteLeft == 1)
+ a = *_srcPtr;
+ else
+ a = READ_LE_UINT16(_srcPtr);
+
+ uint16 b;
+ if (_inputByteLeft <= 2)
+ b = 0;
+ else if(_inputByteLeft == 3)
+ b = *(_srcPtr + 2);
+ else
+ b = READ_LE_UINT16(_srcPtr + 2);
_bitBuffl &= ((1 << _bitCount) - 1);
_bitBuffl |= (a << _bitCount);
@@ -397,9 +425,6 @@ int32 RncDecoder::unpackM2(const void *input, void *output) {
uint16 crcUnpacked = 0;
uint16 crcPacked = 0;
-// Strangerke - Commented (not used)
-// uint16 counts = 0;
-
_bitBuffl = 0;
_bitCount = 0;
@@ -429,7 +454,6 @@ int32 RncDecoder::unpackM2(const void *input, void *output) {
_srcPtr = inputptr;
_dstPtr = (uint8 *)output;
-
uint16 ofs, len;
byte ofs_hi, ofs_lo;
diff --git a/engines/toon/tools.h b/engines/toon/tools.h
index 05fc5c9cda..1434ca26c7 100644
--- a/engines/toon/tools.h
+++ b/engines/toon/tools.h
@@ -42,8 +42,8 @@ const uint32 kCompRNC2 = 0x524E4302;
#define READ_LE_INT16(x) (int16) READ_LE_UINT16(x)
#define READ_LE_INT32(x) (int32) READ_LE_UINT32(x)
-#define WRITE_LE_INT16(x,y) WRITE_LE_UINT16(x,(int16)y)
-#define WRITE_LE_INT32(x,y) WRITE_LE_UINT32(x,(int32)y)
+#define WRITE_LE_INT16(x, y) WRITE_LE_UINT16(x, (int16)y)
+#define WRITE_LE_INT32(x, y) WRITE_LE_UINT32(x, (int32)y)
uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize);
uint32 decompressLZSS(byte *src, byte *dst, int dstsize);
@@ -63,10 +63,12 @@ protected:
const uint8 *_srcPtr;
uint8 *_dstPtr;
+ int16 _inputByteLeft;
+
public:
RncDecoder();
~RncDecoder();
- int32 unpackM1(const void *input, void *output);
+ int32 unpackM1(const void *input, uint16 inputSize, void *output);
int32 unpackM2(const void *input, void *output);
protected:
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index d65230df85..81c4d313e4 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -33,6 +33,7 @@
#include "common/memstream.h"
#include "engines/util.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "graphics/thumbnail.h"
#include "gui/saveload.h"
@@ -49,7 +50,6 @@
namespace Toon {
-
void ToonEngine::init() {
_currentScriptRegion = 0;
_resources = new Resources(this);
@@ -58,7 +58,7 @@ void ToonEngine::init() {
_hotspots = new Hotspots(this);
_mainSurface = new Graphics::Surface();
- _mainSurface->create(1280, 400, 1);
+ _mainSurface->create(TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
_finalPalette = new uint8[768];
_backupPalette = new uint8[768];
@@ -101,14 +101,13 @@ void ToonEngine::init() {
SearchMan.addSubDirectoryMatching(gameDataDir, "ACT1");
SearchMan.addSubDirectoryMatching(gameDataDir, "ACT2");
-
syncSoundSettings();
_pathFinding = new PathFinding(this);
- resources()->openPackage("LOCAL.PAK", true);
- resources()->openPackage("ONETIME.PAK", true);
- resources()->openPackage("DREW.PAK", true);
+ resources()->openPackage("LOCAL.PAK");
+ resources()->openPackage("ONETIME.PAK");
+ resources()->openPackage("DREW.PAK");
for (int32 i = 0; i < 32; i++)
_characters[i] = NULL;
@@ -118,6 +117,8 @@ void ToonEngine::init() {
_drew = _characters[0];
_flux = _characters[1];
+
+
// preload walk anim for flux and drew
_drew->loadWalkAnimation("STNDWALK.CAF");
_drew->setupPalette();
@@ -137,6 +138,9 @@ void ToonEngine::init() {
memset(_sceneAnimations, 0, sizeof(_sceneAnimations));
memset(_sceneAnimationScripts, 0, sizeof(_sceneAnimationScripts));
+ _drew->setVisible(false);
+ _flux->setVisible(false);
+
_gameState->_currentChapter = 1;
initChapter();
loadCursor();
@@ -262,7 +266,6 @@ void ToonEngine::parseInput() {
selectHotspot();
clickEvent();
}
-
}
void ToonEngine::enableTimer(int32 timerId) {
@@ -325,8 +328,8 @@ void ToonEngine::updateScrolling(bool force, int32 timeIncrement) {
if ((_gameState->_locations[_gameState->_currentScene]._flags & 0x80) == 0) {
if (desiredScrollValue < 0)
desiredScrollValue = 0;
- if (desiredScrollValue >= _currentPicture->getWidth() - 640)
- desiredScrollValue = _currentPicture->getWidth() - 640;
+ if (desiredScrollValue >= _currentPicture->getWidth() - TOON_SCREEN_WIDTH)
+ desiredScrollValue = _currentPicture->getWidth() - TOON_SCREEN_WIDTH;
if (force) {
_gameState->_currentScrollValue = desiredScrollValue;
@@ -378,12 +381,23 @@ void ToonEngine::updateTimer(int32 timeIncrement) {
}
void ToonEngine::render() {
- if (_gameState->_inCutaway)
- _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
- else
- _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
- //_currentMask->drawMask(*_mainSurface,0,0,0,0);
+ if (_dirtyAll) {
+ if (_gameState->_inCutaway)
+ _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
+ else
+ _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_HEIGHT));
+ } else {
+ if (_gameState->_inCutaway)
+ _currentCutaway->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ else
+ _currentPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ }
+
+ clearDirtyRects();
+
+ //_currentMask->drawMask(*_mainSurface, 0, 0, 0, 0);
_animationManager->render();
drawInfoLine();
@@ -399,7 +413,7 @@ void ToonEngine::render() {
sprintf(test, "%d %d / mask %d layer %d z %d", _mouseX, _mouseY, getMask()->getData(_mouseX, _mouseY), getLayerAtPoint(_mouseX, _mouseY), getZAtPoint(_mouseX, _mouseY));
int32 c = *(uint8 *)_mainSurface->getBasePtr(_mouseX, _mouseY);
- sprintf(test, "%d %d / color id %d %d,%d,%d", _mouseX, _mouseY, c, _finalPalette[c*3+0], _finalPalette[c*3+1], _finalPalette[c*3+2]);
+ sprintf(test, "%d %d / color id %d %d,%d,%d", _mouseX, _mouseY, c, _finalPalette[c * 3 + 0], _finalPalette[c * 3 + 1], _finalPalette[c * 3 + 2]);
_fontRenderer->setFont(_fontToon);
_fontRenderer->renderText(40, 150, Common::String(test), 0);
@@ -422,8 +436,8 @@ void ToonEngine::render() {
// add a little sleep here
int32 newMillis = (int32)_system->getMillis();
int32 sleepMs = 1; // Minimum delay to allow thread scheduling
- if ((newMillis - _lastRenderTime) < _tickLength)
- sleepMs = _tickLength - (newMillis - _lastRenderTime);
+ if ((newMillis - _lastRenderTime) < _tickLength * 2)
+ sleepMs = _tickLength * 2 - (newMillis - _lastRenderTime);
assert(sleepMs >= 0);
_system->delayMillis(sleepMs);
_lastRenderTime = _system->getMillis();
@@ -454,24 +468,24 @@ void ToonEngine::doMagnifierEffect() {
11, 11, 11, 11, 12
};
- byte tempBuffer[25*25];
+ byte tempBuffer[25 * 25];
for (int32 y = -12; y <= 12; y++) {
for (int32 x = -12; x <= 12; x++) {
int32 destPitch = surface.pitch;
uint8 *curRow = (uint8 *)surface.pixels + (posY + y) * destPitch + (posX + x);
- tempBuffer[(y+12) * 25 + x + 12] = *curRow;
+ tempBuffer[(y + 12) * 25 + x + 12] = *curRow;
}
}
for (int32 y = -12; y <= 12; y++) {
for (int32 x = -12; x <= 12; x++) {
int32 dist = y * y + x * x;
- if (dist > 144)
+ if (dist > 144)
continue;
int32 destPitch = surface.pitch;
uint8 *curRow = (uint8 *)surface.pixels + (posY + y) * destPitch + (posX + x);
int32 lerp = (512 + intSqrt[dist] * 256 / 12);
- *curRow = tempBuffer[(y*lerp/1024+12) * 25 + x*lerp/1024 + 12];
+ *curRow = tempBuffer[(y * lerp / 1024 + 12) * 25 + x * lerp / 1024 + 12];
}
}
}
@@ -484,7 +498,50 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
_cursorAnimationInstance->setPosition(_mouseX - 40 + state()->_currentScrollValue - _cursorOffsetX, _mouseY - 40 - _cursorOffsetY, 0, false);
_cursorAnimationInstance->render();
}
- _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, 1280, 0, 0, 640, 400);
+
+ // Handle dirty rects here
+ static int32 lastScroll = 0;
+
+ if (_dirtyAll || _gameState->_currentScrollValue != lastScroll) {
+ // we have to refresh everything in case of scrolling.
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, TOON_BACKBUFFER_WIDTH, 0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ } else {
+
+ int32 offX = 0;
+ for (uint i = 0; i < _oldDirtyRects.size(); i++) {
+ Common::Rect rect = _oldDirtyRects[i];
+ rect.translate(-state()->_currentScrollValue, 0);
+ offX = 0;
+ if(rect.right <= 0)
+ continue;
+ if (rect.left < 0) {
+ offX = -rect.left;
+ rect.left = 0;
+ }
+ rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + _oldDirtyRects[i].left + offX + _oldDirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+
+ for (uint i = 0; i < _dirtyRects.size(); i++) {
+ Common::Rect rect = _dirtyRects[i];
+ rect.translate(-state()->_currentScrollValue, 0);
+ offX = 0;
+ if (rect.right <= 0)
+ continue;
+ if (rect.left < 0) {
+ offX = -rect.left;
+ rect.left = 0;
+ }
+ rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + _dirtyRects[i].left + offX + _dirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+ }
+ lastScroll = _gameState->_currentScrollValue;
+
if (updateScreen) {
_system->updateScreen();
_shouldQuit = shouldQuit(); // update game quit flag - this shouldn't be called all the time, as it's a virtual function
@@ -589,6 +646,7 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
bool musicPlaying = false;
_gameState->_inMenu = true;
+ dirtyAllScreen();
while (!doExit) {
clickingOn = MAINMENUHOTSPOT_NONE;
@@ -607,7 +665,15 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
}
while (!clickRelease) {
- mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+
+ if(_dirtyAll) {
+ mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ addDirtyRect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ } else {
+ mainmenuPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ }
+
+ clearDirtyRects();
for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++) {
if (entries[entryNr].menuMask & menuMask) {
@@ -719,7 +785,7 @@ Common::Error ToonEngine::run() {
g_eventRec.registerRandomSource(_rnd, "toon");
- initGraphics(640, 400, true);
+ initGraphics(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT, true);
init();
// do we need to load directly a game?
@@ -783,6 +849,7 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
_backupPalette = NULL;
_additionalPalette1 = NULL;
_additionalPalette2 = NULL;
+ _additionalPalette2Present = false;
_cutawayPalette = NULL;
_universalPalette = NULL;
_fluxPalette = NULL;
@@ -817,7 +884,20 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
_inventoryIcons = NULL;
_inventoryIconSlots = NULL;
_genericTexts = NULL;
- _audioManager = NULL;
+ _audioManager = NULL;
+ _gameState = NULL;
+
+ _locationDirNotVisited = NULL;
+ _locationDirVisited = NULL;
+ _specialInfoLine = NULL;
+
+ for (int i = 0; i < 64; i++) {
+ _sceneAnimations[i]._active = false;
+ }
+
+ for (int i = 0; i < 32; i++) {
+ _characters[i] = NULL;
+ }
memset(&_scriptData, 0, sizeof(EMCData));
@@ -859,7 +939,7 @@ ToonEngine::~ToonEngine() {
_mainSurface->free();
delete _mainSurface;
}
-
+
delete[] _finalPalette;
delete[] _backupPalette;
delete[] _additionalPalette1;
@@ -888,7 +968,6 @@ ToonEngine::~ToonEngine() {
delete _pathFinding;
-
for (int32 i = 0; i < 64; i++) {
if (_sceneAnimations[i]._active) {
// see if one character shares this instance
@@ -950,8 +1029,6 @@ void ToonEngine::simpleUpdate(bool waitCharacterToTalk) {
_animationManager->update(elapsedTime);
_audioManager->updateAmbientSFX();
render();
-
-
}
void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
@@ -967,13 +1044,8 @@ void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
// adapted from KyraEngine
void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
-
-
static int32 numReentrant = 0;
numReentrant++;
-
-// Strangerke - Commented (not used)
-// uint32 nextTime = _system->getMillis() + _tickLength;
const int startScript = _lastProcessedSceneScript;
_updatingSceneScriptRunFlag = true;
@@ -1006,10 +1078,8 @@ void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
} while (_lastProcessedSceneScript != startScript && !_shouldQuit);
-
_updatingSceneScriptRunFlag = false;
numReentrant--;
-
}
void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
@@ -1077,15 +1147,15 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
_mouseButton = 0;
_lastMouseButton = 0x3;
-
// load package
strcpy(temp, createRoomFilename(Common::String::format("%s.PAK", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
- resources()->openPackage(temp, true);
+ resources()->openPackage(temp);
strcpy(temp, state()->_locations[SceneId]._name);
strcat(temp, ".NPP");
loadAdditionalPalette(temp, 0);
+ _additionalPalette2Present = false;
strcpy(temp, state()->_locations[SceneId]._name);
strcat(temp, ".NP2");
loadAdditionalPalette(temp, 1);
@@ -1198,6 +1268,9 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
state()->_mouseHidden = false;
+ clearDirtyRects();
+ dirtyAllScreen();
+
if (!forGameLoad) {
_script->start(&_scriptState[0], 0);
@@ -1215,7 +1288,7 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
_gameState->_nextSpecialEnterX = -1;
_gameState->_nextSpecialEnterY = -1;
}
-
+
_script->start(&_scriptState[0], 3);
while (_script->run(&_scriptState[0]))
@@ -1253,10 +1326,11 @@ void ToonEngine::loadAdditionalPalette(Common::String fileName, int32 mode) {
case 1:
memcpy(_additionalPalette2, palette, 69);
fixPaletteEntries(_additionalPalette2, 23);
+ _additionalPalette2Present = true;
break;
case 2:
- memcpy(_cutawayPalette, palette, 768);
- fixPaletteEntries(_cutawayPalette, 256);
+ memcpy(_cutawayPalette, palette, size);
+ fixPaletteEntries(_cutawayPalette, size/3);
break;
case 3:
memcpy(_universalPalette, palette, 96);
@@ -1290,7 +1364,6 @@ void ToonEngine::initChapter() {
_script->unload(&data);
setupGeneralPalette();
-
}
void ToonEngine::loadCursor() {
@@ -1412,10 +1485,9 @@ void ToonEngine::clickEvent() {
return;
}
-
int32 mouseX = _mouseX;
if (_gameState->_inCutaway) {
- mouseX += 1280;
+ mouseX += TOON_BACKBUFFER_WIDTH;
}
// find hotspot
@@ -1443,7 +1515,6 @@ void ToonEngine::clickEvent() {
}
}
-
if (!currentHot) {
int32 xx, yy;
@@ -1471,9 +1542,6 @@ void ToonEngine::clickEvent() {
int16 command = currentHot->getData(commandId);
int16 argument = currentHot->getData(commandId + 1);
int16 priority = currentHot->getPriority();
-// Strangerke - Commented (not used)
-// int16 ref = currentHot->getRef();
-// int16 pad1 = currentHot->getData(6);
if (!_gameState->_inCutaway && !_gameState->_inCloseUp) {
if (leftButton && (currentHot->getData(4) != 2 || _gameState->_mouseState >= 0) && currentHot->getData(5) != -1) {
@@ -1515,8 +1583,6 @@ void ToonEngine::clickEvent() {
break;
case 7:
// switch to CloseUp
-// Strangerke - Commented (not used)
-// int closeup = 1;
break;
case 8:
// face flux
@@ -1524,11 +1590,6 @@ void ToonEngine::clickEvent() {
break;
case 9:
case 10:
-// Strangerke - Commented (not used)
-// if (rand() % 1 == 1) {
-// } else {
-// }
- // setFluxFacingPoint(x,y)
sayLines(2, argument);
break;
case 11:
@@ -1552,7 +1613,6 @@ void ToonEngine::clickEvent() {
int32 val = _scriptState[_currentScriptRegion].regs[4];
currentHot->setData(4, currentHot->getData(4) & val);
}
-
}
void ToonEngine::selectHotspot() {
@@ -1564,7 +1624,7 @@ void ToonEngine::selectHotspot() {
int32 mouseX = _mouseX;
if (_gameState->_inCutaway)
- mouseX += 1280;
+ mouseX += TOON_BACKBUFFER_WIDTH;
if (_gameState->_sackVisible) {
if (_mouseX > 0 && _mouseX < 40 && _mouseY > 356 && _mouseY < 396) {
@@ -1722,7 +1782,6 @@ void ToonEngine::exitScene() {
strcpy(temp, createRoomFilename(Common::String::format("%s.PAK", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
resources()->closePackage(temp);
-
_drew->stopWalk();
_flux->stopWalk();
@@ -1734,9 +1793,10 @@ void ToonEngine::flipScreens() {
_gameState->_inCloseUp = !_gameState->_inCloseUp;
if (_gameState->_inCloseUp) {
- _gameState->_currentScrollValue = 640;
+ _gameState->_currentScrollValue = TOON_SCREEN_WIDTH;
setPaletteEntries(_cutawayPalette, 1, 128);
- setPaletteEntries(_additionalPalette2, 232, 23);
+ if (_additionalPalette2Present)
+ setPaletteEntries(_additionalPalette2, 232, 23);
} else {
_gameState->_currentScrollValue = 0;
_currentPicture->setupPalette();
@@ -1750,9 +1810,9 @@ void ToonEngine::fadeIn(int32 numFrames) {
uint8 vmpalette[3 * 256];
for (int32 i = 0; i < 256; i++) {
- vmpalette[i*3+0] = f * _finalPalette[i*3+0] / (numFrames - 1);
- vmpalette[i*3+1] = f * _finalPalette[i*3+1] / (numFrames - 1);
- vmpalette[i*3+2] = f * _finalPalette[i*3+2] / (numFrames - 1);
+ vmpalette[i * 3 + 0] = f * _finalPalette[i * 3 + 0] / (numFrames - 1);
+ vmpalette[i * 3 + 1] = f * _finalPalette[i * 3 + 1] / (numFrames - 1);
+ vmpalette[i * 3 + 2] = f * _finalPalette[i * 3 + 2] / (numFrames - 1);
}
_system->getPaletteManager()->setPalette(vmpalette, 0, 256);
_system->updateScreen();
@@ -1768,9 +1828,9 @@ void ToonEngine::fadeOut(int32 numFrames) {
for (int32 f = 0; f < numFrames; f++) {
uint8 vmpalette[3 * 256];
for (int32 i = 0; i < 256; i++) {
- vmpalette[i*3+0] = (numFrames - f - 1) * oldpalette[i*3+0] / (numFrames - 1);
- vmpalette[i*3+1] = (numFrames - f - 1) * oldpalette[i*3+1] / (numFrames - 1);
- vmpalette[i*3+2] = (numFrames - f - 1) * oldpalette[i*3+2] / (numFrames - 1);
+ vmpalette[i * 3 + 0] = (numFrames - f - 1) * oldpalette[i * 3 + 0] / (numFrames - 1);
+ vmpalette[i * 3 + 1] = (numFrames - f - 1) * oldpalette[i * 3 + 1] / (numFrames - 1);
+ vmpalette[i * 3 + 2] = (numFrames - f - 1) * oldpalette[i * 3 + 2] / (numFrames - 1);
}
_system->getPaletteManager()->setPalette(vmpalette, 0, 256);
_system->updateScreen();
@@ -1824,11 +1884,11 @@ int32 ToonEngine::getScaleAtPoint(int32 x, int32 y) {
return 1024;
// clamp values
- x = MIN<int32>(1279, MAX<int32>(0, x));
- y = MIN<int32>(399, MAX<int32>(0, y));
+ x = MIN<int32>(TOON_BACKBUFFER_WIDTH - 1, MAX<int32>(0, x));
+ y = MIN<int32>(TOON_BACKBUFFER_HEIGHT - 1, MAX<int32>(0, y));
int32 maskData = _currentMask->getData(x, y) & 0x1f;
- return _roomScaleData[maskData+2] * 1024 / 100;
+ return _roomScaleData[maskData + 2] * 1024 / 100;
}
int32 ToonEngine::getLayerAtPoint(int32 x, int32 y) {
@@ -1836,11 +1896,11 @@ int32 ToonEngine::getLayerAtPoint(int32 x, int32 y) {
return 0;
// clamp values
- x = MIN<int32>(1279, MAX<int32>(0, x));
- y = MIN<int32>(399, MAX<int32>(0, y));
+ x = MIN<int32>(TOON_BACKBUFFER_WIDTH - 1, MAX<int32>(0, x));
+ y = MIN<int32>(TOON_BACKBUFFER_HEIGHT - 1, MAX<int32>(0, y));
int32 maskData = _currentMask->getData(x, y) & 0x1f;
- return _roomScaleData[maskData+130] << 5;
+ return _roomScaleData[maskData + 130] << 5;
}
int32 ToonEngine::getZAtPoint(int32 x, int32 y) {
@@ -1917,25 +1977,11 @@ void ToonEngine::sayLines(int numLines, int dialogId) {
if (oldShowMouse)
Game.MouseHiddenCount = 0;
#endif
-
}
int32 ToonEngine::simpleCharacterTalk(int32 dialogid) {
int32 myId = 0;
-// Strangerke - Commented (not used)
-#if 0
- char *myLine;
- if (dialogid < 1000) {
- myLine = _roomTexts->getText(dialogid);
- myId = dialogid;
- } else {
- myLine = _genericTexts->getText(dialogid - 1000);
- myId = dialogid - 1000;
- }
- debugC(0, 0xfff, "Talker = %d will say '%s' \n", READ_LE_UINT16(c - 2), myLine);
-#endif
-
if (_audioManager->voiceStillPlaying())
_audioManager->stopCurrentVoice();
@@ -1952,14 +1998,6 @@ int32 ToonEngine::simpleCharacterTalk(int32 dialogid) {
void ToonEngine::playTalkAnimOnCharacter(int32 animID, int32 characterId, bool talker) {
if (animID || talker) {
-// Strangerke - Commented (not used)
-#if 0
- if (_gameState->_inCutaway || _gameState->_inInventory) {
- if (talker) {
- // character talks
- }
- } else
-#endif
if (characterId == 0) {
_drew->playAnim(animID, 0, (talker ? 8 : 0) + 2);
} else if (characterId == 1) {
@@ -2009,7 +2047,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
_gameState->_mouseHidden = true;
}
-
// get what is before the string
int a = READ_LE_UINT16(myLine - 2);
char *b = myLine - 2 - 4 * a;
@@ -2020,14 +2057,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
char *e = c - 2 - 4 * numParticipants;
READ_LE_UINT16(e);
-// Strangerke - Commented (not used)
-// char *g = e - 2 * f;
-
- // flag as talking
-// Strangerke - Commented (not used)
-// char *h = c;
-
-
// if one voice is still playing, wait !
if (blocking) {
while (_audioManager->voiceStillPlaying() && !_shouldQuit)
@@ -2085,8 +2114,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
_currentTextLine = myLine;
_currentTextLineCharacterId = talkerId;
_currentTextLineId = dialogid;
-
-
} else {
Character *character = getCharacterById(talkerId);
if (character)
@@ -2095,7 +2122,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
debugC(0, 0xfff, "Talker = %d (num participants : %d) will say '%s'", (int)talkerId , (int)numParticipants, myLine);
-
getTextPosition(talkerId, &_currentTextLineX, &_currentTextLineY);
if (dialogid < 1000) {
@@ -2115,8 +2141,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
if (character)
character->setTalking(false);
}
-
-
return 1;
}
@@ -2131,7 +2155,7 @@ void ToonEngine::haveAConversation(int32 convId) {
_gameState->_currentConversationId = convId;
// change the music to the "conversation" music if needed.
- playRoomMusic();
+ playRoomMusic();
if (conv->_enable) {
// fix dialog script based on new flags
@@ -2149,7 +2173,6 @@ void ToonEngine::haveAConversation(int32 convId) {
doFrame();
}
-
_mouseButton = 0;
_gameState->_firstConverstationLine = true;
@@ -2178,11 +2201,13 @@ void ToonEngine::haveAConversation(int32 convId) {
a++;
}
}
- if (_shouldQuit) return;
+
+ if (_shouldQuit)
+ return;
+
_gameState->_showConversationIcons = false;
_gameState->_mouseHidden = 1;
-
if (selected < 0 || selected == 1 || selected == 3) {
if (_gameState->_firstConverstationLine)
processConversationClick(conv, 3);
@@ -2194,9 +2219,6 @@ void ToonEngine::haveAConversation(int32 convId) {
}
}
-// Strangerke - Commented (not used)
-// int cur = 0;
-
for (int i = 0; i < 10; i++) {
if (conv->state[i]._data2 == 2) {
if (i != 3)
@@ -2211,8 +2233,7 @@ void ToonEngine::haveAConversation(int32 convId) {
_gameState->_sackVisible = true;
// switch back to original music
- playRoomMusic();
-
+ playRoomMusic();
}
void ToonEngine::drawConversationIcons() {
@@ -2334,7 +2355,6 @@ retry:
break;
}
}
-
}
// hardcoded conversation flag to know if one dialogue icon must be displayed or not
@@ -2495,7 +2515,7 @@ int32 ToonEngine::runConversationCommand(int16 **command) {
int16 *v5 = *command;
int v2 = READ_LE_INT16(v5);
- int v4 = READ_LE_INT16(v5+1);
+ int v4 = READ_LE_INT16(v5 + 1);
int result = v2 - 100;
switch (v2) {
case 100:
@@ -2528,9 +2548,6 @@ int32 ToonEngine::runConversationCommand(int16 **command) {
}
int32 ToonEngine::waitTicks(int32 numTicks, bool breakOnMouseClick) {
-// Strangerke - Commented (not used)
-// Common::EventManager *_event = _system->getEventManager();
-
uint32 nextTime = _system->getMillis() + numTicks * _tickLength;
while (_system->getMillis() < nextTime || numTicks == -1) {
//if (!_animationSceneScriptRunFlag)
@@ -2549,7 +2566,13 @@ void ToonEngine::renderInventory() {
if (!_gameState->_inInventory)
return;
- _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ if (!_dirtyAll) {
+ _inventoryPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ } else {
+ _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT));
+ }
+ clearDirtyRects();
// draw items on screen
for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
@@ -2577,13 +2600,13 @@ void ToonEngine::renderInventory() {
int32 ToonEngine::showInventory() {
int32 oldScrollValue = _gameState->_currentScrollValue;
-// Strangerke - Commented (not used)
-// Common::EventManager *_event = _system->getEventManager();
+
delete _inventoryPicture;
_inventoryPicture = new Picture(this);
fadeOut(5);
_inventoryPicture->loadPicture("SACK128.CPS", true);
_inventoryPicture->setupPalette();
+ dirtyAllScreen();
if (_gameState->_mouseState >= 0) {
setCursor(_gameState->_mouseState, true, -18, -14);
@@ -2632,7 +2655,6 @@ int32 ToonEngine::showInventory() {
int32 modItem = getSpecialInventoryItem(item);
if (modItem) {
-
if (modItem == -1) {
_gameState->_mouseState = item;
_gameState->_inventory[foundObj] = 0;
@@ -2681,7 +2703,7 @@ int32 ToonEngine::showInventory() {
}
_gameState->_currentScrollValue = oldScrollValue;
- _gameState->_inInventory = false;
+ _gameState->_inInventory = false;
_mouseButton = 0;
_lastMouseButton = 0x3;
@@ -2697,6 +2719,7 @@ int32 ToonEngine::showInventory() {
setupGeneralPalette();
}
flushPalette();
+ dirtyAllScreen();
_firstFrame = true;
return 0;
@@ -2771,6 +2794,7 @@ void ToonEngine::showCutaway(Common::String cutawayPicture) {
_currentCutaway->setupPalette();
_oldScrollValue = _gameState->_currentScrollValue;
_gameState->_currentScrollValue = 0;
+ dirtyAllScreen();
flushPalette();
}
@@ -2781,6 +2805,7 @@ void ToonEngine::hideCutaway() {
_gameState->_currentScrollValue = _oldScrollValue;
_currentCutaway = 0;
_currentPicture->setupPalette();
+ dirtyAllScreen();
flushPalette();
}
@@ -2805,7 +2830,7 @@ void ToonEngine::rearrangeInventory() {
if (_gameState->_inventory[i] == 0) {
// move all the following items from one
for (int32 j = i + 1; j < _gameState->_numInventoryItems; j++) {
- _gameState->_inventory[j-1] = _gameState->_inventory[j];
+ _gameState->_inventory[j - 1] = _gameState->_inventory[j];
}
_gameState->_numInventoryItems--;
}
@@ -2819,14 +2844,14 @@ void ToonEngine::newGame() {
addItemToInventory(67);
addItemToInventory(11);
addItemToInventory(19);
- loadScene(_gameState->_currentScene);
+ loadScene(22);
+ //loadScene(_gameState->_currentScene);
} else {
//loadScene(4);
loadScene(_gameState->_currentScene);
}
}
-
void ToonEngine::playSFX(int32 id, int32 volume) {
if (id < 0)
_audioManager->playSFX(-id + 1, volume, true);
@@ -2852,7 +2877,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
// drew
int32 x = _drew->getX();
int32 y = _drew->getY();
- if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + 640) {
+ if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
if (!_gameState->_inCutaway && !_gameState->_inInventory) {
*retX = x;
*retY = y - ((_drew->getScale() * 256 / 1024) >> 1) - 45;
@@ -2862,7 +2887,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
// flux
int32 x = _flux->getX();
int32 y = _flux->getY();
- if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + 640) {
+ if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
if (!_gameState->_inCutaway) {
*retX = x;
*retY = y - ((_drew->getScale() * 100 / 1024) >> 1) - 30;
@@ -2892,7 +2917,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
Character *character = getCharacterById(characterId);
if (character && !_gameState->_inCutaway) {
if (character->getAnimationInstance()) {
- if (character->getX() >= _gameState->_currentScrollValue && character->getX() <= _gameState->_currentScrollValue + 640) {
+ if (character->getX() >= _gameState->_currentScrollValue && character->getX() <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
int32 x1, y1, x2, y2;
character->getAnimationInstance()->getRect(&x1, &y1, &x2, &y2);
*retX = (x1 + x2) / 2;
@@ -2921,7 +2946,7 @@ void ToonEngine::drawConversationLine() {
}
void ToonEngine::pauseEngineIntern(bool pause) {
-
+
Engine::pauseEngineIntern(pause);
static int32 pauseStart = 0;
@@ -3013,7 +3038,6 @@ bool ToonEngine::saveGame(int32 slot, Common::String saveGameDesc) {
saveFile->writeUint32BE(saveDate);
saveFile->writeUint16BE(saveTime);
-
// save global state
_gameState->save(saveFile);
_gameState->saveConversations(saveFile);
@@ -3040,7 +3064,6 @@ bool ToonEngine::saveGame(int32 slot, Common::String saveGameDesc) {
_sceneAnimations[i].save(this, saveFile);
}
-
for (int32 i = 0; i < 8; i++) {
if (_characters[i]) {
saveFile->writeSByte(i);
@@ -3120,7 +3143,7 @@ bool ToonEngine::loadGame(int32 slot) {
_sceneAnimationScripts[i]._frozen = loadFile->readByte();
_sceneAnimationScripts[i]._frozenForConversation = false;
int32 oldTimer = loadFile->readSint32BE();
- _sceneAnimationScripts[i]._lastTimer = MAX<int32>(0,oldTimer + timerDiff);
+ _sceneAnimationScripts[i]._lastTimer = MAX<int32>(0, oldTimer + timerDiff);
_script->loadState(&_sceneAnimationScripts[i]._state, loadFile);
}
@@ -3159,7 +3182,7 @@ bool ToonEngine::loadGame(int32 slot) {
// load "command buffer"
int32 size = loadFile->readSint16BE();
if (size) {
- uint8 *buf = new uint8[size+2];
+ uint8 *buf = new uint8[size + 2];
loadFile->read(buf, size + 2);
Common::MemoryReadStream rStr(buf, size + 2);
@@ -3278,10 +3301,6 @@ void ToonEngine::initCharacter(int32 characterId, int32 animScriptId, int32 scen
return;
}
-// Strangerke - Commented (not used)
-// if (_characters[characterIndex])
-// delete current char
-
_characters[characterIndex] = new Character(this);
_characters[characterIndex]->setId(characterId);
_characters[characterIndex]->setAnimScript(animScriptId);
@@ -3405,6 +3424,7 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
Picture *pic = new Picture(this);
pic->loadPicture(str, false);
pic->setupPalette();
+ dirtyAllScreen();
flushPalette();
if (lineId) {
@@ -3428,7 +3448,13 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
break;
}
- pic->draw(*_mainSurface, 0, 0, 0, 0);
+ if (!_dirtyAll) {
+ pic->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ } else {
+ pic->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT));
+ }
+ clearDirtyRects();
drawConversationLine();
if (!_audioManager->voiceStillPlaying()) {
@@ -3447,11 +3473,11 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
}
fadeOut(5);
+ dirtyAllScreen();
restorePalette();
_firstFrame = true;
_gameState->_currentScrollValue = oldScrollValue;
delete pic;
-
}
int32 ToonEngine::handleInventoryOnInventory(int32 itemDest, int32 itemSrc) {
@@ -3493,7 +3519,7 @@ int32 ToonEngine::handleInventoryOnInventory(int32 itemDest, int32 itemSrc) {
case 11:
if (itemSrc == 0xb) {
_gameState->_mouseState = -1;
- replaceItemFromInventory(11,12);
+ replaceItemFromInventory(11, 12);
setCursor(0, false, 0, 0);
rearrangeInventory();
return 1;
@@ -4506,9 +4532,9 @@ void ToonEngine::createShadowLUT() {
for (int32 i = 0; i < 255; i++) {
// goal color
- uint32 destR = _finalPalette[i*3+0] * scaleNum / scaleDenom;
- uint32 destG = _finalPalette[i*3+1] * scaleNum / scaleDenom;
- uint32 destB = _finalPalette[i*3+2] * scaleNum / scaleDenom;
+ uint32 destR = _finalPalette[i * 3 + 0] * scaleNum / scaleDenom;
+ uint32 destG = _finalPalette[i * 3 + 1] * scaleNum / scaleDenom;
+ uint32 destB = _finalPalette[i * 3 + 2] * scaleNum / scaleDenom;
// search only in the "picture palette" which is in colors 1-128 and 200-255
int32 colorDist = 0xffffff;
@@ -4516,9 +4542,9 @@ void ToonEngine::createShadowLUT() {
for (int32 c = 1; c < 129; c++) {
- int32 diffR = _finalPalette[c*3+0] - destR;
- int32 diffG = _finalPalette[c*3+1] - destG;
- int32 diffB = _finalPalette[c*3+2] - destB;
+ int32 diffR = _finalPalette[c * 3 + 0] - destR;
+ int32 diffG = _finalPalette[c * 3 + 1] - destG;
+ int32 diffB = _finalPalette[c * 3 + 2] - destB;
if (colorDist > diffR * diffR + diffG * diffG + diffB * diffB) {
colorDist = diffR * diffR + diffG * diffG + diffB * diffB;
@@ -4528,9 +4554,9 @@ void ToonEngine::createShadowLUT() {
for (int32 c = 200; c < 256; c++) {
- int32 diffR = _finalPalette[c*3+0] - destR;
- int32 diffG = _finalPalette[c*3+1] - destG;
- int32 diffB = _finalPalette[c*3+2] - destB;
+ int32 diffR = _finalPalette[c * 3 + 0] - destR;
+ int32 diffG = _finalPalette[c * 3 + 1] - destG;
+ int32 diffB = _finalPalette[c * 3 + 2] - destB;
if (colorDist > diffR * diffR + diffG * diffG + diffB * diffB) {
colorDist = diffR * diffR + diffG * diffG + diffB * diffB;
@@ -4660,6 +4686,47 @@ void ToonEngine::playRoomMusic() {
_audioManager->playMusic(_gameState->_locations[_gameState->_currentScene]._name, _gameState->_locations[_gameState->_currentScene]._music);
}
+void ToonEngine::dirtyAllScreen()
+{
+ _dirtyRects.clear();
+ _dirtyAll = true;
+}
+
+void ToonEngine::addDirtyRect( int32 left, int32 top, int32 right, int32 bottom ) {
+ left = MIN<int32>(MAX<int32>(left, 0), TOON_BACKBUFFER_WIDTH);
+ right = MIN<int32>(MAX<int32>(right, 0), TOON_BACKBUFFER_WIDTH);
+ top = MIN<int32>(MAX<int32>(top, 0), TOON_BACKBUFFER_HEIGHT);
+ bottom = MIN<int32>(MAX<int32>(bottom, 0), TOON_BACKBUFFER_HEIGHT);
+
+ Common::Rect rect(left, top, right, bottom);
+
+ if (bottom - top <= 0 || right - left <= 0)
+ return;
+
+ for (uint32 i = 0; i < _dirtyRects.size(); i++) {
+ if (_dirtyRects[i].contains(rect))
+ return;
+ if (rect.contains(_dirtyRects[i])) {
+ _dirtyRects.remove_at(i);
+ i--;
+ }
+ }
+
+ // check also in the old rect (of the old frame)
+ for (int32 i = _oldDirtyRects.size() - 1 ; i >= 0; i--) {
+ if (rect.contains(_oldDirtyRects[i])) {
+ _oldDirtyRects.remove_at(i);
+ }
+ }
+
+ _dirtyRects.push_back(rect);
+}
+
+void ToonEngine::clearDirtyRects() {
+ _oldDirtyRects = _dirtyRects;
+ _dirtyRects.clear();
+ _dirtyAll = false;
+}
void SceneAnimation::save(ToonEngine *vm, Common::WriteStream *stream) {
stream->writeByte(_active);
stream->writeSint32BE(_id);
@@ -4686,7 +4753,6 @@ void SceneAnimation::load(ToonEngine *vm, Common::ReadStream *stream) {
_active = stream->readByte();
_id = stream->readSint32BE();
-
if (!_active)
return;
diff --git a/engines/toon/toon.h b/engines/toon/toon.h
index f3370aed5e..373437d658 100644
--- a/engines/toon/toon.h
+++ b/engines/toon/toon.h
@@ -52,6 +52,11 @@ class MemoryWriteStreamDynamic;
#define TOON_SAVEGAME_VERSION 4
#define DATAALIGNMENT 4
+#define TOON_SCREEN_WIDTH 640
+#define TOON_SCREEN_HEIGHT 400
+#define TOON_BACKBUFFER_WIDTH 1280
+#define TOON_BACKBUFFER_HEIGHT 400
+
/**
* This is the namespace of the Toon engine.
*
@@ -206,8 +211,6 @@ public:
void waitForScriptStep();
void doMagnifierEffect();
-
-
bool canSaveGameStateCurrently();
bool canLoadGameStateCurrently();
void pauseEngineIntern(bool pause);
@@ -334,6 +337,10 @@ public:
(f == kSupportsSavingDuringRuntime);
}
+ void dirtyAllScreen();
+ void addDirtyRect(int32 left, int32 top, int32 right, int32 bottom);
+ void clearDirtyRects();
+
protected:
OSystem *_system;
int32 _tickLength;
@@ -345,6 +352,7 @@ protected:
uint8 *_backupPalette;
uint8 *_additionalPalette1;
uint8 *_additionalPalette2;
+ bool _additionalPalette2Present;
uint8 *_cutawayPalette;
uint8 *_universalPalette;
uint8 *_fluxPalette;
@@ -371,6 +379,11 @@ protected:
bool _updatingSceneScriptRunFlag;
Graphics::Surface *_mainSurface;
+ Common::Array<Common::Rect> _dirtyRects;
+ Common::Array<Common::Rect> _oldDirtyRects;
+
+ bool _dirtyAll;
+
AnimationInstance *_cursorAnimationInstance;
Animation *_cursorAnimation;
diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp
index 52967c25c7..eb10c61893 100644
--- a/engines/touche/menu.cpp
+++ b/engines/touche/menu.cpp
@@ -331,14 +331,14 @@ void ToucheEngine::handleMenuAction(void *menu, int actionId) {
break;
case kActionPerformSaveLoad:
if (menuData->mode == kMenuLoadStateMode) {
- if (loadGameState(_saveLoadCurrentSlot) == Common::kNoError) {
+ if (loadGameState(_saveLoadCurrentSlot).getCode() == Common::kNoError) {
menuData->quit = true;
}
} else if (menuData->mode == kMenuSaveStateMode) {
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
const char *description = menuData->saveLoadDescriptionsTable[_saveLoadCurrentSlot];
if (strlen(description) > 0) {
- if (saveGameState(_saveLoadCurrentSlot, description) == Common::kNoError) {
+ if (saveGameState(_saveLoadCurrentSlot, description).getCode() == Common::kNoError) {
menuData->quit = true;
}
}
diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp
index 0b15643767..c89375d876 100644
--- a/engines/touche/midi.cpp
+++ b/engines/touche/midi.cpp
@@ -32,143 +32,83 @@
namespace Touche {
-MidiPlayer::MidiPlayer()
- : _driver(0), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0) {
- memset(_channelsTable, 0, sizeof(_channelsTable));
+static const uint8 _gmToRol[256] = {
+ 0x01, 0x02, 0x03, 0x08, 0x04, 0x05, 0x11, 0x14, 0x66, 0x66, 0x66, 0x62, 0x69, 0x68, 0x67, 0x26,
+ 0x09, 0x0A, 0x0B, 0x0E, 0x0F, 0x10, 0x10, 0x10, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D, 0x3E, 0x3F, 0x3F,
+ 0x47, 0x41, 0x42, 0x48, 0x45, 0x46, 0x1D, 0x1E, 0x35, 0x36, 0x37, 0x39, 0x33, 0x34, 0x3A, 0x71,
+ 0x31, 0x32, 0x31, 0x32, 0x23, 0x23, 0x23, 0x7B, 0x59, 0x5B, 0x5F, 0x5A, 0x5D, 0x60, 0x19, 0x1A,
+ 0x4F, 0x50, 0x51, 0x52, 0x55, 0x56, 0x57, 0x53, 0x4B, 0x49, 0x4D, 0x4E, 0x6F, 0x6C, 0x6D, 0x6E,
+ 0x30, 0x19, 0x4E, 0x2B, 0x28, 0x23, 0x19, 0x30, 0x21, 0x25, 0x1C, 0x21, 0x24, 0x22, 0x21, 0x22,
+ 0x2A, 0x25, 0x24, 0x26, 0x2E, 0x22, 0x29, 0x21, 0x40, 0x40, 0x6A, 0x6A, 0x68, 0x10, 0x35, 0x10,
+ 0x7F, 0x6B, 0x69, 0x75, 0x76, 0x72, 0x74, 0x01, 0x01, 0x70, 0x01, 0x7D, 0x7C, 0x01, 0x01, 0x01
+};
+
+
+MidiPlayer::MidiPlayer() {
+
+ // FIXME: Necessary?
memset(_channelsVolume, 0, sizeof(_channelsVolume));
- open();
-}
-MidiPlayer::~MidiPlayer() {
- close();
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+ _driver = MidiDriver::createMidi(dev);
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->setTimerCallback(this, &timerCallback);
+
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+ }
}
void MidiPlayer::play(Common::ReadStream &stream, int size, bool loop) {
+ Common::StackLock lock(_mutex);
+
stop();
- _midiData = (uint8 *)malloc(size);
+ _midiData = (byte *)malloc(size);
if (_midiData) {
stream.read(_midiData, size);
- _mutex.lock();
+
+ _parser = MidiParser::createParser_SMF();
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+
_parser->loadMusic(_midiData, size);
_parser->setTrack(0);
_isLooping = loop;
_isPlaying = true;
- _mutex.unlock();
}
}
-void MidiPlayer::stop() {
- _mutex.lock();
- if (_isPlaying) {
- _isPlaying = false;
- _parser->unloadMusic();
- free(_midiData);
- _midiData = 0;
- }
- _mutex.unlock();
-}
-
-void MidiPlayer::updateTimer() {
- _mutex.lock();
- if (_isPlaying) {
- _parser->onTimer();
- }
- _mutex.unlock();
-}
-
void MidiPlayer::adjustVolume(int diff) {
setVolume(_masterVolume + diff);
}
void MidiPlayer::setVolume(int volume) {
+ // FIXME: This is almost identical to Audio::MidiPlayer::setVolume,
+ // the only difference is that this implementation will always
+ // transmit the volume change, even if the current _masterVolume
+ // equals the new master volume. This *could* make a difference in
+ // some situations.
+ // So, we should determine whether Touche requires this behavioral
+ // difference; and maybe also if other engines could benefit from it
+ // (as hypothetically, it might fix some subtle bugs?)
_masterVolume = CLIP(volume, 0, 255);
- _mutex.lock();
- for (int i = 0; i < NUM_CHANNELS; ++i) {
+ Common::StackLock lock(_mutex);
+ for (int i = 0; i < kNumChannels; ++i) {
if (_channelsTable[i]) {
_channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
}
}
- _mutex.unlock();
-}
-
-int MidiPlayer::open() {
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
- _driver = MidiDriver::createMidi(dev);
- int ret = _driver->open();
- if (ret == 0) {
- _parser = MidiParser::createParser_SMF();
- _parser->setMidiDriver(this);
- _parser->setTimerRate(_driver->getBaseTempo());
- _driver->setTimerCallback(this, &timerCallback);
-
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
- }
- return ret;
-}
-
-void MidiPlayer::close() {
- stop();
- _mutex.lock();
- _driver->setTimerCallback(NULL, NULL);
- _driver->close();
- delete _driver;
- _driver = 0;
- _parser->setMidiDriver(NULL);
- delete _parser;
- _mutex.unlock();
}
void MidiPlayer::send(uint32 b) {
- byte volume, ch = (byte)(b & 0xF);
- switch (b & 0xFFF0) {
- case 0x07B0: // volume change
- volume = (byte)((b >> 16) & 0x7F);
- _channelsVolume[ch] = volume;
- volume = volume * _masterVolume / 255;
- b = (b & 0xFF00FFFF) | (volume << 16);
- break;
- case 0x7BB0: // all notes off
- if (!_channelsTable[ch]) {
- // channel not yet allocated, no need to send the event
- return;
- }
- break;
- default:
- if ((b & 0xF0) == 0xC0 && _nativeMT32) { // program change
- b = (b & 0xFFFF00FF) | (_gmToRol[(b >> 8) & 0x7F] << 8);
- }
- break;
- }
- if (!_channelsTable[ch]) {
- _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ if ((b & 0xF0) == 0xC0 && _nativeMT32) { // program change
+ b = (b & 0xFFFF00FF) | (_gmToRol[(b >> 8) & 0x7F] << 8);
}
- if (_channelsTable[ch]) {
- _channelsTable[ch]->send(b);
- }
-}
-
-void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
- switch (type) {
- case 0x2F: // end of Track
- if (_isLooping) {
- _parser->jumpToTick(0);
- } else {
- stop();
- }
- break;
- default:
-// warning("Unhandled meta event: %02x", type);
- break;
- }
-}
-
-void MidiPlayer::timerCallback(void *p) {
- MidiPlayer *player = (MidiPlayer *)p;
- player->updateTimer();
+ Audio::MidiPlayer::send(b);
}
} // Touche namespace
diff --git a/engines/touche/midi.h b/engines/touche/midi.h
index 8e43c12037..bde4950b93 100644
--- a/engines/touche/midi.h
+++ b/engines/touche/midi.h
@@ -29,60 +29,26 @@
#include "common/util.h"
#include "common/mutex.h"
-#include "audio/mididrv.h"
+#include "audio/midiplayer.h"
class MidiParser;
namespace Common {
- class ReadStream;
+class ReadStream;
}
namespace Touche {
-class MidiPlayer : public MidiDriver {
+class MidiPlayer : public Audio::MidiPlayer {
public:
-
- enum {
- NUM_CHANNELS = 16
- };
-
MidiPlayer();
- ~MidiPlayer();
void play(Common::ReadStream &stream, int size, bool loop = false);
- void stop();
- void updateTimer();
void adjustVolume(int diff);
void setVolume(int volume);
- int getVolume() const { return _masterVolume; }
- void setLooping(bool loop) { _isLooping = loop; }
-
- // MidiDriver interface
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
- uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
-private:
-
- static void timerCallback(void *p);
-
- MidiDriver *_driver;
- MidiParser *_parser;
- uint8 *_midiData;
- bool _isLooping;
- bool _isPlaying;
- int _masterVolume;
- bool _nativeMT32;
- MidiChannel *_channelsTable[NUM_CHANNELS];
- uint8 _channelsVolume[NUM_CHANNELS];
- Common::Mutex _mutex;
- static const uint8 _gmToRol[];
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
};
} // namespace Touche
diff --git a/engines/touche/resource.cpp b/engines/touche/resource.cpp
index 3c108e2931..93406dcb8b 100644
--- a/engines/touche/resource.cpp
+++ b/engines/touche/resource.cpp
@@ -24,6 +24,7 @@
*/
+#include "common/textconsole.h"
#include "audio/decoders/flac.h"
#include "audio/mixer.h"
diff --git a/engines/touche/saveload.cpp b/engines/touche/saveload.cpp
index 73817a5a1a..42b68d015c 100644
--- a/engines/touche/saveload.cpp
+++ b/engines/touche/saveload.cpp
@@ -24,6 +24,7 @@
*/
+#include "common/textconsole.h"
#include "common/savefile.h"
#include "touche/graphics.h"
diff --git a/engines/touche/staticres.cpp b/engines/touche/staticres.cpp
index a377a6e45f..74aa7954de 100644
--- a/engines/touche/staticres.cpp
+++ b/engines/touche/staticres.cpp
@@ -1822,15 +1822,4 @@ int Graphics::_fontSize = Graphics::_engFontSize;
const uint8 *Graphics::_fontData = Graphics::_engFontData;
-const uint8 MidiPlayer::_gmToRol[] = {
- 0x01, 0x02, 0x03, 0x08, 0x04, 0x05, 0x11, 0x14, 0x66, 0x66, 0x66, 0x62, 0x69, 0x68, 0x67, 0x26,
- 0x09, 0x0A, 0x0B, 0x0E, 0x0F, 0x10, 0x10, 0x10, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D, 0x3E, 0x3F, 0x3F,
- 0x47, 0x41, 0x42, 0x48, 0x45, 0x46, 0x1D, 0x1E, 0x35, 0x36, 0x37, 0x39, 0x33, 0x34, 0x3A, 0x71,
- 0x31, 0x32, 0x31, 0x32, 0x23, 0x23, 0x23, 0x7B, 0x59, 0x5B, 0x5F, 0x5A, 0x5D, 0x60, 0x19, 0x1A,
- 0x4F, 0x50, 0x51, 0x52, 0x55, 0x56, 0x57, 0x53, 0x4B, 0x49, 0x4D, 0x4E, 0x6F, 0x6C, 0x6D, 0x6E,
- 0x30, 0x19, 0x4E, 0x2B, 0x28, 0x23, 0x19, 0x30, 0x21, 0x25, 0x1C, 0x21, 0x24, 0x22, 0x21, 0x22,
- 0x2A, 0x25, 0x24, 0x26, 0x2E, 0x22, 0x29, 0x21, 0x40, 0x40, 0x6A, 0x6A, 0x68, 0x10, 0x35, 0x10,
- 0x7F, 0x6B, 0x69, 0x75, 0x76, 0x72, 0x74, 0x01, 0x01, 0x70, 0x01, 0x7D, 0x7C, 0x01, 0x01, 0x01
-};
-
} // namespace Touche
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index 97d533f29f..15a2b1c53a 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -28,13 +28,18 @@
#include "common/debug-channels.h"
#include "common/events.h"
#include "common/EventRecorder.h"
-#include "common/file.h"
#include "common/fs.h"
#include "common/system.h"
+#include "common/archive.h"
+#include "common/debug.h"
+#include "common/error.h"
+#include "common/keyboard.h"
+#include "common/textconsole.h"
#include "engines/util.h"
#include "graphics/cursorman.h"
-#include "audio/mididrv.h"
+#include "graphics/palette.h"
+#include "gui/debugger.h"
#include "touche/midi.h"
#include "touche/touche.h"
@@ -44,7 +49,6 @@ namespace Touche {
ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
: Engine(system), _midiPlayer(0), _language(language) {
-
_saveLoadCurrentPage = 0;
_saveLoadCurrentSlot = 0;
_hideInventoryTexts = false;
@@ -103,9 +107,8 @@ Common::Error ToucheEngine::run() {
_midiPlayer = new MidiPlayer;
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ // Setup mixer
+ syncSoundSettings();
res_openDataFile();
res_allocateTables();
@@ -245,10 +248,9 @@ Common::Point ToucheEngine::getMousePos() const {
}
void ToucheEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
readConfigurationSettings();
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
}
void ToucheEngine::mainLoop() {
diff --git a/engines/tsage/converse.cpp b/engines/tsage/converse.cpp
new file mode 100644
index 0000000000..8e36acf2b6
--- /dev/null
+++ b/engines/tsage/converse.cpp
@@ -0,0 +1,953 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/str-array.h"
+
+#include "tsage/tsage.h"
+#include "tsage/globals.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+#define STRIP_WORD_DELAY 30
+
+
+SequenceManager::SequenceManager() : Action() {
+ Common::set_to(&_objectList[0], &_objectList[6], (SceneObject *)NULL);
+ _sequenceData.clear();
+ _field24 = 0;
+ _sequenceOffset = 0;
+ _resNum = 0;
+ _field26 = 0;
+ _objectIndex = 0;
+ _keepActive = false;
+ setup();
+}
+
+void SequenceManager::setup() {
+ _sequenceOffset = 0;
+ _objectIndex = 0;
+ _sceneObject = _objectList[0];
+}
+
+void SequenceManager::synchronise(Serialiser &s) {
+ Action::synchronise(s);
+
+ s.syncAsSint32LE(_resNum);
+ s.syncAsSint32LE(_sequenceOffset);
+ s.syncAsByte(_keepActive);
+ s.syncAsSint32LE(_field24);
+ s.syncAsSint32LE(_field26);
+
+ s.syncAsSint32LE(_objectIndex);
+ SYNC_POINTER(_sceneObject);
+ for (int i = 0; i < 6; ++i)
+ SYNC_POINTER(_objectList[i]);
+
+ int seqSize = _sequenceData.size();
+ s.syncAsUint32LE(seqSize);
+ if (s.isLoading())
+ _sequenceData.resize(seqSize);
+ if (seqSize > 0)
+ s.syncBytes(&_sequenceData[0], seqSize);
+}
+
+void SequenceManager::remove() {
+ if ((!_sequenceData.empty()) && !_keepActive) {
+ _sequenceData.clear();
+ }
+
+ if (_globals->_sceneObjects->contains(&_sceneText))
+ _sceneText.remove();
+
+ Common::set_to(&_objectList[0], &_objectList[6], (SceneObject *)NULL);
+ Action::remove();
+}
+
+void SequenceManager::signal() {
+ if (_globals->_sceneObjects->contains(&_sceneText))
+ _sceneText.hide();
+
+ bool continueFlag = true;
+ while (continueFlag) {
+ if (_sequenceOffset >=_sequenceData.size()) {
+ // Reached the end of the sequence
+ if (!_keepActive)
+ remove();
+ break;
+ }
+
+ uint16 idx = static_cast<uint16>(getNextValue() - 32000);
+ if (idx > 34)
+ continue;
+
+ int16 v1, v2, v3;
+ switch (idx) {
+ case 0:
+ // Stop sequence
+ continueFlag = false;
+ break;
+ case 1:
+ _sceneObject->animate(ANIM_MODE_1, NULL);
+ break;
+ case 2:
+ _sceneObject->animate(ANIM_MODE_2, NULL);
+ break;
+ case 3:
+ _sceneObject->animate(ANIM_MODE_3);
+ break;
+ case 4:
+ v1 = getNextValue();
+ v2 = getNextValue();
+ _sceneObject->animate(ANIM_MODE_8, v1, v2 ? this : NULL);
+ break;
+ case 5:
+ v1 = getNextValue();
+ v2 = getNextValue();
+ _sceneObject->animate(ANIM_MODE_7, v1, v2 ? this : NULL);
+ break;
+ case 6:
+ v2 = getNextValue();
+ _sceneObject->animate(ANIM_MODE_5, v2 ? this : NULL);
+ break;
+ case 7:
+ v2 = getNextValue();
+ _sceneObject->animate(ANIM_MODE_6, v2 ? this : NULL);
+ break;
+ case 8:
+ v1 = getNextValue();
+ v3 = getNextValue();
+ v2 = getNextValue();
+ _sceneObject->animate(ANIM_MODE_4, v1, v3, v2 ? this : NULL);
+ break;
+ case 9:
+ v1 = getNextValue();
+ v3 = getNextValue();
+ v2 = getNextValue();
+ _globals->_sceneManager._scene->_sceneBounds.moveTo(v3, v2);
+ _globals->_sceneManager._scene->loadScene(v1);
+ break;
+ case 10: {
+ int resNum= getNextValue();
+ int lineNum = getNextValue();
+ int color = getNextValue();
+ int xp = getNextValue();
+ int yp = getNextValue();
+ int width = getNextValue();
+ setMessage(resNum, lineNum, color, Common::Point(xp, yp), width);
+ break;
+ }
+ case 11:
+ v1 = getNextValue();
+ v2 = getNextValue();
+ setAction(globalManager(), v2 ? this : NULL, v1, _objectList[0], _objectList[1], _objectList[2], _objectList[3], NULL);
+ break;
+ case 12:
+ v1 = getNextValue();
+ setDelay(v1);
+ break;
+ case 13: {
+ v1 = getNextValue();
+ v3 = getNextValue();
+ v2 = getNextValue();
+ NpcMover *mover = new NpcMover();
+ Common::Point destPos(v1, v3);
+ _sceneObject->addMover(mover, &destPos, v2 ? this : NULL);
+ break;
+ }
+ case 14:
+ v1 = getNextValue();
+ _sceneObject->_numFrames = v1;
+ break;
+ case 15:
+ v1 = getNextValue();
+ _sceneObject->_moveRate = v1;
+ break;
+ case 16:
+ v1 = getNextValue();
+ v2 = getNextValue();
+ _sceneObject->_moveDiff = Common::Point(v1, v2);
+ break;
+ case 17:
+ _sceneObject->hide();
+ break;
+ case 18:
+ _sceneObject->show();
+ break;
+ case 19:
+ v1 = getNextValue();
+ _sceneObject->setVisage(v1);
+ break;
+ case 20:
+ v1 = getNextValue();
+ _sceneObject->setStrip(v1);
+ break;
+ case 21:
+ v1 = getNextValue();
+ _sceneObject->setFrame(v1);
+ break;
+ case 22:
+ v1 = getNextValue();
+ _sceneObject->fixPriority(v1);
+ break;
+ case 23:
+ v1 = getNextValue();
+ _sceneObject->changeZoom(v1);
+ break;
+ case 24:
+ v1 = getNextValue();
+ v2 = getNextValue();
+ v3 = getNextValue();
+ _sceneObject->setPosition(Common::Point(v1, v2), v3);
+ break;
+ case 25: {
+ int yStart = getNextValue();
+ int minPercent = getNextValue();
+ int yEnd = getNextValue();
+ int maxPercent = getNextValue();
+ _globals->_sceneManager._scene->setZoomPercents(yStart, minPercent, yEnd, maxPercent);
+ break;
+ }
+ case 26:
+ v1 = getNextValue();
+ v2 = getNextValue();
+ _soundHandler.startSound(v1, v2 ? this : NULL, 127);
+ break;
+ case 27: {
+ v1 = getNextValue();
+ v3 = getNextValue();
+ v2 = getNextValue();
+ PlayerMover *mover = new PlayerMover();
+ Common::Point destPos(v1, v3);
+ _sceneObject->addMover(mover, &destPos, v2 ? this : NULL);
+ break;
+ }
+ case 28:
+ _objectIndex = getNextValue();
+ assert((_objectIndex >= 0) && (_objectIndex < 6));
+ _sceneObject = _objectList[_objectIndex];
+ assert(_sceneObject);
+ break;
+ case 29:
+ _sceneObject->animate(ANIM_MODE_NONE);
+ break;
+ case 30:
+ v1 = getNextValue();
+ _globals->_scrollFollower = (v1 == -1) ? NULL : _objectList[v1];
+ break;
+ case 31:
+ _sceneObject->setObjectWrapper(new SceneObjectWrapper());
+ break;
+ case 32:
+ _sceneObject->setObjectWrapper(NULL);
+ break;
+ case 33:
+ v1 = getNextValue();
+ if (_keepActive)
+ setDelay(1);
+ else {
+ _sceneText.remove();
+ _globals->_sceneManager._scene->_stripManager.start(v1, this);
+ }
+ break;
+ case 34: {
+ v1 = getNextValue();
+ v2 = getNextValue();
+ int objIndex1 = getNextValue() - 1;
+ int objIndex2 = getNextValue() - 1;
+ int objIndex3 = getNextValue() - 1;
+ int objIndex4 = getNextValue() - 1;
+ int objIndex5 = getNextValue() - 1;
+ int objIndex6 = getNextValue() - 1;
+
+ setAction(globalManager(), v2 ? this : NULL, v1, _objectList[objIndex1], _objectList[objIndex2],
+ _objectList[objIndex3], _objectList[objIndex4], _objectList[objIndex5], _objectList[objIndex6], NULL);
+ break;
+ }
+ default:
+ error("SequenceManager::signal - Unknown action %d at offset %xh", idx, _sequenceOffset - 2);
+ break;
+ }
+ }
+}
+
+void SequenceManager::process(Event &event) {
+ if (((event.eventType == EVENT_BUTTON_DOWN) || (event.eventType == EVENT_KEYPRESS)) &&
+ !event.handled && _globals->_sceneObjects->contains(&_sceneText)) {
+ // Remove the text item
+ _sceneText.remove();
+ setDelay(2);
+ event.handled = true;
+ } else {
+ Action::process(event);
+ }
+}
+
+
+void SequenceManager::attached(EventHandler *newOwner, EventHandler *endHandler, va_list va) {
+ // Get the sequence number to use
+ _resNum = va_arg(va, int);
+
+ byte *seqData = _resourceManager->getResource(RES_SEQUENCE, _resNum, 0);
+ uint seqSize = _vm->_memoryManager.getSize(seqData);
+
+ _sequenceData.resize(seqSize);
+ Common::copy(seqData, seqData + seqSize, &_sequenceData[0]);
+
+ DEALLOCATE(seqData);
+
+ Common::set_to(&_objectList[0], &_objectList[6], (SceneObject *)NULL);
+ for (int idx = 0; idx < 6; ++idx) {
+ _objectList[idx] = va_arg(va, SceneObject *);
+ if (!_objectList[idx])
+ break;
+ }
+
+ setup();
+ Action::attached(newOwner, endHandler, va);
+}
+
+/**
+ * Returns the next Id in the sequence
+ */
+uint16 SequenceManager::getNextValue() {
+ uint16 result = READ_LE_UINT16(&_sequenceData[0] + _sequenceOffset);
+ _sequenceOffset += 2;
+ return result;
+}
+
+void SequenceManager::setMessage(int resNum, int lineNum, int color, const Common::Point &pt, int width) {
+ _sceneText._color1 = color;
+ _sceneText._color2 = 0;
+ _sceneText._color3 = 0;
+ _sceneText._fontNumber = 2;
+ _sceneText._width = width;
+
+ // Get the display message
+ Common::String msg = _resourceManager->getMessage(resNum, lineNum);
+
+ // Get the needed rect, and move it to the desired position
+ Rect textRect;
+ _globals->gfxManager().getStringBounds(msg.c_str(), textRect, width);
+ Rect sceneBounds = _globals->_sceneManager._scene->_sceneBounds;
+ sceneBounds.collapse(4, 2);
+ textRect.moveTo(pt);
+ textRect.contain(sceneBounds);
+
+ // Set the text message
+ _sceneText.setup(msg);
+ _sceneText.setPosition(Common::Point(textRect.left, textRect.top));
+ _sceneText.fixPriority(255);
+ _sceneText.show();
+
+ // Set the delay based on the number of words
+ int numWords = 0;
+ const char *msgP = msg.c_str();
+ while (*msgP) {
+ if (*msgP++ == ' ')
+ ++numWords;
+ }
+
+ setDelay(numWords * 18 + 120);
+}
+
+SequenceManager *SequenceManager::globalManager() {
+ return &_globals->_sequenceManager;
+}
+
+/*--------------------------------------------------------------------------*/
+
+ConversationChoiceDialog::ConversationChoiceDialog() {
+ _stdColor = 23;
+ _highlightColor = _globals->_scenePalette._colors.background;
+ _fontNumber = 1;
+}
+
+int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) {
+ _gfxManager._font.setFontNumber(_fontNumber);
+
+ _bounds = Rect(20, 0, 20, 0);
+ _choiceList.clear();
+
+ // Set up the list of choices
+ int yp = 0;
+ for (uint idx = 0; idx < choiceList.size(); ++idx) {
+ Rect tempRect;
+ _gfxManager._font.getStringBounds(choiceList[idx].c_str(), tempRect, 265);
+ tempRect.moveTo(25, yp + 10);
+
+ _choiceList.push_back(ChoiceEntry(choiceList[idx], tempRect));
+ yp += tempRect.height() + 5;
+ _bounds.extend(tempRect);
+ }
+ _selectedIndex = _choiceList.size();
+
+ // Set the position for the dialog
+ _bounds.bottom -= 10;
+ yp = 180 - _bounds.height();
+ _bounds.translate(0, yp);
+ _bounds.right = _bounds.left + 280;
+
+ // Draw the dialog
+ draw();
+ _globals->_events.showCursor();
+
+ // Event handling loop
+ Event event;
+ while (!_vm->getEventManager()->shouldQuit()) {
+ while (!_globals->_events.getEvent(event, EVENT_KEYPRESS | EVENT_BUTTON_DOWN | EVENT_MOUSE_MOVE) &&
+ !_vm->getEventManager()->shouldQuit())
+ ;
+ if (_vm->getEventManager()->shouldQuit())
+ break;
+
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode >= Common::KEYCODE_1) &&
+ (event.kbd.keycode <= (Common::KEYCODE_0 + (int)_choiceList.size()))) {
+ // Selected an option by number
+ _selectedIndex = event.kbd.keycode - Common::KEYCODE_1;
+ break;
+ } else if ((_selectedIndex != _choiceList.size()) && ((event.eventType == EVENT_BUTTON_DOWN) ||
+ (event.eventType == EVENT_BUTTON_UP))) {
+ // Item selected
+ break;
+ } else {
+ // Check if any item is highlighted
+ event.mousePos.x -= _gfxManager._bounds.left;
+ event.mousePos.y -= _gfxManager._bounds.top;
+
+ uint idx = 0;
+ while ((idx < _choiceList.size()) && !_choiceList[idx]._bounds.contains(event.mousePos.x, event.mousePos.y))
+ ++idx;
+
+ if (idx != _selectedIndex) {
+ if (_selectedIndex != _choiceList.size()) {
+ // De-highlight previously selected item
+ _gfxManager._font._colors.foreground = _stdColor;
+ _gfxManager._font.writeLines(_choiceList[_selectedIndex]._msg.c_str(),
+ _choiceList[_selectedIndex]._bounds, ALIGN_LEFT);
+ }
+
+ _selectedIndex = idx;
+
+ if (_selectedIndex != _choiceList.size()) {
+ // Highlight the new item
+ _gfxManager._font._colors.foreground = _highlightColor;
+ _gfxManager._font.writeLines(_choiceList[idx]._msg.c_str(), _choiceList[idx]._bounds, ALIGN_LEFT);
+ }
+
+ }
+ }
+ }
+
+ // Remove the dialog
+ remove();
+
+ return _selectedIndex;
+}
+
+void ConversationChoiceDialog::draw() {
+ // Make a backup copy of the area the dialog will occupy
+ Rect tempRect = _bounds;
+ tempRect.collapse(-10, -10);
+ _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), tempRect);
+
+ // Fill in the contents of the entire dialog
+ _gfxManager._bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ drawFrame();
+
+ _gfxManager._bounds = tempRect;
+ _gfxManager._font._colors.foreground = _stdColor;
+ _gfxManager.activate();
+
+ // Loop through writing the conversation choices
+ for (uint idx = 0; idx < _choiceList.size(); ++idx) {
+ Common::String strNum = Common::String::format("%d", idx + 1);
+
+ // Write the choice number
+ _gfxManager._font.setPosition(13, _choiceList[idx]._bounds.top);
+ _gfxManager._font.writeString(strNum.c_str());
+
+ _gfxManager._font.writeLines(_choiceList[idx]._msg.c_str(), _choiceList[idx]._bounds, ALIGN_LEFT);
+ }
+
+ _gfxManager.deactivate();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Obj44::load(const byte *dataP) {
+ _id = READ_LE_UINT16(dataP);
+ for (int idx = 0; idx < OBJ44_LIST_SIZE; ++idx)
+ _field2[idx] = READ_LE_UINT16(dataP + 2 + idx * 2);
+
+ const byte *listP = dataP + 0x10;
+ for (int idx = 0; idx < OBJ44_LIST_SIZE; ++idx, listP += 10) {
+ _list[idx]._id = READ_LE_UINT16(listP);
+ _list[idx]._scriptOffset = READ_LE_UINT16(listP + 2);
+ }
+
+ _speakerOffset = READ_LE_UINT16(dataP + 0x42);
+}
+
+void Obj44::synchronise(Serialiser &s) {
+ s.syncAsSint32LE(_id);
+ for (int idx = 0; idx < OBJ44_LIST_SIZE; ++idx)
+ s.syncAsSint32LE(_field2[idx]);
+ for (int idx = 0; idx < OBJ44_LIST_SIZE; ++idx)
+ _list[idx].synchronise(s);
+ s.syncAsUint32LE(_speakerOffset);
+}
+
+/*--------------------------------------------------------------------------*/
+
+StripManager::StripManager() {
+ _callbackObject = NULL;
+ _activeSpeaker = NULL;
+ reset();
+}
+
+StripManager::~StripManager() {
+}
+
+void StripManager::start(int stripNum, EventHandler *owner, StripCallback *callback) {
+ reset();
+
+ _stripNum = stripNum;
+ _callbackObject = callback;
+ _sceneNumber = _globals->_sceneManager._scene->_screenNumber;
+ _sceneBounds = _globals->_sceneManager._scene->_sceneBounds;
+ _script.clear();
+
+ assert(owner);
+ owner->setAction(this, owner);
+}
+
+void StripManager::reset() {
+ _actionIndex = 0;
+ _delayFrames = 0;
+ _owner = NULL;
+ _endHandler = NULL;
+ _field2E6 = false;
+ _stripNum = -1;
+ _obj44Index = 0;
+ _field2E8 = 0;
+ _field20 = 0;
+ _activeSpeaker = NULL;
+ _textShown = false;
+ _callbackObject = NULL;
+
+ _obj44List.clear();
+ if (!_script.empty()) {
+ _script.clear();
+ }
+}
+
+void StripManager::load() {
+ // Get the script
+ byte *script = _resourceManager->getResource(RES_STRIP, _stripNum, 2);
+ uint scriptSize = _vm->_memoryManager.getSize(script);
+
+ _script.resize(scriptSize);
+ Common::copy(script, script + scriptSize, &_script[0]);
+
+ DEALLOCATE(script);
+
+ // Get the object list
+ byte *obj44List = _resourceManager->getResource(RES_STRIP, _stripNum, 1);
+ int dataSize = _vm->_memoryManager.getSize(obj44List);
+ assert((dataSize % 0x44) == 0);
+
+ byte *dataP = obj44List;
+ for (int idx = 0; idx < (dataSize / 0x44); ++idx, dataP += 0x44) {
+ Obj44 obj;
+ obj.load(dataP);
+ _obj44List.push_back(obj);
+ }
+
+ DEALLOCATE(obj44List);
+}
+
+void StripManager::synchronise(Serialiser &s) {
+ Action::synchronise(s);
+
+ s.syncAsSint32LE(_stripNum);
+ s.syncAsSint32LE(_obj44Index);
+ s.syncAsSint32LE(_field20);
+ s.syncAsSint32LE(_sceneNumber);
+ _sceneBounds.synchronise(s);
+ SYNC_POINTER(_activeSpeaker);
+ s.syncAsByte(_textShown);
+ s.syncAsByte(_field2E6);
+ s.syncAsSint32LE(_field2E8);
+
+ // Synchronise the item list
+ int arrSize = _obj44List.size();
+ s.syncAsUint16LE(arrSize);
+ if (s.isLoading())
+ _obj44List.resize(arrSize);
+ for (int i = 0; i < arrSize; ++i)
+ _obj44List[i].synchronise(s);
+
+ // Synhcronise script data
+ int scriptSize = _script.size();
+ s.syncAsUint16LE(scriptSize);
+ if (s.isLoading())
+ _script.resize(scriptSize);
+ if (scriptSize > 0)
+ s.syncBytes(&_script[0], scriptSize);
+
+ // Add speaker list
+ arrSize = _speakerList.size();
+ s.syncAsUint16LE(arrSize);
+ if (s.isLoading())
+ _speakerList.resize(arrSize);
+ for (int i = 0; i < arrSize; ++i)
+ SYNC_POINTER(_speakerList[i]);
+
+ SYNC_POINTER(_callbackObject);
+}
+
+void StripManager::remove() {
+ if (_textShown) {
+ if (_activeSpeaker)
+ _activeSpeaker->removeText();
+ _textShown = false;
+ }
+
+ if (_activeSpeaker)
+ _activeSpeaker->remove();
+
+ if (_sceneNumber != _globals->_sceneManager._scene->_screenNumber) {
+ _globals->_sceneManager._scene->_sceneBounds = _sceneBounds;
+ _globals->_sceneManager._scene->loadScene(_sceneNumber);
+ }
+
+ Action::remove();
+}
+
+void StripManager::signal() {
+ if (_textShown) {
+ _activeSpeaker->removeText();
+ _textShown = false;
+ }
+
+ if (_obj44Index < 0) {
+ EventHandler *owner = _endHandler;
+ int stripNum = ABS(_obj44Index);
+ remove();
+
+ start(stripNum, owner);
+ return;
+ } else if (_obj44Index == 10000) {
+ // Reached end of strip
+ remove();
+ return;
+ }
+
+ // Run strip
+
+ if (_obj44List.size() == 0)
+ // Load the data for the strip
+ load();
+
+ Obj44 &obj44 = _obj44List[_obj44Index];
+ _field2E8 = obj44._id;
+ Common::StringArray choiceList;
+
+ // Build up a list of script entries
+ int idx;
+ for (idx = 0; idx < OBJ44_LIST_SIZE; ++idx) {
+ if (!obj44._list[idx]._id)
+ break;
+
+ // Get the next one
+ choiceList.push_back((const char *)&_script[0] + obj44._list[idx]._scriptOffset);
+ }
+
+ int strIndex = 0;
+ if (choiceList.size() > 1)
+ // Get the user to select a conversation option
+ strIndex = _choiceDialog.execute(choiceList);
+
+ if ((choiceList.size() != 1) && !_field2E6)
+ _delayFrames = 1;
+ else {
+ Speaker *speakerP = getSpeaker((const char *)&_script[0] + obj44._speakerOffset);
+ if (!speakerP)
+ error("Speaker not found. Screenplay: %s %d", (const char *)&_script[0] + obj44._speakerOffset, _stripNum);
+
+ if (speakerP != _activeSpeaker) {
+ if (_activeSpeaker)
+ _activeSpeaker->remove();
+ _activeSpeaker = speakerP;
+
+ if ((_activeSpeaker->_newSceneNumber == -1) && (_globals->_sceneManager._scene->_screenNumber != _sceneNumber)) {
+ _globals->_sceneManager._scene->_sceneBounds = _sceneBounds;
+ _globals->_sceneManager._scene->loadScene(_sceneNumber);
+ }
+
+ _activeSpeaker->proc12(this);
+ }
+
+ if (_callbackObject) {
+ for (idx = 0; idx < OBJ44_LIST_SIZE; ++idx) {
+ if (!obj44._field2[idx])
+ break;
+
+ _callbackObject->stripCallback(obj44._field2[idx]);
+ }
+ }
+
+ _textShown = true;
+ _activeSpeaker->setText(choiceList[strIndex]);
+ }
+
+ _obj44Index = getNewIndex(obj44._list[strIndex]._id);
+ if (_obj44Index == 10001) {
+ MessageDialog::show("Strip Failure: Node not found", OK_BTN_STRING);
+ _obj44Index = 0;
+ }
+}
+
+void StripManager::process(Event &event) {
+ Action::process(event);
+ if (event.handled)
+ return;
+
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ if (_obj44Index != 10000) {
+ int currIndex = _obj44Index;
+ while (!_obj44List[_obj44Index + 1]._id) {
+ _obj44Index = getNewIndex(_obj44List[_obj44Index]._id);
+ if ((_obj44Index < 0) || (_obj44Index == 10000))
+ break;
+ currIndex = _obj44Index;
+ }
+
+ _field2E8 = _obj44List[currIndex]._id;
+ }
+
+ // Signal the end of the strip
+ _delayFrames = 0;
+ event.handled = true;
+ signal();
+ } else if (event.eventType & (EVENT_BUTTON_DOWN | EVENT_KEYPRESS)) {
+ // Move to next sequence in the strip
+ _delayFrames = 0;
+ event.handled = true;
+ signal();
+ }
+}
+
+void StripManager::addSpeaker(Speaker *speaker) {
+ assert(_speakerList.size() < 100);
+ _speakerList.push_back(speaker);
+}
+
+Speaker *StripManager::getSpeaker(const char *speakerName) {
+ for (uint idx = 0; idx < _speakerList.size(); ++idx) {
+ if (!strcmp(_speakerList[idx]->_speakerName.c_str(), speakerName))
+ return _speakerList[idx];
+ }
+
+ return NULL;
+}
+
+int StripManager::getNewIndex(int id) {
+ if (id == 10000)
+ return id;
+
+ for (uint idx = 0; idx < _obj44List.size(); ++idx) {
+ if (_obj44List[idx]._id == id) {
+ return (id == 0) ? 10001 : idx;
+ }
+ }
+
+ return 10001;
+}
+
+/*--------------------------------------------------------------------------*/
+
+Speaker::Speaker() : EventHandler() {
+ _newSceneNumber = -1;
+ _hideObjects = true;
+ _field18 = 0;
+ _textWidth = 140;
+ _textPos = Common::Point(10, 20);
+ _fontNumber = 2;
+ _textMode = ALIGN_LEFT;
+ _color1 = _color2 = _color3 = _globals->_scenePalette._colors.foreground;
+ _action = NULL;
+ _speakerName = "SPEAKER";
+}
+
+void Speaker::synchronise(Serialiser &s) {
+ EventHandler::synchronise(s);
+
+ _fieldA.synchronise(s);
+ SYNC_POINTER(_field18);
+ s.syncString(_speakerName);
+ s.syncAsSint32LE(_newSceneNumber);
+ s.syncAsSint32LE(_oldSceneNumber);
+ _sceneBounds.synchronise(s);
+ s.syncAsSint32LE(_textWidth);
+ s.syncAsSint16LE(_textPos.x); s.syncAsSint16LE(_textPos.y);
+ s.syncAsSint32LE(_fontNumber);
+ SYNC_ENUM(_textMode, TextAlign);
+ s.syncAsSint16LE(_color1);
+ s.syncAsSint16LE(_color2);
+ s.syncAsSint16LE(_color3);
+ s.syncAsByte(_hideObjects);
+}
+
+void Speaker::remove() {
+ if (_hideObjects)
+ SceneObjectList::deactivate();
+}
+
+void Speaker::proc12(Action *action) {
+ _action = action;
+ if (_newSceneNumber != -1) {
+ _oldSceneNumber = _globals->_sceneManager._sceneNumber;
+ _sceneBounds = _globals->_sceneManager._scene->_sceneBounds;
+ _globals->_sceneManager._scene->loadScene(_newSceneNumber);
+ }
+
+ if (_hideObjects)
+ // Activate the object list for display
+ _objectList.activate();
+
+ // Draw the speaker objects without any fading
+ FadeMode fadeMode = _globals->_sceneManager._fadeMode;
+ _globals->_sceneManager._fadeMode = FADEMODE_IMMEDIATE;
+ _globals->_sceneObjects->draw();
+ _globals->_sceneManager._fadeMode = fadeMode;
+}
+
+void Speaker::setText(const Common::String &msg) {
+ _globals->_sceneObjects->draw();
+
+ _sceneText._color1 = _color1;
+ _sceneText._color2 = _color2;
+ _sceneText._color3 = _color3;
+ _sceneText._width = _textWidth;
+ _sceneText._fontNumber = _fontNumber;
+ _sceneText._textMode = _textMode;
+ _sceneText.setup(msg);
+ _sceneText.setPosition(_textPos);
+ _sceneText.fixPriority(256);
+
+ // Count the number of words (by spaces) in the string
+ const char *msgP = msg.c_str();
+ int spaceCount = 0;
+ while (*msgP) {
+ if (*msgP++ == ' ')
+ ++spaceCount;
+ }
+
+ int numFrames = spaceCount * STRIP_WORD_DELAY + 120;
+ if (_action)
+ _action->setDelay(numFrames);
+}
+
+void Speaker::removeText() {
+ _sceneText.remove();
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerGameText::SpeakerGameText() : Speaker() {
+ _speakerName = "GAMETEXT";
+ _textPos = Common::Point(40, 40);
+ _textMode = ALIGN_CENTER;
+ _color1 = 7;
+ _textWidth = 230;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+ScreenSpeaker::ScreenSpeaker() : Speaker() {
+ _npc = NULL;
+ _textMode = ALIGN_CENTER;
+}
+
+void ScreenSpeaker::setText(const Common::String &msg) {
+ GfxManager gfxMan;
+ gfxMan.activate();
+ gfxMan._font.setFontNumber(_fontNumber);
+ Rect textRect;
+
+ _globals->gfxManager().getStringBounds(msg.c_str(), textRect, _textWidth);
+ if (_npc) {
+ textRect.center(_npc->_position.x, _npc->_bounds.top - (textRect.height() / 2 + 10));
+ } else {
+ textRect.center(_globals->_sceneManager._scene->_sceneBounds.left +
+ (_globals->_sceneManager._scene->_sceneBounds.width() / 2),
+ _globals->_sceneManager._scene->_sceneBounds.top);
+ }
+
+ Rect rect2 = _globals->_sceneManager._scene->_sceneBounds;
+ rect2.collapse(10, 6);
+ textRect.contain(rect2);
+
+ _textPos.x = textRect.left;
+ _textPos.y = textRect.top;
+ Speaker::setText(msg);
+
+ gfxMan.deactivate();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SpeakerAction::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(60) + 60);
+ break;
+ case 1:
+ static_cast<SceneObject *>(_owner)->setFrame(1);
+ static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_5, this, NULL);
+ break;
+ case 2:
+ setDelay(_globals->_randomSource.getRandomNumber(10));
+ _actionIndex = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void AnimatedSpeaker::removeText() {
+ Speaker::removeText();
+ _object1.remove();
+ _object2.remove();
+
+ _objectList.draw();
+}
+
+} // end of namespace tSage
diff --git a/engines/tsage/converse.h b/engines/tsage/converse.h
new file mode 100644
index 0000000000..fd2abcd872
--- /dev/null
+++ b/engines/tsage/converse.h
@@ -0,0 +1,229 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_CONVERSE_H
+#define TSAGE_CONVERSE_H
+
+#include "tsage/core.h"
+#include "tsage/dialogs.h"
+
+namespace tSage {
+
+class StripCallback : public Action {
+public:
+ virtual void stripCallback(int v) = 0;
+};
+
+class SequenceManager : public Action {
+private:
+ void setup();
+ uint16 getNextValue();
+ void setMessage(int resNum, int lineNum, int color, const Common::Point &pt, int width);
+ SequenceManager *globalManager();
+public:
+ SceneText _sceneText;
+ int _resNum;
+ uint _sequenceOffset;
+ bool _keepActive;
+ int _field24;
+ int _field26;
+ Common::Array<byte> _sequenceData;
+ int _objectIndex;
+ SceneObject *_sceneObject;
+ SceneObject *_objectList[6];
+ SoundHandler _soundHandler;
+public:
+ SequenceManager();
+
+ virtual Common::String getClassName() { return "SequenceManager"; }
+ virtual void synchronise(Serialiser &s);
+ virtual void remove();
+ virtual void signal();
+ virtual void process(Event &event);
+ virtual void attached(EventHandler *newOwner, EventHandler *endHandler, va_list va);
+};
+
+
+class Speaker : public EventHandler {
+public:
+ Rect _fieldA;
+ Action *_field18;
+ Common::String _speakerName;
+ int _newSceneNumber;
+ int _oldSceneNumber;
+ SceneObjectList _objectList;
+ Rect _sceneBounds;
+ SceneText _sceneText;
+ int _textWidth;
+ Common::Point _textPos;
+ int _fontNumber;
+ TextAlign _textMode;
+ int _color1, _color2, _color3;
+ bool _hideObjects;
+public:
+ Speaker();
+
+ virtual Common::String getClassName() { return "Speaker"; }
+ virtual void synchronise(Serialiser &s);
+ virtual void remove();
+ virtual void proc12(Action *action);
+ virtual void setText(const Common::String &msg);
+ virtual void removeText();
+
+ void setTextPos(const Common::Point &pt) { _textPos = pt; }
+};
+
+class SpeakerGameText : public Speaker {
+public:
+ SpeakerGameText();
+
+ virtual Common::String getClassName() { return "SpeakerGameText"; }
+};
+
+class ScreenSpeaker : public Speaker {
+public:
+ SceneItem *_npc;
+public:
+ ScreenSpeaker();
+
+ virtual Common::String getClassName() { return "ScreenSpeaker"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerAction : public Action {
+public:
+ virtual void signal();
+
+ virtual Common::String getClassName() { return "SpeakerAction"; }
+};
+
+class AnimatedSpeaker : public Speaker {
+public:
+ SceneObject _object1;
+ SceneObject _object2;
+ SpeakerAction _speakerAction;
+public:
+ virtual Common::String getClassName() { return "AnimatedSpeaker"; }
+ virtual void removeText();
+};
+
+class ChoiceEntry {
+public:
+ Common::String _msg;
+ Rect _bounds;
+
+ ChoiceEntry() {}
+ ChoiceEntry(const Common::String &msg, const Rect &bounds) {
+ _msg = msg;
+ _bounds = bounds;
+ }
+};
+
+class ConversationChoiceDialog : public ModalDialog {
+public:
+ int _stdColor;
+ int _highlightColor;
+ int _fontNumber;
+ int _savedFgColor;
+ int _savedFontNumber;
+ Common::Array<ChoiceEntry> _choiceList;
+ uint _selectedIndex;
+public:
+ ConversationChoiceDialog();
+
+ void setColors(int stdColor, int highlightColor) {
+ _stdColor = stdColor;
+ _highlightColor = highlightColor;
+ }
+ void setFontNumber(int fontNum) { _fontNumber = fontNum; }
+ int execute(const Common::StringArray &choiceList);
+
+ virtual void draw();
+};
+
+class Obj0A : public Serialisable {
+public:
+ int _id;
+ uint _scriptOffset;
+
+ virtual void synchronise(Serialiser &s) {
+ s.syncAsSint32LE(_id);
+ s.syncAsUint32LE(_scriptOffset);
+ }
+};
+
+#define OBJ44_LIST_SIZE 5
+
+class Obj44 : public Serialisable {
+public:
+ int _id;
+ int _field2[OBJ44_LIST_SIZE];
+ Obj0A _list[OBJ44_LIST_SIZE];
+ uint _speakerOffset;
+public:
+ void load(const byte *dataP);
+ virtual void synchronise(Serialiser &s);
+};
+
+class StripManager : public Action {
+private:
+ void reset();
+ void load();
+ Speaker *getSpeaker(const char *speakerName);
+ int getNewIndex(int newId);
+public:
+ int _stripNum;
+ int _obj44Index;
+ int _field20;
+ int _sceneNumber;
+ Rect _sceneBounds;
+ ConversationChoiceDialog _choiceDialog;
+ Common::Array<Speaker *> _speakerList;
+ StripCallback *_callbackObject;
+ Speaker *_activeSpeaker;
+ bool _textShown;
+ bool _field2E6;
+ int _field2E8;
+ Common::Array<Obj44> _obj44List;
+ Common::Array<byte> _script;
+public:
+ StripManager();
+ virtual ~StripManager();
+
+ virtual void synchronise(Serialiser &s);
+ virtual void remove();
+ virtual void signal();
+ virtual void process(Event &event);
+
+ void start(int stripNum, EventHandler *owner, StripCallback *callback = NULL);
+ void setCallback(StripCallback *callback) { _callbackObject = callback; }
+ void setColors(int stdColor, int highlightColor) { _choiceDialog.setColors(stdColor, highlightColor); }
+ void setFontNumber(int fontNum) { _choiceDialog.setFontNumber(fontNum); }
+ void addSpeaker(Speaker *speaker);
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
new file mode 100644
index 0000000000..eab5efbce0
--- /dev/null
+++ b/engines/tsage/core.cpp
@@ -0,0 +1,3646 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+#include "engines/engine.h"
+#include "graphics/palette.h"
+#include "tsage/tsage.h"
+#include "tsage/core.h"
+#include "tsage/dialogs.h"
+#include "tsage/events.h"
+#include "tsage/scenes.h"
+#include "tsage/staticres.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+// The engine uses ScumMVM screen buffering, so all logic is hardcoded to use pane buffer 0
+#define CURRENT_PANENUM 0
+
+/*--------------------------------------------------------------------------*/
+
+InvObject::InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType cursorId, const Common::String description) :
+ _sceneNumber(sceneNumber), _rlbNum(rlbNum), _cursorNum(cursorNum), _cursorId(cursorId),
+ _description(description) {
+ _displayResNum = 3;
+ _iconResNum = 5;
+
+ // Decode the image for the inventory item to get it's display bounds
+ uint size;
+ byte *imgData = _resourceManager->getSubResource(_displayResNum, _rlbNum, _cursorNum, &size);
+ GfxSurface s = surfaceFromRes(imgData);
+ _bounds = s.getBounds();
+
+ DEALLOCATE(imgData);
+}
+
+void InvObject::setCursor() {
+ _globals->_events._currentCursor = _cursorId;
+
+ if (_iconResNum != -1) {
+ GfxSurface s = surfaceFromRes(_iconResNum, _rlbNum, _cursorNum);
+
+ Graphics::Surface src = s.lockSurface();
+ _globals->_events.setCursor(src, s._transColor, s._centroid, _cursorId);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+InvObjectList::InvObjectList() {
+ _selectedItem = NULL;
+}
+
+void InvObjectList::synchronise(Serialiser &s) {
+ SavedObject::synchronise(s);
+ SYNC_POINTER(_selectedItem);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void EventHandler::dispatch() {
+ if (_action) _action->dispatch();
+}
+
+void EventHandler::setAction(Action *action, EventHandler *endHandler, ...) {
+ if (_action) {
+ _action->_endHandler = NULL;
+ _action->remove();
+ }
+
+ _action = action;
+ if (action) {
+ va_list va;
+ va_start(va, endHandler);
+ _action->attached(this, endHandler, va);
+ va_end(va);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Action::Action() {
+ _actionIndex = 0;
+ _owner = NULL;
+ _endHandler = NULL;
+ _attached = false;
+}
+
+void Action::synchronise(Serialiser &s) {
+ EventHandler::synchronise(s);
+
+ SYNC_POINTER(_owner);
+ s.syncAsSint32LE(_actionIndex);
+ s.syncAsSint32LE(_delayFrames);
+ s.syncAsUint32LE(_startFrame);
+ s.syncAsByte(_attached);
+ SYNC_POINTER(_endHandler);
+}
+
+void Action::remove() {
+ if (_action)
+ _action->remove();
+
+ if (_owner) {
+ _owner->_action = NULL;
+ _owner = NULL;
+ } else {
+ _globals->_sceneManager.removeAction(this);
+ }
+
+ _attached = false;
+ if (_endHandler)
+ _endHandler->signal();
+}
+
+void Action::process(Event &event) {
+ if (_action)
+ _action->process(event);
+}
+
+void Action::dispatch() {
+ if (_action)
+ _action->dispatch();
+
+ if (_delayFrames) {
+ uint32 frameNumber = _globals->_events.getFrameNumber();
+
+ if (frameNumber >= _startFrame) {
+ _delayFrames -= frameNumber - _startFrame;
+ _startFrame = frameNumber;
+ if (_delayFrames <= 0) {
+ _delayFrames = 0;
+ signal();
+ }
+ }
+ }
+}
+
+void Action::attached(EventHandler *newOwner, EventHandler *endHandler, va_list va) {
+ _actionIndex = 0;
+ _delayFrames = 0;
+ _startFrame = _globals->_events.getFrameNumber();
+ _owner = newOwner;
+ _endHandler = endHandler;
+ _attached = true;
+ signal();
+}
+
+void Action::setDelay(int numFrames) {
+ _delayFrames = numFrames;
+ _startFrame = _globals->_events.getFrameNumber();
+}
+
+/*--------------------------------------------------------------------------*/
+
+ObjectMover::~ObjectMover() {
+ if (_sceneObject->_mover == this)
+ _sceneObject->_mover = NULL;
+}
+
+void ObjectMover::synchronise(Serialiser &s) {
+ EventHandler::synchronise(s);
+
+ s.syncAsSint16LE(_destPosition.x); s.syncAsSint16LE(_destPosition.y);
+ s.syncAsSint16LE(_moveDelta.x); s.syncAsSint16LE(_moveDelta.y);
+ s.syncAsSint16LE(_moveSign.x); s.syncAsSint16LE(_moveSign.y);
+ s.syncAsSint32LE(_minorDiff);
+ s.syncAsSint32LE(_majorDiff);
+ s.syncAsSint32LE(_changeCtr);
+ SYNC_POINTER(_action);
+ SYNC_POINTER(_sceneObject);
+}
+
+void ObjectMover::remove() {
+ if (_sceneObject->_mover == this)
+ _sceneObject->_mover = NULL;
+
+ delete this;
+}
+
+void ObjectMover::dispatch() {
+ Common::Point currPos = _sceneObject->_position;
+ int yDiff = _sceneObject->_yDiff;
+
+ if (dontMove())
+ return;
+
+ _sceneObject->_regionIndex = 0;
+ if (_moveDelta.x >= _moveDelta.y) {
+ int xAmount = _moveSign.x * _sceneObject->_moveDiff.x * _sceneObject->_percent / 100;
+ if (!xAmount)
+ xAmount = _moveSign.x;
+ currPos.x += xAmount;
+
+ int yAmount = ABS(_destPosition.y - currPos.y);
+ int yChange = _majorDiff / ABS(xAmount);
+ int ySign;
+
+ if (!yChange)
+ ySign = _moveSign.y;
+ else {
+ int v = yAmount / yChange;
+ _changeCtr += yAmount % yChange;
+ if (_changeCtr >= yChange) {
+ ++v;
+ _changeCtr -= yChange;
+ }
+
+ ySign = _moveSign.y * v;
+ }
+
+ currPos.y += ySign;
+ _majorDiff -= ABS(xAmount);
+
+ } else {
+ int yAmount = _moveSign.y * _sceneObject->_moveDiff.y * _sceneObject->_percent / 100;
+ if (!yAmount)
+ yAmount = _moveSign.y;
+ currPos.y += yAmount;
+
+ int xAmount = ABS(_destPosition.x - currPos.x);
+ int xChange = _majorDiff / ABS(yAmount);
+ int xSign;
+
+ if (!xChange)
+ xSign = _moveSign.x;
+ else {
+ int v = xAmount / xChange;
+ _changeCtr += xAmount % xChange;
+ if (_changeCtr >= xChange) {
+ ++v;
+ _changeCtr -= xChange;
+ }
+
+ xSign = _moveSign.x * v;
+ }
+
+ currPos.x += xSign;
+ _majorDiff -= ABS(yAmount);
+ }
+
+ _sceneObject->_regionIndex = _sceneObject->checkRegion(currPos);
+ if (!_sceneObject->_regionIndex) {
+ _sceneObject->setPosition(currPos, yDiff);
+ _sceneObject->getHorizBounds();
+
+ if (dontMove()) {
+ _sceneObject->_position = _destPosition;
+ endMove();
+ }
+ } else {
+ endMove();
+ }
+}
+
+void ObjectMover::setup(const Common::Point &destPos) {
+ _sceneObject->calcAngle(destPos);
+
+ if ((_sceneObject->_objectWrapper) && !(_sceneObject->_flags & OBJFLAG_SUPPRESS_DISPATCH))
+ _sceneObject->_objectWrapper->dispatch();
+
+ // Get the difference
+ int diffX = destPos.x - _sceneObject->_position.x;
+ int diffY = destPos.y - _sceneObject->_position.y;
+ int xSign = (diffX < 0) ? -1 : (diffX > 0 ? 1 : 0);
+ int ySign = (diffY < 0) ? -1 : (diffY > 0 ? 1 : 0);
+ diffX = ABS(diffX);
+ diffY = ABS(diffY);
+
+ if (diffX < diffY) {
+ _minorDiff = diffX / 2;
+ _majorDiff = diffY;
+ } else {
+ _minorDiff = diffY / 2;
+ _majorDiff = diffX;
+ }
+
+ // Set the destination position
+ _destPosition = destPos;
+ _moveDelta = Common::Point(diffX, diffY);
+ _moveSign = Common::Point(xSign, ySign);
+ _changeCtr = 0;
+
+ if (!diffX && !diffY)
+ // Object is already at the correct destination
+ endMove();
+}
+
+bool ObjectMover::dontMove() const {
+ return (_majorDiff <= 0);
+}
+
+void ObjectMover::endMove() {
+ EventHandler *actionP = _action;
+ remove();
+
+ if (actionP)
+ actionP->signal();
+}
+
+/*--------------------------------------------------------------------------*/
+
+ObjectMover2::ObjectMover2() : ObjectMover() {
+ _destObject = NULL;
+}
+
+void ObjectMover2::synchronise(Serialiser &s) {
+ ObjectMover::synchronise(s);
+
+ SYNC_POINTER(_destObject);
+ s.syncAsSint32LE(_minArea);
+ s.syncAsSint32LE(_maxArea);
+}
+
+void ObjectMover2::dispatch() {
+ int area = _sceneObject->getSpliceArea(_destObject);
+ if (area > _maxArea) {
+ // Setup again for the new destination
+ setup(_destObject->_position);
+ ObjectMover::dispatch();
+ } else if (area >= _minArea) {
+ // Keep dispatching
+ ObjectMover::dispatch();
+ } else {
+ // Within minimum, so end move
+ endMove();
+ }
+}
+
+void ObjectMover2::startMove(SceneObject *sceneObj, va_list va) {
+ // Set up fields
+ _sceneObject = sceneObj;
+
+ _minArea = va_arg(va, int);
+ _maxArea = va_arg(va, int);
+ _destObject = va_arg(va, SceneObject *);
+
+ setup(_destObject->_position);
+}
+
+void ObjectMover2::endMove() {
+ _sceneObject->_regionIndex = 0x40;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void ObjectMover3::dispatch() {
+ int area = _sceneObject->getSpliceArea(_destObject);
+ if (area <= _minArea) {
+ endMove();
+ } else {
+ setup(_destObject->_position);
+ ObjectMover::dispatch();
+ }
+}
+
+void ObjectMover3::startMove(SceneObject *sceneObj, va_list va) {
+ _sceneObject = sceneObj;
+ _destObject = va_arg(va, SceneObject *);
+ _minArea = va_arg(va, int);
+ _action = va_arg(va, Action *);
+
+ setup(_destObject->_position);
+}
+
+void ObjectMover3::endMove() {
+ ObjectMover::endMove();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void NpcMover::startMove(SceneObject *sceneObj, va_list va) {
+ _sceneObject = sceneObj;
+
+ Common::Point *destPos = va_arg(va, Common::Point *);
+ _action = va_arg(va, Action *);
+
+ setup(*destPos);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void PlayerMover::synchronise(Serialiser &s) {
+ NpcMover::synchronise(s);
+
+ s.syncAsSint16LE(_finalDest.x); s.syncAsSint16LE(_finalDest.y);
+ s.syncAsSint32LE(_routeIndex);
+
+ for (int i = 0; i < MAX_ROUTE_SIZE; ++i) {
+ s.syncAsSint16LE(_routeList[i].x); s.syncAsSint16LE(_routeList[i].y);
+ }
+}
+
+void PlayerMover::startMove(SceneObject *sceneObj, va_list va) {
+ _sceneObject = sceneObj;
+ Common::Point *pt = va_arg(va, Common::Point *);
+ _finalDest = *pt;
+ _action = va_arg(va, Action *);
+
+ setDest(_finalDest);
+}
+
+void PlayerMover::endMove() {
+ while (++_routeIndex != 0) {
+ if ((_routeList[_routeIndex].x == ROUTE_END_VAL) ||
+ (_routeList[_routeIndex].y == ROUTE_END_VAL) ||
+ (_sceneObject->_regionIndex)) {
+ // Movement route is completely finished
+ ObjectMover::endMove();
+ return;
+ }
+
+ if ((_routeList[_routeIndex].x != _sceneObject->_position.x) ||
+ (_routeList[_routeIndex].y != _sceneObject->_position.y))
+ break;
+ }
+
+ // Set up the new interim destination along the route
+ _globals->_walkRegions._routeEnds.moveSrc = _globals->_walkRegions._routeEnds.moveDest;
+ _globals->_walkRegions._routeEnds.moveDest = _routeList[_routeIndex];
+ setup(_routeList[_routeIndex]);
+ dispatch();
+}
+
+void PlayerMover::setDest(const Common::Point &destPos) {
+ _routeList[0] = _sceneObject->_position;
+
+ if (_globals->_walkRegions._resNum == -1) {
+ // Scene has no walk regions defined, so player can walk anywhere directly
+ _routeList[0] = destPos;
+ _routeList[1] = Common::Point(ROUTE_END_VAL, ROUTE_END_VAL);
+ } else {
+ // Figure out a path to the destination (or as close as possible to it)
+ pathfind(_routeList, _sceneObject->_position, destPos, _globals->_walkRegions._routeEnds);
+ }
+
+ _routeIndex = 0;
+ _globals->_walkRegions._routeEnds.moveSrc = _sceneObject->_position;
+ _globals->_walkRegions._routeEnds.moveDest = _routeList[0];
+ setup(_routeList[0]);
+}
+
+#define REGION_LIST_SIZE 20
+
+void PlayerMover::pathfind(Common::Point *routeList, Common::Point srcPos, Common::Point destPos, RouteEnds routeEnds) {
+ Common::List<int> regionIndexes;
+ RouteEnds tempRouteEnds;
+ int routeRegions[REGION_LIST_SIZE];
+ Common::Point objPos;
+
+ // Get the region the source is in
+ int srcRegion = _globals->_walkRegions.indexOf(srcPos);
+ if (srcRegion == -1) {
+ srcRegion = findClosestRegion(srcPos, regionIndexes);
+ }
+
+ // Main loop for building up the path
+ routeRegions[0] = 0;
+ while (!routeRegions[0]) {
+ // Check the destination region
+ int destRegion = _globals->_walkRegions.indexOf(destPos, &regionIndexes);
+
+ if ((srcRegion == -1) && (destRegion == -1)) {
+ // Both source and destination are outside walkable areas
+ } else if (srcRegion == -1) {
+ // Source is outside walkable areas
+ tempRouteEnds = routeEnds;
+ objPos = _sceneObject->_position;
+
+ Common::Point newPos;
+ findLinePoint(&tempRouteEnds, &objPos, 1, &newPos);
+ int srcId = _globals->_walkRegions.indexOf(newPos);
+
+ if (srcId == -1) {
+ tempRouteEnds.moveDest = tempRouteEnds.moveSrc;
+ tempRouteEnds.moveSrc = routeEnds.moveDest;
+
+ findLinePoint(&tempRouteEnds, &objPos, 1, &newPos);
+ srcRegion = _globals->_walkRegions.indexOf(newPos);
+
+ if (srcRegion == -1)
+ srcRegion = checkMover(srcPos, destPos);
+ }
+
+ } else if (destRegion == -1) {
+ // Destination is outside walkable areas
+ destRegion = findClosestRegion(destPos, regionIndexes);
+ if (destRegion == -1) {
+ // No further route found, so end it
+ *routeList++ = srcPos;
+ break;
+ } else {
+ _finalDest = destPos;
+ }
+ }
+
+ if (srcRegion == destRegion) {
+ *routeList++ = (srcRegion == -1) ? srcPos : destPos;
+ break;
+ }
+
+ int var6;
+ proc1(routeRegions, srcRegion, destRegion, var6);
+
+ if (!routeRegions[0]) {
+ regionIndexes.push_back(destRegion);
+ continue;
+ }
+
+ _globals->_walkRegions._field18[0]._pt1 = srcPos;
+ _globals->_walkRegions._field18[0]._pt2 = srcPos;
+ _globals->_walkRegions._field18[1]._pt1 = destPos;
+ _globals->_walkRegions._field18[1]._pt2 = destPos;
+
+ int tempList[REGION_LIST_SIZE];
+ tempList[0] = 0;
+ int endIndex = 0;
+ int idx = 1;
+
+ do {
+ int breakEntry = routeRegions[idx];
+ int breakEntry2 = routeRegions[idx + 1];
+
+ int listIndex = 0;
+ while (_globals->_walkRegions._idxList[_globals->_walkRegions[breakEntry]._idxListIndex + listIndex] !=
+ breakEntry2)
+ ++listIndex;
+
+ tempList[idx] = _globals->_walkRegions._idxList2[_globals->_walkRegions[breakEntry]._idxList2Index
+ + listIndex];
+
+ ++endIndex;
+ } while (routeRegions[++idx] != destRegion);
+
+ tempList[idx] = 1;
+ for (int listIndex = 1; listIndex <= endIndex; ++listIndex) {
+ int var10 = tempList[listIndex];
+ int var12 = tempList[listIndex + 1];
+
+ if (sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var12]._pt1,
+ _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2) &&
+ sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var12]._pt2,
+ _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2))
+ continue;
+
+ Common::Point tempPt;
+ if (sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[1]._pt1,
+ _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2, &tempPt)) {
+ // Add point to the route list
+ _globals->_walkRegions._field18[0]._pt1 = tempPt;
+ *routeList++ = tempPt;
+ } else {
+ int v16 =
+ (findDistance(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var10]._pt1) << 1) +
+ (findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[1]._pt1) << 1) +
+ findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var12]._pt1) +
+ findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var12]._pt2);
+
+ int v1A =
+ (findDistance(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var10]._pt2) << 1) +
+ (findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[1]._pt2) << 1) +
+ findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[var12]._pt1) +
+ findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[var12]._pt2);
+
+ if (v16 < v1A) {
+ checkMovement2(_globals->_walkRegions._field18[var10]._pt1,
+ _globals->_walkRegions._field18[var10]._pt2, 1, objPos);
+ } else {
+ checkMovement2(_globals->_walkRegions._field18[var10]._pt2,
+ _globals->_walkRegions._field18[var10]._pt1, 1, objPos);
+ }
+
+ _globals->_walkRegions._field18[0]._pt1 = objPos;
+ *routeList++ = objPos;
+ }
+ }
+
+ // Add in the route entry
+ *routeList++ = _globals->_walkRegions._field18[1]._pt1;
+ }
+
+ // Mark the end of the path
+ *routeList = Common::Point(ROUTE_END_VAL, ROUTE_END_VAL);
+}
+
+int PlayerMover::regionIndexOf(const Common::Point &pt) {
+ for (uint idx = 0; idx < _globals->_walkRegions._regionList.size(); ++idx) {
+ if (_globals->_walkRegions._regionList[idx].contains(pt))
+ return idx + 1;
+ }
+
+ return 0;
+}
+
+int PlayerMover::findClosestRegion(Common::Point &pt, const Common::List<int> &indexList) {
+ int newY = pt.y;
+ int result = 0;
+
+ for (int idx = 1; idx < SCREEN_WIDTH; ++idx, newY += idx) {
+ int newX = pt.x + idx;
+ result = regionIndexOf(newX, pt.y);
+
+ if ((result == 0) || contains(indexList, result)) {
+ newY = pt.y + idx;
+ result = regionIndexOf(newX, newY);
+
+ if ((result == 0) || contains(indexList, result)) {
+ newX -= idx;
+ result = regionIndexOf(newX, newY);
+
+ if ((result == 0) || contains(indexList, result)) {
+ newX -= idx;
+ result = regionIndexOf(newX, newY);
+
+ if ((result == 0) || contains(indexList, result)) {
+ newY -= idx;
+ result = regionIndexOf(newX, newY);
+
+ if ((result == 0) || contains(indexList, result)) {
+ newY -= idx;
+ result = regionIndexOf(newX, newY);
+
+ if ((result == 0) || contains(indexList, result)) {
+ newX += idx;
+ result = regionIndexOf(newX, newY);
+
+ if ((result == 0) || contains(indexList, result)) {
+ newX += idx;
+ result = regionIndexOf(newX, newY);
+
+ if ((result == 0) || contains(indexList, result)) {
+ continue;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Found an index
+ pt.x = newX;
+ pt.y = newY;
+ return result;
+ }
+
+ return (result == 0) ? -1 : result;
+}
+
+Common::Point *PlayerMover::findLinePoint(RouteEnds *routeEnds, Common::Point *objPos, int length, Common::Point *outPos) {
+ int xp = objPos->x + (((routeEnds->moveDest.y - routeEnds->moveSrc.y) * 9) / 8);
+ int yp = objPos->y - (((routeEnds->moveDest.x - routeEnds->moveSrc.x) * 8) / 9);
+
+ int xDiff = xp - objPos->x;
+ int yDiff = yp - objPos->y;
+ int xDirection = (xDiff == 0) ? 0 : ((xDiff < 0) ? 1 : -1);
+ int yDirection = (yDiff == 0) ? 0 : ((yDiff < 0) ? 1 : -1);
+ xDiff = ABS(xDiff);
+ yDiff = ABS(yDiff);
+ int majorChange = MAX(xDiff, yDiff) / 2;
+
+ int outX = objPos->x;
+ int outY = objPos->y;
+
+ while (length-- > 0) {
+ if (xDiff < yDiff) {
+ outY += yDirection;
+ majorChange += xDiff;
+ if (majorChange > yDiff) {
+ majorChange -= yDiff;
+ outX += xDirection;
+ }
+ } else {
+ outX += xDirection;
+ majorChange += yDiff;
+ if (majorChange > xDiff) {
+ majorChange -= xDiff;
+ outY += yDirection;
+ }
+ }
+ }
+
+ outPos->x = outX;
+ outPos->y = outY;
+ return outPos;
+}
+
+int PlayerMover::checkMover(Common::Point &srcPos, const Common::Point &destPos) {
+ int regionIndex = 0;
+ Common::Point objPos = _sceneObject->_position;
+ uint32 regionBitList = _sceneObject->_regionBitList;
+ _sceneObject->_regionBitList = 0;
+
+ _sceneObject->_position.x = srcPos.x;
+ _sceneObject->_position.y = srcPos.y;
+ _sceneObject->_mover = NULL;
+
+ NpcMover *mover = new NpcMover();
+ _sceneObject->addMover(mover, &destPos, NULL);
+
+ // Handle automatic movement of the player until a walkable region is reached,
+ // or the end point of the movement is
+ do {
+ _sceneObject->_mover->dispatch();
+
+ // Scan walk regions for point
+ for (uint idx = 0; idx < _globals->_walkRegions._regionList.size(); ++idx) {
+ if (_globals->_walkRegions[idx].contains(_sceneObject->_position)) {
+ regionIndex = idx + 1;
+ srcPos = _sceneObject->_position;
+ break;
+ }
+ }
+ } while ((regionIndex == 0) && (_sceneObject->_mover) && !_vm->shouldQuit());
+
+ _sceneObject->_position = objPos;
+ _sceneObject->_regionBitList = regionBitList;
+
+ if (_sceneObject->_mover)
+ _sceneObject->_mover->remove();
+
+ _sceneObject->_mover = this;
+ return regionIndex;
+}
+
+void PlayerMover::checkMovement2(const Common::Point &srcPos, const Common::Point &destPos, int numSteps, Common::Point &ptOut) {
+ Common::Point objPos = _sceneObject->_position;
+ _sceneObject->_position = srcPos;
+ uint32 regionBitList = _sceneObject->_regionBitList;
+ _sceneObject->_position = srcPos;
+ _sceneObject->_mover = NULL;
+
+ NpcMover *mover = new NpcMover();
+ _sceneObject->addMover(mover, &destPos, NULL);
+
+ while ((numSteps > 0) && ((_sceneObject->_position.x != destPos.x) || (_sceneObject->_position.y != destPos.y))) {
+ _sceneObject->_mover->dispatch();
+ --numSteps;
+ }
+
+ ptOut = _sceneObject->_position;
+ _sceneObject->_position = objPos;
+ _sceneObject->_regionBitList = regionBitList;
+
+ if (_sceneObject->_mover)
+ _sceneObject->_mover->remove();
+
+ _sceneObject->_mover = this;
+}
+
+int PlayerMover::proc1(int *routeList, int srcRegion, int destRegion, int &v) {
+ int tempList[REGION_LIST_SIZE + 1];
+ v = 0;
+ for (int idx = 0; idx <= *routeList; ++idx)
+ tempList[idx] = routeList[idx];
+
+ if (*routeList == REGION_LIST_SIZE)
+ // Sequence too long
+ return 32000;
+
+ int regionIndex;
+ for (regionIndex = 1; regionIndex <= *tempList; ++regionIndex) {
+ if (routeList[regionIndex] == srcRegion)
+ // Current path returns to original source region, so don't allow it
+ return 32000;
+ }
+
+ WalkRegion &srcWalkRegion = _globals->_walkRegions[srcRegion];
+ int distance;
+ if (!routeList[0]) {
+ // No route
+ distance = 0;
+ } else {
+ WalkRegion &region = _globals->_walkRegions[routeList[*routeList]];
+ distance = findDistance(srcWalkRegion._pt, region._pt);
+ }
+
+ tempList[++*tempList] = srcRegion;
+ int newIndex = *tempList;
+
+ if (srcRegion == destRegion) {
+ v = 1;
+ for (int idx = newIndex; idx <= *tempList; ++idx) {
+ routeList[idx] = tempList[idx];
+ ++*routeList;
+ }
+ return distance;
+ } else {
+ int foundIndex = 0;
+ int idx = 0;
+ int currDest;
+ while ((currDest = _globals->_walkRegions._idxList[srcWalkRegion._idxListIndex + idx]) != 0) {
+ if (currDest == destRegion) {
+ foundIndex = idx;
+ break;
+ }
+
+ ++idx;
+ }
+
+ int resultOffset = 31990;
+ while (((currDest = _globals->_walkRegions._idxList[srcWalkRegion._idxListIndex + foundIndex]) != 0) && (v == 0)) {
+ int newDistance = proc1(tempList, currDest, destRegion, v);
+
+ if ((newDistance <= resultOffset) || v) {
+ routeList[0] = newIndex - 1;
+
+ for (int i = newIndex; i <= tempList[0]; ++i) {
+ routeList[i] = tempList[i];
+ ++routeList[0];
+ }
+
+ resultOffset = newDistance;
+ }
+
+ tempList[0] = newIndex;
+ ++foundIndex;
+ }
+
+ v = 0;
+ return resultOffset + distance;
+ }
+}
+
+int PlayerMover::findDistance(const Common::Point &pt1, const Common::Point &pt2) {
+ int diff = ABS(pt1.x - pt2.x);
+ double xx = diff * diff;
+ diff = ABS(pt1.y - pt2.y);
+ double yy = diff * 8.0 / 7.0;
+ yy *= yy;
+
+ return (int)sqrt(xx + yy);
+}
+
+bool PlayerMover::sub_F8E5(const Common::Point &pt1, const Common::Point &pt2, const Common::Point &pt3,
+ const Common::Point &pt4, Common::Point *ptOut) {
+ double diff1 = pt2.x - pt1.x;
+ double diff2 = pt2.y - pt1.y;
+ double diff3 = pt4.x - pt3.x;
+ double diff4 = pt4.y - pt3.y;
+ double var10 = 0.0, var8 = 0.0;
+ double var18 = 0.0, var20 = 0.0;
+
+ if (diff1 != 0.0) {
+ var8 = diff2 / diff1;
+ var18 = pt1.y - (pt1.x * var8);
+ }
+ if (diff3 != 0.0) {
+ var10 = diff4 / diff3;
+ var20 = pt3.y - (pt3.x * var10);
+ }
+
+ if (var8 == var10)
+ return false;
+
+ double var48, var50;
+ if (diff1 == 0) {
+ if (diff3 == 0)
+ return false;
+
+ var48 = pt1.x;
+ var50 = var10 * var48 + var20;
+ } else {
+ var48 = (diff3 == 0) ? pt3.x : (var20 - var18) / (var8 - var10);
+ var50 = var8 * var48 + var18;
+ }
+
+ bool var52 = false, var56 = false, var54 = false, var58 = false;
+ Common::Point tempPt((int)(var48 + 0.5), (int)(var50 + 0.5));
+
+ if ((tempPt.x >= pt3.x) && (tempPt.x <= pt4.x))
+ var56 = true;
+ else if ((tempPt.x >= pt4.x) && (tempPt.x <= pt3.x))
+ var56 = true;
+ if (var56) {
+ if ((tempPt.y >= pt3.y) && (tempPt.y <= pt4.y))
+ var58 = true;
+ else if ((tempPt.y >= pt4.y) && (tempPt.y <= pt3.y))
+ var58 = true;
+ }
+
+ if ((tempPt.x >= pt1.x) && (tempPt.x <= pt2.x))
+ var52 = true;
+ else if ((tempPt.x >= pt2.x) && (tempPt.x <= pt1.x))
+ var52 = true;
+ if (var52) {
+ if ((tempPt.y >= pt1.y) && (tempPt.y <= pt2.y))
+ var54 = true;
+ else if ((tempPt.y >= pt2.y) && (tempPt.y <= pt1.y))
+ var54 = true;
+ }
+
+ if (var52 && var54 && var56 && var58) {
+ if (ptOut)
+ *ptOut = tempPt;
+ return true;
+ }
+
+ return false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void PlayerMover2::synchronise(Serialiser &s) {
+ PlayerMover::synchronise(s);
+ SYNC_POINTER(_destObject);
+ s.syncAsSint16LE(_maxArea);
+ s.syncAsSint16LE(_minArea);
+}
+
+void PlayerMover2::dispatch() {
+ int total = _sceneObject->getSpliceArea(_destObject);
+
+ if (total <= _minArea)
+ endMove();
+ else {
+ setDest(_destObject->_position);
+ ObjectMover::dispatch();
+ }
+}
+
+void PlayerMover2::startMove(SceneObject *sceneObj, va_list va) {
+ _sceneObject = sceneObj;
+ _maxArea = va_arg(va, int);
+ _minArea = va_arg(va, int);
+ _destObject = va_arg(va, SceneObject *);
+
+ PlayerMover::setDest(_destObject->_position);
+}
+
+void PlayerMover2::endMove() {
+ _sceneObject->_regionIndex = 0x40;
+}
+
+/*--------------------------------------------------------------------------*/
+
+PaletteModifier::PaletteModifier() {
+ _scenePalette = NULL;
+ _action = NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+
+PaletteModifierCached::PaletteModifierCached(): PaletteModifier() {
+ _step = 0;
+ _percent = 0;
+}
+
+void PaletteModifierCached::setPalette(ScenePalette *palette, int step) {
+ _scenePalette = palette;
+ _step = step;
+ _percent = 100;
+}
+
+void PaletteModifierCached::synchronise(Serialiser &s) {
+ PaletteModifier::synchronise(s);
+
+ s.syncAsByte(_step);
+ s.syncAsSint32LE(_percent);
+}
+
+/*--------------------------------------------------------------------------*/
+
+PaletteRotation::PaletteRotation() : PaletteModifierCached() {
+ _percent = 0;
+ _delayCtr = 0;
+ _frameNumber = _globals->_events.getFrameNumber();
+}
+
+void PaletteRotation::synchronise(Serialiser &s) {
+ PaletteModifierCached::synchronise(s);
+
+ s.syncAsSint32LE(_delayCtr);
+ s.syncAsUint32LE(_frameNumber);
+ s.syncAsSint32LE(_currIndex);
+ s.syncAsSint32LE(_start);
+ s.syncAsSint32LE(_end);
+ s.syncAsSint32LE(_rotationMode);
+ s.syncAsSint32LE(_duration);
+ s.syncBytes(&_palette[0], 256 * 3);
+}
+
+void PaletteRotation::signal() {
+ if (_delayCtr) {
+ uint32 frameNumber = _globals->_events.getFrameNumber();
+
+ if (frameNumber >= _frameNumber) {
+ _delayCtr = frameNumber - _frameNumber;
+ _frameNumber = frameNumber;
+
+ if (_delayCtr < 0)
+ _delayCtr = 0;
+ }
+ }
+
+ if (_delayCtr)
+ return;
+ _delayCtr = _percent;
+ if (_step)
+ return;
+
+ bool flag = true;
+ switch (_rotationMode) {
+ case -1:
+ if (--_currIndex < _start) {
+ flag = decDuration();
+ if (flag)
+ _currIndex = _end - 1;
+ }
+ break;
+ case 1:
+ if (++_currIndex >= _end) {
+ flag = decDuration();
+ if (flag)
+ _currIndex = _start;
+ }
+ break;
+ case 2:
+ if (++_currIndex >= _end) {
+ flag = decDuration();
+ if (flag) {
+ _currIndex = _end - 2;
+ _rotationMode = 3;
+ }
+ }
+ break;
+ case 3:
+ if (--_currIndex < _start) {
+ flag = decDuration();
+ if (flag) {
+ _currIndex = _start + 1;
+ _rotationMode = 2;
+ }
+ }
+ break;
+ }
+
+ if (flag) {
+ int count2 = _currIndex - _start;
+ int count = _end - _currIndex;
+ g_system->getPaletteManager()->setPalette((const byte *)&_palette[_currIndex * 3], _start, count);
+
+ if (count2) {
+ g_system->getPaletteManager()->setPalette((const byte *)&_palette[_start * 3], _start + count, count2);
+ }
+ }
+}
+
+void PaletteRotation::remove() {
+ Action *action = _action;
+ g_system->getPaletteManager()->setPalette((const byte *)&_palette[_start * 3], _start, _end - _start);
+
+ _scenePalette->_listeners.remove(this);
+
+ delete this;
+ if (action)
+ action->signal();
+}
+
+void PaletteRotation::set(ScenePalette *palette, int start, int end, int rotationMode, int duration, Action *action) {
+ _duration = duration;
+ _step = false;
+ _action = action;
+ _scenePalette = palette;
+
+ Common::copy(&palette->_palette[0], &palette->_palette[256 * 3], &_palette[0]);
+
+ _start = start;
+ _end = end + 1;
+ _rotationMode = rotationMode;
+
+ switch (_rotationMode) {
+ case -1:
+ case 3:
+ _currIndex = _end;
+ break;
+ default:
+ _currIndex = _start;
+ break;
+ }
+}
+
+bool PaletteRotation::decDuration() {
+ if (_duration) {
+ if (--_duration == 0) {
+ remove();
+ return false;
+ }
+ }
+ return true;
+}
+
+void PaletteRotation::setDelay(int amount) {
+ _percent = _delayCtr = amount;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void PaletteFader::synchronise(Serialiser &s) {
+ PaletteModifierCached::synchronise(s);
+
+ s.syncAsSint16LE(_step);
+ s.syncAsSint16LE(_percent);
+ s.syncBytes(&_palette[0], 256 * 3);
+}
+
+void PaletteFader::signal() {
+ _percent -= _step;
+ if (_percent > 0) {
+ _scenePalette->fade((byte *)_palette, true /* 256 */, _percent);
+ } else {
+ remove();
+ }
+}
+
+void PaletteFader::remove() {
+ // Save of a copy of the object's action, since it will be used after the object is destroyed
+ Action *action = _action;
+
+ Common::copy(&_palette[0], &_palette[256 * 3], &_scenePalette->_palette[0]);
+ _scenePalette->refresh();
+ _scenePalette->_listeners.remove(this);
+ delete this;
+
+ if (action)
+ action->signal();
+}
+
+/*--------------------------------------------------------------------------*/
+
+ScenePalette::ScenePalette() {
+ // Set a default gradiant range
+ byte *palData = &_palette[0];
+ for (int idx = 0; idx < 256; ++idx) {
+ *palData++ = idx;
+ *palData++ = idx;
+ *palData++ = idx;
+ }
+
+ _field412 = 0;
+}
+
+ScenePalette::ScenePalette(int paletteNum) {
+ loadPalette(paletteNum);
+}
+
+bool ScenePalette::loadPalette(int paletteNum) {
+ byte *palData = _resourceManager->getResource(RES_PALETTE, paletteNum, 0, true);
+ if (!palData)
+ return false;
+
+ int palStart = READ_LE_UINT16(palData);
+ int palSize = READ_LE_UINT16(palData + 2);
+ assert(palSize <= 256);
+
+ byte *destP = &_palette[palStart * 3];
+ byte *srcP = palData + 6;
+
+ Common::copy(&srcP[0], &srcP[palSize * 3], destP);
+
+ DEALLOCATE(palData);
+ return true;
+}
+
+void ScenePalette::refresh() {
+ // Set indexes for standard colors to closest color in the palette
+ _colors.background = indexOf(255, 255, 255); // White background
+ _colors.foreground = indexOf(0, 0, 0); // Black foreground
+ _redColor = indexOf(180, 0, 0); // Red-ish
+ _greenColor = indexOf(0, 180, 0); // Green-ish
+ _blueColor = indexOf(0, 0, 180); // Blue-ish
+ _aquaColor = indexOf(0, 180, 180); // Aqua
+ _purpleColor = indexOf(180, 0, 180); // Purple
+ _limeColor = indexOf(180, 180, 0); // Lime
+
+ // Refresh the palette
+ g_system->getPaletteManager()->setPalette((const byte *)&_palette[0], 0, 256);
+}
+
+/**
+ * Loads a section of the palette into the game palette
+ */
+void ScenePalette::setPalette(int index, int count) {
+ g_system->getPaletteManager()->setPalette((const byte *)&_palette[index * 3], index, count);
+}
+
+/**
+ * Returns the palette index with the closest matching color to that specified
+ * @param r R component
+ * @param g G component
+ * @param b B component
+ * @param threshold Closeness threshold.
+ * @remarks A threshold may be provided to specify how close the matching color must be
+ */
+uint8 ScenePalette::indexOf(uint r, uint g, uint b, int threshold) {
+ int palIndex = -1;
+ byte *palData = &_palette[0];
+
+ for (int i = 0; i < 256; ++i) {
+ byte ir = *palData++;
+ byte ig = *palData++;
+ byte ib = *palData++;
+ int rDiff = abs(ir - (int)r);
+ int gDiff = abs(ig - (int)g);
+ int bDiff = abs(ib - (int)b);
+
+ int idxThreshold = rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
+ if (idxThreshold < threshold) {
+ threshold = idxThreshold;
+ palIndex = i;
+ }
+ }
+
+ return palIndex;
+}
+
+/**
+ * Loads the specified range of the palette with the current system palette
+ * @param start Start index
+ * @param count Number of palette entries
+ */
+void ScenePalette::getPalette(int start, int count) {
+ g_system->getPaletteManager()->grabPalette((byte *)&_palette[start], start, count);
+}
+
+void ScenePalette::signalListeners() {
+ SynchronisedList<PaletteModifier *>::iterator i = _listeners.begin();
+ while (i != _listeners.end()) {
+ PaletteModifier *obj = *i;
+ ++i;
+ obj->signal();
+ }
+}
+
+void ScenePalette::clearListeners() {
+ SynchronisedList<PaletteModifier *>::iterator i = _listeners.begin();
+ while (i != _listeners.end()) {
+ PaletteModifier *obj = *i;
+ ++i;
+ obj->remove();
+ }
+}
+
+void ScenePalette::fade(const byte *adjustData, bool fullAdjust, int percent) {
+ byte tempPalette[256 * 3];
+
+ // Ensure the percent adjustment is within 0 - 100%
+ percent = CLIP(percent, 0, 100);
+
+ for (int palIndex = 0; palIndex < 256; ++palIndex) {
+ const byte *srcP = (const byte *)&_palette[palIndex * 3];
+ byte *destP = &tempPalette[palIndex * 3];
+
+ for (int rgbIndex = 0; rgbIndex < 3; ++rgbIndex, ++srcP, ++destP) {
+ *destP = *srcP - ((*srcP - adjustData[rgbIndex]) * (100 - percent)) / 100;
+ }
+
+ if (fullAdjust)
+ adjustData += 3;
+ }
+
+ // Set the altered pale4tte
+ g_system->getPaletteManager()->setPalette((const byte *)&tempPalette[0], 0, 256);
+ g_system->updateScreen();
+}
+
+PaletteRotation *ScenePalette::addRotation(int start, int end, int rotationMode, int duration, Action *action) {
+ PaletteRotation *obj = new PaletteRotation();
+
+ if ((rotationMode == 2) || (rotationMode == 3))
+ duration <<= 1;
+
+ obj->set(this, start, end, rotationMode, duration, action);
+ _listeners.push_back(obj);
+ return obj;
+}
+
+PaletteFader *ScenePalette::addFader(const byte *arrBufferRGB, int palSize, int percent, Action *action) {
+ PaletteFader *fader = new PaletteFader();
+ fader->_action = action;
+ for (int i = 0; i < 256 * 3; i += 3) {
+ fader->_palette[i] = *(arrBufferRGB + 0);
+ fader->_palette[i + 1] = *(arrBufferRGB + 1);
+ fader->_palette[i + 2] = *(arrBufferRGB + 2);
+
+ if (palSize > 1)
+ arrBufferRGB += 3;
+ }
+
+ fader->setPalette(this, percent);
+ _globals->_scenePalette._listeners.push_back(fader);
+ return fader;
+}
+
+
+void ScenePalette::changeBackground(const Rect &bounds, FadeMode fadeMode) {
+ ScenePalette tempPalette;
+
+ if (_globals->_sceneManager._hasPalette) {
+ if ((fadeMode == FADEMODE_GRADUAL) || (fadeMode == FADEMODE_IMMEDIATE)) {
+ // Fade out any active palette
+ tempPalette.getPalette();
+ uint32 adjustData = 0;
+
+ for (int percent = 100; percent >= 0; percent -= 5) {
+ if (fadeMode == FADEMODE_IMMEDIATE)
+ percent = 0;
+ tempPalette.fade((byte *)&adjustData, false, percent);
+ g_system->delayMillis(10);
+ }
+ } else {
+ _globals->_scenePalette.refresh();
+ _globals->_sceneManager._hasPalette = false;
+ }
+ }
+
+ _globals->_screenSurface.copyFrom(_globals->_sceneManager._scene->_backSurface,
+ bounds, Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), NULL);
+
+ for (SynchronisedList<PaletteModifier *>::iterator i = tempPalette._listeners.begin(); i != tempPalette._listeners.end(); ++i)
+ delete *i;
+ tempPalette._listeners.clear();
+}
+
+void ScenePalette::synchronise(Serialiser &s) {
+ SavedObject::synchronise(s);
+
+ s.syncBytes(_palette, 256 * 3);
+ s.syncAsSint32LE(_colors.foreground);
+ s.syncAsSint32LE(_colors.background);
+
+ s.syncAsSint32LE(_field412);
+ s.syncAsByte(_redColor);
+ s.syncAsByte(_greenColor);
+ s.syncAsByte(_blueColor);
+ s.syncAsByte(_aquaColor);
+ s.syncAsByte(_purpleColor);
+ s.syncAsByte(_limeColor);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SceneItem::synchronise(Serialiser &s) {
+ EventHandler::synchronise(s);
+
+ _bounds.synchronise(s);
+ s.syncString(_msg);
+ s.syncAsSint32LE(_fieldE);
+ s.syncAsSint32LE(_field10);
+ s.syncAsSint16LE(_position.x); s.syncAsSint32LE(_position.y);
+ s.syncAsSint16LE(_yDiff);
+ s.syncAsSint32LE(_sceneRegionId);
+}
+
+void SceneItem::remove() {
+ _globals->_sceneItems.remove(this);
+}
+
+void SceneItem::doAction(int action) {
+ const char *msg = NULL;
+
+ switch ((int)action) {
+ case CURSOR_LOOK:
+ msg = LOOK_SCENE_HOTSPOT;
+ break;
+ case CURSOR_USE:
+ msg = USE_SCENE_HOTSPOT;
+ break;
+ case CURSOR_TALK:
+ msg = TALK_SCENE_HOTSPOT;
+ break;
+ case 0x1000:
+ msg = SPECIAL_SCENE_HOTSPOT;
+ break;
+ default:
+ msg = DEFAULT_SCENE_HOTSPOT;
+ break;
+ }
+
+ GUIErrorMessage(msg);
+}
+
+bool SceneItem::contains(const Common::Point &pt) {
+ const Rect &sceneBounds = _globals->_sceneManager._scene->_sceneBounds;
+
+ if (_sceneRegionId == 0)
+ return _bounds.contains(pt.x + sceneBounds.left, pt.y + sceneBounds.top);
+ else
+ return _globals->_sceneRegions.indexOf(Common::Point(pt.x + sceneBounds.left,
+ pt.y + sceneBounds.top)) == _sceneRegionId;
+}
+
+void SceneItem::display(int resNum, int lineNum, ...) {
+ Common::String msg = !resNum ? Common::String() : _resourceManager->getMessage(resNum, lineNum);
+
+ if (_globals->_sceneObjects->contains(&_globals->_sceneText)) {
+ _globals->_sceneText.remove();
+ _globals->_sceneObjects->draw();
+ }
+
+ GfxFontBackup font;
+ Common::Point pos(160, 100);
+ Rect textRect;
+ int maxWidth = 120;
+ bool keepOnscreen = false;
+ bool centerText = true;
+
+ if (resNum) {
+ va_list va;
+ va_start(va, lineNum);
+
+ int mode;
+ do {
+ // Get next instruction
+ mode = va_arg(va, int);
+
+ switch (mode) {
+ case SET_WIDTH:
+ // Set width
+ maxWidth = va_arg(va, int);
+ _globals->_sceneText._width = maxWidth;
+ break;
+ case SET_X:
+ // Set the X Position
+ pos.x = va_arg(va, int);
+ break;
+ case SET_Y:
+ // Set the Y Position
+ pos.y = va_arg(va, int);
+ break;
+ case SET_FONT:
+ // Set the font number
+ _globals->_sceneText._fontNumber = va_arg(va, int);
+ _globals->gfxManager()._font.setFontNumber(_globals->_sceneText._fontNumber);
+ break;
+ case SET_BG_COLOR: {
+ // Set the background color
+ int bgColor = va_arg(va, int);
+ _globals->gfxManager()._font._colors.background = bgColor;
+ if (!bgColor)
+ _globals->gfxManager().setFillFlag(false);
+ break;
+ }
+ case SET_FG_COLOR:
+ // Set the foreground color
+ _globals->_sceneText._color1 = va_arg(va, int);
+ _globals->gfxManager()._font._colors.foreground = _globals->_sceneText._color1;
+ break;
+ case SET_KEEP_ONSCREEN:
+ // Suppresses immediate display
+ keepOnscreen = va_arg(va, int) != 0;
+ break;
+ case SET_EXT_BGCOLOR: {
+ // Set secondary bg color
+ int v = va_arg(va, int);
+ _globals->_sceneText._color2 = v;
+ _globals->gfxManager()._font._colors2.background = v;
+ break;
+ }
+ case SET_EXT_FGCOLOR: {
+ // Set secondary fg color
+ int v = va_arg(va, int);
+ _globals->_sceneText._color3 = v;
+ _globals->gfxManager()._font._colors.foreground = v;
+ break;
+ }
+ case SET_POS_MODE:
+ // Set whether a custom x/y is used
+ centerText = va_arg(va, int) != 0;
+ break;
+ case SET_TEXT_MODE:
+ // Set the text mode
+ _globals->_sceneText._textMode = (TextAlign)va_arg(va, int);
+ break;
+ default:
+ break;
+ }
+ } while (mode != LIST_END);
+
+ va_end(va);
+ }
+
+ if (resNum) {
+ // Get required bounding size
+ _globals->gfxManager().getStringBounds(msg.c_str(), textRect, maxWidth);
+ textRect.center(pos.x, pos.y);
+
+ textRect.contain(_globals->gfxManager()._bounds);
+ if (centerText) {
+ _globals->_sceneText._color1 = _globals->_sceneText._color2;
+ _globals->_sceneText._color2 = 0;
+ _globals->_sceneText._color3 = 0;
+ }
+
+ _globals->_sceneText.setup(msg);
+ if (centerText) {
+ _globals->_sceneText.setPosition(Common::Point(
+ _globals->_sceneManager._scene->_sceneBounds.left + textRect.left,
+ _globals->_sceneManager._scene->_sceneBounds.top + textRect.top), 0);
+ } else {
+ _globals->_sceneText.setPosition(pos, 0);
+ }
+
+ _globals->_sceneText.fixPriority(255);
+ _globals->_sceneObjects->draw();
+ }
+
+ // Unless the flag is set to keep the message on-screen, show it until a mouse or keypress, then remove it
+ if (!keepOnscreen && !msg.empty()) {
+ Event event;
+
+ // Keep event on-screen until a mouse or keypress
+ while (!_vm->getEventManager()->shouldQuit() && !_globals->_events.getEvent(event,
+ EVENT_BUTTON_DOWN | EVENT_KEYPRESS)) {
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+
+ _globals->_sceneText.remove();
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SceneHotspot::doAction(int action) {
+ switch ((int)action) {
+ case CURSOR_LOOK:
+ display(1, 0, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ display(1, 5, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_TALK:
+ display(1, 15, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_WALK:
+ break;
+ default:
+ display(2, action, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void NamedHotspot::doAction(int action) {
+ switch (action) {
+ case CURSOR_WALK:
+ // Nothing
+ break;
+ case CURSOR_LOOK:
+ if (_lookLineNum == -1)
+ SceneHotspot::doAction(action);
+ else
+ SceneItem::display(_resnum, _lookLineNum, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ if (_useLineNum == -1)
+ SceneHotspot::doAction(action);
+ else
+ SceneItem::display(_resnum, _useLineNum, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void NamedHotspot::setup(int ys, int xs, int ye, int xe, const int resnum, const int lookLineNum, const int useLineNum) {
+ setBounds(ys, xe, ye, xs);
+ _resnum = resnum;
+ _lookLineNum = lookLineNum;
+ _useLineNum = useLineNum;
+ _globals->_sceneItems.addItems(this, NULL);
+}
+
+void NamedHotspot::synchronise(Serialiser &s) {
+ SceneHotspot::synchronise(s);
+ s.syncAsSint16LE(_resnum);
+ s.syncAsSint16LE(_lookLineNum);
+ s.syncAsSint16LE(_useLineNum);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SceneObjectWrapper::setSceneObject(SceneObject *so) {
+ _sceneObject = so;
+ so->_strip = 1;
+ so->_flags |= OBJFLAG_PANES;
+}
+
+void SceneObjectWrapper::synchronise(Serialiser &s) {
+ EventHandler::synchronise(s);
+ SYNC_POINTER(_sceneObject);
+}
+
+void SceneObjectWrapper::remove() {
+ delete this;
+}
+
+void SceneObjectWrapper::dispatch() {
+ _visageImages.setVisage(_sceneObject->_visage);
+ int frameCount = _visageImages.getFrameCount();
+ int angle = _sceneObject->_angle;
+ int strip = _sceneObject->_strip;
+
+ if (frameCount == 4) {
+ if ((angle > 314) || (angle < 45))
+ strip = 4;
+ if ((angle > 44) && (angle < 135))
+ strip = 1;
+ if ((angle >= 135) && (angle < 225))
+ strip = 3;
+ if ((angle >= 225) && (angle < 315))
+ strip = 2;
+ } else if (frameCount == 8) {
+ if ((angle > 330) || (angle < 30))
+ strip = 4;
+ if ((angle >= 30) && (angle < 70))
+ strip = 7;
+ if ((angle >= 70) && (angle < 110))
+ strip = 1;
+ if ((angle >= 110) && (angle < 150))
+ strip = 5;
+ if ((angle >= 150) && (angle < 210))
+ strip = 3;
+ if ((angle >= 210) && (angle < 250))
+ strip = 6;
+ if ((angle >= 250) && (angle < 290))
+ strip = 2;
+ if ((angle >= 290) && (angle < 331))
+ strip = 8;
+ }
+
+ if (strip > frameCount)
+ strip = frameCount;
+
+ _sceneObject->setStrip(strip);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SceneObject::SceneObject() : SceneHotspot() {
+ _endAction = NULL;
+ _mover = NULL;
+ _objectWrapper = NULL;
+ _flags = 0;
+ _walkStartFrame = 0;
+ _animateMode = ANIM_MODE_NONE;
+ _updateStartFrame = 0;
+ _moveDiff.x = 5;
+ _moveDiff.y = 3;
+ _numFrames = 10;
+ _numFrames = 10;
+ _moveRate = 10;
+ _regionBitList = 0;
+ _sceneRegionId = 0;
+ _percent = 100;
+ _flags |= OBJFLAG_PANES;
+
+ _frameChange = 0;
+}
+
+SceneObject::SceneObject(const SceneObject &so) : SceneHotspot() {
+ *this = so;
+ if (_objectWrapper)
+ // Create a fresh object wrapper for this object
+ _objectWrapper = new SceneObjectWrapper();
+}
+
+SceneObject::~SceneObject() {
+ delete _mover;
+ delete _objectWrapper;
+}
+
+int SceneObject::getNewFrame() {
+ int frameNum = _frame + _frameChange;
+
+ if (_frameChange > 0) {
+ if (frameNum > getFrameCount()) {
+ frameNum = 1;
+ if (_animateMode == ANIM_MODE_1)
+ ++frameNum;
+ }
+ } else if (frameNum < 1) {
+ frameNum = getFrameCount();
+ }
+
+ return frameNum;
+}
+
+int SceneObject::getFrameCount() {
+ _visageImages.setVisage(_visage, _strip);
+ return _visageImages.getFrameCount();
+}
+
+void SceneObject::animEnded() {
+ _animateMode = ANIM_MODE_NONE;
+ if (_endAction)
+ _endAction->signal();
+}
+
+int SceneObject::changeFrame() {
+ int frameNum = _frame;
+ uint32 mouseCtr = _globals->_events.getFrameNumber();
+
+ if ((_updateStartFrame <= mouseCtr) || (_animateMode == ANIM_MODE_1)) {
+ if (_numFrames > 0) {
+ int v = 60 / _numFrames;
+ _updateStartFrame = mouseCtr + v;
+
+ frameNum = getNewFrame();
+ }
+ }
+
+ return frameNum;
+}
+
+void SceneObject::setPosition(const Common::Point &p, int yDiff) {
+ _position = p;
+ _yDiff = yDiff;
+ _flags |= OBJFLAG_PANES;
+}
+
+void SceneObject::setZoom(int percent) {
+ assert((percent >= -1) && (percent < 999));
+ if (percent != _percent) {
+ _percent = percent;
+ _flags |= OBJFLAG_PANES;
+ }
+}
+
+void SceneObject::updateZoom() {
+ changeZoom(_percent);
+}
+
+void SceneObject::changeZoom(int percent) {
+ if (percent == -1)
+ _flags &= ~OBJFLAG_ZOOMED;
+ else {
+ _flags |= OBJFLAG_ZOOMED;
+ setZoom(percent);
+ }
+}
+
+void SceneObject::setStrip(int stripNum) {
+ if (stripNum != _strip) {
+ _strip = stripNum;
+ _flags |= OBJFLAG_PANES;
+ }
+}
+
+void SceneObject::setStrip2(int stripNum) {
+ if (stripNum == -1)
+ _flags &= ~OBJFLAG_SUPPRESS_DISPATCH;
+ else {
+ _flags |= OBJFLAG_SUPPRESS_DISPATCH;
+ setStrip(stripNum);
+ }
+}
+
+void SceneObject::setFrame(int frameNum) {
+ if (frameNum != _frame) {
+ _frame = frameNum;
+ _flags |= OBJFLAG_PANES;
+ }
+}
+
+void SceneObject::setFrame2(int frameNum) {
+ if (frameNum != -1) {
+ _flags |= OBJFLAG_NO_UPDATES;
+ setFrame(frameNum);
+ } else {
+ _flags &= ~OBJFLAG_NO_UPDATES;
+ }
+}
+
+void SceneObject::setPriority(int priority) {
+ if (priority != _priority) {
+ _priority = priority;
+ _flags |= OBJFLAG_PANES;
+ }
+}
+
+void SceneObject::fixPriority(int priority) {
+ if (priority == -1) {
+ _flags &= ~OBJFLAG_FIXED_PRIORITY;
+ } else {
+ _flags |= OBJFLAG_FIXED_PRIORITY;
+ setPriority(priority);
+ }
+}
+
+void SceneObject::setVisage(int visage) {
+ if (visage != _visage) {
+ _visage = visage;
+ _flags |= OBJFLAG_PANES;
+ }
+}
+
+void SceneObject::setObjectWrapper(SceneObjectWrapper *objWrapper) {
+ if (_objectWrapper)
+ _objectWrapper->remove();
+ _objectWrapper = objWrapper;
+ if (objWrapper)
+ objWrapper->setSceneObject(this);
+}
+
+void SceneObject::addMover(ObjectMover *mover, ...) {
+ if (_mover)
+ _mover->remove();
+ _mover = mover;
+
+ if (mover) {
+ // Set up the assigned mover
+ _walkStartFrame = _globals->_events.getFrameNumber();
+ if (_moveRate != 0)
+ _walkStartFrame = 60 / _moveRate;
+
+ // Signal the mover that movement is beginning
+ va_list va;
+ va_start(va, mover);
+ mover->startMove(this, va);
+ va_end(va);
+ }
+}
+
+void SceneObject::getHorizBounds() {
+ Rect tempRect;
+
+ GfxSurface frame = getFrame();
+ tempRect.resize(frame, _position.x, _position.y - _yDiff, _percent);
+
+ _xs = tempRect.left;
+ _xe = tempRect.right;
+}
+
+int SceneObject::getRegionIndex() {
+ return _globals->_sceneRegions.indexOf(_position);
+}
+
+int SceneObject::checkRegion(const Common::Point &pt) {
+ Rect tempRect;
+ int regionIndex = 0;
+
+ // Temporarily change the position
+ Common::Point savedPos = _position;
+ _position = pt;
+
+ int regIndex = _globals->_sceneRegions.indexOf(pt);
+ if (_regionBitList & (1 << regIndex))
+ regionIndex = regIndex;
+
+ // Restore position
+ _position = savedPos;
+
+ // Get the object's frame bounds
+ GfxSurface frame = getFrame();
+ tempRect.resize(frame, _position.x, _position.y - _yDiff, _percent);
+
+ int yPos, newY;
+ if ((_position.y - _yDiff) <= (pt.y - _yDiff)) {
+ yPos = _position.y - _yDiff;
+ newY = pt.y;
+ } else {
+ yPos = pt.y - _yDiff;
+ newY = _position.y;
+ }
+ newY -= _yDiff;
+
+ SynchronisedList<SceneObject *>::iterator i;
+ for (i = _globals->_sceneObjects->begin(); (regionIndex == 0) && (i != _globals->_sceneObjects->end()); ++i) {
+ if ((*i) && ((*i)->_flags & OBJFLAG_CHECK_REGION)) {
+ int objYDiff = (*i)->_position.y - _yDiff;
+ if ((objYDiff >= yPos) && (objYDiff <= newY) &&
+ ((*i)->_xs < tempRect.right) && ((*i)->_xe > tempRect.left)) {
+ // Found index
+ regionIndex = -1; //****DEBUG*** = *i;
+ break;
+ }
+ }
+ }
+
+ return regionIndex;
+}
+
+void SceneObject::animate(AnimateMode animMode, ...) {
+ _animateMode = animMode;
+ _updateStartFrame = _globals->_events.getFrameNumber();
+ if (_numFrames)
+ _updateStartFrame += 60 / _numFrames;
+
+ va_list va;
+ va_start(va, animMode);
+
+ switch (_animateMode) {
+ case ANIM_MODE_NONE:
+ _endAction = NULL;
+ break;
+
+ case ANIM_MODE_1:
+ _frameChange = 1;
+ _field2E = _position;
+ _endAction = 0;
+ break;
+
+ case ANIM_MODE_2:
+ _frameChange = 1;
+ _endAction = NULL;
+ break;
+
+ case ANIM_MODE_3:
+ _frameChange = -1;
+ _endAction = NULL;
+ break;
+
+ case ANIM_MODE_4:
+ _endFrame = va_arg(va, int);
+ _frameChange = va_arg(va, int);
+ _endAction = va_arg(va, Action *);
+ if (_endFrame == _frame)
+ setFrame(getNewFrame());
+ break;
+
+ case ANIM_MODE_5:
+ _frameChange = 1;
+ _endFrame = getFrameCount();
+ _endAction = va_arg(va, Action *);
+ if (_endFrame == _frame)
+ setFrame(getNewFrame());
+ break;
+
+ case ANIM_MODE_6:
+ _frameChange = -1;
+ _endAction = va_arg(va, Action *);
+ _endFrame = 1;
+ if (_frame == _endFrame)
+ setFrame(getNewFrame());
+ break;
+
+ case ANIM_MODE_7:
+ _endFrame = va_arg(va, int);
+ _endAction = va_arg(va, Action *);
+ _frameChange = 1;
+ break;
+
+ case ANIM_MODE_8:
+ _field68 = va_arg(va, int);
+ _endAction = va_arg(va, Action *);
+ _frameChange = 1;
+ _endFrame = getFrameCount();
+ if (_frame == _endFrame)
+ setFrame(getNewFrame());
+ break;
+ }
+}
+
+SceneObject *SceneObject::clone() const {
+ SceneObject *obj = new SceneObject(*this);
+ return obj;
+}
+
+void SceneObject::checkAngle(const SceneObject *obj) {
+ _angle = GfxManager::getAngle(_position, obj->_position);
+
+ if (_objectWrapper)
+ _objectWrapper->dispatch();
+}
+
+void SceneObject::hide() {
+ _flags |= OBJFLAG_HIDE;
+ if (_flags & OBJFLAG_HIDING)
+ _flags |= OBJFLAG_PANES;
+}
+
+void SceneObject::show() {
+ if (_flags & OBJFLAG_HIDE) {
+ _flags &= ~OBJFLAG_HIDE;
+ _flags |= OBJFLAG_PANES;
+ }
+}
+
+int SceneObject::getSpliceArea(const SceneObject *obj) {
+ int xd = ABS(_position.x - obj->_position.x);
+ int yd = ABS(_position.y - obj->_position.y);
+
+ return (xd * xd + yd) / 2;
+}
+
+void SceneObject::synchronise(Serialiser &s) {
+ SceneHotspot::synchronise(s);
+
+ s.syncAsUint32LE(_updateStartFrame);
+ s.syncAsUint32LE(_walkStartFrame);
+ s.syncAsSint16LE(_field2E.x); s.syncAsSint16LE(_field2E.y);
+ s.syncAsSint16LE(_percent);
+ s.syncAsSint16LE(_priority);
+ s.syncAsSint16LE(_angle);
+ s.syncAsUint32LE(_flags);
+ s.syncAsSint16LE(_xs);
+ s.syncAsSint16LE(_xe);
+ _paneRects[0].synchronise(s);
+ _paneRects[1].synchronise(s);
+ s.syncAsSint32LE(_visage);
+ SYNC_POINTER(_objectWrapper);
+ s.syncAsSint32LE(_strip);
+ SYNC_ENUM(_animateMode, AnimateMode);
+ s.syncAsSint32LE(_frame);
+ s.syncAsSint32LE(_endFrame);
+ s.syncAsSint32LE(_field68);
+ s.syncAsSint32LE(_frameChange);
+ s.syncAsSint32LE(_numFrames);
+ s.syncAsSint32LE(_regionIndex);
+ SYNC_POINTER(_mover);
+ s.syncAsSint16LE(_moveDiff.x); s.syncAsSint16LE(_moveDiff.y);
+ s.syncAsSint32LE(_moveRate);
+ SYNC_POINTER(_endAction);
+ s.syncAsUint32LE(_regionBitList);
+}
+
+void SceneObject::postInit(SceneObjectList *OwnerList) {
+ if (!OwnerList)
+ OwnerList = _globals->_sceneObjects;
+
+ if (!OwnerList->contains(this)) {
+ _percent = 100;
+ _priority = 255;
+ _flags = 4;
+ _visage = 0;
+ _strip = 1;
+ _frame = 1;
+ _objectWrapper = NULL;
+ _animateMode = ANIM_MODE_NONE;
+ _endAction = 0;
+ _mover = NULL;
+ _yDiff = 0;
+ _moveDiff.x = 5;
+ _moveDiff.y = 3;
+ _moveRate = 10;
+ _regionIndex = 0x40;
+ _numFrames = 10;
+ _regionBitList = 0;
+
+ OwnerList->push_back(this);
+ _flags |= OBJFLAG_PANES;
+ }
+}
+
+void SceneObject::remove() {
+ SceneItem::remove();
+ if (_globals->_sceneObjects->contains(this))
+ // For objects in the object list, flag the object for removal in the next drawing, so that
+ // the drawing code has a chance to restore the area previously covered by the object
+ _flags |= OBJFLAG_PANES | OBJFLAG_REMOVE | OBJFLAG_HIDE;
+ else
+ // Not in the list, so immediately remove the object
+ removeObject();
+}
+
+void SceneObject::dispatch() {
+ uint32 currTime = _globals->_events.getFrameNumber();
+ if (_action)
+ _action->dispatch();
+
+ if (_mover && (_walkStartFrame <= currTime)) {
+ if (_moveRate) {
+ int frameInc = 60 / _moveRate;
+ _walkStartFrame = currTime + frameInc;
+ }
+ _mover->dispatch();
+ }
+
+ if (!(_flags & OBJFLAG_NO_UPDATES)) {
+ switch (_animateMode) {
+ case ANIM_MODE_1:
+ if (isNoMover())
+ setFrame(1);
+ else if ((_field2E.x != _position.x) || (_field2E.y != _position.y)) {
+ setFrame(changeFrame());
+ _field2E = _position;
+
+ }
+ break;
+
+ case ANIM_MODE_2:
+ case ANIM_MODE_3:
+ setFrame(changeFrame());
+
+ break;
+ case ANIM_MODE_4:
+ case ANIM_MODE_5:
+ case ANIM_MODE_6:
+ if (_frame == _endFrame)
+ animEnded();
+ else
+ setFrame(changeFrame());
+ break;
+
+ case ANIM_MODE_7:
+ if (changeFrame() != _frame) {
+ // Pick a new random frame
+ int frameNum = 0;
+ do {
+ int count = getFrameCount();
+ frameNum = _globals->_randomSource.getRandomNumber(count - 1);
+ } while (frameNum == _frame);
+
+ setFrame(frameNum);
+ if (_endFrame) {
+ if (--_endFrame == 0)
+ animEnded();
+ }
+ }
+ break;
+
+ case ANIM_MODE_8:
+ if (_frame == _endFrame) {
+ if (_frameChange != -1) {
+ _frameChange = -1;
+ _endFrame = 1;
+
+ setFrame(changeFrame());
+ } else if (!_field68 || (--_field68 > 0)) {
+ _frameChange = 1;
+ _endFrame = getFrameCount();
+
+ setFrame(changeFrame());
+ } else {
+ animEnded();
+ }
+ } else {
+ setFrame(changeFrame());
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Handle updating the zoom and/or priority
+ if (!(_flags & OBJFLAG_ZOOMED)) {
+ int yp = CLIP((int)_position.y, 0, 255);
+ setZoom(_globals->_sceneManager._scene->_zoomPercents[yp]);
+ }
+ if (!(_flags & OBJFLAG_FIXED_PRIORITY)) {
+ setPriority(_position.y);
+ }
+}
+
+void SceneObject::calcAngle(const Common::Point &pt) {
+ int newAngle = GfxManager::getAngle(_position, pt);
+ if (newAngle != -1)
+ _angle = newAngle;
+}
+
+void SceneObject::removeObject() {
+ _globals->_sceneItems.remove(this);
+ _globals->_sceneObjects->remove(this);
+
+ if (_visage) {
+ _visage = 0;
+ }
+
+ if (_objectWrapper) {
+ _objectWrapper->remove();
+ _objectWrapper = NULL;
+ }
+ if (_mover) {
+ _mover->remove();
+ _mover = NULL;
+ }
+ if (_flags & OBJFLAG_CLONED)
+ // Cloned temporary object, so delete it
+ delete this;
+}
+
+GfxSurface SceneObject::getFrame() {
+ _visageImages.setVisage(_visage, _strip);
+ return _visageImages.getFrame(_frame);
+}
+
+void SceneObject::reposition() {
+ GfxSurface frame = getFrame();
+ _bounds.resize(frame, _position.x, _position.y - _yDiff, _percent);
+ _xs = _bounds.left;
+ _xe = _bounds.right;
+}
+
+/**
+ * Draws an object into the scene
+ */
+void SceneObject::draw() {
+ Rect destRect = _bounds;
+ destRect.translate(-_globals->_sceneManager._scene->_sceneBounds.left,
+ -_globals->_sceneManager._scene->_sceneBounds.top);
+ Region *priorityRegion = _globals->_sceneManager._scene->_priorities.find(_priority);
+ GfxSurface frame = getFrame();
+ _globals->gfxManager().copyFrom(frame, destRect, priorityRegion);
+}
+
+/**
+ * Refreshes the background around the area of a scene object prior to it's being redrawn,
+ * in case it is moving
+ */
+void SceneObject::updateScreen() {
+ Rect srcRect = _paneRects[CURRENT_PANENUM];
+ const Rect &sceneBounds = _globals->_sceneManager._scene->_sceneBounds;
+ srcRect.left = (srcRect.left / 4) * 4;
+ srcRect.right = ((srcRect.right + 3) / 4) * 4;
+ srcRect.clip(_globals->_sceneManager._scene->_sceneBounds);
+
+ if (srcRect.isValidRect()) {
+ Rect destRect = srcRect;
+ destRect.translate(-sceneBounds.left, -sceneBounds.top);
+ srcRect.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y);
+
+ _globals->_screenSurface.copyFrom(_globals->_sceneManager._scene->_backSurface, srcRect, destRect);
+ }
+}
+
+void SceneObject::setup(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority) {
+ postInit();
+ setVisage(visage);
+ setStrip(stripFrameNum);
+ setFrame(frameNum);
+ setPosition(Common::Point(posX, posY), 0);
+ fixPriority(priority);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SceneObjectList::draw() {
+ Common::Array<SceneObject *> objList;
+ int paneNum = 0;
+ int xAmount = 0, yAmount = 0;
+
+ if (_objList.size() == 0) {
+ // Alternate draw mode
+
+ if (_globals->_paneRefreshFlag[paneNum] == 1) {
+ // Load the background
+ _globals->_sceneManager._scene->refreshBackground(0, 0);
+
+ Rect tempRect = _globals->_sceneManager._scene->_sceneBounds;
+ tempRect.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y);
+ ScenePalette::changeBackground(tempRect, _globals->_sceneManager._fadeMode);
+ } else {
+ _globals->_paneRegions[CURRENT_PANENUM].draw();
+ }
+
+ _globals->_paneRegions[CURRENT_PANENUM].setRect(0, 0, 0, 0);
+ _globals->_sceneManager.fadeInIfNecessary();
+
+ } else {
+ // If there is a scroll follower, check whether it has moved off-screen
+ if (_globals->_scrollFollower) {
+ const Rect &scrollerRect = _globals->_sceneManager._scrollerRect;
+ Common::Point objPos(
+ _globals->_scrollFollower->_position.x - _globals->_sceneManager._scene->_sceneBounds.left,
+ _globals->_scrollFollower->_position.y - _globals->_sceneManager._scene->_sceneBounds.top);
+ int loadCount = 0;
+
+ if (objPos.x >= scrollerRect.right) {
+ xAmount = 8;
+ loadCount = 20;
+ }
+ if (objPos.x < scrollerRect.left) {
+ xAmount = -8;
+ loadCount = 20;
+ }
+ if (objPos.y >= scrollerRect.bottom) {
+ yAmount = 2;
+ loadCount = 25;
+ }
+ if (objPos.y < scrollerRect.top) {
+ yAmount = -2;
+ loadCount = 25;
+ }
+
+ if (loadCount > 0)
+ _globals->_sceneManager.setBgOffset(Common::Point(xAmount, yAmount), loadCount);
+ }
+
+ if (_globals->_sceneManager._sceneLoadCount > 0) {
+ --_globals->_sceneManager._sceneLoadCount;
+ _globals->_sceneManager._scene->loadBackground(_globals->_sceneManager._sceneBgOffset.x,
+ _globals->_sceneManager._sceneBgOffset.y);
+ }
+
+ // Set up the flag mask
+ uint32 flagMask = (paneNum == 0) ? OBJFLAG_PANE_0 : OBJFLAG_PANE_1;
+
+ // Initial loop to set up object list and update object position, priority, and flags
+ for (SynchronisedList<SceneObject *>::iterator i = _globals->_sceneObjects->begin();
+ i != _globals->_sceneObjects->end(); ++i) {
+ SceneObject *obj = *i;
+ objList.push_back(obj);
+
+ if (!(obj->_flags & OBJFLAG_HIDE))
+ obj->_flags &= ~OBJFLAG_HIDING;
+
+ // Reposition the bounds of the object to match the desired position
+ obj->reposition();
+
+ // Handle updating object priority
+ if (!(obj->_flags & OBJFLAG_FIXED_PRIORITY)) {
+ obj->_priority = MIN((int)obj->_position.y,
+ (int)_globals->_sceneManager._scene->_backgroundBounds.bottom - 1);
+ }
+
+ if ((_globals->_paneRefreshFlag[paneNum] != 0) || !_globals->_paneRegions[paneNum].empty()) {
+ obj->_flags |= flagMask;
+ }
+ }
+
+ // Check for any intersections, and then sort the object list by priority
+ checkIntersection(objList, objList.size(), CURRENT_PANENUM);
+ sortList(objList);
+
+ if (_globals->_paneRefreshFlag[paneNum] == 1) {
+ // Load the background
+ _globals->_sceneManager._scene->refreshBackground(0, 0);
+ }
+
+ _globals->_sceneManager._scene->_sceneBounds.left &= ~3;
+ _globals->_sceneManager._scene->_sceneBounds.right &= ~3;
+ _globals->_sceneOffset.x &= ~3;
+
+ if (_globals->_paneRefreshFlag[paneNum] != 0) {
+ // Change the background
+ Rect tempRect = _globals->_sceneManager._scene->_sceneBounds;
+ tempRect.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y);
+ ScenePalette::changeBackground(tempRect, _globals->_sceneManager._fadeMode);
+ } else {
+ for (uint objIndex = 0; objIndex < objList.size(); ++objIndex) {
+ SceneObject *obj = objList[objIndex];
+
+ if ((obj->_flags & flagMask) && obj->_paneRects[paneNum].isValidRect())
+ obj->updateScreen();
+ }
+
+ _globals->_paneRegions[paneNum].draw();
+ }
+
+ _globals->_paneRegions[paneNum].setRect(0, 0, 0, 0);
+redraw:
+ // Main draw loop
+ for (uint objIndex = 0; objIndex < objList.size(); ++objIndex) {
+ SceneObject *obj = objList[objIndex];
+
+ if ((obj->_flags & flagMask) && !(obj->_flags & OBJFLAG_HIDE)) {
+ obj->_paneRects[paneNum] = obj->_bounds;
+ obj->draw();
+ }
+ }
+
+ // Update the palette
+ _globals->_sceneManager.fadeInIfNecessary();
+ _globals->_sceneManager._loadMode = 0;
+ _globals->_paneRefreshFlag[paneNum] = 0;
+
+ // Loop through the object list, removing any objects and refreshing the screen as necessary
+ for (uint objIndex = 0; objIndex < objList.size(); ++objIndex) {
+ SceneObject *obj = objList[objIndex];
+
+ if (obj->_flags & OBJFLAG_HIDE)
+ obj->_flags |= OBJFLAG_HIDING;
+ obj->_flags &= ~flagMask;
+ if (obj->_flags & OBJFLAG_REMOVE) {
+ obj->_flags |= OBJFLAG_PANES;
+
+ checkIntersection(objList, objIndex, CURRENT_PANENUM);
+
+ obj->updateScreen();
+ obj->removeObject();
+
+ // FIXME: Currently, removing objects causes screen flickers when the removed object intersects
+ // another drawn object, since the background is briefly redrawn over the object. For now, I'm
+ // using a forced jump back to redraw objects. In the long term, I should figure out how the
+ // original game does this properly
+ objList.remove_at(objIndex);
+ goto redraw;
+ }
+ }
+ }
+}
+
+void SceneObjectList::checkIntersection(Common::Array<SceneObject *> &ObjList, uint ObjIndex, int PaneNum) {
+ uint32 flagMask = (PaneNum == 0) ? OBJFLAG_PANE_0 : OBJFLAG_PANE_1;
+ SceneObject *obj = (ObjIndex == ObjList.size()) ? NULL : ObjList[ObjIndex];
+ Rect rect1;
+
+ for (uint idx = 0; idx < ObjList.size(); ++idx) {
+ SceneObject *currObj = ObjList[idx];
+
+ if (ObjIndex == ObjList.size()) {
+ if (currObj->_flags & flagMask)
+ checkIntersection(ObjList, idx, PaneNum);
+ } else if (idx != ObjIndex) {
+ Rect &paneRect = obj->_paneRects[PaneNum];
+ Rect objBounds = currObj->_bounds;
+ if (paneRect.isValidRect())
+ objBounds.extend(paneRect);
+
+ Rect objBounds2 = currObj->_bounds;
+ if (paneRect.isValidRect())
+ objBounds2.extend(paneRect);
+
+ objBounds.left &= ~3;
+ objBounds.right += 3;
+ objBounds.right &= ~3;
+ objBounds2.left &= ~3;
+ objBounds2.right += 3;
+ objBounds2.right &= ~3;
+
+ if (objBounds.intersects(objBounds2) && !(currObj->_flags & flagMask)) {
+ currObj->_flags |= flagMask;
+ checkIntersection(ObjList, idx, PaneNum);
+ }
+ }
+ }
+}
+
+struct SceneObjectLess {
+ bool operator()(const SceneObject *x, const SceneObject *y) const {
+ if (y->_priority > x->_priority)
+ return true;
+ else if ((y->_priority == x->_priority) && (y->_position.y > x->_position.y))
+ return true;
+ else if ((y->_priority == x->_priority) && (y->_position.y == x->_position.y) &&
+ (y->_yDiff > x->_yDiff))
+ return true;
+
+ return false;
+ }
+};
+
+void SceneObjectList::sortList(Common::Array<SceneObject *> &ObjList) {
+ Common::sort(ObjList.begin(), ObjList.end(), SceneObjectLess());
+}
+
+void SceneObjectList::activate() {
+ SceneObjectList *objectList = _globals->_sceneObjects;
+ _globals->_sceneObjects = this;
+ _globals->_sceneObjects_queue.push_front(this);
+
+ // Flag all the objects as modified
+ SynchronisedList<SceneObject *>::iterator i;
+ for (i = begin(); i != end(); ++i) {
+ (*i)->_flags |= OBJFLAG_PANES;
+ }
+
+ // Replicate all existing objects on the old object list
+ for (i = objectList->begin(); i != objectList->end(); ++i) {
+ SceneObject *sceneObj = (*i)->clone();
+ sceneObj->_flags |= OBJFLAG_HIDE | OBJFLAG_REMOVE | OBJFLAG_CLONED;
+ push_front(sceneObj);
+ }
+}
+
+void SceneObjectList::deactivate() {
+ if (_globals->_sceneObjects_queue.size() <= 1)
+ return;
+
+ SceneObjectList *objectList = *_globals->_sceneObjects_queue.begin();
+ _globals->_sceneObjects_queue.pop_front();
+ _globals->_sceneObjects = *_globals->_sceneObjects_queue.begin();
+
+ SynchronisedList<SceneObject *>::iterator i;
+ for (i = objectList->begin(); i != objectList->end(); ++i) {
+ if (!((*i)->_flags & OBJFLAG_CLONED)) {
+ SceneObject *sceneObj = (*i)->clone();
+ sceneObj->_flags |= OBJFLAG_HIDE | OBJFLAG_REMOVE | OBJFLAG_CLONED;
+ _globals->_sceneObjects->push_front(sceneObj);
+ }
+ }
+}
+
+void SceneObjectList::synchronise(Serialiser &s) {
+ SavedObject::synchronise(s);
+ _objList.synchronise(s);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SceneText::SceneText() : SceneObject() {
+ _fontNumber = 2;
+ _width = 160;
+ _textMode = ALIGN_LEFT;
+ _color2 = 0;
+ _color3 = 0;
+}
+
+SceneText::~SceneText() {
+}
+
+void SceneText::setup(const Common::String &msg) {
+ GfxManager gfxMan(_textSurface);
+ gfxMan.activate();
+ Rect textRect;
+
+ gfxMan._font.setFontNumber(_fontNumber);
+ gfxMan._font._colors.foreground = _color1;
+ gfxMan._font._colors2.background = _color2;
+ gfxMan._font._colors2.foreground = _color3;
+
+ gfxMan.getStringBounds(msg.c_str(), textRect, _width);
+
+ // Set up a new blank surface to hold the text
+ _textSurface.create(textRect.width(), textRect.height());
+ _textSurface._transColor = 0xff;
+ _textSurface.fillRect(textRect, _textSurface._transColor);
+
+ // Write the text to the surface
+ gfxMan._bounds = textRect;
+ gfxMan._font.writeLines(msg.c_str(), textRect, _textMode);
+
+ // Do post-init, which adds this SceneText object to the scene
+ postInit();
+ gfxMan.deactivate();
+}
+
+void SceneText::synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+
+ s.syncAsSint16LE(_fontNumber);
+ s.syncAsSint16LE(_width);
+ s.syncAsSint16LE(_color1);
+ s.syncAsSint16LE(_color2);
+ s.syncAsSint16LE(_color3);
+ SYNC_ENUM(_textMode, TextAlign);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Visage::Visage() {
+ _resNum = 0;
+ _rlbNum = 0;
+ _data = NULL;
+}
+
+Visage::Visage(const Visage &v) {
+ _resNum = v._resNum;
+ _rlbNum = v._rlbNum;
+ _data = v._data;
+ if (_data)
+ _vm->_memoryManager.incLocks(_data);
+}
+
+Visage &Visage::operator=(const Visage &s) {
+ _resNum = s._resNum;
+ _rlbNum = s._rlbNum;
+ _data = s._data;
+ if (_data)
+ _vm->_memoryManager.incLocks(_data);
+
+ return *this;
+}
+
+void Visage::setVisage(int resNum, int rlbNum) {
+ if ((_resNum != resNum) || (_rlbNum != rlbNum)) {
+ _resNum = resNum;
+ _rlbNum = rlbNum;
+ DEALLOCATE(_data);
+ _data = _resourceManager->getResource(RES_VISAGE, resNum, rlbNum);
+ assert(_data);
+ }
+}
+
+Visage::~Visage() {
+ DEALLOCATE(_data);
+}
+
+GfxSurface Visage::getFrame(int frameNum) {
+ int numFrames = READ_LE_UINT16(_data);
+ if (frameNum > numFrames)
+ frameNum = numFrames;
+ if (frameNum > 0)
+ --frameNum;
+
+ int offset = READ_LE_UINT32(_data + 2 + frameNum * 4);
+ byte *frameData = _data + offset;
+
+ return surfaceFromRes(frameData);
+}
+
+int Visage::getFrameCount() const {
+ return READ_LE_UINT16(_data);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Player::postInit(SceneObjectList *OwnerList) {
+ SceneObject::postInit();
+
+ _canWalk = true;
+ _uiEnabled = true;
+ _percent = 100;
+ _field8C = 10;
+ _moveDiff.x = 4;
+ _moveDiff.y = 2;
+}
+
+void Player::disableControl() {
+ _canWalk = false;
+ _uiEnabled = false;
+ _globals->_events.setCursor(CURSOR_NONE);
+}
+
+void Player::enableControl() {
+ _canWalk = true;
+ _uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_WALK);
+
+ switch (_globals->_events.getCursor()) {
+ case CURSOR_WALK:
+ case CURSOR_LOOK:
+ case CURSOR_USE:
+ case CURSOR_TALK:
+ _globals->_events.setCursor(_globals->_events.getCursor());
+ break;
+ default:
+ _globals->_events.setCursor(CURSOR_WALK);
+ break;
+ }
+}
+
+void Player::process(Event &event) {
+ if (!event.handled && (event.eventType == EVENT_BUTTON_DOWN) &&
+ (_globals->_events.getCursor() == CURSOR_WALK) && _globals->_player._canWalk &&
+ (_position != event.mousePos) && _globals->_sceneObjects->contains(this)) {
+
+ PlayerMover *newMover = new PlayerMover();
+ Common::Point destPos(event.mousePos.x + _globals->_sceneManager._scene->_sceneBounds.left,
+ event.mousePos.y + _globals->_sceneManager._scene->_sceneBounds.top);
+
+ addMover(newMover, &destPos, NULL);
+ event.handled = true;
+ }
+}
+
+void Player::synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+
+ s.syncAsByte(_canWalk);
+ s.syncAsByte(_uiEnabled);
+ s.syncAsSint16LE(_field8C);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Region::Region(int resNum, int rlbNum, ResourceType ctlType) {
+ _regionId = rlbNum;
+
+ byte *regionData = _resourceManager->getResource(ctlType, resNum, rlbNum);
+ assert(regionData);
+
+ load(regionData);
+
+ DEALLOCATE(regionData);
+}
+
+Region::Region(int regionId, const byte *regionData) {
+ _regionId = regionId;
+ load(regionData);
+}
+
+void Region::load(const byte *regionData) {
+ // Set the region bounds
+ _bounds.top = READ_LE_UINT16(regionData + 6);
+ _bounds.left = READ_LE_UINT16(regionData + 8);
+ _bounds.bottom = READ_LE_UINT16(regionData + 10);
+ _bounds.right = READ_LE_UINT16(regionData + 12);
+
+ // Special handling for small size regions
+ _regionSize = READ_LE_UINT16(regionData);
+ if (_regionSize == 14)
+ // No line slices
+ return;
+
+ // Set up the line slices
+ for (int y = 0; y < (_regionSize == 22 ? 1 : _bounds.height()); ++y) {
+ int slicesCount = READ_LE_UINT16(regionData + 16 + y * 4);
+ int slicesOffset = READ_LE_UINT16(regionData + 14 + y * 4);
+ assert(slicesCount < 100);
+ LineSliceSet sliceSet;
+ sliceSet.load(slicesCount, regionData + 14 + slicesOffset);
+
+ _ySlices.push_back(sliceSet);
+ }
+}
+
+/**
+ * Returns true if the given region contains the specified point
+ * @param pt Specified position
+ */
+bool Region::contains(const Common::Point &pt) {
+ // First check if the point falls inside the overall bounding rectangle
+ if (!_bounds.contains(pt) || _ySlices.empty())
+ return false;
+
+ // Get the correct Y line to use
+ const LineSliceSet &line = getLineSlices(pt.y);
+
+ // Loop through the horizontal slice list to see if the point falls in one
+ for (uint idx = 0; idx < line.items.size(); ++idx) {
+ if ((pt.x >= line.items[idx].xs) && (pt.x < line.items[idx].xe))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Returns true if the given region is empty
+ */
+bool Region::empty() const {
+ return !_bounds.isValidRect() && (_regionSize == 14);
+}
+
+void Region::clear() {
+ _bounds.set(0, 0, 0, 0);
+ _regionId = 0;
+ _regionSize = 0;
+}
+
+void Region::setRect(const Rect &r) {
+ setRect(r.left, r.top, r.right, r.bottom);
+}
+
+void Region::setRect(int xs, int ys, int xe, int ye) {
+ bool validRect = (ys < ye) && (xs < xe);
+ _ySlices.clear();
+
+ if (!validRect) {
+ _regionSize = 14;
+ _bounds.set(0, 0, 0, 0);
+ } else {
+ _regionSize = 22;
+ _bounds.set(xs, ys, xe, ye);
+
+ LineSliceSet sliceSet;
+ sliceSet.load2(1, xs, xe);
+
+ _ySlices.push_back(sliceSet);
+ }
+}
+
+const LineSliceSet &Region::getLineSlices(int yp) {
+ return _ySlices[(_regionSize == 22) ? 0 : yp - _bounds.top];
+}
+
+LineSliceSet Region::sectPoints(int yp, const LineSliceSet &sliceSet) {
+ if ((yp < _bounds.top) || (yp >= _bounds.bottom))
+ return LineSliceSet();
+
+ const LineSliceSet &ySet = getLineSlices(yp);
+ return mergeSlices(sliceSet, ySet);
+}
+
+LineSliceSet Region::mergeSlices(const LineSliceSet &set1, const LineSliceSet &set2) {
+ LineSliceSet result;
+
+ uint set1Index = 0, set2Index = 0;
+
+ while ((set1Index < set1.items.size()) && (set2Index < set2.items.size())) {
+ if (set1.items[set1Index].xe <= set2.items[set2Index].xs) {
+ ++set1Index;
+ } else if (set2.items[set2Index].xe <= set1.items[set1Index].xs) {
+ ++set2Index;
+ } else {
+ bool set1Flag = set1.items[set1Index].xs >= set2.items[set2Index].xs;
+ const LineSlice &slice = set1Flag ? set1.items[set1Index] : set2.items[set2Index];
+
+ result.add(slice.xs, MIN(set1.items[set1Index].xe, set2.items[set2Index].xe));
+ if (set1Flag)
+ ++set1Index;
+ else
+ ++set2Index;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Copies the background covered by the given region to the screen surface
+ */
+void Region::draw() {
+ Rect &sceneBounds = _globals->_sceneManager._scene->_sceneBounds;
+
+ for (int yp = sceneBounds.top; yp < sceneBounds.bottom; ++yp) {
+ // Generate a line slice set
+ LineSliceSet tempSet;
+ tempSet.add(sceneBounds.left, sceneBounds.right);
+ LineSliceSet newSet = sectPoints(yp, tempSet);
+
+ // Loop through the calculated slices
+ for (uint idx = 0; idx < newSet.items.size(); ++idx) {
+ Rect rect1(newSet.items[idx].xs, yp, newSet.items[idx].xe, yp + 1);
+ rect1.left &= ~3;
+ rect1.right = (rect1.right + 3) & ~3;
+
+ Rect rect2 = rect1;
+ rect1.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y);
+ rect2.translate(-sceneBounds.left, -sceneBounds.top);
+
+ _globals->gfxManager().getSurface().copyFrom(_globals->_sceneManager._scene->_backSurface,
+ rect1, rect2);
+ }
+ }
+}
+
+void Region::uniteLine(int yp, LineSliceSet &sliceSet) {
+ // TODO: More properly implement like the original
+
+ // First expand the bounds as necessary to fit in the row
+ if (_ySlices.empty()) {
+ _bounds = Rect(sliceSet.items[0].xs, yp, sliceSet.items[sliceSet.items.size() - 1].xe, yp + 1);
+ _ySlices.push_back(LineSliceSet());
+ }
+ while (yp < _bounds.top) {
+ _ySlices.insert_at(0, LineSliceSet());
+ --_bounds.top;
+ }
+ while (yp >= _bounds.bottom) {
+ _ySlices.push_back(LineSliceSet());
+ ++_bounds.bottom;
+ }
+
+ // Merge the existing line set into the line
+ LineSliceSet &destSet = _ySlices[yp - _bounds.top];
+ for (uint srcIndex = 0; srcIndex < sliceSet.items.size(); ++srcIndex) {
+ LineSlice &srcSlice = sliceSet.items[srcIndex];
+
+ // Check if overlaps existing slices
+ uint destIndex = 0;
+ while (destIndex < destSet.items.size()) {
+ LineSlice &destSlice = destSet.items[destIndex];
+ if (((srcSlice.xs >= destSlice.xs) && (srcSlice.xs <= destSlice.xe)) ||
+ ((srcSlice.xe >= destSlice.xs) && (srcSlice.xe <= destSlice.xe)) ||
+ ((srcSlice.xs < destSlice.xs) && (srcSlice.xe > destSlice.xe))) {
+ // Intersecting, so merge them
+ destSlice.xs = MIN(srcSlice.xs, destSlice.xs);
+ destSlice.xe = MAX(srcSlice.xe, destSlice.xe);
+ break;
+ }
+ ++destIndex;
+ }
+ if (destIndex == destSet.items.size()) {
+ // No intersecting region found, so add it to the list
+ destSet.items.push_back(srcSlice);
+ }
+ }
+
+ // Check whether to expand the left/bounds bounds
+ if (destSet.items[0].xs < _bounds.left)
+ _bounds.left = destSet.items[0].xs;
+ if (destSet.items[destSet.items.size() - 1].xe > _bounds.right)
+ _bounds.right = destSet.items[destSet.items.size() - 1].xe;
+}
+
+void Region::uniteRect(const Rect &rect) {
+ for (int yp = rect.top; yp < rect.bottom; ++yp) {
+ LineSliceSet sliceSet;
+ sliceSet.add(rect.left, rect.right);
+ uniteLine(yp, sliceSet);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SceneRegions::load(int sceneNum) {
+ clear();
+
+ byte *regionData = _resourceManager->getResource(RES_CONTROL, sceneNum, 9999, true);
+
+ if (regionData) {
+ int regionCount = READ_LE_UINT16(regionData);
+ for (int regionCtr = 0; regionCtr < regionCount; ++regionCtr) {
+ int rlbNum = READ_LE_UINT16(regionData + regionCtr * 6 + 2);
+
+ push_back(Region(sceneNum, rlbNum));
+ }
+
+ DEALLOCATE(regionData);
+ }
+}
+
+int SceneRegions::indexOf(const Common::Point &pt) {
+ for (SceneRegions::iterator i = begin(); i != end(); ++i) {
+ if ((*i).contains(pt))
+ return (*i)._regionId;
+ }
+
+ return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SoundHandler::SoundHandler() {
+ _action = NULL;
+ _field280 = -1;
+ if (_globals)
+ _globals->_sceneListeners.push_back(this);
+}
+
+SoundHandler::~SoundHandler() {
+ if (_globals)
+ _globals->_sceneListeners.remove(this);
+}
+
+void SoundHandler::dispatch() {
+ EventHandler::dispatch();
+ int v = _sound.proc12();
+
+ if (v != -1) {
+ _field280 = v;
+ _sound.proc2(-1);
+
+ if (_action)
+ _action->signal();
+ }
+
+ if (_field280 != -1) {
+ // FIXME: Hardcoded to only flag a sound ended if an action has been set
+ if (_action) {
+// if (!_sound.proc3()) {
+ _field280 = -1;
+ if (_action) {
+ _action->signal();
+ _action = NULL;
+ }
+ }
+ }
+}
+
+void SoundHandler::startSound(int soundNum, Action *action, int volume) {
+ _action = action;
+ _field280 = 0;
+ setVolume(volume);
+ _sound.startSound(soundNum);
+
+ warning("TODO: SoundHandler::startSound");
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+void SceneItemList::addItems(SceneItem *first, ...) {
+ va_list va;
+ va_start(va, first);
+
+ SceneItem *p = first;
+ while (p) {
+ push_back(p);
+ p = va_arg(va, SceneItem *);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+RegionSupportRec WalkRegion::_processList[PROCESS_LIST_SIZE];
+
+void RegionSupportRec::process() {
+ if (_xDiff < _yDiff) {
+ _halfDiff += _xDiff;
+ if (_halfDiff > _yDiff) {
+ _halfDiff -= _yDiff;
+ _xp += _xDirection;
+ }
+ } else {
+ do {
+ _xp += _xDirection;
+ _halfDiff += _yDiff;
+ } while (_halfDiff <= _xDiff);
+ _halfDiff -= _xDiff;
+ }
+ --_yDiff2;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void WalkRegion::loadRegion(byte *dataP, int size) {
+ // First clear the region
+ clear();
+
+ // Decode the data for the region
+ int dataCount, regionHeight;
+ loadProcessList(dataP, size, dataCount, regionHeight);
+
+ int processIndex = 0, idx2 = 0, count;
+ for (int yp = _processList[0]._yp; yp < regionHeight; ++yp) {
+ process3(yp, dataCount, processIndex, idx2);
+ process4(yp, processIndex, idx2, count);
+
+ loadRecords(yp, count, processIndex);
+ }
+}
+
+void WalkRegion::loadProcessList(byte *dataP, int dataSize, int &dataIndex, int &regionHeight) {
+ dataIndex = 0;
+ int x1 = READ_LE_UINT16(dataP + (dataSize - 1) * 4);
+ int y1 = READ_LE_UINT16(dataP + (dataSize - 1) * 4 + 2);
+ regionHeight = y1;
+
+ for (int idx = 0; idx < dataSize; ++idx) {
+ int xp = READ_LE_UINT16(dataP + idx * 4);
+ int yp = READ_LE_UINT16(dataP + idx * 4 + 2);
+ if (yp != y1) {
+ /*
+ * Commented out: doesn't seem to be used
+ int v;
+ if (idx == (dataSize - 1))
+ v = READ_LE_UINT16(dataP + 2);
+ else
+ v = process1(idx, dataP, dataSize);
+ warning("TODO: v not used? - %d", v);
+ */
+ process2(dataIndex, x1, y1, xp, yp);
+ ++dataIndex;
+ }
+
+ // Keep regionHeight as the maximum of any y
+ if (yp > regionHeight)
+ regionHeight = yp;
+
+ x1 = xp;
+ y1 = yp;
+ }
+}
+
+int WalkRegion::process1(int idx, byte *dataP, int dataSize) {
+ int idx2 = idx + 1;
+ if (idx2 == dataSize)
+ idx2 = 0;
+
+ while (READ_LE_UINT16(dataP + idx2 * 4 + 2) == READ_LE_UINT16(dataP + idx * 4 + 2)) {
+ if (idx2 == (dataSize - 1))
+ idx2 = 0;
+ else
+ ++idx2;
+ }
+
+ return READ_LE_UINT16(dataP + idx2 * 4 + 2);
+}
+
+void WalkRegion::process2(int dataIndex, int x1, int y1, int x2, int y2) {
+ int xDiff = ABS(x2 - x1);
+ int yDiff = ABS(y2 - y1);
+ int halfDiff = MAX(xDiff, yDiff) / 2;
+ int yMax = MIN(y1, y2);
+
+ while (dataIndex && (_processList[dataIndex - 1]._yp > yMax)) {
+ _processList[dataIndex] = _processList[dataIndex - 1];
+ --dataIndex;
+ }
+ _processList[dataIndex]._yp = yMax;
+
+ _processList[dataIndex]._xp = (y1 >= y2) ? x2 : x1;
+ _processList[dataIndex]._xDiff = xDiff;
+ _processList[dataIndex]._yDiff = yDiff;
+ _processList[dataIndex]._halfDiff = halfDiff;
+
+ int xTemp = (y1 >= y2) ? x1 - x2 : x2 - x1;
+ _processList[dataIndex]._xDirection = (xTemp == 0) ? 0 : ((xTemp < 0) ? -1 : 1);
+ _processList[dataIndex]._yDiff2 = yDiff;
+}
+
+void WalkRegion::process3(int yp, int dataCount, int &idx1, int &idx2) {
+ while ((idx2 < (dataCount - 1)) && (_processList[idx2 + 1]._yp <= yp))
+ ++idx2;
+ while (!_processList[idx1]._yDiff2)
+ ++idx1;
+}
+
+void WalkRegion::process4(int yp, int idx1, int idx2, int &count) {
+ count = 0;
+ for (int idx = idx1; idx <= idx2; ++idx) {
+ if (_processList[idx]._yDiff2 > 0)
+ ++count;
+ process5(idx, idx1);
+ }
+}
+
+void WalkRegion::process5(int idx1, int idx2) {
+ while ((idx1 > idx2) && (_processList[idx1 - 1]._xp > _processList[idx1]._xp)) {
+ SWAP(_processList[idx1], _processList[idx1 - 1]);
+ --idx1;
+ }
+}
+
+void WalkRegion::loadRecords(int yp, int size, int processIndex) {
+ LineSliceSet sliceSet;
+ int sliceCount = size / 2;
+
+ for (int idx = 0; idx < sliceCount; ++idx, ++processIndex) {
+ while (!_processList[processIndex]._yDiff2)
+ ++processIndex;
+
+ int sliceXs = _processList[processIndex]._xp;
+ _processList[processIndex].process();
+
+ do {
+ ++processIndex;
+ } while (!_processList[processIndex]._yDiff2);
+
+ int sliceXe = _processList[processIndex]._xp;
+ _processList[processIndex].process();
+
+ sliceSet.items.push_back(LineSlice(sliceXs, sliceXe));
+ }
+
+ uniteLine(yp, sliceSet);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void WRField18::load(byte *data) {
+ _pt1.x = READ_LE_UINT16(data);
+ _pt1.y = READ_LE_UINT16(data + 2);
+ _pt2.x = READ_LE_UINT16(data + 4);
+ _pt2.y = READ_LE_UINT16(data + 6);
+ _v = READ_LE_UINT16(data + 8);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void WalkRegions::clear() {
+ _regionList.clear();
+ _field18.clear();
+ _idxList.clear();
+ _idxList2.clear();
+}
+
+void WalkRegions::load(int sceneNum) {
+ clear();
+ _resNum = sceneNum;
+
+ if (_vm->getFeatures() & GF_ALT_REGIONS) {
+ loadRevised();
+ } else {
+ loadOriginal();
+ }
+}
+
+/**
+ * This version handles loading walk regions for Ringworld floppy version and Demo #1
+ */
+void WalkRegions::loadOriginal() {
+ byte *regionData = _resourceManager->getResource(RES_WALKRGNS, _resNum, 1, true);
+ if (!regionData) {
+ // No data, so return
+ _resNum = -1;
+ return;
+ }
+
+ byte *dataP;
+ int dataSize;
+
+ // Load the field 18 list
+ dataP = _resourceManager->getResource(RES_WALKRGNS, _resNum, 2);
+ dataSize = _vm->_memoryManager.getSize(dataP);
+ assert(dataSize % 10 == 0);
+
+ byte *p = dataP;
+ for (int idx = 0; idx < (dataSize / 10); ++idx, p += 10) {
+ WRField18 rec;
+ rec.load(p);
+ _field18.push_back(rec);
+ }
+
+ DEALLOCATE(dataP);
+
+ // Load the idx list
+ dataP = _resourceManager->getResource(RES_WALKRGNS, _resNum, 3);
+ dataSize = _vm->_memoryManager.getSize(dataP);
+ assert(dataSize % 2 == 0);
+
+ p = dataP;
+ for (int idx = 0; idx < (dataSize / 2); ++idx, p += 2)
+ _idxList.push_back(READ_LE_UINT16(p));
+
+ DEALLOCATE(dataP);
+
+ // Load the secondary idx list
+ dataP = _resourceManager->getResource(RES_WALKRGNS, _resNum, 4);
+ dataSize = _vm->_memoryManager.getSize(dataP);
+ assert(dataSize % 2 == 0);
+
+ p = dataP;
+ for (int idx = 0; idx < (dataSize / 2); ++idx, p += 2)
+ _idxList2.push_back(READ_LE_UINT16(p));
+
+ DEALLOCATE(dataP);
+
+ // Handle the loading of the actual regions themselves
+ dataP = _resourceManager->getResource(RES_WALKRGNS, _resNum, 5);
+
+ byte *pWalkRegion = regionData + 16;
+ byte *srcP = dataP;
+ for (; (int16)READ_LE_UINT16(pWalkRegion) != -20000; pWalkRegion += 16) {
+ WalkRegion wr;
+
+ // Set the Walk region specific fields
+ wr._pt.x = (int16)READ_LE_UINT16(pWalkRegion);
+ wr._pt.y = (int16)READ_LE_UINT16(pWalkRegion + 2);
+ wr._idxListIndex = READ_LE_UINT32(pWalkRegion + 4);
+ wr._idxList2Index = READ_LE_UINT32(pWalkRegion + 8);
+
+ // Read in the region data
+ int size = READ_LE_UINT16(srcP);
+ srcP += 2;
+ wr.loadRegion(srcP, size);
+
+ srcP += size * 4;
+ _regionList.push_back(wr);
+ }
+
+ DEALLOCATE(dataP);
+ DEALLOCATE(regionData);
+}
+
+/**
+ * This version handles loading walk regions for Ringworld CD version and Demo #2. Given it's the newer
+ * version, it may also be used by future game titles
+ */
+void WalkRegions::loadRevised() {
+ byte *regionData = _resourceManager->getResource(RES_WALKRGNS, _resNum, 2, true);
+ if (!regionData) {
+ // No data, so return
+ _resNum = -1;
+ return;
+ }
+
+ byte *data1P = regionData + READ_LE_UINT32(regionData);
+ byte *data2P = regionData + READ_LE_UINT32(regionData + 4);
+ byte *data3P = regionData + READ_LE_UINT32(regionData + 8);
+ byte *data4P = regionData + READ_LE_UINT32(regionData + 12);
+ byte *regionOffset = regionData + 16;
+ int dataSize;
+
+ // Load the field 18 list
+ dataSize = READ_LE_UINT32(regionData + 8) - READ_LE_UINT32(regionData + 4);
+ assert(dataSize % 10 == 0);
+
+ byte *p = data2P;
+ for (int idx = 0; idx < (dataSize / 10); ++idx, p += 10) {
+ WRField18 rec;
+ rec.load(p);
+ _field18.push_back(rec);
+ }
+
+ // Load the idx list
+ dataSize = READ_LE_UINT32(regionData + 12) - READ_LE_UINT32(regionData + 8);
+ assert(dataSize % 2 == 0);
+
+ p = data3P;
+ for (int idx = 0; idx < (dataSize / 2); ++idx, p += 2)
+ _idxList.push_back(READ_LE_UINT16(p));
+
+ // Load the secondary idx list
+ dataSize = READ_LE_UINT32(regionData + 16) - READ_LE_UINT32(regionData + 12);
+ assert(dataSize % 2 == 0);
+
+ p = data4P;
+ for (int idx = 0; idx < (dataSize / 2); ++idx, p += 2)
+ _idxList2.push_back(READ_LE_UINT16(p));
+
+ // Handle the loading of the actual regions themselves
+ byte *pWalkRegion = data1P + 16;
+ for (; (int16)READ_LE_UINT16(pWalkRegion) != -20000; pWalkRegion += 16, regionOffset += 4) {
+ WalkRegion wr;
+ byte *srcP = regionData + READ_LE_UINT32(regionOffset);
+
+ // Set the Walk region specific fields
+ wr._pt.x = (int16)READ_LE_UINT16(pWalkRegion);
+ wr._pt.y = (int16)READ_LE_UINT16(pWalkRegion + 2);
+ wr._idxListIndex = READ_LE_UINT32(pWalkRegion + 4);
+ wr._idxList2Index = READ_LE_UINT32(pWalkRegion + 8);
+
+ // Read in the region data
+ wr._regionId = 0;
+ wr.load(srcP);
+
+ _regionList.push_back(wr);
+ }
+
+ DEALLOCATE(regionData);
+}
+
+/**
+ * Returns the index of the walk region that contains the given point
+ * @param pt Point to locate
+ * @param indexList List of region indexes that should be ignored
+ */
+int WalkRegions::indexOf(const Common::Point &pt, const Common::List<int> *indexList) {
+ for (uint idx = 0; idx < _regionList.size(); ++idx) {
+ if ((!indexList || !contains(*indexList, int(idx + 1))) && _regionList[idx].contains(pt))
+ return idx + 1;
+ }
+
+ return -1;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void ScenePriorities::load(int resNum) {
+ _resNum = resNum;
+ clear();
+
+ bool altMode = (_vm->getFeatures() & GF_ALT_REGIONS) != 0;
+ byte *regionData = _resourceManager->getResource(RES_PRIORITY, resNum, altMode ? 1 : 9999, true);
+ if (!regionData)
+ return;
+
+ int regionCount = READ_LE_UINT16(regionData);
+ for (int regionCtr = 0; regionCtr < regionCount; ++regionCtr) {
+ if (altMode) {
+ // Region data is embedded within the resource
+ uint16 regionId = READ_LE_UINT16(regionData + regionCtr * 6 + 2);
+ uint32 dataOffset = READ_LE_UINT32(regionData + regionCtr * 6 + 4);
+ push_back(Region(regionId, regionData + dataOffset));
+ } else {
+ // The data contains the index of another resource containing the region data
+ int rlbNum = READ_LE_UINT16(regionData + regionCtr * 6 + 2);
+
+ push_back(Region(resNum, rlbNum, RES_PRIORITY));
+ }
+ }
+
+ DEALLOCATE(regionData);
+}
+
+Region *ScenePriorities::find(int priority) {
+ // If no priority regions are loaded, then return the placeholder region
+ if (empty())
+ return &_defaultPriorityRegion;
+
+ if (priority > 255)
+ priority = 255;
+
+ // Loop through the regions to find the closest for the given priority level
+ int minRegionId = 9998;
+ Region *region = NULL;
+ for (ScenePriorities::iterator i = begin(); i != end(); ++i) {
+ Region *r = &(*i);
+ int regionId = r->_regionId;
+
+ if ((regionId > priority) && (regionId < minRegionId)) {
+ minRegionId = regionId;
+ region = r;
+ }
+ }
+
+ assert(region);
+ return region;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void FloatSet::add(double v1, double v2, double v3) {
+ _float1 += v1;
+ _float2 += v2;
+ _float3 += v3;
+}
+
+void FloatSet::proc1(double v) {
+ double diff = (cos(v) * _float1) - (sin(v) * _float2);
+ _float2 = (sin(v) * _float1) + (cos(v) * _float2);
+ _float1 = diff;
+}
+
+double FloatSet::sqrt(FloatSet &floatSet) {
+ double f1Diff = _float1 - floatSet._float1;
+ double f2Diff = _float2 - floatSet._float2;
+ double f3Diff = _float3 - floatSet._float3;
+
+ return ::sqrt(f1Diff * f1Diff + f2Diff * f2Diff + f3Diff * f3Diff);
+}
+
+/*--------------------------------------------------------------------------*/
+
+GameHandler::GameHandler() : EventHandler() {
+ _nextWaitCtr = 1;
+ _waitCtr.setCtr(1);
+ _field14 = 10;
+}
+
+GameHandler::~GameHandler() {
+ if (_globals)
+ _globals->_game->removeHandler(this);
+}
+
+void GameHandler::execute() {
+ if (_waitCtr.decCtr() == 0) {
+ _waitCtr.setCtr(_nextWaitCtr);
+ dispatch();
+ }
+}
+
+void GameHandler::synchronise(Serialiser &s) {
+ EventHandler::synchronise(s);
+
+ _lockCtr.synchronise(s);
+ _waitCtr.synchronise(s);
+ s.syncAsSint16LE(_nextWaitCtr);
+ s.syncAsSint16LE(_field14);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SceneHandler::SceneHandler() {
+ _saveGameSlot = -1;
+ _loadGameSlot = -1;
+}
+
+void SceneHandler::registerHandler() {
+ postInit();
+ _globals->_game->addHandler(this);
+}
+
+void SceneHandler::postInit(SceneObjectList *OwnerList) {
+ _delayTicks = 2;
+
+ _globals->_scenePalette.loadPalette(0);
+ _globals->_scenePalette.refresh();
+
+ // TODO: Bunch of other scene related setup goes here
+ _globals->_soundManager.postInit();
+
+ _globals->_game->start();
+}
+
+void SceneHandler::process(Event &event) {
+ // Main keypress handler
+ if ((event.eventType == EVENT_KEYPRESS) && !event.handled) {
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_F1:
+ // F1 - Help
+ MessageDialog::show((_vm->getFeatures() & GF_DEMO) ? DEMO_HELP_MSG : HELP_MSG, OK_BTN_STRING);
+ break;
+
+ case Common::KEYCODE_F2: {
+ // F2 - Sound Options
+ ConfigDialog *dlg = new ConfigDialog();
+ dlg->runModal();
+ delete dlg;
+ _globals->_events.setCursorFromFlag();
+ break;
+ }
+
+ case Common::KEYCODE_F3:
+ // F3 - Quit
+ _globals->_game->quitGame();
+ event.handled = false;
+ break;
+
+ case Common::KEYCODE_F4:
+ // F4 - Restart
+ _globals->_game->restartGame();
+ _globals->_events.setCursorFromFlag();
+ break;
+
+ case Common::KEYCODE_F7:
+ // F7 - Restore
+ _globals->_game->restoreGame();
+ _globals->_events.setCursorFromFlag();
+ break;
+
+ case Common::KEYCODE_F10:
+ // F10 - Pause
+ GfxDialog::setPalette();
+ MessageDialog::show(GAME_PAUSED_MSG, OK_BTN_STRING);
+ _globals->_events.setCursorFromFlag();
+ break;
+
+ default:
+ break;
+ }
+
+ _globals->_events.setCursorFromFlag();
+ }
+
+ // Check for displaying right-click dialog
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (event.btnState == BTNSHIFT_RIGHT) &&
+ _globals->_player._uiEnabled) {
+ RightClickDialog *dlg = new RightClickDialog();
+ dlg->execute();
+ delete dlg;
+
+ event.handled = true;
+ return;
+ }
+
+ // If there is an active scene, pass the event to it
+ if (_globals->_sceneManager._scene)
+ _globals->_sceneManager._scene->process(event);
+
+ if (!event.handled) {
+ // Separate check for F5 - Save key
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_F5)) {
+ // F5 - Save
+ _globals->_game->saveGame();
+ event.handled = true;
+ _globals->_events.setCursorFromFlag();
+ }
+
+ // Check for debugger
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_d) &&
+ (event.kbd.flags & Common::KBD_CTRL)) {
+ // Attach to the debugger
+ _vm->_debugger->attach();
+ _vm->_debugger->onFrame();
+ }
+
+ // Mouse press handling
+ if (_globals->_player._uiEnabled && (event.eventType == EVENT_BUTTON_DOWN) &&
+ !_globals->_sceneItems.empty()) {
+ // Scan the item list to find one the mouse is within
+ SynchronisedList<SceneItem *>::iterator i = _globals->_sceneItems.begin();
+ while ((i != _globals->_sceneItems.end()) && !(*i)->contains(event.mousePos))
+ ++i;
+
+ if (i != _globals->_sceneItems.end()) {
+ // Pass the action to the item
+ (*i)->doAction(_globals->_events.getCursor());
+ event.handled = _globals->_events.getCursor() != CURSOR_WALK;
+
+ if (_globals->_player._uiEnabled && _globals->_player._canWalk &&
+ (_globals->_events.getCursor() != CURSOR_LOOK)) {
+ _globals->_events.setCursor(CURSOR_WALK);
+ } else if (_globals->_player._canWalk && (_globals->_events.getCursor() != CURSOR_LOOK)) {
+ _globals->_events.setCursor(CURSOR_WALK);
+ } else if (_globals->_player._uiEnabled && (_globals->_events.getCursor() != CURSOR_LOOK)) {
+ _globals->_events.setCursor(CURSOR_USE);
+ }
+ }
+
+ // Handle player processing
+ _globals->_player.process(event);
+ }
+ }
+}
+
+void SceneHandler::dispatch() {
+ // Handle game saving and loading
+ if (_saveGameSlot != -1) {
+ int saveSlot = _saveGameSlot;
+ _saveGameSlot = -1;
+ Common::Error err = _saver->save(saveSlot, _saveName);
+ // FIXME: Make use of the description string in err to enhance
+ // the error reported to the user.
+ if (err.getCode() != Common::kNoError)
+ GUIErrorMessage(SAVE_ERROR_MSG);
+ }
+ if (_loadGameSlot != -1) {
+ int loadSlot = _loadGameSlot;
+ _loadGameSlot = -1;
+ _saver->restore(loadSlot);
+ _globals->_events.setCursorFromFlag();
+ }
+
+ _globals->_soundManager.dispatch();
+ _globals->_scenePalette.signalListeners();
+
+ // Dispatch to any objects registered in the scene
+ _globals->_sceneObjects->recurse(SceneHandler::dispatchObject);
+
+ // If a scene is active, then dispatch to it
+ if (_globals->_sceneManager._scene)
+ _globals->_sceneManager._scene->dispatch();
+
+ //TODO: Figure out purpose of the given list
+ //_globals->_regions.forEach(SceneHandler::handleListener);
+
+ Event event;
+ while (_globals->_events.getEvent(event))
+ process(event);
+
+ // Handle drawing the contents of the scene
+ if (_globals->_sceneManager._scene)
+ _globals->_sceneObjects->draw();
+
+ // Check to see if any scene change is required
+ _globals->_sceneManager.checkScene();
+
+ // Signal the ScummVM debugger
+ _vm->_debugger->onFrame();
+
+ // Delay between frames
+ _globals->_events.delay(_delayTicks);
+}
+
+void SceneHandler::dispatchObject(EventHandler *obj) {
+ obj->dispatch();
+}
+
+void SceneHandler::saveListener(Serialiser &ser) {
+ warning("TODO: SceneHandler::saveListener");
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Game::execute() {
+ // Main game loop
+ bool activeFlag = false;
+ do {
+ // Process all currently atcive game handlers
+ activeFlag = false;
+ for (SynchronisedList<GameHandler *>::iterator i = _handlers.begin(); i != _handlers.end(); ++i) {
+ GameHandler *gh = *i;
+ if (gh->_lockCtr.getCtr() == 0) {
+ gh->execute();
+ activeFlag = true;
+ }
+ }
+ } while (activeFlag && !_vm->getEventManager()->shouldQuit());
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/core.h b/engines/tsage/core.h
new file mode 100644
index 0000000000..45a39b24bb
--- /dev/null
+++ b/engines/tsage/core.h
@@ -0,0 +1,940 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_CORE_H
+#define TSAGE_CORE_H
+
+#include "common/scummsys.h"
+#include "common/endian.h"
+#include "common/error.h"
+#include "common/list.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+#include "tsage/events.h"
+#include "tsage/graphics.h"
+#include "tsage/resources.h"
+#include "tsage/saveload.h"
+#include "tsage/sound.h"
+
+namespace tSage {
+
+#define MAX_FLAGS 256
+
+class EventHandler;
+class SceneObject;
+class SceneObjectList;
+class ObjectMover;
+class Action;
+class Serialiser;
+
+class InvObject : public SavedObject {
+public:
+ int _sceneNumber;
+ int _displayResNum;
+ int _rlbNum;
+ int _cursorNum;
+ Rect _bounds;
+ CursorType _cursorId;
+ Common::String _description;
+ int _iconResNum;
+public:
+ InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType cursorId, const Common::String description);
+
+ bool inInventory() const { return _sceneNumber == 1; }
+ void setCursor();
+
+ virtual Common::String getClassName() { return "InvObject"; }
+ virtual void synchronise(Serialiser &s) {
+ s.syncAsUint16LE(_sceneNumber);
+ }
+};
+
+class InvObjectList : public SavedObject {
+public:
+ SynchronisedList<InvObject *> _itemList;
+ InvObject *_selectedItem;
+
+ InvObjectList();
+
+ virtual Common::String getClassName() { return "InvObjectList"; }
+ virtual void synchronise(Serialiser &s);
+};
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * Basic reference counter class
+ */
+class RefCounter : public Serialisable {
+private:
+ int _ctr;
+public:
+ RefCounter() { clear(); }
+ virtual ~RefCounter() {}
+
+ RefCounter(int v) { _ctr = v; }
+
+ void clear() { _ctr = 0; }
+ void setCtr(int v) { _ctr = v; }
+ int decCtr() {
+ if (_ctr > 0) --_ctr;
+ return _ctr;
+ }
+ int incCtr() { return ++_ctr; }
+ int getCtr() const { return _ctr; }
+
+ virtual void synchronise(Serialiser &s) { s.syncAsSint16LE(_ctr); }
+};
+
+class EventHandler : public SavedObject {
+public:
+ Action *_action;
+
+ EventHandler() : SavedObject() { _action = NULL; }
+ virtual ~EventHandler() { destroy(); }
+
+ virtual void synchronise(Serialiser &s) { SYNC_POINTER(_action); }
+ virtual Common::String getClassName() { return "EventHandler"; }
+ virtual void postInit(SceneObjectList *OwnerList = NULL) {}
+ virtual void remove() {}
+ virtual void signal() {}
+ virtual void process(Event &event) {}
+ virtual void dispatch();
+ virtual void setAction(Action *action) { setAction(action, NULL); }
+ virtual void setAction(Action *action, EventHandler *endHandler, ...);
+ virtual void destroy() {};
+};
+
+class Action : public EventHandler {
+public:
+ EventHandler *_owner;
+ int _actionIndex;
+ int _delayFrames;
+ uint32 _startFrame;
+ bool _attached;
+ EventHandler *_endHandler;
+
+ Action();
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "Action"; }
+ virtual void remove();
+ virtual void process(Event &event);
+ virtual void dispatch();
+ virtual void attached(EventHandler *newOwner, EventHandler *endHandler, va_list va);
+
+ void attach(EventHandler *newOwner, EventHandler *endHandler, ...) {
+ va_list va;
+ va_start(va, endHandler);
+ attached(newOwner, endHandler, va);
+ va_end(va);
+ }
+ int getActionIndex() const { return _actionIndex; }
+ void setActionIndex(int index) { _actionIndex = index; }
+ void setDelay(int numFrames);
+};
+
+class ActionExt : public Action {
+public:
+ int _state;
+};
+
+class ObjectMover : public EventHandler {
+public:
+ Common::Point _destPosition;
+ Common::Point _moveDelta;
+ Common::Point _moveSign;
+ int _minorDiff;
+ int _majorDiff;
+ int _changeCtr;
+ Action *_action;
+ SceneObject *_sceneObject;
+public:
+ ObjectMover() { _action = NULL; _sceneObject = NULL; }
+ virtual ~ObjectMover();
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "ObjectMover"; }
+ virtual void remove();
+ virtual void dispatch();
+ virtual void startMove(SceneObject *sceneObj, va_list va) {}
+ virtual void setup(const Common::Point &destPos);
+ virtual bool dontMove() const;
+ virtual void endMove();
+};
+
+class ObjectMover2 : public ObjectMover {
+public:
+ SceneObject *_destObject;
+ int _minArea;
+ int _maxArea;
+public:
+ ObjectMover2();
+ virtual ~ObjectMover2() {}
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "ObjectMover2"; }
+ virtual void dispatch();
+ virtual void startMove(SceneObject *sceneObj, va_list va);
+ virtual void endMove();
+};
+
+class ObjectMover3 : public ObjectMover2 {
+public:
+ virtual Common::String getClassName() { return "ObjectMover3"; }
+ virtual void dispatch();
+ virtual void startMove(SceneObject *sceneObj, va_list va);
+ virtual void endMove();
+};
+
+class NpcMover : public ObjectMover {
+public:
+ virtual Common::String getClassName() { return "NpcMover"; }
+ virtual void startMove(SceneObject *sceneObj, va_list va);
+};
+
+#define MAX_ROUTE_SIZE 20
+#define ROUTE_END_VAL -20000
+
+class RouteEnds {
+public:
+ Common::Point moveSrc;
+ Common::Point moveDest;
+};
+
+class PlayerMover : public NpcMover {
+protected:
+ void setDest(const Common::Point &destPos);
+ void pathfind(Common::Point *routeList, Common::Point srcPos, Common::Point destPos, RouteEnds routeEnds);
+ int regionIndexOf(const Common::Point &pt);
+ int regionIndexOf(int xp, int yp) { return regionIndexOf(Common::Point(xp, yp)); }
+ int findClosestRegion(Common::Point &pt, const Common::List<int> &indexList);
+ int checkMover(Common::Point &srcPos, const Common::Point &destPos);
+ void checkMovement2(const Common::Point &pt1, const Common::Point &pt2, int numSteps, Common::Point &ptOut);
+ int proc1(int *routeList, int srcRegion, int destRegion, int &v);
+
+ static Common::Point *findLinePoint(RouteEnds *routeEnds, Common::Point *objPos, int length, Common::Point *outPos);
+ static int findDistance(const Common::Point &pt1, const Common::Point &pt2);
+ static bool sub_F8E5(const Common::Point &pt1, const Common::Point &pt2, const Common::Point &pt3,
+ const Common::Point &pt4, Common::Point *ptOut = NULL);
+public:
+ Common::Point _finalDest;
+ Common::Point _routeList[MAX_ROUTE_SIZE];
+ int _routeIndex;
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "PlayerMover"; }
+ virtual void startMove(SceneObject *sceneObj, va_list va);
+ virtual void endMove();
+};
+
+class PlayerMover2 : public PlayerMover {
+public:
+ SceneObject *_destObject;
+ int _maxArea;
+ int _minArea;
+ PlayerMover2() : PlayerMover() { _destObject = NULL; }
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "PlayerMover2"; }
+ virtual void dispatch();
+ virtual void startMove(SceneObject *sceneObj, va_list va);
+ virtual void endMove();
+};
+
+/*--------------------------------------------------------------------------*/
+
+class ScenePalette;
+
+class PaletteModifier : public SavedObject {
+public:
+ ScenePalette *_scenePalette;
+ Action *_action;
+public:
+ PaletteModifier();
+
+ virtual void synchronise(Serialiser &s) {
+ SYNC_POINTER(_scenePalette);
+ SYNC_POINTER(_action);
+ }
+ virtual void signal() = 0;
+ virtual void remove() = 0;
+};
+
+class PaletteModifierCached: public PaletteModifier {
+public:
+ byte _palette[256 * 3];
+ int _step;
+ int _percent;
+
+ PaletteModifierCached();
+
+ void setPalette(ScenePalette *palette, int step);
+ virtual Common::String getClassName() { return "PaletteModifierCached"; }
+ virtual void synchronise(Serialiser &s);
+};
+
+class PaletteRotation: public PaletteModifierCached {
+public:
+ int _delayCtr;
+ uint32 _frameNumber;
+ int _currIndex;
+ int _start;
+ int _end;
+ int _rotationMode;
+ int _duration;
+public:
+ PaletteRotation();
+
+ virtual Common::String getClassName() { return "PaletteRotation"; }
+ virtual void synchronise(Serialiser &s);
+ virtual void signal();
+ virtual void remove();
+
+ void setStep(int step) { _step = step; }
+ void set(ScenePalette *palette, int start, int end, int rotationMode, int duration, Action *action);
+ bool decDuration();
+ void setDelay(int amount);
+};
+
+class PaletteFader: public PaletteModifierCached {
+public:
+ byte _palette[256 * 3];
+public:
+ virtual Common::String getClassName() { return "PaletteFader"; }
+ virtual void synchronise(Serialiser &s);
+ virtual void signal();
+ virtual void remove();
+};
+
+/*--------------------------------------------------------------------------*/
+
+enum FadeMode {FADEMODE_NONE = 0, FADEMODE_GRADUAL = 1, FADEMODE_IMMEDIATE = 2};
+
+class ScenePalette : public SavedObject {
+public:
+ byte _palette[256 * 3];
+ GfxColors _colors;
+ SynchronisedList<PaletteModifier *> _listeners;
+ int _field412;
+
+ uint8 _redColor;
+ uint8 _greenColor;
+ uint8 _blueColor;
+ uint8 _aquaColor;
+ uint8 _purpleColor;
+ uint8 _limeColor;
+public:
+ ScenePalette();
+ ScenePalette(int paletteNum);
+
+ bool loadPalette(int paletteNum);
+ void refresh();
+ void setPalette(int index, int count);
+ uint8 indexOf(uint r, uint g, uint b, int threshold = 0xffff);
+ void getPalette(int start = 0, int count = 256);
+ void signalListeners();
+ void clearListeners();
+ void fade(const byte *adjustData, bool fullAdjust, int percent);
+ PaletteRotation *addRotation(int start, int end, int rotationMode, int duration = 0, Action *action = NULL);
+ PaletteFader *addFader(const byte *arrBufferRGB, int palSize, int percent, Action *action);
+
+ static void changeBackground(const Rect &bounds, FadeMode fadeMode);
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "ScenePalette"; }
+};
+
+// DisplayParamType constant set. This must not be an enum
+const int SET_WIDTH = 0;
+const int SET_X = 1;
+const int SET_Y = 2;
+const int SET_FONT = 3;
+const int SET_BG_COLOR = 4;
+const int SET_FG_COLOR = 5;
+const int SET_KEEP_ONSCREEN = 6;
+const int SET_EXT_BGCOLOR = 7;
+const int SET_EXT_FGCOLOR = 8;
+const int SET_POS_MODE = 9;
+const int SET_TEXT_MODE = 10;
+const int LIST_END = -999;
+
+class SceneItem : public EventHandler {
+public:
+ Rect _bounds;
+ Common::String _msg;
+ int _fieldE, _field10;
+ Common::Point _position;
+ int _yDiff;
+ int _sceneRegionId;
+public:
+ SceneItem() : EventHandler() { _msg = "Feature"; _action = NULL; _sceneRegionId = 0; }
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "SceneItem"; }
+ virtual void remove();
+ virtual void destroy() {}
+ virtual void startMover(CursorType action) { doAction(action); }
+ virtual void doAction(int action);
+
+ bool contains(const Common::Point &pt);
+ void setBounds(const Rect &newBounds) { _bounds = newBounds; }
+ void setBounds(const int ys, const int xe, const int ye, const int xs) { _bounds = Rect(MIN(xs, xe), MIN(ys, ye), MAX(xs, xe), MAX(ys, ye)); }
+ static void display(int resNum, int lineNum, ...);
+ static void display2(int resNum, int lineNum) {
+ display(resNum, lineNum, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ }
+};
+
+class SceneItemExt : public SceneItem {
+public:
+ int _state;
+
+ virtual Common::String getClassName() { return "SceneItemExt"; }
+ virtual void synchronise(Serialiser &s) {
+ SceneItem::synchronise(s);
+ s.syncAsSint16LE(_state);
+ }
+};
+
+class SceneHotspot : public SceneItem {
+public:
+ SceneHotspot() : SceneItem() {}
+
+ virtual Common::String getClassName() { return "SceneHotspot"; }
+ virtual void doAction(int action);
+};
+
+class NamedHotspot : public SceneHotspot {
+public:
+ int _resnum, _lookLineNum, _useLineNum;
+ NamedHotspot() : SceneHotspot() {}
+
+ void setup(int ys, int xs, int ye, int xe, const int resnum, const int lookLineNum, const int useLineNum);
+ virtual void doAction(int action);
+ virtual Common::String getClassName() { return "NamedHotspot"; }
+ virtual void synchronise(Serialiser &s);
+};
+
+enum AnimateMode {ANIM_MODE_NONE = 0, ANIM_MODE_1 = 1, ANIM_MODE_2 = 2, ANIM_MODE_3 = 3,
+ ANIM_MODE_4 = 4, ANIM_MODE_5 = 5, ANIM_MODE_6 = 6, ANIM_MODE_7 = 7, ANIM_MODE_8 = 8};
+
+class SceneObject;
+
+class Visage {
+private:
+ byte *_data;
+public:
+ int _resNum;
+ int _rlbNum;
+public:
+ Visage();
+ Visage(const Visage &v);
+ ~Visage();
+
+ void setVisage(int resNum, int rlbNum = 9999);
+ GfxSurface getFrame(int frameNum);
+ int getFrameCount() const;
+ Visage &operator=(const Visage &s);
+};
+
+class SceneObjectWrapper : public EventHandler {
+private:
+ Visage _visageImages;
+public:
+ SceneObject *_sceneObject;
+public:
+ SceneObjectWrapper() { _sceneObject = NULL; }
+ virtual ~SceneObjectWrapper() {}
+
+ void setSceneObject(SceneObject *so);
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "SceneObjectWrapper"; }
+ virtual void remove();
+ virtual void dispatch();
+};
+
+enum ObjectFlags {OBJFLAG_FIXED_PRIORITY = 1, OBJFLAG_NO_UPDATES = 2, OBJFLAG_ZOOMED = 4,
+ OBJFLAG_SUPPRESS_DISPATCH = 8, OBJFLAG_HIDE = 0x100, OBJFLAG_HIDING = 0x200, OBJFLAG_REMOVE = 0x400,
+ OBJFLAG_CLONED = 0x800, OBJFLAG_CHECK_REGION = 0x1000, OBJFLAG_PANE_0 = 0x4000, OBJFLAG_PANE_1 = 0x8000,
+ OBJFLAG_PANES = OBJFLAG_PANE_0 | OBJFLAG_PANE_1
+};
+
+class SceneObject : public SceneHotspot {
+private:
+ Visage _visageImages;
+
+ int getNewFrame();
+ void animEnded();
+ int changeFrame();
+ bool isNoMover() const { return !_mover || (_regionIndex > 0); }
+public:
+ uint32 _updateStartFrame;
+ uint32 _walkStartFrame;
+ Common::Point _field2E;
+ int _percent;
+ int _priority;
+ int _angle;
+ uint32 _flags;
+ int _xs, _xe;
+ Rect _paneRects[2];
+ int _visage;
+ SceneObjectWrapper *_objectWrapper;
+ int _strip;
+ AnimateMode _animateMode;
+ int _frame;
+ int _endFrame;
+ int _field68;
+ int _frameChange;
+ int _numFrames;
+ int _regionIndex;
+ EventHandler *_mover;
+ Common::Point _moveDiff;
+ int _moveRate;
+ Action *_endAction;
+ uint32 _regionBitList;
+public:
+ SceneObject();
+ SceneObject(const SceneObject &so);
+ virtual ~SceneObject();
+
+ void setPosition(const Common::Point &p, int yDiff = 0);
+ void setStrip(int frameNum);
+ void setStrip2(int frameNum);
+ void setZoom(int percent);
+ void updateZoom();
+ void changeZoom(int percent);
+ void setFrame(int frameNum);
+ void setFrame2(int frameNum);
+ void setPriority(int priority);
+ void fixPriority(int priority);
+ void setVisage(int visage);
+ void setObjectWrapper(SceneObjectWrapper *objWrapper);
+ void addMover(ObjectMover *mover, ...);
+ void getHorizBounds();
+ int getRegionIndex();
+ int checkRegion(const Common::Point &pt);
+ void animate(AnimateMode animMode, ...);
+ SceneObject *clone() const;
+ void checkAngle(const SceneObject *obj);
+ void hide();
+ void show();
+ int getSpliceArea(const SceneObject *obj);
+ int getFrameCount();
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "SceneObject"; }
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void process(Event &event) { event.handled = true; }
+ virtual void dispatch();
+ virtual void calcAngle(const Common::Point &pt);
+ virtual void removeObject();
+ virtual GfxSurface getFrame();
+ virtual void reposition();
+ virtual void draw();
+ virtual void proc19() {}
+ virtual void updateScreen();
+ void setup(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority);
+};
+
+class SceneObjectExt : public SceneObject {
+public:
+ int _state;
+
+ virtual void synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+ s.syncAsSint16LE(_state);
+ }
+ virtual Common::String getClassName() { return "SceneObjectExt"; }
+};
+
+class SceneText : public SceneObject {
+public:
+ int _fontNumber;
+ int _width;
+ TextAlign _textMode;
+ int _color1;
+ int _color2;
+ int _color3;
+ GfxSurface _textSurface;
+public:
+ SceneText();
+ ~SceneText();
+
+ void setup(const Common::String &msg);
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "SceneText"; }
+ virtual GfxSurface getFrame() { return _textSurface; }
+};
+
+class Player : public SceneObject {
+public:
+ bool _canWalk;
+ bool _uiEnabled;
+ int _field8C;
+public:
+ Player() : SceneObject() {}
+
+ virtual Common::String getClassName() { return "Player"; }
+ virtual void synchronise(Serialiser &s);
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void process(Event &event);
+
+ void disableControl();
+ void enableControl();
+};
+
+/*--------------------------------------------------------------------------*/
+
+class LineSliceSet {
+public:
+ Common::Array<LineSlice> items;
+
+ void load(int size, const byte *srcP) {
+ for (int i = 0; i < size; ++i, srcP += 4)
+ items.push_back(LineSlice(READ_LE_UINT16(srcP), READ_LE_UINT16(srcP + 2)));
+ }
+ void load2(int size, ...) {
+ va_list va;
+ va_start(va, size);
+
+ while (size-- > 0) {
+ int xs = va_arg(va, int);
+ int xe = va_arg(va, int);
+ items.push_back(LineSlice(xs, xe));
+ }
+ }
+
+ void add(LineSlice &slice) { items.push_back(slice); }
+ void add(int xs, int xe) { items.push_back(LineSlice(xs, xe)); }
+ static LineSliceSet mergeSlices(const LineSliceSet &set1, LineSliceSet &set2);
+};
+
+class Region {
+public:
+ int _regionSize;
+ int _regionId;
+ Rect _bounds;
+ Common::Array<LineSliceSet> _ySlices;
+public:
+ Region() { _regionSize = 0; _regionId = 0; }
+ Region(int resNum, int rlbNum, ResourceType ctlType = RES_CONTROL);
+ Region(int regionId, const byte *regionData);
+
+ void load(const byte *regionData);
+ bool contains(const Common::Point &pt);
+ bool empty() const;
+ void clear();
+ void setRect(const Rect &r);
+ void setRect(int xs, int ys, int xe, int ye);
+ const LineSliceSet &getLineSlices(int yp);
+ LineSliceSet sectPoints(int yp, const LineSliceSet &sliceSet);
+ void draw();
+ void uniteLine(int yp, LineSliceSet &sliceSet);
+ void uniteRect(const Rect &rect);
+
+ static LineSliceSet mergeSlices(const LineSliceSet &set1, const LineSliceSet &set2);
+};
+
+class SceneRegions : public Common::List<Region> {
+public:
+ void load(int sceneNum);
+
+ int indexOf(const Common::Point &pt);
+};
+
+class SceneObjectList : public SavedObject {
+private:
+ void checkIntersection(Common::Array<SceneObject *> &ObjList, uint ObjIndex, int PaneNum);
+
+ SynchronisedList<SceneObject *> _objList;
+ bool _listAltered;
+public:
+ SceneObjectList() { _listAltered = false; }
+ void sortList(Common::Array<SceneObject *> &ObjList);
+
+ virtual Common::String getClassName() { return "SceneObjectList"; }
+ virtual void synchronise(Serialiser &s);
+
+ void draw();
+ void activate();
+ static void deactivate();
+
+ typedef void (*EventHandlerFn)(EventHandler *fn);
+ void recurse(EventHandlerFn Fn) {
+ // Loop through each object
+ _listAltered = false;
+ for (SynchronisedList<SceneObject *>::iterator i = _objList.begin(); i != _objList.end() && !_listAltered; ) {
+ SceneObject *o = *i;
+ ++i;
+ Fn(o);
+ }
+ }
+ SynchronisedList<SceneObject *>::iterator begin() { return _objList.begin(); }
+ SynchronisedList<SceneObject *>::iterator end() { return _objList.end(); }
+ int size() const { return _objList.size(); }
+ bool contains(SceneObject *sceneObj) { return tSage::contains(_objList, sceneObj); }
+ void push_back(SceneObject *sceneObj) { _objList.push_back(sceneObj); }
+ void push_front(SceneObject *sceneObj) { _objList.push_front(sceneObj); }
+ void remove(SceneObject *sceneObj) {
+ _objList.remove(sceneObj);
+ _listAltered = true;
+ }
+};
+
+class ScenePriorities : public Common::List<Region> {
+public:
+ int _resNum;
+ int _field14;
+ int _field16;
+ Region _defaultPriorityRegion;
+public:
+ void load(int resNum);
+
+ Region *find(int priority);
+};
+
+/*--------------------------------------------------------------------------*/
+
+class GameSoundHandler {
+public:
+ void proc1() {
+ warning("TODO: GameSoundHandler::proc1");
+ }
+ void proc5(int v) {
+ warning("TODO: GameSoundHandler::proc5");
+ }
+ void proc11(int v1, int v2, int v3, int v4) {
+ warning("TODO: GameSoundHandler::proc11");
+ }
+ int proc12() {
+ // TODO
+ return -1;
+ }
+ void proc2(int v) {
+ // TODO
+ }
+ int proc3() {
+ return 0;
+ }
+ void setVolume(int volume) {
+ warning("TODO GameSoundHandler::setVolume");
+ }
+ void startSound(int soundNum) {
+ warning("TODO GameSoundHandler::startSound");
+ }
+};
+
+class SoundHandler : public EventHandler {
+public:
+ GameSoundHandler _sound;
+ Action *_action;
+ int _field280;
+public:
+ SoundHandler();
+ ~SoundHandler();
+
+ void startSound(int soundNum, Action *action = NULL, int volume = 127);
+ void proc1(Action *action) {
+ proc11(0, 5, 10, 1, action);
+ }
+ void proc2(int v) {
+ warning("TODO: SoundHandler::proc2");
+ }
+ void proc3() {
+ warning("TODO: SoundHandler::proc5");
+ }
+ void proc4() {
+ _sound.proc1();
+ }
+ void proc5(int v) {
+ _sound.proc5(v);
+ }
+ void proc11(int v1, int v2, int v3, int v4, Action *action) {
+ if (action)
+ _action = action;
+
+ _sound.proc11(v1, v2, v3, v4);
+ }
+ void setVolume(int volume) { _sound.setVolume(volume); }
+
+ virtual Common::String getClassName() { return "SoundHandler"; }
+ virtual void dispatch();
+};
+
+/*--------------------------------------------------------------------------*/
+
+class SceneItemList : public SynchronisedList<SceneItem *> {
+public:
+ void addItems(SceneItem *first, ...);
+};
+
+/*--------------------------------------------------------------------------*/
+
+class RegionSupportRec {
+public:
+ int _yp;
+ int _xp;
+ int _xDiff;
+ int _yDiff;
+ int _xDirection;
+ int _halfDiff;
+ int _yDiff2;
+
+ void process();
+};
+
+#define PROCESS_LIST_SIZE 100
+
+class WalkRegion : public Region {
+private:
+ static RegionSupportRec _processList[PROCESS_LIST_SIZE];
+ void loadProcessList(byte *dataP, int dataSize, int &dataIndex, int &regionHeight);
+ int process1(int idx, byte *dataP, int dataSize);
+ void process2(int dataIndex, int x1, int y1, int x2, int y2);
+ void process3(int yp, int dataCount, int &idx1, int &idx2);
+ void process4(int yp, int idx1, int idx2, int &count);
+ void process5(int idx1, int idx2);
+ void loadRecords(int yp, int size, int processIndex);
+ void process6(RegionSupportRec &rec);
+public:
+ Common::Point _pt;
+ int _idxListIndex;
+ int _idxList2Index;
+public:
+ void loadRegion(byte *dataP, int size);
+};
+
+class WRField18 {
+public:
+ Common::Point _pt1, _pt2;
+ int _v;
+public:
+ void load(byte *data);
+};
+
+class WalkRegions {
+private:
+ void loadOriginal();
+ void loadRevised();
+public:
+ int _resNum;
+ RouteEnds _routeEnds;
+ Common::Array<WalkRegion> _regionList;
+ Common::Array<WRField18> _field18;
+ Common::Array<int> _idxList;
+ Common::Array<int> _idxList2;
+public:
+ WalkRegions() { _resNum = -1; }
+
+ void clear();
+ void load(int sceneNum);
+ int indexOf(const Common::Point &pt, const Common::List<int> *indexList = NULL);
+ WalkRegion &operator[](int idx) {
+ assert((idx >= 1) && (idx <= (int)_regionList.size()));
+ return _regionList[idx - 1];
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+class FloatSet {
+public:
+ double _float1, _float2, _float3, _float4;
+
+ FloatSet() { _float1 = _float2 = _float3 = _float4 = 0; }
+ void add(double v1, double v2, double v3);
+ void proc1(double v);
+ double sqrt(FloatSet &floatSet);
+};
+
+/*--------------------------------------------------------------------------*/
+
+class GameHandler : public EventHandler {
+public:
+ RefCounter _lockCtr;
+ RefCounter _waitCtr;
+ int _nextWaitCtr;
+ int _field14;
+public:
+ GameHandler();
+ virtual ~GameHandler();
+ void execute();
+
+ virtual void synchronise(Serialiser &s);
+ virtual Common::String getClassName() { return "GameHandler"; }
+ virtual void postInit(SceneObjectList *OwnerList = NULL) {}
+ virtual void dispatch() {}
+};
+
+class SceneHandler : public GameHandler {
+public:
+ int _saveGameSlot;
+ int _loadGameSlot;
+ int _delayTicks;
+ Common::String _saveName;
+public:
+ SceneHandler();
+ void registerHandler();
+
+ virtual Common::String getClassName() { return "SceneHandler"; }
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void process(Event &event);
+ virtual void dispatch();
+
+ static void dispatchObject(EventHandler *obj);
+ static void saveListener(Serialiser &ser);
+};
+
+/*--------------------------------------------------------------------------*/
+
+class Game {
+protected:
+ SynchronisedList<GameHandler *> _handlers;
+
+ static bool notLockedFn(GameHandler *g);
+ virtual void handleSaveLoad(bool saveFlag, int &saveSlot, Common::String &saveName) {}
+public:
+ virtual ~Game() {}
+
+ void addHandler(GameHandler *entry) { _handlers.push_back(entry); }
+ void removeHandler(GameHandler *entry) { _handlers.remove(entry); }
+
+ void execute();
+ virtual void start() = 0;
+ virtual void restart() {}
+ virtual void restartGame() {}
+ virtual void saveGame() {}
+ virtual void restoreGame() {}
+ virtual void quitGame() {}
+ virtual void endGame(int resNum, int lineNum) {}
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/debugger.cpp b/engines/tsage/debugger.cpp
new file mode 100644
index 0000000000..eecc844292
--- /dev/null
+++ b/engines/tsage/debugger.cpp
@@ -0,0 +1,399 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/debugger.h"
+#include "tsage/globals.h"
+#include "tsage/graphics.h"
+#include "tsage/ringworld_logic.h"
+
+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("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("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;
+}
+
+/**
+ * This command loads up the specified new scene number
+ */
+bool Debugger::Cmd_Scene(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Usage: %s <scene number> [prior scene #]\n", argv[0]);
+ return true;
+ } else {
+ if (argc == 3)
+ _globals->_sceneManager._sceneNumber = strToInt(argv[2]);
+
+ _globals->_sceneManager.changeScene(strToInt(argv[1]));
+ return false;
+ }
+}
+
+/**
+ * This command draws the walk regions onto the screen
+ */
+bool Debugger::Cmd_WalkRegions(int argc, const char **argv) {
+ if (argc != 1) {
+ DebugPrintf("Usage: %s\n", argv[0]);
+ return true;
+ }
+
+ // Color index to use for the first walk region
+ int color = 16;
+
+ // Lock the background surface for access
+ Graphics::Surface destSurface = _globals->_sceneManager._scene->_backSurface.lockSurface();
+
+ // Loop through drawing each walk region in a different color to the background surface
+ Common::String regionsDesc;
+
+ for (uint regionIndex = 0; regionIndex < _globals->_walkRegions._regionList.size(); ++regionIndex, ++color) {
+ WalkRegion &wr = _globals->_walkRegions._regionList[regionIndex];
+
+ for (int yp = wr._bounds.top; yp < wr._bounds.bottom; ++yp) {
+ LineSliceSet sliceSet = wr.getLineSlices(yp);
+
+ for (uint idx = 0; idx < sliceSet.items.size(); ++idx)
+ destSurface.hLine(sliceSet.items[idx].xs - _globals->_sceneOffset.x, yp,
+ sliceSet.items[idx].xe - _globals->_sceneOffset.x, color);
+ }
+
+ regionsDesc += Common::String::format("Region #%d d bounds=%d,%d,%d,%d\n",
+ regionIndex, wr._bounds.left, wr._bounds.top, wr._bounds.right, wr._bounds.bottom);
+ }
+
+ // Release the surface
+ _globals->_sceneManager._scene->_backSurface.unlockSurface();
+
+ // Mark the scene as requiring a full redraw
+ _globals->_paneRefreshFlag[0] = 2;
+
+ DebugPrintf("Total regions = %d\n", _globals->_walkRegions._regionList.size());
+ DebugPrintf("%s\n", regionsDesc.c_str());
+
+ return false;
+}
+
+/*
+ * This command draws the priority regions onto the screen
+ */
+bool Debugger::Cmd_PriorityRegions(int argc, const char **argv) {
+ int regionNum = 0;
+
+ // Check for an optional specific region to display
+ if (argc == 2)
+ regionNum = strToInt(argv[1]);
+
+ // Color index to use for the first priority region
+ int color = 16;
+ int count = 0;
+
+ // Lock the background surface for access
+ Graphics::Surface destSurface = _globals->_sceneManager._scene->_backSurface.lockSurface();
+
+ Common::List<Region>::iterator i = _globals->_sceneManager._scene->_priorities.begin();
+ Common::String regionsDesc;
+
+ for (; i != _globals->_sceneManager._scene->_priorities.end(); ++i, ++color, ++count) {
+ Region &r = *i;
+
+ if ((regionNum == 0) || (regionNum == (count + 1))) {
+ for (int y = 0; y < destSurface.h; ++y) {
+ byte *destP = (byte *)destSurface.getBasePtr(0, y);
+
+ for (int x = 0; x < destSurface.w; ++x) {
+ if (r.contains(Common::Point(_globals->_sceneManager._scene->_sceneBounds.left + x,
+ _globals->_sceneManager._scene->_sceneBounds.top + y)))
+ *destP = color;
+ ++destP;
+ }
+ }
+ }
+
+ regionsDesc += Common::String::format("Region Priority = %d bounds=%d,%d,%d,%d\n",
+ r._regionId, r._bounds.left, r._bounds.top, r._bounds.right, r._bounds.bottom);
+ }
+
+ // Release the surface
+ _globals->_sceneManager._scene->_backSurface.unlockSurface();
+
+ // Mark the scene as requiring a full redraw
+ _globals->_paneRefreshFlag[0] = 2;
+
+ DebugPrintf("Total regions = %d\n", count);
+ DebugPrintf("%s", regionsDesc.c_str());
+
+ return true;
+}
+
+/*
+ * This command sets a flag
+ */
+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]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ _globals->setFlag(flagNum);
+ return true;
+}
+
+/*
+ * This command gets the value of a flag
+ */
+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]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ DebugPrintf("Value: %d\n", _globals->getFlag(flagNum));
+ return true;
+}
+
+/*
+ * This command clears a flag
+ */
+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]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ _globals->clearFlag(flagNum);
+ return true;
+}
+
+/*
+ * This command lists the objects available, and their ID
+ */
+bool Debugger::Cmd_ListObjects(int argc, const char **argv) {
+ if (argc != 1) {
+ 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");
+ return true;
+}
+
+/*
+ * This command gets an item, or move it to a room
+ */
+bool Debugger::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");
+ return true;
+ }
+
+ int objNum = strToInt(argv[1]);
+ int sceneNum = 1;
+ if (argc == 3)
+ sceneNum = strToInt(argv[2]);
+
+ switch (objNum) {
+ case OBJECT_STUNNER:
+ RING_INVENTORY._stunner._sceneNumber = sceneNum;
+ break;
+ case OBJECT_SCANNER:
+ RING_INVENTORY._scanner._sceneNumber = sceneNum;
+ break;
+ case OBJECT_STASIS_BOX:
+ RING_INVENTORY._stasisBox._sceneNumber = sceneNum;
+ break;
+ case OBJECT_INFODISK:
+ RING_INVENTORY._infoDisk._sceneNumber = sceneNum;
+ break;
+ case OBJECT_STASIS_NEGATOR:
+ RING_INVENTORY._stasisNegator._sceneNumber = sceneNum;
+ break;
+ case OBJECT_KEY_DEVICE:
+ RING_INVENTORY._keyDevice._sceneNumber = sceneNum;
+ break;
+ case OBJECT_MEDKIT:
+ RING_INVENTORY._medkit._sceneNumber = sceneNum;
+ break;
+ case OBJECT_LADDER:
+ RING_INVENTORY._ladder._sceneNumber = sceneNum;
+ break;
+ case OBJECT_ROPE:
+ RING_INVENTORY._rope._sceneNumber = sceneNum;
+ break;
+ case OBJECT_KEY:
+ RING_INVENTORY._key._sceneNumber = sceneNum;
+ break;
+ case OBJECT_TRANSLATOR:
+ RING_INVENTORY._translator._sceneNumber = sceneNum;
+ break;
+ case OBJECT_ALE:
+ RING_INVENTORY._ale._sceneNumber = sceneNum;
+ break;
+ case OBJECT_PAPER:
+ RING_INVENTORY._paper._sceneNumber = sceneNum;
+ break;
+ case OBJECT_WALDOS:
+ RING_INVENTORY._waldos._sceneNumber = sceneNum;
+ break;
+ case OBJECT_STASIS_BOX2:
+ RING_INVENTORY._stasisBox2._sceneNumber = sceneNum;
+ break;
+ case OBJECT_RING:
+ RING_INVENTORY._ring._sceneNumber = sceneNum;
+ break;
+ case OBJECT_CLOAK:
+ RING_INVENTORY._cloak._sceneNumber = sceneNum;
+ break;
+ case OBJECT_TUNIC:
+ RING_INVENTORY._tunic._sceneNumber = sceneNum;
+ break;
+ case OBJECT_CANDLE:
+ RING_INVENTORY._candle._sceneNumber = sceneNum;
+ break;
+ case OBJECT_STRAW:
+ RING_INVENTORY._straw._sceneNumber = sceneNum;
+ break;
+ case OBJECT_SCIMITAR:
+ RING_INVENTORY._scimitar._sceneNumber = sceneNum;
+ break;
+ case OBJECT_SWORD:
+ RING_INVENTORY._sword._sceneNumber = sceneNum;
+ break;
+ case OBJECT_HELMET:
+ RING_INVENTORY._helmet._sceneNumber = sceneNum;
+ break;
+ case OBJECT_ITEMS:
+ RING_INVENTORY._items._sceneNumber = sceneNum;
+ break;
+ case OBJECT_CONCENTRATOR:
+ RING_INVENTORY._concentrator._sceneNumber = sceneNum;
+ break;
+ case OBJECT_NULLIFIER:
+ RING_INVENTORY._nullifier._sceneNumber = sceneNum;
+ break;
+ case OBJECT_PEG:
+ RING_INVENTORY._peg._sceneNumber = sceneNum;
+ break;
+ case OBJECT_VIAL:
+ RING_INVENTORY._vial._sceneNumber = sceneNum;
+ break;
+ case OBJECT_JACKET:
+ RING_INVENTORY._jacket._sceneNumber = sceneNum;
+ break;
+ case OBJECT_TUNIC2:
+ RING_INVENTORY._tunic2._sceneNumber = sceneNum;
+ break;
+ case OBJECT_BONE:
+ RING_INVENTORY._bone._sceneNumber = sceneNum;
+ break;
+ case OBJECT_EMPTY_JAR:
+ RING_INVENTORY._emptyJar._sceneNumber = sceneNum;
+ break;
+ case OBJECT_JAR:
+ RING_INVENTORY._jar._sceneNumber = sceneNum;
+ break;
+ default:
+ DebugPrintf("Invlid object Id %s\n", argv[1]);
+ }
+
+ return true;
+}
+
+/**
+ * Give a specified item to the player
+ */
+bool Debugger::Cmd_Item(int argc, const char **argv) {
+ RING_INVENTORY._stasisBox._sceneNumber = 1;
+ return true;
+}
+
+
+} // End of namespace tSage
diff --git a/engines/tsage/debugger.h b/engines/tsage/debugger.h
new file mode 100644
index 0000000000..a34bb1ef0a
--- /dev/null
+++ b/engines/tsage/debugger.h
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_DEBUGGER_H
+#define TSAGE_DEBUGGER_H
+
+#include "common/scummsys.h"
+#include "gui/debugger.h"
+
+namespace tSage {
+
+class Debugger : public GUI::Debugger {
+public:
+ Debugger();
+ virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ
+
+protected:
+ bool Cmd_Scene(int argc, const char **argv);
+ bool Cmd_WalkRegions(int argc, const char **argv);
+ bool Cmd_PriorityRegions(int argc, const char **argv);
+ bool Cmd_SetFlag(int argc, const char **argv);
+ bool Cmd_GetFlag(int argc, const char **argv);
+ bool Cmd_ClearFlag(int argc, const char **argv);
+ bool Cmd_ListObjects(int argc, const char **argv);
+ bool Cmd_MoveObject(int argc, const char **argv);
+
+ bool Cmd_Item(int argc, const char **argv);
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp
new file mode 100644
index 0000000000..ba7b459304
--- /dev/null
+++ b/engines/tsage/detection.cpp
@@ -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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/config-manager.h"
+#include "common/system.h"
+#include "common/savefile.h"
+
+#include "engines/advancedDetector.h"
+
+#include "base/plugins.h"
+
+#include "tsage/tsage.h"
+
+namespace tSage {
+
+struct tSageGameDescription {
+ ADGameDescription desc;
+
+ int gameID;
+ uint32 features;
+};
+
+const char *TSageEngine::getGameId() const {
+ return _gameDescription->desc.gameid;
+}
+
+uint32 TSageEngine::getGameID() const {
+ return _gameDescription->gameID;
+}
+
+uint32 TSageEngine::getFeatures() const {
+ return _gameDescription->features;
+}
+
+Common::String TSageEngine::getPrimaryFilename() const {
+ return Common::String(_gameDescription->desc.filesDescriptions[0].fileName);
+}
+
+} // End of namespace tSage
+
+static const PlainGameDescriptor tSageGameTitles[] = {
+ { "tsage", "Unknown Tsunami TSAGE-based Game" },
+ { "ring", "Ringworld: Revenge of the Patriarch" },
+ { "blueforce", "Blue Force" },
+ { 0, 0 }
+};
+
+#include "engines/tsage/detection_tables.h"
+
+static const ADParams detectionParams = {
+ (const byte *)tSage::gameDescriptions,
+ sizeof(tSage::tSageGameDescription),
+ 0,
+ tSageGameTitles,
+ 0,
+ "tsage",
+ NULL,
+ 0,
+ Common::GUIO_NONE,
+ 0,
+ NULL
+};
+
+#define MAX_SAVES 100
+
+class TSageMetaEngine : public AdvancedMetaEngine {
+public:
+ TSageMetaEngine() : AdvancedMetaEngine(detectionParams) {
+ }
+
+ virtual const char *getName() const {
+ return "TsAGE Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "(c) Tsunami Media";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const {
+ switch (f) {
+ case kSupportsListSaves:
+ case kSupportsDeleteSave:
+ case kSupportsLoadingDuringStartup:
+ case kSavesSupportMetaInfo:
+ case kSavesSupportThumbnail:
+ case kSavesSupportCreationDate:
+ case kSavesSupportPlayTime:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ if (desc) {
+ *engine = new tSage::TSageEngine(syst, (const tSage::tSageGameDescription *)desc);
+ }
+ return desc != 0;
+ }
+
+ static Common::String generateGameStateFileName(const char *target, int slot) {
+ return Common::String::format("%s.%03d", target, slot);
+ }
+
+ virtual SaveStateList listSaves(const char *target) const {
+ Common::String pattern = target;
+ pattern += ".???";
+
+ Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end());
+ tSage::tSageSavegameHeader header;
+
+ 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) {
+ if (tSage::Saver::readSavegameHeader(in, header)) {
+ saveList.push_back(SaveStateDescriptor(slot, header.saveName));
+ delete header.thumbnail;
+ }
+
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+ }
+
+ virtual int getMaximumSaveSlot() const {
+ return MAX_SAVES - 1;
+ }
+
+ virtual void removeSaveState(const char *target, int slot) const {
+ Common::String filename = Common::String::format("%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(filename);
+ }
+
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const {
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(
+ generateGameStateFileName(target, slot));
+ assert(f);
+
+ tSage::tSageSavegameHeader header;
+ tSage::Saver::readSavegameHeader(f, header);
+ delete f;
+
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header.saveName);
+ desc.setDeletableFlag(true);
+ desc.setWriteProtectedFlag(false);
+ desc.setThumbnail(header.thumbnail);
+ desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
+ desc.setSaveTime(header.saveHour, header.saveMinutes);
+ desc.setPlayTime(header.totalFrames * GAME_FRAME_TIME);
+
+ return desc;
+ }
+};
+
+#if PLUGIN_ENABLED_DYNAMIC(TSAGE)
+REGISTER_PLUGIN_DYNAMIC(TSAGE, PLUGIN_TYPE_ENGINE, TSageMetaEngine);
+#else
+REGISTER_PLUGIN_STATIC(TSAGE, PLUGIN_TYPE_ENGINE, TSageMetaEngine);
+#endif
diff --git a/engines/tsage/detection_tables.h b/engines/tsage/detection_tables.h
new file mode 100644
index 0000000000..d165900d55
--- /dev/null
+++ b/engines/tsage/detection_tables.h
@@ -0,0 +1,119 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace tSage {
+
+static const tSageGameDescription gameDescriptions[] = {
+
+ // Ringworld English CD version
+ {
+ {
+ "ring",
+ "CD",
+ AD_ENTRY1s("ring.rlb", "466f0e6492d9d0f34d35c5cd088de90f", 37847618),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_Ringworld,
+ GF_CD | GF_ALT_REGIONS
+ },
+ // Ringworld First Wave English CD version
+ {
+ {
+ "ring",
+ "CD",
+ AD_ENTRY1s("ring.rlb", "0a25b4ee58d44a54425c0b47e5096bbc", 37847618),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_Ringworld,
+ GF_CD | GF_ALT_REGIONS
+ },
+ // Ringworld English Floppy version
+ {
+ {
+ "ring",
+ "Floppy",
+ AD_ENTRY1s("ring.rlb", "61f78f68a56832ae95fe06748c403234", 8438770),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_Ringworld,
+ GF_FLOPPY
+ },
+ // Ringworld English Floppy Demo #1 version
+ {
+ {
+ "ring",
+ "Floppy Demo",
+ AD_ENTRY1s("tsage.rlb", "bf4e8525d0cab84b08b57126092eeacd", 833453),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_Ringworld,
+ GF_FLOPPY | GF_DEMO
+ },
+ // Ringworld English Floppy Demo #2 version
+ {
+ {
+ "ring",
+ "Floppy Demo",
+ AD_ENTRY1s("demoring.rlb", "9ecf48e088a0d475778fab480b3dbdd0", 832206),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_Ringworld,
+ GF_FLOPPY | GF_DEMO | GF_ALT_REGIONS
+ },
+
+ // Blue Force
+ {
+ {
+ "blueforce",
+ "",
+ AD_ENTRY1s("blue.rlb", "467da43c848cc0e800b547c59d84ccb1", 10032614),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_BlueForce,
+ GF_FLOPPY
+ },
+
+ { AD_TABLE_END_MARKER, 0, 0 }
+};
+
+} // End of namespace tSage
diff --git a/engines/tsage/dialogs.cpp b/engines/tsage/dialogs.cpp
new file mode 100644
index 0000000000..b5f00bf73c
--- /dev/null
+++ b/engines/tsage/dialogs.cpp
@@ -0,0 +1,600 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/translation.h"
+
+#include "gui/dialog.h"
+#include "gui/widget.h"
+
+#include "tsage/tsage.h"
+#include "tsage/core.h"
+#include "tsage/dialogs.h"
+#include "tsage/staticres.h"
+#include "tsage/globals.h"
+#include "tsage/ringworld_logic.h"
+
+namespace tSage {
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * This dialog class provides a simple message display with support for either one or two buttons.
+ */
+MessageDialog::MessageDialog(const Common::String &message, const Common::String &btn1Message,
+ const Common::String &btn2Message) : GfxDialog() {
+ // Set up the message
+ addElements(&_msg, &_btn1, NULL);
+
+ _msg.set(message, 200, ALIGN_LEFT);
+ _btn1._bounds.moveTo(_msg._bounds.left, _msg._bounds.bottom + 2);
+ _defaultButton = &_btn1;
+
+ // Set up the first button
+ _btn1.setText(btn1Message);
+ _btn1._bounds.moveTo(_msg._bounds.right - _btn1._bounds.width(), _msg._bounds.bottom);
+
+ if (!btn2Message.empty()) {
+ // Set up the second button
+ _defaultButton = &_btn2;
+ add(&_btn2);
+ _btn2.setText(btn2Message);
+ _btn2._bounds.moveTo(_msg._bounds.right - _btn2._bounds.width(), _msg._bounds.bottom);
+ _btn1._bounds.translate(-(_btn2._bounds.width() + 4), 0);
+ }
+
+ // Do post setup for the dialog
+ setDefaults();
+
+ // Set the dialog's center
+ setCenter(_globals->_dialogCenter.x, _globals->_dialogCenter.y);
+}
+
+int MessageDialog::show(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message) {
+ // Ensure that the cursor is the arrow
+ _globals->_events.pushCursor(CURSOR_ARROW);
+ _globals->_events.showCursor();
+
+ int result = show2(message, btn1Message, btn2Message);
+
+ _globals->_events.popCursor();
+ return result;
+}
+
+int MessageDialog::show2(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message) {
+ MessageDialog *dlg = new MessageDialog(message, btn1Message, btn2Message);
+ dlg->draw();
+
+ GfxButton *selectedButton = dlg->execute();
+ int result = (selectedButton == &dlg->_btn1) ? 0 : 1;
+
+ delete dlg;
+ return result;
+}
+
+/*--------------------------------------------------------------------------*/
+
+ConfigDialog::ConfigDialog() : GUI::OptionsDialog("", "GlobalConfig") {
+ //
+ // Sound controllers
+ //
+
+ addVolumeControls(this, "GlobalConfig.");
+ setVolumeSettingsState(true); // could disable controls by GUI options
+
+ //
+ // Add the buttons
+ //
+
+ new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), 0, GUI::kOKCmd);
+ new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), 0, GUI::kCloseCmd);
+}
+
+/*--------------------------------------------------------------------------*/
+
+#define BUTTON_WIDTH 28
+#define BUTTON_HEIGHT 29
+
+RightClickButton::RightClickButton(int buttonIndex, int xp, int yp) : GfxButton() {
+ _buttonIndex = buttonIndex;
+ this->_bounds.left = xp;
+ this->_bounds.top = yp;
+ this->_bounds.setWidth(BUTTON_WIDTH);
+ this->_bounds.setHeight(BUTTON_HEIGHT);
+ _savedButton = NULL;
+}
+
+void RightClickButton::highlight() {
+ if (_savedButton) {
+ // Button was previously highlighted, so de-highlight by restoring saved area
+ _globals->gfxManager().copyFrom(*_savedButton, _bounds.left, _bounds.top);
+ delete _savedButton;
+ _savedButton = NULL;
+ } else {
+ // Highlight button by getting the needed highlighted image resource
+ _savedButton = Surface_getArea(_globals->gfxManager().getSurface(), _bounds);
+
+ uint size;
+ byte *imgData = _resourceManager->getSubResource(7, 2, _buttonIndex, &size);
+
+ GfxSurface btnSelected = surfaceFromRes(imgData);
+ _globals->gfxManager().copyFrom(btnSelected, _bounds.left, _bounds.top);
+
+ DEALLOCATE(imgData);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * This dialog implements the right-click dialog
+ */
+RightClickDialog::RightClickDialog() : GfxDialog(),
+ _walkButton(1, 48, 12), _lookButton(2, 31, 29), _useButton(3, 65, 29),
+ _talkButton(4, 14, 47), _inventoryButton(5, 48, 47), _optionsButton(6, 83, 47) {
+ Rect rectArea, dialogRect;
+
+ // Set the palette and change the cursor
+ _gfxManager.setDialogPalette();
+ _globals->_events.setCursor(CURSOR_ARROW);
+
+ // Get the dialog image
+ _surface = surfaceFromRes(7, 1, 1);
+
+ // Set the dialog position
+ dialogRect.resize(_surface, 0, 0, 100);
+ dialogRect.center(_globals->_events._mousePos.x, _globals->_events._mousePos.y);
+
+ // Ensure the dialog will be entirely on-screen
+ Rect screenRect = _globals->gfxManager()._bounds;
+ screenRect.collapse(4, 4);
+ dialogRect.contain(screenRect);
+
+ _bounds = dialogRect;
+ _gfxManager._bounds = _bounds;
+
+ _highlightedButton = NULL;
+ _selectedAction = -1;
+}
+
+RightClickDialog::~RightClickDialog() {
+}
+
+RightClickButton *RightClickDialog::findButton(const Common::Point &pt) {
+ RightClickButton *btnList[] = { &_walkButton, &_lookButton, &_useButton, &_talkButton, &_inventoryButton, &_optionsButton };
+
+ for (int i = 0; i < 6; ++i) {
+ btnList[i]->_owner = this;
+
+ if (btnList[i]->_bounds.contains(pt))
+ return btnList[i];
+ }
+
+ return NULL;
+}
+
+void RightClickDialog::draw() {
+ // Save the covered background area
+ _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), _bounds);
+
+ // Draw the dialog image
+ _globals->gfxManager().copyFrom(_surface, _bounds.left, _bounds.top);
+}
+
+bool RightClickDialog::process(Event &event) {
+ switch (event.eventType) {
+ case EVENT_MOUSE_MOVE: {
+ // Check whether a button is highlighted
+ RightClickButton *btn = findButton(event.mousePos);
+
+ if (btn != _highlightedButton) {
+ // De-highlight any previously selected button
+ if (_highlightedButton) {
+ _highlightedButton->highlight();
+ _highlightedButton = NULL;
+ }
+ if (btn) {
+ // Highlight the new button
+ btn->highlight();
+ _highlightedButton = btn;
+ }
+ }
+ event.handled = true;
+ return true;
+ }
+
+ case EVENT_BUTTON_DOWN:
+ // If a button is highlighted, then flag the selected button index
+ if (_highlightedButton)
+ _selectedAction = _highlightedButton->_buttonIndex;
+ else
+ _selectedAction = _lookButton._buttonIndex;
+ event.handled = true;
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void RightClickDialog::execute() {
+ // Draw the dialog
+ draw();
+
+ // Dialog event handler loop
+ _gfxManager.activate();
+
+ while (!_vm->getEventManager()->shouldQuit() && (_selectedAction == -1)) {
+ Event evt;
+ while (_globals->_events.getEvent(evt, EVENT_MOUSE_MOVE | EVENT_BUTTON_DOWN)) {
+ evt.mousePos.x -= _bounds.left;
+ evt.mousePos.y -= _bounds.top;
+
+ process(evt);
+ }
+
+ g_system->delayMillis(10);
+ g_system->updateScreen();
+ }
+
+ // Execute the specified action
+ switch (_selectedAction) {
+ case 1:
+ // Look action
+ _globals->_events.setCursor(CURSOR_LOOK);
+ break;
+ case 2:
+ // Walk action
+ _globals->_events.setCursor(CURSOR_WALK);
+ break;
+ case 3:
+ // Use cursor
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 4:
+ // Talk cursor
+ _globals->_events.setCursor(CURSOR_TALK);
+ break;
+ case 5:
+ // Inventory dialog
+ InventoryDialog::show();
+ break;
+ case 6:
+ // Dialog options
+ OptionsDialog::show();
+ break;
+ }
+
+ _gfxManager.deactivate();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void ModalDialog::draw() {
+ // Set the palette for use in the dialog
+ setPalette();
+
+ // Make a backup copy of the area the dialog will occupy
+ Rect tempRect = _bounds;
+ tempRect.collapse(-10, -10);
+ _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), tempRect);
+
+ _gfxManager.activate();
+
+ // Fill in the contents of the entire dialog
+ _gfxManager._bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ drawFrame();
+
+ // Draw each element in the dialog in order
+ GfxElementList::iterator i;
+ for (i = _elements.begin(); i != _elements.end(); ++i) {
+ (*i)->draw();
+ }
+
+ _gfxManager.deactivate();
+}
+
+void ModalDialog::drawFrame() {
+ Rect origRect = _bounds;
+ _bounds.collapse(-10, -10);
+
+ // Fill the dialog area
+ _globals->gfxManager().fillRect(origRect, 54);
+
+ // Draw top line
+ GfxSurface surface = surfaceFromRes(8, 1, 7);
+ for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10)
+ surface.draw(Common::Point(xp, _bounds.top));
+ surface.draw(Common::Point(_bounds.right - 20, _bounds.top));
+
+ surface = surfaceFromRes(8, 1, 1);
+ surface.draw(Common::Point(_bounds.left, _bounds.top));
+
+ surface = surfaceFromRes(8, 1, 4);
+ surface.draw(Common::Point(_bounds.right - 10, _bounds.top));
+
+ // Draw vertical edges
+ surface = surfaceFromRes(8, 1, 2);
+ for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10)
+ surface.draw(Common::Point(_bounds.left, yp));
+ surface.draw(Common::Point(_bounds.left, _bounds.bottom - 20));
+
+ surface = surfaceFromRes(8, 1, 5);
+ for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10)
+ surface.draw(Common::Point(_bounds.right - 10, yp));
+ surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 20));
+
+ // Draw bottom line
+ surface = surfaceFromRes(8, 1, 8);
+ for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10)
+ surface.draw(Common::Point(xp, _bounds.bottom - 10));
+ surface.draw(Common::Point(_bounds.right - 20, _bounds.bottom - 10));
+
+ surface = surfaceFromRes(8, 1, 3);
+ surface.draw(Common::Point(_bounds.left, _bounds.bottom - 10));
+
+ surface = surfaceFromRes(8, 1, 6);
+ surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 10));
+
+ // Set the dialog's manager bounds
+ _gfxManager._bounds = origRect;
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool GfxInvImage::process(Event &event) {
+ if (!event.handled && (event.eventType == EVENT_BUTTON_DOWN)) {
+ event.handled = _bounds.contains(event.mousePos);
+ return event.handled;
+ }
+
+ return false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void InventoryDialog::show() {
+ // Determine how many items are in the player's inventory
+ int itemCount = 0;
+ SynchronisedList<InvObject *>::iterator i;
+ for (i = RING_INVENTORY._itemList.begin(); i != RING_INVENTORY._itemList.end(); ++i) {
+ if ((*i)->inInventory())
+ ++itemCount;
+ }
+
+ if (itemCount == 0) {
+ MessageDialog::show(INV_EMPTY_MSG, OK_BTN_STRING);
+ return;
+ }
+
+ InventoryDialog *dlg = new InventoryDialog();
+ dlg->draw();
+ dlg->execute();
+ delete dlg;
+}
+
+InventoryDialog::InventoryDialog() {
+ // Determine the maximum size of the image of any item in the player's inventory
+ int imgWidth = 0, imgHeight = 0;
+
+ SynchronisedList<InvObject *>::iterator i;
+ for (i = RING_INVENTORY._itemList.begin(); i != RING_INVENTORY._itemList.end(); ++i) {
+ InvObject *invObject = *i;
+ if (invObject->inInventory()) {
+ // Get the image for the item
+ GfxSurface itemSurface = surfaceFromRes(invObject->_displayResNum, invObject->_rlbNum, invObject->_cursorNum);
+
+ // Maintain the dimensions of the largest item image
+ imgWidth = MAX(imgWidth, (int)itemSurface.getBounds().width());
+ imgHeight = MAX(imgHeight, (int)itemSurface.getBounds().height());
+
+ // Add the item to the display list
+ GfxInvImage *img = new GfxInvImage();
+ _images.push_back(img);
+ img->setDetails(invObject->_displayResNum, invObject->_rlbNum, invObject->_cursorNum);
+ img->_invObject = invObject;
+ add(img);
+ }
+ }
+ assert(_images.size() > 0);
+
+ // Figure out the number of columns/rows to show all the items
+ int cellsSize = 3;
+ while ((cellsSize * cellsSize) < (int)_images.size())
+ ++cellsSize;
+
+ // Set the position of each inventory item to be displayed
+ int cellX = 0;
+ Common::Point pt(0, 0);
+
+ for (uint idx = 0; idx < _images.size(); ++idx) {
+ if (cellX == cellsSize) {
+ // Move to the start of the next line
+ pt.x = 0;
+ pt.y += imgHeight + 2;
+ cellX = 0;
+ }
+
+ _images[idx]->_bounds.moveTo(pt.x, pt.y);
+
+ pt.x += imgWidth + 2;
+ ++cellX;
+ }
+
+ // Set up the buttons
+ pt.y += imgHeight + 2;
+ _btnOk.setText(OK_BTN_STRING);
+ _btnOk._bounds.moveTo((imgWidth + 2) * cellsSize - _btnOk._bounds.width(), pt.y);
+ _btnLook.setText(LOOK_BTN_STRING);
+ _btnLook._bounds.moveTo(_btnOk._bounds.left - _btnLook._bounds.width() - 2, _btnOk._bounds.top);
+ addElements(&_btnLook, &_btnOk, NULL);
+
+ frame();
+ setCenter(SCREEN_CENTER_X, SCREEN_CENTER_Y);
+}
+
+InventoryDialog::~InventoryDialog() {
+ for (uint idx = 0; idx < _images.size(); ++idx)
+ delete _images[idx];
+}
+
+void InventoryDialog::execute() {
+ if ((RING_INVENTORY._selectedItem) && RING_INVENTORY._selectedItem->inInventory())
+ RING_INVENTORY._selectedItem->setCursor();
+
+ GfxElement *hiliteObj;
+ bool lookFlag = false;
+ _gfxManager.activate();
+
+ while (!_vm->getEventManager()->shouldQuit()) {
+ // Get events
+ Event event;
+ while (!_globals->_events.getEvent(event) && !_vm->getEventManager()->shouldQuit())
+ ;
+ if (_vm->getEventManager()->shouldQuit())
+ return;
+
+ hiliteObj = NULL;
+ if ((event.eventType == EVENT_BUTTON_DOWN) && !_bounds.contains(event.mousePos))
+ break;
+
+ // Pass event to elements
+ event.mousePos.x -= _gfxManager._bounds.left;
+ event.mousePos.y -= _gfxManager._bounds.top;
+
+ for (GfxElementList::iterator i = _elements.begin(); i != _elements.end(); ++i) {
+ if ((*i)->process(event))
+ hiliteObj = *i;
+ }
+
+ if (!event.handled && event.eventType == EVENT_KEYPRESS) {
+ if ((event.kbd.keycode == Common::KEYCODE_RETURN) || (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ // Exit the dialog
+ //hiliteObj = &_btnOk;
+ break;
+ }
+ }
+
+ if (hiliteObj == &_btnOk) {
+ // Ok button clicked
+ if (lookFlag)
+ _globals->_events.setCursor(CURSOR_WALK);
+ break;
+ } else if (hiliteObj == &_btnLook) {
+ // Look button clicked
+ if (_btnLook._message == LOOK_BTN_STRING) {
+ _btnLook._message = PICK_BTN_STRING;
+ lookFlag = 1;
+ _globals->_events.setCursor(CURSOR_LOOK);
+ } else {
+ _btnLook._message = LOOK_BTN_STRING;
+ lookFlag = 0;
+ _globals->_events.setCursor(CURSOR_WALK);
+ }
+
+ hiliteObj->draw();
+ } else if (hiliteObj) {
+ // Inventory item selected
+ InvObject *invObject = static_cast<GfxInvImage *>(hiliteObj)->_invObject;
+ if (lookFlag) {
+ _globals->_screenSurface.displayText(invObject->_description);
+ } else {
+ RING_INVENTORY._selectedItem = invObject;
+ invObject->setCursor();
+ }
+ }
+ }
+
+ _gfxManager.deactivate();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void OptionsDialog::show() {
+ OptionsDialog *dlg = new OptionsDialog();
+ dlg->draw();
+
+ GfxButton *btn = dlg->execute();
+
+ if (btn == &dlg->_btnQuit) {
+ // Quit game
+ if (MessageDialog::show(QUIT_CONFIRM_MSG, CANCEL_BTN_STRING, QUIT_BTN_STRING) == 1) {
+ _vm->quitGame();
+ }
+ } else if (btn == &dlg->_btnRestart) {
+ // Restart game
+ _globals->_game->restartGame();
+ } else if (btn == &dlg->_btnSound) {
+ // Sound dialog
+ } else if (btn == &dlg->_btnSave) {
+ // Save button
+ _globals->_game->saveGame();
+ } else if (btn == &dlg->_btnRestore) {
+ // Restore button
+ _globals->_game->restoreGame();
+ }
+
+ dlg->remove();
+ delete dlg;
+}
+
+OptionsDialog::OptionsDialog() {
+ // Set the element text
+ _gfxMessage.set(OPTIONS_MSG, 140, ALIGN_LEFT);
+ _btnRestore.setText(RESTORE_BTN_STRING);
+ _btnSave.setText(SAVE_BTN_STRING);
+ _btnRestart.setText(RESTART_BTN_STRING);
+ _btnQuit.setText(QUIT_BTN_STRING);
+ _btnSound.setText(SOUND_BTN_STRING);
+ _btnResume.setText(RESUME_BTN_STRING);
+
+ // Set position of the elements
+ _gfxMessage._bounds.moveTo(0, 1);
+ _btnRestore._bounds.moveTo(0, _gfxMessage._bounds.bottom + 1);
+ _btnSave._bounds.moveTo(0, _btnRestore._bounds.bottom + 1);
+ _btnRestart._bounds.moveTo(0, _btnSave._bounds.bottom + 1);
+ _btnQuit._bounds.moveTo(0, _btnRestart._bounds.bottom + 1);
+ _btnSound._bounds.moveTo(0, _btnQuit._bounds.bottom + 1);
+ _btnResume._bounds.moveTo(0, _btnSound._bounds.bottom + 1);
+
+ // Set all the buttons to the widest button
+ GfxButton *btnList[6] = {&_btnRestore, &_btnSave, &_btnRestart, &_btnQuit, &_btnSound, &_btnResume};
+ int16 btnWidth = 0;
+ for (int idx = 0; idx < 6; ++idx)
+ btnWidth = MAX(btnWidth, btnList[idx]->_bounds.width());
+ for (int idx = 0; idx < 6; ++idx)
+ btnList[idx]->_bounds.setWidth(btnWidth);
+
+ // Add the items to the dialog
+ addElements(&_gfxMessage, &_btnRestore, &_btnSave, &_btnRestart, &_btnQuit, &_btnSound, &_btnResume, NULL);
+
+ // Set the dialog size and position
+ frame();
+ setCenter(160, 100);
+}
+
+
+} // End of namespace tSage
diff --git a/engines/tsage/dialogs.h b/engines/tsage/dialogs.h
new file mode 100644
index 0000000000..c24fa2dd3b
--- /dev/null
+++ b/engines/tsage/dialogs.h
@@ -0,0 +1,136 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_DIALOGS_H
+#define TSAGE_DIALOGS_H
+
+#include "gui/options.h"
+#include "tsage/events.h"
+#include "tsage/graphics.h"
+#include "common/list.h"
+#include "common/rect.h"
+#include "common/system.h"
+
+namespace tSage {
+
+class MessageDialog : public GfxDialog {
+public:
+ GfxButton _btn1, _btn2;
+ GfxDialog _dialog;
+ GfxMessage _msg;
+public:
+ MessageDialog(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message = Common::String());
+
+ static int show(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message = Common::String());
+ static int show2(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message = Common::String());
+};
+
+class ConfigDialog : public GUI::OptionsDialog {
+public:
+ ConfigDialog();
+};
+
+class RightClickButton : public GfxButton {
+private:
+ GfxSurface *_savedButton;
+public:
+ int _buttonIndex;
+
+ RightClickButton(int buttonIndex, int xp, int yp);
+ ~RightClickButton() { delete _savedButton; }
+
+ virtual void highlight();
+};
+
+class RightClickDialog : public GfxDialog {
+private:
+ GfxSurface _surface;
+ RightClickButton *_highlightedButton;
+ int _selectedAction;
+ RightClickButton _walkButton, _lookButton, _useButton, _talkButton, _inventoryButton, _optionsButton;
+
+ RightClickButton *findButton(const Common::Point &pt);
+public:
+ RightClickDialog();
+ ~RightClickDialog();
+
+ virtual void draw();
+ virtual bool process(Event &event);
+ void execute();
+};
+
+/*--------------------------------------------------------------------------*/
+
+class ModalDialog : public GfxDialog {
+protected:
+ void drawFrame();
+public:
+ virtual void draw();
+};
+
+/*--------------------------------------------------------------------------*/
+
+class GfxInvImage : public GfxImage {
+public:
+ InvObject *_invObject;
+public:
+ GfxInvImage() : GfxImage(), _invObject(NULL) {}
+
+ virtual bool process(Event &event);
+};
+
+#define MAX_INVOBJECT_DISPLAY 20
+
+class InventoryDialog : public ModalDialog {
+private:
+ Common::Array<GfxInvImage *> _images;
+ GfxButton _btnOk, _btnLook;
+public:
+ InventoryDialog();
+ virtual ~InventoryDialog();
+ void execute();
+
+ static void show();
+};
+
+/*--------------------------------------------------------------------------*/
+
+class OptionsDialog : public ModalDialog {
+private:
+ GfxButton _btnSave, _btnRestore, _btnRestart;
+ GfxButton _btnQuit, _btnResume;
+ GfxButton _btnSound;
+ GfxMessage _gfxMessage;
+public:
+ OptionsDialog();
+ virtual ~OptionsDialog() {}
+ GfxButton *execute() { return GfxDialog::execute(&_btnResume); }
+
+ static void show();
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp
new file mode 100644
index 0000000000..bcfff9fc1d
--- /dev/null
+++ b/engines/tsage/events.cpp
@@ -0,0 +1,311 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/events.h"
+#include "common/singleton.h"
+#include "graphics/cursorman.h"
+#include "common/system.h"
+
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/staticres.h"
+#include "tsage/tsage.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+EventsClass::EventsClass() {
+ _currentCursor = CURSOR_NONE;
+ hideCursor();
+ _frameNumber = 0;
+ _priorFrameTime = 0;
+ _prevDelayFrame = 0;
+ _saver->addListener(this);
+}
+
+bool EventsClass::pollEvent() {
+ uint32 milli = g_system->getMillis();
+ if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
+ _priorFrameTime = milli;
+ ++_frameNumber;
+
+ g_system->updateScreen();
+ }
+
+ if (!g_system->getEventManager()->pollEvent(_event)) return false;
+
+ // Handle keypress
+ switch (_event.type) {
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RTL:
+ break;
+
+ case Common::EVENT_MOUSEMOVE:
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONDOWN:
+ case Common::EVENT_RBUTTONUP:
+ // Keep a copy of the current mouse position
+ _mousePos = _event.mouse;
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void EventsClass::waitForPress(int eventMask) {
+ Event evt;
+ while (!_vm->getEventManager()->shouldQuit() && !getEvent(evt, eventMask))
+ g_system->delayMillis(10);
+}
+
+/**
+ * Standard event retrieval, which only returns keyboard and mouse clicks
+ */
+bool EventsClass::getEvent(Event &evt, int eventMask) {
+ while (pollEvent() && !_vm->getEventManager()->shouldQuit()) {
+ evt.handled = false;
+ evt.eventType = EVENT_NONE;
+ evt.mousePos = _event.mouse;
+ evt.kbd = _event.kbd;
+
+ switch (_event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ evt.eventType = EVENT_MOUSE_MOVE;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ evt.eventType = EVENT_BUTTON_DOWN;
+ evt.btnState = BTNSHIFT_LEFT;
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ evt.eventType = EVENT_BUTTON_DOWN;
+ evt.btnState = BTNSHIFT_RIGHT;
+ break;
+ case Common::EVENT_MBUTTONDOWN:
+ evt.eventType = EVENT_BUTTON_DOWN;
+ evt.btnState = BTNSHIFT_MIDDLE;
+ break;
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ case Common::EVENT_MBUTTONUP:
+ evt.eventType = EVENT_BUTTON_UP;
+ evt.btnState = 0;
+ break;
+ case Common::EVENT_KEYDOWN:
+ evt.eventType = EVENT_KEYPRESS;
+ evt.kbd = _event.kbd;
+ break;
+ default:
+ break;
+ }
+
+ if (evt.eventType & eventMask)
+ return true;
+ }
+
+ evt.handled = false;
+ evt.eventType = EVENT_NONE;
+
+ return false;
+}
+
+/**
+ * Sets the specified cursor
+ *
+ * @cursorType Specified cursor number
+ */
+void EventsClass::setCursor(CursorType cursorType) {
+ _globals->clearFlag(122);
+
+ if ((_currentCursor == cursorType) && CursorMan.isVisible())
+ return;
+
+ if (cursorType == CURSOR_NONE) {
+ if (CursorMan.isVisible())
+ CursorMan.showMouse(false);
+ return;
+ }
+
+ CursorMan.showMouse(true);
+
+ const byte *cursor;
+ bool delFlag = true;
+ uint size;
+
+ switch (cursorType) {
+ case CURSOR_CROSSHAIRS:
+ // Crosshairs cursor
+ cursor = _resourceManager->getSubResource(4, 1, 6, &size);
+ _globals->setFlag(122);
+ break;
+
+ case CURSOR_LOOK:
+ // Look cursor
+ cursor = _resourceManager->getSubResource(4, 1, 5, &size);
+ _currentCursor = CURSOR_LOOK;
+ break;
+
+ case CURSOR_USE:
+ // Use cursor
+ cursor = _resourceManager->getSubResource(4, 1, 4, &size);
+ _currentCursor = CURSOR_USE;
+ break;
+
+ case CURSOR_TALK:
+ // Talk cursor
+ cursor = _resourceManager->getSubResource(4, 1, 3, &size);
+ _currentCursor = CURSOR_TALK;
+ break;
+
+ case CURSOR_ARROW:
+ // Arrow cursor
+ cursor = CURSOR_ARROW_DATA;
+ delFlag = false;
+ break;
+
+ case CURSOR_WALK:
+ default:
+ // Walk cursor
+ cursor = CURSOR_WALK_DATA;
+ _currentCursor = CURSOR_WALK;
+ delFlag = false;
+ break;
+ }
+
+ // Decode the cursor
+ GfxSurface s = surfaceFromRes(cursor);
+
+ Graphics::Surface surface = s.lockSurface();
+ const byte *cursorData = (const byte *)surface.getBasePtr(0, 0);
+ CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor);
+ s.unlockSurface();
+
+ if (delFlag)
+ DEALLOCATE(cursor);
+}
+
+void EventsClass::pushCursor(CursorType cursorType) {
+ const byte *cursor;
+ bool delFlag = true;
+ uint size;
+
+ switch (cursorType) {
+ case CURSOR_CROSSHAIRS:
+ // Crosshairs cursor
+ cursor = _resourceManager->getSubResource(4, 1, 6, &size);
+ break;
+
+ case CURSOR_LOOK:
+ // Look cursor
+ cursor = _resourceManager->getSubResource(4, 1, 5, &size);
+ break;
+
+ case CURSOR_USE:
+ // Use cursor
+ cursor = _resourceManager->getSubResource(4, 1, 4, &size);
+ break;
+
+ case CURSOR_TALK:
+ // Talk cursor
+ cursor = _resourceManager->getSubResource(4, 1, 3, &size);
+ break;
+
+ case CURSOR_ARROW:
+ // Arrow cursor
+ cursor = CURSOR_ARROW_DATA;
+ delFlag = false;
+ break;
+
+ case CURSOR_WALK:
+ default:
+ // Walk cursor
+ cursor = CURSOR_WALK_DATA;
+ delFlag = false;
+ break;
+ }
+
+ // Decode the cursor
+ GfxSurface s = surfaceFromRes(cursor);
+
+ Graphics::Surface surface = s.lockSurface();
+ const byte *cursorData = (const byte *)surface.getBasePtr(0, 0);
+ CursorMan.pushCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor);
+ s.unlockSurface();
+
+ if (delFlag)
+ DEALLOCATE(cursor);
+}
+
+void EventsClass::popCursor() {
+ CursorMan.popCursor();
+}
+
+void EventsClass::setCursor(Graphics::Surface &cursor, int transColor, const Common::Point &hotspot, CursorType cursorId) {
+ const byte *cursorData = (const byte *)cursor.getBasePtr(0, 0);
+ CursorMan.replaceCursor(cursorData, cursor.w, cursor.h, hotspot.x, hotspot.y, transColor);
+
+ _currentCursor = cursorId;
+}
+
+void EventsClass::setCursorFromFlag() {
+ setCursor(_globals->getFlag(122) ? CURSOR_CROSSHAIRS : _currentCursor);
+}
+
+void EventsClass::showCursor() {
+ CursorMan.showMouse(true);
+}
+
+void EventsClass::hideCursor() {
+ CursorMan.showMouse(false);
+}
+
+bool EventsClass::isCursorVisible() const {
+ return CursorMan.isVisible();
+}
+
+/**
+ * Delays the game for the specified number of frames, if necessary, from the
+ * previous time the delay method was called
+ */
+void EventsClass::delay(int numFrames) {
+ while (_frameNumber < (_prevDelayFrame + numFrames)) {
+ uint32 delayAmount = CLIP(_priorFrameTime + GAME_FRAME_TIME - g_system->getMillis(),
+ (uint32)0, (uint32)GAME_FRAME_TIME);
+ if (delayAmount > 0)
+ g_system->delayMillis(delayAmount);
+
+ ++_frameNumber;
+ _priorFrameTime = g_system->getMillis();
+ }
+
+ g_system->updateScreen();
+ _prevDelayFrame = _frameNumber;
+ _priorFrameTime = g_system->getMillis();
+}
+
+} // end of namespace tSage
diff --git a/engines/tsage/events.h b/engines/tsage/events.h
new file mode 100644
index 0000000000..90516b2353
--- /dev/null
+++ b/engines/tsage/events.h
@@ -0,0 +1,112 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_EVENTS_H
+#define TSAGE_EVENTS_H
+
+#include "common/events.h"
+#include "common/array.h"
+#include "common/str.h"
+#include "graphics/surface.h"
+#include "tsage/saveload.h"
+
+namespace tSage {
+
+enum EventType {EVENT_NONE = 0, EVENT_BUTTON_DOWN = 1, EVENT_BUTTON_UP = 2, EVENT_KEYPRESS = 4,
+ EVENT_MOUSE_MOVE = 8};
+
+enum ButtonShiftFlags {BTNSHIFT_LEFT = 0, BTNSHIFT_RIGHT = 3, BTNSHIFT_MIDDLE = 4};
+
+// Intrinisc game delay between execution frames. This runs at 60Hz
+#define GAME_FRAME_TIME (1000 / 60)
+
+class GfxManager;
+
+class Event {
+public:
+ EventType eventType;
+ Common::Point mousePos;
+ int btnState;
+ Common::KeyState kbd;
+ int ctr;
+ GfxManager *gfxMan;
+ bool handled;
+};
+
+enum CursorType {
+ OBJECT_STUNNER = 0, OBJECT_SCANNER = 1, OBJECT_STASIS_BOX = 2,
+ OBJECT_INFODISK = 3, OBJECT_STASIS_NEGATOR = 4, OBJECT_KEY_DEVICE = 5, OBJECT_MEDKIT = 6,
+ OBJECT_LADDER = 7, OBJECT_ROPE = 8, OBJECT_KEY = 9, OBJECT_TRANSLATOR = 10, OBJECT_ALE = 11,
+ OBJECT_PAPER = 12, OBJECT_WALDOS = 13, OBJECT_STASIS_BOX2 = 14, OBJECT_RING = 15,
+ OBJECT_CLOAK = 16, OBJECT_TUNIC = 17, OBJECT_CANDLE = 18, OBJECT_STRAW = 19, OBJECT_SCIMITAR = 20,
+ OBJECT_SWORD = 21, OBJECT_HELMET = 22, OBJECT_ITEMS = 23, OBJECT_CONCENTRATOR = 24,
+ OBJECT_NULLIFIER = 25, OBJECT_PEG = 26, OBJECT_VIAL = 27, OBJECT_JACKET = 28,
+ OBJECT_TUNIC2 = 29, OBJECT_BONE = 30, OBJECT_EMPTY_JAR = 31, OBJECT_JAR = 32,
+
+ CURSOR_WALK = 0x100, CURSOR_LOOK = 0x200, CURSOR_700 = 700, CURSOR_USE = 0x400, CURSOR_TALK = 0x800,
+ CURSOR_NONE = -1, CURSOR_CROSSHAIRS = -2, CURSOR_ARROW = -3
+};
+
+class EventsClass : public SaveListener {
+private:
+ Common::Event _event;
+ uint32 _frameNumber;
+ uint32 _prevDelayFrame;
+ uint32 _priorFrameTime;
+public:
+ EventsClass();
+
+ Common::Point _mousePos;
+ CursorType _currentCursor;
+
+ void setCursor(CursorType cursorType);
+ void pushCursor(CursorType cursorType);
+ void popCursor();
+ void setCursor(Graphics::Surface &cursor, int transColor, const Common::Point &hotspot, CursorType cursorId);
+ void setCursorFromFlag();
+ CursorType getCursor() const { return _currentCursor; }
+ void showCursor();
+ void hideCursor();
+ bool isCursorVisible() const;
+
+ bool pollEvent();
+ void waitForPress(int eventMask = EVENT_BUTTON_DOWN | EVENT_KEYPRESS);
+
+ bool getEvent(Event &evt, int eventMask = ~EVENT_MOUSE_MOVE);
+ Common::Event event() { return _event; }
+ Common::EventType type() { return _event.type; }
+ uint32 getFrameNumber() const { return _frameNumber; }
+ void delay(int numFrames);
+
+ virtual void listenerSynchronise(Serialiser &s) {
+ s.syncAsUint32LE(_frameNumber);
+ s.syncAsUint32LE(_prevDelayFrame);
+ // TODO: Synchronise unknown stuff
+ }
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp
new file mode 100644
index 0000000000..10db2e9c5d
--- /dev/null
+++ b/engines/tsage/globals.cpp
@@ -0,0 +1,127 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/globals.h"
+#include "tsage/tsage.h"
+#include "tsage/ringworld_logic.h"
+
+namespace tSage {
+
+Globals *_globals = NULL;
+ResourceManager *_resourceManager = NULL;
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * Instantiates a saved object that can be instantiated
+ */
+static SavedObject *classFactoryProc(const Common::String &className) {
+ if (className == "ObjectMover") return new ObjectMover();
+ if (className == "NpcMover") return new NpcMover();
+ if (className == "ObjectMover2") return new ObjectMover2();
+ if (className == "ObjectMover3") return new ObjectMover3();
+ if (className == "PlayerMover") return new PlayerMover();
+ if (className == "SceneObjectWrapper") return new SceneObjectWrapper();
+
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+
+Globals::Globals() :
+ _dialogCenter(160, 140),
+ _gfxManagerInstance(_screenSurface) {
+ reset();
+ _stripNum = 0;
+
+ if (_vm->getFeatures() & GF_DEMO) {
+ _gfxFontNumber = 0;
+ _gfxColors.background = 6;
+ _gfxColors.foreground = 0;
+ _fontColors.background = 0;
+ _fontColors.foreground = 0;
+ _dialogCenter.y = 80;
+ } else {
+ _gfxFontNumber = 50;
+ _gfxColors.background = 53;
+ _gfxColors.foreground = 18;
+ _fontColors.background = 51;
+ _fontColors.foreground = 54;
+ }
+ _screenSurface.setScreenSurface();
+ _gfxManagers.push_back(&_gfxManagerInstance);
+
+ _sceneObjects = &_sceneObjectsInstance;
+ _sceneObjects_queue.push_front(_sceneObjects);
+
+ _prevSceneOffset = Common::Point(-1, -1);
+ _sceneListeners.push_back(&_soundHandler);
+ _sceneListeners.push_back(&_sequenceManager._soundHandler);
+
+ _scrollFollower = NULL;
+ _inventory = NULL;
+
+ if (!(_vm->getFeatures() & GF_DEMO)) {
+ _inventory = new RingworldInvObjectList();
+ _game = new RingworldGame();
+ } else {
+ _game = new RingworldDemoGame();
+ }
+}
+
+Globals::~Globals() {
+ _globals = NULL;
+}
+
+void Globals::reset() {
+ Common::set_to(&_flags[0], &_flags[MAX_FLAGS], false);
+ _saver->addFactory(classFactoryProc);
+}
+
+void Globals::synchronise(Serialiser &s) {
+ SavedObject::synchronise(s);
+ assert(_gfxManagers.size() == 1);
+
+ _sceneItems.synchronise(s);
+ SYNC_POINTER(_sceneObjects);
+ _sceneObjects_queue.synchronise(s);
+ s.syncAsSint32LE(_gfxFontNumber);
+ s.syncAsSint32LE(_gfxColors.background);
+ s.syncAsSint32LE(_gfxColors.foreground);
+ s.syncAsSint32LE(_fontColors.background);
+ s.syncAsSint32LE(_fontColors.foreground);
+
+ s.syncAsSint16LE(_dialogCenter.x); s.syncAsSint16LE(_dialogCenter.y);
+ _sceneListeners.synchronise(s);
+ for (int i = 0; i < 256; ++i)
+ s.syncAsByte(_flags[i]);
+
+ s.syncAsSint16LE(_sceneOffset.x); s.syncAsSint16LE(_sceneOffset.y);
+ s.syncAsSint16LE(_prevSceneOffset.x); s.syncAsSint16LE(_prevSceneOffset.y);
+ SYNC_POINTER(_scrollFollower);
+ s.syncAsSint32LE(_stripNum);
+}
+
+} // end of namespace tSage
diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h
new file mode 100644
index 0000000000..9e9ddd58d7
--- /dev/null
+++ b/engines/tsage/globals.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_GLOBALS_H
+#define TSAGE_GLOBALS_H
+
+#include "common/random.h"
+#include "tsage/core.h"
+#include "tsage/dialogs.h"
+#include "tsage/scenes.h"
+#include "tsage/events.h"
+#include "tsage/saveload.h"
+
+namespace tSage {
+
+class Globals : public SavedObject {
+public:
+ GfxSurface _screenSurface;
+ GfxManager _gfxManagerInstance;
+ Common::List<GfxManager *> _gfxManagers;
+ SceneHandler _sceneHandler;
+ Game *_game;
+ EventsClass _events;
+ SceneManager _sceneManager;
+ ScenePalette _scenePalette;
+ SceneRegions _sceneRegions;
+ SceneItemList _sceneItems;
+ SceneObjectList _sceneObjectsInstance;
+ SceneObjectList *_sceneObjects;
+ SynchronisedList<SceneObjectList *> _sceneObjects_queue;
+ SceneText _sceneText;
+ int _gfxFontNumber;
+ GfxColors _gfxColors;
+ GfxColors _fontColors;
+ SoundManager _soundManager;
+ Common::Point _dialogCenter;
+ WalkRegions _walkRegions;
+ SynchronisedList<EventHandler *> _sceneListeners;
+ bool _flags[256];
+ Player _player;
+ SoundHandler _soundHandler;
+ InvObjectList *_inventory;
+ Region _paneRegions[2];
+ int _paneRefreshFlag[2];
+ Common::Point _sceneOffset;
+ Common::Point _prevSceneOffset;
+ SceneObject *_scrollFollower;
+ SequenceManager _sequenceManager;
+ Common::RandomSource _randomSource;
+ int _stripNum;
+public:
+ Globals();
+ ~Globals();
+
+ void reset();
+ void setFlag(int flagNum) {
+ assert((flagNum > 0) && (flagNum < MAX_FLAGS));
+ _flags[flagNum] = true;
+ }
+ void clearFlag(int flagNum) {
+ assert((flagNum > 0) && (flagNum < MAX_FLAGS));
+ _flags[flagNum] = false;
+ }
+ bool getFlag(int flagNum) const {
+ assert((flagNum > 0) && (flagNum < MAX_FLAGS));
+ return _flags[flagNum];
+ }
+
+ GfxManager &gfxManager() { return **_gfxManagers.begin(); }
+ virtual Common::String getClassName() { return "Globals"; }
+ virtual void synchronise(Serialiser &s);
+};
+
+extern Globals *_globals;
+
+// Note: Currently this can't be part of the _globals structure, since it needs to be constructed
+// prior to many of the fields in Globals execute their constructors
+extern ResourceManager *_resourceManager;
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
new file mode 100644
index 0000000000..af38f211b2
--- /dev/null
+++ b/engines/tsage/graphics.cpp
@@ -0,0 +1,1444 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/events.h"
+#include "tsage/graphics.h"
+#include "tsage/resources.h"
+#include "tsage/tsage.h"
+#include "tsage/core.h"
+#include "common/algorithm.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+/**
+ * Creates a new graphics surface with the specified area of another surface
+ *
+ * @src Source surface
+ * @bounds Area to backup
+ */
+GfxSurface *Surface_getArea(GfxSurface &src, const Rect &bounds) {
+ assert(bounds.isValidRect());
+ GfxSurface *dest = new GfxSurface();
+ dest->create(bounds.width(), bounds.height());
+
+ Graphics::Surface srcSurface = src.lockSurface();
+ Graphics::Surface destSurface = dest->lockSurface();
+
+ byte *srcP = (byte *)srcSurface.getBasePtr(bounds.left, bounds.top);
+ byte *destP = (byte *)destSurface.getBasePtr(0, 0);
+
+ for (int y = bounds.top; y < bounds.bottom; ++y, srcP += srcSurface.pitch, destP += destSurface.pitch)
+ Common::copy(srcP, srcP + destSurface.pitch, destP);
+
+ src.unlockSurface();
+ dest->unlockSurface();
+ return dest;
+}
+
+/**
+ * Translates a raw image resource into a graphics surface. The caller is then responsible
+ * for managing and destroying the surface when done with it
+ *
+ * @imgData Raw image resource
+ * @size Size of the resource
+ */
+GfxSurface surfaceFromRes(const byte *imgData) {
+ Rect r(0, 0, READ_LE_UINT16(imgData), READ_LE_UINT16(imgData + 2));
+ GfxSurface s;
+ s.create(r.width(), r.height());
+ s._centroid.x = READ_LE_UINT16(imgData + 4);
+ s._centroid.y = READ_LE_UINT16(imgData + 6);
+ s._transColor = *(imgData + 8);
+
+ bool rleEncoded = (imgData[9] & 2) != 0;
+
+ const byte *srcP = imgData + 10;
+ Graphics::Surface destSurface = s.lockSurface();
+ byte *destP = (byte *)destSurface.getBasePtr(0, 0);
+
+ if (!rleEncoded) {
+ Common::copy(srcP, srcP + (r.width() * r.height()), destP);
+ } else {
+ Common::set_to(destP, destP + (r.width() * r.height()), s._transColor);
+
+ for (int yp = 0; yp < r.height(); ++yp) {
+ int width = r.width();
+ destP = (byte *)destSurface.getBasePtr(0, yp);
+
+ while (width > 0) {
+ uint8 controlVal = *srcP++;
+ if ((controlVal & 0x80) == 0) {
+ // Copy specified number of bytes
+
+ Common::copy(srcP, srcP + controlVal, destP);
+ width -= controlVal;
+ srcP += controlVal;
+ destP += controlVal;
+ } else if ((controlVal & 0x40) == 0) {
+ // Skip a specified number of output pixels
+ destP += controlVal & 0x3f;
+ width -= controlVal & 0x3f;
+ } else {
+ // Copy a specified pixel a given number of times
+ controlVal &= 0x3f;
+ int pixel = *srcP++;
+
+ Common::set_to(destP, destP + controlVal, pixel);
+ destP += controlVal;
+ width -= controlVal;
+ }
+ }
+ assert(width == 0);
+ }
+ }
+
+ s.unlockSurface();
+ return s;
+}
+
+GfxSurface surfaceFromRes(int resNum, int rlbNum, int subNum) {
+ uint size;
+ byte *imgData = _resourceManager->getSubResource(resNum, rlbNum, subNum, &size);
+ GfxSurface surface = surfaceFromRes(imgData);
+ DEALLOCATE(imgData);
+
+ return surface;
+}
+/*--------------------------------------------------------------------------*/
+
+void Rect::set(int16 x1, int16 y1, int16 x2, int16 y2) {
+ left = x1; top = y1;
+ right = x2; bottom = y2;
+}
+
+/**
+ * Collapses the rectangle in all four directions by the given x and y amounts
+ *
+ * @dx x amount to collapse x edges by
+ * @dy y amount to collapse y edges by
+ */
+void Rect::collapse(int dx, int dy) {
+ left += dx; right -= dx;
+ top += dy; bottom -= dy;
+}
+
+/**
+ * Centers the rectangle at a given position
+ *
+ * @xp x position for new center
+ * @yp y position for new center
+ */
+void Rect::center(int xp, int yp) {
+ moveTo(xp - (width() / 2), yp - (height() / 2));
+}
+
+/**
+ * Centers the rectangle at the center of a second passed rectangle
+ *
+ * @r Second rectangle whose center to use
+ */
+void Rect::center(const Rect &r) {
+ center(r.left + (r.width() / 2), r.top + (r.height() / 2));
+}
+
+/*
+ * Repositions the bounds if necessary so it falls entirely within the passed bounds
+ *
+ * @r The bounds the current rect should be within
+ */
+void Rect::contain(const Rect &r) {
+ if (left < r.left) translate(r.left - left, 0);
+ if (right > r.right) translate(r.right - right, 0);
+ if (top < r.top) translate(0, r.top - top);
+ if (bottom > r.bottom) translate(0, r.bottom - bottom);
+}
+
+/**
+ * Resizes and positions a given rect based on raw image data and a passed scaling percentage
+ *
+ * @frame Raw image frame
+ * @xp New x position
+ * @yp New y position
+ * @percent Scaling percentage
+ */
+void Rect::resize(const GfxSurface &surface, int xp, int yp, int percent) {
+ int xe = surface.getBounds().width() * percent / 100;
+ int ye = surface.getBounds().height() * percent / 100;
+ this->set(0, 0, xe, ye);
+
+ if (!right) ++right;
+ if (!bottom) ++bottom;
+
+ this->moveTo(xp, yp);
+
+ int xd = surface._centroid.x * percent / 100;
+ int yd = surface._centroid.y * percent / 100;
+ this->translate(-xd, -yd);
+}
+
+/**
+ * Expands the pane region to contain the specified Rect
+ */
+void Rect::expandPanes() {
+ _globals->_paneRegions[0].uniteRect(*this);
+ _globals->_paneRegions[1].uniteRect(*this);
+}
+
+/**
+ * Serialises the given rect
+ */
+void Rect::synchronise(Serialiser &s) {
+ s.syncAsSint16LE(left);
+ s.syncAsSint16LE(top);
+ s.syncAsSint16LE(right);
+ s.syncAsSint16LE(bottom);
+}
+
+/*--------------------------------------------------------------------------*/
+
+GfxSurface::GfxSurface() : _bounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) {
+ _disableUpdates = false;
+ _screenSurface = false;
+ _lockSurfaceCtr = 0;
+ _customSurface = NULL;
+ _screenSurfaceP = NULL;
+}
+
+GfxSurface::GfxSurface(const GfxSurface &s) {
+ _lockSurfaceCtr = 0;
+ _customSurface = NULL;
+ this->operator =(s);
+}
+
+GfxSurface::~GfxSurface() {
+ if (_customSurface) {
+ _customSurface->free();
+ delete _customSurface;
+ }
+}
+
+/**
+ * Specifies that the surface will encapsulate the ScummVM screen surface
+ */
+void GfxSurface::setScreenSurface() {
+ _screenSurface = true;
+ _customSurface = NULL;
+ _lockSurfaceCtr = 0;
+}
+
+/**
+ * Specifies that the surface should maintain it's own internal surface
+ */
+void GfxSurface::create(int width, int height) {
+ assert((width >= 0) && (height >= 0));
+ _screenSurface = false;
+ _customSurface = new Graphics::Surface();
+ _customSurface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ _bounds = Rect(0, 0, width, height);
+}
+
+/**
+ * Locks the surface for access, and returns a raw ScummVM surface to manipulate it
+ */
+Graphics::Surface GfxSurface::lockSurface() {
+ ++_lockSurfaceCtr;
+
+ Graphics::Surface *src;
+ if (_screenSurface) {
+ if (_lockSurfaceCtr == 1)
+ _screenSurfaceP = g_system->lockScreen();
+ src = _screenSurfaceP;
+ } else
+ src = _customSurface;
+ assert(src);
+
+ // Setup the returned surface either as one pointing to the same pixels as the source, or
+ // as a subset of the source one based on the currently set bounds
+ Graphics::Surface result;
+ result.w = _bounds.width();
+ result.h = _bounds.height();
+ result.pitch = src->pitch;
+ result.format = src->format;
+ result.pixels = src->getBasePtr(_bounds.left, _bounds.top);
+
+ return result;
+}
+
+/**
+ * Unlocks the surface after having accessed it with the lockSurface method
+ */
+void GfxSurface::unlockSurface() {
+ assert(_lockSurfaceCtr > 0);
+ --_lockSurfaceCtr;
+
+ if ((_lockSurfaceCtr == 0) && _screenSurface) {
+ g_system->unlockScreen();
+ }
+}
+
+/**
+ * Fills a specified rectangle on the surface with the specified color
+ *
+ * @bounds Area to fill
+ * @color Color to use
+ */
+void GfxSurface::fillRect(const Rect &bounds, int color) {
+ Graphics::Surface surface = lockSurface();
+ surface.fillRect(bounds, color);
+ unlockSurface();
+}
+
+GfxSurface &GfxSurface::operator=(const GfxSurface &s) {
+ assert(_lockSurfaceCtr == 0);
+ assert(s._lockSurfaceCtr == 0);
+
+ if (_customSurface) {
+ _customSurface->free();
+ delete _customSurface;
+ }
+
+ _customSurface = s._customSurface;
+ _screenSurface = s._screenSurface;
+ _disableUpdates = s._disableUpdates;
+ _bounds = s._bounds;
+ _centroid = s._centroid;
+ _transColor = s._transColor;
+
+ if (_customSurface) {
+ // Surface owns the internal data, so replicate it so new surface owns it's own
+ _customSurface = new Graphics::Surface();
+ _customSurface->create(s._customSurface->w, s._customSurface->h, Graphics::PixelFormat::createFormatCLUT8());
+ const byte *srcP = (const byte *)s._customSurface->getBasePtr(0, 0);
+ byte *destP = (byte *)_customSurface->getBasePtr(0, 0);
+
+ Common::copy(srcP, srcP + (_bounds.width() * _bounds.height()), destP);
+ }
+
+ return *this;
+}
+
+/**
+ * Displays a message on-screen until either a mouse or keypress
+ */
+bool GfxSurface::displayText(const Common::String &msg, const Common::Point &pt) {
+ // Set up a new graphics manager
+ GfxManager gfxManager;
+ gfxManager.activate();
+ gfxManager._font._colors.background = 0;
+ gfxManager._font._colors.foreground = 7;
+ gfxManager._font.setFontNumber(2);
+
+ // Get the area for text display
+ Rect textRect;
+ gfxManager.getStringBounds(msg.c_str(), textRect, 200);
+ textRect.center(pt.x, pt.y);
+
+ // Make a backup copy of the area the text will occupy
+ Rect saveRect = textRect;
+ saveRect.collapse(-20, -8);
+ GfxSurface *savedArea = Surface_getArea(gfxManager.getSurface(), saveRect);
+
+ // Display the text
+ gfxManager._font.writeLines(msg.c_str(), textRect, ALIGN_LEFT);
+
+ // Write for a mouse or keypress
+ Event event;
+ while (!_globals->_events.getEvent(event, EVENT_BUTTON_DOWN | EVENT_KEYPRESS) && !_vm->getEventManager()->shouldQuit())
+ ;
+
+ // Restore the display area
+ gfxManager.copyFrom(*savedArea, saveRect.left, saveRect.top);
+ delete savedArea;
+
+ gfxManager.deactivate();
+ return (event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_RETURN);
+}
+
+/**
+ * Loads a quarter of a screen from a resource
+ */
+void GfxSurface::loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection) {
+ int screenNum = _globals->_sceneManager._scene->_activeScreenNumber;
+ Rect updateRect(0, 0, 160, 100);
+ updateRect.translate(xHalf * 160, yHalf * 100);
+ int xHalfCount = (_globals->_sceneManager._scene->_backgroundBounds.right + 159) / 160;
+ int yHalfCount = (_globals->_sceneManager._scene->_backgroundBounds.bottom + 99) / 100;
+
+ if (xSection < xHalfCount && ySection < yHalfCount) {
+ int rlbNum = xSection * yHalfCount + ySection;
+ byte *data = _resourceManager->getResource(RES_BITMAP, screenNum, rlbNum);
+
+ for (int y = 0; y < updateRect.height(); ++y) {
+ byte *pSrc = data + y * 160;
+ byte *pDest = (byte *)dest.getBasePtr(updateRect.left, updateRect.top + y);
+
+ for (int x = 0; x < updateRect.width(); ++x, ++pSrc, ++pDest) {
+ *pDest = *pSrc;
+ }
+ }
+
+ DEALLOCATE(data);
+ }
+}
+
+/**
+ * Returns an array indicating which pixels of a source image horizontally or vertically get
+ * included in a scaled image
+ */
+static int *scaleLine(int size, int srcSize) {
+ const int PRECISION_FACTOR = 1000;
+ int scale = PRECISION_FACTOR * size / srcSize;
+ assert(scale >= 0);
+ int *v = new int[size];
+ Common::set_to(v, &v[size], -1);
+
+ int distCtr = 0;
+ int *destP = v;
+ for (int distIndex = 0; distIndex < srcSize; ++distIndex) {
+ distCtr += scale;
+ while (distCtr >= PRECISION_FACTOR) {
+ assert(destP < &v[size]);
+ *destP++ = distIndex;
+ distCtr -= PRECISION_FACTOR;
+ }
+ }
+
+ return v;
+}
+
+/**
+ * Scales a passed surface, creating a new surface with the result
+ * @param srcImage Source image to scale
+ * @param NewWidth New width for scaled image
+ * @param NewHeight New height for scaled image
+ * @remarks Caller is responsible for freeing the returned surface
+ */
+static GfxSurface ResizeSurface(GfxSurface &src, int xSize, int ySize, int transIndex) {
+ GfxSurface s;
+ s.create(xSize, ySize);
+
+ Graphics::Surface srcImage = src.lockSurface();
+ Graphics::Surface destImage = s.lockSurface();
+
+ int *horizUsage = scaleLine(xSize, srcImage.w);
+ int *vertUsage = scaleLine(ySize, srcImage.h);
+
+ // Loop to create scaled version
+ for (int yp = 0; yp < ySize; ++yp) {
+ byte *destP = (byte *)destImage.getBasePtr(0, yp);
+
+ if (vertUsage[yp] == -1) {
+ Common::set_to(destP, destP + xSize, transIndex);
+ } else {
+ const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]);
+
+ for (int xp = 0; xp < xSize; ++xp) {
+ if (horizUsage[xp] != -1) {
+ const byte *tempSrcP = srcP + horizUsage[xp];
+ *destP++ = *tempSrcP++;
+ } else {
+ // Pixel overrun at the end of the line
+ *destP++ = transIndex;
+ }
+ }
+ }
+ }
+
+ // Unlock surfaces
+ src.unlockSurface();
+ s.unlockSurface();
+
+ // Delete arrays and return surface
+ delete[] horizUsage;
+ delete[] vertUsage;
+ return s;
+}
+
+/**
+ * Copys an area from one GfxSurface to another
+ */
+void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Region *priorityRegion) {
+ GfxSurface srcImage;
+ if (srcBounds.isEmpty())
+ return;
+
+ if (srcBounds == src.getBounds())
+ srcImage = src;
+ else {
+ // Set the source image to be the subset specified by the source bounds
+ Graphics::Surface srcSurface = src.lockSurface();
+
+ srcImage.create(srcBounds.width(), srcBounds.height());
+ Graphics::Surface destSurface = srcImage.lockSurface();
+
+ const byte *srcP = (const byte *)srcSurface.getBasePtr(srcBounds.left, srcBounds.top);
+ byte *destP = (byte *)destSurface.pixels;
+ for (int yp = srcBounds.top; yp < srcBounds.bottom; ++yp, srcP += srcSurface.pitch, destP += destSurface.pitch) {
+ Common::copy(srcP, srcP + srcBounds.width(), destP);
+ }
+
+ srcImage.unlockSurface();
+ src.unlockSurface();
+ }
+
+ if ((destBounds.width() != srcBounds.width()) || (destBounds.height() != srcBounds.height()))
+ srcImage = ResizeSurface(srcImage, destBounds.width(), destBounds.height(), src._transColor);
+
+ Graphics::Surface srcSurface = srcImage.lockSurface();
+ Graphics::Surface destSurface = lockSurface();
+
+ // Adjust bounds to ensure destination will be on-screen
+ int srcX = 0, srcY = 0;
+ if (destBounds.left < 0) {
+ srcX = -destBounds.left;
+ destBounds.left = 0;
+ }
+ if (destBounds.top < 0) {
+ srcY = -destBounds.top;
+ destBounds.top = 0;
+ }
+ if (destBounds.right > destSurface.w)
+ destBounds.right = destSurface.w;
+ if (destBounds.bottom > destSurface.h)
+ destBounds.bottom = destSurface.h;
+
+ if (destBounds.isValidRect()) {
+ const byte *pSrc = (const byte *)srcSurface.getBasePtr(srcX, srcY);
+ byte *pDest = (byte *)destSurface.getBasePtr(destBounds.left, destBounds.top);
+
+ for (int y = 0; y < destBounds.height(); ++y, pSrc += srcSurface.pitch, pDest += destSurface.pitch) {
+
+ if (!priorityRegion && (src._transColor == -1))
+ Common::copy(pSrc, pSrc + destBounds.width(), pDest);
+ else {
+ const byte *tempSrc = pSrc;
+ byte *tempDest = pDest;
+ int xp = destBounds.left;
+
+ while (tempSrc < (pSrc + destBounds.width())) {
+ if (!priorityRegion || !priorityRegion->contains(Common::Point(
+ xp + _globals->_sceneManager._scene->_sceneBounds.left,
+ destBounds.top + y + _globals->_sceneManager._scene->_sceneBounds.top))) {
+ if (*tempSrc != src._transColor)
+ *tempDest = *tempSrc;
+ }
+ ++tempSrc;
+ ++tempDest;
+ ++xp;
+ }
+ }
+ }
+ }
+
+ unlockSurface();
+ srcImage.unlockSurface();
+}
+
+void GfxSurface::draw(const Common::Point &pt, Rect *rect) {
+ Rect tempRect = getBounds();
+ tempRect.translate(-_centroid.x, -_centroid.y);
+ tempRect.translate(pt.x, pt.y);
+
+ if (rect) {
+ // Only copy needed rect out without drawing
+ *rect = tempRect;
+ } else {
+ // Draw image
+ _globals->gfxManager().copyFrom(*this, tempRect, NULL);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+GfxElement::GfxElement() {
+ _owner = NULL;
+ _keycode = 0;
+ _flags = 0;
+}
+
+void GfxElement::setDefaults() {
+ _flags = 0;
+ _fontNumber = _globals->_gfxFontNumber;
+ _colors = _globals->_gfxColors;
+ _fontColors = _globals->_fontColors;
+}
+
+/**
+ * Highlights the specified graphics element
+ */
+void GfxElement::highlight() {
+ // Get a lock on the surface
+ GfxManager &gfxManager = _globals->gfxManager();
+ Graphics::Surface surface = gfxManager.lockSurface();
+
+ // Scan through the contents of the element, switching any occurances of the foreground
+ // color with the background color and vice versa
+ Rect tempRect(_bounds);
+ tempRect.collapse(2, 2);
+
+ for (int yp = tempRect.top; yp < tempRect.bottom; ++yp) {
+ byte *lineP = (byte *)surface.getBasePtr(tempRect.left, yp);
+ for (int xp = tempRect.left; xp < tempRect.right; ++xp, ++lineP) {
+ if (*lineP == _colors.background) *lineP = _colors.foreground;
+ else if (*lineP == _colors.foreground) *lineP = _colors.background;
+ }
+ }
+
+ // Release the surface
+ gfxManager.unlockSurface();
+}
+
+/**
+ * Fills the background of the specified element with a border frame
+ */
+void GfxElement::drawFrame() {
+ // Get a lock on the surface and save the active font
+ GfxManager &gfxManager = _globals->gfxManager();
+ gfxManager.lockSurface();
+
+ uint8 bgColor, fgColor;
+ if (_flags & GFXFLAG_THICK_FRAME) {
+ bgColor = 0;
+ fgColor = 0;
+ } else {
+ bgColor = _fontColors.background;
+ fgColor = _fontColors.foreground;
+ }
+
+ Rect tempRect = _bounds;
+ tempRect.collapse(3, 3);
+ tempRect.collapse(-1, -1);
+ gfxManager.fillRect(tempRect, _colors.background);
+
+ --tempRect.bottom; --tempRect.right;
+ gfxManager.fillArea(tempRect.left, tempRect.top, bgColor);
+ gfxManager.fillArea(tempRect.left, tempRect.bottom, fgColor);
+ gfxManager.fillArea(tempRect.right, tempRect.top, fgColor);
+ gfxManager.fillArea(tempRect.right, tempRect.bottom, fgColor);
+
+ tempRect.collapse(-1, -1);
+ gfxManager.fillRect2(tempRect.left + 1, tempRect.top, tempRect.width() - 1, 1, bgColor);
+ gfxManager.fillRect2(tempRect.left, tempRect.top + 1, 1, tempRect.height() - 1, bgColor);
+ gfxManager.fillRect2(tempRect.left + 1, tempRect.bottom, tempRect.width() - 1, 1, fgColor);
+ gfxManager.fillRect2(tempRect.right, tempRect.top + 1, 1, tempRect.height() - 1, fgColor);
+
+ gfxManager.fillArea(tempRect.left, tempRect.top, 0);
+ gfxManager.fillArea(tempRect.left, tempRect.bottom, 0);
+ gfxManager.fillArea(tempRect.right, tempRect.top, 0);
+ gfxManager.fillArea(tempRect.right, tempRect.bottom, 0);
+
+ tempRect.collapse(-1, -1);
+ gfxManager.fillRect2(tempRect.left + 2, tempRect.top, tempRect.width() - 3, 1, 0);
+ gfxManager.fillRect2(tempRect.left, tempRect.top + 2, 1, tempRect.height() - 3, 0);
+ gfxManager.fillRect2(tempRect.left + 2, tempRect.bottom, tempRect.width() - 3, 1, 0);
+ gfxManager.fillRect2(tempRect.right, tempRect.top + 2, 1, tempRect.height() - 3, 0);
+
+ gfxManager.unlockSurface();
+}
+
+/**
+ * Handles events when the control has focus
+ *
+ * @event Event to process
+ */
+bool GfxElement::focusedEvent(Event &event) {
+ bool highlightFlag = false;
+
+ while (!_vm->getEventManager()->shouldQuit()) {
+ g_system->delayMillis(10);
+
+ if (_bounds.contains(event.mousePos)) {
+ if (!highlightFlag) {
+ // First highlight call to show the highlight
+ highlightFlag = true;
+ highlight();
+ }
+ } else if (highlightFlag) {
+ // Mouse is outside the element, so remove the highlight
+ highlightFlag = false;
+ highlight();
+ }
+
+ if (_globals->_events.getEvent(event, EVENT_BUTTON_UP))
+ break;
+ }
+
+ if (highlightFlag) {
+ // Mouse is outside the element, so remove the highlight
+ highlight();
+ }
+
+ return highlightFlag;
+}
+
+/*--------------------------------------------------------------------------*/
+
+GfxImage::GfxImage() : GfxElement() {
+ _resNum = 0;
+ _rlbNum = 0;
+ _cursorNum = 0;
+}
+
+void GfxImage::setDetails(int resNum, int rlbNum, int cursorNum) {
+ _resNum = resNum;
+ _rlbNum = rlbNum;
+ _cursorNum = cursorNum;
+ setDefaults();
+}
+
+void GfxImage::setDefaults() {
+ GfxElement::setDefaults();
+
+ // Decode the image
+ uint size;
+ byte *imgData = _resourceManager->getSubResource(_resNum, _rlbNum, _cursorNum, &size);
+ _surface = surfaceFromRes(imgData);
+ DEALLOCATE(imgData);
+
+ // Set up the display bounds
+ Rect imgBounds = _surface.getBounds();
+ imgBounds.moveTo(_bounds.left, _bounds.top);
+ _bounds = imgBounds;
+}
+
+void GfxImage::draw() {
+ Rect tempRect = _bounds;
+ tempRect.translate(_globals->gfxManager()._topLeft.x, _globals->gfxManager()._topLeft.y);
+
+ _globals->gfxManager().copyFrom(_surface, tempRect);
+}
+
+/*--------------------------------------------------------------------------*/
+
+GfxMessage::GfxMessage() : GfxElement() {
+ _textAlign = ALIGN_LEFT;
+ _width = 0;
+}
+
+void GfxMessage::set(const Common::String &s, int width, TextAlign textAlign) {
+ _message = s;
+ _width = width;
+ _textAlign = textAlign;
+
+ setDefaults();
+}
+
+void GfxMessage::setDefaults() {
+ GfxElement::setDefaults();
+
+ GfxFontBackup font;
+ GfxManager &gfxManager = _globals->gfxManager();
+ Rect tempRect;
+
+ gfxManager._font.setFontNumber(this->_fontNumber);
+ gfxManager.getStringBounds(_message.c_str(), tempRect, _width);
+
+ tempRect.collapse(-1, -1);
+ tempRect.moveTo(_bounds.left, _bounds.top);
+ _bounds = tempRect;
+}
+
+void GfxMessage::draw() {
+ GfxFontBackup font;
+ GfxManager &gfxManager = _globals->gfxManager();
+
+ // Set the font and color
+ gfxManager.setFillFlag(false);
+ gfxManager._font.setFontNumber(_fontNumber);
+ gfxManager._font._colors.foreground = this->_colors.foreground;
+
+ // Display the text
+ gfxManager._font.writeLines(_message.c_str(), _bounds, _textAlign);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void GfxButton::setDefaults() {
+ GfxElement::setDefaults();
+
+ GfxFontBackup font;
+ GfxManager &gfxManager = _globals->gfxManager();
+ Rect tempRect;
+
+ // Get the string bounds and round up the x end to a multiple of 16
+ gfxManager._font.setFontNumber(this->_fontNumber);
+ gfxManager._font.getStringBounds(_message.c_str(), tempRect, 240);
+ tempRect.right = ((tempRect.right + 15) / 16) * 16;
+
+ // Set the button bounds to a reduced area
+ tempRect.collapse(-3, -3);
+ tempRect.moveTo(_bounds.left, _bounds.top);
+ _bounds = tempRect;
+}
+
+void GfxButton::draw() {
+ // Get a lock on the surface and save the active font
+ GfxFontBackup font;
+ GfxManager &gfxManager = _globals->gfxManager();
+ gfxManager.lockSurface();
+
+ // Draw a basic frame for the button
+ drawFrame();
+
+ // Set the font and color
+ gfxManager._font.setFontNumber(_fontNumber);
+ gfxManager._font._colors.foreground = this->_colors.foreground;
+
+ // Display the button's text
+ Rect tempRect(_bounds);
+ tempRect.collapse(3, 3);
+ gfxManager._font.writeLines(_message.c_str(), tempRect, ALIGN_CENTER);
+
+ gfxManager.unlockSurface();
+}
+
+bool GfxButton::process(Event &event) {
+ switch (event.eventType) {
+ case EVENT_BUTTON_DOWN:
+ if (!event.handled) {
+ if (_bounds.contains(event.mousePos)) {
+ bool result = focusedEvent(event);
+ event.handled = true;
+ return result;
+ }
+ }
+ break;
+
+ case EVENT_KEYPRESS:
+ if (!event.handled && (event.kbd.keycode == _keycode)) {
+ // TODO: Ensure momentary click operation displays
+ highlight();
+ g_system->delayMillis(20);
+ highlight();
+
+ event.handled = true;
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+GfxDialog::GfxDialog() {
+ _savedArea = NULL;
+ _defaultButton = NULL;
+}
+
+GfxDialog::~GfxDialog() {
+ remove();
+}
+
+void GfxDialog::setDefaults() {
+ GfxElement::setDefaults();
+
+ // Initialise the embedded graphics manager
+ _gfxManager.setDefaults();
+
+ // Figure out a rect needed for all the added elements
+ GfxElementList::iterator i;
+ Rect tempRect;
+ for (i = _elements.begin(); i != _elements.end(); ++i)
+ tempRect.extend((*i)->_bounds);
+
+ // Set the dialog boundaries
+ _gfxManager._bounds = tempRect;
+ tempRect.collapse(-6, -6);
+ _bounds = tempRect;
+}
+
+void GfxDialog::remove() {
+ if (_savedArea) {
+ // Restore the area the dialog covered
+ _globals->_gfxManagerInstance.copyFrom(*_savedArea, _bounds.left, _bounds.top);
+
+ delete _savedArea;
+ _savedArea = NULL;
+ }
+}
+
+void GfxDialog::draw() {
+ Rect tempRect(_bounds);
+
+ // Make a backup copy of the area the dialog will occupy
+ _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), _bounds);
+
+ // Set the palette for use in the dialog
+ setPalette();
+
+ _gfxManager.activate();
+
+ // Fill in the contents of the entire dialog
+ _gfxManager._bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ drawFrame();
+
+ // Reset the dialog's graphics manager to only draw within the dialog boundaries
+ tempRect.translate(6, 6);
+ _gfxManager._bounds = tempRect;
+
+ // Draw each element in the dialog in order
+ GfxElementList::iterator i;
+ for (i = _elements.begin(); i != _elements.end(); ++i) {
+ (*i)->draw();
+ }
+
+ // If there's a default button, then draw it
+ if (_defaultButton) {
+ _defaultButton->_flags |= GFXFLAG_THICK_FRAME;
+ _defaultButton->draw();
+ }
+
+ _gfxManager.deactivate();
+}
+
+void GfxDialog::add(GfxElement *element) {
+ _elements.push_back(element);
+ element->_owner = this;
+}
+
+void GfxDialog::addElements(GfxElement *ge, ...) {
+ va_list va;
+ va_start(va, ge);
+ GfxElement *gfxElement = ge;
+ while (gfxElement) {
+ add(gfxElement);
+
+ gfxElement = va_arg(va, GfxElement *);
+ }
+
+ va_end(va);
+}
+
+void GfxDialog::setTopLeft(int xp, int yp) {
+ _bounds.moveTo(xp - 6, yp - 6);
+}
+
+void GfxDialog::setCenter(int xp, int yp) {
+ setTopLeft(xp - (_bounds.width() / 2), yp - (_bounds.height() / 2));
+}
+
+GfxButton *GfxDialog::execute(GfxButton *defaultButton) {
+ _gfxManager.activate();
+
+ if (defaultButton != _defaultButton) {
+ if (_defaultButton) {
+ _defaultButton->_flags &= ~GFXFLAG_THICK_FRAME;
+ _defaultButton->draw();
+ }
+ _defaultButton = defaultButton;
+ }
+ if (_defaultButton) {
+ _defaultButton->_flags |= GFXFLAG_THICK_FRAME;
+ _defaultButton->draw();
+ }
+
+ // Event loop
+ GfxButton *selectedButton = NULL;
+
+ while (!_vm->getEventManager()->shouldQuit()) {
+ Event event;
+ while (_globals->_events.getEvent(event)) {
+ // Adjust mouse positions to be relative within the dialog
+ event.mousePos.x -= _gfxManager._bounds.left;
+ event.mousePos.y -= _gfxManager._bounds.top;
+
+ for (GfxElementList::iterator i = _elements.begin(); i != _elements.end(); ++i) {
+ if ((*i)->process(event))
+ selectedButton = static_cast<GfxButton *>(*i);
+ }
+ }
+
+ if (selectedButton)
+ break;
+ else if (!event.handled) {
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ selectedButton = NULL;
+ break;
+ } else if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_RETURN)) {
+ selectedButton = defaultButton;
+ break;
+ }
+ }
+ }
+
+ _gfxManager.deactivate();
+ if (_defaultButton)
+ _defaultButton->_flags &= ~GFXFLAG_THICK_FRAME;
+
+ return selectedButton;
+}
+
+void GfxDialog::setPalette() {
+ _globals->_scenePalette.loadPalette(0);
+ _globals->_scenePalette.setPalette(0, 1);
+ _globals->_scenePalette.setPalette(_globals->_scenePalette._colors.foreground, 1);
+ _globals->_scenePalette.setPalette(_globals->_fontColors.background, 1);
+ _globals->_scenePalette.setPalette(_globals->_fontColors.foreground, 1);
+ _globals->_scenePalette.setPalette(255, 1);
+}
+
+/*--------------------------------------------------------------------------*/
+
+GfxManager::GfxManager() : _surface(_globals->_screenSurface), _oldManager(NULL) {
+ _font.setOwner(this);
+ _font._fillFlag = false;
+ _bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+}
+
+GfxManager::GfxManager(GfxSurface &s) : _surface(s), _oldManager(NULL) {
+ _font.setOwner(this);
+ _font._fillFlag = false;
+}
+
+void GfxManager::setDefaults() {
+ Rect screenBounds(0, 0, g_system->getWidth(), g_system->getHeight());
+
+ _surface.setBounds(screenBounds);
+ _bounds = screenBounds;
+ _pane0Rect4 = screenBounds;
+
+ _font._edgeSize = Common::Point(1, 1);
+ _font._colors = _globals->_fontColors;
+ _font.setFontNumber(_globals->_gfxFontNumber);
+}
+
+void GfxManager::activate() {
+ assert(!contains(_globals->_gfxManagers, this));
+ _globals->_gfxManagers.push_front(this);
+}
+
+void GfxManager::deactivate() {
+ // Assert that there will still be another manager, and we're correctly removing our own
+ assert((_globals->_gfxManagers.size() > 1) && (&_globals->gfxManager() == this));
+ _globals->_gfxManagers.pop_front();
+}
+
+int GfxManager::getStringWidth(const char *s, int numChars) {
+ return _font.getStringWidth(s, numChars);
+}
+
+int GfxManager::getStringWidth(const char *s) {
+ return _font.getStringWidth(s);
+}
+
+void GfxManager::getStringBounds(const char *s, Rect &bounds, int maxWidth) {
+ _font.getStringBounds(s, bounds, maxWidth);
+}
+
+void GfxManager::fillArea(int xp, int yp, int color) {
+ _surface.setBounds(_bounds);
+ Rect tempRect(xp, yp, xp + _font._edgeSize.x, yp + _font._edgeSize.y);
+ _surface.fillRect(tempRect, color);
+}
+
+void GfxManager::fillRect(const Rect &bounds, int color) {
+ _surface.setBounds(_bounds);
+ _surface.fillRect(bounds, color);
+}
+
+void GfxManager::fillRect2(int xs, int ys, int width, int height, int color) {
+ _surface.setBounds(_bounds);
+ _surface.fillRect(Rect(xs, ys, xs + width, ys + height), color);
+}
+
+/**
+ * Sets up the standard palette for dialog displays
+ */
+void GfxManager::setDialogPalette() {
+ // Get the main palette information
+ byte palData[256 * 3];
+ uint count, start;
+ _resourceManager->getPalette(0, &palData[0], &start, &count);
+ g_system->getPaletteManager()->setPalette(&palData[0], start, count);
+
+ // Miscellaneous
+ uint32 white = 0xffffffff;
+ g_system->getPaletteManager()->setPalette((const byte *)&white, 255, 1);
+}
+
+/**
+ * Returns the angle of line connecting two points
+ */
+int GfxManager::getAngle(const Common::Point &p1, const Common::Point &p2) {
+ int xDiff = p2.x - p1.x, yDiff = p1.y - p2.y;
+
+ if (!xDiff && !yDiff)
+ return -1;
+ else if (!xDiff)
+ return (p2.y >= p1.y) ? 180 : 0;
+ else if (!yDiff)
+ return (p2.x >= p1.x) ? 90 : 270;
+ else {
+ int result = (((xDiff * 100) / ((abs(xDiff) + abs(yDiff))) * 90) / 100);
+
+ if (yDiff < 0)
+ result = 180 - result;
+ else if (xDiff < 0)
+ result += 360;
+
+ return result;
+ }
+}
+/*--------------------------------------------------------------------------*/
+
+
+GfxFont::GfxFont() {
+ _fontNumber = (_vm->getFeatures() & GF_DEMO) ? 0 : 50;
+ _numChars = 0;
+ _bpp = 0;
+ _fontData = NULL;
+ _fillFlag = false;
+}
+
+GfxFont::~GfxFont() {
+ DEALLOCATE(_fontData);
+}
+
+/**
+ * Sets the current active font number
+ *
+ * @fontNumber New font number
+ */
+void GfxFont::setFontNumber(uint32 fontNumber) {
+ if ((_fontNumber == fontNumber) && (_fontData))
+ return;
+
+ DEALLOCATE(_fontData);
+
+ _fontNumber = fontNumber;
+
+ _fontData = _resourceManager->getResource(RES_FONT, _fontNumber, 0, true);
+ if (!_fontData)
+ _fontData = _resourceManager->getResource(RES_FONT, _fontNumber, 0);
+
+ _numChars = READ_LE_UINT16(_fontData + 4);
+ _fontSize.y = READ_LE_UINT16(_fontData + 6);
+ _fontSize.x = READ_LE_UINT16(_fontData + 8);
+ _bpp = READ_LE_UINT16(_fontData + 10);
+}
+
+/**
+ * Returns the width of the given specified character
+ *
+ * @ch Character to return width of
+ */
+int GfxFont::getCharWidth(char ch) {
+ assert(_numChars > 0);
+ uint32 charOffset = READ_LE_UINT32(_fontData + 12 + (uint8)ch * 4);
+ return _fontData[charOffset] & 0x1f;
+}
+
+/**
+ * Returns the width of the given string in the current font
+ *
+ * @s String to return the width of
+ * @numChars Number of characters within the string to use
+ */
+int GfxFont::getStringWidth(const char *s, int numChars) {
+ assert(_numChars > 0);
+ int width = 0;
+
+ for (; numChars > 0; --numChars, ++s) {
+ uint32 charOffset = READ_LE_UINT32(_fontData + 12 + (uint8)*s * 4);
+ int charWidth = _fontData[charOffset] & 0x1f;
+
+ width += charWidth;
+ }
+
+ return width;
+}
+
+/**
+ * Returns the width of the given string in the current font
+ *
+ * @s String to return the width of
+ */
+int GfxFont::getStringWidth(const char *s) {
+ return getStringWidth(s, strlen(s));
+}
+
+/**
+ * Returns the maximum number of characters for words that will fit into a given width
+ *
+ * @s Message to be analysed
+ * @maxWidth Maximum allowed width
+ */
+int GfxFont::getStringFit(const char *&s, int maxWidth) {
+ const char *nextWord = NULL;
+ const char *sStart = s;
+ int numChars = 1;
+ int strWidth = 1;
+ char nextChar;
+
+ for (;;) {
+ nextChar = *s++;
+
+ if ((nextChar == '\r') || (nextChar == '\0'))
+ break;
+
+ // Check if it's a word end
+ if (nextChar == ' ') {
+ nextWord = s;
+ }
+
+ strWidth = getStringWidth(sStart, numChars);
+ if (strWidth > maxWidth) {
+ if (nextWord) {
+ s = nextWord;
+ nextChar = ' ';
+ }
+ break;
+ }
+
+ ++numChars;
+ }
+
+ int totalChars = s - sStart;
+ if (nextChar == '\0')
+ --s;
+ if ((nextChar == ' ') || (nextChar == '\r') || (nextChar == '\0'))
+ --totalChars;
+
+ return totalChars;
+}
+
+/**
+ * Fills out the passed rect with the dimensions of a given string word-wrapped to a
+ * maximum specified width
+ *
+ * @s Message to be analysed
+ * @bounds Rectangle to put output size into
+ * @maxWidth Maximum allowed line width in pixels
+ */
+void GfxFont::getStringBounds(const char *s, Rect &bounds, int maxWidth) {
+ if (maxWidth == 0) {
+ // No maximum width, so set bounds for a single line
+ bounds.set(0, 0, getStringWidth(s), getHeight());
+ } else {
+ int numLines = 0;
+ int lineWidth = 0;
+
+ // Loop to figure out the number of lines required, and the maximum line width
+ while (*s) {
+ const char *msg = s;
+ int numChars = getStringFit(msg, maxWidth);
+ lineWidth = MAX(lineWidth, getStringWidth(s, numChars));
+
+ s = msg;
+ ++numLines;
+ }
+
+ bounds.set(0, 0, lineWidth, numLines * getHeight());
+ }
+}
+
+/**
+ * Writes out a character at the currently set position using the active font
+ *
+ * @ch Character to display
+ */
+int GfxFont::writeChar(const char ch) {
+ assert((_fontData != NULL) && ((uint8)ch < _numChars));
+ uint32 charOffset = READ_LE_UINT32(_fontData + 12 + (uint8)ch * 4);
+ int charWidth = _fontData[charOffset] & 0x1f;
+ int charHeight = (READ_LE_UINT16(_fontData + charOffset) >> 5) & 0x3f;
+ int yOffset = (_fontData[charOffset + 1] >> 3) & 0x1f;
+ const uint8 *dataP = &_fontData[charOffset + 2];
+
+ // Lock the surface for access
+ Graphics::Surface surfacePtr = _gfxManager->lockSurface();
+
+ Rect charRect;
+ charRect.set(0, 0, charWidth, _fontSize.y);
+ charRect.translate(_topLeft.x + _position.x, _topLeft.y + _position.y + yOffset);
+
+ if (_fillFlag)
+ surfacePtr.fillRect(charRect, _colors.background);
+
+ charRect.bottom = charRect.top + charHeight;
+
+ // Display the character
+ int bitCtr = 0;
+ uint8 v = 0;
+ for (int yp = charRect.top; yp < charRect.bottom; ++yp) {
+ byte *destP = (byte *)surfacePtr.getBasePtr(charRect.left, yp);
+
+ for (int xs = 0; xs < charRect.width(); ++xs, ++destP) {
+ // Get the next color index to use
+ if ((bitCtr % 8) == 0) v = *dataP++;
+ int colIndex = 0;
+ for (int subCtr = 0; subCtr < _bpp; ++subCtr, ++bitCtr) {
+ colIndex = (colIndex << 1) | (v & 0x80 ? 1 : 0);
+ v <<= 1;
+ }
+
+ switch (colIndex) {
+ //case 0: *destP = _colors.background; break;
+ case 1: *destP = _colors.foreground; break;
+ case 2: *destP = _colors2.background; break;
+ case 3: *destP = _colors2.foreground; break;
+ }
+ }
+ }
+
+ _position.x += charWidth;
+ _gfxManager->unlockSurface();
+ return charWidth;
+}
+
+/**
+ * Writes the specified number of characters from the specified string at the current text position
+ *
+ * @s String to display
+ * @numChars Number of characters to print
+ */
+void GfxFont::writeString(const char *s, int numChars) {
+ // Lock the surface for access
+ _gfxManager->lockSurface();
+
+ while ((numChars-- > 0) && (*s != '\0')) {
+ writeChar(*s);
+ ++s;
+ }
+
+ // Release the surface lock
+ _gfxManager->unlockSurface();
+}
+
+/**
+ * Writes the the specified string at the current text position
+ *
+ * @s String to display
+ */
+void GfxFont::writeString(const char *s) {
+ writeString(s, strlen(s));
+}
+
+/**
+ * Writes a specified string within a given area with support for word wrapping and text alignment types
+ *
+ * @s String to display
+ * @bounds Bounds to display the text within
+ * @align Text alignment mode
+ */
+void GfxFont::writeLines(const char *s, const Rect &bounds, TextAlign align) {
+ int lineNum = 0;
+
+ // Lock the surface for access
+ _gfxManager->lockSurface();
+
+ while (*s) {
+ const char *msgP = s;
+ int numChars = getStringFit(msgP, bounds.width());
+
+ _position.y = bounds.top + lineNum * getHeight();
+
+ switch (align) {
+ case ALIGN_RIGHT:
+ // Right aligned text
+ _position.x = bounds.right - getStringWidth(s, numChars);
+ writeString(s, numChars);
+ break;
+
+ case ALIGN_CENTER:
+ // Center aligned text
+ _position.x = bounds.left + (bounds.width() / 2) - (getStringWidth(s, numChars) / 2);
+ writeString(s, numChars);
+ break;
+
+ case ALIGN_JUSTIFIED: {
+ // Justified text
+ // Get the number of words in the string portion
+ int charCtr = 0, numWords = 0;
+ while (charCtr < numChars) {
+ if (s[charCtr] == ' ')
+ ++numWords;
+ ++charCtr;
+ }
+ // If end of string, count final word
+ if (*msgP == '\0')
+ ++numWords;
+
+ // Display the words of the string
+ int spareWidth = bounds.width() - getStringWidth(s, numChars);
+ charCtr = 0;
+ _position.x = bounds.left;
+
+ while (charCtr < numChars) {
+ writeChar(s[charCtr]);
+ if ((numWords > 0) && (s[charCtr] == ' ')) {
+ int separationWidth = spareWidth / numWords;
+ spareWidth -= separationWidth;
+ --numWords;
+ _position.x += separationWidth;
+ }
+
+ ++charCtr;
+ }
+ break;
+ }
+
+ case ALIGN_LEFT:
+ default:
+ // Standard text
+ _position.x = bounds.left;
+ writeString(s, numChars);
+ break;
+ }
+
+ // Next line
+ s = msgP;
+ ++lineNum;
+ }
+
+ // Release the surface lock
+ _gfxManager->unlockSurface();
+}
+
+/*--------------------------------------------------------------------------*/
+
+GfxFontBackup::GfxFontBackup() {
+ _edgeSize = _globals->gfxManager()._font._edgeSize;
+ _position = _globals->gfxManager()._font._position;
+ _colors = _globals->gfxManager()._font._colors;
+ _fontNumber = _globals->gfxManager()._font._fontNumber;
+}
+
+GfxFontBackup::~GfxFontBackup() {
+ _globals->gfxManager()._font.setFontNumber(_fontNumber);
+ _globals->gfxManager()._font._edgeSize = _edgeSize;
+ _globals->gfxManager()._font._position = _position;
+ _globals->gfxManager()._font._colors = _colors;
+}
+
+
+} // End of namespace tSage
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
new file mode 100644
index 0000000000..c266d74bc5
--- /dev/null
+++ b/engines/tsage/graphics.h
@@ -0,0 +1,349 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef RING_GRAPHICS_H
+#define RING_GRAPHICS_H
+
+#include "tsage/events.h"
+#include "tsage/saveload.h"
+#include "common/list.h"
+#include "common/rect.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+
+namespace tSage {
+
+class GfxSurface;
+class Region;
+
+/**
+ * Extended Rect class with extra support methods
+ */
+class Rect : public Common::Rect, public Serialisable {
+public:
+ Rect() : Common::Rect() {};
+ Rect(int16 x1, int16 y1, int16 x2, int16 y2) : Common::Rect(x1, y1, x2, y2) {};
+
+ void set(int16 x1, int16 y1, int16 x2, int16 y2);
+ void collapse(int dx, int dy);
+ void center(int dx, int dy);
+ void center(const Rect &r);
+ void center(const Common::Point &pt) { center(pt.x, pt.y); }
+ void contain(const Rect &r);
+ void resize(const GfxSurface &surface, int xp, int yp, int percent);
+ void expandPanes();
+
+ virtual void synchronise(Serialiser &s);
+};
+
+class GfxColors {
+public:
+ uint8 foreground;
+ uint8 background;
+
+ GfxColors() : foreground(0), background(0) {};
+};
+
+class LineSlice {
+public:
+ int xs, xe;
+
+ LineSlice() { xs = 0; xe = 0; }
+ LineSlice(int xStart, int xEnd) { xs = xStart; xe = xEnd; }
+};
+
+class GfxSurface {
+private:
+ Graphics::Surface *_customSurface;
+ Graphics::Surface *_screenSurfaceP;
+ int _lockSurfaceCtr;
+ bool _screenSurface;
+
+ bool _disableUpdates;
+ Rect _bounds;
+public:
+ Common::Point _centroid;
+ int _transColor;
+public:
+ GfxSurface();
+ GfxSurface(const GfxSurface &s);
+ ~GfxSurface();
+
+ void setScreenSurface();
+ Graphics::Surface lockSurface();
+ void unlockSurface();
+ void create(int width, int height);
+ void setBounds(const Rect &bounds) { _bounds = bounds; };
+ const Rect &getBounds() const { return _bounds; };
+
+ void copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Region *priorityRegion = NULL);
+ void copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion = NULL) {
+ copyFrom(src, src.getBounds(), destBounds, priorityRegion);
+ }
+ void copyFrom(GfxSurface &src, int destX = 0, int destY = 0, Region *priorityRegion = NULL) {
+ Rect tempRect = src.getBounds();
+ tempRect.moveTo(destX, destY);
+ copyFrom(src, tempRect, priorityRegion);
+ }
+ void draw(const Common::Point &pt, Rect *rect = NULL);
+ void fillRect(const Rect &bounds, int color);
+ GfxSurface &operator=(const GfxSurface &s);
+
+ static void loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection);
+ static bool displayText(const Common::String &msg, const Common::Point &pt = Common::Point(160, 100));
+};
+
+enum TextAlign {ALIGN_LEFT = 0, ALIGN_CENTER = 1, ALIGN_RIGHT = 2, ALIGN_JUSTIFIED = 3};
+
+class GfxFont {
+ friend class GfxFontBackup;
+private:
+ GfxManager *_gfxManager;
+ // Raw font details
+ const byte *_fontData;
+ int _numChars;
+ Common::Point _fontSize;
+ int _bpp;
+public:
+ // Font fields
+ Common::Point _edgeSize;
+ Common::Point _position;
+ bool _fillFlag;
+ GfxColors _colors;
+ GfxColors _colors2;
+ uint32 _fontNumber;
+ Common::Point _topLeft;
+public:
+ GfxFont();
+ virtual ~GfxFont();
+
+ void setFontNumber(uint32 fontNumber);
+ int32 getHeight() const { return _fontSize.y; }
+ int getCharWidth(char ch);
+ int getStringWidth(const char *s, int numChars);
+ int getStringWidth(const char *s);
+ int getStringFit(const char *&s, int maxWidth);
+ void getStringBounds(const char *s, Rect &bounds, int maxWidth);
+
+ void setOwner(GfxManager *owner) { _gfxManager = owner; }
+ void setPosition(int xp, int yp) { _position.x = xp; _position.y = yp; }
+ int writeChar(const char ch);
+ void writeString(const char *s);
+ void writeString(const char *s, int numChars);
+ void writeLines(const char *s, const Rect &bounds, TextAlign align);
+};
+
+class GfxFontBackup {
+private:
+ GfxSurface *_surface;
+ Common::Point _edgeSize;
+ Common::Point _position;
+ GfxColors _colors;
+ uint32 _fontNumber;
+public:
+ GfxFontBackup();
+ ~GfxFontBackup();
+};
+
+enum GFX_FLAGS {GFXFLAG_THICK_FRAME = 8};
+
+class GfxManager;
+
+class GfxElement {
+public:
+ GfxElement *_owner;
+ Rect _bounds;
+ uint16 _flags;
+ uint16 _fontNumber;
+ GfxColors _colors;
+ GfxColors _fontColors;
+ uint16 _keycode;
+public:
+ GfxElement();
+ virtual ~GfxElement() {}
+
+ void drawFrame();
+
+ // Virtual table method
+ virtual void setDefaults();
+ virtual void remove() { _owner = NULL; }
+ virtual void highlight();
+ virtual void draw() {};
+ virtual bool process(Event &event) { return false; };
+ virtual bool focusedEvent(Event &event);
+};
+
+class GfxImage : public GfxElement {
+public:
+ GfxSurface _surface;
+ int _resNum;
+ int _rlbNum;
+ int _cursorNum;
+public:
+ GfxImage();
+
+ void setDetails(int resNum, int rlbNum, int cursorNum);
+
+ virtual void setDefaults();
+ virtual void draw();
+ virtual bool process(Event &event) { return false; }
+};
+
+class GfxMessage : public GfxElement {
+public:
+ Common::String _message;
+ TextAlign _textAlign;
+ int _width;
+public:
+ GfxMessage();
+ virtual ~GfxMessage() {}
+
+ void set(const Common::String &s, int width, TextAlign textAlign);
+
+ virtual void setDefaults();
+ virtual void draw();
+};
+
+class GfxButton : public GfxElement {
+private:
+ void setFocus();
+public:
+ Common::String _message;
+public:
+ GfxButton() : GfxElement() {};
+ virtual ~GfxButton() {}
+
+ void setText(const Common::String &s) {
+ _message = s;
+ setDefaults();
+ }
+
+ // Virtual table method
+ virtual void setDefaults();
+ virtual void draw();
+ virtual bool process(Event &event);
+};
+
+class GfxManager {
+private:
+ GfxSurface &_surface;
+public:
+ GfxManager *_oldManager;
+ Common::Point _topLeft;
+ Rect _bounds;
+ Rect _pane0Rect4;
+ GfxFont _font;
+public:
+ GfxManager();
+ GfxManager(GfxSurface &s);
+ virtual ~GfxManager() {}
+
+ void setDefaults();
+ void activate();
+ void deactivate();
+
+ // Accessor methods
+ int getStringWidth(const char *s, int numChars);
+ int getStringWidth(const char *s);
+ void getStringBounds(const char *s, Rect &bounds, int maxWidth);
+
+ void setDialogPalette();
+ Graphics::Surface lockSurface() {
+ _surface.setBounds(_bounds);
+ return _surface.lockSurface();
+ }
+ void unlockSurface() { _surface.unlockSurface(); };
+ void fillArea(int xp, int yp, int color);
+ void fillRect(const Rect &bounds, int color);
+ void fillRect2(int xs, int ys, int width, int height, int color);
+ void setFillFlag(bool v) { _font._fillFlag = v; }
+
+ static int getAngle(const Common::Point &p1, const Common::Point &p2);
+
+ // Virtual method table
+ virtual void xorArea(const Common::Rect &r, int color, int fillMode) {
+ //_surface->xorArea(r, color, fillMode);
+ }
+ virtual void draw(const Common::Rect &r, void *gfxData, int v1, GfxColors *colors) {
+ //_surface->draw(r, gfxData, v1, colors);
+ }
+ virtual void copy(const byte *src, byte *dest, int size) {
+ Common::copy(src, src + size, dest);
+ }
+ virtual void set(byte *dest, int size, byte val) {
+ Common::set_to(dest, dest + size, val);
+ }
+ void copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion = NULL) {
+ _surface.setBounds(_bounds);
+ _surface.copyFrom(src, destBounds, priorityRegion);
+ }
+ void copyFrom(GfxSurface &src, int destX, int destY) {
+ _surface.setBounds(_bounds);
+ _surface.copyFrom(src, destX, destY);
+ g_system->updateScreen();
+ }
+ GfxSurface &getSurface() {
+ _surface.setBounds(_bounds);
+ return _surface;
+ }
+};
+
+typedef Common::List<GfxElement *> GfxElementList;
+
+class GfxDialog : public GfxElement {
+public:
+ GfxManager _gfxManager;
+ GfxElementList _elements;
+ GfxButton *_defaultButton;
+ GfxSurface *_savedArea;
+public:
+ GfxDialog();
+ virtual ~GfxDialog();
+
+ void add(GfxElement *element);
+ void addElements(GfxElement *ge, ...);
+ void setTopLeft(int xp, int yp);
+ void setCenter(int xp, int yp);
+ void frame() {
+ setDefaults();
+ _bounds.collapse(6, 6);
+ }
+ GfxButton *execute(GfxButton *defaultButton = NULL);
+
+ virtual void setDefaults();
+ virtual void remove();
+ virtual void draw();
+
+ static void setPalette();
+};
+
+GfxSurface *Surface_getArea(GfxSurface &src, const Rect &bounds);
+
+GfxSurface surfaceFromRes(const byte *imgData);
+GfxSurface surfaceFromRes(int resNum, int rlbNum, int subNum);
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/module.mk b/engines/tsage/module.mk
new file mode 100644
index 0000000000..2f9194a9ba
--- /dev/null
+++ b/engines/tsage/module.mk
@@ -0,0 +1,36 @@
+MODULE := engines/tsage
+
+MODULE_OBJS := \
+ converse.o \
+ core.o \
+ debugger.o \
+ detection.o \
+ dialogs.o \
+ events.o \
+ globals.o \
+ graphics.o \
+ resources.o \
+ ringworld_demo.o \
+ ringworld_logic.o \
+ ringworld_scenes1.o \
+ ringworld_scenes2.o \
+ ringworld_scenes3.o \
+ ringworld_scenes4.o \
+ ringworld_scenes5.o \
+ ringworld_scenes6.o \
+ ringworld_scenes8.o \
+ ringworld_scenes10.o \
+ saveload.o \
+ scenes.o \
+ sound.o \
+ staticres.o \
+ tsage.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_TSAGE), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
+
diff --git a/engines/tsage/resources.cpp b/engines/tsage/resources.cpp
new file mode 100644
index 0000000000..2b678a848a
--- /dev/null
+++ b/engines/tsage/resources.cpp
@@ -0,0 +1,501 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/endian.h"
+#include "common/file.h"
+#include "common/stack.h"
+#include "common/util.h"
+#include "tsage/resources.h"
+#include "tsage/tsage.h"
+
+namespace tSage {
+
+
+MemoryManager::MemoryManager() {
+ _memoryPool = new MemoryHeader*[MEMORY_POOL_SIZE];
+ Common::set_to(&_memoryPool[0], &_memoryPool[MEMORY_POOL_SIZE], (MemoryHeader *)NULL);
+}
+
+MemoryManager::~MemoryManager() {
+ for (int i = 0; i < MEMORY_POOL_SIZE; ++i) {
+ if (_memoryPool[i] != NULL)
+ free(_memoryPool[i]);
+ }
+ delete[] _memoryPool;
+}
+
+uint16 MemoryManager::allocate(uint32 size) {
+ int idx = 0;
+ while ((idx < MEMORY_POOL_SIZE) && (_memoryPool[idx] != NULL))
+ ++idx;
+ if (idx == MEMORY_POOL_SIZE)
+ error("Out of memory handles");
+
+ // Create the new entry
+ _memoryPool[idx] = (MemoryHeader *)malloc(sizeof(MemoryHeader) + size);
+ _memoryPool[idx]->id = MEMORY_ENTRY_ID;
+ _memoryPool[idx]->index = idx;
+ _memoryPool[idx]->lockCtr = 0;
+ _memoryPool[idx]->criticalCtr = 0;
+ _memoryPool[idx]->tag = 0;
+ _memoryPool[idx]->size = size;
+
+ // Return it's index
+ return idx;
+}
+
+byte *MemoryManager::allocate2(uint32 size) {
+ uint32 idx = allocate(size);
+ return lock(idx);
+}
+
+byte *MemoryManager::lock(uint32 handle) {
+ assert((int)handle < MEMORY_POOL_SIZE);
+ return (byte *)_memoryPool[handle] + sizeof(MemoryHeader);
+}
+
+int MemoryManager::indexOf(const byte *p) {
+ for (int idx = 0; idx < MEMORY_POOL_SIZE; ++idx) {
+ if (((byte *)_memoryPool[idx] + sizeof(MemoryHeader)) == p)
+ return idx;
+ }
+
+ return -1;
+}
+
+void MemoryManager::deallocate(const byte *p) {
+ if (!p)
+ return;
+
+ int idx = indexOf(p);
+ assert(idx != -1);
+ if (_memoryPool[idx]->lockCtr-- == 0) {
+ free(_memoryPool[idx]);
+ _memoryPool[idx] = NULL;
+ }
+}
+
+uint32 MemoryManager::getSize(const byte *p) {
+ int idx = indexOf(p);
+ assert(idx >= 0);
+ return _memoryPool[idx]->size;
+}
+
+void MemoryManager::incLocks(const byte *p) {
+ int idx = indexOf(p);
+ assert(idx >= 0);
+ _memoryPool[idx]->lockCtr++;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static uint16 bitMasks[4] = {0x1ff, 0x3ff, 0x7ff, 0xfff};
+
+uint16 BitReader::readToken() {
+ assert((numBits >= 9) && (numBits <= 12));
+ uint16 result = _remainder;
+ int bitsLeft = numBits - _bitsLeft;
+ int bitOffset = _bitsLeft;
+ _bitsLeft = 0;
+
+ while (bitsLeft >= 0) {
+ _remainder = readByte();
+ result |= _remainder << bitOffset;
+ bitsLeft -= 8;
+ bitOffset += 8;
+ }
+
+ _bitsLeft = -bitsLeft;
+ _remainder >>= 8 - _bitsLeft;
+ return result & bitMasks[numBits - 9];
+}
+
+/*-------------------------------------------------------------------------*/
+
+TLib::TLib(MemoryManager &memManager, const Common::String &filename) :
+ _memoryManager(memManager) {
+
+ // If the resource strings list isn't yet loaded, load them
+ if (_resStrings.size() == 0) {
+ Common::File f;
+ if (f.open("tsage.cfg")) {
+ while (!f.eos()) {
+ _resStrings.push_back(f.readLine());
+ }
+ f.close();
+ }
+ }
+
+ if (!_file.open(filename))
+ error("Missing file %s", filename.c_str());
+
+ loadIndex();
+}
+
+TLib::~TLib() {
+ _resStrings.clear();
+}
+
+void TLib::loadSection(uint32 fileOffset) {
+ _resources.clear();
+ _file.seek(fileOffset);
+ _sections.fileOffset = fileOffset;
+
+ if (_file.readUint32BE() != 0x544D492D)
+ error("Data block is not valid Rlb data");
+
+ /*uint8 unknown1 = */_file.readByte();
+ uint16 numEntries = _file.readByte();
+
+ for (uint i = 0; i < numEntries; ++i) {
+ uint16 id = _file.readUint16LE();
+ uint16 size = _file.readUint16LE();
+ uint16 uncSize = _file.readUint16LE();
+ uint8 sizeHi = _file.readByte();
+ uint8 type = _file.readByte() >> 5;
+ assert(type <= 1);
+ uint32 offset = _file.readUint32LE();
+
+ ResourceEntry re;
+ re.id = id;
+ re.fileOffset = offset;
+ re.isCompressed = type != 0;
+ re.size = ((sizeHi & 0xF) << 16) | size;
+ re.uncompressedSize = ((sizeHi & 0xF0) << 12) | uncSize;
+
+ _resources.push_back(re);
+ }
+}
+
+struct DecodeReference {
+ uint16 vWord;
+ uint8 vByte;
+};
+
+/**
+ * Gets a resource from the currently loaded section
+ */
+byte *TLib::getResource(uint16 id, bool suppressErrors) {
+ // Scan for an entry for the given Id
+ ResourceEntry *re = NULL;
+ ResourceList::iterator iter;
+ for (iter = _resources.begin(); iter != _resources.end(); ++iter) {
+ if ((*iter).id == id) {
+ re = &(*iter);
+ break;
+ }
+ }
+ if (!re) {
+ if (suppressErrors)
+ return NULL;
+ error("Could not find resource Id #%d", id);
+ }
+
+ if (!re->isCompressed) {
+ // Read in the resource data and return it
+ byte *dataP = _memoryManager.allocate2(re->size);
+ _file.seek(_sections.fileOffset + re->fileOffset);
+ _file.read(dataP, re->size);
+
+ return dataP;
+ }
+
+ /*
+ * Decompress the data block
+ */
+
+ _file.seek(_sections.fileOffset + re->fileOffset);
+ Common::ReadStream *compStream = _file.readStream(re->size);
+ BitReader bitReader(*compStream);
+
+ byte *dataOut = _memoryManager.allocate2(re->uncompressedSize);
+ byte *destP = dataOut;
+ uint bytesWritten = 0;
+
+ uint16 ctrCurrent = 0x102, ctrMax = 0x200;
+ uint16 word_48050 = 0, currentToken = 0, word_48054 =0;
+ byte byte_49068 = 0, byte_49069 = 0;
+ DecodeReference table[0x1000];
+ for (int i = 0; i < 0x1000; ++i) {
+ table[i].vByte = table[i].vWord = 0;
+ }
+ Common::Stack<uint16> tokenList;
+
+ for (;;) {
+ // Get the next decode token
+ uint16 token = bitReader.readToken();
+
+ // Handle the token
+ if (token == 0x101) {
+ // End of compressed stream
+ break;
+ } else if (token == 0x100) {
+ // Reset bit-rate
+ bitReader.numBits = 9;
+ ctrMax = 0x200;
+ ctrCurrent = 0x102;
+
+ // Set variables with next token
+ currentToken = word_48050 = bitReader.readToken();
+ byte_49069 = byte_49068 = (byte)currentToken;
+
+ ++bytesWritten;
+ assert(bytesWritten <= re->uncompressedSize);
+ *destP++ = byte_49069;
+ } else {
+ word_48054 = word_48050 = token;
+
+ if (token >= ctrCurrent) {
+ word_48050 = currentToken;
+ tokenList.push(byte_49068);
+ }
+
+ while (word_48050 >= 0x100) {
+ assert(word_48050 < 0x1000);
+ tokenList.push(table[word_48050].vByte);
+ word_48050 = table[word_48050].vWord;
+ }
+
+ byte_49069 = byte_49068 = (byte)word_48050;
+ tokenList.push(word_48050);
+
+ // Write out any cached tokens
+ while (!tokenList.empty()) {
+ ++bytesWritten;
+ assert(bytesWritten <= re->uncompressedSize);
+ *destP++ = tokenList.pop();
+ }
+
+ assert(ctrCurrent < 0x1000);
+ table[ctrCurrent].vByte = byte_49069;
+ table[ctrCurrent].vWord = currentToken;
+ ++ctrCurrent;
+
+ currentToken = word_48054;
+ if ((ctrCurrent >= ctrMax) && (bitReader.numBits != 12)) {
+ // Move to the next higher bit-rate
+ ++bitReader.numBits;
+ ctrMax <<= 1;
+ }
+ }
+ }
+
+ assert(bytesWritten == re->uncompressedSize);
+ delete compStream;
+ return dataOut;
+}
+
+/**
+ * Finds the correct section and loads the specified resource within it
+ */
+byte *TLib::getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors) {
+ SectionList::iterator i = _sections.begin();
+ while ((i != _sections.end()) && ((*i).resType != resType || (*i).resNum != resNum))
+ ++i;
+ if (i == _sections.end()) {
+ if (suppressErrors)
+ return NULL;
+ error("Unknown resource type %d num %d", resType, resNum);
+ }
+
+ loadSection((*i).fileOffset);
+
+ return getResource(rlbNum, suppressErrors);
+}
+
+void TLib::loadIndex() {
+ uint16 resNum, configId, fileOffset;
+
+ // Load the root resources section
+ loadSection(0);
+
+ // Get the single resource from it
+ const byte *pData = getResource(0);
+ const byte *p = pData;
+
+ _sections.clear();
+
+ // Loop through reading the entries
+ while ((resNum = READ_LE_UINT16(p)) != 0xffff) {
+ configId = READ_LE_UINT16(p + 2);
+ fileOffset = READ_LE_UINT16(p + 4);
+ p += 6;
+
+ SectionEntry se;
+ se.resNum = resNum;
+ se.resType = (ResourceType)(configId & 0x1f);
+ se.fileOffset = (((configId >> 5) & 0x7ff) << 16) | fileOffset;
+
+ _sections.push_back(se);
+ }
+
+ _memoryManager.deallocate(pData);
+}
+
+/**
+ * Retrieves the specified palette resource and returns it's data
+ *
+ * @paletteNum Specefies the palette number
+ */
+bool TLib::getPalette(int paletteNum, byte *palData, uint *startNum, uint *numEntries) {
+ // Get the specified palette
+ byte *dataIn = getResource(RES_PALETTE, 0, paletteNum, true);
+ if (!dataIn)
+ return false;
+
+ *startNum = READ_LE_UINT16(dataIn);
+ *numEntries = READ_LE_UINT16(dataIn + 2);
+ assert((*startNum < 256) && ((*startNum + *numEntries) <= 256));
+
+ // Copy over the data
+ Common::copy(&dataIn[6], &dataIn[6 + *numEntries * 3], palData);
+
+ _memoryManager.deallocate(dataIn);
+ return true;
+}
+
+byte *TLib::getSubResource(int resNum, int rlbNum, int index, uint *size, bool suppressErrors) {
+ // Get the specified image set
+ byte *dataIn = getResource(RES_VISAGE, resNum, rlbNum);
+ if (!dataIn) {
+ if (suppressErrors)
+ return NULL;
+
+ error("Unknown sub resource %d/%d index %d", resNum, rlbNum, index);
+ }
+
+ int numEntries = READ_LE_UINT16(dataIn);
+ uint32 entryOffset = READ_LE_UINT32(dataIn + 2 + (index - 1) * 4);
+ uint32 nextOffset = (index == numEntries) ?
+ _memoryManager.getSize(dataIn) : READ_LE_UINT32(dataIn + 2 + index * 4);
+ *size = nextOffset - entryOffset;
+ assert(*size < (1024 * 1024));
+
+ byte *entry = _memoryManager.allocate2(*size);
+ Common::copy(&dataIn[entryOffset], &dataIn[nextOffset], entry);
+
+ _memoryManager.deallocate(dataIn);
+ return entry;
+}
+
+/**
+ * Retrieves a given message resource, and returns the specified message number
+ */
+bool TLib::getMessage(int resNum, int lineNum, Common::String &result, bool suppressErrors) {
+ byte *msgData = getResource(RES_MESSAGE, resNum, 0, true);
+ if (!msgData) {
+ if (suppressErrors)
+ return false;
+
+ error("Unknown message %d line %d", resNum, lineNum);
+ }
+
+ const char *srcP = (const char *)msgData;
+ while (lineNum-- > 0)
+ srcP += strlen(srcP) + 1;
+
+ result = Common::String(srcP);
+ _memoryManager.deallocate(msgData);
+ return true;
+}
+
+/*--------------------------------------------------------------------------*/
+
+ResourceManager::~ResourceManager() {
+ for (uint idx = 0; idx < _libList.size(); ++idx)
+ delete _libList[idx];
+}
+
+void ResourceManager::addLib(const Common::String &libName) {
+ assert(_libList.size() < 5);
+
+ _libList.push_back(new TLib(_vm->_memoryManager, libName));
+}
+
+byte *ResourceManager::getResource(uint16 id, bool suppressErrors) {
+ byte *result = NULL;
+ for (uint idx = 0; idx < _libList.size(); ++idx) {
+ result = _libList[idx]->getResource(id, true);
+ if (result)
+ return result;
+ }
+
+ if (!result && !suppressErrors)
+ error("Could not find resource Id #%d", id);
+ return NULL;
+}
+
+byte *ResourceManager::getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors) {
+ byte *result = NULL;
+ for (uint idx = 0; idx < _libList.size(); ++idx) {
+ result = _libList[idx]->getResource(resType, resNum, rlbNum, true);
+ if (result)
+ return result;
+ }
+
+ if (!result && !suppressErrors)
+ error("Unknown resource type %d num %d", resType, resNum);
+ return NULL;
+}
+
+void ResourceManager::getPalette(int paletteNum, byte *palData, uint *startNum, uint *numEntries, bool suppressErrors) {
+ for (uint idx = 0; idx < _libList.size(); ++idx) {
+ if (_libList[idx]->getPalette(paletteNum, palData, startNum, numEntries))
+ return;
+ }
+
+ if (!suppressErrors)
+ error("Unknown palette resource %d", paletteNum);
+ *numEntries = 0;
+}
+
+byte *ResourceManager::getSubResource(int resNum, int rlbNum, int index, uint *size, bool suppressErrors) {
+ byte *result = NULL;
+ for (uint idx = 0; idx < _libList.size(); ++idx) {
+ result = _libList[idx]->getSubResource(resNum, rlbNum, index, size, true);
+ if (result)
+ return result;
+ }
+
+ if (!result && !suppressErrors)
+ error("Unknown resource %d/%d index %d", resNum, rlbNum, index);
+ return NULL;
+}
+
+Common::String ResourceManager::getMessage(int resNum, int lineNum, bool suppressErrors) {
+ Common::String result;
+
+ for (uint idx = 0; idx < _libList.size(); ++idx) {
+ if (_libList[idx]->getMessage(resNum, lineNum, result, true))
+ return result;
+ }
+
+ if (!suppressErrors)
+ error("Unknown message %d line %d", resNum, lineNum);
+ return result;
+}
+
+} // end of namespace tSage
diff --git a/engines/tsage/resources.h b/engines/tsage/resources.h
new file mode 100644
index 0000000000..7b518cabd6
--- /dev/null
+++ b/engines/tsage/resources.h
@@ -0,0 +1,183 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef RING_RESOURCES_H
+#define RING_RESOURCES_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/file.h"
+#include "common/list.h"
+#include "common/str.h"
+#include "common/str-array.h"
+#include "common/textconsole.h"
+#include "common/util.h"
+#include "graphics/surface.h"
+
+namespace tSage {
+
+// Magic number used by original game to identify valid memory blocks
+const uint32 MEMORY_ENTRY_ID = 0xE11DA722;
+
+const int MEMORY_POOL_SIZE = 1000;
+
+enum ResourceType { RES_LIBRARY, RES_STRIP, RES_IMAGE, RES_PALETTE, RES_VISAGE, RES_SOUND, RES_MESSAGE,
+ RES_FONT, RES_POINTER, RES_BANK, RES_SND_DRIVER, RES_PRIORITY, RES_CONTROL, RES_WALKRGNS,
+ RES_BITMAP, RES_SAVE, RES_SEQUENCE };
+
+class MemoryHeader {
+public:
+ uint32 id;
+ int16 index;
+ int lockCtr;
+ int criticalCtr;
+ uint8 tag;
+ uint32 size;
+
+ MemoryHeader() {
+ id = 0;
+ index = 0;
+ lockCtr = 0;
+ criticalCtr = 0;
+ tag = 0;
+ size = 0;
+ }
+};
+
+class SectionEntry {
+public:
+ ResourceType resType;
+ uint16 resNum;
+ uint32 fileOffset;
+
+ SectionEntry() {
+ resType = RES_LIBRARY;
+ resNum = 0;
+ fileOffset = 0;
+ }
+};
+
+class ResourceEntry {
+public:
+ uint16 id;
+ bool isCompressed;
+ uint32 fileOffset;
+ uint32 size;
+ uint32 uncompressedSize;
+
+ ResourceEntry() {
+ id = 0;
+ isCompressed = false;
+ fileOffset = 0;
+ size = 0;
+ uncompressedSize = 0;
+ }
+};
+
+typedef Common::List<ResourceEntry> ResourceList;
+
+class SectionList : public Common::List<SectionEntry> {
+public:
+ uint32 fileOffset;
+
+ SectionList() {
+ fileOffset = 0;
+ }
+};
+
+class MemoryManager {
+private:
+ MemoryHeader **_memoryPool;
+public:
+ MemoryManager();
+ ~MemoryManager();
+
+ uint16 allocate(uint32 size);
+ byte *allocate2(uint32 size);
+ byte *lock(uint32 handle);
+ int indexOf(const byte *p);
+ void deallocate(const byte *p);
+ void deallocate(uint16 handle) { warning("TODO: MemoryManager::deallocate(handle)"); }
+ uint32 getSize(const byte *p);
+ void incLocks(const byte *p);
+};
+
+class BitReader {
+private:
+ Common::ReadStream &_stream;
+ uint8 _remainder, _bitsLeft;
+ byte readByte() { return _stream.eos() ? 0 : _stream.readByte(); }
+public:
+ BitReader(Common::ReadStream &s) : _stream(s) {
+ numBits = 9;
+ _remainder = 0;
+ _bitsLeft = 0;
+ }
+ uint16 readToken();
+
+ int numBits;
+};
+
+class TLib {
+private:
+ Common::StringArray _resStrings;
+ MemoryManager &_memoryManager;
+private:
+ Common::File _file;
+ ResourceList _resources;
+ SectionList _sections;
+
+ void loadSection(uint32 fileOffset);
+ void loadIndex();
+public:
+ TLib(MemoryManager &memManager, const Common::String &filename);
+ ~TLib();
+
+ byte *getResource(uint16 id, bool suppressErrors = false);
+ byte *getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors = false);
+ bool getPalette(int paletteNum, byte *palData, uint *startNum, uint *numEntries);
+ byte *getSubResource(int resNum, int rlbNum, int index, uint *size, bool suppressErrors = false);
+ bool getMessage(int resNum, int lineNum, Common::String &result, bool suppressErrors = false);
+};
+
+class ResourceManager {
+private:
+ Common::Array<TLib *> _libList;
+public:
+ ~ResourceManager();
+
+ void addLib(const Common::String &libName);
+
+ byte *getResource(uint16 id, bool suppressErrors = false);
+ byte *getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors = false);
+ void getPalette(int paletteNum, byte *palData, uint *startNum, uint *numEntries, bool suppressErrors = false);
+ byte *getSubResource(int resNum, int rlbNum, int index, uint *size, bool suppressErrors = false);
+ Common::String getMessage(int resNum, int lineNum, bool suppressErrors = false);
+};
+
+
+} // end of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_demo.cpp b/engines/tsage/ringworld_demo.cpp
new file mode 100644
index 0000000000..29438c0347
--- /dev/null
+++ b/engines/tsage/ringworld_demo.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/ringworld_demo.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+/*--------------------------------------------------------------------------
+ * Ringworld Demo scene
+ *
+ *--------------------------------------------------------------------------*/
+
+void RingworldDemoScene::postInit(SceneObjectList *OwnerList) {
+ signal();
+}
+
+void RingworldDemoScene::signal() {
+ _soundHandler.startSound(4);
+ _actor1.postInit();
+ _actor2.postInit();
+ _actor3.postInit();
+ _actor4.postInit();
+ _actor5.postInit();
+ _actor6.postInit();
+
+ setAction(&_sequenceManager, this, 22, &_actor1, &_actor2, &_actor3, &_actor4, &_actor5, &_actor6, NULL);
+}
+
+void RingworldDemoScene::process(Event &event) {
+
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_demo.h b/engines/tsage/ringworld_demo.h
new file mode 100644
index 0000000000..63ffe56555
--- /dev/null
+++ b/engines/tsage/ringworld_demo.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_DEMO_H
+#define TSAGE_RINGWORLD_DEMO_H
+
+#include "common/scummsys.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+
+class RingworldDemoScene: public Scene {
+public:
+ SequenceManager _sequenceManager;
+ SceneObject _actor1, _actor2, _actor3;
+ SceneObject _actor4, _actor5, _actor6;
+ SoundHandler _soundHandler;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void process(Event &event);
+ virtual void signal();
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_logic.cpp b/engines/tsage/ringworld_logic.cpp
new file mode 100644
index 0000000000..204f798f81
--- /dev/null
+++ b/engines/tsage/ringworld_logic.cpp
@@ -0,0 +1,1421 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/config-manager.h"
+#include "common/translation.h"
+#include "gui/saveload.h"
+#include "tsage/ringworld_logic.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+#include "tsage/ringworld_demo.h"
+#include "tsage/ringworld_scenes1.h"
+#include "tsage/ringworld_scenes2.h"
+#include "tsage/ringworld_scenes3.h"
+#include "tsage/ringworld_scenes4.h"
+#include "tsage/ringworld_scenes5.h"
+#include "tsage/ringworld_scenes6.h"
+#include "tsage/ringworld_scenes8.h"
+#include "tsage/ringworld_scenes10.h"
+
+namespace tSage {
+
+Scene *SceneFactory::createScene(int sceneNumber) {
+ if (_vm->getFeatures() & GF_DEMO)
+ return new RingworldDemoScene();
+
+ switch (sceneNumber) {
+ /* Scene group 1 */
+ // Kziniti Palace (Introduction)
+ case 10: return new Scene10();
+ // Outer Space (Introduction)
+ case 15: return new Scene15();
+ // Cut-scenes for Ch'mee house in distance
+ case 20: return new Scene20();
+ // Outside Ch'mee residence
+ case 30: return new Scene30();
+ // Chmeee Home
+ case 40: return new Scene40();
+ // By Flycycles
+ case 50: return new Scene50();
+ // Flycycle controls
+ case 60: return new Scene60();
+ // Shipyard Entrance
+ case 90: return new Scene90();
+ // Ship Close-up
+ case 95: return new Scene95();
+ // Sunflower navigation sequence
+ case 6100: return new Scene6100();
+
+ /* Scene group 2 */
+ // Title screen
+ case 1000: return new Scene1000();
+ // Fleeing planet cutscene
+ case 1001: return new Scene1001();
+ // Unused
+ case 1250: return new Scene1250();
+ // Ringworld Wall
+ case 1400: return new Scene1400();
+ // Ringworld Space-port
+ case 1500: return new Scene1500();
+
+ /* Scene group 3 - Part #1 */
+ // Cockpit cutscenes
+ case 2000: return new Scene2000();
+ // Starcraft - Cockpit
+ case 2100: return new Scene2100();
+ // Encyclopedia
+ case 2120: return new Scene2120();
+ // Starcraft - Level 2
+ case 2150: return new Scene2150();
+ // Starcraft - AutoDoc
+ case 2200: return new Scene2200();
+ // Stasis Field Map
+ case 2222: return new Scene2222();
+ // Starcraft - Quinn's Room
+ case 2230: return new Scene2230();
+
+ /* Scene group 3 - Part #2 */
+ // Starcraft - Storage Room
+ case 2280: return new Scene2280();
+ // Starcraft - Hanger Bay
+ case 2300: return new Scene2300();
+ // Starcraft - Copy Protection Screen
+ case 2310: return new Scene2310();
+ // Starcraft - Lander Bay
+ case 2320: return new Scene2320();
+ // Scene 2400 - Descending in Lander
+ case 2400: return new Scene2400();
+
+ /* Scene group 4 */
+ // Ringworld Scan
+ case 3500: return new Scene3500();
+ // Remote Viewer
+ case 3700: return new Scene3700();
+
+ /* Scene group 5 */
+ // Village
+ case 4000: return new Scene4000();
+ // Village - Outside Lander
+ case 4010: return new Scene4010();
+ // Village - Puzzle Board
+ case 4025: return new Scene4025();
+ // Village - Temple Antechamber
+ case 4045: return new Scene4045();
+ // Village - Temple
+ case 4050: return new Scene4050();
+ // Village - Hut
+ case 4100: return new Scene4100();
+ // Village - Bedroom
+ case 4150: return new Scene4150();
+ // Village - Near Slaver Ship
+ case 4250: return new Scene4250();
+ // Village - Slaver Ship
+ case 4300: return new Scene4300();
+ // Village - Slaver Ship Keypad
+ case 4301: return new Scene4301();
+
+ /* Scene group 6 */
+ // Caverns - Entrance
+ case 5000: return new Scene5000();
+ // Caverns
+ case 5100: return new Scene5100();
+ // Caverns - Throne-room
+ case 5200: return new Scene5200();
+ // Caverns - Pit
+ case 5300: return new Scene5300();
+
+ /* Scene group 8 */
+ // Landing near beach
+ case 7000: return new Scene7000();
+ // Underwater: swimming
+ case 7100: return new Scene7100();
+ // Underwater: Entering the cave
+ case 7200: return new Scene7200();
+ // Underwater: Lord Poria
+ case 7300: return new Scene7300();
+ // Floating Buildings: Outside
+ case 7600: return new Scene7600();
+ // Floating Buildings: In the lab
+ case 7700: return new Scene7700();
+
+ /* Scene group 10 */
+ // Near beach: Slave washing clothes
+ case 9100: return new Scene9100();
+ // Castle: Outside the bulwarks
+ case 9150: return new Scene9150();
+ // Castle: Near the fountain
+ case 9200: return new Scene9200();
+ // Castle: In front of a large guarded door
+ case 9300: return new Scene9300();
+ // Castle: In a hallway
+ case 9350: return new Scene9350();
+ // Castle: In a hallway
+ case 9360: return new Scene9360();
+ // Castle: Black-Smith room
+ case 9400: return new Scene9400();
+ // Castle: Dining room
+ case 9450: return new Scene9450();
+ // Castle: Bedroom
+ case 9500: return new Scene9500();
+ // Castle: Balcony
+ case 9700: return new Scene9700();
+ // Castle: In the garden
+ case 9750: return new Scene9750();
+ // Castle: Dressing room
+ case 9850: return new Scene9850();
+ // Ending
+ case 9900: return new Scene9900();
+ // Space travel
+ case 9999: return new Scene9999();
+
+ default:
+ error("Unknown scene number - %d", sceneNumber);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+DisplayHotspot::DisplayHotspot(int regionId, ...) {
+ _sceneRegionId = regionId;
+
+ // Load up the actions
+ va_list va;
+ va_start(va, regionId);
+
+ int param = va_arg(va, int);
+ while (param != LIST_END) {
+ _actions.push_back(param);
+ param = va_arg(va, int);
+ }
+
+ va_end(va);
+}
+
+bool DisplayHotspot::performAction(int action) {
+ for (uint i = 0; i < _actions.size(); i += 3) {
+ if (_actions[i] == action) {
+ display(_actions[i + 1], _actions[i + 2], SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+DisplayObject::DisplayObject(int firstAction, ...) {
+ // Load up the actions
+ va_list va;
+ va_start(va, firstAction);
+
+ int param = firstAction;
+ while (param != LIST_END) {
+ _actions.push_back(param);
+ param = va_arg(va, int);
+ }
+
+ va_end(va);
+}
+
+bool DisplayObject::performAction(int action) {
+ for (uint i = 0; i < _actions.size(); i += 3) {
+ if (_actions[i] == action) {
+ display(_actions[i + 1], _actions[i + 2], SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SceneArea::SceneArea() {
+ _savedArea = NULL;
+ _pt.x = _pt.y = 0;
+}
+
+SceneArea::~SceneArea() {
+ delete _savedArea;
+}
+
+void SceneArea::setup(int resNum, int rlbNum, int subNum, int actionId) {
+ _resNum = resNum;
+ _rlbNum = rlbNum;
+ _subNum = subNum;
+ _actionId = actionId;
+
+ _surface = surfaceFromRes(resNum, rlbNum, subNum);
+}
+
+void SceneArea::draw2() {
+ _surface.draw(Common::Point(_bounds.left, _bounds.top));
+}
+
+void SceneArea::display() {
+ _bounds.left = _pt.x - (_surface.getBounds().width() / 2);
+ _bounds.top = _pt.y + 1 - _surface.getBounds().height();
+ _bounds.setWidth(_surface.getBounds().width());
+ _bounds.setHeight(_surface.getBounds().height());
+
+ _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), _bounds);
+ draw2();
+}
+
+void SceneArea::restore() {
+ assert(_savedArea);
+ _savedArea->draw(Common::Point(_bounds.left, _bounds.top));
+ delete _savedArea;
+ _savedArea = NULL;
+}
+
+void SceneArea::draw(bool flag) {
+ _surface = surfaceFromRes(_resNum, _rlbNum, flag ? _subNum + 1 : _subNum);
+ _surface.draw(Common::Point(_bounds.left, _bounds.top));
+}
+
+void SceneArea::wait() {
+ // Wait until a mouse or keypress
+ Event event;
+ while (!_vm->getEventManager()->shouldQuit() && !_globals->_events.getEvent(event)) {
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+
+ SynchronisedList<SceneItem *>::iterator ii;
+ for (ii = _globals->_sceneItems.begin(); ii != _globals->_sceneItems.end(); ++ii) {
+ SceneItem *sceneItem = *ii;
+ if (sceneItem->contains(event.mousePos)) {
+ sceneItem->doAction(_actionId);
+ break;
+ }
+ }
+
+ _globals->_events.setCursor(CURSOR_ARROW);
+}
+
+void SceneArea::synchronise(Serialiser &s) {
+ SavedObject::synchronise(s);
+
+ s.syncAsSint16LE(_pt.x);
+ s.syncAsSint16LE(_pt.y);
+ s.syncAsSint32LE(_resNum);
+ s.syncAsSint32LE(_rlbNum);
+ s.syncAsSint32LE(_subNum);
+ s.syncAsSint32LE(_actionId);
+ _bounds.synchronise(s);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerGText::SpeakerGText() {
+ _speakerName = "GTEXT";
+ _textWidth = 160;
+ _textPos = Common::Point(130, 10);
+ _color1 = 42;
+ _hideObjects = false;
+}
+
+void SpeakerGText::setText(const Common::String &msg) {
+ // Set the animation properties
+ _sceneObject.postInit();
+ _sceneObject.setVisage(9405);
+ _sceneObject.setStrip2(3);
+ _sceneObject.fixPriority(255);
+ _sceneObject.changeZoom(100);
+ _sceneObject._frame = 1;
+ _sceneObject.setPosition(Common::Point(183, 71));
+ _sceneObject.animate(ANIM_MODE_7, 0, NULL);
+
+ // Set the text
+ Rect textRect;
+ _globals->gfxManager()._font.getStringBounds(msg.c_str(), textRect, _textWidth);
+ textRect.center(_sceneObject._position.x, _sceneObject._position.y);
+ _textPos.x = textRect.left;
+ Speaker::setText(msg);
+}
+
+void SpeakerGText::removeText() {
+ _sceneObject.remove();
+ Speaker::removeText();
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerPOR::SpeakerPOR() {
+ _speakerName = "POR";
+ _newSceneNumber = 7221;
+ _textPos = Common::Point(10, 30);
+ _color1 = 41;
+}
+
+void SpeakerPOR::SpeakerAction1::signal(){
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(60) + 60);
+ break;
+ case 1:
+ static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_5, this, NULL);
+ break;
+ case 2:
+ setDelay(_globals->_randomSource.getRandomNumber(10));
+ _actionIndex = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+void SpeakerPOR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(7223);
+ _object1.setStrip2(2);
+ _object1.setPosition(Common::Point(191, 166), 0);
+ _object1.animate(ANIM_MODE_7, 0, 0);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(7223);
+ _object2.setPosition(Common::Point(159, 86), 0);
+ _object2.setAction(&_speakerAction, 0);
+
+ _object3.postInit(&_objectList);
+ _object3.setVisage(7223);
+ _object3.setStrip(3);
+ _object3.setPosition(Common::Point(119, 107), 0);
+ _object3.fixPriority(199);
+ _object3.setAction(&_action2);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerOR::SpeakerOR() {
+ _speakerName = "OR";
+ _newSceneNumber = 9430;
+ _textPos = Common::Point(8, 36);
+ _color1 = 42;
+ _textWidth = 136;
+}
+
+void SpeakerOR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(9431);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(202, 147), 0);
+ _object1.animate(ANIM_MODE_7, 0, 0);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(9431);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.setZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(199, 85), 0);
+ _object2.setAction(&_speakerAction, 0);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerOText::SpeakerOText() : SpeakerGText() {
+ _speakerName = "OTEXT";
+ _textWidth = 240;
+ _textPos = Common::Point(130, 10);
+ _color1 = 42;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerQText::SpeakerQText() : ScreenSpeaker() {
+ _speakerName = "QTEXT";
+ _textPos = Common::Point(160, 40);
+ _color1 = 35;
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerSText::SpeakerSText() : ScreenSpeaker() {
+ _speakerName = "STEXT";
+ _color1 = 13;
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerPOText::SpeakerPOText() : ScreenSpeaker() {
+ _speakerName = "POTEXT";
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _color1 = 41;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerMText::SpeakerMText() {
+ _speakerName = "MTEXT";
+ _color1 = 22;
+ _textWidth = 230;
+ _textMode = ALIGN_CENTER;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerCText::SpeakerCText() {
+ _speakerName = "CTEXT";
+ _color1 = 4;
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerEText::SpeakerEText() {
+ _speakerName = "ETEXT";
+ _textPos = Common::Point(20, 20);
+ _color1 = 22;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerGR::SpeakerGR() {
+ _speakerName = "GR";
+ _newSceneNumber = 9220;
+ _textWidth = 136;
+ _textPos = Common::Point(168, 36);
+ _color1 = 14;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerHText::SpeakerHText() {
+ _speakerName = "HTEXT";
+ _textPos = Common::Point(160, 40);
+ _color1 = 52;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerSKText::SpeakerSKText() : ScreenSpeaker() {
+ _speakerName = "SKTEXT";
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _color1 = 5;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerPText::SpeakerPText() {
+ _speakerName = "PTEXT";
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _color1 = 5;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerCHFText::SpeakerCHFText() {
+ _speakerName = "CHFTEXT";
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _color1 = 56;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerCDRText::SpeakerCDRText() {
+ _speakerName = "CDRTEXT";
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _color1 = 52;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerFLText::SpeakerFLText() {
+ _speakerName = "FLTEXT";
+ _textPos = Common::Point(10, 40);
+ _color1 = 17;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerBatText::SpeakerBatText() {
+ _speakerName = "BATTEXT";
+ _textWidth = 240;
+ _textMode = ALIGN_CENTER;
+ _color1 = 3;
+ _hideObjects = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerSKL::SpeakerSKL() : AnimatedSpeaker() {
+ _speakerName = "SKL";
+ _newSceneNumber = 7011;
+ _textPos = Common::Point(10, 30);
+ _color1 = 10;
+}
+
+void SpeakerSKL::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(7013);
+ _object1.setStrip2(2);
+ _object1._frame = 1;
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1.setPosition(Common::Point(203, 120));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(7013);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(197, 80));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerQL::SpeakerQL() : AnimatedSpeaker() {
+ _speakerName = "QL";
+ _newSceneNumber = 2610;
+ _textPos = Common::Point(160, 30);
+ _color1 = 35;
+ _textMode = ALIGN_CENTER;
+}
+
+void SpeakerQL::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(2612);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(128, 146));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(2612);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(122, 84));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerSR::SpeakerSR() {
+ _speakerName = "SR";
+ _newSceneNumber = 2811;
+ _textPos = Common::Point(10, 30);
+ _color1 = 13;
+ _textMode = ALIGN_CENTER;
+}
+
+void SpeakerSR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(2813);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(224, 198));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(2813);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(203, 96));
+ _object2.setAction(&_speakerAction, NULL);
+
+ _object3.postInit(&_objectList);
+ _object3.setVisage(2813);
+ _object3.setStrip(3);
+ _object3.setPosition(Common::Point(204, 91));
+ _object3.fixPriority(199);
+ _object3._numFrames = 3;
+ _object3.animate(ANIM_MODE_7, 0, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerSL::SpeakerSL() {
+ _speakerName = "SL";
+ _newSceneNumber = 2810;
+ _textPos = Common::Point(140, 30);
+ _textWidth = 160;
+ _color1 = 13;
+ _textMode = ALIGN_CENTER;
+}
+
+void SpeakerSL::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(2812);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(95, 198));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(2812);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(116, 96));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerQR::SpeakerQR() {
+ _speakerName = "QR";
+ _newSceneNumber = 2611;
+ _textPos = Common::Point(10, 30);
+ _color1 = 13;
+ _textMode = ALIGN_CENTER;
+}
+
+void SpeakerQR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(2613);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(191, 146));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(2613);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(197, 84));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerQU::SpeakerQU() {
+ _speakerName = "QU";
+ _newSceneNumber = 7020;
+ _textPos = Common::Point(160, 30);
+ _color1 = 35;
+ _textMode = ALIGN_CENTER;
+}
+
+void SpeakerQU::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(7021);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(116, 120), 0);
+ _object1.animate(ANIM_MODE_7, 0, 0);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(7021);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(111, 84), 0);
+ _object2.setAction(&_speakerAction, 0);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerCR::SpeakerCR() {
+ _speakerName = "CR";
+ _newSceneNumber = 9010;
+ _textPos = Common::Point(20, 40);
+ _color1 = 4;
+}
+
+void SpeakerCR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(9011);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.setPosition(Common::Point(219, 168));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(9011);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.setPosition(Common::Point(232, 81));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerMR::SpeakerMR() {
+ _speakerName = "MR";
+ _newSceneNumber = 2711;
+ _textPos = Common::Point(40, 10);
+ _color1 = 22;
+}
+
+void SpeakerMR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(2713);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(220, 143));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(2713);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(215, 99));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerSAL::SpeakerSAL() {
+ _speakerName = "SAL";
+ _newSceneNumber = 2851;
+ _textPos = Common::Point(10, 30);
+ _color1 = 13;
+ _textMode = ALIGN_CENTER;
+}
+
+void SpeakerSAL::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(2853);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(185, 200));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(2853);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(170, 92));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerML::SpeakerML() {
+ _speakerName = "ML";
+ _newSceneNumber = 2710;
+ _textPos = Common::Point(160, 40);
+ _color1 = 22;
+}
+
+void SpeakerML::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(2712);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(99, 143));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(2712);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(105, 99));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerCHFL::SpeakerCHFL() {
+ _speakerName = "CHFL";
+ _newSceneNumber = 4111;
+ _textPos = Common::Point(10, 40);
+ _color1 = 56;
+}
+
+void SpeakerCHFL::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(4113);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(205, 116));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(4113);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(202, 71));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerCHFR::SpeakerCHFR() {
+ _speakerName = "CHFR";
+ _newSceneNumber = 4110;
+ _textPos = Common::Point(160, 40);
+ _color1 = 56;
+}
+
+void SpeakerCHFR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(4112);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(103, 116));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(4112);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(106, 71));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerPL::SpeakerPL() {
+ _speakerName = "PL";
+ _newSceneNumber = 4060;
+ _textPos = Common::Point(160, 40);
+ _color1 = 5;
+}
+
+void SpeakerPL::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(4062);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(107, 117));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(4062);
+ _object2.setStrip2(1);
+ _object2.fixPriority(200);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(105, 62));
+ _object2.setAction(&_speakerAction, NULL);
+
+ _object3.postInit(&_objectList);
+ _object3.setVisage(4062);
+ _object3.setStrip2(3);
+ _object3.fixPriority(255);
+ _object3._frame = 1;
+ _object3.setPosition(Common::Point(105, 59));
+ _object3.setAction(&_speakerAction2, NULL);
+
+ Speaker::setText(msg);
+}
+
+void SpeakerPL::removeText() {
+ _object3.remove();
+ AnimatedSpeaker::removeText();
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerPR::SpeakerPR() {
+ _speakerName = "PR";
+ _newSceneNumber = 4061;
+ _textPos = Common::Point(10, 40);
+ _color1 = 5;
+}
+
+void SpeakerPR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(4063);
+ _object1.setStrip2(1);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(212, 117));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(4063);
+ _object2.setStrip2(2);
+ _object2.fixPriority(200);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(214, 62));
+ _object2.setAction(&_speakerAction, NULL);
+
+ _object3.postInit(&_objectList);
+ _object3.setVisage(4063);
+ _object3.setStrip2(3);
+ _object3.fixPriority(255);
+ _object3.changeZoom(100);
+ _object3._frame = 1;
+ _object3.setPosition(Common::Point(214, 59));
+ _object3.setAction(&_speakerAction2, NULL);
+
+ Speaker::setText(msg);
+}
+
+void SpeakerPR::removeText() {
+ _object3.remove();
+ AnimatedSpeaker::removeText();
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerCDR::SpeakerCDR() {
+ _speakerName = "CDR";
+ _newSceneNumber = 4161;
+ _textPos = Common::Point(10, 40);
+ _color1 = 52;
+}
+
+void SpeakerCDR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(4163);
+ _object1.setStrip2(1);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(208, 97));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(4163);
+ _object2.setStrip2(2);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(200, 57));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerCDL::SpeakerCDL() {
+ _speakerName = "CDL";
+ _newSceneNumber = 4160;
+ _textPos = Common::Point(160, 40);
+ _color1 = 52;
+}
+
+void SpeakerCDL::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(4162);
+ _object1.setStrip2(1);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(112, 97));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(4162);
+ _object2.setStrip2(2);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(115, 57));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerFLL::SpeakerFLL() {
+ _speakerName = "FLL";
+ _newSceneNumber = 5221;
+ _textPos = Common::Point(10, 40);
+ _color1 = 17;
+}
+
+void SpeakerFLL::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(5223);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(216, 129));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(5223);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(210, 67));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerBatR::SpeakerBatR() {
+ _speakerName = "BATR";
+ _newSceneNumber = 5360;
+ _textPos = Common::Point(140, 40);
+ _color1 = 3;
+}
+
+void SpeakerBatR::setText(const Common::String &msg) {
+ _object1.postInit(&_objectList);
+ _object1.setVisage(5361);
+ _object1.setStrip2(2);
+ _object1.fixPriority(255);
+ _object1.changeZoom(100);
+ _object1._frame = 1;
+ _object1.setPosition(Common::Point(137, 122));
+ _object1.animate(ANIM_MODE_7, 0, NULL);
+
+ _object2.postInit(&_objectList);
+ _object2.setVisage(5361);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object2.changeZoom(100);
+ _object2._frame = 1;
+ _object2.setPosition(Common::Point(137, 104));
+ _object2.setAction(&_speakerAction, NULL);
+
+ Speaker::setText(msg);
+}
+
+/*--------------------------------------------------------------------------*/
+
+RingworldInvObjectList::RingworldInvObjectList() :
+ _stunner(2280, 1, 2, OBJECT_STUNNER, "This is your stunner."),
+ _scanner(1, 1, 3, OBJECT_SCANNER, "A combination scanner comm unit."),
+ _stasisBox(5200, 1, 4, OBJECT_STASIS_BOX, "A stasis box."),
+ _infoDisk(40, 1, 1, OBJECT_INFODISK, "The infodisk you took from the assassin."),
+ _stasisNegator(0, 2, 2, OBJECT_STASIS_NEGATOR, "The stasis field negator."),
+ _keyDevice(4250, 1, 6, OBJECT_KEY_DEVICE, "A magnetic key device."),
+ _medkit(2280, 1, 7, OBJECT_MEDKIT, "Your medkit."),
+ _ladder(4100, 1, 8, OBJECT_LADDER, "The chief's ladder."),
+ _rope(4150, 1, 9, OBJECT_ROPE, "The chief's rope."),
+ _key(7700, 1, 11, OBJECT_KEY, "A key."),
+ _translator(7700, 1, 13, OBJECT_TRANSLATOR, "The dolphin translator box."),
+ _ale(2150, 1, 10, OBJECT_ALE, "A bottle of ale."),
+ _paper(7700, 1, 12, OBJECT_PAPER, "A slip of paper with the numbers 2,4, and 3 written on it."),
+ _waldos(0, 1, 14, OBJECT_WALDOS, "A pair of waldos from the ruined probe."),
+ _stasisBox2(8100, 1, 4, OBJECT_STASIS_BOX2, "A stasis box."),
+ _ring(8100, 2, 5, OBJECT_RING, "This is a signet ring sent to you by Louis Wu."),
+ _cloak(9850, 2, 6, OBJECT_CLOAK, "A fine silk cloak."),
+ _tunic(9450, 2, 7, OBJECT_TUNIC, "The patriarch's soiled tunic."),
+ _candle(9500, 2, 8, OBJECT_CANDLE, "A tallow candle."),
+ _straw(9400, 2, 9, OBJECT_STRAW, "Clean, dry straw."),
+ _scimitar(9850, 1, 18, OBJECT_SCIMITAR, "A scimitar from the Patriarch's closet."),
+ _sword(9850, 1, 17, OBJECT_SWORD, "A short sword from the Patriarch's closet."),
+ _helmet(9500, 2, 4, OBJECT_HELMET, "Some type of helmet."),
+ _items(4300, 2, 10, OBJECT_ITEMS, "Two interesting items from the Tnuctipun vessel."),
+ _concentrator(4300, 2, 11, OBJECT_CONCENTRATOR, "The Tnuctipun anti-matter concentrator contained in a stasis field."),
+ _nullifier(5200, 2, 12, OBJECT_NULLIFIER, "A purported neural wave nullifier."),
+ _peg(4045, 2, 16, OBJECT_PEG, "A peg with a symbol."),
+ _vial(5100, 2, 17, OBJECT_VIAL, "A vial of the bat creatures anti-pheromone drug."),
+ _jacket(9850, 3, 1, OBJECT_JACKET, "A natty padded jacket."),
+ _tunic2(9850, 3, 2, OBJECT_TUNIC2, "A very hairy tunic."),
+ _bone(5300, 3, 5, OBJECT_BONE, "A very sharp bone."),
+ _jar(7700, 3, 4, OBJECT_JAR, "An jar filled with a green substance."),
+ _emptyJar(7700, 3, 3, OBJECT_EMPTY_JAR, "An empty jar.") {
+
+ // Add the items to the list
+ _itemList.push_back(&_stunner);
+ _itemList.push_back(&_scanner);
+ _itemList.push_back(&_stasisBox);
+ _itemList.push_back(&_infoDisk);
+ _itemList.push_back(&_stasisNegator);
+ _itemList.push_back(&_keyDevice);
+ _itemList.push_back(&_medkit);
+ _itemList.push_back(&_ladder);
+ _itemList.push_back(&_rope);
+ _itemList.push_back(&_key);
+ _itemList.push_back(&_translator);
+ _itemList.push_back(&_ale);
+ _itemList.push_back(&_paper);
+ _itemList.push_back(&_waldos);
+ _itemList.push_back(&_stasisBox2);
+ _itemList.push_back(&_ring);
+ _itemList.push_back(&_cloak);
+ _itemList.push_back(&_tunic);
+ _itemList.push_back(&_candle);
+ _itemList.push_back(&_straw);
+ _itemList.push_back(&_scimitar);
+ _itemList.push_back(&_sword);
+ _itemList.push_back(&_helmet);
+ _itemList.push_back(&_items);
+ _itemList.push_back(&_concentrator);
+ _itemList.push_back(&_nullifier);
+ _itemList.push_back(&_peg);
+ _itemList.push_back(&_vial);
+ _itemList.push_back(&_jacket);
+ _itemList.push_back(&_tunic2);
+ _itemList.push_back(&_bone);
+ _itemList.push_back(&_jar);
+ _itemList.push_back(&_emptyJar);
+
+ _selectedItem = NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void RingworldGame::restartGame() {
+ if (MessageDialog::show(RESTART_MSG, CANCEL_BTN_STRING, RESTART_BTN_STRING) == 1)
+ _globals->_game->restart();
+}
+
+void RingworldGame::saveGame() {
+ if (_globals->getFlag(50))
+ MessageDialog::show(SAVING_NOT_ALLOWED_MSG, OK_BTN_STRING);
+ else {
+ // Show the save dialog
+ handleSaveLoad(true, _globals->_sceneHandler._saveGameSlot, _globals->_sceneHandler._saveName);
+ }
+}
+
+void RingworldGame::restoreGame() {
+ if (_globals->getFlag(50))
+ MessageDialog::show(RESTORING_NOT_ALLOWED_MSG, OK_BTN_STRING);
+ else {
+ // Show the load dialog
+ handleSaveLoad(false, _globals->_sceneHandler._loadGameSlot, _globals->_sceneHandler._saveName);
+ }
+}
+
+void RingworldGame::quitGame() {
+ if (MessageDialog::show(QUIT_CONFIRM_MSG, CANCEL_BTN_STRING, QUIT_BTN_STRING) == 1)
+ _vm->quitGame();
+}
+
+void RingworldGame::handleSaveLoad(bool saveFlag, int &saveSlot, Common::String &saveName) {
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(_vm->getGameId(), &plugin);
+ GUI::SaveLoadChooser *dialog;
+ if (saveFlag)
+ dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"));
+ else
+ dialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"));
+
+ dialog->setSaveMode(saveFlag);
+
+ saveSlot = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+ saveName = dialog->getResultString();
+
+ delete dialog;
+}
+
+void RingworldGame::start() {
+ // Set some default flags and cursor
+ _globals->setFlag(12);
+ _globals->setFlag(34);
+ _globals->_events.setCursor(CURSOR_WALK);
+
+ // Set the screen to scroll in response to the player moving off-screen
+ _globals->_scrollFollower = &_globals->_player;
+
+ // Set the object's that will be in the player's inventory by default
+ RING_INVENTORY._stunner._sceneNumber = 1;
+ RING_INVENTORY._scanner._sceneNumber = 1;
+ RING_INVENTORY._ring._sceneNumber = 1;
+
+ // Switch to the title screen
+ _globals->_sceneManager.setNewScene(1000);
+
+ _globals->_events.showCursor();
+}
+
+void RingworldGame::restart() {
+ _globals->_scenePalette.clearListeners();
+ _globals->_soundHandler.proc3();
+
+ // Reset the flags
+ _globals->reset();
+ _globals->setFlag(34);
+
+ // Clear save/load slots
+ _globals->_sceneHandler._saveGameSlot = -1;
+ _globals->_sceneHandler._loadGameSlot = -1;
+
+ _globals->_stripNum = 0;
+ _globals->_events.setCursor(CURSOR_WALK);
+
+ // Reset item properties
+ RING_INVENTORY._stunner._sceneNumber = 1;
+ RING_INVENTORY._scanner._sceneNumber = 1;
+ RING_INVENTORY._stasisBox._sceneNumber = 5200;
+ RING_INVENTORY._infoDisk._sceneNumber = 40;
+ RING_INVENTORY._stasisNegator._sceneNumber = 0;
+ RING_INVENTORY._keyDevice._sceneNumber = 0;
+ RING_INVENTORY._medkit._sceneNumber = 2280;
+ RING_INVENTORY._ladder._sceneNumber = 4100;
+ RING_INVENTORY._rope._sceneNumber = 4150;
+ RING_INVENTORY._key._sceneNumber = 7700;
+ RING_INVENTORY._translator._sceneNumber = 2150;
+ RING_INVENTORY._paper._sceneNumber = 7700;
+ RING_INVENTORY._waldos._sceneNumber = 0;
+ RING_INVENTORY._ring._sceneNumber = 1;
+ RING_INVENTORY._stasisBox2._sceneNumber = 8100;
+ RING_INVENTORY._cloak._sceneNumber = 9850;
+ RING_INVENTORY._tunic._sceneNumber = 9450;
+ RING_INVENTORY._candle._sceneNumber = 9500;
+ RING_INVENTORY._straw._sceneNumber = 9400;
+ RING_INVENTORY._scimitar._sceneNumber = 9850;
+ RING_INVENTORY._sword._sceneNumber = 9850;
+ RING_INVENTORY._helmet._sceneNumber = 9500;
+ RING_INVENTORY._items._sceneNumber = 4300;
+ RING_INVENTORY._concentrator._sceneNumber = 4300;
+ RING_INVENTORY._nullifier._sceneNumber = 4300;
+ RING_INVENTORY._peg._sceneNumber = 4045;
+ RING_INVENTORY._vial._sceneNumber = 5100;
+ RING_INVENTORY._jacket._sceneNumber = 9850;
+ RING_INVENTORY._tunic2._sceneNumber = 9850;
+ RING_INVENTORY._bone._sceneNumber = 5300;
+ RING_INVENTORY._jar._sceneNumber = 7700;
+ RING_INVENTORY._emptyJar._sceneNumber = 7700;
+ RING_INVENTORY._selectedItem = NULL;
+
+ // Change to the first game scene
+ _globals->_sceneManager.changeScene(30);
+}
+
+void RingworldGame::endGame(int resNum, int lineNum) {
+ _globals->_events.setCursor(CURSOR_WALK);
+ Common::String msg = _resourceManager->getMessage(resNum, lineNum);
+ bool savesExist = _saver->savegamesExist();
+
+ if (!savesExist) {
+ // No savegames exist, so prompt the user to restart or quit
+ if (MessageDialog::show(msg, QUIT_BTN_STRING, RESTART_BTN_STRING) == 0)
+ _vm->quitGame();
+ else
+ restart();
+ } else {
+ // Savegames exist, so prompt for Restore/Restart
+ bool breakFlag;
+ do {
+ if (MessageDialog::show(msg, RESTART_BTN_STRING, RESTORE_BTN_STRING) == 0) {
+ breakFlag = true;
+ } else {
+ handleSaveLoad(false, _globals->_sceneHandler._loadGameSlot, _globals->_sceneHandler._saveName);
+ breakFlag = _globals->_sceneHandler._loadGameSlot > 0;
+ }
+ } while (!breakFlag);
+ }
+
+ _globals->_events.setCursorFromFlag();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void RingworldDemoGame::start() {
+ // Start the demo's single scene
+ _globals->_sceneManager.changeScene(1);
+
+ _globals->_events.setCursor(CURSOR_NONE);
+}
+
+void RingworldDemoGame::restart() {
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_logic.h b/engines/tsage/ringworld_logic.h
new file mode 100644
index 0000000000..eb395d59b8
--- /dev/null
+++ b/engines/tsage/ringworld_logic.h
@@ -0,0 +1,473 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_LOGIC_H
+#define TSAGE_RINGWORLD_LOGIC_H
+
+#include "common/scummsys.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+#define ADD_PLAYER_MOVER(X, Y) { Common::Point pt(X, Y); PlayerMover *mover = new PlayerMover(); \
+ _globals->_player.addMover(mover, &pt, this); }
+#define ADD_PLAYER_MOVER_NULL(OBJ, X, Y) { Common::Point pt(X, Y); PlayerMover *mover = new PlayerMover(); \
+ OBJ.addMover(mover, &pt, NULL); }
+#define ADD_PLAYER_MOVER_THIS(OBJ, X, Y) { Common::Point pt(X, Y); PlayerMover *mover = new PlayerMover(); \
+ OBJ.addMover(mover, &pt, this); }
+
+#define ADD_MOVER(OBJ, X, Y) { Common::Point pt(X, Y); NpcMover *mover = new NpcMover(); \
+ OBJ.addMover(mover, &pt, this); }
+#define ADD_MOVER_NULL(OBJ, X, Y) { Common::Point pt(X, Y); NpcMover *mover = new NpcMover(); \
+ OBJ.addMover(mover, &pt, NULL); }
+
+
+class SceneFactory {
+public:
+ static Scene *createScene(int sceneNumber);
+};
+
+class DisplayHotspot : public SceneObject {
+private:
+ Common::Array<int> _actions;
+ bool performAction(int action);
+public:
+ DisplayHotspot(int regionId, ...);
+
+ virtual void doAction(int action) {
+ if (!performAction(action))
+ SceneHotspot::doAction(action);
+ }
+};
+
+class DisplayObject : public SceneObject {
+private:
+ Common::Array<int> _actions;
+ bool performAction(int action);
+public:
+ DisplayObject(int firstAction, ...);
+
+ virtual void doAction(int action) {
+ if (!performAction(action))
+ SceneHotspot::doAction(action);
+ }
+};
+
+class SceneArea : public SavedObject {
+public:
+ GfxSurface _surface;
+ GfxSurface *_savedArea;
+ Common::Point _pt;
+ int _resNum;
+ int _rlbNum;
+ int _subNum;
+ int _actionId;
+ Rect _bounds;
+public:
+ SceneArea();
+ ~SceneArea();
+
+ void setup(int resNum, int rlbNum, int subNum, int actionId);
+ void draw2();
+ void display();
+ void restore();
+
+ virtual void synchronise(Serialiser &s);
+ virtual void draw(bool flag);
+ virtual void wait();
+};
+
+/*--------------------------------------------------------------------------*/
+// Ringworld specific game speakers
+
+class SpeakerGText : public Speaker {
+public:
+ SceneObject _sceneObject;
+public:
+ SpeakerGText();
+
+ virtual Common::String getClassName() { return "SpeakerGText"; }
+ virtual void setText(const Common::String &msg);
+ virtual void removeText();
+};
+
+class SpeakerPOR : public AnimatedSpeaker {
+ class SpeakerAction1 : public SpeakerAction {
+ public:
+ virtual void signal();
+ };
+
+public:
+ SceneObject _object3;
+ SpeakerAction1 _action2;
+public:
+ SpeakerPOR();
+ virtual Common::String getClassName() { return "SpeakerPOR"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerOR : public AnimatedSpeaker {
+public:
+ SpeakerOR();
+ virtual Common::String getClassName() { return "SpeakerOR"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerOText : public SpeakerGText {
+public:
+ SpeakerOText();
+
+ virtual Common::String getClassName() { return "SpeakerOText"; }
+};
+
+class SpeakerPOText : public ScreenSpeaker {
+public:
+ SpeakerPOText();
+
+ virtual Common::String getClassName() { return "SpeakerPOText"; }
+};
+
+class SpeakerSText : public ScreenSpeaker {
+public:
+ SpeakerSText();
+
+ virtual Common::String getClassName() { return "SpeakerSText"; }
+};
+
+class SpeakerQText : public ScreenSpeaker {
+public:
+ SpeakerQText();
+
+ virtual Common::String getClassName() { return "SpeakerQText"; }
+};
+
+class SpeakerMText : public ScreenSpeaker {
+public:
+ SpeakerMText();
+
+ virtual Common::String getClassName() { return "SpeakerMText"; }
+};
+
+class SpeakerCText : public ScreenSpeaker {
+public:
+ SpeakerCText();
+
+ virtual Common::String getClassName() { return "SpeakerCText"; }
+};
+
+class SpeakerEText : public ScreenSpeaker {
+public:
+ SpeakerEText();
+
+ virtual Common::String getClassName() { return "SpeakerEText"; }
+};
+
+class SpeakerGR : public AnimatedSpeaker {
+public:
+ SpeakerGR();
+
+ virtual Common::String getClassName() { return "SpeakerGR"; }
+};
+
+class SpeakerHText : public ScreenSpeaker {
+public:
+ SpeakerHText();
+
+ virtual Common::String getClassName() { return "SpeakerHText"; }
+};
+
+class SpeakerPText : public ScreenSpeaker {
+public:
+ SpeakerPText();
+
+ virtual Common::String getClassName() { return "SpeakerPText"; }
+};
+
+class SpeakerCHFText : public ScreenSpeaker {
+public:
+ SpeakerCHFText();
+
+ virtual Common::String getClassName() { return "SpeakerCHFText"; }
+};
+
+class SpeakerSKText : public ScreenSpeaker {
+public:
+ SpeakerSKText();
+
+ virtual Common::String getClassName() { return "SpeakerSKText"; }
+};
+
+class SpeakerCDRText : public ScreenSpeaker {
+public:
+ SpeakerCDRText();
+
+ virtual Common::String getClassName() { return "SpeakerCDRText"; }
+};
+
+class SpeakerFLText : public ScreenSpeaker {
+public:
+ SpeakerFLText();
+
+ virtual Common::String getClassName() { return "SpeakerFLText"; }
+};
+
+class SpeakerBatText : public ScreenSpeaker {
+public:
+ SpeakerBatText();
+
+ virtual Common::String getClassName() { return "SpeakerFLText"; }
+};
+
+class SpeakerQR : public AnimatedSpeaker {
+public:
+ SpeakerQR();
+
+ virtual Common::String getClassName() { return "SpeakerQR"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerQU : public AnimatedSpeaker {
+public:
+ SpeakerQU();
+
+ virtual Common::String getClassName() { return "SpeakerQU"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerSKL : public AnimatedSpeaker {
+public:
+ SpeakerSKL();
+
+ virtual Common::String getClassName() { return "SpeakerQL"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerQL : public AnimatedSpeaker {
+public:
+ SpeakerQL();
+
+ virtual Common::String getClassName() { return "SpeakerQL"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerSR : public AnimatedSpeaker {
+public:
+ SceneObject _object3;
+public:
+ SpeakerSR();
+
+ virtual Common::String getClassName() { return "SpeakerSR"; }
+ void setText(const Common::String &msg);
+};
+
+class SpeakerSL : public AnimatedSpeaker {
+public:
+ SpeakerSL();
+
+ virtual Common::String getClassName() { return "SpeakerSL"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerCR : public AnimatedSpeaker {
+public:
+ SpeakerCR();
+
+ virtual Common::String getClassName() { return "SpeakerCR"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerMR : public AnimatedSpeaker {
+public:
+ SpeakerMR();
+
+ virtual Common::String getClassName() { return "SpeakerMR"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerSAL : public AnimatedSpeaker {
+public:
+ SpeakerSAL();
+
+ virtual Common::String getClassName() { return "SpeakerSAL"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerML : public AnimatedSpeaker {
+public:
+ SpeakerML();
+
+ virtual Common::String getClassName() { return "SpeakerML"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerCHFL : public AnimatedSpeaker {
+public:
+ SpeakerCHFL();
+
+ virtual Common::String getClassName() { return "SpeakerCHFL"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerCHFR : public AnimatedSpeaker {
+public:
+ SpeakerCHFR();
+
+ virtual Common::String getClassName() { return "SpeakerCHFR"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerPL : public AnimatedSpeaker {
+public:
+ SceneObject _object3;
+ SpeakerAction _speakerAction2;
+
+ SpeakerPL();
+
+ virtual Common::String getClassName() { return "SpeakerPL"; }
+ virtual void setText(const Common::String &msg);
+ virtual void removeText();
+};
+
+class SpeakerPR : public AnimatedSpeaker {
+public:
+ SceneObject _object3;
+ SpeakerAction _speakerAction2;
+
+ SpeakerPR();
+
+ virtual Common::String getClassName() { return "SpeakerPR"; }
+ virtual void setText(const Common::String &msg);
+ virtual void removeText();
+};
+
+class SpeakerCDR : public AnimatedSpeaker {
+public:
+ SpeakerCDR();
+
+ virtual Common::String getClassName() { return "SpeakerCDR"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerCDL : public AnimatedSpeaker {
+public:
+ SpeakerCDL();
+
+ virtual Common::String getClassName() { return "SpeakerCDL"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerFLL : public AnimatedSpeaker {
+public:
+ SpeakerFLL();
+
+ virtual Common::String getClassName() { return "SpeakerFLL"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerBatR : public AnimatedSpeaker {
+public:
+ SpeakerBatR();
+
+ virtual Common::String getClassName() { return "SpeakerBatR"; }
+ virtual void setText(const Common::String &msg);
+};
+
+/*--------------------------------------------------------------------------*/
+
+class RingworldInvObjectList : public InvObjectList {
+public:
+ InvObject _stunner;
+ InvObject _scanner;
+ InvObject _stasisBox;
+ InvObject _infoDisk;
+ InvObject _stasisNegator;
+ InvObject _keyDevice;
+ InvObject _medkit;
+ InvObject _ladder;
+ InvObject _rope;
+ InvObject _key;
+ InvObject _translator;
+ InvObject _ale;
+ InvObject _paper;
+ InvObject _waldos;
+ InvObject _stasisBox2;
+ InvObject _ring;
+ InvObject _cloak;
+ InvObject _tunic;
+ InvObject _candle;
+ InvObject _straw;
+ InvObject _scimitar;
+ InvObject _sword;
+ InvObject _helmet;
+ InvObject _items;
+ InvObject _concentrator;
+ InvObject _nullifier;
+ InvObject _peg;
+ InvObject _vial;
+ InvObject _jacket;
+ InvObject _tunic2;
+ InvObject _bone;
+ InvObject _jar;
+ InvObject _emptyJar;
+public:
+ RingworldInvObjectList();
+
+ virtual Common::String getClassName() { return "RingworldInvObjectList"; }
+};
+
+#define RING_INVENTORY (*((RingworldInvObjectList *)_globals->_inventory))
+
+class RingworldGame: public Game {
+protected:
+ virtual void handleSaveLoad(bool saveFlag, int &saveSlot, Common::String &saveName);
+public:
+ virtual void start();
+ virtual void restart();
+ virtual void restartGame();
+ virtual void saveGame();
+ virtual void restoreGame();
+ virtual void quitGame();
+ virtual void endGame(int resNum, int lineNum);
+};
+
+class RingworldDemoGame: public Game {
+protected:
+ virtual void restart();
+public:
+ virtual void start();
+ virtual void restartGame() {}
+ virtual void saveGame() {}
+ virtual void restoreGame() {}
+ virtual void quitGame() {}
+ virtual void endGame(int resNum, int lineNum) {}
+};
+
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_scenes1.cpp b/engines/tsage/ringworld_scenes1.cpp
new file mode 100644
index 0000000000..9811cd52d3
--- /dev/null
+++ b/engines/tsage/ringworld_scenes1.cpp
@@ -0,0 +1,3302 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/ringworld_scenes1.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+/*--------------------------------------------------------------------------
+ * Scene 10 - Kziniti Palace (Introduction)
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene10::Action1::signal() {
+ Scene10 *scene = (Scene10 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(6);
+ break;
+ case 1:
+ _globals->_scenePalette.addRotation(240, 254, -1);
+ scene->_stripManager.start(10, this);
+ break;
+ case 2:
+ scene->_speakerSText.setTextPos(Common::Point(20, 20));
+ scene->_speakerSText._color1 = 10;
+ scene->_speakerSText._textWidth = 160;
+ scene->_stripManager.start(11, this, scene);
+ break;
+ case 3:
+ scene->_object2.hide();
+ scene->_object3.hide();
+ scene->_object3.setAction(NULL);
+ scene->_object4.animate(ANIM_MODE_5, this);
+ break;
+ case 4:
+ case 9:
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 5:
+ scene->_object2.setStrip(3);
+ scene->_object2.setFrame(1);
+ scene->_object2.setPosition(Common::Point(240, 51));
+ scene->_object2.show();
+
+ scene->_object3.setStrip(6);
+ scene->_object3.setFrame(1);
+ scene->_object3.setPosition(Common::Point(200, 76));
+ scene->_object3._numFrames = 20;
+ scene->_object3.show();
+
+ scene->_stripManager.start(12, this, scene);
+ break;
+ case 6:
+ scene->_object2.hide();
+ scene->_object3.hide();
+ scene->_object1.animate(ANIM_MODE_6, this);
+ break;
+ case 7:
+ scene->_object3.show();
+ scene->_object3.setStrip2(5);
+ scene->_object3._numFrames = 10;
+ scene->_object3.setPosition(Common::Point(180, 87));
+ scene->_object3.setAction(&scene->_action2);
+
+ scene->_object2.setStrip(4);
+ scene->_object2.setFrame(1);
+ scene->_object2.setPosition(Common::Point(204, 59));
+ scene->_object2.show();
+
+ scene->_stripManager.start(13, this, scene);
+ break;
+ case 8:
+ scene->_object2.hide();
+ scene->_object3.hide();
+ scene->_object4.animate(ANIM_MODE_6, this);
+ break;
+ case 10:
+ _globals->_soundHandler.proc1(this);
+ break;
+ case 11:
+ _globals->_scenePalette.clearListeners();
+ _globals->_sceneManager.changeScene(15);
+ break;
+ }
+}
+
+void Scene10::Action2::signal() {
+ Scene10 *scene = (Scene10 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(179));
+ break;
+ case 1:
+ scene->_object3.setFrame(1);
+ scene->_object3.animate(ANIM_MODE_5, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene10::postInit(SceneObjectList *OwnerList) {
+ loadScene(10);
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _speakerSText._speakerName = "STEXT";
+ _speakerQText._speakerName = "QTEXT";
+ _speakerSText._hideObjects = false;
+ _speakerQText._hideObjects = false;
+ _speakerQText.setTextPos(Common::Point(140, 120));
+ _speakerQText._color1 = 4;
+ _speakerQText._textWidth = 160;
+ _speakerSText.setTextPos(Common::Point(20, 20));
+ _speakerSText._color1 = 7;
+ _speakerSText._textWidth = 320;
+
+ _stripManager.setCallback(this);
+
+ _object1.postInit();
+ _object1.setVisage(10);
+ _object1.setPosition(Common::Point(232, 90));
+ _object1.fixPriority(1);
+
+ _object2.postInit();
+ _object2.setVisage(10);
+ _object2.setStrip(4);
+ _object2.setFrame(1);
+ _object2.setPosition(Common::Point(204, 59));
+ _object2.fixPriority(198);
+
+ _object3.postInit();
+ _object3.setVisage(10);
+ _object3.setStrip2(5);
+ _object3.setPosition(Common::Point(180, 87));
+ _object3.fixPriority(196);
+ _object3.setAction(&_action2);
+
+ _object4.postInit();
+ _object4.setVisage(10);
+ _object4.setStrip(2);
+ _object4.setPosition(Common::Point(0, 209));
+ _object4.animate(ANIM_MODE_1, NULL);
+
+ _object5.postInit();
+ _object5.setVisage(11);
+ _object5.setPosition(Common::Point(107, 146));
+ _object5.animate(ANIM_MODE_2, NULL);
+ _object5._numFrames = 5;
+
+ _object6.postInit();
+ _object6.setVisage(11);
+ _object6.setStrip(2);
+ _object6.setPosition(Common::Point(287, 149));
+ _object6.animate(ANIM_MODE_2, NULL);
+ _object6._numFrames = 5;
+
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+
+ setAction(&_action1);
+ _globals->_soundHandler.startSound(5);
+}
+
+void Scene10::stripCallback(int v) {
+ switch (v) {
+ case 1:
+ _object2.animate(ANIM_MODE_7, -1, NULL);
+ break;
+ case 2:
+ _object2.animate(ANIM_MODE_NONE);
+ break;
+ case 3:
+ _object2.animate(ANIM_MODE_7, -1, NULL);
+ _object3.animate(ANIM_MODE_5, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 15 - Outer Space (Introduction)
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene15::Action1::signal() {
+ Scene15 *scene = (Scene15 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ SceneItem::display(15, 0, SET_Y, 20, SET_FONT, 2, SET_BG_COLOR, -1, SET_EXT_BGCOLOR, 7,
+ SET_WIDTH, 320, SET_KEEP_ONSCREEN, 1, LIST_END);
+ setDelay(300);
+ break;
+ case 2: {
+ SceneItem::display(15, 1, SET_Y, 20, SET_FONT, 2, SET_BG_COLOR, -1, SET_EXT_BGCOLOR, 7,
+ SET_WIDTH, 320, SET_KEEP_ONSCREEN, 1, LIST_END);
+ scene->_object1.postInit();
+ scene->_object1.setVisage(15);
+ scene->_object1.setPosition(Common::Point(160, -10));
+ scene->_object1.animate(ANIM_MODE_2, NULL);
+ Common::Point pt(160, 100);
+ NpcMover *mover = new NpcMover();
+ scene->_object1.addMover(mover, &pt, this);
+ scene->_soundHandler.startSound(7);
+ break;
+ }
+ case 3:
+ SceneItem::display(0, 0);
+ _globals->_sceneManager.changeScene(20);
+ break;
+ }
+}
+
+void Scene15::Action1::dispatch() {
+ Scene15 *scene = (Scene15 *)_globals->_sceneManager._scene;
+
+ if (scene->_object1._position.y < 100)
+ scene->_object1.changeZoom(100 - scene->_object1._position.y);
+ Action::dispatch();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene15::postInit(SceneObjectList *OwnerList) {
+ loadScene(15);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+ _globals->_soundHandler.startSound(6);
+ setAction(&_action1);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 20 - Cut-scenes where House Chmeee is in the distance
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene20::Action1::signal() {
+ Scene20 *scene = (Scene20 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(120);
+ break;
+ case 1:
+ scene->_stripManager.start(20, this);
+ break;
+ case 2:
+ _globals->_soundHandler.proc1(this);
+ break;
+ case 3:
+ _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL;
+ _globals->_sceneManager.changeScene(30); // First game scene
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene20::Action2::signal() {
+ Scene20 *scene = (Scene20 *)_globals->_sceneManager._scene;
+ NpcMover *npcMover;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ SceneItem::display(20, 1, SET_WIDTH, 200, SET_Y, 20, SET_X, 160, SET_KEEP_ONSCREEN, true,
+ SET_EXT_BGCOLOR, 4, LIST_END);
+ setDelay(120);
+ break;
+ case 2: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(455, 77);
+ _globals->_player.addMover(mover, &pt, this);
+ ObjectMover2 *mover2 = new ObjectMover2();
+ scene->_SceneObjectExt.addMover(mover2, 5, 10, &_globals->_player);
+ ObjectMover2 *mover3 = new ObjectMover2();
+ scene->_sceneObject3.addMover(mover3, 10, 15, &_globals->_player);
+ break;
+ }
+ case 3: {
+ npcMover = new NpcMover();
+ Common::Point pt(557, 100);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 4: {
+ npcMover = new NpcMover();
+ Common::Point pt(602, 90);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 5: {
+ npcMover = new NpcMover();
+ Common::Point pt(618, 90);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 6: {
+ npcMover = new NpcMover();
+ Common::Point pt(615, 81);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 7: {
+ npcMover = new NpcMover();
+ Common::Point pt(588, 79);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 8:
+ scene->_sound.proc4();
+ scene->_sound.proc1(this);
+ break;
+ case 9:
+ SceneItem::display(0, 0, LIST_END);
+ _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL;
+ _globals->_sceneManager.changeScene(40);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene20::Action3::signal() {
+ Scene20 *scene = (Scene20 *)_globals->_sceneManager._scene;
+ NpcMover *npcMover;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(120);
+ break;
+ case 1: {
+ npcMover = new NpcMover();
+ Common::Point pt(615, 81);
+ _globals->_player.addMover(npcMover, &pt, this);
+ ObjectMover2 *mover1 = new ObjectMover2();
+ scene->_SceneObjectExt.addMover(mover1, 5, 10, &_globals->_player);
+ ObjectMover2 *mover2 = new ObjectMover2();
+ scene->_sceneObject3.addMover(mover2, 20, 25, &_globals->_player);
+ break;
+ }
+ case 2: {
+ npcMover = new NpcMover();
+ Common::Point pt(618, 90);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 3: {
+ _globals->_player._moveDiff = Common::Point(10, 10);
+ scene->_SceneObjectExt._moveDiff = Common::Point(10, 10);
+ scene->_sceneObject3._moveDiff = Common::Point(10, 10);
+ npcMover = new NpcMover();
+ Common::Point pt(445, 132);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 4: {
+ npcMover = new NpcMover();
+ Common::Point pt(151, 137);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 5: {
+ npcMover = new NpcMover();
+ Common::Point pt(-15, 137);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 6:
+ scene->_sound.startSound(60, this, 127);
+ _globals->_soundHandler.proc4();
+ break;
+ case 7:
+ _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL;
+ _globals->_sceneManager.changeScene(90);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene20::Action4::signal() {
+ Scene20 *scene = (Scene20 *)_globals->_sceneManager._scene;
+ NpcMover *npcMover;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1: {
+ npcMover = new NpcMover();
+ Common::Point pt(486, 134);
+ _globals->_player.addMover(npcMover, &pt, this);
+ ObjectMover2 *mover1 = new ObjectMover2();
+ scene->_SceneObjectExt.addMover(mover1, 20, 35, &_globals->_player);
+ break;
+ }
+ case 2: {
+ _globals->_player._moveDiff = Common::Point(12, 12);
+ scene->_SceneObjectExt._moveDiff = Common::Point(12, 12);
+ NpcMover *mover1 = new NpcMover();
+ Common::Point pt(486, 134);
+ scene->_sceneObject3.addMover(mover1, &pt, this);
+ NpcMover *mover2 = new NpcMover();
+ pt = Common::Point(-15, 134);
+ _globals->_player.addMover(mover2, &pt, NULL);
+ NpcMover *mover3 = new NpcMover();
+ pt = Common::Point(-15, 134);
+ scene->_SceneObjectExt.addMover(mover3, &pt, NULL);
+ break;
+ }
+ case 3: {
+ scene->_sceneObject3._moveDiff = Common::Point(20, 20);
+ npcMover = new NpcMover();
+ Common::Point pt(320, 134);
+ scene->_sceneObject3.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 4: {
+ scene->_sound.startSound(28);
+ scene->_sceneObject4.postInit();
+ scene->_sceneObject4.setVisage(21);
+ scene->_sceneObject4.setStrip(3);
+ scene->_sceneObject4.setPosition(Common::Point(scene->_sceneObject3._position.x - 36,
+ scene->_sceneObject3._position.y - 1));
+ scene->_sceneObject4._moveDiff.x = 48;
+
+ ObjectMover3 *mover = new ObjectMover3();
+ scene->_sceneObject4.addMover(mover, &scene->_SceneObjectExt, 4, this);
+ break;
+ }
+ case 5: {
+ scene->_sound.startSound(42);
+ scene->_sceneObject4.remove();
+ scene->_SceneObjectExt.setVisage(21);
+ scene->_SceneObjectExt.setStrip(1);
+ scene->_SceneObjectExt.setFrame(1);
+ scene->_SceneObjectExt.animate(ANIM_MODE_5, NULL);
+
+ scene->_SceneObjectExt._moveDiff.x = 4;
+ NpcMover *mover1 = new NpcMover();
+ Common::Point pt(scene->_SceneObjectExt._position.x - 12, scene->_SceneObjectExt._position.y + 5);
+ scene->_SceneObjectExt.addMover(mover1, &pt, NULL);
+
+ scene->_sceneObject5.postInit();
+ scene->_sceneObject5.setVisage(21);
+ scene->_sceneObject5.setStrip(3);
+ scene->_sceneObject5.setPosition(Common::Point(scene->_sceneObject3._position.x - 36,
+ scene->_sceneObject3._position.y - 1));
+ scene->_sceneObject5._moveDiff.x = 48;
+
+ ObjectMover3 *mover = new ObjectMover3();
+ scene->_sceneObject5.addMover(mover, &_globals->_player, 4, this);
+ break;
+ }
+ case 6: {
+ scene->_sound.startSound(42);
+ scene->_SceneObjectExt.setStrip(2);
+ scene->_SceneObjectExt.animate(ANIM_MODE_2, NULL);
+
+ scene->_sceneObject5.remove();
+ _globals->_player.setVisage(21);
+ _globals->_player.setStrip(1);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ _globals->_player._moveDiff.x = 4;
+
+ npcMover = new NpcMover();
+ Common::Point pt(_globals->_player._position.x - 25, _globals->_player._position.y + 5);
+ _globals->_player.addMover(npcMover, &pt, this);
+ break;
+ }
+ case 7:
+ _globals->_player.setStrip(2);
+ _globals->_player.animate(ANIM_MODE_2, NULL);
+ scene->_sound.startSound(77, this, 127);
+ break;
+ case 8:
+ _globals->_game->endGame(20, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene20::Scene20() {
+}
+
+void Scene20::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerGameText);
+ _speakerQText._npc = &_globals->_player;
+
+ if (_globals->_sceneManager._previousScene == 30) {
+ // Cut scene: Assassins are coming
+ _globals->_player.postInit();
+ _globals->_player.setVisage(20);
+ _globals->_player.setPosition(Common::Point(405, 69));
+ _globals->_player._moveDiff = Common::Point(10, 10);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ _SceneObjectExt.postInit();
+ _SceneObjectExt.setVisage(20);
+ _SceneObjectExt.setPosition(Common::Point(400, 69));
+ _SceneObjectExt.animate(ANIM_MODE_1, NULL);
+
+ _sceneObject3.postInit();
+ _sceneObject3.setVisage(20);
+ _sceneObject3.setPosition(Common::Point(395, 69));
+ _sceneObject3.animate(ANIM_MODE_1, NULL);
+
+ _SceneObjectExt._moveDiff = Common::Point(10, 10);
+ _sceneObject3._moveDiff = Common::Point(10, 10);
+ _globals->_soundHandler.startSound(20);
+ _sound.startSound(21);
+ _sound.proc5(1);
+ setAction(&_action2);
+
+ _sceneBounds = Rect(320, 0, 640, 200);
+ } else if (_globals->_sceneManager._previousScene == 60) {
+ // Evasion
+ _sound.startSound(30);
+ _globals->_player.postInit();
+ _globals->_player.setVisage(20);
+ _globals->_player.setPosition(Common::Point(588, 79));
+ _globals->_player._moveDiff = Common::Point(5, 5);
+ _globals->_player.fixPriority(50);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ _SceneObjectExt.postInit();
+ _SceneObjectExt.setVisage(20);
+ _SceneObjectExt.setPosition(Common::Point(583, 79));
+ _SceneObjectExt.animate(ANIM_MODE_1, NULL);
+
+ _sceneObject3.postInit();
+ _sceneObject3.setVisage(20);
+ _sceneObject3.setStrip2(2);
+ _sceneObject3.setPosition(Common::Point(595, 79));
+ _sceneObject3.animate(ANIM_MODE_1, NULL);
+
+ if ((_globals->getFlag(120) && _globals->getFlag(116)) ||
+ (_globals->getFlag(117) && _globals->getFlag(119))) {
+ // Successful evasion
+ setAction(&_action3);
+ } else if (_globals->getFlag(104)) {
+ _sceneMode = 21;
+ setAction(&_sequenceManager, this, 21, &_globals->_player, &_SceneObjectExt, NULL);
+ } else {
+ // Failed evasion
+ _sceneObject3._moveDiff = Common::Point(8, 8);
+ setAction(&_action4);
+ }
+ _sceneBounds.center(_globals->_player._position.x, _globals->_player._position.y);
+ } else {
+ // Intro: Quinn looking at the monaster
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2640);
+ _globals->_player.animate(ANIM_MODE_NONE, NULL);
+ _globals->_player.setStrip2(1);
+ _globals->_player.setFrame2(4);
+ _globals->_player.fixPriority(200);
+ _globals->_player.setPosition(Common::Point(425, 233));
+
+ setAction(&_action1);
+ _speakerQText.setTextPos(Common::Point(350, 20));
+ _speakerQText._textWidth = 260;
+ _speakerGameText.setTextPos(Common::Point(350, 20));
+ _speakerGameText._textWidth = 260;
+
+ _globals->_soundHandler.startSound(8);
+ _sceneBounds = Rect(320, 0, 640, 200);
+ }
+
+ _globals->_player.disableControl();
+ loadScene(20);
+}
+
+void Scene20::signal() {
+ if (_sceneMode == 21)
+ _globals->_sceneManager.changeScene(90);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 30 - First game scene (Outside Ch'mee house)
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene30::BeamObject::doAction(int action) {
+ if (action == OBJECT_SCANNER)
+ display2(30, 14);
+ else if (action == CURSOR_LOOK)
+ display2(30, 2);
+ else if (action == CURSOR_USE) {
+ Scene30 *parent = (Scene30 *)_globals->_sceneManager._scene;
+ parent->setAction(&parent->_beamAction);
+ } else
+ SceneObject::doAction(action);
+}
+
+void Scene30::DoorObject::doAction(int action) {
+ if (action == OBJECT_SCANNER)
+ display2(30, 13);
+ else if (action == CURSOR_LOOK)
+ display2(30, 1);
+ else if (action == CURSOR_USE)
+ display2(30, 7);
+ else
+ SceneObject::doAction(action);
+}
+
+void Scene30::BeamAction::signal() {
+ Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ // Disable control and move player to the doorway beam
+ _globals->_player.disableControl();
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(114, 198);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+
+ case 1:
+ // Perform the animation of player raising hand
+ _globals->_player.setVisage(31);
+ _globals->_player.setStrip(1);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+
+ case 2:
+ // Hide the beam and lower the player's hand
+ scene->_sound.startSound(10, NULL, 127);
+ _globals->_player.animate(ANIM_MODE_6, this);
+ scene->_beam.remove();
+ break;
+
+ case 3: {
+ // Bring the Kzin to the doorway
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip(7);
+ scene->_kzin.postInit();
+ scene->_kzin.setVisage(2801);
+ scene->_kzin.animate(ANIM_MODE_1, NULL);
+ scene->_kzin.setObjectWrapper(new SceneObjectWrapper());
+ scene->_kzin.setPosition(Common::Point(334, 1));
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(158, 170);
+ scene->_kzin.addMover(mover, &pt, this);
+ _globals->_sceneItems.push_front(&scene->_kzin);
+ break;
+ }
+
+ case 4:
+ // Open the door
+ scene->_sound.startSound(11, NULL, 127);
+ scene->_door.animate(ANIM_MODE_5, this);
+ break;
+
+ case 5:
+ // Run the Kzin's talk sequence
+ scene->_sound.startSound(13, NULL, 127);
+ _globals->_soundHandler.startSound(12, NULL, 127);
+ scene->_stripManager.start((scene->_sceneMode == 0) ? 30 : 37, this);
+ break;
+
+ case 6:
+ // Slight delay
+ setDelay(3);
+ break;
+
+ case 7:
+ // Re-activate player control
+ scene->_sceneMode = 31;
+ scene->_kzin.setAction(&scene->_kzinAction);
+ _globals->_player.enableControl();
+
+ // End this action
+ remove();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene30::KzinAction::signal() {
+ Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1200);
+ break;
+ case 1:
+ _globals->_soundHandler.proc2(0);
+ _globals->_player.disableControl();
+ setAction(&scene->_sequenceManager, _globals->_sceneManager._scene, 31, &scene->_kzin, &scene->_door, NULL);
+ break;
+ case 2:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene30::RingAction::signal() {
+ Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ scene->_kzin.setAction(NULL);
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(114, 198);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+
+ case 1:
+ _globals->_player.checkAngle(&scene->_kzin);
+ scene->_stripManager.start(32, this);
+ break;
+
+ case 2: {
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(143, 177);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+
+ case 3:
+ scene->_sound.startSound(11, NULL, 127);
+ scene->_door.animate(ANIM_MODE_6, this);
+ break;
+
+ case 4: {
+ scene->_sound.startSound(13, NULL, 127);
+ NpcMover *kzinMover = new NpcMover();
+ Common::Point pt(354, 5);
+ scene->_kzin.addMover(kzinMover, &pt, this);
+ NpcMover *playerMover = new NpcMover();
+ pt = Common::Point(335, 36);
+ _globals->_player.addMover(playerMover, &pt, this);
+ break;
+ }
+
+ case 5:
+ break;
+
+ case 6:
+ _globals->_sceneManager.changeScene(20);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Scene30::TalkAction::signal() {
+ Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ scene->_kzin.setAction(NULL);
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(114, 198);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ _globals->_player.checkAngle(&scene->_kzin);
+ scene->_stripManager.start(34, this);
+ break;
+ case 2:
+ setDelay(5);
+ break;
+ case 3:
+ scene->_kzin.setAction(&scene->_kzinAction);
+ _globals->_player.enableControl();
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene30::KzinObject::doAction(int action) {
+ Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ display2(30, 12);
+ break;
+ case OBJECT_SCANNER:
+ display2(30, 11);
+ break;
+ case OBJECT_RING:
+ RING_INVENTORY._ring._sceneNumber = 30;
+ scene->setAction(&scene->_ringAction);
+ break;
+ case CURSOR_LOOK:
+ display2(30, 6);
+ break;
+ case CURSOR_USE:
+ display2(30, 10);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_talkAction);
+ break;
+ default:
+ SceneObject::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene30::Scene30() :
+ _groundHotspot(9, OBJECT_SCANNER, 50, 17, CURSOR_LOOK, 30, 3, CURSOR_USE, 30, 8, LIST_END),
+ _wallsHotspot(8, OBJECT_SCANNER, 50, 13, CURSOR_LOOK, 30, 0, CURSOR_USE, 30, 7, LIST_END),
+ _courtyardHotspot(0, CURSOR_LOOK, 30, 4, LIST_END),
+ _treeHotspot(10, OBJECT_SCANNER, 40, 39, CURSOR_LOOK, 30, 5, CURSOR_USE, 30, 9, LIST_END) {
+}
+
+void Scene30::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ // Add the speaker classes to the strip manager
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerSR);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _speakerSText._npc = &_kzin;
+ _speakerQText._npc = &_globals->_player;
+
+
+ // Setup player
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setStrip(7);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(114, 198));
+ _globals->_player.changeZoom(75);
+ _globals->_player.enableControl();
+
+ // Set up beam object
+ _beam.postInit();
+ _beam.setVisage(31);
+ _beam.setStrip(2);
+ _beam.setPosition(Common::Point(124, 178));
+ _beam.fixPriority(188);
+
+ // Set up door object
+ _door.postInit();
+ _door.setVisage(30);
+ _door.setPosition(Common::Point(150, 183));
+
+ // Final processing and add of scene items
+ _courtyardHotspot.setBounds(Rect(0, 0, 320, 200));
+
+ // Add the objects and hotspots to the scene
+ _globals->_sceneItems.addItems(&_beam, &_wallsHotspot, &_door, &_treeHotspot, &_groundHotspot,
+ &_courtyardHotspot, NULL);
+
+ // Load the scene data
+ loadScene(30);
+ _sceneMode = 0;
+}
+
+void Scene30::signal() {
+ if (_sceneMode == 31) {
+ // Re-activate beam if the Kzin goes back inside
+ _beam.postInit();
+ _beam.setVisage(31);
+ _beam.setStrip(2);
+ _beam.setPosition(Common::Point(124, 178));
+ _beam.fixPriority(188);
+ _globals->_sceneItems.push_front(&_beam);
+ _globals->_player.enableControl();
+ } else if (_sceneMode == 32) {
+ _globals->_player.disableControl();
+ _sceneMode = 31;
+ setAction(&_sequenceManager, _globals->_sceneManager._scene, 31, &_kzin, &_door, NULL);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 40 - Chmeee Home
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene40::Action1::signal() {
+ Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(120);
+ break;
+ case 1:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(40, this);
+ break;
+ case 2:
+ scene->_doorway.postInit();
+ scene->_doorway.setVisage(46);
+ scene->_doorway.setPosition(Common::Point(305, 61));
+ scene->_doorway.animate(ANIM_MODE_5, this);
+ scene->_soundHandler.startSound(25);
+ break;
+ case 3:
+ scene->_doorway.hide();
+ scene->_dyingKzin.setPosition(Common::Point(296, 62));
+ _globals->_player.animate(ANIM_MODE_5, NULL);
+ scene->_object1.setVisage(43);
+ scene->_object1.setStrip(3);
+ scene->_object1.animate(ANIM_MODE_5, NULL);
+ scene->_object2.hide();
+ scene->_object3.hide();
+ scene->_stripManager.start(45, this);
+ break;
+ case 4:
+ scene->_object2.remove();
+ scene->_object3.remove();
+ scene->_assassin.setVisage(42);
+ scene->_assassin.setStrip(2);
+ scene->_assassin.setFrame(1);
+ scene->_assassin.setPosition(Common::Point(13, 171));
+ scene->_assassin.animate(ANIM_MODE_5, this);
+ scene->_soundHandler.startSound(25);
+ break;
+ case 5:
+ scene->_doorway.show();
+ scene->_doorway.setVisage(42);
+ scene->_doorway.setStrip(3);
+ scene->_doorway.setFrame(1);
+ scene->_doorway.setPosition(Common::Point(41, 144));
+ scene->_assassin.animate(ANIM_MODE_6, NULL);
+ setDelay(6);
+ break;
+ case 6:
+ scene->_doorway.setPosition(Common::Point(178, 101));
+ setDelay(6);
+ break;
+ case 7:
+ scene->_doorway.setPosition(Common::Point(271, 69));
+ setDelay(6);
+ break;
+ case 8:
+ scene->_doorway.remove();
+ scene->_dyingKzin.animate(ANIM_MODE_5, this);
+ break;
+ case 9: {
+ scene->_dyingKzin.setStrip(1);
+ //Workaround: The original uses setFrame(1) but it's completely wrong.
+ scene->_dyingKzin.setFrame(2);
+ scene->_dyingKzin._moveDiff.y = 15;
+ scene->_dyingKzin.animate(ANIM_MODE_5, NULL);
+ Common::Point pt(223, 186);
+ NpcMover *mover = new NpcMover();
+ scene->_dyingKzin.addMover(mover, &pt, this);
+ break;
+ }
+ case 10: {
+ scene->_soundHandler.startSound(27);
+ Common::Point pt(223, 184);
+ NpcMover *mover = new NpcMover();
+ scene->_dyingKzin.addMover(mover, &pt, this);
+ break;
+ }
+ case 11: {
+ Common::Point pt(223, 186);
+ NpcMover *mover = new NpcMover();
+ scene->_dyingKzin.addMover(mover, &pt, this);
+ break;
+ }
+ case 12: {
+ _globals->_soundHandler.startSound(26);
+ _globals->_player._uiEnabled = true;
+ scene->_assassin.setVisage(42);
+ scene->_assassin.setPosition(Common::Point(4, 191));
+ scene->_assassin.setStrip(1);
+ scene->_assassin.animate(ANIM_MODE_1, NULL);
+ Common::Point pt(230, 187);
+ NpcMover *mover = new NpcMover();
+ scene->_assassin.addMover(mover, &pt, this);
+ break;
+ }
+ case 13:
+ setDelay(180);
+ break;
+ case 14:
+ scene->_assassin.setVisage(45);
+ scene->_assassin.setStrip(1);
+ scene->_assassin.setFrame(1);
+ scene->_assassin.animate(ANIM_MODE_5, this);
+ scene->_soundHandler.startSound(28);
+ break;
+ case 15:
+ _globals->_player.disableControl();
+ scene->_object1.setVisage(40);
+ scene->_object1.setStrip(4);
+ scene->_object1.setFrame(1);
+ scene->_object1.animate(ANIM_MODE_5, NULL);
+ _globals->_player.setVisage(40);
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 16:
+ _globals->_soundHandler.startSound(77, this);
+ break;
+ case 17:
+ _globals->_game->endGame(40, 20);
+ remove();
+ break;
+ }
+}
+
+void Scene40::Action2::signal() {
+ Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ if (scene->_assassin._position.x < 229)
+ _actionIndex = 0;
+ setDelay(1);
+ break;
+ case 1:
+ scene->_assassin.animate(ANIM_MODE_NONE, NULL);
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2: {
+ scene->_soundHandler.startSound(28);
+ scene->_doorway.postInit();
+ scene->_doorway.setVisage(16);
+ scene->_doorway.setStrip2(6);
+ scene->_doorway.fixPriority(200);
+ scene->_doorway.setPosition(Common::Point(159, 191));
+ scene->_doorway._moveDiff = Common::Point(40, 40);
+ scene->_doorway._moveRate = 60;
+ scene->_doorway.animate(ANIM_MODE_5, NULL);
+
+ Common::Point pt(271, 165);
+ NpcMover *mover = new NpcMover();
+ scene->_doorway.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ scene->_doorway.remove();
+ scene->_assassin.setVisage(44);
+ scene->_assassin._frame = 1;
+ scene->_assassin.animate(ANIM_MODE_5, this);
+ scene->_soundHandler.startSound(29);
+ RING_INVENTORY._infoDisk._sceneNumber = 40;
+ break;
+ case 4:
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 5: {
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip(1);
+ Common::Point pt(230, 195);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 6: {
+ _globals->_player.setStrip(7);
+ scene->_object1.setVisage(2806);
+ scene->_object1.animate(ANIM_MODE_1, NULL);
+ SceneObjectWrapper *wrapper = new SceneObjectWrapper();
+ scene->_object1.setObjectWrapper(wrapper);
+ Common::Point pt(200, 190);
+ NpcMover *mover = new NpcMover();
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 7:
+ scene->_stripManager.start(44, this);
+ break;
+ case 8: {
+ Common::Point pt(170, 260);
+ NpcMover *mover = new NpcMover();
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 9:
+ scene->_dyingKzin.setAction(&scene->_action7);
+ scene->_object1.remove();
+ _globals->_stripNum = 88;
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player.enableControl();
+ scene->_assassin.setAction(&scene->_action8);
+ break;
+ }
+}
+
+void Scene40::Action3::signal() {
+ Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.setAction(NULL);
+ _globals->_stripNum = 99;
+ _globals->_player.disableControl();
+ Common::Point pt(240, 195);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ _globals->_player.setVisage(5010);
+ _globals->_player._strip = 2;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_4, 5, 1, this);
+ break;
+ case 2:
+ scene->_assassin.setStrip(2);
+ scene->_assassin.setFrame(1);
+ RING_INVENTORY._infoDisk._sceneNumber = 1;
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 3:
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip(7);
+ _globals->_stripNum = 88;
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene40::Action4::signal() {
+ switch (_actionIndex++) {
+ case 0: {
+ Common::Point pt(178, 190);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ _globals->_stripNum = 88;
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene40::Action5::signal() {
+ Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(119) + 120);
+ break;
+ case 1:
+ scene->_object2.animate(ANIM_MODE_8, 1, this);
+ _actionIndex = 0;
+ }
+}
+
+void Scene40::Action6::signal() {
+ Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_object1.postInit();
+ scene->_object1.setVisage(16);
+ scene->_object1.setStrip2(6);
+ scene->_object1._moveDiff = Common::Point(40, 40);
+ scene->_object1.setPosition(Common::Point(313, 53));
+ scene->_object1._moveRate = 60;
+
+ Common::Point pt(141, 194);
+ NpcMover *mover = new NpcMover();
+ scene->_object1.addMover(mover, &pt, NULL);
+ scene->_object1.animate(ANIM_MODE_5, NULL);
+
+ scene->_doorway.postInit();
+ scene->_doorway.setVisage(46);
+ scene->_doorway.setPosition(Common::Point(305, 61));
+ scene->_doorway.animate(ANIM_MODE_5, this);
+ scene->_soundHandler.startSound(25);
+ break;
+ }
+ case 1:
+ scene->_soundHandler.startSound(28);
+ scene->_doorway.setPosition(Common::Point(148, 74));
+ scene->_doorway.setFrame(1);
+ scene->_doorway.setStrip(2);
+ scene->_doorway.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ remove();
+ break;
+ }
+}
+
+void Scene40::Action7::signal() {
+ Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ // TODO: check if it's rand(500) or rand(499)+500
+ setDelay(_globals->_randomSource.getRandomNumber(500));
+ break;
+ case 1:
+ scene->_object7.postInit();
+ scene->_object7.setVisage(46);
+
+ if (_globals->_randomSource.getRandomNumber(32767) >= 16384) {
+ scene->_object7.setStrip(3);
+ scene->_object7.setPosition(Common::Point(15, 185));
+ } else {
+ scene->_object7.setPosition(Common::Point(305, 61));
+ scene->_object7.setFrame(15);
+ }
+ scene->_object7.animate(ANIM_MODE_5, this);
+ scene->_soundHandler.startSound(25);
+ break;
+ case 2:
+ scene->_object7.remove();
+ _actionIndex = 0;
+ setDelay(60);
+ break;
+ }
+}
+
+void Scene40::Action8::signal() {
+ Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(300);
+ break;
+ case 1:
+ _globals->_player.disableControl();
+
+ if ((_globals->_player._position.y >= 197) || (_globals->_player._visage)) {
+ _actionIndex = 1;
+ setDelay(30);
+ } else {
+ scene->_doorway.postInit();
+ scene->_doorway.setVisage(16);
+ scene->_doorway.setStrip2(6);
+ scene->_doorway.fixPriority(200);
+ scene->_doorway._moveRate = 60;
+
+ if (_globals->_player._position.x >= 145) {
+ scene->_doorway.fixPriority(-1);
+ scene->_doorway.setPosition(Common::Point(6, 157));
+ } else {
+ scene->_doorway.setPosition(Common::Point(313, 53));
+ }
+
+ scene->_doorway._moveDiff = Common::Point(40, 40);
+ Common::Point pt(_globals->_player._position.x, _globals->_player._position.y - 18);
+ NpcMover *mover = new NpcMover();
+ scene->_doorway.addMover(mover, &pt, this);
+ scene->_doorway.animate(ANIM_MODE_5, NULL);
+ }
+ break;
+ case 2:
+ scene->_doorway.remove();
+ _globals->_player.setVisage(40);
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ _globals->_soundHandler.startSound(77, this);
+ break;
+ case 4:
+ _globals->_game->endGame(40, 45);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene40::DyingKzin::doAction(int action) {
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(40, 44);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(40, 43);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(40, 12);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(40, 18);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene40::Assassin::doAction(int action) {
+ Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ if (scene->_assassin._visage == 44)
+ SceneItem::display2(40, 21);
+ else {
+ _globals->_player.disableControl();
+ Common::Point pt(230, 187);
+ NpcMover *mover = new NpcMover();
+ addMover(mover, &pt, NULL);
+ scene->setAction(&scene->_action2);
+ }
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(40, (scene->_assassin._visage == 44) ? 22 : 23);
+ break;
+ case CURSOR_LOOK:
+ if (scene->_assassin._visage != 44)
+ SceneItem::display2(40, 13);
+ else
+ SceneItem::display2(40, (RING_INVENTORY._infoDisk._sceneNumber == 1) ? 19 : 14);
+ break;
+ case CURSOR_USE:
+ if (scene->_assassin._visage != 44)
+ SceneItem::display2(40, 15);
+ else if (RING_INVENTORY._infoDisk._sceneNumber == 1)
+ SceneItem::display2(40, 19);
+ else {
+ _globals->_player.disableControl();
+ setAction(&scene->_action3);
+ }
+ break;
+ case CURSOR_TALK:
+ SceneItem::display2(40, 38);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene40::Item2::doAction(int action) {
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(40, 35);
+ _globals->_events.setCursor(CURSOR_WALK);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(40, 34);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(40, 8);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(40, 36);
+ break;
+ case CURSOR_TALK:
+ SceneItem::display2(40, 37);
+ break;
+ default:
+ SceneItem::doAction(action);
+ break;
+ }
+}
+
+void Scene40::Item6::doAction(int action) {
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(40, 25);
+ _globals->_events.setCursor(CURSOR_WALK);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(40, 42);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(40, 6);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(40, 36);
+ break;
+ default:
+ SceneItem::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene40::Scene40() :
+ _item1(2, OBJECT_SCANNER, 40, 24, OBJECT_STUNNER, 40, 25, CURSOR_LOOK, 40, 7, CURSOR_USE, 40, 16, LIST_END),
+ _item3(5, OBJECT_SCANNER, 40, 26, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 9, CURSOR_USE, 40, 17, LIST_END),
+ _item4(6, OBJECT_SCANNER, 40, 31, OBJECT_STUNNER, 40, 32, CURSOR_LOOK, 40, 5, CURSOR_USE, 40, 33, LIST_END),
+ _item5(0, CURSOR_LOOK, 40, 11, LIST_END),
+ _item7(4, OBJECT_SCANNER, 40, 26, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 9, CURSOR_USE, 40, 17, LIST_END),
+ _item8(8, OBJECT_SCANNER, 40, 39, OBJECT_STUNNER, 40, 40, CURSOR_LOOK, 40, 3, CURSOR_USE, 40, 41, LIST_END) {
+}
+
+void Scene40::postInit(SceneObjectList *OwnerList) {
+ loadScene(40);
+ Scene::postInit();
+
+ setZoomPercents(0, 100, 200, 100);
+ _globals->_stripNum = 99;
+
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerSL);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerGameText);
+
+ _speakerGameText._color1 = 9;
+ _speakerGameText.setTextPos(Common::Point(160, 30));
+ _speakerQText._npc = &_globals->_player;
+ _speakerSText._npc = &_object1;
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(130, 220));
+ _globals->_player.disableControl();
+
+ if (_globals->_sceneManager._previousScene == 20) {
+ _globals->_soundHandler.startSound(24);
+ _globals->_player.setVisage(43);
+
+ _object1.postInit();
+ _object1.setVisage(41);
+ _object1.setPosition(Common::Point(105, 220));
+ _object2.postInit();
+ _object2.setVisage(41);
+ _object2.setStrip(6);
+ _object2.fixPriority(200);
+ _object2.setPosition(Common::Point(94, 189));
+ _object2.setAction(&_action5);
+
+ _object3.postInit();
+ _object3.setVisage(41);
+ _object3.setStrip(5);
+ _object3.fixPriority(205);
+ _object3.setPosition(Common::Point(110, 186));
+ _object3._numFrames = 2;
+ _object3.animate(ANIM_MODE_8, NULL, NULL);
+
+ _assassin.postInit();
+ _assassin.setPosition(Common::Point(-40, 191));
+ _globals->_sceneItems.push_back(&_assassin);
+
+ _dyingKzin.postInit();
+ _dyingKzin.setVisage(40);
+ _dyingKzin.setStrip(6);
+ _dyingKzin.setPosition(Common::Point(-90, 65));
+ _dyingKzin.fixPriority(170);
+
+ setAction(&_action1);
+ } else {
+ _doorway.postInit();
+ _doorway.setVisage(46);
+ _doorway.setPosition(Common::Point(148, 74));
+ _doorway.setStrip(2);
+ _doorway.setFrame(_doorway.getFrameCount());
+
+ _dyingKzin.postInit();
+ _dyingKzin.setVisage(40);
+ _dyingKzin.setPosition(Common::Point(205, 183));
+ _dyingKzin.fixPriority(170);
+ _dyingKzin._frame = 9;
+ _dyingKzin.setAction(&_action7);
+
+ _assassin.postInit();
+ _assassin.setVisage(44);
+ _assassin.setPosition(Common::Point(230, 187));
+ _assassin.setAction(&_action8);
+
+ if (RING_INVENTORY._infoDisk._sceneNumber == 40) {
+ _assassin.setStrip(1);
+ _assassin.setFrame(_assassin.getFrameCount());
+ } else {
+ _assassin.setStrip(2);
+ }
+
+ _globals->_sceneItems.push_back(&_assassin);
+ _globals->_player.setPosition(Common::Point(170, 220));
+
+ setAction(&_action4);
+ }
+
+ _item5.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _item6._sceneRegionId = 3;
+ _item2._sceneRegionId = 7;
+
+ _globals->_sceneItems.addItems(&_dyingKzin, &_item8, &_item1, &_item2, &_item3, &_item4,
+ &_item6, &_item7, &_item5, NULL);
+}
+
+void Scene40::signal() {
+ if (_sceneMode == 41)
+ _globals->_sceneManager.changeScene(50);
+}
+
+void Scene40::dispatch() {
+ if ((_globals->_stripNum == 88) && (_globals->_player._position.y >= 197)) {
+ _globals->_player.disableControl();
+ _globals->_stripNum = 0;
+ _globals->_player.setAction(NULL);
+ _sceneMode = 41;
+ setAction(&_sequenceManager, this, 41, &_globals->_player, NULL);
+
+ if (_globals->_sceneManager._previousScene == 20) {
+ _dyingKzin.setAction(&_action6);
+ }
+ }
+
+ Scene::dispatch();
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 50 - By Flycycles
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene50::Action1::signal() {
+ Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setAction(&scene->_sequenceManager, this, 54, &_globals->_player, NULL);
+ break;
+ case 1:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(63, this);
+ break;
+ case 2:
+ if (scene->_stripManager._field2E8 != 107) {
+ _globals->_player.enableControl();
+ remove();
+ } else {
+ Common::Point pt(282, 139);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ }
+ break;
+ case 3:
+ _globals->_stripNum = -1;
+ _globals->_sceneManager.changeScene(60);
+ break;
+ }
+}
+
+void Scene50::Action2::signal() {
+ Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ scene->_stripManager.start(66, this);
+ break;
+ case 1: {
+ Common::Point pt(141, 142);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _globals->_sceneManager.changeScene(40);
+ remove();
+ break;
+ }
+}
+
+void Scene50::Action3::signal() {
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ Common::Point pt(136, 185);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ _globals->_sceneManager.changeScene(60);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene50::Object1::doAction(int action) {
+ Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(50, 20);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(50, 19);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(50, 4);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(50, 21);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 52;
+ scene->setAction(&scene->_sequenceManager, scene, 52, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene50::Object2::doAction(int action) {
+ Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(50, 11);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(50, 10);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(50, 1);
+ break;
+ case OBJECT_INFODISK:
+ case CURSOR_USE:
+ _globals->_stripNum = 50;
+ scene->setAction(&scene->_action3);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene50::Object3::doAction(int action) {
+ Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(50, 11);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(50, 10);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(50, 1);
+ break;
+ case OBJECT_INFODISK:
+ case CURSOR_USE:
+ SceneItem::display2(50, 8);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 52;
+ scene->setAction(&scene->_sequenceManager, scene, 52, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene50::Object4::doAction(int action) {
+ Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(50, 11);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(50, 10);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(50, 1);
+ break;
+ case OBJECT_INFODISK:
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ _globals->_stripNum = 0;
+ scene->_sceneMode = 51;
+ scene->setAction(&scene->_sequenceManager, scene, 51, &_globals->_player, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene50::Scene50() :
+ _item0(0, CURSOR_LOOK, 50, 3, LIST_END),
+ _item1(0, OBJECT_SCANNER, 50, 15, CURSOR_USE, 50, 16, CURSOR_LOOK, 50, 3, LIST_END),
+ _item2(0, CURSOR_LOOK, 50, 7, LIST_END),
+ _item3(8, OBJECT_STUNNER, 50, 14, OBJECT_SCANNER, 50, 13, CURSOR_LOOK, 50, 3, LIST_END),
+ _item4(9, OBJECT_SCANNER, 40, 39, OBJECT_STUNNER, 40, 40, CURSOR_USE, 40, 41, CURSOR_LOOK, 50, 5, LIST_END),
+ _item5(10, OBJECT_SCANNER, 50, 17, OBJECT_STUNNER, 50, 18, CURSOR_LOOK, 50, 6, CURSOR_USE, 30, 8, LIST_END) {
+}
+
+void Scene50::postInit(SceneObjectList *OwnerList) {
+ loadScene(50);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSText);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player._canWalk = false;
+ _globals->_player.changeZoom(75);
+ _globals->_player._moveDiff.y = 3;
+
+ if (_globals->_sceneManager._previousScene == 40) {
+ _globals->_player.setPosition(Common::Point(128, 123));
+ } else if (_globals->_stripNum == 50) {
+ _globals->_player.setPosition(Common::Point(136, 185));
+ } else {
+ _globals->_player.setPosition(Common::Point(270, 143));
+ }
+
+ _object2.postInit();
+ _object2.setVisage(2331);
+ _object2.setStrip(6);
+ _object2.setPosition(Common::Point(136, 192));
+ _object2.fixPriority(200);
+
+ _object3.postInit();
+ _object3.setVisage(2337);
+ _object3.setStrip(6);
+ _object3.setPosition(Common::Point(260, 180));
+ _object3.fixPriority(200);
+
+ _object4.postInit();
+ _object4.setVisage(2331);
+ _object4.setStrip(6);
+ _object4.setPosition(Common::Point(295, 144));
+ _object4.fixPriority(178);
+
+ _globals->_sceneItems.addItems(&_object2, &_object3, &_object4, NULL);
+
+ if (!_globals->getFlag(101)) {
+ _globals->_player.disableControl();
+ _globals->setFlag(101);
+ setAction(&_action1);
+ } else {
+ _globals->_player.enableControl();
+
+ if (_globals->_sceneManager._previousScene == 40) {
+ _globals->_player.disableControl();
+ _sceneMode = 54;
+ setAction(&_sequenceManager, this, 54, &_globals->_player, NULL);
+ }
+ }
+
+ _item0.setBounds(Rect(200, 0, 320, 200));
+ _globals->_sceneItems.addItems(&_item3, &_item4, &_item5, &_item0, NULL);
+ _doorwayRect = Rect(80, 108, 160, 112);
+}
+
+void Scene50::signal() {
+ switch (_sceneMode) {
+ case 51:
+ _globals->_sceneManager.changeScene(60);
+ break;
+ case 55:
+ _globals->_sceneManager.changeScene(40);
+ break;
+ case 52:
+ case 54:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene50::dispatch() {
+ if ((_sceneMode != 55) && _doorwayRect.contains(_globals->_player._position)) {
+ // Player in house doorway, start player moving to within
+ _globals->_player.disableControl();
+ _sceneMode = 55;
+ Common::Point pt(89, 111);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 60 - Flycycle controls
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene60::Action1::signal() {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(3);
+ break;
+ case 1:
+ scene->_floppyDrive.postInit();
+ scene->_floppyDrive.setVisage(60);
+ scene->_floppyDrive.setStrip(7);
+ scene->_floppyDrive.setPosition(Common::Point(136, 65));
+ scene->_floppyDrive.animate(ANIM_MODE_5, this);
+
+ scene->_soundHandler1.startSound(35);
+ break;
+ case 2:
+ scene->_redLights.postInit();
+ scene->_redLights.setVisage(60);
+ scene->_redLights.setPosition(Common::Point(199, 186));
+ scene->_redLights.animate(ANIM_MODE_8, 0, NULL);
+ scene->_redLights._numFrames = 5;
+
+ scene->_controlButton.animate(ANIM_MODE_2, NULL);
+
+ if (!_globals->getFlag(83)) {
+ scene->_message.postInit();
+ scene->_message.setVisage(60);
+ scene->_message.setStrip2(3);
+ scene->_message.setFrame(2);
+ scene->_message.setPosition(Common::Point(148, 85));
+ scene->_message.animate(ANIM_MODE_2, NULL);
+ scene->_message._numFrames = 5;
+
+ _globals->_sceneItems.push_front(&scene->_message);
+ scene->_soundHandler2.startSound(38);
+ }
+
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 3:
+ scene->_soundHandler2.startSound(37);
+ scene->loadScene(65);
+ scene->_message.remove();
+
+ if (_globals->_sceneObjects->contains(&scene->_redLights))
+ scene->_redLights.remove();
+
+ scene->_controlButton.remove();
+ scene->_slaveButton.remove();
+ scene->_masterButton.remove();
+ scene->_item1.remove();
+ scene->_item2.remove();
+
+ scene->_nextButton.postInit();
+ scene->_nextButton.setVisage(65);
+ scene->_nextButton.setPosition(Common::Point(118, 197));
+
+ scene->_prevButton.postInit();
+ scene->_prevButton.setVisage(65);
+ scene->_prevButton.setStrip(2);
+ scene->_prevButton.setPosition(Common::Point(160, 197));
+
+ scene->_exitButton.postInit();
+ scene->_exitButton.setVisage(65);
+ scene->_exitButton.setStrip(3);
+ scene->_exitButton.setPosition(Common::Point(202, 197));
+
+ scene->_rose.postInit();
+ scene->_rose.setVisage(65);
+ scene->_rose.setStrip(4);
+ scene->_rose.setFrame(1);
+ scene->_rose.setPosition(Common::Point(145, 165));
+
+ _globals->_sceneItems.push_front(&scene->_nextButton);
+ _globals->_sceneItems.push_front(&scene->_prevButton);
+ _globals->_sceneItems.push_front(&scene->_exitButton);
+ setDelay(10);
+
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 4:
+ _globals->setFlag(90);
+ // Deliberate fall-through
+ case 5:
+ case 6:
+ case 7:
+ SceneItem::display(60, _actionIndex - 4, SET_Y, 40, SET_X, 25, SET_FONT, 75,
+ SET_EXT_BGCOLOR, -1, SET_FG_COLOR, 34, SET_POS_MODE, 0,
+ SET_WIDTH, 280, SET_KEEP_ONSCREEN, 1, LIST_END);
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 9:
+ _globals->_player._uiEnabled = false;
+ RING_INVENTORY._infoDisk._sceneNumber = 1;
+
+ if (_globals->_sceneObjects->contains(&scene->_message))
+ scene->_message.remove();
+
+ scene->_controlButton.animate(ANIM_MODE_NONE);
+ scene->_controlButton.setFrame(1);
+ scene->_redLights.remove();
+
+ scene->_floppyDrive.postInit();
+ scene->_floppyDrive.setVisage(60);
+ scene->_floppyDrive.setStrip(7);
+ scene->_floppyDrive.setPosition(Common::Point(136, 65));
+ scene->_floppyDrive.setFrame(scene->_floppyDrive.getFrameCount());
+ scene->_floppyDrive.animate(ANIM_MODE_6, this);
+
+ scene->_soundHandler1.startSound(35);
+ scene->_soundHandler3.proc3();
+
+ scene->_masterButton.setFrame(1);
+ scene->_masterButton._state = 0;
+
+ _globals->clearFlag(103);
+ _globals->clearFlag(!_globals->_stripNum ? 116 : 119);
+ break;
+ case 10:
+ setDelay(60);
+ break;
+ case 11:
+ _globals->_player._uiEnabled = true;
+ scene->_floppyDrive.remove();
+ remove();
+ break;
+ case 8:
+ default:
+ break;
+ }
+}
+
+void Scene60::Action2::signal() {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ case 2:
+ setDelay(3);
+ break;
+ case 1:
+ scene->_stripManager.start(66, this);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(50);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene60::PrevObject::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display2(60, 16);
+ } else if (action == CURSOR_USE) {
+ animate(ANIM_MODE_8, 1, NULL);
+
+ if (scene->_action1.getActionIndex() > 5) {
+ scene->_soundHandler3.startSound(36);
+ scene->_action1.setActionIndex(scene->_action1.getActionIndex() - 2);
+ scene->_action1.setDelay(1);
+ }
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene60::NextObject::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display2(60, 17);
+ } else if (action == CURSOR_USE) {
+ animate(ANIM_MODE_8, 1, NULL);
+
+ if (scene->_action1.getActionIndex() < 8) {
+ scene->_soundHandler3.startSound(36);
+ scene->_action1.setDelay(1);
+ }
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene60::ExitObject::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display2(60, 18);
+ } else if (action == CURSOR_USE) {
+ scene->_soundHandler3.startSound(36);
+ animate(ANIM_MODE_8, 1, NULL);
+ scene->_nextButton.remove();
+ scene->_prevButton.remove();
+ scene->_exitButton.remove();
+ scene->_rose.remove();
+
+ SceneItem::display(0, 0);
+ scene->loadScene(60);
+
+ scene->_controlButton.postInit();
+ scene->_controlButton.setVisage(60);
+ scene->_controlButton.setStrip(5);
+ scene->_controlButton.setPosition(Common::Point(233, 143));
+ scene->_controlButton.animate(ANIM_MODE_2, NULL);
+
+ scene->_slaveButton.postInit();
+ scene->_slaveButton.setVisage(60);
+ scene->_slaveButton.setStrip(8);
+ scene->_slaveButton.setPosition(Common::Point(143, 125));
+
+ scene->_masterButton.postInit();
+ scene->_masterButton.setVisage(60);
+ scene->_masterButton.setStrip(8);
+ scene->_masterButton.setPosition(Common::Point(143, 105));
+
+ _globals->_sceneItems.push_front(&scene->_masterButton);
+ _globals->_sceneItems.push_front(&scene->_slaveButton);
+
+ scene->_redLights.postInit();
+ scene->_redLights.setVisage(60);
+ scene->_redLights.setPosition(Common::Point(199, 186));
+ scene->_redLights.animate(ANIM_MODE_8, 0, NULL);
+ scene->_redLights._numFrames = 5;
+ scene->_redLights.setAction(&scene->_sequenceManager, scene, 61, NULL);
+
+ if (scene->_slaveButton._state)
+ scene->_slaveButton.setFrame(2);
+ if (scene->_masterButton._state)
+ scene->_masterButton.setFrame(2);
+
+ _globals->_sceneItems.push_front(&scene->_item1);
+ _globals->_sceneItems.push_front(&scene->_controlButton);
+ _globals->_sceneItems.push_front(&scene->_slaveButton);
+ _globals->_sceneItems.push_front(&scene->_masterButton);
+ _globals->_sceneItems.push_back(&scene->_item2);
+
+ _globals->gfxManager()._font.setFontNumber(2);
+ _globals->_sceneText._fontNumber = 2;
+
+ scene->_action1.setActionIndex(2);
+ scene->_action1.setDelay(1);
+ scene->_sceneMode = 9999;
+ scene->signal();
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene60::MessageObject::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display2(60, 9);
+ } else if (action == CURSOR_USE) {
+ scene->_action1.setDelay(1);
+ _globals->setFlag(83);
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene60::ControlObject::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display2(60, 11);
+ } else if (action == CURSOR_USE) {
+ if (_animateMode == ANIM_MODE_NONE)
+ SceneItem::display2(60, 14);
+ else if (!scene->_slaveButton._state) {
+ _globals->_soundHandler.startSound(40);
+ _globals->_soundHandler.proc5(1);
+ _globals->_sceneManager.changeScene(20);
+ } else {
+ scene->_sceneMode = 15;
+ setAction(&scene->_sequenceManager, scene, 62, NULL);
+ }
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene60::SlaveObject::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display2(60, 8);
+ } else if (action == CURSOR_USE) {
+ if (scene->_masterButton._state)
+ scene->_sceneMode = 19;
+ else if (_state) {
+ scene->_soundHandler3.proc3();
+ animate(ANIM_MODE_6, NULL);
+ _globals->clearFlag(102);
+ _globals->clearFlag(!_globals->_stripNum ? 117 : 120);
+ _state = 0;
+ scene->_sceneMode = 9998;
+ } else {
+ scene->_soundHandler3.startSound(39);
+ _globals->setFlag(102);
+ _globals->setFlag(!_globals->_stripNum ? 117 : 120);
+ animate(ANIM_MODE_5, NULL);
+ _state = 1;
+ scene->_sceneMode = 9998;
+ }
+
+ setAction(&scene->_sequenceManager, scene, 62, NULL);
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene60::MasterObject::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display2(60, 7);
+ } else if (action == CURSOR_USE) {
+ if (!scene->_controlButton._animateMode)
+ scene->_sceneMode = 14;
+ else if (scene->_slaveButton._state)
+ scene->_sceneMode = 20;
+ else if (_state) {
+ scene->_soundHandler3.proc3();
+ animate(ANIM_MODE_6, NULL);
+ _state = 0;
+ _globals->clearFlag(103);
+ _globals->clearFlag(!_globals->_stripNum ? 116 : 119);
+ scene->_sceneMode = 9998;
+ } else {
+ scene->_soundHandler3.startSound(39);
+ animate(ANIM_MODE_5, NULL);
+ _state = 1;
+ _globals->setFlag(103);
+ _globals->setFlag(!_globals->_stripNum ? 116 : 119);
+ scene->_sceneMode = 9998;
+ }
+
+ setAction(&scene->_sequenceManager, scene, 62, NULL);
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene60::FloppyDrive::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display2(60, 13);
+ } else if (action == CURSOR_USE) {
+ _globals->setFlag(!_globals->_stripNum ? 118 : 121);
+ scene->setAction(&scene->_action1);
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene60::Item1::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_INFODISK:
+ RING_INVENTORY._infoDisk._sceneNumber = 60;
+ _globals->setFlag(!_globals->_stripNum ? 118 : 121);
+ scene->_sceneMode = 0;
+ scene->setAction(&scene->_action1);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(60, 10);
+ break;
+ case CURSOR_USE:
+ if (RING_INVENTORY._infoDisk._sceneNumber == 60) {
+ if (_globals->getFlag(118) && !_globals->_stripNum) {
+ _globals->clearFlag(118);
+ scene->setAction(&scene->_action1);
+ scene->_action1.setActionIndex(9);
+ scene->_action1.setDelay(1);
+ }
+ if (_globals->getFlag(121) && !_globals->_stripNum) {
+ _globals->clearFlag(121);
+ scene->setAction(&scene->_action1);
+ scene->_action1.setActionIndex(9);
+ scene->_action1.setDelay(1);
+ }
+ } else if (RING_INVENTORY._infoDisk._sceneNumber == 1) {
+ scene->_sceneMode = 0;
+ setAction(&scene->_sequenceManager, scene, 62, NULL);
+ } else {
+ scene->setAction(&scene->_action2);
+ }
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene60::Item::doAction(int action) {
+ Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(60, _messageNum);
+ break;
+ case CURSOR_USE:
+ scene->_sceneMode = _sceneMode;
+ setAction(&scene->_sequenceManager, this, 62, NULL);
+ break;
+ default:
+ SceneItem::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene60::Scene60() :
+ _item2(0, 12, 12),
+ _item3(8, 22, 23),
+ _item4(9, 24, 25),
+ _item5(10, 26, 27),
+ _item6(11, 28, 29) {
+}
+
+void Scene60::postInit(SceneObjectList *OwnerList) {
+ loadScene(60);
+ Scene::postInit();
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSText);
+
+ _globals->_player._uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_USE);
+
+ _slaveButton.postInit();
+ _slaveButton.setVisage(60);
+ _slaveButton.setStrip(8);
+ _slaveButton.setPosition(Common::Point(143, 125));
+ _slaveButton._state = 0;
+
+ _masterButton.postInit();
+ _masterButton.setVisage(60);
+ _masterButton.setStrip(8);
+ _masterButton.setPosition(Common::Point(143, 105));
+ _masterButton._state = 0;
+
+ _globals->_sceneItems.push_back(&_masterButton);
+ _globals->_sceneItems.push_back(&_slaveButton);
+
+ _controlButton.postInit();
+ _controlButton.setVisage(60);
+ _controlButton.setStrip(5);
+ _controlButton.setPosition(Common::Point(233, 143));
+ _globals->_sceneItems.push_back(&_controlButton);
+
+ if (_globals->_stripNum == -1) {
+ _globals->_stripNum = 0;
+ } else {
+ _globals->_player.disableControl();
+ _sceneMode = 9999;
+ setAction(&_sequenceManager, this, 61, NULL);
+ }
+
+ _item1.setBounds(Rect(130, 55, 174, 70));
+ _item2.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+
+ if (_globals->_stripNum == 0) {
+ if (_globals->getFlag(117)) {
+ _slaveButton._state = 1;
+ _slaveButton.setFrame(2);
+ }
+
+ if (_globals->getFlag(116)) {
+ _masterButton._state = 1;
+ _masterButton.setFrame(2);
+ }
+
+ if (_globals->getFlag(118)) {
+ _controlButton.animate(ANIM_MODE_2, NULL);
+
+ _redLights.postInit();
+ _redLights.setVisage(60);
+ _redLights.setPosition(Common::Point(199, 186));
+ _redLights.animate(ANIM_MODE_8, 0, NULL);
+
+ _soundHandler1.startSound(35);
+
+ if (!_globals->getFlag(83)) {
+ _message.postInit();
+ _message.setVisage(60);
+ _message.setStrip2(3);
+ _message.setFrame(2);
+ _message.setPosition(Common::Point(148, 85));
+ _message.animate(ANIM_MODE_2, NULL);
+ _message._numFrames = 5;
+ _globals->_sceneItems.push_front(&_message);
+
+ _soundHandler2.startSound(38);
+ }
+ }
+ } else {
+ if (_globals->getFlag(120)) {
+ _slaveButton._state = 1;
+ _slaveButton.setFrame(2);
+ }
+
+ if (_globals->getFlag(119)) {
+ _masterButton._state = 1;
+ _masterButton.setFrame(2);
+ }
+
+ if (_globals->getFlag(121)) {
+ _controlButton.animate(ANIM_MODE_2, NULL);
+
+ _redLights.postInit();
+ _redLights.setVisage(60);
+ _redLights.setPosition(Common::Point(199, 186));
+ _redLights.animate(ANIM_MODE_8, 0, NULL);
+ _redLights._numFrames = 5;
+
+ _soundHandler1.startSound(35);
+
+ if (!_globals->getFlag(83)) {
+ _message.postInit();
+ _message.setVisage(60);
+ _message.setStrip2(3);
+ _message.setFrame(2);
+ _message.setPosition(Common::Point(148, 85));
+ _message.animate(ANIM_MODE_2, NULL);
+ _message._numFrames = 5;
+ _globals->_sceneItems.push_front(&_message);
+
+ _soundHandler2.startSound(38);
+ }
+ }
+ }
+
+ _globals->_sceneItems.addItems(&_item3, &_item4, &_item5, &_item6,
+ &_item1, &_item2, NULL);
+}
+
+void Scene60::signal() {
+ if (_sceneMode != 0) {
+ if (_sceneMode == 9998) {
+ _globals->_events.setCursor(CURSOR_USE);
+ } else if (_sceneMode == 9999) {
+ _globals->_player._uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_USE);
+
+ _gfxButton.setText(EXIT_MSG);
+ _gfxButton._bounds.center(160, 193);
+ _gfxButton.draw();
+ _gfxButton._bounds.expandPanes();
+ } else {
+ SceneItem::display2(60, _sceneMode);
+ _globals->_events.setCursor(CURSOR_USE);
+ }
+ }
+}
+
+void Scene60::process(Event &event) {
+ Scene::process(event);
+
+ if (_screenNumber == 60) {
+ if (_gfxButton.process(event))
+ _globals->_sceneManager.changeScene(50);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 90 - Shipyard Entrance
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene90::Action1::signal() {
+ Scene90 *scene = (Scene90 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ _globals->_scenePalette.addRotation(64, 72, -1);
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(90, this);
+ break;
+ case 2:
+ setDelay(2);
+ break;
+ case 3: {
+ Common::Point pt(278, 191);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 4:
+ scene->_object2.setStrip(3);
+ setDelay(2);
+ break;
+ case 5:
+ scene->_soundHandler2.startSound(58);
+
+ if (scene->_stripManager._field2E8 == 220)
+ scene->_stripManager.start(91, this, scene);
+ else {
+ scene->_stripManager.start(_globals->getFlag(104) ? 93 : 92, this, scene);
+ _actionIndex = 7;
+ }
+ break;
+ case 6:
+ scene->_object2.animate(ANIM_MODE_NONE);
+ _globals->_player._uiEnabled = true;
+ break;
+ case 7:
+ scene->_object2.animate(ANIM_MODE_NONE);
+ _globals->_soundHandler.startSound(56);
+ scene->_object3.animate(ANIM_MODE_5, this);
+ break;
+ case 8: {
+ Common::Point pt(215, 127);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object5.addMover(mover, &pt, this);
+ break;
+ }
+ case 9: {
+ Common::Point pt1(215, 127);
+ PlayerMover *mover1 = new PlayerMover();
+ scene->_object1.addMover(mover1, &pt1, this);
+ Common::Point pt2(86, 62);
+ PlayerMover *mover2 = new PlayerMover();
+ scene->_object5.addMover(mover2, &pt2, this);
+ break;
+ }
+ case 10: {
+ PlayerMover2 *mover = new PlayerMover2();
+ scene->_object1.addMover(mover, 10, 15, &scene->_object5);
+
+ if (!_globals->getFlag(104)) {
+ mover = new PlayerMover2();
+ scene->_object4.addMover(mover, 10, 15, &scene->_object1);
+ }
+ setDelay(60);
+ break;
+ }
+ case 11:
+ _globals->_soundHandler.startSound(57);
+ _globals->_soundHandler.startSound(68);
+ scene->_object3.animate(ANIM_MODE_6, NULL);
+
+ SceneItem::display(90, _globals->getFlag(104) ? 15 : 14,
+ SET_EXT_BGCOLOR, 13, SET_KEEP_ONSCREEN, -1, SET_X, 120, SET_Y, 20, LIST_END);
+ break;
+ case 12:
+ SceneItem::display(0, 0);
+ _globals->_scenePalette.clearListeners();
+ _globals->_sceneManager.changeScene(95);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene90::Object1::doAction(int action) {
+ Scene90 *scene = (Scene90 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(90, 7);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 97;
+ setAction(&scene->_sequenceManager, scene, 97, this, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene90::Object2::doAction(int action) {
+ Scene90 *scene = (Scene90 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->_object6.postInit();
+ scene->_object6.setVisage(90);
+ scene->_object6.setStrip(6);
+ scene->_object6.setPosition(Common::Point(184, 210));
+ scene->_object6.hide();
+
+ scene->_sceneMode = 91;
+ scene->_soundHandler1.startSound(59);
+ scene->_soundHandler1.proc5(1);
+ scene->setAction(&scene->_sequenceManager, scene, 91, this, &scene->_object6, NULL);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(90, 8);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ setAction(&scene->_sequenceManager, scene, 96, this, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene90::Scene90() :
+ _item1(0, CURSOR_LOOK, 90, 9, LIST_END),
+ _item2(0, CURSOR_LOOK, 90, 10, LIST_END),
+ _item3(0, CURSOR_LOOK, 90, 11, LIST_END),
+ _object3(OBJECT_STUNNER, 90, 13, CURSOR_LOOK, 90, 12, CURSOR_USE, 90, 16, LIST_END),
+ _object4(CURSOR_LOOK, 90, 17, LIST_END),
+ _object5(CURSOR_LOOK, 90, 18, CURSOR_USE, 90, 19, LIST_END) {
+}
+
+void Scene90::stripCallback(int v) {
+ Scene90 *scene = (Scene90 *)_globals->_sceneManager._scene;
+
+ if (v == 1)
+ scene->_object2.animate(ANIM_MODE_7, NULL);
+ else if (v == 2)
+ scene->_object2.animate(ANIM_MODE_NONE);
+}
+
+void Scene90::postInit(SceneObjectList *OwnerList) {
+ loadScene(90);
+ Scene::postInit();
+
+ setZoomPercents(70, 10, 180, 100);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerSR);
+
+ _speakerMText._npc = &_object2;
+ _speakerQText._textWidth = 160;
+ _speakerQText._npc = &_object5;
+ _speakerSText._npc = &_object1;
+
+ _object5.postInit();
+ _object5.setVisage(2333);
+ _object5.setObjectWrapper(new SceneObjectWrapper());
+ _object5._strip = 7;
+ _object5._moveDiff = Common::Point(22, 22);
+ _object5.setPosition(Common::Point(151, 177));
+ _object5.changeZoom(-1);
+ _globals->_sceneItems.push_back(&_object5);
+
+ _object1.postInit();
+ _object1.setVisage(2337);
+ _object1.setObjectWrapper(new SceneObjectWrapper());
+ _object1._strip = 4;
+ _object1._moveDiff = Common::Point(20, 20);
+ _object1.setPosition(Common::Point(212, 183));
+ _object1.changeZoom(-1);
+ _globals->_sceneItems.push_back(&_object1);
+
+ if (!_globals->getFlag(104)) {
+ _object4.postInit();
+ _object4.setVisage(2331);
+ _object4.setObjectWrapper(new SceneObjectWrapper());
+ _object4._strip = 4;
+ _object4._moveDiff = Common::Point(20, 20);
+ _object4.setPosition(Common::Point(251, 207));
+ _object4.changeZoom(-1);
+ _globals->_sceneItems.push_back(&_object4);
+ }
+
+ _object2.postInit();
+ _object2.setVisage(90);
+ _object2.animate(ANIM_MODE_1, NULL);
+ _object2.setPosition(Common::Point(315, 185));
+ _object2._strip = 2;
+ _globals->_sceneItems.push_back(&_object2);
+
+ _object3.postInit();
+ _object3.setVisage(90);
+ _object3.animate(ANIM_MODE_1, NULL);
+ _object3.setPosition(Common::Point(196, 181));
+ _object3.fixPriority(175);
+ _globals->_sceneItems.push_back(&_object3);
+
+ _globals->_player.disableControl();
+ _globals->_soundHandler.startSound(55);
+ _soundHandler1.startSound(52);
+ _soundHandler1.proc5(1);
+
+ setAction(&_action1);
+
+ _item3.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _item1.setBounds(Rect(271, 65, 271, 186));
+ _item2.setBounds(Rect(0, 17, 124, 77));
+
+ _globals->_sceneItems.addItems(&_item1, &_item2, &_item3, NULL);
+}
+
+void Scene90::signal() {
+ switch (_sceneMode) {
+ case 91:
+ _sceneMode = 92;
+ _globals->_soundHandler.startSound(77, this);
+ break;
+ case 92:
+ _globals->_scenePalette.clearListeners();
+ _globals->_game->endGame(90, 6);
+ break;
+ case 96:
+ _globals->_player.enableControl();
+ break;
+ case 97:
+ _stripManager._field2E8 = 0;
+ _action1.setActionIndex(5);
+ _action1.setDelay(1);
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 95 - Ship Close-up
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene95::Action1::signal() {
+ Scene95 *scene = (Scene95 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _state = 6;
+ setDelay(60);
+ break;
+ case 1:
+ if (_state) {
+ SceneItem::display(95, _state % 2, SET_FONT, 2,
+ SET_EXT_BGCOLOR, -1, SET_EXT_BGCOLOR, 20,
+ SET_WIDTH, 200, SET_KEEP_ONSCREEN, 1, SET_TEXT_MODE, 1, LIST_END);
+ --_state;
+ _actionIndex = 1;
+ }
+ setDelay(60);
+ break;
+ case 2: {
+ scene->_soundHandler.startSound(66);
+ scene->_object3._numFrames = 5;
+ scene->_object3.animate(ANIM_MODE_5, NULL);
+ SceneItem::display(0, 0);
+
+ Common::Point pt1(5, 198);
+ NpcMover *mover1 = new NpcMover();
+ _globals->_player.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(9, 190);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object1.addMover(mover2, &pt2, NULL);
+ break;
+ }
+ case 3: {
+ scene->_soundHandler.startSound(21);
+
+ Common::Point pt1(235, 72);
+ PlayerMover *mover1 = new PlayerMover();
+ _globals->_player.addMover(mover1, &pt1, NULL);
+
+ Common::Point pt2(235, 72);
+ PlayerMover *mover2 = new PlayerMover();
+ scene->_object1.addMover(mover2, &pt2, NULL);
+
+ SceneItem::display(95, 2, SET_Y, 45, SET_FONT, 2,
+ SET_BG_COLOR, -1, SET_EXT_BGCOLOR, 13, SET_WIDTH, 200,
+ SET_KEEP_ONSCREEN, 1, LIST_END);
+ setDelay(240);
+ break;
+ }
+ case 4:
+ scene->_object3.remove();
+
+ SceneItem::display(95, 3, SET_Y, 45, SET_FONT, 2,
+ SET_BG_COLOR, -1, SET_EXT_BGCOLOR, 35, SET_WIDTH, 200,
+ SET_KEEP_ONSCREEN, 1, LIST_END);
+ setDelay(240);
+ break;
+ case 5:
+ SceneItem::display(95, 4, SET_Y, 45, SET_FONT, 2,
+ SET_BG_COLOR, -1, SET_EXT_BGCOLOR, 35, SET_WIDTH, 200,
+ SET_KEEP_ONSCREEN, 1, LIST_END);
+ setDelay(240);
+ break;
+ case 6:
+ setDelay(20);
+ break;
+ case 7: {
+ SceneItem::display(0, 0);
+ _globals->_player.setVisage(92);
+ _globals->_player.setPosition(Common::Point(-25, 200));
+ scene->_object1.setVisage(91);
+ scene->_object1.setPosition(Common::Point(-22, 220));
+
+ scene->_soundHandler.startSound(21);
+
+ Common::Point pt1(5, 198);
+ NpcMover *mover1 = new NpcMover();
+ _globals->_player.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(9, 190);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object1.addMover(mover2, &pt2, NULL);
+ break;
+ }
+ case 8: {
+ Common::Point pt1(108, 112);
+ PlayerMover *mover1 = new PlayerMover();
+ _globals->_player.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(108, 112);
+ PlayerMover *mover2 = new PlayerMover();
+ scene->_object1.addMover(mover2, &pt2, NULL);
+ break;
+ }
+ case 9:
+ _globals->_sceneManager.changeScene(2300);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene95::Scene95() {
+}
+
+void Scene95::postInit(SceneObjectList *OwnerList) {
+ loadScene(95);
+ Scene::postInit();
+ setZoomPercents(100, 10, 200, 100);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2337);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player._strip = 4;
+ _globals->_player._moveDiff = Common::Point(30, 30);
+ _globals->_player.setPosition(Common::Point(-35, 200));
+ _globals->_player.changeZoom(-1);
+ _globals->_player.disableControl();
+
+ _object1.postInit();
+ _object1.setVisage(2333);
+ _object1.setPosition(Common::Point(-22, 220));
+ _object1.animate(ANIM_MODE_1, NULL);
+ _object1.setObjectWrapper(new SceneObjectWrapper());
+ _object1._moveDiff = Common::Point(30, 30);
+ _object1.changeZoom(-1);
+
+ _object3.postInit();
+ _object3.setVisage(96);
+ _object3.setPosition(Common::Point(29, 198));
+
+ _soundHandler.startSound(67);
+ setAction(&_action1);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 6100 - Sunflower navigation sequence
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene6100::Action1::signal() {
+ Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->showMessage(SCENE6100_CAREFUL, 13, this);
+ break;
+ case 1:
+ scene->showMessage(SCENE6100_TOUGHER, 35, this);
+ break;
+ case 2:
+ scene->showMessage(NULL, 0, NULL);
+ remove();
+ break;
+ }
+}
+
+void Scene6100::Action2::signal() {
+ Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->showMessage(SCENE6100_ONE_MORE_HIT, 13, this);
+ break;
+ case 1:
+ scene->showMessage(SCENE6100_DOING_BEST, 35, this);
+ break;
+ case 2:
+ scene->showMessage(NULL, 0, NULL);
+ remove();
+ break;
+ }
+}
+
+void Scene6100::Action3::signal() {
+ Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_speed = 0;
+ setDelay(60);
+ break;
+ case 1:
+ _globals->_scenePalette.clearListeners();
+ scene->_fadePercent = 100;
+ _globals->_scenePalette.refresh();
+ scene->loadScene(9997);
+ scene->_object1.hide();
+ scene->_object2.hide();
+ scene->_object3.hide();
+ scene->_sunflower1.hide();
+ scene->_sunflower2.hide();
+ scene->_sunflower3.hide();
+ scene->_rocks.hide();
+ scene->_sceneText.hide();
+
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(8120, this);
+ break;
+ case 2:
+ scene->showMessage(SCENE6100_REPAIR, 7, this);
+ break;
+ case 3:
+ scene->showMessage(NULL, 0, NULL);
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(8130, this);
+ break;
+ case 4:
+ _globals->setFlag(76);
+ _globals->_sceneManager.changeScene(
+ (scene->_stripManager._field2E8 == 135) ? 6100 : 2320);
+ remove();
+ break;
+ }
+}
+
+void Scene6100::Action4::signal() {
+ Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->showMessage(SCENE6100_ROCKY_AREA, 13, this);
+ break;
+ case 1:
+ scene->showMessage(SCENE6100_REPLY, 35, this);
+ break;
+ case 2:
+ scene->showMessage(NULL, 0, NULL);
+ remove();
+ break;
+ }
+}
+
+void Scene6100::Action5::dispatch() {
+ Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene;
+ FloatSet zeroSet;
+ const double MULTIPLY_FACTOR = 0.01744; // 2 * pi / 360
+
+ if (scene->_turnAmount) {
+ scene->_angle = (scene->_turnAmount + scene->_angle) % 360;
+
+ for (int objIndex = 1; objIndex <= 3; ++objIndex) {
+ SceneObject *obj = &scene->_object1;
+ if (objIndex == 2) obj = &scene->_object2;
+ if (objIndex == 3) obj = &scene->_object3;
+
+ obj->_position.x += scene->_turnAmount * 2;
+ if (obj->_position.x >= 320)
+ obj->_position.x -= 480;
+ if (obj->_position.x < -160)
+ obj->_position.x += 480;
+ }
+ }
+
+ scene->_object1._flags |= OBJFLAG_PANES;
+ scene->_object2._flags |= OBJFLAG_PANES;
+ scene->_object3._flags |= OBJFLAG_PANES;
+
+ double distance = scene->_speed;
+ double angle = (double)scene->_angle * MULTIPLY_FACTOR;
+ scene->_probe._floats._float1 += sin(angle) * distance;
+ scene->_probe._floats._float2 += cos(angle) * distance;
+
+ for (int idx = 0; idx < 4; ++idx) {
+ FloatSet tempSet = scene->_objList[idx]->_floats;
+ tempSet.add(-scene->_probe._floats._float1, -scene->_probe._floats._float2,
+ -scene->_probe._floats._float3);
+
+ tempSet.proc1(scene->_angle * MULTIPLY_FACTOR);
+
+ double sqrtVal = tempSet.sqrt(zeroSet);
+ if (sqrtVal != 0.0) {
+ scene->_objList[idx]->_position.y = static_cast<int>(13800.0 / sqrtVal + 62.0);
+ }
+
+ scene->_objList[idx]->_position.x = static_cast<int>(
+ 160.0 - (330.0 / (tempSet._float2 + 330.0) * tempSet._float1));
+ scene->_objList[idx]->dispatch();
+
+ if (tempSet._float2 < 0) {
+ scene->_objList[idx]->_position.y = 300;
+
+ if (idx != 3) {
+ scene->_objList[idx]->_floats._float1 =
+ _globals->_randomSource.getRandomNumber(199);
+ scene->_objList[idx]->_floats._float2 =
+ _globals->_randomSource.getRandomNumber(999) + 750.0;
+
+ scene->_objList[idx]->_floats.proc1(
+ -(scene->_turnAmount * 10 + scene->_angle) * MULTIPLY_FACTOR);
+ scene->_objList[idx]->_floats.add(scene->_probe._floats._float1,
+ scene->_probe._floats._float2, scene->_probe._floats._float3);
+ }
+ }
+
+ if (idx == 3) {
+ scene->_rocksCheck = (ABS((int)tempSet._float1) < 100) && (tempSet._float2 > 0);
+ }
+
+ scene->_objList[idx]->_flags |= OBJFLAG_PANES;
+
+ if ((idx != 3) && (scene->_fadePercent == 100) &&
+ (tempSet.sqrt(zeroSet) < 150.0)) {
+ switch (scene->_hitCount++) {
+ case 1:
+ scene->_soundHandler.startSound(233);
+ scene->showMessage(NULL, 0, NULL);
+
+ if (!_globals->getFlag(76))
+ scene->_probe.setAction(&scene->_action2);
+ break;
+
+ case 2:
+ scene->_soundHandler.startSound(234);
+ scene->showMessage(NULL, 0, NULL);
+
+ if (!_globals->getFlag(76))
+ scene->_probe.setAction(NULL);
+ scene->setAction(&scene->_action3);
+ break;
+
+ default:
+ scene->_soundHandler.startSound(233);
+ scene->showMessage(NULL, 0, NULL);
+
+ if (!_globals->getFlag(76))
+ scene->_probe.setAction(&scene->_action1);
+ break;
+ }
+
+ _globals->_scenePalette.clearListeners();
+ scene->_fadePercent = 0;
+ }
+ }
+}
+
+void Scene6100::GetBoxAction::signal() {
+ Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_turnAmount = 0;
+ Common::Point pt(scene->_rocks._position.x, scene->_rocks._position.y + 10);
+ ProbeMover *mover = new ProbeMover();
+ scene->_probe.addMover(mover, &pt, NULL);
+ scene->_probe.show();
+ break;
+ }
+ case 1: {
+ scene->showMessage(SCENE6100_TAKE_CONTROLS, 35, this);
+ _globals->_scenePalette.clearListeners();
+
+ Common::Point pt(scene->_rocks._position.x, scene->_rocks._position.y - 10);
+ NpcMover *mover = new NpcMover();
+ scene->_probe.addMover(mover, &pt, NULL);
+ break;
+ }
+ case 2:
+ scene->_probe._percent = 4;
+ scene->showMessage(SCENE6100_SURPRISE, 13, this);
+ break;
+ case 3:
+ scene->showMessage(SCENE6100_SWEAT, 35, this);
+ break;
+ case 4:
+ scene->showMessage(SCENE6100_VERY_WELL, 13, this);
+ break;
+ case 5:
+ scene->showMessage(NULL, 0, NULL);
+ _globals->_sceneManager.changeScene(2320);
+ remove();
+ }
+}
+
+void Scene6100::GetBoxAction::dispatch() {
+ Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene;
+
+ if (!scene->_probe._mover && (scene->_getBoxAction._actionIndex >= 1)) {
+ if (scene->_getBoxAction._actionIndex == 1) {
+ scene->_speed = 0;
+ scene->_getBoxAction.signal();
+ }
+
+ if (scene->_probe._percent > 4)
+ // Handle the probe disappearing into the rocks
+ scene->_probe._percent = scene->_probe._percent * 7 / 8;
+ scene->_probe._flags |= OBJFLAG_PANES;
+ }
+
+ Action::dispatch();
+}
+
+void Scene6100::Action7::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ setDelay(90);
+ break;
+ case 2:
+ _globals->_sceneManager.changeScene(2100);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene6100::ProbeMover::dispatch() {
+ Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene;
+
+ if (!dontMove()) {
+ if (scene->_speed > 0) {
+ scene->_action5.dispatch();
+ scene->_speed = (scene->_speed * 4) / 5;
+ }
+ }
+
+ NpcMover::dispatch();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene6100::Item1::doAction(int action) {
+ SceneItem::display2(4000, 0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene6100::postInit(SceneObjectList *OwnerList) {
+ loadScene(6100);
+ Scene::postInit();
+ setZoomPercents(62, 2, 200, 425);
+ _globals->_sceneHandler._delayTicks = 8;
+
+ _globals->_player.disableControl();
+ _globals->_events.setCursor(CURSOR_WALK);
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerSL);
+
+ _object1.postInit();
+ _object1.setVisage(6100);
+ _object1._frame = 1;
+ _object1._strip = 4;
+ _object1.setPosition(Common::Point(0, 60));
+ _object1.fixPriority(1);
+
+ _object2.postInit();
+ _object2.setVisage(6100);
+ _object2._frame = 1;
+ _object2._strip = 4;
+ _object2.setPosition(Common::Point(160, 60));
+ _object2.fixPriority(1);
+
+ _object3.postInit();
+ _object3.setVisage(6100);
+ _object3._frame = 1;
+ _object3._strip = 4;
+ _object3.setPosition(Common::Point(320, 60));
+ _object3.fixPriority(1);
+
+ _rocks.postInit();
+ _rocks.setVisage(6100);
+ _rocks._frame = 1;
+ _rocks._strip = 3;
+ _rocks.setPosition(Common::Point(320, 0));
+ _rocks.fixPriority(2);
+ _rocks.changeZoom(-1);
+ _rocks._floats._float1 = 320.0;
+ _rocks._floats._float2 = 25000.0;
+ _rocks._floats._float3 = 0.0;
+
+ _probe.postInit();
+ _probe._moveDiff = Common::Point(15, 15);
+ _probe.setVisage(6100);
+ _probe._frame = 1;
+ _probe._strip = 5;
+ _probe.setPosition(Common::Point(160, 260));
+ _probe.fixPriority(3);
+ _probe._floats._float1 = 320.0;
+ _probe._floats._float2 = 0.0;
+ _probe._floats._float3 = 0.0;
+ _probe.hide();
+
+ _objList[0] = &_sunflower1;
+ _objList[1] = &_sunflower2;
+ _objList[2] = &_sunflower3;
+ _objList[3] = &_rocks;
+
+ int baseVal = 2000;
+ for (int idx = 0; idx < 3; ++idx) {
+ _objList[idx]->_floats._float1 = _globals->_randomSource.getRandomNumber(999);
+ _objList[idx]->_floats._float2 = baseVal;
+ _objList[idx]->_floats._float3 = 0.0;
+ baseVal += _globals->_randomSource.getRandomNumber(499);
+
+ _objList[idx]->postInit();
+ _objList[idx]->setVisage(6100);
+ _objList[idx]->_frame = 1;
+ _objList[idx]->_strip = 2;
+
+ _objList[idx]->setPosition(Common::Point(
+ _globals->_randomSource.getRandomNumber(319), 60));
+ _objList[idx]->fixPriority(1);
+ _objList[idx]->changeZoom(-1);
+ }
+
+ _speed = 30;
+ _fadePercent = 100;
+ _rocksCheck = false;
+ _hitCount = 0;
+ _turnAmount = 0;
+ _angle = 0;
+ _msgActive = false;
+
+ setAction(&_action5);
+ _globals->_scenePalette.addRotation(96, 143, -1);
+
+ if (!_globals->getFlag(76))
+ _probe.setAction(&_action4);
+
+ _globals->_soundHandler.startSound(231);
+}
+
+void Scene6100::remove() {
+ _globals->_player.disableControl();
+ _globals->_scenePalette.clearListeners();
+ Scene::remove();
+}
+
+void Scene6100::process(Event &event) {
+ Scene::process(event);
+
+ if (event.eventType == EVENT_KEYPRESS) {
+ // Handle incremental turning speeds with arrow keys
+ if ((event.kbd.keycode == Common::KEYCODE_LEFT) || (event.kbd.keycode == Common::KEYCODE_KP4)) {
+ _turnAmount = MAX(_turnAmount - 1, -8);
+ } else if ((event.kbd.keycode == Common::KEYCODE_RIGHT) || (event.kbd.keycode == Common::KEYCODE_KP6)) {
+ _turnAmount = MIN(_turnAmount + 1, -8);
+ }
+ }
+
+ if (_probe._action)
+ _probe._action->process(event);
+}
+
+void Scene6100::dispatch() {
+ Scene::dispatch();
+
+ if (_probe._action)
+ _probe._action->dispatch();
+
+ // Handle mouse controlling the turning
+ int changeAmount = (_globals->_events._mousePos.x - 160) / -20;
+ _turnAmount += (changeAmount - _turnAmount) / 2;
+
+ if (_fadePercent < 100) {
+ _fadePercent += 10;
+ if (_fadePercent >= 100) {
+ _globals->_scenePalette.addRotation(96, 143, -1);
+ _fadePercent = 100;
+ }
+
+ byte adjustData[] = {0xff, 0xff, 0xff, 0};
+ _globals->_scenePalette.fade(adjustData, false, _fadePercent);
+ }
+
+ if (_action != &_action3) {
+ // Display the distance remaining to the target
+ int distance = (int)_probe._floats.sqrt(_rocks._floats);
+ Common::String s = Common::String::format("%06d", distance);
+
+ _sceneText.setPosition(Common::Point(24, 160));
+ _sceneText._fontNumber = 0;
+ _sceneText._color1 = 35;
+ _sceneText.setup(s);
+ }
+
+ if (_rocksCheck && (_action == &_action5)) {
+ // Check whether the probe is close enough to the rocks
+ double distance = _probe._floats.sqrt(_rocks._floats);
+
+ if ((distance >= 300.0) && (distance <= 500.0))
+ setAction(&_getBoxAction);
+ }
+}
+
+void Scene6100::showMessage(const Common::String &msg, int color, Action *action) {
+ if (_msgActive) {
+ _msgActive = false;
+ _speaker1.removeText();
+ }
+
+ if (!msg.empty()) {
+ _msgActive = true;
+ _speaker1._textPos.x = 20;
+ _speaker1._textWidth = 280;
+ _speaker1._color1 = color;
+ _speaker1._action = action;
+ _speaker1.setText(msg);
+ }
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes1.h b/engines/tsage/ringworld_scenes1.h
new file mode 100644
index 0000000000..be6d8e6337
--- /dev/null
+++ b/engines/tsage/ringworld_scenes1.h
@@ -0,0 +1,536 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_SCENES1_H
+#define TSAGE_RINGWORLD_SCENES1_H
+
+#include "common/scummsys.h"
+#include "tsage/ringworld_logic.h"
+#include "tsage/converse.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+class Scene10 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+public:
+ Speaker _speakerSText;
+ Speaker _speakerQText;
+ Action1 _action1;
+ Action2 _action2;
+ SceneObject _object1, _object2, _object3;
+ SceneObject _object4, _object5, _object6;
+
+ virtual void stripCallback(int v);
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene15 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ virtual void dispatch();
+ };
+public:
+ Action1 _action1;
+ SceneObject _object1;
+ SoundHandler _soundHandler;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene20 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+public:
+ SequenceManager _sequenceManager;
+ SpeakerQText _speakerQText;
+ SpeakerGameText _speakerGameText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ SceneObject _sceneObject1, _SceneObjectExt, _sceneObject3, _sceneObject4, _sceneObject5;
+ SoundHandler _sound;
+public:
+ Scene20();
+ virtual ~Scene20() {}
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+};
+
+class Scene30 : public Scene {
+ /* Scene objects */
+ // Doorway beam sensor
+ class BeamObject : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ // Doorway object
+ class DoorObject : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ // Kzin object
+ class KzinObject : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+ /* Actions */
+ class BeamAction : public Action {
+ public:
+ virtual void signal();
+ };
+ class KzinAction : public Action {
+ public:
+ virtual void signal();
+ };
+ class RingAction : public Action {
+ public:
+ virtual void signal();
+ };
+ class TalkAction : public Action {
+ public:
+ virtual void signal();
+ };
+
+public:
+ SoundHandler _sound;
+ DisplayHotspot _groundHotspot, _wallsHotspot, _courtyardHotspot, _treeHotspot;
+ BeamObject _beam;
+ DoorObject _door;
+ KzinObject _kzin;
+
+ BeamAction _beamAction;
+ KzinAction _kzinAction;
+ RingAction _ringAction;
+ TalkAction _talkAction;
+ SequenceManager _sequenceManager;
+
+ SpeakerSR _speakerSR;
+ SpeakerQL _speakerQL;
+ SpeakerSText _speakerSText;
+ SpeakerQText _speakerQText;
+public:
+ Scene30();
+ virtual ~Scene30() {}
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+};
+
+class Scene40 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action8 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Objects */
+ class DyingKzin : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Assassin : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+ /* Items */
+ class Item2 : public SceneItem {
+ public:
+ virtual void doAction(int action);
+ };
+ class Item6 : public SceneItem {
+ public:
+ virtual void doAction(int action);
+ };
+ class Item8 : public SceneItem {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SpeakerSL _speakerSL;
+ SpeakerQR _speakerQR;
+ SpeakerQText _speakerQText;
+ SpeakerSText _speakerSText;
+ SpeakerGameText _speakerGameText;
+ SoundHandler _soundHandler;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ Action8 _action8;
+ SceneObject _object1, _object2, _object3;
+ DyingKzin _dyingKzin;
+ Assassin _assassin;
+ SceneObject _doorway, _object7, _object8;
+ DisplayHotspot _item1;
+ Item2 _item2;
+ DisplayHotspot _item3, _item4, _item5;
+ Item6 _item6;
+ DisplayHotspot _item7, _item8;
+
+ Scene40();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene50 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Objects */
+ class Object1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object3 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object4 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ SequenceManager _sequenceManager;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Object1 _object1;
+ Object2 _object2;
+ Object3 _object3;
+ Object4 _object4;
+ Rect _doorwayRect;
+ SpeakerSText _speakerSText;
+ SpeakerQText _speakerQText;
+ DisplayHotspot _item0, _item1, _item2;
+ DisplayHotspot _item3, _item4, _item5;
+
+ Scene50();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene60 : public Scene {
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class PrevObject : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class NextObject : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class ExitObject : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class MessageObject : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class ControlObject : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class SlaveObject : public SceneObjectExt {
+ public:
+ virtual void doAction(int action);
+ };
+ class MasterObject : public SceneObjectExt {
+ public:
+ virtual void doAction(int action);
+ };
+ class FloppyDrive : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Item1 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class Item : public SceneHotspot {
+ public:
+ int _messageNum, _sceneMode;
+
+ Item(int sceneRegionId, int messageNum, int sceneMode) {
+ _sceneRegionId = sceneRegionId;
+ _messageNum = messageNum;
+ _sceneMode = sceneMode;
+ }
+ virtual void doAction(int action);
+ };
+
+public:
+ GfxButton _gfxButton;
+ SequenceManager _sequenceManager;
+ SpeakerQText _speakerQText;
+ SpeakerSText _speakerSText;
+ Action1 _action1;
+ Action2 _action2;
+ SceneObject _rose;
+ PrevObject _prevButton;
+ NextObject _nextButton;
+ ExitObject _exitButton;
+ MessageObject _message;
+ ControlObject _controlButton;
+ SlaveObject _slaveButton;
+ MasterObject _masterButton;
+ FloppyDrive _floppyDrive;
+ SceneObject _redLights;
+ Item1 _item1;
+ Item _item2, _item3, _item4, _item5, _item6;
+ SoundHandler _soundHandler1;
+ SoundHandler _soundHandler2;
+ SoundHandler _soundHandler3;
+
+ Scene60();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void process(Event &event);
+};
+
+class Scene90 : public Scene {
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Object1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SpeakerSText _speakerSText;
+ SpeakerQText _speakerQText;
+ SpeakerQL _speakerQL;
+ SpeakerSR _speakerSR;
+ SpeakerMText _speakerMText;
+ Action1 _action1;
+ Object1 _object1;
+ Object2 _object2;
+ DisplayObject _object3, _object4, _object5;
+ SceneObject _object6;
+ DisplayHotspot _item1, _item2, _item3;
+ SoundHandler _soundHandler1, _soundHandler2;
+
+ Scene90();
+
+ virtual void stripCallback(int v);
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+};
+
+class Scene95 : public Scene {
+ class Action1 : public ActionExt {
+ public:
+ virtual void signal();
+ };
+
+public:
+ Action1 _action1;
+ int _field326;
+ SceneObject _object1, _object2, _object3;
+ SoundHandler _soundHandler;
+
+ Scene95();
+ virtual void postInit(SceneObjectList *OwnerList);
+};
+
+class Scene6100 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void dispatch();
+ };
+ class GetBoxAction : public Action {
+ public:
+ virtual void signal();
+ virtual void dispatch();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Objects */
+ class Object : public SceneObject {
+ public:
+ FloatSet _floats;
+ };
+ class ProbeMover : public NpcMover {
+ public:
+ virtual void dispatch();
+ };
+
+ /* Items */
+ class Item1 : public SceneItem {
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ GetBoxAction _getBoxAction;
+ Action7 _action7;
+ SoundHandler _soundHandler;
+ Speaker _speaker1;
+ SpeakerQR _speakerQR;
+ SpeakerSL _speakerSL;
+ SceneObject _object1, _object2, _object3;
+ Object _rocks, _probe;
+ Object _sunflower1, _sunflower2, _sunflower3;
+ SceneText _sceneText;
+ SceneItem _item1;
+
+ int _turnAmount, _angle, _speed, _fadePercent;
+ int _hitCount;
+ bool _rocksCheck;
+ Object *_objList[4];
+ bool _msgActive;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void process(Event &event);
+ virtual void dispatch();
+ void showMessage(const Common::String &msg, int color, Action *action);
+
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_scenes10.cpp b/engines/tsage/ringworld_scenes10.cpp
new file mode 100644
index 0000000000..661c64b93f
--- /dev/null
+++ b/engines/tsage/ringworld_scenes10.cpp
@@ -0,0 +1,2072 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "graphics/cursorman.h"
+#include "tsage/ringworld_scenes10.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+Scene2::Scene2() : Scene() {
+ _sceneState = 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Object9350::postInit(SceneObjectList *OwnerList) {
+ //SceneObject::postInit(&_globals->_sceneManager._altSceneObjects);
+ SceneObject::postInit(OwnerList);
+}
+
+void Object9350::draw() {
+ reposition();
+ Rect destRect = _bounds;
+ destRect.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y);
+ Region *priorityRegion = _globals->_sceneManager._scene->_priorities.find(_globals->_sceneManager._scene->_stripManager._stripNum);
+ GfxSurface frame = getFrame();
+ _globals->gfxManager().copyFrom(frame, destRect, priorityRegion);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9100
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9100::SceneHotspot1::doAction(int action) {
+ Scene9100 *scene = (Scene9100 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_TALK) {
+ if (_globals->getFlag(23)) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 9104;
+ } else {
+ _globals->setFlag(23);
+ _globals->_player.disableControl();
+ scene->_sceneMode = 9105;
+ }
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &_globals->_player, &scene->_object5, &scene->_object6, NULL);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9100::dispatch() {
+ Scene9100 *scene = (Scene9100 *)_globals->_sceneManager._scene;
+
+ if (!_action) {
+ if (_globals->_player._position.x < 25) {
+ _globals->_player.disableControl();
+ if (!_globals->getFlag(23) || _globals->getFlag(11))
+ _sceneMode = 9106;
+ else {
+ _sceneMode = 9108;
+ _globals->setFlag(11);
+ }
+
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &_globals->_player, NULL);
+ }
+ } else {
+ Scene::dispatch();
+ }
+}
+
+void Scene9100::signal() {
+ Scene9100 *scene = (Scene9100 *)_globals->_sceneManager._scene;
+
+ switch (scene->_sceneMode) {
+ case 9102:
+ case 9106:
+ case 9108:
+ _globals->_sceneManager.changeScene(9150);
+ break;
+ case 9105:
+ _sceneHotspot3.remove();
+ // No break on purpose
+ case 9103:
+ case 9104:
+ case 9107:
+ case 9109:
+ default:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene9100::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+ _object1.postInit();
+ _object1.setVisage(9100);
+ _object1._strip = 1;
+ _object1._numFrames = 6;
+ _object1.setPosition(Common::Point(279, 132), 0);
+ _object1.animate(ANIM_MODE_2, 0);
+ _object1.fixPriority(10);
+
+ _globals->_player.postInit();
+
+ _object2.postInit();
+ _object2.hide();
+
+ _object3.postInit();
+ _object3.hide();
+
+ _object4.postInit();
+ _object4.hide();
+
+ _object5.postInit();
+ _object5.hide();
+
+ if (!_globals->getFlag(23)) {
+ _object6.postInit();
+ _object6.setVisage(9111);
+ _object6.setStrip(6);
+ _object6.setFrame(1);
+ _object6.setPosition(Common::Point(138, 166));
+ _sceneHotspot3.setup(145, 125, 166, 156, 9100, 40, 43);
+ }
+ _sceneHotspot1.setup(140, 176, 185, 215, 9100, 36, 37);
+ _sceneHotspot2.setup(161, 138, 182, 175, 9100, 38, 39);
+ _sceneHotspot4.setup(37, 196, 47, 320, 9100, 44, -1);
+ _sceneHotspot5.setup(69, 36, 121, 272, 9100, 45, 46);
+ _sceneHotspot6.setup(127, 0, 200, 52, 9100, 47, 48);
+
+ _globals->_soundHandler.startSound(251);
+ if (_globals->_sceneManager._previousScene == 9150) {
+ if (_globals->getFlag(20)) {
+ _globals->_player.disableControl();
+ if (_globals->getFlag(11))
+ _sceneMode = 9107;
+ else
+ _sceneMode = 9109;
+ setAction(&_sequenceManager, this, _sceneMode, &_globals->_player, &_object5, NULL);
+ } else {
+ _sceneMode = 9103;
+ _globals->_player.disableControl();
+ setAction(&_sequenceManager, this, _sceneMode, &_globals->_player, &_object2, &_object3, &_object4, &_object5, NULL);
+ _globals->setFlag(20);
+ }
+ } else {
+ _sceneMode = 9102;
+ _globals->_player.disableControl();
+ setAction(&_sequenceManager, this, _sceneMode, &_globals->_player, &_object2, &_object3, &_object4, &_object5, NULL);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9150
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9150::Object3::signal() {
+ switch (_signalFlag++) {
+ case 0:
+ _timer = 10 + _globals->_randomSource.getRandomNumber(90);
+ break;
+ default:
+ animate(ANIM_MODE_5, this);
+ _signalFlag = 0;
+ break;
+ }
+}
+
+void Scene9150::Object3::dispatch() {
+ SceneObject::dispatch();
+ if ((_timer != 0) && (--_timer == 0))
+ signal();
+}
+
+void Scene9150::signal() {
+ switch (_sceneMode) {
+ case 9151:
+ case 9157:
+ _globals->_sceneManager.changeScene(9100);
+ break;
+ case 9153:
+ _globals->_sceneManager.changeScene(9300);
+ break;
+ case 9152:
+ case 9155:
+ case 9156:
+ _globals->_player.enableControl();
+ break;
+ case 9154:
+ default:
+ break;
+ }
+}
+
+void Scene9150::dispatch() {
+
+ if ((_sceneState != 0) && (_sceneBounds.left == 0)) {
+ _object3._timer = 0;
+ _sceneState = 0;
+ _object3.setAction(&_sequenceManager2, NULL, 9154, &_object3, NULL);
+ _sceneHotspot10.remove();
+ }
+
+ if (_action) {
+ _action->dispatch();
+ } else {
+ if (_globals->_player._position.x >= 160) {
+ if (_globals->_player._position.x > 630) {
+ _globals->_player.disableControl();
+ _sceneMode = 9157;
+ setAction(&_sequenceManager1, this, _sceneMode, &_globals->_player, 0);
+ }
+ } else {
+ _globals->_player.disableControl();
+ if (_globals->getFlag(11)) {
+ _globals->_soundHandler.startSound(286);
+ _sceneMode = 9153;
+ } else {
+ _sceneMode = 9156;
+ }
+ setAction(&_sequenceManager1, this, _sceneMode, &_globals->_player, 0);
+ }
+ }
+}
+
+void Scene9150::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+ _globals->_player.postInit();
+
+ _object3.postInit();
+ _sceneState = 1;
+ _object3.setVisage(9151);
+ _object3._strip = 1;
+ _object3._frame = 1;
+ _object3.setPosition(Common::Point(312, 95), 0);
+ _object3.signal();
+
+ _sceneHotspot1.setup(0, 0, 200, 94, 9150, 46, -1);
+ _sceneHotspot2.setup(51, 90, 118, 230, 9150, 47, -1);
+ _sceneHotspot3.setup(182, 104, 200, 320, 9150, 48, 49);
+ _sceneHotspot4.setup(103, 292, 152, 314, 9150, 50, 51);
+ _sceneHotspot5.setup(115, 350, 160, 374, 9150, 52, 53);
+ _sceneHotspot6.setup(0, 471, 200, 531, 9150, 54, 55);
+ _sceneHotspot7.setup(170, 320, 185, 640, 9150, 56, -1);
+ _sceneHotspot9.setup(157, 107, 186, 320, 9150, 56, -1);
+ _sceneHotspot8.setup(133, 584, 142, 640, 9150, 57, -1);
+ _sceneHotspot10.setup(83, 304, 103, 323, 9150, 58, 59);
+
+ _globals->_soundHandler.startSound(285);
+ _globals->_player.disableControl();
+
+ if (_globals->getFlag(20)) {
+ // Walking alone
+ _globals->_scrollFollower = &_globals->_player;
+ if (_globals->getFlag(11))
+ // Hero wearing peasan suit
+ _sceneMode = 9155;
+ else
+ // Hero wearing Purple suit
+ _sceneMode = 9152;
+ setAction(&_sequenceManager1, this, _sceneMode, &_globals->_player, 0);
+ } else {
+ // Walking with the tiger
+ _sceneMode = 9151;
+ _object2.postInit();
+ _object2.hide();
+ _object1.postInit();
+ setAction(&_sequenceManager1, this, _sceneMode, &_globals->_player, &_object1, &_object2, 0);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9200
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9200::SceneHotspot1::doAction(int action) {
+ Scene9200 *scene = (Scene9200 *)_globals->_sceneManager._scene;
+
+ if (action == OBJECT_TUNIC) {
+ _globals->_player.disableControl();
+ if (_globals->getFlag(93)) {
+ scene->_sceneState = 9214;
+ scene->setAction(&scene->_sequenceManager, scene, 9214, &_globals->_player, &scene->_object2, 0);
+ } else {
+ _globals->setFlag(93);
+ scene->_sceneState = 9213;
+ scene->setAction(&scene->_sequenceManager, scene, 9213, &_globals->_player, &scene->_object2, 0);
+ }
+ } else if (action <= 100) {
+ _globals->_player.disableControl();
+ scene->_sceneState = 9214;
+ scene->setAction(&scene->_sequenceManager, scene, 9214, &_globals->_player, &scene->_object2, 0);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9200::signal() {
+ switch (_sceneState++) {
+ case 9207:
+ _globals->_sceneManager.changeScene(9700);
+ break;
+ case 9208:
+ case 9211:
+ case 9212:
+ _globals->_sceneManager.changeScene(9500);
+ break;
+ case 9209:
+ _globals->_sceneManager.changeScene(9360);
+ break;
+ case 9210:
+ _hotspot1.remove();
+ // No break on purpose
+ case 9201:
+ case 9202:
+ case 9203:
+ case 9204:
+ case 9205:
+ case 9206:
+ default:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene9200::process(Event &event) {
+ Scene::process(event);
+}
+
+void Scene9200::dispatch() {
+// Rect rect9200 = Rect(320, 175, 250, 154);
+ Rect rect9200 = Rect(250, 154, 320, 175);
+
+ if (_action) {
+ _action->dispatch();
+ } else {
+ if ( (_globals->_player._position.x <= 0) || ((_globals->_player._position.x < 100) && (_globals->_player._position.y > 199))) {
+ _globals->_player.disableControl();
+ _sceneState = 9209;
+ setAction(&_sequenceManager, this, 9209, &_globals->_player, &_object2, &_object3, 0);
+ } else {
+ if (rect9200.contains(_globals->_player._position)) {
+ if (_globals->getFlag(93)) {
+ if (_globals->getFlag(86)) {
+ _sceneState = 9215;
+ setAction(&_sequenceManager, this, 9215, &_globals->_player, &_object2, &_object3, 0);
+ } else {
+ _sceneState = 9208;
+ setAction(&_sequenceManager, this, 9208, &_globals->_player, &_object2, &_object3, 0);
+ }
+ } else {
+ _globals->_player.disableControl();
+ _sceneState = 9204;
+ setAction(&_sequenceManager, this, 9204, &_globals->_player, &_object2, &_object3, 0);
+ }
+ } else {
+ if (_globals->_player._position.y < 140) {
+ _globals->_player.disableControl();
+ _sceneState = 9207;
+ setAction(&_sequenceManager, this, 9207, &_globals->_player, &_object2, &_object3, 0);
+ }
+ }
+ }
+ }
+}
+
+void Scene9200::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(130, 50, 200, 150);
+
+ _globals->_player.postInit();
+ _object3.postInit();
+ _object3.hide();
+ _object1.postInit();
+ // Water animation
+ _object1.setVisage(9200);
+ _object1._strip = 3;
+ _object1.animate(ANIM_MODE_2, 0);
+ _object1.setPosition(Common::Point(132, 114), 0);
+ _object1.fixPriority(140);
+ _soundHandler.startSound(297);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerGR);
+ _stripManager.addSpeaker(&_speakerGText);
+
+ if (!_globals->getFlag(86)) {
+ _object2.postInit();
+ _hotspot1.setup(96, 194, 160, 234, 9200, 29, 31);
+ }
+ _hotspot2.setup(164, 0, 200, 282, 9200, 0, 1);
+ _hotspot3.setup(140, 39, 165, 153, 9200, 2, 3);
+ _hotspot4.setup(92, 122, 139, 152, 9200, 4, 5);
+ _hotspot5.setup(33, 20, 142, 115, 9200, 6, 7);
+ _hotspot6.setup(104, 235, 153, 265, 9200, 8, 9);
+ _hotspot7.setup(107, 262, 153, 286, 9200, 10, 11);
+ _hotspot8.setup(69, 276, 164, 320, 9200, 12, 13);
+
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player.disableControl();
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 9500:
+ if (_globals->getFlag(85)) {
+ if (RING_INVENTORY._helmet._sceneNumber == 1) {
+ _globals->setFlag(86);
+ _globals->_player.disableControl();
+ _sceneState = 9210;
+ setAction(&_sequenceManager, this, 9210, &_globals->_player, &_object2, &_object3, NULL);
+ } else {
+ _globals->_player.disableControl();
+ _sceneState = 9212;
+ setAction(&_sequenceManager, this, 9212, &_globals->_player, &_object2, &_object3, NULL);
+ }
+ } else {
+ if (RING_INVENTORY._helmet._sceneNumber == 1) {
+ _globals->_player.disableControl();
+ _sceneState = 9211;
+ setAction(&_sequenceManager, this, 9211, &_globals->_player, &_object2, &_object3, NULL);
+ } else {
+ _globals->_player.disableControl();
+ _sceneState = 9202;
+ setAction(&_sequenceManager, this, 9202, &_globals->_player, &_object2, &_object3, NULL);
+ }
+ }
+ break;
+ case 9700:
+ if (_globals->getFlag(86)) {
+ _sceneState = 9206;
+ setAction(&_sequenceManager, this, 9206, &_globals->_player, &_object2, &_object3, 0);
+ } else {
+ _sceneState = 9203;
+ setAction(&_sequenceManager, this, 9203, &_globals->_player, &_object2, &_object3, 0);
+ }
+ break;
+ case 9360:
+ default:
+ if (_globals->getFlag(86)) {
+ _sceneState = 9205;
+ setAction(&_sequenceManager, this, 9205, &_globals->_player, &_object2, &_object3, 0);
+ } else {
+ _sceneState = 9201;
+ setAction(&_sequenceManager, this, 9201, &_globals->_player, &_object2, &_object3, 0);
+ }
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9300
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9300::signal() {
+ switch (_sceneMode++) {
+ case 9301:
+ _globals->setFlag(84);
+ // No break on purpose
+ case 9303:
+ _globals->_soundHandler.startSound(295);
+ _globals->_sceneManager.changeScene(9350);
+ break;
+ case 9302:
+ _globals->_player.enableControl();
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene9300::dispatch() {
+ if (_action) {
+ _action->dispatch();
+ } else if (_globals->_player._position.y < 145) {
+ _globals->_player.disableControl();
+ _sceneMode = 9303;
+ setAction(&_sequenceManager, this, 9303, &_globals->_player, &_object1, &_object2, 0);
+ }
+}
+
+void Scene9300::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(130, 75, 230, 150);
+
+ _sceneMode = 0;
+ _globals->_player.postInit();
+ _globals->_player.changeZoom(-1);
+ _object1.postInit();
+ _object2.postInit();
+ _globals->_soundHandler.startSound(289);
+
+ _hotspot1.setup(35, 142, 76, 212, 9300, 0, 1);
+ _hotspot2.setup(28, 90, 81, 143, 9300, 2, 3);
+ _hotspot3.setup(78, 142, 146, 216, 9300, 4, 5);
+ _hotspot4.setup(3, 43, 91, 74, 9300, 6, 7);
+ _hotspot5.setup(82, 19, 157, 65, 9300, 8, 9);
+ _hotspot6.setup(5, 218, 84, 274, 9300, 10, 11);
+ _hotspot7.setup(86, 233, 168, 293, 9300, 12, 13);
+ _hotspot8.setup(157, 0, 200, 230, 9300, 14, 15);
+ _hotspot9.setup(169, 227, 200, 320, 9300, 16, 17);
+ _hotspot10.setup(145, 97, 166, 225, 9300, 18, 19);
+ _hotspot11.setup(81, 75, 145, 145, 9300, 20, 21);
+ _hotspot12.setup(0, 0, 94, 35, 9300, 22, 23);
+ _hotspot13.setup(12, 268, 149, 320, 9300, 24, 25);
+
+ if (_globals->_sceneManager._previousScene == 9350) {
+ _globals->_player.disableControl();
+ _sceneMode = 9302;
+ setAction(&_sequenceManager, this, 9302, &_globals->_player, &_object1, &_object2, 0);
+ } else {
+ _globals->_player.disableControl();
+ _sceneMode = 9301;
+ setAction(&_sequenceManager, this, 9301, &_globals->_player, &_object1, &_object2, 0);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9350
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene9350::signal() {
+ switch (_sceneState ++) {
+ case 0:
+ case 9352:
+ case 9353:
+ case 9354:
+ _globals->_player.enableControl();
+ break;
+ case 9355:
+ _globals->_sceneManager.changeScene(9300);
+ break;
+ case 9356:
+ _globals->_sceneManager.changeScene(9360);
+ break;
+ case 9357:
+ case 9359:
+ _globals->_sceneManager.changeScene(9400);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene9350::dispatch() {
+ if (_action == 0) {
+ if ((_globals->_player._position.x > 300) && (_globals->_player._position.y < 160)) {
+ _globals->_player.disableControl();
+ _sceneState = 9356;
+ setAction(&_sequenceManager, this, 9356, &_globals->_player, &_object2, 0);
+ } else if ((_globals->_player._position.x > 110) && (_globals->_player._position.y >= 195)) {
+ _globals->_player.disableControl();
+ _sceneState = 9357;
+ setAction(&_sequenceManager, this, 9357, &_globals->_player, &_object2, 0);
+ } else if ((_globals->_player._position.x < 10) || ((_globals->_player._position.x <= 110) && (_globals->_player._position.y >= 195))) {
+ _globals->_player.disableControl();
+ _sceneState = 9355;
+ setAction(&_sequenceManager, this, 9355, &_globals->_player, &_object2, 0);
+ }
+ } else {
+ Scene::dispatch();
+ }
+}
+
+void Scene9350::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(95, 80, 200, 100);
+ _globals->_player.postInit();
+
+ _object1.setup(9351, 1, 3, 139, 97, 0);
+ _sceneHotspot1.setup(42, 0, 97, 60, 9350, 0, -1);
+ _sceneHotspot2.setup(37, 205, 82, 256, 9350, 0, -1);
+ _sceneHotspot3.setup(29, 93, 92, 174, 9350, 1, -1);
+ _sceneHotspot4.setup(0, 308, 109, 320, 9350, 2, -1);
+ _sceneHotspot5.setup(0, 0, 200, 320, 9350, 3, -1);
+
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player.disableControl();
+
+ if (_globals->_sceneManager._previousScene == 9360) {
+ _globals->_player.disableControl();
+ _sceneState = 9352;
+ setAction(&_sequenceManager, this, 9352, &_globals->_player, &_object2, NULL);
+ } else if (_globals->_sceneManager._previousScene == 9400) {
+ _globals->_player.disableControl();
+ _sceneState = 9353;
+ setAction(&_sequenceManager, this, 9353, &_globals->_player, &_object2, NULL);
+ } else {
+ if (_globals->getFlag(84)) {
+ _globals->clearFlag(84);
+ _object2.postInit();
+ _globals->_player.disableControl();
+ _sceneState = 9359;
+ setAction(&_sequenceManager, this, 9359, &_globals->_player, &_object2, NULL);
+ } else {
+ _globals->_player.disableControl();
+ _sceneState = 9354;
+ setAction(&_sequenceManager, this, 9354, &_globals->_player, &_object2, NULL);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9360
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene9360::signal() {
+ switch (_sceneState ++) {
+ case 0:
+ case 9362:
+ case 9363:
+ case 9364:
+ _globals->_player.enableControl();
+ break;
+ case 9365:
+ _globals->_sceneManager.changeScene(9350);
+ break;
+ case 9366:
+ _globals->_sceneManager.changeScene(9200);
+ break;
+ case 9367:
+ _globals->_sceneManager.changeScene(9450);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene9360::dispatch() {
+ if (_action == 0) {
+ if ((_globals->_player._position.x > 300) && (_globals->_player._position.y < 160)) {
+ _globals->_player.disableControl();
+ _sceneState = 9366;
+ setAction(&_sequenceManager, this, 9366, &_globals->_player, 0);
+ } else if ((_globals->_player._position.x > 110) && (_globals->_player._position.y >= 195)) {
+ _globals->_player.disableControl();
+ _sceneState = 9367;
+ setAction(&_sequenceManager, this, 9367, &_globals->_player, 0);
+ } else if ((_globals->_player._position.x < 10) || ((_globals->_player._position.x <= 110) && (_globals->_player._position.y >= 195))) {
+ _globals->_player.disableControl();
+ _sceneState = 9365;
+ setAction(&_sequenceManager, this, 9365, &_globals->_player, 0);
+ }
+ } else {
+ Scene::dispatch();
+ }
+}
+
+void Scene9360::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(95, 80, 200, 100);
+ _globals->_player.postInit();
+
+ _hotspot1.setup(37, 92, 93, 173, 9360, 0, 1);
+ _hotspot2.setup(42, 0, 100, 63, 9360, 2, -1);
+ _hotspot3.setup(36, 205, 82, 260, 9360, 3, -1);
+ _hotspot4.setup(103, 2, 200, 320, 9360, 4, -1);
+ _hotspot5.setup(0, 0, 37, 320, 9360, 4, -1);
+ _hotspot6.setup(35, 61, 103, 92, 9360, 4, -1);
+ _hotspot7.setup(33, 174, 93, 207, 9360, 4, -1);
+ _hotspot8.setup(28, 257, 149, 320, 9360, 4, -1);
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player.disableControl();
+ if (_globals->_sceneManager._previousScene == 9350) {
+ _globals->_player.disableControl();
+ _sceneState = 9364;
+ setAction(&_sequenceManager, this, 9364, &_globals->_player, 0);
+ } else if (_globals->_sceneManager._previousScene == 9450) {
+ _globals->_player.disableControl();
+ _sceneState = 9363;
+ setAction(&_sequenceManager, this, 9363, &_globals->_player, 0);
+ } else {
+ _globals->_player.disableControl();
+ _sceneState = 9362;
+ setAction(&_sequenceManager, this, 9362, &_globals->_player, 0);
+ }
+ _object1.setup(9351, 1, 1, 131, 90, 0);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9400
+ *
+ *--------------------------------------------------------------------------*/
+Scene9400::Scene9400() {
+ _field1032 = 0;
+}
+
+void Scene9400::SceneHotspot7::doAction(int action) {
+ Scene9400 *scene = (Scene9400 *)_globals->_sceneManager._scene;
+
+ if ((action == CURSOR_USE) && (RING_INVENTORY._straw._sceneNumber != 1)) {
+ scene->_sceneState = 1;
+ RING_INVENTORY._straw._sceneNumber = 1;
+ scene->setAction(&scene->_sequenceManager, scene, 9408, &_globals->_player, 0);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9400::SceneHotspot8::doAction(int action) {
+ Scene9400 *scene = (Scene9400 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_TALK) {
+ _globals->_player.disableControl();
+ scene->_sceneState = 2;
+ scene->signal();
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9400::signal() {
+ switch (_sceneState ++) {
+ case 0:
+ _object1._numFrames = 6;
+ _stripManager.start(9400, this);
+ break;
+ case 1:
+ _object1._numFrames = 6;
+ _object1.animate(ANIM_MODE_2, 0);
+ _globals->_player.enableControl();
+ break;
+ case 2:
+ _object1.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ _stripManager.start(9405, this);
+ break;
+ case 4:
+ _object1.animate(ANIM_MODE_2, this);
+ _globals->_player.enableControl();
+ break;
+ case 9350:
+ _globals->_sceneManager.changeScene(9350);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene9400::dispatch() {
+ if ((_object1._animateMode == 2) && (_object1._strip == 1) && (_object1._frame == 4)){
+ if (_field1032 == 0) {
+ _soundHandler.startSound(296);
+ _field1032 = 1;
+ }
+ } else {
+ _field1032 = 0;
+ }
+ if (_action == 0) {
+ if (_globals->_player._position.y < 120) {
+ _sceneState = 9350;
+ _globals->_player.disableControl();
+ setAction(&_action1);
+ Common::Point pt(-45, 88);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ }
+ } else {
+ Scene::dispatch();
+ }
+}
+
+void Scene9400::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ _screenNumber = 9400;
+ setZoomPercents(0, 100, 200, 100);
+ _globals->_player.postInit();
+ _object1.postInit(0);
+ _object3.postInit(0);
+ _speakerQText._textPos.x = 20;
+
+ _hotspot7.setup(157, 66, 180, 110, 9400, 21, 23);
+ _hotspot5.setup(130, 133, 152, 198, 9400, 22, -1);
+ _hotspot1.setup(33, 280, 69, 297, 9400, 1, 2);
+ _hotspot2.setup(73, 96, 87, 159, 9400, 3, 4);
+ _hotspot3.setup(89, 253, 111, 305, 9400, 5, 6);
+ _hotspot4.setup(46, 0, 116, 35, 9400, 7, 8);
+ _hotspot8.setup(58, 169, 122, 200, 9400, 9, 10);
+ _hotspot6.setup(0, 0, 199, 319, 9400, 16, 0);
+
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerOR);
+ _stripManager.addSpeaker(&_speakerOText);
+
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player.disableControl();
+
+ // Useless check (skipped) : if (_globals->_sceneManager._previousScene == 9350)
+ _sceneState = 2;
+ if (!_globals->getFlag(89)) {
+ _globals->setFlag(89);
+ _sceneState = 0;
+ }
+
+ setAction(&_sequenceManager, this, 9400, &_globals->_player, &_object1, &_object3, 0);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9450
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9450::Object2::signal() {
+ Scene9450 *scene = (Scene9450 *)_globals->_sceneManager._scene;
+
+ this->setAction(&scene->_sequenceManager3, this, 9458, this, &scene->_object1, 0);
+}
+
+void Scene9450::Object3::dispatch() {
+ SceneObject::dispatch();
+ _percent = (_percent * 20) / 30;
+}
+
+void Scene9450::Hotspot1::doAction(int action) {
+ Scene9450 *scene = (Scene9450 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_USE) {
+ if (scene->_object2._action)
+ scene->_object2._action->remove();
+ scene->_sceneMode = 9459;
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_sequenceManager1, scene, 9459, &scene->_object2, &scene->_object1, &scene->_object3, &_globals->_player, 0);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9450::Hotspot3::doAction(int action) {
+ Scene9450 *scene = (Scene9450 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_CLOAK:
+ case OBJECT_JACKET:
+ case OBJECT_TUNIC2:
+ scene->_sceneMode = 9460;
+ _globals->_player.disableControl();
+ setAction(&scene->_sequenceManager1, scene, 9460, &_globals->_player, &scene->_object2, &scene->_object1, 0);
+ break;
+ case OBJECT_TUNIC:
+ SceneItem::display(9450, 49, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_WALK:
+ // nothing
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display(9450, 41, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ case CURSOR_TALK:
+ if (RING_INVENTORY._tunic._sceneNumber == 9450) {
+ if (scene->_object2._action)
+ scene->_object2._action->remove();
+ scene->_sceneMode = 9459;
+ _globals->_player.disableControl();
+ setAction(&scene->_sequenceManager1, scene, 9459, &scene->_object2, &scene->_object1, &scene->_object3, &_globals->_player, 0);
+ } else if ((RING_INVENTORY._cloak._sceneNumber != 1) && (RING_INVENTORY._jacket._sceneNumber != 1) && (RING_INVENTORY._tunic2._sceneNumber != 1)) {
+ SceneItem::display(9450, 38, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else {
+ scene->_sceneMode = 9460;
+ _globals->_player.disableControl();
+ setAction(&scene->_sequenceManager1, scene, 9460, &_globals->_player, &scene->_object2, &scene->_object1, 0);
+ }
+ break;
+ default:
+ SceneItem::display(9450, 45, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ }
+}
+
+void Scene9450::signal() {
+ switch (_sceneMode++) {
+ case 1002:
+ case 1004:
+ // Drink
+ setAction(&_sequenceManager1, this, 9456, &_object2, &_object1, &_object3, 0);
+ break;
+ case 1005:
+ // Bring me more wine
+ setAction(&_sequenceManager1, this, 9457, &_object2, &_object1, &_object3, 0);
+ break;
+ case 9451:
+ if (_globals->getFlag(87)) {
+ _globals->_player.enableControl();
+ } else {
+ _sceneMode = 1001;
+ if (_object2._action)
+ _object2._action->remove();
+ }
+ // No break on purpose
+ case 1001:
+ case 1003:
+ // Eat
+ setAction(&_sequenceManager1, this, 9455, &_object2, &_object1, &_object3, 0);
+ break;
+ case 9453:
+ _globals->_sceneManager.changeScene(9360);
+ break;
+ case 9459:
+ RING_INVENTORY._tunic._sceneNumber = 1;
+ _object2.signal();
+ _globals->_player.enableControl();
+ _globals->_events.setCursor(CURSOR_WALK);
+ _hotspot1.remove();
+ break;
+ case 1006:
+ _globals->setFlag(87);
+ // No break on purpose
+ default:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene9450::dispatch() {
+ if (_action) {
+ _action->dispatch();
+ } else {
+ if ((_globals->_player._position.y < 98) && (_globals->_player._position.x > 241) && (_globals->_player._position.x < 282)) {
+ _globals->_player.disableControl();
+ _sceneMode = 9452;
+ setAction(&_sequenceManager1, this, 9452, &_globals->_player, 0);
+ } else if ((_globals->_player._position.y < 99) && (_globals->_player._position.x > 68) && (_globals->_player._position.x < 103)) {
+ _globals->_player.disableControl();
+ _sceneMode = 9453;
+ setAction(&_sequenceManager1, this, 9453, &_globals->_player, 0);
+ }
+ }
+}
+
+void Scene9450::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(84, 75, 167, 150);
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player.postInit();
+
+ _object2.postInit();
+ _object1.postInit();
+ _object1.hide();
+
+ _globals->_player.disableControl();
+ _sceneMode = 9451;
+ setAction(&_sequenceManager1, this, 9451, &_globals->_player, 0);
+
+ if (_globals->getFlag(87)) {
+ if (RING_INVENTORY._tunic._sceneNumber == 1) {
+ _object2.signal();
+ } else {
+ _object2.setPosition(Common::Point(184, 144), 0);
+ _object2.setVisage(9451);
+ _object2.fixPriority(250);
+ _object2._strip = 5;
+ _object2._frame = 10;
+ }
+ } else {
+ _object3.postInit();
+ _object3.hide();
+ _object3.setAction(&_sequenceManager2, 0, 9455, &_object2, &_object1, 0);
+ }
+
+ if (RING_INVENTORY._tunic._sceneNumber != 1)
+ _hotspot1.setup(123, 139, 138, 170, 9450, 37, -1);
+
+ _hotspot2.setup(153, 102, 176, 141, 9450, 39, 40);
+ _hotspot3.setup(97, 198, 130, 229, 9450, 41, 42);
+ _hotspot15.setup(131, 190, 145, 212, 9450, 43, 44);
+ _hotspot4.setup(33, 144, 105, 192, 9450, 0, 1);
+ _hotspot5.setup(20, 236, 106, 287, 9450, 2, 3);
+ _hotspot6.setup(137, 119, 195, 320, 9450, 4, 5);
+ _hotspot7.setup(20, 59, 99, 111, 9450, 6, -1);
+ _hotspot8.setup(110, 0, 199, 117, 9450, 7, 8);
+ _hotspot9.setup(101, 104, 130, 174, 9450, 9, 10);
+ _hotspot10.setup(110, 246, 149, 319, 9450, 11, 12);
+ _hotspot11.setup(16, 34, 74, 62, 6450, 13, 14);
+ _hotspot12.setup(19, 108, 72, 134, 9450, 15, 16);
+ _hotspot13.setup(18, 215, 71, 237, 9450, 17, 18);
+ _hotspot14.setup(15, 288, 76, 314, 9450, 19, 20);
+ _hotspot16.setup(0, 0, 200, 320, 9450, 46, -1);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9500
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9500::Hotspot1::doAction(int action) {
+ Scene9500 *scene = (Scene9500 *)_globals->_sceneManager._scene;
+
+ if (action == OBJECT_SWORD) {
+ scene->_sceneMode = 9510;
+ _globals->setFlag(92);
+ RING_INVENTORY._sword._sceneNumber = 9500;
+ _globals->_player.disableControl();
+ _globals->_sceneItems.remove(this);
+ scene->_hotspot2.setup(87, 294, 104, 314, 9400, 17, -1);
+ scene->setAction(&scene->_sequenceManager, scene, 9510, &_globals->_player, &scene->_object2, 0);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9500::Hotspot2::doAction(int action) {
+ Scene9500 *scene = (Scene9500 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_USE) {
+ scene->_sceneMode = 9511;
+ _globals->_player.disableControl();
+ _globals->_sceneItems.remove(this);
+ scene->setAction(&scene->_sequenceManager, scene, 9511, &_globals->_player, &scene->_object2, 0);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9500::Hotspot3::doAction(int action) {
+ Scene9500 *scene = (Scene9500 *)_globals->_sceneManager._scene;
+
+ if ((action == CURSOR_USE) && (RING_INVENTORY._candle._sceneNumber != 1)){
+ scene->_sceneMode = 9505;
+ _globals->_player.disableControl();
+ _globals->_sceneItems.remove(this);
+ scene->setAction(&scene->_sequenceManager, scene, 9505, &_globals->_player, &scene->_candle, 0);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9500::Hotspot4::doAction(int action) {
+ Scene9500 *scene = (Scene9500 *)_globals->_sceneManager._scene;
+
+ if (action == OBJECT_CANDLE) {
+ _globals->_player.disableControl();
+ if (RING_INVENTORY._straw._sceneNumber == 9500) {
+ scene->_sceneMode = 9506;
+ _globals->_sceneItems.remove(&scene->_hotspot5);
+ _globals->_sceneItems.remove(this);
+ scene->setAction(&scene->_sequenceManager, scene, 9506, &_globals->_player, &scene->_object3, 0);
+ RING_INVENTORY._candle._sceneNumber = 9850;
+ } else {
+ scene->_sceneMode = 9507;
+ scene->setAction(&scene->_sequenceManager, scene, 9507, &_globals->_player, &scene->_object3, 0);
+ }
+ } else if (action == OBJECT_STRAW) {
+ scene->_sceneMode = 9512;
+ _globals->_player.disableControl();
+ RING_INVENTORY._straw._sceneNumber = 9500;
+ scene->setAction(&scene->_sequenceManager, scene, 9512, &_globals->_player, &scene->_object3, 0);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9500::signal() {
+ switch (_sceneMode) {
+ case 9503:
+ _globals->_sceneManager.changeScene(9200);
+ _globals->_soundHandler.startSound(295);
+ break;
+ case 9504:
+ _globals->_sceneManager.changeScene(9850);
+ break;
+ case 9505:
+ _candle.setStrip(2);
+ RING_INVENTORY._candle._sceneNumber = 1;
+ _globals->_player.enableControl();
+ break;
+ case 9506:
+ _globals->setFlag(85);
+ _globals->_player.enableControl();
+ break;
+ case 9511:
+ RING_INVENTORY._helmet._sceneNumber = 1;
+ _globals->_player.enableControl();
+ if (!_globals->getFlag(51)) {
+ _globals->setFlag(51);
+ _globals->_player.disableControl();
+ _sceneMode = 9514;
+ setAction(&_sequenceManager, this, 9514, &_globals->_player, 0, 0, 0, 0);
+ }
+ break;
+ case 0:
+ case 9514:
+ default:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene9500::dispatch() {
+ if (_action) {
+ _action->dispatch();
+ } else {
+ if (_globals->_player._position.y >= 199) {
+ _globals->_player.disableControl();
+ _sceneMode = 9503;
+ setAction(&_sequenceManager, this, 9503, &_globals->_player, 0, 0, 0, 0);
+ } else if (_globals->_player._position.y < 127) {
+ _globals->_player.disableControl();
+ _sceneMode = 9504;
+ setAction(&_sequenceManager, this, 9504, &_globals->_player, 0, 0, 0, 0);
+ }
+ }
+
+}
+
+void Scene9500::process(Event &event) {
+ Scene::process(event);
+}
+
+void Scene9500::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(110, 75, 200, 150);
+
+ _globals->_player.postInit();
+ _globals->_soundHandler.startSound(305);
+
+ _candle.postInit(0);
+ _candle.setVisage(9500);
+ _candle.setStrip(1);
+ _candle.animate(ANIM_MODE_2);
+ _candle.setPosition(Common::Point(30, 105), 0);
+ if (RING_INVENTORY._candle._sceneNumber != 9500)
+ _candle.setStrip(2);
+
+ _object3.postInit(0);
+ _object3.hide();
+ _object3.fixPriority(150);
+ _object3.setPosition(Common::Point(166, 133));
+ if (RING_INVENTORY._straw._sceneNumber == 9500) {
+ _object3.show();
+ _object3.setVisage(5);
+ _object3._strip = 2;
+ _object3._frame = 9;
+ _object3.setPosition(Common::Point(168, 128));
+ if (_globals->getFlag(85)) {
+ _object3.setVisage(9500);
+ _object3.setStrip(4);
+ _object3.animate(ANIM_MODE_8, 0, 0);
+ _object3.setPosition(Common::Point(166, 133));
+ }
+ }
+
+ _object2.postInit(0);
+ _object2.hide();
+ if (_globals->getFlag(92)) {
+ _object2.show();
+ _object2.setVisage(9501);
+ _object2.setStrip(1);
+ _object2.setFrame(_object2.getFrameCount());
+ _object2.setPosition(Common::Point(303, 130));
+ _object2.fixPriority(132);
+ if (RING_INVENTORY._helmet._sceneNumber == 1) {
+ _hotspot2.setup(87, 294, 104, 314, 9400, 17, -1);
+ } else {
+ _object2.setStrip(2);
+ _object2.setFrame(1);
+ }
+ } else {
+ _hotspot1.setup(105, 295, 134, 313, 9500, 9, 10);
+ }
+
+ _hotspot17.setup(101, 293, 135, 315, 9500, 9, 10);
+ _hotspot3.setup(84, 12, 107, 47, 9500, 15, 15);
+ _hotspot6.setup(93, 11, 167, 46, 9500, 0, 1);
+ _hotspot7.setup(100, 70, 125, 139, 9500, 2, 3);
+
+ if (!_globals->getFlag(85)) {
+ _hotspot5.setup(111, 68, 155, 244, 9500, 17, -1);
+ _hotspot4.setup(57, 71, 120, 126, 9500, 16, -1);
+ }
+
+ _hotspot8.setup(60, 24, 90, 53, 9500, 4, 5);
+ _hotspot9.setup(72, 143, 93, 163, 9500, 4, 5);
+ _hotspot10.setup(70, 205, 92, 228, 9500, 4, 5);
+ _hotspot11.setup(66, 291, 90, 317, 9500, 4, 5);
+ _hotspot12.setup(22, 58, 101, 145, 9500, 6, 7);
+ _hotspot13.setup(121, 57, 163, 249, 9500, 6, 7);
+ _hotspot14.setup(115, 133, 135, 252, 9500, 6, 7);
+ _hotspot15.setup(55, 240, 125, 254, 9500, 6, 7);
+ _hotspot16.setup(53, 251, 132, 288, 9500, 8, -1);
+ _hotspot19.setup(101, 207, 120, 225, 9500, 9, 10);
+ _hotspot18.setup(98, 144, 117, 162, 9500, 9, 10);
+ _hotspot20.setup(102, 27, 132, 50, 9500, 9, 10);
+
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player.disableControl();
+
+ if ((_globals->_sceneManager._previousScene == 9200) || (_globals->_sceneManager._previousScene != 9850)) {
+ _sceneMode = 0;
+ if (RING_INVENTORY._helmet._sceneNumber != 1) {
+ setAction(&_sequenceManager, this, 9501, &_globals->_player, &_candle, 0);
+ } else {
+ RING_INVENTORY._helmet._sceneNumber = 9500;
+ _hotspot2.setup(87, 294, 104, 314, 9400, 17, -1);
+ setAction(&_sequenceManager, this, 9513, &_globals->_player, &_object2, 0);
+ }
+ } else {
+ _sceneMode = 0;
+ setAction(&_sequenceManager, this, 9502, &_globals->_player, &_candle, 0);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9700
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9700::signal() {
+ switch (_sceneMode ++) {
+ case 9703:
+ _globals->setFlag(88);
+ // No break on purpose
+ case 9701:
+ case 9702:
+ _gfxButton1.setText(EXIT_MSG);
+ _gfxButton1._bounds.center(50, 190);
+ _gfxButton1.draw();
+ _gfxButton1._bounds.expandPanes();
+ _globals->_player.enableControl();
+ _globals->_player._canWalk = 0;
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 9704:
+ _globals->_soundHandler.startSound(323);
+ _globals->_sceneManager.changeScene(9750);
+ break;
+ }
+}
+
+void Scene9700::process(Event &event) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && !_action) {
+ if (_gfxButton1.process(event)) {
+ _globals->_sceneManager.changeScene(9200);
+ } else if (_globals->_events._currentCursor == OBJECT_SCANNER) {
+ event.handled = true;
+ if (RING_INVENTORY._helmet._sceneNumber == 1) {
+ _globals->_player.disableControl();
+ _sceneMode = 9704;
+ setAction(&_sequenceManager, this, 9704, &_globals->_player, &_object1, 0);
+ } else {
+ _globals->_player.disableControl();
+ _sceneMode = 9703;
+ setAction(&_sequenceManager, this, 9703, &_globals->_player, &_object1, 0);
+ }
+ }
+ }
+}
+
+void Scene9700::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _sceneHotspot1.setup(84, 218, 151, 278, 9700, 14, -1);
+ _sceneHotspot2.setup(89, 11, 151, 121, 9700, 14, -1);
+ _sceneHotspot3.setup(69, 119, 138, 218, 9700, 15, 16);
+ _sceneHotspot4.setup(34, 13, 88, 116, 9700, 17, -1);
+ _sceneHotspot5.setup(52, 119, 68, 204, 9700, 17, -1);
+ _sceneHotspot6.setup(0, 22, 56, 275, 9700, 18, -1);
+
+ _object1.postInit();
+ _object1.hide();
+ _globals->_player.postInit();
+ if (_globals->getFlag(97)) {
+ _globals->_player.disableControl();
+ _sceneMode = 9701;
+ setAction(&_sequenceManager, this, 9701, &_globals->_player, &_object1, 0);
+ _globals->setFlag(97);
+ } else {
+ _globals->_player.disableControl();
+ _sceneMode = 9702;
+ setAction(&_sequenceManager, this, 9702, &_globals->_player, &_object1, 0);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9750
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9750::signal() {
+ switch (_sceneMode ++) {
+ case 9751:
+ _globals->_soundHandler.proc1(this);
+ break;
+ case 9752:
+ _globals->_sceneManager.changeScene(2100);
+ default:
+ break;
+ }
+}
+
+void Scene9750::dispatch() {
+ Scene::dispatch();
+}
+
+void Scene9750::postInit(SceneObjectList *OwnerList) {
+ loadScene(9750);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _globals->_player.postInit();
+ _object1.postInit();
+ _object1.hide();
+ _object2.postInit();
+ _object2.hide();
+ _globals->_player.disableControl();
+ _sceneMode = 9751;
+ setAction(&_sequenceManager, this, 9751, &_globals->_player, &_object1, &_object2, 0);
+}
+
+
+/*--------------------------------------------------------------------------
+ * Scene 9850
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9850::Object6::doAction(int action) {
+ if ((_flags & OBJFLAG_HIDE) == 0) {
+ if (action == CURSOR_LOOK) {
+ SceneItem::display(9850, 27, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else if (action == CURSOR_USE) {
+ RING_INVENTORY._scimitar._sceneNumber = 1;
+ hide();
+ } else {
+ SceneHotspot::doAction(action);
+ }
+ }
+}
+void Scene9850::Object7::doAction(int action) {
+ if ((_flags & OBJFLAG_HIDE) == 0) {
+ if (action == CURSOR_LOOK) {
+ SceneItem::display(9850, 28, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else if (action == CURSOR_USE) {
+ RING_INVENTORY._sword._sceneNumber = 1;
+ hide();
+ } else {
+ SceneHotspot::doAction(action);
+ }
+ }
+}
+
+// Hair covered tunic
+void Scene9850::Hotspot12::doAction(int action) {
+ Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_USE) {
+ if (RING_INVENTORY._tunic2._sceneNumber != 1) {
+ RING_INVENTORY._tunic2._sceneNumber = 1;
+ _globals->_player.disableControl();
+ scene->_sceneMode = 9858;
+ setAction(&scene->_sequenceManager, scene, 9858, &_globals->_player, &scene->_objTunic2, 0);
+ } else {
+ RING_INVENTORY._tunic2._sceneNumber = 9850;
+ _globals->_player.disableControl();
+ scene->_sceneMode = 9861;
+ setAction(&scene->_sequenceManager, scene, 9861, &_globals->_player, &scene->_objTunic2, 0);
+ }
+ } else if ((action != CURSOR_LOOK) || (RING_INVENTORY._tunic2._sceneNumber != 1)) {
+ NamedHotspot::doAction(action);
+ } else {
+ SceneItem::display(9850, 30, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ }
+}
+
+void Scene9850::Hotspot14::doAction(int action) {
+ Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_USE) {
+ if (RING_INVENTORY._jacket._sceneNumber != 1) {
+ RING_INVENTORY._jacket._sceneNumber = 1;
+ _globals->_player.disableControl();
+ scene->_sceneMode = 9857;
+ setAction(&scene->_sequenceManager, scene, 9857, &_globals->_player, &scene->_objJacket, NULL);
+ } else {
+ RING_INVENTORY._jacket._sceneNumber = 9850;
+ _globals->_player.disableControl();
+ scene->_sceneMode = 9860;
+ setAction(&scene->_sequenceManager, scene, 9860, &_globals->_player, &scene->_objJacket, NULL);
+ }
+ } else if ((action != CURSOR_LOOK) || (RING_INVENTORY._jacket._sceneNumber != 1)) {
+ NamedHotspot::doAction(action);
+ } else {
+ SceneItem::display(9850, 30, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ }
+}
+
+void Scene9850::Hotspot16::doAction(int action) {
+ Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_USE) {
+ if (RING_INVENTORY._cloak._sceneNumber != 1) {
+ RING_INVENTORY._cloak._sceneNumber = 1;
+ _globals->_player.disableControl();
+ scene->_sceneMode = 9862;
+ setAction(&scene->_sequenceManager, scene, 9862, &_globals->_player, &scene->_objCloak, 0);
+ } else {
+ RING_INVENTORY._cloak._sceneNumber = 9850;
+ _globals->_player.disableControl();
+ scene->_sceneMode = 9859;
+ setAction(&scene->_sequenceManager, scene, 9859, &_globals->_player, &scene->_objCloak, 0);
+ }
+ } else if ((action != CURSOR_LOOK) || (RING_INVENTORY._cloak._sceneNumber != 1)) {
+ NamedHotspot::doAction(action);
+ } else {
+ SceneItem::display(9850, 30, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ }
+}
+
+void Scene9850::Hotspot17::doAction(int action) {
+ Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene;
+
+ if (action == OBJECT_SCANNER) {
+ SceneItem::display(9850, 32, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else {
+ if (action == CURSOR_USE)
+ scene->_soundHandler.startSound(306);
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9850::Hotspot18::doAction(int action) {
+ Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene;
+
+ if (action == OBJECT_SCANNER) {
+ SceneItem::display(9850, 32, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else {
+ if (action == CURSOR_USE)
+ scene->_soundHandler.startSound(306);
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9850::Hotspot19::doAction(int action) {
+ Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene;
+
+ if (action == OBJECT_SCANNER) {
+ SceneItem::display(9850, 31, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else {
+ if (action == CURSOR_USE)
+ scene->_soundHandler.startSound(313);
+ NamedHotspot::doAction(action);
+ }
+}
+
+// Arrow on Statue
+void Scene9850::Hotspot20::doAction(int action) {
+ Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_USE) {
+ _globals->_player.disableControl();
+ if (scene->_objSword._state == 0) {
+ if (RING_INVENTORY._scimitar._sceneNumber == 9850)
+ scene->_objScimitar.show();
+ if (RING_INVENTORY._sword._sceneNumber == 9850)
+ scene->_objSword.show();
+ scene->_sceneMode = 11;
+ setAction(&scene->_sequenceManager, scene, 9853, &_globals->_player, &scene->_objDoor, &scene->_objLever, 0);
+ } else {
+ scene->_sceneMode = 10;
+ setAction(&scene->_sequenceManager, scene, 9854, &_globals->_player, &scene->_objDoor, &scene->_objLever, 0);
+ }
+ scene->_objSword._state ^= 1;
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene9850::signal() {
+ switch (_sceneMode ++) {
+ case 10:
+ // Hidden closet closed
+ if (RING_INVENTORY._scimitar._sceneNumber == 9850)
+ _objScimitar.hide();
+ if (RING_INVENTORY._sword._sceneNumber == 9850)
+ _objSword.hide();
+ _globals->_sceneItems.remove(&_objScimitar);
+ _globals->_sceneItems.remove(&_objSword);
+ _globals->_sceneItems.addItems(&_hotspot19, NULL);
+ _globals->_player.enableControl();
+ break;
+ case 11:
+ // Hidden closet opened
+ if (RING_INVENTORY._scimitar._sceneNumber == 9850)
+ _globals->_sceneItems.addItems(&_objScimitar, NULL);
+ if (RING_INVENTORY._sword._sceneNumber == 9850)
+ _globals->_sceneItems.addItems(&_objSword, NULL);
+ _globals->_sceneItems.remove(&_hotspot19);
+ _globals->_player.enableControl();
+ break;
+ case 9500:
+ _globals->_sceneManager.changeScene(_sceneMode - 1);
+ break;
+ case 0:
+ default:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene9850::process(Event &event) {
+ Scene::process(event);
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_4)) {
+ event.handled = true;
+ _globals->_player.disableControl();
+ if (_objSword._state == 0) {
+ _sceneMode = 0;
+ setAction(&_sequenceManager, this, 9853, &_objLever, &_objDoor, &_objScimitar, &_objSword, 0);
+ } else {
+ _sceneMode = 10;
+ setAction(&_sequenceManager, this, 9854, &_objLever, &_objDoor, &_objScimitar, &_objSword, 0);
+ }
+ _objSword._state ^= 1;
+ }
+}
+
+void Scene9850::dispatch() {
+ if (_action) {
+ _action->dispatch();
+ } else if (_globals->_player._position.y >= 198) {
+ _globals->_player.disableControl();
+ _sceneMode = 9500;
+ setAction(&_sequenceManager, this, 9852, &_globals->_player, 0);
+ }
+}
+
+void Scene9850::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ _objSword._state = 0;
+
+ _objDoor.postInit();
+ _objDoor.setVisage(9850);
+ _objDoor.setStrip(1);
+ _objDoor.setFrame(1);
+ _objDoor.setPosition(Common::Point(28, 118));
+ _objDoor.fixPriority(90);
+
+ _objLever.postInit();
+ _objLever.setVisage(9850);
+ _objLever.setStrip(4);
+ _objLever.setFrame(1);
+ _objLever.setPosition(Common::Point(256, 35));
+
+ _objCloak.postInit();
+ _objCloak.setVisage(9850);
+ _objCloak.setStrip(5);
+ _objCloak.setFrame(1);
+ _objCloak.fixPriority(90);
+ _objCloak.setPosition(Common::Point(157, 81));
+ if (RING_INVENTORY._cloak._sceneNumber != 9850)
+ _objCloak.hide();
+
+ _objJacket.postInit();
+ _objJacket.setVisage(9850);
+ _objJacket.setStrip(5);
+ _objJacket.setFrame(2);
+ _objJacket.fixPriority(90);
+ _objJacket.setPosition(Common::Point(201, 84));
+ if (RING_INVENTORY._jacket._sceneNumber != 9850)
+ _objJacket.hide();
+
+ _objTunic2.postInit();
+ _objTunic2.setVisage(9850);
+ _objTunic2.setStrip(5);
+ _objTunic2.setFrame(3);
+ _objTunic2.fixPriority(90);
+ _objTunic2.setPosition(Common::Point(295, 90));
+ if (RING_INVENTORY._tunic2._sceneNumber != 9850)
+ _objTunic2.hide();
+
+ if (RING_INVENTORY._scimitar._sceneNumber == 9850) {
+ _objScimitar.postInit();
+ _objScimitar.setVisage(9850);
+ _objScimitar.setStrip(2);
+ _objScimitar.setFrame(1);
+ _objScimitar.setPosition(Common::Point(55, 83));
+ _objScimitar.fixPriority(80);
+ _objScimitar.hide();
+ }
+
+ if (RING_INVENTORY._sword._sceneNumber == 9850) {
+ _objSword.postInit();
+ _objSword.setVisage(9850);
+ _objSword.setStrip(3);
+ _objSword.setFrame(1);
+ _objSword.setPosition(Common::Point(56, 101));
+ _objSword.fixPriority(80);
+ _objSword.hide();
+ }
+
+ _spotLever.setup(30, 251, 45, 270, 9850, 26, -1);
+ _hotspot1.setup(123, 0, 200, 320, 9850, 0, 1);
+ _hotspot2.setup(107, 87, 133, 308, 9850, 0, 1);
+ _hotspot3.setup(2, 28, 53, 80, 9850, 2, 3);
+ _hotspot4.setup(13, 0, 55, 27, 9850, 2, 3);
+ _hotspot5.setup(8, 74, 27, 91, 9850, 4, 5);
+ _hotspot17.setup(61, 0, 125, 28, 9850, 6, 7);
+ _hotspot18.setup(51, 95, 105, 145, 9850, 6, 7);
+ _hotspot19.setup(56, 28, 115, 97, 9850, 6, 8);
+ _hotspot6.setup(0, 223, 115, 257, 9850, 9, 10);
+ _hotspot7.setup(15, 254, 33, 268, 9850, 9, -1);
+ _hotspot8.setup(17, 218, 37, 233, 9850, 9, 10);
+ _hotspot9.setup(8, 113, 26, 221, 9850, 11, 12);
+ _hotspot10.setup(14, 94, 53, 112, 9850, 13, 14);
+ _hotspot11.setup(5, 269, 29, 303, 9850, 15, 16);
+ _hotspot12.setup(43, 278, 91, 317, 9850, 17, 18);
+ _hotspot13.setup(47, 263, 112, 282, 9850, 19, 20);
+ _hotspot14.setup(43, 188, 86, 224, 9850, 21, 22);
+ _hotspot15.setup(43, 162, 92, 191, 9850, 23, 24);
+ _hotspot16.setup(40, 146, 90, 169, 9850, 25, -1);
+
+ _globals->_player.postInit();
+ _globals->_player.disableControl();
+ _sceneMode = 0;
+ setAction(&_sequenceManager, this, 9851, &_globals->_player, 0);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9900
+ *
+ *--------------------------------------------------------------------------*/
+void Scene9900::strAction1::signal() {
+ const byte mask1[3] = {0xff, 0xff, 0xff};
+ const byte mask2[3] = {0, 0, 0};
+
+ Scene9900 *scene = (Scene9900 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_soundHandler.startSound(351);
+ _object9.postInit();
+ _object9.setVisage(18);
+ _object9._frame = 1;
+ _object9._strip = 6;
+ _object9.fixPriority(250);
+ _object9.setPosition(Common::Point(171, 59));
+ _object9.animate(ANIM_MODE_5, 0);
+ _globals->_scenePalette.addRotation(67, 111, 1, 1, this);
+ scene->_object2.hide();
+ break;
+ case 1:
+ _palette1.getPalette();
+ _globals->_scenePalette.addFader(&mask1[0], 1, 10, this);
+ break;
+ case 2:
+ _object9.remove();
+ _globals->_scenePalette.addFader(&mask2[0], 1, 5, this);
+ break;
+ case 3:
+ _globals->_soundHandler.startSound(377);
+ setDelay(120);
+ break;
+ case 4:
+ _globals->_scenePalette.addFader(_palette1._palette, 256, 1, this);
+ break;
+ case 5:
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene9900::strAction2::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ _lineNum = 0;
+ _txtArray1Index = 0;
+ _txtArray1[0]._position.y = 200;
+ _txtArray1[1]._position.y = 300;
+ _txtArray2[0]._position.y = 400;
+ _txtArray2[1]._position.y = 500;
+ _var3 = 0;
+ // No break on purpose
+ case 1: {
+ Common::String msg = _resourceManager->getMessage(8030, _lineNum++);
+ if (msg.compareTo("LASTCREDIT")) {
+ if (_var3) {
+ // Not used?
+ // int x = _txtArray1[_txtArray1Index].getFrame().getBounds().height();
+ _txtArray1[_txtArray1Index]._moveDiff.y = 10;
+
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(_txtArray1[_txtArray1Index]._position.x, -100);
+ _txtArray1[_txtArray1Index].addMover(mover, &pt, NULL);
+
+ // Not used?
+ // int x = _txtArray2[_txtArray1Index].getFrame().getBounds().height();
+ _txtArray2[_txtArray1Index]._moveDiff.y = 10;
+ _txtArray1Index = (_txtArray1Index + 1) % 2;
+ }
+ _var3 = 1;
+ _txtArray1[_txtArray1Index]._textMode = ALIGN_CENTER;
+ _txtArray1[_txtArray1Index]._width = 240;
+ _txtArray1[_txtArray1Index]._fontNumber = 2;
+ _txtArray1[_txtArray1Index]._color1 = 7;
+ _txtArray1[_txtArray1Index].setup(msg);
+ _txtArray1[_txtArray1Index]._moveRate = 20;
+ _txtArray1[_txtArray1Index]._moveDiff.y = 2;
+ _txtArray1[_txtArray1Index].fixPriority(255);
+ int frameWidth = _txtArray1[_txtArray1Index].getFrame().getBounds().width();
+ int frameHeight = _txtArray1[_txtArray1Index].getFrame().getBounds().height();
+ _txtArray1[_txtArray1Index].setPosition(Common::Point((320 - frameWidth) / 2, 200));
+
+ NpcMover *mover2 = new NpcMover();
+ Common::Point pt2(_txtArray1[_txtArray1Index]._position.x, 100);
+ _txtArray1[_txtArray1Index].addMover(mover2, &pt2, this);
+
+ _txtArray2[_txtArray1Index]._textMode = ALIGN_CENTER;
+ _txtArray2[_txtArray1Index]._width = 240;
+ _txtArray2[_txtArray1Index]._fontNumber = 2;
+ _txtArray2[_txtArray1Index]._color1 = 23;
+
+ msg = _resourceManager->getMessage(8030, _lineNum++);
+ _txtArray2[_txtArray1Index].setup(msg);
+ _txtArray2[_txtArray1Index]._moveRate = 20;
+ _txtArray2[_txtArray1Index]._moveDiff.y = 2;
+ _txtArray2[_txtArray1Index].fixPriority(255);
+ frameWidth = _txtArray2[_txtArray1Index].getFrame().getBounds().width();
+ _txtArray2[_txtArray1Index].setPosition(Common::Point((320 - frameWidth) / 2, 200 + frameHeight));
+ } else {
+ _globals->_player.enableControl();
+ _actionIndex = 3;
+ signal();
+ }
+ break;
+ }
+ case 2:
+ setDelay(60);
+ _actionIndex = 1;
+ break;
+ case 3:
+ setDelay(7200);
+ break;
+ case 4:
+ _txtArray1[0].remove();
+ _txtArray1[1].remove();
+ _txtArray2[0].remove();
+ _txtArray2[1].remove();
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+void Scene9900::strAction2::dispatch() {
+// if (this->_txtArray1[0]._textSurface != 0) {
+ int frameHeight = _txtArray1[0].getFrame().getBounds().height();
+ _txtArray2[0]._position.y = frameHeight + _txtArray1[0]._position.y;
+ _txtArray2[0]._flags |= OBJFLAG_PANES;
+// }
+// if (this->_txtArray1[1]._textSurface != 0) {
+ frameHeight = _txtArray1[1].getFrame().getBounds().height();
+ _txtArray2[1]._position.y = frameHeight + _txtArray1[1]._position.y;
+ _txtArray2[1]._flags |= OBJFLAG_PANES;
+// }
+ Action::dispatch();
+}
+
+void Scene9900::strAction3::signal() {
+ const byte mask3[3] = {0xff, 0, 0};
+ const byte mask4[3] = {0, 0, 0};
+
+ switch (_actionIndex++) {
+ case 0:
+ _palette2.getPalette();
+ _palette3.loadPalette(2003);
+ _globals->_scenePalette.addFader(_palette3._palette, 256, 5, this);
+ break;
+ case 1:
+ _globals->_scenePalette.addFader(&mask3[0], 1, 10, this);
+ break;
+ case 2:
+ _globals->_scenePalette.addFader(&mask4[0], 1, 1, this);
+ break;
+ case 3:
+ _palette2.loadPalette(17);
+ _globals->_sceneManager._scene->loadScene(17);
+ _globals->_scenePalette.addFader(_palette2._palette, 256, 5, this);
+ break;
+ case 4:
+ _globals->_game->endGame(9900, 61);
+ remove();
+ default:
+ break;
+ }
+}
+
+void Scene9900::signal() {
+ if ((_sceneMode != 9913) && (_sceneMode != 9905) && (_sceneMode != 9904) && (_sceneMode != 9912)) {
+ _object1.hide();
+ _object2.hide();
+ _object3.hide();
+ _object4.hide();
+ _object5.hide();
+ _object6.hide();
+ }
+
+ _object1.animate(ANIM_MODE_NONE, 0);
+ _object2.animate(ANIM_MODE_NONE, 0);
+ _object3.animate(ANIM_MODE_NONE, 0);
+ _object4.animate(ANIM_MODE_NONE, 0);
+ _object5.animate(ANIM_MODE_NONE, 0);
+ _object6.animate(ANIM_MODE_NONE, 0);
+
+ _object1.setObjectWrapper(0);
+ _object2.setObjectWrapper(0);
+ _object3.setObjectWrapper(0);
+ _object4.setObjectWrapper(0);
+ _object5.setObjectWrapper(0);
+ _object6.setObjectWrapper(0);
+
+ _object1.addMover(0);
+ _object2.addMover(0);
+ _object3.addMover(0);
+ _object4.addMover(0);
+ _object5.addMover(0);
+ _object6.addMover(0);
+
+ switch (_sceneMode){
+ case 150:
+ _globals->_soundHandler.startSound(380);
+ _object8.postInit(0);
+ _object8.setVisage(2002);
+ _object8.setStrip(1);
+ _object8.setFrame(1);
+ _object8.fixPriority(200);
+ _object8.setPosition(Common::Point(64, 199));
+ _globals->_player.disableControl();
+ _sceneMode = 9908;
+ setAction(&_sequenceManager, this, 9908, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ break;
+ case 162:
+ warning("TBC: shutdown();");
+ _globals->_game->quitGame();
+ break;
+ case 9901:
+ _globals->_player.disableControl();
+ _sceneMode = 9906;
+ setAction(&_sequenceManager, this, 9906, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ _globals->_player._uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 9902:
+ _globals->_player.disableControl();
+ _sceneMode = 9901;
+ setAction(&_sequenceManager, this, 9901, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ break;
+ case 9903:
+ _globals->_player.disableControl();
+ _sceneMode = 9902;
+ setAction(&_sequenceManager, this, 9902, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ break;
+ case 9904:
+ _globals->_soundHandler.startSound(390);
+ _sceneMode = 9912;
+ setAction(&_strAction2, this);
+ break;
+ case 9905:
+ _sceneMode = 150;
+ setAction(&_strAction1, this);
+ break;
+ case 9906:
+ if (_object8._state == 0) {
+ _globals->_player.disableControl();
+ _sceneMode = 9913;
+ setAction(&_sequenceManager, this, 9913, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ } else {
+ _globals->_player.disableControl();
+ _sceneMode = 9905;
+ setAction(&_sequenceManager, this, 9905, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ }
+ break;
+ case 9907:
+ _globals->_player.disableControl();
+ _sceneMode = 9903;
+ setAction(&_sequenceManager, this, 9903, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ break;
+ case 9908:
+ _object8.remove();
+ _globals->_player.disableControl();
+ _sceneMode = 9904;
+ setAction(&_sequenceManager, this, 9904, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ break;
+ case 9909:
+ _globals->_soundHandler.startSound(375);
+ _globals->_player.disableControl();
+ _sceneMode = 9907;
+ setAction(&_sequenceManager, this, 9907, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ break;
+ case 9910:
+ _globals->_player.disableControl();
+ _sceneMode = 9911;
+ setAction(&_sequenceManager, this, 9911, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ break;
+ case 9911:
+ _globals->_soundHandler.startSound(367);
+ _globals->_player.disableControl();
+ _sceneMode = 9909;
+ setAction(&_sequenceManager, this, 9909, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ break;
+ case 9912:
+ _globals->_player.disableControl();
+ _sceneMode = 9912;
+ setAction(&_sequenceManager, this, 9912, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+ _sceneMode = 162;
+ _globals->_player.enableControl();
+ _globals->_player._canWalk = false;
+ break;
+ case 9913:
+ _sceneMode = 200;
+ setAction(&_strAction3, this);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene9900::process(Event &event) {
+ if (event.handled)
+ return;
+ Scene::process(event);
+ if (_sceneMode == 9906) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (_globals->_events.getCursor() == OBJECT_ITEMS)) {
+ _object8._state = 1;
+ RING_INVENTORY._items._sceneNumber = 9900;
+ _globals->_events.setCursor(CURSOR_USE);
+ }
+ }
+}
+
+void Scene9900::dispatch() {
+ if (_action)
+ _action->dispatch();
+}
+
+void Scene9900::postInit(SceneObjectList *OwnerList) {
+ _object1.postInit(0);
+ _object1.hide();
+ _object2.postInit(0);
+ _object2.hide();
+ _object3.postInit(0);
+ _object3.hide();
+ _object4.postInit(0);
+ _object4.hide();
+ _object5.postInit(0);
+ _object5.hide();
+ _object6.postInit(0);
+ _object6.hide();
+
+ _object8._state = 0;
+
+ RING_INVENTORY._concentrator._sceneNumber = 9900;
+ RING_INVENTORY._items._rlbNum = 3;
+ RING_INVENTORY._items._cursorNum = 6;
+ RING_INVENTORY._items._description = Common::String("One of the items from the stasis ship. The other is on the Lance's bridge.");
+
+ _stripManager.addSpeaker(&_speakerMR);
+ _globals->_player.disableControl();
+ _sceneMode = 9910;
+ setAction(&_sequenceManager, this, 9910, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 9999
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene9999::Action1::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(600);
+ break;
+ case 1:
+ _globals->_sceneManager.changeScene(3500);
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene9999::Action2::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ SceneItem::display(9999, 0, SET_Y, 10, SET_X, 30, SET_FONT, 2, SET_BG_COLOR, -1, SET_EXT_BGCOLOR, 23, SET_WIDTH, 260, SET_KEEP_ONSCREEN, 1, LIST_END);
+ setDelay(300);
+ break;
+ case 2:
+ _globals->_stripNum = 3600;
+ _globals->_sceneManager.changeScene(3600);
+ default:
+ break;
+ }
+}
+
+void Scene9999::postInit(SceneObjectList *OwnerList) {
+ loadScene(9998);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _object1.postInit();
+ _object1.setVisage(1303);
+ _object1.setStrip2(3);
+ _object1.setPosition(Common::Point(160, 152), 0);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(1303);
+ _globals->_player.setStrip2(1);
+ _globals->_player.fixPriority(250);
+ _globals->_player.animate(ANIM_MODE_2, 0);
+ _globals->_player.setPosition(Common::Point(194, 98), 0);
+ _globals->_player._numFrames = 20;
+ _globals->_player.disableControl();
+
+ _object2.postInit();
+ _object2.setVisage(1303);
+ _object2.setStrip2(2);
+ _object2.fixPriority(2);
+ _object2.setPosition(Common::Point(164, 149), 0);
+
+ _object3.postInit();
+ _object3.setVisage(1303);
+ _object3.setStrip2(2);
+ _object3.fixPriority(2);
+ _object3.setFrame(2);
+ _object3.setPosition(Common::Point(292, 149), 0);
+ _object3.setAction(&_action3);
+
+ if (_globals->_sceneManager._previousScene == 3500)
+ setAction(&_action2);
+ else
+ setAction(&_action1);
+
+ _globals->_sceneManager._scene->_sceneBounds.center(_globals->_player._position.x, _globals->_player._position.y);
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+
+ if (_globals->_sceneManager._previousScene == 3500)
+ _globals->_stripNum = 2222;
+ else
+ _globals->_stripNum = 2121;
+
+ _globals->_soundHandler.startSound(118);
+
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes10.h b/engines/tsage/ringworld_scenes10.h
new file mode 100644
index 0000000000..2f5ce0f825
--- /dev/null
+++ b/engines/tsage/ringworld_scenes10.h
@@ -0,0 +1,533 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_SCENES10_H
+#define TSAGE_RINGWORLD_SCENES10_H
+
+#include "common/scummsys.h"
+#include "tsage/ringworld_logic.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+class SceneObject9150 : public SceneObject {
+public:
+ int _timer, _signalFlag;
+
+ virtual void synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+ s.syncAsSint16LE(_timer);
+ s.syncAsSint16LE(_signalFlag);
+ }
+ virtual Common::String getClassName() { return "SceneObject9150"; }
+};
+
+class Scene2 : public Scene {
+public :
+ int _sceneState;
+
+ Scene2();
+ virtual void synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ s.syncAsSint16LE(_sceneState);
+ }
+};
+
+class Object9350 : public SceneObject {
+public:
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void draw();
+};
+
+class Scene9100 : public Scene {
+ /* Items */
+ class SceneHotspot1 : public NamedHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SceneObject _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+ SceneObject _object4;
+ SceneObject _object5;
+ SceneObject _object6;
+ SceneHotspot1 _sceneHotspot1;
+ NamedHotspot _sceneHotspot2;
+ NamedHotspot _sceneHotspot3;
+ NamedHotspot _sceneHotspot4;
+ NamedHotspot _sceneHotspot5;
+ NamedHotspot _sceneHotspot6;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene9150 : public Scene2 {
+ class Object3 : public SceneObject9150 {
+ public:
+ virtual void signal();
+ virtual void dispatch();
+ };
+public:
+ SequenceManager _sequenceManager1;
+ SequenceManager _sequenceManager2;
+ SceneObject _object1;
+ SceneObject _object2;
+ Object3 _object3;
+ NamedHotspot _sceneHotspot1;
+ NamedHotspot _sceneHotspot2;
+ NamedHotspot _sceneHotspot3;
+ NamedHotspot _sceneHotspot4;
+ NamedHotspot _sceneHotspot5;
+ NamedHotspot _sceneHotspot6;
+ NamedHotspot _sceneHotspot7;
+ NamedHotspot _sceneHotspot8;
+ NamedHotspot _sceneHotspot9;
+ NamedHotspot _sceneHotspot10;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene9200 : public Scene2 {
+ class SceneHotspot1 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SceneObject _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+ Action _action1;
+ SpeakerGText _speakerGText;
+ SpeakerGR _speakerGR;
+ SpeakerQText _speakerQText;
+ SoundHandler _soundHandler;
+ SceneHotspot1 _hotspot1;
+ NamedHotspot _hotspot2;
+ NamedHotspot _hotspot3;
+ NamedHotspot _hotspot4;
+ NamedHotspot _hotspot5;
+ NamedHotspot _hotspot6;
+ NamedHotspot _hotspot7;
+ NamedHotspot _hotspot8;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+ virtual void process(Event &event);
+};
+
+class Scene9300 : public Scene {
+public:
+ SequenceManager _sequenceManager;
+ SceneObject _object1;
+ SceneObject _object2;
+ NamedHotspot _hotspot1;
+ NamedHotspot _hotspot2;
+ NamedHotspot _hotspot3;
+ NamedHotspot _hotspot4;
+ NamedHotspot _hotspot5;
+ NamedHotspot _hotspot6;
+ NamedHotspot _hotspot7;
+ NamedHotspot _hotspot8;
+ NamedHotspot _hotspot9;
+ NamedHotspot _hotspot10;
+ NamedHotspot _hotspot11;
+ NamedHotspot _hotspot12;
+ NamedHotspot _hotspot13;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene9350 : public Scene2 {
+public:
+ SequenceManager _sequenceManager;
+ Object9350 _object1;
+ SceneObject _object2;
+ NamedHotspot _sceneHotspot1;
+ NamedHotspot _sceneHotspot2;
+ NamedHotspot _sceneHotspot3;
+ NamedHotspot _sceneHotspot4;
+ NamedHotspot _sceneHotspot5;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene9360 : public Scene2 {
+public:
+ SequenceManager _sequenceManager;
+ Action _action1;
+ Object9350 _object1;
+ NamedHotspot _hotspot1;
+ NamedHotspot _hotspot2;
+ NamedHotspot _hotspot3;
+ NamedHotspot _hotspot4;
+ NamedHotspot _hotspot5;
+ NamedHotspot _hotspot6;
+ NamedHotspot _hotspot7;
+ NamedHotspot _hotspot8;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene9400 : public Scene2 {
+ class SceneHotspot7 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class SceneHotspot8 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ Scene9400();
+ SequenceManager _sequenceManager;
+ Action _action1;
+ SceneObject _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+ SpeakerOText _speakerOText;
+ SpeakerOR _speakerOR;
+ SpeakerQText _speakerQText;
+ NamedHotspot _hotspot1;
+ NamedHotspot _hotspot2;
+ NamedHotspot _hotspot3;
+ NamedHotspot _hotspot4;
+ NamedHotspot _hotspot5;
+ NamedHotspot _hotspot6;
+ SoundHandler _soundHandler;
+ int _field1032;
+ SceneHotspot7 _hotspot7;
+ SceneHotspot8 _hotspot8;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene9450 : public Scene2 {
+ class Object2 : public SceneObject {
+ public:
+ virtual void signal();
+ };
+
+ class Object3 : public SceneObject9150 {
+ public:
+ virtual void dispatch();
+ };
+
+ class Hotspot1 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot3 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SceneObject _object1;
+ SequenceManager _sequenceManager1;
+ SequenceManager _sequenceManager2;
+ Object2 _object2;
+ SequenceManager _sequenceManager3;
+ Object3 _object3;
+ Hotspot1 _hotspot1;
+ NamedHotspot _hotspot2;
+ Hotspot3 _hotspot3;
+ NamedHotspot _hotspot4;
+ NamedHotspot _hotspot5;
+ NamedHotspot _hotspot6;
+ NamedHotspot _hotspot7;
+ NamedHotspot _hotspot8;
+ NamedHotspot _hotspot9;
+ NamedHotspot _hotspot10;
+ NamedHotspot _hotspot11;
+ NamedHotspot _hotspot12;
+ NamedHotspot _hotspot13;
+ NamedHotspot _hotspot14;
+ NamedHotspot _hotspot15;
+ NamedHotspot _hotspot16;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene9500 : public Scene2 {
+ class Hotspot1 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot2 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot3 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot4 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ SequenceManager _sequenceManager;
+ SceneObject _candle;
+ SceneObject _object2;
+ SceneObject _object3;
+ Hotspot1 _hotspot1;
+ Hotspot2 _hotspot2;
+ Hotspot3 _hotspot3;
+ Hotspot4 _hotspot4;
+ Hotspot4 _hotspot5;
+ NamedHotspot _hotspot6;
+ NamedHotspot _hotspot7;
+ NamedHotspot _hotspot8;
+ NamedHotspot _hotspot9;
+ NamedHotspot _hotspot10;
+ NamedHotspot _hotspot11;
+ NamedHotspot _hotspot12;
+ NamedHotspot _hotspot13;
+ NamedHotspot _hotspot14;
+ NamedHotspot _hotspot15;
+ NamedHotspot _hotspot16;
+ NamedHotspot _hotspot17;
+ NamedHotspot _hotspot18;
+ NamedHotspot _hotspot19;
+ NamedHotspot _hotspot20;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+ virtual void process(Event &event);
+};
+
+class Scene9700 : public Scene2 {
+ SequenceManager _sequenceManager;
+ SceneObject _object1;
+ NamedHotspot _sceneHotspot1;
+ NamedHotspot _sceneHotspot2;
+ NamedHotspot _sceneHotspot3;
+ NamedHotspot _sceneHotspot4;
+ NamedHotspot _sceneHotspot5;
+ NamedHotspot _sceneHotspot6;
+ GfxButton _gfxButton1;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void process(Event &event);
+};
+
+class Scene9750 : public Scene {
+public:
+ SequenceManager _sequenceManager;
+ SceneObject _object1;
+ SceneObject _object2;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene9850 : public Scene {
+ class Object6 : public SceneObject{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Object7 : public SceneObjectExt{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot12 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot14 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot16 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot17 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot18 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot19 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot20 : public NamedHotspot{
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SceneObject _objDoor;
+ SceneObject _objCloak;
+ SceneObject _objJacket;
+ SceneObject _objTunic2;
+ SceneObject _objLever;
+ Object6 _objScimitar;
+ Object7 _objSword;
+ SoundHandler _soundHandler;
+ NamedHotspot _hotspot1;
+ NamedHotspot _hotspot2;
+ NamedHotspot _hotspot3;
+ NamedHotspot _hotspot4;
+ NamedHotspot _hotspot5;
+ NamedHotspot _hotspot6;
+ NamedHotspot _hotspot7;
+ NamedHotspot _hotspot8;
+ NamedHotspot _hotspot9;
+ NamedHotspot _hotspot10;
+ NamedHotspot _hotspot11;
+ Hotspot12 _hotspot12;
+ NamedHotspot _hotspot13;
+ Hotspot14 _hotspot14;
+ NamedHotspot _hotspot15;
+ Hotspot16 _hotspot16;
+ Hotspot17 _hotspot17;
+ Hotspot18 _hotspot18;
+ Hotspot19 _hotspot19;
+ Hotspot20 _spotLever;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void process(Event &event);
+ virtual void dispatch();
+};
+
+class Scene9900 : public Scene {
+ class strAction1 : public Action {
+ public:
+ SceneObject _object9;
+ ScenePalette _palette1;
+
+ virtual void signal();
+ };
+
+ class strAction2 : public Action {
+ public:
+ SceneText _txtArray1[2];
+ SceneText _txtArray2[2];
+ int _lineNum, _txtArray1Index, _var3;
+
+ virtual void signal();
+ virtual void dispatch();
+ };
+
+ class strAction3 : public Action {
+ public:
+ SceneObject _object10;
+ ScenePalette _palette2;
+ ScenePalette _palette3;
+
+ virtual void signal();
+ };
+
+public:
+ SoundHandler _soundHandler;
+ SequenceManager _sequenceManager;
+ SceneObject _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+ SceneObject _object4;
+ SceneObject _object5;
+ SceneObject _object6;
+ SceneObject _object7;
+ SceneObjectExt _object8;
+ strAction1 _strAction1;
+ strAction2 _strAction2;
+ strAction3 _strAction3;
+ SpeakerMR _speakerMR;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+ virtual void process(Event &event);
+};
+
+class Scene9999 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+
+public:
+
+ Action1 _action1;
+ Action2 _action2;
+ Action _action3;
+ SceneObject _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_scenes2.cpp b/engines/tsage/ringworld_scenes2.cpp
new file mode 100644
index 0000000000..6a8db81adf
--- /dev/null
+++ b/engines/tsage/ringworld_scenes2.cpp
@@ -0,0 +1,927 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/config-manager.h"
+#include "tsage/ringworld_scenes2.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+/*--------------------------------------------------------------------------
+ * Scene 1000 - Title Screen
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene1000::Action1::signal() {
+ Scene1000 *scene = (Scene1000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(10);
+ break;
+ case 1:
+ scene->_object4.postInit();
+ scene->_object4.setVisage(1001);
+ scene->_object4._frame = 1;
+ scene->_object4.setStrip2(5);
+ scene->_object4.changeZoom(100);
+ scene->_object4.animate(ANIM_MODE_2, NULL);
+ scene->_object4.setPosition(Common::Point(403, 163));
+ setDelay(90);
+ break;
+ case 2: {
+ SceneItem::display(0, 0);
+ scene->_object4.remove();
+ scene->_object1.changeZoom(-1);
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(180, 100);
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ _globals->_sceneManager.changeScene(1400);
+ break;
+ }
+
+}
+
+void Scene1000::Action2::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(10);
+ break;
+ case 1:
+ SceneItem::display(1000, 0, SET_Y, 20, SET_FONT, 2, SET_BG_COLOR, -1,
+ SET_EXT_BGCOLOR, 35, SET_WIDTH, 200, SET_KEEP_ONSCREEN, 1, LIST_END);
+ setDelay(180);
+ break;
+ case 2:
+ SceneItem::display(0, 0);
+ _globals->_sceneManager.changeScene(2000);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene1000::Action3::signal() {
+ Scene1000 *scene = (Scene1000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_sceneManager._scene->loadBackground(0, 0);
+ setDelay(60);
+ break;
+ case 1: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(158, 31);
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ case 3:
+ setDelay(60);
+ break;
+ case 4:
+ _globals->_player.show();
+ setDelay(240);
+ break;
+ case 5: {
+ const char *SEEN_INTRO = "seen_intro";
+ if (!ConfMan.hasKey(SEEN_INTRO) || !ConfMan.getBool(SEEN_INTRO)) {
+ // First time being played, so show the introduction
+ ConfMan.setBool(SEEN_INTRO, true);
+ ConfMan.flushToDisk();
+ setDelay(1);
+ } else {
+ // Prompt user for whether to start play or watch introduction
+ _globals->_player.enableControl();
+
+ if (MessageDialog::show2(WATCH_INTRO_MSG, START_PLAY_BTN_STRING, INTRODUCTION_BTN_STRING) == 0) {
+ _actionIndex = 20;
+ _globals->_soundHandler.proc1(this);
+ } else {
+ setDelay(1);
+ }
+ }
+
+ _globals->_player.disableControl();
+ break;
+ }
+ case 6: {
+ scene->_object3.remove();
+ _globals->_player.setStrip2(2);
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(480, 100);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 7:
+ _globals->_scenePalette.loadPalette(1002);
+ _globals->_scenePalette.refresh();
+ _globals->_scenePalette.addRotation(80, 95, -1);
+ scene->_object3.postInit();
+ scene->_object3.setVisage(1002);
+ scene->_object3.setStrip(1);
+ scene->_object3.setPosition(Common::Point(284, 122));
+ scene->_object3.changeZoom(1);
+
+ zoom(true);
+ setDelay(200);
+ break;
+ case 8:
+ zoom(false);
+ setDelay(10);
+ break;
+ case 9:
+ scene->_object3.setStrip(2);
+ scene->_object3.setPosition(Common::Point(285, 155));
+
+ zoom(true);
+ setDelay(400);
+ break;
+ case 10:
+ zoom(false);
+ setDelay(10);
+ break;
+ case 11:
+ scene->_object3.setStrip(3);
+ scene->_object3.setPosition(Common::Point(279, 172));
+
+ zoom(true);
+ setDelay(240);
+ break;
+ case 12:
+ zoom(false);
+ setDelay(10);
+ break;
+ case 13:
+ scene->_object3.setStrip(4);
+ scene->_object3.setPosition(Common::Point(270, 128));
+
+ zoom(true);
+ setDelay(300);
+ break;
+ case 14:
+ zoom(false);
+ setDelay(10);
+ break;
+ case 15:
+ scene->_object3.setStrip(1);
+ scene->_object3.setFrame(2);
+ scene->_object3.setPosition(Common::Point(283, 137));
+
+ zoom(true);
+ setDelay(300);
+ break;
+ case 16:
+ zoom(false);
+ setDelay(10);
+ break;
+ case 17:
+ scene->_object3.setStrip(5);
+ scene->_object3.setFrame(1);
+ scene->_object3.setPosition(Common::Point(292, 192));
+
+ zoom(true);
+ setDelay(300);
+ break;
+ case 18:
+ zoom(false);
+ _globals->_scenePalette.clearListeners();
+ _globals->_soundHandler.proc1(this);
+ break;
+ case 19:
+ _globals->_sceneManager.changeScene(10);
+ break;
+ case 20:
+ _globals->_sceneManager.changeScene(30);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene1000::Action3::zoom(bool up) {
+ Scene1000 *scene = (Scene1000 *)_globals->_sceneManager._scene;
+
+ if (up) {
+ while ((scene->_object3._percent < 100) && !_vm->shouldQuit()) {
+ scene->_object3.changeZoom(MIN(scene->_object3._percent + 5, 100));
+ _globals->_sceneObjects->draw();
+ _globals->_events.delay(1);
+ }
+ } else {
+ while ((scene->_object3._percent > 0) && !_vm->shouldQuit()) {
+ scene->_object3.changeZoom(MAX(scene->_object3._percent - 5, 0));
+ _globals->_sceneObjects->draw();
+ _globals->_events.delay(1);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene1000::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+ loadScene(1000);
+
+ if (_globals->_sceneManager._previousScene == 2000) {
+ setZoomPercents(150, 10, 180, 100);
+ _object1.postInit();
+ _object1.setVisage(1001);
+ _object1._strip = 7;
+ _object1.animate(ANIM_MODE_2, 0);
+ _object1._moveDiff = Common::Point(1, 1);
+ _object1.setPosition(Common::Point(120, 180));
+
+ setAction(&_action2);
+
+ _globals->_sceneManager._scene->_sceneBounds.center(_object1._position.x, _object1._position.y);
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+ _globals->_soundHandler.startSound(114);
+ } else if (_globals->_sceneManager._previousScene == 2222) {
+ setZoomPercents(150, 10, 180, 100);
+ _object1.postInit();
+ _object1.setVisage(1001);
+ _object1._strip = 7;
+ _object1.animate(ANIM_MODE_2, 0);
+ _object1._moveDiff = Common::Point(2, 2);
+ _object1.setPosition(Common::Point(120, 180));
+
+ _globals->_sceneManager._scene->_sceneBounds.center(_object1._position.x, _object1._position.y);
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+
+ setAction(&_action1);
+ } else {
+ _globals->_soundHandler.startSound(4);
+ setZoomPercents(0, 10, 30, 100);
+ _object3.postInit();
+ _object3.setVisage(1050);
+ _object3.changeZoom(-1);
+ _object3.setPosition(Common::Point(158, 0));
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(1050);
+ _globals->_player.setStrip(3);
+ _globals->_player.setPosition(Common::Point(160, 191));
+ _globals->_player._moveDiff.x = 12;
+ _globals->_player.hide();
+ _globals->_player.disableControl();
+
+ _globals->_sceneManager._scene->_sceneBounds.center(_object3._position.x, _object3._position.y);
+
+ setAction(&_action3);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 1001 - Fleeing planet cutscene
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene1001::Action1::signal() {
+ Scene1001 *scene = (Scene1001 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ scene->_object3.animate(ANIM_MODE_5, this);
+ break;
+ case 2: {
+ Common::Point pt(108, 171);
+ NpcMover *mover = new NpcMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 3: {
+ Common::Point pt(170, 159);
+ NpcMover *mover = new NpcMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 4: {
+ scene->_object2.postInit();
+ scene->_object2.setVisage(16);
+ scene->_object2.setStrip2(4);
+ scene->_object2.setPosition(Common::Point(61, 177));
+ scene->_object2.animate(ANIM_MODE_5, this);
+
+ Common::Point pt(320, 100);
+ NpcMover *mover = new NpcMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 5: {
+ Common::Point pt(82, 166);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 6: {
+ Common::Point pt(64, 149);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 7: {
+ Common::Point pt(15, 136);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 8: {
+ Common::Point pt(-5, 120);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 9: {
+ scene->_object1.postInit();
+ scene->_object1.setVisage(16);
+ scene->_object1.setStrip2(1);
+ scene->_object1.setFrame(1);
+ scene->_object1.setPosition(Common::Point(-75, 87));
+ scene->_object1.animate(ANIM_MODE_2, NULL);
+
+ Common::Point pt(0, 100);
+ NpcMover *mover = new NpcMover();
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 10: {
+ Common::Point pt1(107, 115);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object1.addMover(mover1, &pt1, NULL);
+
+ scene->_object3.setVisage(16);
+ scene->_object3.setStrip2(5);
+ scene->_object3.setFrame2(2);
+ scene->_object3.setPosition(Common::Point(220, 200));
+
+ Common::Point pt2(187, 181);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object3.addMover(mover2, &pt2, this);
+ break;
+ }
+ case 11: {
+ scene->_object2.setVisage(16);
+ scene->_object2.setStrip2(5);
+ scene->_object2.setFrame2(1);
+ scene->_object2.setPosition(Common::Point(211, 0));
+
+ Common::Point pt(189, 30);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 12:
+ scene->_stripManager.start(100, this);
+ break;
+ case 13: {
+ scene->_object4.postInit();
+ scene->_object4.setVisage(16);
+ scene->_object4.setStrip2(2);
+ scene->_object4.setFrame(4);
+ scene->_object4.setPosition(Common::Point(360, 80));
+ scene->_object4.animate(ANIM_MODE_2, NULL);
+
+ Common::Point pt(303, 97);
+ NpcMover *mover = new NpcMover();
+ scene->_object4.addMover(mover, &pt, this);
+ break;
+ }
+ case 14:
+ scene->_stripManager.start(110, this);
+ break;
+ case 15:
+ setDelay(10);
+ break;
+ case 16: {
+ scene->_soundHandler1.startSound(90);
+
+ scene->_object6.postInit();
+ scene->_object6.setVisage(16);
+ scene->_object6.setStrip2(6);
+ scene->_object6.setFrame2(2);
+ scene->_object6._moveDiff = Common::Point(20, 20);
+ scene->_object6.fixPriority(20);
+ scene->_object6.setPosition(Common::Point(scene->_object2._position.x - 6, scene->_object2._position.y + 7));
+ scene->_object6.animate(ANIM_MODE_5, NULL);
+
+ Common::Point pt(scene->_object6._position.x - 70, scene->_object6._position.y + 70);
+ NpcMover *mover = new NpcMover();
+ scene->_object6.addMover(mover, &pt, this);
+ break;
+ }
+ case 17: {
+ scene->_soundHandler1.startSound(90);
+ scene->_object6.remove();
+
+ scene->_object7.postInit();
+ scene->_object7.setVisage(16);
+ scene->_object7.setStrip2(6);
+ scene->_object7.setFrame2(1);
+ scene->_object7._moveDiff = Common::Point(20, 20);
+ scene->_object7.setPosition(Common::Point(scene->_object3._position.x - 28, scene->_object3._position.y - 11));
+ scene->_object7.fixPriority(200);
+ scene->_object7.animate(ANIM_MODE_5, NULL);
+
+ Common::Point pt(scene->_object7._position.x - 70, scene->_object7._position.y - 70);
+ NpcMover *mover = new NpcMover();
+ scene->_object7.addMover(mover, &pt, this);
+ break;
+ }
+ case 18:
+ scene->_object7.remove();
+
+ scene->_object5.postInit();
+ scene->_object5.setVisage(16);
+ scene->_object5.setPosition(Common::Point(306, 93));
+ scene->_object5._strip = 3;
+ scene->_object5.fixPriority(200);
+ scene->_object5.animate(ANIM_MODE_2, NULL);
+ setDelay(30);
+ break;
+ case 19: {
+ _globals->_soundHandler.startSound(91);
+ byte adjustData[4] = {0xff, 0xff, 0xff, 0};
+ _globals->_scenePalette.fade(adjustData, true, 0);
+
+ scene->_object1._strip = 7;
+ scene->_object1._frame = 1;
+ scene->_object1.setPosition(Common::Point(314, 112));
+ scene->_object1.addMover(NULL);
+ setDelay(2);
+ }
+ case 20:
+ _globals->_scenePalette.loadPalette(16);
+ _globals->_scenePalette.refresh();
+ setDelay(6);
+ break;
+ case 21:
+ scene->_object1._numFrames = 15;
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 22:
+ _globals->_soundHandler.startSound(92);
+ scene->_stripManager.start(111, this);
+ break;
+ case 23:
+ setDelay(60);
+ break;
+ case 24:
+ _globals->_sceneManager.changeScene(2000);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene1001::postInit(SceneObjectList *OwnerList) {
+ loadScene(16);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerCText);
+ _stripManager.addSpeaker(&_speakerCR);
+ _stripManager.addSpeaker(&_speakerSL);
+ _speakerQText._color1 = 11;
+
+ _object3.postInit();
+ _object3.setVisage(16);
+ _object3.setStrip2(4);
+ _object3.setPosition(Common::Point(61, 177));
+
+ _globals->_soundHandler.startSound(85);
+ setAction(&_action1);
+}
+
+
+/*--------------------------------------------------------------------------
+ * Scene 1250 -
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene1250::Action1::signal() {
+ Scene1250 *scene = (Scene1250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(120) + 60);
+ break;
+ case 1:
+ scene->_object1.animate(ANIM_MODE_5, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene1250::Action2::signal() {
+ Scene1250 *scene = (Scene1250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ switch (_globals->_randomSource.getRandomNumber(2)) {
+ case 0:
+ scene->_object2.setPosition(Common::Point(163, 75));
+ break;
+ case 1:
+ scene->_object2.setPosition(Common::Point(109, 65));
+ break;
+ case 2:
+ scene->_object2.setPosition(Common::Point(267, 20));
+ break;
+ }
+
+ setDelay(30);
+ break;
+ case 1:
+ scene->_object2.animate(ANIM_MODE_5, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene1250::Action3::signal() {
+ Scene1250 *scene = (Scene1250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ scene->_stripManager.start(1251, this);
+ break;
+ case 2:
+ setDelay(6);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(1000);
+ break;
+ }
+}
+
+void Scene1250::Action4::signal() {
+ Scene1250 *scene = (Scene1250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(3);
+ break;
+ case 1:
+ scene->_stripManager.start(1250, this);
+ break;
+ case 2:
+ setDelay(6);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(2000);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene1250::postInit(SceneObjectList *OwnerList) {
+ loadScene(1250);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerQText);
+ _speakerQText._textPos = Common::Point(120, 120);
+ _speakerQText._textWidth = 180;
+
+ _object1.postInit();
+ _object1.setVisage(1250);
+ _object1.setPosition(Common::Point(126, 69));
+ _object1.setStrip2(1);
+ _object1._frame = 1;
+ _object1.setAction(&_action1);
+
+ _object2.postInit();
+ _object2.setVisage(1250);
+ _object2.setPosition(Common::Point(126, 69));
+ _object2.setStrip2(2);
+ _object2.fixPriority(255);
+ _object2._frame = 1;
+ _object2.setAction(&_action2);
+
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+
+ if ((_globals->_sceneManager._previousScene != 2000) || (_globals->_stripNum != 1250)) {
+ setAction(&_action4);
+ } else {
+ setAction(&_action3);
+ _globals->_soundHandler.startSound(114);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 1400 - Ringworld Wall
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene1400::Action1::signal() {
+ Scene1400 *scene = (Scene1400 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1: {
+ SceneItem::display(1400, 0, SET_X, 120, SET_Y, 610, SET_FONT, 2, SET_EXT_BGCOLOR, 23, SET_KEEP_ONSCREEN, -1, LIST_END);
+
+ Common::Point pt(160, 700);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ _globals->_player.setStrip2(3);
+ _globals->_player.changeZoom(100);
+
+ Common::Point pt(160, 100);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+
+ SceneItem::display(0, 0);
+ setDelay(360);
+ break;
+ }
+ case 3:
+ SceneItem::display(1400, 2, SET_X, 60, SET_Y, _globals->_sceneManager._scene->_sceneBounds.bottom - 80,
+ SET_FONT, 2, SET_FG_COLOR, 13, SET_POS_MODE, 0, SET_KEEP_ONSCREEN, -1, LIST_END);
+ setDelay(420);
+ break;
+ case 4:
+ SceneItem::display(0, 0);
+ setDelay(360);
+ break;
+ case 5:
+ SceneItem::display(1400, 3, SET_X, 60, SET_Y, _globals->_sceneManager._scene->_sceneBounds.bottom - 80,
+ SET_FONT, 2, SET_FG_COLOR, 23, SET_POS_MODE, 0, SET_KEEP_ONSCREEN, -1, LIST_END);
+ setDelay(360);
+ break;
+ case 6:
+ SceneItem::display(0, 0);
+ break;
+ case 7: {
+ _globals->_player._frame = 1;
+ _globals->_player.setStrip2(1);
+ _globals->_player._numFrames = 5;
+ _globals->_player.animate(ANIM_MODE_5, this);
+
+ Common::Point pt(205, 70);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, NULL);
+ _globals->_sceneManager._fadeMode = FADEMODE_NONE;
+
+ scene->loadScene(1402);
+ break;
+ }
+ case 8:
+ _globals->_player.setStrip2(2);
+ _globals->_player._numFrames = 10;
+ _globals->_player.animate(ANIM_MODE_2, NULL);
+
+ SceneItem::display(1400, 4, SET_X, 30, SET_Y, _globals->_player._position.y + 10, SET_FONT, 2,
+ SET_FG_COLOR, 13, SET_POS_MODE, 0, SET_KEEP_ONSCREEN, -1, LIST_END);
+ setDelay(300);
+ break;
+ case 9: {
+ SceneItem::display(0, 0);
+ Common::Point pt(450, 45);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 10:
+ _globals->_sceneManager._scrollerRect = Rect(40, 20, 280, 180);
+ _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL;
+ _globals->_stripNum = 1500;
+ _globals->_soundHandler.proc3();
+
+ _globals->_sceneManager.changeScene(1500);
+ break;
+ }
+}
+
+void Scene1400::Action1::dispatch() {
+ Action::dispatch();
+
+ if ((_actionIndex > 3) && (_actionIndex < 9))
+ _globals->_sceneText.setPosition(Common::Point(60, _globals->_sceneManager._scene->_sceneBounds.bottom - 80));
+
+ if ((_actionIndex <= 2) && (_globals->_player._percent > 22))
+ _globals->_player.changeZoom(100 - (800 - _globals->_player._position.y));
+
+ if ((_actionIndex >= 9) && (_globals->_player._percent > 22))
+ _globals->_player.changeZoom(100 - (_globals->_player._position.x - 205));
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene1400::postInit(SceneObjectList *OwnerList) {
+ if (_globals->_stripNum != 1400) {
+ loadScene(1401);
+ } else {
+ loadScene(1402);
+ }
+ Scene::postInit();
+
+ _globals->_sceneManager._scrollerRect = Rect(40, 90, 280, 180);
+ _globals->_player.postInit();
+ _globals->_player.setVisage(1401);
+ _globals->_player.animate(ANIM_MODE_2, 0);
+ _globals->_player.setStrip2(4);
+ _globals->_player.fixPriority(4);
+ _globals->_player.disableControl();
+
+ _globals->_player._moveDiff = Common::Point(4, 2);
+ _globals->_player.setPosition(Common::Point(160, 800));
+ _globals->_sceneManager._scene->_sceneBounds.center(_globals->_player._position);
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.y = (_globals->_sceneManager._scene->_sceneBounds.top / 100) * 100;
+
+ setAction(&_action1);
+ _globals->_soundHandler.startSound(118);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 1500 - Ringworld Space-port
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene1500::Action1::signal() {
+ Scene1500 *scene = (Scene1500 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_object1.postInit();
+ scene->_object1.setVisage(1501);
+ scene->_object1._moveDiff = Common::Point(2, 1);
+ scene->_object1.setPosition(Common::Point(204, 85));
+ scene->_object1.animate(ANIM_MODE_2, NULL);
+ scene->_object1._numFrames = 3;
+ scene->_object1.changeZoom(-1);
+
+ Common::Point pt(238, 121);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 1: {
+ Common::Point pt(312, 145);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ scene->_object1.setStrip(2);
+ scene->_object1.setFrame(1);
+ scene->_object1._moveDiff.y = 2;
+ scene->_object1._numFrames = 5;
+
+ Common::Point pt(310, 150);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 3: {
+ Common::Point pt(304, 165);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 4: {
+ scene->_object1._numFrames = 3;
+ scene->_object1.setStrip2(3);
+ scene->_object1.animate(ANIM_MODE_2, this);
+
+ Common::Point pt(94, 175);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object1.addMover(mover, &pt, this);
+ break;
+ }
+ case 5:
+ setDelay(30);
+ break;
+ case 6:
+ scene->_soundHandler.startSound(123);
+ scene->_object1.setStrip2(4);
+ scene->_object1.setFrame(1);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 7:
+ scene->_object1.setStrip2(5);
+ scene->_object1.animate(ANIM_MODE_2, NULL);
+ scene->_soundHandler.startSound(124, this);
+ break;
+ case 8:
+ _globals->_soundHandler.startSound(126, this);
+ break;
+ case 9:
+ _globals->_soundHandler.startSound(127);
+ _globals->_sceneManager.changeScene(2000);
+ break;
+ }
+}
+
+void Scene1500::Action2::signal() {
+ Scene1500 *scene = (Scene1500 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(6);
+ break;
+ case 1: {
+ scene->_object2.postInit();
+ scene->_object2.setVisage(1502);
+ scene->_object2.fixPriority(255);
+ scene->_object2.changeZoom(5);
+ scene->_object2._frame = 1;
+ scene->_object2._moveDiff = Common::Point(1, 1);
+ scene->_object2.setPosition(Common::Point(104, 184));
+ scene->_object2.animate(ANIM_MODE_2, NULL);
+
+ Common::Point pt(118, 147);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ scene->_object2._moveDiff.x = 5;
+ scene->_object2.changeZoom(-1);
+ Common::Point pt(-55, 200);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ scene->_soundHandler.proc4();
+ _globals->_stripNum = 1505;
+ _globals->_sceneManager.changeScene(2400);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene1500::postInit(SceneObjectList *OwnerList) {
+ loadScene(1500);
+ Scene::postInit();
+
+ if ((_globals->_stripNum == 1500) || ((_globals->_stripNum != 1504) && (_globals->_stripNum != 2751))) {
+ _globals->_soundHandler.startSound(120);
+ setZoomPercents(105, 20, 145, 100);
+
+ setAction(&_action1);
+ } else {
+ setZoomPercents(150, 5, 200, 100);
+
+ _object1.postInit();
+ _object1.setVisage(1501);
+ _object1.setStrip2(5);
+ _object1.setPosition(Common::Point(94, 175));
+ _object1.animate(ANIM_MODE_2, NULL);
+
+ setAction(&_action2);
+ }
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes2.h b/engines/tsage/ringworld_scenes2.h
new file mode 100644
index 0000000000..75843d3570
--- /dev/null
+++ b/engines/tsage/ringworld_scenes2.h
@@ -0,0 +1,152 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_SCENES2_H
+#define TSAGE_RINGWORLD_SCENES2_H
+
+#include "common/scummsys.h"
+#include "tsage/ringworld_logic.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+class Scene1000 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ private:
+ void zoom(bool up);
+ public:
+ virtual void signal();
+ };
+
+public:
+ SceneObject _object1, _object2, _object3, _object4;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene1001 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+public:
+ SpeakerQText _speakerQText;
+ SpeakerSL _speakerSL;
+ SpeakerCText _speakerCText;
+ SpeakerCR _speakerCR;
+ Action1 _action1;
+ SceneObject _object1, _object2, _object3, _object4;
+ SceneObject _object5, _object6, _object7;
+ SoundHandler _soundHandler1, _soundHandler2;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene1250 : public Scene {
+public:
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+public:
+ SpeakerQText _speakerQText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ SceneObject _object1, _object2;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene1400 : public Scene {
+public:
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ virtual void dispatch();
+ };
+public:
+ Action1 _action1;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+
+};
+
+class Scene1500 : public Scene {
+public:
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+public:
+ SoundHandler _soundHandler;
+ Action1 _action1;
+ Action2 _action2;
+ SceneObject _object1, _object2, _object3;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_scenes3.cpp b/engines/tsage/ringworld_scenes3.cpp
new file mode 100644
index 0000000000..13dfc1a40b
--- /dev/null
+++ b/engines/tsage/ringworld_scenes3.cpp
@@ -0,0 +1,6110 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/config-manager.h"
+#include "tsage/ringworld_scenes3.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+/*--------------------------------------------------------------------------
+ * Scene 2000 - Cockpit cutscenes
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2000::Action1::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ error("Old stuff");
+ break;
+ case 1:
+ scene->_stripManager.start(2075, this);
+ break;
+ case 2:
+ setDelay(4);
+ break;
+ case 3:
+ _globals->_stripNum = 0;
+ _globals->_sceneManager.changeScene(1250);
+ break;
+ }
+}
+
+void Scene2000::Action2::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_object2.animate(ANIM_MODE_6, NULL);
+ setDelay(_globals->_randomSource.getRandomNumber(179) + 60);
+ break;
+ case 1:
+ setDelay(_globals->_randomSource.getRandomNumber(179) + 60);
+ if (_globals->_randomSource.getRandomNumber(4) >= 2)
+ _actionIndex = 0;
+ break;
+ case 2:
+ setDelay(_globals->_randomSource.getRandomNumber(179) + 60);
+ _actionIndex = _globals->_randomSource.getRandomNumber(1);
+ break;
+ }
+}
+
+void Scene2000::Action3::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_object6.animate(ANIM_MODE_5, NULL);
+ setDelay(_globals->_randomSource.getRandomNumber(179) + 60);
+ break;
+ case 1:
+ scene->_object6.animate(ANIM_MODE_6, NULL);
+ setDelay(_globals->_randomSource.getRandomNumber(179) + 60);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene2000::Action4::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_object4.animate(ANIM_MODE_5, NULL);
+ setDelay(_globals->_randomSource.getRandomNumber(179) + 60);
+ break;
+ case 1:
+ scene->_object4.animate(ANIM_MODE_6, NULL);
+ setDelay(_globals->_randomSource.getRandomNumber(179) + 60);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene2000::Action5::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_object3.animate(ANIM_MODE_5, NULL);
+ setDelay(_globals->_randomSource.getRandomNumber(125) + 300);
+ break;
+ case 1:
+ scene->_object3.animate(ANIM_MODE_6, NULL);
+ setDelay(_globals->_randomSource.getRandomNumber(125) + 300);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene2000::Action6::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(130);
+ break;
+ case 1:
+ scene->_soundHandler2.startSound(79);
+ scene->_stripManager.start(2000, this);
+ break;
+ case 2:
+ _globals->_soundHandler.startSound(81);
+ scene->_object6.postInit();
+ scene->_object6.setVisage(2003);
+ scene->_object6.setAction(NULL);
+ scene->_object6.setStrip2(2);
+ scene->_object6.setPosition(Common::Point(184, 137));
+ scene->_object6.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ scene->_stripManager.start(95, this);
+ break;
+ case 4:
+ scene->_object6.animate(ANIM_MODE_6, this);
+ break;
+ case 5:
+ _globals->_soundHandler.startSound(80);
+ scene->_object6.remove();
+ _globals->_sceneManager.changeScene(1001);
+ break;
+ }
+}
+
+void Scene2000::Action7::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ scene->_stripManager.start(2072, this);
+ break;
+ case 2:
+ setDelay(3);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(2222);
+ break;
+ }
+}
+
+void Scene2000::Action8::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ error("Old stuff");
+ break;
+ case 1:
+ scene->_stripManager.start(2073, this);
+ break;
+ case 2:
+ setDelay(10);
+ break;
+ case 3:
+ _globals->_stripNum = 2005;
+ _globals->_sceneManager.changeScene(1000);
+ break;
+ }
+}
+
+void Scene2000::Action9::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ error("Old stuff");
+ break;
+ case 1:
+ scene->_stripManager.start(2074, this);
+ break;
+ case 2:
+ setDelay(3);
+ break;
+ case 3:
+ _globals->_stripNum = 2008;
+ _globals->_sceneManager.changeScene(9999);
+ break;
+ }
+}
+
+void Scene2000::Action10::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ error("Old stuff");
+ break;
+ case 2:
+ SceneItem::display(2000, 17, SET_Y, 20, SET_X, 110, SET_FONT, 2, SET_BG_COLOR, -1,
+ SET_FG_COLOR, 17, SET_WIDTH, 200, SET_POS_MODE, 0, SET_KEEP_ONSCREEN, 1, LIST_END);
+ break;
+ case 3:
+ SceneItem::display(0, 0);
+ _globals->_stripNum = 0;
+ _globals->_sceneManager.changeScene(9999);
+ break;
+ }
+}
+
+void Scene2000::Action11::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ error("Old stuff");
+ break;
+ case 1:
+ scene->_stripManager.start(2076, this);
+ break;
+ case 2:
+ scene->_stripManager.start(2077, this);
+ break;
+ case 3:
+ _globals->_stripNum = 0;
+ _globals->_sceneManager.changeScene(1400);
+ break;
+ }
+}
+
+void Scene2000::Action12::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(2020, this);
+ break;
+ case 2:
+ _globals->_player.disableControl();
+ setDelay(10);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(2300);
+ break;
+ }
+}
+
+void Scene2000::Action13::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ scene->_stripManager.start(2078, this);
+ break;
+ case 2:
+ SceneItem::display(0, 0);
+ _globals->_stripNum = 2751;
+ _globals->_sceneManager.changeScene(1500);
+ break;
+ }
+}
+
+void Scene2000::Action14::signal() {
+ Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(30);
+ break;
+ case 1:
+ scene->_stripManager.start(2070, this);
+ break;
+ case 2:
+ setDelay(60);
+ break;
+ case 3:
+ _globals->_soundHandler.startSound(99);
+ scene->_object8.show();
+ scene->_object8.animate(ANIM_MODE_5, this);
+ break;
+ case 4:
+ _globals->_soundHandler.startSound(12);
+ scene->_object8.setStrip(2);
+ scene->_object8.setFrame(1);
+ scene->_object9.show();
+ scene->_object10.show();
+ setDelay(60);
+ break;
+ case 5:
+ scene->_stripManager.start(2001, this, scene);
+ break;
+ case 6:
+ _globals->_soundHandler.proc1(0/* was false */);
+ scene->_object8.setStrip(1);
+ scene->_object8.setFrame(scene->_object8.getFrameCount());
+ scene->_object8.animate(ANIM_MODE_6, this);
+
+ scene->_object9.remove();
+ scene->_object10.remove();
+ break;
+ case 7:
+ _globals->_soundHandler.startSound(111);
+ scene->_object8.remove();
+ setDelay(5);
+ break;
+ case 8:
+ scene->_stripManager.start(2071, this);
+ break;
+ case 9:
+ _globals->_stripNum = 1250;
+ _globals->_sceneManager.changeScene(1000);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2000::postInit(SceneObjectList *OwnerList) {
+ loadScene(2000);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerSL);
+ _stripManager.addSpeaker(&_speakerMR);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerGameText);
+ _stripManager.addSpeaker(&_speakerHText);
+
+ _speakerQText._npc = &_object2;
+ _speakerSText._npc = &_object3;
+ _speakerMText._npc = &_object6;
+ _speakerHText._npc = &_object6;
+ _stripManager.setCallback(this);
+
+ _object3.postInit();
+ _object3.setVisage(2002);
+ _object3.setPosition(Common::Point(65, 199));
+
+ _object4.postInit();
+ _object4.setVisage(2002);
+ _object4.setStrip(2);
+ _object4.setPosition(Common::Point(125, 199));
+ _object4.setAction(&_action4);
+
+ _object2.postInit();
+ _object2.setVisage(2001);
+ _object2.setPosition(Common::Point(43, 115));
+ _object2.setAction(&_action2);
+
+ _globals->_player.disableControl();
+
+ _object6.postInit();
+ _object6.setVisage(2003);
+ _object6.setPosition(Common::Point(267, 170));
+ _object6.setAction(&_action3);
+
+ _object8.postInit();
+ _object8.setVisage(2005);
+ _object8.setPosition(Common::Point(169, 133));
+ _object8.setPriority(133);
+ _object8.hide();
+
+ _object9.postInit();
+ _object9.setVisage(2005);
+ _object9.setStrip2(3);
+ _object9.setFrame(4);
+ _object9.setPosition(Common::Point(136, 86));
+ _object9.fixPriority(190);
+ _object9.hide();
+
+ _object10.postInit();
+ _object10.setVisage(2005);
+ _object10.setStrip2(5);
+ _object10.setFrame(4);
+ _object10.setPosition(Common::Point(202, 86));
+ _object10.fixPriority(195);
+ _object10.hide();
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 1000:
+ setAction(&_action7);
+ break;
+ case 1001:
+ _object6.remove();
+ setAction(&_action12);
+ break;
+ case 1500:
+ setAction(&_action13);
+ break;
+ case 2200:
+ _globals->_soundHandler.startSound(111);
+ setAction(&_action14);
+ break;
+ case 2222:
+ _globals->_soundHandler.startSound(115);
+ setAction(&_action8);
+ break;
+ case 3500:
+ setAction(&_action11);
+ break;
+ default:
+ _object6.remove();
+ _globals->_soundHandler.startSound(80);
+ setAction(&_action6);
+ break;
+ }
+
+ _soundHandler1.startSound(78);
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+}
+
+void Scene2000::stripCallback(int v) {
+ switch (v) {
+ case 0:
+ _object9.setStrip(3);
+ _object9.animate(ANIM_MODE_7, NULL);
+ _object10.setStrip(6);
+ _object10.setFrame(1);
+ _object10.animate(ANIM_MODE_5, NULL);
+ break;
+ case 1:
+ _object10.setStrip(5);
+ _object10.animate(ANIM_MODE_7, NULL);
+ _object9.setStrip(4);
+ _object9.setFrame(1);
+ _object9.animate(ANIM_MODE_5, NULL);
+ break;
+ case 2:
+ _object9.animate(ANIM_MODE_NONE, NULL);
+ break;
+ case 3:
+ _object10.setStrip(6);
+ _object10.setFrame(1);
+ _object10.animate(ANIM_MODE_5, NULL);
+ _object9.setStrip(4);
+ _object9.setFrame(1);
+ _object9.animate(ANIM_MODE_5, NULL);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2100 - Starcraft Cockpit
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2100::Action1::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ if (!scene->_field1800)
+ setDelay(1);
+ else {
+ setAction(&scene->_sequenceManager, this, 2102, &_globals->_player, NULL);
+ scene->_field1800 = 0;
+ }
+ break;
+ case 1: {
+ Common::Point pt(157, 62);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 3: {
+ Common::Point pt(157, 56);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 4:
+ _globals->_player._strip = 3;
+ setDelay(3);
+ break;
+ case 5:
+ _globals->_player.fixPriority(1);
+ scene->_area1.display();
+ scene->_area2.display();
+ scene->_area3.display();
+ scene->_area4.display();
+
+ scene->_area1.draw(true);
+ _state = 0;
+ _globals->_events.setCursor(CURSOR_USE);
+
+ while (!_state && !_vm->getEventManager()->shouldQuit()) {
+ // Wait for an event
+ Event event;
+ if (!_globals->_events.getEvent(event)) {
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ continue;
+ }
+
+ if (scene->_area1._bounds.contains(event.mousePos)) {
+ scene->_area1.draw(true);
+ _state = scene->_area1._actionId;
+ }
+ if (scene->_area2._bounds.contains(event.mousePos)) {
+ scene->_area1.draw(false);
+ scene->_area2.draw(true);
+ _state = scene->_area2._actionId;
+ }
+ if (scene->_area3._bounds.contains(event.mousePos)) {
+ scene->_area1.draw(false);
+ scene->_area3.draw(true);
+ _state = scene->_area3._actionId;
+ }
+ }
+
+ scene->_soundHandler.startSound(161);
+ scene->_area1.restore();
+ scene->_area2.restore();
+ scene->_area3.restore();
+ scene->_area4.restore();
+
+ if (_state == 2100) {
+ setDelay(1);
+ } else {
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_6, this);
+ }
+ break;
+ case 6:
+ if (_state == 2100) {
+ Common::Point pt(157, 65);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ } else {
+ _globals->_sceneManager.changeScene(_state);
+ }
+ break;
+ case 7:
+ _globals->_player.fixPriority(-1);
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_6, this);
+ break;
+ case 8:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene2100::Action2::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_object3._numFrames = 5;
+ setDelay(_globals->_randomSource.getRandomNumber(59));
+ break;
+ case 1:
+ scene->_object3.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ setDelay(_globals->_randomSource.getRandomNumber(59));
+ break;
+ case 3:
+ scene->_object3.animate(ANIM_MODE_6, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene2100::Action3::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ case 2:
+ setDelay(_globals->_randomSource.getRandomNumber(119));
+ break;
+ case 1:
+ scene->_object2.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ scene->_object2.animate(ANIM_MODE_6, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene2100::Action4::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ if (!scene->_field1800)
+ setDelay(1);
+ else
+ setAction(&scene->_sequenceManager, this, 2102, &_globals->_player, NULL);
+ break;
+ case 1: {
+ Common::Point pt(80, 66);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _globals->_player.setVisage(2109);
+ _globals->_player._frame = 1;
+ _globals->_player._strip = 2;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(2120);
+ break;
+ }
+}
+
+void Scene2100::Action5::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL);
+ break;
+ case 2: {
+ Common::Point pt(272, 127);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ _globals->_player.checkAngle(&scene->_object3);
+ setDelay(30);
+ break;
+ case 4:
+ _globals->_sceneManager.changeScene(3700);
+ break;
+ }
+}
+
+void Scene2100::Action6::signal() {
+ // Seeker stands up and walks to the elevator
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_object2.setVisage(2806);
+ scene->_object2.setStrip(1);
+ scene->_object2.setStrip2(-1);
+ scene->_object2.changeZoom(-1);
+ scene->_object2.setPosition(Common::Point(155, 116));
+ scene->_object2.setObjectWrapper(new SceneObjectWrapper());
+ scene->_object2.setAction(NULL);
+ scene->_object2.animate(ANIM_MODE_1, NULL);
+
+ Common::Point pt(130, 116);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 1: {
+ scene->_object2.fixPriority(-1);
+ Common::Point pt(153, 67);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ remove();
+ break;
+ }
+}
+
+void Scene2100::Action7::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL);
+ break;
+ case 2:
+ setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, NULL);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(8100);
+ break;
+ }
+}
+
+void Scene2100::Action8::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL);
+ break;
+ case 2: {
+ Common::Point pt(200, 174);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ _globals->_player.checkAngle(&scene->_object3);
+ scene->_stripManager.start((RING_INVENTORY._translator._sceneNumber == 1) ? 7720 : 7710, this);
+ break;
+ case 4:
+ if (RING_INVENTORY._translator._sceneNumber != 1)
+ _globals->_sceneManager.changeScene(7600);
+ else {
+ _globals->setFlag(24);
+ _globals->_player.enableControl();
+ remove();
+ }
+ break;
+ }
+}
+
+void Scene2100::Action9::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ scene->_stripManager.start(6050, this);
+ break;
+ case 2:
+ scene->_soundHandler.startSound(99);
+ scene->_object4.show();
+ scene->_object4.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ scene->_soundHandler.startSound(12);
+ scene->_object4.setStrip(2);
+ scene->_stripManager.start(6051, this, scene);
+ break;
+ case 4:
+ scene->_soundHandler.proc1(0/* was false */);
+ scene->_object4.setStrip(1);
+ scene->_object4.setFrame(scene->_object4.getFrameCount());
+ scene->_object4.animate(ANIM_MODE_6, this);
+ break;
+ case 5:
+ scene->_object4.hide();
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(6010, this);
+ break;
+ case 6:
+ if (scene->_stripManager._field2E8 != 165)
+ setAction(&scene->_action10);
+ else
+ setAction(&scene->_action11);
+ break;
+ }
+}
+
+void Scene2100::Action10::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager, this, 2102, &_globals->_player, NULL);
+ break;
+ case 2: {
+ _globals->_player.disableControl();
+ Common::Point pt(155, 64);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ scene->_object3.setVisage(2105);
+ scene->_object3.setStrip(2);
+ scene->_object3.setFrame(1);
+ scene->_object3._numFrames = 10;
+ scene->_object3.setAction(NULL);
+ scene->_object3.animate(ANIM_MODE_5, this);
+ break;
+ case 4: {
+ scene->_object3.setVisage(2705);
+ scene->_object3.setStrip2(-1);
+ scene->_object3.changeZoom(-1);
+ scene->_object3.fixPriority(-1);
+ scene->_object3.setPosition(Common::Point(260, 156));
+ scene->_object3.setObjectWrapper(new SceneObjectWrapper());
+ scene->_object3.animate(ANIM_MODE_1, NULL);
+
+ Common::Point pt(166, 64);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object3.addMover(mover, &pt, this);
+
+ setAction(&scene->_action6, NULL);
+ break;
+ }
+ case 5:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 6: {
+ _globals->_player.fixPriority(1);
+ Common::Point pt(144, 54);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 7: {
+ scene->_object3.fixPriority(2);
+ Common::Point pt1(163, 55);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object3.addMover(mover1, &pt1, NULL);
+
+ scene->_object2.fixPriority(2);
+ Common::Point pt2(158, 55);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object2.addMover(mover2, &pt2, this);
+ break;
+ }
+ case 8:
+ _globals->_player.fixPriority(1);
+ _globals->_player.setStrip(1);
+ scene->_object3.fixPriority(1);
+ scene->_object3.setStrip(2);
+ scene->_object2.fixPriority(2);
+ scene->_object2.setStrip(3);
+
+ setDelay(45);
+ break;
+ case 9:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_6, this);
+ break;
+ case 10:
+ _globals->setFlag(70);
+ _globals->_stripNum = 2101;
+ _globals->_sceneManager.changeScene(2320);
+ break;
+ }
+}
+
+void Scene2100::Action11::signal() {
+ // Miranda stands up and walks to the elevator
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ scene->_object3._numFrames = 10;
+ scene->_object3.setAction(NULL);
+ scene->_object3.setVisage(2105);
+ scene->_object3.setStrip(2);
+ scene->_object3.setFrame(1);
+ scene->_object3.animate(ANIM_MODE_5, this);
+ break;
+ case 2: {
+ scene->_object3.setVisage(2705);
+ scene->_object3.setStrip2(-1);
+ scene->_object3.changeZoom(-1);
+ scene->_object3.fixPriority(-1);
+ scene->_object3.setPosition(Common::Point(260, 156));
+ scene->_object3.setObjectWrapper(new SceneObjectWrapper());
+ scene->_object3.animate(ANIM_MODE_1, NULL);
+
+ Common::Point pt(158, 62);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object3.addMover(mover, &pt, this);
+
+ setAction(&scene->_action6, NULL);
+ break;
+ }
+ case 3:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 4: {
+ scene->_object3.fixPriority(1);
+ Common::Point pt1(163, 55);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object3.addMover(mover1, &pt1, NULL);
+
+ scene->_object2.fixPriority(1);
+ Common::Point pt2(158, 55);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object2.addMover(mover2, &pt2, this);
+ break;
+ }
+ case 5:
+ scene->_object3.setStrip(2);
+ scene->_object2.setStrip(3);
+ setDelay(45);
+ break;
+ case 6:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_6, this);
+ break;
+ case 7:
+ scene->_object3.remove();
+ scene->_object2.remove();
+ _globals->setFlag(70);
+ _globals->_stripNum = 2102;
+ _globals->_player.enableControl();
+ _globals->_player._canWalk = false;
+ break;
+ }
+}
+
+void Scene2100::Action12::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ scene->_stripManager.start(6000, this);
+ break;
+ case 2:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 3: {
+ Common::Point pt1(158, 74);
+ NpcMover *mover1 = new NpcMover();
+ _globals->_player.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(158, 68);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object2.addMover(mover2, &pt2, NULL);
+ break;
+ }
+ case 4: {
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_6, NULL);
+
+ _globals->_player.fixPriority(-1);
+ Common::Point pt1(277, 84);
+ PlayerMover *mover1 = new PlayerMover();
+ _globals->_player.addMover(mover1, &pt1, this);
+
+ scene->_object2.fixPriority(-1);
+ Common::Point pt2(255, 76);
+ PlayerMover *mover2 = new PlayerMover();
+ scene->_object2.addMover(mover2, &pt2, this);
+ break;
+ }
+ case 6:
+ _globals->_player.setStrip(4);
+ scene->_object2.setStrip(4);
+ setDelay(60);
+ break;
+ case 7:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(6052, this);
+ break;
+ case 8:
+ if (scene->_stripManager._field2E8 == 320)
+ _globals->setFlag(74);
+ setDelay(30);
+ break;
+ case 9:
+ _globals->_events.setCursor(OBJECT_STUNNER);
+ scene->_object2.setAction(&scene->_action13);
+ setDelay(60);
+ break;
+ case 10:
+ if (_globals->getFlag(74))
+ setDelay(1);
+ else
+ setAction(&scene->_sequenceManager, this, 2101, &_globals->_player, NULL);
+ break;
+ case 11:
+ scene->_stripManager.start(2170, this);
+ break;
+ case 12:
+ setDelay(5);
+ break;
+ case 13:
+ scene->_stripManager.start(_globals->getFlag(74) ? 2172 : 2174, this);
+ break;
+ case 14:
+ if (_globals->getFlag(74)) {
+ _globals->_stripNum = 6100;
+ _globals->_sceneManager.changeScene(2320);
+ } else {
+ _globals->_sceneManager.changeScene(6100);
+ }
+ remove();
+ break;
+ }
+}
+
+void Scene2100::Action13::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(6);
+ break;
+ case 1: {
+ scene->_object2.fixPriority(113);
+ Common::Point pt(178, 116);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ Common::Point pt(150, 116);
+ NpcMover *mover = new NpcMover();
+ scene->_object2.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ scene->_object2.setVisage(2108);
+ scene->_object2._strip = 3;
+ scene->_object2.setPosition(Common::Point(150, 100));
+ scene->_object2.animate(ANIM_MODE_NONE, NULL);
+ scene->_object2.changeZoom(100);
+ scene->_object2.setAction(&scene->_action3);
+ setDelay(15);
+ break;
+ case 4:
+ remove();
+ break;
+ }
+}
+
+void Scene2100::Action14::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(6);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL);
+ break;
+ case 2:
+ setAction(&scene->_sequenceManager, this, 2101, &_globals->_player, NULL);
+ break;
+ case 3:
+ scene->_stripManager.start(6008, this);
+ break;
+ case 4:
+ scene->_soundHandler.startSound(99);
+ scene->_object4.show();
+ scene->_object4.animate(ANIM_MODE_5, this);
+ break;
+ case 5:
+ scene->_object4.setStrip(2);
+ scene->_stripManager.start(6009, this, scene);
+ break;
+ case 6:
+ scene->_soundHandler.proc1(0/* was false */);
+ scene->_object4.setStrip(1);
+ scene->_object4.setFrame(scene->_object4.getFrameCount());
+ scene->_object4.animate(ANIM_MODE_6, this);
+ break;
+ case 7:
+ scene->_stripManager.start(6060, this);
+ break;
+ case 8:
+ scene->_object3._numFrames = 10;
+ scene->_object3.setAction(NULL);
+ scene->_object3.setVisage(2105);
+ scene->_object3.setStrip(2);
+ scene->_object3.setFrame(1);
+ scene->_object3.animate(ANIM_MODE_5, this);
+ break;
+ case 9: {
+ scene->_object3.setVisage(2705);
+ scene->_object3.setStrip2(-1);
+ scene->_object3.changeZoom(-1);
+ scene->_object3.fixPriority(-1);
+ scene->_object3.setPosition(Common::Point(260, 156));
+ scene->_object3.setObjectWrapper(new SceneObjectWrapper());
+ scene->_object3.animate(ANIM_MODE_1, NULL);
+
+ Common::Point pt(157, 65);
+ PlayerMover *mover = new PlayerMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 10:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 11: {
+ Common::Point pt(159, 51);
+ NpcMover *mover = new NpcMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 12:
+ scene->_object3.setStrip(2);
+ setDelay(30);
+ case 13:
+ scene->_object3.fixPriority(1);
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_6, this);
+ break;
+ case 14:
+ setDelay(90);
+ break;
+ case 15:
+ _globals->_sceneManager.changeScene(7000);
+ remove();
+ break;
+ }
+}
+
+void Scene2100::Action15::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(6);
+ break;
+ case 1:
+ scene->_object3.postInit();
+ scene->_object3.setVisage(2705);
+ scene->_object3.animate(ANIM_MODE_1, NULL);
+ scene->_object3.setObjectWrapper(new SceneObjectWrapper());
+ scene->_object3.setPosition(Common::Point(157, 56));
+ scene->_object3.fixPriority(1);
+ scene->_object3.changeZoom(-1);
+
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 2: {
+ scene->_object3.fixPriority(-1);
+ Common::Point pt(177, 68);
+ NpcMover *mover = new NpcMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 3: {
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_6, this);
+
+ Common::Point pt(272, 140);
+ NpcMover *mover = new NpcMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 4: {
+ Common::Point pt(266, 150);
+ NpcMover *mover = new NpcMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 5: {
+ scene->_object3.fixPriority(156);
+
+ Common::Point pt(260, 156);
+ NpcMover *mover = new NpcMover();
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 6:
+ scene->_object3.setVisage(2105);
+ scene->_object3._strip = 1;
+ scene->_object3._frame = 1;
+ scene->_object3.setPosition(Common::Point(256, 156));
+ scene->_object3.animate(ANIM_MODE_5, this);
+ scene->_object3.changeZoom(100);
+
+ scene->_object3.animate(ANIM_MODE_NONE, NULL);
+ break;
+ case 7:
+ remove();
+ break;
+ }
+}
+
+void Scene2100::Action16::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ case 4:
+ setDelay(3);
+ break;
+ case 1:
+ scene->_stripManager.start(7001, this);
+ break;
+ case 2:
+ setAction(&scene->_sequenceManager, this, 2102, &_globals->_player, NULL);
+ break;
+ case 3: {
+ _globals->_player.disableControl();
+ Common::Point pt(155, 63);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 5:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 6: {
+ Common::Point pt(160, 54);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 7:
+ _globals->_player.fixPriority(1);
+ _globals->_player.setStrip(3);
+ setDelay(45);
+ break;
+ case 8:
+ scene->_soundHandler.startSound(162);
+ scene->_object1.animate(ANIM_MODE_6, this);
+ break;
+ case 9:
+ _globals->setFlag(15);
+ _globals->setFlag(36);
+ _globals->_sceneManager.changeScene(7000);
+ remove();
+ break;
+ }
+}
+
+void Scene2100::Action17::signal() {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL);
+ break;
+ case 2:
+ setAction(&scene->_sequenceManager, this, 2101, &_globals->_player, NULL);
+ break;
+ case 3:
+ scene->_stripManager.start(7070, this);
+ break;
+ case 4:
+ scene->_soundHandler.startSound(99);
+ scene->_object4.show();
+ scene->_object4.animate(ANIM_MODE_5, this);
+ break;
+ case 5:
+ scene->_soundHandler.startSound(12);
+ scene->_object4.setStrip(2);
+ scene->_stripManager.start(7071, this, scene);
+ break;
+ case 6:
+ scene->_soundHandler.proc1(NULL);
+ scene->_object4.setStrip(1);
+ scene->_object4.setFrame(scene->_object4.getFrameCount());
+ scene->_object4.animate(ANIM_MODE_6, this);
+ break;
+ case 7:
+ scene->_stripManager.start(7072, this);
+ break;
+ case 8:
+ RING_INVENTORY._stasisNegator._sceneNumber = 1;
+ _globals->_sceneManager.changeScene(9100);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2100::Hotspot2::doAction(int action) {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2100, 3);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2100, 29);
+ else {
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action4);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2100::Hotspot3::doAction(int action) {
+ // Computer, on the left
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2100, 4);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2100, 29);
+ else {
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action4);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2100::Hotspot4::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2100, 5);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2100, 6);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2100::Hotspot8::doAction(int action) {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2100, 12);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2100, 29);
+ else {
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action4);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2100::Hotspot10::doAction(int action) {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2100, 13);
+ break;
+ case CURSOR_USE:
+ if (scene->_field1800) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2102;
+ scene->setAction(&scene->_sequenceManager, scene, 2102, &_globals->_player, NULL);
+ } else if (_globals->getFlag(13)) {
+ SceneItem::display2(2100, 28);
+ } else {
+ scene->setAction(&scene->_sequenceManager, scene, 2101, &_globals->_player, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2100::Hotspot14::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(0))
+ SceneItem::display2(2100, 19);
+ else
+ SceneItem::display2(2100, 18);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(1))
+ SceneItem::display2(2100, 21);
+ else
+ SceneItem::display2(2100, 20);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2100::Object1::doAction(int action) {
+ // Elevator
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2100, 1);
+ break;
+ case CURSOR_USE:
+ scene->setAction(&scene->_action1);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2100::Object2::doAction(int action) {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2100, 30);
+ break;
+ case CURSOR_TALK:
+ if (_globals->getFlag(72)) {
+ _globals->_player.disableControl();
+ if (!_globals->getFlag(52))
+ scene->setAction(&scene->_sequenceManager, scene, 2111, NULL);
+ else {
+ scene->_sceneMode = _globals->getFlag(53) ? 2112 : 2110;
+ scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, NULL);
+ }
+ } else {
+ if (_globals->getFlag(14))
+ SceneItem::display2(2100, 32);
+ else {
+ _globals->setFlag(14);
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2108;
+ scene->setAction(&scene->_sequenceManager, scene, 2109, NULL);
+ }
+ }
+
+ scene->setAction(&scene->_action4);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2100::Object3::doAction(int action) {
+ Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (!_globals->getFlag(59))
+ SceneItem::display2(2100, 34);
+ else
+ error("***I have no response.");
+ break;
+
+ case CURSOR_TALK:
+ if (!_globals->getFlag(59)) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2108;
+ scene->setAction(&scene->_sequenceManager, scene, 2108, NULL);
+ } else {
+ error("***I have no response.");
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene2100::Scene2100() :
+ _hotspot1(0, CURSOR_LOOK, 2100, 2, LIST_END),
+ _hotspot5(0, CURSOR_LOOK, 2100, 9, LIST_END),
+ _hotspot6(0, CURSOR_LOOK, 2100, 7, CURSOR_USE, 2100, 8, LIST_END),
+ _hotspot7(0, CURSOR_LOOK, 2100, 7, CURSOR_USE, 2100, 11, LIST_END),
+ _hotspot9(0, CURSOR_LOOK, 2100, 14, LIST_END),
+ _hotspot11(0, CURSOR_LOOK, 2100, 15, CURSOR_USE, 2100, 16, LIST_END),
+ _hotspot12(0, CURSOR_LOOK, 2100, 24, CURSOR_USE, 2100, 25, LIST_END),
+ _hotspot13(0, CURSOR_LOOK, 2100, 17, LIST_END),
+ _hotspot15(0, CURSOR_LOOK, 2100, 22, CURSOR_USE, 2100, 23, LIST_END) {
+}
+
+void Scene2100::postInit(SceneObjectList *OwnerList) {
+ loadScene(2100);
+ Scene::postInit();
+ setZoomPercents(60, 80, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerMR);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerSL);
+ _stripManager.addSpeaker(&_speakerSAL);
+ _stripManager.addSpeaker(&_speakerHText);
+ _stripManager.addSpeaker(&_speakerGameText);
+ _speakerMText._npc = &_object3;
+ _speakerQText._npc = &_globals->_player;
+ _speakerSText._npc = &_object2;
+
+ _object1.postInit();
+ _object1.setVisage(2100);
+ _object1.animate(ANIM_MODE_NONE, NULL);
+ _object1.setPosition(Common::Point(157, 57));
+ _object1.fixPriority(5);
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(2101);
+ _hotspot3._frame = 1;
+ _hotspot3.animate(ANIM_MODE_2, NULL);
+ _hotspot3.setPosition(Common::Point(53, 44));
+ _hotspot3.changeZoom(100);
+ _hotspot3.fixPriority(1);
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(2101);
+ _hotspot4._frame = 1;
+ _hotspot4._strip = 3;
+ _hotspot4.animate(ANIM_MODE_8, 0, NULL);
+ _hotspot4.setPosition(Common::Point(274, 52));
+ _hotspot4.changeZoom(100);
+ _hotspot4.fixPriority(1);
+
+ _hotspot5.postInit();
+ _hotspot5.setVisage(2101);
+ _hotspot5._frame = 1;
+ _hotspot5._strip = 4;
+ _hotspot5.animate(ANIM_MODE_8, 0, NULL);
+ _hotspot5.setPosition(Common::Point(219, 141));
+ _hotspot5.changeZoom(100);
+ _hotspot5.fixPriority(160);
+
+ _hotspot6.postInit();
+ _hotspot6.setVisage(2101);
+ _hotspot6._frame = 1;
+ _hotspot6._strip = 5;
+ _hotspot6.fixPriority(175);
+ _hotspot6.animate(ANIM_MODE_8, 0, NULL);
+ _hotspot6.setPosition(Common::Point(97, 142));
+ _hotspot6.changeZoom(100);
+
+ _hotspot7.postInit();
+ _hotspot7.setVisage(2101);
+ _hotspot7._frame = 1;
+ _hotspot7._strip = 6;
+ _hotspot7.animate(ANIM_MODE_NONE, NULL);
+ _hotspot7.setPosition(Common::Point(133, 46));
+ _hotspot7.changeZoom(100);
+ _hotspot7.fixPriority(1);
+
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2101);
+ _hotspot8._frame = 1;
+ _hotspot8._strip = 7;
+ _hotspot8.animate(ANIM_MODE_8, 0, NULL);
+ _hotspot8.setPosition(Common::Point(20, 45));
+ _hotspot8.changeZoom(100);
+ _hotspot8.fixPriority(1);
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(2101);
+ _hotspot2._frame = 1;
+ _hotspot2._strip = 8;
+ _hotspot2.animate(ANIM_MODE_8, 0, NULL);
+ _hotspot2.setPosition(Common::Point(88, 41));
+ _hotspot2.changeZoom(100);
+ _hotspot2.fixPriority(1);
+
+ _hotspot11.setBounds(Rect(139, 74, 173, 96));
+ _hotspot10.setBounds(Rect(71, 100, 91, 135));
+ _hotspot9.setBounds(Rect(225, 110, 251, 136));
+ _hotspot14.setBounds(Rect(100, 97, 216, 130));
+ _hotspot13.setBounds(Rect(13, 124, 94, 168));
+ _hotspot12.setBounds(Rect(217, 141, 307, 155));
+ _hotspot15.setBounds(Rect(14, 90, 46, 107));
+ _hotspot1.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+
+ if (!_globals->getFlag(36) && !_globals->getFlag(70) && !_globals->getFlag(43)) {
+ _object3.postInit();
+ _object3.setPosition(Common::Point(246, 156));
+ _object3.animate(ANIM_MODE_NONE, NULL);
+ _object3.changeZoom(100);
+ _object3.fixPriority(156);
+ _object3.setVisage(2107);
+ _object3.setStrip(1);
+ _object3.setAction(&_action2);
+ _globals->_sceneItems.push_back(&_object3);
+ }
+
+ if (!_globals->getFlag(59) && !_globals->getFlag(70) && !_globals->getFlag(37) && !_globals->getFlag(114)) {
+ _object2.postInit();
+ _object2.setVisage(2108);
+ _object2._strip = 3;
+ _object2.setPosition(Common::Point(150, 100));
+ _object2.animate(ANIM_MODE_NONE, NULL);
+ _object2.changeZoom(100);
+ _object2.fixPriority(113);
+ _object2.setAction(&_action3);
+ _globals->_sceneItems.push_back(&_object2);
+ }
+
+ _globals->_sceneItems.addItems(&_hotspot15, &_hotspot11, &_hotspot10, &_hotspot9, &_hotspot14,
+ &_hotspot13, &_hotspot12, &_hotspot8, &_object1, &_hotspot2, &_hotspot3, &_hotspot4, &_hotspot5,
+ &_hotspot6, &_hotspot7, &_hotspot1, NULL);
+
+ _area1.setup(2153, 2, 1, 2100);
+ _area1._pt = Common::Point(200, 31);
+ _area2.setup(2153, 3, 1, 2150);
+ _area2._pt = Common::Point(200, 50);
+ _area3.setup(2153, 4, 1, 2320);
+ _area3._pt = Common::Point(200, 75);
+ _area4.setup(2153, 1, 1, OBJECT_TRANSLATOR);
+ _area4._pt = Common::Point(237, 77);
+
+ _globals->_player.postInit();
+ if (_globals->getFlag(13)) {
+ _globals->_player.setVisage(2170);
+ _globals->_player._moveDiff.y = 1;
+ } else {
+ _globals->_player.setVisage(0);
+ _globals->_player._moveDiff.y = 3;
+ }
+
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player._moveDiff.x = 4;
+ _globals->_player.changeZoom(-1);
+ _globals->_player.disableControl();
+ _field1800 = 0;
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 2120:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ _object1.fixPriority(-1);
+ _globals->_player.fixPriority(-1);
+ _globals->_player.setPosition(Common::Point(80, 66));
+ _globals->_player.enableControl();
+ break;
+ case 2150:
+ _globals->_player.fixPriority(1);
+ _globals->_player.setPosition(Common::Point(157, 56));
+ _sceneMode = 2104;
+ setAction(&_sequenceManager, this, 2104, &_globals->_player, &_object1, NULL);
+ break;
+ case 2222:
+ if (_globals->_sceneObjects->contains(&_object3))
+ _object3.remove();
+
+ _globals->_player.fixPriority(1);
+ _globals->_player.setPosition(Common::Point(144, 55));
+
+ _object2.setVisage(2806);
+ _object2.changeZoom(-1);
+ _object2.setPosition(Common::Point(158, 55));
+ _object2.fixPriority(1);
+ _object2.setAction(NULL);
+ _object2.setObjectWrapper(new SceneObjectWrapper());
+ _object2.animate(ANIM_MODE_1, NULL);
+ _object2.setStrip(3);
+ setAction(&_action12);
+ break;
+ case 2320:
+ if (_globals->_stripNum == 2321) {
+ if (_globals->_sceneObjects->contains(&_object3))
+ _object3.remove();
+
+ _globals->_player.fixPriority(1);
+ _globals->_player.setPosition(Common::Point(144, 55));
+
+ _object2.postInit();
+ _object2.setVisage(2806);
+ _object2.setStrip(1);
+ _object2.changeZoom(-1);
+ _object2.setPosition(Common::Point(158, 55));
+ _object2.fixPriority(1);
+ _object2.setAction(NULL);
+ _object2.setObjectWrapper(new SceneObjectWrapper());
+ _object2.animate(ANIM_MODE_1, NULL);
+
+ setAction(&_action12);
+ } else if (_globals->_stripNum == 6100) {
+ _globals->_player.setPosition(Common::Point(157, 56));
+ _globals->_player.fixPriority(1);
+
+ _object4.postInit();
+ _object4.setVisage(2102);
+ _object4.setPosition(Common::Point(160, 199));
+ _object4.hide();
+
+ setAction(&_action14);
+ } else {
+ _globals->_player.disableControl();
+ _globals->_player.setPosition(Common::Point(157, 56));
+ _sceneMode = 2104;
+
+ setAction(&_sequenceManager, this, 2104, &_globals->_player, &_object1, NULL);
+ }
+ break;
+ case 3700:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ Scene::setZoomPercents(80, 75, 100, 90);
+
+ if (_globals->_sceneObjects->contains(&_object2))
+ _object2.remove();
+
+ _globals->_player._angle = 225;
+ _globals->_player.setStrip(6);
+ _globals->_player.setFrame(1);
+ _globals->_player.fixPriority(-1);
+ _globals->_player.setPosition(Common::Point(272, 127));
+
+ _object3.setPosition(Common::Point(246, 156));
+ _object3.fixPriority(156);
+ _sceneMode = 2105;
+ setAction(&_sequenceManager, this, 2105, &_object3, NULL);
+ break;
+ case 4250:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ _globals->clearFlag(43);
+
+ _globals->_player.setVisage(2104);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(65, 149));
+ _globals->_player.fixPriority(152);
+ _globals->_player.setStrip(2);
+
+ _object4.postInit();
+ _object4.setVisage(2102);
+ _object4.setPosition(Common::Point(160, 199));
+ _object4.hide();
+
+ _sceneMode = 2107;
+ setAction(&_sequenceManager, this, 2107, &_object4, NULL);
+ break;
+ case 5000:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+
+ if (_globals->_sceneObjects->contains(&_object2))
+ _object2.remove();
+
+ _globals->_player.setStrip(3);
+ _globals->_player.setFrame(1);
+ _globals->_player.fixPriority(1);
+ _globals->_player.setPosition(Common::Point(157, 56));
+
+ _object3.setPosition(Common::Point(246, 156));
+ _object3.fixPriority(156);
+
+ setAction(&_action5);
+ break;
+ case 5100:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ _globals->_player.setVisage(2104);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(65, 149));
+ _globals->_player.fixPriority(152);
+ _globals->_player.setStrip(2);
+
+ _field1800 = 1;
+
+ _object4.postInit();
+ _object4.setVisage(2102);
+ _object4.setPosition(Common::Point(160, 199));
+ _object4.hide();
+
+ RING_INVENTORY._stasisBox._sceneNumber = 0;
+ setAction(&_action9);
+ break;
+ case 7000:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+
+ if (RING_INVENTORY._stasisBox2._sceneNumber == 1) {
+ _globals->_player.fixPriority(1);
+ _globals->_player.setPosition(Common::Point(157, 56));
+
+ _object4.postInit();
+ _object4.setVisage(2102);
+ _object4.setPosition(Common::Point(160, 199));
+ _object4.hide();
+ _globals->clearFlag(15);
+ _globals->clearFlag(109);
+ _globals->clearFlag(72);
+
+ setAction(&_action17);
+ } else {
+ _globals->_player.setVisage(2104);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(65, 149));
+ _globals->_player.fixPriority(152);
+ _globals->_player.setStrip(2);
+
+ _field1800 = 1;
+ setAction(&_action16);
+ }
+ break;
+ case 7600:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+
+ if (_globals->_sceneObjects->contains(&_object2))
+ _object2.remove();
+
+ _globals->_player.fixPriority(1);
+ _globals->_player.setPosition(Common::Point(157, 56));
+
+ setAction(&_action8);
+ break;
+ case 8100:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+
+ _globals->_player.setVisage(2104);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(65, 149));
+ _globals->_player.fixPriority(152);
+ _globals->_player.setStrip(2);
+
+ _sceneMode = 2106;
+ setAction(&_sequenceManager, this, 2106, NULL);
+ break;
+ case 9750:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+
+ _globals->_player.setVisage(2104);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(65, 149));
+ _globals->_player.fixPriority(152);
+ _globals->_player.setStrip(2);
+
+ _object4.postInit();
+ _object4.setVisage(2102);
+ _object4.setPosition(Common::Point(160, 199));
+ _object4.hide();
+
+ _sceneMode = 2103;
+ setAction(&_sequenceManager, this, 2103, &_object4, NULL);
+ break;
+ default:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+
+ _globals->_player._uiEnabled = true;
+ break;
+ }
+
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+}
+
+void Scene2100::stripCallback(int v) {
+ switch (v) {
+ case 1:
+ _object4._numFrames = 4;
+ _object4.animate(ANIM_MODE_7, NULL);
+ break;
+ case 2:
+ _object4.animate(ANIM_MODE_NONE, NULL);
+ break;
+ }
+}
+
+void Scene2100::signal() {
+ switch (_sceneMode) {
+ case 2101:
+ _field1800 = 1;
+ _globals->_player._uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 2102:
+ _field1800 = 0;
+ _globals->_player.enableControl();
+ break;
+ case 2103:
+ _globals->_stripNum = 9000;
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ case 2106:
+ _globals->_sceneManager.changeScene(7000);
+ break;
+ case 2107:
+ _globals->_sceneManager.changeScene(5000);
+ break;
+ case 2104:
+ case 2105:
+ case 2108:
+ case 2110:
+ case 2111:
+ case 2112:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2120 - Encyclopedia
+ *
+ *--------------------------------------------------------------------------*/
+
+Scene2120::Action1::Action1() {
+ _entries.push_back(Entry(0, 0, 0));
+ _entries.push_back(Entry(0, 0, 0));
+ _entries.push_back(Entry(4, 1, 2123));
+ _entries.push_back(Entry(1, 6, 0));
+ _entries.push_back(Entry(2, 8, 0));
+ _entries.push_back(Entry(1, 11, 0));
+ _entries.push_back(Entry(4, 13, 2131));
+ _entries.push_back(Entry(2, 18, 0));
+ _entries.push_back(Entry(4, 21, 0));
+ _entries.push_back(Entry(7, 26, 2128));
+ _entries.push_back(Entry(3, 34, 0));
+ _entries.push_back(Entry(0, 38, 0));
+ _entries.push_back(Entry(3, 39, 2126));
+ _entries.push_back(Entry(3, 43, 0));
+ _entries.push_back(Entry(4, 47, 2125));
+ _entries.push_back(Entry(3, 52, 0));
+ _entries.push_back(Entry(4, 56, 2129));
+ _entries.push_back(Entry(7, 61, 0));
+ _entries.push_back(Entry(2, 69, 2127));
+ _entries.push_back(Entry(7, 72, 2122));
+ _entries.push_back(Entry(0, 80, 2124));
+ _entries.push_back(Entry(0, 81, 0));
+ _entries.push_back(Entry(0, 82, 0));
+ _entries.push_back(Entry(1, 83, 0));
+ _entries.push_back(Entry(2, 85, 2132));
+ _entries.push_back(Entry(1, 88, 2133));
+ _entries.push_back(Entry(2, 90, 2136));
+ _entries.push_back(Entry(1, 93, 0));
+ _entries.push_back(Entry(10, 95, 2135));
+ _entries.push_back(Entry(5, 106, 0));
+ _entries.push_back(Entry(2, 112, 2134));
+ _entries.push_back(Entry(1, 115, 2130));
+ _entries.push_back(Entry(0, 117, 0));
+}
+
+void Scene2120::Action1::signal() {
+ Scene2120 *scene = (Scene2120 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ _globals->_events.setCursor(CURSOR_WALK);
+ break;
+ case 1:
+ // First page of index
+ SceneItem::display(2120, 0, SET_X, 120, SET_FONT, 1, SET_EXT_BGCOLOR, 7, SET_BG_COLOR, -1,
+ SET_WIDTH, 200, SET_KEEP_ONSCREEN, -1, SET_TEXT_MODE, 0, LIST_END);
+ break;
+ case 2:
+ // Second page of index
+ SceneItem::display(2120, 1, SET_X, 120, SET_FONT, 1, SET_EXT_BGCOLOR, 7, SET_BG_COLOR, -1,
+ SET_WIDTH, 200, SET_KEEP_ONSCREEN, -1, SET_TEXT_MODE, 0, LIST_END);
+ break;
+ case 3:
+ // Display an image associated with the encyclopedia entry
+ SceneItem::display(0, 0);
+
+ scene->_visageHotspot.postInit();
+ scene->_visageHotspot.setVisage(_entries[scene->_subjectIndex]._visage);
+ scene->_visageHotspot.setPosition(Common::Point(129, 180));
+ scene->_visageHotspot.animate(ANIM_MODE_NONE, NULL);
+ scene->_visageVisable = true;
+ break;
+ case 4:
+ // Display page of text
+ SceneItem::display(2121, _entries[scene->_subjectIndex]._lineNum + scene->_lineOffset,
+ SET_X, 130, SET_FONT, 1, SET_EXT_BGCOLOR, 7, SET_BG_COLOR, -1, SET_WIDTH, 200,
+ SET_KEEP_ONSCREEN, -1, SET_TEXT_MODE, 0, LIST_END);
+ _actionIndex = 4;
+ break;
+ }
+}
+
+void Scene2120::Action1::dispatch() {
+ Scene2120 *scene = (Scene2120 *)_globals->_sceneManager._scene;
+
+ Event event;
+ if (_globals->_events.getEvent(event) && (event.eventType == EVENT_BUTTON_DOWN)) {
+ if (scene->_listRect.contains(event.mousePos) && (scene->_dbMode != 2)) {
+ scene->_topicArrowHotspot.setPosition(Common::Point(scene->_topicArrowHotspot._position.x, event.mousePos.y));
+ }
+
+ // Subject button handling
+ if (scene->_subjectButton._bounds.contains(event.mousePos) && (scene->_dbMode != 2)) {
+ scene->_arrowHotspot.setPosition(Common::Point(291, 34));
+ scene->_arrowHotspot._strip = 1;
+ scene->_arrowHotspot.animate(ANIM_MODE_5, NULL);
+
+ if (scene->_dbMode == 0)
+ scene->_subjectIndex = (scene->_topicArrowHotspot._position.y - 48) / 8;
+ else
+ scene->_subjectIndex = (scene->_topicArrowHotspot._position.y - 44) / 8 + 16;
+
+ if ((scene->_subjectIndex == 27) && _globals->getFlag(70))
+ _globals->setFlag(75);
+
+ scene->_topicArrowHotspot.hide();
+ scene->_prevDbMode = scene->_dbMode;
+ scene->_dbMode = 2;
+ scene->_lineOffset = 0;
+
+ _actionIndex = !_entries[scene->_subjectIndex]._visage ? 4 : 3;
+ setDelay(30);
+ scene->_soundHandler.startSound(159);
+ }
+
+ // Next Page button handling
+ if (scene->_nextPageButton._bounds.contains(event.mousePos)) {
+ if (!scene->_dbMode) {
+ scene->_arrowHotspot._strip = 2;
+ scene->_arrowHotspot.setPosition(Common::Point(291, 76));
+ scene->_arrowHotspot.animate(ANIM_MODE_5, NULL);
+ scene->_dbMode = 1;
+
+ _actionIndex = 2;
+ setDelay(30);
+ }
+
+ if ((scene->_dbMode == 2) && (scene->_lineOffset < _entries[scene->_subjectIndex]._size)) {
+ if (!scene->_visageVisable) {
+ ++scene->_lineOffset;
+ } else {
+ scene->_visageVisable = false;
+ scene->_visageHotspot.remove();
+ }
+ setDelay(30);
+ }
+
+ if ((scene->_subjectIndex == 20) && scene->_visageVisable) {
+ scene->_visageVisable = false;
+ scene->_visageHotspot.remove();
+ setDelay(30);
+ }
+
+ scene->_soundHandler.startSound(159);
+ }
+
+ // Previous Page button handling
+ if (scene->_previousPageButton._bounds.contains(event.mousePos)) {
+ switch (scene->_dbMode) {
+ case 1:
+ scene->_arrowHotspot._strip = 3;
+ scene->_arrowHotspot.setPosition(Common::Point(291, 117));
+ scene->_arrowHotspot.animate(ANIM_MODE_5, NULL);
+
+ scene->_dbMode = 0;
+ _actionIndex = 1;
+ setDelay(30);
+ break;
+ case 2:
+ if (scene->_lineOffset > 0) {
+ --scene->_lineOffset;
+ setDelay(20);
+ }
+ if ((_entries[scene->_subjectIndex]._visage != 0) && (scene->_lineOffset == 0)) {
+ _actionIndex = 3;
+ setDelay(30);
+ }
+ break;
+ }
+
+ scene->_soundHandler.startSound(159);
+ }
+
+ // Exit button handling
+ if (scene->_exitButton._bounds.contains(event.mousePos)) {
+ if (scene->_dbMode != 2) {
+ // In the index, so return to the previous scene
+ setAction(NULL);
+ SceneItem::display(0, 0);
+
+ _globals->_gfxManagerInstance._font.setFontNumber(2);
+ _globals->_sceneText._fontNumber = 2;
+ _globals->_sceneManager.changeScene(_globals->_sceneManager._previousScene);
+ } else {
+ // Exit out of topic display to index
+ SceneItem::display(0, 0);
+
+ if (_entries[scene->_subjectIndex]._visage)
+ scene->_visageHotspot.remove();
+
+ scene->_arrowHotspot._strip = 4;
+ scene->_arrowHotspot.setPosition(Common::Point(291, 159));
+ scene->_arrowHotspot.animate(ANIM_MODE_5, NULL);
+ scene->_dbMode = scene->_prevDbMode;
+ _actionIndex = scene->_prevDbMode + 1;
+
+ scene->_topicArrowHotspot.show();
+ setDelay(1);
+ }
+
+ scene->_soundHandler.startSound(159);
+ }
+ }
+
+ Action::dispatch();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2120::postInit(SceneObjectList *OwnerList) {
+ loadScene(2120);
+ setZoomPercents(0, 100, 200, 100);
+ _globals->_player.disableControl();
+
+ _listRect = Rect(18, 48, 260, 177);
+ _subjectButton.setBounds(Rect(266, 13, 320, 56));
+ _nextPageButton.setBounds(Rect(266, 56, 320, 98));
+ _previousPageButton.setBounds(Rect(266, 98, 320, 140));
+ _exitButton.setBounds(Rect(266, 140, 320, 182));
+
+ _topicArrowHotspot.postInit();
+ _topicArrowHotspot.setVisage(2120);
+ _topicArrowHotspot.animate(ANIM_MODE_NONE, NULL);
+ _topicArrowHotspot.setPosition(Common::Point(240, 55));
+
+ _arrowHotspot.postInit();
+ _arrowHotspot.setVisage(2121);
+ _arrowHotspot.animate(ANIM_MODE_NONE, NULL);
+ _arrowHotspot._frame = 1;
+ _arrowHotspot.setPosition(Common::Point(400, 200));
+
+ _dbMode = 0;
+ _prevDbMode = 0;
+ _visageVisable = false;
+ _subjectIndex = 0;
+
+ setAction(&_action1);
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+}
+
+void Scene2120::synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+
+ s.syncAsSint16LE(_dbMode);
+ s.syncAsSint16LE(_prevDbMode);
+ s.syncAsSint16LE(_visageVisable);
+ s.syncAsSint16LE(_subjectIndex);
+ s.syncAsSint16LE(_lineOffset);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2150 - Starcraft Level 2
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2150::Action1::signal() {
+ Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ Common::Point pt(158, 103);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ scene->_soundHandler.startSound(162);
+ scene->_hotspot1.animate(ANIM_MODE_5, this);
+ break;
+ case 2: {
+ _globals->_player.setStrip2(4);
+ Common::Point pt(158, 95);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ _globals->_player.setStrip2(-1);
+ _globals->_player._strip = 3;
+ setDelay(10);
+ break;
+ case 4:
+ scene->_area1.display();
+ scene->_area2.display();
+ scene->_area3.display();
+ scene->_area4.display();
+
+ scene->_area2.draw(true);
+ _state = 0;
+ _globals->_events.setCursor(CURSOR_USE);
+
+ while (!_state && !_vm->getEventManager()->shouldQuit()) {
+ // Wait for an event
+ Event event;
+ if (!_globals->_events.getEvent(event)) {
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ continue;
+ }
+
+ if (scene->_area1._bounds.contains(event.mousePos)) {
+ scene->_area2.draw(false);
+ scene->_area1.draw(true);
+ _state = scene->_area1._actionId;
+ }
+ if (scene->_area2._bounds.contains(event.mousePos)) {
+ scene->_area2.draw(true);
+ _state = scene->_area2._actionId;
+ }
+ if (scene->_area3._bounds.contains(event.mousePos)) {
+ scene->_area2.draw(false);
+ scene->_area3.draw(true);
+ _state = scene->_area3._actionId;
+ }
+ }
+
+ scene->_soundHandler.startSound(161);
+ scene->_area1.restore();
+ scene->_area2.restore();
+ scene->_area3.restore();
+ scene->_area4.restore();
+
+ if (_state == 2150) {
+ setDelay(1);
+ } else {
+ scene->_soundHandler.startSound(162);
+ scene->_hotspot1.animate(ANIM_MODE_6, this);
+ }
+ break;
+ case 5:
+ if (_state == 2150) {
+ Common::Point pt(158, 103);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ } else {
+ _globals->_sceneManager.changeScene(_state);
+ }
+ break;
+ case 6:
+ scene->_soundHandler.startSound(162);
+ scene->_hotspot1.animate(ANIM_MODE_6, this);
+ break;
+ case 7:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene2150::Action2::signal() {
+ Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ Common::Point pt(47, 85);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ _globals->_player.setVisage(2152);
+ _globals->_player.setFrame(1);
+ _globals->_player.setStrip(8);
+ _globals->_player.animate(ANIM_MODE_8, 1, this);
+
+ scene->_soundHandler.startSound(163);
+ break;
+ case 2:
+ scene->_soundHandler.startSound(164);
+ scene->_hotspot10.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start((RING_INVENTORY._ale._sceneNumber == 2150) ? 2151 : 2152, this);
+ break;
+ case 4:
+ scene->_hotspot14.postInit();
+ scene->_hotspot14.setVisage(2152);
+ scene->_hotspot14.setStrip(6);
+ scene->_hotspot14.setPosition(Common::Point(59, 54));
+
+ if (scene->_stripManager._field2E8 == 15) {
+ scene->_hotspot14.setFrame(5);
+ RING_INVENTORY._ale._sceneNumber = 1;
+ } else {
+ scene->_hotspot14.setFrame(scene->_stripManager._field2E8 - 5);
+ }
+
+ _globals->_player.setFrame(1);
+ _globals->_player.setStrip(7);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 5:
+ scene->_soundHandler.startSound(164);
+ scene->_hotspot10.animate(ANIM_MODE_6, NULL);
+ scene->_hotspot14.remove();
+
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 6:
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.enableControl();
+
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2150::Hotspot1::doAction(int action) {
+ Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2150, 0);
+ break;
+ case CURSOR_USE:
+ scene->setAction(&scene->_action1);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2150::Hotspot2::doAction(int action) {
+ Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2150, 1);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2156;
+ scene->setAction(&scene->_sequenceManager, scene, 2156, &_globals->_player, this, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2150::Hotspot4::doAction(int action) {
+ Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2150, 3);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2155;
+ scene->setAction(&scene->_sequenceManager, scene, 2155, &_globals->_player, &scene->_hotspot4, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2150::Hotspot7::doAction(int action) {
+ Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2150, 7);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2150, 19);
+ else {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2154;
+ scene->setAction(&scene->_sequenceManager, scene, 2154, &_globals->_player, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2150::Hotspot10::doAction(int action) {
+ Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2150, 10);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2150, 19);
+ else
+ scene->setAction(&scene->_action2);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene2150::Scene2150() :
+ _hotspot3(18, CURSOR_LOOK, 2150, 2, CURSOR_USE, 2150, 18, LIST_END),
+ _hotspot5(17, CURSOR_LOOK, 2150, 4, CURSOR_USE, 2150, 18, LIST_END),
+ _hotspot6(0, CURSOR_LOOK, 2150, 5, CURSOR_USE, 2150, 18, LIST_END),
+ _hotspot8(16, CURSOR_LOOK, 2150, 8, LIST_END),
+ _hotspot9(0, CURSOR_LOOK, 2150, 9, CURSOR_USE, 2150, 13, LIST_END),
+ _hotspot11(0, CURSOR_LOOK, 2150, 12, LIST_END) {
+}
+
+void Scene2150::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(55, 85, 200, 100);
+ loadScene(2150);
+
+ _stripManager.addSpeaker(&_speakerGameText);
+
+ _hotspot7.postInit();
+ _hotspot7.setVisage(2152);
+ _hotspot7._frame = 1;
+ _hotspot7._strip = 2;
+ _hotspot7.animate(ANIM_MODE_8, NULL);
+ _hotspot7.setPosition(Common::Point(122, 62));
+ _hotspot7.changeZoom(100);
+ _hotspot7.fixPriority(76);
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(2151);
+ _hotspot2._frame = 1;
+ _hotspot2._strip = 3;
+ _hotspot2.animate(ANIM_MODE_NONE, NULL);
+ _hotspot2.setPosition(Common::Point(257, 67));
+ _hotspot2.changeZoom(100);
+ _hotspot2.fixPriority(60);
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(2151);
+ _hotspot1._frame = 1;
+ _hotspot1._strip = 2;
+ _hotspot1.animate(ANIM_MODE_NONE, NULL);
+ _hotspot1.setPosition(Common::Point(158, 99));
+ _hotspot1.changeZoom(100);
+ _hotspot1.fixPriority(99);
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(2150);
+ _hotspot4._frame = 1;
+ _hotspot4._strip = 2;
+ _hotspot4.animate(ANIM_MODE_NONE, NULL);
+ _hotspot4.setPosition(Common::Point(218, 200));
+ _hotspot4.changeZoom(100);
+ _hotspot4.fixPriority(200);
+
+ _hotspot10.postInit();
+ _hotspot10.setVisage(2152);
+ _hotspot10.setStrip(5);
+ _hotspot10.setPosition(Common::Point(59, 56));
+
+ _rect1 = Rect(260, 70, 270, 77);
+ _rect2 = Rect(222, 142, 252, 150);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(_globals->getFlag(13) ? 2170 : 0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.fixPriority(-1);
+ _globals->_player.changeZoom(-1);
+ _globals->_player._moveDiff.y = 3;
+
+ _hotspot8.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot9.setBounds(Rect(133, 0, 198, 91));
+ _hotspot11.setBounds(Rect(142, 119, 176, 158));
+
+ _globals->_sceneItems.addItems(&_hotspot1, &_hotspot2, &_hotspot3, &_hotspot4, &_hotspot5,
+ &_hotspot6, &_hotspot7, &_hotspot10, &_hotspot9, &_hotspot11, &_hotspot8, NULL);
+
+ _area1.setup(2153, 2, 1, 2100);
+ _area1._pt = Common::Point(200, 31);
+ _area2.setup(2153, 3, 1, 2150);
+ _area2._pt = Common::Point(200, 50);
+ _area3.setup(2153, 4, 1, 2320);
+ _area3._pt = Common::Point(200, 75);
+ _area4.setup(2153, 1, 1, 10);
+ _area4._pt = Common::Point(237, 77);
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 2120:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ _globals->_player.setPosition(Common::Point(108, 99));
+ break;
+ case 2200:
+ _globals->_player.disableControl();
+ _globals->_player.setPosition(Common::Point(159, 240));
+ _sceneMode = 2152;
+ setAction(&_sequenceManager, this, 2152, &_globals->_player, NULL);
+ break;
+ case 2280:
+ _globals->_player.disableControl();
+ _globals->_player._angle = 180;
+ _globals->_player.setPosition(Common::Point(265, 80));
+
+ _hotspot2._frame = _hotspot2.getFrameCount();
+ _sceneMode = 2157;
+ setAction(&_sequenceManager, this, 2157, &_hotspot2, NULL);
+ break;
+ case 2230:
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player._strip = 4;
+ _globals->_player.setPosition(Common::Point(229, 139));
+ break;
+ case 2100:
+ default:
+ _globals->_player.disableControl();
+ _globals->_player.setPosition(Common::Point(158, 95));
+ _globals->_player.setStrip(3);
+ _sceneMode = 2151;
+
+ setAction(&_sequenceManager, this, 2151, &_globals->_player, &_hotspot1, NULL);
+ break;
+ }
+
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+}
+
+void Scene2150::synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ _rect1.synchronise(s);
+ _rect2.synchronise(s);
+}
+
+void Scene2150::signal() {
+ switch (_sceneMode) {
+ case 2151:
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.enableControl();
+ break;
+ case 2152:
+ case 2153:
+ case 2157:
+ _globals->_player.enableControl();
+ break;
+ case 2154:
+ _globals->_sceneManager.changeScene(2120);
+ break;
+ case 2155:
+ _globals->_sceneManager.changeScene(2230);
+ break;
+ case 2156:
+ _globals->_sceneManager.changeScene(2280);
+ break;
+ }
+}
+
+void Scene2150::dispatch() {
+ Scene::dispatch();
+
+ if (!_action) {
+ if (_rect1.contains(_globals->_player._position)) {
+ _globals->_player.disableControl();
+ _sceneMode = 2156;
+ setAction(&_sequenceManager, this, 2156, &_globals->_player, &_hotspot2, NULL);
+ }
+ if (_rect2.contains(_globals->_player._position)) {
+ _globals->_player.disableControl();
+ _sceneMode = 2155;
+ setAction(&_sequenceManager, this, 2155, &_globals->_player, &_hotspot4, NULL);
+ }
+ if (_globals->_player._position.y >= 196) {
+ _globals->_player.disableControl();
+ SceneItem::display2(2150, 20);
+
+ _sceneMode = 2153;
+ setAction(&_sequenceManager, this, 2153, &_globals->_player, NULL);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2200 - Starcraft - AutoDoc
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2200::Action1::signal() {
+ Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(6);
+ break;
+ case 1:
+ scene->_hotspot4.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ SceneItem::display2(2200, 7);
+ _globals->_sceneManager.changeScene(2150);
+ remove();
+ break;
+ }
+}
+
+void Scene2200::Action2::signal() {
+ Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(3);
+ break;
+ case 1:
+ setDelay(30);
+ break;
+ case 2:
+ scene->_hotspot4.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ scene->_hotspot4.setStrip(4);
+ setDelay(30);
+ break;
+ case 4:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(2040, this, scene);
+ break;
+ case 5:
+ scene->_hotspot4.setStrip(4);
+ scene->_hotspot4.animate(ANIM_MODE_NONE, NULL);
+ _globals->_player._uiEnabled = true;
+ remove();
+ break;
+ }
+}
+
+void Scene2200::Action3::signal() {
+ Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_soundHandler2.startSound(103);
+
+ scene->_hotspot4.setStrip(4);
+ scene->_hotspot4.animate(ANIM_MODE_NONE, NULL);
+ _globals->_player.disableControl();
+
+ scene->_hotspot2.postInit();
+ scene->_hotspot2.setVisage(2201);
+ scene->_hotspot2._strip = 2;
+ scene->_hotspot2.setPosition(Common::Point(218, 0));
+
+ Common::Point pt(218, 63);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot2.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ scene->_soundHandler2.startSound(104);
+ scene->_hotspot4.setStrip(2);
+ scene->_hotspot4.setFrame(2);
+ setDelay(120);
+ break;
+ case 2:
+ if (_globals->getFlag(83)) {
+ _actionIndex = 8;
+ setDelay(5);
+ } else {
+ for (SynchronisedList<SceneObject *>::iterator i = _globals->_sceneObjects->begin();
+ i != _globals->_sceneObjects->end(); ++i) {
+ (*i)->hide();
+ }
+
+ _globals->_sceneManager._scene->loadScene(66);
+
+ scene->_hotspot6.postInit();
+ scene->_hotspot6.setVisage(66);
+ scene->_hotspot6.setPosition(Common::Point(160, 197));
+
+ scene->_hotspot7.postInit();
+ scene->_hotspot7.setVisage(65);
+ scene->_hotspot7.setStrip(4);
+ scene->_hotspot7.setFrame(1);
+ scene->_hotspot7.setPosition(Common::Point(145, 165));
+
+ SceneItem::display(60, 1, SET_Y, 40, SET_X, 25, SET_FONT, 75, SET_BG_COLOR, -1, SET_FG_COLOR, 34,
+ SET_POS_MODE, 0, SET_WIDTH, 280, SET_KEEP_ONSCREEN, 1, LIST_END);
+ _state = 1;
+ setDelay(1800);
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ SceneItem::display(60, _actionIndex - 2, SET_Y, 40, SET_X, 25, SET_FONT, 75, SET_BG_COLOR, -1, SET_FG_COLOR, 34,
+ SET_POS_MODE, 0, SET_WIDTH, 280, SET_KEEP_ONSCREEN, 1, LIST_END);
+ setDelay(1800);
+ break;
+ case 6:
+ scene->_hotspot7.remove();
+ SceneItem::display(0, 0);
+ _state = 0;
+ setDelay(5);
+ break;
+ case 7:
+ for (SynchronisedList<SceneObject *>::iterator i = _globals->_sceneObjects->begin();
+ i != _globals->_sceneObjects->end(); ++i)
+ (*i)->show();
+
+ scene->_hotspot6.remove();
+ _globals->_sceneManager._scene->loadScene(2200);
+ setDelay(5);
+ break;
+ case 8:
+ scene->_stripManager.start(2060, this, scene);
+ break;
+ case 9:
+ scene->_hotspot4.setStrip(4);
+ scene->_hotspot4.animate(ANIM_MODE_NONE, NULL);
+ break;
+ case 10:
+ _globals->_sceneManager.changeScene(2000);
+ remove();
+ break;
+ }
+}
+
+void Scene2200::Action3::process(Event &event) {
+ if (!event.handled && ((event.eventType == EVENT_KEYPRESS) || (event.eventType == EVENT_BUTTON_DOWN))) {
+ _state = 0;
+ event.handled = true;
+ setDelay(1);
+ }
+
+ Action::process(event);
+}
+
+void Scene2200::Action4::signal() {
+ Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1:
+ scene->_stripManager.start(2202, this, scene);
+ break;
+ case 2:
+ scene->_hotspot4.setStrip(4);
+ scene->_hotspot4.animate(ANIM_MODE_NONE, NULL);
+ setDelay(10);
+ break;
+ case 3:
+ _globals->_player._uiEnabled = true;
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2200::Hotspot3::doAction(int action) {
+ Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2200, 10);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2200, 11);
+ break;
+ case CURSOR_TALK:
+ _globals->_player._uiEnabled = false;
+ scene->setAction(&scene->_action4);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2200::Hotspot5::doAction(int action) {
+ Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2200, 8);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2200, 9);
+ break;
+ case CURSOR_TALK:
+ scene->_sceneMode = 2201;
+ _globals->_player._uiEnabled = false;
+ scene->setAction(&scene->_sequenceManager, scene, 2201, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2200::Hotspot9::doAction(int action) {
+ Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2200, _globals->getFlag(8) ? 1 : 0);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2200, 3);
+ break;
+ case OBJECT_INFODISK:
+ if (_globals->_sceneManager._previousScene == 2310) {
+ scene->_soundHandler2.startSound(35);
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action3);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+
+Scene2200::Scene2200() :
+ _hotspot1(0, CURSOR_LOOK, 2200, 5, CURSOR_USE, 2200, 6, LIST_END),
+ _hotspot10(0, CURSOR_LOOK, 2200, 4, LIST_END) {
+}
+
+void Scene2200::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(0, 200, 200, 200);
+ loadScene(2200);
+
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSL);
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerMR);
+ _stripManager.addSpeaker(&_speakerGameText);
+
+ _speakerQText._npc = &_globals->_player;
+ _speakerSText._npc = &_hotspot5;
+ _speakerMText._npc = &_hotspot3;
+
+ _stripManager.setCallback(this);
+
+ _hotspot5.postInit();
+ _hotspot5.setVisage(2840);
+ _hotspot5.setPosition(Common::Point(50, 235));
+
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2840);
+ _hotspot8.setStrip(2);
+ _hotspot8.setPosition(Common::Point(96, 184));
+ _hotspot8.fixPriority(236);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2640);
+ _globals->_player.setFrame2(3);
+ _globals->_player.setPosition(Common::Point(110, 233));
+ _globals->_player.disableControl();
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 2150:
+ _hotspot5.remove();
+ _hotspot8.remove();
+ break;
+ case 4000:
+ _globals->_soundHandler.startSound(100);
+ _globals->_soundHandler.proc5(true);
+ _globals->_player.remove();
+ _hotspot5.remove();
+ _hotspot8.remove();
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(2202);
+ _hotspot1.setPosition(Common::Point(175, 173));
+ _hotspot1.fixPriority(99);
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(2202);
+ _hotspot3._strip = 2;
+ _hotspot3.setPosition(Common::Point(152, 76));
+ _hotspot3.fixPriority(100);
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(2202);
+ _hotspot4._strip = 3;
+ _hotspot4.setPosition(Common::Point(115, 76));
+ _hotspot4.fixPriority(200);
+
+ setAction(&_action1);
+ break;
+ case 2310:
+ default:
+ RING_INVENTORY._infoDisk._sceneNumber = 1;
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(2215);
+ _hotspot3.setPosition(Common::Point(144, 132));
+ _globals->_sceneItems.push_back(&_hotspot3);
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(2215);
+ _hotspot4._strip = 2;
+ _hotspot4.setPosition(Common::Point(120, 78));
+ _hotspot4.fixPriority(255);
+ _globals->_sceneItems.push_back(&_hotspot4);
+
+ _soundHandler1.startSound(101);
+ _soundHandler2.startSound(100);
+ _globals->_soundHandler.proc5(true);
+
+ _globals->_sceneItems.push_back(&_hotspot5);
+ setAction(&_action2);
+ break;
+ }
+
+ _exitRect = Rect(0, 0, 35, SCREEN_HEIGHT);
+ _hotspot9.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot10.setBounds(Rect(87, 43, 149, 109));
+
+ _globals->_sceneItems.addItems(&_hotspot10, &_hotspot9, NULL);
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+}
+
+void Scene2200::stripCallback(int v) {
+ switch (v) {
+ case 1:
+ _hotspot4.setStrip(3);
+ _hotspot4.animate(ANIM_MODE_7, 0, NULL);
+ break;
+ case 2:
+ _hotspot4.setStrip(4);
+ _hotspot4.animate(ANIM_MODE_NONE, NULL);
+ break;
+ }
+}
+
+void Scene2200::synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ _exitRect.synchronise(s);
+}
+
+void Scene2200::signal() {
+ if ((_sceneMode == 2201) || (_sceneMode == 2202))
+ _globals->_player._uiEnabled = true;
+}
+
+void Scene2200::dispatch() {
+ Scene::dispatch();
+
+ if (!_action) {
+ if (_exitRect.contains(_globals->_player._position))
+ _globals->_sceneManager.changeScene(2150);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2222 - Stasis Field Map
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2222::Action1::signal() {
+ Scene2222 *scene = (Scene2222 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1:
+ scene->_stripManager.start(2222, this);
+ break;
+ case 2:
+ setDelay(30);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(1000);
+ break;
+ }
+}
+
+void Scene2222::Action2::signal() {
+ Scene2222 *scene = (Scene2222 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ scene->_stripManager.start(5700, this);
+ break;
+ case 2:
+ setDelay(120);
+ break;
+ case 3:
+ _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL;
+ _globals->_sceneManager.changeScene(2100);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2222::postInit(SceneObjectList *OwnerList) {
+ loadScene((_globals->_sceneManager._previousScene == 2000) ? 3400 : 3450);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSR);
+ _stripManager.addSpeaker(&_speakerML);
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(3401);
+ _hotspot1.setStrip2(1);
+ _hotspot1._frame = 1;
+ _hotspot1.animate(ANIM_MODE_2, 0);
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(3401);
+ _hotspot2.setStrip2(2);
+ _hotspot2._frame = 2;
+ _hotspot2.animate(ANIM_MODE_2, 0);
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(3401);
+ _hotspot3.setStrip2(2);
+ _hotspot3._frame = 3;
+ _hotspot3.animate(ANIM_MODE_2, 0);
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(3401);
+ _hotspot4.setStrip2(2);
+ _hotspot4._frame = 4;
+ _hotspot4.animate(ANIM_MODE_2, 0);
+
+ _hotspot5.postInit();
+ _hotspot5.setVisage(3401);
+ _hotspot5.setStrip2(2);
+ _hotspot5.setFrame(5);
+ _hotspot5.animate(ANIM_MODE_2, 0);
+
+ if (_globals->_sceneManager._previousScene == 2100) {
+ _hotspot1.setPosition(Common::Point(61, 101));
+ _hotspot2.setPosition(Common::Point(239, 149));
+ _hotspot3.setPosition(Common::Point(184, 85));
+ _hotspot4.setPosition(Common::Point(105, 165));
+ _hotspot5.remove();
+
+ setAction(&_action2);
+ } else {
+ _hotspot1.setPosition(Common::Point(110, 108));
+ _hotspot2.setPosition(Common::Point(175, 136));
+ _hotspot3.setPosition(Common::Point(162, 96));
+ _hotspot4.setPosition(Common::Point(118, 141));
+ _hotspot5.setPosition(Common::Point(124, 107));
+
+ setAction(&_action1);
+ }
+
+ _soundHandler.startSound(116);
+ _globals->_sceneManager._scene->_sceneBounds.center(_hotspot1._position);
+
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+}
+
+
+/*--------------------------------------------------------------------------
+ * Scene 2230 - Starcraft - Quinn's Room
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2230::Action1::signal() {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ switch (scene->_field30A) {
+ case 1:
+ scene->setAction(&scene->_action3);
+ break;
+ case 2:
+ scene->setAction(&scene->_action6);
+ break;
+ default:
+ setDelay(10);
+ break;
+ }
+ break;
+ case 1: {
+ Common::Point pt(84, 74);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ scene->_hotspot1.animate(ANIM_MODE_5, this);
+ break;
+ case 3: {
+ Common::Point pt(63, 60);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 4:
+ scene->_hotspot1.animate(ANIM_MODE_6, this);
+ break;
+ case 5:
+ _globals->_sceneManager.changeScene(2150);
+ break;
+ }
+}
+
+void Scene2230::Action2::signal() {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ switch (scene->_field30A) {
+ case 2:
+ scene->setAction(&scene->_action6, this);
+ break;
+ default:
+ setDelay(10);
+ break;
+ }
+ break;
+ case 1: {
+ _globals->_player.disableControl();
+ scene->_field30A = 1;
+ _globals->_player._regionBitList |= ~0x80;
+ Common::Point pt(160, 96);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _globals->_player.setVisage(2235);
+ _globals->_player.setStrip2(1);
+ _globals->_player.fixPriority(100);
+ _globals->_player._frame = 1;
+ _globals->_player.setPosition(Common::Point(200, 68));
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ scene->_soundHandler.startSound(157);
+ _globals->_player._moveDiff = Common::Point(1, 1);
+ _globals->_player.setAction(&scene->_action4);
+ _globals->_player._uiEnabled = true;
+
+ _globals->_events.setCursor(CURSOR_USE);
+ remove();
+ break;
+ }
+}
+
+void Scene2230::Action3::signal() {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.setAction(NULL);
+ _globals->_player._moveDiff = Common::Point(5, 3);
+ _globals->_player.setStrip2(_globals->_player._strip);
+
+ Common::Point pt(190, 74);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+
+ scene->_soundHandler.proc3();
+ break;
+ }
+ case 1:
+ _globals->_player._strip = 3;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ _globals->_player._regionBitList |= 0x80;
+ scene->_field30A = 0;
+
+ _globals->_player.setVisage(0);
+ _globals->_player.setStrip2(-1);
+ _globals->_player.fixPriority(-1);
+ _globals->_player.setPosition(Common::Point(164, 96));
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player._canWalk = true;
+
+ _globals->_events.setCursor(CURSOR_USE);
+ remove();
+ }
+}
+
+void Scene2230::Action4::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ Common::Point pt(190 + _globals->_randomSource.getRandomNumber(9), 68);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene2230::Action5::signal() {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ switch (scene->_field30A) {
+ case 2:
+ scene->setAction(&scene->_action3, this);
+ break;
+ default:
+ setDelay(10);
+ break;
+ }
+ break;
+ case 1: {
+ _globals->_player.disableControl();
+ Common::Point pt(209, 124);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _globals->_player.fixPriority(1430);
+ _globals->_player.setVisage(2232);
+ _globals->_player._strip = 1;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ _globals->_events.setCursor(CURSOR_USE);
+ _globals->_player._uiEnabled = true;
+ scene->_field30A = 2;
+ remove();
+ break;
+ }
+}
+
+void Scene2230::Action6::signal() {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player._strip = 2;
+ _globals->_player._frame = 1;
+ _globals->_player.fixPriority(-1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 1:
+ scene->_field30A = 0;
+ _globals->_player.setVisage(0);
+ _globals->_player._strip = 1;
+ _globals->_player._canWalk = true;
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ remove();
+ break;
+ }
+}
+
+void Scene2230::Action7::signal() {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+
+ switch (scene->_field30A) {
+ case 1:
+ scene->setAction(&scene->_action3, this);
+ break;
+ case 2:
+ scene->setAction(&scene->_action6, this);
+ break;
+ default:
+ setDelay(10);
+ break;
+ }
+ break;
+ case 1: {
+ Common::Point pt(140, 119);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ scene->_soundHandler.startSound(158);
+ scene->_hotspot8.setStrip2(2);
+
+ Common::Point pt(scene->_hotspot8._position.x, 97);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot8.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ scene->_hotspot2.postInit();
+ scene->_hotspot2.setVisage(2231);
+ scene->_hotspot2._strip = 3;
+ scene->_hotspot2.setPosition(Common::Point(166, 116));
+ scene->_hotspot2.fixPriority(131);
+ scene->_hotspot2.animate(ANIM_MODE_5, this);
+
+ scene->_hotspot8._frame = 2;
+ break;
+ case 4:
+ _globals->_sceneItems.push_front(&scene->_hotspot10);
+ _globals->_sceneItems.push_front(&scene->_hotspot11);
+ _globals->_sceneItems.push_front(&scene->_hotspot12);
+
+ scene->_hotspot2.remove();
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene2230::Action8::signal() {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+
+ switch (scene->_field30A) {
+ case 1:
+ scene->setAction(&scene->_action3, this);
+ break;
+ case 2:
+ scene->setAction(&scene->_action6, this);
+ break;
+ default:
+ setDelay(10);
+ break;
+ }
+ break;
+ case 1: {
+ Common::Point pt(140, 119);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ _globals->_sceneItems.remove(&scene->_hotspot10);
+ _globals->_sceneItems.remove(&scene->_hotspot11);
+ _globals->_sceneItems.remove(&scene->_hotspot12);
+
+ switch (scene->_field30A) {
+ case 1:
+ scene->setAction(&scene->_action3, this);
+ break;
+ case 2:
+ scene->setAction(&scene->_action6, this);
+ break;
+ default:
+ setDelay(10);
+ break;
+ }
+ break;
+ }
+ case 3:
+ scene->_hotspot2.postInit();
+ scene->_hotspot2.setVisage(2231);
+ scene->_hotspot2._strip = 3;
+ scene->_hotspot2._frame = scene->_hotspot2.getFrameCount();
+ scene->_hotspot2.setPosition(Common::Point(166, 116));
+ scene->_hotspot2.fixPriority(131);
+ scene->_hotspot2.animate(ANIM_MODE_6, this);
+ break;
+ case 4: {
+ scene->_soundHandler.startSound(158);
+ scene->_hotspot2.remove();
+ scene->_hotspot8._frame = 1;
+
+ Common::Point pt(scene->_hotspot8._position.x, 133);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot8.addMover(mover, &pt, this);
+ break;
+ }
+ case 5:
+ scene->_hotspot8.setStrip2(1);
+ _globals->_player.enableControl();
+
+ remove();
+ break;
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2230::Hotspot1::doAction(int action) {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2230, 0);
+ break;
+ case CURSOR_USE:
+ scene->setAction(&scene->_action1);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot3::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(4))
+ SceneItem::display2(2230, 1);
+ else {
+ SceneItem::display2(2230, 1);
+ SceneItem::display2(2230, 2);
+ SceneItem::display2(2230, 3);
+ _globals->setFlag(4);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot4::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(30))
+ SceneItem::display2(2230, 6);
+ else if (_globals->getFlag(29)) {
+ SceneItem::display2(2230, 5);
+ _globals->setFlag(30);
+ } else {
+ SceneItem::display2(2230, 4);
+ _globals->setFlag(29);
+ }
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2230, 7);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot5::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(5))
+ SceneItem::display2(2230, 9);
+ else {
+ _globals->setFlag(5);
+ SceneItem::display2(2230, 8);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot6::doAction(int action) {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(6))
+ SceneItem::display2(2230, 11);
+ else {
+ _globals->setFlag(6);
+ SceneItem::display2(2230, 10);
+ }
+ break;
+ case CURSOR_USE:
+ if (scene->_field30A == 1)
+ scene->setAction(&scene->_action3);
+ else if (_globals->getFlag(13))
+ SceneItem::display2(2230, 28);
+ else
+ scene->setAction(&scene->_action2);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot7::doAction(int action) {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(7))
+ SceneItem::display2(2230, 13);
+ else {
+ _globals->setFlag(6);
+ SceneItem::display2(2230, 12);
+ }
+ break;
+ case CURSOR_USE:
+ if (scene->_field30A == 2)
+ scene->setAction(&scene->_action6);
+ else if (_globals->getFlag(13))
+ SceneItem::display2(2230, 29);
+ else
+ scene->setAction(&scene->_action5);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot8::doAction(int action) {
+ Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (scene->_hotspot8._strip == 1) {
+ if (_globals->getFlag(22))
+ SceneItem::display2(2230, 19);
+ else {
+ _globals->setFlag(22);
+ SceneItem::display2(2230, 14);
+ }
+ } else {
+ if (_globals->getFlag(25))
+ SceneItem::display2(2230, 21);
+ else {
+ _globals->setFlag(25);
+ SceneItem::display2(2230, 20);
+ }
+ }
+ break;
+ case CURSOR_USE:
+ if (scene->_hotspot8._strip == 1)
+ scene->setAction(&scene->_action7);
+ else
+ scene->setAction(&scene->_action8);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot10::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(26))
+ SceneItem::display2(2230, 25);
+ else {
+ _globals->setFlag(26);
+ SceneItem::display2(2230, 24);
+ }
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2230, 28);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot11::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(27))
+ SceneItem::display2(2230, 23);
+ else {
+ _globals->setFlag(27);
+ SceneItem::display2(2230, 22);
+ }
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2230, 28);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2230::Hotspot12::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(28))
+ SceneItem::display2(2230, 27);
+ else {
+ _globals->setFlag(28);
+ SceneItem::display2(2230, 26);
+ }
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2230, 28);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene2230::Scene2230() :
+ _hotspot9(0, CURSOR_LOOK, 2230, 16, CURSOR_USE, 2230, 18, LIST_END) {
+}
+
+void Scene2230::postInit(SceneObjectList *OwnerList) {
+ loadScene(2230);
+ Scene::postInit();
+ setZoomPercents(75, 80, 120, 100);
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(2230);
+ _hotspot1._frame = 1;
+ _hotspot1.animate(ANIM_MODE_NONE, 0);
+ _hotspot1.setPosition(Common::Point(72, 69));
+ _hotspot1.changeZoom(100);
+
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2231);
+ _hotspot8._frame = 1;
+ _hotspot8.animate(ANIM_MODE_NONE, 0);
+ _hotspot8.setPosition(Common::Point(164, 133));
+ _hotspot8.changeZoom(100);
+ _hotspot8.fixPriority(129);
+
+ _rect1 = Rect(59, 64, 89, 74);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(_globals->getFlag(13) ? 2170 : 0);
+ _globals->_player.animate(ANIM_MODE_1, 0);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(80, 80));
+ _globals->_player._moveDiff.y = 3;
+ _globals->_player._regionBitList |= 0x80;
+ _globals->_player.changeZoom(-1);
+
+ _field30A = 0;
+ _globals->_player.enableControl();
+
+ _hotspot5.setBounds(Rect(108, 34, 142, 76));
+ _hotspot4.setBounds(Rect(92, 14, 106, 57));
+ _hotspot6.setBounds(Rect(169, 58, 261, 95));
+ _hotspot7.setBounds(Rect(111, 117, 222, 158));
+ _hotspot3.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot10.setBounds(Rect(170, 96, 176, 106));
+ _hotspot11.setBounds(Rect(158, 109, 164, 115));
+ _hotspot12.setBounds(Rect(170, 109, 177, 115));
+
+ _globals->_sceneItems.addItems(&_hotspot8, &_hotspot5, &_hotspot4, &_hotspot6, &_hotspot7,
+ &_hotspot1, &_hotspot3, NULL);
+
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+}
+
+void Scene2230::synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ _rect1.synchronise(s);
+ s.syncAsSint16LE(_field30A);
+}
+
+void Scene2230::dispatch() {
+ Scene::dispatch();
+
+ if (!_action) {
+ if (_rect1.contains(_globals->_player._position))
+ setAction(&_action1);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2280 - Starcraft - Storage Room
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2280::Action1::signal() {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ Common::Point pt(192, 97);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ scene->_soundHandler.startSound(162);
+ scene->_hotspot16.animate(ANIM_MODE_5, this);
+ break;
+ case 2: {
+ Common::Point pt(218, 87);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ _globals->_player.setStrip(3);
+ setDelay(10);
+ break;
+ case 4:
+ _globals->_player.fixPriority(1);
+ scene->_soundHandler.startSound(162);
+ scene->_hotspot16.animate(ANIM_MODE_6, this);
+ break;
+ case 5:
+ _globals->_sceneManager.changeScene(7000);
+ break;
+ }
+}
+
+void Scene2280::Action2::signal() {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ Common::Point pt(94, 117);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ scene->_soundHandler.startSound(265);
+
+ _globals->_player.setVisage(2162);
+ _globals->_player._frame = 1;
+ _globals->_player._strip = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+
+ scene->_hotspot8.remove();
+ scene->_hotspot10.remove();
+ break;
+ case 2:
+ _globals->_player._frame = 1;
+ _globals->_player._strip = 2;
+ _globals->_player.animate(ANIM_MODE_4, 3, 1, this);
+ break;
+ case 3:
+ _globals->_player.animate(ANIM_MODE_5, this);
+ scene->_hotspot12.remove();
+ break;
+ case 4:
+ scene->_soundHandler.startSound(266);
+ _globals->_player.setVisage(2170);
+ _globals->_player._frame = 1;
+ _globals->_player._strip = 4;
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player._moveDiff = Common::Point(4, 1);
+
+ _globals->setFlag(13);
+ SceneItem::display2(2280, 37);
+
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene2280::Action3::signal() {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ Common::Point pt(94, 117);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ scene->_soundHandler.startSound(265);
+
+ _globals->_player.setVisage(2162);
+ _globals->_player._frame = 6;
+ _globals->_player._strip = 2;
+ _globals->_player.animate(ANIM_MODE_4, 3, -1, this);
+ break;
+ case 2:
+ scene->_hotspot12.postInit();
+ scene->_hotspot12.setVisage(2280);
+ scene->_hotspot12._strip = 2;
+ scene->_hotspot12._frame = 3;
+ scene->_hotspot12.setPosition(Common::Point(88, 76));
+ scene->_hotspot12.fixPriority(1);
+
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 3:
+ _globals->_player._strip = 1;
+ _globals->_player._frame = 12;
+
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 4:
+ scene->_hotspot8.postInit();
+ scene->_hotspot8.setVisage(2280);
+ scene->_hotspot8._strip = 2;
+ scene->_hotspot8._frame = 1;
+ scene->_hotspot8.animate(ANIM_MODE_NONE, NULL);
+ scene->_hotspot8.setPosition(Common::Point(79, 108));
+ scene->_hotspot8.changeZoom(100);
+ scene->_hotspot8.fixPriority(1);
+
+ scene->_hotspot10.postInit();
+ scene->_hotspot10.setVisage(2280);
+ scene->_hotspot10._strip = 2;
+ scene->_hotspot10._frame = 2;
+ scene->_hotspot10.animate(ANIM_MODE_NONE, NULL);
+ scene->_hotspot10.setPosition(Common::Point(79, 104));
+ scene->_hotspot10.changeZoom(100);
+ scene->_hotspot10.fixPriority(1);
+
+ _globals->clearFlag(13);
+
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player._strip = 4;
+ _globals->_player._moveDiff = Common::Point(3, 5);
+
+ SceneItem::display2(2280, 38);
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene2280::Action4::signal() {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ switch (_state) {
+ case 1:
+ case 51: {
+ Common::Point pt(163, 67);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 6:
+ case 50: {
+ Common::Point pt(173, 63);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ }
+ break;
+ }
+ case 1:
+ _globals->_player.setVisage(2161);
+ _globals->_player._strip = 1;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ switch (_state) {
+ case 1:
+ scene->_hotspot18.remove();
+ RING_INVENTORY._scanner._sceneNumber = 1;
+ break;
+ case 6:
+ scene->_hotspot17.remove();
+ RING_INVENTORY._medkit._sceneNumber = 1;
+ break;
+ case 50:
+ scene->_hotspot17.postInit();
+ scene->_hotspot17.setVisage(2161);
+ scene->_hotspot17._strip = 2;
+ scene->_hotspot17._frame = 1;
+ scene->_hotspot17.animate(ANIM_MODE_NONE, NULL);
+ scene->_hotspot17.setPosition(Common::Point(162, 39));
+ scene->_hotspot17.changeZoom(100);
+ scene->_hotspot17.fixPriority(1);
+
+ RING_INVENTORY._medkit._sceneNumber = 2280;
+ _globals->_sceneItems.push_front(&scene->_hotspot17);
+ break;
+ case 51:
+ scene->_hotspot18.postInit();
+ scene->_hotspot18.setVisage(2161);
+ scene->_hotspot18._strip = 2;
+ scene->_hotspot18._frame = 2;
+ scene->_hotspot18.animate(ANIM_MODE_NONE, NULL);
+ scene->_hotspot18.setPosition(Common::Point(152, 43));
+ scene->_hotspot18.changeZoom(100);
+ scene->_hotspot18.fixPriority(1);
+
+ RING_INVENTORY._scanner._sceneNumber = 2280;
+ _globals->_sceneItems.push_front(&scene->_hotspot18);
+ break;
+ }
+
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 3:
+ _globals->_player.enableControl();
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player._strip = 2;
+
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2280::Hotspot1::doAction(int action) {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(16))
+ SceneItem::display2(2280, 22);
+ else {
+ _globals->setFlag(16);
+ SceneItem::display2(2230, 21);
+ }
+ break;
+ case CURSOR_USE:
+ if (!_globals->getFlag(15))
+ SceneItem::display2(2280, 23);
+ else if (!_globals->getFlag(13))
+ SceneItem::display2(2280, 46);
+ else {
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action1);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot2::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(2))
+ SceneItem::display2(2280, 1);
+ else {
+ _globals->setFlag(2);
+ SceneItem::display2(2280, 0);
+ }
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2280, 2);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot4::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(21))
+ SceneItem::display2(2280, 33);
+ else {
+ _globals->setFlag(21);
+ SceneItem::display2(2280, 32);
+ }
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2280, 34);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot7::doAction(int action) {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2280, 24);
+ break;
+ case OBJECT_SCANNER:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2280, 43);
+ else {
+ _globals->_player.disableControl();
+ scene->_action4._state = 51;
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_events._currentCursor = CURSOR_700;
+ scene->setAction(&scene->_action4);
+ }
+ break;
+ case OBJECT_MEDKIT:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2280, 43);
+ else {
+ _globals->_player.disableControl();
+ scene->_action4._state = 50;
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_events._currentCursor = CURSOR_700;
+ scene->setAction(&scene->_action4);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot8::doAction(int action) {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2280, 3);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action2);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot10::doAction(int action) {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2280, 4);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action2);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot12::doAction(int action) {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2280, 11);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action2);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot14::doAction(int action) {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2280, 3);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ if (_globals->getFlag(13))
+ scene->setAction(&scene->_action3);
+ else
+ scene->setAction(&scene->_action2);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot17::doAction(int action) {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(18))
+ SceneItem::display2(2280, 26);
+ else {
+ _globals->setFlag(18);
+ SceneItem::display2(2280, 25);
+ }
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2280, 29);
+ else {
+ _globals->_player.disableControl();
+ scene->_action4._state = 6;
+ scene->setAction(&scene->_action4);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2280::Hotspot18::doAction(int action) {
+ Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(19))
+ SceneItem::display2(2280, 28);
+ else {
+ _globals->setFlag(19);
+ SceneItem::display2(2280, 27);
+ }
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2280, 29);
+ else {
+ _globals->_player.disableControl();
+ scene->_action4._state = 1;
+ scene->setAction(&scene->_action4);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene2280::Scene2280() :
+ _hotspot3(0, CURSOR_LOOK, 2280, 30, CURSOR_USE, 31, 0, LIST_END),
+ _hotspot5(0, CURSOR_LOOK, 2280, 35, CURSOR_USE, 2280, 36, LIST_END),
+ _hotspot6(0, CURSOR_LOOK, 2280, 19, CURSOR_USE, 2280, 20, LIST_END),
+ _hotspot9(0, CURSOR_LOOK, 2280, 5, CURSOR_USE, 2280, 6, LIST_END),
+ _hotspot11(0, CURSOR_LOOK, 2280, 7, CURSOR_USE, 2280, 8, LIST_END),
+ _hotspot13(0, CURSOR_LOOK, 2280, 9, CURSOR_USE, 2280, 10, LIST_END),
+ _hotspot15(0, CURSOR_LOOK, 2280, 45, LIST_END),
+ _hotspot16(0, CURSOR_LOOK, 2280, 16, CURSOR_USE, 2280, 42, LIST_END) {
+}
+
+void Scene2280::postInit(SceneObjectList *OwnerList) {
+ loadScene(2280);
+ Scene::postInit();
+ setZoomPercents(0, 70, 200, 100);
+
+ _hotspot16.postInit();
+ _hotspot16.setVisage(2281);
+ _hotspot16.setPosition(Common::Point(208, 90));
+ _hotspot16.fixPriority(80);
+
+ if (RING_INVENTORY._medkit._sceneNumber == 2280) {
+ _hotspot17.postInit();
+ _hotspot17.setVisage(2161);
+ _hotspot17._strip = 2;
+ _hotspot17.setPosition(Common::Point(162, 39));
+ _hotspot17.fixPriority(1);
+
+ _globals->_sceneItems.push_back(&_hotspot17);
+ }
+
+ if (RING_INVENTORY._scanner._sceneNumber == 2280) {
+ _hotspot18.postInit();
+ _hotspot18.setVisage(2161);
+ _hotspot18._strip = 2;
+ _hotspot18._frame = 2;
+ _hotspot17.setPosition(Common::Point(152, 43));
+ _hotspot17.fixPriority(1);
+
+ _globals->_sceneItems.push_back(&_hotspot17);
+ }
+
+ if (!_globals->getFlag(13)) {
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2280);
+ _hotspot8._strip = 2;
+ _hotspot8.setPosition(Common::Point(79, 108));
+ _hotspot8.fixPriority(1);
+
+ _hotspot10.postInit();
+ _hotspot10.setVisage(2280);
+ _hotspot10._strip = 2;
+ _hotspot10._frame = 2;
+ _hotspot10.setPosition(Common::Point(79, 104));
+ _hotspot10.fixPriority(2);
+
+ _hotspot12.postInit();
+ _hotspot12.setVisage(2280);
+ _hotspot12._strip = 2;
+ _hotspot12._frame = 3;
+ _hotspot12.setPosition(Common::Point(88, 76));
+ _hotspot12.fixPriority(1);
+
+ _globals->_sceneItems.addItems(&_hotspot8, &_hotspot10, &_hotspot12, NULL);
+ }
+
+ _hotspot14.setBounds(Rect(70, 50, 90, 104));
+
+ _hotspot9.postInit();
+ _hotspot9.setVisage(2280);
+ _hotspot9.setPosition(Common::Point(104, 96));
+ _hotspot9.fixPriority(1);
+
+ _hotspot11.postInit();
+ _hotspot11.setVisage(2280);
+ _hotspot11._frame = 2;
+ _hotspot11.setPosition(Common::Point(130, 79));
+ _hotspot11.fixPriority(1);
+
+ _hotspot13.postInit();
+ _hotspot13.setVisage(2280);
+ _hotspot13._frame = 3;
+ _hotspot13.setPosition(Common::Point(113, 63));
+ _hotspot13.fixPriority(1);
+
+ _hotspot1.setBounds(Rect(225, 70, 234, 80));
+ _hotspot2.setBounds(Rect(44, 78, 56, 105));
+ _hotspot3.setBounds(Rect(47, 108, 56, 117));
+ _hotspot4.setBounds(Rect(56, 78, 69, 101));
+ _hotspot5.setBounds(Rect(56, 108, 66, 113));
+ _hotspot6.setBounds(Rect(261, 39, 276, 90));
+ _hotspot7.setBounds(Rect(142, 19, 174, 38));
+ _hotspot15.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+
+ _exitRect = Rect(145, 180, 195, 195);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(_globals->getFlag(13) ? 2170 : 0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(146, 161));
+ _globals->_player.changeZoom(-1);
+ _globals->_player._moveDiff = Common::Point(4, 3);
+
+ if ((_globals->_sceneManager._previousScene != 7300) && (_globals->_sceneManager._previousScene != 7000)) {
+ _globals->_player.enableControl();
+ } else {
+ _globals->setFlag(109);
+ _globals->_player.fixPriority(76);
+ _globals->_player.disableControl();
+
+ _sceneMode = 2281;
+ setAction(&_sequenceManager, this, 2281, &_globals->_player, &_hotspot16, NULL);
+
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ }
+
+ _globals->_sceneItems.addItems(&_hotspot13, &_hotspot11, &_hotspot9, &_hotspot14, &_hotspot7,
+ &_hotspot6, &_hotspot2, &_hotspot3, &_hotspot4, &_hotspot5, &_hotspot1, &_hotspot16, &_hotspot15, NULL);
+
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+}
+
+void Scene2280::signal() {
+ if (_sceneMode == 2281) {
+ _globals->_player.fixPriority(-1);
+ _globals->_player.enableControl();
+ }
+}
+
+void Scene2280::dispatch() {
+ Scene::dispatch();
+ if (!_action) {
+ if (_exitRect.contains(_globals->_player._position))
+ _globals->_sceneManager.changeScene(2150);
+ }
+}
+
+void Scene2280::synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ _exitRect.synchronise(s);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2300 - Starcraft - Hanger Bay
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2300::Action1::signal() {
+ Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1: {
+ Common::Point pt(SCREEN_WIDTH, SCREEN_HEIGHT);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot2.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ scene->_hotspot8.setAction(&scene->_action4);
+ scene->_soundHandler2.startSound(21);
+
+ Common::Point pt1(95, scene->_hotspot5._position.y);
+ NpcMover *mover1 = new NpcMover();
+ scene->_hotspot5.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(99, scene->_hotspot6._position.y);
+ NpcMover *mover2 = new NpcMover();
+ scene->_hotspot6.addMover(mover2, &pt2, NULL);
+ break;
+ }
+ case 3:
+ setDelay(2);
+ _globals->_player._uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_WALK);
+ break;
+ case 4: {
+ scene->_hotspot5.setVisage(93);
+ scene->_hotspot6.setVisage(94);
+ scene->_hotspot5.setStrip(1);
+ scene->_hotspot6.setStrip(1);
+ scene->_hotspot5.changeZoom(50);
+ scene->_hotspot6.changeZoom(50);
+ scene->_hotspot5._moveDiff.x = 5;
+ scene->_hotspot6._moveDiff.x = 5;
+ scene->_hotspot5.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot6.animate(ANIM_MODE_1, NULL);
+
+ Common::Point pt1(178, 147);
+ NpcMover *mover1 = new NpcMover();
+ scene->_hotspot5.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(170, 145);
+ NpcMover *mover2 = new NpcMover();
+ scene->_hotspot6.addMover(mover2, &pt2, this);
+ break;
+ }
+ case 6:
+ scene->_soundHandler1.startSound(28);
+ _globals->_player.disableControl();
+
+ scene->_hotspot2.setVisage(40);
+ scene->_hotspot2.setStrip(4);
+ scene->_hotspot2.setFrame(1);
+ scene->_hotspot2.animate(ANIM_MODE_5, NULL);
+
+ _globals->_player.setVisage(40);
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 7:
+ _globals->_soundHandler.startSound(77, this);
+ break;
+ case 8:
+ _globals->_game->endGame(2300, 0);
+ break;
+ case 9:
+ if (scene->_hotspot5._mover)
+ scene->_hotspot5.addMover(NULL);
+ if (scene->_hotspot6._mover)
+ scene->_hotspot6.addMover(NULL);
+
+ scene->_hotspot5.animate(ANIM_MODE_NONE, NULL);
+ scene->_hotspot6.animate(ANIM_MODE_NONE, NULL);
+
+ _globals->_player.disableControl();
+ _globals->_player.setVisage(2672);
+ _globals->_player._strip = 5;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 10:
+ _globals->_player.setVisage(2674);
+ _globals->_player._strip = 5;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 11:
+ scene->_soundHandler1.startSound(28);
+
+ scene->_hotspot5._strip = 2;
+ scene->_hotspot6._strip = 2;
+ scene->_hotspot5._frame = 1;
+ scene->_hotspot6._frame = 1;
+ scene->_hotspot5.animate(ANIM_MODE_5, NULL);
+ scene->_hotspot6.animate(ANIM_MODE_5, NULL);
+ scene->_hotspot5.fixPriority(20);
+ scene->_hotspot6.fixPriority(20);
+
+ _globals->_player.setVisage(2672);
+ _globals->_player._strip = 5;
+ _globals->_player._frame = _globals->_player.getFrameCount();
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 12:
+ scene->_soundHandler1.startSound(77);
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip(4);
+ _globals->_player._uiEnabled = false;
+ setDelay(60);
+ break;
+ case 13:
+ scene->_stripManager.start(2300, this);
+ break;
+ case 14:
+ setDelay(5);
+ _actionIndex = 16;
+ break;
+ case 15: {
+ Common::Point pt1(101, 148);
+ PlayerMover *mover1 = new PlayerMover();
+ _globals->_player.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(scene->_hotspot5._position.x + 5, scene->_hotspot5._position.y + 5);
+ NpcMover *mover2 = new NpcMover();
+ scene->_hotspot2.addMover(mover2, &pt2, NULL);
+ break;
+ }
+ case 16:
+ _globals->_sceneManager.changeScene(2000);
+ remove();
+ break;
+ }
+}
+
+void Scene2300::Action2::signal() {
+ Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(30);
+ break;
+ case 1: {
+ Common::Point pt(153, 135);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(2030, this);
+ break;
+ case 3:
+ _globals->_player.enableControl();
+ setDelay(600);
+ break;
+ case 4: {
+ _globals->_player.disableControl();
+
+ scene->_hotspot2.postInit();
+ scene->_hotspot2.setVisage(2801);
+ scene->_hotspot2.setPosition(Common::Point(109, 145));
+ scene->_hotspot2.changeZoom(50);
+ scene->_hotspot2.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot2.setObjectWrapper(new SceneObjectWrapper());
+
+ Common::Point pt(160, 145);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot2.addMover(mover, &pt, this);
+ break;
+ }
+ case 5:
+ scene->_stripManager.start(2032, this);
+ break;
+ case 6:
+ scene->_hotspot2.setVisage(93);
+ scene->_hotspot2.setStrip(3);
+ scene->_hotspot2.setFrame(1);
+ scene->_hotspot2.animate(ANIM_MODE_5, this);
+
+ scene->_soundHandler1.startSound(28);
+ scene->_soundHandler2.startSound(97);
+ break;
+ case 7:
+ scene->_hotspot7._strip = 2;
+ scene->_hotspot7._frame = 1;
+ scene->_hotspot7.animate(ANIM_MODE_5, this);
+ break;
+ case 8:
+ scene->_hotspot2.animate(ANIM_MODE_6, this);
+ break;
+ case 9:
+ scene->_stripManager.start(2035, this);
+ break;
+ case 10:
+ _globals->_sceneManager.changeScene(2310);
+ break;
+ }
+}
+
+void Scene2300::Action3::signal() {
+ Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ Common::Point pt(153, 135);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ _globals->_player.disableControl();
+ _globals->_player.setVisage(2672);
+ _globals->_player._strip = 2;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ _globals->_player.setVisage(2674);
+ _globals->_player._strip = 2;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ scene->_soundHandler1.startSound(97);
+ scene->_soundHandler2.startSound(28);
+
+ scene->_hotspot7._strip = 2;
+ scene->_hotspot7._frame = 1;
+ scene->_hotspot7.animate(ANIM_MODE_5, this);
+
+ _globals->_player.setVisage(2672);
+ _globals->_player._strip = 2;
+ _globals->_player._frame = _globals->_player.getFrameCount();
+ _globals->_player.animate(ANIM_MODE_6, NULL);
+ break;
+ case 4:
+ scene->_soundHandler2.startSound(97);
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip(1);
+ scene->_stripManager.start(2034, this);
+ break;
+ case 5:
+ setDelay(10);
+ break;
+ case 6:
+ _globals->_sceneManager.changeScene(2310);
+ break;
+ }
+}
+
+void Scene2300::Action4::signal() {
+ Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_hotspot8.animate(ANIM_MODE_5, this);
+ scene->_soundHandler1.startSound(11);
+ break;
+ case 1:
+ scene->_hotspot9.postInit();
+ scene->_hotspot9.setVisage(2301);
+ scene->_hotspot9.setStrip2(2);
+ scene->_hotspot9.setFrame(3);
+ scene->_hotspot9.setPosition(Common::Point(273, 199));
+ scene->_hotspot9.fixPriority(19);
+ scene->_hotspot9.animate(ANIM_MODE_5, this);
+ scene->_soundHandler1.startSound(11);
+ break;
+ case 2:
+ scene->_hotspot8.remove();
+
+ scene->_hotspot10.postInit();
+ scene->_hotspot10.setVisage(2301);
+ scene->_hotspot10.setStrip(3);
+ scene->_hotspot10.setFrame(4);
+ scene->_hotspot10.setPosition(Common::Point(292, 113));
+ scene->_hotspot10.animate(ANIM_MODE_5, this);
+ scene->_soundHandler1.startSound(11);
+ break;
+ case 3:
+ scene->_soundHandler1.startSound(13);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2300::Hotspot5::doAction(int action) {
+ Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ _globals->_player.disableControl();
+ _globals->_player.addMover(NULL);
+ scene->_action1.setActionIndex(9);
+ scene->_action1.setDelay(1);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(2300, 3);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2300, 4);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2300::Hotspot7::doAction(int action) {
+ Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ scene->setAction(&scene->_action3);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(2300, 2);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(2300, 21);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene2300::Scene2300() :
+ _hotspot11(0, CURSOR_LOOK, 2300, 6, CURSOR_USE, 2300, 14, LIST_END),
+ _hotspot12(0, CURSOR_LOOK, 2300, 5, CURSOR_USE, 2300, 13, LIST_END),
+ _hotspot13(0, CURSOR_LOOK, 2300, 9, CURSOR_USE, 2300, 20, LIST_END),
+ _hotspot14(0, CURSOR_LOOK, 2300, 7, CURSOR_USE, 2300, 15, LIST_END),
+ _hotspot15(0, CURSOR_LOOK, 2300, 1, LIST_END) {
+}
+
+void Scene2300::postInit(SceneObjectList *OwnerList) {
+ loadScene(2300);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerSL);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSText);
+
+ RING_INVENTORY._stunner._sceneNumber = 1;
+ RING_INVENTORY._infoDisk._sceneNumber = 1;
+
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2301);
+ _hotspot8.setPosition(Common::Point(288, 74));
+
+ _globals->_soundHandler.startSound(96);
+ if (_globals->_sceneManager._previousScene == 2000) {
+ _hotspot8.remove();
+
+ _hotspot9.postInit();
+ _hotspot9.setVisage(2301);
+ _hotspot9.setStrip2(2);
+ _hotspot9._frame = _hotspot9.getFrameCount();
+ _hotspot9.setPosition(Common::Point(273, 199));
+ _hotspot9.fixPriority(1);
+
+ _hotspot10.postInit();
+ _hotspot10.setVisage(2301);
+ _hotspot10.setStrip(3);
+ _hotspot10._frame = _hotspot10.getFrameCount();
+ _hotspot10.setPosition(Common::Point(292, 113));
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.setPosition(Common::Point(109, 139));
+ _globals->_player.changeZoom(40);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.disableControl();
+
+ _hotspot7.postInit();
+ _hotspot7.setVisage(2302);
+ _hotspot7.animate(ANIM_MODE_2, NULL);
+ _hotspot7.setPosition(Common::Point(229, 125));
+ _hotspot7._numFrames = 5;
+
+ _soundHandler1.startSound(95);
+ _soundHandler2.startSound(96);
+ _globals->_sceneItems.push_back(&_hotspot7);
+
+ setAction(&_action2);
+ } else {
+ _hotspot8._numFrames = 3;
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(2331);
+ _hotspot3.setStrip(7);
+ _hotspot3.setPosition(Common::Point(231, 190));
+ _hotspot3.changeZoom(40);
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(2801);
+ _hotspot2.setPosition(Common::Point(269, 195));
+ _hotspot2.changeZoom(50);
+ _hotspot2.animate(ANIM_MODE_1, NULL);
+ _hotspot2.setObjectWrapper(new SceneObjectWrapper());
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(2331);
+ _hotspot1.setStrip(7);
+ _hotspot1.setPosition(Common::Point(255, 190));
+ _hotspot1.changeZoom(40);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.setPosition(Common::Point(203, 191));
+ _globals->_player.changeZoom(40);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.disableControl();
+
+ _hotspot5.postInit();
+ _hotspot5.setVisage(91);
+ _hotspot5.setPosition(Common::Point(343, 145));
+ _hotspot5._moveDiff = Common::Point(35, 35);
+ _hotspot5.changeZoom(40);
+ _hotspot5.setObjectWrapper(new SceneObjectWrapper());
+
+ _hotspot6.postInit();
+ _hotspot6.setVisage(92);
+ _hotspot6.setPosition(Common::Point(343, 130));
+ _hotspot6._moveDiff = Common::Point(35, 35);
+ _hotspot6.changeZoom(40);
+ _hotspot6.setObjectWrapper(new SceneObjectWrapper());
+
+ _globals->_sceneItems.push_back(&_hotspot5);
+ setAction(&_action1);
+ }
+
+ _hotspot12._sceneRegionId = 8;
+ _hotspot11._sceneRegionId = 9;
+ _hotspot13._sceneRegionId = 10;
+ _hotspot14._sceneRegionId = 11;
+
+ _hotspot15.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _globals->_sceneItems.addItems(&_hotspot12, &_hotspot11, &_hotspot13, &_hotspot14, &_hotspot15, NULL);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2310 - Starcraft - Copy Protection Screen
+ *
+ *--------------------------------------------------------------------------*/
+
+Scene2310::Scene2310() {
+ _pageList[0].set(0, 0, 0, 0, 0, 0);
+ _pageList[1].set(1, 0, 3, 2, 1, 4);
+ _pageList[2].set(2, 1, 4, 3, 2, 0);
+ _pageList[3].set(3, 2, 0, 4, 3, 1);
+ _pageList[4].set(4, 3, 1, 0, 2, 4);
+ _pageList[5].set(5, 4, 2, 1, 3, 0);
+ _pageList[6].set(6, 0, 4, 2, 3, 1);
+ _pageList[7].set(7, 1, 0, 2, 4, 3);
+ _pageList[8].set(8, 2, 1, 3, 0, 4);
+ _pageList[9].set(9, 3, 2, 4, 1, 0);
+ _pageList[10].set(10, 4, 1, 2, 0, 3);
+ _pageList[11].set(11, 0, 2, 3, 4, 1);
+ _pageList[12].set(12, 1, 2, 0, 4, 3);
+ _pageList[13].set(13, 2, 4, 0, 3, 1);
+ _pageList[14].set(14, 3, 4, 1, 0, 2);
+ _pageList[15].set(15, 4, 3, 1, 2, 0);
+ _pageList[16].set(16, 0, 1, 4, 2, 3);
+ _pageList[17].set(17, 1, 3, 4, 0, 2);
+ _pageList[18].set(18, 2, 3, 0, 1, 4);
+ _pageList[19].set(19, 3, 0, 1, 4, 2);
+ _pageList[20].set(20, 4, 0, 3, 1, 2);
+}
+
+void Scene2310::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ loadScene(2301);
+ Common::Point pointList[5] = { Common::Point(142, 82), Common::Point(158, 82), Common::Point(174, 82),
+ Common::Point(190, 82), Common::Point(205, 82) };
+
+ for (int idx = 0; idx < 5; ++idx) {
+ _wireList[idx].postInit();
+ _wireList[idx].setVisage(2300);
+ _wireList[idx]._strip = idx + 1;
+ _wireList[idx]._frame = 1;
+ _wireList[idx].setPosition(pointList[idx]);
+ }
+
+ _rectList[0].set(135, 70, 151, 140);
+ _rectList[1].set(151, 70, 167, 140);
+ _rectList[2].set(167, 70, 183, 140);
+ _rectList[3].set(183, 70, 199, 140);
+ _rectList[4].set(199, 70, 215, 140);
+
+ _globals->_player.disableControl();
+ _globals->_events.setCursor(CURSOR_WALK);
+
+ _wireIndex = 5;
+ if (_vm->getFeatures() & GF_CD)
+ _pageIndex = _globals->_randomSource.getRandomNumber(14) + 2;
+ else
+ _pageIndex = _globals->_randomSource.getRandomNumber(19) + 1;
+ signal();
+}
+
+void Scene2310::signal() {
+ switch (_sceneMode++) {
+ case 0: {
+ Common::String fmtString = _resourceManager->getMessage(2300, 22);
+ Common::String msg = Common::String::format(fmtString.c_str(), _pageList[_pageIndex]._pageNumber);
+
+ _sceneText._width = 280;
+ _sceneText._textMode = ALIGN_CENTER;
+ _sceneText._color1 = 35;
+ _sceneText._fontNumber = 2;
+ _sceneText.setup(msg);
+ _sceneText.fixPriority(255);
+ _sceneText.setPosition(Common::Point(30, 20));
+ break;
+ }
+ case 1: {
+ Common::String msg = _resourceManager->getMessage(2300, 23);
+ _sceneText.setup(msg);
+ _sceneText.fixPriority(255);
+ _sceneText.setPosition(Common::Point(30, 170));
+
+ _globals->_sceneObjects->draw();
+ _globals->_events.waitForPress();
+
+ _sceneText.hide();
+ _globals->_sceneObjects->draw();
+
+ _globals->_sceneManager.changeScene(2200);
+ break;
+ }
+ }
+}
+
+void Scene2310::synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+
+ s.syncAsSint16LE(_wireIndex);
+ s.syncAsSint16LE(_pageIndex);
+}
+
+void Scene2310::process(Event &event) {
+ int frameNum = 0;
+
+ if (!event.handled && (event.eventType == EVENT_BUTTON_DOWN)) {
+ int idx = 0;
+ while (idx < 5) {
+ if (_rectList[idx].contains(event.mousePos))
+ break;
+ ++idx;
+ }
+
+ if (idx < 5) {
+ // In handled rectangle area
+ if (_wireIndex == 5) {
+ // No wire is currently active, so start moving designated wire
+ _wireIndex = idx;
+ frameNum = idx + 2;
+
+ if (event.mousePos.y > 105)
+ idx = findObject(idx);
+
+ if (idx != 5) {
+ _wireList[idx].hide();
+ _globals->_sceneObjects->draw();
+ _wireList[idx].setFrame(frameNum);
+
+ _wireList[idx].show();
+ _globals->_sceneObjects->draw();
+ }
+ } else {
+ // End the moving of the currently active wire
+ _wireList[_wireIndex].setFrame(idx + 2);
+ _wireIndex = 5;
+
+ // Check if solution has been reached
+ int idx2 = 0;
+ do {
+ int objIndex = findObject(idx2);
+ if (_pageList[_pageIndex]._connectionList[idx2] != objIndex)
+ // Mismatch
+ break;
+ } while (++idx2 < 5);
+
+ if (idx2 == 5)
+ // All the entries are correct
+ signal();
+ }
+
+ event.handled = true;
+ } else if (_wireIndex != 5) {
+ // Reset the active wire back to unplugged
+ _wireList[_wireIndex].setFrame(1);
+ _wireIndex = 5;
+ }
+ }
+}
+
+void Scene2310::dispatch() {
+ if (_wireIndex != 5) {
+ for (int idx = 0; idx < 5; ++idx) {
+ if (_rectList[idx].contains(_globals->_events._mousePos)) {
+ _wireList[_wireIndex].setFrame(idx + 2);
+ return;
+ }
+ }
+
+ _wireList[_wireIndex].setFrame(1);
+ }
+}
+
+int Scene2310::findObject(int objIndex) {
+ for (int idx = 0; idx < 5; ++idx) {
+ if (_wireList[idx]._frame == (objIndex + 2))
+ return idx;
+ }
+
+ return 5;
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2320 - Starcraft - Lander Bay
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2320::Action1::signal() {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ if (_globals->_sceneManager._previousScene == 2120)
+ _actionIndex = 3;
+ break;
+ case 1: {
+ Common::Point pt(513, 144);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot11.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ Common::Point pt(510, 164);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot11.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ setAction(&scene->_sequenceManager2, this, 2328, &scene->_hotspot11, NULL);
+ break;
+ case 4:
+ scene->_hotspot11.animate(ANIM_MODE_NONE);
+ setDelay(120);
+ _actionIndex = 3;
+ break;
+ }
+}
+
+void Scene2320::Action2::signal() {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_soundHandler.startSound(253);
+ scene->_hotspot13.fixPriority(99);
+
+ Common::Point pt(scene->_hotspot13._position.x, 200);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot13.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ scene->_hotspot13.hide();
+ remove();
+ break;
+ }
+}
+
+void Scene2320::Action3::signal() {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ Common::Point pt(320, 86);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 1:
+ scene->_soundHandler.startSound(162);
+ scene->_hotspot6.animate(ANIM_MODE_5, this);
+ break;
+ case 2: {
+ Common::Point pt(320, 79);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ _globals->_player.fixPriority(scene->_hotspot6._priority - 1);
+ _globals->_player._strip = 3;
+ setDelay(10);
+ break;
+ case 4:
+ scene->_area1.display();
+ scene->_area2.display();
+ scene->_area3.display();
+ scene->_area4.display();
+
+ scene->_area3.draw(true);
+ _state = 0;
+ _globals->_events.setCursor(CURSOR_USE);
+
+ while (!_state && !_vm->getEventManager()->shouldQuit()) {
+ // Wait for an event
+ Event event;
+ if (!_globals->_events.getEvent(event)) {
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ continue;
+ }
+
+ if (scene->_area1._bounds.contains(event.mousePos)) {
+ scene->_area1.draw(true);
+ scene->_area3.draw(false);
+ _state = scene->_area1._actionId;
+ }
+ if (scene->_area2._bounds.contains(event.mousePos)) {
+ scene->_area3.draw(false);
+ scene->_area2.draw(true);
+ _state = scene->_area2._actionId;
+ }
+ if (scene->_area3._bounds.contains(event.mousePos)) {
+ scene->_area3.draw(true);
+ _state = scene->_area3._actionId;
+ }
+ }
+
+ scene->_soundHandler.startSound(161);
+ scene->_area1.restore();
+ scene->_area2.restore();
+ scene->_area3.restore();
+ scene->_area4.restore();
+
+ if (_state == 2320) {
+ setDelay(10);
+ } else {
+ scene->_soundHandler.startSound(162);
+ scene->_hotspot6.animate(ANIM_MODE_6, this);
+ }
+ break;
+ case 5: {
+ if (_state == 2320)
+ _globals->_player.fixPriority(-1);
+ else
+ _globals->_sceneManager.changeScene(_state);
+
+ Common::Point pt(320, 86);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 6:
+ scene->_soundHandler.startSound(162);
+ scene->_hotspot6.animate(ANIM_MODE_6, this);
+ break;
+ case 7:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene2320::Action4::signal() {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1: {
+ Common::Point pt(213, 84);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ case 16:
+ _globals->_player.setVisage(2109);
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ _globals->_player.animate(ANIM_MODE_6, NULL);
+ setAction(&scene->_action2, this);
+ break;
+ case 4: {
+ scene->_hotspot16.postInit();
+ scene->_hotspot16.setVisage(2331);
+ scene->_hotspot16.setStrip(3);
+ scene->_hotspot16.fixPriority(149);
+ scene->_hotspot16.setPosition(Common::Point(320, 202));
+ scene->_hotspot16.show();
+
+ Common::Point pt(320, 121);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot16.addMover(mover, &pt, this);
+ break;
+ }
+ case 5: {
+ scene->_hotspot16.fixPriority(200);
+ Common::Point pt(320, 180);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot16.addMover(mover, &pt, this);
+ break;
+ }
+ case 6: {
+ scene->_hotspot16.fixPriority(-1);
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ Common::Point pt(233, 176);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 7: {
+ Common::Point pt(291, 194);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 8:
+ _globals->_player.setStrip(5);
+ _globals->_player.setFrame(1);
+ setDelay(13);
+ break;
+ case 9:
+ if (!_globals->getFlag(109)) {
+ SceneItem::display2(2320, 19);
+ } else {
+ _globals->_sceneManager.changeScene(7600);
+ }
+ break;
+ case 10:
+ if (_globals->getFlag(109)) {
+ _globals->_soundHandler.startSound(40);
+ _globals->_soundHandler.proc5(true);
+
+ Common::Point pt(303, 240);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ } else {
+ setDelay(3);
+ }
+ break;
+ case 11:
+ if (_globals->getFlag(109)) {
+ _globals->_sceneManager.changeScene(7600);
+ } else {
+ SceneItem::display2(2320, 19);
+ setDelay(3);
+ }
+ break;
+ case 12:
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 13:
+ _globals->_player.setVisage(0);
+ _globals->_player.setPosition(Common::Point(291, 194));
+ _globals->_player.setStrip(5);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ scene->_hotspot16.show();
+ setDelay(3);
+ break;
+ case 14: {
+ Common::Point pt(233, 176);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 15: {
+ Common::Point pt(213, 85);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 17: {
+ _globals->_player.animate(ANIM_MODE_6, NULL);
+ scene->_hotspot16.fixPriority(160);
+
+ Common::Point pt(320, 121);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot16.addMover(mover, &pt, this);
+ break;
+ }
+ case 18: {
+ Common::Point pt(320, 202);
+ PlayerMover *mover = new PlayerMover();
+ scene->_hotspot16.addMover(mover, &pt, this);
+ break;
+ }
+ case 19: {
+ scene->_hotspot16.remove();
+ scene->_soundHandler.startSound(253);
+
+ scene->_hotspot13.show();
+ Common::Point pt(319, 157);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot13.addMover(mover, &pt, this);
+ break;
+ }
+ case 20:
+ _globals->_player.enableControl();
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ scene->_hotspot13.fixPriority(1);
+ remove();
+ break;
+ }
+}
+
+void Scene2320::Action5::signal() {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ ADD_PLAYER_MOVER(163, 126);
+ break;
+ case 1:
+ ADD_PLAYER_MOVER(165, 132);
+ break;
+ case 2:
+ setDelay(2);
+ break;
+ case 3:
+ if (!_globals->getFlag(59))
+ setDelay(10);
+ else
+ scene->_stripManager.start(2323, this);
+ break;
+ case 4:
+ _globals->_player.setVisage(2347);
+ _globals->_player.setStrip(1);
+ _globals->_player.setFrame(1);
+ _globals->_player.fixPriority(137);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 5:
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 6:
+ if (_globals->getFlag(72))
+ _globals->_sceneManager.changeScene(7000);
+ else if (_globals->getFlag(59))
+ _globals->_sceneManager.changeScene(5000);
+ else if (!_globals->getFlag(43) || (RING_INVENTORY._ale._sceneNumber != 1))
+ setDelay(10);
+ else {
+ scene->_hotspot11.setAction(NULL);
+ scene->_hotspot11.setVisage(2705);
+ scene->_hotspot11.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot11.setObjectWrapper(new SceneObjectWrapper());
+
+ Common::Point pt(185, 135);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot11.addMover(mover, &pt, NULL);
+
+ _globals->clearFlag(43);
+ scene->_stripManager.start(2325, this);
+ }
+ break;
+ case 7:
+ setDelay(10);
+ break;
+ case 8:
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ }
+}
+
+void Scene2320::Action6::signal() {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 2:
+ _globals->_player.setStrip(1);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 3:
+ _globals->_player.setVisage(0);
+ _globals->_player.setStrip(3);
+ _globals->_player.fixPriority(-1);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ setDelay(60);
+ break;
+ case 4:
+ if ((_globals->_sceneManager._previousScene != 4000) || _globals->getFlag(43))
+ setDelay(3);
+ else if (_globals->getFlag(35)) {
+ _globals->setFlag(43);
+ scene->_stripManager.start(4200, this);
+ _globals->setFlag(69);
+ } else if (_globals->getFlag(36)) {
+ setDelay(3);
+ } else {
+ _globals->setFlag(43);
+ scene->_stripManager.start(4210, this);
+ break;
+ }
+ break;
+ case 5:
+ if (_globals->_sceneObjects->contains(&scene->_hotspot11)) {
+ scene->_hotspot11.setAction(&scene->_action1);
+
+ if (_globals->_sceneObjects->contains(&scene->_hotspot10)) {
+ ADD_MOVER(scene->_hotspot10, 491, 160);
+ } else {
+ setDelay(60);
+ }
+
+ _globals->_sceneItems.push_front(&scene->_hotspot11);
+ } else {
+ setDelay(3);
+ }
+ break;
+ case 6:
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene2320::Action7::signal() {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ _globals->_soundHandler.startSound(162);
+ scene->_hotspot6.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ scene->_hotspot10.fixPriority(-1);
+ ADD_MOVER_NULL(scene->_hotspot10, 321, 94);
+ scene->_hotspot11.fixPriority(-1);
+ ADD_MOVER_NULL(scene->_hotspot11, 346, 85);
+
+ _globals->_player.fixPriority(-1);
+ ADD_MOVER(_globals->_player, 297, 89);
+ break;
+ case 3:
+ ADD_PLAYER_MOVER(462, 182);
+ break;
+ case 4:
+ ADD_MOVER(scene->_hotspot11, 391, 88);
+ break;
+ case 5:
+ ADD_MOVER(scene->_hotspot11, 500, 164);
+ ADD_MOVER(scene->_hotspot10, 382, 93);
+ _globals->_player.setStrip(3);
+ break;
+ case 6:
+ ADD_MOVER_NULL(scene->_hotspot10, 491, 160);
+ ADD_MOVER(_globals->_player, 391, 88);
+ break;
+ case 7:
+ ADD_PLAYER_MOVER(462, 182);
+ break;
+ case 8:
+ _globals->_player.setStrip(7);
+ setDelay(15);
+ break;
+ case 9:
+ scene->_stripManager.start(6020, this);
+ break;
+ case 10:
+ setDelay(6);
+ break;
+ case 11:
+ scene->_stripManager.start(6022, this);
+ break;
+ case 12:
+ _globals->_player.enableControl();
+ RING_INVENTORY._stasisBox._sceneNumber = 2320;
+ break;
+ }
+}
+
+void Scene2320::Action8::signal() {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1:
+ ADD_PLAYER_MOVER(462, 182);
+ break;
+ case 2:
+ _globals->_player.setStrip(7);
+ setDelay(5);
+ break;
+ case 3:
+ scene->_speakerGameText.setTextPos(Common::Point(_globals->_sceneManager._scene->_sceneBounds.left + 30, 10));
+ scene->_stripManager.start(_globals->getFlag(75) ? 6030 : 2320, this);
+ break;
+ case 4:
+ if (_globals->getFlag(75))
+ setDelay(3);
+ else
+ _globals->_player.enableControl();
+ break;
+ case 5:
+ RING_INVENTORY._stasisBox._sceneNumber = 2320;
+ scene->_sceneMode = 2326;
+ scene->_speakerGameText.setTextPos(Common::Point(_globals->_sceneManager._scene->_sceneBounds.left + 30, 10));
+ scene->setAction(&scene->_sequenceManager1, scene, 2326, &_globals->_player, &scene->_hotspot11, NULL);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2320::Hotspot5::doAction(int action) {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2320, 13);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(70))
+ SceneItem::display2(2320, 33);
+ else if (_globals->getFlag(13))
+ SceneItem::display2(2320, 18);
+ else
+ scene->setAction(&scene->_action5);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2320::Hotspot6::doAction(int action) {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2320, 2);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action3);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2320::Hotspot8::doAction(int action) {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2320, 23);
+ break;
+ case CURSOR_USE:
+ scene->_sceneMode = 2336;
+ scene->setAction(&scene->_sequenceManager1, scene, 2336, &_globals->_player, this, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2320::Hotspot10::doAction(int action) {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2320, 26);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2329;
+
+ if (_globals->getFlag(13)) {
+ scene->_stripManager.start(2337, scene);
+ } else if (_globals->getFlag(70)) {
+ scene->setAction(&scene->_action8);
+ } else if (_globals->getFlag(109)) {
+ scene->setAction(&scene->_sequenceManager1, scene, 2337, NULL);
+ } else if (!_state) {
+ ++_state;
+ scene->setAction(&scene->_sequenceManager1, scene, 2334, NULL);
+ } else {
+ scene->setAction(&scene->_sequenceManager1, scene, 2335, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2320::Hotspot11::doAction(int action) {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2320, 25);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2329;
+
+ if (_globals->getFlag(13)) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5000;
+ scene->_stripManager.start(2336, scene);
+ } else if (_globals->getFlag(70)) {
+ scene->setAction(&scene->_action8);
+ } else {
+ scene->_sceneMode = 2329;
+
+ if (RING_INVENTORY._ale._sceneNumber == 1) {
+ scene->setAction(&scene->_sequenceManager1, scene, 2329, NULL);
+ } else if (!_globals->getFlag(110)) {
+ _globals->setFlag(110);
+ scene->setAction(&scene->_sequenceManager1, scene, 2330, NULL);
+ } else if (RING_INVENTORY._peg._sceneNumber != 1) {
+ scene->setAction(&scene->_sequenceManager1, scene, 2331, NULL);
+ } else if (!_state) {
+ ++_state;
+ scene->setAction(&scene->_sequenceManager1, scene, 2332, NULL);
+ } else {
+ scene->setAction(&scene->_sequenceManager1, scene, 2333, NULL);
+ }
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2320::Hotspot12::doAction(int action) {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2320, 5);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2320, 24);
+ else {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 2322;
+ scene->setAction(&scene->_sequenceManager1, scene, 2322, &_globals->_player, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2320::Hotspot14::doAction(int action) {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2320, 17);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(24)) {
+ _globals->clearFlag(24);
+ _globals->_player.disableControl();
+
+ scene->_hotspot8.postInit();
+ scene->_hotspot8.setVisage(2345);
+ scene->_hotspot8.setPosition(Common::Point(634, 65));
+ scene->_hotspot8.hide();
+
+ _globals->_sceneItems.push_front(&scene->_hotspot8);
+ RING_INVENTORY._waldos._sceneNumber = 2320;
+
+ scene->_hotspot9.postInit();
+ scene->_hotspot9.setVisage(2345);
+ scene->_hotspot9._strip = 6;
+ scene->_hotspot9.setPosition(Common::Point(536, 103));
+ scene->_hotspot9.fixPriority(200);
+ scene->_hotspot9.hide();
+
+ scene->_hotspot16.postInit();
+ scene->_hotspot16.setVisage(2345);
+ scene->_hotspot16.setStrip(8);
+ scene->_hotspot16.setPosition(Common::Point(536, 103));
+ scene->_hotspot16.hide();
+
+ scene->_sceneMode = 2324;
+ scene->setAction(&scene->_sequenceManager1, scene, 2324, &_globals->_player, &scene->_hotspot7,
+ &scene->_hotspot8, &scene->_hotspot9, &scene->_hotspot16, NULL);
+ } else if (_globals->getFlag(13)) {
+ SceneItem::display2(2320, 24);
+ } else if (!_globals->getFlag(76)) {
+ SceneItem::display2(2320, 28);
+ } else if (!RING_INVENTORY._waldos._sceneNumber) {
+ SceneItem::display2(2320, 27);
+ } else {
+ SceneItem::display2(2320, 29);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene2320::Hotspot15::doAction(int action) {
+ Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(2320, 16);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(13))
+ SceneItem::display2(2320, 24);
+ else
+ scene->setAction(&scene->_action4);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+Scene2320::Scene2320() :
+ _hotspot1(0, CURSOR_LOOK, 2320, 0, LIST_END),
+ _hotspot2(0, CURSOR_LOOK, 2320, 1, LIST_END),
+ _hotspot3(0, CURSOR_LOOK, 2320, 11, LIST_END),
+ _hotspot4(0, CURSOR_LOOK, 2320, 14, LIST_END),
+ _hotspot13(0, CURSOR_LOOK, 2320, 12, LIST_END)
+{
+}
+
+void Scene2320::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(60, 75, 100, 100);
+
+ _stripManager.addSpeaker(&_speakerMR);
+ _stripManager.addSpeaker(&_speakerML);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerSR);
+ _stripManager.addSpeaker(&_speakerSL);
+ _stripManager.addSpeaker(&_speakerSAL);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerGameText);
+
+ _speakerMText._npc = &_hotspot11;
+ _speakerQText._npc = &_globals->_player;
+ _hotspotPtr = &_hotspot10;
+
+ _hotspot6.postInit();
+ _hotspot6.setVisage(2321);
+ _hotspot6.setPosition(Common::Point(320, 67));
+
+ _hotspot7.postInit();
+ _hotspot7.setVisage(2344);
+ _hotspot7.setPosition(Common::Point(604, 92));
+
+ _hotspot13.postInit();
+ _hotspot13.setVisage(2323);
+ _hotspot13.setPosition(Common::Point(319, 157));
+ _hotspot13.fixPriority(1);
+
+ _hotspot12.postInit();
+ _hotspot12.setVisage(2321);
+ _hotspot12._strip = 4;
+ _hotspot12.animate(ANIM_MODE_8, 0, NULL);
+ _hotspot12.setPosition(Common::Point(412, 46));
+
+ if (RING_INVENTORY._waldos._sceneNumber == 2320) {
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2345);
+ _hotspot8.setStrip(5);
+ _hotspot8.setFrame(8);
+ _hotspot8.setPosition(Common::Point(541, 103));
+ _hotspot8.fixPriority(201);
+
+ _globals->_sceneItems.push_back(&_hotspot8);
+ }
+
+ _area1.setup(2153, 2, 1, 2100);
+ _area1._pt = Common::Point(200, 31);
+ _area2.setup(2153, 3, 1, 2150);
+ _area2._pt = Common::Point(200, 50);
+ _area3.setup(2153, 4, 1, 2320);
+ _area3._pt = Common::Point(200, 75);
+ _area4.setup(2153, 1, 1, 10);
+ _area4._pt = Common::Point(237, 77);
+
+ if (_globals->getFlag(43)) {
+ _hotspot11.postInit();
+ _hotspot11.setVisage(2705);
+ _hotspot11._strip = 3;
+ _hotspot11.setPosition(Common::Point(510, 156));
+ _globals->_sceneItems.push_back(&_hotspot11);
+ _hotspot11._state = 0;
+ _hotspot11.setAction(&_action1);
+ }
+
+ _globals->_player.postInit();
+ if (_globals->getFlag(13))
+ _globals->_player.setVisage(2170);
+ else
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(320, 79));
+ _globals->_player.fixPriority(10);
+ _globals->_player.changeZoom(-1);
+ _globals->_player._moveDiff.y = 3;
+ _globals->_player.disableControl();
+
+ if (_globals->getFlag(114)) {
+ _hotspot10.postInit();
+ _hotspot10.setVisage(2806);
+ _hotspot10.setPosition(Common::Point(481, 162));
+ _hotspot10.changeZoom(-1);
+ _hotspot10.setStrip(5);
+ _hotspot10._state = 0;
+
+ _globals->_sceneItems.push_back(&_hotspot10);
+ }
+
+ if (_globals->getFlag(70)) {
+ _hotspot11.postInit();
+ _hotspot11.setVisage(2705);
+ _hotspot11.setPosition(Common::Point(500, 164));
+
+ _hotspot10.postInit();
+ _hotspot10.setVisage(2806);
+ _hotspot10.setPosition(Common::Point(481, 162));
+ _hotspot10.changeZoom(-1);
+ _hotspot10.setStrip(5);
+
+ _globals->_sceneItems.addItems(&_hotspot11, &_hotspot10, NULL);
+ }
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 2120:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+
+ _globals->_player.fixPriority(-1);
+ _globals->_player.setPosition(Common::Point(389, 72));
+ _globals->_player.enableControl();
+ break;
+ case 4000:
+ if (!_globals->getFlag(36) && !_globals->getFlag(43)) {
+ _hotspot11.postInit();
+ _hotspot11.setVisage(2705);
+ _hotspot11.setPosition(Common::Point(178, 118));
+ _hotspot11.animate(ANIM_MODE_1, NULL);
+ }
+ // Deliberate fall-through
+ case 4250:
+ case 5000:
+ case 7000:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ if ((_globals->_sceneManager._previousScene == 7000) && !_globals->getFlag(80))
+ _globals->setFlag(36);
+
+ _globals->_player.disableControl();
+ _globals->_player.animate(ANIM_MODE_NONE, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setVisage(2347);
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(5);
+ _globals->_player.fixPriority(137);
+ _globals->_player.setPosition(Common::Point(165, 132));
+
+ setAction(&_action6);
+ break;
+ case 6100:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2345);
+ _hotspot8.setPosition(Common::Point(634, 65));
+ _hotspot8.hide();
+
+ _sceneMode = 2325;
+ setAction(&_sequenceManager1, this, 2325, &_globals->_player, &_hotspot6, &_hotspot8, &_hotspot7, NULL);
+ break;
+ case 7600:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ _soundHandler.startSound(21);
+
+ _globals->_player.setVisage(2323);
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(_globals->_player.getFrameCount());
+ _globals->_player.setPosition(Common::Point(303, 176));
+ _globals->_player.fixPriority(-1);
+ _globals->_player.disableControl();
+
+ _hotspot13.setPosition(Common::Point(319, 199));
+
+ _hotspot16.postInit();
+ _hotspot16.setVisage(2331);
+ _hotspot16._strip = 3;
+ _hotspot16.fixPriority(160);
+ _hotspot16.setPosition(Common::Point(320, 202));
+ _hotspot16.hide();
+
+ _sceneMode = 2338;
+ setAction(&_sequenceManager1, this, 2338, &_globals->_player, &_hotspot16, &_hotspot13, NULL);
+ break;
+ default:
+ switch (_globals->_stripNum) {
+ case 2101:
+ _globals->_player.disableControl();
+ _globals->_player.setStrip(3);
+ _globals->_player.setPosition(Common::Point(307, 84));
+
+ _hotspot11.postInit();
+ _hotspot11.setVisage(2705);
+ _hotspot11._strip = 2;
+ _hotspot11.fixPriority(10);
+ _hotspot11.setPosition(Common::Point(322, 80));
+ _hotspot11.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot11.animate(ANIM_MODE_1, NULL);
+
+ _hotspot10.postInit();
+ _hotspot10.setVisage(2806);
+ _hotspot10.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot10.changeZoom(-1);
+ _hotspot10.fixPriority(10);
+ _hotspot10.setPosition(Common::Point(318, 89));
+ _hotspot10._strip = 3;
+ _hotspot10.animate(ANIM_MODE_1, NULL);
+
+ setAction(&_action7);
+ break;
+ case 6100:
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2345);
+ _hotspot8.setPosition(Common::Point(634, 65));
+ _hotspot8.hide();
+
+ _sceneMode = 2325;
+ setAction(&_sequenceManager1, this, 2325, &_globals->_player, &_hotspot6, &_hotspot8, &_hotspot7, NULL);
+ break;
+ default:
+ _globals->_soundHandler.startSound(160);
+ _globals->_soundHandler.proc5(true);
+ _sceneMode = 2321;
+
+ _globals->_player.setStrip(3);
+ setAction(&_sequenceManager1, this, 2321, &_globals->_player, &_hotspot6, NULL);
+ break;
+ }
+ }
+
+ _globals->_stripNum = 0;
+ _globals->_sceneManager._scene->_sceneBounds.center(_globals->_player._position);
+ loadScene(2320);
+
+ _hotspot14._sceneRegionId = 8;
+ _hotspot1.setBounds(Rect(0, 0, 640, 200));
+ _hotspot2.setBounds(Rect(278, 0, 362, 61));
+ _hotspot3.setBounds(Rect(282, 62, 367, 98));
+ _hotspot4.setBounds(Rect(67, 38, 112, 113));
+ _hotspot5.setBounds(Rect(104, 122, 174, 157));
+ _hotspot15.setBounds(Rect(191, 53, 205, 63));
+
+ _globals->_sceneItems.addItems(&_hotspot14, &_hotspot15, &_hotspot5, &_hotspot6, &_hotspot12,
+ &_hotspot13, &_hotspot4, &_hotspot3, &_hotspot2, &_hotspot1, NULL);
+}
+
+void Scene2320::synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ SYNC_POINTER(_hotspotPtr);
+}
+
+void Scene2320::signal() {
+ switch (_sceneMode) {
+ case 2321:
+ case 2327:
+ case 2329:
+ if (_globals->getFlag(43) && !_hotspot11._action)
+ _hotspot11.setAction(&_action1);
+ _globals->_player.enableControl();
+ break;
+ case 2322:
+ _globals->_sceneManager.changeScene(2120);
+ break;
+ case 2323:
+ _globals->_player.disableControl();
+ break;
+ case 2338:
+ case 2324:
+ _hotspot16.remove();
+ _globals->_player.enableControl();
+ break;
+ case 2325:
+ _globals->setFlag(76);
+ _globals->clearFlag(70);
+ _globals->_stripNum = 6100;
+ _globals->_sceneManager.changeScene(2100);
+ break;
+ case 2326:
+ _globals->clearFlag(70);
+ RING_INVENTORY._nullifier._sceneNumber = 1;
+ _globals->_stripNum = 2321;
+ _globals->_sceneManager.changeScene(2100);
+ break;
+ case 2336:
+ _globals->setFlag(77);
+ RING_INVENTORY._waldos._sceneNumber = 1;
+ _hotspot8.remove();
+ break;
+ case 5000:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2400 - Descending in Lander
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene2400::Action1::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ ADD_MOVER(_globals->_player, 160, 71);
+ break;
+ case 2:
+ ADD_MOVER(_globals->_player, 160, 360);
+ break;
+ case 3:
+ _globals->_player._moveDiff = Common::Point(1, 1);
+ ADD_MOVER(_globals->_player, 140, 375);
+ break;
+ case 4:
+ ADD_MOVER(_globals->_player, 87, 338);
+ break;
+ case 5:
+ _globals->_player.hide();
+ setDelay(60);
+ break;
+ case 6:
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ }
+}
+
+void Scene2400::Action1::dispatch() {
+ Action::dispatch();
+ if ((_actionIndex == 4) && (_globals->_player._percent > 5))
+ _globals->_player.changeZoom(_globals->_player._percent - 2);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene2400::postInit(SceneObjectList *OwnerList) {
+ loadScene(2400);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2410);
+ _globals->_player.setPosition(Common::Point(340, -10));
+ _globals->_player.animate(ANIM_MODE_2, NULL);
+ _globals->_player.disableControl();
+
+ setAction(&_action1);
+
+ _globals->_sceneManager._scene->_sceneBounds.center(_globals->_player._position.x, _globals->_player._position.y);
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160;
+
+ _globals->_soundHandler.startSound(153);
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes3.h b/engines/tsage/ringworld_scenes3.h
new file mode 100644
index 0000000000..2cbe8de65b
--- /dev/null
+++ b/engines/tsage/ringworld_scenes3.h
@@ -0,0 +1,896 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_SCENES3_H
+#define TSAGE_RINGWORLD_SCENES3_H
+
+#include "common/scummsys.h"
+#include "tsage/core.h"
+#include "tsage/converse.h"
+#include "tsage/ringworld_logic.h"
+
+namespace tSage {
+
+class Scene2000 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action8 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action9 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action10 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action11 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action12 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action13 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action14 : public Action {
+ public:
+ virtual void signal();
+ };
+
+public:
+ SpeakerSL _speakerSL;
+ SpeakerQR _speakerQR;
+ SpeakerMR _speakerMR;
+ SpeakerQText _speakerQText;
+ SpeakerMText _speakerMText;
+ SpeakerSText _speakerSText;
+ SpeakerHText _speakerHText;
+ SpeakerGameText _speakerGameText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ Action8 _action8;
+ Action9 _action9;
+ Action10 _action10;
+ Action11 _action11;
+ Action12 _action12;
+ Action13 _action13;
+ Action14 _action14;
+ SceneObject _object1, _object2, _object3, _object4, _object5;
+ SceneObject _object6, _object7, _object8, _object9, _object10;
+ SoundHandler _soundHandler1, _soundHandler2;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void stripCallback(int v);
+};
+
+class Scene2100 : public Scene {
+ /* Actions */
+ class Action1 : public ActionExt {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action8 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action9 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action10 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action11 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action12 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action13 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action14 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action15 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action16 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action17 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot3 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot4 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot10 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot14 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+ /* Objects */
+ class Object1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object3 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SoundHandler _soundHandler;
+ SpeakerMText _speakerMText;
+ SpeakerMR _speakerMR;
+ SpeakerQL _speakerQL;
+ SpeakerQR _speakerQR;
+ SpeakerQText _speakerQText;
+ SpeakerGameText _speakerGameText;
+ SpeakerSText _speakerSText;
+ SpeakerSL _speakerSL;
+ SpeakerSAL _speakerSAL;
+ SpeakerHText _speakerHText;
+
+ DisplayHotspot _hotspot1;
+ Hotspot2 _hotspot2;
+ Hotspot3 _hotspot3;
+ Hotspot4 _hotspot4;
+ DisplayHotspot _hotspot5, _hotspot6, _hotspot7;
+ Hotspot8 _hotspot8;
+ DisplayHotspot _hotspot9;
+ Hotspot10 _hotspot10;
+ DisplayHotspot _hotspot11, _hotspot12, _hotspot13;
+ Hotspot14 _hotspot14;
+ DisplayHotspot _hotspot15;
+
+ Object1 _object1;
+ Object2 _object2;
+ Object3 _object3;
+ SceneObject _object4;
+
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ Action8 _action8;
+ Action9 _action9;
+ Action10 _action10;
+ Action11 _action11;
+ Action12 _action12;
+ Action13 _action13;
+ Action14 _action14;
+ Action15 _action15;
+ Action16 _action16;
+ Action17 _action17;
+ int _field1800;
+ SceneArea _area1, _area2, _area3, _area4;
+
+ Scene2100();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void stripCallback(int v);
+ virtual void signal();
+};
+
+class Scene2120 : public Scene {
+ /* Actions */
+ class Entry {
+ public:
+ int _size;
+ int _lineNum;
+ int _visage;
+
+ Entry() { _size = 0; _lineNum = 0; _visage = 0; }
+ Entry(int size, int lineNum, int visage) { _size = size; _lineNum = lineNum; _visage = visage; }
+ };
+
+ class Action1 : public Action {
+ private:
+ Common::Array<Entry> _entries;
+ public:
+ Action1();
+
+ virtual void signal();
+ virtual void dispatch();
+ };
+
+public:
+ SoundHandler _soundHandler;
+ SceneObject _topicArrowHotspot, _arrowHotspot, _visageHotspot;
+ SceneObject _subjectButton, _nextPageButton, _previousPageButton, _exitButton;
+ Action1 _action1;
+ Rect _listRect;
+ int _dbMode, _prevDbMode;
+ bool _visageVisable;
+ int _subjectIndex;
+ int _lineOffset;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void synchronise(Serialiser &s);
+};
+
+class Scene2150 : public Scene {
+ /* Actions */
+ class Action1 : public ActionExt {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot4 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot7 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot10 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SoundHandler _soundHandler;
+ SequenceManager _sequenceManager;
+ SpeakerGameText _speakerGameText;
+
+ Rect _rect1, _rect2;
+ Hotspot1 _hotspot1;
+ Hotspot2 _hotspot2;
+ DisplayHotspot _hotspot3;
+ Hotspot4 _hotspot4;
+ DisplayHotspot _hotspot5, _hotspot6;
+ Hotspot7 _hotspot7;
+ DisplayHotspot _hotspot8, _hotspot9;
+ Hotspot10 _hotspot10;
+ DisplayHotspot _hotspot11;
+ SceneObject _hotspot12, _hotspot13, _hotspot14;
+ SceneArea _area1, _area2, _area3, _area4;
+ Action1 _action1;
+ Action2 _action2;
+
+ Scene2150();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void synchronise(Serialiser &s);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene2200 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public ActionExt {
+ public:
+ virtual void signal();
+ virtual void process(Event &event);
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot3 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot5 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot9 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SpeakerMText _speakerMText;
+ SpeakerSText _speakerSText;
+ SpeakerQText _speakerQText;
+ SpeakerSL _speakerSL;
+ SpeakerQR _speakerQR;
+ SpeakerQL _speakerQL;
+ SpeakerMR _speakerMR;
+ SpeakerGameText _speakerGameText;
+ Rect _exitRect;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ DisplayHotspot _hotspot1;
+ Hotspot3 _hotspot3;
+ Hotspot5 _hotspot5;
+ Hotspot9 _hotspot9;
+ DisplayHotspot _hotspot10;
+ SceneObject _hotspot2, _hotspot4;
+ SceneObject _hotspot6, _hotspot7, _hotspot8;
+ SoundHandler _soundHandler1, _soundHandler2;
+
+ Scene2200();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void stripCallback(int v);
+ virtual void synchronise(Serialiser &s);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene2222 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+
+public:
+ SoundHandler _soundHandler;
+ SpeakerSText _speakerSText;
+ SpeakerMText _speakerMText;
+ SpeakerQText _speakerQText;
+ SpeakerML _speakerML;
+ SpeakerSR _speakerSR;
+ Action1 _action1;
+ Action2 _action2;
+ SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4, _hotspot5;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene2230 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action8 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot3 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot4 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot5 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot6 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot7 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot10 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot11 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot12 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SoundHandler _soundHandler;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ Action8 _action8;
+ Hotspot1 _hotspot1;
+ Hotspot3 _hotspot3;
+ Hotspot4 _hotspot4;
+ SceneObject _hotspot2;
+ Hotspot5 _hotspot5;
+ Hotspot6 _hotspot6;
+ Hotspot7 _hotspot7;
+ Hotspot8 _hotspot8;
+ DisplayHotspot _hotspot9;
+ Hotspot10 _hotspot10;
+ Hotspot11 _hotspot11;
+ Hotspot12 _hotspot12;
+ Rect _rect1;
+ int _field30A;
+
+ Scene2230();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void synchronise(Serialiser &s);
+ virtual void dispatch();
+};
+
+class Scene2280 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public ActionExt {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot4 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot7 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot10 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot12 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot14 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot15 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot16 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot17 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot18 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ SoundHandler _soundHandler;
+ SequenceManager _sequenceManager;
+ Rect _exitRect;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Hotspot1 _hotspot1;
+ Hotspot2 _hotspot2;
+ DisplayHotspot _hotspot3;
+ Hotspot4 _hotspot4;
+ DisplayHotspot _hotspot5, _hotspot6;
+ Hotspot7 _hotspot7;
+ Hotspot8 _hotspot8;
+ DisplayHotspot _hotspot9;
+ Hotspot10 _hotspot10;
+ DisplayHotspot _hotspot11;
+ Hotspot12 _hotspot12;
+ DisplayHotspot _hotspot13;
+ Hotspot14 _hotspot14;
+ DisplayHotspot _hotspot15, _hotspot16;
+ Hotspot17 _hotspot17;
+ Hotspot18 _hotspot18;
+
+ Scene2280();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void synchronise(Serialiser &s);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene2300 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public ActionExt {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot5 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot7 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SoundHandler _soundHandler1, _soundHandler2;
+ SpeakerSL _speakerSL;
+ SpeakerMText _speakerMText;
+ SpeakerQText _speakerQText;
+ SpeakerSText _speakerSText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4;
+ Hotspot5 _hotspot5;
+ SceneObject _hotspot6;
+ Hotspot7 _hotspot7;
+ SceneObject _hotspot8, _hotspot9, _hotspot10;
+ DisplayHotspot _hotspot11, _hotspot12, _hotspot13, _hotspot14, _hotspot15;
+
+ Scene2300();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene2310 : public Scene {
+private:
+ int findObject(int objIndex);
+
+ /* Custom classes */
+ class ProtectionEntry {
+ public:
+ int _pageNumber;
+ int _connectionList[5];
+
+ void set(int pageNumber, int v1, int v2, int v3, int v4, int v5) {
+ _pageNumber = pageNumber;
+ _connectionList[0] = v1; _connectionList[1] = v2; _connectionList[2] = v3;
+ _connectionList[3] = v4; _connectionList[4] = v5;
+ }
+ };
+
+public:
+ SequenceManager _sequenceManager;
+ int _wireIndex, _pageIndex;
+ SceneObject _wireList[5];
+ Rect _rectList[5];
+ SceneText _sceneText;
+ ProtectionEntry _pageList[21];
+
+ Scene2310();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void synchronise(Serialiser &s);
+ virtual void signal();
+ virtual void process(Event &event);
+ virtual void dispatch();
+};
+
+class Scene2320 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public ActionExt {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action8 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot5 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot6 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot10 : public SceneObjectExt {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot11 : public SceneObjectExt {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot12 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot14 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot15 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SoundHandler _soundHandler;
+ SequenceManager _sequenceManager1, _sequenceManager2;
+ SpeakerMText _speakerMText;
+ SpeakerMR _speakerMR;
+ SpeakerML _speakerML;
+ SpeakerQText _speakerQText;
+ SpeakerQL _speakerQL;
+ SpeakerQR _speakerQR;
+ SpeakerSAL _speakerSAL;
+ SpeakerSL _speakerSL;
+ SpeakerSR _speakerSR;
+ SpeakerSText _speakerSText;
+ SpeakerGameText _speakerGameText;
+ SceneArea _area1, _area2, _area3, _area4;
+ DisplayHotspot _hotspot1, _hotspot2, _hotspot3, _hotspot4;
+ Hotspot5 _hotspot5;
+ Hotspot6 _hotspot6;
+ SceneObject _hotspot7, _hotspot9;
+ Hotspot8 _hotspot8;
+ Hotspot10 _hotspot10;
+ Hotspot11 _hotspot11;
+ Hotspot12 _hotspot12;
+ DisplayHotspot _hotspot13;
+ Hotspot14 _hotspot14;
+ Hotspot15 _hotspot15;
+ SceneObject _hotspot16;
+ SceneItem *_hotspotPtr;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ Action8 _action8;
+
+ Scene2320();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void synchronise(Serialiser &s);
+ virtual void signal();
+};
+
+class Scene2400 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ virtual void dispatch();
+ };
+public:
+ Action1 _action1;
+ SceneObject _object;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_scenes4.cpp b/engines/tsage/ringworld_scenes4.cpp
new file mode 100644
index 0000000000..89feb223a1
--- /dev/null
+++ b/engines/tsage/ringworld_scenes4.cpp
@@ -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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/config-manager.h"
+#include "tsage/ringworld_scenes4.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+/*--------------------------------------------------------------------------
+ * Scene 3500 - Ringworld Scan
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene3500::Action1::signal() {
+ Scene3500 *scene = (Scene3500 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ scene->_stripManager.start(3500, this);
+ break;
+ case 2:
+ setDelay(3);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(9999);
+ break;
+ }
+}
+
+void Scene3500::Action2::signal() {
+ Scene3500 *scene = (Scene3500 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ scene->_stripManager.start(3501, this);
+ break;
+ case 2:
+ setDelay(3);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(2012);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene3500::postInit(SceneObjectList *OwnerList) {
+ loadScene((_globals->_stripNum == 3600) ? 3600 : 3500);
+ Scene::postInit();
+
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerSText);
+
+ _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds);
+ _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.top / 160) * 160;
+
+ setAction((_globals->_stripNum == 3600) ? (Action *)&_action2 : (Action *)&_action1);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 3700 - Remote Viewer
+ *
+ *--------------------------------------------------------------------------*/
+
+#define VIEW_FRAME_DELAY 10
+
+Scene3700::Viewer::Viewer() {
+ _images1.setVisage(3705, 1);
+ _images2.setVisage(3705, 2);
+
+ _frameList[0] = 1;
+ for (int idx = 1; idx <= 3; ++idx)
+ _frameList[idx] = _globals->_randomSource.getRandomNumber(4) + 1;
+
+ _active = true;
+ _countdownCtr = 0;
+ _percentList[0] = 120;
+ _percentList[1] = 50;
+ _percentList[2] = 75;
+ _percentList[3] = 114;
+}
+
+void Scene3700::Viewer::synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+ s.syncAsByte(_active);
+ s.syncAsSint16LE(_countdownCtr);
+ for (int idx = 0; idx < 4; ++idx) {
+ s.syncAsSint16LE(_frameList[idx]);
+ s.syncAsSint16LE(_percentList[idx]);
+ }
+}
+
+void Scene3700::Viewer::dispatch() {
+ if (_active) {
+ if (_countdownCtr-- <= 0) {
+ _countdownCtr = VIEW_FRAME_DELAY;
+
+ for (int idx = 3; idx > 1; --idx)
+ _frameList[idx] = _frameList[idx - 1];
+
+ int newFrame;
+ do {
+ newFrame = _globals->_randomSource.getRandomNumber(4) + 1;
+ } while (newFrame == _frameList[2]);
+
+ _frameList[1] = newFrame;
+ _flags |= OBJFLAG_PANES;
+ }
+ }
+}
+
+void Scene3700::Viewer::reposition() {
+ _bounds = Rect(123, 40, 285, 123);
+}
+
+void Scene3700::Viewer::draw() {
+ Region *priorityRegion = _globals->_sceneManager._scene->_priorities.find(1);
+
+ for (int idx = 0; idx < 4; ++idx) {
+ Visage &v = (idx == 0) ? _images1 : _images2;
+
+ GfxSurface img = v.getFrame(_frameList[idx]);
+ Rect destRect = img.getBounds();
+ destRect.resize(img, (_position.x - _globals->_sceneOffset.x),
+ (_position.y - _globals->_sceneOffset.y - _yDiff), _percentList[idx]);
+
+ destRect.translate(-_globals->_sceneManager._scene->_sceneBounds.left,
+ -_globals->_sceneManager._scene->_sceneBounds.top);
+
+ _globals->gfxManager().copyFrom(img, destRect, priorityRegion);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene3700::Action1::signal() {
+ Scene3700 *scene = (Scene3700 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ scene->_stripManager.start(2162, this);
+ break;
+ case 2:
+ scene->_viewer._active = false;
+ setDelay(90);
+ break;
+ case 3:
+ scene->_soundHandler.startSound(196);
+ scene->_viewer.hide();
+
+ scene->_hotspot1.postInit();
+ scene->_hotspot1.setVisage(3710);
+ scene->_hotspot1.setStrip(1);
+ scene->_hotspot1.setFrame(1);
+ scene->_hotspot1.setPosition(Common::Point(204, 120));
+
+ setDelay(90);
+ break;
+ case 4:
+ scene->_soundHandler.startSound(197);
+ scene->_hotspot1.hide();
+
+ scene->_hotspot2.postInit();
+ scene->_hotspot2.setVisage(3710);
+ scene->_hotspot2.setStrip(2);
+ scene->_hotspot2.setFrame(1);
+ scene->_hotspot2.setPosition(Common::Point(204, 120));
+
+ setDelay(30);
+ break;
+ case 5:
+ scene->_soundHandler.startSound(198);
+ scene->_hotspot2.hide();
+ scene->_hotspot1.show();
+ setDelay(90);
+ break;
+ case 6:
+ scene->_stripManager.start(2166, this);
+ break;
+ case 7:
+ setDelay(60);
+ break;
+ case 8:
+ scene->_hotspot1.remove();
+ scene->_hotspot2.show();
+ _globals->setFlag(59);
+ setDelay(30);
+ break;
+ case 9:
+ _globals->_sceneManager.changeScene(2100);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene3700::postInit(tSage::SceneObjectList *OwnerList) {
+ Scene::postInit();
+ loadScene(3700);
+
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerMR);
+ _speakerSText.setTextPos(Common::Point(20, 15));
+ _speakerMText.setTextPos(Common::Point(20, 15));
+
+ _viewer.postInit();
+ _viewer.setVisage(3705);
+ _viewer.setStrip(1);
+ _viewer.setFrame(2);
+ _viewer.setPosition(Common::Point(195, 83));
+
+ setAction(&_action1);
+ _globals->_soundHandler.startSound(195);
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes4.h b/engines/tsage/ringworld_scenes4.h
new file mode 100644
index 0000000000..f5dac297fc
--- /dev/null
+++ b/engines/tsage/ringworld_scenes4.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_SCENES4_H
+#define TSAGE_RINGWORLD_SCENES4_H
+
+#include "common/scummsys.h"
+#include "tsage/core.h"
+#include "tsage/converse.h"
+#include "tsage/ringworld_logic.h"
+
+namespace tSage {
+
+class Scene3500 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+public:
+ SpeakerSText _speakerSText;
+ SpeakerMText _speakerMText;
+ SpeakerQText _speakerQText;
+ Action1 _action1;
+ Action2 _action2;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene3700 : public Scene {
+ /* Custom classes */
+ class Viewer : public SceneObject {
+ public:
+ Visage _images1;
+ Visage _images2;
+
+ int _frameList[4];
+ int _percentList[4];
+ bool _active;
+ int _countdownCtr;
+
+ Viewer();
+ virtual Common::String getClassName() { return "Viewer"; }
+ virtual void synchronise(Serialiser &s);
+ virtual void dispatch();
+ virtual void reposition();
+ virtual void draw();
+ };
+
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+public:
+ Viewer _viewer;
+ Action1 _action1;
+ SceneObject _hotspot1, _hotspot2;
+ SpeakerSText _speakerSText;
+ SpeakerMText _speakerMText;
+ SpeakerMR _speakerMR;
+ SoundHandler _soundHandler;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_scenes5.cpp b/engines/tsage/ringworld_scenes5.cpp
new file mode 100644
index 0000000000..3dfd421b60
--- /dev/null
+++ b/engines/tsage/ringworld_scenes5.cpp
@@ -0,0 +1,4413 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/config-manager.h"
+#include "tsage/ringworld_scenes5.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+/*--------------------------------------------------------------------------
+ * Scene 4000 - Village
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4000::Action1::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_hotspot5.postInit();
+ scene->_hotspot5.setVisage(2870);
+ scene->_hotspot5.setObjectWrapper(new SceneObjectWrapper());
+ scene->_hotspot5.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot5.setPosition(Common::Point(116, 160));
+
+// ADD_PLAYER_MOVER_NULL(scene->_hotspot5, 208, 169);
+ Common::Point pt(208, 169);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot5.addMover(mover, &pt, this);
+
+ RING_INVENTORY._ale._sceneNumber = 0;
+ _globals->clearFlag(42);
+ _globals->clearFlag(36);
+ _globals->clearFlag(43);
+ _globals->clearFlag(37);
+ break;
+ }
+ case 1: {
+ scene->_guardRock.postInit();
+ scene->_guardRock.setVisage(4001);
+ scene->_guardRock.animate(ANIM_MODE_1, NULL);
+ scene->_guardRock.setObjectWrapper(new SceneObjectWrapper());
+ scene->_guardRock.setPosition(Common::Point(314, 132));
+ scene->_guardRock._moveDiff = Common::Point(4, 2);
+
+ ADD_PLAYER_MOVER_NULL(scene->_guardRock, 288, 167);
+
+ scene->_olo.postInit();
+ scene->_olo.setVisage(4006);
+ scene->_olo.animate(ANIM_MODE_1, NULL);
+ scene->_olo.setStrip(1);
+ scene->_olo.setPosition(Common::Point(207, 136));
+
+ ADD_PLAYER_MOVER_NULL(scene->_olo, 220, 151);
+
+ scene->_miranda.postInit();
+ scene->_miranda.setVisage(2701);
+ scene->_miranda.animate(ANIM_MODE_1, NULL);
+ scene->_miranda.setObjectWrapper(new SceneObjectWrapper());
+ scene->_miranda._moveDiff = Common::Point(4, 2);
+ scene->_miranda.setPosition(Common::Point(300, 135));
+
+ ADD_PLAYER_MOVER_THIS(scene->_miranda, 266, 169);
+
+ ADD_PLAYER_MOVER_NULL(_globals->_player, 241, 155);
+ break;
+ }
+ case 2:
+ scene->_stripManager.start(4400, this);
+ break;
+ case 3: {
+ Common::Point pt1(30, 86);
+ PlayerMover *mover1 = new PlayerMover();
+ scene->_miranda.addMover(mover1, &pt1, this);
+
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot5, 3, 86);
+ break;
+ }
+ case 4:
+ ADD_MOVER(scene->_miranda, -30, 86);
+ ADD_MOVER(scene->_hotspot5, -40, 86);
+ break;
+ case 5:
+ _globals->_soundHandler.startSound(155);
+ _globals->setFlag(43);
+ _globals->setFlag(114);
+ scene->_stripManager.start(4430, this);
+ break;
+ case 6:
+ ADD_PLAYER_MOVER_THIS(scene->_olo, 277, 175);
+ ADD_PLAYER_MOVER_NULL(_globals->_player, 258, 187);
+ break;
+ case 7:
+ scene->_stripManager.start(4440, this);
+ break;
+ case 8:
+ setDelay(30);
+ break;
+ case 9:
+ _globals->setFlag(96);
+ _globals->_sceneManager.changeScene(4025);
+ break;
+ }
+}
+
+void Scene4000::Action2::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setAction(&scene->_sequenceManager1, this, 4001, &_globals->_player, NULL);
+
+ scene->_hotspot5.postInit();
+ scene->_hotspot5.setVisage(2801);
+ scene->_hotspot5.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot5.setObjectWrapper(new SceneObjectWrapper());
+ scene->_hotspot5._moveDiff.x = 5;
+ scene->_hotspot5.setPosition(Common::Point(-8, 88));
+
+ scene->_lander.setAction(&scene->_sequenceManager3, NULL, 4003, &scene->_hotspot5, NULL);
+ scene->_miranda.setAction(&scene->_sequenceManager2, NULL, 4002, &scene->_miranda, NULL);
+ break;
+ case 1:
+ _globals->_player.disableControl();
+
+ scene->_lander.remove();
+ ADD_MOVER(scene->_guardRock, scene->_hotspot5._position.x + 30, scene->_hotspot5._position.y - 10);
+ break;
+ case 2:
+ _globals->_player.checkAngle(&scene->_guardRock);
+ scene->_hotspot5.checkAngle(&scene->_guardRock);
+ scene->_miranda.checkAngle(&scene->_guardRock);
+ scene->_stripManager.start(4000, this);
+ break;
+ case 3:
+ scene->_hotspot2.setVisage(4017);
+ scene->_hotspot2.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot2.setStrip(2);
+
+ ADD_MOVER(scene->_hotspot2, 116, 160);
+ ADD_MOVER(scene->_hotspot5, 116, 160);
+
+ _globals->setFlag(37);
+ break;
+ case 4:
+ break;
+ case 5:
+ scene->_stripManager.start(4010, this);
+ break;
+ case 6:
+ ADD_PLAYER_MOVER_NULL(scene->_guardRock, 230, 149);
+ ADD_PLAYER_MOVER(210, 136);
+ ADD_PLAYER_MOVER_NULL(scene->_miranda, 210, 133);
+ break;
+ case 7:
+ _globals->_sceneManager.changeScene(4045);
+ break;
+ }
+}
+
+void Scene4000::Action3::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_hotspot8.setVisage(4017);
+ scene->_hotspot8.setFrame2(-1);
+ scene->_hotspot8.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot8.setObjectWrapper(new SceneObjectWrapper());
+ ADD_MOVER(scene->_hotspot8, 118, 145);
+ break;
+ case 1:
+ scene->_hotspot8.remove();
+ remove();
+ break;
+ }
+}
+
+void Scene4000::Action4::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player._uiEnabled = false;
+ ADD_MOVER(_globals->_player, 257, 57);
+ break;
+ case 1:
+ _globals->_player.setVisage(4008);
+ _globals->_player.setPosition(Common::Point(258, 83));
+ _globals->_player._frame = 1;
+ _globals->_player._strip = 3;
+ _globals->_player.animate(ANIM_MODE_4, 2, 1, this);
+ break;
+ case 2:
+ scene->_rope.postInit();
+ scene->_rope.setVisage(4000);
+ scene->_rope.setStrip(7);
+ scene->_rope.setFrame(3);
+ scene->_rope.setPosition(Common::Point(268, 44));
+
+ RING_INVENTORY._rope._sceneNumber = 4000;
+ _globals->_events.setCursor(CURSOR_USE);
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 3:
+ _globals->_player.setVisage(2602);
+ _globals->_player.setPosition(Common::Point(257, 57));
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player._uiEnabled = true;
+
+ _globals->setFlag(41);
+ remove();
+ break;
+ }
+}
+
+void Scene4000::Action5::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(15);
+ break;
+ case 1:
+ scene->_stripManager.start(_globals->_stripNum, this);
+ break;
+ case 2:
+ setDelay(10);
+ break;
+ case 3:
+ scene->_hotspot8.setVisage(4017);
+ scene->_hotspot8.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot8.setFrame2(-1);
+ scene->_hotspot8.setAction(&scene->_action3);
+
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4000::Action6::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(30);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager1, this, 4001, &_globals->_player, NULL);
+
+ if (!_globals->getFlag(36))
+ scene->_miranda.setAction(&scene->_sequenceManager2, NULL, 4002, &scene->_miranda, NULL);
+ break;
+ case 2:
+ _globals->_player.disableControl();
+ ADD_MOVER(scene->_guardRock, _globals->_player._position.x + 30, _globals->_player._position.y - 5);
+ break;
+ case 3:
+ scene->_stripManager.start(_globals->getFlag(35) ? 4500 : 4502, this);
+ break;
+ case 4:
+ _globals->clearFlag(35);
+ ADD_MOVER_NULL(scene->_guardRock, 292, 138);
+ ADD_PLAYER_MOVER(283, 147);
+
+ if (!_globals->getFlag(36))
+ ADD_PLAYER_MOVER_NULL(scene->_miranda, 280, 150);
+ RING_INVENTORY._ale._sceneNumber = 4100;
+ break;
+ case 5:
+ _globals->_sceneManager.changeScene(4100);
+ break;
+ }
+}
+
+void Scene4000::Action7::signal() {
+ // Climb down left Chimney using a rope
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+
+ scene->_rope.setFrame(1);
+ ADD_MOVER(_globals->_player, 247, 53);
+ break;
+ case 1:
+ _globals->_player.setVisage(4008);
+ _globals->_player.setStrip(4);
+ _globals->_player.setFrame(1);
+ _globals->_player.fixPriority(16);
+ _globals->_player.setPosition(Common::Point(260, 55));
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ _globals->_sceneManager.changeScene(4050);
+ break;
+ }
+}
+
+void Scene4000::Action8::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ if (_globals->getFlag(41))
+ scene->_rope.setFrame(2);
+
+ ADD_MOVER(_globals->_player, 289, 53);
+ break;
+ case 1:
+ _globals->_player.setVisage(4008);
+ _globals->_player.setStrip(5);
+ _globals->_player.setPriority(16);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(283, 52));
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ _globals->_player.remove();
+ setDelay(60);
+ break;
+ case 3:
+ _globals->_soundHandler.startSound(170);
+ scene->_smoke2.setVisage(4000);
+ scene->_smoke2.setStrip(6);
+ scene->_smoke2.animate(ANIM_MODE_2, NULL);
+ setDelay(60);
+ break;
+ case 4:
+ _globals->_soundHandler.startSound(77, this);
+ break;
+ case 5:
+ _globals->_game->endGame(4000, 15);
+ remove();
+ break;
+ }
+}
+
+void Scene4000::Action9::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(119) + 240);
+ break;
+ case 1:
+ static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_8, 1, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene4000::Action10::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(119) + 240);
+ break;
+ case 1:
+ static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_8, 1, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene4000::Action11::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ ADD_MOVER(scene->_lander, -30, 70);
+ break;
+ case 1:
+ setDelay(60);
+ break;
+ case 2:
+ scene->_hotspot5.postInit();
+ scene->_hotspot5.setVisage(2801);
+ scene->_hotspot5.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot5.setObjectWrapper(new SceneObjectWrapper());
+ scene->_hotspot5._moveDiff.x = 4;
+ scene->_hotspot5.setPosition(Common::Point(-8, 88));
+
+ setAction(&scene->_sequenceManager1, this, 4001, &_globals->_player, NULL);
+
+ scene->_miranda.setPosition(Common::Point(-210, 139));
+ scene->_miranda.setAction(&scene->_sequenceManager2, NULL, 4002, &scene->_miranda, NULL);
+ scene->_lander.setAction(&scene->_sequenceManager3, NULL, 4003, &scene->_hotspot5, NULL);
+ break;
+ case 3:
+ scene->_stripManager.start(8000, this);
+ break;
+ case 4:
+ ADD_MOVER(scene->_olo, 263, 187);
+ scene->_olo.animate(ANIM_MODE_1, NULL);
+ break;
+ case 5:
+ scene->_soundHandler1.proc3();
+ scene->_forceField.remove();
+
+ ADD_MOVER(_globals->_player, 340, 163);
+ ADD_MOVER_NULL(scene->_miranda, 340, 169);
+ ADD_MOVER_NULL(scene->_hotspot5, 340, 165);
+ break;
+ case 6:
+ _globals->_sceneManager.changeScene(4250);
+ break;
+ }
+}
+
+void Scene4000::Action12::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(5);
+ break;
+ case 1:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(4015, this);
+ break;
+ case 2:
+ _globals->setFlag(32);
+ if (scene->_stripManager._field2E8 == 275) {
+ _globals->setFlag(82);
+ ADD_MOVER_NULL(scene->_guardRock, 292, 138);
+ ADD_PLAYER_MOVER(283, 147);
+ } else {
+ setDelay(30);
+ }
+ break;
+ case 3:
+ if (scene->_stripManager._field2E8 == 275) {
+ _globals->_sceneManager.changeScene(4100);
+ } else {
+ ADD_PLAYER_MOVER_THIS(scene->_guardRock, 300, 132);
+ }
+ break;
+ case 4:
+ scene->_guardRock.hide();
+ scene->_stripManager.start(4020, this);
+ break;
+ case 5:
+ _globals->setFlag(35);
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4000::Action13::signal() {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ scene->_soundHandler2.startSound(151);
+ scene->_soundHandler2.proc5(true);
+ ADD_MOVER(scene->_lander, -30, 70);
+ break;
+ case 2:
+ scene->_soundHandler2.proc4();
+ _globals->_sceneManager.changeScene(4010);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4000::Miranda::doAction(int action) {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(4000, 31);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 29);
+ break;
+ case CURSOR_TALK:
+ if (_globals->getFlag(31)) {
+ if (!_globals->getFlag(111)) {
+ _globals->setFlag(111);
+ _globals->_stripNum = 4070;
+ } else if (!_globals->getFlag(33))
+ _globals->_stripNum = 4094;
+ else if (!_globals->getFlag(112)) {
+ _globals->setFlag(112);
+ _globals->_stripNum = 4300;
+ } else if (!_globals->getFlag(113)) {
+ _globals->setFlag(113);
+ _globals->_stripNum = 4093;
+ } else
+ _globals->_stripNum = 4094;
+ } else {
+ if (!_globals->getFlag(33))
+ _globals->_stripNum = 4094;
+ else if (!_globals->getFlag(112)) {
+ _globals->setFlag(112);
+ _globals->_stripNum = 4300;
+ } else
+ _globals->_stripNum = 4094;
+ }
+
+ scene->setAction(&scene->_action5);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::Hotspot8::doAction(int action) {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(4000, 26);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 25);
+ break;
+ case CURSOR_TALK:
+ if (RING_INVENTORY._peg._sceneNumber == 1)
+ SceneItem::display2(4000, 34);
+ else {
+ switch (_ctr) {
+ case 0:
+ _globals->_stripNum = 4090;
+ break;
+ case 1:
+ _globals->_stripNum = 4091;
+ break;
+ case 2:
+ _globals->_stripNum = 4092;
+ break;
+ default:
+ SceneItem::display2(4000, 34);
+ break;
+ }
+
+ if (_globals->_stripNum) {
+ setAction(NULL);
+ addMover(NULL);
+ ++_ctr;
+ scene->setAction(&scene->_action5);
+ }
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::GuardRock::doAction(int action) {
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(4000, 28);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 27);
+ break;
+ case CURSOR_TALK:
+ error("*** Do we need dialog.");
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::Ladder::doAction(int action) {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 30);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ if (_globals->getFlag(40)) {
+ scene->_sceneMode = 4005;
+ scene->setAction(&scene->_sequenceManager1, scene, 4005, &_globals->_player, NULL);
+ } else {
+ scene->_sceneMode = 4004;
+ scene->setAction(&scene->_sequenceManager1, scene, 4004, &_globals->_player, &scene->_ladder, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::TheTech::doAction(int action) {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 13);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4000, 19);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4000, 20);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(40))
+ SceneItem::display2(4000, 37);
+ else {
+ _globals->_player.disableControl();
+ if (_globals->_sceneObjects->contains(&scene->_miranda))
+ _globals->clearFlag(96);
+
+ scene->_sceneMode = 4012;
+ scene->setAction(&scene->_sequenceManager1, scene, 4012, &_globals->_player, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::Hotspot13::doAction(int action) {
+ // Rock
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 21);
+ break;
+ case OBJECT_ROPE:
+ if (_globals->getFlag(40))
+ scene->setAction(&scene->_action4);
+ else
+ SceneItem::display2(4000, 22);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::Hotspot::doAction(int action) {
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 16);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4000, 17);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4000, 18);
+ break;
+ case OBJECT_LADDER: {
+ _globals->_player.disableControl();
+
+ scene->_ladder.postInit();
+ scene->_ladder.setVisage(4000);
+ scene->_ladder.setStrip(5);
+ scene->_ladder.setPosition(Common::Point(245, 147));
+ scene->_ladder.hide();
+ _globals->_sceneItems.push_front(&scene->_ladder);
+
+ if (_globals->_sceneObjects->contains(&scene->_hotspot8)) {
+ scene->_hotspot8.setAction(NULL);
+ Common::Point pt(118, 145);
+ NpcMover *mover = new NpcMover();
+ scene->_hotspot18.addMover(mover, &pt, NULL);
+ }
+
+ scene->_sceneMode = 4004;
+ scene->setAction(&scene->_sequenceManager1, scene, 4011, &_globals->_player, &scene->_ladder, NULL);
+ break;
+ }
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::Hotspot17::doAction(int action) {
+ // Left Chimney
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 23);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(40))
+ scene->setAction(&scene->_action7);
+ else
+ SceneItem::display2(4000, 24);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::Hotspot18::doAction(int action) {
+ // Right Chimney
+ Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, 36);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(40))
+ scene->setAction(&scene->_action8);
+ else
+ SceneItem::display2(4000, 24);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4000::Hotspot23::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4000, _globals->getFlag(31) ? 10 : 9);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene4000::Scene4000() :
+ _forceField(0, CURSOR_LOOK, 4000, 14, CURSOR_USE, 4000, 32, OBJECT_STUNNER, 4000, 33,
+ OBJECT_SCANNER, 4000, 19, LIST_END),
+ _hotspot19(0, CURSOR_LOOK, 4000, 7, LIST_END),
+ _hotspot20(0, CURSOR_LOOK, 4000, 3, LIST_END),
+ _hotspot21(0, CURSOR_LOOK, 4000, 1, LIST_END),
+ _hotspot22(0, CURSOR_LOOK, 4000, 8, LIST_END),
+ _hotspot24(0, CURSOR_LOOK, 4000, 11, LIST_END),
+ _hotspot25(0, CURSOR_LOOK, 4000, 4, LIST_END),
+ _hotspot26(0, CURSOR_LOOK, 4000, 0, LIST_END) {
+}
+
+void Scene4000::postInit(SceneObjectList *OwnerList) {
+ loadScene(4000);
+ Scene::postInit();
+ setZoomPercents(0, 20, 70, 50);
+
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerML);
+ _stripManager.addSpeaker(&_speakerMR);
+ _stripManager.addSpeaker(&_speakerSR);
+ _stripManager.addSpeaker(&_speakerCHFL);
+ _stripManager.addSpeaker(&_speakerPL);
+ _stripManager.addSpeaker(&_speakerPText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerCHFR);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerCHFText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerMText);
+
+ _speakerCHFText._npc = &_guardRock;
+ _speakerSText._npc = &_hotspot5;
+ _speakerMText._npc = &_miranda;
+ _speakerPText._npc = &_olo;
+ _speakerQText._npc = &_globals->_player;
+
+ _hotspot13.setBounds(Rect(263, 41, 278, 55));
+ _hotspot14.setBounds(Rect(96 /*140*/, 177, 140 /*96*/, 204));
+ _hotspot15.setBounds(Rect(227, 101, 264, 143));
+ _hotspot16.setBounds(Rect(306, 100, 319, 148));
+ _hotspot17.setBounds(Rect(231, 53, 254, 60));
+ _hotspot18.setBounds(Rect(285, 51, 310, 60));
+ _hotspot26.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot21.setBounds(Rect(28, 7, 53, 64));
+ _hotspot22.setBounds(Rect(125, 155, 140, 189));
+ _hotspot23.setBounds(Rect(205, 102, 220, 142));
+ _hotspot24.setBounds(Rect(270, 111, 297, 147));
+
+ _hotspot19._sceneRegionId = 16;
+ _hotspot20._sceneRegionId = 18;
+ _hotspot25._sceneRegionId = 17;
+
+ _smoke1.postInit();
+ _smoke1.setVisage(4000);
+ _smoke1.fixPriority(1);
+ _smoke1.setFrame(2);
+ _smoke1.setPosition(Common::Point(242, 59));
+ _smoke1.animate(ANIM_MODE_2, NULL);
+
+ _smoke2.postInit();
+ _smoke2.setVisage(4000);
+ _smoke2.setStrip(2);
+ _smoke2.fixPriority(1);
+ _smoke2.setFrame(2);
+ _smoke2.setPosition(Common::Point(299, 59));
+ _smoke2.animate(ANIM_MODE_2, NULL);
+
+ if (RING_INVENTORY._ladder._sceneNumber != 4000) {
+ // if ladder is not in the scene, activate the hotspot on the wall
+ _hotspot8.postInit();
+ _hotspot8.setVisage(4018);
+ _hotspot8.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot8._strip = 2;
+ _hotspot8._numFrames = 5;
+ _hotspot8.setPosition(Common::Point(306, 154));
+ _hotspot8.setAction(&_action9);
+ }
+
+ _theTech.postInit();
+ _theTech.setVisage(4000);
+ _theTech.setStrip(3);
+ _theTech.setFrame(3);
+ _theTech.fixPriority(200);
+ _theTech.setPosition(Common::Point(281, 176));
+
+ if (_globals->getFlag(34)) {
+ _soundHandler1.startSound(156);
+
+ _forceField.postInit();
+ _forceField.setVisage(4000);
+ _forceField.setStrip(4);
+ _forceField.setPosition(Common::Point(312, 174));
+ _forceField.fixPriority(200);
+ _forceField.animate(ANIM_MODE_8, 0, NULL);
+
+ _globals->_sceneItems.push_back(&_forceField);
+ }
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2602);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(-28, 86));
+
+ if (!_globals->getFlag(36) && !_globals->getFlag(43)) {
+ _miranda.postInit();
+ _miranda.setVisage(2701);
+ _miranda.animate(ANIM_MODE_1, NULL);
+ _miranda.setObjectWrapper(new SceneObjectWrapper());
+ _miranda._moveDiff = Common::Point(4, 2);
+ _miranda.setPosition(Common::Point(-210, 139));
+
+ _globals->_sceneItems.push_back(&_miranda);
+ }
+
+ _globals->clearFlag(40);
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 2320:
+ _globals->_soundHandler.startSound(155);
+
+ if (RING_INVENTORY._ale._sceneNumber == 1) {
+ _guardRock.postInit();
+ _guardRock.setVisage(4001);
+ _guardRock.animate(ANIM_MODE_1, NULL);
+ _guardRock.setObjectWrapper(new SceneObjectWrapper());
+ _guardRock.setPosition(Common::Point(314, 132));
+
+ setAction(&_action6);
+ } else {
+ _globals->_player.disableControl();
+ _sceneMode = 4001;
+ setAction(&_sequenceManager1, this, 4001, &_globals->_player, NULL);
+
+ if (!_globals->getFlag(36) && !_globals->getFlag(43))
+ _miranda.setAction(&_sequenceManager2, NULL, 4002, &_miranda, NULL);
+ }
+
+ if (_globals->getFlag(42))
+ _hotspot8.setAction(&_action3);
+ else if (_globals->getFlag(91))
+ _hotspot8.remove();
+ break;
+
+ case 4010:
+ _miranda.setPosition(Common::Point(-210, 139));
+
+ _guardRock.postInit();
+ _guardRock.setVisage(4001);
+ _guardRock.animate(ANIM_MODE_1, NULL);
+ _guardRock.setObjectWrapper(new SceneObjectWrapper());
+ _guardRock.setPosition(Common::Point(314, 132));
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(4018);
+ _hotspot2._strip = 1;
+ _hotspot2._numFrames = 5;
+ _hotspot2.setPosition(Common::Point(182, 146));
+ _hotspot2.setAction(&_action10);
+
+ setAction(&_action2);
+ break;
+
+ case 4025:
+ if (RING_INVENTORY._ladder._sceneNumber == 4000)
+ _hotspot8.remove();
+
+ _globals->_player.setPosition(Common::Point(260, 185));
+
+ if (!_globals->getFlag(36) && !_globals->getFlag(43))
+ _miranda.setPosition(Common::Point(246, 146));
+
+ if (_globals->getFlag(96)) {
+ _olo.postInit();
+ _olo.setVisage(4006);
+ _olo.animate(ANIM_MODE_1, NULL);
+ _olo.setObjectWrapper(new SceneObjectWrapper());
+ _olo.setPosition(Common::Point(290, 163));
+ }
+
+ if (_globals->_stripNum == 4025) {
+ _soundHandler1.startSound(182);
+ _forceField.remove();
+
+ _hotspot5.postInit();
+ _hotspot5.setVisage(2801);
+ _hotspot5.animate(ANIM_MODE_1, NULL);
+ _hotspot5.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot5._moveDiff.x = 4;
+ _hotspot5.setPosition(Common::Point(-18, 86));
+
+ _globals->_player.disableControl();
+
+ if (!_globals->getFlag(96)) {
+ _olo.postInit();
+ _olo.setVisage(4006);
+ _olo.animate(ANIM_MODE_1, NULL);
+ _olo.setObjectWrapper(new SceneObjectWrapper());
+ _olo.setPosition(Common::Point(195, 128));
+
+ Common::Point pt(268, 157);
+ PlayerMover *mover = new PlayerMover();
+ _olo.addMover(mover, &pt, NULL);
+ }
+
+ _sceneMode = 4003;
+ setAction(&_sequenceManager1, this, 4003, &_hotspot5, NULL);
+ } else if (_globals->getFlag(96)) {
+ _globals->_player.disableControl();
+ _sceneMode = 4013;
+ setAction(&_sequenceManager1, this, 4013, &_olo, NULL);
+ }
+
+ _globals->clearFlag(96);
+ break;
+
+ case 4045:
+ _globals->_player.enableControl();
+
+ if (RING_INVENTORY._ladder._sceneNumber != 4000) {
+ _hotspot8.postInit();
+ _hotspot8.setVisage(4017);
+ _hotspot8.animate(ANIM_MODE_1, NULL);
+ _hotspot8.setPosition(Common::Point(199, 188));
+ _hotspot8.setAction(&_action3);
+ }
+
+ _globals->_player.setPosition(Common::Point(208, 153));
+ if (!_globals->getFlag(36) && !_globals->getFlag(43))
+ _miranda.setPosition(Common::Point(246, 146));
+
+ if (_globals->getFlag(39)) {
+ _globals->clearFlag(39);
+
+ _olo.postInit();
+ _olo.setVisage(4006);
+ _olo.animate(ANIM_MODE_1, NULL);
+ _olo.setObjectWrapper(new SceneObjectWrapper());
+ _olo.setPosition(Common::Point(219, 150));
+
+ _globals->_player.disableControl();
+ setAction(&_sequenceManager1, this, 4010, &_globals->_player, NULL);
+ }
+
+ if (_globals->_stripNum == 4000) {
+ _globals->_stripNum = 0;
+
+ _guardRock.postInit();
+ _guardRock.setVisage(4001);
+ _guardRock.animate(ANIM_MODE_1, NULL);
+ _guardRock.setObjectWrapper(new SceneObjectWrapper());
+ _guardRock.setPosition(Common::Point(231, 159));
+ _guardRock.setStrip(4);
+
+ setAction(&_action12);
+ }
+ break;
+
+ case 4050:
+ _globals->_soundHandler.startSound(155);
+ _globals->_player.disableControl();
+
+ if (_globals->_stripNum == 4050) {
+ _globals->_player.setVisage(4008);
+ _globals->_player.setStrip(4);
+ _globals->_player.setFrame(_globals->_player.getFrameCount());
+ _globals->_player.fixPriority(16);
+ _globals->_player.setPosition(Common::Point(260, 55));
+
+ _sceneMode = 4007;
+ setAction(&_sequenceManager1, this, 4007, &_globals->_player, NULL);
+ } else {
+ _globals->_player.setPosition(Common::Point(208, 153));
+ _globals->_player.enableControl();
+ }
+
+ if (RING_INVENTORY._ladder._sceneNumber != 4000)
+ _hotspot8.remove();
+ break;
+
+ case 4100:
+ _globals->_player.enableControl();
+ _globals->_player.setPosition(Common::Point(270, 155));
+
+ if (_globals->getFlag(42) && (RING_INVENTORY._ladder._sceneNumber != 4000)) {
+ _hotspot8.setVisage(4017);
+ _hotspot8.animate(ANIM_MODE_1, NULL);
+ _hotspot8.setPosition(Common::Point(244, 151));
+ _hotspot8.setAction(&_action3);
+ }
+
+ if (!_globals->getFlag(36) && !_globals->getFlag(43))
+ _miranda.setPosition(Common::Point(246, 146));
+ break;
+
+ default:
+ _globals->_soundHandler.startSound(155);
+
+ _lander.postInit();
+ _lander.setVisage(4002);
+ _lander._moveDiff = Common::Point(10, 10);
+ _lander.setPosition(Common::Point(-100, 80));
+ _lander.changeZoom(-1);
+ _lander.setPosition(Common::Point(130, -1));
+ _lander.animate(ANIM_MODE_2, NULL);
+
+ if (_globals->_stripNum == 9000) {
+ _olo.postInit();
+ _olo.setVisage(4006);
+ _olo.setPosition(Common::Point(235, 153));
+
+ _guardRock.postInit();
+ _guardRock.setVisage(4001);
+ _guardRock.setStrip(3);
+ _guardRock.setPosition(Common::Point(255, 153));
+
+ setAction(&_action11);
+ RING_INVENTORY._ladder._sceneNumber = 4100;
+ RING_INVENTORY._rope._sceneNumber = 4150;
+
+ _soundHandler1.startSound(156);
+
+ _forceField.postInit();
+ _forceField.setVisage(4000);
+ _forceField.setStrip(4);
+ _forceField.setPosition(Common::Point(312, 174));
+ _forceField.fixPriority(200);
+ _forceField.animate(ANIM_MODE_8, 0, NULL);
+ } else {
+ if (!_globals->getFlag(37)) {
+ _hotspot2.postInit();
+ _hotspot2.setVisage(4018);
+ _hotspot2._strip = 1;
+ _hotspot2._numFrames = 5;
+ _hotspot2.setPosition(Common::Point(182, 146));
+ _hotspot2.setAction(&_action10);
+ }
+ _miranda.setPosition(Common::Point(-210, 139));
+ setAction(&_action13);
+ }
+
+ break;
+ }
+
+ if (RING_INVENTORY._ladder._sceneNumber == 4000) {
+ _ladder.postInit();
+ _ladder.setVisage(4000);
+ _ladder.setStrip(5);
+ _ladder.setPosition(Common::Point(245, 147));
+
+ _globals->_sceneItems.push_back(&_ladder);
+ }
+
+ if (RING_INVENTORY._rope._sceneNumber == 4000) {
+ _rope.postInit();
+ _rope.setVisage(4000);
+ _rope.setStrip(7);
+ _rope.fixPriority(1);
+ _rope.setPosition(Common::Point(268, 44));
+ }
+
+ _globals->_sceneItems.addItems(&_hotspot8, &_hotspot17, &_hotspot18, &_hotspot14, &_hotspot15,
+ &_hotspot16, &_theTech, &_hotspot13, &_hotspot21, &_hotspot20, &_hotspot22, &_hotspot23,
+ &_hotspot24, &_hotspot25, &_hotspot19, &_hotspot26, NULL);
+}
+
+void Scene4000::signal() {
+ switch (_sceneMode) {
+ case 4001:
+ _globals->_player.enableControl();
+ break;
+ case 4002:
+ case 4011:
+ break;
+ case 4003:
+ _sceneMode = 4014;
+ setAction(&_sequenceManager1, this, 4014, &_globals->_player, &_hotspot5, NULL);
+ break;
+ case 4004:
+ RING_INVENTORY._ladder._sceneNumber = 4000;
+ // Deliberate fall-through
+ case 4007:
+ _globals->_player._uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_USE);
+ _globals->setFlag(40);
+ break;
+ case 4005:
+ _globals->_player.enableControl();
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->clearFlag(40);
+ break;
+ case 4006:
+ _globals->_sceneManager.changeScene(4045);
+ break;
+ case 4008:
+ _globals->_sceneManager.changeScene(2320);
+ break;
+ case 4009:
+ _globals->_sceneManager.changeScene(2200);
+ break;
+ case 4010:
+ _globals->setFlag(38);
+ _olo.remove();
+ break;
+ case 4012:
+ _globals->_player.checkAngle(&_theTech);
+ _globals->_sceneManager.changeScene(4025);
+ break;
+ case 4013:
+ _globals->_player.enableControl();
+ _olo.remove();
+ break;
+ case 4014:
+ _globals->_sceneManager.changeScene(4250);
+ break;
+ case 4015:
+ ADD_MOVER_NULL(_miranda, 0, _miranda._position.y - 5);
+ break;
+ }
+}
+
+void Scene4000::dispatch() {
+ Scene::dispatch();
+
+ if ((_globals->_player.getRegionIndex() == 10) || (_globals->_player.getRegionIndex() == 6))
+ _globals->_player.fixPriority(200);
+ if (_globals->_player.getRegionIndex() == 11)
+ _globals->_player.fixPriority(-1);
+ if (_globals->_player.getRegionIndex() == 5)
+ _globals->_player.fixPriority(94);
+
+ if (_globals->_sceneObjects->contains(&_hotspot5)) {
+ if ((_hotspot5.getRegionIndex() == 10) || (_hotspot5.getRegionIndex() == 6))
+ _hotspot5.fixPriority(200);
+ if (_hotspot5.getRegionIndex() == 11)
+ _hotspot5.fixPriority(-1);
+ if (_hotspot5.getRegionIndex() == 5)
+ _hotspot5.fixPriority(94);
+ }
+
+ if (_globals->_sceneObjects->contains(&_miranda)) {
+ if (!_miranda._mover)
+ _miranda.checkAngle(&_globals->_player);
+ if (!_action && _globals->_player.getRegionIndex() == 23) {
+ ADD_MOVER_NULL(_miranda, 204, 186);
+ }
+
+ if ((_miranda.getRegionIndex() == 10) || (_miranda.getRegionIndex() == 6))
+ _miranda.fixPriority(200);
+ if (_miranda.getRegionIndex() == 11)
+ _miranda.fixPriority(-1);
+ if (_miranda.getRegionIndex() == 5)
+ _miranda.fixPriority(94);
+ }
+
+ if (!_action) {
+ if ((RING_INVENTORY._peg._sceneNumber == 1) && _globals->getFlag(34) &&
+ _globals->getFlag(37) && !_globals->getFlag(40)) {
+ _globals->_player.disableControl();
+ _soundHandler1.startSound(177);
+ _globals->_soundHandler.startSound(178);
+
+ setAction(&_action1);
+ }
+
+ if (_globals->_player.getRegionIndex() == 2)
+ _globals->_sceneManager.changeScene(4045);
+ if (_globals->_player.getRegionIndex() == 15)
+ _globals->_sceneManager.changeScene(4100);
+
+ if ((_globals->_player._position.x <= 5) && (_globals->_player._position.y < 100)) {
+ _globals->_player.disableControl();
+
+ if (!_globals->_sceneObjects->contains(&_miranda) || (_miranda._position.y <= 100)) {
+ _sceneMode = 4008;
+ setAction(&_sequenceManager1, this, 4008, &_globals->_player, NULL);
+ } else {
+ _sceneMode = 4015;
+ _globals->_player.addMover(NULL);
+ setAction(&_sequenceManager1, this, 4015, &_globals->_player, &_miranda, NULL);
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4010 - Village - Outside Lander
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4010::postInit(SceneObjectList *OwnerList) {
+ loadScene(4010);
+ Scene::postInit();
+ setZoomPercents(0, 20, 70, 50);
+
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerMText);
+ _speakerSText._npc = &_hotspot1;
+ _speakerMText._npc = &_hotspot2;
+ _speakerQText._npc = &_globals->_player;
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(-38, 175));
+ _globals->_player.changeZoom(75);
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(2705);
+ _hotspot2.animate(ANIM_MODE_1, NULL);
+ _hotspot2.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot2._moveDiff = Common::Point(4, 2);
+ _hotspot2.setPosition(Common::Point(-50, 185));
+ _hotspot2.changeZoom(75);
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(2806);
+ _hotspot1.setPosition(Common::Point(-20, 175));
+ _hotspot1.changeZoom(75);
+ _hotspot1.animate(ANIM_MODE_1, NULL);
+ _hotspot1.setObjectWrapper(new SceneObjectWrapper());
+
+ _globals->_player.disableControl();
+ setAction(&_sequenceManager, this, 4017, &_globals->_player, &_hotspot1, &_hotspot2, NULL);
+}
+
+void Scene4010::signal() {
+ _globals->_sceneManager.changeScene(4000);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4025 - Village - Puzzle Board
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4025::Action1::signal() {
+ Scene4025 *scene = (Scene4025 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_armHotspot._strip = scene->_pegPtr->_armStrip;
+ scene->_armHotspot._frame = 4;
+ scene->_armHotspot.animate(ANIM_MODE_4, 2, -1, this);
+
+ if (scene->_pegPtr->_armStrip > 3) {
+ if (scene->_hole1._armStrip == scene->_pegPtr->_armStrip)
+ scene->_hole1._pegPtr = NULL;
+ if (scene->_hole2._armStrip == scene->_pegPtr->_armStrip)
+ scene->_hole2._pegPtr = NULL;
+ if (scene->_hole3._armStrip == scene->_pegPtr->_armStrip)
+ scene->_hole3._pegPtr = NULL;
+ if (scene->_hole4._armStrip == scene->_pegPtr->_armStrip)
+ scene->_hole4._pegPtr = NULL;
+ if (scene->_hole5._armStrip == scene->_pegPtr->_armStrip)
+ scene->_hole5._pegPtr = NULL;
+ }
+ break;
+ case 1:
+ scene->_pegPtr->hide();
+
+ if (scene->_pegPtr2) {
+ if (scene->_pegPtr->_armStrip == 3)
+ scene->_pegPtr2->_strip = 2;
+
+ scene->_pegPtr2->setPosition(scene->_pegPtr->_position);
+ scene->_pegPtr2->show();
+ scene->_pegPtr2->_armStrip = scene->_pegPtr->_armStrip;
+ }
+
+ scene->_pegPtr->_armStrip = 0;
+ scene->_pegPtr->setPosition(Common::Point(-10, -10));
+ scene->_pegPtr2 = scene->_pegPtr;
+ scene->_armHotspot.animate(ANIM_MODE_5, this);
+ break;
+
+ case 2:
+ _globals->_player._uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_USE);
+ remove();
+ break;
+ }
+}
+
+void Scene4025::Action2::signal() {
+ Scene4025 *scene = (Scene4025 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_armHotspot._strip = scene->_holePtr->_armStrip;
+ scene->_armHotspot.animate(ANIM_MODE_4, 2, -1, this);
+ break;
+ case 1:
+ if (!scene->_pegPtr2) {
+ // Getting a peg from a hole
+ scene->_holePtr->_pegPtr->hide();
+ scene->_pegPtr = scene->_holePtr->_pegPtr;
+ scene->_pegPtr->_armStrip = 0;
+ scene->_pegPtr->setPosition(Common::Point(-10, -10));
+ scene->_pegPtr2 = scene->_holePtr->_pegPtr;
+ scene->_holePtr->_pegPtr = NULL;
+ } else {
+ // Placing a peg into a hole
+ scene->_pegPtr2 = NULL;
+ if (scene->_holePtr->_pegPtr) {
+ scene->_holePtr->_pegPtr->hide();
+ scene->_pegPtr2 = scene->_holePtr->_pegPtr;
+ }
+
+ assert(scene->_pegPtr);
+ scene->_pegPtr->setPosition(scene->_holePtr->_newPosition);
+ scene->_pegPtr->setStrip(1);
+ scene->_pegPtr->show();
+ scene->_pegPtr->_armStrip = scene->_holePtr->_armStrip;
+
+ scene->_holePtr->_pegPtr = scene->_pegPtr;
+ scene->_pegPtr = scene->_pegPtr2;
+ }
+ scene->_armHotspot.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ _globals->_player._uiEnabled = true;
+ _globals->_events.setCursor(CURSOR_USE);
+ remove();
+ break;
+ }
+}
+
+void Scene4025::Action3::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ _globals->_scenePalette.addRotation(64, 111, -1);
+ setDelay(120);
+ break;
+ case 1:
+ _globals->clearFlag(34);
+ _globals->_stripNum = 4025;
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4025::Hole::synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+ SYNC_POINTER(_pegPtr);
+ s.syncAsSint16LE(_armStrip);
+ s.syncAsSint16LE(_newPosition.x);
+ s.syncAsSint16LE(_newPosition.y);
+}
+
+void Scene4025::Hole::doAction(int action) {
+ Scene4025 *scene = (Scene4025 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4025, 3);
+ break;
+ case CURSOR_USE:
+ if (!scene->_pegPtr && !_pegPtr) {
+ setAction(&scene->_sequenceManager, scene, 4028, NULL);
+ } else {
+ _globals->_player.disableControl();
+ scene->_holePtr = this;
+ scene->setAction(&scene->_action2);
+ }
+ break;
+ case OBJECT_PEG:
+ if (!scene->_pegPtr2) {
+ _globals->_player.disableControl();
+ _globals->_events.setCursor(CURSOR_USE);
+ RING_INVENTORY._peg._sceneNumber = 4025;
+
+ scene->_pegPtr = &scene->_peg5;
+ scene->_holePtr = this;
+ scene->_pegPtr->_armStrip = 0;
+ scene->_pegPtr2 = scene->_pegPtr;
+
+ scene->setAction(&scene->_action2);
+ } else {
+ scene->_sceneMode = 4027;
+ scene->setAction(&scene->_sequenceManager, scene, 4027, NULL);
+ }
+ break;
+ }
+}
+
+void Scene4025::Peg::synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+ s.syncAsSint16LE(_field88);
+ SYNC_POINTER(_armStrip);
+}
+
+void Scene4025::Peg::doAction(int action) {
+ Scene4025 *scene = (Scene4025 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4025, 1);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->_pegPtr = this;
+ scene->setAction(&scene->_action1);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene4025::Scene4025() : Scene() {
+ _holePtr = NULL;
+ _pegPtr = _pegPtr2 = NULL;
+}
+
+void Scene4025::postInit(SceneObjectList *OwnerList) {
+ loadScene(4025);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _globals->_events.setCursor(CURSOR_USE);
+ _pegPtr = _pegPtr2 = NULL;
+
+ _peg1.postInit();
+ _peg1._field88 = 1;
+ _peg1.setVisage(4025);
+ _peg1.setStrip(2);
+ _peg1.setFrame(1);
+ _peg1.setPosition(Common::Point(203, 61));
+
+ _peg2.postInit();
+ _peg2._field88 = 4;
+ _peg2.setVisage(4025);
+ _peg2.setStrip(2);
+ _peg2.setFrame(2);
+ _peg2.setPosition(Common::Point(195, 57));
+
+ _peg3.postInit();
+ _peg3._field88 = 0;
+ _peg3.setVisage(4025);
+ _peg3.setStrip(2);
+ _peg3.setFrame(3);
+ _peg3.setPosition(Common::Point(202, 66));
+
+ _peg4.postInit();
+ _peg4._field88 = 3;
+ _peg4.setVisage(4025);
+ _peg4.setStrip(2);
+ _peg4.setFrame(4);
+ _peg4.setPosition(Common::Point(194, 68));
+
+ _peg5.postInit();
+ _peg5._field88 = 2;
+ _peg5.setVisage(4025);
+ _peg5.setStrip(1);
+ _peg5.setFrame(5);
+ _peg5.hide();
+
+ // Hole N-W
+ _hole1.postInit();
+ _hole1.setVisage(4025);
+ _hole1.setStrip(1);
+ _hole1.setFrame2(6);
+ _hole1.setPosition(Common::Point(123, 51));
+ _hole1._pegPtr = NULL;
+ _hole1._newPosition = Common::Point(123, 44);
+ _hole1._armStrip = 8;
+
+ // Hole N-E
+ _hole2.postInit();
+ _hole2.setVisage(4025);
+ _hole2.setStrip(1);
+ _hole2.setFrame2(7);
+ _hole2.setPosition(Common::Point(167, 51));
+ _hole2._pegPtr = NULL;
+ _hole2._newPosition = Common::Point(166, 44);
+ _hole2._armStrip = 7;
+
+ // Hole Center
+ _hole3.postInit();
+ _hole3.setVisage(4025);
+ _hole3.setStrip(1);
+ _hole3.setFrame2(8);
+ _hole3.setPosition(Common::Point(145, 69));
+ _hole3._pegPtr = NULL;
+ _hole3._newPosition = Common::Point(145, 60);
+ _hole3._armStrip = 6;
+
+ // Hole S-W
+ _hole4.postInit();
+ _hole4.setVisage(4025);
+ _hole4.setStrip(1);
+ _hole4.setFrame2(9);
+ _hole4.setPosition(Common::Point(123, 87));
+ _hole4._pegPtr = NULL;
+ _hole4._newPosition = Common::Point(123, 80);
+ _hole4._armStrip = 5;
+
+ // Hole S-E
+ _hole5.postInit();
+ _hole5.setVisage(4025);
+ _hole5.setStrip(1);
+ _hole5.setFrame2(10);
+ _hole5.setPosition(Common::Point(167, 87));
+ _hole5._pegPtr = NULL;
+ _hole5._newPosition = Common::Point(166, 80);
+ _hole5._armStrip = 4;
+
+ _hole1.fixPriority(1);
+ _hole2.fixPriority(1);
+ _hole3.fixPriority(1);
+ _hole4.fixPriority(1);
+ _hole5.fixPriority(1);
+
+ _armHotspot.postInit();
+ _armHotspot.setVisage(4025);
+ _armHotspot.setPosition(Common::Point(190, 161));
+ _armHotspot.setStrip(3);
+ _armHotspot.setFrame(4);
+
+ _globals->_sceneItems.addItems(&_hole1, &_hole2, &_hole3, &_hole4, &_hole5,
+ &_peg1, &_peg2, &_peg3, &_peg4, &_peg5, NULL);
+
+ _globals->_player._uiEnabled = true;
+ _globals->_player.disableControl();
+ setAction(&_sequenceManager, this, 4026, NULL);
+}
+
+void Scene4025::synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ SYNC_POINTER(_pegPtr);
+ SYNC_POINTER(_pegPtr2);
+ SYNC_POINTER(_holePtr);
+}
+
+void Scene4025::remove() {
+ _globals->_scenePalette.clearListeners();
+ Scene::remove();
+}
+
+void Scene4025::signal() {
+ if (_sceneMode != 4027) {
+ if (_sceneMode != 4028) {
+ _gfxButton.setText(EXIT_MSG);
+ _gfxButton._bounds.center(144, 107);
+ _gfxButton.draw();
+ _gfxButton._bounds.expandPanes();
+ }
+
+ _globals->_player._uiEnabled = true;
+ }
+
+ _globals->_events.setCursor(CURSOR_USE);
+}
+
+void Scene4025::process(Event &event) {
+ Scene::process(event);
+
+ if (_gfxButton.process(event)) {
+ if (RING_INVENTORY._peg._sceneNumber == 4025)
+ RING_INVENTORY._peg._sceneNumber = 1;
+
+ _globals->_sceneManager.changeScene(4000);
+ }
+}
+
+void Scene4025::dispatch() {
+ if (!_action && (_peg1._armStrip == 7) && (_peg2._armStrip == 4) && (_peg3._armStrip == 8) &&
+ (_peg4._armStrip == 5) && (_peg5._armStrip == 6))
+ setAction(&_action3);
+
+ Scene::dispatch();
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4045 - Village - Temple Antechamber
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4045::Action1::signal() {
+ Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(60);
+ break;
+ case 1:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(4040, this, scene);
+ break;
+ case 2:
+ scene->_olloFace.animate(ANIM_MODE_NONE, NULL);
+ scene->_hotspot4.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ setDelay(60);
+ break;
+ case 4:
+ scene->_hotspot4.animate(ANIM_MODE_6, this);
+ break;
+ case 5:
+ ADD_MOVER(_globals->_player, 150, 300);
+ break;
+ case 6:
+ _globals->_stripNum = 4000;
+ _globals->_sceneManager.changeScene(4000);
+ remove();
+ break;
+ }
+}
+
+void Scene4045::Action2::signal() {
+ Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(15);
+ break;
+ case 1:
+ scene->_stripManager.start(_globals->_stripNum, this, scene);
+ break;
+ case 2:
+ scene->_olloFace.animate(ANIM_MODE_NONE, NULL);
+ setDelay(10);
+ break;
+ case 3:
+ if (_globals->getFlag(38)) {
+ _globals->_player.enableControl();
+ remove();
+ } else {
+ ADD_MOVER(_globals->_player, 150, 300);
+ }
+ break;
+ case 4:
+ _globals->setFlag(39);
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ }
+}
+
+void Scene4045::Action3::signal() {
+ Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ scene->_hotspot4.animate(ANIM_MODE_5, this);
+ break;
+ case 1:
+ scene->_stripManager.start(4504, this, scene);
+ break;
+ case 2:
+ scene->_hotspot4.animate(ANIM_MODE_6, NULL);
+ scene->_olloFace.animate(ANIM_MODE_NONE, NULL);
+ ADD_MOVER(_globals->_player, 91, 1264);
+ break;
+ case 3:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4045::OlloStand::doAction(int action) {
+ Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(4045, 19);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(4045, (_strip == 1) ? 5 : 14);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(4045, 18);
+ break;
+ case CURSOR_TALK:
+ if (_strip == 5) {
+ setStrip(6);
+ animate(ANIM_MODE_NONE, 0);
+ }
+ if (_globals->_player._position.y < 135) {
+ scene->_sceneMode = 4046;
+ _numFrames = 10;
+ _globals->_player.disableControl();
+
+ scene->setAction(&scene->_sequenceManager, this, 4046, &_globals->_player, this, NULL);
+ } else {
+ if (!_globals->getFlag(31)) {
+ _globals->setFlag(31);
+ _globals->_stripNum = 4080;
+ } else if (!_globals->getFlag(38))
+ _globals->_stripNum = 4060;
+ else
+ _globals->_stripNum = 4503;
+
+ scene->setAction(&scene->_action2);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4045::Miranda::doAction(int action) {
+ Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4045, 9);
+ break;
+ case CURSOR_TALK:
+ scene->_sceneMode = 4102;
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_sequenceManager, scene, 4104, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4045::Necklace::doAction(int action) {
+ Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4045, 17);
+ break;
+ case CURSOR_USE:
+ if (_globals->_player._position.y < 135) {
+ SceneItem::display2(4045, 16);
+ RING_INVENTORY._peg._sceneNumber = 1;
+ _globals->_events.setCursor(CURSOR_WALK);
+ remove();
+ } else {
+ scene->_sceneMode = 4047;
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_sequenceManager, scene, 4047, &_globals->_player, &scene->_olloStand, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene4045::Scene4045() :
+ _flame(0, CURSOR_LOOK, 4045, 1, CURSOR_USE, 4100, 21, LIST_END),
+ _hotspot7(9, CURSOR_LOOK, 4045, 0, CURSOR_USE, 4045, 15, LIST_END),
+ _hotspot8(10, CURSOR_LOOK, 4045, 2, LIST_END),
+ _hotspot9(11, CURSOR_LOOK, 4045, 3, CURSOR_USE, 4045, 15, LIST_END),
+ _hotspot10(12, CURSOR_LOOK, 4045, 4, CURSOR_USE, 4045, 19, LIST_END),
+ _hotspot11(13, CURSOR_LOOK, 4045, 6, CURSOR_USE, 4045, 15, LIST_END),
+ _hotspot12(14, CURSOR_LOOK, 4045, 7, CURSOR_USE, 4045, 29, LIST_END),
+ _hotspot13(15, CURSOR_LOOK, 4045, 8, CURSOR_USE, 4045, 19, LIST_END),
+ _hotspot14(0, CURSOR_LOOK, 4045, 10, LIST_END) {
+
+ _hotspot14.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+}
+
+void Scene4045::postInit(SceneObjectList *OwnerList) {
+ loadScene(4045);
+ Scene::postInit();
+ setZoomPercents(100, 60, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerML);
+ _stripManager.addSpeaker(&_speakerPR);
+ _stripManager.addSpeaker(&_speakerPText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.setCallback(this);
+
+ _speakerQText._textPos.y = 140;
+
+ _flame.postInit();
+ _flame.setVisage(4045);
+ _flame.setPosition(Common::Point(47, 111));
+ _flame.animate(ANIM_MODE_2, NULL);
+ _flame.fixPriority(156);
+ _globals->_sceneItems.push_back(&_flame);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(4200);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player._moveDiff = Common::Point(7, 4);
+
+ _olloStand.postInit();
+ _olloStand.setVisage(4051);
+
+ _olloFace.postInit();
+ _olloFace.setVisage(4051);
+ _olloFace.setStrip(4);
+ _olloFace.fixPriority(152);
+
+ if(_globals->_sceneManager._previousScene == 4050) {
+ _globals->_soundHandler.startSound(155);
+ _globals->_player.setPosition(Common::Point(72, 128));
+ _globals->_player.enableControl();
+
+ _olloStand.setStrip(5);
+ _olloStand.setPosition(Common::Point(173, 99));
+ _olloStand._numFrames = 1;
+ _olloStand.animate(ANIM_MODE_2, NULL);
+
+ _olloFace.setPosition(Common::Point(177, 40));
+
+ if (RING_INVENTORY._peg._sceneNumber == 4045) {
+ _necklace.postInit();
+ _necklace.setVisage(4045);
+ _necklace.setStrip(2);
+ _necklace.setPosition(Common::Point(108, 82));
+ _globals->_sceneItems.push_back(&_necklace);
+ }
+ } else {
+ _globals->_player.setPosition(Common::Point(108, 192));
+ _globals->_player.setStrip(4);
+
+ if (!_globals->getFlag(36) && !_globals->getFlag(43)) {
+ _miranda.postInit();
+ _miranda.setVisage(4102);
+ _miranda.animate(ANIM_MODE_NONE, NULL);
+ _miranda.setStrip(3);
+ _miranda.setFrame(2);
+ _miranda.changeZoom(-1);
+
+ _miranda.setPosition(Common::Point(66, 209));
+ _globals->_sceneItems.push_back(&_miranda);
+ }
+
+ if (_globals->getFlag(31)) {
+ // Olo asleep
+ _olloStand.setVisage(4051);
+ _olloStand.setStrip(5);
+ _olloStand.setPosition(Common::Point(173, 99));
+ _olloStand._numFrames = 1;
+ _olloStand.animate(ANIM_MODE_2, NULL);
+
+ _olloFace.setPosition(Common::Point(177, 40));
+
+ if (RING_INVENTORY._peg._sceneNumber == 4045) {
+ _necklace.postInit();
+ _necklace.setVisage(4045);
+ _necklace.setStrip(2);
+ _necklace.setPosition(Common::Point(108, 82));
+ _globals->_sceneItems.push_back(&_necklace);
+ }
+ } else {
+ _olloStand.setPosition(Common::Point(186, 149));
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(4051);
+ _hotspot4.setStrip(2);
+ _hotspot4.fixPriority(152);
+ _hotspot4.setPosition(Common::Point(202, 80));
+
+ _olloFace.setPosition(Common::Point(192, 77));
+ _globals->setFlag(31);
+ setAction(&_action1);
+
+ _globals->_player.disableControl();
+ }
+ }
+
+ _globals->_sceneItems.addItems(&_olloStand, &_hotspot7, &_hotspot8, &_hotspot9, &_hotspot10,
+ &_hotspot13, &_hotspot11, &_hotspot12, &_hotspot14, NULL);
+}
+
+void Scene4045::stripCallback(int v) {
+ switch (v) {
+ case 1:
+ _olloFace.animate(ANIM_MODE_7, 0, NULL);
+ break;
+ case 2:
+ _olloFace.animate(ANIM_MODE_NONE, NULL);
+ break;
+ }
+}
+
+void Scene4045::signal() {
+ switch (_sceneMode) {
+ case 4046:
+ case 4047:
+ _olloFace.animate(ANIM_MODE_NONE, NULL);
+ break;
+ case 4050:
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ case 4102:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene4045::dispatch() {
+ if (!_action) {
+ if (_globals->_player.getRegionIndex() == 8) {
+ _globals->_player.addMover(NULL);
+ if (_olloStand._strip != 1) {
+ _globals->_player.disableControl();
+ _sceneMode = 4046;
+ _olloStand._numFrames = 10;
+ setAction(&_sequenceManager, this, 4046, &_globals->_player, &_olloStand, NULL);
+ } else {
+ setAction(&_action3);
+ }
+ }
+
+ if (_globals->_player.getRegionIndex() == 10)
+ _globals->_sceneManager.changeScene(4050);
+ if (_globals->_player._position.y >= 196) {
+ _sceneMode = 4050;
+ _globals->_player.disableControl();
+ setAction(&_sequenceManager, this, 4105, &_globals->_player, NULL);
+ }
+ }
+
+ Scene::dispatch();
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4000 - Village - Temple
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4050::Action1::signal() {
+ // "Map" on the wall
+ Scene4050 *scene = (Scene4050 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1: {
+ Common::Point pt(204, 152);
+ PlayerMover *mover = new PlayerMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _globals->_player.checkAngle(&scene->_hotspot17);
+
+ scene->_hotspot14.postInit();
+ scene->_hotspot14.setVisage(4050);
+ scene->_hotspot14.setStrip(2);
+ scene->_hotspot14.setPosition(Common::Point(91, 154));
+ scene->_hotspot14.fixPriority(200);
+ setDelay(10);
+ break;
+ case 3:
+ _globals->_events.waitForPress();
+ _globals->setFlag(45);
+ scene->_hotspot14.remove();
+
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4050::Action2::signal() {
+ // Climb down the rope
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(120);
+ break;
+ case 1:
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ _globals->_player.setVisage(4202);
+ _globals->_player.changeZoom(100);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(192, 130));
+
+ ADD_MOVER(_globals->_player, 215, 130);
+ break;
+ case 3:
+ _globals->_player.setVisage(4052);
+ _globals->_player.setStrip(5);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(236, 130));
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 4:
+ _globals->_player.setVisage(4202);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setPosition(Common::Point(210, 185));
+ _globals->_player.fixPriority(-1);
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4050::Action3::signal() {
+ // Climb up the rope
+ switch (_actionIndex++) {
+ case 0:
+ ADD_PLAYER_MOVER(210, 185);
+ break;
+ case 1:
+ _globals->_player.fixPriority(200);
+ _globals->_player.setVisage(4052);
+ _globals->_player.setStrip(5);
+ _globals->_player.changeZoom(100);
+ _globals->_player.setFrame(_globals->_player.getFrameCount());
+ _globals->_player.setPosition(Common::Point(236, 130));
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 2:
+ _globals->_player.setVisage(4202);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(215, 130));
+ ADD_MOVER(_globals->_player, 212, 130);
+ break;
+ case 3:
+ _globals->_stripNum = 4050;
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ }
+}
+
+void Scene4050::Action4::signal() {
+ Scene4050 *scene = (Scene4050 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ ADD_MOVER(_globals->_player, 189, 135);
+ _globals->_player.fixPriority(200);
+ break;
+ case 1:
+ _globals->_player._moveDiff.y = 3;
+ _globals->_player.setStrip2(3);
+ _globals->_player._frame = 1;
+ _globals->_player.setPosition(Common::Point(189, 129));
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ _globals->_player.setVisage(4202);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(192, 130));
+ _globals->_player.changeZoom(100);
+ ADD_MOVER(_globals->_player, 215, 130);
+
+ scene->_hotspot16.postInit();
+ scene->_hotspot16.setVisage(4052);
+ scene->_hotspot16.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot16.setStrip2(6);
+ scene->_hotspot16.setPosition(Common::Point(160, 240));
+ ADD_MOVER(scene->_hotspot16, 172, 188);
+ break;
+ case 3:
+ _globals->_player.setVisage(4052);
+ _globals->_player.setStrip(5);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(238, 130));
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 4:
+ _globals->_player.setVisage(4052);
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(216, 184));
+ _globals->_player.fixPriority(-1);
+ break;
+ case 5:
+ scene->_hotspot16.setStrip2(4);
+ scene->_hotspot16.setFrame(1);
+ scene->_hotspot16.animate(ANIM_MODE_4, 4, 1, this);;
+ break;
+ case 6:
+ scene->_hotspot16.animate(ANIM_MODE_5, NULL);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 7:
+ _globals->_player.setVisage(4202);
+ _globals->_player.setStrip(6);
+ _globals->_player.setFrame(1);
+
+ scene->_stripManager.start(4051, this);
+ break;
+ case 8:
+ setDelay(15);
+ break;
+ case 9:
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4050::Hotspot15::doAction(int action) {
+ Scene4050 *scene = (Scene4050 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4050, 14);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ setAction(&scene->_action3);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4050::Hotspot17::doAction(int action) {
+ Scene4050 *scene = (Scene4050 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ scene->setAction(&scene->_action1);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(4050, 24);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene4050::Scene4050() :
+ _hotspot1(0, CURSOR_LOOK, 4050, 0, LIST_END),
+ _hotspot2(0, CURSOR_LOOK, 4050, 1, CURSOR_USE, 4050, 15, LIST_END),
+ _hotspot3(0, CURSOR_LOOK, 4050, 2, CURSOR_USE, 4050, 16, LIST_END),
+ _hotspot4(0, CURSOR_LOOK, 4050, 4, LIST_END),
+ _hotspot5(0, CURSOR_LOOK, 4050, 5, LIST_END),
+ _hotspot6(0, CURSOR_LOOK, 4050, 5, LIST_END),
+ _hotspot7(0, CURSOR_LOOK, 4050, 6, CURSOR_USE, 4050, 18, LIST_END),
+ _hotspot8(0, CURSOR_LOOK, 4050, 7, CURSOR_USE, 4050, 19, LIST_END),
+ _hotspot9(0, CURSOR_LOOK, 4050, 8, CURSOR_USE, 4050, 20, LIST_END),
+ _hotspot10(0, CURSOR_LOOK, 4050, 9, CURSOR_USE, 4050, 21, LIST_END),
+ _hotspot11(0, CURSOR_LOOK, 4050, 10, CURSOR_USE, 4050, 22, LIST_END),
+ _hotspot12(0, CURSOR_LOOK, 4050, 11, CURSOR_USE, 4050, 23, LIST_END),
+ _hotspot13(0, CURSOR_LOOK, 4050, 3, CURSOR_USE, 4050, 17, LIST_END) {
+}
+
+void Scene4050::postInit(SceneObjectList *OwnerList) {
+ loadScene(4050);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerPText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerGameText);
+
+ _globals->_player.postInit();
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 4000:
+ if (_globals->getFlag(41)) {
+ // Using a rope
+ _hotspot15.postInit();
+ _hotspot15.setVisage(4054);
+ _hotspot15.setPosition(Common::Point(206, 103));
+ _globals->_sceneItems.push_back(&_hotspot15);
+
+ _globals->_player.setVisage(4008);
+ _globals->_player.setPosition(Common::Point(206, 62));
+ _globals->_player.changeZoom(130);
+ _globals->_player.fixPriority(200);
+ _globals->_player.setStrip(2);
+
+ setAction(&_action2);
+ _globals->_soundHandler.startSound(175);
+ } else {
+ // Without the rope
+ _globals->_player.setVisage(5315);
+ _globals->_player.setPosition(Common::Point(189, 83));
+ _globals->_player.changeZoom(130);
+ _globals->_player.setStrip2(2);
+ _globals->_player._moveDiff.y = 10;
+ _globals->_player.animate(ANIM_MODE_2, NULL);
+
+ setAction(&_action4);
+ _globals->_soundHandler.startSound(176);
+ }
+ break;
+ case 4045:
+ _hotspot15.postInit();
+ _hotspot15.setVisage(4054);
+ _hotspot15.setPosition(Common::Point(206, 103));
+ _globals->_sceneItems.push_back(&_hotspot15);
+
+ _globals->_player.setVisage(4202);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(193, 193));
+
+ _globals->_soundHandler.startSound(175);
+ break;
+ default:
+ break;
+ }
+
+ _hotspot13.postInit();
+ _hotspot13.setVisage(4053);
+ _hotspot13.animate(ANIM_MODE_2, NULL);
+ _hotspot13.setPosition(Common::Point(190, 97));
+
+ _hotspot17.postInit();
+ _hotspot17.setVisage(4050);
+ _hotspot17.setPosition(Common::Point(209, 119));
+ _hotspot17.fixPriority(2);
+
+ _hotspot1.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot2.setBounds(Rect(150, 25, 198, 125));
+ _hotspot3.setBounds(Rect(56, 94, 88, 153));
+ _hotspot4.setBounds(Rect(170, 7, 209, 18));
+ _hotspot5.setBounds(Rect(190, 72, 212, 92));
+ _hotspot6.setBounds(Rect(122, 75, 145, 93));
+ _hotspot7.setBounds(Rect(109, 103, 263, 158));
+ _hotspot8.setBounds(Rect(157, 160, 213, 173));
+ _hotspot9.setBounds(Rect(95, 157, 120, 178));
+ _hotspot10.setBounds(Rect(278, 43, 310, 115));
+ _hotspot11.setBounds(Rect(263, 105, 279, 147));
+ _hotspot12.setBounds(Rect(258, 154, 307, 180));
+
+ _globals->_sceneItems.addItems(&_hotspot17, &_hotspot12, &_hotspot11, &_hotspot10, &_hotspot13,
+ &_hotspot2, &_hotspot3, &_hotspot4, &_hotspot5, &_hotspot6, &_hotspot8, &_hotspot9,
+ &_hotspot7, &_hotspot1, NULL);
+}
+
+void Scene4050::signal() {
+ if (_sceneMode == 4050)
+ _globals->_sceneManager.changeScene(4045);
+}
+
+void Scene4050::dispatch() {
+ if (!_action) {
+ if ((_globals->_player._canWalk) && (_globals->_player._position.y > 196)) {
+ _sceneMode = 4050;
+ _globals->_player.disableControl();
+
+ Common::Point pt(160, 275);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ }
+ }
+ Scene::dispatch();
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4100 - Village - Hut
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4100::Action1::signal() {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(10);
+ break;
+ case 1:
+ scene->_stripManager.start(_globals->_stripNum, this);
+ break;
+ case 2:
+ setDelay(30);
+ break;
+ case 3:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4100::Action2::signal() {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_hotspot2.postInit();
+ scene->_hotspot2.changeZoom(95);
+ scene->_hotspot2.setVisage(4120);
+ scene->_hotspot2.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot2.setStrip2(4);
+ scene->_hotspot2.fixPriority(100);
+ scene->_hotspot2.setPosition(Common::Point(214, 119));
+
+ setDelay(3);
+ break;
+ case 1:
+ ADD_MOVER(scene->_hotspot2, 249, 131);
+ break;
+ case 2:
+ scene->_hotspot2.setStrip2(3);
+ scene->_hotspot2.setFrame2(5);
+ scene->_hotspot2.animate(ANIM_MODE_NONE, NULL);
+ setDelay(3);
+ break;
+ case 3:
+ remove();
+ break;
+ }
+}
+
+
+void Scene4100::Action3::signal() {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->clearFlag(43);
+ _globals->setFlag(36);
+ setDelay(15);
+ break;
+ case 1:
+ scene->_stripManager.start(4505, this);
+ break;
+ case 2:
+ setAction(&scene->_action2, this);
+ break;
+ case 3:
+ scene->_stripManager.start(4510, this);
+ break;
+ case 4:
+ setDelay(15);
+ break;
+ case 5:
+ _globals->_sceneManager.changeScene(4150);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene4100::Action4::signal() {
+ // Rock getting drunk
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ scene->_hotspot1.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ scene->_hotspot1.setVisage(4105);
+ scene->_hotspot1.setFrame(1);
+ scene->_hotspot1.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ _globals->clearFlag(43);
+ _globals->setFlag(42);
+ scene->_stripManager.start(4119, this);
+ break;
+ case 4:
+ setDelay(15);
+ break;
+ case 5:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4100::Action5::signal() {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ ADD_PLAYER_MOVER(58, 151);
+ break;
+ case 1:
+ if (RING_INVENTORY._ladder._sceneNumber == 4100) {
+ RING_INVENTORY._ladder._sceneNumber = 1;
+ scene->_ladder.remove();
+ } else {
+ scene->_ladder.postInit();
+ scene->_ladder.setVisage(4101);
+ scene->_ladder.setPosition(Common::Point(49, 144));
+
+ RING_INVENTORY._ladder._sceneNumber = 4100;
+ _globals->_sceneItems.push_front(&scene->_ladder);
+ }
+
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+
+void Scene4100::Action6::signal() {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ scene->_stripManager.start(4103, this);
+ ADD_PLAYER_MOVER(245, 167);
+ break;
+ case 1:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4100::Hotspot1::doAction(int action) {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_STUNNER:
+ SceneItem::display2(4100, 16);
+ break;
+ case OBJECT_ALE:
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action3);
+ break;
+ case CURSOR_LOOK:
+ SceneItem::display2(4100, _globals->getFlag(42) ? 24 : 12);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(4100, 22);
+ break;
+ case CURSOR_TALK:
+ if (RING_INVENTORY._peg._sceneNumber == 1) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 4109;
+ scene->setAction(&scene->_sequenceManager, scene, 4109, NULL);
+ } else if (_globals->getFlag(42)) {
+ scene->_sceneMode = 4102;
+ scene->setAction(&scene->_sequenceManager, scene, 4102, NULL);
+ } else {
+ if (_globals->getFlag(33))
+ _globals->_stripNum = 4077;
+ else if (_globals->getFlag(82)) {
+ _globals->clearFlag(82);
+ _globals->_stripNum = 4100;
+ } else {
+ _globals->_stripNum = 4075;
+ _globals->setFlag(33);
+ }
+
+ scene->setAction(&scene->_action1);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4100::Hotspot2::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ error("*** The Chief's daughter... WOW!");
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4100::Miranda::doAction(int action) {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4100, 14);
+ break;
+ case CURSOR_TALK:
+ scene->_sceneMode = 4102;
+ scene->setAction(&scene->_sequenceManager, scene, 4104, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4100::Ladder::doAction(int action) {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4100, 2);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(42)) {
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action5);
+ } else {
+ scene->_sceneMode = 4102;
+ scene->setAction(&scene->_sequenceManager, scene, 4103, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/**
+ Exit hotspot, South
+ */
+void Scene4100::Hotspot14::doAction(int action) {
+ Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4100, 0);
+ break;
+ case OBJECT_LADDER:
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action5);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+Scene4100::Scene4100() :
+ _hotspot3(0, CURSOR_LOOK, 4100, 10, CURSOR_USE, 4100, 21, LIST_END),
+ _hotspot4(0, CURSOR_LOOK, 4100, 8, LIST_END),
+ _hotspot7(0, CURSOR_USE, 4100, 3, CURSOR_USE, 4150, 29, LIST_END),
+ _hotspot8(0, CURSOR_LOOK, 4100, 5, LIST_END),
+ _hotspot9(0, CURSOR_LOOK, 4100, 6, CURSOR_USE, 4100, 20, LIST_END),
+ _hotspot10(0, CURSOR_LOOK, 4100, 7, CURSOR_USE, 4100, 19, LIST_END),
+ _hotspot11(0, CURSOR_LOOK, 4100, 8, CURSOR_USE, 4100, 18, LIST_END),
+ _hotspot12(0, CURSOR_LOOK, 4100, 9, LIST_END),
+ _hotspot13(0, CURSOR_LOOK, 4100, 11, CURSOR_USE, 4100, 17, LIST_END) {
+}
+
+void Scene4100::postInit(SceneObjectList *OwnerList) {
+ loadScene(4100);
+ Scene::postInit();
+ setZoomPercents(135, 80, 190, 100);
+
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerCHFText);
+ _stripManager.addSpeaker(&_speakerCDRText);
+ _stripManager.addSpeaker(&_speakerCDR);
+ _stripManager.addSpeaker(&_speakerML);
+ _stripManager.addSpeaker(&_speakerQR);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(4200);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip(4);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(88, 180));
+ _globals->_player._moveDiff = Common::Point(7, 4);
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(4102);
+ _hotspot1.fixPriority(129);
+ _hotspot1.setPosition(Common::Point(171, 120));
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(4130);
+ _hotspot3.animate(ANIM_MODE_2, NULL);
+ _hotspot3.fixPriority(200);
+ _hotspot3.setPosition(Common::Point(272, 110));
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(4130);
+ _hotspot4.animate(ANIM_MODE_2, NULL);
+ _hotspot4.setStrip2(2);
+ _hotspot4.setPosition(Common::Point(152, 167));
+
+ if (_globals->getFlag(36)) {
+ _hotspot1.setVisage(4105);
+ _hotspot1.setStrip(1);
+ _hotspot1.setFrame(4);
+ } else if (!_globals->getFlag(43)) {
+ _miranda.postInit();
+ _miranda.setVisage(4102);
+ _miranda.setStrip2(3);
+ _miranda.setFrame(2);
+ _miranda.setPosition(Common::Point(65, 188));
+
+ _globals->_sceneItems.push_back(&_miranda);
+ }
+
+ if (RING_INVENTORY._ladder._sceneNumber == 4100) {
+ _ladder.postInit();
+ _ladder.setVisage(4101);
+ _ladder.setPosition(Common::Point(49, 144));
+
+ _globals->_sceneItems.push_back(&_ladder);
+ }
+
+ _hotspot14.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot7._sceneRegionId = 16;
+ _hotspot8.setBounds(Rect(90, 0, 211, 113));
+ _hotspot9.setBounds(Rect(207, 96, 235, 115));
+ _hotspot10.setBounds(Rect(87, 81, 212, 107));
+ _hotspot11.setBounds(Rect(61, 148, 243, 168));
+ _hotspot12.setBounds(Rect(229, 59, 256, 122));
+ _hotspot13.setBounds(Rect(255, 152, 286, 183));
+
+ _globals->_sceneItems.addItems(&_hotspot3, &_hotspot1, &_hotspot13, &_hotspot12, &_hotspot4,
+ &_hotspot11, &_hotspot9, &_hotspot7, &_hotspot10, &_hotspot8, &_hotspot14, NULL);
+
+ if (_globals->_sceneManager._previousScene == 4150) {
+ _globals->_soundHandler.startSound(155);
+
+ if (!_globals->getFlag(42)) {
+ _hotspot1.setVisage(4104);
+ _hotspot1.setPosition(Common::Point(152, 118));
+ _hotspot1.setStrip2(-1);
+ _hotspot1.setFrame2(-1);
+ _hotspot1.setFrame(1);
+
+ _globals->_player.setStrip(2);
+ _globals->_player.disableControl();
+ setAction(&_action4);
+
+ _globals->clearFlag(43);
+ }
+
+ _globals->_player.setPosition(Common::Point(252, 139));
+ _globals->_player.setStrip(2);
+ } else {
+ if ((RING_INVENTORY._ale._sceneNumber == 4100) && !_globals->getFlag(42)) {
+ _globals->_player.disableControl();
+ setAction(&_action3);
+ }
+ if (_globals->getFlag(35)) {
+ _globals->_player.disableControl();
+ _sceneMode = 4101;
+ setAction(&_sequenceManager, this, 4101, &_globals->_player, NULL);
+ }
+ }
+}
+
+void Scene4100::signal() {
+ switch (_sceneMode) {
+ case 4101:
+ _globals->_sceneManager.changeScene(4000);
+ break;
+ case 4102:
+ case 4103:
+ case 4109:
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene4100::dispatch() {
+ if (!_action) {
+ if ((_globals->_player.getRegionIndex() == 15) && !_globals->getFlag(42))
+ setAction(&_action6);
+
+ if (_globals->_player.getRegionIndex() == 8)
+ _globals->_sceneManager.changeScene(4150);
+
+ if (_globals->_player._position.y >= 196) {
+ _globals->_player.disableControl();
+ _sceneMode = 4101;
+ setAction(&_sequenceManager, this, 4105, &_globals->_player, NULL);
+ }
+ }
+
+ Scene::dispatch();
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4150 - Village - Bedroom
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4150::Action1::signal() {
+ Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene;
+ byte adjustData[4] = {0, 0, 0, 0};
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1:
+ scene->_stripManager.start(4520, this);
+ break;
+ case 2:
+ setDelay(15);
+ break;
+ case 3:
+ setAction(&scene->_action2, this);
+ break;
+ case 4: {
+ for (int idx = 100; idx >= 0; idx -= 5) {
+ _globals->_scenePalette.fade(adjustData, false, idx);
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+
+ scene->_hotspot4.postInit();
+ scene->_hotspot4.setVisage(4150);
+ scene->_hotspot4.setStrip(2);
+ scene->_hotspot4.setPosition(Common::Point(166, 157));
+
+ scene->_hotspot1.postInit();
+ scene->_hotspot1.setVisage(4156);
+ scene->_hotspot1.setStrip(1);
+ scene->_hotspot1.setFrame(1);
+
+ setDelay(120);
+ break;
+ }
+ case 5:
+ _globals->_scenePalette.loadPalette(4150);
+ _globals->_scenePalette.refresh();
+ setDelay(60);
+ break;
+ case 6:
+ scene->_stripManager.start(4522, this);
+ break;
+ case 7:
+ for (int idx = 100; idx >= 0; idx -= 5) {
+ _globals->_scenePalette.fade(adjustData, false, idx);
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+
+ scene->_hotspot4.remove();
+ scene->_hotspot1.setVisage(4157);
+ scene->_hotspot1.animate(ANIM_MODE_NONE, NULL);
+ scene->_hotspot1.setStrip(1);
+ scene->_hotspot1.setFrame(1);
+ scene->_hotspot1.show();
+
+ _globals->_player.setVisage(4200);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip(3);
+ _globals->_player.setPosition(Common::Point(139, 166));
+ _globals->_player._moveDiff = Common::Point(7, 3);
+ _globals->_player.show();
+
+ setDelay(120);
+ break;
+ case 8:
+ _globals->_scenePalette.loadPalette(4150);
+ _globals->_scenePalette.refresh();
+ setDelay(30);
+ break;
+ case 9:
+ scene->_stripManager.start(4523, this);
+ break;
+ case 10:
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player._moveDiff = Common::Point(7, 4);
+ _globals->_player.setStrip(3);
+ _globals->_player.enableControl();
+
+ remove();
+ break;
+ }
+}
+
+void Scene4150::Action2::signal() {
+ Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(3);
+ break;
+ case 1:
+ scene->_hotspot1.setVisage(4152);
+ scene->_hotspot1.setStrip(1);
+ scene->_hotspot1.setFrame(1);
+ scene->_hotspot1.animate(ANIM_MODE_5, this);
+
+ _globals->_player.animate(ANIM_MODE_5, NULL);
+ break;
+ case 2:
+ _globals->_player.hide();
+ scene->_hotspot1.setVisage(4153);
+ scene->_hotspot1.setStrip(1);
+ scene->_hotspot1.setFrame(1);
+ scene->_hotspot1.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ remove();
+ break;
+ }
+}
+
+void Scene4150::Action3::signal() {
+ Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(15);
+ break;
+ case 1:
+ _globals->_player.checkAngle(&scene->_hotspot3);
+
+ if (RING_INVENTORY._rope._sceneNumber == 1) {
+ scene->_hotspot3.postInit();
+ scene->_hotspot3.setVisage(4150);
+ scene->_hotspot3.setPosition(Common::Point(175, 70));
+
+ RING_INVENTORY._rope._sceneNumber = 4150;
+ _globals->_sceneItems.push_front(&scene->_hotspot3);
+ } else {
+ RING_INVENTORY._rope._sceneNumber = 1;
+ scene->_hotspot3.remove();
+ }
+
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4150::HotspotGroup1::doAction(int action) {
+ Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4150, 0);
+ break;
+ case OBJECT_ROPE:
+ scene->setAction(&scene->_action3);
+ break;
+ }
+}
+
+void Scene4150::HotspotGroup3::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4150, _globals->getFlag(46) ? 9 : 8);
+ _globals->setFlag(46);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(4150, 30);
+ break;
+ }
+}
+
+void Scene4150::HotspotGroup6::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4150, _globals->getFlag(47) ? 16 : 15);
+ _globals->setFlag(47);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(4150, 31);
+ break;
+ }
+}
+
+void Scene4150::Hotspot3::doAction(int action) {
+ Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4150, 20);
+ break;
+ case CURSOR_USE:
+ scene->setAction(&scene->_action3);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene4150::Scene4150() :
+ _hotspot1(0, CURSOR_LOOK, 4150, 17, CURSOR_USE, 4150, 21, CURSOR_TALK, 4150, 21,
+ OBJECT_SCANNER, 4150, 22, OBJECT_STUNNER, 4150, 23, LIST_END),
+ _hotspot2(0, CURSOR_LOOK, 4150, 4, CURSOR_USE, 4150, 24, LIST_END),
+ _hotspot7(0, CURSOR_LOOK, 4150, 1, CURSOR_USE, 4150, 25, OBJECT_ROPE, 4150, 26, LIST_END),
+ _hotspot8(0, CURSOR_LOOK, 4150, 1, CURSOR_USE, 4150, 25, OBJECT_ROPE, 4150, 26, LIST_END),
+ _hotspot9(0, CURSOR_LOOK, 4150, 2, CURSOR_USE, 4150, 27, OBJECT_SCANNER, 4150, 28,
+ OBJECT_STUNNER, 4150, 32, LIST_END),
+ _hotspot10(0, CURSOR_LOOK, 4150, 5, CURSOR_USE, 4150, 29, LIST_END),
+ _hotspot11(0, CURSOR_LOOK, 4150, 6, CURSOR_USE, 4150, 29, LIST_END),
+ _hotspot12(0, CURSOR_LOOK, 4150, 7, CURSOR_USE, 4150, 29, LIST_END),
+ _hotspot17(0, CURSOR_LOOK, 4150, 10, CURSOR_USE, 4150, 27, OBJECT_STUNNER, 4150, 32, LIST_END),
+ _hotspot18(0, CURSOR_LOOK, 4150, 11, CURSOR_USE, 4150, 32, OBJECT_STUNNER, 4150, 27, LIST_END),
+ _hotspot19(0, CURSOR_LOOK, 4150, 12, CURSOR_USE, 4150, 29, LIST_END),
+ _hotspot20(0, CURSOR_LOOK, 4150, 13, CURSOR_USE, 4150, 29, LIST_END),
+ _hotspot21(0, CURSOR_LOOK, 4150, 13, CURSOR_USE, 4150, 29, LIST_END),
+ _hotspot22(0, CURSOR_LOOK, 4150, 13, CURSOR_USE, 4150, 29, LIST_END),
+ _hotspot23(0, CURSOR_LOOK, 4150, 14, CURSOR_USE, 4150, 27, OBJECT_STUNNER, 4150, 32, LIST_END),
+ _hotspot24(0, CURSOR_LOOK, 4150, 14, CURSOR_USE, 4150, 27, OBJECT_STUNNER, 4150, 32, LIST_END)
+ {
+}
+
+void Scene4150::postInit(SceneObjectList *OwnerList) {
+ loadScene(4150);
+ Scene::postInit();
+ setZoomPercents(60, 85, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerCDL);
+ _stripManager.addSpeaker(&_speakerQText);
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(4171);
+ _hotspot2.animate(ANIM_MODE_2, NULL);
+ _hotspot2.fixPriority(100);
+ _hotspot2.setPosition(Common::Point(76, 147));
+
+ _hotspot1.postInit();
+ _hotspot1.setPosition(Common::Point(177, 201));
+
+ if (_globals->getFlag(44)) {
+ _globals->_player.postInit();
+ _globals->_player.setVisage(4200);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setStrip(2);
+ _globals->_player.setPosition(Common::Point(328, 160));
+ _globals->_player._moveDiff = Common::Point(7, 4);
+ _globals->_player.disableControl();
+
+ _sceneMode = 4151;
+ setAction(&_sequenceManager, this, 4151, &_globals->_player, NULL);
+
+ _hotspot1.setVisage(4157);
+ _hotspot1.setPosition(Common::Point(177, 201));
+ } else {
+ _globals->_player.postInit();
+ _globals->_player.setVisage(4154);
+ _globals->_player._canWalk = false;
+ _globals->_player.setPosition(Common::Point(198, 202));
+ _globals->_player.disableControl();
+
+ _hotspot1.setVisage(4152);
+ setAction(&_action1);
+ _globals->setFlag(44);
+ }
+
+ if (RING_INVENTORY._rope._sceneNumber == 4150) {
+ _hotspot3.postInit();
+ _hotspot3.setVisage(4150);
+ _hotspot3.setPosition(Common::Point(175, 70));
+
+ _globals->_sceneItems.push_back(&_hotspot3);
+ }
+
+ _globals->_sceneItems.push_back(&_hotspot1);
+
+ _hotspot5.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot6.setBounds(Rect(28, 121, 80, 148));
+ _hotspot7.setBounds(Rect(27, 17, 127, 100));
+ _hotspot8.setBounds(Rect(62, 11, 117, 22));
+ _hotspot9.setBounds(Rect(48, 78, 104, 94));
+ _hotspot10.setBounds(Rect(32, 107, 58, 119));
+ _hotspot11.setBounds(Rect(1, 130, 17, 163));
+ _hotspot12.setBounds(Rect(1, 158, 78, 197));
+ _hotspot13.setBounds(Rect(253, 11, 274, 188));
+ _hotspot14.setBounds(Rect(4, 15, 29, 153));
+ _hotspot15.setBounds(Rect(127, 22, 146, 133));
+ _hotspot16.setBounds(Rect(165, 22, 181, 141));
+ _hotspot17.setBounds(Rect(186, 31, 217, 52));
+ _hotspot18.setBounds(Rect(200, 31, 251, 86));
+ _hotspot19.setBounds(Rect(183, 81, 234, 111));
+ _hotspot20.setBounds(Rect(188, 120, 219, 142));
+ _hotspot21.setBounds(Rect(235, 122, 249, 145));
+ _hotspot22.setBounds(Rect(283, 125, 320, 146));
+ _hotspot23.setBounds(Rect(284, 27, 306, 160));
+ _hotspot24.setBounds(Rect(257, 72, 284, 99));
+ _hotspot25.setBounds(Rect(183, 155, 316, 190));
+ _hotspot26.setBounds(Rect(98, 169, 238, 198));
+
+ _globals->_sceneItems.addItems(&_hotspot24, &_hotspot23, &_hotspot13, &_hotspot25,
+ &_hotspot26, &_hotspot19, &_hotspot22, &_hotspot20, &_hotspot17, &_hotspot16,
+ &_hotspot15, &_hotspot11, &_hotspot14, &_hotspot18, &_hotspot21, &_hotspot12,
+ &_hotspot10, &_hotspot9, &_hotspot8, &_hotspot7, &_hotspot6, &_hotspot2,
+ &_hotspot5, NULL);
+
+ _globals->_soundHandler.startSound(165);
+ _soundHandler.startSound(311);
+}
+
+void Scene4150::signal() {
+ if (_sceneMode == 4151)
+ _globals->_player.enableControl();
+ else if (_sceneMode == 4152)
+ _globals->_sceneManager.changeScene(4100);
+}
+
+void Scene4150::dispatch() {
+ Scene::dispatch();
+
+ if (!_action && (_globals->_player._position.x >= 316)) {
+ _globals->_soundHandler.proc1(NULL);
+ _globals->_player.disableControl();
+ _sceneMode = 4152;
+ setAction(&_sequenceManager, this, 4152, &_globals->_player, NULL);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4000 - Village
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4250::Action1::signal() {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ ADD_MOVER_NULL(_globals->_player, 6, 190);
+ ADD_MOVER_NULL(scene->_hotspot3, 9, 195);
+ ADD_MOVER(scene->_hotspot1, 12, 185);
+ break;
+ case 2:
+ setDelay(30);
+ break;
+ case 3:
+ scene->_stripManager.start(4450, this);
+ break;
+ case 4:
+ case 7:
+ setDelay(15);
+ break;
+ case 5:
+ ADD_PLAYER_MOVER(220, 175);
+ scene->_hotspot1.fixPriority(105);
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot1, 197, 173);
+ break;
+ case 6:
+ scene->_stripManager.start(4470, this);
+ break;
+ case 8:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4250::Action2::signal() {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ ADD_PLAYER_MOVER(247, 182);
+ break;
+ case 1:
+ _globals->_player.setVisage(2670);
+ _globals->_player.changeZoom(50);
+ _globals->_player.setStrip(3);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ if ((_globals->_stripNum == 9000) || (_globals->_stripNum == 4300)) {
+ scene->_stripManager.start(4205, this);
+ } else {
+ scene->_stripManager.start(4490, this);
+ }
+ break;
+ case 3:
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 4:
+ _globals->_player.setVisage(2602);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.changeZoom(70);
+
+ if ((_globals->_stripNum == 9000) || (_globals->_stripNum == 4300)) {
+ _globals->_player.enableControl();
+ remove();
+ } else {
+ ADD_PLAYER_MOVER(6, 180);
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot1, 12, 185);
+ }
+ break;
+ case 5:
+ ADD_PLAYER_MOVER(-16, 180);
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot1, -12, 185);
+ scene->_hotspot3.setStrip2(2);
+ ADD_MOVER_NULL(scene->_hotspot5, -30, 195);
+ break;
+ case 6:
+ _globals->clearFlag(59);
+ _globals->clearFlag(70);
+ _globals->clearFlag(37);
+ _globals->clearFlag(114);
+ _globals->clearFlag(36);
+ _globals->clearFlag(43);
+ _globals->_sceneManager.changeScene(2100);
+ break;
+ }
+}
+
+void Scene4250::Action3::signal() {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(3);
+ break;
+ case 1:
+ scene->_stripManager.start(4480, this);
+ break;
+ case 2:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4250::Action4::signal() {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ _globals->_player.addMover(NULL);
+ scene->_stripManager.start((RING_INVENTORY._helmet._sceneNumber == 4250) ? 4259 : 4256, this);
+ break;
+ case 2:
+ ADD_PLAYER_MOVER(_globals->_player._position.x + 5, _globals->_player._position.y);
+ break;
+ case 3:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene4250::Action5::signal() {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ scene->_hotspot4.fixPriority(195);
+ scene->_hotspot1.fixPriority(105);
+ ADD_MOVER_NULL(_globals->_player, 6, 185);
+ ADD_MOVER_NULL(scene->_hotspot4, 9, 190);
+ ADD_MOVER(scene->_hotspot1, 12, 180);
+ break;
+ case 2:
+ ADD_PLAYER_MOVER(252, 176);
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot1, 197, 173);
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot4, 239, 195);
+ break;
+ case 3:
+ scene->_hotspot4.fixPriority(-1);
+ scene->_hotspot1.setStrip(5);
+ scene->_hotspot4.setStrip(7);
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4250::Hotspot1::doAction(int action) {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4250, (RING_INVENTORY._helmet._sceneNumber == 4250) ? 19 : 14);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ if (!_globals->_sceneObjects->contains(&scene->_hotspot4)) {
+ scene->setAction(&scene->_action3);
+ } else {
+ scene->_sceneMode = 4260;
+ if (RING_INVENTORY._helmet._sceneNumber == 4250) {
+ scene->_sceneMode = 4265;
+ scene->setAction(&scene->_sequenceManager, scene, 4265, this, NULL);
+ } else {
+ scene->setAction(&scene->_sequenceManager, scene,
+ _globals->_sceneObjects->contains(&scene->_hotspot6) ? 4260 : 4262, this, NULL);
+ }
+ }
+ break;
+ case OBJECT_SCANNER:
+ if (RING_INVENTORY._helmet._sceneNumber == 4250)
+ SceneItem::display2(4250, 21);
+ else
+ SceneHotspot::doAction(action);
+ break;
+ case OBJECT_STUNNER:
+ if (RING_INVENTORY._helmet._sceneNumber == 4250)
+ SceneItem::display2(4250, 22);
+ else
+ SceneHotspot::doAction(action);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4250::Hotspot2::doAction(int action) {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ case CURSOR_USE:
+ SceneItem::display2(4250, 16);
+ break;
+ case OBJECT_SCANNER:
+ if ((_globals->_stripNum == 9000) || (_globals->_stripNum == 4300))
+ scene->setAction(&scene->_action2);
+ else if (_globals->getFlag(55))
+ SceneItem::display2(4250, 17);
+ else {
+ _globals->setFlag(55);
+ scene->setAction(&scene->_action2);
+ }
+ break;
+ case OBJECT_STASIS_NEGATOR:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 4252;
+ scene->setAction(&scene->_sequenceManager, scene, 4252, &_globals->_player, this, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4250::Hotspot4::doAction(int action) {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4250, (RING_INVENTORY._helmet._sceneNumber == 4250) ? 18 : 5);
+ break;
+ case OBJECT_SCANNER:
+ if (RING_INVENTORY._helmet._sceneNumber == 4250)
+ SceneItem::display2(4250, 21);
+ else
+ SceneHotspot::doAction(action);
+ break;
+ case OBJECT_STUNNER:
+ if (RING_INVENTORY._helmet._sceneNumber == 4250)
+ SceneItem::display2(4250, 22);
+ else
+ SceneHotspot::doAction(action);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ if (!_globals->_sceneObjects->contains(&scene->_hotspot6)) {
+ scene->_sceneMode = 4254;
+ scene->setAction(&scene->_sequenceManager, scene, 4263, NULL);
+ } else {
+ scene->_sceneMode = 4254;
+
+ if (RING_INVENTORY._helmet._sceneNumber == 4250) {
+ scene->_sceneMode = 4266;
+ scene->setAction(&scene->_sequenceManager, scene, 4266, this, NULL);
+ } else {
+ scene->setAction(&scene->_sequenceManager, scene,
+ (RING_INVENTORY._concentrator._sceneNumber == 1) ? 4255 : 4254, NULL);
+ }
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4250::Hotspot6::doAction(int action) {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4250, (RING_INVENTORY._helmet._sceneNumber == 4250) ? 7 : 6);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4250, (RING_INVENTORY._helmet._sceneNumber == 4250) ? 1 : 2);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4250, (RING_INVENTORY._helmet._sceneNumber == 4250) ? 20 : 3);
+ break;
+ case OBJECT_HELMET:
+ _globals->_soundHandler.startSound(354);
+ _globals->_player.disableControl();
+ RING_INVENTORY._helmet._sceneNumber = 4250;
+
+ if (RING_INVENTORY._concentrator._sceneNumber == 1) {
+ if (_globals->getFlag(115)) {
+ scene->_sceneMode = 4269;
+ scene->setAction(&scene->_sequenceManager, scene, 4269, this, NULL);
+ } else {
+ _globals->setFlag(115);
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_sceneMode = 4256;
+ scene->setAction(&scene->_sequenceManager, scene, 4256, this, NULL);
+ }
+ } else if (RING_INVENTORY._keyDevice._sceneNumber == 1) {
+ scene->_sceneMode = 4267;
+ scene->setAction(&scene->_sequenceManager, scene, 4267, this, NULL);
+ } else if (RING_INVENTORY._keyDevice._sceneNumber == 4300) {
+ scene->_sceneMode = 4268;
+ scene->setAction(&scene->_sequenceManager, scene, 4268, this, NULL);
+ } else {
+ _globals->_events.setCursor(CURSOR_WALK);
+ ADD_MOVER_NULL(scene->_hotspot1, 241, 169);
+ scene->_sceneMode = 4261;
+ scene->setAction(&scene->_sequenceManager, scene, 4261, &_globals->_player, this, NULL);
+ }
+ break;
+ case OBJECT_NULLIFIER:
+ if (RING_INVENTORY._helmet._sceneNumber == 4250) {
+ _globals->_soundHandler.startSound(353);
+ _globals->_player.disableControl();
+ RING_INVENTORY._helmet._sceneNumber = 1;
+
+ scene->_sceneMode = 4257;
+ scene->setAction(&scene->_sequenceManager, scene, 4257, &_globals->_player, this, NULL);
+ } else {
+ SceneItem::display2(4250, 4);
+ }
+ break;
+ case CURSOR_TALK:
+ if (RING_INVENTORY._helmet._sceneNumber == 4250)
+ doAction(OBJECT_HELMET);
+ else {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 4264;
+ scene->setAction(&scene->_sequenceManager, scene, 4264, this, NULL);
+ }
+ break;
+ case CURSOR_USE:
+ if (RING_INVENTORY._helmet._sceneNumber == 4250)
+ doAction(OBJECT_HELMET);
+ else {
+ _globals->_player.disableControl();
+ if ((RING_INVENTORY._items._sceneNumber != 1) || (RING_INVENTORY._concentrator._sceneNumber != 1)) {
+ scene->_sceneMode = 4258;
+ scene->setAction(&scene->_sequenceManager, scene, 4258, this, NULL);
+ } else {
+ scene->_hotspot2.postInit();
+ scene->_hotspot2.setVisage(4251);
+ scene->_hotspot2.setFrame(scene->_hotspot2.getFrameCount());
+ scene->_hotspot2.setPosition(Common::Point(267, 172));
+ scene->_hotspot2.hide();
+
+ scene->_sceneMode = 4259;
+ scene->setAction(&scene->_sequenceManager, scene, 4259, &_globals->_player, this, &scene->_hotspot2, NULL);
+ }
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4250::Hotspot8::doAction(int action) {
+ Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ case CURSOR_USE:
+ _globals->_sceneManager.changeScene(4300);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4250, 24);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4250, 25);
+ break;
+ case OBJECT_STASIS_NEGATOR:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 4270;
+ scene->setAction(&scene->_sequenceManager, scene,
+ (RING_INVENTORY._helmet._sceneNumber == 4250) ? 4270 : 4271, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene4250::Scene4250() :
+ _hotspot7(0, CURSOR_LOOK, 4250, 0, LIST_END) {
+}
+
+void Scene4250::postInit(tSage::SceneObjectList *OwnerList) {
+ loadScene(4250);
+ Scene::postInit();
+ setZoomPercents(160, 90, 185, 100);
+
+ _stripManager.addSpeaker(&_speakerSR);
+ _stripManager.addSpeaker(&_speakerSL);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerGameText);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerPText);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerFLText);
+
+ _speakerSText.setTextPos(Common::Point(40, 40));
+ _speakerPText.setTextPos(Common::Point(40, 100));
+ _hotspot8._sceneRegionId = 16;
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2602);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(-13, 190));
+ _globals->_player.changeZoom(-1);
+ _globals->_player._moveDiff = Common::Point(4, 1);
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(2801);
+ _hotspot1.animate(ANIM_MODE_1, NULL);
+ _hotspot1.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot1.setPosition(Common::Point(-18, 185));
+ _hotspot1.changeZoom(-1);
+ _hotspot1._moveDiff = Common::Point(4, 1);
+ _globals->_sceneItems.push_back(&_hotspot1);
+
+ if (_globals->_sceneManager._previousScene == 4300) {
+ _hotspot5.postInit();
+ _hotspot5.setVisage(4250);
+ _hotspot5.setPosition(Common::Point(268, 168));
+ _hotspot5.fixPriority(1);
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(2701);
+ _hotspot4.animate(ANIM_MODE_1, NULL);
+ _hotspot4.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot4.setPosition(Common::Point(272, 175));
+ _hotspot4.setStrip(2);
+ _hotspot4._moveDiff = Common::Point(4, 1);
+ _hotspot4.changeZoom(70);
+ _globals->_sceneItems.push_back(&_hotspot4);
+
+ _hotspot1.setPosition(Common::Point(197, 173));
+ _hotspot1.changeZoom(70);
+
+ _globals->_player.setPosition(Common::Point(252, 176));
+ _globals->_player.changeZoom(70);
+
+ _hotspot6.postInit();
+ _hotspot6.setVisage(4302);
+ _hotspot6.setStrip(4);
+ _hotspot6.setFrame(3);
+ _hotspot6.changeZoom(50);
+ _hotspot6.fixPriority(70);
+ _hotspot6.setPosition(Common::Point(261, 175));
+
+ if (RING_INVENTORY._helmet._sceneNumber == 4250) {
+ _hotspot6.setStrip(6);
+ _hotspot6.setFrame(_hotspot6.getFrameCount());
+ }
+
+ if (_globals->getFlag(98)) {
+ _globals->_sceneItems.push_front(&_hotspot6);
+ } else {
+ _hotspot6.hide();
+ if ((_globals->_stripNum == 4300) || (_globals->_stripNum == 4301)) {
+ _globals->setFlag(98);
+ _globals->_player.setVisage(4302);
+ _globals->_player.setStrip(5);
+ _globals->_player.changeZoom(50);
+ _globals->_player.disableControl();
+
+ _hotspot4.setPosition(Common::Point(239, 195));
+ _sceneMode = 4253;
+ _globals->_sceneItems.push_front(&_hotspot6);
+
+ setAction(&_sequenceManager, this, 4253, &_globals->_player, &_hotspot6, &_hotspot4, NULL);
+ }
+ }
+ } else if (_globals->_stripNum == 9000) {
+ _hotspot4.postInit();
+ _hotspot4.setVisage(2701);
+ _hotspot4.animate(ANIM_MODE_1, NULL);
+ _hotspot4.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot4.setPosition(Common::Point(-15, 195));
+ _hotspot4._moveDiff = Common::Point(4, 1);
+ _globals->_sceneItems.push_back(&_hotspot4);
+
+ setAction(&_action5);
+ } else {
+ _hotspot3.postInit();
+ _hotspot3.setVisage(4006);
+ _hotspot3.animate(ANIM_MODE_1, NULL);
+ _hotspot3.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot3.setPosition(Common::Point(-15, 195));
+ _hotspot3.setStrip2(3);
+ _hotspot3._moveDiff = Common::Point(4, 1);
+
+ setAction(&_action1);
+ _globals->clearFlag(43);
+ _globals->clearFlag(114);
+ _globals->clearFlag(36);
+ }
+
+ if (_globals->getFlag(17)) {
+ _globals->_sceneItems.push_back(&_hotspot8);
+ } else {
+ _hotspot2.postInit();
+ _hotspot2.setVisage(4251);
+ _hotspot2.setStrip2(1);
+ _hotspot2.fixPriority(2);
+ _hotspot2.setFrame(1);
+ _hotspot2.setPosition(Common::Point(267, 172));
+
+ _globals->_sceneItems.push_back(&_hotspot2);
+ }
+
+ _hotspot7.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _globals->_sceneItems.push_back(&_hotspot7);
+ _globals->_soundHandler.startSound(185);
+}
+
+void Scene4250::signal() {
+ switch (_sceneMode) {
+ case 4252:
+ _globals->setFlag(17);
+ _globals->_sceneManager.changeScene(4301);
+ break;
+ case 4253:
+ if (_globals->_stripNum == 4301) {
+ ADD_MOVER_NULL(_hotspot1, 241, 169);
+ setAction(&_sequenceManager, this, 4261, &_globals->_player, &_hotspot6, NULL);
+ } else {
+ _globals->_player.enableControl();
+ }
+ break;
+ case 4254:
+ case 4256:
+ case 4257:
+ case 4258:
+ case 4260:
+ case 4264:
+ case 4265:
+ case 4266:
+ case 4267:
+ case 4268:
+ case 4269:
+ case 4270:
+ _globals->_player.enableControl();
+ break;
+ case 4255:
+ case 4262:
+ case 4263:
+ break;
+ case 4259:
+ _globals->_soundHandler.startSound(360);
+ _globals->_sceneManager.changeScene(9900);
+ break;
+ case 4261:
+ RING_INVENTORY._keyDevice._sceneNumber = 1;
+ _globals->_player.enableControl();
+ break;
+ }
+}
+
+void Scene4250::dispatch() {
+ if (_globals->_player.getRegionIndex() == 8)
+ _globals->_player.changeZoom(90 - (_globals->_player._position.y - 153));
+ if (_globals->_player.getRegionIndex() == 12)
+ _globals->_player.changeZoom(70);
+ if (_globals->_player.getRegionIndex() == 15) {
+ _globals->_player.changeZoom(-1);
+ _globals->_player.fixPriority(-1);
+ }
+
+ if (_hotspot1.getRegionIndex() == 8)
+ _hotspot1.changeZoom(90 - (_hotspot1._position.y - 153));
+ if (_hotspot1.getRegionIndex() == 12)
+ _hotspot1.changeZoom(70);
+ if (_hotspot1.getRegionIndex() == 15) {
+ _hotspot1.changeZoom(-1);
+ _hotspot1.fixPriority(-1);
+ }
+
+ if (_hotspot4.getRegionIndex() == 8)
+ _hotspot4.changeZoom(90 - (_hotspot4._position.y - 153));
+ if (_hotspot4.getRegionIndex() == 12)
+ _hotspot4.changeZoom(70);
+ if (_hotspot4.getRegionIndex() == 15) {
+ _hotspot4.changeZoom(-1);
+ _hotspot4.fixPriority(-1);
+ }
+
+ Scene::dispatch();
+
+ if (!_action) {
+ if (!_globals->getFlag(55) && (_globals->_player.getRegionIndex() == 12)) {
+ setAction(&_action4);
+ }
+
+ if (_globals->_sceneObjects->contains(&_hotspot6) && (_globals->_player.getRegionIndex() == 12))
+ setAction(&_action4);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4300 - Village - Slaver Ship
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4300::Action1::signal() {
+ Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->setFlag(56);
+ _globals->_scenePalette.addRotation(240, 254, -1);
+ scene->_hotspot7.animate(ANIM_MODE_6, this);
+ _globals->_soundHandler.startSound(164);
+ break;
+ case 1:
+ _globals->_soundHandler.startSound(340);
+ scene->_soundHandler1.startSound(341);
+ scene->_hotspot1.remove();
+ setDelay(3);
+ break;
+ case 2:
+ scene->_soundHandler1.startSound(341);
+ scene->_hotspot2.remove();
+ setDelay(6);
+ break;
+ case 3:
+ scene->_soundHandler1.startSound(341);
+ scene->_hotspot3.remove();
+ setDelay(6);
+ break;
+ case 4:
+ scene->_soundHandler1.startSound(341);
+ scene->_hotspot4.remove();
+ setDelay(12);
+ break;
+ case 5:
+ scene->_soundHandler1.startSound(341);
+ scene->_hotspot5.remove();
+ setDelay(12);
+ break;
+ case 6:
+ scene->_soundHandler1.startSound(341);
+ scene->_hotspot6.remove();
+ setDelay(60);
+ break;
+ case 7:
+ scene->_hotspot10.fixPriority(250);
+ scene->_hotspot10.animate(ANIM_MODE_5, this);
+ break;
+ case 8:
+ scene->_hotspot13.show();
+ scene->_stripManager.start(8015, this, scene);
+ break;
+ case 9:
+ _globals->_soundHandler.startSound(350);
+ _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL;
+ _globals->_events.setCursor(CURSOR_USE);
+ _globals->_player.enableControl();
+
+ remove();
+ break;
+ }
+}
+
+void Scene4300::Action2::signal() {
+ Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(3);
+ break;
+ case 1:
+ scene->_stripManager.start(8016, this, scene);
+ break;
+ case 2:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4300::Hotspot8::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4300, 15);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(4300, 18);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4300, 14);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4300, 19);
+ break;
+ case OBJECT_KEY_DEVICE:
+ RING_INVENTORY._keyDevice._sceneNumber = 4300;
+ _globals->_scenePalette.addRotation(240, 254, -1);
+ animate(ANIM_MODE_5, NULL);
+
+ _globals->setFlag(99);
+ _globals->_sceneItems.push_back(this);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4300::Hotspot9::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if ((RING_INVENTORY._stasisBox2._sceneNumber == 4300) ||
+ (RING_INVENTORY._concentrator._sceneNumber == 1))
+ SceneItem::display2(4300, 7);
+ else
+ SceneItem::display2(4300, 1);
+ break;
+ case CURSOR_USE:
+ if ((RING_INVENTORY._stasisBox2._sceneNumber == 4300) ||
+ (RING_INVENTORY._concentrator._sceneNumber == 1))
+ SceneItem::display2(4300, 7);
+ else
+ SceneItem::display2(4300, 3);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4300, 24);
+ break;
+ case OBJECT_SCANNER:
+ if ((RING_INVENTORY._stasisBox2._sceneNumber == 4300) ||
+ (RING_INVENTORY._concentrator._sceneNumber != 1))
+ SceneItem::display2(4300, 22);
+ else
+ SceneItem::display2(4300, 23);
+ break;
+ default:
+ NamedHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4300::Hotspot10::doAction(int action) {
+ Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4300, 2);
+ break;
+ case CURSOR_TALK:
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action2);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4300, 20);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4300, 21);
+ break;
+ case CURSOR_USE:
+ case OBJECT_HELMET:
+ _globals->_stripNum = (action == CURSOR_USE) ? 4300 : 4301;
+ _globals->_events.setCursor(CURSOR_NONE);
+ _globals->_sceneManager.changeScene(4250);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4300::Hotspot15::signal() {
+ Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene;
+
+ scene->_soundHandler2.startSound(345);
+
+ _strip = (_globals->_randomSource.getRandomNumber(6) < 2) ? 2 : 1;
+ if ((RING_INVENTORY._stasisBox2._sceneNumber == 4300) ||
+ (RING_INVENTORY._concentrator._sceneNumber == 1)) {
+ setStrip(1);
+ setFrame(1);
+ animate(ANIM_MODE_NONE, NULL);
+ } else {
+ animate(ANIM_MODE_5, this);
+ }
+}
+
+void Scene4300::Hotspot16::doAction(int action) {
+ Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4300, 8);
+ break;
+ case CURSOR_USE:
+ if ((RING_INVENTORY._stasisBox2._sceneNumber != 4300) &&
+ (RING_INVENTORY._concentrator._sceneNumber != 4300)) {
+ SceneItem::display2(4300, 16);
+ } else {
+ scene->_sceneMode = 4302;
+ scene->setAction(&scene->_sequenceManager, scene, 4302, this, NULL);
+ }
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4300, 27);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4300, 24);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene4300::Hotspot17::doAction(int action) {
+ Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4300, (RING_INVENTORY._stasisBox2._sceneNumber == 4300) ? 17 : 11);
+ break;
+ case CURSOR_USE:
+ if (RING_INVENTORY._stasisBox2._sceneNumber != 4300)
+ SceneItem::display2(4300, 13);
+ else {
+ _globals->_scenePalette.clearListeners();
+ remove();
+
+ SceneItem::display2(4300, 12);
+ RING_INVENTORY._concentrator._sceneNumber = 1;
+ }
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4300, 25);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4300, 26);
+ break;
+ case OBJECT_STASIS_BOX2:
+ scene->_soundHandler1.startSound(352);
+ _globals->_events.setCursor(CURSOR_USE);
+ scene->_sceneMode = 4303;
+
+ scene->setAction(&scene->_sequenceManager, scene, 4303, this, NULL);
+ break;
+ }
+}
+
+void Scene4300::Hotspot19::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4300, 9);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4300, 28);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4300, 24);
+ break;
+ case CURSOR_USE:
+ if ((RING_INVENTORY._stasisBox2._sceneNumber != 4300) &&
+ (RING_INVENTORY._concentrator._sceneNumber != 4300))
+ SceneItem::display2(4300, 10);
+ else
+ SceneItem::display2(4300, 29);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene4300::Scene4300() :
+ _hotspot18(0, CURSOR_LOOK, 4300, 0, LIST_END) {
+}
+
+void Scene4300::postInit(SceneObjectList *OwnerList) {
+ loadScene(4300);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerFLText);
+
+ _hotspot11.setup(76, 97, 102, 127, 4300, 5, 6);
+
+ _hotspot7.postInit();
+ _hotspot7.setPosition(Common::Point(90, 128));
+ _hotspot7.setVisage(4303);
+ _hotspot7.fixPriority(250);
+ _globals->_sceneItems.push_back(&_hotspot7);
+
+ _hotspot9.setup(120, 49, 174, 91, 4300, -1, -1);
+
+ _hotspot15.postInit();
+ _hotspot15.setVisage(4300);
+ _hotspot15.setPosition(Common::Point(149, 79));
+ _hotspot15.signal();
+
+ if (!_globals->getFlag(99)) {
+ _hotspot8.postInit();
+ _hotspot8.setVisage(4300);
+ _hotspot8.setStrip(3);
+ _hotspot8.setPosition(Common::Point(196, 47));
+ _globals->_sceneItems.push_back(&_hotspot8);
+ }
+
+ if (RING_INVENTORY._concentrator._sceneNumber == 4300) {
+ _hotspot17.postInit();
+ _hotspot17.setVisage(4300);
+ _hotspot17.setStrip(6);
+ _hotspot17.fixPriority(1);
+ _hotspot17.setPosition(Common::Point(200, 69));
+
+ if (RING_INVENTORY._stasisBox2._sceneNumber == 4300)
+ _hotspot17.setFrame(_hotspot17.getFrameCount());
+
+ _globals->_sceneItems.push_back(&_hotspot17);
+ }
+
+ if (!_globals->getFlag(98)) {
+ _hotspot10.postInit();
+ _hotspot10.setVisage(4302);
+ _hotspot10.setPosition(Common::Point(244, 179));
+ _hotspot10.fixPriority(100);
+ _globals->_sceneItems.push_back(&_hotspot10);
+
+ _hotspot12.postInit();
+ _hotspot12.setVisage(4302);
+ _hotspot12.setStrip2(3);
+ _hotspot12.setPosition(Common::Point(231, 185));
+ _hotspot12.fixPriority(251);
+ _hotspot12.hide();
+
+ _hotspot13.postInit();
+ _hotspot13.hide();
+ _hotspot13.setVisage(4302);
+ _hotspot13.setStrip2(2);
+ _hotspot13.setPosition(Common::Point(256, 168));
+ _hotspot13.fixPriority(251);
+ _hotspot13._numFrames = 1;
+ _hotspot13.animate(ANIM_MODE_8, 0, NULL);
+ }
+
+ if (RING_INVENTORY._items._sceneNumber == 4300) {
+ _hotspot16.postInit();
+ _hotspot16.setVisage(4300);
+ _hotspot16.setPosition(Common::Point(169, 141));
+ _hotspot16.fixPriority(1);
+ _hotspot16.setStrip(4);
+ _globals->_sceneItems.push_back(&_hotspot16);
+ }
+
+ if (_globals->_sceneManager._previousScene == 4301) {
+ _globals->_player.disableControl();
+ _hotspot7.setFrame(_hotspot7.getFrameCount());
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(4301);
+ _hotspot1.fixPriority(145);
+ _hotspot1.setPosition(Common::Point(160, 64));
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(4301);
+ _hotspot2.setStrip2(2);
+ _hotspot2.fixPriority(140);
+ _hotspot2.setPosition(Common::Point(166, 90));
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(4301);
+ _hotspot3.setStrip2(3);
+ _hotspot3.fixPriority(135);
+ _hotspot3.setPosition(Common::Point(173, 114));
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(4301);
+ _hotspot4.setStrip2(4);
+ _hotspot4.fixPriority(130);
+ _hotspot4.setPosition(Common::Point(187, 141));
+
+ _hotspot5.postInit();
+ _hotspot5.setVisage(4301);
+ _hotspot5.setStrip2(5);
+ _hotspot5.fixPriority(125);
+ _hotspot5.setPosition(Common::Point(201, 164));
+
+ _hotspot6.postInit();
+ _hotspot6.setVisage(4301);
+ _hotspot6.setStrip2(6);
+ _hotspot6.fixPriority(120);
+ _hotspot6.setPosition(Common::Point(219, 186));
+
+ setAction(&_action1);
+ } else {
+ _globals->_player.disableControl();
+ _sceneMode = 4304;
+ setAction(&_sequenceManager, this, 4304, NULL);
+ }
+
+ _hotspot10.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot19._sceneRegionId = 0;
+ _globals->_sceneItems.push_back(&_hotspot19);
+ _globals->_sceneItems.push_back(&_hotspot18);
+}
+
+void Scene4300::stripCallback(int v) {
+ switch (v) {
+ case 1:
+ _hotspot12.show();
+ _hotspot12.animate(ANIM_MODE_7, 0, NULL);
+ break;
+ case 2:
+ _hotspot12.hide();
+ break;
+ }
+}
+
+void Scene4300::remove() {
+ _globals->_scenePalette.clearListeners();
+ Scene::remove();
+}
+
+void Scene4300::signal() {
+ switch (_sceneMode) {
+ case 4302:
+ RING_INVENTORY._items._sceneNumber = 1;
+ _hotspot16.remove();
+ _globals->_player.enableControl();
+ break;
+ case 4303:
+ RING_INVENTORY._stasisBox2._sceneNumber = 4300;
+ _hotspot15.setStrip(1);
+ _hotspot15.setFrame(1);
+ _hotspot15.animate(ANIM_MODE_NONE, NULL);
+ break;
+ case 4304:
+ _hotspot14.postInit();
+ _hotspot14.setVisage(4300);
+ _hotspot14.setStrip(7);
+ _hotspot14.setPosition(Common::Point(60, 199));
+
+ _gfxButton.setText(EXIT_MSG);
+ _gfxButton._bounds.center(60, 193);
+ _gfxButton.draw();
+ _gfxButton._bounds.expandPanes();
+
+ _globals->_player.enableControl();
+ _globals->_scenePalette.addRotation(240, 254, -1);
+ break;
+ }
+}
+
+void Scene4300::dispatch() {
+ if (_action)
+ _action->dispatch();
+}
+
+void Scene4300::process(Event &event) {
+ Scene::process(event);
+ if (_gfxButton.process(event))
+ _globals->_sceneManager.changeScene(4250);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 4301 - Village - Slaver Ship Keypad
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene4301::Action1::synchronise(Serialiser &s) {
+ Action::synchronise(s);
+ s.syncAsSint16LE(_field34E);
+ for (int idx = 0; idx < 6; ++idx)
+ s.syncAsSint16LE(_indexList[idx]);
+}
+
+void Scene4301::Action1::remove() {
+ Scene4301 *scene = (Scene4301 *)_globals->_sceneManager._scene;
+ _globals->_player.enableControl();
+
+ for (_state = 0; _state < 6; ++_state)
+ _buttonList[_state].remove();
+
+ scene->_hotspot3.remove();
+ scene->_hotspot2.remove();
+
+ scene->_hotspot1.animate(ANIM_MODE_6, NULL);
+ Action::remove();
+}
+
+void Scene4301::Action1::signal() {
+ Scene4301 *scene = (Scene4301 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_soundHandler.startSound(164);
+ scene->_hotspot1.animate(ANIM_MODE_5, this);
+ break;
+ case 1:
+ _globals->_soundHandler.startSound(335);
+ _globals->_events.setCursor(CURSOR_USE);
+
+ scene->_hotspot2.postInit();
+ scene->_hotspot2.setVisage(4303);
+ scene->_hotspot2.setStrip(2);
+ scene->_hotspot2.setFrame(1);
+ scene->_hotspot2.setPosition(Common::Point(30, 15));
+ scene->_hotspot2.fixPriority(255);
+
+ scene->_hotspot3.postInit();
+ scene->_hotspot3.setVisage(4303);
+ scene->_hotspot3.setStrip(2);
+ scene->_hotspot3.setFrame(2);
+ scene->_hotspot3.setPosition(Common::Point(48, 29));
+ scene->_hotspot3.fixPriority(255);
+ scene->_hotspot3.hide();
+
+ _field34E = 0;
+ _state = 0;
+ _actionIndex = 2;
+ break;
+ case 10:
+ _globals->_events.setCursor(CURSOR_NONE);
+ scene->_soundHandler.startSound(337);
+ if (scene->_hotspot3._flags & OBJFLAG_HIDE)
+ scene->_hotspot3.show();
+ else
+ scene->_hotspot3.hide();
+ setDelay(20);
+
+ if (_state <= 8)
+ _actionIndex = 10;
+ ++_state;
+ break;
+ case 11:
+ for (_state = 0; _state < 6; ++_state)
+ _buttonList[_state].remove();
+
+ scene->_soundHandler.startSound(338);
+ scene->_hotspot3.hide();
+
+ _actionIndex = 2;
+ _state = 0;
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 20:
+ _globals->_player.disableControl();
+ scene->_soundHandler.startSound(339);
+ scene->_hotspot3._frame = 3;
+ if (scene->_hotspot3._flags & OBJFLAG_HIDE)
+ scene->_hotspot3.show();
+ else
+ scene->_hotspot3.hide();
+
+ if (_state <= 8)
+ _actionIndex = 20;
+ ++_state;
+
+ setDelay(20);
+ break;
+ case 21:
+ scene->_field68E = true;
+ remove();
+ break;
+ }
+}
+
+void Scene4301::Action1::process(Event &event) {
+ Scene4301 *scene = (Scene4301 *)_globals->_sceneManager._scene;
+ Rect buttonsRect;
+
+ Action::process(event);
+ if (event.handled || (_actionIndex != 2))
+ return;
+
+ buttonsRect = Rect(14, 35, 112, 100);
+ buttonsRect.translate(30, 15);
+
+ if ((event.eventType == EVENT_BUTTON_DOWN) && buttonsRect.contains(event.mousePos)) {
+ event.handled = true;
+ scene->_soundHandler.startSound(336);
+
+ int buttonIndex = ((event.mousePos.y - buttonsRect.top) / 33) * 3 +
+ ((event.mousePos.x - buttonsRect.left) / 33);
+
+ _buttonList[_state].postInit();
+ _buttonList[_state].setVisage(4303);
+ _buttonList[_state].setStrip(buttonIndex + 3);
+ _buttonList[_state].setFrame(1);
+ _buttonList[_state].setPosition(Common::Point((_state % 3) * 25 + 55, (_state / 3) * 25 + 121));
+ _buttonList[_state].fixPriority(255);
+ _buttonList[_state]._numFrames = 25;
+ _buttonList[_state].animate(ANIM_MODE_5, NULL);
+
+ _indexList[_state++] = buttonIndex;
+
+ if (_state == 6) {
+ // Six buttons pressed
+ if ((_indexList[0] == 2) && (_indexList[1] == 3) && (_indexList[2] == 0) &&
+ (_indexList[3] == 4) && (_indexList[4] == 1) && (_indexList[5] == 5)) {
+ // Entered the correct full combination
+ _state = 0;
+ _actionIndex = 20;
+ } else {
+ // Incorrect combination entered
+ _state = 0;
+ _actionIndex = 10;
+ }
+
+ signal();
+ }
+ }
+
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ event.handled = true;
+ remove();
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4301::Hotspot4::doAction(int action) {
+ Scene4301 *scene = (Scene4301 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_USE) {
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action1);
+ } else {
+ NamedHotspot::doAction(action);
+ }
+}
+
+void Scene4301::Hotspot5::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(4300, 0);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(4300, 30);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(4300, 31);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(4300, 32);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene4301::postInit(SceneObjectList *OwnerList) {
+ _globals->setFlag(50);
+ loadScene(4301);
+ Scene::postInit();
+ setZoomPercents(0, 100, 200, 100);
+
+ _field68E = false;
+ RING_INVENTORY._stasisBox2._sceneNumber = 1;
+ _hotspot4.setup(97, 76, 127, 102, 4300, 5, 6);
+
+ _hotspot1.postInit();
+ _hotspot1.setPosition(Common::Point(90, 128));
+ _hotspot1.setVisage(4303);
+ _hotspot1._strip = 1;
+ _hotspot1._frame = 1;
+ _hotspot1.fixPriority(250);
+
+ _hotspot5.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _globals->_sceneItems.push_back(&_hotspot5);
+
+ _globals->_player.enableControl();
+}
+
+void Scene4301::dispatch() {
+ if (_action) {
+ _action->dispatch();
+ } else if (_field68E) {
+ _field68E = 0;
+ _globals->clearFlag(50);
+ _globals->_sceneManager._fadeMode = FADEMODE_NONE;
+ _globals->_sceneManager.setNewScene(4300);
+ }
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes5.h b/engines/tsage/ringworld_scenes5.h
new file mode 100644
index 0000000000..626eab5dab
--- /dev/null
+++ b/engines/tsage/ringworld_scenes5.h
@@ -0,0 +1,696 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_SCENES5_H
+#define TSAGE_RINGWORLD_SCENES5_H
+
+#include "common/scummsys.h"
+#include "tsage/core.h"
+#include "tsage/converse.h"
+#include "tsage/ringworld_logic.h"
+
+namespace tSage {
+
+class Scene4000 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action8 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action9 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action10 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action11 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action12 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action13 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Miranda : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot8 : public SceneObject {
+ private:
+ int _ctr;
+ public:
+ virtual void synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+ s.syncAsUint16LE(_ctr);
+ }
+ virtual void doAction(int action);
+ };
+ class GuardRock : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Ladder : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class TheTech : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot13 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot17 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot18 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot23 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager1, _sequenceManager2, _sequenceManager3;
+ SoundHandler _soundHandler1, _soundHandler2;
+ SpeakerQR _speakerQR;
+ SpeakerML _speakerML;
+ SpeakerMR _speakerMR;
+ SpeakerSR _speakerSR;
+ SpeakerCHFL _speakerCHFL;
+ SpeakerPL _speakerPL;
+ SpeakerPText _speakerPText;
+ SpeakerQText _speakerQText;
+ SpeakerSText _speakerSText;
+ SpeakerMText _speakerMText;
+ SpeakerCHFR _speakerCHFR;
+ SpeakerQL _speakerQL;
+ SpeakerCHFText _speakerCHFText;
+ SceneObject _smoke1, _hotspot2, _lander, _olo, _hotspot5, _rope;
+ Miranda _miranda;
+ Hotspot8 _hotspot8;
+ GuardRock _guardRock;
+ Ladder _ladder;
+ DisplayHotspot _forceField;
+ TheTech _theTech;
+ Hotspot13 _hotspot13;
+ Hotspot _hotspot14, _hotspot15, _hotspot16;
+ Hotspot17 _hotspot17;
+ Hotspot18 _hotspot18;
+ DisplayHotspot _hotspot19, _hotspot20, _hotspot21, _hotspot22;
+ Hotspot23 _hotspot23;
+ DisplayHotspot _hotspot24, _hotspot25, _hotspot26;
+ SceneObject _smoke2;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ Action8 _action8;
+ Action9 _action9;
+ Action10 _action10;
+ Action11 _action11;
+ Action12 _action12;
+ Action13 _action13;
+
+ Scene4000();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene4010 : public Scene {
+public:
+ SequenceManager _sequenceManager;
+ SpeakerQText _speakerQText;
+ SpeakerSText _speakerSText;
+ SpeakerMText _speakerMText;
+ SceneObject _hotspot1, _hotspot2;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+};
+
+class Scene4025 : public Scene {
+ /* Custom classes */
+ class Peg;
+
+ class Hole : public SceneObject {
+ public:
+ Peg *_pegPtr;
+ int _armStrip;
+ Common::Point _newPosition;
+
+ virtual void synchronise(Serialiser &s);
+ virtual void doAction(int action);
+ };
+ class Peg : public SceneObject {
+ public:
+ int _field88;
+ int _armStrip;
+
+ Peg() : SceneObject() { _field88 = 0; _armStrip = 3; }
+ virtual void synchronise(Serialiser &s);
+ virtual void doAction(int action);
+ };
+
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+public:
+ SequenceManager _sequenceManager;
+ GfxButton _gfxButton;
+ SceneObject _armHotspot;
+ Hole _hole1, _hole2, _hole3, _hole4, _hole5;
+ Peg _peg1, _peg2, _peg3, _peg4, _peg5;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Peg *_pegPtr, *_pegPtr2;
+ Hole *_holePtr;
+
+ Scene4025();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void synchronise(Serialiser &s);
+ virtual void remove();
+ virtual void signal();
+ virtual void process(Event &event);
+ virtual void dispatch();
+};
+
+class Scene4045 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class OlloStand : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Miranda : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Necklace : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ SequenceManager _sequenceManager;
+ SpeakerQR _speakerQR;
+ SpeakerML _speakerML;
+ SpeakerPR _speakerPR;
+ SpeakerPText _speakerPText;
+ SpeakerQText _speakerQText;
+ SpeakerQL _speakerQL;
+ OlloStand _olloStand;
+ Miranda _miranda;
+ DisplayHotspot _flame;
+ SceneObject _hotspot4, _olloFace;
+ Necklace _necklace;
+ DisplayHotspot _hotspot7, _hotspot8, _hotspot9, _hotspot10;
+ DisplayHotspot _hotspot11, _hotspot12, _hotspot13, _hotspot14;
+ Action1 _action1;
+ Action _action2;
+ Action _action3;
+
+ Scene4045();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void stripCallback(int v);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene4050 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot15 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot17 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SpeakerPText _speakerPText;
+ SpeakerQText _speakerQText;
+ SpeakerGameText _speakerGameText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ DisplayHotspot _hotspot1, _hotspot2, _hotspot3, _hotspot4, _hotspot5;
+ DisplayHotspot _hotspot6, _hotspot7, _hotspot8, _hotspot9, _hotspot10;
+ DisplayHotspot _hotspot11, _hotspot12, _hotspot13;
+ SceneObject _hotspot14;
+ Hotspot15 _hotspot15;
+ SceneObject _hotspot16;
+ Hotspot17 _hotspot17;
+
+ Scene4050();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene4100 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Miranda : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Ladder : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot14 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SpeakerMText _speakerMText;
+ SpeakerML _speakerML;
+ SpeakerQText _speakerQText;
+ SpeakerQR _speakerQR;
+ SpeakerCHFText _speakerCHFText;
+ SpeakerCDRText _speakerCDRText;
+ SpeakerCDR _speakerCDR;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Hotspot1 _hotspot1;
+ Hotspot2 _hotspot2;
+ DisplayHotspot _hotspot3, _hotspot4;
+ Miranda _miranda;
+ Ladder _ladder;
+ DisplayHotspot _hotspot7, _hotspot8, _hotspot9, _hotspot10;
+ DisplayHotspot _hotspot11, _hotspot12, _hotspot13;
+ Hotspot14 _hotspot14;
+
+ Scene4100();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene4150 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class HotspotGroup1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class HotspotGroup3 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class HotspotGroup6 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+ class Hotspot3 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ SequenceManager _sequenceManager;
+ SoundHandler _soundHandler;
+ SpeakerQText _speakerQText;
+ SpeakerQR _speakerQR;
+ SpeakerCDL _speakerCDL;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ DisplayHotspot _hotspot1, _hotspot2;
+ Hotspot3 _hotspot3;
+ SceneObject _hotspot4;
+ HotspotGroup1 _hotspot5, _hotspot6;
+ DisplayHotspot _hotspot7, _hotspot8, _hotspot9, _hotspot10, _hotspot11, _hotspot12;
+ HotspotGroup3 _hotspot13, _hotspot14, _hotspot15, _hotspot16;
+ DisplayHotspot _hotspot17, _hotspot18, _hotspot19, _hotspot20, _hotspot21;
+ DisplayHotspot _hotspot22, _hotspot23, _hotspot24;
+ HotspotGroup6 _hotspot25, _hotspot26;
+
+ Scene4150();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene4250 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot4 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot6 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ SequenceManager _sequenceManager;
+ SoundHandler _soundHandler;
+ SpeakerSR _speakerSR;
+ SpeakerSL _speakerSL;
+ SpeakerSText _speakerSText;
+ SpeakerGameText _speakerGameText;
+ SpeakerQL _speakerQL;
+ SpeakerQR _speakerQR;
+ SpeakerQText _speakerQText;
+ SpeakerPText _speakerPText;
+ SpeakerMText _speakerMText;
+ SpeakerFLText _speakerFLText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Hotspot1 _hotspot1;
+ Hotspot2 _hotspot2;
+ SceneObject _hotspot3;
+ Hotspot4 _hotspot4;
+ SceneObject _hotspot5;
+ Hotspot6 _hotspot6;
+ DisplayHotspot _hotspot7;
+ Hotspot8 _hotspot8;
+
+ Scene4250();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene4300 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot9 : public NamedHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot10 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot15 : public SceneObject {
+ public:
+ virtual void signal();
+ };
+ class Hotspot16 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot17 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot19 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SoundHandler _soundHandler1, _soundHandler2;
+ SequenceManager _sequenceManager;
+ GfxButton _gfxButton;
+ SpeakerQText _speakerQText;
+ SpeakerSText _speakerSText;
+ SpeakerMText _speakerMText;
+ SpeakerFLText _speakerFLText;
+
+ SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4;
+ SceneObject _hotspot5, _hotspot6, _hotspot7;
+ Hotspot8 _hotspot8;
+ Hotspot9 _hotspot9;
+ Hotspot10 _hotspot10;
+ NamedHotspot _hotspot11;
+ SceneObject _hotspot12, _hotspot13, _hotspot14;
+ Hotspot15 _hotspot15;
+ Hotspot16 _hotspot16;
+ Hotspot17 _hotspot17;
+ DisplayHotspot _hotspot18;
+ Hotspot19 _hotspot19;
+ Action1 _action1;
+ Action2 _action2;
+
+ Scene4300();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void stripCallback(int v);
+ virtual void remove();
+ virtual void signal();
+ virtual void dispatch();
+ virtual void process(Event &event);
+};
+
+class Scene4301 : public Scene {
+ /* Actions */
+ class Action1 : public ActionExt {
+ public:
+ SceneObject _buttonList[6];
+ int _field34E;
+ int _indexList[6];
+
+ virtual void synchronise(Serialiser &s);
+ virtual void remove();
+ virtual void signal();
+ virtual void process(Event &event);
+ };
+
+ /* Hotspots */
+ class Hotspot4 : public NamedHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot5 : public NamedHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ Common::List<int> _list1;
+ SequenceManager _sequenceManager;
+ SoundHandler _soundHandler;
+ Action1 _action1;
+ SceneObject _hotspot1, _hotspot2, _hotspot3;
+ Hotspot4 _hotspot4;
+ Hotspot5 _hotspot5;
+ bool _field68E;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void dispatch();
+ virtual void synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ s.syncAsSint16LE(_field68E);
+ }
+};
+
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_scenes6.cpp b/engines/tsage/ringworld_scenes6.cpp
new file mode 100644
index 0000000000..17f7654e70
--- /dev/null
+++ b/engines/tsage/ringworld_scenes6.cpp
@@ -0,0 +1,2191 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/ringworld_scenes6.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+/*--------------------------------------------------------------------------
+ * Scene 5000 - Caverns - Entrance
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene5000::Action1::signal() {
+ // Ship landing
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ scene->_soundHandler.startSound(190);
+ scene->_soundHandler.proc5(true);
+ ADD_MOVER(scene->_hotspot1, 283, 12);
+ break;
+ case 2:
+ break;
+ case 3:
+ scene->_hotspot1._moveDiff.y = 1;
+ scene->_hotspot4.setPosition(Common::Point(scene->_hotspot1._position.x,
+ scene->_hotspot1._position.y + 15));
+ scene->_hotspot4.show();
+ setDelay(15);
+ break;
+ case 4:
+ scene->_soundHandler.proc4();
+ ADD_MOVER(scene->_hotspot1, 233, 80);
+ break;
+ case 5:
+ scene->_hotspot3.animate(ANIM_MODE_8, 0, NULL);
+ scene->_hotspot3.show();
+ ADD_MOVER(scene->_hotspot1, 233, 90);
+ break;
+ case 6:
+ scene->_hotspot3.remove();
+ scene->_hotspot2.setPosition(Common::Point(233, 76));
+ scene->_hotspot2.show();
+ scene->_hotspot2.animate(ANIM_MODE_5, this);
+
+ scene->_hotspot4.remove();
+ break;
+ case 7:
+ setDelay(60);
+ scene->_hotspot2.remove();
+ break;
+ case 8:
+ scene->_hotspot5.show();
+ scene->_hotspot5.animate(ANIM_MODE_5, this);
+ break;
+ case 9:
+ scene->setAction(&scene->_action2);
+ break;
+ }
+}
+
+void Scene5000::Action1::dispatch() {
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+ Action::dispatch();
+
+ if (_actionIndex == 3) {
+ if (scene->_hotspot1._percent % 2 == 0) {
+ ++scene->_hotspot1._position.y;
+ if (scene->_hotspot1._position.x > 233)
+ --scene->_hotspot1._position.x;
+ }
+
+ scene->_hotspot1.changeZoom(++scene->_hotspot1._percent);
+ scene->_hotspot1._flags |= OBJFLAG_PANES;
+
+ if (scene->_hotspot1._percent >= 100)
+ signal();
+ }
+
+ if ((_actionIndex == 5) || (_actionIndex == 6)) {
+ scene->_hotspot4.setPosition(Common::Point(scene->_hotspot1._position.x,
+ scene->_hotspot1._position.y + 15));
+ }
+}
+
+void Scene5000::Action2::signal() {
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.setPosition(Common::Point(217, 76));
+ setDelay(10);
+ break;
+ case 1:
+ _globals->_player.setStrip2(3);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ ADD_MOVER(_globals->_player, 214, 89);
+ break;
+ case 2:
+ if (!_globals->getFlag(59))
+ setAction(&scene->_action3, this);
+ _globals->_player.fixPriority(15);
+ ADD_MOVER(_globals->_player, 208, 100);
+ break;
+ case 3:
+ ADD_MOVER(_globals->_player, 213, 98);
+ break;
+ case 4:
+ ADD_MOVER(_globals->_player, 215, 115);
+ break;
+ case 5:
+ _globals->_player.changeZoom(47);
+ ADD_MOVER(_globals->_player, 220, 125);
+ break;
+ case 6:
+ ADD_MOVER(_globals->_player, 229, 115);
+ break;
+ case 7:
+ _globals->_player.changeZoom(-1);
+ _globals->_player.fixPriority(35);
+ ADD_MOVER(_globals->_player, 201, 166);
+ break;
+ case 8:
+ _globals->_player.updateZoom();
+ ADD_MOVER(_globals->_player, 205, 146);
+ break;
+ case 9:
+ _globals->_player.changeZoom(-1);
+ _globals->_player.fixPriority(50);
+ ADD_MOVER(_globals->_player, 220, 182);
+ break;
+ case 10:
+ _globals->_player.updateZoom();
+ ADD_MOVER(_globals->_player, 208, 163);
+ break;
+ case 11:
+ _globals->_player.changeZoom(-1);
+ _globals->_player.setStrip2(-1);
+ _globals->_player.fixPriority(-1);
+ ADD_MOVER(_globals->_player, 208, 175);
+ break;
+ case 12:
+ _globals->_player.setStrip(8);
+ _globals->_player.setFrame(1);
+ setDelay(10);
+ break;
+ case 13:
+ if (!_globals->_sceneObjects->contains(&scene->_hotspot7))
+ setDelay(10);
+ break;
+ case 14:
+ setDelay(30);
+ break;
+ case 15:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene5000::Action3::signal() {
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(10);
+ break;
+ case 1:
+ scene->_hotspot7.postInit();
+ scene->_hotspot7.setVisage(2809);
+ scene->_hotspot7.setObjectWrapper(new SceneObjectWrapper());
+ scene->_hotspot7.setPosition(Common::Point(217, 76));
+ scene->_hotspot7.changeZoom(10);
+ scene->_hotspot7.setStrip2(3);
+ scene->_hotspot7.fixPriority(200);
+ scene->_hotspot7._moveDiff.y = 2;
+ scene->_hotspot7.animate(ANIM_MODE_1, NULL);
+ ADD_MOVER(scene->_hotspot7, 214, 89);
+
+ _globals->_sceneItems.push_front(&scene->_hotspot7);
+ break;
+ case 2:
+ scene->_hotspot7.changeZoom(-1);
+ scene->_hotspot7.fixPriority(14);
+ ADD_MOVER(scene->_hotspot7, 208, 100);
+ break;
+ case 3:
+ ADD_MOVER(scene->_hotspot7, 213, 98);
+ break;
+ case 4:
+ scene->_hotspot7.fixPriority(19);
+ ADD_MOVER(scene->_hotspot7, 213, 98);
+ break;
+ case 5:
+ scene->_hotspot7.changeZoom(46);
+ ADD_MOVER(scene->_hotspot7, 220, 125);
+ break;
+ case 6:
+ ADD_MOVER(scene->_hotspot7, 229, 115);
+ break;
+ case 7:
+ scene->_hotspot7.changeZoom(-1);
+ scene->_hotspot7.fixPriority(34);
+ ADD_MOVER(scene->_hotspot7, 201, 166);
+ break;
+ case 8:
+ scene->_hotspot7.updateZoom();
+ ADD_MOVER(scene->_hotspot7, 205, 146);
+ break;
+ case 9:
+ scene->_hotspot7.changeZoom(-1);
+ scene->_hotspot7.fixPriority(49);
+ ADD_MOVER(scene->_hotspot7, 210, 182);
+ break;
+ case 10:
+ scene->_hotspot7.updateZoom();
+ ADD_MOVER(scene->_hotspot7, 208, 163);
+ break;
+ case 11:
+ scene->_hotspot7.changeZoom(-1);
+ scene->_hotspot7.setStrip2(-1);
+ scene->_hotspot7.fixPriority(-1);
+ ADD_MOVER(scene->_hotspot7, 175, 166);
+ break;
+ case 12:
+ ADD_MOVER(scene->_hotspot7, 126, 146);
+ break;
+ case 13:
+ scene->_hotspot7.setStrip(2);
+ remove();
+ break;
+ }
+}
+
+void Scene5000::Action4::signal() {
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1);
+ break;
+ case 1:
+ _globals->_player.fixPriority(50);
+ _globals->_player.setStrip2(4);
+ ADD_MOVER(_globals->_player, 210, 182);
+ break;
+ case 2:
+ ADD_MOVER(_globals->_player, 205, 146);
+ break;
+ case 3:
+ _globals->_player.fixPriority(35);
+ ADD_MOVER(_globals->_player, 201, 166);
+ break;
+ case 4:
+ ADD_MOVER(_globals->_player, 229, 115);
+ break;
+ case 5:
+ _globals->_player.fixPriority(20);
+ _globals->_player.changeZoom(47);
+ ADD_MOVER(_globals->_player, 220, 125);
+ break;
+ case 6:
+ ADD_MOVER(_globals->_player, 215, 115);
+ break;
+ case 7:
+ _globals->_player.changeZoom(-1);
+ ADD_MOVER(_globals->_player, 213, 98);
+ break;
+ case 8:
+ _globals->_player.fixPriority(15);
+ ADD_MOVER(_globals->_player, 208, 100);
+ break;
+ case 9:
+ ADD_MOVER(_globals->_player, 214, 89);
+ break;
+ case 10:
+ ADD_MOVER(_globals->_player, 217, 76);
+ break;
+ case 11:
+ _globals->_player.hide();
+ setDelay(60);
+ break;
+ case 12:
+ if (!_globals->_sceneObjects->contains(&scene->_hotspot7))
+ _globals->_sceneManager.changeScene(2320);
+ remove();
+ break;
+ }
+}
+
+void Scene5000::Action5::signal() {
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ ADD_MOVER(_globals->_player, 91, 155);
+ break;
+ case 1:
+ _globals->_player.setVisage(2670);
+ _globals->_player._strip = 4;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ SceneItem::display2(5000, _globals->_sceneObjects->contains(&scene->_hotspot7) ? 17 : 13);
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 3:
+ _globals->_player.setVisage(0);
+ _globals->_player._strip = 8;
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ _globals->_player.enableControl();
+ remove();
+ }
+}
+
+void Scene5000::Action6::signal() {
+ // Discussion between the hero and Seeker, then the hero goes back to the lander
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ _globals->_events.setCursor(CURSOR_WALK);
+ scene->_stripManager.start(2150, this);
+ break;
+ case 2:
+ _globals->_events.setCursor(CURSOR_NONE);
+ scene->setAction(&scene->_sequenceManager, this, 5001, &scene->_hotspot7, NULL);
+ break;
+ case 3:
+ ADD_PLAYER_MOVER(208, 163);
+ break;
+ case 4:
+ _globals->_player.fixPriority(50);
+ _globals->_player.setStrip2(4);
+ ADD_MOVER(_globals->_player, 210, 182);
+ break;
+ case 5:
+ _globals->_sceneManager.changeScene(2100);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene5000::Hotspot7::doAction(int action) {
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5000, 12);
+ break;
+ case CURSOR_TALK:
+ scene->setAction(&scene->_action6);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5000::Hotspot8::doAction(int action) {
+ // Cave
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5000, 10);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(5000, 14);
+ break;
+ case OBJECT_SCANNER:
+ scene->setAction(&scene->_action5);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5000::HotspotGroup1::doAction(int action) {
+ Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene;
+
+ if (_globals->_sceneObjects->contains(&scene->_hotspot7))
+ scene->setAction(&scene->_action6);
+ else
+ SceneItem::display2(5000, 11);
+}
+/*--------------------------------------------------------------------------*/
+
+Scene5000::Scene5000() :
+ _hotspot1(0, CURSOR_LOOK, 5000, 3, LIST_END),
+ _hotspot12(0, CURSOR_LOOK, 5000, 6, CURSOR_USE, 5000, 7, OBJECT_STUNNER, 5000, 14,
+ OBJECT_SCANNER, 5000, 16, LIST_END),
+ _hotspot13(0, CURSOR_LOOK, 5000, 8, CURSOR_USE, 5000, 9, OBJECT_STUNNER, 5000, 0,
+ OBJECT_SCANNER, 5000, 16, LIST_END),
+ _hotspot14(0, CURSOR_LOOK, 5000, 8, CURSOR_USE, 5000, 9, OBJECT_STUNNER, 5000, 0,
+ OBJECT_SCANNER, 5000, 16, LIST_END),
+ _hotspot15(0, CURSOR_LOOK, 5000, 2, OBJECT_STUNNER, 5000, 15, LIST_END),
+ _hotspot16(0, CURSOR_LOOK, 5000, 4, CURSOR_USE, 5000, 5, LIST_END),
+ _hotspot17(0, CURSOR_LOOK, 5000, 1, LIST_END),
+ _hotspot18(0, CURSOR_LOOK, 5000, 0, LIST_END) {
+}
+
+
+void Scene5000::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ loadScene(5000);
+
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerQText);
+
+ _globals->_player.postInit();
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player._moveDiff = Common::Point(4, 2);
+ _globals->_player.changeZoom(-1);
+ _globals->_player.disableControl();
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(5001);
+ _hotspot1.setFrame2(1);
+ _hotspot1._moveDiff = Common::Point(5, 5);
+ _hotspot1.fixPriority(10);
+ _hotspot1.changeZoom(10);
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(5001);
+ _hotspot4.setStrip2(2);
+ _hotspot4._moveDiff = Common::Point(5, 1);
+ _hotspot4.fixPriority(10);
+ _hotspot4.changeZoom(100);
+ _hotspot4.animate(ANIM_MODE_8, 0, NULL);
+ _hotspot4.hide();
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(5001);
+ _hotspot2.setStrip2(3);
+ _hotspot2._numFrames = 5;
+ _hotspot2.hide();
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(5001);
+ _hotspot3.setStrip2(5);
+ _hotspot3._numFrames = 5;
+ _hotspot3.setPosition(Common::Point(233, 76));
+ _hotspot3.hide();
+
+ _hotspot5.postInit();
+ _hotspot5.setVisage(5001);
+ _hotspot5.setStrip2(4);
+ _hotspot5._numFrames = 5;
+ _hotspot5.fixPriority(15);
+ _hotspot5.setPosition(Common::Point(218, 76));
+ _hotspot5.hide();
+
+ _hotspot9.postInit();
+ _hotspot9.setVisage(5002);
+ _hotspot9.fixPriority(80);
+ _hotspot9.setPosition(Common::Point(71, 174));
+
+ _hotspot10.postInit();
+ _hotspot10.setVisage(5002);
+ _hotspot10.setStrip2(2);
+ _hotspot10.setPosition(Common::Point(87, 120));
+
+ _hotspot11.postInit();
+ _hotspot11.setVisage(5002);
+ _hotspot11.setStrip2(2);
+ _hotspot11.setFrame(3);
+ _hotspot10.setPosition(Common::Point(93, 118));
+
+ setZoomPercents(95, 10, 145, 100);
+
+ _hotspot8.setBounds(Rect(0, 73, 87, 144));
+ _hotspot18.setBounds(Rect(54, 0, 319, 85));
+ _hotspot17.setBounds(Rect(184, 0, 199, 79));
+ _hotspot13.setBounds(Rect(0, 164, 135, 200));
+ _hotspot14.setBounds(Rect(0, 0, 105, 140));
+ _hotspot15.setBounds(Rect(266, 70, 291, 85));
+ _hotspot16.setBounds(Rect(0, 86, 319, 200));
+ _hotspot12.setBounds(Rect(230, 143, 244, 150));
+
+ _globals->_sceneItems.addItems(&_hotspot9, &_hotspot10, &_hotspot11, &_hotspot8, &_hotspot13,
+ &_hotspot14, &_hotspot12, &_hotspot15, &_hotspot17, &_hotspot18, &_hotspot16, NULL);
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 1000:
+ case 2100:
+ case 2320:
+ if (_globals->getFlag(59)) {
+ _hotspot1.setPosition(Common::Point(233, 90));
+ _hotspot1.changeZoom(100);
+ _hotspot1.show();
+
+ _hotspot5.setFrame(1);
+ _hotspot5.animate(ANIM_MODE_5, NULL);
+ _hotspot5.setPosition(Common::Point(218, 76));
+ _hotspot5.show();
+
+ _globals->_player.setPosition(Common::Point(217, -10));
+ _globals->_player.disableControl();
+
+ setAction(&_action2);
+ } else {
+ _globals->_player.setPosition(Common::Point(217, -10));
+ _hotspot1.setPosition(Common::Point(320, -10));
+ _globals->_player.disableControl();
+
+ setAction(&_action1);
+ }
+ break;
+ default:
+ _globals->_player.disableControl();
+ _globals->_player.setPosition(Common::Point(0, 146));
+
+ _hotspot1.changeZoom(100);
+ _hotspot1.setPosition(Common::Point(233, 90));
+ _hotspot1.show();
+
+ _hotspot5.setFrame(_hotspot5.getFrameCount());
+ _hotspot5.show();
+
+ _sceneMode = 5004;
+ setAction(&_sequenceManager, this, 5004, &_globals->_player, NULL);
+ break;
+ }
+
+ _globals->_soundHandler.startSound(190);
+}
+
+void Scene5000::signal() {
+ switch (_sceneMode) {
+ case 5002:
+ case 5003:
+ case 5004:
+ _globals->_player.enableControl();
+ break;
+ case 5005:
+ _globals->_sceneManager.changeScene(5100);
+ break;
+ }
+}
+
+void Scene5000::dispatch() {
+ Scene::dispatch();
+
+ if (!_action) {
+ if (!_globals->_sceneObjects->contains(&_hotspot7) && (_globals->_player.getRegionIndex() == 10)) {
+ _globals->_player.disableControl();
+ _sceneMode = 5005;
+ setAction(&_sequenceManager, this, 5005, &_globals->_player, NULL);
+ }
+
+ if (_globals->_player.getRegionIndex() == 8) {
+ _globals->_player.disableControl();
+
+ if (_globals->_sceneObjects->contains(&_hotspot7)) {
+ _sceneMode = 5003;
+ _globals->_player.addMover(NULL);
+ setAction(&_sequenceManager, this, 5003, &_globals->_player, NULL);
+ } else {
+ setAction(&_action4);
+ }
+ }
+
+ if (_globals->_sceneObjects->contains(&_hotspot7) && (_globals->_player.getRegionIndex() == 15)) {
+ _sceneMode = 5002;
+ _globals->_player.disableControl();
+ _globals->_player.addMover(NULL);
+ setAction(&_sequenceManager, this, 5002, &_globals->_player, NULL);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 5100 - Caverns
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene5100::Action1::signal() {
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1:
+ ADD_MOVER(_globals->_player, 1111, 165);
+ break;
+ case 2:
+ _globals->_player.setStrip(6);
+ _globals->_player.setFrame(1);
+ setDelay(60);
+ break;
+ case 3:
+ if (_globals->getFlag(10)) {
+ _globals->_player.enableControl();
+ remove();
+ } else {
+ _globals->setFlag(10);
+ scene->_stripManager.start(5102, this);
+ }
+ break;
+ case 4:
+ scene->_soundHandler.startSound(206);
+
+ scene->_hotspot5.postInit();
+ scene->_hotspot5.setVisage(5362);
+ scene->_hotspot5.setPosition(Common::Point(1160, 34));
+ scene->_hotspot5.setStrip2(2);
+ scene->_hotspot5.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot5.fixPriority(10);
+
+ _globals->_sceneItems.push_front(&scene->_hotspot5);
+ ADD_MOVER(scene->_hotspot5, 999, 14);
+ break;
+ case 5:
+ scene->_hotspot5.setStrip2(4);
+ scene->_hotspot5._frame = 1;
+ scene->_hotspot5.animate(ANIM_MODE_5, this);
+ break;
+ case 6:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene5100::Action2::signal() {
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(5);
+ break;
+ case 1:
+ if (scene->_hotspot8._visage == 2806)
+ setDelay(1);
+ else
+ scene->_hotspot8.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ if (scene->_hotspot8._visage != 2806) {
+ scene->_hotspot8.setVisage(2806);
+ scene->_hotspot8.setPosition(Common::Point(548, 193));
+ scene->_hotspot8.animate(ANIM_MODE_1, NULL);
+ scene->_hotspot8._angle = 325;
+ scene->_hotspot8.setObjectWrapper(new SceneObjectWrapper());
+ scene->_hotspot8.setStrip(8);
+ }
+
+ scene->_stripManager.start(5129, this);
+ break;
+ case 3:
+ if (_globals->_player._position.x >= 966) {
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot8, 1215, 155);
+ } else {
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot8, 966, 185);
+ }
+
+ if (_globals->_player._position.x >= 966) {
+ setDelay(1);
+ } else {
+ ADD_PLAYER_MOVER(966, 190);
+ }
+ break;
+ case 4:
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot8, 1215, 155);
+ ADD_PLAYER_MOVER(1215, 155);
+ break;
+ case 5:
+ _globals->_sceneManager.changeScene(2100);
+ break;
+ }
+}
+
+void Scene5100::Action3::signal() {
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->setFlag(62);
+ _globals->_player.disableControl();
+ _globals->_player.addMover(NULL);
+
+ scene->_hotspot2.addMover(NULL);
+ scene->_hotspot3.addMover(NULL);
+ _globals->_player.setVisage(2672);
+
+ if (static_cast<SceneObject *>(_owner)->_position.x >= _globals->_player._position.x)
+ _globals->_player._strip = 4;
+ else
+ _globals->_player._strip = 3;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 1:
+ _globals->_player.setVisage(2674);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ scene->_soundHandler.startSound(28);
+ if (static_cast<SceneObject *>(_owner)->_position.x < _globals->_player._position.x) {
+ scene->_hotspot2.setVisage(5130);
+ scene->_hotspot2._strip = 1;
+ scene->_hotspot2._frame = 1;
+ scene->_hotspot2.animate(ANIM_MODE_5, this);
+ scene->_hotspot2.setAction(NULL);
+
+ scene->_hotspot3.setStrip2(1);
+ ADD_PLAYER_MOVER_THIS(scene->_hotspot3, 1200, 100);
+ } else {
+ scene->_hotspot3.setVisage(5130);
+ scene->_hotspot3._strip = 1;
+ scene->_hotspot3._frame = 1;
+ scene->_hotspot3.animate(ANIM_MODE_5, this);
+ scene->_hotspot3.setAction(NULL);
+
+ scene->_hotspot2.setStrip2(2);
+ ADD_PLAYER_MOVER_NULL(scene->_hotspot2, 10, 140);
+
+ }
+
+ _globals->_player.setVisage(2672);
+ _globals->_player._frame = _globals->_player.getFrameCount();
+ _globals->_player.animate(ANIM_MODE_6, this);
+ break;
+ case 3:
+ break;
+ case 4:
+ SceneItem::display2(5100, 38);
+ _globals->_player.enableControl();
+
+ _globals->_player.setVisage(0);
+ _globals->_player._strip = 8;
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ remove();
+ break;
+ }
+}
+
+void Scene5100::Action4::signal() {
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ _globals->_player.disableControl();
+ scene->_soundHandler.startSound(208);
+ SceneItem::display2(5100, 15);
+
+ ObjectMover3 *mover = new ObjectMover3();
+ scene->_hotspot2.addMover(mover, &_globals->_player, 20, this);
+ break;
+ }
+ case 1:
+ scene->_hotspot1.postInit();
+ scene->_hotspot1.setVisage(5120);
+ scene->_hotspot1.setPosition(Common::Point(795, 161));
+ scene->_hotspot1._strip = 4;
+ scene->_hotspot1.animate(ANIM_MODE_5, this);
+ break;
+ case 2:
+ setDelay(15);
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(5200);
+ break;
+ }
+}
+
+void Scene5100::Action5::signal() {
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(60);
+ break;
+ case 1:
+ scene->_stripManager.start(5128, this);
+ break;
+ case 2:
+ setDelay(15);
+ break;
+ case 3:
+ scene->_sceneMode = 5106;
+ scene->setAction(&scene->_sequenceManager, scene, 5106, &_globals->_player, NULL);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene5100::HotspotGroup1::doAction(int action) {
+ // Flesh Eaters
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5100, _globals->getFlag(62) ? 41 : 26);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(5100, 11);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(5100, 17);
+ break;
+ case OBJECT_STUNNER:
+ if (_globals->getFlag(62))
+ SceneItem::display2(5100, 42);
+ else
+ setAction(&scene->_action3);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5100::Hotspot4::doAction(int action) {
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5100, 31);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5110;
+ scene->setAction(&scene->_sequenceManager, scene, 5110, &_globals->_player, this, &scene->_hotspot7, NULL);
+ break;
+ case CURSOR_TALK:
+ SceneItem::display2(5100, 34);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(5100, 36);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(5100, 37);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5100::HotspotGroup2::doAction(int action) {
+ // Bat
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5100, _globals->getFlag(108) ? 47 : 23);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(5100, 29);
+ break;
+ case CURSOR_TALK:
+ if (_position.x >= 600)
+ SceneItem::display2(5100, 28);
+ else {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5114;
+ scene->setAction(&scene->_sequenceManager, scene, 5114, NULL);
+ }
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(5100, 43);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5100::Hotspot9::doAction(int action) {
+ // Rope
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5100, 32);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5117;
+ scene->setAction(&scene->_sequenceManager, scene, 5117, &_globals->_player, NULL);
+ break;
+ case OBJECT_STUNNER:
+ SceneItem::display2(5100, 35);
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(5100, 44);
+ break;
+ case OBJECT_BONE:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5116;
+ scene->setAction(&scene->_sequenceManager, scene, 5116, &_globals->_player, this, &scene->_hotspot10,
+ &scene->_hotspot4, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5100::Hotspot17::doAction(int action) {
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5100, 18);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(67))
+ SceneItem::display2(5100, 19);
+ else {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5101;
+ scene->setAction(&scene->_sequenceManager, scene, 5101, &_globals->_player, this, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5100::Hotspot18::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->_sceneManager._previousScene != 5000) {
+ SceneItem::display2(5100, 3);
+ } else {
+ switch (_index1) {
+ case 0:
+ SceneItem::display2(5100, 0);
+ ++_index1;
+ break;
+ case 1:
+ SceneItem::display2(5100, 1);
+ ++_index1;
+ break;
+ default:
+ SceneItem::display2(5100, 2);
+ break;
+ }
+ }
+ break;
+ case CURSOR_USE:
+ switch (_index2) {
+ case 0:
+ SceneItem::display2(5100, 8);
+ ++_index2;
+ break;
+ case 1:
+ SceneItem::display2(5100, 9);
+ ++_index2;
+ break;
+ default:
+ SceneItem::display2(5100, 10);
+ break;
+ }
+ break;
+
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5100::Hotspot19::doAction(int action) {
+ // Pillar
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5100, _globals->_sceneObjects->contains(&scene->_hotspot14) ? 27 : 20);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5106;
+
+ if (_globals->getFlag(66))
+ scene->setAction(&scene->_sequenceManager, scene, 5113, &_globals->_player, NULL);
+ else {
+ _globals->setFlag(66);
+ scene->setAction(&scene->_sequenceManager, scene, 5106, &_globals->_player, &scene->_hotspot14, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5100::Hotspot20::doAction(int action) {
+ Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5100, 21);
+ break;
+ case CURSOR_USE:
+ _globals->_player.disableControl();
+
+ if (_globals->getFlag(67)) {
+ scene->_sceneMode = 5112;
+ scene->setAction(&scene->_sequenceManager, scene, 5112, &_globals->_player, NULL);
+ } else {
+ scene->_sceneMode = 5101;
+ scene->setAction(&scene->_sequenceManager, scene, 5106, &_globals->_player, &scene->_hotspot17, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene5100::Scene5100() :
+ _hotspot16(0, CURSOR_LOOK, 5100, 48, LIST_END),
+ _hotspot21(0, CURSOR_LOOK, 5100, 4, CURSOR_USE, 5100, 5, LIST_END) {
+}
+
+void Scene5100::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(50, 10, 200, 100);
+ _sceneMode = 0;
+
+ _stripManager.addSpeaker(&_speakerMText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerGameText);
+ _stripManager.addSpeaker(&_speakerBatText);
+ _speakerQText._npc = &_globals->_player;
+ _speakerMText._npc = &_globals->_player;
+ _speakerSText._npc = &_hotspot8;
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.disableControl();
+
+ if (!_globals->getFlag(66)) {
+ _hotspot14.postInit();
+ _hotspot14.setVisage(5101);
+ _hotspot14.setPosition(Common::Point(498, 147));
+ _hotspot14.fixPriority(200);
+ _hotspot14._moveDiff.y = 10;
+ }
+
+ _hotspot17.postInit();
+ _hotspot17.setVisage(5101);
+ _hotspot17._strip = 2;
+ _hotspot17.fixPriority(200);
+
+ if (_globals->getFlag(67))
+ _hotspot17.setPosition(Common::Point(554, 192));
+ else
+ _hotspot17.setPosition(Common::Point(539, 179));
+
+ _hotspot19.setBounds(Rect(488, 115, 508, 148));
+ _hotspot21.setBounds(Rect(1150, 85, 1173, 112));
+ _hotspot20.setBounds(Rect(517, 193, 562, 200));
+ _globals->_sceneItems.addItems(&_hotspot19, &_hotspot21, NULL);
+
+ if (_globals->getFlag(67)) {
+ _globals->_sceneItems.addItems(&_hotspot20, &_hotspot17, NULL);
+ } else {
+ _globals->_sceneItems.addItems(&_hotspot17, &_hotspot20, NULL);
+ }
+
+ if (!_globals->getFlag(105)) {
+ _hotspot4.postInit();
+ _hotspot4.setVisage(5363);
+ _hotspot4.setPosition(Common::Point(1025, 65));
+ _hotspot4.setStrip(4);
+ _hotspot4.animate(ANIM_MODE_7, 0, NULL);;
+ _globals->_sceneItems.push_back(&_hotspot4);
+
+ _hotspot9.postInit();
+ _hotspot9.setVisage(5363);
+ _hotspot9.setPosition(Common::Point(966, 120));
+ _globals->_sceneItems.push_back(&_hotspot9);
+
+ _hotspot10.postInit();
+ _hotspot10.setVisage(5363);
+ _hotspot10.setPosition(Common::Point(999, 68));
+ _hotspot10.setStrip(2);
+
+ _hotspot6.postInit();
+ _hotspot6.setVisage(5362);
+ _hotspot6.setPosition(Common::Point(1017, 34));
+ _hotspot6._strip = 4;
+ _hotspot6._frame = _hotspot6.getFrameCount();
+ _globals->_sceneItems.push_back(&_hotspot6);
+ }
+
+ _hotspot16._sceneRegionId = 15;
+ _globals->_sceneItems.push_back(&_hotspot16);
+
+ if (!_globals->getFlag(62)) {
+ _hotspot2.postInit();
+ _hotspot2.setVisage(5110);
+ _hotspot2.animate(ANIM_MODE_1, NULL);
+ _hotspot2._moveDiff.x = 4;
+ _globals->_sceneItems.push_back(&_hotspot2);
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(5110);
+ _hotspot3.animate(ANIM_MODE_1, NULL);
+ _hotspot3._moveDiff.x = 4;
+ _globals->_sceneItems.push_back(&_hotspot3);
+
+ if (_globals->getFlag(61)) {
+ _hotspot2.setPosition(Common::Point(483, 189));
+ _hotspot3.setPosition(Common::Point(811, 182));
+ } else {
+ _hotspot2.setPosition(Common::Point(610, 170));
+ _hotspot3.setPosition(Common::Point(600, 180));
+ }
+ }
+
+ if (_globals->getFlag(60) && (RING_INVENTORY._stasisBox._sceneNumber == 1) &&
+ _globals->getFlag(107) && _globals->getFlag(67)) {
+ _hotspot8.postInit();
+ _hotspot8.setVisage(2806);
+ _hotspot8.setPosition(Common::Point(557, 178));
+ _hotspot8.animate(ANIM_MODE_1, NULL);
+ _hotspot8.setObjectWrapper(new SceneObjectWrapper());
+
+ _globals->clearFlag(59);
+ }
+
+ switch (_globals->_sceneManager._previousScene) {
+ case 5000:
+ default:
+ _globals->_player.setPosition(Common::Point(1184, 160));
+ setAction(&_action1);
+ break;
+ case 5200:
+ if (_globals->_stripNum == 5200) {
+ _globals->_player.setVisage(5101);
+ _globals->_player.fixPriority(200);
+ _globals->_player.setStrip(5);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(513, 199));
+
+ _sceneMode = 5108;
+ setAction(&_sequenceManager, this, 5108, &_globals->_player, NULL);
+ } else {
+ _globals->_player.setPosition(Common::Point(20, 175));
+
+ _hotspot13.postInit();
+ _hotspot13.setVisage(5110);
+ _hotspot13.setPosition(Common::Point(578, 192));
+ _hotspot13._strip = 2;
+
+ _hotspot11.postInit();
+ _hotspot11.setVisage(5110);
+ _hotspot11.setPosition(Common::Point(5, 162));
+ _hotspot11.setStrip2(1);
+ _hotspot11._moveDiff = Common::Point(4, 2);
+ _hotspot11.animate(ANIM_MODE_1, NULL);
+
+ ObjectMover2 *mover = new ObjectMover2();
+ _hotspot11.addMover(mover, 15, 20, &_globals->_player);
+
+ _hotspot12.postInit();
+ _hotspot12.setVisage(5110);
+ _hotspot12.setPosition(Common::Point(15, 164));
+ _hotspot12.setStrip2(1);
+ _hotspot12._moveDiff = Common::Point(4, 2);
+ _hotspot12.animate(ANIM_MODE_1, NULL);
+
+ ObjectMover2 *mover2 = new ObjectMover2();
+ _hotspot12.addMover(mover2, 25, 50, &_globals->_player);
+
+ _hotspot17.setPosition(Common::Point(554, 182));
+ _globals->_player.disableControl();
+
+ _sceneMode = 5105;
+ setAction(&_sequenceManager, this, 5105, &_globals->_player, NULL);
+ }
+ break;
+ case 5300:
+ switch (_globals->_stripNum) {
+ case 5300:
+ _sceneMode = 5111;
+
+ _globals->_player.setVisage(5101);
+ _globals->_player.setStrip(6);
+ _globals->_player.fixPriority(170);
+ _globals->_player.setPosition(Common::Point(1168, 110));
+
+ setAction(&_sequenceManager, this, 5111, &_globals->_player, NULL);
+ _hotspot8.setPosition(Common::Point(1107, 178));
+ break;
+ case 5302:
+ _globals->_player.setPosition(Common::Point(512, 190));
+
+ if (_globals->_sceneObjects->contains(&_hotspot8))
+ setAction(&_action2);
+ else
+ _globals->_player.enableControl();
+ break;
+ case 5303:
+ _hotspot8.setVisage(5102);
+ _hotspot8.setPosition(Common::Point(533, 172));
+ _globals->_player.setPosition(Common::Point(512, 190));
+ setAction(&_action2);
+ break;
+ }
+
+ if (_globals->getFlag(108)) {
+ _hotspot6.postInit();
+ _hotspot6.setVisage(5362);
+ _hotspot6.setPosition(Common::Point(542, 19));
+ _hotspot6.setStrip(6);
+ _hotspot6.setFrame(1);
+ _globals->_sceneItems.push_back(&_hotspot6);
+ } else if (RING_INVENTORY._vial._sceneNumber != 5100) {
+ _hotspot6.postInit();
+ _hotspot6.setVisage(5362);
+ _hotspot6.setPosition(Common::Point(1152, 70));
+ _hotspot6.fixPriority(170);
+ _hotspot6.setStrip(6);
+ _hotspot6.setFrame(1);
+ _globals->_sceneItems.push_back(&_hotspot6);
+ }
+ break;
+ }
+
+ _hotspot18.setBounds(Rect(0, 0, 1280, 200));
+ _globals->_sceneItems.push_back(&_hotspot18);
+
+ _hotspot15.postInit();
+ _hotspot15.setVisage(5140);
+ _hotspot15.setStrip(3);
+ _hotspot15.setPosition(Common::Point(977, 173));
+ _hotspot15.fixPriority(1);
+
+ _globals->_sceneManager._scene->_sceneBounds.center(_globals->_player._position);
+ loadScene(5100);
+ _globals->_soundHandler.startSound(205);
+}
+
+void Scene5100::signal() {
+ switch (_sceneMode) {
+ case 5101:
+ case 5112:
+ _globals->setFlag(67);
+ _globals->_sceneManager.changeScene(5300);
+ break;
+ case 5102:
+ case 5114:
+ _globals->_player.enableControl();
+ break;
+ case 5103:
+ if (_globals->getFlag(61)) {
+ SceneItem::display2(5100, 46);
+ _globals->_sceneManager.changeScene(5300);
+ } else {
+ SceneItem::display2(5100, 45);
+ _globals->_sceneManager.changeScene(5200);
+ }
+ break;
+ case 5105:
+ _globals->_sceneManager.changeScene(5300);
+ break;
+ case 5106:
+ _globals->_stripNum = 5111;
+ _globals->_sceneManager.changeScene(5200);
+ break;
+ case 5108:
+ if (!_globals->getFlag(60))
+ _globals->_player.enableControl();
+ else if (RING_INVENTORY._stasisBox._sceneNumber == 1)
+ setAction(&_action2);
+ else
+ setAction(&_action5);
+ break;
+ case 5110:
+ SceneItem::display2(5100, 30);
+ _globals->_player._angle = 325;
+ _globals->_player.enableControl();
+ break;
+ case 5111:
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setVisage(0);
+ _globals->_player.setStrip(6);
+ _globals->_player.fixPriority(-1);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ if ((RING_INVENTORY._vial._sceneNumber != 5100) && !_globals->getFlag(108)) {
+ _globals->setFlag(108);
+ _sceneMode = 5130;
+ _globals->_player.disableControl();
+
+ _speakerBatText.setTextPos(Common::Point(_globals->_sceneManager._scene->_sceneBounds.left + 20, 30));
+ setAction(&_sequenceManager, this, 5130, &_globals->_player, &_hotspot6, NULL);
+ } else if (_globals->_sceneObjects->contains(&_hotspot8)) {
+ setAction(&_action2);
+ } else {
+ _globals->_player.enableControl();
+ }
+ break;
+ case 5116:
+ _globals->setFlag(105);
+ RING_INVENTORY._bone._sceneNumber = 0;
+
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setVisage(0);
+ _globals->_player.setStrip(6);
+ _globals->_player.fixPriority(-1);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ // No break on purpose
+ case 5117:
+ _globals->_player.enableControl();
+ break;
+ case 5130:
+ _hotspot6.setVisage(5362);
+ _hotspot6.setPosition(Common::Point(542, 25));
+ _hotspot6.setStrip(6);
+ _hotspot6.setFrame(1);
+ _globals->_player.enableControl();
+ break;
+ case 5150:
+ _globals->clearFlag(60);
+ _globals->_sceneManager.changeScene(5300);
+ break;
+ }
+}
+
+void Scene5100::dispatch() {
+ // Flesheater trap
+ if (_hotspot15._bounds.contains(_globals->_player._position) && !_globals->_player._visage) {
+ _globals->_player.disableControl();
+ _globals->_player.addMover(NULL);
+
+ _soundHandler.startSound(207);
+ _sceneMode = 5103;
+ setAction(&_sequenceManager, this, (_globals->_player._position.x >= 966) ? 5104 : 5103,
+ &_globals->_player, &_hotspot15, NULL);
+ }
+
+ if (_globals->getFlag(61) && !_globals->getFlag(62) &&
+ ((_globals->_player._position.x - _hotspot2._position.x) < 160) &&
+ (_globals->_sceneManager._previousScene != 5200) &&
+ (_globals->_sceneManager._previousScene != 5150)) {
+ setAction(NULL);
+ _sceneMode = 5150;
+ _soundHandler.startSound(208);
+
+ if (RING_INVENTORY._vial._sceneNumber == 5100) {
+ _globals->_player.addMover(NULL);
+ _globals->_player.disableControl();
+ SceneItem::display2(5100, 39);
+ }
+
+ _hotspot2.setStrip2(1);
+ _hotspot3.setStrip2(2);
+
+ ObjectMover3 *mover1 = new ObjectMover3();
+ _hotspot2.addMover(mover1, &_globals->_player, 20, this);
+ ObjectMover3 *mover2 = new ObjectMover3();
+ _hotspot3.addMover(mover2, &_globals->_player, 20, this);
+ }
+
+ if (!_action) {
+ if (((_globals->_player._position.x - _hotspot2._position.x) < 130) && !_globals->getFlag(61)) {
+ _globals->_player._canWalk = false;
+ _globals->_player.addMover(NULL);
+
+ Common::Point pt(20, 25);
+ PlayerMover2 *mover = new PlayerMover2();
+ _hotspot3.addMover(mover, &pt, &_globals->_player);
+ setAction(&_action4);
+ }
+
+ if ((_globals->_sceneManager._scene->_backgroundBounds.right - 85) <= _globals->_player._position.x)
+ _globals->_sceneManager.changeScene(5000);
+
+ if (_globals->_player.getRegionIndex() == 8) {
+ _sceneMode = 5114;
+ setAction(&_sequenceManager, this, 5115, &_globals->_player, NULL);
+ }
+ }
+
+ Scene::dispatch();
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 5200 - Caverns - Throne Room
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene5200::Action1::signal() {
+ Scene5200 *scene = (Scene5200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(59) + 120);
+ break;
+ case 1:
+ scene->_hotspot3.animate(ANIM_MODE_8, 1, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene5200::Action2::signal() {
+ // Quinn obtains the stasis box from the flesheater throne room
+ Scene5200 *scene = (Scene5200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ ADD_PLAYER_MOVER(92, 52);
+ break;
+ case 1:
+ _globals->_player.setVisage(5202);
+ _globals->_player._strip = 4;
+ _globals->_player._frame = 1;
+ _globals->_player.animate(ANIM_MODE_4, 3, 1, this);
+ break;
+ case 2:
+ scene->_soundHandler.proc3();
+ scene->_hotspot14.remove();
+
+ RING_INVENTORY._stasisBox._sceneNumber = 1;
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ _globals->_player.setVisage(0);
+ _globals->_player._strip = 3;
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+
+ scene->_hotspot8.animate(ANIM_MODE_2, NULL);
+ ADD_MOVER(scene->_hotspot8, 141, 77);
+ break;
+ case 4:
+ scene->_soundHandler.startSound(303);
+
+ scene->_hotspot8._strip = 2;
+ scene->_hotspot8._frame = 1;
+ scene->_hotspot8.animate(ANIM_MODE_5, this);
+ break;
+ case 5:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene5200::Action3::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(5);
+ break;
+ case 1:
+ ADD_PLAYER_MOVER(285, 62);
+ break;
+ case 2:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene5200::Action4::signal() {
+ Scene5200 *scene = (Scene5200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(120);
+ break;
+ case 1:
+ _globals->_soundHandler.startSound(209);
+ scene->_stripManager.start(5202, this, scene);
+ break;
+ case 2:
+ scene->_hotspot6.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ setDelay(10);
+ break;
+ case 4:
+ scene->_stripManager.start(5204, this, scene);
+ break;
+ case 5:
+ setDelay(60);
+ break;
+ case 6:
+ _globals->_sceneManager.changeScene(5100);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene5200::Hotspot9::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (!_state) {
+ ++_state;
+ SceneItem::display2(5200, 5);
+ } else {
+ SceneItem::display2(5200, 6);
+ }
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(5200, 14);
+ break;
+ default:
+ SceneItem::doAction(action);
+ break;
+ }
+}
+
+void Scene5200::Hotspot10::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (!_state) {
+ ++_state;
+ SceneItem::display2(5200, 7);
+ } else {
+ SceneItem::display2(5200, 8);
+ }
+ break;
+ default:
+ SceneObject::doAction(action);
+ break;
+ }
+}
+
+void Scene5200::Hotspot14::doAction(int action) {
+ Scene5200 *scene = (Scene5200 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5200, 4);
+ break;
+ case CURSOR_USE:
+ scene->setAction(&scene->_action2);
+ break;
+ default:
+ SceneObject::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene5200::Scene5200() :
+ _hotspot11(0, CURSOR_LOOK, 5200, 0, CURSOR_USE, 5200, 13, LIST_END),
+ _hotspot12(10, CURSOR_LOOK, 5200, 9, LIST_END),
+ _hotspot13(8, CURSOR_LOOK, 5200, 0, CURSOR_USE, 5200, 13, LIST_END) {
+}
+
+
+void Scene5200::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(0, 150, 199, 150);
+ _fieldA = 5600;
+ _fieldE = 5100;
+
+ _hotspot9._state = 0;
+ _hotspot10._state = 0;
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerGameText);
+ _stripManager.addSpeaker(&_speakerFLText);
+ _stripManager.addSpeaker(&_speakerFLL);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.setCallback(this);
+
+ _speakerFLText._textPos.x = 160;
+ _speakerQText._textPos.x = 20;
+
+ if (RING_INVENTORY._stasisBox._sceneNumber == 5200) {
+ _soundHandler.startSound(216);
+ _soundHandler.proc5(true);
+
+ _hotspot14.postInit();
+ _hotspot14.setVisage(5202);
+ _hotspot14._strip = 3;
+ _hotspot14.setPosition(Common::Point(105, 52));
+ _hotspot14.fixPriority(90);
+
+ _hotspot8.postInit();
+ _hotspot8.setVisage(5202);
+ _hotspot8._strip = 1;
+ _hotspot8.setPosition(Common::Point(96, 53));
+ _hotspot8.fixPriority(90);
+ _globals->_sceneItems.push_back(&_hotspot14);
+ }
+
+ if (_globals->_stripNum == 5111) {
+ // Happens when the player enters the throne room via the secret passage,
+ // after talking with the bat. No NPCs are around and the player can
+ // obtain the stasis box.
+ _globals->_soundHandler.startSound(205);
+ _globals->_player.disableControl();
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.changeZoom(75);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip(1);
+ _globals->_player.setFrame(3);
+ _globals->_player.setPosition(Common::Point(307, 62));
+
+ setAction(&_action3);
+ } else {
+ // Happens when the player is captured by the flesh eaters the first time.
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2640);
+ _globals->_player._strip = 1;
+ _globals->_player._frame = 4;
+ _globals->_player.setPosition(Common::Point(105, 199));
+
+ _hotspot5.postInit();
+ _hotspot5.setVisage(5210);
+ _hotspot5._frame = 2;
+ _hotspot5.setPosition(Common::Point(189, 167));
+
+ _hotspot6.postInit();
+ _hotspot6.setVisage(5210);
+ _hotspot6._frame = 1;
+ _hotspot6._strip = 2;
+ _hotspot6.setPosition(Common::Point(159, 137));
+
+ _hotspot7.postInit();
+ _hotspot7.setVisage(5210);
+ _hotspot7._frame = 1;
+ _hotspot7._strip = 4;
+ _hotspot7.fixPriority(168);
+ _hotspot7.setPosition(Common::Point(186, 106));
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(5212);
+ _hotspot1._frame = 1;
+ _hotspot1.setPosition(Common::Point(62, 132));
+
+ _hotspot2.postInit();
+ _hotspot2.setVisage(5212);
+ _hotspot2._strip = 3;
+ _hotspot2.setPosition(Common::Point(148, 141));
+ _hotspot2.fixPriority(90);
+
+ _hotspot3.postInit();
+ _hotspot3.setVisage(5212);
+ _hotspot3._strip = 2;
+ _hotspot3.setPosition(Common::Point(62, 109));
+ _hotspot3.fixPriority(138);
+ _hotspot3.setAction(&_action1);
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(5212);
+ _hotspot4._strip = 4;
+ _hotspot4.setPosition(Common::Point(146, 110));
+ _hotspot4.fixPriority(90);
+
+ _globals->_player.disableControl();
+ _globals->setFlag(61);
+
+ setAction(&_action4);
+ }
+
+ _hotspot11.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot9._sceneRegionId = 11;
+ _hotspot10._sceneRegionId = 9;
+ _hotspot12._sceneRegionId = 10;
+ _hotspot13._sceneRegionId = 8;
+
+ _globals->_sceneItems.addItems(&_hotspot12, &_hotspot13, &_hotspot9, &_hotspot10, &_hotspot11, NULL);
+ _globals->_sceneManager._scene->_sceneBounds.center(_globals->_player._position);
+ loadScene(5200);
+}
+
+void Scene5200::stripCallback(int v) {
+ switch (v) {
+ case 1:
+ _hotspot7.animate(ANIM_MODE_2, NULL);
+ break;
+ case 2:
+ _hotspot7.animate(ANIM_MODE_NONE, NULL);
+ break;
+ }
+}
+
+void Scene5200::dispatch() {
+ Scene::dispatch();
+
+ if (!_action && (_globals->_player.getRegionIndex() == 12)) {
+ _globals->_stripNum = 5200;
+ _globals->_sceneManager.changeScene(5100);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 5300 - Caverns - Pit
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene5300::Action1::signal() {
+ Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ scene->_hotspot2._numFrames = 4;
+ scene->_hotspot2.animate(ANIM_MODE_8, 1, NULL);
+ setDelay(120);
+ break;
+ case 2:
+ scene->_hotspot2.animate(ANIM_MODE_NONE, NULL);
+
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setStrip2(-1);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ ADD_MOVER(_globals->_player, 85, 170);
+ break;
+ case 3:
+ scene->_hotspot2.fixPriority(-1);
+ _globals->_player.checkAngle(&scene->_hotspot2);
+ setAction(&scene->_sequenceManager, this, 5305, &scene->_hotspot2, NULL);
+ break;
+ case 4:
+ scene->_stripManager.start(5316, this);
+ break;
+ case 5:
+ if (!_globals->getFlag(106) || !_globals->getFlag(107) || (RING_INVENTORY._stasisBox._sceneNumber != 1)) {
+ _globals->_player.enableControl();
+ remove();
+ } else {
+ _globals->getFlag(60);
+
+ if (_globals->getFlag(67)) {
+ scene->_sceneMode = 5310;
+ scene->setAction(&scene->_sequenceManager, scene, 5310, &_globals->_player, &scene->_hotspot2, NULL);
+ } else {
+ scene->_sceneMode = 5347;
+ scene->setAction(&scene->_sequenceManager, scene, 5347, NULL);
+ }
+ }
+ break;
+ }
+}
+
+void Scene5300::Action2::signal() {
+ Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(60);
+ break;
+ case 1:
+ _globals->setFlag(60);
+ scene->_stripManager.start(5328, this);
+ break;
+ case 2:
+ if (RING_INVENTORY._stasisBox._sceneNumber == 1) {
+ _globals->_stripNum = 5303;
+ setDelay(5);
+ } else {
+ _globals->_stripNum = 5302;
+ scene->_stripManager.start(5329, this);
+ }
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(5100);
+ remove();
+ break;
+ }
+}
+
+void Scene5300::Action3::signal() {
+ Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(30);
+ break;
+ case 1:
+ scene->_stripManager.start(_globals->_stripNum, this);
+ break;
+ case 2:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene5300::Hotspot1::doAction(int action) {
+ Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5300, 24);
+ break;
+ case CURSOR_TALK:
+ _globals->_stripNum = 5312;
+ scene->setAction(&scene->_action3);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5300::Hotspot2::doAction(int action) {
+ Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5300, 23);
+ break;
+ case CURSOR_USE:
+ if (!_globals->getFlag(106)) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5302;
+ scene->setAction(&scene->_sequenceManager, scene, 5302, &_globals->_player, NULL);
+ } else {
+ SceneItem::display2(5300, _globals->getFlag(107) ? 25 : 20);
+ }
+ break;
+ case CURSOR_TALK:
+ if (!_globals->getFlag(106)) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5302;
+ scene->setAction(&scene->_sequenceManager, scene, 5302, &_globals->_player, NULL);
+ } else if (!_globals->getFlag(107)) {
+ SceneItem::display2(5300, 11);
+ } else {
+ _globals->_player.disableControl();
+
+ if (RING_INVENTORY._stasisBox._sceneNumber != 1) {
+ scene->setAction(&scene->_sequenceManager, scene, 5316, NULL);
+ } else {
+ _globals->setFlag(60);
+ scene->_sceneMode = _globals->getFlag(67) ? 5315 : 5347;
+ scene->setAction(&scene->_sequenceManager, scene, 5315, this);
+ }
+ }
+ break;
+ case OBJECT_SCANNER:
+ SceneItem::display2(5300, _globals->getFlag(107) ? 10 : 9);
+ break;
+ case OBJECT_MEDKIT:
+ if (_globals->getFlag(106))
+ SceneItem::display2(5300, 7);
+ else {
+ _globals->setFlag(106);
+ _globals->_player.disableControl();
+
+ scene->_sceneMode = 5303;
+ scene->setAction(&scene->_sequenceManager, scene, 5303, &_globals->_player, NULL);
+ }
+ break;
+ case OBJECT_VIAL:
+ if (_globals->getFlag(107)) {
+ SceneItem::display2(5300, 8);
+ } else {
+ RING_INVENTORY._vial._sceneNumber = 5300;
+ _globals->setFlag(107);
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5304;
+
+ scene->setAction(&scene->_sequenceManager, scene, 5304, &_globals->_player, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5300::Hotspot5::doAction(int action) {
+ Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5300, 27);
+ break;
+ case CURSOR_USE:
+ RING_INVENTORY._bone._sceneNumber = 1;
+ _globals->_player.disableControl();
+
+ scene->_sceneMode = 5309;
+ scene->setAction(&scene->_sequenceManager, scene, 5309, &_globals->_player, this, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5300::Hotspot6::doAction(int action) {
+ // Left Hole
+ Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (!_globals->getFlag(105) || (RING_INVENTORY._vial._sceneNumber == 1))
+ SceneItem::display2(5300, 4);
+ else
+ SceneItem::display2(5300, 26);
+ break;
+ case CURSOR_USE:
+ if (!_globals->getFlag(105) || (RING_INVENTORY._vial._sceneNumber != 5100)) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5301;
+ scene->setAction(&scene->_sequenceManager, scene, 5301, &_globals->_player, NULL);
+ } else {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 5307;
+ RING_INVENTORY._vial._sceneNumber = 1;
+
+ scene->setAction(&scene->_sequenceManager, scene, 5307, &scene->_hotspot1, &_globals->_player,
+ &scene->_hotspot4, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5300::Hotspot7::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(63))
+ SceneItem::display2(5300, 2);
+ else {
+ _globals->setFlag(63);
+ SceneItem::display2(5300, 0);
+ SceneItem::display2(5300, 1);
+ }
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(64))
+ SceneItem::display2(5300, 15);
+ else {
+ _globals->setFlag(64);
+ SceneItem::display2(5300, 14);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene5300::Hotspot8::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display2(5300, _globals->getFlag(65) ? 6 : 5);
+ break;
+ case CURSOR_USE:
+ SceneItem::display2(5300, 18);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene5300::Scene5300() :
+ _hotspot3(0, CURSOR_LOOK, 5300, 3, CURSOR_USE, 5300, 16, LIST_END) {
+}
+
+void Scene5300::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ loadScene(5300);
+ setZoomPercents(0, 100, 199, 100);
+
+ _stripManager.addSpeaker(&_speakerQR);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerBatR);
+ _stripManager.addSpeaker(&_speakerSR);
+ _stripManager.addSpeaker(&_speakerSL);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerBatText);
+ _stripManager.addSpeaker(&_speakerSText);
+ _stripManager.addSpeaker(&_speakerGameText);
+
+ if (_globals->getFlag(106) && _globals->getFlag(107)) {
+ _hotspot2.postInit();
+ _hotspot2.setVisage(2806);
+ _hotspot2.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot2.setPosition(Common::Point(63, 170));
+ _hotspot2.animate(ANIM_MODE_1, NULL);
+ } else {
+ _hotspot2.postInit();
+ _hotspot2.setVisage(5310);
+ _hotspot2.setPosition(Common::Point(63, 170));
+ _hotspot2.animate(ANIM_MODE_1, NULL);
+ _hotspot2.fixPriority(98);
+ }
+
+ _hotspot1.postInit();
+ _hotspot1.setVisage(5362);
+ _hotspot1.setStrip2(3);
+ _hotspot1.setFrame2(5);
+ _hotspot1.setPosition(Common::Point(76, 48));
+
+ _hotspot4.postInit();
+ _hotspot4.setVisage(5316);
+ _hotspot4.setStrip(2);
+ _hotspot4.setPosition(Common::Point(89, 65));
+ _hotspot4.animate(ANIM_MODE_2, NULL);
+ _hotspot4.hide();
+
+ if (_globals->getFlag(67)) {
+ _globals->_player.postInit();
+ _globals->_player.setVisage(5316);
+ _globals->_player.setPosition(Common::Point(191, 27));
+ _globals->_player.disableControl();
+
+ if (_globals->getFlag(107) && _globals->getFlag(106)) {
+ _hotspot2.postInit();
+ _hotspot2.setObjectWrapper(new SceneObjectWrapper());
+ _hotspot2.animate(ANIM_MODE_1, NULL);
+
+ setAction(&_action2);
+ } else {
+ _globals->_player.setVisage(5315);
+ _globals->_player.setPosition(Common::Point(204, 86));
+ _globals->_player.animate(ANIM_MODE_2, NULL);
+ _globals->_player.setStrip2(1);
+ _globals->_player._moveDiff.y = 12;
+
+ _sceneMode = 5308;
+ setAction(&_sequenceManager, this, 5308, &_globals->_player, NULL);
+ }
+ } else {
+ _hotspot3.postInit();
+ _hotspot3.setVisage(5301);
+ _hotspot3.setPosition(Common::Point(172, 32));
+ _hotspot3.fixPriority(1);
+ _hotspot3.animate(ANIM_MODE_NONE, NULL);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(5315);
+ _globals->_player.setPosition(Common::Point(204, 86));
+ _globals->_player.animate(ANIM_MODE_2, NULL);
+ _globals->_player.setStrip2(1);
+ _globals->_player._moveDiff.y = 12;
+ _globals->_player.disableControl();
+
+ _sceneMode = 5306;
+ setAction(&_sequenceManager, this, 5306, &_globals->_player, &_hotspot3, NULL);
+ }
+
+ _field1B0A = 1;
+ if (RING_INVENTORY._bone._sceneNumber == 5300) {
+ _hotspot5.postInit();
+ _hotspot5.setVisage(5301);
+ _hotspot5.setStrip(2);
+ _hotspot5.setPosition(Common::Point(190, 147));
+ _globals->_sceneItems.push_back(&_hotspot5);
+ }
+
+ _hotspot6.setBounds(Rect(74, 51, 114, 69));
+ _hotspot7.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _hotspot8._sceneRegionId = 8;
+
+ _globals->_sceneItems.addItems(&_hotspot8, &_hotspot2, &_hotspot6, &_hotspot3, &_hotspot7, NULL);
+ _globals->_soundHandler.startSound(212);
+}
+
+void Scene5300::signal() {
+ switch (_sceneMode) {
+ case 5301:
+ _globals->_stripNum = 5300;
+ _globals->_sceneManager.changeScene(5100);
+ break;
+ case 5307:
+ _soundHandler.proc1(NULL);
+ // No break on purpose
+ case 5302:
+ case 5308:
+ case 5316:
+ case 5347:
+ _globals->_player.setStrip2(-1);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.enableControl();
+ break;
+ case 5303:
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.enableControl();
+
+ if (_globals->getFlag(107))
+ setAction(&_action1);
+ else
+ SceneItem::display2(5300, 28);
+ break;
+ case 5304:
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.enableControl();
+
+ if (_globals->getFlag(106))
+ setAction(&_action1);
+ else
+ SceneItem::display2(5300, 28);
+ break;
+ case 5306:
+ _globals->clearFlag(67);
+ _globals->_player.setStrip2(-1);
+
+ if ((RING_INVENTORY._vial._sceneNumber == 1) || (RING_INVENTORY._vial._sceneNumber == 5300))
+ _stripManager.start(5303, this);
+ else
+ _stripManager.start(5302, this);
+ _sceneMode = 5302;
+ break;
+ case 5309:
+ _hotspot5.remove();
+ _globals->_player.enableControl();
+ break;
+ case 5310:
+ _hotspot2.fixPriority(41);
+ _sceneMode = 5315;
+
+ setAction(&_sequenceManager, this, 5315, &_hotspot2, NULL);
+ break;
+ case 5315:
+ _globals->_stripNum = 5315;
+ _globals->_sceneManager.changeScene(5100);
+ break;
+ }
+}
+
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes6.h b/engines/tsage/ringworld_scenes6.h
new file mode 100644
index 0000000000..16b2800fc6
--- /dev/null
+++ b/engines/tsage/ringworld_scenes6.h
@@ -0,0 +1,333 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_SCENES6_H
+#define TSAGE_RINGWORLD_SCENES6_H
+
+#include "common/scummsys.h"
+#include "tsage/ringworld_logic.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+class Scene5000 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ virtual void dispatch();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot7 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class HotspotGroup1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SoundHandler _soundHandler;
+ SpeakerSText _speakerSText;
+ SpeakerQText _speakerQText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ DisplayHotspot _hotspot1;
+ SceneObject _hotspot2, _hotspot3, _hotspot4, _hotspot5, _hotspot6;
+ Hotspot7 _hotspot7;
+ Hotspot8 _hotspot8;
+ HotspotGroup1 _hotspot9, _hotspot10, _hotspot11;
+ DisplayHotspot _hotspot12, _hotspot13, _hotspot14, _hotspot15;
+ DisplayHotspot _hotspot16, _hotspot17, _hotspot18;
+
+ Scene5000();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene5100 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class HotspotGroup1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class HotspotGroup2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot4 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot9 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot17 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot18 : public SceneHotspot {
+ public:
+ int _index1;
+ int _index2;
+
+ virtual void doAction(int action);
+ };
+ class Hotspot19 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot20 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SequenceManager _sequenceManager;
+ SoundHandler _soundHandler;
+ SpeakerMText _speakerMText;
+ SpeakerQText _speakerQText;
+ SpeakerSText _speakerSText;
+ SpeakerBatText _speakerBatText;
+ SpeakerGameText _speakerGameText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ HotspotGroup1 _hotspot1, _hotspot2, _hotspot3;
+ Hotspot4 _hotspot4;
+ HotspotGroup2 _hotspot5, _hotspot6, _hotspot7;
+ SceneObject _hotspot8;
+ Hotspot9 _hotspot9;
+ SceneObject _hotspot10, _hotspot11, _hotspot12, _hotspot13, _hotspot14, _hotspot15;
+ DisplayHotspot _hotspot16;
+ Hotspot17 _hotspot17;
+ Hotspot18 _hotspot18;
+ Hotspot19 _hotspot19;
+ Hotspot20 _hotspot20;
+ DisplayHotspot _hotspot21;
+
+ Scene5100();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene5200 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot9 : public SceneObjectExt {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot10 : public SceneObjectExt {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot14 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SoundHandler _soundHandler;
+ SpeakerFLL _speakerFLL;
+ SpeakerFLText _speakerFLText;
+ SpeakerQL _speakerQL;
+ SpeakerQText _speakerQText;
+ SpeakerGameText _speakerGameText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+
+ SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4, _hotspot5, _hotspot6, _hotspot7;
+ SceneObject _hotspot8;
+ Hotspot9 _hotspot9;
+ Hotspot10 _hotspot10;
+ DisplayHotspot _hotspot11, _hotspot12, _hotspot13;
+ Hotspot14 _hotspot14;
+
+ Scene5200();
+ virtual void stripCallback(int v);
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void dispatch();
+};
+
+class Scene5300 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Hotspots */
+ class Hotspot1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot2 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot5 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot6 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot7 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Hotspot8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SoundHandler _soundHandler;
+ SequenceManager _sequenceManager;
+ SpeakerQR _speakerQR;
+ SpeakerQL _speakerQL;
+ SpeakerQText _speakerQText;
+ SpeakerBatR _speakerBatR;
+ SpeakerBatText _speakerBatText;
+ SpeakerSR _speakerSR;
+ SpeakerSL _speakerSL;
+ SpeakerSText _speakerSText;
+ SpeakerGameText _speakerGameText;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Hotspot1 _hotspot1;
+ Hotspot2 _hotspot2;
+ DisplayHotspot _hotspot3;
+ SceneObject _hotspot4;
+ Hotspot5 _hotspot5;
+ Hotspot6 _hotspot6;
+ Hotspot7 _hotspot7;
+ Hotspot8 _hotspot8;
+ int _field1B0A;
+
+ Scene5300();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void synchronise(Serialiser &s) {
+ Scene::synchronise(s);
+ s.syncAsSint16LE(_field1B0A);
+ }
+};
+
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/ringworld_scenes8.cpp b/engines/tsage/ringworld_scenes8.cpp
new file mode 100644
index 0000000000..3f1895a432
--- /dev/null
+++ b/engines/tsage/ringworld_scenes8.cpp
@@ -0,0 +1,2526 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "graphics/cursorman.h"
+#include "tsage/ringworld_scenes8.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+void NamedHotspotMult::synchronise(Serialiser &s) {
+ SceneHotspot::synchronise(s);
+ s.syncAsSint16LE(_useLineNum);
+ s.syncAsSint16LE(_lookLineNum);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 7000
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene7000::Action1::signal() {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ setAction(&scene->_action6, this);
+ break;
+ case 2:
+ scene->_soundHandler.startSound(252);
+ scene->_object8.remove();
+ scene->_object1.postInit();
+ scene->_object1.setVisage(7003);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ scene->_object1.setPosition(Common::Point(151, 182), 0);
+ scene->_object1.fixPriority(205);
+ _globals->_sceneItems.push_front(&scene->_object1);
+ break;
+ case 3:
+ scene->_object1._numFrames = 4;
+ scene->_object1.setStrip(2);
+ scene->_object1.animate(ANIM_MODE_8, 0, NULL);
+ scene->_stripManager.start(7005, this);
+ break;
+ case 4:
+ scene->_object1.animate(ANIM_MODE_2, NULL);
+ setDelay(3);
+ break;
+ case 5:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::Action2::signal() {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ _globals->_player.addMover(0, 0);
+ _globals->_player.setVisage(7006);
+ _globals->_player.setStrip(1);
+ _globals->_player.setFrame(1);
+ _globals->_player.setPosition(Common::Point(_globals->_player._position.x, _globals->_player._position.y + 13));
+ _globals->_player.changeZoom(68);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ scene->_object1.remove();
+ break;
+ case 2:
+ _globals->_sceneManager.changeScene(7100);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::Action3::dispatch() {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+
+ Action::dispatch();
+ if (_actionIndex == 4)
+ scene->_object4.setPosition(scene->_object3._position, 0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::Action3::signal() {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ scene->setZoomPercents(10, 10, 62, 100);
+ scene->_object4.postInit();
+ scene->_object4.setVisage(5001);
+ scene->_object4.setStrip2(2);
+ scene->_object4.animate(ANIM_MODE_8, 0, NULL);
+ scene->_object4.setPosition(Common::Point(10, 18), 0);
+ scene->_object4.fixPriority(10);
+ scene->_object4.changeZoom(100);
+ scene->_object4.hide();
+ break;
+ case 1: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(107, 65);
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ scene->_object3._moveDiff.y = 1;
+ scene->_object3.fixPriority(10);
+ scene->_object4.setPosition(Common::Point(scene->_object3._position.x, scene->_object3._position.y + 15), 0);
+ scene->_object4.show();
+ setDelay(30);
+ break;
+ case 3: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(107, 92);
+ scene->_object3.addMover(mover, &pt, this);
+ break;
+ }
+ case 4:
+ scene->_object4.remove();
+ _globals->_sceneManager.changeScene(2100);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::Action4::signal() {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ scene->_object1.animate(ANIM_MODE_6, this);
+ break;
+ case 1:
+ scene->_object1.hide();
+ setDelay(300);
+ break;
+ case 2:
+ _globals->_soundHandler.startSound(252);
+ scene->_object1.show();
+ scene->_object1.setStrip(3);
+ scene->_object1.setFrame(1);
+ scene->_object1.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ scene->_object1.setStrip(4);
+ scene->_object1.animate(ANIM_MODE_8, 0, NULL);
+ _globals->setFlag(81);
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::Action5::signal() {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ NpcMover *playerMover = new NpcMover();
+ Common::Point pt(88, 121);
+ _globals->_player.addMover(playerMover, &pt, this);
+ break;
+ }
+ case 1:
+ _globals->_player.checkAngle(&scene->_object1);
+ _globals->_soundHandler.startSound(252);
+ scene->_object1.setStrip(2);
+ scene->_stripManager.start(7015, this);
+ break;
+ case 2:
+ scene->_object1.setStrip(1);
+ scene->_object1.setFrame(4);
+ scene->_object1.animate(ANIM_MODE_6, this);
+ break;
+ case 3: {
+ scene->_object1.remove();
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(31, 94);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 4: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(11, 94);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 5: {
+ _globals->_player.fixPriority(10);
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(11, 89);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 6: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(41, 89);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 7:
+ _globals->clearFlag(36);
+ _globals->clearFlag(37);
+ _globals->clearFlag(72);
+ _globals->clearFlag(13);
+ _globals->_sceneManager.changeScene(2100);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::Action6::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(12, 91);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(8, 91);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(31, 96);
+ _globals->_player.addMover(mover, &pt, this);
+ _globals->_player.fixPriority(-1);
+ break;
+ }
+ case 4: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(83, 117);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 5: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(95, 121);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 6:
+ _globals->_player.setStrip(3);
+ _globals->_player.setFrame(1);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::Action7::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ _globals->_player.disableControl();
+ setDelay(3);
+ break;
+ case 1:
+ setDelay(3);
+ break;
+ case 2: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(31, 94);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(11, 94);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 4: {
+ _globals->_player.fixPriority(10);
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(11, 89);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 5: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(41, 89);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 6:
+ if (_globals->getFlag(13))
+ _globals->_sceneManager.changeScene(2280);
+ else
+ _globals->_sceneManager.changeScene(2320);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::SceneItem1::doAction(int action) {
+ if (action == CURSOR_LOOK)
+ SceneItem::display(7000, 2, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+
+ SceneItem::doAction(action);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::Object1::doAction(int action) {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_TRANSLATOR:
+ _globals->_player.disableControl();
+ RING_INVENTORY._translator._sceneNumber = 7000;
+
+ if ((RING_INVENTORY._waldos._sceneNumber != 7000) && (RING_INVENTORY._jar._sceneNumber != 7000)) {
+ scene->_sceneMode = 7004;
+ scene->setAction(&scene->_sequenceManager, scene, 7004, &_globals->_player, this, NULL);
+ } else if (RING_INVENTORY._waldos._sceneNumber != 7000) {
+ scene->_sceneMode = 7011;
+ scene->setAction(&scene->_sequenceManager, scene, 7010, &_globals->_player, &scene->_object1, NULL);
+ } else if (RING_INVENTORY._jar._sceneNumber != 7000) {
+ scene->_sceneMode = 7012;
+ scene->setAction(&scene->_sequenceManager, scene, 7010, &_globals->_player, &scene->_object1, NULL);
+ } else {
+ scene->_sceneMode = 7015;
+ scene->setAction(&scene->_sequenceManager, scene, 7017, &_globals->_player, NULL);
+ }
+ break;
+ case OBJECT_WALDOS:
+ _globals->_player.disableControl();
+ RING_INVENTORY._waldos._sceneNumber = 7000;
+ if (RING_INVENTORY._translator._sceneNumber == 7000) {
+ if (RING_INVENTORY._jar._sceneNumber == 7000) {
+ scene->_sceneMode = 7015;
+ scene->setAction(&scene->_sequenceManager, scene, 7015, &_globals->_player, NULL);
+ } else {
+ scene->_sceneMode = 7006;
+ scene->setAction(&scene->_sequenceManager, scene, 7006, &_globals->_player, NULL);
+ }
+ } else {
+ scene->_sceneMode = 7009;
+ scene->setAction(&scene->_sequenceManager, scene, 7009, &_globals->_player, NULL);
+ }
+ break;
+ case OBJECT_JAR:
+ _globals->_player.disableControl();
+ RING_INVENTORY._jar._sceneNumber = 7000;
+
+ if (RING_INVENTORY._translator._sceneNumber == 7000) {
+ if (RING_INVENTORY._waldos._sceneNumber != 7000) {
+ scene->_sceneMode = 7007;
+ scene->setAction(&scene->_sequenceManager, scene, 7007, &_globals->_player, &scene->_object1, NULL);
+ } else {
+ scene->_sceneMode = 7015;
+ scene->setAction(&scene->_sequenceManager, scene, 7016, &_globals->_player, NULL);
+ }
+ } else {
+ scene->_sceneMode = 7008;
+ scene->setAction(&scene->_sequenceManager, scene, 7008, &_globals->_player, NULL);
+ }
+ break;
+ case CURSOR_LOOK:
+ if (_globals->getFlag(81))
+ SceneItem::display(7000, 1, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ else
+ SceneItem::display(7000, 0, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(81)) {
+ RING_INVENTORY._stasisBox2._sceneNumber = 1;
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action5);
+ } else {
+ SceneItem::display(7000, 5, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ }
+ break;
+ case CURSOR_TALK:
+ if (_globals->getFlag(81)) {
+ RING_INVENTORY._stasisBox2._sceneNumber = 1;
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action5);
+ } else if (_globals->getFlag(52)) {
+ scene->_sceneMode = 7005;
+ scene->setAction(&scene->_sequenceManager, scene, 7013, 0, 0);
+ } else if (_globals->getFlag(13)) {
+ _globals->_sceneManager._sceneNumber = 7002;
+ scene->setAction(&scene->_sequenceManager, scene, 7014, 0, 0);
+ } else {
+ _globals->_sceneManager._sceneNumber = 7002;
+ scene->setAction(&scene->_sequenceManager, scene, 7002, 0, 0);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::dispatch() {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+
+ if (!_action) {
+ if (_globals->_sceneRegions.indexOf(_globals->_player._position) == 8) {
+ if (!_globals->getFlag(13)) {
+ _globals->_player.disableControl();
+ _globals->_player.addMover(NULL);
+ SceneItem::display2(7000, 3);
+ _sceneMode = 7001;
+ setAction(&scene->_sequenceManager, this, 7001, &_globals->_player, NULL);
+ } else if (!_globals->getFlag(52)) {
+ setAction(&_action2);
+ } else {
+ _globals->_player.disableControl();
+ _sceneMode = 7003;
+ setAction(&scene->_sequenceManager, this, 7003, &_globals->_player, NULL);
+ }
+ }
+ if (_globals->_sceneRegions.indexOf(_globals->_player._position) == 9)
+ scene->setAction(&scene->_action7);
+ }
+ Scene::dispatch();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::postInit(SceneObjectList *OwnerList) {
+ loadScene(7000);
+ Scene::postInit();
+ setZoomPercents(93, 25, 119, 55);
+ _stripManager.addSpeaker(&_speakerSKText);
+ _stripManager.addSpeaker(&_speakerSKL);
+ _stripManager.addSpeaker(&_speakerQText);
+ _stripManager.addSpeaker(&_speakerQL);
+ _stripManager.addSpeaker(&_speakerQR);
+
+ _speakerSKText._npc = &_object1;
+ _speakerQText._npc = &_globals->_player;
+
+ _object5.postInit();
+ _object5.setVisage(7001);
+ _object5.setStrip2(1);
+ _object5.animate(ANIM_MODE_2, NULL);
+ _object5.setPosition(Common::Point(49, 147), 0);
+ _object5.fixPriority(1);
+
+ _object6.postInit();
+ _object6.setVisage(7001);
+ _object6.setStrip2(2);
+ _object6.animate(ANIM_MODE_2, NULL);
+ _object6.setPosition(Common::Point(160, 139), 0);
+ _object6.fixPriority(1);
+
+ _object7.postInit();
+ _object7.setVisage(7001);
+ _object7.setStrip2(3);
+ _object7.animate(ANIM_MODE_2, NULL);
+ _object7.setPosition(Common::Point(272, 129), 0);
+ _object7.fixPriority(1);
+
+ _object8.postInit();
+ _object8.setVisage(7001);
+ _object8.setStrip2(4);
+ _object8.animate(ANIM_MODE_2, NULL);
+ _object8.setPosition(Common::Point(176, 175), 0);
+ _object8.fixPriority(1);
+
+ if (_globals->getFlag(72)) {
+ _object3.postInit();
+ _object3.setVisage(5001);
+ _object3.setStrip2(1);
+ _object3.setPosition(Common::Point(107, 92), 0);
+ _object3.changeZoom(100);
+ _object3.fixPriority(10);
+
+ _object1.postInit();
+ _object1.setVisage(7003);
+ if (_globals->getFlag(81))
+ _object1.setStrip(4);
+ else
+ _object1.setStrip(2);
+ _object1.setPosition(Common::Point(87, 129), 0);
+ _object1._numFrames = 4;
+ _object1.changeZoom(45);
+ _object1.animate(ANIM_MODE_8, 0, NULL);
+ _globals->_sceneItems.push_back(&_object1);
+ }
+ _soundHandler.startSound(251);
+ if (_globals->_sceneManager._previousScene == 2100) {
+ if (_globals->getFlag(72)) {
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ SceneObjectWrapper *wrapper = new SceneObjectWrapper();
+ _globals->_player.setObjectWrapper(wrapper);
+ _globals->_player.setPosition(Common::Point(57, 94), 0);
+ _globals->_player.changeZoom(-1);
+ _globals->_player.fixPriority(10);
+ if (_globals->getFlag(81)) {
+ setAction(&_action4);
+ } else {
+ _object1.setPosition(Common::Point(151, 182), 0);
+ _object1.changeZoom(100);
+ setAction(&_action1);
+ }
+ } else {
+ _globals->_soundHandler.startSound(250);
+ _globals->setFlag(72);
+
+ _object3.postInit();
+ _object3.setVisage(5001);
+ _object3.setStrip2(1);
+ _object3.animate(ANIM_MODE_1, NULL);
+ _object3.setPosition(Common::Point(307, 0), 0);
+ _object3.changeZoom(-1);
+ setAction(&_action3);
+ }
+ } else if (_globals->_sceneManager._previousScene == 2280) {
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2170);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setPosition(Common::Point(57, 94), 0);
+ _globals->_player.changeZoom(-1);
+ _globals->_player.fixPriority(10);
+ _globals->_player.disableControl();
+ _sceneMode = 7001;
+ setAction(&_action6, this);
+ if (!_globals->getFlag(81)) {
+ _object1.setPosition(Common::Point(151, 182), 0);
+ _object1.changeZoom(100);
+ }
+ _object8.remove();
+ _object9.remove();
+ } else if (_globals->_sceneManager._previousScene == 2320) {
+ _globals->_player.postInit();
+ _globals->_player.setVisage(0);
+ _globals->_player.animate(ANIM_MODE_1, 0);
+ SceneObjectWrapper *wrapper = new SceneObjectWrapper();
+ _globals->_player.setObjectWrapper(wrapper);
+ _globals->_player.setPosition(Common::Point(57, 94), 0);
+ _globals->_player.changeZoom(-1);
+ _globals->_player.fixPriority(10);
+ _sceneMode = 7001;
+ setAction(&_action6, this);
+ } else {
+ _globals->setFlag(72);
+
+ _object3.postInit();
+ _object3.setVisage(5001);
+ _object3.setStrip2(1);
+ _object3.setPosition(Common::Point(307, 0), 0);
+ _soundHandler.startSound(151);
+ _soundHandler.proc5(1);
+ _globals->_soundHandler.startSound(250);
+ setAction(&_action3);
+ }
+
+ _sceneItem1.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _globals->_sceneItems.push_back(&_sceneItem1);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7000::signal() {
+ Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene;
+ switch (_sceneMode) {
+ case 7001:
+ case 7002:
+ case 7004:
+ case 7005:
+ case 7006:
+ case 7007:
+ case 7008:
+ case 7009:
+ _globals->_player.enableControl();
+ break;
+ case 7003:
+ _sceneMode = 7001;
+ setAction(&scene->_sequenceManager, this, 7001, &_globals->_player, NULL);
+ break;
+ case 7011:
+ _sceneMode = 7005;
+ setAction(&scene->_sequenceManager, this, 7005, &_globals->_player, NULL);
+ break;
+ case 7012:
+ _sceneMode = 7005;
+ setAction(&scene->_sequenceManager, this, 7012, &_globals->_player, NULL);
+ break;
+ case 7015:
+ setAction(&_action4);
+ break;
+ }
+}
+
+
+/*--------------------------------------------------------------------------
+ * Scene 7100
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene7100::Action3::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1);
+ break;
+ case 1: {
+ Common::Point pt(433, 308);
+ NpcMover *mover = new NpcMover();
+ scene->_object4.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ scene->_object4.remove();
+ remove();
+ break;
+ }
+}
+
+void Scene7100::Action4::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(1) + 1);
+ break;
+ case 1: {
+ scene->_object5.setStrip(3);
+ Common::Point pt(85, 52);
+ NpcMover *mover = new NpcMover();
+ scene->_object5.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ scene->_object5.setStrip(4);
+ Common::Point pt(20, 52);
+ NpcMover *mover = new NpcMover();
+ scene->_object5.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ _actionIndex = 0;
+ setDelay(1);
+ break;
+ }
+}
+
+void Scene7100::Action5::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1);
+ break;
+ case 1: {
+ Common::Point pt(59, 151);
+ NpcMover *mover = new NpcMover();
+ scene->_object9.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ scene->_object9.setStrip2(1);
+ Common::Point pt(127, 144);
+ NpcMover *mover = new NpcMover();
+ scene->_object9.addMover(mover, &pt, this);
+ break;
+ }
+ case 3: {
+ scene->_object9.setStrip2(2);
+ scene->_object9.fixPriority(180);
+ Common::Point pt(8, 181);
+ NpcMover *mover = new NpcMover();
+ scene->_object9.addMover(mover, &pt, this);
+ break;
+ }
+ case 4: {
+ scene->_object9.remove();
+ remove();
+ }
+ }
+}
+
+void Scene7100::Action6::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1);
+ scene->_object10.fixPriority(8);
+ scene->_object10.setPosition(Common::Point(155, 187), 0);
+
+ scene->_object11.fixPriority(8);
+ scene->_object11.setPosition(Common::Point(155, 190), 0);
+
+ scene->_object12.fixPriority(8);
+ scene->_object12.setPosition(Common::Point(151, 193), 0);
+ break;
+ case 1: {
+ Common::Point pt1(167, 187);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object10.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(165, 185);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object11.addMover(mover2, &pt2, 0);
+
+ Common::Point pt3(163, 183);
+ NpcMover *mover3 = new NpcMover();
+ scene->_object12.addMover(mover3, &pt3, 0);
+ break;
+ }
+ case 2: {
+ scene->_object10.setStrip2(6);
+ Common::Point pt1(91, 187);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object10.addMover(mover1, &pt1, this);
+
+ scene->_object11.setStrip2(6);
+ scene->_object11.fixPriority(50);
+ Common::Point pt2(89, 185);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object11.addMover(mover2, &pt2, 0);
+
+ scene->_object12.setStrip2(6);
+ scene->_object12.fixPriority(50);
+ Common::Point pt3(87, 183);
+ NpcMover *mover3 = new NpcMover();
+ scene->_object12.addMover(mover3, &pt3, 0);
+ break;
+ }
+ case 3:
+ _actionIndex = 0;
+ setDelay(1);
+ break;
+ }
+}
+
+void Scene7100::Action7::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1);
+ break;
+ case 1: {
+ scene->_object13.setStrip2(8);
+ Common::Point pt(324, 87);
+ NpcMover *mover = new NpcMover();
+ scene->_object13.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ scene->_object13.setStrip2(2);
+ Common::Point pt(524, 104);
+ NpcMover *mover = new NpcMover();
+ scene->_object13.addMover(mover, &pt, 0);
+ break;
+ }
+ case 3:
+ _actionIndex = 0;
+ setDelay(1);
+ break;
+ }
+}
+
+void Scene7100::Action8::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1);
+ break;
+ case 1: {
+ scene->_object17.setStrip2(4);
+ scene->_object18.setStrip2(4);
+ scene->_object19.setStrip2(4);
+
+ Common::Point pt1(482, 153);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object17.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(480, 146);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object18.addMover(mover2, &pt2, 0);
+
+ Common::Point pt3(470, 153);
+ NpcMover *mover3 = new NpcMover();
+ scene->_object19.addMover(mover3, &pt3, 0);
+ break;
+ }
+ case 2: {
+ scene->_object17.setStrip2(3);
+ scene->_object18.setStrip2(3);
+ scene->_object19.setStrip2(3);
+
+ Common::Point pt1(506, 186);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object17.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(502, 179);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object18.addMover(mover2, &pt2, 0);
+
+ Common::Point pt3(495, 184);
+ NpcMover *mover3 = new NpcMover();
+ scene->_object19.addMover(mover3, &pt3, 0);
+ break;
+ }
+ case 3: {
+ scene->_object17.setStrip2(4);
+ scene->_object18.setStrip2(4);
+ scene->_object19.setStrip2(4);
+
+ Common::Point pt1(386, 167);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object17.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(379, 161);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object18.addMover(mover2, &pt2, 0);
+
+ Common::Point pt3(373, 167);
+ NpcMover *mover3 = new NpcMover();
+ scene->_object19.addMover(mover3, &pt3, 0);
+ break;
+ }
+ case 4: {
+ scene->_object17.setStrip2(3);
+ scene->_object18.setStrip2(3);
+ scene->_object19.setStrip2(3);
+
+ Common::Point pt1(479, 193);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object17.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(473, 187);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object18.addMover(mover2, &pt2, 0);
+
+ Common::Point pt3(466, 192);
+ NpcMover *mover3 = new NpcMover();
+ scene->_object19.addMover(mover3, &pt3, 0);
+ break;
+ }
+ case 5: {
+ Common::Point pt1(552, 183);
+ NpcMover *mover1 = new NpcMover();
+ scene->_object17.addMover(mover1, &pt1, this);
+
+ Common::Point pt2(552, 178);
+ NpcMover *mover2 = new NpcMover();
+ scene->_object18.addMover(mover2, &pt2, 0);
+
+ Common::Point pt3(541, 183);
+ NpcMover *mover3 = new NpcMover();
+ scene->_object19.addMover(mover3, &pt3, 0);
+
+ _actionIndex = 0;
+ break;
+ }
+ }
+}
+
+void Scene7100::Action9::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1);
+ break;
+ case 1: {
+ scene->_object24.setStrip2(1);
+ Common::Point pt(64, 159);
+ NpcMover *mover = new NpcMover();
+ scene->_object24.addMover(mover, &pt, this);
+ break;
+ }
+ case 2: {
+ scene->_object24.setStrip2(2);
+ scene->_object24.fixPriority(160);
+ Common::Point pt(34, 159);
+ NpcMover *mover = new NpcMover();
+ scene->_object24.addMover(mover, &pt, this);
+ break;
+ }
+ case 3: {
+ scene->_object24.setStrip2(1);
+ Common::Point pt(64, 159);
+ NpcMover *mover = new NpcMover();
+ scene->_object24.addMover(mover, &pt, this);
+ break;
+ }
+ case 4: {
+ scene->_object24.setStrip2(2);
+ scene->_object24.fixPriority(180);
+ Common::Point pt(-12, 182);
+ NpcMover *mover = new NpcMover();
+ scene->_object24.addMover(mover, &pt, this);
+ break;
+ }
+ case 5: {
+ _actionIndex = 0;
+ setDelay(1);
+ break;
+ }
+ }
+}
+
+void Scene7100::Action10::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(1000);
+ break;
+ case 1: {
+ Common::Point pt(610, -60);
+ NpcMover *mover = new NpcMover();
+ scene->_object25.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ scene->_object25.remove();
+ remove();
+ break;
+ }
+}
+
+void Scene7100::Action11::signal() {
+ Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1: {
+ Common::Point pt(154, 175);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ ObjectMover2 *mover2 = new ObjectMover2();
+ scene->_object1.addMover(mover2, 25, 35, &_globals->_player);
+ break;
+ }
+ case 2: {
+ Common::Point pt(700, 155);
+ NpcMover *mover = new NpcMover();
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 3:
+ _globals->_sceneManager.changeScene(7200);
+ remove();
+ break;
+ }
+}
+
+void Scene7100::postInit(SceneObjectList *OwnerList) {
+ loadScene(7100);
+ Scene::postInit();
+ setZoomPercents(60, 85, 200, 100);
+
+ _object2.postInit();
+ _object2.setVisage(7161);
+ _object2.animate(ANIM_MODE_2, 0);
+ _object2.setPosition(Common::Point(10, 140), 0);
+ _object2._numFrames = 1;
+ _object2.fixPriority(180);
+ _object2.setAction(&_action1, 0);
+
+ _object3.postInit();
+ _object3.setVisage(7161);
+ _object3.animate(ANIM_MODE_2, 0);
+ _object3.setPosition(Common::Point(34, 115), 0);
+ _object3._numFrames = 1;
+ _object3.fixPriority(180);
+ _object3.setAction(&_action2, 0);
+
+ _object4.postInit();
+ _object4.setVisage(7164);
+ _object4.animate(ANIM_MODE_2, 0);
+ _object4.setPosition(Common::Point(-10, 159), 0);
+ _object4._numFrames = 2;
+ _object4.fixPriority(250);
+ _object4.setAction(&_action3, 0);
+
+ _object5.postInit();
+ _object5.setVisage(7162);
+ _object5.setStrip(3);
+ _object5.animate(ANIM_MODE_2, 0);
+ _object5.setPosition(Common::Point(20, 52), 0);
+ _object5.setAction(&_action4, 0);
+
+ _object9.postInit();
+ _object9.setVisage(7160);
+ _object5.setStrip(2);
+ _object9.animate(ANIM_MODE_2, 0);
+ _object9.setPosition(Common::Point(110, 168), 0);
+ _object9._numFrames = 2;
+ _object9.fixPriority(16);
+ _object9.setAction(&_action5, 0);
+
+ _object13.postInit();
+ _object13.setVisage(7161);
+ _object13.setStrip(8);
+ _object13.animate(ANIM_MODE_2, 0);
+ _object13.setPosition(Common::Point(524, 104), 0);
+ _object13._numFrames = 5;
+ _object13.fixPriority(250);
+ _object13.setAction(&_action7, 0);
+
+ _object17.postInit();
+ _object17.setVisage(7160);
+ _object17.setStrip(3);
+ _object17.animate(ANIM_MODE_2, 0);
+ _object17.setPosition(Common::Point(552, 183), 0);
+ _object17._numFrames = 4;
+ _object17._moveDiff.x = 12;
+ _object17._moveDiff.y = 12;
+ _object17.setAction(&_action8, 0);
+
+ _object18.postInit();
+ _object18.setVisage(7160);
+ _object18.setStrip(3);
+ _object18.animate(ANIM_MODE_2, 0);
+ _object18.setPosition(Common::Point(552, 178), 0);
+ _object18._numFrames = 4;
+ _object18._moveDiff.x = 12;
+ _object18._moveDiff.y = 12;
+
+ _object19.postInit();
+ _object19.setVisage(7160);
+ _object19.setStrip(3);
+ _object19.animate(ANIM_MODE_2, 0);
+ _object19.setPosition(Common::Point(541, 183), 0);
+ _object19._numFrames = 4;
+ _object19._moveDiff.x = 12;
+ _object19._moveDiff.y = 12;
+
+ _object24.postInit();
+ _object24.setVisage(7162);
+ _object24.setStrip(1);
+ _object24.animate(ANIM_MODE_2, 0);
+ _object24.setPosition(Common::Point(-12, 182), 0);
+ _object24._numFrames = 4;
+ _object24.fixPriority(180);
+ _object24.setAction(&_action9, 0);
+
+ _object25.postInit();
+ _object25.setVisage(7163);
+ _object25.animate(ANIM_MODE_2, 0);
+ _object25.setPosition(Common::Point(551, 145), 0);
+ _object25._numFrames = 5;
+ _object25.fixPriority(160);
+ _object25.setAction(&_action10, 0);
+
+ // Swimmer 1
+ _globals->_player.postInit();
+ _globals->_player.setVisage(7101);
+ _globals->_player.animate(ANIM_MODE_2, 0);
+ _globals->_player._moveDiff.x = 4;
+ _globals->_player._moveDiff.y = 2;
+ _globals->_player.setPosition(Common::Point(135, 135), 0);
+ _globals->_player.fixPriority(200);
+ _globals->_player.disableControl();
+
+ // Swimmer 2
+ _object1.postInit();
+ _object1.setVisage(7110);
+ _object1.animate(ANIM_MODE_1, 0);
+ _object1._moveDiff.x = 4;
+ _object1._moveDiff.y = 2;
+ _object1.setPosition(Common::Point(100, 100), 0);
+
+ setAction(&_action11);
+ _soundHandler1.startSound(270);
+ _soundHandler2.startSound(275);
+ _globals->_soundHandler.startSound(270);
+}
+/*--------------------------------------------------------------------------
+ * Scene 7200
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene7200::Action1::signal() {
+ Scene7200 *scene = (Scene7200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(15);
+ break;
+ case 1: {
+ PlayerMover *mover1 = new PlayerMover();
+ Common::Point pt1(165, 147);
+ scene->_swimmer.addMover(mover1, &pt1, this);
+ Common::Point pt2(207, 138);
+ PlayerMover *mover2 = new PlayerMover();
+ _globals->_player.addMover(mover2, &pt2, this);
+ break;
+ }
+ case 2:
+ break;
+ case 3:
+ _globals->_sceneManager.changeScene(7300);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7200::Action2::signal() {
+ Scene7200 *scene = (Scene7200 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(3);
+ break;
+ case 1: {
+ scene->_object2.fixPriority(25);
+ scene->_object3.fixPriority(25);
+ scene->_object4.fixPriority(25);
+ scene->_object2.setStrip(1);
+ scene->_object3.setStrip(1);
+ scene->_object4.setStrip(1);
+ NpcMover *mover1 = new NpcMover();
+ Common::Point pt1(54, 90);
+ scene->_object2.addMover(mover1, &pt1, this);
+ NpcMover *mover2 = new NpcMover();
+ Common::Point pt2(56, 85);
+ scene->_object3.addMover(mover2, &pt2, 0);
+ NpcMover *mover3 = new NpcMover();
+ Common::Point pt3(54, 80);
+ scene->_object4.addMover(mover3, &pt3, 0);
+ break;
+ }
+ case 2: {
+ scene->_object2.fixPriority(160);
+ scene->_object3.fixPriority(160);
+ scene->_object4.fixPriority(160);
+ scene->_object2.setStrip(2);
+ scene->_object3.setStrip(2);
+ scene->_object4.setStrip(2);
+ NpcMover *mover1 = new NpcMover();
+ Common::Point pt1(10, 89);
+ scene->_object2.addMover(mover1, &pt1, this);
+ NpcMover *mover2 = new NpcMover();
+ Common::Point pt2(12, 84);
+ scene->_object3.addMover(mover2, &pt2, 0);
+ NpcMover *mover3 = new NpcMover();
+ Common::Point pt3(10, 79);
+ scene->_object4.addMover(mover3, &pt3, 0);
+ break;
+ }
+ case 3:
+ _actionIndex = 0;
+ setDelay(1);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7200::postInit(SceneObjectList *OwnerList) {
+ loadScene(7200);
+ Scene::postInit();
+ _object2.postInit();
+ _object2.setVisage(7160);
+ _object2.animate(ANIM_MODE_2, 0);
+ _object2.setZoom(10);
+ _object2.setPosition(Common::Point(53, 88), 0);
+ _object2.setAction(&_action2);
+
+ _object3.postInit();
+ _object3.setVisage(7160);
+ _object3.animate(ANIM_MODE_2, 0);
+ _object3.setZoom(10);
+ _object3.setPosition(Common::Point(55, 83), 0);
+
+ _object4.postInit();
+ _object4.setVisage(7160);
+ _object4.animate(ANIM_MODE_2, 0);
+ _object4.setZoom(10);
+ _object4.setPosition(Common::Point(57, 78), 0);
+
+ _object5.postInit();
+ _object5.setVisage(7201);
+ _object5.setPosition(Common::Point(300, 172), 0);
+ _object5.setPriority(172);
+ _object5.animate(ANIM_MODE_2, 0);
+ _object5._numFrames = 3;
+
+ _object6.postInit();
+ _object6.setVisage(7201);
+ _object6.setStrip2(3);
+ _object6.setPosition(Common::Point(144, 97), 0);
+ _object6.setPriority(199);
+ _object6.animate(ANIM_MODE_2, 0);
+ _object6._numFrames = 3;
+
+ _object7.postInit();
+ _object7.setVisage(7201);
+ _object7.setStrip2(4);
+ _object7.setPosition(Common::Point(115, 123), 0);
+ _object7.setPriority(199);
+ _object7.animate(ANIM_MODE_2, 0);
+ _object7._numFrames = 3;
+
+ _object8.postInit();
+ _object8.setVisage(7201);
+ _object8.setStrip2(6);
+ _object8.setPosition(Common::Point(140, 173), 0);
+ _object8.setPriority(199);
+ _object8.animate(ANIM_MODE_2, 0);
+ _object8._numFrames = 3;
+
+ _object9.postInit();
+ _object9.setVisage(7201);
+ _object9.setStrip2(7);
+ _object9.setPosition(Common::Point(215, 196), 0);
+ _object9.setPriority(199);
+ _object9.animate(ANIM_MODE_2, 0);
+ _object9._numFrames = 3;
+
+ // Orange swimmer
+ _globals->_player.postInit();
+ _globals->_player.setVisage(7110);
+ _globals->_player.animate(ANIM_MODE_1, 0);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setZoom(50);
+ _globals->_player.setPosition(Common::Point(-18, 16), 0);
+ _globals->_player.disableControl();
+
+ _swimmer.postInit();
+ _swimmer.setVisage(7101);
+ _swimmer.animate(ANIM_MODE_1, 0);
+ _swimmer.setObjectWrapper(new SceneObjectWrapper());
+ _swimmer.setZoom(50);
+ _swimmer.setPosition(Common::Point(-8, 16), 0);
+
+ setAction(&_action1);
+ _soundHandler.startSound(271);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 7300
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene7300::Action1::signal() {
+ Scene7300 *scene = (Scene7300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ case 1:
+ case 3:
+ setDelay(30);
+ break;
+ case 2:
+ scene->_stripManager.start(7300, this);
+ break;
+ case 4: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(102, 122);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 5:
+ _globals->_player.setStrip(2);
+ _globals->_player.setFrame(1);
+ _globals->_player.animate(ANIM_MODE_5, this);
+ break;
+ case 6:
+ _globals->_player.setStrip(3);
+ _globals->_player._numFrames = 5;
+ _globals->_player.animate(ANIM_MODE_2, this);
+ if (RING_INVENTORY._translator._sceneNumber == 1)
+ scene->_stripManager.start(7310, this);
+ else
+ scene->_stripManager.start(7305, this);
+ break;
+ case 7:
+ setDelay(3);
+ _globals->_soundHandler.proc1(NULL);
+ break;
+ case 8:
+ _globals->_sceneManager.changeScene(2280);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7300::Action2::signal() {
+ Scene7300 *scene = (Scene7300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1:
+ NpcMover *mover1 = new NpcMover();
+ Common::Point pt(_globals->_randomSource.getRandomNumber(3) + 203, _globals->_randomSource.getRandomNumber(3) + 96);
+ scene->_object3.addMover(mover1, &pt, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7300::Action3::signal() {
+ Scene7300 *scene = (Scene7300 *)_globals->_sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1:
+ NpcMover *mover1 = new NpcMover();
+ Common::Point pt(_globals->_randomSource.getRandomNumber(5) + 76, _globals->_randomSource.getRandomNumber(5) + 78);
+ scene->_object1.addMover(mover1, &pt, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7300::Action4::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1:
+ _actionIndex = 0;
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7300::dispatch() {
+ Scene7300 *scene = (Scene7300 *)_globals->_sceneManager._scene;
+ scene->_object4.setPosition(Common::Point(scene->_object3._position.x + 15, scene->_object3._position.y + 61));
+ scene->_object2.setPosition(Common::Point(scene->_object1._position.x + 1, scene->_object1._position.y - 31));
+
+ Scene::dispatch();
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7300::postInit(SceneObjectList *OwnerList) {
+ loadScene(7300);
+
+ Scene::postInit();
+ setZoomPercents(60, 85, 200, 100);
+
+ _globals->setFlag(52);
+ _globals->setFlag(24);
+ _globals->setFlag(109);
+
+ _stripManager.addSpeaker(&_speakerPOR);
+ _stripManager.addSpeaker(&_speakerPOText);
+ _stripManager.addSpeaker(&_speakerSKText);
+ _stripManager.addSpeaker(&_speakerQU);
+
+ _speakerSKText.setTextPos(Common::Point(100, 20));
+ _speakerPOText.setTextPos(Common::Point(100, 160));
+
+ _object4.postInit();
+ _object4.setVisage(7311);
+ _object4.setStrip(1);
+ _object4.setFrame(1);
+ _object4.setPosition(Common::Point(218, 157), 0);
+
+ _object3.postInit();
+ _object3.setVisage(7311);
+ _object3.setStrip(2);
+ _object3.setFrame(1);
+ _object3.setPosition(Common::Point(203, 96), 0);
+ _object3._numFrames = 2;
+ _object3._moveDiff = Common::Point(1, 1);
+ _object3.animate(ANIM_MODE_8, 0, 0);
+ _object3._moveRate = 2;
+ _object3.setAction(&_action2);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(7305);
+ _globals->_player.animate(ANIM_MODE_1, 0);
+ _globals->_player.setPosition(Common::Point(-100, 100), 0);
+ _globals->_player.disableControl();
+
+ _object1.postInit();
+ _object1.setVisage(7312);
+ _object1.animate(ANIM_MODE_1, 0);
+ _object1._moveDiff = Common::Point(1, 1);
+ _object1.setPosition(Common::Point(76, 78), 0);
+ _object1._moveRate = 1;
+ _object1.setAction(&_action3);
+
+ _object2.postInit();
+ _object2.setVisage(7312);
+ _object2.setStrip(2);
+ _object2.animate(ANIM_MODE_2, 0);
+ _object2.setPosition(Common::Point(77, 47), 0);
+ _object2.fixPriority(190);
+
+ _object5.postInit();
+ _object5.setVisage(7300);
+ _object5.setPosition(Common::Point(106, 45), 0);
+ _object5.animate(ANIM_MODE_2, 0);
+ _object5._numFrames = 5;
+
+ _object6.postInit();
+ _object6.setVisage(7300);
+ _object6.setStrip2(2);
+ _object6.setPosition(Common::Point(283, 193), 0);
+ _object6.animate(ANIM_MODE_2, 0);
+ _object6._numFrames = 3;
+
+ _object7.postInit();
+ _object7.setVisage(7300);
+ _object7.setStrip(4);
+ _object7.setPosition(Common::Point(295, 77), 0);
+ _object7.animate(ANIM_MODE_2, 0);
+ _object7._numFrames = 3;
+
+ _object8.postInit();
+ _object8.setVisage(7300);
+ _object8.setStrip(5);
+ _object8.setPosition(Common::Point(1, 147), 0);
+ _object8.animate(ANIM_MODE_2, 0);
+ _object8._numFrames = 2;
+
+ setAction(&_action1);
+ _globals->_soundHandler.startSound(272);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 7600
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene7600::Action1::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(120);
+ break;
+ case 1: {
+ PlayerMover *mover = new PlayerMover();
+ Common::Point pt(389, 57);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _globals->_sceneManager.changeScene(7700);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7600::Action2::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1: {
+ NpcMover *mover = new NpcMover();
+ Common::Point pt(-30, 195);
+ _globals->_player.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _globals->_sceneManager.changeScene(2320);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene7600::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit();
+ setZoomPercents(100, 0, 200, 100);
+
+ _object2.postInit();
+ _object2.setVisage(7601);
+ _object2.setStrip(1);
+ _object2.animate(ANIM_MODE_2, NULL);
+ _object2.setPosition(Common::Point(48, 135));
+ _object2.fixPriority(1);
+
+ _object3.postInit();
+ _object3.setVisage(7601);
+ _object3.setStrip(2);
+ _object3.animate(ANIM_MODE_2, NULL);
+ _object3.setPosition(Common::Point(158, 136));
+ _object3.fixPriority(1);
+
+ _object4.postInit();
+ _object4.setVisage(7601);
+ _object4.setStrip(3);
+ _object4.animate(ANIM_MODE_2, NULL);
+ _object4.setPosition(Common::Point(293, 141));
+ _object4.fixPriority(1);
+
+ _object5.postInit();
+ _object5.setVisage(7601);
+ _object5.setStrip(4);
+ _object5.animate(ANIM_MODE_2, NULL);
+ _object5.setPosition(Common::Point(405, 143));
+ _object5.fixPriority(1);
+
+ _object6.postInit();
+ _object6.setVisage(7601);
+ _object6.setStrip(5);
+ _object6.animate(ANIM_MODE_2, NULL);
+ _object6.setPosition(Common::Point(379, 191));
+ _object6.fixPriority(1);
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(2333);
+ _globals->_player.animate(ANIM_MODE_1, NULL);
+ _globals->_player.setObjectWrapper(new SceneObjectWrapper());
+ _globals->_player.setStrip(1);
+ _globals->_player._moveDiff = Common::Point(16, 16);
+ _globals->_player.changeZoom(-1);
+ _globals->_player.disableControl();
+
+ if (_globals->_sceneManager._previousScene == 7700) {
+ _globals->_player.setPosition(Common::Point(389, 57));
+ setAction(&_action2);
+ } else {
+ _globals->_player.setPosition(Common::Point(-50, 195));
+ setAction(&_action1);
+ }
+ _sceneBounds.center(_globals->_player._position.x, _globals->_player._position.y);
+ loadScene(7600);
+ _soundHandler2.startSound(255);
+ _soundHandler1.startSound(251);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 7700
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene7700::Action1::signal() {
+ SceneObject *fmtObj = (SceneObject *) _endHandler;
+ switch (_actionIndex++) {
+ case 0: {
+ PlayerMover *mover1 = new PlayerMover();
+ Common::Point pt = Common::Point(fmtObj->_position.x, fmtObj->_position.y + 30);
+ _globals->_player.addMover(mover1, &pt, this);
+ break;
+ }
+ case 1:
+ _globals->_player.checkAngle(fmtObj);
+ if (_globals->_player._field8C == 0)
+ fmtObj->animate(ANIM_MODE_5, this);
+ else
+ fmtObj->animate(ANIM_MODE_6, this);
+ break;
+ case 2:
+ remove();
+ break;
+ }
+}
+
+void Scene7700::Action2::signal() {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+ switch (_actionIndex++) {
+ case 0:
+ case 2:
+ setDelay(_globals->_randomSource.getRandomNumber(60) + 60);
+ break;
+ case 1:
+ scene->_prof.animate(ANIM_MODE_7, 0, 0);
+ setDelay(20);
+ break;
+ case 3:
+ scene->_prof.animate(ANIM_MODE_6, this);
+ _actionIndex = 0;
+ break;
+ }
+}
+
+void Scene7700::Action3::signal() {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+ switch (_actionIndex++) {
+ case 0:
+ scene->_object15.animate(ANIM_MODE_5, this);
+ break;
+ case 1:
+ scene->_sceneItem10.remove();
+ scene->_object15.remove();
+ scene->_sceneHotspot8.remove();
+ scene->_sceneHotspot9.remove();
+ scene->_object19.remove();
+ setDelay(60);
+ // No break on purpose!
+ case 2:
+ scene->_soundHandler.startSound(260);
+ scene->_object8.setVisage(7703);
+ scene->_object8.setPosition(Common::Point(177, 97), 0);
+ scene->_object8.setStrip2(3);
+ scene->_object8.animate(ANIM_MODE_5, this);
+ scene->_object8._numFrames = 3;
+ break;
+ case 3:
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene7700::Action4::signal() {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+ switch (_actionIndex++) {
+ case 2:
+ scene->_object13.remove();
+ // No break on purpose!
+ case 0:
+ setDelay(3);
+ break;
+ case 1:
+ CursorMan.showMouse(false);
+ scene->_object13.postInit();
+ scene->_object13.setVisage(7700);
+ scene->_object13.setStrip2(7);
+ scene->_object13.setPosition(Common::Point(151, 33), 0);
+ scene->_object13.animate(ANIM_MODE_5, this);
+ break;
+ case 3:
+ CursorMan.showMouse(true);
+ SceneItem::display(7700, 11, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ _globals->_player.enableControl();
+ remove();
+ break;
+ }
+}
+
+void Scene7700::Action5::signal() {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(_globals->_randomSource.getRandomNumber(240));
+ break;
+ case 1: {
+ scene->_cloud.setFrame(_globals->_randomSource.getRandomNumber(1) + 1);
+ scene->_cloud.setPosition(Common::Point(133, 145 + _globals->_randomSource.getRandomNumber(54)), 0);
+
+ Common::Point pt(360, scene->_cloud._position.y);
+ NpcMover *mover = new NpcMover();
+ scene->_cloud.addMover(mover, &pt, this);
+ _actionIndex = 0;
+ break;
+ }
+ }
+}
+
+void Scene7700::Action6::signal() {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(5);
+ break;
+ case 1: {
+ Common::Point pt(2, 66);
+ NpcMover *mover = new NpcMover();
+ scene->_easterEgg1.addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ scene->_easterEgg1.setStrip(2);
+ scene->_easterEgg1.setPosition(Common::Point(43, 65), 0);
+
+ scene->_easterEgg2.postInit();
+ scene->_easterEgg2.setVisage(7708);
+ scene->_easterEgg2.setStrip(3);
+ scene->_easterEgg2.setPosition(Common::Point(116, 54), 0);
+ scene->_easterEgg2.animate(ANIM_MODE_2, 0);
+
+ setDelay(120);
+ break;
+ case 3:
+ scene->_easterEgg1.remove();
+ scene->_easterEgg2.remove();
+ remove();
+ break;
+ }
+}
+
+void Scene7700::SceneHotspot1::doAction(int action) {
+ if (action == CURSOR_LOOK)
+ SceneItem::display(7700, 4, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ else
+ SceneHotspot::doAction(action);
+}
+
+void Scene7700::SceneHotspot2::doAction(int action) {
+ if (action == CURSOR_LOOK)
+ SceneItem::display(7700, 6, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ else
+ SceneHotspot::doAction(action);
+}
+
+void Scene7700::SceneHotspot3::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_KEY:
+ SceneItem::display(7702, 3, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ RING_INVENTORY._key._sceneNumber = 7700;
+ break;
+ case CURSOR_LOOK:
+ if (RING_INVENTORY._key._sceneNumber == 7700)
+ scene->setAction(&scene->_action4, 0);
+ else
+ SceneItem::display(7700, 53, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ if (!_globals->getFlag(78)) {
+ scene->_sceneMode = 7712;
+ scene->setAction(&scene->_sequenceManager, scene, 7715, 0);
+ } else if (RING_INVENTORY._key._sceneNumber == 7700) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 7705;
+ scene->setAction(&scene->_sequenceManager, scene, 7705, &_globals->_player, NULL);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene7700::SceneHotspot4::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display(7700, 12, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ if (!_globals->getFlag(78)) {
+ scene->_sceneMode = 7712;
+ scene->setAction(&scene->_sequenceManager, scene, 7715, 0);
+ } else {
+ SceneItem::display(7700, 12, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene7700::SceneHotspot5::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display(7700, 28, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(78)) {
+ if (RING_INVENTORY._paper._sceneNumber == 7700) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 7708;
+ scene->setAction(&scene->_sequenceManager, scene, 7708, &_globals->_player, 0);
+ }
+ } else {
+ scene->_sceneMode = 7712;
+ scene->setAction(&scene->_sequenceManager, scene, 7715, 0);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene7700::SceneHotspot6::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display(7700, 43, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ SceneItem::display(7700, 56, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene7700::SceneItem7::doAction(int action) {
+ if (action == CURSOR_LOOK)
+ SceneItem::display(7700, 51, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+}
+
+void Scene7700::SceneHotspot8::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display(7700, 48, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ scene->_sceneMode = 7709;
+ scene->_soundHandler.startSound(259);
+ scene->_object15.setFrame(scene->_object15.getFrameCount());
+ scene->_object15.animate(ANIM_MODE_6, scene);
+ if ((scene->_field977 == 2) && (scene->_field97B == 0)) {
+ scene->_field979++;
+ } else {
+ scene->_field97B = 0;
+ scene->_field979 = 0;
+ scene->_field977 = 0;
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene7700::SceneHotspot9::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display(7700, 48, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ scene->_sceneMode = 7709;
+ scene->_soundHandler.startSound(259);
+ scene->_object15.setFrame(1);
+ scene->_object15.animate(ANIM_MODE_5, scene);
+ if (scene->_field977 > 2) {
+ scene->_field97B = 0;
+ scene->_field979 = 0;
+ scene->_field977 = 0;
+ }
+
+ if (scene->_field979 != 0) {
+ if (scene->_field979 != 4) {
+ scene->_field97B = 0;
+ scene->_field979 = 0;
+ scene->_field977 = 0;
+ } else {
+ scene->_field97B++;
+ if (scene->_field97B == 3) {
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action3);
+ }
+ }
+ } else {
+ scene->_field977++;
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene7700::SceneItem10::doAction(int action) {
+}
+
+void Scene7700::Object1::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display(7700, _lookLineNum, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else if (action == CURSOR_USE) {
+ if (_globals->getFlag(78)) {
+ _globals->_player.disableControl();
+ scene->setAction(&scene->_action1, this);
+ } else {
+ scene->_sceneMode = 7712;
+ scene->setAction(&scene->_sequenceManager, scene, 7715, 0);
+ }
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene7700::SceneHotspot11::doAction(int action) {
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display(7700, _lookLineNum, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ SceneItem::display(7701, _useLineNum, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene7700::Object1::signal() {
+ if (_state == 0) {
+ _state = 1;
+ SceneItem::display(7701, _defltLineNum, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else {
+ _state = 0;
+ }
+ _globals->_player.enableControl();
+}
+
+void Scene7700::Object3::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display(7700, 34, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else if (action == CURSOR_USE) {
+ if (_globals->getFlag(78)) {
+ if (scene->_object3._frame == 1) {
+ _globals->_player.disableControl();
+ scene->_sceneMode = 7707;
+ scene->setAction(&scene->_sequenceManager, scene, 7707, &_globals->_player, this, 0);
+ } else {
+ SceneItem::display(7700, 60, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ }
+ } else {
+ scene->_sceneMode = 7712;
+ scene->setAction(&scene->_sequenceManager, scene, 7715, 0);
+ }
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene7700::Object7::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ if (_globals->getFlag(78))
+ SceneItem::display(7700, 45, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ else
+ SceneItem::display(7700, 44, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ if (_globals->getFlag(78)) {
+ SceneItem::display(7701, 41, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else {
+ scene->_sceneMode = 7712;
+ scene->setAction(&scene->_sequenceManager, scene, 7714, 0);
+ }
+ break;
+ case CURSOR_TALK:
+ if (_globals->getFlag(78)) {
+ SceneItem::display(7702, 1, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else {
+ _globals->_player.disableControl();
+ if (_state == 0) {
+ _state = 1;
+ scene->_sceneMode = 7703;
+ scene->setAction(&scene->_sequenceManager, scene, 7703, 0);
+ } else {
+ scene->_sceneMode = 7712;
+ scene->setAction(&scene->_sequenceManager, scene, 7712, 0);
+ }
+ }
+ break;
+ case OBJECT_STUNNER:
+ if (!_globals->getFlag(78)) {
+ _globals->_soundHandler.proc3();
+ _globals->setFlag(78);
+ setAction(0);
+ _globals->_player.disableControl();
+ scene->_sceneMode = 7704;
+ scene->setAction(&scene->_sequenceManager, scene, 7704, &_globals->_player, this, 0);
+ }
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ break;
+ }
+}
+
+void Scene7700::Object8::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ if ((action == CURSOR_LOOK) || (action == CURSOR_USE)) {
+ if (_strip == 3) {
+ scene->_object9.postInit();
+ scene->_object9.setVisage(7701);
+ scene->_object9.setStrip2(3);
+ scene->_object9.setPosition(Common::Point(91, 166), 0);
+ scene->_object9.fixPriority(200);
+
+ scene->_object14.postInit();
+ scene->_object14.setVisage(7701);
+ scene->_object14.setStrip(2);
+ scene->_object14.fixPriority(250);
+ scene->_object14.setPosition(Common::Point(139, 151), 0);
+
+ scene->_gfxButton.setText(EXIT_MSG);
+ scene->_gfxButton._bounds.center(140, 189);
+ scene->_gfxButton.draw();
+
+ _globals->_sceneItems.push_front(&scene->_sceneItem10);
+ _globals->_sceneItems.push_front(&scene->_object9);
+ _globals->_player._canWalk = false;
+ } else if (_globals->getFlag(78)) {
+ scene->_object15.postInit();
+ scene->_object15.setVisage(7701);
+ scene->_object15.setPosition(Common::Point(140, 165), 0);
+ scene->_object15.fixPriority(200);
+
+ scene->_gfxButton.setText(EXIT_MSG);
+ scene->_gfxButton._bounds.center(140, 186);
+ scene->_gfxButton.draw();
+ scene->_gfxButton._bounds.expandPanes();
+
+ scene->_object19.postInit();
+ scene->_object19.setVisage(7700);
+ scene->_object19.setStrip(6);
+ scene->_object19.setPosition(Common::Point(140, 192), 0);
+
+ _globals->_sceneItems.push_front(&scene->_sceneItem10);
+ _globals->_sceneItems.push_front(&scene->_sceneHotspot8);
+ _globals->_sceneItems.push_front(&scene->_sceneHotspot9);
+ _globals->_events.setCursor(CURSOR_WALK);
+ _globals->_player._canWalk = false;
+ } else {
+ scene->setAction(&scene->_sequenceManager, scene, 7715, NULL);
+ }
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene7700::Object9::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case CURSOR_LOOK:
+ SceneItem::display(7700, 49, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ SceneItem::display(7701, 42, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_TALK:
+ SceneItem::display(7702, 4, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case OBJECT_KEY:
+ if (_frame == 1) {
+ if (!_globals->getFlag(80)) {
+ scene->_object10.postInit();
+ scene->_object10.setVisage(7701);
+ scene->_object10.setStrip(4);
+ scene->_object10.setPosition(Common::Point(159, 136));
+ _globals->_sceneItems.push_front(&scene->_object10);
+ scene->_object10.fixPriority(240);
+ }
+ scene->_soundHandler.startSound(262);
+ scene->_object14.animate(ANIM_MODE_5, 0);
+ }
+ _globals->_events.setCursor(CURSOR_WALK);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene7700::Object10::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display(7700, 50, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else if (action == CURSOR_USE) {
+ _globals->_player._canWalk = true;
+ RING_INVENTORY._translator._sceneNumber = 1;
+ _globals->setFlag(80);
+ scene->_sceneItem10.remove();
+ scene->_gfxButton._bounds.expandPanes();
+ scene->_object14.remove();
+ scene->_object9.remove();
+ remove();
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene7700::Object11::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ switch (action) {
+ case OBJECT_SCANNER:
+ if (_frame != 1)
+ SceneItem::display(7701, 44, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ else
+ SceneItem::doAction(action);
+ break;
+ case CURSOR_LOOK:
+ if (_frame != 1)
+ SceneItem::display(7700, 9, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ else
+ SceneItem::display(7700, 52, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_USE:
+ if (_frame != 1) {
+ SceneItem::display(7701, 8, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else {
+ _globals->setFlag(49);
+ _globals->_player.disableControl();
+ scene->_sceneMode = 7706;
+ scene->setAction(&scene->_sequenceManager, scene, 7706, &_globals->_player, this, NULL);
+ }
+ break;
+ case OBJECT_EMPTY_JAR:
+ RING_INVENTORY._emptyJar._sceneNumber = 0;
+ RING_INVENTORY._jar._sceneNumber = 1;
+ _globals->_player.disableControl();
+ scene->_sceneMode = 7710;
+ scene->setAction(&scene->_sequenceManager, scene, 7710, &_globals->_player, NULL);
+ break;
+ default:
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene7700::Object12::doAction(int action) {
+ Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene;
+
+ if (action == CURSOR_LOOK) {
+ SceneItem::display(7700, 15, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ } else if (action == CURSOR_USE) {
+ if (_globals->getFlag(78)) {
+ scene->_sceneMode = 7713;
+ scene->setAction(&scene->_sequenceManager, scene, 7713, &_globals->_player, NULL);
+ } else {
+ scene->_sceneMode = 7712;
+ scene->setAction(&scene->_sequenceManager, scene, 7715, NULL);
+ }
+ } else {
+ SceneHotspot::doAction(action);
+ }
+}
+
+void Scene7700::signal() {
+ switch (_sceneMode) {
+ case 7701:
+ _globals->_player.fixPriority(-1);
+ _globals->_player.setStrip2(-1);
+ if (_globals->getFlag(78)) {
+ _globals->_player.enableControl();
+ } else {
+ _sceneMode = 7711;
+ setAction(&_sequenceManager, this, 7711, 0);
+ }
+ break;
+ case 7702:
+ _soundHandler.proc1(0);
+ _globals->_sceneManager.changeScene(7600);
+ break;
+ case 7703:
+ case 7706:
+ case 7707:
+ case 7711:
+ case 7712:
+ _globals->_player.enableControl();
+ break;
+ case 7704:
+ _globals->_soundHandler.startSound(256);
+ _prof.setStrip2(4);
+ _prof.setFrame2(1);
+ _prof.setPosition(Common::Point(159, 87), 0);
+ _globals->_player.enableControl();
+ break;
+ case 7705:
+ RING_INVENTORY._key._sceneNumber = 1;
+ _globals->_player.enableControl();
+ break;
+ case 7708:
+ RING_INVENTORY._paper._sceneNumber = 1;
+ _globals->_player.enableControl();
+ break;
+ case 7709:
+ _globals->_events.setCursor(CURSOR_USE);
+ break;
+ case 7710:
+ _globals->_player.enableControl();
+ SceneItem::display(7700, 62, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case 7713:
+ _emptyJar.remove();
+ RING_INVENTORY._emptyJar._sceneNumber = 1;
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene7700::process(Event &event) {
+ Scene::process(event);
+
+ if (contains<SceneItem *>(_globals->_sceneItems, &_sceneItem10)) {
+ if (_gfxButton.process(event)) {
+ _sceneItem10.remove();
+ _object15.remove();
+ _object9.remove();
+ if (_globals->_sceneObjects->contains(&_object10))
+ _object10.remove();
+ if (_globals->_sceneObjects->contains(&_object14))
+ _object14.remove();
+ _object19.remove();
+ _gfxButton._bounds.expandPanes();
+ _globals->_player._canWalk = true;
+ }
+ }
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_p)) {
+ event.handled = true;
+ if (!_globals->_sceneObjects->contains(&_easterEgg1)) {
+ _easterEgg1.postInit();
+ _easterEgg1.setVisage(7708);
+ _easterEgg1.setPosition(Common::Point(163, 50), 0);
+ _easterEgg1.fixPriority(1);
+ _easterEgg1.animate(ANIM_MODE_2, 0);
+ _easterEgg1.setAction(&_action6);
+ }
+ }
+}
+
+void Scene7700::dispatch() {
+ if ((_globals->_sceneRegions.indexOf(_globals->_player._position) == 6) || (_globals->_player._position.x < 10))
+ _globals->_player.changeZoom(100 - ((_globals->_player._position.y - 68) / 2));
+ else
+ _globals->_player.changeZoom(-1);
+
+ if ((_action == 0) && (_globals->_sceneRegions.indexOf(_globals->_player._position) == 30)) {
+ _globals->_player.disableControl();
+ _sceneMode = 7702;
+ setAction(&_sequenceManager, this, 7702, &_globals->_player, 0);
+ }
+ Scene::dispatch();
+}
+
+void Scene7700::postInit(SceneObjectList *OwnerList) {
+ loadScene(7700);
+ Scene::postInit();
+ setZoomPercents(100, 80, 200, 100);
+ _globals->setFlag(53);
+ _field97B = 0;
+ _field979 = 0;
+ _field977 = 0;
+
+ _stripManager.addSpeaker(&_speakerEText);
+ _stripManager.addSpeaker(&_speakerQText);
+ _speakerQText._npc = &_globals->_player;
+ _speakerEText._npc = &_prof;
+
+ _globals->_player.postInit();
+ _globals->_player.setVisage(4201);
+ _globals->_player.animate(ANIM_MODE_1, 0);
+ SceneObjectWrapper *wrapper = new SceneObjectWrapper();
+ _globals->_player.setObjectWrapper(wrapper);
+ _globals->_player.setPosition(Common::Point(-19, 68), 0);
+ _globals->_player.setStrip2(7);
+ _globals->_player.fixPriority(95);
+ _globals->_player.changeZoom(80);
+ _globals->_player._moveDiff.x = 6;
+ _globals->_player._moveDiff.y = 3;
+ _globals->_player.disableControl();
+
+ _prof.postInit();
+ _prof.setVisage(7706);
+
+ if (_globals->getFlag(78)) {
+ _prof.setStrip2(4);
+ _prof.fixPriority(80);
+ _prof.setPosition(Common::Point(159, 87), 0);
+ } else {
+ _prof.setPosition(Common::Point(203, 87), 0);
+ _prof.setStrip2(2);
+ _prof._numFrames = 6;
+ _prof.setAction(&_action2);
+ }
+
+ _cloud.postInit();
+ _cloud.setVisage(7700);
+ _cloud.setStrip2(5);
+ _cloud.fixPriority(1);
+ _cloud.setPosition(Common::Point(133, 160), 0);
+ _cloud._moveDiff.x = 1;
+ _cloud._moveRate = 7;
+ _cloud.setAction(&_action5);
+
+ _object1.postInit();
+ _object1.setVisage(7700);
+ _object1.setPosition(Common::Point(184, 61), 0);
+ _object1._lookLineNum = 18;
+ _object1._defltLineNum = 16;
+
+ _object2.postInit();
+ _object2.setVisage(7700);
+ _object2.setPosition(Common::Point(184, 70), 0);
+ _object2.fixPriority(60);
+ _object2._lookLineNum = 19;
+ _object2._defltLineNum = 17;
+
+ _object3.postInit();
+ _object3.setVisage(7703);
+ _object3.setPosition(Common::Point(288, 36), 0);
+ _object3.setStrip(2);
+
+ _object4.postInit();
+ _object4.setVisage(7700);
+ _object4.setPosition(Common::Point(268, 59), 0);
+ _object4.setStrip(2);
+ _object4._lookLineNum = 37;
+ _object4._defltLineNum = 35;
+
+ _object5.postInit();
+ _object5.setVisage(7700);
+ _object5.setPosition(Common::Point(268, 67), 0);
+ _object5.fixPriority(58);
+ _object5.setStrip2(3);
+ _object5._lookLineNum = 38;
+ _object5._defltLineNum = 36;
+
+ _object6.postInit();
+ _object6.setVisage(7700);
+ _object6.setPosition(Common::Point(268, 75), 0);
+ _object6.fixPriority(57);
+ _object6.setStrip2(4);
+ _object6._lookLineNum = 40;
+ _object6._defltLineNum = 43;
+
+ _object8.postInit();
+ _object8.setVisage(7703);
+ _object8.setPosition(Common::Point(203, 91), 0);
+ _object8.setStrip2(4);
+ _object8.fixPriority(86);
+
+ _sceneHotspot8.setBounds(82, 141, 161, 92);
+ _sceneHotspot9.setBounds(82, 187, 161, 141);
+
+ _cork.postInit();
+ _cork.setVisage(7703);
+ _cork.setPosition(Common::Point(32, 128), 0);
+
+ if (_globals->getFlag(49))
+ _cork.setFrame(_cork.getFrameCount());
+
+ if (RING_INVENTORY._emptyJar._sceneNumber == 7700) {
+ _emptyJar.postInit();
+ _emptyJar.setVisage(7700);
+ _emptyJar.setStrip(8);
+ _emptyJar.setPosition(Common::Point(189, 48), 0);
+ _globals->_sceneItems.addItems(&_emptyJar, NULL);
+ }
+ _sceneHotspot1._sceneRegionId = 28;
+ _sceneHotspot2._sceneRegionId = 6;
+ _sceneHotspot3._sceneRegionId = 10;
+ _sceneHotspot4._sceneRegionId = 11;
+ _sceneHotspot5._sceneRegionId = 9;
+ _sceneHotspot6._sceneRegionId = 7;
+
+ _sceneItem7.setBounds(0, 320, 200, 0);
+ _sceneItem10.setBounds(0, 320, 200, 0);
+
+ _sceneHotspot11._sceneRegionId = 57;
+ _sceneHotspot11._useLineNum = 0;
+ _sceneHotspot11._lookLineNum = 0;
+ _sceneHotspot12._sceneRegionId = 2;
+ _sceneHotspot12._useLineNum = 2;
+ _sceneHotspot12._lookLineNum = 2;
+ _sceneHotspot13._sceneRegionId = 12;
+ _sceneHotspot13._useLineNum = 3;
+ _sceneHotspot13._lookLineNum = 3;
+ _sceneHotspot14._sceneRegionId = 18;
+ _sceneHotspot14._useLineNum = 4;
+ _sceneHotspot14._lookLineNum = 5;
+ _sceneHotspot15.setBounds(0, 55, 50, 8);
+ _sceneHotspot15._useLineNum = 6;
+ _sceneHotspot15._lookLineNum = 7;
+ _sceneHotspot16.setBounds(0, 130, 34, 103);
+ _sceneHotspot16._useLineNum = 7;
+ _sceneHotspot16._lookLineNum = 8;
+ _sceneHotspot17.setBounds(41, 180, 46, 170);
+ _sceneHotspot17._useLineNum = 11;
+ _sceneHotspot17._lookLineNum = 13;
+ _sceneHotspot18.setBounds(38, 187, 46, 180);
+ _sceneHotspot18._useLineNum = 12;
+ _sceneHotspot18._lookLineNum = 14;
+ _sceneHotspot19._sceneRegionId = 3;
+ _sceneHotspot19._useLineNum = 14;
+ _sceneHotspot19._lookLineNum = 16;
+ _sceneHotspot20._sceneRegionId = 14;
+ _sceneHotspot20._useLineNum = 15;
+ _sceneHotspot20._lookLineNum = 17;
+ _sceneHotspot21.setBounds(9, 215, 26, 210);
+ _sceneHotspot21._useLineNum = 18;
+ _sceneHotspot21._lookLineNum = 20;
+ _sceneHotspot22.setBounds(10, 221, 26, 215);
+ _sceneHotspot22._useLineNum = 19;
+ _sceneHotspot22._lookLineNum = 21;
+ _sceneHotspot23.setBounds(6, 230, 26, 225);
+ _sceneHotspot23._useLineNum = 20;
+ _sceneHotspot23._lookLineNum = 22;
+ _sceneHotspot24._sceneRegionId = 13;
+ _sceneHotspot24._useLineNum = 21;
+ _sceneHotspot24._lookLineNum = 23;
+ _sceneHotspot25._sceneRegionId = 21;
+ _sceneHotspot25._useLineNum = 22;
+ _sceneHotspot25._lookLineNum = 24;
+ _sceneHotspot26._sceneRegionId = 19;
+ _sceneHotspot26._useLineNum = 23;
+ _sceneHotspot26._lookLineNum = 25;
+ _sceneHotspot27._sceneRegionId = 27;
+ _sceneHotspot27._useLineNum = 24;
+ _sceneHotspot27._lookLineNum = 26;
+ _sceneHotspot28._sceneRegionId = 15;
+ _sceneHotspot28._useLineNum = 25;
+ _sceneHotspot28._lookLineNum = 27;
+ _sceneHotspot29._sceneRegionId = 26;
+ _sceneHotspot29._useLineNum = 27;
+ _sceneHotspot29._lookLineNum = 29;
+ _sceneHotspot30.setBounds(0, 317, 34, 310);
+ _sceneHotspot30._useLineNum = 28;
+ _sceneHotspot30._lookLineNum = 30;
+ _sceneHotspot31._sceneRegionId = 17;
+ _sceneHotspot31._useLineNum = 29;
+ _sceneHotspot31._lookLineNum = 31;
+ _sceneHotspot32._sceneRegionId = 25;
+ _sceneHotspot32._useLineNum = 30;
+ _sceneHotspot32._lookLineNum = 32;
+ _sceneHotspot33._sceneRegionId = 5;
+ _sceneHotspot33._useLineNum = 31;
+ _sceneHotspot33._lookLineNum = 33;
+ _sceneHotspot34.setBounds(42, 292, 48, 281);
+ _sceneHotspot34._useLineNum = 32;
+ _sceneHotspot34._lookLineNum = 35;
+ _sceneHotspot35._sceneRegionId = 24;
+ _sceneHotspot35._useLineNum = 38;
+ _sceneHotspot35._lookLineNum = 41;
+ _sceneHotspot36._sceneRegionId = 1;
+ _sceneHotspot36._useLineNum = 39;
+ _sceneHotspot36._lookLineNum = 42;
+
+ _globals->_sceneItems.addItems(&_prof, &_sceneHotspot35, &_object8, &_sceneHotspot34, &_sceneHotspot33, &_sceneHotspot32, NULL);
+ _globals->_sceneItems.addItems(&_sceneHotspot31, &_sceneHotspot30, &_sceneHotspot29, &_sceneHotspot5, &_sceneHotspot28, &_sceneHotspot27, NULL);
+ _globals->_sceneItems.addItems(&_sceneHotspot26, &_sceneHotspot25, &_sceneHotspot24, &_sceneHotspot23, &_sceneHotspot22, &_sceneHotspot21, NULL);
+ _globals->_sceneItems.addItems(&_sceneHotspot20, &_sceneHotspot19, &_sceneHotspot18, &_sceneHotspot17, &_sceneHotspot4, &_sceneHotspot3, NULL);
+ _globals->_sceneItems.addItems(&_sceneHotspot16, &_sceneHotspot15, &_sceneHotspot2, &_sceneHotspot14, &_cork, &_sceneHotspot1, NULL);
+ _globals->_sceneItems.addItems(&_sceneHotspot13, &_sceneHotspot12, &_sceneHotspot11, &_object2, &_object1, &_object3, NULL);
+ _globals->_sceneItems.addItems(&_object6, &_object5, &_object4, &_sceneHotspot6, &_sceneHotspot36, &_sceneItem7, NULL);
+
+ _sceneMode = 7701;
+ setAction(&_sequenceManager, this, 7701, &_globals->_player, 0);
+ _soundHandler.startSound(256);
+}
+
+Scene7700::Scene7700() {
+ _object1._state = 0;
+ _object2._state = 0;
+ _object4._state = 0;
+ _object5._state = 0;
+ _object6._state = 0;
+ _prof._state = 0;
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes8.h b/engines/tsage/ringworld_scenes8.h
new file mode 100644
index 0000000000..e40f3d4133
--- /dev/null
+++ b/engines/tsage/ringworld_scenes8.h
@@ -0,0 +1,496 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD_SCENES8_H
+#define TSAGE_RINGWORLD_SCENES8_H
+
+#include "common/scummsys.h"
+#include "tsage/ringworld_logic.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+class NamedHotspotMult : public SceneHotspot {
+public:
+ int _useLineNum, _lookLineNum;
+ NamedHotspotMult() : SceneHotspot() {}
+
+ virtual Common::String getClassName() { return "NamedHotspotMult"; }
+ virtual void synchronise(Serialiser &s);
+};
+
+class SceneObject7700 : public SceneObjectExt {
+public:
+ int _lookLineNum, _defltLineNum;
+
+ virtual void synchronise(Serialiser &s) {
+ SceneObject::synchronise(s);
+ s.syncAsSint16LE(_lookLineNum);
+ s.syncAsSint16LE(_defltLineNum);
+ }
+ virtual Common::String getClassName() { return "SceneObject7700"; }
+};
+
+class Scene7000 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void dispatch();
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ /* Objects */
+ class Object1 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+ /* Items */
+ class SceneItem1 : public SceneItem {
+ public:
+ virtual void doAction(int action);
+ };
+
+public:
+ SoundHandler _soundHandler;
+ SequenceManager _sequenceManager;
+ SpeakerSKText _speakerSKText;
+ SpeakerSKL _speakerSKL;
+ SpeakerQL _speakerQL;
+ SpeakerQR _speakerQR;
+ SpeakerQText _speakerQText;
+ Object1 _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+ SceneObject _object4;
+ SceneObject _object5;
+ SceneObject _object6;
+ SceneObject _object7;
+ SceneObject _object8;
+ SceneObject _object9;
+ SceneObject _object10;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ SceneItem1 _sceneItem1;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class Scene7100 : public Scene {
+ /* Actions */
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action7 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action8 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action9 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action10 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action11 : public Action {
+ public:
+ virtual void signal();
+ };
+
+public:
+ SoundHandler _soundHandler1;
+ SoundHandler _soundHandler2;
+ SceneObject _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+ SceneObject _object4;
+ SceneObject _object5;
+ SceneObject _object6;
+ SceneObject _object7;
+ SceneObject _object8;
+ SceneObject _object9;
+ SceneObject _object10;
+ SceneObject _object11;
+ SceneObject _object12;
+ SceneObject _object13;
+ SceneObject _object14;
+ SceneObject _object15;
+ SceneObject _object16;
+ SceneObject _object17;
+ SceneObject _object18;
+ SceneObject _object19;
+ SceneObject _object20;
+ SceneObject _object21;
+ SceneObject _object22;
+ SceneObject _object23;
+ SceneObject _object24;
+ SceneObject _object25;
+ Action _action1;
+ Action _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ Action8 _action8;
+ Action9 _action9;
+ Action10 _action10;
+ Action11 _action11;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene7200 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+
+public:
+ Action1 _action1;
+ Action2 _action2;
+ SceneObject _swimmer;
+ SceneObject _object2;
+ SceneObject _object3;
+ SceneObject _object4;
+ SceneObject _object5;
+ SceneObject _object6;
+ SceneObject _object7;
+ SceneObject _object8;
+ SceneObject _object9;
+ SoundHandler _soundHandler;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene7300 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+
+public:
+ SpeakerPOR _speakerPOR;
+ SpeakerPOText _speakerPOText;
+ SpeakerSKText _speakerSKText;
+ SpeakerQU _speakerQU;
+ SceneObject _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+ SceneObject _object4;
+ SceneObject _object5;
+ SceneObject _object6;
+ SceneObject _object7;
+ SceneObject _object8;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void dispatch();
+};
+
+class Scene7600 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+
+public:
+ Action1 _action1;
+ Action2 _action2;
+ SceneObject _object1;
+ SceneObject _object2;
+ SceneObject _object3;
+ SceneObject _object4;
+ SceneObject _object5;
+ SceneObject _object6;
+ SoundHandler _soundHandler1;
+ SoundHandler _soundHandler2;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene7700 : public Scene {
+ /* Actions */
+ class Action1 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action2 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action3 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action4 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5 : public Action {
+ public:
+ virtual void signal();
+ };
+ class Action6 : public Action {
+ public:
+ virtual void signal();
+ };
+
+ class Object1 : public SceneObject7700 {
+ public:
+ virtual void signal();
+ virtual void doAction(int action);
+ };
+ class Object3 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object7 : public SceneObjectExt {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object8 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object9 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object10 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object11 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+ class Object12 : public SceneObject {
+ public:
+ virtual void doAction(int action);
+ };
+
+ /* Items */
+ class SceneHotspot1 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneHotspot2 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneHotspot3 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneHotspot4 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneHotspot5 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneHotspot6 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneItem7 : public SceneItem {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneHotspot8 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneHotspot9 : public SceneHotspot {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneItem10 : public SceneItem {
+ public:
+ virtual void doAction(int action);
+ };
+ class SceneHotspot11 : public NamedHotspotMult {
+ public:
+ virtual void doAction(int action);
+ };
+public:
+ SoundHandler _soundHandler;
+ SequenceManager _sequenceManager;
+ GfxButton _gfxButton;
+ SpeakerEText _speakerEText;
+ SpeakerQText _speakerQText;
+ Object1 _object1;
+ Object1 _object2;
+ Object3 _object3;
+ Object1 _object4;
+ Object1 _object5;
+ Object1 _object6;
+ Object7 _prof;
+ Object8 _object8;
+ Object9 _object9;
+ Object10 _object10;
+ Object11 _cork;
+ Object12 _emptyJar;
+ SceneObject _object13;
+ SceneObject _object14;
+ SceneObject _object15;
+ SceneObject _cloud;
+ SceneObject _easterEgg1;
+ SceneObject _easterEgg2;
+ SceneObject _object19;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ SceneHotspot1 _sceneHotspot1;
+ SceneHotspot2 _sceneHotspot2;
+ SceneHotspot3 _sceneHotspot3;
+ SceneHotspot4 _sceneHotspot4;
+ SceneHotspot5 _sceneHotspot5;
+ SceneHotspot6 _sceneHotspot6;
+ SceneItem7 _sceneItem7;
+ SceneHotspot8 _sceneHotspot8;
+ SceneHotspot9 _sceneHotspot9;
+ SceneItem10 _sceneItem10;
+ SceneHotspot11 _sceneHotspot11;
+ SceneHotspot11 _sceneHotspot12;
+ SceneHotspot11 _sceneHotspot13;
+ SceneHotspot11 _sceneHotspot14;
+ SceneHotspot11 _sceneHotspot15;
+ SceneHotspot11 _sceneHotspot16;
+ SceneHotspot11 _sceneHotspot17;
+ SceneHotspot11 _sceneHotspot18;
+ SceneHotspot11 _sceneHotspot19;
+ SceneHotspot11 _sceneHotspot20;
+ SceneHotspot11 _sceneHotspot21;
+ SceneHotspot11 _sceneHotspot22;
+ SceneHotspot11 _sceneHotspot23;
+ SceneHotspot11 _sceneHotspot24;
+ SceneHotspot11 _sceneHotspot25;
+ SceneHotspot11 _sceneHotspot26;
+ SceneHotspot11 _sceneHotspot27;
+ SceneHotspot11 _sceneHotspot28;
+ SceneHotspot11 _sceneHotspot29;
+ SceneHotspot11 _sceneHotspot30;
+ SceneHotspot11 _sceneHotspot31;
+ SceneHotspot11 _sceneHotspot32;
+ SceneHotspot11 _sceneHotspot33;
+ SceneHotspot11 _sceneHotspot34;
+ SceneHotspot11 _sceneHotspot35;
+ SceneHotspot11 _sceneHotspot36;
+ int _field977, _field979, _field97B;
+
+ Scene7700();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void process(Event &event);
+ virtual void dispatch();
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp
new file mode 100644
index 0000000000..317bc4bbb7
--- /dev/null
+++ b/engines/tsage/saveload.cpp
@@ -0,0 +1,401 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/savefile.h"
+#include "graphics/palette.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
+#include "tsage/globals.h"
+#include "tsage/saveload.h"
+#include "tsage/tsage.h"
+
+namespace tSage {
+
+Saver *_saver;
+
+SavedObject::SavedObject() {
+ _saver->addObject(this);
+}
+
+SavedObject::~SavedObject() {
+ _saver->removeObject(this);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Saver::Saver() {
+ _macroSaveFlag = false;
+ _macroRestoreFlag = false;
+}
+
+Saver::~Saver() {
+ // Internal validation that no saved object is still present
+ int totalLost = 0;
+ for (SynchronisedList<SavedObject *>::iterator i = _saver->_objList.begin(); i != _saver->_objList.end(); ++i) {
+ SavedObject *so = *i;
+ if (so)
+ ++totalLost;
+ }
+
+ if (totalLost)
+ warning("Saved object not destroyed");
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Serialiser::syncPointer(SavedObject **ptr, Common::Serializer::Version minVersion,
+ Common::Serializer::Version maxVersion) {
+ int idx;
+ assert(ptr);
+
+ if (isSaving()) {
+ // Get the object index for the given pointer and write it out
+ if (!*ptr) {
+ idx = 0;
+ } else {
+ idx = _saver->blockIndexOf(*ptr);
+ assert(idx > 0);
+ }
+ syncAsUint32LE(idx);
+ } else {
+ // Load in the object index and add it into the unresolved pointer list
+ syncAsUint32LE(idx);
+ *ptr = NULL;
+ if (idx > 0)
+ // For non-zero (null) pointers, create a record for later resolving it to an address
+ _saver->addSavedObjectPtr(ptr, idx);
+ }
+}
+
+void Serialiser::validate(const Common::String &s, Common::Serializer::Version minVersion,
+ Common::Serializer::Version maxVersion) {
+ Common::String tempStr = s;
+ syncString(tempStr, minVersion, maxVersion);
+
+ if (isLoading() && (tempStr != s))
+ error("Savegame is corrupt");
+}
+
+void Serialiser::validate(int v, Common::Serializer::Version minVersion,
+ Common::Serializer::Version maxVersion) {
+ int tempVal = v;
+ syncAsUint32LE(tempVal, minVersion, maxVersion);
+ if (isLoading() && (tempVal != v))
+ error("Savegame is corrupt");
+}
+
+/*--------------------------------------------------------------------------*/
+
+Common::Error Saver::save(int slot, const Common::String &saveName) {
+ assert(!getMacroRestoreFlag());
+
+ // Signal any objects registered for notification
+ _saveNotifiers.notify(false);
+
+ // Set fields
+ _macroSaveFlag = true;
+ _saveSlot = slot;
+
+ // Set up the serialiser
+ Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(_vm->generateSaveName(slot));
+ Serialiser serialiser(NULL, saveFile);
+
+ // Write out the savegame header
+ tSageSavegameHeader header;
+ header.saveName = saveName;
+ header.version = TSAGE_SAVEGAME_VERSION;
+ writeSavegameHeader(saveFile, header);
+
+ // Save out objects that need to come at the start of the savegame
+ for (SynchronisedList<SaveListener *>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
+ (*i)->listenerSynchronise(serialiser);
+ }
+
+ // Save each registered SaveObject descendant object into the savegame file
+ for (SynchronisedList<SavedObject *>::iterator i = _objList.begin(); i != _objList.end(); ++i) {
+ serialiser.validate((*i)->getClassName());
+ (*i)->synchronise(serialiser);
+ }
+
+ // Save file complete
+ saveFile->writeString("END");
+ saveFile->finalize();
+ delete saveFile;
+
+ // Final post-save notification
+ _macroSaveFlag = false;
+ _saveNotifiers.notify(true);
+
+ return Common::kNoError;
+}
+
+Common::Error Saver::restore(int slot) {
+ assert(!getMacroRestoreFlag());
+
+ // Signal any objects registered for notification
+ _loadNotifiers.notify(false);
+
+ // Set fields
+ _macroRestoreFlag = true;
+ _saveSlot = slot;
+ _unresolvedPtrs.clear();
+
+ // Set up the serialiser
+ Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(_vm->generateSaveName(slot));
+ Serialiser serialiser(saveFile, NULL);
+
+ // Read in the savegame header
+ tSageSavegameHeader header;
+ readSavegameHeader(saveFile, header);
+ delete header.thumbnail;
+
+ // Load in data for objects that need to come at the start of the savegame
+ for (Common::List<SaveListener *>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
+ (*i)->listenerSynchronise(serialiser);
+ }
+
+ // Loop through each registered object to load in the data
+ for (SynchronisedList<SavedObject *>::iterator i = _objList.begin(); i != _objList.end(); ++i) {
+ serialiser.validate((*i)->getClassName());
+ (*i)->synchronise(serialiser);
+ }
+
+ // Loop through the remaining data of the file, instantiating new objects.
+ // Note: I don't store pointers to instantiated objects here, because it's not necessary - the mere act
+ // of instantiating a saved object registers it with the saver, and will then be resolved to whatever
+ // object originally had a pointer to it as part of the post-processing step
+ Common::String className;
+ serialiser.syncString(className);
+ while (className != "END") {
+ SavedObject *savedObject;
+ if (!_factoryPtr || ((savedObject = _factoryPtr(className)) == NULL))
+ error("Unknown class name '%s' encountered trying to restore savegame", className.c_str());
+
+ // Populate the contents of the object
+ savedObject->synchronise(serialiser);
+
+ // Move to next object
+ serialiser.syncString(className);
+ }
+
+ // Post-process any unresolved pointers to get the correct pointer
+ resolveLoadPointers();
+
+ delete saveFile;
+
+ // Final post-restore notifications
+ _macroRestoreFlag = false;
+ _loadNotifiers.notify(false);
+
+ return Common::kNoError;
+}
+
+const char *SAVEGAME_STR = "SCUMMVM_TSAGE";
+#define SAVEGAME_STR_SIZE 13
+
+bool Saver::readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header) {
+ char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
+ header.thumbnail = NULL;
+
+ // 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 != TSAGE_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 = new Graphics::Surface();
+ if (!Graphics::loadThumbnail(*in, *header.thumbnail)) {
+ delete header.thumbnail;
+ header.thumbnail = NULL;
+ 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();
+ header.totalFrames = in->readUint32LE();
+
+ return true;
+}
+
+void Saver::writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &header) {
+ // Write out a savegame header
+ out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1);
+
+ out->writeByte(TSAGE_SAVEGAME_VERSION);
+
+ // 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);
+
+ // Create a thumbnail and save it
+ Graphics::Surface *thumb = new Graphics::Surface();
+ Graphics::Surface s = _globals->_screenSurface.lockSurface();
+ ::createThumbnail(thumb, (const byte *)s.pixels, SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette);
+ Graphics::saveThumbnail(*out, *thumb);
+ _globals->_screenSurface.unlockSurface();
+ 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);
+ out->writeUint32LE(_globals->_events.getFrameNumber());
+}
+
+/**
+ * Adds a serialisable object that should be saved/restored before any other objects
+ */
+void Saver::addListener(SaveListener *obj) {
+ _listeners.push_back(obj);
+}
+
+/**
+ * Adds a listener to be notified before the saving starts
+ */
+void Saver::addSaveNotifier(SaveNotifierFn fn) {
+ _saveNotifiers.push_back(fn);
+}
+
+/**
+ * Adds a listener to be notified before the saving starts
+ */
+void Saver::addLoadNotifier(SaveNotifierFn fn) {
+ _loadNotifiers.push_back(fn);
+}
+
+/**
+ * Registers a SavedObject descendant object for being saved in savegame files
+ */
+void Saver::addObject(SavedObject *obj) {
+ _objList.push_back(obj);
+}
+
+/**
+ * Removes a SavedObject descendant object from the save object list
+ */
+void Saver::removeObject(SavedObject *obj) {
+ _objList.remove(obj);
+}
+
+/**
+ * Returns true if any savegames exist
+ */
+bool Saver::savegamesExist() const {
+ Common::String slot1Name = _vm->generateSaveName(1);
+
+ Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(slot1Name);
+ bool result = saveFile != NULL;
+ delete saveFile;
+ return result;
+}
+
+/**
+ * Returns the index of the saved block associated with the given saved object pointer
+ */
+int Saver::blockIndexOf(SavedObject *p) {
+ int objIndex = 1;
+ Common::List<SavedObject *>::iterator iObj;
+
+ for (iObj = _objList.begin(); iObj != _objList.end(); ++iObj, ++objIndex) {
+ SavedObject *iObjP = *iObj;
+ if (iObjP == p)
+ return objIndex;
+ }
+
+ return 0;
+}
+
+/**
+ * Returns the number of objects in the object list registry
+ */
+int Saver::getObjectCount() const {
+ return _objList.size();
+}
+
+/**
+ * List any currently active objects
+ */
+void Saver::listObjects() {
+ Common::List<SavedObject *>::iterator i;
+ int count = 1;
+
+ for (i = _objList.begin(); i != _objList.end(); ++i, ++count)
+ debug("%d - %s", count, (*i)->getClassName().c_str());
+ debugN("\n");
+}
+
+/**
+ * Returns the pointer associated with the specified object index
+ */
+void Saver::resolveLoadPointers() {
+ if (_unresolvedPtrs.size() == 0)
+ // Nothing to resolve
+ return;
+
+ // Outer loop through the main object list
+ int objIndex = 1;
+ for (SynchronisedList<SavedObject *>::iterator iObj = _objList.begin(); iObj != _objList.end(); ++iObj, ++objIndex) {
+ Common::List<SavedObjectRef>::iterator iPtr;
+ SavedObject *pObj = *iObj;
+
+ for (iPtr = _unresolvedPtrs.begin(); iPtr != _unresolvedPtrs.end(); ) {
+ SavedObjectRef &r = *iPtr;
+ if (r._objIndex == objIndex) {
+ // Found an unresolved pointer to this object
+ SavedObject **objPP = r._savedObject;
+ *objPP = pObj;
+ iPtr = _unresolvedPtrs.erase(iPtr);
+ } else {
+ ++iPtr;
+ }
+ }
+ }
+
+ // At this point, all the unresolved pointers should have been resolved and removed
+ if (_unresolvedPtrs.size() > 0)
+ error("Could not resolve savegame block pointers");
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h
new file mode 100644
index 0000000000..c45271b8fc
--- /dev/null
+++ b/engines/tsage/saveload.h
@@ -0,0 +1,223 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_SAVELOAD_H
+#define TSAGE_SAVELOAD_H
+
+#include "common/scummsys.h"
+#include "common/list.h"
+#include "common/memstream.h"
+#include "common/savefile.h"
+#include "common/serializer.h"
+
+namespace tSage {
+
+typedef void (*SaveNotifierFn)(bool postFlag);
+
+#define TSAGE_SAVEGAME_VERSION 1
+
+class SavedObject;
+
+struct tSageSavegameHeader {
+ uint8 version;
+ Common::String saveName;
+ Graphics::Surface *thumbnail;
+ int saveYear, saveMonth, saveDay;
+ int saveHour, saveMinutes;
+ int totalFrames;
+};
+
+/*--------------------------------------------------------------------------*/
+
+// FIXME: workaround to supress spurious strict-alias warnings on older GCC
+// versions. this should be resolved with the savegame rewrite
+#define SYNC_POINTER(x) do { \
+ SavedObject **y = (SavedObject **)((void *)&x); \
+ s.syncPointer(y); \
+} while (false)
+
+#define SYNC_ENUM(FIELD, TYPE) int v_##FIELD = (int)FIELD; s.syncAsUint16LE(v_##FIELD); \
+ if (s.isLoading()) FIELD = (TYPE)v_##FIELD;
+
+/**
+ * Derived serialiser class with extra synchronisation types
+ */
+class Serialiser : public Common::Serializer {
+public:
+ Serialiser(Common::SeekableReadStream *in, Common::WriteStream *out) : Common::Serializer(in, out) {}
+
+ void syncPointer(SavedObject **ptr, Common::Serializer::Version minVersion = 0,
+ Common::Serializer::Version maxVersion = kLastVersion);
+ void validate(const Common::String &s, Common::Serializer::Version minVersion = 0,
+ Common::Serializer::Version maxVersion = kLastVersion);
+ void validate(int v, Common::Serializer::Version minVersion = 0,
+ Common::Serializer::Version maxVersion = kLastVersion);
+};
+
+/*--------------------------------------------------------------------------*/
+
+class Serialisable {
+public:
+ virtual ~Serialisable() {}
+ virtual void synchronise(Serialiser &s) = 0;
+};
+
+class SaveListener {
+public:
+ virtual ~SaveListener() {}
+ virtual void listenerSynchronise(Serialiser &s) = 0;
+};
+
+/*--------------------------------------------------------------------------*/
+
+class SavedObject : public Serialisable {
+public:
+ SavedObject();
+ virtual ~SavedObject();
+
+ virtual Common::String getClassName() { return "SavedObject"; }
+ virtual void synchronise(Serialiser &s) {}
+
+ static SavedObject *createInstance(const Common::String &className);
+};
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * Derived list class with extra functionality
+ */
+template<typename T>
+class SynchronisedList : public Common::List<T> {
+public:
+ void synchronise(Serialiser &s) {
+ int entryCount;
+
+ if (s.isLoading()) {
+ this->clear();
+ s.syncAsUint32LE(entryCount);
+
+ for (int idx = 0; idx < entryCount; ++idx) {
+ this->push_back(static_cast<T>((T)NULL));
+ T &obj = Common::List<T>::back();
+ s.syncPointer((SavedObject **)&obj);
+ }
+ } else {
+ // Get the list size
+ entryCount = this->size();
+
+ // Write out list
+ s.syncAsUint32LE(entryCount);
+ for (typename Common::List<T>::iterator i = this->begin(); i != this->end(); ++i) {
+ s.syncPointer((SavedObject **)&*i);
+ }
+ }
+ }
+};
+
+/**
+ * Search whether an element is contained in a list.
+ *
+ * @param l List to search.
+ * @param v Element to search for.
+ * @return True in case the element is contained, false otherwise.
+ */
+template<typename T>
+inline bool contains(const Common::List<T> &l, const T &v) {
+ return (Common::find(l.begin(), l.end(), v) != l.end());
+}
+
+/**
+ * Derived list class for holding function pointers
+ */
+template<typename T>
+class FunctionList : public Common::List<void (*)(T)> {
+public:
+ void notify(T v) {
+ for (typename Common::List<void (*)(T)>::iterator i = this->begin(); i != this->end(); ++i) {
+ (*i)(v);
+ }
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+class SavedObjectRef {
+public:
+ SavedObject **_savedObject;
+ int _objIndex;
+
+ SavedObjectRef() : _savedObject(NULL), _objIndex(-1) {}
+ SavedObjectRef(SavedObject **so, int objIndex) : _savedObject(so), _objIndex(objIndex) {}
+};
+
+typedef SavedObject *(*SavedObjectFactory)(const Common::String &className);
+
+class Saver {
+private:
+ Common::List<SavedObject *> _objList;
+ FunctionList<bool> _saveNotifiers;
+ FunctionList<bool> _loadNotifiers;
+ Common::List<SaveListener *> _listeners;
+
+ Common::List<SavedObjectRef> _unresolvedPtrs;
+ SavedObjectFactory _factoryPtr;
+
+ bool _macroSaveFlag;
+ bool _macroRestoreFlag;
+ int _saveSlot;
+
+ void resolveLoadPointers();
+public:
+ Saver();
+ ~Saver();
+
+ Common::Error save(int slot, const Common::String &saveName);
+ Common::Error restore(int slot);
+ static bool readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header);
+ static void writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &header);
+
+ void addListener(SaveListener *obj);
+ void addSaveNotifier(SaveNotifierFn fn);
+ void addLoadNotifier(SaveNotifierFn fn);
+ void addObject(SavedObject *obj);
+ void removeObject(SavedObject *obj);
+ void addFactory(SavedObjectFactory fn) { _factoryPtr = fn; }
+ void addSavedObjectPtr(SavedObject **ptr, int objIndex) {
+ _unresolvedPtrs.push_back(SavedObjectRef(ptr, objIndex));
+ }
+
+ bool savegamesExist() const;
+ bool getMacroSaveFlag() const { return _macroSaveFlag; }
+ bool getMacroRestoreFlag() const { return _macroRestoreFlag; }
+ int blockIndexOf(SavedObject *p);
+ int getObjectCount() const;
+ void listObjects();
+};
+
+extern Saver *_saver;
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/scenes.cpp b/engines/tsage/scenes.cpp
new file mode 100644
index 0000000000..a59c86c97d
--- /dev/null
+++ b/engines/tsage/scenes.cpp
@@ -0,0 +1,495 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+#include "tsage/ringworld_logic.h"
+#include "tsage/tsage.h"
+#include "tsage/saveload.h"
+
+namespace tSage {
+
+SceneManager::SceneManager() {
+ _scene = NULL;
+ _hasPalette = false;
+ _sceneNumber = -1;
+ _nextSceneNumber = -1;
+ _previousScene = 0;
+ _fadeMode = FADEMODE_GRADUAL;
+ _scrollerRect = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ _saver->addListener(this);
+ _objectCount = 0;
+}
+
+SceneManager::~SceneManager() {
+ delete _scene;
+}
+
+void SceneManager::setNewScene(int sceneNumber) {
+ warning("SetNewScene(%d)", sceneNumber);
+ _nextSceneNumber = sceneNumber;
+}
+
+void SceneManager::checkScene() {
+ if (_nextSceneNumber != -1) {
+ sceneChange();
+ _nextSceneNumber = -1;
+ }
+
+ Common::for_each(_globals->_sceneListeners.begin(), _globals->_sceneListeners.end(), SceneHandler::dispatchObject);
+}
+
+void SceneManager::sceneChange() {
+ int activeScreenNumber = 0;
+
+ // Handle removing the scene
+ if (_scene) {
+ activeScreenNumber = _scene->_activeScreenNumber;
+ _scene->remove();
+ }
+
+ // Clear the scene objects
+ SynchronisedList<SceneObject *>::iterator io = _globals->_sceneObjects->begin();
+ while (io != _globals->_sceneObjects->end()) {
+ SceneObject *sceneObj = *io;
+ ++io;
+ sceneObj->removeObject();
+ }
+
+ // Clear the secondary scene object list
+ io = _globals->_sceneManager._altSceneObjects.begin();
+ while (io != _globals->_sceneManager._altSceneObjects.end()) {
+ SceneObject *sceneObj = *io;
+ ++io;
+ sceneObj->removeObject();
+ }
+
+ // Clear the hotspot list
+ SynchronisedList<SceneItem *>::iterator ii = _globals->_sceneItems.begin();
+ while (ii != _globals->_sceneItems.end()) {
+ SceneItem *sceneItem = *ii;
+ ++ii;
+ sceneItem->remove();
+ }
+
+ // TODO: Clear _list_45BAA list
+
+ // If there is an active scene, deactivate it
+ if (_scene) {
+ _previousScene = _sceneNumber;
+
+ delete _scene;
+ _scene = NULL;
+ _sceneNumber = -1;
+ }
+
+ // Set the next scene to be active
+ _sceneNumber = _nextSceneNumber;
+
+ // TODO: Unknown check of word_45CD3 / call to saver method
+
+ // Free any regions
+ disposeRegions();
+
+ // Ensure that the same number of objects are registered now as when the scene started
+ if (_objectCount > 0) {
+ assert(_objectCount == _saver->getObjectCount());
+ }
+ _objectCount = _saver->getObjectCount();
+ _globals->_sceneHandler._delayTicks = 2;
+
+ // Instantiate and set the new scene
+ _scene = getNewScene();
+
+ if (!_saver->getMacroRestoreFlag())
+ _scene->postInit();
+ else
+ _scene->loadScene(activeScreenNumber);
+}
+
+Scene *SceneManager::getNewScene() {
+ return SceneFactory::createScene(_nextSceneNumber);
+}
+
+void SceneManager::fadeInIfNecessary() {
+ if (_hasPalette) {
+ uint32 adjustData = 0;
+ for (int percent = 0; percent < 100; percent += 5) {
+ if (_globals->_sceneManager._fadeMode == FADEMODE_IMMEDIATE)
+ percent = 100;
+
+ _globals->_scenePalette.fade((const byte *)&adjustData, false, percent);
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+
+ _globals->_scenePalette.refresh();
+ _hasPalette = false;
+ }
+}
+
+void SceneManager::changeScene(int newSceneNumber) {
+ warning("changeScene(%d)", newSceneNumber);
+ // Fade out the scene
+ ScenePalette scenePalette;
+ uint32 adjustData = 0;
+ _globals->_scenePalette.clearListeners();
+ scenePalette.getPalette();
+
+ for (int percent = 100; percent >= 0; percent -= 5) {
+ scenePalette.fade((byte *)&adjustData, false, percent);
+ g_system->delayMillis(10);
+ }
+
+ // Stop any objects that were animating
+ SynchronisedList<SceneObject *>::iterator i;
+ for (i = _globals->_sceneObjects->begin(); i != _globals->_sceneObjects->end(); ++i) {
+ SceneObject *sceneObj = *i;
+ Common::Point pt(0, 0);
+ sceneObj->addMover(NULL, &pt);
+ sceneObj->setObjectWrapper(NULL);
+ sceneObj->animate(ANIM_MODE_NONE, 0);
+
+ sceneObj->_flags &= !OBJFLAG_PANES;
+ }
+
+ // Blank out the screen
+ _globals->_screenSurface.fillRect(_globals->_screenSurface.getBounds(), 0);
+
+ // Set the new scene to be loaded
+ setNewScene(newSceneNumber);
+}
+
+void SceneManager::setup() {
+ _saver->addLoadNotifier(SceneManager::loadNotifier);
+ setBackSurface();
+}
+
+void SceneManager::setBackSurface() {
+ int size = _globals->_sceneManager._scene->_backgroundBounds.width() *
+ _globals->_sceneManager._scene->_backgroundBounds.height();
+
+ if (size > 96000) {
+ if (_globals->_sceneManager._scene->_backgroundBounds.width() <= SCREEN_WIDTH) {
+ // Standard size creation
+ _globals->_sceneManager._scene->_backSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT * 3 / 2);
+ _globals->_sceneManager._scrollerRect = Rect(0, 30, SCREEN_WIDTH, SCREEN_HEIGHT - 30);
+ } else {
+ // Wide screen needs extra space to allow for scrolling
+ _globals->_sceneManager._scene->_backSurface.create(SCREEN_WIDTH * 3 / 2, SCREEN_HEIGHT);
+ _globals->_sceneManager._scrollerRect = Rect(80, 0, SCREEN_WIDTH - 80, SCREEN_HEIGHT);
+ }
+ } else {
+ _globals->_sceneManager._scene->_backSurface.create(
+ _globals->_sceneManager._scene->_backgroundBounds.width(),
+ _globals->_sceneManager._scene->_backgroundBounds.height()
+ );
+ _globals->_sceneManager._scrollerRect = Rect(80, 20, SCREEN_WIDTH - 80, SCREEN_HEIGHT - 20);
+ }
+}
+
+void SceneManager::saveListener(int saveMode) {
+ warning("TODO: SceneManager::saveLIstener");
+}
+
+void SceneManager::loadNotifier(bool postFlag) {
+ if (postFlag) {
+ if (_globals->_sceneManager._scene->_activeScreenNumber != -1)
+ _globals->_sceneManager._scene->loadSceneData(_globals->_sceneManager._scene->_activeScreenNumber);
+ _globals->_sceneManager._hasPalette = true;
+ }
+}
+
+void SceneManager::setBgOffset(const Common::Point &pt, int loadCount) {
+ _sceneBgOffset = pt;
+ _sceneLoadCount = loadCount;
+}
+
+void SceneManager::listenerSynchronise(Serialiser &s) {
+ s.validate("SceneManager");
+
+ _altSceneObjects.synchronise(s);
+ s.syncAsSint32LE(_sceneNumber);
+ s.syncAsUint16LE(_globals->_sceneManager._scene->_activeScreenNumber);
+
+ if (s.isLoading()) {
+ changeScene(_sceneNumber);
+ checkScene();
+ }
+
+ _globals->_sceneManager._scrollerRect.synchronise(s);
+ SYNC_POINTER(_globals->_scrollFollower);
+ s.syncAsSint16LE(_loadMode);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene::Scene() : _sceneBounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
+ _backgroundBounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) {
+ _sceneMode = 0;
+ _oldSceneBounds = Rect(4000, 4000, 4100, 4100);
+ Common::set_to(&_zoomPercents[0], &_zoomPercents[256], 0);
+}
+
+Scene::~Scene() {
+}
+
+void Scene::synchronise(Serialiser &s) {
+ StripCallback::synchronise(s);
+
+ s.syncAsSint32LE(_field12);
+ s.syncAsSint32LE(_screenNumber);
+ s.syncAsSint32LE(_activeScreenNumber);
+ s.syncAsSint32LE(_sceneMode);
+ _backgroundBounds.synchronise(s);
+ _sceneBounds.synchronise(s);
+ _oldSceneBounds.synchronise(s);
+ s.syncAsSint16LE(_fieldA);
+ s.syncAsSint16LE(_fieldE);
+
+ for (int i = 0; i < 256; ++i)
+ s.syncAsUint16LE(_enabledSections[i]);
+ for (int i = 0; i < 256; ++i)
+ s.syncAsSint16LE(_zoomPercents[i]);
+}
+
+void Scene::postInit(SceneObjectList *OwnerList) {
+ _action = NULL;
+ _field12 = 0;
+ _sceneMode = 0;
+}
+
+void Scene::process(Event &event) {
+ if (_action)
+ _action->process(event);
+}
+
+void Scene::dispatch() {
+ if (_action)
+ _action->dispatch();
+}
+
+void Scene::loadScene(int sceneNum) {
+ warning("loadScene(%d)", sceneNum);
+ _screenNumber = sceneNum;
+ if (_globals->_scenePalette.loadPalette(sceneNum))
+ _globals->_sceneManager._hasPalette = true;
+
+ loadSceneData(sceneNum);
+}
+
+void Scene::loadSceneData(int sceneNum) {
+ _activeScreenNumber = sceneNum;
+
+ // Get the basic scene size
+ byte *data = _resourceManager->getResource(RES_BITMAP, sceneNum, 9999);
+ _backgroundBounds = Rect(0, 0, READ_LE_UINT16(data), READ_LE_UINT16(data + 2));
+ _globals->_sceneManager._scene->_sceneBounds.contain(_backgroundBounds);
+ DEALLOCATE(data);
+
+ // Set up a surface for storing the scene background
+ SceneManager::setBackSurface();
+
+ // Load the data lists for the scene
+ _globals->_walkRegions.load(sceneNum);
+
+ // Load the item regions of the scene
+ _globals->_sceneRegions.load(sceneNum);
+
+ // Load the priority regions
+ _priorities.load(sceneNum);
+
+ // Initialise the section enabled list
+ Common::set_to(&_enabledSections[0], &_enabledSections[16 * 16], 0xffff);
+
+ _globals->_sceneOffset.x = (_sceneBounds.left / 160) * 160;
+ _globals->_sceneOffset.y = (_sceneBounds.top / 100) * 100;
+ _globals->_paneRefreshFlag[0] = 1;
+ _globals->_paneRefreshFlag[1] = 1;
+ _globals->_sceneManager._loadMode = 1;
+ _globals->_sceneManager._sceneLoadCount = 0;
+ _globals->_sceneManager._sceneBgOffset = Common::Point(0, 0);
+
+ // Load the background for the scene
+ loadBackground(0, 0);
+}
+
+void Scene::loadBackground(int xAmount, int yAmount) {
+ // Adjust the scene bounds by the passed scroll amounts
+ _sceneBounds.translate(xAmount, yAmount);
+ _sceneBounds.contain(_backgroundBounds);
+ _sceneBounds.left &= ~3;
+ _sceneBounds.right &= ~3;
+ _globals->_sceneOffset.x &= ~3;
+
+ if ((_sceneBounds.top != _oldSceneBounds.top) || (_sceneBounds.left != _oldSceneBounds.left)) {
+ if (_globals->_sceneManager._loadMode == 0) {
+ _globals->_paneRefreshFlag[0] = 2;
+ _globals->_paneRefreshFlag[1] = 2;
+ _globals->_sceneManager._loadMode = 2;
+ }
+ _oldSceneBounds = _sceneBounds;
+ }
+
+ _globals->_sceneOffset.x = (_sceneBounds.left / 160) * 160;
+ _globals->_sceneOffset.y = (_sceneBounds.top / 100) * 100;
+
+ if ((_backgroundBounds.width() / 160) == 3)
+ _globals->_sceneOffset.x = 0;
+ if ((_backgroundBounds.height() / 100) == 3)
+ _globals->_sceneOffset.y = 0;
+
+ if ((_globals->_sceneOffset.x != _globals->_prevSceneOffset.x) ||
+ (_globals->_sceneOffset.y != _globals->_prevSceneOffset.y)) {
+ // Change has happend, so refresh background
+ _globals->_prevSceneOffset = _globals->_sceneOffset;
+ refreshBackground(xAmount, yAmount);
+ }
+}
+
+void Scene::refreshBackground(int xAmount, int yAmount) {
+ if (_globals->_sceneManager._scene->_activeScreenNumber == -1)
+ return;
+
+ // Set the quadrant ranges
+ int xHalfCount = MIN(_backSurface.getBounds().width() / 160, _backgroundBounds.width() / 160);
+ int yHalfCount = MIN(_backSurface.getBounds().height() / 100, _backgroundBounds.height() / 100);
+ int xHalfOffset = (_backgroundBounds.width() / 160) == 3 ? 0 : _sceneBounds.left / 160;
+ int yHalfOffset = (_backgroundBounds.height() / 100) == 3 ? 0 : _sceneBounds.top / 100;
+
+ // Set the limits and increment amounts
+ int xInc = (xAmount < 0) ? -1 : 1;
+ int xSectionStart = (xAmount < 0) ? 15 : 0;
+ int xSectionEnd = (xAmount < 0) ? -1 : 16;
+ int yInc = (yAmount < 0) ? -1 : 1;
+ int ySectionStart = (yAmount < 0) ? 15 : 0;
+ int ySectionEnd = (yAmount < 0) ? -1 : 16;
+ bool changedFlag = false;
+
+ for (int yp = ySectionStart; yp != ySectionEnd; yp += yInc) {
+ for (int xp = xSectionStart; xp != xSectionEnd; xp += xInc) {
+ if ((yp < yHalfOffset) || (yp >= (yHalfOffset + yHalfCount)) ||
+ (xp < xHalfOffset) || (xp >= (xHalfOffset + xHalfCount))) {
+ // Flag section as enabled
+ _enabledSections[xp * 16 + yp] = 0xffff;
+ } else {
+ // Check if the section is already loaded
+ if ((_enabledSections[xp * 16 + yp] == 0xffff) || ((xAmount == 0) && (yAmount == 0))) {
+ // Chunk isn't loaded, so load it in
+ Graphics::Surface s = _backSurface.lockSurface();
+ GfxSurface::loadScreenSection(s, xp - xHalfOffset, yp - yHalfOffset, xp, yp);
+ _backSurface.unlockSurface();
+ changedFlag = true;
+ } else {
+ int yv = (_enabledSections[xp * 16 + yp] == ((xp - xHalfOffset) << 4)) ? 0 : 1;
+ if (yv | (yp - yHalfOffset)) {
+ // Copy an existing 160x100 screen section previously loaded
+ int xSectionDest = xp - xHalfOffset;
+ int ySectionDest = yp - yHalfOffset;
+ int xSectionSrc = _enabledSections[xp * 16 + yp] >> 4;
+ int ySectionSrc = _enabledSections[xp * 16 + yp] & 0xf;
+
+ Rect srcBounds(xSectionSrc * 160, ySectionSrc * 100,
+ (xSectionSrc + 1) * 160, (ySectionSrc + 1) * 100);
+ Rect destBounds(xSectionDest * 160, ySectionDest * 100,
+ (xSectionDest + 1) * 160, (ySectionDest + 1) * 100);
+
+ _backSurface.copyFrom(_backSurface, srcBounds, destBounds);
+ }
+ }
+
+ _enabledSections[xp * 16 + yp] =
+ ((xp - xHalfOffset) << 4) | (yp - yHalfOffset);
+ }
+ }
+ }
+
+ if (changedFlag) {
+ drawAltObjects();
+ }
+}
+
+void Scene::drawAltObjects() {
+ Common::Array<SceneObject *> objList;
+
+ // Initial loop to set the priority for entries in the list
+ for (SynchronisedList<SceneObject *>::iterator i = _globals->_sceneManager._altSceneObjects.begin();
+ i != _globals->_sceneManager._altSceneObjects.end(); ++i) {
+ SceneObject *obj = *i;
+ objList.push_back(obj);
+
+ // Handle updating object priority
+ if (!(obj->_flags & OBJFLAG_FIXED_PRIORITY)) {
+ obj->_priority = MIN((int)obj->_position.y - 1,
+ (int)_globals->_sceneManager._scene->_backgroundBounds.bottom);
+ }
+ }
+
+ // Sort the list by priority
+ _globals->_sceneManager._altSceneObjects.sortList(objList);
+
+ // Drawing loop
+ for (uint objIndex = 0; objIndex < objList.size(); ++objIndex) {
+ SceneObject *obj = objList[objIndex];
+
+ obj->reposition();
+ obj->draw();
+ }
+}
+
+void Scene::setZoomPercents(int yStart, int minPercent, int yEnd, int maxPercent) {
+ int var_6 = 0;
+ int v = 0;
+ while (v < yStart)
+ _zoomPercents[v++] = minPercent;
+
+ int diff1 = ABS(maxPercent - minPercent);
+ int diff2 = ABS(yEnd - yStart);
+ int var_8 = MAX(diff1, diff2);
+
+ while (var_8-- != 0) {
+ _zoomPercents[v] = minPercent;
+ if (diff2 <= diff1) {
+ ++minPercent;
+ var_6 += diff2;
+ if (var_6 >= diff1) {
+ var_6 -= diff1;
+ ++v;
+ }
+ } else {
+ ++v;
+ var_6 += diff1;
+ if (var_6 >= diff2) {
+ var_6 -= diff2;
+ ++minPercent;
+ }
+ }
+ }
+
+ while (yEnd < 256)
+ _zoomPercents[yEnd++] = minPercent;
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/scenes.h b/engines/tsage/scenes.h
new file mode 100644
index 0000000000..0ac906728f
--- /dev/null
+++ b/engines/tsage/scenes.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_SCENES_H
+#define TSAGE_SCENES_H
+
+#include "common/scummsys.h"
+#include "tsage/converse.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/saveload.h"
+
+namespace tSage {
+
+class Scene : public StripCallback {
+private:
+ void drawAltObjects();
+public:
+ int _field12;
+ int _screenNumber;
+ int _activeScreenNumber;
+ int _sceneMode;
+ StripManager _stripManager;
+
+ Rect _backgroundBounds;
+ GfxSurface _backSurface;
+ Rect _sceneBounds;
+ Rect _oldSceneBounds;
+ int _enabledSections[256];
+ int _zoomPercents[256];
+ ScenePriorities _priorities;
+
+ int _fieldA;
+ int _fieldE;
+public:
+ Scene();
+ virtual ~Scene();
+
+ virtual Common::String getClassName() { return "Scene"; }
+ virtual void synchronise(Serialiser &s);
+ virtual void stripCallback(int v) {}
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void process(Event &event);
+ virtual void dispatch();
+ virtual void loadScene(int sceneNum);
+
+ void setZoomPercents(int yStart, int minPercent, int yEnd, int maxPercent);
+ void loadBackground(int xAmount, int yAmount);
+ void refreshBackground(int xAmount, int yAmount);
+ void loadSceneData(int sceneNum);
+};
+
+class SceneManager : public GameHandler, public SaveListener {
+private:
+ void disposeRegions() { warning("TODO: disposeRegions()"); }
+ Scene *getNewScene();
+public:
+ Scene *_scene;
+ bool _hasPalette;
+ int _loadMode;
+ int _sceneNumber;
+ int _previousScene;
+ int _nextSceneNumber;
+ FadeMode _fadeMode;
+ Common::Point _sceneBgOffset;
+ int _sceneLoadCount;
+ Rect _scrollerRect;
+ SceneObjectList _altSceneObjects;
+ int _objectCount;
+public:
+ SceneManager();
+ virtual ~SceneManager();
+
+ virtual void listenerSynchronise(Serialiser &s);
+ void setNewScene(int sceneNumber);
+ void checkScene();
+ void sceneChange();
+ void fadeInIfNecessary();
+ void changeScene(int newSceneNumber);
+ void setBgOffset(const Common::Point &pt, int loadCount);
+
+ void removeAction(Action *action) {
+ // Not currently implemented because addAction method doesn't seem to have any callers
+ }
+
+ static void setup();
+ static void setBackSurface();
+ static void saveListener(int saveMode);
+ static void loadNotifier(bool postFlag);
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
new file mode 100644
index 0000000000..63e753104e
--- /dev/null
+++ b/engines/tsage/sound.cpp
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/core.h"
+#include "tsage/globals.h"
+#include "tsage/debugger.h"
+#include "tsage/graphics.h"
+
+namespace tSage {
+
+void SoundManager::postInit() {
+ _saver->addSaveNotifier(&SoundManager::saveNotifier);
+ _saver->addLoadNotifier(&SoundManager::loadNotifier);
+ _saver->addListener(this);
+}
+
+void SoundManager::saveNotifier(bool postFlag) {
+ _globals->_soundManager.saveNotifierProc(postFlag);
+}
+
+void SoundManager::saveNotifierProc(bool postFlag) {
+ warning("TODO: SoundManager::saveNotifierProc");
+}
+
+void SoundManager::loadNotifier(bool postFlag) {
+ _globals->_soundManager.loadNotifierProc(postFlag);
+}
+
+void SoundManager::loadNotifierProc(bool postFlag) {
+ warning("TODO: SoundManager::loadNotifierProc");
+}
+
+void SoundManager::listenerSynchronise(Serialiser &s) {
+ s.validate("SoundManager");
+ warning("TODO: SoundManager listenerSynchronise");
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
new file mode 100644
index 0000000000..a495344038
--- /dev/null
+++ b/engines/tsage/sound.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_SOUND_H
+#define TSAGE_SOUND_H
+
+#include "common/scummsys.h"
+#include "tsage/saveload.h"
+
+namespace tSage {
+
+class SoundManager : public SaveListener {
+public:
+ void dispatch() {}
+ virtual void listenerSynchronise(Serialiser &s);
+ virtual void postInit();
+
+ void proc2() {}
+ static void saveNotifier(bool postFlag);
+ void saveNotifierProc(bool postFlag);
+ static void loadNotifier(bool postFlag);
+ void loadNotifierProc(bool postFlag);
+};
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/staticres.cpp b/engines/tsage/staticres.cpp
new file mode 100644
index 0000000000..bc85718035
--- /dev/null
+++ b/engines/tsage/staticres.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "tsage/staticres.h"
+
+namespace tSage {
+
+const byte CURSOR_ARROW_DATA[] = {
+ 15, 0, 15, 0, 0, 0, 0, 0, 9, 0,
+ 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09
+};
+
+const byte CURSOR_WALK_DATA[] = {
+ 15, 0, 15, 0, 7, 0, 7, 0, 9, 0,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x09, 0x09, 0x09, 0x09, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09
+};
+
+const char *LOOK_SCENE_HOTSPOT = "You see nothing special.";
+const char *USE_SCENE_HOTSPOT = "That accomplishes nothing.";
+const char *TALK_SCENE_HOTSPOT = "Yak, yak.";
+const char *SPECIAL_SCENE_HOTSPOT = "That is a unique use for that.";
+const char *DEFAULT_SCENE_HOTSPOT = "That accomplishes nothing.";
+const char *SAVE_ERROR_MSG = "Error occurred saving game. Please do not try to restore this game!";
+const char *SAVING_NOT_ALLOWED_MSG = "Saving is not allowed at this time.";
+const char *RESTORING_NOT_ALLOWED_MSG = "Restoring is not allowed at this time.";
+const char *RESTART_CONFIRM_MSG = "Do you want to restart your game?";
+const char *WATCH_INTRO_MSG = "Do you wish to watch the introduction?";
+const char *INV_EMPTY_MSG = "You have nothing in your possesion.";
+
+const char *HELP_MSG = "Ringworld\rRevenge of the Patriarch\x14\rScummVM Version\r\r\
+\x01 Keyboard shortcuts...\rF2 - Sound options\rF3 - Quit\r\
+F4 - Restart\rF5 - Save game\rF7 - Restore Game\rF10 - Pause game";
+const char *QUIT_CONFIRM_MSG = "Do you want to quit playing this game?";
+const char *RESTART_MSG = "Do you want to restart this game?";
+const char *GAME_PAUSED_MSG = "Game is paused.";
+const char *OPTIONS_MSG = "\x01Options...";
+const char *OK_BTN_STRING = " Ok ";
+const char *CANCEL_BTN_STRING = "Cancel";
+const char *QUIT_BTN_STRING = " Quit ";
+const char *RESTART_BTN_STRING = "Restart";
+const char *SAVE_BTN_STRING = "Save";
+const char *RESTORE_BTN_STRING = "Restore";
+const char *SOUND_BTN_STRING = "Sound";
+const char *RESUME_BTN_STRING = " Resume \rplay";
+const char *LOOK_BTN_STRING = "Look";
+const char *PICK_BTN_STRING = "Pick";
+const char *START_PLAY_BTN_STRING = " Start Play ";
+const char *INTRODUCTION_BTN_STRING = "Introduction";
+
+const char *EXIT_MSG = " EXIT ";
+const char *SCENE6100_CAREFUL = "Be careful! The probe cannot handle too much of that.";
+const char *SCENE6100_TOUGHER = "Hey! This is tougher than it looks!";
+const char *SCENE6100_ONE_MORE_HIT = "You had better be more careful. One more hit like that \
+and the probe may be destroyed.";
+const char *SCENE6100_DOING_BEST = "I'm doing the best I can. I just hope it holds together!";
+const char *SCENE6100_REPAIR = "\r\rQuinn and Seeker repair the probe....";
+const char *SCENE6100_ROCKY_AREA = "The rocky area should be directly ahead of you. Do you see it?";
+const char *SCENE6100_REPLY = "Yes. Now if I can just avoid those sunbeams.";
+const char *SCENE6100_TAKE_CONTROLS = "You had better take the controls Seeker. My hands are sweating.";
+const char *SCENE6100_SURPRISE = "You surprise me Quinn. I would have thought you of hardier stock.";
+const char *SCENE6100_SWEAT = "Humans sweat, Kzin twitch their tail. What's the difference?";
+const char *SCENE6100_VERY_WELL = "Very well. I will retrieve the stasis box and return the probe. \
+Wait for it's return in the lander bay.";
+
+const char *DEMO_HELP_MSG = " Help...\rF2 - Sound Options\rF3 - Exit demo\r\rPress ENTER\rto continue";
+const char *DEMO_PAUSED_MSG = " demo is paused";
+
+} // End of namespace tSage
diff --git a/engines/tsage/staticres.h b/engines/tsage/staticres.h
new file mode 100644
index 0000000000..0db349f8a7
--- /dev/null
+++ b/engines/tsage/staticres.h
@@ -0,0 +1,88 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_STATICRES_H
+#define TSAGE_STATICRES_H
+
+#include "common/scummsys.h"
+
+namespace tSage {
+
+extern const byte CURSOR_ARROW_DATA[];
+
+extern const byte CURSOR_WALK_DATA[];
+
+extern const char *LOOK_SCENE_HOTSPOT;
+extern const char *USE_SCENE_HOTSPOT;
+extern const char *TALK_SCENE_HOTSPOT;
+extern const char *SPECIAL_SCENE_HOTSPOT;
+extern const char *DEFAULT_SCENE_HOTSPOT;
+extern const char *SAVE_ERROR_MSG;
+extern const char *SAVING_NOT_ALLOWED_MSG;
+extern const char *RESTORING_NOT_ALLOWED_MSG;
+extern const char *RESTART_CONFIRM_MSG;
+extern const char *WATCH_INTRO_MSG;
+
+// Dialogs
+extern const char *HELP_MSG;
+extern const char *QUIT_CONFIRM_MSG;
+extern const char *RESTART_MSG;
+extern const char *GAME_PAUSED_MSG;
+extern const char *OPTIONS_MSG;
+extern const char *OK_BTN_STRING;
+extern const char *CANCEL_BTN_STRING;
+extern const char *QUIT_BTN_STRING;
+extern const char *RESTART_BTN_STRING;
+extern const char *SAVE_BTN_STRING;
+extern const char *RESTORE_BTN_STRING;
+extern const char *SOUND_BTN_STRING;
+extern const char *RESUME_BTN_STRING;
+extern const char *LOOK_BTN_STRING;
+extern const char *PICK_BTN_STRING;
+extern const char *INV_EMPTY_MSG;
+extern const char *START_PLAY_BTN_STRING;
+extern const char *INTRODUCTION_BTN_STRING;
+
+// Scene specific resources
+extern const char *EXIT_MSG;
+extern const char *SCENE6100_CAREFUL;
+extern const char *SCENE6100_TOUGHER;
+extern const char *SCENE6100_ONE_MORE_HIT;
+extern const char *SCENE6100_DOING_BEST;
+extern const char *SCENE6100_REPAIR;
+extern const char *SCENE6100_ROCKY_AREA;
+extern const char *SCENE6100_REPLY;
+extern const char *SCENE6100_TAKE_CONTROLS;
+extern const char *SCENE6100_SURPRISE;
+extern const char *SCENE6100_SWEAT;
+extern const char *SCENE6100_VERY_WELL;
+
+// Demo messages
+extern const char *DEMO_HELP_MSG;
+extern const char *DEMO_PAUSED_MSG;
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tsage/tsage.cpp b/engines/tsage/tsage.cpp
new file mode 100644
index 0000000000..d6f07c999b
--- /dev/null
+++ b/engines/tsage/tsage.cpp
@@ -0,0 +1,136 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/debug-channels.h"
+#include "engines/util.h"
+
+#include "tsage/tsage.h"
+#include "tsage/core.h"
+#include "tsage/dialogs.h"
+#include "tsage/events.h"
+#include "tsage/resources.h"
+#include "tsage/globals.h"
+
+namespace tSage {
+
+TSageEngine *_vm = NULL;
+
+TSageEngine::TSageEngine(OSystem *system, const tSageGameDescription *gameDesc) : Engine(system),
+ _gameDescription(gameDesc) {
+ _vm = this;
+ DebugMan.addDebugChannel(kRingDebugScripts, "scripts", "Scripts debugging");
+ _debugger = new Debugger();
+}
+
+Common::Error TSageEngine::init() {
+ initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, false);
+
+ return Common::kNoError;
+}
+
+TSageEngine::~TSageEngine() {
+ // Remove all of our debug levels here
+ DebugMan.clearAllDebugChannels();
+ delete _debugger;
+}
+
+bool TSageEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+void TSageEngine::initialise() {
+ _saver = new Saver();
+
+ // Set up the resource manager
+ _resourceManager = new ResourceManager();
+ if (_vm->getFeatures() & GF_DEMO) {
+ // Add the single library file associated with the demo
+ _resourceManager->addLib(getPrimaryFilename());
+ } else {
+ _resourceManager->addLib("RING.RLB");
+ _resourceManager->addLib("TSAGE.RLB");
+ }
+
+ _globals = new Globals();
+ _globals->gfxManager().setDefaults();
+}
+
+void TSageEngine::deinitialise() {
+ delete _globals;
+ delete _resourceManager;
+ delete _saver;
+}
+
+Common::Error TSageEngine::run() {
+ // Basic initialisation
+ initialise();
+
+ _globals->_sceneHandler.registerHandler();
+ _globals->_game->execute();
+
+ deinitialise();
+ return Common::kNoError;
+}
+
+/**
+ * Returns true if it is currently okay to restore a game
+ */
+bool TSageEngine::canLoadGameStateCurrently() {
+ return (_globals->getFlag(50) == 0) && _globals->_player._uiEnabled;
+}
+
+/**
+ * Returns true if it is currently okay to save the game
+ */
+bool TSageEngine::canSaveGameStateCurrently() {
+ return (_globals->getFlag(50) == 0) && _globals->_player._uiEnabled;
+}
+
+/**
+ * Load the savegame at the specified slot index
+ */
+Common::Error TSageEngine::loadGameState(int slot) {
+ return _saver->restore(slot);
+}
+
+/**
+ * Save the game to the given slot index, and with the given name
+ */
+Common::Error TSageEngine::saveGameState(int slot, const char *desc) {
+ return _saver->save(slot, desc);
+}
+
+/**
+ * Support method that generates a savegame name
+ * @param slot Slot number
+ */
+Common::String TSageEngine::generateSaveName(int slot) {
+ return Common::String::format("%s.%03d", _targetName.c_str(), slot);
+}
+
+} // End of namespace tSage
diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h
new file mode 100644
index 0000000000..06c66d8f42
--- /dev/null
+++ b/engines/tsage/tsage.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef TSAGE_H
+#define TSAGE_H
+
+#include "engines/advancedDetector.h"
+#include "engines/engine.h"
+#include "common/rect.h"
+#include "audio/mixer.h"
+#include "common/file.h"
+
+#include "tsage/core.h"
+#include "tsage/resources.h"
+#include "tsage/debugger.h"
+#include "tsage/events.h"
+#include "tsage/graphics.h"
+#include "tsage/resources.h"
+
+
+namespace tSage {
+
+enum {
+ GType_Ringworld = 0,
+ GType_BlueForce = 1
+};
+
+enum {
+ GF_DEMO = 1 << 0,
+ GF_CD = 1 << 1,
+ GF_FLOPPY = 1 << 2,
+ GF_ALT_REGIONS = 1 << 3
+};
+
+enum {
+ kRingDebugScripts = 1 << 0
+};
+
+struct tSageGameDescription;
+
+#define SCREEN_WIDTH 320
+#define SCREEN_HEIGHT 200
+#define SCREEN_CENTER_X 160
+#define SCREEN_CENTER_Y 100
+
+class TSageEngine : public Engine {
+private:
+ const tSageGameDescription *_gameDescription;
+public:
+ TSageEngine(OSystem *system, const tSageGameDescription *gameDesc);
+ ~TSageEngine();
+ virtual bool hasFeature(EngineFeature f) const;
+
+ MemoryManager _memoryManager;
+ Debugger *_debugger;
+
+ const char *getGameId() const;
+ uint32 getGameID() const;
+ uint32 getFeatures() const;
+ Common::String getPrimaryFilename() const;
+
+ virtual Common::Error init();
+ virtual Common::Error run();
+ virtual bool canLoadGameStateCurrently();
+ virtual bool canSaveGameStateCurrently();
+ virtual Common::Error loadGameState(int slot);
+ virtual Common::Error saveGameState(int slot, const char *desc);
+ Common::String generateSaveName(int slot);
+
+ void initialise();
+ void deinitialise();
+};
+
+extern TSageEngine *_vm;
+
+#define ALLOCATE_HANDLE(x) _vm->_memoryManager.allocate(x)
+#define ALLOCATE(x) _vm->_memoryManager.allocate2(x)
+#define DEALLOCATE(x) _vm->_memoryManager.deallocate(x)
+
+} // End of namespace tSage
+
+#endif
diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp
index f0437d2f87..7404abc2e7 100644
--- a/engines/tucker/detection.cpp
+++ b/engines/tucker/detection.cpp
@@ -122,8 +122,8 @@ static const ADParams detectionParams = {
0,
// Flags
0,
- // Additional GUI options (for every game}
- Common::GUIO_NOLAUNCHLOAD,
+ // Additional GUI options (for every game)
+ Common::GUIO_NONE,
// Maximum directory depth
1,
// List of directory globs
@@ -156,6 +156,7 @@ public:
virtual bool hasFeature(MetaEngineFeature f) const {
switch (f) {
case kSupportsListSaves:
+ case kSupportsLoadingDuringStartup:
case kSupportsDeleteSave:
return true;
default:
diff --git a/engines/tucker/locations.cpp b/engines/tucker/locations.cpp
index 108c6bcad5..ee117d233d 100644
--- a/engines/tucker/locations.cpp
+++ b/engines/tucker/locations.cpp
@@ -26,6 +26,7 @@
#include "tucker/tucker.h"
#include "tucker/graphics.h"
#include "common/system.h"
+#include "graphics/palette.h"
namespace Tucker {
diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp
index c0f1baae99..aeb4399dee 100644
--- a/engines/tucker/resource.cpp
+++ b/engines/tucker/resource.cpp
@@ -24,6 +24,7 @@
*/
#include "common/file.h"
+#include "common/textconsole.h"
#include "audio/audiostream.h"
#include "audio/decoders/flac.h"
diff --git a/engines/tucker/saveload.cpp b/engines/tucker/saveload.cpp
index 83533a90c3..52c6bf19ce 100644
--- a/engines/tucker/saveload.cpp
+++ b/engines/tucker/saveload.cpp
@@ -24,6 +24,7 @@
*/
#include "common/savefile.h"
+#include "common/textconsole.h"
#include "tucker/tucker.h"
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index 5e99e3ccef..d747b346ee 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -24,11 +24,14 @@
*/
#include "common/system.h"
+#include "common/textconsole.h"
#include "audio/audiostream.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/wave.h"
+#include "graphics/palette.h"
+
#include "tucker/tucker.h"
#include "tucker/graphics.h"
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
index 6e44eadc47..ed3046867b 100644
--- a/engines/tucker/tucker.cpp
+++ b/engines/tucker/tucker.cpp
@@ -26,10 +26,17 @@
#include "common/config-manager.h"
#include "common/events.h"
#include "common/system.h"
+#include "common/archive.h"
+#include "common/debug.h"
+#include "common/error.h"
+#include "common/keyboard.h"
+#include "common/textconsole.h"
#include "engines/util.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
+#include "gui/debugger.h"
#include "tucker/tucker.h"
#include "tucker/graphics.h"
@@ -68,12 +75,6 @@ Common::Error TuckerEngine::run() {
return Common::kNoError;
}
-void TuckerEngine::syncSoundSettings() {
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
-}
-
int TuckerEngine::getRandomNumber() {
return _rnd.getRandomNumber(0x7FFF);
}
@@ -130,10 +131,7 @@ void TuckerEngine::restart() {
_timerCounter2 = 0;
_partNum = _currentPartNum = 0;
_locationNum = 0;
- _nextLocationNum = ConfMan.getInt("boot_param");
- if (_nextLocationNum == 0) {
- _nextLocationNum = (_gameFlags & kGameFlagDemo) == 0 ? kStartupLocationGame : kStartupLocationDemo;
- }
+ _nextLocationNum = (_gameFlags & kGameFlagDemo) == 0 ? kStartupLocationGame : kStartupLocationDemo;
_gamePaused = false;
_gameDebug = false;
_displayGameHints = false;
@@ -359,6 +357,15 @@ void TuckerEngine::mainLoop() {
_spriteAnimationFrameIndex = _spriteAnimationsTable[14].firstFrameIndex;
+ if (ConfMan.hasKey("save_slot")) {
+ const int slot = ConfMan.getInt("save_slot");
+ if (slot >= 0 && slot <= kLastSaveSlot) {
+ loadGameState(slot);
+ }
+ } else if (ConfMan.hasKey("boot_param")) {
+ _nextLocationNum = ConfMan.getInt("boot_param");
+ }
+
do {
++_syncCounter;
if (_flagsTable[137] != _flagsTable[138]) {
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index fd931998e4..532892fd48 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -280,7 +280,6 @@ public:
virtual Common::Error run();
virtual bool hasFeature(EngineFeature f) const;
- virtual void syncSoundSettings();
GUI::Debugger *getDebugger() { return _console; }
protected: