aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorMatthew Hoops2011-08-26 22:44:17 -0400
committerMatthew Hoops2011-08-26 22:44:17 -0400
commit4a69dc13d92e82fff85dc5a3a923b74ced259ffa (patch)
tree8945cd3745fd65f28b043caf7b1beddbbce2b2a1 /engines
parentad293b249e74dd1cfbdbd721d02145efbdaf9eca (diff)
parent5e174cbfe466dbbe8e5470b0a00de1481b986181 (diff)
downloadscummvm-rg350-4a69dc13d92e82fff85dc5a3a923b74ced259ffa.tar.gz
scummvm-rg350-4a69dc13d92e82fff85dc5a3a923b74ced259ffa.tar.bz2
scummvm-rg350-4a69dc13d92e82fff85dc5a3a923b74ced259ffa.zip
Merge remote branch 'upstream/master' into pegasus
Diffstat (limited to 'engines')
-rw-r--r--engines/advancedDetector.h2
-rw-r--r--engines/agi/agi.cpp12
-rw-r--r--engines/agi/agi.h259
-rw-r--r--engines/agi/checks.cpp30
-rw-r--r--engines/agi/console.cpp34
-rw-r--r--engines/agi/console.h32
-rw-r--r--engines/agi/cycle.cpp6
-rw-r--r--engines/agi/detection.cpp36
-rw-r--r--engines/agi/detection_tables.h87
-rw-r--r--engines/agi/id.cpp18
-rw-r--r--engines/agi/keyboard.cpp4
-rw-r--r--engines/agi/loader_v1.cpp329
-rw-r--r--engines/agi/module.mk3
-rw-r--r--engines/agi/motion.cpp28
-rw-r--r--engines/agi/objects.cpp36
-rw-r--r--engines/agi/op_cmd.cpp1442
-rw-r--r--engines/agi/op_dbg.cpp255
-rw-r--r--engines/agi/op_test.cpp435
-rw-r--r--engines/agi/opcodes.cpp381
-rw-r--r--engines/agi/opcodes.h246
-rw-r--r--engines/agi/preagi.cpp230
-rw-r--r--engines/agi/preagi.h25
-rw-r--r--engines/agi/preagi_common.cpp205
-rw-r--r--engines/agi/preagi_mickey.cpp1068
-rw-r--r--engines/agi/preagi_mickey.h18
-rw-r--r--engines/agi/preagi_troll.cpp305
-rw-r--r--engines/agi/preagi_troll.h13
-rw-r--r--engines/agi/preagi_winnie.cpp575
-rw-r--r--engines/agi/preagi_winnie.h15
-rw-r--r--engines/agi/saveload.cpp10
-rw-r--r--engines/agi/sound.cpp27
-rw-r--r--engines/agi/sound.h10
-rw-r--r--engines/agi/sound_2gs.cpp2
-rw-r--r--engines/agi/sound_2gs.h2
-rw-r--r--engines/agi/sound_coco3.cpp2
-rw-r--r--engines/agi/sound_coco3.h2
-rw-r--r--engines/agi/sound_midi.cpp2
-rw-r--r--engines/agi/sound_midi.h2
-rw-r--r--engines/agi/sound_pcjr.cpp166
-rw-r--r--engines/agi/sound_pcjr.h17
-rw-r--r--engines/agi/sound_sarien.cpp2
-rw-r--r--engines/agi/sound_sarien.h2
-rw-r--r--engines/agi/sprite.cpp14
-rw-r--r--engines/agi/view.cpp57
-rw-r--r--engines/agi/view.h66
-rw-r--r--engines/agi/words.cpp136
-rw-r--r--engines/agos/agos.cpp36
-rw-r--r--engines/agos/agos.h17
-rw-r--r--engines/agos/charset-fontdata.cpp3
-rw-r--r--engines/agos/charset.cpp4
-rw-r--r--engines/agos/contain.cpp2
-rw-r--r--engines/agos/cursor.cpp4
-rw-r--r--engines/agos/debug.cpp1
-rw-r--r--engines/agos/debug.h1
-rw-r--r--engines/agos/debugger.cpp8
-rw-r--r--engines/agos/detection_tables.h52
-rw-r--r--engines/agos/draw.cpp3
-rw-r--r--engines/agos/event.cpp2
-rw-r--r--engines/agos/gfx.cpp3
-rw-r--r--engines/agos/icons.cpp2
-rw-r--r--engines/agos/input.cpp11
-rw-r--r--engines/agos/input_pn.cpp2
-rw-r--r--engines/agos/items.cpp2
-rw-r--r--engines/agos/menus.cpp2
-rw-r--r--engines/agos/midi.cpp4
-rw-r--r--engines/agos/midiparser_s1d.cpp207
-rw-r--r--engines/agos/oracle.cpp1
-rw-r--r--engines/agos/res_ami.cpp2
-rw-r--r--engines/agos/res_snd.cpp42
-rw-r--r--engines/agos/rooms.cpp4
-rw-r--r--engines/agos/saveload.cpp1
-rw-r--r--engines/agos/script.cpp3
-rw-r--r--engines/agos/script_dp.cpp2
-rw-r--r--engines/agos/script_pn.cpp1
-rw-r--r--engines/agos/script_s1.cpp33
-rw-r--r--engines/agos/script_s2.cpp5
-rw-r--r--engines/agos/script_ww.cpp2
-rw-r--r--engines/agos/sound.cpp14
-rw-r--r--engines/agos/sound.h4
-rw-r--r--engines/agos/verb.cpp1
-rw-r--r--engines/agos/vga.cpp1
-rw-r--r--engines/agos/vga_e2.cpp1
-rw-r--r--engines/agos/vga_s2.cpp17
-rw-r--r--engines/agos/window.cpp1
-rw-r--r--engines/agos/zones.cpp2
-rw-r--r--engines/composer/composer.cpp527
-rw-r--r--engines/composer/composer.h215
-rw-r--r--engines/composer/detection.cpp286
-rw-r--r--engines/composer/graphics.cpp774
-rw-r--r--engines/composer/graphics.h71
-rw-r--r--engines/composer/module.mk16
-rw-r--r--engines/composer/resource.cpp337
-rw-r--r--engines/composer/resource.h124
-rw-r--r--engines/composer/scripting.cpp729
-rw-r--r--engines/cruise/cruise.h10
-rw-r--r--engines/cruise/cruise_main.cpp32
-rw-r--r--engines/cruise/module.mk1
-rw-r--r--engines/cruise/saveload.cpp7
-rw-r--r--engines/cruise/sound.cpp1
-rw-r--r--engines/cruise/sound.h4
-rw-r--r--engines/dialogs.cpp1
-rw-r--r--engines/draci/saveload.cpp8
-rw-r--r--engines/drascula/drascula.h8
-rw-r--r--engines/drascula/resource.cpp9
-rw-r--r--engines/drascula/saveload.cpp109
-rw-r--r--engines/dreamweb/backdrop.cpp301
-rw-r--r--engines/dreamweb/detection.cpp11
-rw-r--r--engines/dreamweb/dreamgen.cpp4801
-rw-r--r--engines/dreamweb/dreamgen.h1588
-rw-r--r--engines/dreamweb/dreamweb.cpp35
-rw-r--r--engines/dreamweb/dreamweb.h3
-rw-r--r--engines/dreamweb/module.mk8
-rw-r--r--engines/dreamweb/pathfind.cpp106
-rw-r--r--engines/dreamweb/print.cpp229
-rw-r--r--engines/dreamweb/runtime.h15
-rw-r--r--engines/dreamweb/saveload.cpp343
-rw-r--r--engines/dreamweb/sprite.cpp893
-rw-r--r--engines/dreamweb/structs.h185
-rw-r--r--engines/dreamweb/stubs.cpp1981
-rw-r--r--engines/dreamweb/stubs.h169
-rw-r--r--engines/dreamweb/vgagrafx.cpp415
-rw-r--r--engines/engine.cpp12
-rw-r--r--engines/engines.mk6
-rw-r--r--engines/gob/console.cpp18
-rw-r--r--engines/gob/console.h1
-rw-r--r--engines/gob/dataio.cpp116
-rw-r--r--engines/gob/dataio.h15
-rw-r--r--engines/gob/detection_tables.h6
-rw-r--r--engines/gob/draw_v1.cpp4
-rw-r--r--engines/gob/draw_v2.cpp1
-rw-r--r--engines/gob/game.cpp3
-rw-r--r--engines/gob/gob.cpp12
-rw-r--r--engines/gob/init.h8
-rw-r--r--engines/gob/init_geisha.cpp (renamed from engines/agi/preagi_common.h)40
-rw-r--r--engines/gob/init_v1.cpp4
-rw-r--r--engines/gob/init_v2.cpp4
-rw-r--r--engines/gob/inter.h32
-rw-r--r--engines/gob/inter_geisha.cpp186
-rw-r--r--engines/gob/inter_v1.cpp16
-rw-r--r--engines/gob/inter_v3.cpp35
-rw-r--r--engines/gob/module.mk2
-rw-r--r--engines/gob/palanim.cpp9
-rw-r--r--engines/gob/scenery.cpp2
-rw-r--r--engines/groovie/groovie.cpp3
-rw-r--r--engines/groovie/music.cpp5
-rw-r--r--engines/groovie/music.h2
-rw-r--r--engines/groovie/script.cpp3
-rw-r--r--engines/hugo/detection.cpp7
-rw-r--r--engines/hugo/display.cpp1
-rw-r--r--engines/hugo/file.cpp1
-rw-r--r--engines/hugo/file_v1d.cpp1
-rw-r--r--engines/hugo/file_v1w.cpp1
-rw-r--r--engines/hugo/file_v2d.cpp1
-rw-r--r--engines/hugo/file_v2w.cpp1
-rw-r--r--engines/hugo/file_v3d.cpp1
-rw-r--r--engines/hugo/intro.cpp2
-rw-r--r--engines/hugo/schedule.cpp2
-rw-r--r--engines/hugo/sound.cpp92
-rw-r--r--engines/hugo/sound.h12
-rw-r--r--engines/kyra/animator_hof.cpp1
-rw-r--r--engines/kyra/animator_lok.cpp1
-rw-r--r--engines/kyra/animator_lok.h1
-rw-r--r--engines/kyra/animator_mr.cpp1
-rw-r--r--engines/kyra/animator_v2.cpp1
-rw-r--r--engines/kyra/debugger.cpp1
-rw-r--r--engines/kyra/debugger.h1
-rw-r--r--engines/kyra/detection.cpp1
-rw-r--r--engines/kyra/detection_tables.h197
-rw-r--r--engines/kyra/gui.cpp3
-rw-r--r--engines/kyra/gui.h1
-rw-r--r--engines/kyra/gui_hof.cpp1
-rw-r--r--engines/kyra/gui_hof.h1
-rw-r--r--engines/kyra/gui_lok.cpp1
-rw-r--r--engines/kyra/gui_lok.h1
-rw-r--r--engines/kyra/gui_lol.cpp5
-rw-r--r--engines/kyra/gui_lol.h1
-rw-r--r--engines/kyra/gui_mr.cpp1
-rw-r--r--engines/kyra/gui_mr.h1
-rw-r--r--engines/kyra/gui_v2.cpp1
-rw-r--r--engines/kyra/gui_v2.h1
-rw-r--r--engines/kyra/item.h1
-rw-r--r--engines/kyra/items_hof.cpp1
-rw-r--r--engines/kyra/items_lok.cpp8
-rw-r--r--engines/kyra/items_lol.cpp1
-rw-r--r--engines/kyra/items_mr.cpp1
-rw-r--r--engines/kyra/items_v2.cpp1
-rw-r--r--engines/kyra/kyra_hof.cpp8
-rw-r--r--engines/kyra/kyra_hof.h1
-rw-r--r--engines/kyra/kyra_lok.cpp4
-rw-r--r--engines/kyra/kyra_lok.h1
-rw-r--r--engines/kyra/kyra_mr.cpp1
-rw-r--r--engines/kyra/kyra_mr.h1
-rw-r--r--engines/kyra/kyra_v1.cpp1
-rw-r--r--engines/kyra/kyra_v1.h2
-rw-r--r--engines/kyra/kyra_v2.cpp1
-rw-r--r--engines/kyra/kyra_v2.h1
-rw-r--r--engines/kyra/lol.cpp58
-rw-r--r--engines/kyra/lol.h5
-rw-r--r--engines/kyra/resource.cpp3
-rw-r--r--engines/kyra/resource.h5
-rw-r--r--engines/kyra/saveload.cpp8
-rw-r--r--engines/kyra/saveload_hof.cpp1
-rw-r--r--engines/kyra/saveload_lok.cpp1
-rw-r--r--engines/kyra/saveload_lol.cpp1
-rw-r--r--engines/kyra/saveload_mr.cpp1
-rw-r--r--engines/kyra/scene_hof.cpp3
-rw-r--r--engines/kyra/scene_lok.cpp1
-rw-r--r--engines/kyra/scene_lol.cpp1
-rw-r--r--engines/kyra/scene_mr.cpp4
-rw-r--r--engines/kyra/scene_v2.cpp1
-rw-r--r--engines/kyra/screen.cpp1
-rw-r--r--engines/kyra/screen.h1
-rw-r--r--engines/kyra/screen_hof.cpp1
-rw-r--r--engines/kyra/screen_hof.h1
-rw-r--r--engines/kyra/screen_lol.cpp1
-rw-r--r--engines/kyra/screen_lol.h1
-rw-r--r--engines/kyra/screen_v2.cpp1
-rw-r--r--engines/kyra/screen_v2.h1
-rw-r--r--engines/kyra/script.cpp1
-rw-r--r--engines/kyra/script.h1
-rw-r--r--engines/kyra/script_hof.cpp1
-rw-r--r--engines/kyra/script_lok.cpp6
-rw-r--r--engines/kyra/script_lol.cpp1
-rw-r--r--engines/kyra/script_tim.cpp1
-rw-r--r--engines/kyra/script_tim.h1
-rw-r--r--engines/kyra/script_v1.cpp1
-rw-r--r--engines/kyra/script_v2.cpp1
-rw-r--r--engines/kyra/seqplayer.cpp1
-rw-r--r--engines/kyra/seqplayer.h1
-rw-r--r--engines/kyra/sequences_hof.cpp2
-rw-r--r--engines/kyra/sequences_lok.cpp3
-rw-r--r--engines/kyra/sequences_lol.cpp4
-rw-r--r--engines/kyra/sequences_mr.cpp1
-rw-r--r--engines/kyra/sequences_v2.cpp1
-rw-r--r--engines/kyra/sound.cpp2
-rw-r--r--engines/kyra/sound_adlib.cpp1
-rw-r--r--engines/kyra/sound_adlib.h1
-rw-r--r--engines/kyra/sound_amiga.cpp1
-rw-r--r--engines/kyra/sound_digital.cpp1
-rw-r--r--engines/kyra/sound_lol.cpp1
-rw-r--r--engines/kyra/sound_midi.cpp1
-rw-r--r--engines/kyra/sound_pcspk.cpp1
-rw-r--r--engines/kyra/sound_towns.cpp1
-rw-r--r--engines/kyra/sprites.cpp1
-rw-r--r--engines/kyra/sprites.h1
-rw-r--r--engines/kyra/sprites_lol.cpp1
-rw-r--r--engines/kyra/staticres.cpp28
-rw-r--r--engines/kyra/staticres_lol.cpp23
-rw-r--r--engines/kyra/text.h1
-rw-r--r--engines/kyra/text_hof.h1
-rw-r--r--engines/kyra/text_lol.cpp1
-rw-r--r--engines/kyra/text_lol.h1
-rw-r--r--engines/kyra/text_mr.cpp1
-rw-r--r--engines/kyra/timer.h1
-rw-r--r--engines/kyra/timer_lok.cpp1
-rw-r--r--engines/kyra/timer_lol.cpp1
-rw-r--r--engines/kyra/util.cpp1
-rw-r--r--engines/kyra/util.h1
-rw-r--r--engines/kyra/wsamovie.cpp2
-rw-r--r--engines/kyra/wsamovie.h2
-rw-r--r--engines/lastexpress/lastexpress.cpp3
-rw-r--r--engines/lastexpress/lastexpress.h1
-rw-r--r--engines/lastexpress/module.mk2
-rw-r--r--engines/lure/module.mk1
-rw-r--r--engines/lure/sound.h3
-rw-r--r--engines/m4/converse.cpp6
-rw-r--r--engines/m4/globals.cpp9
-rw-r--r--engines/m4/globals.h2
-rw-r--r--engines/m4/m4.h1
-rw-r--r--engines/m4/mads_logic.cpp41
-rw-r--r--engines/m4/midi.h1
-rw-r--r--engines/m4/saveload.cpp3
-rw-r--r--engines/m4/scripttab.h1
-rw-r--r--engines/made/detection.cpp30
-rw-r--r--engines/mohawk/console.cpp2
-rw-r--r--engines/mohawk/cstime.h2
-rw-r--r--engines/mohawk/cursors.cpp37
-rw-r--r--engines/mohawk/detection_tables.h84
-rw-r--r--engines/mohawk/dialogs.cpp24
-rw-r--r--engines/mohawk/dialogs.h1
-rw-r--r--engines/mohawk/graphics.cpp11
-rw-r--r--engines/mohawk/graphics.h4
-rw-r--r--engines/mohawk/livingbooks.h2
-rw-r--r--engines/mohawk/mohawk.cpp2
-rw-r--r--engines/mohawk/myst.cpp14
-rw-r--r--engines/mohawk/myst.h1
-rw-r--r--engines/mohawk/myst_scripts.cpp2
-rw-r--r--engines/mohawk/myst_stacks/demo.cpp98
-rw-r--r--engines/mohawk/myst_stacks/demo.h14
-rw-r--r--engines/mohawk/myst_stacks/myst.h4
-rw-r--r--engines/mohawk/myst_stacks/preview.cpp213
-rw-r--r--engines/mohawk/myst_stacks/preview.h27
-rw-r--r--engines/mohawk/myst_stacks/slides.cpp25
-rw-r--r--engines/mohawk/myst_stacks/slides.h2
-rw-r--r--engines/mohawk/myst_state.cpp8
-rw-r--r--engines/mohawk/riven.cpp175
-rw-r--r--engines/mohawk/riven.h8
-rw-r--r--engines/mohawk/riven_external.cpp32
-rw-r--r--engines/mohawk/riven_vars.cpp8
-rw-r--r--engines/mohawk/sound.cpp7
-rw-r--r--engines/mohawk/sound.h7
-rw-r--r--engines/parallaction/graphics.h9
-rw-r--r--engines/parallaction/gui_br.cpp1
-rw-r--r--engines/parallaction/sound.h3
-rw-r--r--engines/parallaction/walk.cpp80
-rw-r--r--engines/queen/command.h1
-rw-r--r--engines/queen/credits.cpp1
-rw-r--r--engines/saga/detection.cpp8
-rw-r--r--engines/saga/detection_tables.h16
-rw-r--r--engines/saga/input.cpp1
-rw-r--r--engines/saga/interface.cpp6
-rw-r--r--engines/saga/music.cpp3
-rw-r--r--engines/saga/palanim.h1
-rw-r--r--engines/saga/puzzle.cpp18
-rw-r--r--engines/saga/render.cpp2
-rw-r--r--engines/saga/saga.h1
-rw-r--r--engines/saga/saveload.cpp7
-rw-r--r--engines/saga/shorten.cpp1
-rw-r--r--engines/saga/shorten.h1
-rw-r--r--engines/saga/sthread.cpp1
-rw-r--r--engines/savestate.cpp1
-rw-r--r--engines/sci/decompressor.h1
-rw-r--r--engines/sci/detection.cpp29
-rw-r--r--engines/sci/detection_tables.h8
-rw-r--r--engines/sci/engine/kstring.cpp8
-rw-r--r--engines/sci/engine/script_patches.cpp18
-rw-r--r--engines/sci/engine/seg_manager.cpp6
-rw-r--r--engines/sci/engine/workarounds.cpp2
-rw-r--r--engines/sci/graphics/palette.cpp2
-rw-r--r--engines/sci/graphics/screen.cpp2
-rw-r--r--engines/sci/parser/said.cpp1
-rw-r--r--engines/sci/resource.cpp22
-rw-r--r--engines/sci/sound/drivers/cms.cpp1
-rw-r--r--engines/sci/sound/midiparser_sci.cpp6
-rw-r--r--engines/sci/sound/soundcmd.cpp31
-rw-r--r--engines/sci/sound/soundcmd.h1
-rw-r--r--engines/scumm/cursor.cpp71
-rw-r--r--engines/scumm/detection.cpp4
-rw-r--r--engines/scumm/detection_tables.h10
-rw-r--r--engines/scumm/dialogs.cpp71
-rw-r--r--engines/scumm/gfx.cpp1
-rw-r--r--engines/scumm/he/intern_he.h2
-rw-r--r--engines/scumm/he/logic/baseball2001.cpp63
-rw-r--r--engines/scumm/he/logic/basketball.cpp230
-rw-r--r--engines/scumm/he/logic/football.cpp288
-rw-r--r--engines/scumm/he/logic/funshop.cpp216
-rw-r--r--engines/scumm/he/logic/moonbase.cpp (renamed from engines/tsage/blueforce_logic.h)38
-rw-r--r--engines/scumm/he/logic/puttrace.cpp376
-rw-r--r--engines/scumm/he/logic/soccer.cpp1206
-rw-r--r--engines/scumm/he/logic_he.cpp1393
-rw-r--r--engines/scumm/he/logic_he.h155
-rw-r--r--engines/scumm/he/script_v100he.cpp22
-rw-r--r--engines/scumm/he/script_v72he.cpp11
-rw-r--r--engines/scumm/he/script_v80he.cpp5
-rw-r--r--engines/scumm/he/sprite_he.cpp10
-rw-r--r--engines/scumm/he/sprite_he.h1
-rw-r--r--engines/scumm/he/wiz_he.cpp2
-rw-r--r--engines/scumm/help.cpp2
-rw-r--r--engines/scumm/help.h1
-rw-r--r--engines/scumm/imuse/pcspk.cpp7
-rw-r--r--engines/scumm/imuse/pcspk.h3
-rw-r--r--engines/scumm/imuse/sysex.h1
-rw-r--r--engines/scumm/imuse_digi/dimuse.cpp2
-rw-r--r--engines/scumm/input.cpp12
-rw-r--r--engines/scumm/insane/insane_enemy.cpp1
-rw-r--r--engines/scumm/insane/insane_iact.cpp1
-rw-r--r--engines/scumm/insane/insane_scenes.cpp1
-rw-r--r--engines/scumm/module.mk9
-rw-r--r--engines/scumm/palette.cpp12
-rw-r--r--engines/scumm/player_v2.h5
-rw-r--r--engines/scumm/player_v2base.h6
-rw-r--r--engines/scumm/player_v2cms.cpp536
-rw-r--r--engines/scumm/player_v2cms.h74
-rw-r--r--engines/scumm/saveload.cpp7
-rw-r--r--engines/scumm/scumm-md5.h6
-rw-r--r--engines/scumm/scumm.cpp88
-rw-r--r--engines/scumm/scumm.h6
-rw-r--r--engines/scumm/smush/channel.cpp4
-rw-r--r--engines/scumm/smush/codec37.cpp1
-rw-r--r--engines/scumm/smush/smush_font.cpp1
-rw-r--r--engines/scumm/sound.cpp59
-rw-r--r--engines/scumm/sound.h3
-rw-r--r--engines/scumm/string.cpp10
-rw-r--r--engines/scumm/vars.cpp5
-rw-r--r--engines/sky/autoroute.h1
-rw-r--r--engines/sword1/control.h1
-rw-r--r--engines/sword1/debug.h1
-rw-r--r--engines/sword1/detection.cpp8
-rw-r--r--engines/sword1/music.cpp8
-rw-r--r--engines/sword1/music.h2
-rw-r--r--engines/sword1/object.h1
-rw-r--r--engines/sword1/screen.h3
-rw-r--r--engines/sword1/sound.cpp7
-rw-r--r--engines/sword2/music.cpp4
-rw-r--r--engines/sword2/sound.cpp6
-rw-r--r--engines/sword25/detection.cpp1
-rw-r--r--engines/sword25/sfx/soundengine.cpp2
-rw-r--r--engines/sword25/util/lua/lapi.cpp1
-rw-r--r--engines/sword25/util/lua/lauxlib.cpp1
-rw-r--r--engines/sword25/util/lua/lauxlib.h2
-rw-r--r--engines/sword25/util/lua/lbaselib.cpp1
-rw-r--r--engines/sword25/util/lua/lcode.cpp1
-rw-r--r--engines/sword25/util/lua/ldblib.cpp1
-rw-r--r--engines/sword25/util/lua/ldebug.cpp1
-rw-r--r--engines/sword25/util/lua/ldo.cpp2
-rw-r--r--engines/sword25/util/lua/ldo.h1
-rw-r--r--engines/sword25/util/lua/lfunc.cpp1
-rw-r--r--engines/sword25/util/lua/lgc.cpp1
-rw-r--r--engines/sword25/util/lua/linit.cpp1
-rw-r--r--engines/sword25/util/lua/liolib.cpp1
-rw-r--r--engines/sword25/util/lua/llex.cpp1
-rw-r--r--engines/sword25/util/lua/lmathlib.cpp1
-rw-r--r--engines/sword25/util/lua/lmem.cpp1
-rw-r--r--engines/sword25/util/lua/lmem.h1
-rw-r--r--engines/sword25/util/lua/loadlib.cpp1
-rw-r--r--engines/sword25/util/lua/lobject.h1
-rw-r--r--engines/sword25/util/lua/lopcodes.cpp1
-rw-r--r--engines/sword25/util/lua/loslib.cpp1
-rw-r--r--engines/sword25/util/lua/lstate.cpp1
-rw-r--r--engines/sword25/util/lua/lstate.h1
-rw-r--r--engines/sword25/util/lua/lstring.cpp1
-rw-r--r--engines/sword25/util/lua/lstrlib.cpp1
-rw-r--r--engines/sword25/util/lua/ltablib.cpp1
-rw-r--r--engines/sword25/util/lua/ltm.cpp1
-rw-r--r--engines/sword25/util/lua/luaconf.h1
-rw-r--r--engines/sword25/util/lua/lvm.cpp1
-rw-r--r--engines/sword25/util/lua/lzio.cpp2
-rw-r--r--engines/sword25/util/pluto/CHANGELOG1
-rw-r--r--engines/sword25/util/pluto/FILEFORMAT2
-rw-r--r--engines/sword25/util/pluto/THANKS1
-rw-r--r--engines/sword25/util/pluto/plzio.cpp2
-rw-r--r--engines/teenagent/animation.cpp28
-rw-r--r--engines/teenagent/animation.h2
-rw-r--r--engines/teenagent/detection.cpp5
-rw-r--r--engines/teenagent/font.h1
-rw-r--r--engines/teenagent/inventory.cpp6
-rw-r--r--engines/teenagent/scene.cpp14
-rw-r--r--engines/teenagent/surface.cpp14
-rw-r--r--engines/teenagent/surface.h2
-rw-r--r--engines/teenagent/surface_list.cpp14
-rw-r--r--engines/teenagent/surface_list.h3
-rw-r--r--engines/teenagent/teenagent.cpp2
-rw-r--r--engines/testbed/misc.cpp4
-rw-r--r--engines/tinsel/adpcm.cpp2
-rw-r--r--engines/tinsel/coroutine.cpp1
-rw-r--r--engines/tinsel/detection.cpp16
-rw-r--r--engines/tinsel/detection_tables.h26
-rw-r--r--engines/tinsel/saveload.cpp9
-rw-r--r--engines/tinsel/sound.cpp9
-rw-r--r--engines/tinsel/strres.h1
-rw-r--r--engines/tinsel/tinsel.h4
-rw-r--r--engines/toon/audio.cpp1
-rw-r--r--engines/toon/character.cpp1
-rw-r--r--engines/toon/detection.cpp7
-rw-r--r--engines/toon/drew.cpp1
-rw-r--r--engines/toon/hotspot.cpp1
-rw-r--r--engines/toon/path.cpp100
-rw-r--r--engines/toon/path.h17
-rw-r--r--engines/toon/script.cpp1
-rw-r--r--engines/toon/script.h1
-rw-r--r--engines/tsage/blue_force/blueforce_logic.cpp785
-rw-r--r--engines/tsage/blue_force/blueforce_logic.h294
-rw-r--r--engines/tsage/blue_force/blueforce_scenes0.cpp501
-rw-r--r--engines/tsage/blue_force/blueforce_scenes0.h103
-rw-r--r--engines/tsage/blue_force/blueforce_scenes1.cpp432
-rw-r--r--engines/tsage/blue_force/blueforce_scenes1.h131
-rw-r--r--engines/tsage/blue_force/blueforce_scenes3.cpp602
-rw-r--r--engines/tsage/blue_force/blueforce_scenes3.h137
-rw-r--r--engines/tsage/blue_force/blueforce_ui.cpp366
-rw-r--r--engines/tsage/blue_force/blueforce_ui.h135
-rw-r--r--engines/tsage/blueforce_logic.cpp120
-rw-r--r--engines/tsage/converse.cpp47
-rw-r--r--engines/tsage/converse.h8
-rw-r--r--engines/tsage/core.cpp162
-rw-r--r--engines/tsage/core.h65
-rw-r--r--engines/tsage/debugger.cpp20
-rw-r--r--engines/tsage/debugger.h6
-rw-r--r--engines/tsage/detection.cpp18
-rw-r--r--engines/tsage/detection_tables.h28
-rw-r--r--engines/tsage/dialogs.cpp6
-rw-r--r--engines/tsage/dialogs.h4
-rw-r--r--engines/tsage/events.cpp31
-rw-r--r--engines/tsage/events.h10
-rw-r--r--engines/tsage/globals.cpp92
-rw-r--r--engines/tsage/globals.h46
-rw-r--r--engines/tsage/graphics.cpp22
-rw-r--r--engines/tsage/graphics.h6
-rw-r--r--engines/tsage/module.mk27
-rw-r--r--engines/tsage/resources.cpp4
-rw-r--r--engines/tsage/resources.h4
-rw-r--r--engines/tsage/ringworld/ringworld_demo.cpp (renamed from engines/tsage/ringworld_demo.cpp)10
-rw-r--r--engines/tsage/ringworld/ringworld_demo.h (renamed from engines/tsage/ringworld_demo.h)10
-rw-r--r--engines/tsage/ringworld/ringworld_logic.cpp (renamed from engines/tsage/ringworld_logic.cpp)44
-rw-r--r--engines/tsage/ringworld/ringworld_logic.h (renamed from engines/tsage/ringworld_logic.h)32
-rw-r--r--engines/tsage/ringworld/ringworld_scenes1.cpp (renamed from engines/tsage/ringworld_scenes1.cpp)38
-rw-r--r--engines/tsage/ringworld/ringworld_scenes1.h (renamed from engines/tsage/ringworld_scenes1.h)19
-rw-r--r--engines/tsage/ringworld/ringworld_scenes10.cpp (renamed from engines/tsage/ringworld_scenes10.cpp)13
-rw-r--r--engines/tsage/ringworld/ringworld_scenes10.h (renamed from engines/tsage/ringworld_scenes10.h)11
-rw-r--r--engines/tsage/ringworld/ringworld_scenes2.cpp (renamed from engines/tsage/ringworld_scenes2.cpp)10
-rw-r--r--engines/tsage/ringworld/ringworld_scenes2.h (renamed from engines/tsage/ringworld_scenes2.h)12
-rw-r--r--engines/tsage/ringworld/ringworld_scenes3.cpp (renamed from engines/tsage/ringworld_scenes3.cpp)16
-rw-r--r--engines/tsage/ringworld/ringworld_scenes3.h (renamed from engines/tsage/ringworld_scenes3.h)12
-rw-r--r--engines/tsage/ringworld/ringworld_scenes4.cpp (renamed from engines/tsage/ringworld_scenes4.cpp)12
-rw-r--r--engines/tsage/ringworld/ringworld_scenes4.h (renamed from engines/tsage/ringworld_scenes4.h)12
-rw-r--r--engines/tsage/ringworld/ringworld_scenes5.cpp (renamed from engines/tsage/ringworld_scenes5.cpp)12
-rw-r--r--engines/tsage/ringworld/ringworld_scenes5.h (renamed from engines/tsage/ringworld_scenes5.h)11
-rw-r--r--engines/tsage/ringworld/ringworld_scenes6.cpp (renamed from engines/tsage/ringworld_scenes6.cpp)9
-rw-r--r--engines/tsage/ringworld/ringworld_scenes6.h (renamed from engines/tsage/ringworld_scenes6.h)11
-rw-r--r--engines/tsage/ringworld/ringworld_scenes8.cpp (renamed from engines/tsage/ringworld_scenes8.cpp)12
-rw-r--r--engines/tsage/ringworld/ringworld_scenes8.h (renamed from engines/tsage/ringworld_scenes8.h)12
-rw-r--r--engines/tsage/saveload.cpp11
-rw-r--r--engines/tsage/saveload.h16
-rw-r--r--engines/tsage/scenes.cpp26
-rw-r--r--engines/tsage/scenes.h4
-rw-r--r--engines/tsage/sound.cpp324
-rw-r--r--engines/tsage/sound.h70
-rw-r--r--engines/tsage/staticres.cpp45
-rw-r--r--engines/tsage/staticres.h43
-rw-r--r--engines/tsage/tsage.cpp12
-rw-r--r--engines/tsage/tsage.h5
520 files changed, 21671 insertions, 12681 deletions
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index cbdfdf39d8..c5bfdbd26b 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -161,7 +161,7 @@ protected:
* is primarily based on computing and matching MD5 checksums of files.
* Since doing that for large files can be slow, it can be restricted
* to a subset of all files.
- * Typically this will be set to something between 5 and 50 kilobyte,
+ * Typically this will be set to something between 5 and 50 kilobytes,
* but arbitrary non-zero values are possible. The default is 5000.
*/
uint _md5Bytes;
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 0eefbab04d..4bebf97e95 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -504,6 +504,7 @@ AgiBase::AgiBase(OSystem *syst, const AGIGameDescription *gameDesc) : Engine(sys
_noSaveLoadAllowed = false;
_rnd = new Common::RandomSource("agi");
+ _sound = 0;
initFeatures();
initVersion();
@@ -511,6 +512,11 @@ AgiBase::AgiBase(OSystem *syst, const AGIGameDescription *gameDesc) : Engine(sys
AgiBase::~AgiBase() {
delete _rnd;
+
+ if (_sound) {
+ _sound->deinitSound();
+ delete _sound;
+ }
}
AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBase(syst, gameDesc) {
@@ -536,6 +542,8 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
memset(&_debug, 0, sizeof(struct AgiDebug));
memset(&_mouse, 0, sizeof(struct Mouse));
+ _game._vm = this;
+
_game.clockEnabled = false;
_game.state = STATE_INIT;
@@ -571,7 +579,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_game.controllerOccured[i] = false;
setupOpcodes();
- _curLogic = NULL;
+ _game._curLogic = NULL;
_timerHack = 0;
}
@@ -680,8 +688,6 @@ AgiEngine::~AgiEngine() {
agiDeinit();
delete _loader;
- _sound->deinitSound();
- delete _sound;
_gfx->deinitVideo();
delete _sprites;
delete _picture;
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 0155caf11d..080373d27b 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -88,6 +88,7 @@ typedef signed int Err;
#define _EMPTY 0xfffff
#define EGO_OWNED 0xff
+#define EGO_OWNED_V1 0xf9
#define CRYPT_KEY_SIERRA "Avis Durgan"
#define CRYPT_KEY_AGDS "Alex Simkin"
@@ -131,10 +132,16 @@ enum AgiGameID {
enum AgiGameType {
GType_PreAGI = 0,
- GType_V2 = 1,
- GType_V3 = 2
+ GType_V1 = 1,
+ GType_V2 = 2,
+ GType_V3 = 3
};
+ enum BooterDisks {
+ BooterDisk1 = 0,
+ BooterDisk2 = 1
+ };
+
//
// GF_OLDAMIGAV20 means that the interpreter is an old Amiga AGI interpreter that
// uses value 20 for the computer type (v20 i.e. vComputer) rather than the usual value 5.
@@ -537,6 +544,8 @@ enum {
* by the interpreter.
*/
struct AgiGame {
+ AgiEngine *_vm;
+
State state; /**< state of the interpreter */
// TODO: Check whether adjMouseX and adjMouseY must be saved and loaded when using savegames.
@@ -621,6 +630,11 @@ struct AgiGame {
AgiView views[MAX_DIRS]; /**< AGI view resources */
AgiSound *sounds[MAX_DIRS]; /**< Pointers to AGI sound resources */
+ AgiLogic *_curLogic;
+
+ // words
+ Common::Array<AgiWord*> words[26];
+
// view table
VtEntry viewTable[MAX_VIEWTABLE];
@@ -629,6 +643,13 @@ struct AgiGame {
int simpleSave; /**< select simple savegames */
Common::Rect mouseFence; /**< rectangle set by fence.mouse command */
+
+ // IF condition handling
+ int testResult;
+
+
+ int max_logics;
+ int logic_list[256];
};
class AgiLoader {
@@ -646,6 +667,28 @@ public:
virtual int loadWords(const char *) = 0;
};
+class AgiLoader_v1 : public AgiLoader {
+private:
+ AgiEngine *_vm;
+ Common::String _filenameDisk0;
+ Common::String _filenameDisk1;
+
+ int loadDir_DDP(AgiDir *agid, int offset, int max);
+ int loadDir_BC(AgiDir *agid, int offset, int max);
+ uint8 *loadVolRes(AgiDir *agid);
+
+public:
+ AgiLoader_v1(AgiEngine *vm);
+
+ virtual int init();
+ virtual int deinit();
+ virtual int detectGame();
+ virtual int loadResource(int, int);
+ virtual int unloadResource(int, int);
+ virtual int loadObjects(const char *);
+ virtual int loadWords(const char *);
+};
+
class AgiLoader_v2 : public AgiLoader {
private:
AgiEngine *_vm;
@@ -690,6 +733,7 @@ public:
virtual int loadWords(const char *);
};
+
class GfxMgr;
class SpritesMgr;
class Menu;
@@ -745,6 +789,8 @@ public:
AgiGame _game;
Common::RandomSource *_rnd;
+ SoundMgr *_sound;
+
Mouse _mouse;
bool _noSaveLoadAllowed;
@@ -789,10 +835,14 @@ public:
void initVersion();
void setVersion(uint16 version);
+ const char *getDiskName(uint16 id);
+
bool canLoadGameStateCurrently();
bool canSaveGameStateCurrently();
};
+typedef void (*AgiCommand)(AgiGame *state, uint8 *p);
+
class AgiEngine : public AgiBase {
protected:
// Engine APIs
@@ -851,7 +901,6 @@ public:
char _lastSentence[40];
SpritesMgr *_sprites;
- SoundMgr *_sound;
PictureMgr *_picture;
AgiLoader *_loader; // loader
@@ -915,16 +964,21 @@ public:
void checkQuickLoad();
// Objects
+public:
int showObjects();
- int decodeObjects(uint8 *mem, uint32 flen);
int loadObjects(const char *fname);
- int allocObjects(int);
+ int loadObjects(Common::File &fp);
void unloadObjects();
const char *objectName(unsigned int);
int objectGetLocation(unsigned int);
void objectSetLocation(unsigned int, int);
+private:
+ int decodeObjects(uint8 *mem, uint32 flen);
+ int readObjects(Common::File &fp, int flen);
+ int allocObjects(int);
// Logic
+public:
int decodeLogic(int);
void unloadLogic(int);
int runLogic(int);
@@ -932,8 +986,10 @@ public:
int testIfCode(int);
void executeAgiCommand(uint8, uint8 *);
-private:
+public:
// Some submethods of testIfCode
+ void skipInstruction(byte op);
+ void skipInstructionsUntil(byte v);
uint8 testObjRight(uint8, uint8, uint8, uint8, uint8);
uint8 testObjCenter(uint8, uint8, uint8, uint8, uint8);
uint8 testObjInBox(uint8, uint8, uint8, uint8, uint8);
@@ -966,8 +1022,10 @@ public:
bool isEgoView(const VtEntry *v);
// Words
+public:
int showWords();
int loadWords(const char *);
+ int loadWords_v1(Common::File &f);
void unloadWords();
int findWord(const char *word, int *flen);
void dictionaryWords(char *);
@@ -1045,196 +1103,13 @@ public:
char _predictiveResult[40];
private:
- typedef void (AgiEngine::*AgiCommand)(uint8 *);
-
AgiCommand _agiCommands[183];
- AgiLogic *_curLogic;
- int _timerHack; // Workaround for timer loop in MH1 logic 153
+ AgiCommand _agiCondCommands[256];
void setupOpcodes();
- void cmd_increment(uint8 *p);
- void cmd_decrement(uint8 *p);
- void cmd_assignn(uint8 *p);
- void cmd_assignv(uint8 *p);
- void cmd_addn(uint8 *p);
- void cmd_addv(uint8 *p);
- void cmd_subn(uint8 *p);
- void cmd_subv(uint8 *p); // 0x08
- void cmd_lindirectv(uint8 *p);
- void cmd_rindirect(uint8 *p);
- void cmd_lindirectn(uint8 *p);
- void cmd_set(uint8 *p);
- void cmd_reset(uint8 *p);
- void cmd_toggle(uint8 *p);
- void cmd_set_v(uint8 *p);
- void cmd_reset_v(uint8 *p); // 0x10
- void cmd_toggle_v(uint8 *p);
- void cmd_new_room(uint8 *p);
- void cmd_new_room_f(uint8 *p);
- void cmd_load_logic(uint8 *p);
- void cmd_load_logic_f(uint8 *p);
- void cmd_call(uint8 *p);
- void cmd_call_f(uint8 *p);
- void cmd_load_pic(uint8 *p); // 0x18
- void cmd_draw_pic(uint8 *p);
- void cmd_show_pic(uint8 *p);
- void cmd_discard_pic(uint8 *p);
- void cmd_overlay_pic(uint8 *p);
- void cmd_show_pri_screen(uint8 *p);
- void cmd_load_view(uint8 *p);
- void cmd_load_view_f(uint8 *p);
- void cmd_discard_view(uint8 *p); // 0x20
- void cmd_animate_obj(uint8 *p);
- void cmd_unanimate_all(uint8 *p);
- void cmd_draw(uint8 *p);
- void cmd_erase(uint8 *p);
- void cmd_position(uint8 *p);
- void cmd_position_f(uint8 *p);
- void cmd_get_posn(uint8 *p);
- void cmd_reposition(uint8 *p); // 0x28
- void cmd_set_view(uint8 *p);
- void cmd_set_view_f(uint8 *p);
- void cmd_set_loop(uint8 *p);
- void cmd_set_loop_f(uint8 *p);
- void cmd_fix_loop(uint8 *p);
- void cmd_release_loop(uint8 *p);
- void cmd_set_cel(uint8 *p);
- void cmd_set_cel_f(uint8 *p); // 0x30
- void cmd_last_cel(uint8 *p);
- void cmd_current_cel(uint8 *p);
- void cmd_current_loop(uint8 *p);
- void cmd_current_view(uint8 *p);
- void cmd_number_of_loops(uint8 *p);
- void cmd_set_priority(uint8 *p);
- void cmd_set_priority_f(uint8 *p);
- void cmd_release_priority(uint8 *p); // 0x38
- void cmd_get_priority(uint8 *p);
- void cmd_stop_update(uint8 *p);
- void cmd_start_update(uint8 *p);
- void cmd_force_update(uint8 *p);
- void cmd_ignore_horizon(uint8 *p);
- void cmd_observe_horizon(uint8 *p);
- void cmd_set_horizon(uint8 *p);
- void cmd_object_on_water(uint8 *p); // 0x40
- void cmd_object_on_land(uint8 *p);
- void cmd_object_on_anything(uint8 *p);
- void cmd_ignore_objs(uint8 *p);
- void cmd_observe_objs(uint8 *p);
- void cmd_distance(uint8 *p);
- void cmd_stop_cycling(uint8 *p);
- void cmd_start_cycling(uint8 *p);
- void cmd_normal_cycle(uint8 *p); // 0x48
- void cmd_end_of_loop(uint8 *p);
- void cmd_reverse_cycle(uint8 *p);
- void cmd_reverse_loop(uint8 *p);
- void cmd_cycle_time(uint8 *p);
- void cmd_stop_motion(uint8 *p);
- void cmd_start_motion(uint8 *p);
- void cmd_step_size(uint8 *p);
- void cmd_step_time(uint8 *p); // 0x50
- void cmd_move_obj(uint8 *p);
- void cmd_move_obj_f(uint8 *p);
- void cmd_follow_ego(uint8 *p);
- void cmd_wander(uint8 *p);
- void cmd_normal_motion(uint8 *p);
- void cmd_set_dir(uint8 *p);
- void cmd_get_dir(uint8 *p);
- void cmd_ignore_blocks(uint8 *p); // 0x58
- void cmd_observe_blocks(uint8 *p);
- void cmd_block(uint8 *p);
- void cmd_unblock(uint8 *p);
- void cmd_get(uint8 *p);
- void cmd_get_f(uint8 *p);
- void cmd_drop(uint8 *p);
- void cmd_put(uint8 *p);
- void cmd_put_f(uint8 *p); // 0x60
- void cmd_get_room_f(uint8 *p);
- void cmd_load_sound(uint8 *p);
- void cmd_sound(uint8 *p);
- void cmd_stop_sound(uint8 *p);
- void cmd_print(uint8 *p);
- void cmd_print_f(uint8 *p);
- void cmd_display(uint8 *p);
- void cmd_display_f(uint8 *p); // 0x68
- void cmd_clear_lines(uint8 *p);
- void cmd_text_screen(uint8 *p);
- void cmd_graphics(uint8 *p);
- void cmd_set_cursor_char(uint8 *p);
- void cmd_set_text_attribute(uint8 *p);
- void cmd_shake_screen(uint8 *p);
- void cmd_configure_screen(uint8 *p);
- void cmd_status_line_on(uint8 *p); // 0x70
- void cmd_status_line_off(uint8 *p);
- void cmd_set_string(uint8 *p);
- void cmd_get_string(uint8 *p);
- void cmd_word_to_string(uint8 *p);
- void cmd_parse(uint8 *p);
- void cmd_get_num(uint8 *p);
- void cmd_prevent_input(uint8 *p);
- void cmd_accept_input(uint8 *p); // 0x78
- void cmd_set_key(uint8 *p);
- void cmd_add_to_pic(uint8 *p);
- void cmd_add_to_pic_f(uint8 *p);
- void cmd_status(uint8 *p);
- void cmd_save_game(uint8 *p);
- void cmd_load_game(uint8 *p);
- void cmd_init_disk(uint8 *p);
- void cmd_restart_game(uint8 *p); // 0x80
- void cmd_show_obj(uint8 *p);
- void cmd_random(uint8 *p);
- void cmd_program_control(uint8 *p);
- void cmd_player_control(uint8 *p);
- void cmd_obj_status_f(uint8 *p);
- void cmd_quit(uint8 *p);
- void cmd_show_mem(uint8 *p);
- void cmd_pause(uint8 *p); // 0x88
- void cmd_echo_line(uint8 *p);
- void cmd_cancel_line(uint8 *p);
- void cmd_init_joy(uint8 *p);
- void cmd_toggle_monitor(uint8 *p);
- void cmd_version(uint8 *p);
- void cmd_script_size(uint8 *p);
- void cmd_set_game_id(uint8 *p);
- void cmd_log(uint8 *p); // 0x90
- void cmd_set_scan_start(uint8 *p);
- void cmd_reset_scan_start(uint8 *p);
- void cmd_reposition_to(uint8 *p);
- void cmd_reposition_to_f(uint8 *p);
- void cmd_trace_on(uint8 *p);
- void cmd_trace_info(uint8 *p);
- void cmd_print_at(uint8 *p);
- void cmd_print_at_v(uint8 *p); // 0x98
- //void cmd_discard_view(uint8 *p); // Opcode repeated from 0x20 ?
- void cmd_clear_text_rect(uint8 *p);
- void cmd_set_upper_left(uint8 *p);
- void cmd_set_menu(uint8 *p);
- void cmd_set_menu_item(uint8 *p);
- void cmd_submit_menu(uint8 *p);
- void cmd_enable_item(uint8 *p);
- void cmd_disable_item(uint8 *p); // 0xa0
- void cmd_menu_input(uint8 *p);
- void cmd_show_obj_v(uint8 *p);
- void cmd_open_dialogue(uint8 *p);
- void cmd_close_dialogue(uint8 *p);
- void cmd_mul_n(uint8 *p);
- void cmd_mul_v(uint8 *p);
- void cmd_div_n(uint8 *p);
- void cmd_div_v(uint8 *p); // 0xa8
- void cmd_close_window(uint8 *p);
- void cmd_set_simple(uint8 *p);
- void cmd_push_script(uint8 *p);
- void cmd_pop_script(uint8 *p);
- void cmd_hold_key(uint8 *p);
- void cmd_set_pri_base(uint8 *p);
- void cmd_discard_sound(uint8 *p);
- void cmd_hide_mouse(uint8 *p); // 0xb0
- void cmd_allow_menu(uint8 *p);
- void cmd_show_mouse(uint8 *p);
- void cmd_fence_mouse(uint8 *p);
- void cmd_mouse_posn(uint8 *p);
- void cmd_release_key(uint8 *p);
- void cmd_adj_ego_move_to_x_y(uint8 *p);
+public:
+ int _timerHack; // Workaround for timer loop in MH1 logic 153
};
} // End of namespace Agi
diff --git a/engines/agi/checks.cpp b/engines/agi/checks.cpp
index 20276657ff..c3b31f6ba9 100644
--- a/engines/agi/checks.cpp
+++ b/engines/agi/checks.cpp
@@ -31,7 +31,7 @@ int AgiEngine::checkPosition(VtEntry *v) {
v->xPos + v->xSize > _WIDTH ||
v->yPos - v->ySize + 1 < 0 ||
v->yPos >= _HEIGHT ||
- ((~v->flags & IGNORE_HORIZON) && v->yPos <= _game.horizon)) {
+ ((~v->flags & fIgnoreHorizon) && v->yPos <= _game.horizon)) {
debugC(4, kDebugLevelSprites, "check position failed: x=%d, y=%d, h=%d, w=%d",
v->xPos, v->yPos, v->xSize, v->ySize);
return 0;
@@ -52,14 +52,14 @@ int AgiEngine::checkPosition(VtEntry *v) {
int AgiEngine::checkCollision(VtEntry *v) {
VtEntry *u;
- if (v->flags & IGNORE_OBJECTS)
+ if (v->flags & fIgnoreObjects)
return 0;
for (u = _game.viewTable; u < &_game.viewTable[MAX_VIEWTABLE]; u++) {
- if ((u->flags & (ANIMATED | DRAWN)) != (ANIMATED | DRAWN))
+ if ((u->flags & (fAnimated | fDrawn)) != (fAnimated | fDrawn))
continue;
- if (u->flags & IGNORE_OBJECTS)
+ if (u->flags & fIgnoreObjects)
continue;
// Same object, check next
@@ -92,7 +92,7 @@ int AgiEngine::checkPriority(VtEntry *v) {
int i, trigger, water, pass, pri;
uint8 *p0;
- if (~v->flags & FIXED_PRIORITY) {
+ if (~v->flags & fFixedPriority) {
// Priority bands
v->priority = _game.priTable[v->yPos];
}
@@ -129,7 +129,7 @@ int AgiEngine::checkPriority(VtEntry *v) {
water = 0;
if (pri == 1) { // conditional blue
- if (v->flags & IGNORE_BLOCKS)
+ if (v->flags & fIgnoreBlocks)
continue;
debugC(4, kDebugLevelSprites, "Blocks observed!");
@@ -145,9 +145,9 @@ int AgiEngine::checkPriority(VtEntry *v) {
}
if (pass) {
- if (!water && v->flags & ON_WATER)
+ if (!water && v->flags & fOnWater)
pass = 0;
- if (water && v->flags & ON_LAND)
+ if (water && v->flags & fOnLand)
pass = 0;
}
@@ -180,7 +180,7 @@ void AgiEngine::updatePosition() {
_game.vars[vBorderTouchObj] = 0;
for (v = _game.viewTable; v < &_game.viewTable[MAX_VIEWTABLE]; v++) {
- if ((v->flags & (ANIMATED | UPDATE | DRAWN)) != (ANIMATED | UPDATE | DRAWN)) {
+ if ((v->flags & (fAnimated | fUpdate | fDrawn)) != (fAnimated | fUpdate | fDrawn)) {
continue;
}
@@ -195,7 +195,7 @@ void AgiEngine::updatePosition() {
y = oldY = v->yPos;
// If object has moved, update its position
- if (~v->flags & UPDATE_POS) {
+ if (~v->flags & fUpdatePos) {
int dx[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 };
int dy[9] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 };
x += v->stepSize * dx[v->direction];
@@ -212,7 +212,7 @@ void AgiEngine::updatePosition() {
} else if (x <= 0 && getVersion() == 0x3086) { // KQ4
x = 0; // See Sarien bug #590462
border = 4;
- } else if (v->entry == 0 && x == 0 && v->flags & ADJ_EGO_XY) {
+ } else if (v->entry == 0 && x == 0 && v->flags & fAdjEgoXY) {
// Extra test to walk west clicking the mouse
x = 0;
border = 4;
@@ -228,7 +228,7 @@ void AgiEngine::updatePosition() {
} else if (y > _HEIGHT - 1) {
y = _HEIGHT - 1;
border = 3;
- } else if ((~v->flags & IGNORE_HORIZON) && y <= _game.horizon) {
+ } else if ((~v->flags & fIgnoreHorizon) && y <= _game.horizon) {
debugC(4, kDebugLevelSprites, "y = %d, horizon = %d", y, _game.horizon);
y = _game.horizon + 1;
border = 1;
@@ -251,12 +251,12 @@ void AgiEngine::updatePosition() {
_game.vars[vBorderCode] = v->entry;
_game.vars[vBorderTouchObj] = border;
}
- if (v->motion == MOTION_MOVE_OBJ) {
+ if (v->motion == kMotionMoveObj) {
inDestination(v);
}
}
- v->flags &= ~UPDATE_POS;
+ v->flags &= ~fUpdatePos;
}
}
@@ -276,7 +276,7 @@ void AgiEngine::fixPosition(int n) {
debugC(4, kDebugLevelSprites, "adjusting view table entry #%d (%d,%d)", n, v->xPos, v->yPos);
// test horizon
- if ((~v->flags & IGNORE_HORIZON) && v->yPos <= _game.horizon)
+ if ((~v->flags & fIgnoreHorizon) && v->yPos <= _game.horizon)
v->yPos = _game.horizon + 1;
dir = 0;
diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp
index d49bd57ea2..dd06736290 100644
--- a/engines/agi/console.cpp
+++ b/engines/agi/console.cpp
@@ -96,8 +96,8 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) {
for (int i = 0; logicNamesCmd[i].name; i++) {
if (!strcmp(argv[1], logicNamesCmd[i].name)) {
uint8 p[16];
- if ((argc - 2) != logicNamesCmd[i].numArgs) {
- DebugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].numArgs);
+ if ((argc - 2) != logicNamesCmd[i].argumentsLength()) {
+ DebugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].argumentsLength());
return 0;
}
p[0] = argv[2] ? (char)strtoul(argv[2], NULL, 0) : 0;
@@ -260,7 +260,7 @@ bool Console::Cmd_BT(int argc, const char **argv) {
for (it = _vm->_game.execStack.begin(); it != _vm->_game.execStack.end(); ++it) {
code = _vm->_game.logics[it->script].data;
op = code[it->curIP];
- num = logicNamesCmd[op].numArgs;
+ num = logicNamesCmd[op].argumentsLength();
memmove(p, &code[it->curIP], num);
memset(p + num, 0, CMD_BSIZE - num);
@@ -275,25 +275,21 @@ bool Console::Cmd_BT(int argc, const char **argv) {
return true;
}
-PreAGI_Console::PreAGI_Console(PreAgiEngine *vm) {
- _vm = vm;
-}
-
-Mickey_Console::Mickey_Console(PreAgiEngine *vm, Mickey *mickey) : PreAGI_Console(vm) {
+MickeyConsole::MickeyConsole(MickeyEngine *mickey) : GUI::Debugger() {
_mickey = mickey;
- DCmd_Register("curRoom", WRAP_METHOD(Mickey_Console, Cmd_CurRoom));
- DCmd_Register("gotoRoom", WRAP_METHOD(Mickey_Console, Cmd_GotoRoom));
- DCmd_Register("drawPic", WRAP_METHOD(Mickey_Console, Cmd_DrawPic));
- DCmd_Register("drawObj", WRAP_METHOD(Mickey_Console, Cmd_DrawObj));
+ DCmd_Register("curRoom", WRAP_METHOD(MickeyConsole, Cmd_CurRoom));
+ DCmd_Register("gotoRoom", WRAP_METHOD(MickeyConsole, Cmd_GotoRoom));
+ DCmd_Register("drawPic", WRAP_METHOD(MickeyConsole, Cmd_DrawPic));
+ DCmd_Register("drawObj", WRAP_METHOD(MickeyConsole, Cmd_DrawObj));
}
-bool Mickey_Console::Cmd_CurRoom(int argc, const char **argv) {
+bool MickeyConsole::Cmd_CurRoom(int argc, const char **argv) {
_mickey->debugCurRoom();
return true;
}
-bool Mickey_Console::Cmd_GotoRoom(int argc, const char **argv) {
+bool MickeyConsole::Cmd_GotoRoom(int argc, const char **argv) {
if (argc != 2)
DebugPrintf("Usage: %s <Room number>\n", argv[0]);
else
@@ -301,7 +297,7 @@ bool Mickey_Console::Cmd_GotoRoom(int argc, const char **argv) {
return true;
}
-bool Mickey_Console::Cmd_DrawPic(int argc, const char **argv) {
+bool MickeyConsole::Cmd_DrawPic(int argc, const char **argv) {
if (argc != 2)
DebugPrintf("Usage: %s <Picture number>\n", argv[0]);
else
@@ -309,7 +305,7 @@ bool Mickey_Console::Cmd_DrawPic(int argc, const char **argv) {
return true;
}
-bool Mickey_Console::Cmd_DrawObj(int argc, const char **argv) {
+bool MickeyConsole::Cmd_DrawObj(int argc, const char **argv) {
if (argc != 2)
DebugPrintf("Usage: %s <Object number>\n", argv[0]);
else
@@ -317,13 +313,13 @@ bool Mickey_Console::Cmd_DrawObj(int argc, const char **argv) {
return true;
}
-Winnie_Console::Winnie_Console(PreAgiEngine *vm, Winnie *winnie) : PreAGI_Console(vm) {
+WinnieConsole::WinnieConsole(WinnieEngine *winnie) : GUI::Debugger() {
_winnie = winnie;
- DCmd_Register("curRoom", WRAP_METHOD(Winnie_Console, Cmd_CurRoom));
+ DCmd_Register("curRoom", WRAP_METHOD(WinnieConsole, Cmd_CurRoom));
}
-bool Winnie_Console::Cmd_CurRoom(int argc, const char **argv) {
+bool WinnieConsole::Cmd_CurRoom(int argc, const char **argv) {
_winnie->debugCurRoom();
return true;
diff --git a/engines/agi/console.h b/engines/agi/console.h
index 308b0f1d1f..5f69460907 100644
--- a/engines/agi/console.h
+++ b/engines/agi/console.h
@@ -27,8 +27,8 @@ namespace Agi {
class AgiEngine;
class PreAgiEngine;
-class Winnie;
-class Mickey;
+class MickeyEngine;
+class WinnieEngine;
struct AgiDebug {
int enabled;
@@ -67,23 +67,13 @@ private:
AgiEngine *_vm;
};
-class PreAGI_Console : public GUI::Debugger {
+class MickeyConsole : public GUI::Debugger {
public:
- PreAGI_Console(PreAgiEngine *vm);
- virtual ~PreAGI_Console() {}
+ MickeyConsole(MickeyEngine *mickey);
+ virtual ~MickeyConsole() {}
private:
- PreAgiEngine *_vm;
-};
-
-
-class Mickey_Console : public PreAGI_Console {
-public:
- Mickey_Console(PreAgiEngine *vm, Mickey *mickey);
- virtual ~Mickey_Console() {}
-
-private:
- Mickey *_mickey;
+ MickeyEngine *_mickey;
bool Cmd_CurRoom(int argc, const char **argv);
bool Cmd_GotoRoom(int argc, const char **argv);
@@ -91,17 +81,17 @@ private:
bool Cmd_DrawObj(int argc, const char **argv);
};
-class Winnie_Console : public PreAGI_Console {
+class WinnieConsole : public GUI::Debugger {
public:
- Winnie_Console(PreAgiEngine *vm, Winnie *winnie);
- virtual ~Winnie_Console() {}
+ WinnieConsole(WinnieEngine *winnie);
+ virtual ~WinnieConsole() {}
private:
- Winnie *_winnie;
+ WinnieEngine *_winnie;
bool Cmd_CurRoom(int argc, const char **argv);
};
-} // End of namespace Agi
+} // End of namespace Agi
#endif /* AGI_CONSOLE_H */
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index d86fb36709..e6f122f9f6 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -47,8 +47,8 @@ void AgiEngine::newRoom(int n) {
i = 0;
for (v = _game.viewTable; v < &_game.viewTable[MAX_VIEWTABLE]; v++) {
v->entry = i++;
- v->flags &= ~(ANIMATED | DRAWN);
- v->flags |= UPDATE;
+ v->flags &= ~(fAnimated | fDrawn);
+ v->flags |= fUpdate;
v->stepTime = 1;
v->stepTimeCount = 1;
v->cycleTime = 1;
@@ -220,7 +220,7 @@ int AgiEngine::mainCycle() {
}
// Click-to-walk mouse interface
- if (_game.playerControl && v->flags & ADJ_EGO_XY) {
+ if (_game.playerControl && v->flags & fAdjEgoXY) {
int toX = v->parm1;
int toY = v->parm2;
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index a0736d0cc3..5141ab761f 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -28,6 +28,7 @@
#include "engines/advancedDetector.h"
#include "common/config-manager.h"
#include "common/file.h"
+#include "common/md5.h"
#include "common/savefile.h"
#include "common/textconsole.h"
#include "graphics/thumbnail.h"
@@ -35,6 +36,9 @@
#include "agi/agi.h"
#include "agi/preagi.h"
+#include "agi/preagi_mickey.h"
+#include "agi/preagi_troll.h"
+#include "agi/preagi_winnie.h"
#include "agi/wagparser.h"
@@ -93,6 +97,14 @@ void AgiBase::initVersion() {
_gameVersion = _gameDescription->version;
}
+const char *AgiBase::getDiskName(uint16 id) {
+ for (int i = 0; _gameDescription->desc.filesDescriptions[i].fileName != NULL; i++)
+ if (_gameDescription->desc.filesDescriptions[i].fileType == id)
+ return _gameDescription->desc.filesDescriptions[i].fileName;
+
+ return "";
+}
+
}
static const PlainGameDescriptor agiGames[] = {
@@ -182,8 +194,19 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD
switch (gd->gameType) {
case Agi::GType_PreAGI:
- *engine = new Agi::PreAgiEngine(syst, gd);
+ switch (gd->gameID) {
+ case GID_MICKEY:
+ *engine = new Agi::MickeyEngine(syst, gd);
+ break;
+ case GID_TROLL:
+ *engine = new Agi::TrollEngine(syst, gd);
+ break;
+ case GID_WINNIE:
+ *engine = new Agi::WinnieEngine(syst, gd);
+ break;
+ }
break;
+ case Agi::GType_V1:
case Agi::GType_V2:
case Agi::GType_V3:
*engine = new Agi::AgiEngine(syst, gd);
@@ -258,12 +281,7 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl
char saveVersion = in->readByte();
if (saveVersion >= 4) {
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- if (!Graphics::loadThumbnail(*in, *thumbnail)) {
- delete thumbnail;
- thumbnail = 0;
- }
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
desc.setThumbnail(thumbnail);
@@ -482,7 +500,9 @@ int AgiEngine::agiDetectGame() {
assert(_gameDescription != NULL);
- if (getVersion() <= 0x2999) {
+ if (getVersion() <= 0x2001) {
+ _loader = new AgiLoader_v1(this);
+ } else if (getVersion() <= 0x2999) {
_loader = new AgiLoader_v2(this);
} else {
_loader = new AgiLoader_v3(this);
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index cd3edf50c6..28e94075a6 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -37,7 +37,7 @@ using Common::GUIO_NONE;
gid, \
interp, \
features, \
- ver, \
+ ver \
}
#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \
@@ -53,9 +53,10 @@ using Common::GUIO_NONE;
gid, \
interp, \
features, \
- ver, \
+ ver \
}
+#define BOOTER2(id,extra,fname,md5,size,ver,gid) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2)
#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2)
#define GAME3(id,extra,fname,md5,ver,gid) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3)
@@ -118,6 +119,69 @@ static const AGIGameDescription gameDescriptions[] = {
// AGI Demo for Kings Quest III and Space Quest I
GAME("agidemo", "Demo Kings Quest III and Space Quest I", "502e6bf96827b6c4d3e67c9cdccd1033", 0x2272, GID_AGIDEMO),
+ {
+ // Black Cauldron (PC 3.5" booter) 1.1J [AGI 1.12]
+ {
+ "bc",
+ "Booter 1.1J",
+ {
+ { "bc-d1.img", BooterDisk1, "1d29a82b41c9c7491e2b68d16864bd11", 368640},
+ { "bc-d2.img", BooterDisk2, "5568f7a52e787305656246f95e2aa375", 368640},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_BC,
+ GType_V1,
+ 0,
+ 0x1120
+ },
+
+ {
+ // Black Cauldron (PC 3.5" booter) 1.1K [AGI 1.12]
+ {
+ "bc",
+ "Booter 1.1K",
+ {
+ { "bc-d1.img", BooterDisk1, "98a51d3a372baa9df288b6c0f0232567", 368640},
+ { "bc-d2.img", BooterDisk2, "5568f7a52e787305656246f95e2aa375", 368640},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_BC,
+ GType_V1,
+ 0,
+ 0x1120
+ },
+
+ {
+ // Black Cauldron (PC 3.5" booter) 1.1M [AGI 1.12]
+ {
+ "bc",
+ "Booter 1.1M",
+ {
+ { "bc-d1.img", BooterDisk1, "edc0e5befbe5e44bb109cdf9137ee12d", 368640},
+ { "bc-d2.img", BooterDisk2, "5568f7a52e787305656246f95e2aa375", 368640},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO_NONE
+ },
+ GID_BC,
+ GType_V1,
+ 0,
+ 0x1120
+ },
+
// Black Cauldron (Amiga) 2.00 6/14/87
GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga),
@@ -143,9 +207,9 @@ static const AGIGameDescription gameDescriptions[] = {
// Black Cauldron (CoCo3 360k) [AGI 2.072]
GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3),
-// TODO
-// These aren't supposed to work now as they require unsupported agi engine 2.01
-#if 0
+ // Donald Duck's Playground (PC Booter) 1.0Q
+ BOOTER2("ddp", "Booter 1.0Q", "ddp.img", "f323f10abf8140ffb2668b09af2e7b87", 368640, 0x2001, GID_DDP),
+
// Donald Duck's Playground (Amiga) 1.0C
// Menus not tested
GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga),
@@ -157,7 +221,6 @@ static const AGIGameDescription gameDescriptions[] = {
// reported by Filippos (thebluegr) in bugreport #1654500
// Menus not tested
GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformPC),
-#endif
// Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316
GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga),
@@ -196,7 +259,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_GOLDRUSH,
GType_V3,
GF_MACGOLDRUSH,
- 0x3149,
+ 0x3149
},
@@ -514,7 +577,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_SQ2,
GType_V2,
0,
- 0x2936,
+ 0x2936
},
@@ -659,7 +722,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_FANMADE,
GType_V2,
GF_AGDS,
- 0x2440,
+ 0x2440
},
{
@@ -676,7 +739,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_GETOUTTASQ,
GType_V2,
0,
- 0x2440,
+ 0x2440
},
FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE),
@@ -831,7 +894,7 @@ static const AGIGameDescription gameDescriptions[] = {
GID_FANMADE,
GType_V3,
GF_FANMADE,
- 0x3149,
+ 0x3149
},
FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3),
@@ -859,7 +922,7 @@ static AGIGameDescription g_fallbackDesc = {
GID_FANMADE,
GType_V2,
GF_FANMADE,
- 0x2917,
+ 0x2917
};
} // End of namespace Agi
diff --git a/engines/agi/id.cpp b/engines/agi/id.cpp
index 00f8407529..dd370d4189 100644
--- a/engines/agi/id.cpp
+++ b/engines/agi/id.cpp
@@ -48,14 +48,17 @@ int AgiEngine::setupV2Game(int ver) {
// 'quit' takes 0 args for 2.089
if (ver == 0x2089)
- logicNamesCmd[0x86].numArgs = 0;
+// logicNamesCmd[0x86].numArgs = 0;
+ logicNamesCmd[0x86].args = "";
// 'print.at' and 'print.at.v' take 3 args before 2.272
// This is documented in the specs as only < 2.440, but it seems
// that KQ3 (2.272) needs a 'print.at' taking 4 args.
if (ver < 0x2272) {
- logicNamesCmd[0x97].numArgs = 3;
- logicNamesCmd[0x98].numArgs = 3;
+// logicNamesCmd[0x97].numArgs = 3;
+// logicNamesCmd[0x98].numArgs = 3;
+ logicNamesCmd[0x97].args = "vvv";
+ logicNamesCmd[0x98].args = "vvv";
}
return ec;
@@ -73,8 +76,10 @@ int AgiEngine::setupV3Game(int ver) {
// 'unknown173' also takes 1 arg for 3.002.068, not 0 args.
// Is this actually used anywhere? -- dsymonds
if (ver == 0x3086) {
- logicNamesCmd[0xb0].numArgs = 1;
- logicNamesCmd[0xad].numArgs = 1;
+// logicNamesCmd[0xb0].numArgs = 1;
+// logicNamesCmd[0xad].numArgs = 1;
+ logicNamesCmd[0xb0].args = "n";
+ logicNamesCmd[0xad].args = "n";
}
// FIXME: Apply this fix to other games also that use 2 arguments for command 182.
@@ -83,7 +88,8 @@ int AgiEngine::setupV3Game(int ver) {
// has been set to use AGI 3.149 in ScummVM so that's why this initialization is
// here and not in setupV2Game.
if (getGameID() == GID_GOLDRUSH && getPlatform() == Common::kPlatformAmiga)
- logicNamesCmd[182].numArgs = 2;
+// logicNamesCmd[182].numArgs = 2;
+ logicNamesCmd[182].args = "vv";
return ec;
}
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index f5810a6e8c..d899a6e202 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -180,7 +180,7 @@ int AgiEngine::handleController(int key) {
if (!(getFeatures() & GF_AGIMOUSE)) {
// Handle mouse button events
if (key == BUTTON_LEFT) {
- v->flags |= ADJ_EGO_XY;
+ v->flags |= fAdjEgoXY;
v->parm1 = WIN_TO_PIC_X(_mouse.x);
v->parm2 = WIN_TO_PIC_Y(_mouse.y);
return true;
@@ -188,7 +188,7 @@ int AgiEngine::handleController(int key) {
}
if (d || key == KEY_STATIONARY) {
- v->flags &= ~ADJ_EGO_XY;
+ v->flags &= ~fAdjEgoXY;
v->direction = v->direction == d ? 0 : d;
return true;
}
diff --git a/engines/agi/loader_v1.cpp b/engines/agi/loader_v1.cpp
new file mode 100644
index 0000000000..c6a3e66705
--- /dev/null
+++ b/engines/agi/loader_v1.cpp
@@ -0,0 +1,329 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "agi/agi.h"
+#include "common/md5.h"
+
+#define IMAGE_SIZE 368640 // = 40 * 2 * 9 * 512 = tracks * sides * sectors * sector size
+#define SECTOR_OFFSET(s) ((s) * 512)
+
+#define DDP_BASE_SECTOR 0x1C2
+#define DDP_LOGDIR_SEC SECTOR_OFFSET(171) + 5
+#define DDP_LOGDIR_MAX 43
+#define DDP_PICDIR_SEC SECTOR_OFFSET(180) + 5
+#define DDP_PICDIR_MAX 30
+#define DDP_VIEWDIR_SEC SECTOR_OFFSET(189) + 5
+#define DDP_VIEWDIR_MAX 171
+#define DDP_SNDDIR_SEC SECTOR_OFFSET(198) + 5
+#define DDP_SNDDIR_MAX 64
+
+#define BC_LOGDIR_SEC SECTOR_OFFSET(90) + 5
+#define BC_LOGDIR_MAX 118
+#define BC_VIEWDIR_SEC SECTOR_OFFSET(96) + 5
+#define BC_VIEWDIR_MAX 180
+#define BC_PICDIR_SEC SECTOR_OFFSET(93) + 8
+#define BC_PICDIR_MAX 117
+#define BC_SNDDIR_SEC SECTOR_OFFSET(99) + 5
+#define BC_SNDDIR_MAX 29
+#define BC_WORDS SECTOR_OFFSET(0x26D) + 5
+#define BC_OBJECTS SECTOR_OFFSET(0x1E6) + 3
+
+namespace Agi {
+
+
+AgiLoader_v1::AgiLoader_v1(AgiEngine *vm) {
+ _vm = vm;
+}
+
+int AgiLoader_v1::detectGame() {
+ // Find filenames for the disk images
+ _filenameDisk0 = _vm->getDiskName(BooterDisk1);
+ _filenameDisk1 = _vm->getDiskName(BooterDisk2);
+
+ return _vm->setupV2Game(_vm->getVersion());
+}
+
+int AgiLoader_v1::loadDir_DDP(AgiDir *agid, int offset, int max) {
+ Common::File fp;
+
+ if (!fp.open(_filenameDisk0))
+ return errBadFileOpen;
+
+ // Cleanup
+ for (int i = 0; i < MAX_DIRS; i++) {
+ agid[i].volume = 0xFF;
+ agid[i].offset = _EMPTY;
+ }
+
+ fp.seek(offset, SEEK_SET);
+ for (int i = 0; i <= max; i++) {
+ int b0 = fp.readByte();
+ int b1 = fp.readByte();
+ int b2 = fp.readByte();
+
+ if (b0 == 0xFF && b1 == 0xFF && b2 == 0xFF) {
+ agid[i].volume = 0xFF;
+ agid[i].offset = _EMPTY;
+ } else {
+ int sec = (DDP_BASE_SECTOR + (((b0 & 0xF) << 8) | b1)) >> 1;
+ int off = ((b1 & 0x1) << 8) | b2;
+ agid[i].volume = 0;
+ agid[i].offset = SECTOR_OFFSET(sec) + off;
+ }
+ }
+
+ fp.close();
+
+ return errOK;
+}
+
+int AgiLoader_v1::loadDir_BC(AgiDir *agid, int offset, int max) {
+ Common::File fp;
+
+ if (!fp.open(_filenameDisk0))
+ return errBadFileOpen;
+
+ // Cleanup
+ for (int i = 0; i < MAX_DIRS; i++) {
+ agid[i].volume = 0xFF;
+ agid[i].offset = _EMPTY;
+ }
+
+ fp.seek(offset, SEEK_SET);
+ for (int i = 0; i <= max; i++) {
+ int b0 = fp.readByte();
+ int b1 = fp.readByte();
+ int b2 = fp.readByte();
+
+ if (b0 == 0xFF && b1 == 0xFF && b2 == 0xFF) {
+ agid[i].volume = 0xFF;
+ agid[i].offset = _EMPTY;
+ } else {
+ int sec = (b0 & 0x3F) * 18 + ((b1 >> 1) & 0x1) * 9 + ((b1 >> 2) & 0x1F) - 1;
+ int off = ((b1 & 0x1) << 8) | b2;
+ int vol = (b0 & 0xC0) >> 6;
+ agid[i].volume = 0;
+ agid[i].offset = (vol == 2) * IMAGE_SIZE + SECTOR_OFFSET(sec) + off;
+ }
+ }
+
+ fp.close();
+
+ return errOK;
+}
+
+int AgiLoader_v1::init() {
+ int ec = errOK;
+
+ switch (_vm->getGameID()) {
+ case GID_DDP:
+ ec = loadDir_DDP(_vm->_game.dirLogic, DDP_LOGDIR_SEC, DDP_LOGDIR_MAX);
+ if (ec == errOK)
+ ec = loadDir_DDP(_vm->_game.dirPic, DDP_PICDIR_SEC, DDP_PICDIR_MAX);
+ if (ec == errOK)
+ ec = loadDir_DDP(_vm->_game.dirView, DDP_VIEWDIR_SEC, DDP_VIEWDIR_MAX);
+ if (ec == errOK)
+ ec = loadDir_DDP(_vm->_game.dirSound, DDP_SNDDIR_SEC, DDP_SNDDIR_MAX);
+ break;
+
+ case GID_BC:
+ ec = loadDir_BC(_vm->_game.dirLogic, BC_LOGDIR_SEC, BC_LOGDIR_MAX);
+ if (ec == errOK)
+ ec = loadDir_BC(_vm->_game.dirPic, BC_PICDIR_SEC, BC_PICDIR_MAX);
+ if (ec == errOK)
+ ec = loadDir_BC(_vm->_game.dirView, BC_VIEWDIR_SEC, BC_VIEWDIR_MAX);
+ if (ec == errOK)
+ ec = loadDir_BC(_vm->_game.dirSound, BC_SNDDIR_SEC, BC_SNDDIR_MAX);
+ break;
+ }
+
+ return ec;
+}
+
+int AgiLoader_v1::deinit() {
+ int ec = errOK;
+ return ec;
+}
+
+uint8 *AgiLoader_v1::loadVolRes(struct AgiDir *agid) {
+ uint8 *data = NULL;
+ Common::File fp;
+ int offset = agid->offset;
+
+ if (offset == _EMPTY)
+ return NULL;
+
+ if (offset > IMAGE_SIZE) {
+ fp.open(_filenameDisk1);
+ offset -= IMAGE_SIZE;
+ } else {
+ fp.open(_filenameDisk0);
+ }
+
+ fp.seek(offset, SEEK_SET);
+
+ int signature = fp.readUint16BE();
+ if (signature != 0x1234) {
+ warning("AgiLoader_v1::loadVolRes: bad signature %04x", signature);
+ return NULL;
+ }
+
+ fp.readByte();
+ agid->len = fp.readUint16LE();
+ data = (uint8 *)calloc(1, agid->len + 32);
+ fp.read(data, agid->len);
+
+ fp.close();
+
+ return data;
+}
+
+int AgiLoader_v1::loadResource(int t, int n) {
+ int ec = errOK;
+ uint8 *data = NULL;
+
+ debugC(3, kDebugLevelResources, "(t = %d, n = %d)", t, n);
+ if (n > MAX_DIRS)
+ return errBadResource;
+
+ switch (t) {
+ case rLOGIC:
+ if (~_vm->_game.dirLogic[n].flags & RES_LOADED) {
+ debugC(3, kDebugLevelResources, "loading logic resource %d", n);
+ unloadResource(rLOGIC, n);
+
+ // load raw resource into data
+ data = loadVolRes(&_vm->_game.dirLogic[n]);
+
+ _vm->_game.logics[n].data = data;
+ ec = data ? _vm->decodeLogic(n) : errBadResource;
+
+ _vm->_game.logics[n].sIP = 2;
+ }
+
+ // if logic was cached, we get here
+ // reset code pointers incase it was cached
+
+ _vm->_game.logics[n].cIP = _vm->_game.logics[n].sIP;
+ break;
+ case rPICTURE:
+ // if picture is currently NOT loaded *OR* cacheing is off,
+ // unload the resource (caching == off) and reload it
+
+ debugC(3, kDebugLevelResources, "loading picture resource %d", n);
+ if (_vm->_game.dirPic[n].flags & RES_LOADED)
+ break;
+
+ // if loaded but not cached, unload it
+ // if cached but not loaded, etc
+ unloadResource(rPICTURE, n);
+ data = loadVolRes(&_vm->_game.dirPic[n]);
+
+ if (data != NULL) {
+ _vm->_game.pictures[n].rdata = data;
+ _vm->_game.dirPic[n].flags |= RES_LOADED;
+ } else {
+ ec = errBadResource;
+ }
+ break;
+ case rSOUND:
+ debugC(3, kDebugLevelResources, "loading sound resource %d", n);
+ if (_vm->_game.dirSound[n].flags & RES_LOADED)
+ break;
+
+ data = loadVolRes(&_vm->_game.dirSound[n]);
+
+ if (data != NULL) {
+ // Freeing of the raw resource from memory is delegated to the createFromRawResource-function
+ _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu);
+ _vm->_game.dirSound[n].flags |= RES_LOADED;
+ } else {
+ ec = errBadResource;
+ }
+ break;
+ case rVIEW:
+ // Load a VIEW resource into memory...
+ // Since VIEWS alter the view table ALL the time
+ // can we cache the view? or must we reload it all
+ // the time?
+ if (_vm->_game.dirView[n].flags & RES_LOADED)
+ break;
+
+ debugC(3, kDebugLevelResources, "loading view resource %d", n);
+ unloadResource(rVIEW, n);
+ data = loadVolRes(&_vm->_game.dirView[n]);
+ if (data) {
+ _vm->_game.views[n].rdata = data;
+ _vm->_game.dirView[n].flags |= RES_LOADED;
+ ec = _vm->decodeView(n);
+ } else {
+ ec = errBadResource;
+ }
+ break;
+ default:
+ ec = errBadResource;
+ break;
+ }
+
+ return ec;
+}
+
+int AgiLoader_v1::unloadResource(int t, int n) {
+ switch (t) {
+ case rLOGIC:
+ _vm->unloadLogic(n);
+ break;
+ case rPICTURE:
+ _vm->_picture->unloadPicture(n);
+ break;
+ case rVIEW:
+ _vm->unloadView(n);
+ break;
+ case rSOUND:
+ _vm->_sound->unloadSound(n);
+ break;
+ }
+
+ return errOK;
+}
+
+int AgiLoader_v1::loadObjects(const char *fname) {
+ if (_vm->getGameID() == GID_BC) {
+ Common::File f;
+ f.open(_filenameDisk0);
+ f.seek(BC_OBJECTS, SEEK_SET);
+ return _vm->loadObjects(f);
+ }
+ return errOK;
+}
+
+int AgiLoader_v1::loadWords(const char *fname) {
+ if (_vm->getGameID() == GID_BC) {
+ Common::File f;
+ f.open(_filenameDisk0);
+ f.seek(BC_WORDS, SEEK_SET);
+ return _vm->loadWords_v1(f);
+ }
+ return errOK;
+}
+
+}
diff --git a/engines/agi/module.mk b/engines/agi/module.mk
index 2339d1019f..68d86f7b2e 100644
--- a/engines/agi/module.mk
+++ b/engines/agi/module.mk
@@ -11,6 +11,7 @@ MODULE_OBJS := \
id.o \
inv.o \
keyboard.o \
+ loader_v1.o \
loader_v2.o \
loader_v3.o \
logic.o \
@@ -18,12 +19,12 @@ MODULE_OBJS := \
menu.o \
motion.o \
objects.o \
+ opcodes.o \
op_cmd.o \
op_dbg.o \
op_test.o \
picture.o \
preagi.o \
- preagi_common.o \
preagi_mickey.o \
preagi_troll.o \
preagi_winnie.o \
diff --git a/engines/agi/motion.cpp b/engines/agi/motion.cpp
index 261a7f3e61..e4de232267 100644
--- a/engines/agi/motion.cpp
+++ b/engines/agi/motion.cpp
@@ -52,9 +52,9 @@ void AgiEngine::changePos(VtEntry *v) {
y += v->stepSize * dy[v->direction];
if (checkBlock(x, y) == b) {
- v->flags &= ~MOTION;
+ v->flags &= ~fMotion;
} else {
- v->flags |= MOTION;
+ v->flags |= fMotion;
v->direction = 0;
if (isEgoView(v))
_game.vars[vEgoDir] = 0;
@@ -63,7 +63,7 @@ void AgiEngine::changePos(VtEntry *v) {
void AgiEngine::motionWander(VtEntry *v) {
if (v->parm1--) {
- if (~v->flags & DIDNT_MOVE)
+ if (~v->flags & fDidntMove)
return;
}
@@ -94,14 +94,14 @@ void AgiEngine::motionFollowEgo(VtEntry *v) {
// Already at ego coordinates
if (dir == 0) {
v->direction = 0;
- v->motion = MOTION_NORMAL;
+ v->motion = kMotionNormal;
setflag(v->parm2, true);
return;
}
if (v->parm3 == 0xff) {
v->parm3 = 0;
- } else if (v->flags & DIDNT_MOVE) {
+ } else if (v->flags & fDidntMove) {
int d;
while ((v->direction = _rnd->getRandomNumber(8)) == 0) {
@@ -152,18 +152,20 @@ void AgiEngine::motionMoveObj(VtEntry *v) {
void AgiEngine::checkMotion(VtEntry *v) {
switch (v->motion) {
- case MOTION_WANDER:
+ case kMotionNormal:
+ break;
+ case kMotionWander:
motionWander(v);
break;
- case MOTION_FOLLOW_EGO:
+ case kMotionFollowEgo:
motionFollowEgo(v);
break;
- case MOTION_MOVE_OBJ:
+ case kMotionMoveObj:
motionMoveObj(v);
break;
}
- if ((_game.block.active && (~v->flags & IGNORE_BLOCKS)) && v->direction)
+ if ((_game.block.active && (~v->flags & fIgnoreBlocks)) && v->direction)
changePos(v);
}
@@ -178,7 +180,7 @@ void AgiEngine::checkAllMotions() {
VtEntry *v;
for (v = _game.viewTable; v < &_game.viewTable[MAX_VIEWTABLE]; v++) {
- if ((v->flags & (ANIMATED | UPDATE | DRAWN)) == (ANIMATED | UPDATE | DRAWN)
+ if ((v->flags & (fAnimated | fUpdate | fDrawn)) == (fAnimated | fUpdate | fDrawn)
&& v->stepTimeCount == 1) {
checkMotion(v);
}
@@ -192,11 +194,11 @@ void AgiEngine::checkAllMotions() {
* @param v Pointer to view table entry
*/
void AgiEngine::inDestination(VtEntry *v) {
- if (v->motion == MOTION_MOVE_OBJ) {
+ if (v->motion == kMotionMoveObj) {
v->stepSize = v->parm3;
setflag(v->parm4, true);
}
- v->motion = MOTION_NORMAL;
+ v->motion = kMotionNormal;
if (isEgoView(v))
_game.playerControl = true;
}
@@ -204,7 +206,7 @@ void AgiEngine::inDestination(VtEntry *v) {
/**
* Wrapper for static function motion_moveobj().
* This function is used by cmd_move_object() in the first motion cycle
- * after setting the motion mode to MOTION_MOVE_OBJ.
+ * after setting the motion mode to kMotionMoveObj.
* @param v Pointer to view table entry
*/
void AgiEngine::moveObj(VtEntry *v) {
diff --git a/engines/agi/objects.cpp b/engines/agi/objects.cpp
index e04c9742f3..efc8645287 100644
--- a/engines/agi/objects.cpp
+++ b/engines/agi/objects.cpp
@@ -34,7 +34,7 @@ int AgiEngine::allocObjects(int n) {
}
int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) {
- unsigned int i, so, padsize;
+ unsigned int i, so, padsize, spos;
padsize = _game.gameFlags & ID_AMIGA ? 4 : 3;
@@ -64,11 +64,12 @@ int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) {
return errNotEnoughMemory;
// build the object list
- for (i = 0, so = padsize; i < _game.numObjects; i++, so += padsize) {
+ spos = getVersion() >= 0x2000 ? padsize : 0;
+ for (i = 0, so = spos; i < _game.numObjects; i++, so += padsize) {
int offset;
(_objects + i)->location = *(mem + so + 2);
- offset = READ_LE_UINT16(mem + so) + padsize;
+ offset = READ_LE_UINT16(mem + so) + spos;
if ((uint) offset < flen) {
(_objects + i)->name = (char *)strdup((const char *)mem + offset);
@@ -84,20 +85,33 @@ int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) {
int AgiEngine::loadObjects(const char *fname) {
Common::File fp;
- uint32 flen;
- uint8 *mem;
-
- _objects = NULL;
- _game.numObjects = 0;
debugC(5, kDebugLevelResources, "(Loading objects '%s')", fname);
if (!fp.open(fname))
return errBadFileOpen;
- fp.seek(0, SEEK_END);
- flen = fp.pos();
- fp.seek(0, SEEK_SET);
+ return readObjects(fp, fp.size());
+}
+
+/**
+ * Loads an object file that is in the common VOL resource format. Expects
+ * the file pointer to point to the last field in header, ie. file length.
+ * This is used at least by the V1 booter games.
+ */
+int AgiEngine::loadObjects(Common::File &fp) {
+ int flen = fp.readUint16LE();
+ return readObjects(fp, flen);
+}
+
+/**
+ * Read and decode objects, and store them in the internal structure.
+ *
+ * @param fp File pointer
+ * @param flen File length
+ */
+int AgiEngine::readObjects(Common::File &fp, int flen) {
+ uint8 *mem;
if ((mem = (uint8 *)calloc(1, flen + 32)) == NULL) {
fp.close();
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index bde62fe2d9..17addc0c05 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -41,23 +41,36 @@ namespace Agi {
#define p5 (p[5])
#define p6 (p[6])
-#define ip _curLogic->cIP
-#define vt _game.viewTable[p0]
-#define vt_v _game.viewTable[_game.vars[p0]]
-
-#define _v _game.vars
-
-void AgiEngine::cmd_increment(uint8 *p) {
- if (_v[p0] != 0xff)
- ++_v[p0];
+#define code state->_curLogic->data
+#define ip state->_curLogic->cIP
+#define vt state->viewTable[p0]
+#define vt_v state->viewTable[state->vars[p0]]
+
+#define _v state->vars
+
+#define getGameID() state->_vm->getGameID()
+#define getFeatures() state->_vm->getFeatures()
+#define getVersion() state->_vm->getVersion()
+#define getLanguage() state->_vm->getLanguage()
+#define setflag(a,b) state->_vm->setflag(a,b)
+#define getflag(a) state->_vm->getflag(a)
+
+void cmdIncrement(AgiGame *state, uint8 *p) {
+ if (getVersion() < 0x2000) {
+ if (_v[p0] < 0xf0)
+ ++_v[p0];
+ } else {
+ if (_v[p0] != 0xff)
+ ++_v[p0];
+ }
}
-void AgiEngine::cmd_decrement(uint8 *p) {
+void cmdDecrement(AgiGame *state, uint8 *p) {
if (_v[p0] != 0)
--_v[p0];
}
-void AgiEngine::cmd_assignn(uint8 *p) {
+void cmdAssignN(AgiGame *state, uint8 *p) {
_v[p0] = p1;
// WORKAROUND for a bug in fan _game "Get outta SQ"
@@ -71,84 +84,100 @@ void AgiEngine::cmd_assignn(uint8 *p) {
_v[p0] = 8;
}
-void AgiEngine::cmd_addn(uint8 *p) {
+void cmdAddN(AgiGame *state, uint8 *p) {
_v[p0] += p1;
}
-void AgiEngine::cmd_subn(uint8 *p) {
+void cmdSubN(AgiGame *state, uint8 *p) {
_v[p0] -= p1;
}
-void AgiEngine::cmd_assignv(uint8 *p) {
+void cmdAssignV(AgiGame *state, uint8 *p) {
_v[p0] = _v[p1];
}
-void AgiEngine::cmd_addv(uint8 *p) {
+void cmdAddV(AgiGame *state, uint8 *p) {
_v[p0] += _v[p1];
}
-void AgiEngine::cmd_subv(uint8 *p) {
+void cmdSubV(AgiGame *state, uint8 *p) {
_v[p0] -= _v[p1];
}
-void AgiEngine::cmd_mul_n(uint8 *p) {
+void cmdMulN(AgiGame *state, uint8 *p) {
_v[p0] *= p1;
}
-void AgiEngine::cmd_mul_v(uint8 *p) {
+void cmdMulV(AgiGame *state, uint8 *p) {
_v[p0] *= _v[p1];
}
-void AgiEngine::cmd_div_n(uint8 *p) {
+void cmdDivN(AgiGame *state, uint8 *p) {
_v[p0] /= p1;
}
-void AgiEngine::cmd_div_v(uint8 *p) {
+void cmdDivV(AgiGame *state, uint8 *p) {
_v[p0] /= _v[p1];
}
-void AgiEngine::cmd_random(uint8 *p) {
- _v[p2] = _rnd->getRandomNumber(p1 - p0) + p0;
+void cmdRandomV1(AgiGame *state, uint8 *p) {
+ _v[p0] = state->_vm->_rnd->getRandomNumber(250);
+}
+
+void cmdRandom(AgiGame *state, uint8 *p) {
+ _v[p2] = state->_vm->_rnd->getRandomNumber(p1 - p0) + p0;
}
-void AgiEngine::cmd_lindirectn(uint8 *p) {
+void cmdLindirectN(AgiGame *state, uint8 *p) {
_v[_v[p0]] = p1;
}
-void AgiEngine::cmd_lindirectv(uint8 *p) {
+void cmdLindirectV(AgiGame *state, uint8 *p) {
_v[_v[p0]] = _v[p1];
}
-void AgiEngine::cmd_rindirect(uint8 *p) {
+void cmdRindirect(AgiGame *state, uint8 *p) {
_v[p0] = _v[_v[p1]];
}
-void AgiEngine::cmd_set(uint8 *p) {
+void cmdSet(AgiGame *state, uint8 *p) {
setflag(*p, true);
}
-void AgiEngine::cmd_reset(uint8 *p) {
+void cmdReset(AgiGame *state, uint8 *p) {
setflag(*p, false);
}
-void AgiEngine::cmd_toggle(uint8 *p) {
+void cmdToggle(AgiGame *state, uint8 *p) {
setflag(*p, !getflag(*p));
}
-void AgiEngine::cmd_set_v(uint8 *p) {
- setflag(_v[p0], true);
+void cmdSetV(AgiGame *state, uint8 *p) {
+ if (getVersion() < 0x2000) {
+ _v[p0] = 1;
+ } else {
+ setflag(_v[p0], true);
+ }
}
-void AgiEngine::cmd_reset_v(uint8 *p) {
- setflag(_v[p0], false);
+void cmdResetV(AgiGame *state, uint8 *p) {
+ if (getVersion() < 0x2000) {
+ _v[p0] = 0;
+ } else {
+ setflag(_v[p0], false);
+ }
}
-void AgiEngine::cmd_toggle_v(uint8 *p) {
- setflag(_v[p0], !getflag(_v[p0]));
+void cmdToggleV(AgiGame *state, uint8 *p) {
+ if (getVersion() < 0x2000) {
+ _v[p0] ^= 1;
+ } else {
+ setflag(_v[p0], !getflag(_v[p0]));
+ }
}
-void AgiEngine::cmd_new_room(uint8 *p) {
- newRoom(p0);
+void cmdNewRoom(AgiGame *state, uint8 *p) {
+ state->_vm->newRoom(p0);
// WORKAROUND: Works around intro skipping bug (#1737343) in Gold Rush.
// Intro was skipped because the enter-keypress finalizing the entering
@@ -160,83 +189,83 @@ void AgiEngine::cmd_new_room(uint8 *p) {
// loaded so that no keys from the copy protection scene can be left
// over to cause the intro to skip to the _game's start.
if (getGameID() == GID_GOLDRUSH && p0 == 73)
- _game.keypress = 0;
+ state->keypress = 0;
}
-void AgiEngine::cmd_new_room_f(uint8 *p) {
- newRoom(_v[p0]);
+void cmdNewRoomF(AgiGame *state, uint8 *p) {
+ state->_vm->newRoom(_v[p0]);
}
-void AgiEngine::cmd_load_view(uint8 *p) {
- agiLoadResource(rVIEW, p0);
+void cmdLoadView(AgiGame *state, uint8 *p) {
+ state->_vm->agiLoadResource(rVIEW, p0);
}
-void AgiEngine::cmd_load_logic(uint8 *p) {
- agiLoadResource(rLOGIC, p0);
+void cmdLoadLogic(AgiGame *state, uint8 *p) {
+ state->_vm->agiLoadResource(rLOGIC, p0);
}
-void AgiEngine::cmd_load_sound(uint8 *p) {
- agiLoadResource(rSOUND, p0);
+void cmdLoadSound(AgiGame *state, uint8 *p) {
+ state->_vm->agiLoadResource(rSOUND, p0);
}
-void AgiEngine::cmd_load_view_f(uint8 *p) {
- agiLoadResource(rVIEW, _v[p0]);
+void cmdLoadViewF(AgiGame *state, uint8 *p) {
+ state->_vm->agiLoadResource(rVIEW, _v[p0]);
}
-void AgiEngine::cmd_load_logic_f(uint8 *p) {
- agiLoadResource(rLOGIC, _v[p0]);
+void cmdLoadLogicF(AgiGame *state, uint8 *p) {
+ state->_vm->agiLoadResource(rLOGIC, _v[p0]);
}
-void AgiEngine::cmd_discard_view(uint8 *p) {
- agiUnloadResource(rVIEW, p0);
+void cmdDiscardView(AgiGame *state, uint8 *p) {
+ state->_vm->agiUnloadResource(rVIEW, p0);
}
-void AgiEngine::cmd_object_on_anything(uint8 *p) {
- vt.flags &= ~(ON_WATER | ON_LAND);
+void cmdObjectOnAnything(AgiGame *state, uint8 *p) {
+ vt.flags &= ~(fOnWater | fOnLand);
}
-void AgiEngine::cmd_object_on_land(uint8 *p) {
- vt.flags |= ON_LAND;
+void cmdObjectOnLand(AgiGame *state, uint8 *p) {
+ vt.flags |= fOnLand;
}
-void AgiEngine::cmd_object_on_water(uint8 *p) {
- vt.flags |= ON_WATER;
+void cmdObjectOnWater(AgiGame *state, uint8 *p) {
+ vt.flags |= fOnWater;
}
-void AgiEngine::cmd_observe_horizon(uint8 *p) {
- vt.flags &= ~IGNORE_HORIZON;
+void cmdObserveHorizon(AgiGame *state, uint8 *p) {
+ vt.flags &= ~fIgnoreHorizon;
}
-void AgiEngine::cmd_ignore_horizon(uint8 *p) {
- vt.flags |= IGNORE_HORIZON;
+void cmdIgnoreHorizon(AgiGame *state, uint8 *p) {
+ vt.flags |= fIgnoreHorizon;
}
-void AgiEngine::cmd_observe_objs(uint8 *p) {
- vt.flags &= ~IGNORE_OBJECTS;
+void cmdObserveObjs(AgiGame *state, uint8 *p) {
+ vt.flags &= ~fIgnoreObjects;
}
-void AgiEngine::cmd_ignore_objs(uint8 *p) {
- vt.flags |= IGNORE_OBJECTS;
+void cmdIgnoreObjs(AgiGame *state, uint8 *p) {
+ vt.flags |= fIgnoreObjects;
}
-void AgiEngine::cmd_observe_blocks(uint8 *p) {
- vt.flags &= ~IGNORE_BLOCKS;
+void cmdObserveBlocks(AgiGame *state, uint8 *p) {
+ vt.flags &= ~fIgnoreBlocks;
}
-void AgiEngine::cmd_ignore_blocks(uint8 *p) {
- vt.flags |= IGNORE_BLOCKS;
+void cmdIgnoreBlocks(AgiGame *state, uint8 *p) {
+ vt.flags |= fIgnoreBlocks;
}
-void AgiEngine::cmd_set_horizon(uint8 *p) {
- _game.horizon = p0;
+void cmdSetHorizon(AgiGame *state, uint8 *p) {
+ state->horizon = p0;
}
-void AgiEngine::cmd_get_priority(uint8 *p) {
+void cmdGetPriority(AgiGame *state, uint8 *p) {
_v[p1] = vt.priority;
}
-void AgiEngine::cmd_set_priority(uint8 *p) {
- vt.flags |= FIXED_PRIORITY;
+void cmdSetPriority(AgiGame *state, uint8 *p) {
+ vt.flags |= fFixedPriority;
vt.priority = p1;
// WORKAROUND: this fixes bug #1712585 in KQ4 (dwarf sprite priority)
@@ -253,250 +282,257 @@ void AgiEngine::cmd_set_priority(uint8 *p) {
// Therefore, this workaround only affects that specific part of this scene
// Ego is set to object 19 by script 54
if (getGameID() == GID_KQ4 && vt.currentView == 152) {
- _game.viewTable[19].flags |= FIXED_PRIORITY;
- _game.viewTable[19].priority = 7;
+ state->viewTable[19].flags |= fFixedPriority;
+ state->viewTable[19].priority = 7;
}
}
-void AgiEngine::cmd_set_priority_f(uint8 *p) {
- vt.flags |= FIXED_PRIORITY;
+void cmdSetPriorityF(AgiGame *state, uint8 *p) {
+ vt.flags |= fFixedPriority;
vt.priority = _v[p1];
}
-void AgiEngine::cmd_release_priority(uint8 *p) {
- vt.flags &= ~FIXED_PRIORITY;
+void cmdReleasePriority(AgiGame *state, uint8 *p) {
+ vt.flags &= ~fFixedPriority;
}
-void AgiEngine::cmd_set_upper_left(uint8 *p) { // do nothing (AGI 2.917)
+void cmdSetUpperLeft(AgiGame *state, uint8 *p) { // do nothing (AGI 2.917)
}
-void AgiEngine::cmd_start_update(uint8 *p) {
- startUpdate(&vt);
+void cmdStartUpdate(AgiGame *state, uint8 *p) {
+ state->_vm->startUpdate(&vt);
}
-void AgiEngine::cmd_stop_update(uint8 *p) {
- stopUpdate(&vt);
+void cmdStopUpdate(AgiGame *state, uint8 *p) {
+ state->_vm->stopUpdate(&vt);
}
-void AgiEngine::cmd_current_view(uint8 *p) {
+void cmdCurrentView(AgiGame *state, uint8 *p) {
_v[p1] = vt.currentView;
}
-void AgiEngine::cmd_current_cel(uint8 *p) {
+void cmdCurrentCel(AgiGame *state, uint8 *p) {
_v[p1] = vt.currentCel;
debugC(4, kDebugLevelScripts, "v%d=%d", p1, _v[p1]);
}
-void AgiEngine::cmd_current_loop(uint8 *p) {
+void cmdCurrentLoop(AgiGame *state, uint8 *p) {
_v[p1] = vt.currentLoop;
}
-void AgiEngine::cmd_last_cel(uint8 *p) {
+void cmdLastCel(AgiGame *state, uint8 *p) {
_v[p1] = vt.loopData->numCels - 1;
}
-void AgiEngine::cmd_set_cel(uint8 *p) {
- setCel(&vt, p1);
- vt.flags &= ~DONTUPDATE;
+void cmdSetCel(AgiGame *state, uint8 *p) {
+ state->_vm->setCel(&vt, p1);
+
+ if (getVersion() >= 0x2000) {
+ vt.flags &= ~fDontupdate;
+ }
}
-void AgiEngine::cmd_set_cel_f(uint8 *p) {
- setCel(&vt, _v[p1]);
- vt.flags &= ~DONTUPDATE;
+void cmdSetCelF(AgiGame *state, uint8 *p) {
+ state->_vm->setCel(&vt, _v[p1]);
+ vt.flags &= ~fDontupdate;
}
-void AgiEngine::cmd_set_view(uint8 *p) {
- setView(&vt, p1);
+void cmdSetView(AgiGame *state, uint8 *p) {
+ state->_vm->setView(&vt, p1);
}
-void AgiEngine::cmd_set_view_f(uint8 *p) {
- setView(&vt, _v[p1]);
+void cmdSetViewF(AgiGame *state, uint8 *p) {
+ state->_vm->setView(&vt, _v[p1]);
}
-void AgiEngine::cmd_set_loop(uint8 *p) {
- setLoop(&vt, p1);
+void cmdSetLoop(AgiGame *state, uint8 *p) {
+ state->_vm->setLoop(&vt, p1);
}
-void AgiEngine::cmd_set_loop_f(uint8 *p) {
- setLoop(&vt, _v[p1]);
+void cmdSetLoopF(AgiGame *state, uint8 *p) {
+ state->_vm->setLoop(&vt, _v[p1]);
}
-void AgiEngine::cmd_number_of_loops(uint8 *p) {
+void cmdNumberOfLoops(AgiGame *state, uint8 *p) {
_v[p1] = vt.numLoops;
}
-void AgiEngine::cmd_fix_loop(uint8 *p) {
- vt.flags |= FIX_LOOP;
+void cmdFixLoop(AgiGame *state, uint8 *p) {
+ vt.flags |= fFixLoop;
}
-void AgiEngine::cmd_release_loop(uint8 *p) {
- vt.flags &= ~FIX_LOOP;
+void cmdReleaseLoop(AgiGame *state, uint8 *p) {
+ vt.flags &= ~fFixLoop;
}
-void AgiEngine::cmd_step_size(uint8 *p) {
+void cmdStepSize(AgiGame *state, uint8 *p) {
vt.stepSize = _v[p1];
}
-void AgiEngine::cmd_step_time(uint8 *p) {
+void cmdStepTime(AgiGame *state, uint8 *p) {
vt.stepTime = vt.stepTimeCount = _v[p1];
}
-void AgiEngine::cmd_cycle_time(uint8 *p) {
+void cmdCycleTime(AgiGame *state, uint8 *p) {
vt.cycleTime = vt.cycleTimeCount = _v[p1];
}
-void AgiEngine::cmd_stop_cycling(uint8 *p) {
- vt.flags &= ~CYCLING;
+void cmdStopCycling(AgiGame *state, uint8 *p) {
+ vt.flags &= ~fCycling;
}
-void AgiEngine::cmd_start_cycling(uint8 *p) {
- vt.flags |= CYCLING;
+void cmdStartCycling(AgiGame *state, uint8 *p) {
+ vt.flags |= fCycling;
}
-void AgiEngine::cmd_normal_cycle(uint8 *p) {
- vt.cycle = CYCLE_NORMAL;
- vt.flags |= CYCLING;
+void cmdNormalCycle(AgiGame *state, uint8 *p) {
+ vt.cycle = kCycleNormal;
+ vt.flags |= fCycling;
}
-void AgiEngine::cmd_reverse_cycle(uint8 *p) {
- vt.cycle = CYCLE_REVERSE;
- vt.flags |= CYCLING;
+void cmdReverseCycle(AgiGame *state, uint8 *p) {
+ vt.cycle = kCycleReverse;
+ vt.flags |= fCycling;
}
-void AgiEngine::cmd_set_dir(uint8 *p) {
+void cmdSetDir(AgiGame *state, uint8 *p) {
vt.direction = _v[p1];
}
-void AgiEngine::cmd_get_dir(uint8 *p) {
+void cmdGetDir(AgiGame *state, uint8 *p) {
_v[p1] = vt.direction;
}
-void AgiEngine::cmd_get_room_f(uint8 *p) {
- _v[p1] = objectGetLocation(_v[p0]);
+void cmdGetRoomF(AgiGame *state, uint8 *p) {
+ _v[p1] = state->_vm->objectGetLocation(_v[p0]);
+}
+
+void cmdPut(AgiGame *state, uint8 *p) {
+ state->_vm->objectSetLocation(p0, _v[p1]);
}
-void AgiEngine::cmd_put(uint8 *p) {
- objectSetLocation(p0, _v[p1]);
+void cmdPutF(AgiGame *state, uint8 *p) {
+ state->_vm->objectSetLocation(_v[p0], _v[p1]);
}
-void AgiEngine::cmd_put_f(uint8 *p) {
- objectSetLocation(_v[p0], _v[p1]);
+void cmdDrop(AgiGame *state, uint8 *p) {
+ state->_vm->objectSetLocation(p0, 0);
}
-void AgiEngine::cmd_drop(uint8 *p) {
- objectSetLocation(p0, 0);
+void cmdGet(AgiGame *state, uint8 *p) {
+ state->_vm->objectSetLocation(p0, EGO_OWNED);
}
-void AgiEngine::cmd_get(uint8 *p) {
- objectSetLocation(p0, EGO_OWNED);
+void cmdGetV1(AgiGame *state, uint8 *p) {
+ state->_vm->objectSetLocation(p0, EGO_OWNED_V1);
}
-void AgiEngine::cmd_get_f(uint8 *p) {
- objectSetLocation(_v[p0], EGO_OWNED);
+void cmdGetF(AgiGame *state, uint8 *p) {
+ state->_vm->objectSetLocation(_v[p0], EGO_OWNED);
}
-void AgiEngine::cmd_word_to_string(uint8 *p) {
- strcpy(_game.strings[p0], _game.egoWords[p1].word);
+void cmdWordToString(AgiGame *state, uint8 *p) {
+ strcpy(state->strings[p0], state->egoWords[p1].word);
}
-void AgiEngine::cmd_open_dialogue(uint8 *p) {
- _game.hasWindow = true;
+void cmdOpenDialogue(AgiGame *state, uint8 *p) {
+ state->hasWindow = true;
}
-void AgiEngine::cmd_close_dialogue(uint8 *p) {
- _game.hasWindow = false;
+void cmdCloseDialogue(AgiGame *state, uint8 *p) {
+ state->hasWindow = false;
}
-void AgiEngine::cmd_close_window(uint8 *p) {
- closeWindow();
+void cmdCloseWindow(AgiGame *state, uint8 *p) {
+ state->_vm->closeWindow();
}
-void AgiEngine::cmd_status_line_on(uint8 *p) {
- _game.statusLine = true;
- writeStatus();
+void cmdStatusLineOn(AgiGame *state, uint8 *p) {
+ state->statusLine = true;
+ state->_vm->writeStatus();
}
-void AgiEngine::cmd_status_line_off(uint8 *p) {
- _game.statusLine = false;
- writeStatus();
+void cmdStatusLineOff(AgiGame *state, uint8 *p) {
+ state->statusLine = false;
+ state->_vm->writeStatus();
}
-void AgiEngine::cmd_show_obj(uint8 *p) {
- _sprites->showObj(p0);
+void cmdShowObj(AgiGame *state, uint8 *p) {
+ state->_vm->_sprites->showObj(p0);
}
-void AgiEngine::cmd_show_obj_v(uint8 *p) {
- _sprites->showObj(_v[p0]);
+void cmdShowObjV(AgiGame *state, uint8 *p) {
+ state->_vm->_sprites->showObj(_v[p0]);
}
-void AgiEngine::cmd_sound(uint8 *p) {
- _sound->startSound(p0, p1);
+void cmdSound(AgiGame *state, uint8 *p) {
+ state->_vm->_sound->startSound(p0, p1);
}
-void AgiEngine::cmd_stop_sound(uint8 *p) {
- _sound->stopSound();
+void cmdStopSound(AgiGame *state, uint8 *p) {
+ state->_vm->_sound->stopSound();
}
-void AgiEngine::cmd_menu_input(uint8 *p) {
- newInputMode(INPUT_MENU);
+void cmdMenuInput(AgiGame *state, uint8 *p) {
+ state->_vm->newInputMode(INPUT_MENU);
}
-void AgiEngine::cmd_enable_item(uint8 *p) {
- _menu->setItem(p0, true);
+void cmdEnableItem(AgiGame *state, uint8 *p) {
+ state->_vm->_menu->setItem(p0, true);
}
-void AgiEngine::cmd_disable_item(uint8 *p) {
- _menu->setItem(p0, false);
+void cmdDisableItem(AgiGame *state, uint8 *p) {
+ state->_vm->_menu->setItem(p0, false);
}
-void AgiEngine::cmd_submit_menu(uint8 *p) {
- _menu->submit();
+void cmdSubmitMenu(AgiGame *state, uint8 *p) {
+ state->_vm->_menu->submit();
}
-void AgiEngine::cmd_set_scan_start(uint8 *p) {
- _curLogic->sIP = _curLogic->cIP;
+void cmdSetScanStart(AgiGame *state, uint8 *p) {
+ state->_curLogic->sIP = state->_curLogic->cIP;
}
-void AgiEngine::cmd_reset_scan_start(uint8 *p) {
- _curLogic->sIP = 2;
+void cmdResetScanStart(AgiGame *state, uint8 *p) {
+ state->_curLogic->sIP = 2;
}
-void AgiEngine::cmd_save_game(uint8 *p) {
- _game.simpleSave ? saveGameSimple() : saveGameDialog();
+void cmdSaveGame(AgiGame *state, uint8 *p) {
+ state->simpleSave ? state->_vm->saveGameSimple() : state->_vm->saveGameDialog();
}
-void AgiEngine::cmd_load_game(uint8 *p) {
+void cmdLoadGame(AgiGame *state, uint8 *p) {
assert(1);
- _game.simpleSave ? loadGameSimple() : loadGameDialog();
+ state->simpleSave ? state->_vm->loadGameSimple() : state->_vm->loadGameDialog();
}
-void AgiEngine::cmd_init_disk(uint8 *p) { // do nothing
+void cmdInitDisk(AgiGame *state, uint8 *p) { // do nothing
}
-void AgiEngine::cmd_log(uint8 *p) { // do nothing
+void cmdLog(AgiGame *state, uint8 *p) { // do nothing
}
-void AgiEngine::cmd_trace_on(uint8 *p) { // do nothing
+void cmdTraceOn(AgiGame *state, uint8 *p) { // do nothing
}
-void AgiEngine::cmd_trace_info(uint8 *p) { // do nothing
+void cmdTraceInfo(AgiGame *state, uint8 *p) { // do nothing
}
-void AgiEngine::cmd_show_mem(uint8 *p) {
- messageBox("Enough memory");
+void cmdShowMem(AgiGame *state, uint8 *p) {
+ state->_vm->messageBox("Enough memory");
}
-void AgiEngine::cmd_init_joy(uint8 *p) { // do nothing
+void cmdInitJoy(AgiGame *state, uint8 *p) { // do nothing
}
-void AgiEngine::cmd_script_size(uint8 *p) {
+void cmdScriptSize(AgiGame *state, uint8 *p) {
debug(0, "script.size(%d)", p0);
}
-void AgiEngine::cmd_cancel_line(uint8 *p) {
- _game.inputBuffer[0] = 0;
- _game.cursorPos = 0;
- writePrompt();
+void cmdCancelLine(AgiGame *state, uint8 *p) {
+ state->inputBuffer[0] = 0;
+ state->cursorPos = 0;
+ state->_vm->writePrompt();
}
// This implementation is based on observations of Amiga's Gold Rush.
@@ -509,23 +545,23 @@ void AgiEngine::cmd_cancel_line(uint8 *p) {
// 4051 (When ego is stationary),
// 471 (When walking on the first screen's bridge),
// 71 (When walking around, using the mouse or the keyboard).
-void AgiEngine::cmd_obj_status_f(uint8 *p) {
+void cmdObjStatusF(AgiGame *state, uint8 *p) {
const char *cycleDesc; // Object's cycle description line
const char *motionDesc; // Object's motion description line
char msg[256]; // The whole object status message
// Generate cycle description line
switch (vt_v.cycle) {
- case CYCLE_NORMAL:
+ case kCycleNormal:
cycleDesc = "normal cycle";
break;
- case CYCLE_END_OF_LOOP:
+ case kCycleEndOfLoop:
cycleDesc = "end of loop";
break;
- case CYCLE_REV_LOOP:
+ case kCycleRevLoop:
cycleDesc = "reverse loop";
break;
- case CYCLE_REVERSE:
+ case kCycleReverse:
cycleDesc = "reverse cycle";
break;
default:
@@ -535,16 +571,16 @@ void AgiEngine::cmd_obj_status_f(uint8 *p) {
// Generate motion description line
switch (vt_v.motion) {
- case MOTION_NORMAL:
+ case kMotionNormal:
motionDesc = "normal motion";
break;
- case MOTION_WANDER:
+ case kMotionWander:
motionDesc = "wandering";
break;
- case MOTION_FOLLOW_EGO:
+ case kMotionFollowEgo:
motionDesc = "following ego";
break;
- case MOTION_MOVE_OBJ:
+ case kMotionMoveObj:
// Amiga's Gold Rush! most probably uses "move to (x, y)"
// here with real values for x and y. The same output
// is used when moving the ego around using the mouse.
@@ -570,7 +606,7 @@ void AgiEngine::cmd_obj_status_f(uint8 *p) {
vt_v.stepSize,
cycleDesc,
motionDesc);
- messageBox(msg);
+ state->_vm->messageBox(msg);
}
// unknown commands:
@@ -581,49 +617,49 @@ void AgiEngine::cmd_obj_status_f(uint8 *p) {
// unk_174: Change priority table (used in KQ4) -- j5
// unk_177: Disable menus completely -- j5
// unk_181: Deactivate keypressed control (default control of ego)
-void AgiEngine::cmd_set_simple(uint8 *p) {
+void cmdSetSimple(AgiGame *state, uint8 *p) {
if (!(getFeatures() & (GF_AGI256 | GF_AGI256_2))) {
- _game.simpleSave = true;
+ state->simpleSave = true;
} else { // AGI256 and AGI256-2 use this unknown170 command to load 256 color pictures.
- // Load the picture. Similar to void AgiEngine::cmd_load_pic(uint8 *p).
- _sprites->eraseBoth();
- agiLoadResource(rPICTURE, _v[p0]);
+ // Load the picture. Similar to void cmdLoad_pic(AgiGame *state, uint8 *p).
+ state->_vm->_sprites->eraseBoth();
+ state->_vm->agiLoadResource(rPICTURE, _v[p0]);
- // Draw the picture. Similar to void AgiEngine::cmd_draw_pic(uint8 *p).
- _picture->decodePicture(_v[p0], false, true);
- _sprites->blitBoth();
- _game.pictureShown = 0;
+ // Draw the picture. Similar to void cmdDraw_pic(AgiGame *state, uint8 *p).
+ state->_vm->_picture->decodePicture(_v[p0], false, true);
+ state->_vm->_sprites->blitBoth();
+ state->pictureShown = 0;
- // Show the picture. Similar to void AgiEngine::cmd_show_pic(uint8 *p).
+ // Show the picture. Similar to void cmdShow_pic(AgiGame *state, uint8 *p).
setflag(fOutputMode, false);
- closeWindow();
- _picture->showPic();
- _game.pictureShown = 1;
+ state->_vm->closeWindow();
+ state->_vm->_picture->showPic();
+ state->pictureShown = 1;
// Simulate slowww computer. Many effects rely on this
- pause(kPausePicture);
+ state->_vm->pause(kPausePicture);
}
}
-void AgiEngine::cmd_pop_script(uint8 *p) {
+void cmdPopScript(AgiGame *state, uint8 *p) {
if (getVersion() >= 0x2915) {
debug(0, "pop.script");
}
}
-void AgiEngine::cmd_hold_key(uint8 *p) {
+void cmdHoldKey(AgiGame *state, uint8 *p) {
if (getVersion() >= 0x3098) {
- _egoHoldKey = true;
+ state->_vm->_egoHoldKey = true;
}
}
-void AgiEngine::cmd_discard_sound(uint8 *p) {
+void cmdDiscardSound(AgiGame *state, uint8 *p) {
if (getVersion() >= 0x2936) {
debug(0, "discard.sound");
}
}
-void AgiEngine::cmd_hide_mouse(uint8 *p) {
+void cmdHideMouse(AgiGame *state, uint8 *p) {
// WORKAROUND: Turns off current movement that's being caused with the mouse.
// This fixes problems with too many popup boxes appearing in the Amiga
// Gold Rush's copy protection failure scene (i.e. the hanging scene, logic.192).
@@ -631,37 +667,37 @@ void AgiEngine::cmd_hide_mouse(uint8 *p) {
// to walk somewhere else than to the right using the mouse.
// FIXME: Write a proper implementation using disassembly and
// apply it to other games as well if applicable.
- _game.viewTable[0].flags &= ~ADJ_EGO_XY;
+ state->viewTable[0].flags &= ~fAdjEgoXY;
g_system->showMouse(false);
}
-void AgiEngine::cmd_allow_menu(uint8 *p) {
+void cmdAllowMenu(AgiGame *state, uint8 *p) {
if (getVersion() >= 0x3098) {
setflag(fMenusWork, ((p0 != 0) ? true : false));
}
}
-void AgiEngine::cmd_show_mouse(uint8 *p) {
+void cmdShowMouse(AgiGame *state, uint8 *p) {
g_system->showMouse(true);
}
-void AgiEngine::cmd_fence_mouse(uint8 *p) {
- _game.mouseFence.moveTo(p0, p1);
- _game.mouseFence.setWidth(p2 - p0);
- _game.mouseFence.setHeight(p3 - p1);
+void cmdFenceMouse(AgiGame *state, uint8 *p) {
+ state->mouseFence.moveTo(p0, p1);
+ state->mouseFence.setWidth(p2 - p0);
+ state->mouseFence.setHeight(p3 - p1);
}
-void AgiEngine::cmd_release_key(uint8 *p) {
+void cmdReleaseKey(AgiGame *state, uint8 *p) {
if (getVersion() >= 0x3098) {
- _egoHoldKey = false;
+ state->_vm->_egoHoldKey = false;
}
}
-void AgiEngine::cmd_adj_ego_move_to_x_y(uint8 *p) {
+void cmdAdjEgoMoveToXY(AgiGame *state, uint8 *p) {
int8 x, y;
- switch (logicNamesCmd[182].numArgs) {
+ switch (logicNamesCmd[182].argumentsLength()) {
// The 2 arguments version is used at least in Amiga Gold Rush!
// (v2.05 1989-03-09, Amiga AGI 2.316) in logics 130 and 150
// (Using arguments (0, 0), (0, 7), (0, 8), (9, 9) and (-9, 9)).
@@ -680,57 +716,67 @@ void AgiEngine::cmd_adj_ego_move_to_x_y(uint8 *p) {
// onto the ladder so this is more like it (Although that may be caused
// by something else because this command doesn't do any flag manipulations
// in the Amiga version - checked it with disassembly).
- if (x != _game.adjMouseX || y != _game.adjMouseY)
- _game.viewTable[EGO_VIEW_TABLE].flags &= ~ADJ_EGO_XY;
+ if (x != state->adjMouseX || y != state->adjMouseY)
+ state->viewTable[EGO_VIEW_TABLE].flags &= ~fAdjEgoXY;
- _game.adjMouseX = x;
- _game.adjMouseY = y;
+ state->adjMouseX = x;
+ state->adjMouseY = y;
debugC(4, kDebugLevelScripts, "adj.ego.move.to.x.y(%d, %d)", x, y);
break;
// TODO: Check where (if anywhere) the 0 arguments version is used
case 0:
default:
- _game.viewTable[0].flags |= ADJ_EGO_XY;
+ state->viewTable[0].flags |= fAdjEgoXY;
break;
}
}
-void AgiEngine::cmd_parse(uint8 *p) {
+void cmdParse(AgiGame *state, uint8 *p) {
_v[vWordNotFound] = 0;
setflag(fEnteredCli, false);
setflag(fSaidAcceptedInput, false);
- dictionaryWords(agiSprintf(_game.strings[p0]));
+ state->_vm->dictionaryWords(state->_vm->agiSprintf(state->strings[p0]));
}
-void AgiEngine::cmd_call(uint8 *p) {
+void cmdCall(AgiGame *state, uint8 *p) {
int oldCIP;
int oldLognum;
// CM: we don't save sIP because set.scan.start can be
// used in a called script (fixes xmas demo)
- oldCIP = _curLogic->cIP;
- oldLognum = _game.lognum;
+ oldCIP = state->_curLogic->cIP;
+ oldLognum = state->lognum;
- runLogic(p0);
+ state->_vm->runLogic(p0);
- _game.lognum = oldLognum;
- _curLogic = &_game.logics[_game.lognum];
- _curLogic->cIP = oldCIP;
+ state->lognum = oldLognum;
+ state->_curLogic = &state->logics[state->lognum];
+ state->_curLogic->cIP = oldCIP;
}
-void AgiEngine::cmd_call_f(uint8 *p) {
- cmd_call(&_v[p0]);
+void cmdCallF(AgiGame *state, uint8 *p) {
+ cmdCall(state, &_v[p0]);
+}
+
+void cmdDrawPicV1(AgiGame *state, uint8 *p) {
+ debugC(6, kDebugLevelScripts, "=== draw pic V1 %d ===", _v[p0]);
+ state->_vm->_picture->decodePicture(_v[p0], true);
+
+ state->_vm->clearPrompt();
+
+ // Simulate slowww computer. Many effects rely on this
+ state->_vm->pause(kPausePicture);
}
-void AgiEngine::cmd_draw_pic(uint8 *p) {
+void cmdDrawPic(AgiGame *state, uint8 *p) {
debugC(6, kDebugLevelScripts, "=== draw pic %d ===", _v[p0]);
- _sprites->eraseBoth();
- _picture->decodePicture(_v[p0], true);
- _sprites->blitBoth();
- _sprites->commitBoth();
- _game.pictureShown = 0;
+ state->_vm->_sprites->eraseBoth();
+ state->_vm->_picture->decodePicture(_v[p0], true);
+ state->_vm->_sprites->blitBoth();
+ state->_vm->_sprites->commitBoth();
+ state->pictureShown = 0;
debugC(6, kDebugLevelScripts, "--- end of draw pic %d ---", _v[p0]);
// WORKAROUND for a script bug which exists in SQ1, logic scripts
@@ -749,79 +795,93 @@ void AgiEngine::cmd_draw_pic(uint8 *p) {
setflag(103, false);
// Simulate slowww computer. Many effects rely on this
- pause(kPausePicture);
+ state->_vm->pause(kPausePicture);
}
-void AgiEngine::cmd_show_pic(uint8 *p) {
+void cmdShowPic(AgiGame *state, uint8 *p) {
debugC(6, kDebugLevelScripts, "=== show pic ===");
setflag(fOutputMode, false);
- closeWindow();
- _picture->showPic();
- _game.pictureShown = 1;
+ state->_vm->closeWindow();
+ state->_vm->_picture->showPic();
+ state->pictureShown = 1;
debugC(6, kDebugLevelScripts, "--- end of show pic ---");
}
-void AgiEngine::cmd_load_pic(uint8 *p) {
- _sprites->eraseBoth();
- agiLoadResource(rPICTURE, _v[p0]);
- _sprites->blitBoth();
- _sprites->commitBoth();
+void cmdLoadPic(AgiGame *state, uint8 *p) {
+ state->_vm->_sprites->eraseBoth();
+ state->_vm->agiLoadResource(rPICTURE, _v[p0]);
+ state->_vm->_sprites->blitBoth();
+ state->_vm->_sprites->commitBoth();
}
-void AgiEngine::cmd_discard_pic(uint8 *p) {
+void cmdLoadPicV1(AgiGame *state, uint8 *p) {
+ state->_vm->agiLoadResource(rPICTURE, _v[p0]);
+}
+
+void cmdDiscardPic(AgiGame *state, uint8 *p) {
debugC(6, kDebugLevelScripts, "--- discard pic ---");
// do nothing
}
-void AgiEngine::cmd_overlay_pic(uint8 *p) {
+void cmdOverlayPic(AgiGame *state, uint8 *p) {
debugC(6, kDebugLevelScripts, "--- overlay pic ---");
- _sprites->eraseBoth();
- _picture->decodePicture(_v[p0], false);
- _sprites->blitBoth();
- _game.pictureShown = 0;
- _sprites->commitBoth();
+ state->_vm->_sprites->eraseBoth();
+ state->_vm->_picture->decodePicture(_v[p0], false);
+ state->_vm->_sprites->blitBoth();
+ state->pictureShown = 0;
+ state->_vm->_sprites->commitBoth();
// Simulate slowww computer. Many effects rely on this
- pause(kPausePicture);
+ state->_vm->pause(kPausePicture);
}
-void AgiEngine::cmd_show_pri_screen(uint8 *p) {
- _debug.priority = 1;
- _sprites->eraseBoth();
- _picture->showPic();
- _sprites->blitBoth();
+void cmdShowPriScreen(AgiGame *state, uint8 *p) {
+ state->_vm->_debug.priority = 1;
+ state->_vm->_sprites->eraseBoth();
+ state->_vm->_picture->showPic();
+ state->_vm->_sprites->blitBoth();
- waitKey();
+ state->_vm->waitKey();
- _debug.priority = 0;
- _sprites->eraseBoth();
- _picture->showPic();
- _sprites->blitBoth();
+ state->_vm->_debug.priority = 0;
+ state->_vm->_sprites->eraseBoth();
+ state->_vm->_picture->showPic();
+ state->_vm->_sprites->blitBoth();
}
-void AgiEngine::cmd_animate_obj(uint8 *p) {
- if (vt.flags & ANIMATED)
- return;
+void cmdAnimateObj(AgiGame *state, uint8 *p) {
+ if (getVersion() < 0x2000) {
+ if (vt.flags & fDidntMove)
+ return;
+ } else {
+ if (vt.flags & fAnimated)
+ return;
+ }
debugC(4, kDebugLevelScripts, "animate vt entry #%d", p0);
- vt.flags = ANIMATED | UPDATE | CYCLING;
- vt.motion = MOTION_NORMAL;
- vt.cycle = CYCLE_NORMAL;
+ vt.flags = fAnimated | fUpdate | fCycling;
+
+ if (getVersion() < 0x2000) {
+ vt.flags |= fDidntMove;
+ }
+
+ vt.motion = kMotionNormal;
+ vt.cycle = kCycleNormal;
vt.direction = 0;
}
-void AgiEngine::cmd_unanimate_all(uint8 *p) {
+void cmdUnanimateAll(AgiGame *state, uint8 *p) {
int i;
for (i = 0; i < MAX_VIEWTABLE; i++)
- _game.viewTable[i].flags &= ~(ANIMATED | DRAWN);
+ state->viewTable[i].flags &= ~(fAnimated | fDrawn);
}
-void AgiEngine::cmd_draw(uint8 *p) {
- if (vt.flags & DRAWN)
+void cmdDraw(AgiGame *state, uint8 *p) {
+ if (vt.flags & fDrawn)
return;
if (vt.ySize <= 0 || vt.xSize <= 0)
@@ -829,18 +889,18 @@ void AgiEngine::cmd_draw(uint8 *p) {
debugC(4, kDebugLevelScripts, "draw entry %d", vt.entry);
- vt.flags |= UPDATE;
+ vt.flags |= fUpdate;
if (getVersion() >= 0x3000) {
- setLoop(&vt, vt.currentLoop);
- setCel(&vt, vt.currentCel);
+ state->_vm->setLoop(&vt, vt.currentLoop);
+ state->_vm->setCel(&vt, vt.currentCel);
}
- fixPosition(p0);
+ state->_vm->fixPosition(p0);
vt.xPos2 = vt.xPos;
vt.yPos2 = vt.yPos;
vt.celData2 = vt.celData;
- _sprites->eraseUpdSprites();
- vt.flags |= DRAWN;
+ state->_vm->_sprites->eraseUpdSprites();
+ vt.flags |= fDrawn;
// WORKAROUND: This fixes a bug with AGI Fanmade _game Space Trek.
// The original workaround checked if AGI version was <= 2.440, which could
@@ -854,30 +914,30 @@ void AgiEngine::cmd_draw(uint8 *p) {
// games are affected. If yes, then it'd be best to set this for Space
// Trek only
if (getFeatures() & GF_FANMADE) // See Sarien bug #546562
- vt.flags |= ANIMATED;
+ vt.flags |= fAnimated;
- _sprites->blitUpdSprites();
- vt.flags &= ~DONTUPDATE;
+ state->_vm->_sprites->blitUpdSprites();
+ vt.flags &= ~fDontupdate;
- _sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos, true);
+ state->_vm->_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos, true);
debugC(4, kDebugLevelScripts, "vt entry #%d flags = %02x", p0, vt.flags);
}
-void AgiEngine::cmd_erase(uint8 *p) {
- if (~vt.flags & DRAWN)
+void cmdErase(AgiGame *state, uint8 *p) {
+ if (~vt.flags & fDrawn)
return;
- _sprites->eraseUpdSprites();
+ state->_vm->_sprites->eraseUpdSprites();
- if (vt.flags & UPDATE) {
- vt.flags &= ~DRAWN;
+ if (vt.flags & fUpdate) {
+ vt.flags &= ~fDrawn;
} else {
- _sprites->eraseNonupdSprites();
- vt.flags &= ~DRAWN;
- _sprites->blitNonupdSprites();
+ state->_vm->_sprites->eraseNonupdSprites();
+ vt.flags &= ~fDrawn;
+ state->_vm->_sprites->blitNonupdSprites();
}
- _sprites->blitUpdSprites();
+ state->_vm->_sprites->blitUpdSprites();
int x1, y1, x2, y2;
@@ -886,10 +946,10 @@ void AgiEngine::cmd_erase(uint8 *p) {
y1 = MIN((int)MIN(vt.yPos, vt.yPos2), MIN(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height));
y2 = MAX((int)MAX(vt.yPos, vt.yPos2), MAX(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height));
- _sprites->commitBlock(x1, y1, x2, y2, true);
+ state->_vm->_sprites->commitBlock(x1, y1, x2, y2, true);
}
-void AgiEngine::cmd_position(uint8 *p) {
+void cmdPosition(AgiGame *state, uint8 *p) {
vt.xPos = vt.xPos2 = p1;
vt.yPos = vt.yPos2 = p2;
@@ -907,10 +967,15 @@ void AgiEngine::cmd_position(uint8 *p) {
// strictly need the identical workaround in the position.v-command but it does make
// for a nice symmetry.
if (getFeatures() & GF_CLIPCOORDS)
- clipViewCoordinates(&vt);
+ state->_vm->clipViewCoordinates(&vt);
}
-void AgiEngine::cmd_position_f(uint8 *p) {
+void cmdPositionV1(AgiGame *state, uint8 *p) {
+ vt.xPos = p1;
+ vt.yPos = p2;
+}
+
+void cmdPositionF(AgiGame *state, uint8 *p) {
vt.xPos = vt.xPos2 = _v[p1];
vt.yPos = vt.yPos2 = _v[p2];
@@ -918,19 +983,24 @@ void AgiEngine::cmd_position_f(uint8 *p) {
// with an accompanying identical workaround in position-command (i.e. command 0x25).
// See that workaround's comment for more in-depth information.
if (getFeatures() & GF_CLIPCOORDS)
- clipViewCoordinates(&vt);
+ state->_vm->clipViewCoordinates(&vt);
+}
+
+void cmdPositionFV1(AgiGame *state, uint8 *p) {
+ vt.xPos = _v[p1];
+ vt.yPos = _v[p2];
}
-void AgiEngine::cmd_get_posn(uint8 *p) {
- _game.vars[p1] = (unsigned char)vt.xPos;
- _game.vars[p2] = (unsigned char)vt.yPos;
+void cmdGetPosn(AgiGame *state, uint8 *p) {
+ state->vars[p1] = (unsigned char)vt.xPos;
+ state->vars[p2] = (unsigned char)vt.yPos;
}
-void AgiEngine::cmd_reposition(uint8 *p) {
+void cmdReposition(AgiGame *state, uint8 *p) {
int dx = (int8) _v[p1], dy = (int8) _v[p2];
debugC(4, kDebugLevelScripts, "dx=%d, dy=%d", dx, dy);
- vt.flags |= UPDATE_POS;
+ vt.flags |= fUpdatePos;
if (dx < 0 && vt.xPos < -dx)
vt.xPos = 0;
@@ -942,109 +1012,154 @@ void AgiEngine::cmd_reposition(uint8 *p) {
else
vt.yPos += dy;
- fixPosition(p0);
+ state->_vm->fixPosition(p0);
}
-void AgiEngine::cmd_reposition_to(uint8 *p) {
+void cmdRepositionV1(AgiGame *state, uint8 *p) {
+ vt.xPos2 = vt.xPos;
+ vt.yPos2 = vt.yPos;
+ vt.flags |= fUpdatePos;
+
+ vt.xPos = (vt.xPos + p1) & 0xff;
+ vt.yPos = (vt.yPos + p2) & 0xff;
+}
+
+void cmdRepositionTo(AgiGame *state, uint8 *p) {
vt.xPos = p1;
vt.yPos = p2;
- vt.flags |= UPDATE_POS;
- fixPosition(p0);
+ vt.flags |= fUpdatePos;
+ state->_vm->fixPosition(p0);
}
-void AgiEngine::cmd_reposition_to_f(uint8 *p) {
+void cmdRepositionToF(AgiGame *state, uint8 *p) {
vt.xPos = _v[p1];
vt.yPos = _v[p2];
- vt.flags |= UPDATE_POS;
- fixPosition(p0);
+ vt.flags |= fUpdatePos;
+ state->_vm->fixPosition(p0);
+}
+
+void cmdAddToPic(AgiGame *state, uint8 *p) {
+ state->_vm->_sprites->addToPic(p0, p1, p2, p3, p4, p5, p6);
}
-void AgiEngine::cmd_add_to_pic(uint8 *p) {
- _sprites->addToPic(p0, p1, p2, p3, p4, p5, p6);
+void cmdAddToPicV1(AgiGame *state, uint8 *p) {
+ state->_vm->_sprites->addToPic(p0, p1, p2, p3, p4, p5, -1);
}
-void AgiEngine::cmd_add_to_pic_f(uint8 *p) {
- _sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]);
+void cmdAddToPicF(AgiGame *state, uint8 *p) {
+ state->_vm->_sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]);
}
-void AgiEngine::cmd_force_update(uint8 *p) {
- _sprites->eraseBoth();
- _sprites->blitBoth();
- _sprites->commitBoth();
+void cmdForceUpdate(AgiGame *state, uint8 *p) {
+ state->_vm->_sprites->eraseBoth();
+ state->_vm->_sprites->blitBoth();
+ state->_vm->_sprites->commitBoth();
}
-void AgiEngine::cmd_reverse_loop(uint8 *p) {
+void cmdReverseLoop(AgiGame *state, uint8 *p) {
debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1);
- vt.cycle = CYCLE_REV_LOOP;
- vt.flags |= (DONTUPDATE | UPDATE | CYCLING);
+ vt.cycle = kCycleRevLoop;
+ vt.flags |= (fDontupdate | fUpdate | fCycling);
vt.parm1 = p1;
setflag(p1, false);
}
-void AgiEngine::cmd_end_of_loop(uint8 *p) {
+void cmdReverseLoopV1(AgiGame *state, uint8 *p) {
debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1);
- vt.cycle = CYCLE_END_OF_LOOP;
- vt.flags |= (DONTUPDATE | UPDATE | CYCLING);
+ vt.cycle = kCycleRevLoop;
+ state->_vm->setCel(&vt, 0);
+ vt.flags |= (fDontupdate | fUpdate | fCycling);
+ vt.parm1 = p1;
+ vt.parm3 = 0;
+}
+
+void cmdEndOfLoop(AgiGame *state, uint8 *p) {
+ debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1);
+ vt.cycle = kCycleEndOfLoop;
+ vt.flags |= (fDontupdate | fUpdate | fCycling);
vt.parm1 = p1;
setflag(p1, false);
}
-void AgiEngine::cmd_block(uint8 *p) {
+void cmdEndOfLoopV1(AgiGame *state, uint8 *p) {
+ debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1);
+ vt.cycle = kCycleEndOfLoop;
+ state->_vm->setCel(&vt, 0);
+ vt.flags |= (fDontupdate | fUpdate | fCycling);
+ vt.parm1 = p1;
+ vt.parm3 = 0;
+}
+
+void cmdBlock(AgiGame *state, uint8 *p) {
debugC(4, kDebugLevelScripts, "x1=%d, y1=%d, x2=%d, y2=%d", p0, p1, p2, p3);
- _game.block.active = true;
- _game.block.x1 = p0;
- _game.block.y1 = p1;
- _game.block.x2 = p2;
- _game.block.y2 = p3;
+ state->block.active = true;
+ state->block.x1 = p0;
+ state->block.y1 = p1;
+ state->block.x2 = p2;
+ state->block.y2 = p3;
}
-void AgiEngine::cmd_unblock(uint8 *p) {
- _game.block.active = false;
+void cmdUnblock(AgiGame *state, uint8 *p) {
+ state->block.active = false;
}
-void AgiEngine::cmd_normal_motion(uint8 *p) {
- vt.motion = MOTION_NORMAL;
+void cmdNormalMotion(AgiGame *state, uint8 *p) {
+ vt.motion = kMotionNormal;
}
-void AgiEngine::cmd_stop_motion(uint8 *p) {
+void cmdStopMotion(AgiGame *state, uint8 *p) {
vt.direction = 0;
- vt.motion = MOTION_NORMAL;
+ vt.motion = kMotionNormal;
if (p0 == 0) { // ego only
_v[vEgoDir] = 0;
- _game.playerControl = false;
+ state->playerControl = false;
}
}
-void AgiEngine::cmd_start_motion(uint8 *p) {
- vt.motion = MOTION_NORMAL;
+void cmdStopMotionV1(AgiGame *state, uint8 *p) {
+ vt.flags &= ~fAnimated;
+}
+
+void cmdStartMotion(AgiGame *state, uint8 *p) {
+ vt.motion = kMotionNormal;
if (p0 == 0) { // ego only
_v[vEgoDir] = 0;
- _game.playerControl = true;
+ state->playerControl = true;
}
}
-void AgiEngine::cmd_player_control(uint8 *p) {
- _game.playerControl = true;
- _game.viewTable[0].motion = MOTION_NORMAL;
+void cmdStartMotionV1(AgiGame *state, uint8 *p) {
+ vt.flags |= fAnimated;
}
-void AgiEngine::cmd_program_control(uint8 *p) {
- _game.playerControl = false;
+void cmdPlayerControl(AgiGame *state, uint8 *p) {
+ state->playerControl = true;
+ state->viewTable[0].motion = kMotionNormal;
}
-void AgiEngine::cmd_follow_ego(uint8 *p) {
- vt.motion = MOTION_FOLLOW_EGO;
+void cmdProgramControl(AgiGame *state, uint8 *p) {
+ state->playerControl = false;
+}
+
+void cmdFollowEgo(AgiGame *state, uint8 *p) {
+ vt.motion = kMotionFollowEgo;
vt.parm1 = p1 > vt.stepSize ? p1 : vt.stepSize;
vt.parm2 = p2;
vt.parm3 = 0xff;
- setflag(p2, false);
- vt.flags |= UPDATE;
+
+ if (getVersion() < 0x2000) {
+ _v[p2] = 0;
+ vt.flags |= fUpdate | fAnimated;
+ } else {
+ setflag(p2, false);
+ vt.flags |= fUpdate;
+ }
}
-void AgiEngine::cmd_move_obj(uint8 *p) {
+void cmdMoveObj(AgiGame *state, uint8 *p) {
// _D (_D_WARN "o=%d, x=%d, y=%d, s=%d, f=%d", p0, p1, p2, p3, p4);
- vt.motion = MOTION_MOVE_OBJ;
+ vt.motion = kMotionMoveObj;
vt.parm1 = p1;
vt.parm2 = p2;
vt.parm3 = vt.stepSize;
@@ -1053,19 +1168,24 @@ void AgiEngine::cmd_move_obj(uint8 *p) {
if (p3 != 0)
vt.stepSize = p3;
- setflag(p4, false);
- vt.flags |= UPDATE;
+ if (getVersion() < 0x2000) {
+ _v[p4] = 0;
+ vt.flags |= fUpdate | fAnimated;
+ } else {
+ setflag(p4, false);
+ vt.flags |= fUpdate;
+ }
if (p0 == 0)
- _game.playerControl = false;
+ state->playerControl = false;
// AGI 2.272 (ddp, xmas) doesn't call move_obj!
if (getVersion() > 0x2272)
- moveObj(&vt);
+ state->_vm->moveObj(&vt);
}
-void AgiEngine::cmd_move_obj_f(uint8 *p) {
- vt.motion = MOTION_MOVE_OBJ;
+void cmdMoveObjF(AgiGame *state, uint8 *p) {
+ vt.motion = kMotionMoveObj;
vt.parm1 = _v[p1];
vt.parm2 = _v[p2];
vt.parm3 = vt.stepSize;
@@ -1075,66 +1195,70 @@ void AgiEngine::cmd_move_obj_f(uint8 *p) {
vt.stepSize = _v[p3];
setflag(p4, false);
- vt.flags |= UPDATE;
+ vt.flags |= fUpdate;
if (p0 == 0)
- _game.playerControl = false;
+ state->playerControl = false;
// AGI 2.272 (ddp, xmas) doesn't call move_obj!
if (getVersion() > 0x2272)
- moveObj(&vt);
+ state->_vm->moveObj(&vt);
}
-void AgiEngine::cmd_wander(uint8 *p) {
+void cmdWander(AgiGame *state, uint8 *p) {
if (p0 == 0)
- _game.playerControl = false;
+ state->playerControl = false;
- vt.motion = MOTION_WANDER;
- vt.flags |= UPDATE;
+ vt.motion = kMotionWander;
+ if (getVersion() < 0x2000) {
+ vt.flags |= fUpdate | fAnimated;
+ } else {
+ vt.flags |= fUpdate;
+ }
}
-void AgiEngine::cmd_set_game_id(uint8 *p) {
- if (_curLogic->texts && (p0 - 1) <= _curLogic->numTexts)
- strncpy(_game.id, _curLogic->texts[p0 - 1], 8);
+void cmdSetGameID(AgiGame *state, uint8 *p) {
+ if (state->_curLogic->texts && (p0 - 1) <= state->_curLogic->numTexts)
+ strncpy(state->id, state->_curLogic->texts[p0 - 1], 8);
else
- _game.id[0] = 0;
+ state->id[0] = 0;
- debug(0, "Game ID: \"%s\"", _game.id);
+ debug(0, "Game ID: \"%s\"", state->id);
}
-void AgiEngine::cmd_pause(uint8 *p) {
- int tmp = _game.clockEnabled;
+void cmdPause(AgiGame *state, uint8 *p) {
+ int tmp = state->clockEnabled;
const char *b[] = { "Continue", NULL };
const char *b_ru[] = { "\x8f\xe0\xae\xa4\xae\xab\xa6\xa8\xe2\xec", NULL };
- _game.clockEnabled = false;
+ state->clockEnabled = false;
switch (getLanguage()) {
case Common::RU_RUS:
- selectionBox(" \x88\xa3\xe0\xa0 \xae\xe1\xe2\xa0\xad\xae\xa2\xab\xa5\xad\xa0. \n\n\n", b_ru);
+ state->_vm->selectionBox(" \x88\xa3\xe0\xa0 \xae\xe1\xe2\xa0\xad\xae\xa2\xab\xa5\xad\xa0. \n\n\n", b_ru);
break;
default:
- selectionBox(" Game is paused. \n\n\n", b);
+ state->_vm->selectionBox(" Game is paused. \n\n\n", b);
break;
}
- _game.clockEnabled = tmp;
+ state->clockEnabled = tmp;
}
-void AgiEngine::cmd_set_menu(uint8 *p) {
- debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, _curLogic->numTexts);
+void cmdSetMenu(AgiGame *state, uint8 *p) {
+ debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, state->_curLogic->numTexts);
- if (_curLogic->texts != NULL && p0 <= _curLogic->numTexts)
- _menu->add(_curLogic->texts[p0 - 1]);
+ if (state->_curLogic->texts != NULL && p0 <= state->_curLogic->numTexts)
+ state->_vm->_menu->add(state->_curLogic->texts[p0 - 1]);
}
-void AgiEngine::cmd_set_menu_item(uint8 *p) {
- debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, _curLogic->numTexts);
+void cmdSetMenuItem(AgiGame *state, uint8 *p) {
+ debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, state->_curLogic->numTexts);
- if (_curLogic->texts != NULL && p0 <= _curLogic->numTexts)
- _menu->addItem(_curLogic->texts[p0 - 1], p1);
+ if (state->_curLogic->texts != NULL && p0 <= state->_curLogic->numTexts)
+ state->_vm->_menu->addItem(state->_curLogic->texts[p0 - 1], p1);
}
-void AgiEngine::cmd_version(uint8 *p) {
+void cmdVersion(AgiGame *state, uint8 *p) {
char verMsg[64];
char ver2Msg[] =
"\n"
@@ -1171,89 +1295,94 @@ void AgiEngine::cmd_version(uint8 *p) {
strncpy(q + 1 + gap, verMsg, strlen(verMsg));
sprintf(msg, q, maj, min);
- messageBox(msg);
+ state->_vm->messageBox(msg);
}
-void AgiEngine::cmd_configure_screen(uint8 *p) {
- _game.lineMinPrint = p0;
- _game.lineUserInput = p1;
- _game.lineStatus = p2;
+void cmdConfigureScreen(AgiGame *state, uint8 *p) {
+ state->lineMinPrint = p0;
+ state->lineUserInput = p1;
+ state->lineStatus = p2;
}
-void AgiEngine::cmd_text_screen(uint8 *p) {
+void cmdTextScreen(AgiGame *state, uint8 *p) {
debugC(4, kDebugLevelScripts, "switching to text mode");
- _game.gfxMode = false;
+ state->gfxMode = false;
// Simulates the "bright background bit" of the PC video
// controller.
- if (_game.colorBg)
- _game.colorBg |= 0x08;
+ if (state->colorBg)
+ state->colorBg |= 0x08;
- _gfx->clearScreen(_game.colorBg);
+ state->_vm->_gfx->clearScreen(state->colorBg);
}
-void AgiEngine::cmd_graphics(uint8 *p) {
+void cmdGraphics(AgiGame *state, uint8 *p) {
debugC(4, kDebugLevelScripts, "switching to graphics mode");
- if (!_game.gfxMode) {
- _game.gfxMode = true;
- _gfx->clearScreen(0);
- _picture->showPic();
- writeStatus();
- writePrompt();
+ if (!state->gfxMode) {
+ state->gfxMode = true;
+ state->_vm->_gfx->clearScreen(0);
+ state->_vm->_picture->showPic();
+ state->_vm->writeStatus();
+ state->_vm->writePrompt();
}
}
-void AgiEngine::cmd_set_text_attribute(uint8 *p) {
- _game.colorFg = p0;
- _game.colorBg = p1;
+void cmdSetTextAttribute(AgiGame *state, uint8 *p) {
+ state->colorFg = p0;
+ state->colorBg = p1;
- if (_game.gfxMode) {
- if (_game.colorBg != 0) {
- _game.colorFg = 0;
- _game.colorBg = 15;
+ if (state->gfxMode) {
+ if (state->colorBg != 0) {
+ state->colorFg = 0;
+ state->colorBg = 15;
}
}
}
-void AgiEngine::cmd_status(uint8 *p) {
- inventory();
+void cmdStatus(AgiGame *state, uint8 *p) {
+ state->_vm->inventory();
}
-void AgiEngine::cmd_quit(uint8 *p) {
+void cmdQuit(AgiGame *state, uint8 *p) {
const char *buttons[] = { "Quit", "Continue", NULL };
- _sound->stopSound();
+ state->_vm->_sound->stopSound();
if (p0) {
- quitGame();
+ state->_vm->quitGame();
} else {
- if (selectionBox(" Quit the game, or continue? \n\n\n", buttons) == 0) {
- quitGame();
+ if (state->_vm->selectionBox(" Quit the game, or continue? \n\n\n", buttons) == 0) {
+ state->_vm->quitGame();
}
}
}
-void AgiEngine::cmd_restart_game(uint8 *p) {
+void cmdQuitV1(AgiGame *state, uint8 *p) {
+ state->_vm->_sound->stopSound();
+ state->_vm->quitGame();
+}
+
+void cmdRestartGame(AgiGame *state, uint8 *p) {
const char *buttons[] = { "Restart", "Continue", NULL };
int sel;
- _sound->stopSound();
+ state->_vm->_sound->stopSound();
sel = getflag(fAutoRestart) ? 0 :
- selectionBox(" Restart _game, or continue? \n\n\n", buttons);
+ state->_vm->selectionBox(" Restart _game, or continue? \n\n\n", buttons);
if (sel == 0) {
- _restartGame = true;
+ state->_vm->_restartGame = true;
setflag(fRestartGame, true);
- _menu->enableAll();
+ state->_vm->_menu->enableAll();
}
}
-void AgiEngine::cmd_distance(uint8 *p) {
+void cmdDistance(AgiGame *state, uint8 *p) {
int16 x1, y1, x2, y2, d;
- VtEntry *v0 = &_game.viewTable[p0];
- VtEntry *v1 = &_game.viewTable[p1];
+ VtEntry *v0 = &state->viewTable[p0];
+ VtEntry *v1 = &state->viewTable[p1];
- if (v0->flags & DRAWN && v1->flags & DRAWN) {
+ if (v0->flags & fDrawn && v1->flags & fDrawn) {
x1 = v0->xPos + v0->xSize / 2;
y1 = v0->yPos;
x2 = v1->xPos + v1->xSize / 2;
@@ -1299,24 +1428,24 @@ void AgiEngine::cmd_distance(uint8 *p) {
_v[p2] = (unsigned char)d;
}
-void AgiEngine::cmd_accept_input(uint8 *p) {
+void cmdAcceptInput(AgiGame *state, uint8 *p) {
debugC(4, kDebugLevelScripts | kDebugLevelInput, "input normal");
- newInputMode(INPUT_NORMAL);
- _game.inputEnabled = true;
- writePrompt();
+ state->_vm->newInputMode(INPUT_NORMAL);
+ state->inputEnabled = true;
+ state->_vm->writePrompt();
}
-void AgiEngine::cmd_prevent_input(uint8 *p) {
+void cmdPreventInput(AgiGame *state, uint8 *p) {
debugC(4, kDebugLevelScripts | kDebugLevelInput, "no input");
- newInputMode(INPUT_NONE);
- _game.inputEnabled = false;
+ state->_vm->newInputMode(INPUT_NONE);
+ state->inputEnabled = false;
- clearPrompt();
+ state->_vm->clearPrompt();
}
-void AgiEngine::cmd_get_string(uint8 *p) {
+void cmdGetString(AgiGame *state, uint8 *p) {
int tex, row, col;
debugC(4, kDebugLevelScripts, "%d %d %d %d %d", p0, p1, p2, p3, p4);
@@ -1332,63 +1461,63 @@ void AgiEngine::cmd_get_string(uint8 *p) {
if (col > 39)
col = 39;
- newInputMode(INPUT_GETSTRING);
+ state->_vm->newInputMode(INPUT_GETSTRING);
- if (_curLogic->texts != NULL && _curLogic->numTexts >= tex) {
- int len = strlen(_curLogic->texts[tex]);
+ if (state->_curLogic->texts != NULL && state->_curLogic->numTexts >= tex) {
+ int len = strlen(state->_curLogic->texts[tex]);
- printText(_curLogic->texts[tex], 0, col, row, len, _game.colorFg, _game.colorBg);
- getString(col + len - 1, row, p4, p0);
+ state->_vm->printText(state->_curLogic->texts[tex], 0, col, row, len, state->colorFg, state->colorBg);
+ state->_vm->getString(col + len - 1, row, p4, p0);
// SGEO: display input char
- _gfx->printCharacter((col + len), row, _game.cursorChar, _game.colorFg, _game.colorBg);
+ state->_vm->_gfx->printCharacter((col + len), row, state->cursorChar, state->colorFg, state->colorBg);
}
do {
- mainCycle();
- } while (_game.inputMode == INPUT_GETSTRING && !(shouldQuit() || _restartGame));
+ state->_vm->mainCycle();
+ } while (state->inputMode == INPUT_GETSTRING && !(state->_vm->shouldQuit() || state->_vm->_restartGame));
}
-void AgiEngine::cmd_get_num(uint8 *p) {
+void cmdGetNum(AgiGame *state, uint8 *p) {
debugC(4, kDebugLevelScripts, "%d %d", p0, p1);
- newInputMode(INPUT_GETSTRING);
+ state->_vm->newInputMode(INPUT_GETSTRING);
- if (_curLogic->texts != NULL && _curLogic->numTexts >= (p0 - 1)) {
- int len = strlen(_curLogic->texts[p0 - 1]);
+ if (state->_curLogic->texts != NULL && state->_curLogic->numTexts >= (p0 - 1)) {
+ int len = strlen(state->_curLogic->texts[p0 - 1]);
- printText(_curLogic->texts[p0 - 1], 0, 0, 22, len, _game.colorFg, _game.colorBg);
- getString(len - 1, 22, 3, MAX_STRINGS);
+ state->_vm->printText(state->_curLogic->texts[p0 - 1], 0, 0, 22, len, state->colorFg, state->colorBg);
+ state->_vm->getString(len - 1, 22, 3, MAX_STRINGS);
// CM: display input char
- _gfx->printCharacter((p3 + len), 22, _game.cursorChar, _game.colorFg, _game.colorBg);
+ state->_vm->_gfx->printCharacter((p3 + len), 22, state->cursorChar, state->colorFg, state->colorBg);
}
do {
- mainCycle();
- } while (_game.inputMode == INPUT_GETSTRING && !(shouldQuit() || _restartGame));
+ state->_vm->mainCycle();
+ } while (state->inputMode == INPUT_GETSTRING && !(state->_vm->shouldQuit() || state->_vm->_restartGame));
- _v[p1] = atoi(_game.strings[MAX_STRINGS]);
+ _v[p1] = atoi(state->strings[MAX_STRINGS]);
- debugC(4, kDebugLevelScripts, "[%s] -> %d", _game.strings[MAX_STRINGS], _v[p1]);
+ debugC(4, kDebugLevelScripts, "[%s] -> %d", state->strings[MAX_STRINGS], _v[p1]);
- clearLines(22, 22, _game.colorBg);
- flushLines(22, 22);
+ state->_vm->clearLines(22, 22, state->colorBg);
+ state->_vm->flushLines(22, 22);
}
-void AgiEngine::cmd_set_cursor_char(uint8 *p) {
- if (_curLogic->texts != NULL && (p0 - 1) <= _curLogic->numTexts) {
- _game.cursorChar = *_curLogic->texts[p0 - 1];
+void cmdSetCursorChar(AgiGame *state, uint8 *p) {
+ if (state->_curLogic->texts != NULL && (p0 - 1) <= state->_curLogic->numTexts) {
+ state->cursorChar = *state->_curLogic->texts[p0 - 1];
} else {
// default
- _game.cursorChar = '_';
+ state->cursorChar = '_';
}
}
-void AgiEngine::cmd_set_key(uint8 *p) {
+void cmdSetKey(AgiGame *state, uint8 *p) {
int key;
- if (_game.lastController >= MAX_CONTROLLERS) {
+ if (state->lastController >= MAX_CONTROLLERS) {
warning("Number of set.keys exceeded %d", MAX_CONTROLLERS);
return;
}
@@ -1397,35 +1526,37 @@ void AgiEngine::cmd_set_key(uint8 *p) {
key = 256 * p1 + p0;
- _game.controllers[_game.lastController].keycode = key;
- _game.controllers[_game.lastController].controller = p2;
- _game.lastController++;
+ state->controllers[state->lastController].keycode = key;
+ state->controllers[state->lastController].controller = p2;
+ state->lastController++;
- _game.controllerOccured[p2] = false;
+ state->controllerOccured[p2] = false;
}
-void AgiEngine::cmd_set_string(uint8 *p) {
+void cmdSetString(AgiGame *state, uint8 *p) {
// CM: to avoid crash in Groza (str = 150)
if (p0 > MAX_STRINGS)
return;
- strcpy(_game.strings[p0], _curLogic->texts[p1 - 1]);
+ strcpy(state->strings[p0], state->_curLogic->texts[p1 - 1]);
}
-void AgiEngine::cmd_display(uint8 *p) {
+void cmdDisplay(AgiGame *state, uint8 *p) {
+ // V1 has 4 args
+ int t = (getVersion() >= 0x2000 ? p2 : p3);
int len = 40;
- char *s = wordWrapString(_curLogic->texts[p2 - 1], &len);
+ char *s = state->_vm->wordWrapString(state->_curLogic->texts[t - 1], &len);
- printText(s, p1, 0, p0, 40, _game.colorFg, _game.colorBg);
+ state->_vm->printText(s, p1, 0, p0, 40, state->colorFg, state->colorBg);
free(s);
}
-void AgiEngine::cmd_display_f(uint8 *p) {
- printText(_curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, _game.colorFg, _game.colorBg);
+void cmdDisplayF(AgiGame *state, uint8 *p) {
+ state->_vm->printText(state->_curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, state->colorFg, state->colorBg);
}
-void AgiEngine::cmd_clear_text_rect(uint8 *p) {
+void cmdClearTextRect(AgiGame *state, uint8 *p) {
int c, x1, y1, x2, y2;
if ((c = p4) != 0)
@@ -1446,21 +1577,21 @@ void AgiEngine::cmd_clear_text_rect(uint8 *p) {
if (y2 > GFX_HEIGHT)
y2 = GFX_HEIGHT - 1;
- _gfx->drawRectangle(x1, y1, x2, y2, c);
- _gfx->flushBlock(x1, y1, x2, y2);
+ state->_vm->_gfx->drawRectangle(x1, y1, x2, y2, c);
+ state->_vm->_gfx->flushBlock(x1, y1, x2, y2);
}
-void AgiEngine::cmd_toggle_monitor(uint8 *p) {
+void cmdToggleMonitor(AgiGame *state, uint8 *p) {
debug(0, "toggle.monitor");
}
-void AgiEngine::cmd_echo_line(uint8 *p) {
- strcpy((char *)_game.inputBuffer, (const char *)_game.echoBuffer);
- _game.cursorPos = strlen((char *)_game.inputBuffer);
- _game.hasPrompt = 0;
+void cmdEchoLine(AgiGame *state, uint8 *p) {
+ strcpy((char *)state->inputBuffer, (const char *)state->echoBuffer);
+ state->cursorPos = strlen((char *)state->inputBuffer);
+ state->hasPrompt = 0;
}
-void AgiEngine::cmd_clear_lines(uint8 *p) {
+void cmdClearLines(AgiGame *state, uint8 *p) {
uint8 l;
// Residence 44 calls clear.lines(24,0,0), see Sarien bug #558423
@@ -1470,42 +1601,42 @@ void AgiEngine::cmd_clear_lines(uint8 *p) {
// #1935838 and #1935842
l = (l <= 24) ? l : 24;
- clearLines(p0, l, p2);
- flushLines(p0, l);
+ state->_vm->clearLines(p0, l, p2);
+ state->_vm->flushLines(p0, l);
}
-void AgiEngine::cmd_print(uint8 *p) {
+void cmdPrint(AgiGame *state, uint8 *p) {
int n = p0 < 1 ? 1 : p0;
- print(_curLogic->texts[n - 1], 0, 0, 0);
+ state->_vm->print(state->_curLogic->texts[n - 1], 0, 0, 0);
}
-void AgiEngine::cmd_print_f(uint8 *p) {
+void cmdPrintF(AgiGame *state, uint8 *p) {
int n = _v[p0] < 1 ? 1 : _v[p0];
- print(_curLogic->texts[n - 1], 0, 0, 0);
+ state->_vm->print(state->_curLogic->texts[n - 1], 0, 0, 0);
}
-void AgiEngine::cmd_print_at(uint8 *p) {
+void cmdPrintAt(AgiGame *state, uint8 *p) {
int n = p0 < 1 ? 1 : p0;
debugC(4, kDebugLevelScripts, "%d %d %d %d", p0, p1, p2, p3);
- print(_curLogic->texts[n - 1], p1, p2, p3);
+ state->_vm->print(state->_curLogic->texts[n - 1], p1, p2, p3);
}
-void AgiEngine::cmd_print_at_v(uint8 *p) {
+void cmdPrintAtV(AgiGame *state, uint8 *p) {
int n = _v[p0] < 1 ? 1 : _v[p0];
- print(_curLogic->texts[n - 1], p1, p2, p3);
+ state->_vm->print(state->_curLogic->texts[n - 1], p1, p2, p3);
}
-void AgiEngine::cmd_push_script(uint8 *p) {
+void cmdPushScript(AgiGame *state, uint8 *p) {
// We run AGIMOUSE always as a side effect
if (getFeatures() & GF_AGIMOUSE || true) {
- _game.vars[27] = _mouse.button;
- _game.vars[28] = _mouse.x / 2;
- _game.vars[29] = _mouse.y;
+ state->vars[27] = state->_vm->_mouse.button;
+ state->vars[28] = state->_vm->_mouse.x / 2;
+ state->vars[29] = state->_vm->_mouse.y;
} else {
if (getVersion() >= 0x2915) {
debug(0, "push.script");
@@ -1513,35 +1644,35 @@ void AgiEngine::cmd_push_script(uint8 *p) {
}
}
-void AgiEngine::cmd_set_pri_base(uint8 *p) {
+void cmdSetPriBase(AgiGame *state, uint8 *p) {
int i, x, pri;
debug(0, "Priority base set to %d", p0);
- // _game.alt_pri = true;
+ // state->alt_pri = true;
x = (_HEIGHT - p0) * _HEIGHT / 10;
for (i = 0; i < _HEIGHT; i++) {
pri = (i - p0) < 0 ? 4 : (i - p0) * _HEIGHT / x + 5;
if (pri > 15)
pri = 15;
- _game.priTable[i] = pri;
+ state->priTable[i] = pri;
}
}
-void AgiEngine::cmd_mouse_posn(uint8 *p) {
- _v[p0] = WIN_TO_PIC_X(_mouse.x);
- _v[p1] = WIN_TO_PIC_Y(_mouse.y);
+void cmdMousePosn(AgiGame *state, uint8 *p) {
+ _v[p0] = WIN_TO_PIC_X(state->_vm->_mouse.x);
+ _v[p1] = WIN_TO_PIC_Y(state->_vm->_mouse.y);
}
-void AgiEngine::cmd_shake_screen(uint8 *p) {
+void cmdShakeScreen(AgiGame *state, uint8 *p) {
int i;
// AGIPAL uses shake.screen values between 100 and 109 to set the palette
// (Checked the original AGIPAL-hack's shake.screen-routine's disassembly).
if (p0 >= 100 && p0 < 110) {
if (getFeatures() & GF_AGIPAL) {
- _gfx->setAGIPal(p0);
+ state->_vm->_gfx->setAGIPal(p0);
return;
} else {
warning("It looks like GF_AGIPAL flag is missing");
@@ -1550,212 +1681,60 @@ void AgiEngine::cmd_shake_screen(uint8 *p) {
// Disables input while shaking to prevent bug
// #1678230: AGI: Entering text while screen is shaking
- bool originalValue = _game.inputEnabled;
- _game.inputEnabled = false;
+ bool originalValue = state->inputEnabled;
+ state->inputEnabled = false;
- _gfx->shakeStart();
+ state->_vm->_gfx->shakeStart();
- _sprites->commitBoth(); // Fixes SQ1 demo
+ state->_vm->_sprites->commitBoth(); // Fixes SQ1 demo
for (i = 4 * p0; i; i--) {
- _gfx->shakeScreen(i & 1);
- _gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1);
- mainCycle();
+ state->_vm->_gfx->shakeScreen(i & 1);
+ state->_vm->_gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1);
+ state->_vm->mainCycle();
}
- _gfx->shakeEnd();
+ state->_vm->_gfx->shakeEnd();
// Sets input back to what it was
- _game.inputEnabled = originalValue;
-}
-
-void AgiEngine::setupOpcodes() {
- AgiCommand tmp[] = {
- NULL, // 0x00
- &AgiEngine::cmd_increment,
- &AgiEngine::cmd_decrement,
- &AgiEngine::cmd_assignn,
- &AgiEngine::cmd_assignv,
- &AgiEngine::cmd_addn,
- &AgiEngine::cmd_addv,
- &AgiEngine::cmd_subn,
- &AgiEngine::cmd_subv, // 0x08
- &AgiEngine::cmd_lindirectv,
- &AgiEngine::cmd_rindirect,
- &AgiEngine::cmd_lindirectn,
- &AgiEngine::cmd_set,
- &AgiEngine::cmd_reset,
- &AgiEngine::cmd_toggle,
- &AgiEngine::cmd_set_v,
- &AgiEngine::cmd_reset_v, // 0x10
- &AgiEngine::cmd_toggle_v,
- &AgiEngine::cmd_new_room,
- &AgiEngine::cmd_new_room_f,
- &AgiEngine::cmd_load_logic,
- &AgiEngine::cmd_load_logic_f,
- &AgiEngine::cmd_call,
- &AgiEngine::cmd_call_f,
- &AgiEngine::cmd_load_pic, // 0x18
- &AgiEngine::cmd_draw_pic,
- &AgiEngine::cmd_show_pic,
- &AgiEngine::cmd_discard_pic,
- &AgiEngine::cmd_overlay_pic,
- &AgiEngine::cmd_show_pri_screen,
- &AgiEngine::cmd_load_view,
- &AgiEngine::cmd_load_view_f,
- &AgiEngine::cmd_discard_view, // 0x20
- &AgiEngine::cmd_animate_obj,
- &AgiEngine::cmd_unanimate_all,
- &AgiEngine::cmd_draw,
- &AgiEngine::cmd_erase,
- &AgiEngine::cmd_position,
- &AgiEngine::cmd_position_f,
- &AgiEngine::cmd_get_posn,
- &AgiEngine::cmd_reposition, // 0x28
- &AgiEngine::cmd_set_view,
- &AgiEngine::cmd_set_view_f,
- &AgiEngine::cmd_set_loop,
- &AgiEngine::cmd_set_loop_f,
- &AgiEngine::cmd_fix_loop,
- &AgiEngine::cmd_release_loop,
- &AgiEngine::cmd_set_cel,
- &AgiEngine::cmd_set_cel_f, // 0x30
- &AgiEngine::cmd_last_cel,
- &AgiEngine::cmd_current_cel,
- &AgiEngine::cmd_current_loop,
- &AgiEngine::cmd_current_view,
- &AgiEngine::cmd_number_of_loops,
- &AgiEngine::cmd_set_priority,
- &AgiEngine::cmd_set_priority_f,
- &AgiEngine::cmd_release_priority, // 0x38
- &AgiEngine::cmd_get_priority,
- &AgiEngine::cmd_stop_update,
- &AgiEngine::cmd_start_update,
- &AgiEngine::cmd_force_update,
- &AgiEngine::cmd_ignore_horizon,
- &AgiEngine::cmd_observe_horizon,
- &AgiEngine::cmd_set_horizon,
- &AgiEngine::cmd_object_on_water, // 0x40
- &AgiEngine::cmd_object_on_land,
- &AgiEngine::cmd_object_on_anything,
- &AgiEngine::cmd_ignore_objs,
- &AgiEngine::cmd_observe_objs,
- &AgiEngine::cmd_distance,
- &AgiEngine::cmd_stop_cycling,
- &AgiEngine::cmd_start_cycling,
- &AgiEngine::cmd_normal_cycle, // 0x48
- &AgiEngine::cmd_end_of_loop,
- &AgiEngine::cmd_reverse_cycle,
- &AgiEngine::cmd_reverse_loop,
- &AgiEngine::cmd_cycle_time,
- &AgiEngine::cmd_stop_motion,
- &AgiEngine::cmd_start_motion,
- &AgiEngine::cmd_step_size,
- &AgiEngine::cmd_step_time, // 0x50
- &AgiEngine::cmd_move_obj,
- &AgiEngine::cmd_move_obj_f,
- &AgiEngine::cmd_follow_ego,
- &AgiEngine::cmd_wander,
- &AgiEngine::cmd_normal_motion,
- &AgiEngine::cmd_set_dir,
- &AgiEngine::cmd_get_dir,
- &AgiEngine::cmd_ignore_blocks, // 0x58
- &AgiEngine::cmd_observe_blocks,
- &AgiEngine::cmd_block,
- &AgiEngine::cmd_unblock,
- &AgiEngine::cmd_get,
- &AgiEngine::cmd_get_f,
- &AgiEngine::cmd_drop,
- &AgiEngine::cmd_put,
- &AgiEngine::cmd_put_f, // 0x60
- &AgiEngine::cmd_get_room_f,
- &AgiEngine::cmd_load_sound,
- &AgiEngine::cmd_sound,
- &AgiEngine::cmd_stop_sound,
- &AgiEngine::cmd_print,
- &AgiEngine::cmd_print_f,
- &AgiEngine::cmd_display,
- &AgiEngine::cmd_display_f, // 0x68
- &AgiEngine::cmd_clear_lines,
- &AgiEngine::cmd_text_screen,
- &AgiEngine::cmd_graphics,
- &AgiEngine::cmd_set_cursor_char,
- &AgiEngine::cmd_set_text_attribute,
- &AgiEngine::cmd_shake_screen,
- &AgiEngine::cmd_configure_screen,
- &AgiEngine::cmd_status_line_on, // 0x70
- &AgiEngine::cmd_status_line_off,
- &AgiEngine::cmd_set_string,
- &AgiEngine::cmd_get_string,
- &AgiEngine::cmd_word_to_string,
- &AgiEngine::cmd_parse,
- &AgiEngine::cmd_get_num,
- &AgiEngine::cmd_prevent_input,
- &AgiEngine::cmd_accept_input, // 0x78
- &AgiEngine::cmd_set_key,
- &AgiEngine::cmd_add_to_pic,
- &AgiEngine::cmd_add_to_pic_f,
- &AgiEngine::cmd_status,
- &AgiEngine::cmd_save_game,
- &AgiEngine::cmd_load_game,
- &AgiEngine::cmd_init_disk,
- &AgiEngine::cmd_restart_game, // 0x80
- &AgiEngine::cmd_show_obj,
- &AgiEngine::cmd_random,
- &AgiEngine::cmd_program_control,
- &AgiEngine::cmd_player_control,
- &AgiEngine::cmd_obj_status_f,
- &AgiEngine::cmd_quit,
- &AgiEngine::cmd_show_mem,
- &AgiEngine::cmd_pause, // 0x88
- &AgiEngine::cmd_echo_line,
- &AgiEngine::cmd_cancel_line,
- &AgiEngine::cmd_init_joy,
- &AgiEngine::cmd_toggle_monitor,
- &AgiEngine::cmd_version,
- &AgiEngine::cmd_script_size,
- &AgiEngine::cmd_set_game_id,
- &AgiEngine::cmd_log, // 0x90
- &AgiEngine::cmd_set_scan_start,
- &AgiEngine::cmd_reset_scan_start,
- &AgiEngine::cmd_reposition_to,
- &AgiEngine::cmd_reposition_to_f,
- &AgiEngine::cmd_trace_on,
- &AgiEngine::cmd_trace_info,
- &AgiEngine::cmd_print_at,
- &AgiEngine::cmd_print_at_v, // 0x98
- &AgiEngine::cmd_discard_view, // Opcode repeated from 0x20 ?
- &AgiEngine::cmd_clear_text_rect,
- &AgiEngine::cmd_set_upper_left,
- &AgiEngine::cmd_set_menu,
- &AgiEngine::cmd_set_menu_item,
- &AgiEngine::cmd_submit_menu,
- &AgiEngine::cmd_enable_item,
- &AgiEngine::cmd_disable_item, // 0xa0
- &AgiEngine::cmd_menu_input,
- &AgiEngine::cmd_show_obj_v,
- &AgiEngine::cmd_open_dialogue,
- &AgiEngine::cmd_close_dialogue,
- &AgiEngine::cmd_mul_n,
- &AgiEngine::cmd_mul_v,
- &AgiEngine::cmd_div_n,
- &AgiEngine::cmd_div_v, // 0xa8
- &AgiEngine::cmd_close_window,
- &AgiEngine::cmd_set_simple,
- &AgiEngine::cmd_push_script,
- &AgiEngine::cmd_pop_script,
- &AgiEngine::cmd_hold_key,
- &AgiEngine::cmd_set_pri_base,
- &AgiEngine::cmd_discard_sound,
- &AgiEngine::cmd_hide_mouse, // 0xb0
- &AgiEngine::cmd_allow_menu,
- &AgiEngine::cmd_show_mouse,
- &AgiEngine::cmd_fence_mouse,
- &AgiEngine::cmd_mouse_posn,
- &AgiEngine::cmd_release_key,
- &AgiEngine::cmd_adj_ego_move_to_x_y
- };
- assert(ARRAYSIZE(_agiCommands) == ARRAYSIZE(tmp));
- for (int i = 0; i < ARRAYSIZE(tmp); ++i)
- _agiCommands[i] = tmp[i];
+ state->inputEnabled = originalValue;
+}
+
+void cmdSetSpeed(AgiGame *state, uint8 *p) {
+ // V1 command
+ (void)state;
+ (void)p;
+ // speed = _v[p0];
+}
+
+void cmdSetItemView(AgiGame *state, uint8 *p) {
+ // V1 command
+ (void)state;
+ (void)p;
+}
+
+void cmdCallV1(AgiGame *state, uint8 *p) {
+ state->_vm->agiLoadResource(rLOGIC, p0);
+ state->logic_list[++state->max_logics];
+ _v[13] = 1;
+}
+
+void cmdNewRoomV1(AgiGame *state, uint8 *p) {
+ warning("cmdNewRoomV1()");
+ state->_vm->agiLoadResource(rLOGIC, p0);
+ state->max_logics = 1;
+ state->logic_list[1] = p0;
+ _v[13] = 1;
+}
+
+void cmdNewRoomVV1(AgiGame *state, uint8 *p) {
+ warning("cmdNewRoomVV1()");
+ state->_vm->agiLoadResource(rLOGIC, _v[p0]);
+ state->max_logics = 1;
+ state->logic_list[1] = _v[p0];
+ _v[13] = 1;
+}
+
+void cmdUnknown(AgiGame *state, uint8 *p) {
+ warning("Skipping unknown opcode %2X", *(code + ip - 1));
}
/**
@@ -1763,11 +1742,15 @@ void AgiEngine::setupOpcodes() {
* @param n Number of the logic resource to execute
*/
int AgiEngine::runLogic(int n) {
+ AgiGame *state = &_game;
uint8 op = 0;
uint8 p[CMD_BSIZE] = { 0 };
- uint8 *code = NULL;
int num = 0;
ScriptPos sp;
+ //int logic_index = 0;
+
+ state->logic_list[0] = 0;
+ state->max_logics = 0;
debugC(2, kDebugLevelScripts, "=================");
debugC(2, kDebugLevelScripts, "runLogic(%d)", n);
@@ -1783,10 +1766,9 @@ int AgiEngine::runLogic(int n) {
}
_game.lognum = n;
- _curLogic = &_game.logics[_game.lognum];
+ _game._curLogic = &_game.logics[_game.lognum];
- code = _curLogic->data;
- _curLogic->cIP = _curLogic->sIP;
+ _game._curLogic->cIP = _game._curLogic->sIP;
_timerHack = 0;
while (ip < _game.logics[n].size && !(shouldQuit() || _restartGame)) {
@@ -1833,19 +1815,39 @@ int AgiEngine::runLogic(int n) {
debugC(2, kDebugLevelScripts, "%sreturn() // Logic %d", st, n);
debugC(2, kDebugLevelScripts, "=================");
+// if (getVersion() < 0x2000) {
+// if (logic_index < state->max_logics) {
+// n = state->logic_list[++logic_index];
+// state->_curLogic = &state->logics[n];
+// state->lognum = n;
+// ip = 2;
+// warning("running logic %d\n", n);
+// break;
+// }
+// _v[13]=0;
+// }
+
_game.execStack.pop_back();
return 1;
default:
- num = logicNamesCmd[op].numArgs;
+ num = logicNamesCmd[op].argumentsLength();
memmove(p, code + ip, num);
memset(p + num, 0, CMD_BSIZE - num);
debugC(2, kDebugLevelScripts, "%s%s(%d %d %d)", st, logicNamesCmd[op].name, p[0], p[1], p[2]);
- (this->*_agiCommands[op])(p);
+ _agiCommands[op](&_game, p);
ip += num;
}
+// if ((op == 0x0B || op == 0x3F || op == 0x40) && logic_index < state->max_logics) {
+// n = state->logic_list[++logic_index];
+// state->_curLogic = &state->logics[n];
+// state->lognum = n;
+// ip = 2;
+// warning("running logic %d\n", n);
+// }
+
if (_game.exitAllLogics)
break;
}
@@ -1858,7 +1860,7 @@ int AgiEngine::runLogic(int n) {
void AgiEngine::executeAgiCommand(uint8 op, uint8 *p) {
debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]);
- (this->*_agiCommands[op])(p);
+ _agiCommands[op](&_game, p);
}
} // End of namespace Agi
diff --git a/engines/agi/op_dbg.cpp b/engines/agi/op_dbg.cpp
index be73dbefae..87e235cf17 100644
--- a/engines/agi/op_dbg.cpp
+++ b/engines/agi/op_dbg.cpp
@@ -28,248 +28,17 @@ namespace Agi {
#define ip (_game.logics[lognum].cIP)
#define code (_game.logics[lognum].data)
-#ifdef _L
-#undef _L
-#endif
-
-#define _L(a,b,c) { a, b, c }
-
-struct AgiLogicnames logicNamesTest[] = {
- _L("", 0, 0x00),
- _L("equaln", 2, 0x80),
- _L("equalv", 2, 0xC0),
- _L("lessn", 2, 0x80),
- _L("lessv", 2, 0xC0),
- _L("greatern", 2, 0x80),
- _L("greaterv", 2, 0xC0),
- _L("isset", 1, 0x00),
- _L("issetv", 1, 0x80),
- _L("has", 1, 0x00),
- _L("obj.in.room", 2, 0x40),
- _L("posn", 5, 0x00),
- _L("controller", 1, 0x00),
- _L("have.key", 0, 0x00),
-
- // Not 0 args. Has variable number.
- _L("said", 0, 0x00),
-
- _L("compare.strings", 2, 0x00),
- _L("obj.in.box", 5, 0x00),
- _L("center.posn", 5, 0x00),
- _L("right.posn", 5, 0x00),
-
- // Haven't seen an official name for this command so tried to name it descriptively.
- _L("in.motion.using.mouse", 0, 0x00)
-};
-
-struct AgiLogicnames logicNamesIf[] = {
- _L("OR", 0, 0x00),
- _L("NOT", 0, 0x00),
- _L("ELSE", 0, 0x00),
- _L("IF", 0, 0x00)
-};
-
-struct AgiLogicnames logicNamesCmd[] = {
- _L("return", 0, 0x00), // 00
- _L("increment", 1, 0x80), // 01
- _L("decrement", 1, 0x80), // 02
- _L("assignn", 2, 0x80), // 03
- _L("assignv", 2, 0xC0), // 04
- _L("addn", 2, 0x80), // 05
- _L("addv", 2, 0xC0), // 06
- _L("subn", 2, 0x80), // 07
- _L("subv", 2, 0xC0), // 08
- _L("lindirectv", 2, 0xC0), // 09
- _L("rindirect", 2, 0xC0), // 0A
- _L("lindirectn", 2, 0x80), // 0B
- _L("set", 1, 0x00), // 0C
- _L("reset", 1, 0x00), // 0D
- _L("toggle", 1, 0x00), // 0E
- _L("set.v", 1, 0x80), // 0F
- _L("reset.v", 1, 0x80), // 10
- _L("toggle.v", 1, 0x80), // 11
- _L("new.room", 1, 0x00), // 12
- _L("new.room.v", 1, 0x80), // 13
- _L("load.logics", 1, 0x00), // 14
- _L("load.logics.v", 1, 0x80), // 15
- _L("call", 1, 0x00), // 16
- _L("call.v", 1, 0x80), // 17
- _L("load.pic", 1, 0x80), // 18
- _L("draw.pic", 1, 0x80), // 19
- _L("show.pic", 0, 0x00), // 1A
- _L("discard.pic", 1, 0x80), // 1B
- _L("overlay.pic", 1, 0x80), // 1C
- _L("show.pri.screen", 0, 0x00), // 1D
- _L("load.view", 1, 0x00), // 1E
- _L("load.view.v", 1, 0x80), // 1F
- _L("discard.view", 1, 0x00), // 20
- _L("animate.obj", 1, 0x00), // 21
- _L("unanimate.all", 0, 0x00), // 22
- _L("draw", 1, 0x00), // 23
- _L("erase", 1, 0x00), // 24
- _L("position", 3, 0x00), // 25
- _L("position.v", 3, 0x60), // 26
- _L("get.posn", 3, 0x60), // 27
- _L("reposition", 3, 0x60), // 28
- _L("set.view", 2, 0x00), // 29
- _L("set.view.v", 2, 0x40), // 2A
- _L("set.loop", 2, 0x00), // 2B
- _L("set.loop.v", 2, 0x40), // 2C
- _L("fix.loop", 1, 0x00), // 2D
- _L("release.loop", 1, 0x00), // 2E
- _L("set.cel", 2, 0x00), // 2F
- _L("set.cel.v", 2, 0x40), // 30
- _L("last.cel", 2, 0x40), // 31
- _L("current.cel", 2, 0x40), // 32
- _L("current.loop", 2, 0x40), // 33
- _L("current.view", 2, 0x40), // 34
- _L("number.of.loops", 2, 0x40), // 35
- _L("set.priority", 2, 0x00), // 36
- _L("set.priority.v", 2, 0x40), // 37
- _L("release.priority", 1, 0x00), // 38
- _L("get.priority", 2, 0x40), // 39
- _L("stop.update", 1, 0x00), // 3A
- _L("start.update", 1, 0x00), // 3B
- _L("force.update", 1, 0x00), // 3C
- _L("ignore.horizon", 1, 0x00), // 3D
- _L("observe.horizon", 1, 0x00), // 3E
- _L("set.horizon", 1, 0x00), // 3F
- _L("object.on.water", 1, 0x00), // 40
- _L("object.on.land", 1, 0x00), // 41
- _L("object.on.anything", 1, 0x00), // 42
- _L("ignore.objs", 1, 0x00), // 43
- _L("observe.objs", 1, 0x00), // 44
- _L("distance", 3, 0x20), // 45
- _L("stop.cycling", 1, 0x00), // 46
- _L("start.cycling", 1, 0x00), // 47
- _L("normal.cycle", 1, 0x00), // 48
- _L("end.of.loop", 2, 0x00), // 49
- _L("reverse.cycle", 1, 0x00), // 4A
- _L("reverse.loop", 2, 0x00), // 4B
- _L("cycle.time", 2, 0x40), // 4C
- _L("stop.motion", 1, 0x00), // 4D
- _L("start.motion", 1, 0x00), // 4E
- _L("step.size", 2, 0x40), // 4F
- _L("step.time", 2, 0x40), // 50
- _L("move.obj", 5, 0x00), // 51
- _L("move.obj.v", 5, 0x70), // 52
- _L("follow.ego", 3, 0x00), // 53
- _L("wander", 1, 0x00), // 54
- _L("normal.motion", 1, 0x00), // 55
- _L("set.dir", 2, 0x40), // 56
- _L("get.dir", 2, 0x40), // 57
- _L("ignore.blocks", 1, 0x00), // 58
- _L("observe.blocks", 1, 0x00), // 59
- _L("block", 4, 0x00), // 5A
- _L("unblock", 0, 0x00), // 5B
- _L("get", 1, 0x00), // 5C
- _L("get.v", 1, 0x80), // 5D
- _L("drop", 1, 0x00), // 5E
- _L("put", 2, 0x00), // 5F
- _L("put.v", 2, 0x40), // 60
- _L("get.room.v", 2, 0xC0), // 61
- _L("load.sound", 1, 0x00), // 62
- _L("sound", 2, 0x00), // 63
- _L("stop.sound", 0, 0x00), // 64
- _L("print", 1, 0x00), // 65
- _L("print.v", 1, 0x80), // 66
- _L("display", 3, 0x00), // 67
- _L("display.v", 3, 0xE0), // 68
- _L("clear.lines", 3, 0x00), // 69
- _L("text.screen", 0, 0x00), // 6A
- _L("graphics", 0, 0x00), // 6B
- _L("set.cursor.char", 1, 0x00), // 6C
- _L("set.text.attribute", 2, 0x00), // 6D
- _L("shake.screen", 1, 0x00), // 6E
- _L("configure.screen", 3, 0x00), // 6F
- _L("status.line.on", 0, 0x00), // 70
- _L("status.line.off", 0, 0x00), // 71
- _L("set.string", 2, 0x00), // 72
- _L("get.string", 5, 0x00), // 73
- _L("word.to.string", 2, 0x00), // 74
- _L("parse", 1, 0x00), // 75
- _L("get.num", 2, 0x40), // 76
- _L("prevent.input", 0, 0x00), // 77
- _L("accept.input", 0, 0x00), // 78
- _L("set.key", 3, 0x00), // 79
- _L("add.to.pic", 7, 0x00), // 7A
- _L("add.to.pic.v", 7, 0xFE), // 7B
- _L("status", 0, 0x00), // 7C
- _L("save.game", 0, 0x00), // 7D
- _L("restore.game", 0, 0x00), // 7E
- _L("init.disk", 0, 0x00), // 7F
- _L("restart.game", 0, 0x00), // 80
- _L("show.obj", 1, 0x00), // 81
- _L("random", 3, 0x20), // 82
- _L("program.control", 0, 0x00), // 83
- _L("player.control", 0, 0x00), // 84
- _L("obj.status.v", 1, 0x80), // 85
- // 0 args for AGI version 2.089
- _L("quit", 1, 0x00), // 86
-
- _L("show.mem", 0, 0x00), // 87
- _L("pause", 0, 0x00), // 88
- _L("echo.line", 0, 0x00), // 89
- _L("cancel.line", 0, 0x00), // 8A
- _L("init.joy", 0, 0x00), // 8B
- _L("toggle.monitor", 0, 0x00), // 8C
- _L("version", 0, 0x00), // 8D
- _L("script.size", 1, 0x00), // 8E
- _L("set.game.id", 1, 0x00), // 8F
- _L("log", 1, 0x00), // 90
- _L("set.scan.start", 0, 0x00), // 91
- _L("reset.scan.start", 0, 0x00), // 92
- _L("reposition.to", 3, 0x00), // 93
- _L("reposition.to.v", 3, 0x60), // 94
- _L("trace.on", 0, 0x00), // 95
- _L("trace.info", 3, 0x00), // 96
-
- // 3 args for AGI versions before 2.440
- _L("print.at", 4, 0x00), // 97
- _L("print.at.v", 4, 0x80), // 98
-
- _L("discard.view.v", 1, 0x80), // 99
- _L("clear.text.rect", 5, 0x00), // 9A
- _L("set.upper.left", 2, 0x00), // 9B
- _L("set.menu", 1, 0x00), // 9C
- _L("set.menu.item", 2, 0x00), // 9D
- _L("submit.menu", 0, 0x00), // 9E
- _L("enable.item", 1, 0x00), // 9F
- _L("disable.item", 1, 0x00), // A0
- _L("menu.input", 0, 0x00), // A1
- _L("show.obj.v", 1, 0x01), // A2
- _L("open.dialogue", 0, 0x00), // A3
- _L("close.dialogue", 0, 0x00), // A4
- _L("mul.n", 2, 0x80), // A5
- _L("mul.v", 2, 0xC0), // A6
- _L("div.n", 2, 0x80), // A7
- _L("div.v", 2, 0xC0), // A8
- _L("close.window", 0, 0x00), // A9
-
- _L("set.simple", 1, 0x00), // AA
- _L("push.script", 0, 0x00), // AB
- _L("pop.script", 0, 0x00), // AC
- _L("hold.key", 0, 0x00), // AD
- _L("set.pri.base", 1, 0x00), // AE
- _L("discard.sound", 1, 0x00), // AF
-
- // 1 arg for AGI version 3.002.086
- _L("hide.mouse", 0, 0x00), // B0
-
- _L("allow.menu", 1, 0x00), // B1
- _L("show.mouse", 0, 0x00), // B2
- _L("fence.mouse", 4, 0x00), // B3
- _L("mouse.posn", 2, 0x00), // B4
- _L("release.key", 0, 0x00), // B5
-
- // 2 args for at least the Amiga Gold Rush! (v2.05 1989-03-09) using Amiga AGI 2.316.
- _L("adj.ego.move.to.xy", 0, 0x00), // B6
- _L(NULL, 0, 0x00)
+AgiInstruction logicNamesIf[] = {
+ { "OR", "", NULL },
+ { "NOT", "", NULL },
+ { "ELSE", "", NULL },
+ { "IF", "", NULL }
};
void AgiEngine::debugConsole(int lognum, int mode, const char *str) {
- AgiLogicnames *x;
- uint8 a, c, z;
+ AgiInstruction *x;
+ uint8 a, z;
+ const char *c;
if (str) {
debug(0, " %s", str);
@@ -302,8 +71,8 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) {
break;
default:
x = mode == lCOMMAND_MODE ? logicNamesCmd : logicNamesTest;
- a = (unsigned char)(x + *(code + ip))->numArgs;
- c = (unsigned char)(x + *(code + ip))->argMask;
+ a = x[*(code + ip)].argumentsLength();
+ c = x[*(code + ip)].args;
if (_debug.opcodes) {
debugN(0, "%02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
@@ -321,12 +90,12 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) {
debugN(0, "%s ", (x + *(code + ip))->name);
for (z = 1; a > 0;) {
- if (~c & 0x80) {
+ if (*c == 'n') {
debugN(0, "%d", *(code + (ip + z)));
} else {
debugN(0, "v%d[%d]", *(code + (ip + z)), getvar(*(code + (ip + z))));
}
- c <<= 1;
+ c++;
z++;
if (--a > 0)
debugN(0, ",");
diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp
index 0660a614b6..a44c68e0fc 100644
--- a/engines/agi/op_test.cpp
+++ b/engines/agi/op_test.cpp
@@ -23,18 +23,180 @@
#include "agi/agi.h"
#include "agi/opcodes.h"
+#include "common/endian.h"
namespace Agi {
-#define ip (_game.logics[lognum].cIP)
-#define code (_game.logics[lognum].data)
+#define ip (state->_curLogic->cIP)
+#define code (state->_curLogic->data)
+
+#define getvar(a) state->_vm->getvar(a)
+#define getflag(a) state->_vm->getflag(a)
#define testEqual(v1, v2) (getvar(v1) == (v2))
#define testLess(v1, v2) (getvar(v1) < (v2))
#define testGreater(v1, v2) (getvar(v1) > (v2))
#define testIsSet(flag) (getflag(flag))
-#define testHas(obj) (objectGetLocation(obj) == EGO_OWNED)
-#define testObjInRoom(obj, v) (objectGetLocation(obj) == getvar(v))
+#define testHas(obj) (state->_vm->objectGetLocation(obj) == EGO_OWNED)
+#define testHasV1(obj) (state->_vm->objectGetLocation(obj) == EGO_OWNED_V1)
+#define testObjInRoom(obj, v) (state->_vm->objectGetLocation(obj) == getvar(v))
+
+void condEqual(AgiGame *state, uint8 *p) {
+ if (p[0] == 11)
+ state->_vm->_timerHack++;
+ state->testResult = testEqual(p[0], p[1]);
+}
+
+void condEqualV(AgiGame *state, uint8 *p) {
+ if (p[0] == 11 || p[1] == 11)
+ state->_vm->_timerHack++;
+ state->testResult = testEqual(p[0], getvar(p[1]));
+}
+
+void condLess(AgiGame *state, uint8 *p) {
+ if (p[0] == 11)
+ state->_vm->_timerHack++;
+ state->testResult = testLess(p[0], p[1]);
+}
+
+void condLessV(AgiGame *state, uint8 *p) {
+ if (p[0] == 11 || p[1] == 11)
+ state->_vm->_timerHack++;
+ state->testResult = testLess(p[0], getvar(p[1]));
+}
+
+void condGreater(AgiGame *state, uint8 *p) {
+ if (p[0] == 11)
+ state->_vm->_timerHack++;
+ state->testResult = testGreater(p[0], p[1]);
+}
+
+void condGreaterV(AgiGame *state, uint8 *p) {
+ if (p[0] == 11 || p[1] == 11)
+ state->_vm->_timerHack++;
+ state->testResult = testGreater(p[0], getvar(p[1]));
+}
+
+void condIsSet(AgiGame *state, uint8 *p) {
+ state->testResult = testIsSet(p[0]);
+}
+
+void condIsSetV(AgiGame *state, uint8 *p) {
+ state->testResult = testIsSet(getvar(p[1]));
+}
+
+void condIsSetV1(AgiGame *state, uint8 *p) {
+ state->testResult = getvar(p[0]) > 0;
+}
+
+void condHas(AgiGame *state, uint8 *p) {
+ state->testResult = testHas(p[0]);
+}
+
+void condHasV1(AgiGame *state, uint8 *p) {
+ state->testResult = testHasV1(p[0]);
+}
+
+void condObjInRoom(AgiGame *state, uint8 *p) {
+ state->testResult = testObjInRoom(p[0], p[1]);
+}
+
+void condPosn(AgiGame *state, uint8 *p) {
+ state->testResult = state->_vm->testPosn(p[0], p[1], p[2], p[3], p[4]);
+}
+
+void condController(AgiGame *state, uint8 *p) {
+ state->testResult = state->_vm->testController(p[0]);
+}
+
+void condHaveKey(AgiGame *state, uint8 *p) {
+ state->testResult = state->_vm->testKeypressed();
+}
+
+void condSaid(AgiGame *state, uint8 *p) {
+ int ec = state->_vm->testSaid(p[0], p + 1);
+ state->testResult = ec;
+}
+
+void condSaid1(AgiGame *state, uint8 *p) {
+ state->testResult = false;
+
+ if (!getflag(fEnteredCli))
+ return;
+
+ int id0 = READ_LE_UINT16(p);
+
+ if ((id0 == 1 || id0 == state->egoWords[0].id))
+ state->testResult = true;
+}
+
+void condSaid2(AgiGame *state, uint8 *p) {
+ state->testResult = false;
+
+ if (!getflag(fEnteredCli))
+ return;
+
+ int id0 = READ_LE_UINT16(p);
+ int id1 = READ_LE_UINT16(p + 2);
+
+ if ((id0 == 1 || id0 == state->egoWords[0].id) &&
+ (id1 == 1 || id1 == state->egoWords[1].id))
+ state->testResult = true;
+}
+
+void condSaid3(AgiGame *state, uint8 *p) {
+ state->testResult = false;
+
+ if (!getflag(fEnteredCli))
+ return;
+
+ int id0 = READ_LE_UINT16(p);
+ int id1 = READ_LE_UINT16(p + 2);
+ int id2 = READ_LE_UINT16(p + 4);
+
+ if ((id0 == 1 || id0 == state->egoWords[0].id) &&
+ (id1 == 1 || id1 == state->egoWords[1].id) &&
+ (id2 == 1 || id2 == state->egoWords[2].id))
+ state->testResult = true;
+}
+
+void condBit(AgiGame *state, uint8 *p) {
+ state->testResult = (getvar(p[1]) >> p[0]) & 1;
+}
+
+void condCompareStrings(AgiGame *state, uint8 *p) {
+ debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", state->strings[p[0]], state->strings[p[1]]);
+ state->testResult = state->_vm->testCompareStrings(p[0], p[1]);
+}
+
+void condObjInBox(AgiGame *state, uint8 *p) {
+ state->testResult = state->_vm->testObjInBox(p[0], p[1], p[2], p[3], p[4]);
+}
+
+void condCenterPosn(AgiGame *state, uint8 *p) {
+ state->testResult = state->_vm->testObjCenter(p[0], p[1], p[2], p[3], p[4]);
+}
+
+void condRightPosn(AgiGame *state, uint8 *p) {
+ state->testResult = state->_vm->testObjRight(p[0], p[1], p[2], p[3], p[4]);
+}
+
+void condUnknown13(AgiGame *state, uint8 *p) {
+ // My current theory is that this command checks whether the ego is currently moving
+ // and that that movement has been caused using the mouse and not using the keyboard.
+ // I base this theory on the game's behavior on an Amiga emulator, not on disassembly.
+ // This command is used at least in the Amiga version of Gold Rush! v2.05 1989-03-09
+ // (AGI 2.316) in logics 1, 3, 5, 6, 137 and 192 (Logic.192 revealed this command's nature).
+ // TODO: Check this command's implementation using disassembly just to be sure.
+ int ec = state->viewTable[0].flags & fAdjEgoXY;
+ debugC(7, kDebugLevelScripts, "op_test: in.motion.using.mouse = %s (Amiga-specific testcase 19)", ec ? "true" : "false");
+ state->testResult = ec;
+}
+
+void condUnknown(AgiGame *state, uint8 *p) {
+ warning("Skipping unknown test command %2X", *(code + ip - 1));
+ state->testResult = false;
+}
uint8 AgiEngine::testCompareStrings(uint8 s1, uint8 s2) {
char ms1[MAX_STRINGLEN];
@@ -147,6 +309,7 @@ uint8 AgiEngine::testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) {
// When player has entered something, it is parsed elsewhere
uint8 AgiEngine::testSaid(uint8 nwords, uint8 *cc) {
+ AgiGame *state = &_game;
int c, n = _game.numEgoWords;
int z = 0;
@@ -202,210 +365,110 @@ uint8 AgiEngine::testSaid(uint8 nwords, uint8 *cc) {
}
int AgiEngine::testIfCode(int lognum) {
- int ec = true;
- int retval = true;
- uint8 op = 0;
- uint8 notTest = false;
- uint8 orTest = false;
- uint16 lastIp = ip;
- uint8 p[16] = { 0 };
- bool end_test = false;
-
- while (retval && !(shouldQuit() || _restartGame) && !end_test) {
+ AgiGame *state = &_game;
+ uint8 op;
+ uint8 p[16];
+
+ int notMode = false;
+ int orMode = false;
+ int endTest = false;
+ int result = true;
+
+ while (!(shouldQuit() || _restartGame) && !endTest) {
if (_debug.enabled && (_debug.logic0 || lognum))
debugConsole(lognum, lTEST_MODE, NULL);
- lastIp = ip;
op = *(code + ip++);
memmove(p, (code + ip), 16);
switch (op) {
- case 0xFF: // END IF, TEST true
- end_test = true;
- break;
- case 0xFD:
- notTest = !notTest;
- continue;
- case 0xFC: // OR
- // if or_test is ON and we hit 0xFC, end of OR, then
- // or is STILL false so break.
- if (orTest) {
- ec = false;
- retval = false;
- end_test = true;
+ case 0xFC:
+ if (orMode) {
+ // We have reached the end of an OR expression without
+ // a single test command evaluating as true. Thus the OR
+ // expression evalutes as false which means the whole
+ // expression evaluates as false. So skip until the
+ // ending 0xFF and return.
+ skipInstructionsUntil(0xFF);
+ result = false;
+ endTest = true;
+ } else {
+ orMode = true;
}
-
- orTest = true;
continue;
-
+ case 0xFD:
+ notMode = true;
+ continue;
case 0x00:
- // return true?
- end_test = true;
- break;
- case 0x01:
- ec = testEqual(p[0], p[1]);
- if (p[0] == 11)
- _timerHack++;
- break;
- case 0x02:
- ec = testEqual(p[0], getvar(p[1]));
- if (p[0] == 11 || p[1] == 11)
- _timerHack++;
- break;
- case 0x03:
- ec = testLess(p[0], p[1]);
- if (p[0] == 11)
- _timerHack++;
- break;
- case 0x04:
- ec = testLess(p[0], getvar(p[1]));
- if (p[0] == 11 || p[1] == 11)
- _timerHack++;
- break;
- case 0x05:
- ec = testGreater(p[0], p[1]);
- if (p[0] == 11)
- _timerHack++;
- break;
- case 0x06:
- ec = testGreater(p[0], getvar(p[1]));
- if (p[0] == 11 || p[1] == 11)
- _timerHack++;
- break;
- case 0x07:
- ec = testIsSet(p[0]);
- break;
- case 0x08:
- ec = testIsSet(getvar(p[0]));
- break;
- case 0x09:
- ec = testHas(p[0]);
- break;
- case 0x0A:
- ec = testObjInRoom(p[0], p[1]);
- break;
- case 0x0B:
- ec = testPosn(p[0], p[1], p[2], p[3], p[4]);
- break;
- case 0x0C:
- ec = testController(p[0]);
- break;
- case 0x0D:
- ec = testKeypressed();
- break;
- case 0x0E:
- ec = testSaid(p[0], (uint8 *) code + (ip + 1));
- ip = lastIp;
- ip++; // skip opcode
- ip += p[0] * 2; // skip num_words * 2
- ip++; // skip num_words opcode
- break;
- case 0x0F:
- debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", _game.strings[p[0]], _game.strings[p[1]]);
- ec = testCompareStrings(p[0], p[1]);
- break;
- case 0x10:
- ec = testObjInBox(p[0], p[1], p[2], p[3], p[4]);
- break;
- case 0x11:
- 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]);
- break;
- case 0x13: // Unknown test command 19
- // My current theory is that this command checks whether the ego is currently moving
- // and that that movement has been caused using the mouse and not using the keyboard.
- // I base this theory on the game's behavior on an Amiga emulator, not on disassembly.
- // This command is used at least in the Amiga version of Gold Rush! v2.05 1989-03-09
- // (AGI 2.316) in logics 1, 3, 5, 6, 137 and 192 (Logic.192 revealed this command's nature).
- // TODO: Check this command's implementation using disassembly just to be sure.
- ec = _game.viewTable[0].flags & ADJ_EGO_XY;
- debugC(7, kDebugLevelScripts, "op_test: in.motion.using.mouse = %s (Amiga-specific testcase 19)", ec ? "true" : "false");
- break;
+ case 0xFF:
+ endTest = true;
+ continue;
+
default:
- ec = false;
- end_test = true;
- }
-
- if (!end_test) {
- if (op <= 0x12)
- ip += logicNamesTest[op].numArgs;
-
- // exchange ec value
- if (notTest)
- ec = !ec;
-
- // not is only enabled for 1 test command
- notTest = false;
-
- if (orTest && ec) {
- // a true inside an OR statement passes
- // ENTIRE statement scan for end of OR
-
- // CM: test for opcode < 0xfc changed from 'op' to
- // '*(code+ip)', to avoid problem with the 0xfd (NOT)
- // opcode byte. Changed a bad ip += ... ip++ construct.
- // This should fix the crash with Larry's logic.0 code:
- //
- // if ((isset(4) ||
- // !isset(2) ||
- // v30 == 2 ||
- // v30 == 1)) {
- // goto Label1;
- // }
- //
- // The bytecode is:
- // ff fc 07 04 fd 07 02 01 1e 02 01 1e 01 fc ff
-
- // find end of OR
- while (*(code + ip) != 0xFC) {
- if (*(code + ip) == 0x0E) { // said
- ip++;
-
- // cover count + ^words
- ip += 1 + ((*(code + ip)) * 2);
- continue;
- }
-
- if (*(code + ip) < 0xFC)
- ip += logicNamesTest[*(code + ip)].numArgs;
- ip++;
+ // Evaluate the command and skip the rest of the instruction
+ _agiCondCommands[op](state, p);
+ skipInstruction(op);
+
+ // NOT mode is enabled only for one instruction
+ if (notMode)
+ state->testResult = !state->testResult;
+ notMode = false;
+
+ if (orMode) {
+ if (state->testResult) {
+ // We are in OR mode and the last test command evaluated
+ // as true, thus the whole OR expression evaluates as
+ // true. So skip the rest of the OR expression and
+ // continue normally.
+ skipInstructionsUntil(0xFC);
+ orMode = false;
+ continue;
}
- ip++;
-
- orTest = false;
- retval = true;
} else {
- retval = orTest ? retval || ec : retval && ec;
+ result &= state->testResult;
+ if (!result) {
+ // Since we are in AND mode and the last test command
+ // evaluated as false, the whole expression also evaluates
+ // as false. So skip until the ending 0xFF and return.
+ skipInstructionsUntil(0xFF);
+ endTest = true;
+ continue;
+ }
}
+ break;
}
}
- // if false, scan for end of IP?
- if (retval)
+ // Skip the following IF block if the condition evaluates as false
+ if (result)
ip += 2;
- else {
- ip = lastIp;
- while (*(code + ip) != 0xff) {
- if (*(code + ip) == 0x0e) {
- ip++;
- ip += (*(code + ip)) * 2 + 1;
- } else if (*(code + ip) < 0xfc) {
- ip += logicNamesTest[*(code + ip)].numArgs;
- ip++;
- } else {
- ip++;
- }
- }
- ip++; // skip over 0xFF
+ else
ip += READ_LE_UINT16(code + ip) + 2;
- }
if (_debug.enabled && (_debug.logic0 || lognum))
- debugConsole(lognum, 0xFF, retval ? "=true" : "=false");
+ debugConsole(lognum, 0xFF, result ? "=true" : "=false");
+
+ return result;
+}
- return retval;
+void AgiEngine::skipInstruction(byte op) {
+ AgiGame *state = &_game;
+ if (op >= 0xFC)
+ return;
+ if (op == 0x0E && state->_vm->getVersion() >= 0x2000) // said
+ ip += *(code + ip) * 2 + 1;
+ else
+ ip += logicNamesTest[op].argumentsLength();
+}
+
+void AgiEngine::skipInstructionsUntil(byte v) {
+ AgiGame *state = &_game;
+ while (1) {
+ byte op = *(code + ip++);
+ if (op == v)
+ return;
+ skipInstruction(op);
+ }
}
} // End of namespace Agi
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
new file mode 100644
index 0000000000..c2cecefc52
--- /dev/null
+++ b/engines/agi/opcodes.cpp
@@ -0,0 +1,381 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "agi/agi.h"
+#include "agi/opcodes.h"
+
+namespace Agi {
+
+AgiInstruction *logicNamesTest;
+AgiInstruction *logicNamesCmd;
+
+AgiInstruction insV1Test[] = {
+ { "", "", &condUnknown }, // 00
+ { "equaln", "vn", &condEqual }, // 01
+ { "equalv", "vv", &condEqualV }, // 02
+ { "lessn", "vn", &condLess }, // 03
+ { "lessv", "vv", &condLessV }, // 04
+ { "greatern", "vn", &condGreater }, // 05
+ { "greaterv", "vv", &condGreaterV }, // 06
+ { "isset", "v", &condIsSetV1 }, // 07
+ { "has", "n", &condHasV1 }, // 08
+ { "said", "nnnn", &condSaid2 }, // 09
+ { "posn", "nnnnn", &condPosn }, // 0A
+ { "controller", "n", &condController }, // 0B
+ { "obj.in.room", "nv", &condObjInRoom }, // 0C
+ { "said", "nnnnnn", &condSaid3 }, // 0D
+ { "have.key", "", &condHaveKey }, // 0E
+ { "said", "nn", &condSaid1 }, // 0F
+ { "bit", "nv", &condBit }, // 10
+};
+
+AgiInstruction insV1[] = {
+ { "return", "", NULL }, // 00
+ { "increment", "v", &cmdIncrement }, // 01
+ { "decrement", "v", &cmdDecrement }, // 02
+ { "assignn", "vn", &cmdAssignN }, // 03
+ { "assignv", "vv", &cmdAssignV }, // 04
+ { "addn", "vn", &cmdAddN }, // 05
+ { "addv", "vv", &cmdAddV }, // 06
+ { "subn", "vn", &cmdSubN }, // 07
+ { "subv", "vv", &cmdSubV }, // 08
+ { "load.view", "n", &cmdLoadView }, // 09
+ { "animate.obj", "n", &cmdAnimateObj }, // 0A
+ { "new.room", "n", &cmdNewRoomV1 }, // 0B
+ { "draw.pic", "v", &cmdDrawPicV1 }, // 0C
+ { "print", "s", &cmdPrint }, // 0D TODO
+ { "status", "", &cmdStatus }, // 0E TODO
+ { "save.game", "", &cmdSaveGame }, // 0F TODO
+ { "restore.game", "", &cmdLoadGame }, // 10 TODO
+ { "init.disk", "", &cmdInitDisk }, // 11 TODO
+ { "restart.game", "", &cmdRestartGame }, // 12 TODO
+ { "random", "v", &cmdRandomV1 }, // 13
+ { "get", "n", &cmdGetV1 }, // 14
+ { "drop", "n", &cmdDrop }, // 15
+ { "draw", "n", &cmdDraw }, // 16 TODO
+ { "erase", "n", &cmdErase }, // 17 TODO
+ { "position", "nnn", &cmdPositionV1 }, // 18
+ { "position.v", "nvv", &cmdPositionFV1 }, // 19
+ { "get.posn", "nvv", &cmdGetPosn }, // 1A
+ { "set.cel", "nn", &cmdSetCel }, // 1B
+ { "set.loop", "nn", &cmdSetLoop }, // 1C
+ { "end.of.loop", "nn", &cmdEndOfLoopV1 }, // 1D
+ { "reverse.loop", "nn", &cmdReverseLoopV1 }, // 1E
+ { "move.obj", "nnnnn", &cmdMoveObj }, // 1F
+ { "set.view", "nn", &cmdSetView }, // 20
+ { "follow.ego", "nnn", &cmdFollowEgo }, // 21
+ { "block", "", &cmdBlock }, // 22
+ { "unblock", "", &cmdUnblock }, // 23
+ { "ignore.blocks", "n", &cmdIgnoreBlocks }, // 24
+ { "observe.blocks", "n", &cmdObserveBlocks }, // 25
+ { "wander", "n", &cmdWander }, // 26
+ { "reposition", "nvv", &cmdRepositionV1 }, // 27
+ { "stop.motion", "n", &cmdStopMotionV1 }, // 28
+ { "start.motion", "n", &cmdStartMotionV1 }, // 29
+ { "stop.cycling", "n", &cmdStopCycling }, // 2A
+ { "start.cycling", "n", &cmdStartCycling }, // 2B
+ { "stop.update", "n", &cmdStopUpdate }, // 2C
+ { "start.update", "n", &cmdStartUpdate }, // 2D
+ { "program.control", "", &cmdProgramControl }, // 2E
+ { "player.control", "", &cmdPlayerControl }, // 2F
+ { "set.priority", "nn", &cmdSetPriority }, // 30
+ { "release.priority", "n", &cmdReleasePriority }, // 31
+ { "add.to.pic", "nnnnnn", &cmdAddToPicV1 }, // 32
+ { "set.horizon", "n", &cmdSetHorizon }, // 33
+ { "ignore.horizon", "n", &cmdIgnoreHorizon }, // 34
+ { "observe.horizon", "n", &cmdObserveHorizon }, // 35
+ { "load.logics", "n", &cmdLoadLogic }, // 36 TODO
+ { "object.on.water", "n", &cmdObjectOnWater }, // 37
+ { "load.pic", "v", &cmdLoadPicV1 }, // 38
+ { "load.sound", "n", &cmdLoadSound }, // 39
+ { "sound", "nn", &cmdSound }, // 3A
+ { "stop.sound", "", &cmdStopSound }, // 3B
+ { "set.v", "v", &cmdSetV }, // 3C
+ { "reset.v", "v", &cmdResetV }, // 3D
+ { "toggle.v", "v", &cmdToggleV }, // 3E
+ { "new.room.v", "v", &cmdNewRoomVV1 }, // 3F TODO
+ { "call", "n", &cmdCallV1 }, // 40 TODO
+ { "quit", "", &cmdQuitV1 }, // 41
+ { "set.speed", "v", &cmdSetSpeed }, // 42
+ { "move.obj.v", "nvvvv", &cmdMoveObjF }, // 43
+ { "...", "nn", &cmdUnknown }, // 44
+ { "get.v", "v", &cmdUnknown }, // 45
+ { "assign.v", "vv", &cmdUnknown }, // 46
+ { "...", "n", &cmdUnknown }, // 47 # printvar.v
+ { "get.priority", "nv", &cmdGetPriority }, // 48
+ { "ignore.objs", "n", &cmdIgnoreObjs }, // 49
+ { "observe.objs", "n", &cmdObserveObjs }, // 4A
+ { "distance", "nnv", &cmdDistance }, // 4B
+ { "object.on.land", "n", &cmdObjectOnLand }, // 4C
+ { "...", "nv", &cmdUnknown }, // 4D # set.priority.f
+ { "...", "", &cmdUnknown }, // 4E # show.obj
+ { "load.logics", "n", &cmdLoadLogic }, // 4F # load.global.logics
+ { "display", "nnns", &cmdDisplay }, // 50 TODO: 4 vs 3 args
+ { "prevent.input???", "", &cmdUnknown }, // 51
+ { "...", "", &cmdUnknown }, // 52 # nop
+ { "...", "n", &cmdUnknown }, // 53 # text.screen
+ { "...", "", &cmdUnknown }, // 54 ???
+ { "stop.motion", "", &cmdStopMotion }, // 55 or force.update??
+ { "discard.view", "n", &cmdDiscardView }, // 56
+ { "discard.pic", "v", &cmdDiscardPic }, // 57
+ { "set.item.view", "nn", &cmdSetItemView }, // 58
+ { "...", "", &cmdUnknown }, // 59 # reverse.cycle
+ { "last.cel", "nv", &cmdLastCel }, // 5A
+ { "set.cel.v", "nv", &cmdSetCelF }, // 5B
+ { "...", "", &cmdUnknown }, // 5C # normal.cycle
+ { "load.view", "n", &cmdLoadView }, // 5D
+ { "...", "", &cmdUnknown }, // 5E
+ { "...", "", &cmdUnknown }, // 5F
+ { "setbit", "nv", &cmdUnknown }, // 60
+ { "...", "nv", &cmdUnknown }, // 61 # clearbit
+};
+
+AgiInstruction insV2Test[] = {
+ { "", "", &condUnknown }, // 00
+ { "equaln", "vn", &condEqual }, // 01
+ { "equalv", "vv", &condEqualV }, // 02
+ { "lessn", "vn", &condLess }, // 03
+ { "lessv", "vv", &condLessV }, // 04
+ { "greatern", "vn", &condGreater }, // 05
+ { "greaterv", "vv", &condGreaterV }, // 06
+ { "isset", "n", &condIsSet }, // 07
+ { "issetv", "v", &condIsSetV }, // 08
+ { "has", "n", &condHas }, // 09
+ { "obj.in.room", "nv", &condObjInRoom}, // 0A
+ { "posn", "nnnnn", &condPosn }, // 0B
+ { "controller", "n", &condController }, // 0C
+ { "have.key", "", &condHaveKey}, // 0D
+ { "said", "", &condSaid }, // 0E
+ { "compare.strings", "ss", &condCompareStrings }, // 0F
+ { "obj.in.box", "nnnnn", &condObjInBox }, // 10
+ { "center.posn", "nnnnn", &condCenterPosn }, // 11
+ { "right.posn", "nnnnn", &condRightPosn }, // 12
+ { "in.motion.using.mouse", "", &condUnknown13 } // 13
+};
+
+AgiInstruction insV2[] = {
+ { "return", "", NULL },
+ { "increment", "v", &cmdIncrement },
+ { "decrement", "v", &cmdDecrement },
+ { "assignn", "vn", &cmdAssignN },
+ { "assignv", "vv", &cmdAssignV },
+ { "addn", "vn", &cmdAddN },
+ { "addv", "vv", &cmdAddV },
+ { "subn", "vn", &cmdSubN },
+ { "subv", "vv", &cmdSubV },
+ { "lindirectv", "vv", &cmdLindirectV },
+ { "lindirect", "vv", &cmdRindirect },
+ { "lindirectn", "vn", &cmdLindirectN },
+ { "set", "n", &cmdSet },
+ { "reset", "n", &cmdReset },
+ { "toggle", "n", &cmdToggle },
+ { "set.v", "v", &cmdSetV },
+ { "reset.v", "v", &cmdResetV },
+ { "toggle.v", "v", &cmdToggleV },
+ { "new.room", "n", &cmdNewRoom },
+ { "new.room.v", "v", &cmdNewRoomF },
+ { "load.logics", "n", &cmdLoadLogic },
+ { "load.logics.v", "v", &cmdLoadLogicF },
+ { "call", "n", &cmdCall },
+ { "call.v", "v", &cmdCallF },
+ { "load.pic", "v", &cmdLoadPic },
+ { "draw.pic", "v", &cmdDrawPic },
+ { "show.pic", "", &cmdShowPic },
+ { "discard.pic", "v", &cmdDiscardPic },
+ { "overlay.pic", "v", &cmdOverlayPic },
+ { "show.pri.screen", "", &cmdShowPriScreen },
+ { "load.view", "n", &cmdLoadView },
+ { "load.view.v", "v", &cmdLoadViewF },
+ { "discard.view", "n", &cmdDiscardView },
+ { "animate.obj", "n", &cmdAnimateObj },
+ { "unanimate.all", "", &cmdUnanimateAll },
+ { "draw", "n", &cmdDraw },
+ { "erase", "n", &cmdErase },
+ { "position", "nnn", &cmdPosition },
+ { "position.v", "nvv", &cmdPositionF },
+ { "get.posn", "nvv", &cmdGetPosn },
+ { "reposition", "nvv", &cmdReposition },
+ { "set.view", "nn", &cmdSetView },
+ { "set.view.v", "nv", &cmdSetViewF },
+ { "set.loop", "nn", &cmdSetLoop },
+ { "set.loop.v", "nv", &cmdSetLoopF },
+ { "fix.loop", "n", &cmdFixLoop },
+ { "release.loop", "n", &cmdReleaseLoop },
+ { "set.cel", "nn", &cmdSetCel },
+ { "set.cel.v", "nv", &cmdSetCelF },
+ { "last.cel", "nv", &cmdLastCel },
+ { "current.cel", "nv", &cmdCurrentCel },
+ { "current.loop", "nv", &cmdCurrentLoop },
+ { "current.view", "nv", &cmdCurrentView },
+ { "number.of.loops", "nv", &cmdNumberOfLoops },
+ { "set.priority", "nn", &cmdSetPriority },
+ { "set.priority.v", "nv", &cmdSetPriorityF },
+ { "release.priority", "n", &cmdReleasePriority },
+ { "get.priority", "nn", &cmdGetPriority },
+ { "stop.update", "n", &cmdStopUpdate },
+ { "start.update", "n", &cmdStartUpdate },
+ { "force.update", "n", &cmdForceUpdate },
+ { "ignore.horizon", "n", &cmdIgnoreHorizon },
+ { "observe.horizon", "n", &cmdObserveHorizon },
+ { "set.horizon", "n", &cmdSetHorizon },
+ { "object.on.water", "n", &cmdObjectOnWater },
+ { "object.on.land", "n", &cmdObjectOnLand },
+ { "object.on.anything", "n", &cmdObjectOnAnything },
+ { "ignore.objs", "n", &cmdIgnoreObjs },
+ { "observe.objs", "n", &cmdObserveObjs },
+ { "distance", "nnv", &cmdDistance },
+ { "stop.cycling", "n", &cmdStopCycling },
+ { "start.cycling", "n", &cmdStartCycling },
+ { "normal.cycle", "n", &cmdNormalCycle },
+ { "end.of.loop", "nn", &cmdEndOfLoop },
+ { "reverse.cycle", "n", &cmdReverseCycle },
+ { "reverse.loop", "nn", &cmdReverseLoop },
+ { "cycle.time", "nv", &cmdCycleTime },
+ { "stop.motion", "n", &cmdStopMotion },
+ { "start.motion", "n", &cmdStartMotion },
+ { "step.size", "nv", &cmdStepSize },
+ { "step.time", "nv", &cmdStepTime },
+ { "move.obj", "nnnnn", &cmdMoveObj },
+ { "move.obj.v", "nvvvv", &cmdMoveObjF },
+ { "follow.ego", "nnn", &cmdFollowEgo },
+ { "wander", "n", &cmdWander },
+ { "normal.motion", "n", &cmdNormalMotion },
+ { "set.dir", "nv", &cmdSetDir },
+ { "get.dir", "nv", &cmdGetDir },
+ { "ignore.blocks", "n", &cmdIgnoreBlocks },
+ { "observe.blocks", "n", &cmdObserveBlocks },
+ { "block", "nnnn", &cmdBlock },
+ { "unblock", "", &cmdUnblock },
+ { "get", "n", &cmdGet },
+ { "get.v", "v", &cmdGetF },
+ { "drop", "n", &cmdDrop },
+ { "put", "nn", &cmdPut },
+ { "put.v", "vv", &cmdPutF },
+ { "get.room.v", "vv", &cmdGetRoomF },
+ { "load.sound", "n", &cmdLoadSound },
+ { "sound", "nn", &cmdSound },
+ { "stop.sound", "", &cmdStopSound },
+ { "print", "s", &cmdPrint },
+ { "print.v", "v", &cmdPrintF },
+ { "display", "nns", &cmdDisplay },
+ { "display.v", "vvv", &cmdDisplayF },
+ { "clear.lines", "nns", &cmdClearLines },
+ { "text.screen", "", &cmdTextScreen },
+ { "graphics", "", &cmdGraphics },
+ { "set.cursor.char", "s", &cmdSetCursorChar },
+ { "set.text.attribute", "nn", &cmdSetTextAttribute },
+ { "shake.screen", "n", &cmdShakeScreen },
+ { "configure.screen", "nnn", &cmdConfigureScreen },
+ { "status.line.on", "", &cmdStatusLineOn },
+ { "status.line.off", "", &cmdStatusLineOff },
+ { "set.string", "ns", &cmdSetString },
+ { "get.string", "ns", &cmdGetString },
+ { "word.to.string", "nn", &cmdWordToString },
+ { "parse", "n", &cmdParse },
+ { "get.num", "nv", &cmdGetNum },
+ { "prevent.input", "", &cmdPreventInput },
+ { "accept.input", "", &cmdAcceptInput },
+ { "set.key", "nnn", &cmdSetKey },
+ { "add.to.pic", "nnnnnnn", &cmdAddToPic },
+ { "add.to.pic.v", "vvvvvvv", &cmdAddToPicF },
+ { "status", "", &cmdStatus },
+ { "save.game", "", &cmdSaveGame },
+ { "restore.game", "", &cmdLoadGame },
+ { "init.disk", "", &cmdInitDisk },
+ { "restart.game", "", &cmdRestartGame },
+ { "show.obj", "n", &cmdShowObj },
+ { "random", "nnv", &cmdRandom },
+ { "program.control", "", &cmdProgramControl },
+ { "player.control", "", &cmdPlayerControl },
+ { "obj.status.v", "v", &cmdObjStatusF },
+ { "quit", "n", &cmdQuit },
+ { "show.mem", "", &cmdShowMem },
+ { "pause", "", &cmdPause },
+ { "echo.line", "", &cmdEchoLine },
+ { "cancel.line", "", &cmdCancelLine },
+ { "init.joy", "", &cmdInitJoy },
+ { "toggle.monitor", "", &cmdToggleMonitor },
+ { "version", "", &cmdVersion },
+ { "script.size", "n", &cmdScriptSize },
+ { "set.game.id", "s", &cmdSetGameID },
+ { "log", "s", &cmdLog },
+ { "set.scan.start", "", &cmdSetScanStart },
+ { "reset.scan.start", "", &cmdResetScanStart },
+ { "reposition.to", "nnn", &cmdRepositionTo },
+ { "reposition.to.v", "nvv", &cmdRepositionToF },
+ { "trace.on", "", &cmdTraceOn },
+ { "trace.info", "nnn", &cmdTraceInfo },
+ { "print.at", "snnn", &cmdPrintAt },
+ { "print.at.v", "vnnn", &cmdPrintAtV },
+ { "discard.view.v", "v", &cmdDiscardView},
+ { "clear.text.rect", "nnnnn", &cmdClearTextRect },
+ { "set.upper.left", "nn", &cmdSetUpperLeft },
+ { "set.menu", "s", &cmdSetMenu },
+ { "set.menu.member", "sn", &cmdSetMenuItem },
+ { "submit.menu", "", &cmdSubmitMenu },
+ { "enable.member", "n", &cmdEnableItem },
+ { "disable.member", "n", &cmdDisableItem },
+ { "menu.input", "", &cmdMenuInput },
+ { "show.obj.v", "v", &cmdShowObjV },
+ { "open.dialogue", "", &cmdOpenDialogue },
+ { "close.dialogue", "", &cmdCloseDialogue },
+ { "mul.n", "vn", &cmdMulN },
+ { "mul.v", "vv", &cmdMulV },
+ { "div.n", "vn", &cmdDivN },
+ { "div.v", "vv", &cmdDivV },
+ { "close.window", "", &cmdCloseWindow },
+ { "set.simple", "n", &cmdSetSimple },
+ { "push.script", "", &cmdPushScript },
+ { "pop.script", "", &cmdPopScript },
+ { "hold.key", "", &cmdHoldKey },
+ { "set.pri.base", "n", &cmdSetPriBase },
+ { "discard.sound", "n", &cmdDiscardSound },
+ { "hide.mouse", "", &cmdHideMouse },
+ { "allow.menu", "n", &cmdAllowMenu },
+ { "show.mouse", "", &cmdShowMouse },
+ { "fence.mouse", "nnnn", &cmdFenceMouse },
+ { "mouse.posn", "vv", &cmdMousePosn },
+ { "release.key", "", &cmdReleaseKey },
+ { "adj.ego.move.to.xy", "", &cmdAdjEgoMoveToXY }
+};
+
+void AgiEngine::setupOpcodes() {
+ if (getVersion() >= 0x2000) {
+ for (int i = 0; i <= ARRAYSIZE(insV2Test); ++i)
+ _agiCondCommands[i] = insV2Test[i].func;
+ for (int i = 0; i < ARRAYSIZE(insV2); ++i)
+ _agiCommands[i] = insV2[i].func;
+
+ logicNamesTest = insV2Test;
+ logicNamesCmd = insV2;
+ } else {
+ for (int i = 0; i <= ARRAYSIZE(insV1Test); ++i)
+ _agiCondCommands[i] = insV1Test[i].func;
+ for (int i = 0; i < ARRAYSIZE(insV1); ++i)
+ _agiCommands[i] = insV1[i].func;
+
+ logicNamesTest = insV1Test;
+ logicNamesCmd = insV1;
+ }
+}
+
+}
diff --git a/engines/agi/opcodes.h b/engines/agi/opcodes.h
index b0d2051f0b..7f0f287550 100644
--- a/engines/agi/opcodes.h
+++ b/engines/agi/opcodes.h
@@ -23,17 +23,251 @@
#ifndef AGI_OPCODES_H
#define AGI_OPCODES_H
+#include <string.h>
+
namespace Agi {
-struct AgiLogicnames {
+struct AgiInstruction {
const char *name;
- uint16 numArgs;
- uint16 argMask;
+ const char *args;
+ AgiCommand func;
+
+ int argumentsLength() { return strlen(args); }
};
-extern AgiLogicnames logicNamesTest[];
-extern AgiLogicnames logicNamesCmd[];
-extern AgiLogicnames logicNamesIf[];
+extern AgiInstruction *logicNamesTest;
+extern AgiInstruction *logicNamesCmd;
+
+void cmdIncrement(AgiGame *state, uint8 *p);
+void cmdDecrement(AgiGame *state, uint8 *p);
+void cmdAssignN(AgiGame *state, uint8 *p);
+void cmdAssignV(AgiGame *state, uint8 *p);
+void cmdAddN(AgiGame *state, uint8 *p);
+void cmdAddV(AgiGame *state, uint8 *p);
+void cmdSubN(AgiGame *state, uint8 *p);
+void cmdSubV(AgiGame *state, uint8 *p); // 0x08
+void cmdLindirectV(AgiGame *state, uint8 *p);
+void cmdRindirect(AgiGame *state, uint8 *p);
+void cmdLindirectN(AgiGame *state, uint8 *p);
+void cmdSet(AgiGame *state, uint8 *p);
+void cmdReset(AgiGame *state, uint8 *p);
+void cmdToggle(AgiGame *state, uint8 *p);
+void cmdSetV(AgiGame *state, uint8 *p);
+void cmdResetV(AgiGame *state, uint8 *p); // 0x10
+void cmdToggleV(AgiGame *state, uint8 *p);
+void cmdNewRoom(AgiGame *state, uint8 *p);
+void cmdNewRoomF(AgiGame *state, uint8 *p);
+void cmdLoadLogic(AgiGame *state, uint8 *p);
+void cmdLoadLogicF(AgiGame *state, uint8 *p);
+void cmdCall(AgiGame *state, uint8 *p);
+void cmdCallF(AgiGame *state, uint8 *p);
+void cmdLoadPic(AgiGame *state, uint8 *p); // 0x18
+void cmdLoadPicV1(AgiGame *state, uint8 *p);
+void cmdDrawPic(AgiGame *state, uint8 *p);
+void cmdDrawPicV1(AgiGame *state, uint8 *p);
+void cmdShowPic(AgiGame *state, uint8 *p);
+void cmdDiscardPic(AgiGame *state, uint8 *p);
+void cmdOverlayPic(AgiGame *state, uint8 *p);
+void cmdShowPriScreen(AgiGame *state, uint8 *p);
+void cmdLoadView(AgiGame *state, uint8 *p);
+void cmdLoadViewF(AgiGame *state, uint8 *p);
+void cmdDiscardView(AgiGame *state, uint8 *p); // 0x20
+void cmdAnimateObj(AgiGame *state, uint8 *p);
+void cmdUnanimateAll(AgiGame *state, uint8 *p);
+void cmdDraw(AgiGame *state, uint8 *p);
+void cmdErase(AgiGame *state, uint8 *p);
+void cmdPosition(AgiGame *state, uint8 *p);
+void cmdPositionV1(AgiGame *state, uint8 *p);
+void cmdPositionF(AgiGame *state, uint8 *p);
+void cmdPositionFV1(AgiGame *state, uint8 *p);
+void cmdGetPosn(AgiGame *state, uint8 *p);
+void cmdReposition(AgiGame *state, uint8 *p); // 0x28
+void cmdRepositionV1(AgiGame *state, uint8 *p); // 0x28
+void cmdSetView(AgiGame *state, uint8 *p);
+void cmdSetViewF(AgiGame *state, uint8 *p);
+void cmdSetLoop(AgiGame *state, uint8 *p);
+void cmdSetLoopF(AgiGame *state, uint8 *p);
+void cmdFixLoop(AgiGame *state, uint8 *p);
+void cmdReleaseLoop(AgiGame *state, uint8 *p);
+void cmdSetCel(AgiGame *state, uint8 *p);
+void cmdSetCelF(AgiGame *state, uint8 *p); // 0x30
+void cmdLastCel(AgiGame *state, uint8 *p);
+void cmdCurrentCel(AgiGame *state, uint8 *p);
+void cmdCurrentLoop(AgiGame *state, uint8 *p);
+void cmdCurrentView(AgiGame *state, uint8 *p);
+void cmdNumberOfLoops(AgiGame *state, uint8 *p);
+void cmdSetPriority(AgiGame *state, uint8 *p);
+void cmdSetPriorityF(AgiGame *state, uint8 *p);
+void cmdReleasePriority(AgiGame *state, uint8 *p); // 0x38
+void cmdGetPriority(AgiGame *state, uint8 *p);
+void cmdStopUpdate(AgiGame *state, uint8 *p);
+void cmdStartUpdate(AgiGame *state, uint8 *p);
+void cmdForceUpdate(AgiGame *state, uint8 *p);
+void cmdIgnoreHorizon(AgiGame *state, uint8 *p);
+void cmdObserveHorizon(AgiGame *state, uint8 *p);
+void cmdSetHorizon(AgiGame *state, uint8 *p);
+void cmdObjectOnWater(AgiGame *state, uint8 *p); // 0x40
+void cmdObjectOnLand(AgiGame *state, uint8 *p);
+void cmdObjectOnAnything(AgiGame *state, uint8 *p);
+void cmdIgnoreObjs(AgiGame *state, uint8 *p);
+void cmdObserveObjs(AgiGame *state, uint8 *p);
+void cmdDistance(AgiGame *state, uint8 *p);
+void cmdStopCycling(AgiGame *state, uint8 *p);
+void cmdStartCycling(AgiGame *state, uint8 *p);
+void cmdNormalCycle(AgiGame *state, uint8 *p); // 0x48
+void cmdEndOfLoop(AgiGame *state, uint8 *p);
+void cmdEndOfLoopV1(AgiGame *state, uint8 *p);
+void cmdReverseCycle(AgiGame *state, uint8 *p);
+void cmdReverseLoop(AgiGame *state, uint8 *p);
+void cmdReverseLoopV1(AgiGame *state, uint8 *p);
+void cmdCycleTime(AgiGame *state, uint8 *p);
+void cmdStopMotion(AgiGame *state, uint8 *p);
+void cmdStopMotionV1(AgiGame *state, uint8 *p);
+void cmdStartMotion(AgiGame *state, uint8 *p);
+void cmdStartMotionV1(AgiGame *state, uint8 *p);
+void cmdStepSize(AgiGame *state, uint8 *p);
+void cmdStepTime(AgiGame *state, uint8 *p); // 0x50
+void cmdMoveObj(AgiGame *state, uint8 *p);
+void cmdMoveObjF(AgiGame *state, uint8 *p);
+void cmdFollowEgo(AgiGame *state, uint8 *p);
+void cmdWander(AgiGame *state, uint8 *p);
+void cmdNormalMotion(AgiGame *state, uint8 *p);
+void cmdSetDir(AgiGame *state, uint8 *p);
+void cmdGetDir(AgiGame *state, uint8 *p);
+void cmdIgnoreBlocks(AgiGame *state, uint8 *p); // 0x58
+void cmdObserveBlocks(AgiGame *state, uint8 *p);
+void cmdBlock(AgiGame *state, uint8 *p);
+void cmdUnblock(AgiGame *state, uint8 *p);
+void cmdGet(AgiGame *state, uint8 *p);
+void cmdGetV1(AgiGame *state, uint8 *p);
+void cmdGetF(AgiGame *state, uint8 *p);
+void cmdDrop(AgiGame *state, uint8 *p);
+void cmdPut(AgiGame *state, uint8 *p);
+void cmdPutF(AgiGame *state, uint8 *p); // 0x60
+void cmdGetRoomF(AgiGame *state, uint8 *p);
+void cmdLoadSound(AgiGame *state, uint8 *p);
+void cmdSound(AgiGame *state, uint8 *p);
+void cmdStopSound(AgiGame *state, uint8 *p);
+void cmdPrint(AgiGame *state, uint8 *p);
+void cmdPrintF(AgiGame *state, uint8 *p);
+void cmdDisplay(AgiGame *state, uint8 *p);
+void cmdDisplayF(AgiGame *state, uint8 *p); // 0x68
+void cmdClearLines(AgiGame *state, uint8 *p);
+void cmdTextScreen(AgiGame *state, uint8 *p);
+void cmdGraphics(AgiGame *state, uint8 *p);
+void cmdSetCursorChar(AgiGame *state, uint8 *p);
+void cmdSetTextAttribute(AgiGame *state, uint8 *p);
+void cmdShakeScreen(AgiGame *state, uint8 *p);
+void cmdConfigureScreen(AgiGame *state, uint8 *p);
+void cmdStatusLineOn(AgiGame *state, uint8 *p); // 0x70
+void cmdStatusLineOff(AgiGame *state, uint8 *p);
+void cmdSetString(AgiGame *state, uint8 *p);
+void cmdGetString(AgiGame *state, uint8 *p);
+void cmdWordToString(AgiGame *state, uint8 *p);
+void cmdParse(AgiGame *state, uint8 *p);
+void cmdGetNum(AgiGame *state, uint8 *p);
+void cmdPreventInput(AgiGame *state, uint8 *p);
+void cmdAcceptInput(AgiGame *state, uint8 *p); // 0x78
+void cmdSetKey(AgiGame *state, uint8 *p);
+void cmdAddToPic(AgiGame *state, uint8 *p);
+void cmdAddToPicV1(AgiGame *state, uint8 *p);
+void cmdAddToPicF(AgiGame *state, uint8 *p);
+void cmdStatus(AgiGame *state, uint8 *p);
+void cmdSaveGame(AgiGame *state, uint8 *p);
+void cmdLoadGame(AgiGame *state, uint8 *p);
+void cmdInitDisk(AgiGame *state, uint8 *p);
+void cmdRestartGame(AgiGame *state, uint8 *p); // 0x80
+void cmdShowObj(AgiGame *state, uint8 *p);
+void cmdRandom(AgiGame *state, uint8 *p);
+void cmdRandomV1(AgiGame *state, uint8 *p);
+void cmdProgramControl(AgiGame *state, uint8 *p);
+void cmdPlayerControl(AgiGame *state, uint8 *p);
+void cmdObjStatusF(AgiGame *state, uint8 *p);
+void cmdQuit(AgiGame *state, uint8 *p);
+void cmdQuitV1(AgiGame *state, uint8 *p);
+void cmdShowMem(AgiGame *state, uint8 *p);
+void cmdPause(AgiGame *state, uint8 *p); // 0x88
+void cmdEchoLine(AgiGame *state, uint8 *p);
+void cmdCancelLine(AgiGame *state, uint8 *p);
+void cmdInitJoy(AgiGame *state, uint8 *p);
+void cmdToggleMonitor(AgiGame *state, uint8 *p);
+void cmdVersion(AgiGame *state, uint8 *p);
+void cmdScriptSize(AgiGame *state, uint8 *p);
+void cmdSetGameID(AgiGame *state, uint8 *p);
+void cmdLog(AgiGame *state, uint8 *p); // 0x90
+void cmdSetScanStart(AgiGame *state, uint8 *p);
+void cmdResetScanStart(AgiGame *state, uint8 *p);
+void cmdRepositionTo(AgiGame *state, uint8 *p);
+void cmdRepositionToF(AgiGame *state, uint8 *p);
+void cmdTraceOn(AgiGame *state, uint8 *p);
+void cmdTraceInfo(AgiGame *state, uint8 *p);
+void cmdPrintAt(AgiGame *state, uint8 *p);
+void cmdPrintAtV(AgiGame *state, uint8 *p); // 0x98
+//void cmdDiscardView(AgiGame *state, uint8 *p); // Opcode repeated from 0x20 ?
+void cmdClearTextRect(AgiGame *state, uint8 *p);
+void cmdSetUpperLeft(AgiGame *state, uint8 *p);
+void cmdSetMenu(AgiGame *state, uint8 *p);
+void cmdSetMenuItem(AgiGame *state, uint8 *p);
+void cmdSubmitMenu(AgiGame *state, uint8 *p);
+void cmdEnableItem(AgiGame *state, uint8 *p);
+void cmdDisableItem(AgiGame *state, uint8 *p); // 0xa0
+void cmdMenuInput(AgiGame *state, uint8 *p);
+void cmdShowObjV(AgiGame *state, uint8 *p);
+void cmdOpenDialogue(AgiGame *state, uint8 *p);
+void cmdCloseDialogue(AgiGame *state, uint8 *p);
+void cmdMulN(AgiGame *state, uint8 *p);
+void cmdMulV(AgiGame *state, uint8 *p);
+void cmdDivN(AgiGame *state, uint8 *p);
+void cmdDivV(AgiGame *state, uint8 *p); // 0xa8
+void cmdCloseWindow(AgiGame *state, uint8 *p);
+void cmdSetSimple(AgiGame *state, uint8 *p);
+void cmdPushScript(AgiGame *state, uint8 *p);
+void cmdPopScript(AgiGame *state, uint8 *p);
+void cmdHoldKey(AgiGame *state, uint8 *p);
+void cmdSetPriBase(AgiGame *state, uint8 *p);
+void cmdDiscardSound(AgiGame *state, uint8 *p);
+void cmdHideMouse(AgiGame *state, uint8 *p); // 0xb0
+void cmdAllowMenu(AgiGame *state, uint8 *p);
+void cmdShowMouse(AgiGame *state, uint8 *p);
+void cmdFenceMouse(AgiGame *state, uint8 *p);
+void cmdMousePosn(AgiGame *state, uint8 *p);
+void cmdReleaseKey(AgiGame *state, uint8 *p);
+void cmdAdjEgoMoveToXY(AgiGame *state, uint8 *p);
+
+void cmdSetSpeed(AgiGame *state, uint8 *p);
+void cmdSetItemView(AgiGame *state, uint8 *p);
+void cmdCallV1(AgiGame *state, uint8 *p);
+void cmdNewRoomV1(AgiGame *state, uint8 *p);
+void cmdNewRoomVV1(AgiGame *state, uint8 *p);
+void cmdUnknown(AgiGame *state, uint8 *p);
+
+void condEqual(AgiGame *state, uint8 *p);
+void condEqualV(AgiGame *state, uint8 *p);
+void condLess(AgiGame *state, uint8 *p);
+void condLessV(AgiGame *state, uint8 *p);
+void condGreater(AgiGame *state, uint8 *p);
+void condGreaterV(AgiGame *state, uint8 *p);
+void condIsSet(AgiGame *state, uint8 *p);
+void condIsSetV(AgiGame *state, uint8 *p);
+void condHas(AgiGame *state, uint8 *p);
+void condHasV1(AgiGame *state, uint8 *p);
+void condObjInRoom(AgiGame *state, uint8 *p);
+void condPosn(AgiGame *state, uint8 *p);
+void condController(AgiGame *state, uint8 *p);
+void condHaveKey(AgiGame *state, uint8 *p);
+void condSaid(AgiGame *state, uint8 *p);
+void condCompareStrings(AgiGame *state, uint8 *p);
+void condObjInBox(AgiGame *state, uint8 *p);
+void condCenterPosn(AgiGame *state, uint8 *p);
+void condRightPosn(AgiGame *state, uint8 *p);
+void condUnknown13(AgiGame *state, uint8 *p);
+void condUnknown(AgiGame *state, uint8 *p);
+
+void condIsSetV1(AgiGame *state, uint8 *p);
+void condSaid1(AgiGame *state, uint8 *p);
+void condSaid2(AgiGame *state, uint8 *p);
+void condSaid3(AgiGame *state, uint8 *p);
+void condBit(AgiGame *state, uint8 *p);
} // End of namespace Agi
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp
index c1a6cd33fe..34180b543f 100644
--- a/engines/agi/preagi.cpp
+++ b/engines/agi/preagi.cpp
@@ -22,18 +22,13 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
+#include "common/events.h"
#include "common/random.h"
#include "common/textconsole.h"
-#include "audio/mididrv.h"
-
#include "agi/preagi.h"
#include "agi/graphics.h"
-
-// preagi engines
-#include "agi/preagi_mickey.h"
-#include "agi/preagi_troll.h"
-#include "agi/preagi_winnie.h"
+#include "agi/keyboard.h"
namespace Agi {
@@ -59,19 +54,6 @@ PreAgiEngine::PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) :
}
void PreAgiEngine::initialize() {
- // TODO: Some sound emulation modes do not fit our current music
- // drivers, and I'm not sure what they are. For now, they might
- // as well be called "PC Speaker" and "Not PC Speaker".
-
- switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK))) {
- case MT_PCSPK:
- _soundemu = SOUND_EMU_PC;
- break;
- default:
- _soundemu = SOUND_EMU_NONE;
- break;
- }
-
if (ConfMan.hasKey("render_mode")) {
_renderMode = Common::parseRenderMode(ConfMan.get("render_mode").c_str());
} else if (ConfMan.hasKey("platform")) {
@@ -89,9 +71,7 @@ void PreAgiEngine::initialize() {
}
_gfx = new GfxMgr(this);
- //_sound = new SoundMgr(this, _mixer);
_picture = new PictureMgr(this, _gfx);
- //_sprites = new SpritesMgr(this, _gfx);
_gfx->initMachine();
@@ -111,7 +91,6 @@ void PreAgiEngine::initialize() {
_game.lineMinPrint = 0; // hardcoded
_gfx->initVideo();
- //_sound->initSound();
_speakerStream = new Audio::PCSpeaker(_mixer->getOutputRate());
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
@@ -126,8 +105,6 @@ void PreAgiEngine::initialize() {
memset(&_game.dirPic[i], 0, sizeof(struct AgiDir));
memset(&_game.dirSound[i], 0, sizeof(struct AgiDir));
}
-
- debugC(2, kDebugLevelMain, "Init sound");
}
PreAgiEngine::~PreAgiEngine() {
@@ -135,50 +112,181 @@ PreAgiEngine::~PreAgiEngine() {
delete _speakerStream;
}
+int PreAgiEngine::rnd(int hi) {
+ return (_rnd->getRandomNumber(hi - 1) + 1);
+}
+
+// Screen functions
+void PreAgiEngine::clearScreen(int attr, bool overrideDefault) {
+ if (overrideDefault)
+ _defaultColor = attr;
-Common::Error PreAgiEngine::go() {
- setflag(fSoundOn, true); // enable sound
+ _gfx->clearScreen((attr & 0xF0) / 0x10);
+}
-//
-// FIXME (Fingolfin asks): Why are Mickey, Winnie and Troll standalone classes
-// instead of being subclasses of PreAgiEngine ?
-//
+void PreAgiEngine::clearGfxScreen(int attr) {
+ _gfx->drawRectangle(0, 0, GFX_WIDTH - 1, IDI_MAX_ROW_PIC * 8 -1, (attr & 0xF0) / 0x10);
+}
- // run preagi engine main loop
- switch (getGameID()) {
- case GID_MICKEY:
- {
- Mickey *mickey = new Mickey(this);
- mickey->init();
- mickey->run();
- delete mickey;
- }
- break;
- case GID_WINNIE:
- {
- Winnie *winnie = new Winnie(this);
- winnie->init();
- winnie->run();
- delete winnie;
+// String functions
+
+void PreAgiEngine::drawStr(int row, int col, int attr, const char *buffer) {
+ int code;
+
+ if (attr == kColorDefault)
+ attr = _defaultColor;
+
+ for (int iChar = 0; iChar < (int)strlen(buffer); iChar++) {
+ code = buffer[iChar];
+
+ switch (code) {
+ case '\n':
+ case 0x8D:
+ if (++row == 200 / 8) return;
+ col = 0;
+ break;
+
+ case '|':
+ // swap attribute nibbles
+ break;
+
+ default:
+ _gfx->putTextCharacter(1, col * 8 , row * 8, static_cast<char>(code), attr & 0x0f, (attr & 0xf0) / 0x10, false, getGameID() == GID_MICKEY ? mickey_fontdata : ibm_fontdata);
+
+ if (++col == 320 / 8) {
+ col = 0;
+ if (++row == 200 / 8) return;
+ }
}
- break;
- case GID_TROLL:
- {
- Troll *troll = new Troll(this);
- troll->init();
- troll->run();
- delete troll;
+ }
+}
+
+void PreAgiEngine::drawStrMiddle(int row, int attr, const char *buffer) {
+ int col = (25 / 2) - (strlen(buffer) / 2); // 25 = 320 / 8 (maximum column)
+ drawStr(row, col, attr, buffer);
+}
+
+void PreAgiEngine::clearTextArea() {
+ int start = IDI_MAX_ROW_PIC;
+
+ if (getGameID() == GID_TROLL)
+ start = 21;
+
+ for (int row = start; row < 200 / 8; row++) {
+ clearRow(row);
+ }
+}
+
+void PreAgiEngine::clearRow(int row) {
+ drawStr(row, 0, IDA_DEFAULT, " "); // 40 spaces
+}
+
+void PreAgiEngine::printStr(const char* szMsg) {
+ clearTextArea();
+ drawStr(21, 0, IDA_DEFAULT, szMsg);
+ _gfx->doUpdate();
+ _system->updateScreen();
+}
+
+void PreAgiEngine::XOR80(char *buffer) {
+ for (size_t i = 0; i < strlen(buffer); i++)
+ if (buffer[i] & 0x80)
+ buffer[i] ^= 0x80;
+}
+
+void PreAgiEngine::printStrXOR(char *szMsg) {
+ XOR80(szMsg);
+ printStr(szMsg);
+}
+
+// Input functions
+
+int PreAgiEngine::getSelection(SelectionTypes type) {
+ Common::Event event;
+ GUI::Debugger *console = getDebugger();
+
+ while (!shouldQuit()) {
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_RTL:
+ case Common::EVENT_QUIT:
+ return 0;
+ case Common::EVENT_RBUTTONUP:
+ return 0;
+ case Common::EVENT_LBUTTONUP:
+ if (type == kSelYesNo || type == kSelAnyKey)
+ return 1;
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL) && console) {
+ console->attach();
+ console->onFrame();
+ //FIXME: If not cleared, clicking again will start the console
+ event.kbd.keycode = Common::KEYCODE_INVALID;
+ event.kbd.flags = 0;
+ continue;
+ }
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_y:
+ if (type == kSelYesNo)
+ return 1;
+ case Common::KEYCODE_n:
+ if (type == kSelYesNo)
+ return 0;
+ case Common::KEYCODE_ESCAPE:
+ if (type == kSelNumber || type == kSelAnyKey)
+ return 0;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ case Common::KEYCODE_7:
+ case Common::KEYCODE_8:
+ case Common::KEYCODE_9:
+ if (type == kSelNumber)
+ return event.kbd.keycode - Common::KEYCODE_1 + 1;
+ case Common::KEYCODE_SPACE:
+ if (type == kSelSpace)
+ return 1;
+ case Common::KEYCODE_BACKSPACE:
+ if (type == kSelBackspace)
+ return 0;
+ default:
+ if (event.kbd.flags & Common::KBD_CTRL)
+ break;
+ if (type == kSelYesNo) {
+ return 2;
+ } else if (type == kSelNumber) {
+ return 10;
+ } else if (type == kSelAnyKey || type == kSelBackspace) {
+ return 1;
+ }
+ }
+ break;
+ default:
+ break;
+ }
}
- break;
- default:
- error("Unknown preagi engine");
- break;
+ _system->updateScreen();
+ _system->delayMillis(10);
}
- return Common::kNoError;
+ return 0;
}
-int PreAgiEngine::rnd(int hi) {
- return (_rnd->getRandomNumber(hi - 1) + 1);
+void PreAgiEngine::playNote(int16 frequency, int32 length) {
+ _speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
+ waitForTimer(length);
+}
+
+void PreAgiEngine::waitForTimer(int msec_delay) {
+ uint32 start_time = _system->getMillis();
+
+ while (_system->getMillis() < start_time + msec_delay) {
+ _gfx->doUpdate();
+ _system->updateScreen();
+ _system->delayMillis(10);
+ }
}
} // End of namespace Agi
diff --git a/engines/agi/preagi.h b/engines/agi/preagi.h
index 1a178497ad..14ff483d9f 100644
--- a/engines/agi/preagi.h
+++ b/engines/agi/preagi.h
@@ -24,20 +24,36 @@
#define AGI_PREAGI_H
#include "agi/agi.h"
-#include "agi/preagi_common.h"
#include "audio/softsynth/pcspk.h"
namespace Agi {
+// default attributes
+#define IDA_DEFAULT 0x0F
+#define IDA_DEFAULT_REV 0xF0
+
+#define IDI_SND_OSCILLATOR_FREQUENCY 1193180
+#define IDI_SND_TIMER_RESOLUTION 0.0182
+
+#define kColorDefault 0x1337
+
+#define IDI_MAX_ROW_PIC 20
+
+enum SelectionTypes {
+ kSelYesNo,
+ kSelNumber,
+ kSelSpace,
+ kSelAnyKey,
+ kSelBackspace
+};
+
class PreAgiEngine : public AgiBase {
int _gameId;
protected:
- Common::Error go();
void initialize();
-public:
void pollTimer() {}
int getKeypress() { return 0; }
bool isKeypress() { return false; }
@@ -49,10 +65,7 @@ public:
return _gameId;
}
- //SoundMgr *_sound;
PictureMgr *_picture;
- PreAGI_Console *_console;
- GUI::Debugger *getDebugger() { return _console; }
void clearImageStack() {}
void recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
diff --git a/engines/agi/preagi_common.cpp b/engines/agi/preagi_common.cpp
deleted file mode 100644
index d437dc08f2..0000000000
--- a/engines/agi/preagi_common.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "agi/preagi.h"
-#include "agi/graphics.h"
-#include "agi/keyboard.h"
-
-#include "agi/preagi_common.h"
-
-#include "common/events.h"
-
-namespace Agi {
-
-// Screen functions
-void PreAgiEngine::clearScreen(int attr, bool overrideDefault) {
- if (overrideDefault)
- _defaultColor = attr;
-
- _gfx->clearScreen((attr & 0xF0) / 0x10);
-}
-
-void PreAgiEngine::clearGfxScreen(int attr) {
- _gfx->drawRectangle(0, 0, GFX_WIDTH - 1, IDI_MAX_ROW_PIC * 8 -1, (attr & 0xF0) / 0x10);
-}
-
-// String functions
-
-void PreAgiEngine::drawStr(int row, int col, int attr, const char *buffer) {
- int code;
-
- if (attr == kColorDefault)
- attr = _defaultColor;
-
- for (int iChar = 0; iChar < (int)strlen(buffer); iChar++) {
- code = buffer[iChar];
-
- switch (code) {
- case '\n':
- case 0x8D:
- if (++row == 200 / 8) return;
- col = 0;
- break;
-
- case '|':
- // swap attribute nibbles
- break;
-
- default:
- _gfx->putTextCharacter(1, col * 8 , row * 8, static_cast<char>(code), attr & 0x0f, (attr & 0xf0) / 0x10, false, getGameID() == GID_MICKEY ? mickey_fontdata : ibm_fontdata);
-
- if (++col == 320 / 8) {
- col = 0;
- if (++row == 200 / 8) return;
- }
- }
- }
-}
-
-void PreAgiEngine::drawStrMiddle(int row, int attr, const char *buffer) {
- int col = (25 / 2) - (strlen(buffer) / 2); // 25 = 320 / 8 (maximum column)
- drawStr(row, col, attr, buffer);
-}
-
-void PreAgiEngine::clearTextArea() {
- int start = IDI_MAX_ROW_PIC;
-
- if (getGameID() == GID_TROLL)
- start = 21;
-
- for (int row = start; row < 200 / 8; row++) {
- clearRow(row);
- }
-}
-
-void PreAgiEngine::clearRow(int row) {
- drawStr(row, 0, IDA_DEFAULT, " "); // 40 spaces
-}
-
-void PreAgiEngine::printStr(const char* szMsg) {
- clearTextArea();
- drawStr(21, 0, IDA_DEFAULT, szMsg);
- _gfx->doUpdate();
- _system->updateScreen();
-}
-
-void PreAgiEngine::XOR80(char *buffer) {
- for (size_t i = 0; i < strlen(buffer); i++)
- if (buffer[i] & 0x80)
- buffer[i] ^= 0x80;
-}
-
-void PreAgiEngine::printStrXOR(char *szMsg) {
- XOR80(szMsg);
- printStr(szMsg);
-}
-
-// Input functions
-
-int PreAgiEngine::getSelection(SelectionTypes type) {
- Common::Event event;
-
- while (!shouldQuit()) {
- while (_eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_RTL:
- case Common::EVENT_QUIT:
- return 0;
- case Common::EVENT_RBUTTONUP:
- return 0;
- case Common::EVENT_LBUTTONUP:
- if (type == kSelYesNo || type == kSelAnyKey)
- return 1;
- case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL) && _console) {
- _console->attach();
- _console->onFrame();
- //FIXME: If not cleared, clicking again will start the console
- event.kbd.keycode = Common::KEYCODE_INVALID;
- event.kbd.flags = 0;
- continue;
- }
- switch (event.kbd.keycode) {
- case Common::KEYCODE_y:
- if (type == kSelYesNo)
- return 1;
- case Common::KEYCODE_n:
- if (type == kSelYesNo)
- return 0;
- case Common::KEYCODE_ESCAPE:
- if (type == kSelNumber || type == kSelAnyKey)
- return 0;
- case Common::KEYCODE_1:
- case Common::KEYCODE_2:
- case Common::KEYCODE_3:
- case Common::KEYCODE_4:
- case Common::KEYCODE_5:
- case Common::KEYCODE_6:
- case Common::KEYCODE_7:
- case Common::KEYCODE_8:
- case Common::KEYCODE_9:
- if (type == kSelNumber)
- return event.kbd.keycode - Common::KEYCODE_1 + 1;
- case Common::KEYCODE_SPACE:
- if (type == kSelSpace)
- return 1;
- case Common::KEYCODE_BACKSPACE:
- if (type == kSelBackspace)
- return 0;
- default:
- if (event.kbd.flags & Common::KBD_CTRL)
- break;
- if (type == kSelYesNo) {
- return 2;
- } else if (type == kSelNumber) {
- return 10;
- } else if (type == kSelAnyKey || type == kSelBackspace) {
- return 1;
- }
- }
- break;
- default:
- break;
- }
- }
- _system->updateScreen();
- _system->delayMillis(10);
- }
- return 0;
-}
-
-void PreAgiEngine::playNote(int16 frequency, int32 length) {
- _speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
- waitForTimer(length);
-}
-
-void PreAgiEngine::waitForTimer(int msec_delay) {
- uint32 start_time = _system->getMillis();
-
- while (_system->getMillis() < start_time + msec_delay) {
- _gfx->doUpdate();
- _system->updateScreen();
- _system->delayMillis(10);
- }
-}
-
-}
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index 21eb780916..6d1eb445a2 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -32,7 +32,7 @@
namespace Agi {
-int Mickey::getDat(int iRoom) {
+int MickeyEngine::getDat(int iRoom) {
if (((iRoom > 0) && (iRoom < 24)) || iRoom == 154 || iRoom == 155) return IDI_MSA_PLANET_EARTH;
if ((iRoom >= 30) && (iRoom <= 39)) return IDI_MSA_PLANET_VENUS;
if ((iRoom >= 40) && (iRoom <= 69)) return IDI_MSA_PLANET_NEPTUNE;
@@ -45,7 +45,7 @@ int Mickey::getDat(int iRoom) {
return IDI_MSA_PLANET_SPACESHIP;
}
-void Mickey::readExe(int ofs, uint8 *buffer, long buflen) {
+void MickeyEngine::readExe(int ofs, uint8 *buffer, long buflen) {
Common::File infile;
if (!infile.open("mickey.exe"))
return;
@@ -54,11 +54,11 @@ void Mickey::readExe(int ofs, uint8 *buffer, long buflen) {
infile.close();
}
-void Mickey::getDatFileName(int iRoom, char *szFile) {
+void MickeyEngine::getDatFileName(int iRoom, char *szFile) {
sprintf(szFile, IDS_MSA_PATH_DAT, IDS_MSA_NAME_DAT[getDat(iRoom)]);
}
-void Mickey::readDatHdr(char *szFile, MSA_DAT_HEADER *hdr) {
+void MickeyEngine::readDatHdr(char *szFile, MSA_DAT_HEADER *hdr) {
Common::File infile;
if (!infile.open(szFile))
@@ -83,7 +83,7 @@ void Mickey::readDatHdr(char *szFile, MSA_DAT_HEADER *hdr) {
infile.close();
}
-void Mickey::readOfsData(int offset, int iItem, uint8 *buffer, long buflen) {
+void MickeyEngine::readOfsData(int offset, int iItem, uint8 *buffer, long buflen) {
uint16 ofs[256];
readExe(offset, buffer, buflen);
@@ -97,11 +97,11 @@ void Mickey::readOfsData(int offset, int iItem, uint8 *buffer, long buflen) {
// User Interface
-bool Mickey::chooseY_N(int ofsPrompt, bool fErrorMsg) {
+bool MickeyEngine::chooseY_N(int ofsPrompt, bool fErrorMsg) {
printExeStr(ofsPrompt);
- while (!_vm->shouldQuit()) {
- switch (_vm->getSelection(kSelYesNo)) {
+ while (!shouldQuit()) {
+ switch (getSelection(kSelYesNo)) {
case 0: return false;
case 1: return true;
default:
@@ -117,15 +117,15 @@ bool Mickey::chooseY_N(int ofsPrompt, bool fErrorMsg) {
return false;
}
-int Mickey::choose1to9(int ofsPrompt) {
+int MickeyEngine::choose1to9(int ofsPrompt) {
int answer = 0;
printExeStr(ofsPrompt);
- while (!_vm->shouldQuit()) {
- answer = _vm->getSelection(kSelNumber);
+ while (!shouldQuit()) {
+ answer = getSelection(kSelNumber);
if (answer == 10) {
printExeStr(IDO_MSA_PRESS_1_TO_9);
- if (_vm->getSelection(kSelAnyKey) == 0)
+ if (getSelection(kSelAnyKey) == 0)
return 0;
printExeStr(ofsPrompt);
} else return answer;
@@ -134,38 +134,38 @@ int Mickey::choose1to9(int ofsPrompt) {
return 0;
}
-void Mickey::printStr(char *buffer) {
+void MickeyEngine::printStr(char *buffer) {
int pc = 1;
int nRows, iCol, iRow;
nRows = *buffer + IDI_MSA_ROW_MENU_0;
- _vm->clearTextArea();
+ clearTextArea();
for (iRow = IDI_MSA_ROW_MENU_0; iRow < nRows; iRow++) {
iCol = *(buffer + pc++);
- _vm->drawStr(iRow, iCol, IDA_DEFAULT, buffer + pc);
+ drawStr(iRow, iCol, IDA_DEFAULT, buffer + pc);
pc += strlen(buffer + pc) + 1;
}
// Show the string on screen
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
+ _gfx->doUpdate();
+ _system->updateScreen();
}
-void Mickey::printLine(const char *buffer) {
- _vm->clearTextArea();
+void MickeyEngine::printLine(const char *buffer) {
+ clearTextArea();
- _vm->drawStr(22, 18 - strlen(buffer) / 2, IDA_DEFAULT, buffer);
+ drawStr(22, 18 - strlen(buffer) / 2, IDA_DEFAULT, buffer);
// Show the string on screen
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
+ _gfx->doUpdate();
+ _system->updateScreen();
waitAnyKey(true);
}
-void Mickey::printExeStr(int ofs) {
+void MickeyEngine::printExeStr(int ofs) {
uint8 buffer[256] = {0};
if (!ofs)
@@ -175,7 +175,7 @@ void Mickey::printExeStr(int ofs) {
printStr((char *)buffer);
}
-void Mickey::printExeMsg(int ofs) {
+void MickeyEngine::printExeMsg(int ofs) {
if (!ofs)
return;
@@ -183,9 +183,9 @@ void Mickey::printExeMsg(int ofs) {
waitAnyKey(true);
}
-void Mickey::printDatString(int iStr) {
+void MickeyEngine::printDatString(int iStr) {
char buffer[256];
- int iDat = getDat(_game.iRoom);
+ int iDat = getDat(_gameStateMickey.iRoom);
MSA_DAT_HEADER hdr;
char szFile[256] = {0};
@@ -205,7 +205,7 @@ void Mickey::printDatString(int iStr) {
printStr(buffer);
}
-void Mickey::printDesc(int iRoom) {
+void MickeyEngine::printDesc(int iRoom) {
MSA_DAT_HEADER hdr;
char szFile[256] = {0};
@@ -228,20 +228,20 @@ void Mickey::printDesc(int iRoom) {
free(buffer);
}
-bool Mickey::checkMenu() {
+bool MickeyEngine::checkMenu() {
MSA_MENU menu;
int iSel0, iSel1;
MSA_DAT_HEADER hdr;
char szFile[256] = {0};
Common::File infile;
- getDatFileName(_game.iRoom, szFile);
+ getDatFileName(_gameStateMickey.iRoom, szFile);
readDatHdr(szFile, &hdr);
if (!infile.open(szFile))
return false;
char *buffer = new char[sizeof(MSA_MENU)];
- infile.seek(hdr.ofsRoom[_game.iRoom - 1] + IDI_MSA_OFS_DAT, SEEK_SET);
+ infile.seek(hdr.ofsRoom[_gameStateMickey.iRoom - 1] + IDI_MSA_OFS_DAT, SEEK_SET);
infile.read((uint8 *)buffer, sizeof(MSA_MENU));
infile.close();
@@ -255,7 +255,7 @@ bool Mickey::checkMenu() {
return parse(menu.cmd[iSel0].data[iSel1], menu.arg[iSel0].data[iSel1]);
}
-void Mickey::drawMenu(MSA_MENU menu, int sel0, int sel1) {
+void MickeyEngine::drawMenu(MSA_MENU menu, int sel0, int sel1) {
int iWord;
int iRow;
int sel;
@@ -263,7 +263,7 @@ void Mickey::drawMenu(MSA_MENU menu, int sel0, int sel1) {
// draw menu
- _vm->clearTextArea();
+ clearTextArea();
for (iRow = 0; iRow < 2; iRow++) {
for (iWord = 0; iWord < menu.row[iRow].count; iWord++) {
@@ -277,17 +277,17 @@ void Mickey::drawMenu(MSA_MENU menu, int sel0, int sel1) {
else
attr = IDA_DEFAULT;
- _vm->drawStr(IDI_MSA_ROW_MENU_0 + iRow, menu.row[iRow].entry[iWord].x0,
+ drawStr(IDI_MSA_ROW_MENU_0 + iRow, menu.row[iRow].entry[iWord].x0,
attr, (char *)menu.row[iRow].entry[iWord].szText);
}
}
// Menu created, show it on screen
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
+ _gfx->doUpdate();
+ _system->updateScreen();
}
-void Mickey::getMouseMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow, int x, int y) {
+void MickeyEngine::getMouseMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow, int x, int y) {
int iWord;
int *sel = 0;
@@ -314,7 +314,7 @@ void Mickey::getMouseMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow, i
}
}
-bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
+bool MickeyEngine::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
Common::Event event;
int *sel = 0;
int nWords;
@@ -357,8 +357,8 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
drawMenu(menu, *sel0, *sel1);
- while (!_vm->shouldQuit()) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
+ while (!shouldQuit()) {
+ while (_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
@@ -376,18 +376,18 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
// Change cursor
if (northIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) &&
(event.mouse.y >= 0 && event.mouse.y <= 10)) {
- _vm->_gfx->setCursorPalette(true);
+ _gfx->setCursorPalette(true);
} else if (southIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) &&
(event.mouse.y >= IDI_MSA_PIC_HEIGHT - 10 && event.mouse.y <= IDI_MSA_PIC_HEIGHT)) {
- _vm->_gfx->setCursorPalette(true);
+ _gfx->setCursorPalette(true);
} else if (westIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) &&
(event.mouse.x >= 20 && event.mouse.x <= 30)) {
- _vm->_gfx->setCursorPalette(true);
+ _gfx->setCursorPalette(true);
} else if (eastIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) &&
(event.mouse.x >= IDI_MSA_PIC_WIDTH * 2 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2)) {
- _vm->_gfx->setCursorPalette(true);
+ _gfx->setCursorPalette(true);
} else {
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
}
}
break;
@@ -400,7 +400,7 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
drawMenu(menu, *sel0, *sel1);
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
_clickToMove = true;
} else if (southIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) &&
(event.mouse.y >= IDI_MSA_PIC_HEIGHT - 10 && event.mouse.y <= IDI_MSA_PIC_HEIGHT)) {
@@ -409,7 +409,7 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
drawMenu(menu, *sel0, *sel1);
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
_clickToMove = true;
} else if (westIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) &&
(event.mouse.x >= 20 && event.mouse.x <= 30)) {
@@ -418,7 +418,7 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
drawMenu(menu, *sel0, *sel1);
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
_clickToMove = true;
} else if (eastIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) &&
(event.mouse.x >= IDI_MSA_PIC_WIDTH * 2 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2)) {
@@ -427,10 +427,10 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
drawMenu(menu, *sel0, *sel1);
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
_clickToMove = true;
} else {
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
}
return true;
case Common::EVENT_RBUTTONUP:
@@ -458,20 +458,20 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
}
break;
case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL) && _vm->_console) {
- _vm->_console->attach();
- _vm->_console->onFrame();
+ if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL) && _console) {
+ _console->attach();
+ _console->onFrame();
continue;
}
switch (event.kbd.keycode) {
case Common::KEYCODE_2:
// Hidden message
- if (_game.iRoom == IDI_MSA_PIC_MERCURY_CAVE_0) {
+ if (_gameStateMickey.iRoom == IDI_MSA_PIC_MERCURY_CAVE_0) {
for (int i = 0; i < 5; i++) {
printExeMsg(IDO_MSA_HIDDEN_MSG[i]);
}
- _vm->clearTextArea();
+ clearTextArea();
waitAnyKey();
}
break;
@@ -489,7 +489,7 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
return false;
case Common::KEYCODE_s:
- _vm->flipflag(fSoundOn);
+ flipflag(fSoundOn);
break;
case Common::KEYCODE_c:
inventory();
@@ -552,7 +552,7 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
return false;
}
-void Mickey::getMenuSel(char *buffer, int *sel0, int *sel1) {
+void MickeyEngine::getMenuSel(char *buffer, int *sel0, int *sel1) {
MSA_MENU menu;
memcpy(&menu, buffer, sizeof(MSA_MENU));
@@ -563,8 +563,8 @@ void Mickey::getMenuSel(char *buffer, int *sel0, int *sel1) {
// Show the mouse cursor for the menu
CursorMan.showMouse(true);
- while (!_vm->shouldQuit()) {
- while (!_vm->shouldQuit()) {
+ while (!shouldQuit()) {
+ while (!shouldQuit()) {
if (getMenuSelRow(menu, sel0, sel1, 0)) {
if (_clickToMove)
break;
@@ -586,7 +586,7 @@ void Mickey::getMenuSel(char *buffer, int *sel0, int *sel1) {
CursorMan.showMouse(false);
}
-void Mickey::centerMenu(MSA_MENU *menu) {
+void MickeyEngine::centerMenu(MSA_MENU *menu) {
int iWord;
int iRow;
int w, x;
@@ -606,19 +606,19 @@ void Mickey::centerMenu(MSA_MENU *menu) {
}
}
-void Mickey::patchMenu(MSA_MENU *menu) {
+void MickeyEngine::patchMenu(MSA_MENU *menu) {
uint8 buffer[512];
uint8 menubuf[sizeof(MSA_MENU)];
int nPatches;
int pBuf = 0;
// change planet name in ship airlock menu
- if (_game.iRoom == IDI_MSA_PIC_SHIP_AIRLOCK) {
- strcpy((char *)menu->row[1].entry[2].szText, IDS_MSA_NAME_PLANET[_game.iPlanet]);
+ if (_gameStateMickey.iRoom == IDI_MSA_PIC_SHIP_AIRLOCK) {
+ strcpy((char *)menu->row[1].entry[2].szText, IDS_MSA_NAME_PLANET[_gameStateMickey.iPlanet]);
}
// exit if fix unnecessary
- if (!_game.iRmMenu[_game.iRoom]) {
+ if (!_gameStateMickey.iRmMenu[_gameStateMickey.iRoom]) {
centerMenu(menu);
return;
}
@@ -629,7 +629,7 @@ void Mickey::patchMenu(MSA_MENU *menu) {
// read patches
readOfsData(
IDOFS_MSA_MENU_PATCHES,
- _game.nRmMenu[_game.iRoom] + _game.iRmMenu[_game.iRoom] - 1,
+ _gameStateMickey.nRmMenu[_gameStateMickey.iRoom] + _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] - 1,
buffer, sizeof(buffer)
);
@@ -652,24 +652,24 @@ void Mickey::patchMenu(MSA_MENU *menu) {
centerMenu(menu);
}
-void Mickey::printDatMessage(int iStr) {
+void MickeyEngine::printDatMessage(int iStr) {
printDatString(iStr);
waitAnyKey(true);
}
// Sound
-void Mickey::playNote(MSA_SND_NOTE note) {
+void MickeyEngine::playNote(MSA_SND_NOTE note) {
if (!note.counter) {
// Pause
- _vm->_system->delayMillis((uint) (note.length / IDI_SND_TIMER_RESOLUTION));
+ _system->delayMillis((uint) (note.length / IDI_SND_TIMER_RESOLUTION));
} else {
- _vm->playNote(IDI_SND_OSCILLATOR_FREQUENCY / note.counter, (int32) (note.length / IDI_SND_TIMER_RESOLUTION));
+ PreAgiEngine::playNote(IDI_SND_OSCILLATOR_FREQUENCY / note.counter, (int32) (note.length / IDI_SND_TIMER_RESOLUTION));
}
}
-void Mickey::playSound(ENUM_MSA_SOUND iSound) {
- if (!_vm->getflag(fSoundOn))
+void MickeyEngine::playSound(ENUM_MSA_SOUND iSound) {
+ if (!getflag(fSoundOn))
return;
Common::Event event;
@@ -680,7 +680,7 @@ void Mickey::playSound(ENUM_MSA_SOUND iSound) {
switch (iSound) {
case IDI_MSA_SND_XL30:
for (int iNote = 0; iNote < 6; iNote++) {
- note.counter = _vm->rnd(59600) + 59;
+ note.counter = rnd(59600) + 59;
note.length = 4;
playNote(note);
}
@@ -698,7 +698,7 @@ void Mickey::playSound(ENUM_MSA_SOUND iSound) {
pBuf += 3;
if (iSound == IDI_MSA_SND_THEME) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
+ while (_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
@@ -722,7 +722,7 @@ void Mickey::playSound(ENUM_MSA_SOUND iSound) {
// Graphics
-void Mickey::drawObj(ENUM_MSA_OBJECT iObj, int x0, int y0) {
+void MickeyEngine::drawObj(ENUM_MSA_OBJECT iObj, int x0, int y0) {
char szFile[255] = {0};
sprintf(szFile, IDS_MSA_PATH_OBJ, IDS_MSA_NAME_OBJ[iObj]);
@@ -736,15 +736,15 @@ void Mickey::drawObj(ENUM_MSA_OBJECT iObj, int x0, int y0) {
file.close();
if (iObj == IDI_MSA_OBJECT_CRYSTAL)
- _vm->_picture->setPictureFlags(kPicFStep);
+ _picture->setPictureFlags(kPicFStep);
- _vm->_picture->setOffset(x0, y0);
- _vm->_picture->decodePicture(buffer, size, false, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
- _vm->_picture->setOffset(0, 0);
- _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _picture->setOffset(x0, y0);
+ _picture->decodePicture(buffer, size, false, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _picture->setOffset(0, 0);
+ _picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
}
-void Mickey::drawPic(int iPic) {
+void MickeyEngine::drawPic(int iPic) {
char szFile[255] = {0};
sprintf(szFile, IDS_MSA_PATH_PIC, iPic);
@@ -758,16 +758,16 @@ void Mickey::drawPic(int iPic) {
file.close();
// Note that decodePicture clears the screen
- _vm->_picture->decodePicture(buffer, size, true, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
- _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _picture->decodePicture(buffer, size, true, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
}
-void Mickey::drawRoomAnimation() {
+void MickeyEngine::drawRoomAnimation() {
uint8 objLight[] = {
0xF0, 1, 0xF9, 2, 43, 45, 0xFF
};
- switch (_game.iRoom) {
+ switch (_gameStateMickey.iRoom) {
case IDI_MSA_PIC_EARTH_SHIP:
case IDI_MSA_PIC_VENUS_SHIP:
case IDI_MSA_PIC_NEPTUNE_SHIP:
@@ -790,26 +790,26 @@ void Mickey::drawRoomAnimation() {
uint8 iColor = 0;
- _vm->_picture->setPattern(2, 0);
+ _picture->setPattern(2, 0);
for (int i = 0; i < 12; i++) {
- iColor = _game.nFrame + i;
+ iColor = _gameStateMickey.nFrame + i;
if (iColor > 15)
iColor -= 15;
objLight[1] = iColor;
objLight[4] += 7;
- _vm->_picture->setPictureData(objLight);
- _vm->_picture->setPictureFlags(kPicFCircle);
- _vm->_picture->drawPicture();
+ _picture->setPictureData(objLight);
+ _picture->setPictureFlags(kPicFCircle);
+ _picture->drawPicture();
}
- _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
- _game.nFrame--;
- if (_game.nFrame < 0)
- _game.nFrame = 15;
+ _gameStateMickey.nFrame--;
+ if (_gameStateMickey.nFrame < 0)
+ _gameStateMickey.nFrame = 15;
playSound(IDI_MSA_SND_PRESS_BLUE);
}
@@ -818,12 +818,12 @@ void Mickey::drawRoomAnimation() {
case IDI_MSA_PIC_SHIP_CONTROLS:
// draw XL30 screen
- if (_game.fAnimXL30) {
- if (_game.nFrame > 5)
- _game.nFrame = 0;
+ if (_gameStateMickey.fAnimXL30) {
+ if (_gameStateMickey.nFrame > 5)
+ _gameStateMickey.nFrame = 0;
- drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_XL31 + _game.nFrame), 0, 4);
- _game.nFrame++;
+ drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_XL31 + _gameStateMickey.nFrame), 0, 4);
+ _gameStateMickey.nFrame++;
};
break;
@@ -831,17 +831,17 @@ void Mickey::drawRoomAnimation() {
default:
// draw crystal
- if (_game.iRoom == IDI_MSA_XTAL_ROOM_XY[_game.iPlanet][0]) {
- if (!_game.fHasXtal) {
- switch (_game.iPlanet) {
+ if (_gameStateMickey.iRoom == IDI_MSA_XTAL_ROOM_XY[_gameStateMickey.iPlanet][0]) {
+ if (!_gameStateMickey.fHasXtal) {
+ switch (_gameStateMickey.iPlanet) {
case IDI_MSA_PLANET_VENUS:
- if (_game.iRmMenu[_game.iRoom] != 2)
+ if (_gameStateMickey.iRmMenu[_gameStateMickey.iRoom] != 2)
break;
default:
drawObj(
IDI_MSA_OBJECT_CRYSTAL,
- IDI_MSA_XTAL_ROOM_XY[_game.iPlanet][1],
- IDI_MSA_XTAL_ROOM_XY[_game.iPlanet][2]
+ IDI_MSA_XTAL_ROOM_XY[_gameStateMickey.iPlanet][1],
+ IDI_MSA_XTAL_ROOM_XY[_gameStateMickey.iPlanet][2]
);
break;
}
@@ -852,36 +852,36 @@ void Mickey::drawRoomAnimation() {
}
}
-void Mickey::drawRoom() {
+void MickeyEngine::drawRoom() {
uint8 buffer[256];
int pBuf = 0;
int nObjs;
// Draw room picture
- if (_game.iRoom == IDI_MSA_PIC_TITLE) {
+ if (_gameStateMickey.iRoom == IDI_MSA_PIC_TITLE) {
drawPic(IDI_MSA_PIC_TITLE);
} else {
- drawPic(_game.iRmPic[_game.iRoom]);
+ drawPic(_gameStateMickey.iRmPic[_gameStateMickey.iRoom]);
- if (_game.iRoom == IDI_MSA_PIC_SHIP_CONTROLS) {
+ if (_gameStateMickey.iRoom == IDI_MSA_PIC_SHIP_CONTROLS) {
// Draw ship control room window
- if (_game.fFlying) {
+ if (_gameStateMickey.fFlying) {
drawObj(IDI_MSA_OBJECT_W_SPACE, 0, 0);
} else {
- drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_W_EARTH + _game.iPlanet), 0, 1);
+ drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_W_EARTH + _gameStateMickey.iPlanet), 0, 1);
}
}
}
// Draw room objects
- if (_game.iRoom >= IDI_MSA_MAX_PIC_ROOM) {
+ if (_gameStateMickey.iRoom >= IDI_MSA_MAX_PIC_ROOM) {
drawRoomAnimation();
return;
}
- if (_game.iRmObj[_game.iRoom] != IDI_MSA_OBJECT_NONE) {
+ if (_gameStateMickey.iRmObj[_gameStateMickey.iRoom] != IDI_MSA_OBJECT_NONE) {
readOfsData(IDO_MSA_ROOM_OBJECT_XY_OFFSETS,
- _game.iRmObj[_game.iRoom], buffer, sizeof(buffer));
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom], buffer, sizeof(buffer));
nObjs = buffer[pBuf++];
@@ -914,7 +914,7 @@ const uint8 colorBCG[16][2] = {
{ 0xFF, 0xFF } // F (white, white)
};
-void Mickey::drawLogo() {
+void MickeyEngine::drawLogo() {
// TODO: clean this up and make it work properly, the logo is drawn way off to the right
#if 0
char szFile[256] = {0};
@@ -937,7 +937,7 @@ void Mickey::drawLogo() {
// draw logo bitmap
memcpy(bitmap, buffer, sizeof(bitmap));
- _vm->_picture->setDimensions(w, h);
+ _picture->setDimensions(w, h);
// Show BCG picture
for (int y = 0; y < h; y++) {
@@ -947,40 +947,40 @@ void Mickey::drawLogo() {
color3 = colorBCG[ bitmap[y][x] & 0x0f][0]; // foreground
color4 = colorBCG[ bitmap[y][x] & 0x0f][1]; // foreground
- _vm->_picture->putPixel(x * 4 - xoffset, y, color);
- _vm->_picture->putPixel(x * 4 + 1 - xoffset, y, color2);
- _vm->_picture->putPixel(x * 4 + 2 - xoffset, y, color3);
- _vm->_picture->putPixel(x * 4 + 3 - xoffset, y, color4);
- _vm->_picture->putPixel(x * 4 - xoffset, y + 1, color);
- _vm->_picture->putPixel(x * 4 + 1 - xoffset, y + 1, color2);
- _vm->_picture->putPixel(x * 4 + 2 - xoffset, y + 1, color3);
- _vm->_picture->putPixel(x * 4 + 3 - xoffset, y + 1, color4);
+ _picture->putPixel(x * 4 - xoffset, y, color);
+ _picture->putPixel(x * 4 + 1 - xoffset, y, color2);
+ _picture->putPixel(x * 4 + 2 - xoffset, y, color3);
+ _picture->putPixel(x * 4 + 3 - xoffset, y, color4);
+ _picture->putPixel(x * 4 - xoffset, y + 1, color);
+ _picture->putPixel(x * 4 + 1 - xoffset, y + 1, color2);
+ _picture->putPixel(x * 4 + 2 - xoffset, y + 1, color3);
+ _picture->putPixel(x * 4 + 3 - xoffset, y + 1, color4);
}
}
- _vm->_picture->showPic(10, 10, w, h);
+ _picture->showPic(10, 10, w, h);
delete[] buffer;
#endif
}
-void Mickey::animate() {
- _vm->_system->delayMillis(IDI_MSA_ANIM_DELAY);
+void MickeyEngine::animate() {
+ _system->delayMillis(IDI_MSA_ANIM_DELAY);
drawRoomAnimation();
}
-void Mickey::printRoomDesc() {
+void MickeyEngine::printRoomDesc() {
// print room description
- printDesc(_game.iRoom);
+ printDesc(_gameStateMickey.iRoom);
waitAnyKey(true);
// print extended room description
- if (_game.oRmTxt[_game.iRoom]) {
- printExeMsg(_game.oRmTxt[_game.iRoom] + IDI_MSA_OFS_EXE);
+ if (_gameStateMickey.oRmTxt[_gameStateMickey.iRoom]) {
+ printExeMsg(_gameStateMickey.oRmTxt[_gameStateMickey.iRoom] + IDI_MSA_OFS_EXE);
}
}
-bool Mickey::loadGame() {
+bool MickeyEngine::loadGame() {
Common::InSaveFile *infile;
char szFile[256] = {0};
bool diskerror = true;
@@ -994,15 +994,15 @@ bool Mickey::loadGame() {
return false;
// load game
- sprintf(szFile, "%s.s%02d", _vm->getTargetName().c_str(), sel);
- if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile))) {
+ sprintf(szFile, "%s.s%02d", getTargetName().c_str(), sel);
+ if (!(infile = getSaveFileMan()->openForLoading(szFile))) {
printLine("PLEASE CHECK THE DISK DRIVE");
- if (_vm->getSelection(kSelAnyKey) == 0)
+ if (getSelection(kSelAnyKey) == 0)
return false;
} else {
if (infile->readUint32BE() != MKTAG('M','I','C','K')) {
- warning("Mickey::loadGame wrong save game format");
+ warning("MickeyEngine::loadGame wrong save game format");
return false;
}
@@ -1015,61 +1015,61 @@ bool Mickey::loadGame() {
if (saveVersion != MSA_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, MSA_SAVEGAME_VERSION);
- _game.iRoom = infile->readByte();
- _game.iPlanet = infile->readByte();
- _game.iDisk = infile->readByte();
+ _gameStateMickey.iRoom = infile->readByte();
+ _gameStateMickey.iPlanet = infile->readByte();
+ _gameStateMickey.iDisk = infile->readByte();
- _game.nAir = infile->readByte();
- _game.nButtons = infile->readByte();
- _game.nRocks = infile->readByte();
+ _gameStateMickey.nAir = infile->readByte();
+ _gameStateMickey.nButtons = infile->readByte();
+ _gameStateMickey.nRocks = infile->readByte();
- _game.nXtals = infile->readByte();
+ _gameStateMickey.nXtals = infile->readByte();
for (i = 0; i < IDI_MSA_MAX_DAT; i++)
- _game.iPlanetXtal[i] = infile->readByte();
+ _gameStateMickey.iPlanetXtal[i] = infile->readByte();
for (i = 0; i < IDI_MSA_MAX_PLANET; i++)
- _game.iClue[i] = infile->readUint16LE();
+ _gameStateMickey.iClue[i] = infile->readUint16LE();
- infile->read(_game.szAddr, IDI_MSA_MAX_BUTTON + 1);
+ infile->read(_gameStateMickey.szAddr, IDI_MSA_MAX_BUTTON + 1);
- _game.fHasXtal = infile->readByte() == 1;
- _game.fIntro = infile->readByte() == 1;
- _game.fSuit = infile->readByte() == 1;
- _game.fShipDoorOpen = infile->readByte() == 1;
- _game.fFlying = infile->readByte() == 1;
- _game.fStoryShown = infile->readByte() == 1;
- _game.fPlanetsInitialized = infile->readByte() == 1;
- _game.fTempleDoorOpen = infile->readByte() == 1;
- _game.fAnimXL30 = infile->readByte() == 1;
+ _gameStateMickey.fHasXtal = infile->readByte() == 1;
+ _gameStateMickey.fIntro = infile->readByte() == 1;
+ _gameStateMickey.fSuit = infile->readByte() == 1;
+ _gameStateMickey.fShipDoorOpen = infile->readByte() == 1;
+ _gameStateMickey.fFlying = infile->readByte() == 1;
+ _gameStateMickey.fStoryShown = infile->readByte() == 1;
+ _gameStateMickey.fPlanetsInitialized = infile->readByte() == 1;
+ _gameStateMickey.fTempleDoorOpen = infile->readByte() == 1;
+ _gameStateMickey.fAnimXL30 = infile->readByte() == 1;
for (i = 0; i < IDI_MSA_MAX_ITEM; i++)
- _game.fItem[i] = infile->readByte() == 1;
+ _gameStateMickey.fItem[i] = infile->readByte() == 1;
for (i = 0; i < IDI_MSA_MAX_ITEM; i++)
- _game.fItemUsed[i] = infile->readByte() == 1;
+ _gameStateMickey.fItemUsed[i] = infile->readByte() == 1;
for (i = 0; i < IDI_MSA_MAX_ITEM; i++)
- _game.iItem[i] = infile->readSByte();
+ _gameStateMickey.iItem[i] = infile->readSByte();
- _game.nItems = infile->readByte();
+ _gameStateMickey.nItems = infile->readByte();
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- _game.iRmObj[i] = infile->readSByte();
+ _gameStateMickey.iRmObj[i] = infile->readSByte();
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- _game.iRmPic[i] = infile->readByte();
+ _gameStateMickey.iRmPic[i] = infile->readByte();
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- _game.oRmTxt[i] = infile->readUint16LE();
+ _gameStateMickey.oRmTxt[i] = infile->readUint16LE();
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- _game.iRmMenu[i] = infile->readByte();
+ _gameStateMickey.iRmMenu[i] = infile->readByte();
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- _game.nRmMenu[i] = infile->readByte();
+ _gameStateMickey.nRmMenu[i] = infile->readByte();
- _game.nFrame = infile->readSByte();
+ _gameStateMickey.nFrame = infile->readSByte();
diskerror = false;
delete infile;
@@ -1080,7 +1080,7 @@ bool Mickey::loadGame() {
return true;
}
-void Mickey::saveGame() {
+void MickeyEngine::saveGame() {
Common::OutSaveFile* outfile;
char szFile[256] = {0};
bool diskerror = true;
@@ -1094,7 +1094,7 @@ void Mickey::saveGame() {
else
printExeStr(IDO_MSA_SAVE_GAME[2]);
- if (_vm->getSelection(kSelAnyKey) == 0)
+ if (getSelection(kSelAnyKey) == 0)
return;
while (diskerror) {
@@ -1107,75 +1107,75 @@ void Mickey::saveGame() {
else
printExeStr(IDO_MSA_SAVE_GAME[4]);
- if (_vm->getSelection(kSelAnyKey) == 0)
+ if (getSelection(kSelAnyKey) == 0)
return;
// save game
- sprintf(szFile, "%s.s%02d", _vm->getTargetName().c_str(), sel);
- if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile))) {
+ sprintf(szFile, "%s.s%02d", getTargetName().c_str(), sel);
+ if (!(outfile = getSaveFileMan()->openForSaving(szFile))) {
printLine("PLEASE CHECK THE DISK DRIVE");
- if (_vm->getSelection(kSelAnyKey) == 0)
+ if (getSelection(kSelAnyKey) == 0)
return;
} else {
outfile->writeUint32BE(MKTAG('M','I','C','K')); // header
outfile->writeByte(MSA_SAVEGAME_VERSION);
- outfile->writeByte(_game.iRoom);
- outfile->writeByte(_game.iPlanet);
- outfile->writeByte(_game.iDisk);
+ outfile->writeByte(_gameStateMickey.iRoom);
+ outfile->writeByte(_gameStateMickey.iPlanet);
+ outfile->writeByte(_gameStateMickey.iDisk);
- outfile->writeByte(_game.nAir);
- outfile->writeByte(_game.nButtons);
- outfile->writeByte(_game.nRocks);
+ outfile->writeByte(_gameStateMickey.nAir);
+ outfile->writeByte(_gameStateMickey.nButtons);
+ outfile->writeByte(_gameStateMickey.nRocks);
- outfile->writeByte(_game.nXtals);
+ outfile->writeByte(_gameStateMickey.nXtals);
for (i = 0; i < IDI_MSA_MAX_DAT; i++)
- outfile->writeByte(_game.iPlanetXtal[i]);
+ outfile->writeByte(_gameStateMickey.iPlanetXtal[i]);
for (i = 0; i < IDI_MSA_MAX_PLANET; i++)
- outfile->writeUint16LE(_game.iClue[i]);
+ outfile->writeUint16LE(_gameStateMickey.iClue[i]);
- outfile->write(_game.szAddr, IDI_MSA_MAX_BUTTON + 1);
+ outfile->write(_gameStateMickey.szAddr, IDI_MSA_MAX_BUTTON + 1);
- outfile->writeByte(_game.fHasXtal ? 1 : 0);
- outfile->writeByte(_game.fIntro ? 1 : 0);
- outfile->writeByte(_game.fSuit ? 1 : 0);
- outfile->writeByte(_game.fShipDoorOpen ? 1 : 0);
- outfile->writeByte(_game.fFlying ? 1 : 0);
- outfile->writeByte(_game.fStoryShown ? 1 : 0);
- outfile->writeByte(_game.fPlanetsInitialized ? 1 : 0);
- outfile->writeByte(_game.fTempleDoorOpen ? 1 : 0);
- outfile->writeByte(_game.fAnimXL30 ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fHasXtal ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fIntro ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fSuit ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fShipDoorOpen ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fFlying ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fStoryShown ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fPlanetsInitialized ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fTempleDoorOpen ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fAnimXL30 ? 1 : 0);
for (i = 0; i < IDI_MSA_MAX_ITEM; i++)
- outfile->writeByte(_game.fItem[i] ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fItem[i] ? 1 : 0);
for (i = 0; i < IDI_MSA_MAX_ITEM; i++)
- outfile->writeByte(_game.fItemUsed[i] ? 1 : 0);
+ outfile->writeByte(_gameStateMickey.fItemUsed[i] ? 1 : 0);
for (i = 0; i < IDI_MSA_MAX_ITEM; i++)
- outfile->writeSByte(_game.iItem[i]);
+ outfile->writeSByte(_gameStateMickey.iItem[i]);
- outfile->writeByte(_game.nItems);
+ outfile->writeByte(_gameStateMickey.nItems);
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- outfile->writeSByte(_game.iRmObj[i]);
+ outfile->writeSByte(_gameStateMickey.iRmObj[i]);
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- outfile->writeByte(_game.iRmPic[i]);
+ outfile->writeByte(_gameStateMickey.iRmPic[i]);
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- outfile->writeUint16LE(_game.oRmTxt[i]);
+ outfile->writeUint16LE(_gameStateMickey.oRmTxt[i]);
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- outfile->writeByte(_game.iRmMenu[i]);
+ outfile->writeByte(_gameStateMickey.iRmMenu[i]);
for (i = 0; i < IDI_MSA_MAX_ROOM; i++)
- outfile->writeByte(_game.nRmMenu[i]);
+ outfile->writeByte(_gameStateMickey.nRmMenu[i]);
- outfile->writeSByte(_game.nFrame);
+ outfile->writeSByte(_gameStateMickey.nFrame);
outfile->finalize();
@@ -1190,14 +1190,14 @@ void Mickey::saveGame() {
printExeMsg(IDO_MSA_SAVE_GAME[6]);
}
-void Mickey::showPlanetInfo() {
+void MickeyEngine::showPlanetInfo() {
for (int i = 0; i < 4; i++) {
- printExeStr(IDO_MSA_PLANET_INFO[_game.iPlanet][i]);
+ printExeStr(IDO_MSA_PLANET_INFO[_gameStateMickey.iPlanet][i]);
waitAnyKey();
}
}
-void Mickey::printStory() {
+void MickeyEngine::printStory() {
char buffer[IDI_MSA_LEN_STORY] = {0};
char szLine[41] = {0};
int iRow;
@@ -1205,37 +1205,37 @@ void Mickey::printStory() {
readExe(IDO_MSA_GAME_STORY, (uint8 *)buffer, sizeof(buffer));
- _vm->clearScreen(IDA_DEFAULT);
+ clearScreen(IDA_DEFAULT);
for (iRow = 0; iRow < 25; iRow++) {
strcpy(szLine, buffer + pBuf);
- _vm->drawStr(iRow, 0, IDA_DEFAULT, szLine);
+ drawStr(iRow, 0, IDA_DEFAULT, szLine);
pBuf += strlen(szLine) + 1;
}
waitAnyKey();
- _vm->clearScreen(IDA_DEFAULT);
+ clearScreen(IDA_DEFAULT);
for (iRow = 0; iRow < 21; iRow++) {
strcpy(szLine, buffer + pBuf);
- _vm->drawStr(iRow, 0, IDA_DEFAULT, szLine);
+ drawStr(iRow, 0, IDA_DEFAULT, szLine);
pBuf += strlen(szLine) + 1;
}
waitAnyKey();
//Set back to black
- _vm->_gfx->clearScreen(0);
- _vm->_gfx->doUpdate();
+ _gfx->clearScreen(0);
+ _gfx->doUpdate();
drawRoom();
- _game.fStoryShown = true;
+ _gameStateMickey.fStoryShown = true;
}
-int Mickey::getPlanet() {
- if (!_game.nButtons)
+int MickeyEngine::getPlanet() {
+ if (!_gameStateMickey.nButtons)
return -1;
for (int iPlanet = 0; iPlanet < IDI_MSA_MAX_DAT - 1; iPlanet++) {
- if (!strcmp(IDS_MSA_ADDR_PLANET[iPlanet], _game.szAddr)) {
+ if (!strcmp(IDS_MSA_ADDR_PLANET[iPlanet], _gameStateMickey.szAddr)) {
return iPlanet;
}
}
@@ -1243,49 +1243,49 @@ int Mickey::getPlanet() {
return -1;
}
-void Mickey::pressOB(int iButton) {
+void MickeyEngine::pressOB(int iButton) {
char szButtons[12] = {0};
// check if too many buttons pressed
- if (_game.nButtons == IDI_MSA_MAX_BUTTON) {
- _game.nButtons = 0;
- memset(_game.szAddr, 0, sizeof(_game.szAddr));
+ if (_gameStateMickey.nButtons == IDI_MSA_MAX_BUTTON) {
+ _gameStateMickey.nButtons = 0;
+ memset(_gameStateMickey.szAddr, 0, sizeof(_gameStateMickey.szAddr));
printExeMsg(IDO_MSA_TOO_MANY_BUTTONS_PRESSED);
return;
}
// add button press to address
- _game.nButtons++;
- _game.szAddr[_game.nButtons - 1] = (char)iButton;
+ _gameStateMickey.nButtons++;
+ _gameStateMickey.szAddr[_gameStateMickey.nButtons - 1] = (char)iButton;
// format buttons string
for (int i = 0; i < IDI_MSA_MAX_BUTTON; i++) {
- szButtons[i * 2] = _game.szAddr[i];
- if (_game.szAddr[i + 1]) szButtons[(i * 2) + 1] = ',';
+ szButtons[i * 2] = _gameStateMickey.szAddr[i];
+ if (_gameStateMickey.szAddr[i + 1]) szButtons[(i * 2) + 1] = ',';
}
// print pressed buttons
printLine("MICKEY HAS PRESSED: ");
- _vm->drawStr(20, 22, IDA_DEFAULT, szButtons);
+ drawStr(20, 22, IDA_DEFAULT, szButtons);
waitAnyKey();
}
-void Mickey::insertDisk(int iDisk) {
- _vm->clearTextArea();
- _vm->drawStr(IDI_MSA_ROW_INSERT_DISK, IDI_MSA_COL_INSERT_DISK, IDA_DEFAULT, (const char *)IDS_MSA_INSERT_DISK[iDisk]);
+void MickeyEngine::insertDisk(int iDisk) {
+ clearTextArea();
+ drawStr(IDI_MSA_ROW_INSERT_DISK, IDI_MSA_COL_INSERT_DISK, IDA_DEFAULT, (const char *)IDS_MSA_INSERT_DISK[iDisk]);
waitAnyKey();
}
-void Mickey::gameOver() {
+void MickeyEngine::gameOver() {
// We shouldn't run the game over segment if we're quitting.
- if (_vm->shouldQuit())
+ if (shouldQuit())
return;
drawPic(IDI_MSA_PIC_EARTH_SHIP_LEAVING);
printExeMsg(IDO_MSA_GAME_OVER[3]);
playSound(IDI_MSA_SND_GAME_OVER);
- if (_game.fItemUsed[IDI_MSA_ITEM_LETTER]) {
+ if (_gameStateMickey.fItemUsed[IDI_MSA_ITEM_LETTER]) {
drawPic(IDI_MSA_PIC_EARTH_MINNIE);
printExeMsg(IDO_MSA_GAME_OVER[4]);
printExeMsg(IDO_MSA_GAME_OVER[5]);
@@ -1297,74 +1297,74 @@ void Mickey::gameOver() {
waitAnyKey();
}
-void Mickey::flipSwitch() {
- if (_game.fHasXtal || _game.nXtals) {
- if (!_game.fStoryShown)
+void MickeyEngine::flipSwitch() {
+ if (_gameStateMickey.fHasXtal || _gameStateMickey.nXtals) {
+ if (!_gameStateMickey.fStoryShown)
printStory();
// Initialize planet data
- if (!_game.fPlanetsInitialized) {
+ if (!_gameStateMickey.fPlanetsInitialized) {
int iHint = 0;
int iPlanet = 0;
- memset(_game.iPlanetXtal, 0, sizeof(_game.iPlanetXtal));
- memset(_game.iClue, 0, sizeof(_game.iClue));
+ memset(_gameStateMickey.iPlanetXtal, 0, sizeof(_gameStateMickey.iPlanetXtal));
+ memset(_gameStateMickey.iClue, 0, sizeof(_gameStateMickey.iClue));
- _game.iPlanetXtal[0] = IDI_MSA_PLANET_EARTH;
- _game.iPlanetXtal[8] = IDI_MSA_PLANET_URANUS;
+ _gameStateMickey.iPlanetXtal[0] = IDI_MSA_PLANET_EARTH;
+ _gameStateMickey.iPlanetXtal[8] = IDI_MSA_PLANET_URANUS;
for (int i = 1; i < IDI_MSA_MAX_PLANET; i++) {
if (i < 8) {
do {
// Earth (planet 0) and Uranus (planet 8) are excluded
- iPlanet = _vm->rnd(IDI_MSA_MAX_PLANET - 2);
+ iPlanet = rnd(IDI_MSA_MAX_PLANET - 2);
} while (planetIsAlreadyAssigned(iPlanet));
} else {
iPlanet = IDI_MSA_PLANET_URANUS; // Uranus is always last
}
- _game.iPlanetXtal[i] = iPlanet;
- iHint = _vm->rnd(5) - 1; // clues are 0-4
- _game.iClue[i] = IDO_MSA_NEXT_PIECE[iPlanet][iHint];
+ _gameStateMickey.iPlanetXtal[i] = iPlanet;
+ iHint = rnd(5) - 1; // clues are 0-4
+ _gameStateMickey.iClue[i] = IDO_MSA_NEXT_PIECE[iPlanet][iHint];
}
- _game.fPlanetsInitialized = true;
+ _gameStateMickey.fPlanetsInitialized = true;
}
// activate screen animation
- _game.fAnimXL30 = true;
+ _gameStateMickey.fAnimXL30 = true;
- _vm->clearTextArea();
+ clearTextArea();
playSound(IDI_MSA_SND_XL30);
printExeMsg(IDO_MSA_XL30_SPEAKING);
- if (_game.fHasXtal) {
- _game.fHasXtal = false;
+ if (_gameStateMickey.fHasXtal) {
+ _gameStateMickey.fHasXtal = false;
printExeMsg(IDO_MSA_CRYSTAL_PIECE_FOUND);
}
- if (_game.nXtals == IDI_MSA_MAX_PLANET) {
+ if (_gameStateMickey.nXtals == IDI_MSA_MAX_PLANET) {
printExeMsg(IDO_MSA_GAME_OVER[0]);
printExeMsg(IDO_MSA_GAME_OVER[1]);
printExeMsg(IDO_MSA_GAME_OVER[2]);
#if 0
// DEBUG
- strcpy(_game.szAddr, (char *)IDS_MSA_ADDR_PLANET[IDI_MSA_PLANET_EARTH]);
- _game.nButtons = strlen(_game.szAddr);
+ strcpy(_gameStateMickey.szAddr, (char *)IDS_MSA_ADDR_PLANET[IDI_MSA_PLANET_EARTH]);
+ _gameStateMickey.nButtons = strlen(_gameStateMickey.szAddr);
#endif
} else {
- printExeStr(_game.iClue[_game.nXtals]);
+ printExeStr(_gameStateMickey.iClue[_gameStateMickey.nXtals]);
#if 0
// DEBUG
- _vm->drawStr(24, 12, IDA_DEFAULT, (char *)IDS_MSA_NAME_PLANET_2[_game.iPlanetXtal[_game.nXtals]]);
- _vm->drawStr(24, 22, IDA_DEFAULT, (char *)IDS_MSA_ADDR_PLANET[_game.iPlanetXtal[_game.nXtals]]);
- strcpy(_game.szAddr, (char *)IDS_MSA_ADDR_PLANET[_game.iPlanetXtal[_game.nXtals]]);
- _game.nButtons = strlen(_game.szAddr);
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ drawStr(24, 12, IDA_DEFAULT, (char *)IDS_MSA_NAME_PLANET_2[_gameStateMickey.iPlanetXtal[_gameStateMickey.nXtals]]);
+ drawStr(24, 22, IDA_DEFAULT, (char *)IDS_MSA_ADDR_PLANET[_gameStateMickey.iPlanetXtal[_gameStateMickey.nXtals]]);
+ strcpy(_gameStateMickey.szAddr, (char *)IDS_MSA_ADDR_PLANET[_gameStateMickey.iPlanetXtal[_gameStateMickey.nXtals]]);
+ _gameStateMickey.nButtons = strlen(_gameStateMickey.szAddr);
+ _gfx->doUpdate();
+ _system->updateScreen(); // TODO: this should go in the game's main loop
#endif
waitAnyKey(true);
@@ -1374,73 +1374,73 @@ void Mickey::flipSwitch() {
}
}
-void Mickey::inventory() {
+void MickeyEngine::inventory() {
int iRow = IDI_MSA_ROW_INV_ITEMS;
char szCrystals[12] = {0};
- sprintf(szCrystals, IDS_MSA_CRYSTALS, IDS_MSA_CRYSTAL_NO[_game.nXtals]);
+ sprintf(szCrystals, IDS_MSA_CRYSTALS, IDS_MSA_CRYSTAL_NO[_gameStateMickey.nXtals]);
CursorMan.showMouse(false);
- _vm->clearScreen(IDA_DEFAULT);
- _vm->drawStr(IDI_MSA_ROW_INV_TITLE, IDI_MSA_COL_INV_TITLE, IDA_DEFAULT, IDS_MSA_INVENTORY);
- _vm->drawStr(IDI_MSA_ROW_INV_CRYSTALS, IDI_MSA_COL_INV_ITEMS, IDA_DEFAULT, szCrystals);
+ clearScreen(IDA_DEFAULT);
+ drawStr(IDI_MSA_ROW_INV_TITLE, IDI_MSA_COL_INV_TITLE, IDA_DEFAULT, IDS_MSA_INVENTORY);
+ drawStr(IDI_MSA_ROW_INV_CRYSTALS, IDI_MSA_COL_INV_ITEMS, IDA_DEFAULT, szCrystals);
for (int iItem = 0; iItem < IDI_MSA_MAX_ITEM; iItem++) {
- if (_game.fItem[_game.iItem[iItem]] && (_game.iItem[iItem] != IDI_MSA_OBJECT_NONE)) {
- _vm->drawStr(iRow++, IDI_MSA_COL_INV_ITEMS, IDA_DEFAULT, (const char *)IDS_MSA_NAME_ITEM[_game.iItem[iItem]]);
+ if (_gameStateMickey.fItem[_gameStateMickey.iItem[iItem]] && (_gameStateMickey.iItem[iItem] != IDI_MSA_OBJECT_NONE)) {
+ drawStr(iRow++, IDI_MSA_COL_INV_ITEMS, IDA_DEFAULT, (const char *)IDS_MSA_NAME_ITEM[_gameStateMickey.iItem[iItem]]);
}
}
waitAnyKey();
- _vm->clearScreen(IDA_DEFAULT);
+ clearScreen(IDA_DEFAULT);
CursorMan.showMouse(true);
}
-void Mickey::intro() {
+void MickeyEngine::intro() {
// Draw Sierra logo
//drawLogo(); // Original does not even show this, so we skip it too
//waitAnyKey(); // Not in the original, but needed so that the logo is visible
// draw title picture
- _game.iRoom = IDI_MSA_PIC_TITLE;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_TITLE;
drawRoom();
// show copyright and play theme
printExeMsg(IDO_MSA_COPYRIGHT);
// Quit if necessary
- if (_vm->shouldQuit())
+ if (shouldQuit())
return;
playSound(IDI_MSA_SND_THEME);
// load game
- _game.fIntro = true;
+ _gameStateMickey.fIntro = true;
if (chooseY_N(IDO_MSA_LOAD_GAME[0], true)) {
if (loadGame()) {
- _game.iPlanet = IDI_MSA_PLANET_EARTH;
- _game.fIntro = false;
- _game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
+ _gameStateMickey.iPlanet = IDI_MSA_PLANET_EARTH;
+ _gameStateMickey.fIntro = false;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
return;
}
}
// Quit if necessary
- if (_vm->shouldQuit())
+ if (shouldQuit())
return;
// play spaceship landing scene
- _game.iPlanet = IDI_MSA_PLANET_EARTH;
- _game.iRoom = IDI_MSA_PIC_EARTH_ROAD_4;
+ _gameStateMickey.iPlanet = IDI_MSA_PLANET_EARTH;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_EARTH_ROAD_4;
drawRoom();
printRoomDesc();
// Quit if necessary
- if (_vm->shouldQuit())
+ if (shouldQuit())
return;
playSound(IDI_MSA_SND_SHIP_LAND);
@@ -1450,48 +1450,48 @@ void Mickey::intro() {
playSound(IDI_MSA_SND_PRESS_BLUE);
//Set screen to white
- _vm->_gfx->clearScreen(15);
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
+ _gfx->clearScreen(15);
+ _gfx->doUpdate();
+ _system->updateScreen();
- _vm->_system->delayMillis(IDI_MSA_ANIM_DELAY);
+ _system->delayMillis(IDI_MSA_ANIM_DELAY);
//Set back to black
- _vm->_gfx->clearScreen(0);
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
+ _gfx->clearScreen(0);
+ _gfx->doUpdate();
+ _system->updateScreen();
drawRoom();
- printDesc(_game.iRoom);
+ printDesc(_gameStateMickey.iRoom);
}
printExeMsg(IDO_MSA_INTRO);
}
-void Mickey::getItem(ENUM_MSA_ITEM iItem) {
- _game.fItem[iItem] = true;
- _game.iItem[_game.nItems++] = iItem;
- _game.oRmTxt[_game.iRoom] = 0;
+void MickeyEngine::getItem(ENUM_MSA_ITEM iItem) {
+ _gameStateMickey.fItem[iItem] = true;
+ _gameStateMickey.iItem[_gameStateMickey.nItems++] = iItem;
+ _gameStateMickey.oRmTxt[_gameStateMickey.iRoom] = 0;
playSound(IDI_MSA_SND_TAKE);
drawRoom();
}
-void Mickey::getXtal(int iStr) {
- _game.oRmTxt[_game.iRoom] = 0;
- _game.fHasXtal = true;
- _game.nXtals++;
+void MickeyEngine::getXtal(int iStr) {
+ _gameStateMickey.oRmTxt[_gameStateMickey.iRoom] = 0;
+ _gameStateMickey.fHasXtal = true;
+ _gameStateMickey.nXtals++;
playSound(IDI_MSA_SND_CRYSTAL);
drawRoom();
printDatMessage(iStr);
}
-bool Mickey::parse(int cmd, int arg) {
+bool MickeyEngine::parse(int cmd, int arg) {
switch (cmd) {
// BASIC
case IDI_MSA_ACTION_GOTO_ROOM:
- _game.iRoom = arg;
+ _gameStateMickey.iRoom = arg;
return true;
case IDI_MSA_ACTION_SHOW_INT_STR:
printLine(IDS_MSA_ERRORS[arg]);
@@ -1515,291 +1515,291 @@ bool Mickey::parse(int cmd, int arg) {
// EARTH
case IDI_MSA_ACTION_GET_ROPE:
- if (_game.iRmMenu[_game.iRoom] == 2) {
- _game.iRmObj[_game.iRoom] = IDI_MSA_OBJECT_NONE;
- _game.iRmMenu[_game.iRoom] = 3;
+ if (_gameStateMickey.iRmMenu[_gameStateMickey.iRoom] == 2) {
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = IDI_MSA_OBJECT_NONE;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 3;
getItem(IDI_MSA_ITEM_ROPE);
printLine("MICKEY TAKES THE ROPE");
} else {
- _game.iRmMenu[_game.iRoom] = 1;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
printDatMessage(11);
}
break;
case IDI_MSA_ACTION_UNTIE_ROPE:
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_EARTH_TIRE_SWING_1;
- _game.iRmObj[_game.iRoom] = 0;
- _game.iRmMenu[_game.iRoom] = 2;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_EARTH_TIRE_SWING_1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = 0;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 2;
drawRoom();
printDatMessage(12);
break;
case IDI_MSA_ACTION_GET_BONE:
- _game.iRmObj[_game.iRoom] = IDI_MSA_OBJECT_NONE;
- _game.iRmMenu[_game.iRoom] = 1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = IDI_MSA_OBJECT_NONE;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
getItem(IDI_MSA_ITEM_BONE);
printDatMessage(arg);
break;
case IDI_MSA_ACTION_GET_XTAL_EARTH:
- _game.iRmMenu[_game.iRoom] = 1;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
getXtal(arg);
break;
case IDI_MSA_ACTION_LOOK_DESK:
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmObj[_game.iRoom] = 2;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = 2;
drawRoom();
printDatMessage(arg);
break;
case IDI_MSA_ACTION_WRITE_LETTER:
- _game.iRmMenu[_game.iRoom] = 3;
- _game.iRmMenu[IDI_MSA_PIC_EARTH_MAILBOX] = 1;
- _game.iRmObj[_game.iRoom] = IDI_MSA_OBJECT_NONE;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 3;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_EARTH_MAILBOX] = 1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = IDI_MSA_OBJECT_NONE;
getItem(IDI_MSA_ITEM_LETTER);
printDatMessage(arg);
break;
case IDI_MSA_ACTION_MAIL_LETTER:
- _game.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
- _game.fItem[IDI_MSA_ITEM_LETTER] = false;
- _game.iRmMenu[_game.iRoom] = 0;
+ _gameStateMickey.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
+ _gameStateMickey.fItem[IDI_MSA_ITEM_LETTER] = false;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 0;
printDatMessage(arg);
break;
case IDI_MSA_ACTION_OPEN_MAILBOX:
- if (_game.fItemUsed[IDI_MSA_ITEM_LETTER]) {
+ if (_gameStateMickey.fItemUsed[IDI_MSA_ITEM_LETTER]) {
printDatMessage(110);
} else {
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_CUPBOARD:
- if (_game.iRmMenu[_game.iRoom]) {
- if (_game.iRmObj[_game.iRoom] == IDI_MSA_OBJECT_NONE) {
+ if (_gameStateMickey.iRmMenu[_gameStateMickey.iRoom]) {
+ if (_gameStateMickey.iRmObj[_gameStateMickey.iRoom] == IDI_MSA_OBJECT_NONE) {
printDatMessage(78);
} else {
printDatMessage(arg);
}
} else {
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_EARTH_KITCHEN_1;
- _game.iRmObj[_game.iRoom] = 3;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_EARTH_KITCHEN_1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = 3;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_FLASHLIGHT:
if (!mickeyHasItem(IDI_MSA_ITEM_FLASHLIGHT)) {
- _game.iRmObj[_game.iRoom] = IDI_MSA_OBJECT_NONE;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = IDI_MSA_OBJECT_NONE;
getItem(IDI_MSA_ITEM_FLASHLIGHT);
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_CABINET:
- if (_game.iRmMenu[_game.iRoom]) {
+ if (_gameStateMickey.iRmMenu[_gameStateMickey.iRoom]) {
printDatMessage(109);
} else {
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_EARTH_GARAGE_1;
- _game.iRmObj[_game.iRoom] = 15;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_EARTH_GARAGE_1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = 15;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_CROWBAR:
if (!mickeyHasItem(IDI_MSA_ITEM_CROWBAR)) {
- _game.iRmObj[_game.iRoom]--;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom]--;
getItem(IDI_MSA_ITEM_CROWBAR);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_WRENCH:
if (!mickeyHasItem(IDI_MSA_ITEM_WRENCH)) {
- _game.iRmObj[_game.iRoom] -= 2;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] -= 2;
getItem(IDI_MSA_ITEM_WRENCH);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_CLOSET:
- if (_game.iRmMenu[_game.iRoom]) {
+ if (_gameStateMickey.iRmMenu[_gameStateMickey.iRoom]) {
printDatMessage(99);
} else {
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_EARTH_BEDROOM_1;
- _game.iRmObj[_game.iRoom] = 7;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_EARTH_BEDROOM_1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = 7;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_MATTRESS:
if (!mickeyHasItem(IDI_MSA_ITEM_MATTRESS)) {
- _game.iRmObj[_game.iRoom]--;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom]--;
getItem(IDI_MSA_ITEM_MATTRESS);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_SCARF:
if (!mickeyHasItem(IDI_MSA_ITEM_SCARF)) {
- _game.iRmObj[_game.iRoom] -= 2;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] -= 2;
getItem(IDI_MSA_ITEM_SCARF);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_SUNGLASSES:
if (!mickeyHasItem(IDI_MSA_ITEM_SUNGLASSES)) {
- _game.iRmObj[_game.iRoom]--;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom]--;
getItem(IDI_MSA_ITEM_SUNGLASSES);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_SCALE:
if (!mickeyHasItem(IDI_MSA_ITEM_SCALE)) {
- _game.iRmMenu[IDI_MSA_PIC_VENUS_WEIGH] = 1;
- _game.iRmMenu[IDI_MSA_PIC_NEPTUNE_WEIGH] = 1;
- _game.iRmMenu[IDI_MSA_PIC_MERCURY_WEIGH] = 1;
- _game.iRmMenu[IDI_MSA_PIC_SATURN_WEIGH] = 1;
- _game.iRmMenu[IDI_MSA_PIC_PLUTO_WEIGH] = 1;
- _game.iRmMenu[IDI_MSA_PIC_JUPITER_WEIGH] = 1;
- _game.iRmMenu[IDI_MSA_PIC_MARS_WEIGH] = 1;
- _game.iRmMenu[IDI_MSA_PIC_URANUS_WEIGH] = 1;
- _game.iRmObj[_game.iRoom] -= 2;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_VENUS_WEIGH] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_NEPTUNE_WEIGH] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_MERCURY_WEIGH] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_SATURN_WEIGH] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_PLUTO_WEIGH] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_JUPITER_WEIGH] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_MARS_WEIGH] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_URANUS_WEIGH] = 1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] -= 2;
getItem(IDI_MSA_ITEM_SCALE);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GOTO_SPACESHIP:
- _game.iRoom = IDI_MSA_PIC_SHIP_AIRLOCK;
- if (_game.iPlanet != IDI_MSA_PLANET_EARTH)
+ _gameStateMickey.iRoom = IDI_MSA_PIC_SHIP_AIRLOCK;
+ if (_gameStateMickey.iPlanet != IDI_MSA_PLANET_EARTH)
insertDisk(0);
return true;
// VENUS
case IDI_MSA_ACTION_DOWN_CHASM:
- if (_game.fItem[IDI_MSA_ITEM_ROPE]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_ROPE]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
break;
case IDI_MSA_ACTION_DOWN_ROPE:
- if (_game.fItemUsed[IDI_MSA_ITEM_ROPE]) {
- _game.iRoom = IDI_MSA_PIC_VENUS_PROBE;
+ if (_gameStateMickey.fItemUsed[IDI_MSA_ITEM_ROPE]) {
+ _gameStateMickey.iRoom = IDI_MSA_PIC_VENUS_PROBE;
return true;
} else {
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_USE_ROPE:
- if (_game.fItemUsed[IDI_MSA_ITEM_ROPE]) {
+ if (_gameStateMickey.fItemUsed[IDI_MSA_ITEM_ROPE]) {
printDatMessage(22);
} else {
- _game.fItemUsed[IDI_MSA_ITEM_ROPE] = true;
- _game.fItem[IDI_MSA_ITEM_ROPE] = false;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_VENUS_CHASM_1;
+ _gameStateMickey.fItemUsed[IDI_MSA_ITEM_ROPE] = true;
+ _gameStateMickey.fItem[IDI_MSA_ITEM_ROPE] = false;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_VENUS_CHASM_1;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_HATCH:
- if (_game.fItemUsed[IDI_MSA_ITEM_WRENCH]) {
- if ((_game.iRmMenu[_game.iRoom] == 3) || (_game.iRmPic[_game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1))
+ if (_gameStateMickey.fItemUsed[IDI_MSA_ITEM_WRENCH]) {
+ if ((_gameStateMickey.iRmMenu[_gameStateMickey.iRoom] == 3) || (_gameStateMickey.iRmPic[_gameStateMickey.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1))
printDatMessage(39);
else {
- _game.iRmMenu[_game.iRoom] = 2;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_VENUS_PROBE_1;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 2;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_VENUS_PROBE_1;
drawRoom();
printDatMessage(24);
}
} else {
- if (_game.fItem[IDI_MSA_ITEM_WRENCH]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_WRENCH]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_USE_WRENCH:
- _game.fItemUsed[IDI_MSA_ITEM_WRENCH] = true;
+ _gameStateMickey.fItemUsed[IDI_MSA_ITEM_WRENCH] = true;
printDatString(arg);
- if (_game.iRmPic[_game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1) {
- _vm->clearRow(22);
+ if (_gameStateMickey.iRmPic[_gameStateMickey.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1) {
+ clearRow(22);
}
waitAnyKey();
break;
case IDI_MSA_ACTION_GET_XTAL_VENUS:
- _game.iRmMenu[_game.iRoom] = 3;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 3;
getXtal(arg);
break;
// TRITON (NEPTUNE)
case IDI_MSA_ACTION_LOOK_CASTLE:
- if (!_game.iRmMenu[_game.iRoom]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (!_gameStateMickey.iRmMenu[_gameStateMickey.iRoom]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
break;
case IDI_MSA_ACTION_ENTER_OPENING:
- if (_game.fItemUsed[IDI_MSA_ITEM_CROWBAR]) {
- _game.iRoom = IDI_MSA_PIC_NEPTUNE_CASTLE_4;
+ if (_gameStateMickey.fItemUsed[IDI_MSA_ITEM_CROWBAR]) {
+ _gameStateMickey.iRoom = IDI_MSA_PIC_NEPTUNE_CASTLE_4;
return true;
} else {
- if (_game.fItem[IDI_MSA_ITEM_CROWBAR]) {
- _game.iRmMenu[_game.iRoom] = 2;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_CROWBAR]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 2;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_USE_CROWBAR:
- _game.fItemUsed[IDI_MSA_ITEM_CROWBAR] = true;
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_NEPTUNE_ENTRANCE_1;
+ _gameStateMickey.fItemUsed[IDI_MSA_ITEM_CROWBAR] = true;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_NEPTUNE_ENTRANCE_1;
drawRoom();
printDatMessage(arg);
break;
case IDI_MSA_ACTION_GET_XTAL_NEPTUNE:
- if (_game.fHasXtal) {
+ if (_gameStateMickey.fHasXtal) {
printDatMessage(71);
} else {
- if (_game.fItem[IDI_MSA_ITEM_SCARF]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_SCARF]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_TALK_LEADER:
- _game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
printDatMessage(arg);
return true;
case IDI_MSA_ACTION_GIVE_SCARF:
- _game.iRmObj[_game.iRoom] = 18;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = 18;
getXtal(arg);
- _game.fItem[IDI_MSA_ITEM_SCARF] = false;
- _game.iRmMenu[_game.iRoom] = 0;
- _game.iRmMenu[IDI_MSA_PIC_EARTH_BEDROOM] = 2;
- _game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
+ _gameStateMickey.fItem[IDI_MSA_ITEM_SCARF] = false;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 0;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_EARTH_BEDROOM] = 2;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
return true;
// MERCURY
case IDI_MSA_ACTION_GET_XTAL_MERCURY:
- if (_game.fHasXtal) {
- _game.iRmMenu[_game.iRoom] = 2;
+ if (_gameStateMickey.fHasXtal) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 2;
printDatMessage(32);
} else {
- if (_game.fItem[IDI_MSA_ITEM_SUNGLASSES]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_SUNGLASSES]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GIVE_SUNGLASSES:
- _game.iRmObj[_game.iRoom] = 17;
- _game.iRmMenu[_game.iRoom] = 2;
- _game.fItem[IDI_MSA_ITEM_SUNGLASSES] = false;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = 17;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 2;
+ _gameStateMickey.fItem[IDI_MSA_ITEM_SUNGLASSES] = false;
getXtal(arg);
@@ -1808,30 +1808,30 @@ bool Mickey::parse(int cmd, int arg) {
// TITAN (SATURN)
case IDI_MSA_ACTION_CROSS_LAKE:
- if (_game.fItem[IDI_MSA_ITEM_MATTRESS]) {
- _game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_0] = 1;
- _game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_1] = 1;
- _game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_2] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_MATTRESS]) {
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_0] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_1] = 1;
+ _gameStateMickey.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_2] = 1;
}
printDatMessage(arg);
break;
case IDI_MSA_ACTION_USE_MATTRESS:
- _game.iRoom = IDI_MSA_PIC_SATURN_ISLAND;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_SATURN_ISLAND;
printDatMessage(arg);
return true;
case IDI_MSA_ACTION_GET_XTAL_SATURN:
- if (_game.fHasXtal) {
+ if (_gameStateMickey.fHasXtal) {
printDatMessage(29);
} else {
getXtal(arg);
}
break;
case IDI_MSA_ACTION_LEAVE_ISLAND:
- _game.iRoom = IDI_MSA_PIC_SATURN_LAKE_1;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_SATURN_LAKE_1;
printDatMessage(arg);
@@ -1840,19 +1840,19 @@ bool Mickey::parse(int cmd, int arg) {
// PLUTO
case IDI_MSA_ACTION_GET_XTAL_PLUTO:
- if (_game.fHasXtal) {
+ if (_gameStateMickey.fHasXtal) {
printDatMessage(19);
} else {
- if (_game.fItem[IDI_MSA_ITEM_BONE]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_BONE]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GIVE_BONE:
- _game.fItem[IDI_MSA_ITEM_BONE] = false;
- _game.iRmMenu[_game.iRoom] = 0;
- _game.iRmObj[_game.iRoom] = 16;
+ _gameStateMickey.fItem[IDI_MSA_ITEM_BONE] = false;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 0;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = 16;
getXtal(arg);
@@ -1862,29 +1862,29 @@ bool Mickey::parse(int cmd, int arg) {
case IDI_MSA_ACTION_GET_ROCK_0:
case IDI_MSA_ACTION_GET_ROCK_1:
- if (_game.fItem[IDI_MSA_ITEM_ROCK]) {
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_ROCK]) {
printDatMessage(38);
} else {
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmObj[_game.iRoom] = IDI_MSA_OBJECT_NONE;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom] = IDI_MSA_OBJECT_NONE;
getItem(IDI_MSA_ITEM_ROCK);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_XTAL_JUPITER:
- if (_game.fHasXtal) {
+ if (_gameStateMickey.fHasXtal) {
printDatMessage(15);
} else {
- switch (_game.nRocks) {
+ switch (_gameStateMickey.nRocks) {
case 0:
- if (_game.fItem[IDI_MSA_ITEM_ROCK]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_ROCK]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
break;
case 1:
- if (_game.fItem[IDI_MSA_ITEM_ROCK]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_ROCK]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(34);
break;
@@ -1895,47 +1895,47 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_THROW_ROCK:
- _game.fItem[IDI_MSA_ITEM_ROCK] = false;
- _game.nItems--;
- _game.iRmObj[_game.iRoom]++;
- _game.iRmMenu[_game.iRoom] = 0;
+ _gameStateMickey.fItem[IDI_MSA_ITEM_ROCK] = false;
+ _gameStateMickey.nItems--;
+ _gameStateMickey.iRmObj[_gameStateMickey.iRoom]++;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 0;
drawRoom();
- if (_game.nRocks) {
+ if (_gameStateMickey.nRocks) {
printDatMessage(37);
} else {
printDatMessage(arg);
}
- _game.nRocks++;
+ _gameStateMickey.nRocks++;
break;
// MARS
case IDI_MSA_ACTION_GO_TUBE:
- if (_game.fItem[IDI_MSA_ITEM_FLASHLIGHT]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_FLASHLIGHT]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
break;
case IDI_MSA_ACTION_USE_FLASHLIGHT:
- _game.iRoom = IDI_MSA_PIC_MARS_TUBE_1;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_MARS_TUBE_1;
printDatMessage(15);
return true;
case IDI_MSA_ACTION_PLUTO_DIG:
- if (_game.fHasXtal) {
+ if (_gameStateMickey.fHasXtal) {
printDatMessage(21);
} else {
getXtal(arg);
}
break;
case IDI_MSA_ACTION_GET_XTAL_MARS:
- if (_game.fHasXtal) {
+ if (_gameStateMickey.fHasXtal) {
printDatMessage(23);
} else {
printDatMessage(arg);
@@ -1945,29 +1945,29 @@ bool Mickey::parse(int cmd, int arg) {
// OBERON (URANUS)
case IDI_MSA_ACTION_ENTER_TEMPLE:
- _game.iRoom = IDI_MSA_PIC_URANUS_TEMPLE;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_URANUS_TEMPLE;
return true;
case IDI_MSA_ACTION_USE_CRYSTAL:
- if (_game.iRmMenu[_game.iRoom]) {
+ if (_gameStateMickey.iRmMenu[_gameStateMickey.iRoom]) {
printDatMessage(25);
} else {
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_1;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_1;
drawRoom();
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE;
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_DOOR:
- if (_game.fTempleDoorOpen) {
+ if (_gameStateMickey.fTempleDoorOpen) {
printDatMessage(36);
} else {
- _game.fTempleDoorOpen = 1;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_2;
+ _gameStateMickey.fTempleDoorOpen = 1;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_2;
drawRoom();
@@ -1975,8 +1975,8 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_ENTER_DOOR:
- if (_game.fTempleDoorOpen) {
- _game.iRoom = IDI_MSA_PIC_URANUS_STEPS;
+ if (_gameStateMickey.fTempleDoorOpen) {
+ _gameStateMickey.iRoom = IDI_MSA_PIC_URANUS_STEPS;
return true;
} else {
@@ -1984,17 +1984,17 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_GET_XTAL_URANUS:
- if (_game.fHasXtal) {
+ if (_gameStateMickey.fHasXtal) {
printDatMessage(34);
} else {
- if (_game.fItem[IDI_MSA_ITEM_CROWBAR]) {
- _game.iRmMenu[_game.iRoom] = 1;
+ if (_gameStateMickey.fItem[IDI_MSA_ITEM_CROWBAR]) {
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_USE_CROWBAR_1:
- _game.iRmMenu[_game.iRoom] = 0;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 0;
getXtal(arg);
@@ -2003,11 +2003,11 @@ bool Mickey::parse(int cmd, int arg) {
// SPACESHIP
case IDI_MSA_ACTION_GO_NORTH:
- if (_game.fShipDoorOpen) {
- if (_game.fSuit) {
+ if (_gameStateMickey.fShipDoorOpen) {
+ if (_gameStateMickey.fSuit) {
printDatMessage(45);
} else {
- _game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
return true;
}
} else {
@@ -2015,19 +2015,19 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_GO_PLANET:
- if (!_game.fShipDoorOpen) {
- if ((_game.nXtals == IDI_MSA_MAX_PLANET) && (_game.iPlanet == IDI_MSA_PLANET_EARTH))
+ if (!_gameStateMickey.fShipDoorOpen) {
+ if ((_gameStateMickey.nXtals == IDI_MSA_MAX_PLANET) && (_gameStateMickey.iPlanet == IDI_MSA_PLANET_EARTH))
gameOver();
- if ((_game.iPlanet == _game.iPlanetXtal[_game.nXtals]) || (_game.iPlanet == IDI_MSA_PLANET_EARTH)) {
- _game.fHasXtal = false;
- _game.iRoom = IDI_MSA_HOME_PLANET[_game.iPlanet];
+ if ((_gameStateMickey.iPlanet == _gameStateMickey.iPlanetXtal[_gameStateMickey.nXtals]) || (_gameStateMickey.iPlanet == IDI_MSA_PLANET_EARTH)) {
+ _gameStateMickey.fHasXtal = false;
+ _gameStateMickey.iRoom = IDI_MSA_HOME_PLANET[_gameStateMickey.iPlanet];
- if (_game.iPlanet != IDI_MSA_PLANET_EARTH)
+ if (_gameStateMickey.iPlanet != IDI_MSA_PLANET_EARTH)
insertDisk(1);
return true;
} else {
- _game.iRoom = IDI_MSA_SHIP_PLANET[_game.iPlanet];
+ _gameStateMickey.iRoom = IDI_MSA_SHIP_PLANET[_gameStateMickey.iPlanet];
return true;
}
@@ -2036,20 +2036,20 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_PRESS_BUTTON:
- if (_game.fShipDoorOpen) { // inner door open
- if (_game.iPlanet && !_game.fSuit) {
+ if (_gameStateMickey.fShipDoorOpen) { // inner door open
+ if (_gameStateMickey.iPlanet && !_gameStateMickey.fSuit) {
printDatMessage(arg);
} else {
- _game.fShipDoorOpen = false;
- _game.iRmPic[_game.iRoom]--;
+ _gameStateMickey.fShipDoorOpen = false;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom]--;
drawRoom();
printDatMessage(2);
}
} else {
- _game.fShipDoorOpen = true;
- _game.iRmPic[_game.iRoom]++;
+ _gameStateMickey.fShipDoorOpen = true;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom]++;
drawRoom();
@@ -2057,11 +2057,11 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_WEAR_SPACESUIT:
- if (_game.fSuit) {
- if (_game.fShipDoorOpen) {
- _game.fSuit = false;
- _game.iRmMenu[_game.iRoom] = 0;
- _game.iRmPic[_game.iRoom] -= 2;
+ if (_gameStateMickey.fSuit) {
+ if (_gameStateMickey.fShipDoorOpen) {
+ _gameStateMickey.fSuit = false;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 0;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] -= 2;
drawRoom();
@@ -2070,10 +2070,10 @@ bool Mickey::parse(int cmd, int arg) {
printDatMessage(3);
}
} else {
- if (_game.iPlanet) {
- _game.fSuit = true;
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmPic[_game.iRoom] += 2;
+ if (_gameStateMickey.iPlanet) {
+ _gameStateMickey.fSuit = true;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] += 2;
drawRoom();
@@ -2085,14 +2085,14 @@ bool Mickey::parse(int cmd, int arg) {
break;
case IDI_MSA_ACTION_READ_GAUGE:
printDatString(arg);
- _vm->drawStr(21, 15, IDA_DEFAULT, (const char *)IDS_MSA_TEMP_C[_game.iPlanet]);
- _vm->drawStr(21, 23, IDA_DEFAULT, (const char *)IDS_MSA_TEMP_F[_game.iPlanet]);
+ drawStr(21, 15, IDA_DEFAULT, (const char *)IDS_MSA_TEMP_C[_gameStateMickey.iPlanet]);
+ drawStr(21, 23, IDA_DEFAULT, (const char *)IDS_MSA_TEMP_F[_gameStateMickey.iPlanet]);
waitAnyKey();
break;
case IDI_MSA_ACTION_PRESS_ORANGE:
- if (_game.fFlying) {
+ if (_gameStateMickey.fFlying) {
printDatMessage(4);
} else {
playSound(IDI_MSA_SND_PRESS_ORANGE);
@@ -2101,7 +2101,7 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_PRESS_BLUE:
- if (_game.fFlying) {
+ if (_gameStateMickey.fFlying) {
printDatMessage(4);
} else {
playSound(IDI_MSA_SND_PRESS_BLUE);
@@ -2113,18 +2113,18 @@ bool Mickey::parse(int cmd, int arg) {
flipSwitch();
break;
case IDI_MSA_ACTION_PUSH_THROTTLE:
- if (_game.fFlying) {
- _game.fFlying = false;
- _game.nButtons = 0;
+ if (_gameStateMickey.fFlying) {
+ _gameStateMickey.fFlying = false;
+ _gameStateMickey.nButtons = 0;
- memset(_game.szAddr, 0, sizeof(_game.szAddr));
+ memset(_gameStateMickey.szAddr, 0, sizeof(_gameStateMickey.szAddr));
drawRoom();
printDatString(22);
- _vm->drawStr(IDI_MSA_ROW_PLANET, IDI_MSA_COL_PLANET, IDA_DEFAULT,
- (const char *)IDS_MSA_PLANETS[_game.iPlanet]);
+ drawStr(IDI_MSA_ROW_PLANET, IDI_MSA_COL_PLANET, IDA_DEFAULT,
+ (const char *)IDS_MSA_PLANETS[_gameStateMickey.iPlanet]);
waitAnyKey(true);
@@ -2134,39 +2134,39 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_PULL_THROTTLE:
- if (_game.fFlying) {
+ if (_gameStateMickey.fFlying) {
printDatMessage(18);
} else {
if (getPlanet() != -1) {
- _game.fFlying = true;
- _game.iPlanet = getPlanet();
+ _gameStateMickey.fFlying = true;
+ _gameStateMickey.iPlanet = getPlanet();
drawRoom();
printDatMessage(16);
} else {
- _game.nButtons = 0;
+ _gameStateMickey.nButtons = 0;
- memset(_game.szAddr, 0, sizeof(_game.szAddr));
+ memset(_gameStateMickey.szAddr, 0, sizeof(_gameStateMickey.szAddr));
printDatMessage(17);
}
}
break;
case IDI_MSA_ACTION_LEAVE_ROOM:
- if (_game.fFlying) {
+ if (_gameStateMickey.fFlying) {
printDatMessage(24);
} else {
- _game.iRoom = arg;
+ _gameStateMickey.iRoom = arg;
return true;
}
break;
case IDI_MSA_ACTION_OPEN_CABINET_1:
- if (_game.iRmMenu[_game.iRoom]) {
+ if (_gameStateMickey.iRmMenu[_gameStateMickey.iRoom]) {
printLine("THE CABINET IS ALREADY OPEN");
} else {
- _game.iRmMenu[_game.iRoom] = 1;
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_SHIP_KITCHEN_1;
+ _gameStateMickey.iRmMenu[_gameStateMickey.iRoom] = 1;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_SHIP_KITCHEN_1;
drawRoom();
@@ -2174,7 +2174,7 @@ bool Mickey::parse(int cmd, int arg) {
}
break;
case IDI_MSA_ACTION_READ_MAP:
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_STAR_MAP;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_STAR_MAP;
drawRoom();
@@ -2182,16 +2182,16 @@ bool Mickey::parse(int cmd, int arg) {
printDatMessage(47);
printDatMessage(48);
- _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_SHIP_BEDROOM;
+ _gameStateMickey.iRmPic[_gameStateMickey.iRoom] = IDI_MSA_PIC_SHIP_BEDROOM;
drawRoom();
break;
case IDI_MSA_ACTION_GO_WEST:
- _game.nButtons = 0;
+ _gameStateMickey.nButtons = 0;
- memset(_game.szAddr, 0, sizeof(_game.szAddr));
+ memset(_gameStateMickey.szAddr, 0, sizeof(_gameStateMickey.szAddr));
- _game.iRoom = arg;
+ _gameStateMickey.iRoom = arg;
return true;
}
@@ -2201,14 +2201,14 @@ bool Mickey::parse(int cmd, int arg) {
// Keyboard
-void Mickey::waitAnyKey(bool anim) {
+void MickeyEngine::waitAnyKey(bool anim) {
Common::Event event;
if (!anim)
- _vm->_gfx->doUpdate();
+ _gfx->doUpdate();
- while (!_vm->shouldQuit()) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
+ while (!shouldQuit()) {
+ while (_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
@@ -2223,134 +2223,138 @@ void Mickey::waitAnyKey(bool anim) {
if (anim) {
animate();
- _vm->_gfx->doUpdate();
+ _gfx->doUpdate();
}
- _vm->_system->updateScreen();
- _vm->_system->delayMillis(10);
+ _system->updateScreen();
+ _system->delayMillis(10);
}
}
// Console-related functions
-void Mickey::debugCurRoom() {
- _vm->_console->DebugPrintf("Current Room = %d\n", _game.iRoom);
+void MickeyEngine::debugCurRoom() {
+ _console->DebugPrintf("Current Room = %d\n", _gameStateMickey.iRoom);
- if (_game.iRmObj[_game.iRoom] != IDI_MSA_OBJECT_NONE) {
- _vm->_console->DebugPrintf("Object %d is in the room\n", _game.iRmObj[_game.iRoom]);
+ if (_gameStateMickey.iRmObj[_gameStateMickey.iRoom] != IDI_MSA_OBJECT_NONE) {
+ _console->DebugPrintf("Object %d is in the room\n", _gameStateMickey.iRmObj[_gameStateMickey.iRoom]);
}
}
-void Mickey::debugGotoRoom(int room) {
- _game.iRoom = room;
+void MickeyEngine::debugGotoRoom(int room) {
+ _gameStateMickey.iRoom = room;
drawRoom();
}
-Mickey::Mickey(PreAgiEngine *vm) : _vm(vm) {
- _vm->_console = new Mickey_Console(_vm, this);
+MickeyEngine::MickeyEngine(OSystem *syst, const AGIGameDescription *gameDesc) : PreAgiEngine(syst, gameDesc) {
+ _console = new MickeyConsole(this);
}
-Mickey::~Mickey() {
+MickeyEngine::~MickeyEngine() {
+ delete _console;
}
-void Mickey::init() {
+void MickeyEngine::init() {
uint8 buffer[512];
// clear game struct
- memset(&_game, 0, sizeof(_game));
- memset(&_game.iItem, IDI_MSA_OBJECT_NONE, sizeof(_game.iItem));
+ memset(&_gameStateMickey, 0, sizeof(_gameStateMickey));
+ memset(&_gameStateMickey.iItem, IDI_MSA_OBJECT_NONE, sizeof(_gameStateMickey.iItem));
// read room extended desc flags
//readExe(IDO_MSA_ROOM_TEXT, buffer, sizeof(buffer));
- //memcpy(_game.fRmTxt, buffer, sizeof(_game.fRmTxt));
+ //memcpy(_gameStateMickey.fRmTxt, buffer, sizeof(_gameStateMickey.fRmTxt));
// read room extended desc offsets
readExe(IDO_MSA_ROOM_TEXT_OFFSETS, buffer, sizeof(buffer));
- memcpy(_game.oRmTxt, buffer, sizeof(_game.oRmTxt));
+ memcpy(_gameStateMickey.oRmTxt, buffer, sizeof(_gameStateMickey.oRmTxt));
for (int i = 0; i < IDI_MSA_MAX_ROOM; i++)
- _game.oRmTxt[i] = buffer[i*2] + 256 * buffer[i*2+1];
+ _gameStateMickey.oRmTxt[i] = buffer[i*2] + 256 * buffer[i*2+1];
// read room object indices
//readExe(IDO_MSA_ROOM_OBJECT, buffer, sizeof(buffer));
- //memcpy(_game.iRmObj, buffer, sizeof(_game.iRmObj));
+ //memcpy(_gameStateMickey.iRmObj, buffer, sizeof(_gameStateMickey.iRmObj));
// read room picture indices
//readExe(IDO_MSA_ROOM_PICTURE, buffer, sizeof(buffer));
- //memcpy(_game.iRmPic, buffer, sizeof(_game.iRmPic));
+ //memcpy(_gameStateMickey.iRmPic, buffer, sizeof(_gameStateMickey.iRmPic));
// read room menu patch indices
readExe(IDO_MSA_ROOM_MENU_FIX, buffer, sizeof(buffer));
- memcpy(_game.nRmMenu, buffer, sizeof(_game.nRmMenu));
+ memcpy(_gameStateMickey.nRmMenu, buffer, sizeof(_gameStateMickey.nRmMenu));
// set room picture and room object indices
for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
- _game.iRmPic[i] = i;
- _game.iRmObj[i] = -1;
+ _gameStateMickey.iRmPic[i] = i;
+ _gameStateMickey.iRmObj[i] = -1;
}
- _game.iRmPic[IDI_MSA_PIC_SHIP_AIRLOCK] = IDI_MSA_PIC_SHIP_AIRLOCK_0;
- _game.iRmObj[IDI_MSA_PIC_EARTH_BATHROOM] = 11;
- _game.iRmObj[IDI_MSA_PIC_JUPITER_LAVA] = 21;
- _game.iRmObj[IDI_MSA_PIC_JUPITER_ROCK_0] = 20;
- _game.iRmObj[IDI_MSA_PIC_JUPITER_ROCK_1] = 19;
- _game.iRmObj[IDI_MSA_PIC_EARTH_IN_DOGHOUSE] = 1;
+ _gameStateMickey.iRmPic[IDI_MSA_PIC_SHIP_AIRLOCK] = IDI_MSA_PIC_SHIP_AIRLOCK_0;
+ _gameStateMickey.iRmObj[IDI_MSA_PIC_EARTH_BATHROOM] = 11;
+ _gameStateMickey.iRmObj[IDI_MSA_PIC_JUPITER_LAVA] = 21;
+ _gameStateMickey.iRmObj[IDI_MSA_PIC_JUPITER_ROCK_0] = 20;
+ _gameStateMickey.iRmObj[IDI_MSA_PIC_JUPITER_ROCK_1] = 19;
+ _gameStateMickey.iRmObj[IDI_MSA_PIC_EARTH_IN_DOGHOUSE] = 1;
#if 0
// DEBUG
- _game.iPlanet = IDI_MSA_PLANET_EARTH;
- _game.iRoom = IDI_MSA_PIC_SHIP_CONTROLS;
- _game.fHasXtal = true;
- _game.nXtals = 9;
- _game.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
+ _gameStateMickey.iPlanet = IDI_MSA_PLANET_EARTH;
+ _gameStateMickey.iRoom = IDI_MSA_PIC_SHIP_CONTROLS;
+ _gameStateMickey.fHasXtal = true;
+ _gameStateMickey.nXtals = 9;
+ _gameStateMickey.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
#endif
}
-void Mickey::run() {
- bool done;
+Common::Error MickeyEngine::go() {
+ init();
// Game intro
intro();
// Game loop
- while (!_vm->shouldQuit()) {
+ while (!shouldQuit()) {
drawRoom();
- if (_game.fIntro) {
- _game.fIntro = false;
+ if (_gameStateMickey.fIntro) {
+ _gameStateMickey.fIntro = false;
} else {
printRoomDesc();
}
- if (_game.iRoom == IDI_MSA_PIC_NEPTUNE_GUARD) {
- _game.iRoom = IDI_MSA_PIC_NEPTUNE_LEADER;
+ bool done;
+ if (_gameStateMickey.iRoom == IDI_MSA_PIC_NEPTUNE_GUARD) {
+ _gameStateMickey.iRoom = IDI_MSA_PIC_NEPTUNE_LEADER;
done = true;
} else {
done = false;
}
- while (!done && !_vm->shouldQuit()) {
+ while (!done && !shouldQuit()) {
// Check air supply
- if (_game.fSuit) {
- _game.nAir -= 1;
+ if (_gameStateMickey.fSuit) {
+ _gameStateMickey.nAir -= 1;
for (int i = 0; i < 4; i++) {
- if (_game.nAir == IDI_MSA_AIR_SUPPLY[i]) {
+ if (_gameStateMickey.nAir == IDI_MSA_AIR_SUPPLY[i]) {
playSound(IDI_MSA_SND_XL30);
printExeMsg(IDO_MSA_XL30_SPEAKING);
printExeMsg(IDO_MSA_AIR_SUPPLY[i]);
if (i == 3)
- return;
+ return Common::kNoError;
}
}
} else {
- _game.nAir = 50; // max air supply
+ _gameStateMickey.nAir = 50; // max air supply
}
done = checkMenu();
}
- _game.nFrame = 0;
+ _gameStateMickey.nFrame = 0;
}
gameOver();
-}
+ return Common::kNoError;
}
+
+} // End of namespace Agi
diff --git a/engines/agi/preagi_mickey.h b/engines/agi/preagi_mickey.h
index 62981375c6..673839a592 100644
--- a/engines/agi/preagi_mickey.h
+++ b/engines/agi/preagi_mickey.h
@@ -676,23 +676,25 @@ struct MSA_GAME {
class PreAgiEngine;
-class Mickey {
+class MickeyEngine : public PreAgiEngine {
public:
- Mickey(PreAgiEngine *vm);
- ~Mickey();
+ MickeyEngine(OSystem *syst, const AGIGameDescription *gameDesc);
+ ~MickeyEngine();
void init();
- void run();
+ Common::Error go();
void debugCurRoom();
void debugGotoRoom(int);
void drawPic(int);
void drawObj(ENUM_MSA_OBJECT, int, int);
+ GUI::Debugger *getDebugger() { return _console; }
+
protected:
- PreAgiEngine *_vm;
+ MickeyConsole *_console;
- MSA_GAME _game;
+ MSA_GAME _gameStateMickey;
bool _clickToMove;
int getDat(int);
@@ -741,14 +743,14 @@ protected:
bool planetIsAlreadyAssigned(int planet) {
for (int j = 0; j < IDI_MSA_MAX_PLANET; j++) {
- if (_game.iPlanetXtal[j] == planet)
+ if (_gameStateMickey.iPlanetXtal[j] == planet)
return true;
}
return false;
}
bool mickeyHasItem(int item) {
- if (_game.fItem[item]) {
+ if (_gameStateMickey.fItem[item]) {
printDatMessage(90); // Mickey already has item
return true;
} else {
diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp
index 445a9e34ff..c2e2bef66e 100644
--- a/engines/agi/preagi_troll.cpp
+++ b/engines/agi/preagi_troll.cpp
@@ -31,32 +31,35 @@
namespace Agi {
-Troll::Troll(PreAgiEngine* vm) : _vm(vm) {
+TrollEngine::TrollEngine(OSystem *syst, const AGIGameDescription *gameDesc) : PreAgiEngine(syst, gameDesc) {
+}
+
+TrollEngine::~TrollEngine() {
}
// User Interface
-void Troll::pressAnyKey(int col) {
- _vm->drawStr(24, col, kColorDefault, IDS_TRO_PRESSANYKEY);
- _vm->_gfx->doUpdate();
- _vm->getSelection(kSelAnyKey);
+void TrollEngine::pressAnyKey(int col) {
+ drawStr(24, col, kColorDefault, IDS_TRO_PRESSANYKEY);
+ _gfx->doUpdate();
+ getSelection(kSelAnyKey);
}
-void Troll::drawMenu(const char *szMenu, int iSel) {
- _vm->clearTextArea();
- _vm->drawStr(21, 0, kColorDefault, szMenu);
- _vm->drawStr(22 + iSel, 0, kColorDefault, " *");
- _vm->_gfx->doUpdate();
+void TrollEngine::drawMenu(const char *szMenu, int iSel) {
+ clearTextArea();
+ drawStr(21, 0, kColorDefault, szMenu);
+ drawStr(22 + iSel, 0, kColorDefault, " *");
+ _gfx->doUpdate();
}
-bool Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {
+bool TrollEngine::getMenuSel(const char *szMenu, int *iSel, int nSel) {
Common::Event event;
int y;
drawMenu(szMenu, *iSel);
- while (!_vm->shouldQuit()) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
+ while (!shouldQuit()) {
+ while (_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
@@ -117,8 +120,8 @@ bool Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {
break;
}
}
- _vm->_system->updateScreen();
- _vm->_system->delayMillis(10);
+ _system->updateScreen();
+ _system->delayMillis(10);
}
return true;
@@ -126,18 +129,18 @@ bool Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {
// Graphics
-void Troll::drawPic(int iPic, bool f3IsCont, bool clr, bool troll) {
- _vm->_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT);
+void TrollEngine::drawPic(int iPic, bool f3IsCont, bool clr, bool troll) {
+ _picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT);
if (clr) {
- _vm->clearScreen(0x0f, false);
- _vm->_picture->clear();
+ clearScreen(0x0f, false);
+ _picture->clear();
}
- _vm->_picture->setPictureData(_gameData + IDO_TRO_FRAMEPIC);
- _vm->_picture->drawPicture();
+ _picture->setPictureData(_gameData + IDO_TRO_FRAMEPIC);
+ _picture->drawPicture();
- _vm->_picture->setPictureData(_gameData + _pictureOffsets[iPic]);
+ _picture->setPictureData(_gameData + _pictureOffsets[iPic]);
int addFlag = 0;
@@ -145,26 +148,26 @@ void Troll::drawPic(int iPic, bool f3IsCont, bool clr, bool troll) {
addFlag = kPicFTrollMode;
if (f3IsCont) {
- _vm->_picture->setPictureFlags(kPicFf3Cont | addFlag);
+ _picture->setPictureFlags(kPicFf3Cont | addFlag);
} else {
- _vm->_picture->setPictureFlags(kPicFf3Stop | addFlag);
+ _picture->setPictureFlags(kPicFf3Stop | addFlag);
}
- _vm->_picture->drawPicture();
+ _picture->drawPicture();
- _vm->_picture->showPic();
- _vm->_gfx->doUpdate();
+ _picture->showPic();
+ _gfx->doUpdate();
}
// Game Logic
-void Troll::inventory() {
+void TrollEngine::inventory() {
char tmp[40];
int n;
- _vm->clearScreen(0x07);
- _vm->drawStr(1, 12, kColorDefault, IDS_TRO_TREASURE_0);
- _vm->drawStr(2, 12, kColorDefault, IDS_TRO_TREASURE_1);
+ clearScreen(0x07);
+ drawStr(1, 12, kColorDefault, IDS_TRO_TREASURE_0);
+ drawStr(2, 12, kColorDefault, IDS_TRO_TREASURE_1);
for (int i = 0; i < IDI_TRO_MAX_TREASURE - _treasuresLeft; i++) {
@@ -172,36 +175,36 @@ void Troll::inventory() {
sprintf(tmp, " %2d ", i + 1);
- _vm->drawStr(2 + i, 10, _items[n].bg << 4 | 0x0f, tmp);
- _vm->drawStr(2 + i, 14, _items[n].bg << 4 | _items[n].fg, _items[n].name);
+ drawStr(2 + i, 10, _items[n].bg << 4 | 0x0f, tmp);
+ drawStr(2 + i, 14, _items[n].bg << 4 | _items[n].fg, _items[n].name);
}
switch (_treasuresLeft) {
case 1:
sprintf(tmp, IDS_TRO_TREASURE_5, _treasuresLeft);
- _vm->drawStr(20, 10, kColorDefault, tmp);
+ drawStr(20, 10, kColorDefault, tmp);
break;
case 0:
- _vm->drawStr(20, 1, kColorDefault, IDS_TRO_TREASURE_6);
+ drawStr(20, 1, kColorDefault, IDS_TRO_TREASURE_6);
break;
case IDI_TRO_MAX_TREASURE:
- _vm->drawStr(3, 17, kColorDefault, IDS_TRO_TREASURE_2);
+ drawStr(3, 17, kColorDefault, IDS_TRO_TREASURE_2);
default:
sprintf(tmp, IDS_TRO_TREASURE_4, _treasuresLeft);
- _vm->drawStr(20, 10, kColorDefault, tmp);
+ drawStr(20, 10, kColorDefault, tmp);
break;
}
pressAnyKey(6);
}
-void Troll::waitAnyKeyIntro() {
+void TrollEngine::waitAnyKeyIntro() {
Common::Event event;
int iMsg = 0;
- while (!_vm->shouldQuit()) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
+ while (!shouldQuit()) {
+ while (_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
@@ -217,26 +220,26 @@ void Troll::waitAnyKeyIntro() {
case 200:
iMsg = 0;
case 0:
- _vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_2);
- _vm->_gfx->doUpdate();
+ drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_2);
+ _gfx->doUpdate();
break;
case 100:
- _vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_3);
- _vm->_gfx->doUpdate();
+ drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_3);
+ _gfx->doUpdate();
break;
}
iMsg++;
- _vm->_system->updateScreen();
- _vm->_system->delayMillis(10);
+ _system->updateScreen();
+ _system->delayMillis(10);
}
}
-void Troll::credits() {
- _vm->clearScreen(0x07);
+void TrollEngine::credits() {
+ clearScreen(0x07);
- _vm->drawStr(1, 2, kColorDefault, IDS_TRO_CREDITS_0);
+ drawStr(1, 2, kColorDefault, IDS_TRO_CREDITS_0);
int color = 10;
char str[2];
@@ -245,49 +248,49 @@ void Troll::credits() {
for (uint i = 0; i < strlen(IDS_TRO_CREDITS_1); i++) {
str[0] = IDS_TRO_CREDITS_1[i];
- _vm->drawStr(7, 19 + i, color++, str);
+ drawStr(7, 19 + i, color++, str);
if (color > 15)
color = 9;
}
- _vm->drawStr(8, 19, kColorDefault, IDS_TRO_CREDITS_2);
+ drawStr(8, 19, kColorDefault, IDS_TRO_CREDITS_2);
- _vm->drawStr(13, 11, 9, IDS_TRO_CREDITS_3);
- _vm->drawStr(15, 8, 10, IDS_TRO_CREDITS_4);
- _vm->drawStr(17, 7, 12, IDS_TRO_CREDITS_5);
- _vm->drawStr(19, 2, 14, IDS_TRO_CREDITS_6);
+ drawStr(13, 11, 9, IDS_TRO_CREDITS_3);
+ drawStr(15, 8, 10, IDS_TRO_CREDITS_4);
+ drawStr(17, 7, 12, IDS_TRO_CREDITS_5);
+ drawStr(19, 2, 14, IDS_TRO_CREDITS_6);
- _vm->_gfx->doUpdate();
+ _gfx->doUpdate();
pressAnyKey();
}
-void Troll::tutorial() {
+void TrollEngine::tutorial() {
bool done = false;
int iSel = 0;
//char szTreasure[16] = {0};
- while (!_vm->shouldQuit()) {
- _vm->clearScreen(0xFF);
+ while (!shouldQuit()) {
+ clearScreen(0xFF);
- _vm->printStr(IDS_TRO_TUTORIAL_0);
- _vm->getSelection(kSelSpace);
+ printStr(IDS_TRO_TUTORIAL_0);
+ getSelection(kSelSpace);
- _vm->clearScreen(0x55);
- _vm->setDefaultTextColor(0x0F);
+ clearScreen(0x55);
+ setDefaultTextColor(0x0F);
done = false;
- while (!done && !_vm->shouldQuit()) {
+ while (!done && !shouldQuit()) {
getMenuSel(IDS_TRO_TUTORIAL_1, &iSel, IDI_TRO_MAX_OPTION);
switch (iSel) {
case IDI_TRO_SEL_OPTION_1:
- _vm->clearScreen(0x22, false);
- _vm->_gfx->doUpdate();
+ clearScreen(0x22, false);
+ _gfx->doUpdate();
break;
case IDI_TRO_SEL_OPTION_2:
- _vm->clearScreen(0x00, false);
- _vm->_gfx->doUpdate();
+ clearScreen(0x00, false);
+ _gfx->doUpdate();
break;
case IDI_TRO_SEL_OPTION_3:
done = true;
@@ -296,102 +299,102 @@ void Troll::tutorial() {
}
// do you need more practice ?
- _vm->clearScreen(0x4F);
- _vm->drawStr(7, 4, kColorDefault, IDS_TRO_TUTORIAL_5);
- _vm->drawStr(9, 4, kColorDefault, IDS_TRO_TUTORIAL_6);
- _vm->_gfx->doUpdate();
+ clearScreen(0x4F);
+ drawStr(7, 4, kColorDefault, IDS_TRO_TUTORIAL_5);
+ drawStr(9, 4, kColorDefault, IDS_TRO_TUTORIAL_6);
+ _gfx->doUpdate();
- if (!_vm->getSelection(kSelYesNo))
+ if (!getSelection(kSelYesNo))
break;
}
// show info texts
- _vm->clearScreen(0x5F);
- _vm->drawStr(4, 1, kColorDefault, IDS_TRO_TUTORIAL_7);
- _vm->drawStr(5, 1, kColorDefault, IDS_TRO_TUTORIAL_8);
- _vm->_gfx->doUpdate();
+ clearScreen(0x5F);
+ drawStr(4, 1, kColorDefault, IDS_TRO_TUTORIAL_7);
+ drawStr(5, 1, kColorDefault, IDS_TRO_TUTORIAL_8);
+ _gfx->doUpdate();
pressAnyKey();
- _vm->clearScreen(0x2F);
- _vm->drawStr(6, 1, kColorDefault, IDS_TRO_TUTORIAL_9);
- _vm->_gfx->doUpdate();
+ clearScreen(0x2F);
+ drawStr(6, 1, kColorDefault, IDS_TRO_TUTORIAL_9);
+ _gfx->doUpdate();
pressAnyKey();
- _vm->clearScreen(0x19);
- _vm->drawStr(7, 1, kColorDefault, IDS_TRO_TUTORIAL_10);
- _vm->drawStr(8, 1, kColorDefault, IDS_TRO_TUTORIAL_11);
- _vm->_gfx->doUpdate();
+ clearScreen(0x19);
+ drawStr(7, 1, kColorDefault, IDS_TRO_TUTORIAL_10);
+ drawStr(8, 1, kColorDefault, IDS_TRO_TUTORIAL_11);
+ _gfx->doUpdate();
pressAnyKey();
- _vm->clearScreen(0x6E);
- _vm->drawStr(9, 1, kColorDefault, IDS_TRO_TUTORIAL_12);
- _vm->drawStr(10, 1, kColorDefault, IDS_TRO_TUTORIAL_13);
- _vm->_gfx->doUpdate();
+ clearScreen(0x6E);
+ drawStr(9, 1, kColorDefault, IDS_TRO_TUTORIAL_12);
+ drawStr(10, 1, kColorDefault, IDS_TRO_TUTORIAL_13);
+ _gfx->doUpdate();
pressAnyKey();
- _vm->clearScreen(0x4C);
- _vm->drawStr(11, 1, kColorDefault, IDS_TRO_TUTORIAL_14);
- _vm->drawStr(12, 1, kColorDefault, IDS_TRO_TUTORIAL_15);
- _vm->_gfx->doUpdate();
+ clearScreen(0x4C);
+ drawStr(11, 1, kColorDefault, IDS_TRO_TUTORIAL_14);
+ drawStr(12, 1, kColorDefault, IDS_TRO_TUTORIAL_15);
+ _gfx->doUpdate();
pressAnyKey();
- _vm->clearScreen(0x5D);
- _vm->drawStr(13, 1, kColorDefault, IDS_TRO_TUTORIAL_16);
- _vm->drawStr(14, 1, kColorDefault, IDS_TRO_TUTORIAL_17);
- _vm->drawStr(15, 1, kColorDefault, IDS_TRO_TUTORIAL_18);
- _vm->_gfx->doUpdate();
+ clearScreen(0x5D);
+ drawStr(13, 1, kColorDefault, IDS_TRO_TUTORIAL_16);
+ drawStr(14, 1, kColorDefault, IDS_TRO_TUTORIAL_17);
+ drawStr(15, 1, kColorDefault, IDS_TRO_TUTORIAL_18);
+ _gfx->doUpdate();
pressAnyKey();
// show treasures
- _vm->clearScreen(0x2A);
- _vm->drawStr(2, 1, kColorDefault, IDS_TRO_TUTORIAL_19);
+ clearScreen(0x2A);
+ drawStr(2, 1, kColorDefault, IDS_TRO_TUTORIAL_19);
for (int i = 0; i < IDI_TRO_MAX_TREASURE; i++)
- _vm->drawStr(19 - i, 11, kColorDefault, _items[i].name);
+ drawStr(19 - i, 11, kColorDefault, _items[i].name);
- _vm->_gfx->doUpdate();
+ _gfx->doUpdate();
pressAnyKey();
}
-void Troll::intro() {
+void TrollEngine::intro() {
// sierra on-line presents
- _vm->clearScreen(0x2F);
- _vm->drawStr(9, 10, kColorDefault, IDS_TRO_INTRO_0);
- _vm->drawStr(14, 15, kColorDefault, IDS_TRO_INTRO_1);
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
- _vm->_system->delayMillis(3200);
+ clearScreen(0x2F);
+ drawStr(9, 10, kColorDefault, IDS_TRO_INTRO_0);
+ drawStr(14, 15, kColorDefault, IDS_TRO_INTRO_1);
+ _gfx->doUpdate();
+ _system->updateScreen();
+ _system->delayMillis(3200);
CursorMan.showMouse(true);
// Draw logo
- _vm->setDefaultTextColor(0x0f);
+ setDefaultTextColor(0x0f);
drawPic(45, false, true);
- _vm->_gfx->doUpdate();
+ _gfx->doUpdate();
// wait for keypress and alternate message
waitAnyKeyIntro();
// have you played this game before?
- _vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_4);
- _vm->drawStr(23, 6, kColorDefault, IDS_TRO_INTRO_5);
- _vm->_gfx->doUpdate();
+ drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_4);
+ drawStr(23, 6, kColorDefault, IDS_TRO_INTRO_5);
+ _gfx->doUpdate();
- if (!_vm->getSelection(kSelYesNo))
+ if (!getSelection(kSelYesNo))
tutorial();
credits();
}
-void Troll::gameOver() {
+void TrollEngine::gameOver() {
// We do a check to see if the game should quit. Without this, the game show the picture, plays the
// music, and then quits. So if the game is quitting, we shouldn't run the "game over" part.
- if (_vm->shouldQuit())
+ if (shouldQuit())
return;
char szMoves[40];
- _vm->clearTextArea();
+ clearTextArea();
drawPic(42, true, true);
playTune(4, 25);
@@ -400,19 +403,19 @@ void Troll::gameOver() {
printUserMessage(33);
- _vm->clearTextArea();
+ clearTextArea();
drawPic(46, true, true);
sprintf(szMoves, IDS_TRO_GAMEOVER_0, _moves);
- _vm->drawStr(21, 1, kColorDefault, szMoves);
- _vm->drawStr(22, 1, kColorDefault, IDS_TRO_GAMEOVER_1);
- _vm->_gfx->doUpdate();
+ drawStr(21, 1, kColorDefault, szMoves);
+ drawStr(22, 1, kColorDefault, IDS_TRO_GAMEOVER_1);
+ _gfx->doUpdate();
pressAnyKey();
}
-void Troll::drawTroll() {
+void TrollEngine::drawTroll() {
for (int i = 0; i < IDI_TRO_NUM_NONTROLL; i++)
if (_currentRoom == _nonTrollRooms[i]) {
_isTrollAway = true;
@@ -422,14 +425,14 @@ void Troll::drawTroll() {
drawPic(43, false, false, true);
}
-int Troll::drawRoom(char *menu) {
+int TrollEngine::drawRoom(char *menu) {
int n = 0;
bool contFlag = false;
if (_currentRoom == 1) {
- _vm->_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT);
- _vm->clearScreen(0x00, false);
- _vm->_picture->clear();
+ _picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT);
+ clearScreen(0x00, false);
+ _picture->clear();
} else {
if (_currentRoom != 42) {
@@ -439,7 +442,7 @@ int Troll::drawRoom(char *menu) {
}
drawPic(_currentRoom, contFlag, true);
- _vm->_gfx->doUpdate();
+ _gfx->doUpdate();
if (_currentRoom == 42) {
drawPic(44, false, false); // don't clear
@@ -450,7 +453,7 @@ int Troll::drawRoom(char *menu) {
}
}
- _vm->_gfx->doUpdate();
+ _gfx->doUpdate();
char tmp[10];
strncat(menu, (char*)_gameData + _locMessagesIdx[_currentRoom], 39);
@@ -469,7 +472,7 @@ int Troll::drawRoom(char *menu) {
return n;
}
-void Troll::playTune(int tune, int len) {
+void TrollEngine::playTune(int tune, int len) {
if (!_soundOn)
return;
@@ -482,34 +485,34 @@ void Troll::playTune(int tune, int len) {
duration = READ_LE_UINT16(_gameData + ptr);
ptr += 2;
- _vm->playNote(freq, duration);
+ playNote(freq, duration);
}
}
-void Troll::pickupTreasure(int treasureId) {
+void TrollEngine::pickupTreasure(int treasureId) {
char tmp[40];
_inventory[IDI_TRO_MAX_TREASURE - _treasuresLeft] = treasureId;
if (_currentRoom != 24) {
- _vm->clearTextArea();
+ clearTextArea();
drawPic(_currentRoom, false, true);
- _vm->_gfx->doUpdate();
+ _gfx->doUpdate();
}
printUserMessage(treasureId + 16);
- _vm->clearTextArea();
+ clearTextArea();
_treasuresLeft--;
switch (_treasuresLeft) {
case 1:
- _vm->drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_7);
+ drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_7);
break;
case 0:
- _vm->drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_8);
- _vm->drawStr(23, 4, kColorDefault, IDS_TRO_TREASURE_9);
+ drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_8);
+ drawStr(23, 4, kColorDefault, IDS_TRO_TREASURE_9);
_roomStates[6] = 1;
@@ -517,20 +520,20 @@ void Troll::pickupTreasure(int treasureId) {
break;
default:
sprintf(tmp, IDS_TRO_TREASURE_3, _treasuresLeft);
- _vm->drawStr(22, 1, kColorDefault, tmp);
+ drawStr(22, 1, kColorDefault, tmp);
break;
}
pressAnyKey();
}
-void Troll::printUserMessage(int msgId) {
+void TrollEngine::printUserMessage(int msgId) {
int i;
- _vm->clearTextArea();
+ clearTextArea();
for (i = 0; i < _userMessages[msgId - 1].num; i++) {
- _vm->drawStr(21 + i, 1, kColorDefault, _userMessages[msgId - 1].msg[i]);
+ drawStr(21 + i, 1, kColorDefault, _userMessages[msgId - 1].msg[i]);
}
if (msgId == 34) {
@@ -540,7 +543,7 @@ void Troll::printUserMessage(int msgId) {
pressAnyKey();
}
-void Troll::gameLoop() {
+void TrollEngine::gameLoop() {
bool done = false;
char menu[160+5];
int currentOption, numberOfOptions;
@@ -559,7 +562,7 @@ void Troll::gameLoop() {
memset(_inventory, 0, sizeof(_inventory));
- while (!done && !_vm->shouldQuit()) {
+ while (!done && !shouldQuit()) {
*menu = 0;
currentOption = 0;
@@ -589,7 +592,7 @@ void Troll::gameLoop() {
if (_currentRoom < 6 || _treasuresLeft == 0) {
_isTrollAway = true;
} else { // make odd 1:3
- _isTrollAway = (_vm->rnd(3) != 2);
+ _isTrollAway = (rnd(3) != 2);
}
break;
case OT_GET:
@@ -634,7 +637,7 @@ void Troll::gameLoop() {
}
-void Troll::fillOffsets() {
+void TrollEngine::fillOffsets() {
int i;
for (i = 0; i < IDI_TRO_PICNUM; i++)
@@ -721,8 +724,8 @@ void Troll::fillOffsets() {
// Init
-void Troll::init() {
- _vm->_picture->setPictureVersion(AGIPIC_V15);
+void TrollEngine::init() {
+ _picture->setPictureVersion(AGIPIC_V15);
//SetScreenPar(320, 200, (char*)ibm_fontdata);
const int gaps[] = { 0x3A40, 0x4600, 0x4800, 0x5800, 0x5a00, 0x6a00,
@@ -762,12 +765,16 @@ void Troll::init() {
fillOffsets();
}
-void Troll::run() {
- while (!_vm->shouldQuit()) {
+Common::Error TrollEngine::go() {
+ init();
+
+ while (!shouldQuit()) {
intro();
gameLoop();
gameOver();
}
+
+ return Common::kNoError;
}
} // End of namespace Agi
diff --git a/engines/agi/preagi_troll.h b/engines/agi/preagi_troll.h
index d9a995072b..c14a7872c2 100644
--- a/engines/agi/preagi_troll.h
+++ b/engines/agi/preagi_troll.h
@@ -157,16 +157,14 @@ struct Item {
char name[16];
};
-class Troll {
+class TrollEngine : public PreAgiEngine {
public:
- Troll(PreAgiEngine *vm);
+ TrollEngine(OSystem *syst, const AGIGameDescription *gameDesc);
+ ~TrollEngine();
- void init();
- void run();
+ Common::Error go();
private:
- PreAgiEngine *_vm;
-
int _roomPicture;
int _treasuresLeft;
int _currentRoom;
@@ -180,6 +178,7 @@ private:
byte *_gameData;
+ void init();
void intro();
void drawPic(int iPic, bool f3IsCont, bool clear, bool troll = false);
void drawTroll();
@@ -205,9 +204,7 @@ private:
void fillOffsets();
-private:
// These are come from game data
-
int _pictureOffsets[IDI_TRO_PICNUM];
int _roomPicStartIdx[IDI_TRO_NUM_NUMROOMS];
int _roomPicDeltas[IDI_TRO_NUM_NUMROOMS];
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp
index af26fe62d0..fee8fde2b3 100644
--- a/engines/agi/preagi_winnie.cpp
+++ b/engines/agi/preagi_winnie.cpp
@@ -31,9 +31,11 @@
#include "common/savefile.h"
#include "common/textconsole.h"
+#include "audio/mididrv.h"
+
namespace Agi {
-void Winnie::parseRoomHeader(WTP_ROOM_HDR *roomHdr, byte *buffer, int len) {
+void WinnieEngine::parseRoomHeader(WTP_ROOM_HDR *roomHdr, byte *buffer, int len) {
int i;
Common::MemoryReadStreamEndian readS(buffer, len, _isBigEndian);
@@ -68,7 +70,7 @@ void Winnie::parseRoomHeader(WTP_ROOM_HDR *roomHdr, byte *buffer, int len) {
roomHdr->opt[i].ofsOpt[j] = readS.readUint16();
}
-void Winnie::parseObjHeader(WTP_OBJ_HDR *objHdr, byte *buffer, int len) {
+void WinnieEngine::parseObjHeader(WTP_OBJ_HDR *objHdr, byte *buffer, int len) {
int i;
Common::MemoryReadStreamEndian readS(buffer, len, _isBigEndian);
@@ -85,16 +87,16 @@ void Winnie::parseObjHeader(WTP_OBJ_HDR *objHdr, byte *buffer, int len) {
objHdr->ofsPic = readS.readUint16();
}
-uint32 Winnie::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) {
+uint32 WinnieEngine::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) {
Common::String fileName;
- if (_vm->getPlatform() == Common::kPlatformPC)
+ if (getPlatform() == Common::kPlatformPC)
fileName = Common::String::format(IDS_WTP_ROOM_DOS, iRoom);
- else if (_vm->getPlatform() == Common::kPlatformAmiga)
+ else if (getPlatform() == Common::kPlatformAmiga)
fileName = Common::String::format(IDS_WTP_ROOM_AMIGA, iRoom);
- else if (_vm->getPlatform() == Common::kPlatformC64)
+ else if (getPlatform() == Common::kPlatformC64)
fileName = Common::String::format(IDS_WTP_ROOM_C64, iRoom);
- else if (_vm->getPlatform() == Common::kPlatformApple2GS)
+ else if (getPlatform() == Common::kPlatformApple2GS)
fileName = Common::String::format(IDS_WTP_ROOM_APPLE, iRoom);
Common::File file;
@@ -104,7 +106,7 @@ uint32 Winnie::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) {
}
uint32 filelen = file.size();
- if (_vm->getPlatform() == Common::kPlatformC64) { // Skip the loading address
+ if (getPlatform() == Common::kPlatformC64) { // Skip the loading address
filelen -= 2;
file.seek(2, SEEK_CUR);
}
@@ -118,16 +120,16 @@ uint32 Winnie::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) {
return filelen;
}
-uint32 Winnie::readObj(int iObj, uint8 *buffer) {
+uint32 WinnieEngine::readObj(int iObj, uint8 *buffer) {
Common::String fileName;
- if (_vm->getPlatform() == Common::kPlatformPC)
+ if (getPlatform() == Common::kPlatformPC)
fileName = Common::String::format(IDS_WTP_OBJ_DOS, iObj);
- else if (_vm->getPlatform() == Common::kPlatformAmiga)
+ else if (getPlatform() == Common::kPlatformAmiga)
fileName = Common::String::format(IDS_WTP_OBJ_AMIGA, iObj);
- else if (_vm->getPlatform() == Common::kPlatformC64)
+ else if (getPlatform() == Common::kPlatformC64)
fileName = Common::String::format(IDS_WTP_OBJ_C64, iObj);
- else if (_vm->getPlatform() == Common::kPlatformApple2GS)
+ else if (getPlatform() == Common::kPlatformApple2GS)
fileName = Common::String::format(IDS_WTP_OBJ_APPLE, iObj);
Common::File file;
@@ -137,7 +139,7 @@ uint32 Winnie::readObj(int iObj, uint8 *buffer) {
}
uint32 filelen = file.size();
- if (_vm->getPlatform() == Common::kPlatformC64) { // Skip the loading address
+ if (getPlatform() == Common::kPlatformC64) { // Skip the loading address
filelen -= 2;
file.seek(2, SEEK_CUR);
}
@@ -148,7 +150,7 @@ uint32 Winnie::readObj(int iObj, uint8 *buffer) {
return filelen;
}
-void Winnie::randomize() {
+void WinnieEngine::randomize() {
int iObj = 0;
int iRoom = 0;
bool done;
@@ -157,52 +159,52 @@ void Winnie::randomize() {
done = false;
while (!done) {
- iObj = _vm->rnd(IDI_WTP_MAX_OBJ - 1);
+ iObj = rnd(IDI_WTP_MAX_OBJ - 1);
done = true;
for (int j = 0; j < IDI_WTP_MAX_OBJ_MISSING; j++) {
- if (_game.iUsedObj[j] == iObj) {
+ if (_gameStateWinnie.iUsedObj[j] == iObj) {
done = false;
break;
}
}
}
- _game.iUsedObj[i] = iObj;
+ _gameStateWinnie.iUsedObj[i] = iObj;
done = false;
while (!done) {
- iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL);
+ iRoom = rnd(IDI_WTP_MAX_ROOM_NORMAL);
done = true;
for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) {
- if (_game.iObjRoom[j] == iRoom) {
+ if (_gameStateWinnie.iObjRoom[j] == iRoom) {
done = false;
break;
}
}
}
- _game.iObjRoom[iObj] = iRoom;
+ _gameStateWinnie.iObjRoom[iObj] = iRoom;
}
}
-void Winnie::intro() {
+void WinnieEngine::intro() {
drawPic(IDS_WTP_FILE_LOGO);
- _vm->printStr(IDS_WTP_INTRO_0);
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
- _vm->_system->delayMillis(0x640);
+ printStr(IDS_WTP_INTRO_0);
+ _gfx->doUpdate();
+ _system->updateScreen();
+ _system->delayMillis(0x640);
- if (_vm->getPlatform() == Common::kPlatformAmiga)
- _vm->_gfx->clearScreen(0);
+ if (getPlatform() == Common::kPlatformAmiga)
+ _gfx->clearScreen(0);
drawPic(IDS_WTP_FILE_TITLE);
- _vm->printStr(IDS_WTP_INTRO_1);
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
- _vm->_system->delayMillis(0x640);
+ printStr(IDS_WTP_INTRO_1);
+ _gfx->doUpdate();
+ _system->updateScreen();
+ _system->delayMillis(0x640);
if (!playSound(IDI_WTP_SND_POOH_0))
return;
@@ -214,27 +216,27 @@ void Winnie::intro() {
return;
}
-int Winnie::getObjInRoom(int iRoom) {
+int WinnieEngine::getObjInRoom(int iRoom) {
for (int iObj = 1; iObj < IDI_WTP_MAX_ROOM_OBJ; iObj++)
- if (_game.iObjRoom[iObj] == iRoom)
+ if (_gameStateWinnie.iObjRoom[iObj] == iRoom)
return iObj;
return 0;
}
-void Winnie::setTakeDrop(int fCanSel[]) {
+void WinnieEngine::setTakeDrop(int fCanSel[]) {
fCanSel[IDI_WTP_SEL_TAKE] = getObjInRoom(_room);
- fCanSel[IDI_WTP_SEL_DROP] = _game.iObjHave;
+ fCanSel[IDI_WTP_SEL_DROP] = _gameStateWinnie.iObjHave;
}
-void Winnie::setFlag(int iFlag) {
- _game.fGame[iFlag] = 1;
+void WinnieEngine::setFlag(int iFlag) {
+ _gameStateWinnie.fGame[iFlag] = 1;
}
-void Winnie::clearFlag(int iFlag) {
- _game.fGame[iFlag] = 0;
+void WinnieEngine::clearFlag(int iFlag) {
+ _gameStateWinnie.fGame[iFlag] = 0;
}
-int Winnie::parser(int pc, int index, uint8 *buffer) {
+int WinnieEngine::parser(int pc, int index, uint8 *buffer) {
WTP_ROOM_HDR hdr;
int startpc = pc;
int8 opcode;
@@ -249,7 +251,7 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
// extract header from buffer
parseRoomHeader(&hdr, buffer, sizeof(WTP_ROOM_HDR));
- while (!_vm->shouldQuit()) {
+ while (!shouldQuit()) {
pc = startpc;
// check if block is to be run
@@ -259,7 +261,7 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
return IDI_WTP_PAR_OK;
fBlock = *(buffer + pc++);
- if (_game.fGame[iBlock] != fBlock)
+ if (_gameStateWinnie.fGame[iBlock] != fBlock)
return IDI_WTP_PAR_OK;
// extract text from block
@@ -292,12 +294,12 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
// extract menu string
strcpy(szMenu, (char *)(buffer + pc));
- _vm->XOR80(szMenu);
+ XOR80(szMenu);
break;
default:
// print description
printStrWinnie((char *)(buffer + pc));
- if (_vm->getSelection(kSelBackspace) == 1)
+ if (getSelection(kSelBackspace) == 1)
return IDI_WTP_PAR_OK;
else
return IDI_WTP_PAR_BACK;
@@ -314,7 +316,7 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
// get menu selection
getMenuSel(szMenu, &iSel, fCanSel);
- if (++_game.nMoves == IDI_WTP_MAX_MOVES_UNTIL_WIND)
+ if (++_gameStateWinnie.nMoves == IDI_WTP_MAX_MOVES_UNTIL_WIND)
_doWind = true;
if (_winnieEvent && (_room <= IDI_WTP_MAX_ROOM_TELEPORT)) {
@@ -356,8 +358,8 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
iDir = iSel - IDI_WTP_SEL_NORTH;
if (hdr.roomNew[iDir] == IDI_WTP_ROOM_NONE) {
- _vm->printStr(IDS_WTP_CANT_GO);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_CANT_GO);
+ getSelection(kSelAnyKey);
} else {
_room = hdr.roomNew[iDir];
return IDI_WTP_PAR_GOTO;
@@ -391,7 +393,7 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
case IDO_WTP_PRINT_MSG:
opcode = *(buffer + pc++);
printRoomStr(_room, opcode);
- _vm->getSelection(kSelAnyKey);
+ getSelection(kSelAnyKey);
break;
case IDO_WTP_PRINT_STR:
opcode = *(buffer + pc++);
@@ -416,7 +418,7 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
case IDO_WTP_WALK_MIST:
_mist--;
if (!_mist) {
- _room = _vm->rnd(IDI_WTP_MAX_ROOM_TELEPORT) + 1;
+ _room = rnd(IDI_WTP_MAX_ROOM_TELEPORT) + 1;
return IDI_WTP_PAR_GOTO;
}
break;
@@ -437,13 +439,13 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
showOwlHelp();
break;
case IDO_WTP_GOTO_RND:
- _room = _vm->rnd(IDI_WTP_MAX_ROOM_TELEPORT) + 1;
+ _room = rnd(IDI_WTP_MAX_ROOM_TELEPORT) + 1;
return IDI_WTP_PAR_GOTO;
default:
opcode = 0;
break;
}
- } while (opcode && !_vm->shouldQuit());
+ } while (opcode && !shouldQuit());
if (iNewRoom) {
_room = iNewRoom;
@@ -452,38 +454,38 @@ int Winnie::parser(int pc, int index, uint8 *buffer) {
if (iBlock == 1)
return IDI_WTP_PAR_OK;
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
+ _gfx->doUpdate();
+ _system->updateScreen();
}
return IDI_WTP_PAR_OK;
}
-void Winnie::keyHelp() {
+void WinnieEngine::keyHelp() {
playSound(IDI_WTP_SND_KEYHELP);
- _vm->printStr(IDS_WTP_HELP_0);
- _vm->getSelection(kSelAnyKey);
- _vm->printStr(IDS_WTP_HELP_1);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_HELP_0);
+ getSelection(kSelAnyKey);
+ printStr(IDS_WTP_HELP_1);
+ getSelection(kSelAnyKey);
}
-void Winnie::inventory() {
- if (_game.iObjHave)
- printObjStr(_game.iObjHave, IDI_WTP_OBJ_TAKE);
+void WinnieEngine::inventory() {
+ if (_gameStateWinnie.iObjHave)
+ printObjStr(_gameStateWinnie.iObjHave, IDI_WTP_OBJ_TAKE);
else {
- _vm->clearTextArea();
- _vm->drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, IDS_WTP_INVENTORY_0);
+ clearTextArea();
+ drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, IDS_WTP_INVENTORY_0);
}
- Common::String missing = Common::String::format(IDS_WTP_INVENTORY_1, _game.nObjMiss);
+ Common::String missing = Common::String::format(IDS_WTP_INVENTORY_1, _gameStateWinnie.nObjMiss);
- _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_MENU, IDA_DEFAULT, missing.c_str());
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen(); //TODO: Move to game's main loop
- _vm->getSelection(kSelAnyKey);
+ drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_MENU, IDA_DEFAULT, missing.c_str());
+ _gfx->doUpdate();
+ _system->updateScreen(); //TODO: Move to game's main loop
+ getSelection(kSelAnyKey);
}
-void Winnie::printObjStr(int iObj, int iStr) {
+void WinnieEngine::printObjStr(int iObj, int iStr) {
WTP_OBJ_HDR hdr;
uint8 *buffer = (uint8 *)malloc(2048);
@@ -494,7 +496,7 @@ void Winnie::printObjStr(int iObj, int iStr) {
free(buffer);
}
-bool Winnie::isRightObj(int iRoom, int iObj, int *iCode) {
+bool WinnieEngine::isRightObj(int iRoom, int iObj, int *iCode) {
WTP_ROOM_HDR roomhdr;
WTP_OBJ_HDR objhdr;
uint8 *roomdata = (uint8 *)malloc(4096);
@@ -517,212 +519,212 @@ bool Winnie::isRightObj(int iRoom, int iObj, int *iCode) {
return false;
}
-void Winnie::takeObj(int iRoom) {
- if (_game.iObjHave) {
+void WinnieEngine::takeObj(int iRoom) {
+ if (_gameStateWinnie.iObjHave) {
// player is already carrying an object, can't take
- _vm->printStr(IDS_WTP_CANT_TAKE);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_CANT_TAKE);
+ getSelection(kSelAnyKey);
} else {
// take object
int iObj = getObjInRoom(iRoom);
- _game.iObjHave = iObj;
- _game.iObjRoom[iObj] = 0;
+ _gameStateWinnie.iObjHave = iObj;
+ _gameStateWinnie.iObjRoom[iObj] = 0;
- _vm->printStr(IDS_WTP_OK);
+ printStr(IDS_WTP_OK);
playSound(IDI_WTP_SND_TAKE);
drawRoomPic();
// print object "take" string
- printObjStr(_game.iObjHave, IDI_WTP_OBJ_TAKE);
- _vm->getSelection(kSelAnyKey);
+ printObjStr(_gameStateWinnie.iObjHave, IDI_WTP_OBJ_TAKE);
+ getSelection(kSelAnyKey);
// HACK WARNING
if (iObj == 18) {
- _game.fGame[0x0d] = 1;
+ _gameStateWinnie.fGame[0x0d] = 1;
}
}
}
-void Winnie::dropObj(int iRoom) {
+void WinnieEngine::dropObj(int iRoom) {
int iCode;
if (getObjInRoom(iRoom)) {
// there already is an object in the room, can't drop
- _vm->printStr(IDS_WTP_CANT_DROP);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_CANT_DROP);
+ getSelection(kSelAnyKey);
} else {
// HACK WARNING
- if (_game.iObjHave == 18) {
- _game.fGame[0x0d] = 0;
+ if (_gameStateWinnie.iObjHave == 18) {
+ _gameStateWinnie.fGame[0x0d] = 0;
}
- if (isRightObj(iRoom, _game.iObjHave, &iCode)) {
+ if (isRightObj(iRoom, _gameStateWinnie.iObjHave, &iCode)) {
// object has been dropped in the right place
- _vm->printStr(IDS_WTP_OK);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_OK);
+ getSelection(kSelAnyKey);
playSound(IDI_WTP_SND_DROP_OK);
- printObjStr(_game.iObjHave, IDI_WTP_OBJ_DROP);
- _vm->getSelection(kSelAnyKey);
+ printObjStr(_gameStateWinnie.iObjHave, IDI_WTP_OBJ_DROP);
+ getSelection(kSelAnyKey);
// increase amount of objects returned, decrease amount of objects missing
- _game.nObjMiss--;
- _game.nObjRet++;
+ _gameStateWinnie.nObjMiss--;
+ _gameStateWinnie.nObjRet++;
// xor the dropped object with 0x80 to signify it has been dropped in the right place
for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) {
- if (_game.iUsedObj[i] == _game.iObjHave) {
- _game.iUsedObj[i] ^= 0x80;
+ if (_gameStateWinnie.iUsedObj[i] == _gameStateWinnie.iObjHave) {
+ _gameStateWinnie.iUsedObj[i] ^= 0x80;
break;
}
}
// set flag according to dropped object's id
- _game.fGame[iCode] = 1;
+ _gameStateWinnie.fGame[iCode] = 1;
// player is carrying nothing
- _game.iObjHave = 0;
+ _gameStateWinnie.iObjHave = 0;
- if (!_game.nObjMiss) {
+ if (!_gameStateWinnie.nObjMiss) {
// all objects returned, tell player to find party
playSound(IDI_WTP_SND_FANFARE);
- _vm->printStr(IDS_WTP_GAME_OVER_0);
- _vm->getSelection(kSelAnyKey);
- _vm->printStr(IDS_WTP_GAME_OVER_1);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_GAME_OVER_0);
+ getSelection(kSelAnyKey);
+ printStr(IDS_WTP_GAME_OVER_1);
+ getSelection(kSelAnyKey);
}
} else {
// drop object in the given room
- _game.iObjRoom[_game.iObjHave] = iRoom;
+ _gameStateWinnie.iObjRoom[_gameStateWinnie.iObjHave] = iRoom;
// object has been dropped in the wrong place
- _vm->printStr(IDS_WTP_WRONG_PLACE);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_WRONG_PLACE);
+ getSelection(kSelAnyKey);
playSound(IDI_WTP_SND_DROP);
drawRoomPic();
- _vm->printStr(IDS_WTP_WRONG_PLACE);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_WRONG_PLACE);
+ getSelection(kSelAnyKey);
// print object description
- printObjStr(_game.iObjHave, IDI_WTP_OBJ_DESC);
- _vm->getSelection(kSelAnyKey);
+ printObjStr(_gameStateWinnie.iObjHave, IDI_WTP_OBJ_DESC);
+ getSelection(kSelAnyKey);
- _game.iObjHave = 0;
+ _gameStateWinnie.iObjHave = 0;
}
}
}
-void Winnie::dropObjRnd() {
- if (!_game.iObjHave)
+void WinnieEngine::dropObjRnd() {
+ if (!_gameStateWinnie.iObjHave)
return;
int iRoom = 0;
bool done = false;
while (!done) {
- iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL);
+ iRoom = rnd(IDI_WTP_MAX_ROOM_NORMAL);
done = true;
if (iRoom == _room)
done = false;
for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) {
- if (_game.iObjRoom[j] == iRoom) {
+ if (_gameStateWinnie.iObjRoom[j] == iRoom) {
done = false;
}
}
}
- _game.iObjRoom[_game.iObjHave] = iRoom;
- _game.iObjHave = 0;
+ _gameStateWinnie.iObjRoom[_gameStateWinnie.iObjHave] = iRoom;
+ _gameStateWinnie.iObjHave = 0;
}
-void Winnie::wind() {
+void WinnieEngine::wind() {
int iRoom = 0;
bool done;
_doWind = 0;
- _game.nMoves = 0;
- if (!_game.nObjMiss)
+ _gameStateWinnie.nMoves = 0;
+ if (!_gameStateWinnie.nObjMiss)
return;
- _vm->printStr(IDS_WTP_WIND_0);
+ printStr(IDS_WTP_WIND_0);
playSound(IDI_WTP_SND_WIND_0);
- _vm->getSelection(kSelAnyKey);
+ getSelection(kSelAnyKey);
- _vm->printStr(IDS_WTP_WIND_1);
+ printStr(IDS_WTP_WIND_1);
playSound(IDI_WTP_SND_WIND_0);
- _vm->getSelection(kSelAnyKey);
+ getSelection(kSelAnyKey);
dropObjRnd();
// randomize positions of objects at large
for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) {
- if (!(_game.iUsedObj[i] & IDI_XOR_KEY)) {
+ if (!(_gameStateWinnie.iUsedObj[i] & IDI_XOR_KEY)) {
done = false;
while (!done) {
- iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL);
+ iRoom = rnd(IDI_WTP_MAX_ROOM_NORMAL);
done = true;
for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) {
- if (_game.iObjRoom[j] == iRoom) {
+ if (_gameStateWinnie.iObjRoom[j] == iRoom) {
done = false;
}
}
}
- _game.iObjRoom[_game.iUsedObj[i]] = iRoom;
+ _gameStateWinnie.iObjRoom[_gameStateWinnie.iUsedObj[i]] = iRoom;
}
}
}
-void Winnie::mist() {
+void WinnieEngine::mist() {
// mist length in turns is (2-5)
- _mist = _vm->rnd(4) + 2;
+ _mist = rnd(4) + 2;
_room = IDI_WTP_ROOM_MIST;
drawRoomPic();
- _vm->printStr(IDS_WTP_MIST);
+ printStr(IDS_WTP_MIST);
}
-void Winnie::tigger() {
+void WinnieEngine::tigger() {
_room = IDI_WTP_ROOM_TIGGER;
drawRoomPic();
- _vm->printStr(IDS_WTP_TIGGER);
+ printStr(IDS_WTP_TIGGER);
dropObjRnd();
}
-void Winnie::showOwlHelp() {
- if (_game.iObjHave) {
- _vm->printStr(IDS_WTP_OWL_0);
- _vm->getSelection(kSelAnyKey);
- printObjStr(_game.iObjHave, IDI_WTP_OBJ_HELP);
- _vm->getSelection(kSelAnyKey);
+void WinnieEngine::showOwlHelp() {
+ if (_gameStateWinnie.iObjHave) {
+ printStr(IDS_WTP_OWL_0);
+ getSelection(kSelAnyKey);
+ printObjStr(_gameStateWinnie.iObjHave, IDI_WTP_OBJ_HELP);
+ getSelection(kSelAnyKey);
}
if (getObjInRoom(_room)) {
- _vm->printStr(IDS_WTP_OWL_0);
- _vm->getSelection(kSelAnyKey);
+ printStr(IDS_WTP_OWL_0);
+ getSelection(kSelAnyKey);
printObjStr(getObjInRoom(_room), IDI_WTP_OBJ_HELP);
- _vm->getSelection(kSelAnyKey);
+ getSelection(kSelAnyKey);
}
}
-void Winnie::drawMenu(char *szMenu, int iSel, int fCanSel[]) {
+void WinnieEngine::drawMenu(char *szMenu, int iSel, int fCanSel[]) {
int iRow = 0, iCol = 0;
- _vm->clearTextArea();
- _vm->drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, szMenu);
+ clearTextArea();
+ drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, szMenu);
if (fCanSel[IDI_WTP_SEL_NORTH])
- _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_NSEW, IDA_DEFAULT, IDS_WTP_NSEW);
+ drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_NSEW, IDA_DEFAULT, IDS_WTP_NSEW);
if (fCanSel[IDI_WTP_SEL_TAKE])
- _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_TAKE, IDA_DEFAULT, IDS_WTP_TAKE);
+ drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_TAKE, IDA_DEFAULT, IDS_WTP_TAKE);
if (fCanSel[IDI_WTP_SEL_DROP])
- _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_DROP, IDA_DEFAULT, IDS_WTP_DROP);
+ drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_DROP, IDA_DEFAULT, IDS_WTP_DROP);
switch (iSel) {
case IDI_WTP_SEL_OPT_1:
@@ -756,26 +758,26 @@ void Winnie::drawMenu(char *szMenu, int iSel, int fCanSel[]) {
iCol = IDI_WTP_COL_DROP;
break;
}
- _vm->drawStr(iRow, iCol - 1, IDA_DEFAULT, ">");
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen(); //TODO: Move to game's main loop
+ drawStr(iRow, iCol - 1, IDA_DEFAULT, ">");
+ _gfx->doUpdate();
+ _system->updateScreen(); //TODO: Move to game's main loop
}
-void Winnie::incMenuSel(int *iSel, int fCanSel[]) {
+void WinnieEngine::incMenuSel(int *iSel, int fCanSel[]) {
do {
*iSel += 1;
if (*iSel > IDI_WTP_SEL_DROP) *iSel = IDI_WTP_SEL_OPT_1;
} while (!fCanSel[*iSel]);
}
-void Winnie::decMenuSel(int *iSel, int fCanSel[]) {
+void WinnieEngine::decMenuSel(int *iSel, int fCanSel[]) {
do {
*iSel -= 1;
if (*iSel < IDI_WTP_SEL_OPT_1) *iSel = IDI_WTP_SEL_DROP;
} while (!fCanSel[*iSel]);
}
-void Winnie::getMenuMouseSel(int *iSel, int fCanSel[], int x, int y) {
+void WinnieEngine::getMenuMouseSel(int *iSel, int fCanSel[], int x, int y) {
switch (y) {
case IDI_WTP_ROW_OPTION_1:
case IDI_WTP_ROW_OPTION_2:
@@ -793,7 +795,7 @@ void Winnie::getMenuMouseSel(int *iSel, int fCanSel[], int x, int y) {
}
}
-void Winnie::makeSel(int *iSel, int fCanSel[]) {
+void WinnieEngine::makeSel(int *iSel, int fCanSel[]) {
if (fCanSel[*iSel])
return;
@@ -801,7 +803,7 @@ void Winnie::makeSel(int *iSel, int fCanSel[]) {
clrMenuSel(iSel, fCanSel);
}
-void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
+void WinnieEngine::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
Common::Event event;
int x, y;
@@ -811,8 +813,8 @@ void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
// Show the mouse cursor for the menu
CursorMan.showMouse(true);
- while (!_vm->shouldQuit()) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
+ while (!shouldQuit()) {
+ while (_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
@@ -824,15 +826,15 @@ void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
// Change cursor
if (fCanSel[IDI_WTP_SEL_NORTH] && hotspotNorth.contains(event.mouse.x, event.mouse.y)) {
- _vm->_gfx->setCursorPalette(true);
+ _gfx->setCursorPalette(true);
} else if (fCanSel[IDI_WTP_SEL_SOUTH] && hotspotSouth.contains(event.mouse.x, event.mouse.y)) {
- _vm->_gfx->setCursorPalette(true);
+ _gfx->setCursorPalette(true);
} else if (fCanSel[IDI_WTP_SEL_WEST] && hotspotWest.contains(event.mouse.x, event.mouse.y)) {
- _vm->_gfx->setCursorPalette(true);
+ _gfx->setCursorPalette(true);
} else if (fCanSel[IDI_WTP_SEL_EAST] && hotspotEast.contains(event.mouse.x, event.mouse.y)) {
- _vm->_gfx->setCursorPalette(true);
+ _gfx->setCursorPalette(true);
} else {
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
}
break;
@@ -841,25 +843,25 @@ void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
if (fCanSel[IDI_WTP_SEL_NORTH] && hotspotNorth.contains(event.mouse.x, event.mouse.y)) {
*iSel = IDI_WTP_SEL_NORTH;
makeSel(iSel, fCanSel);
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
return;
} else if (fCanSel[IDI_WTP_SEL_SOUTH] && hotspotSouth.contains(event.mouse.x, event.mouse.y)) {
*iSel = IDI_WTP_SEL_SOUTH;
makeSel(iSel, fCanSel);
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
return;
} else if (fCanSel[IDI_WTP_SEL_WEST] && hotspotWest.contains(event.mouse.x, event.mouse.y)) {
*iSel = IDI_WTP_SEL_WEST;
makeSel(iSel, fCanSel);
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
return;
} else if (fCanSel[IDI_WTP_SEL_EAST] && hotspotEast.contains(event.mouse.x, event.mouse.y)) {
*iSel = IDI_WTP_SEL_EAST;
makeSel(iSel, fCanSel);
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
return;
} else {
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
}
switch (*iSel) {
@@ -896,9 +898,9 @@ void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
incMenuSel(iSel, fCanSel);
break;
case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL) && _vm->_console) {
- _vm->_console->attach();
- _vm->_console->onFrame();
+ if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL) && _console) {
+ _console->attach();
+ _console->onFrame();
continue;
}
@@ -944,7 +946,7 @@ void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
break;
case Common::KEYCODE_s:
if (event.kbd.flags & Common::KBD_CTRL) {
- _vm->flipflag(fSoundOn);
+ flipflag(fSoundOn);
} else {
*iSel = IDI_WTP_SEL_SOUTH;
makeSel(iSel, fCanSel);
@@ -1005,24 +1007,24 @@ void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
}
}
-void Winnie::gameLoop() {
+void WinnieEngine::gameLoop() {
WTP_ROOM_HDR hdr;
uint8 *roomdata = (uint8 *)malloc(4096);
int iBlock;
phase0:
- if (!_game.nObjMiss && (_room == IDI_WTP_ROOM_PICNIC))
+ if (!_gameStateWinnie.nObjMiss && (_room == IDI_WTP_ROOM_PICNIC))
_room = IDI_WTP_ROOM_PARTY;
readRoom(_room, roomdata, hdr);
drawRoomPic();
- _vm->_gfx->doUpdate();
- _vm->_system->updateScreen();
+ _gfx->doUpdate();
+ _system->updateScreen();
phase1:
if (getObjInRoom(_room)) {
printObjStr(getObjInRoom(_room), IDI_WTP_OBJ_DESC);
- _vm->getSelection(kSelAnyKey);
+ getSelection(kSelAnyKey);
}
phase2:
@@ -1031,7 +1033,7 @@ phase2:
goto phase1;
}
- while (!_vm->shouldQuit()) {
+ while (!shouldQuit()) {
for (iBlock = 0; iBlock < IDI_WTP_MAX_BLOCK; iBlock++) {
switch (parser(hdr.ofsBlock[iBlock] - _roomOffset, iBlock, roomdata)) {
case IDI_WTP_PAR_GOTO:
@@ -1047,10 +1049,10 @@ phase2:
free(roomdata);
}
-void Winnie::drawPic(const char *szName) {
+void WinnieEngine::drawPic(const char *szName) {
Common::String fileName = szName;
- if (_vm->getPlatform() != Common::kPlatformAmiga)
+ if (getPlatform() != Common::kPlatformAmiga)
fileName += ".pic";
Common::File file;
@@ -1065,13 +1067,13 @@ void Winnie::drawPic(const char *szName) {
file.read(buffer, size);
file.close();
- _vm->_picture->decodePicture(buffer, size, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
- _vm->_picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->decodePicture(buffer, size, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
free(buffer);
}
-void Winnie::drawObjPic(int iObj, int x0, int y0) {
+void WinnieEngine::drawObjPic(int iObj, int x0, int y0) {
if (!iObj)
return;
@@ -1080,28 +1082,28 @@ void Winnie::drawObjPic(int iObj, int x0, int y0) {
uint32 objSize = readObj(iObj, buffer);
parseObjHeader(&objhdr, buffer, sizeof(WTP_OBJ_HDR));
- _vm->_picture->setOffset(x0, y0);
- _vm->_picture->decodePicture(buffer + objhdr.ofsPic - _objOffset, objSize, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
- _vm->_picture->setOffset(0, 0);
- _vm->_picture->showPic(10, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->setOffset(x0, y0);
+ _picture->decodePicture(buffer + objhdr.ofsPic - _objOffset, objSize, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->setOffset(0, 0);
+ _picture->showPic(10, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
free(buffer);
}
-void Winnie::drawRoomPic() {
+void WinnieEngine::drawRoomPic() {
WTP_ROOM_HDR roomhdr;
uint8 *buffer = (uint8 *)malloc(4096);
int iObj = getObjInRoom(_room);
// clear gfx screen
- _vm->_gfx->clearScreen(0);
+ _gfx->clearScreen(0);
// read room picture
readRoom(_room, buffer, roomhdr);
// draw room picture
- _vm->_picture->decodePicture(buffer + roomhdr.ofsPic - _roomOffset, 4096, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
- _vm->_picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->decodePicture(buffer + roomhdr.ofsPic - _roomOffset, 4096, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
// draw object picture
drawObjPic(iObj, IDI_WTP_PIC_X0 + roomhdr.objX, IDI_WTP_PIC_Y0 + roomhdr.objY);
@@ -1109,21 +1111,68 @@ void Winnie::drawRoomPic() {
free(buffer);
}
-bool Winnie::playSound(ENUM_WTP_SOUND iSound) {
- //TODO
- warning ("STUB: playSound(%d)", iSound);
- return 1;
+bool WinnieEngine::playSound(ENUM_WTP_SOUND iSound) {
+ // TODO: Only DOS sound is supported, currently
+ if (getPlatform() != Common::kPlatformPC) {
+ warning("STUB: playSound(%d)", iSound);
+ return false;
+ }
+
+ Common::String fileName = Common::String::format(IDS_WTP_SND_DOS, iSound);
+
+ Common::File file;
+ if (!file.open(fileName))
+ return false;
+
+ uint32 size = file.size();
+ byte *data = new byte[size];
+ file.read(data, size);
+ file.close();
+
+ _game.sounds[0] = AgiSound::createFromRawResource(data, size, 0, *_sound, _soundemu);
+ _sound->startSound(0, 0);
+
+ bool cursorShowing = CursorMan.showMouse(false);
+ _system->updateScreen();
+
+ // Loop until the sound is done
+ bool skippedSound = false;
+ while (!shouldQuit() && _game.sounds[0]->isPlaying()) {
+ Common::Event event;
+ while (_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ _sound->stopSound();
+ skippedSound = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ _system->delayMillis(10);
+ }
+
+ if (cursorShowing) {
+ CursorMan.showMouse(true);
+ _system->updateScreen();
+ }
+
+ delete _game.sounds[0];
+ _game.sounds[0] = 0;
+
+ return !shouldQuit() && !skippedSound;
}
-void Winnie::clrMenuSel(int *iSel, int fCanSel[]) {
+void WinnieEngine::clrMenuSel(int *iSel, int fCanSel[]) {
*iSel = IDI_WTP_SEL_OPT_1;
while (!fCanSel[*iSel]) {
*iSel += 1;
}
- _vm->_gfx->setCursorPalette(false);
+ _gfx->setCursorPalette(false);
}
-void Winnie::printRoomStr(int iRoom, int iStr) {
+void WinnieEngine::printRoomStr(int iRoom, int iStr) {
WTP_ROOM_HDR hdr;
uint8 *buffer = (uint8 *)malloc(4096);
@@ -1133,23 +1182,23 @@ void Winnie::printRoomStr(int iRoom, int iStr) {
free(buffer);
}
-void Winnie::gameOver() {
+void WinnieEngine::gameOver() {
// sing the Pooh song forever
- while (!_vm->shouldQuit()) {
- _vm->printStr(IDS_WTP_SONG_0);
+ while (!shouldQuit()) {
+ printStr(IDS_WTP_SONG_0);
playSound(IDI_WTP_SND_POOH_0);
- _vm->printStr(IDS_WTP_SONG_1);
+ printStr(IDS_WTP_SONG_1);
playSound(IDI_WTP_SND_POOH_1);
- _vm->printStr(IDS_WTP_SONG_2);
+ printStr(IDS_WTP_SONG_2);
playSound(IDI_WTP_SND_POOH_2);
- _vm->getSelection(kSelAnyKey);
+ getSelection(kSelAnyKey);
}
}
-void Winnie::saveGame() {
+void WinnieEngine::saveGame() {
int i = 0;
- Common::OutSaveFile *outfile = _vm->getSaveFileMan()->openForSaving(IDS_WTP_FILE_SAVEGAME);
+ Common::OutSaveFile *outfile = getSaveFileMan()->openForSaving(IDS_WTP_FILE_SAVEGAME);
if (!outfile)
return;
@@ -1157,20 +1206,20 @@ void Winnie::saveGame() {
outfile->writeUint32BE(MKTAG('W','I','N','N')); // header
outfile->writeByte(WTP_SAVEGAME_VERSION);
- outfile->writeByte(_game.fSound);
- outfile->writeByte(_game.nMoves);
- outfile->writeByte(_game.nObjMiss);
- outfile->writeByte(_game.nObjRet);
- outfile->writeByte(_game.iObjHave);
+ outfile->writeByte(_gameStateWinnie.fSound);
+ outfile->writeByte(_gameStateWinnie.nMoves);
+ outfile->writeByte(_gameStateWinnie.nObjMiss);
+ outfile->writeByte(_gameStateWinnie.nObjRet);
+ outfile->writeByte(_gameStateWinnie.iObjHave);
for (i = 0; i < IDI_WTP_MAX_FLAG; i++)
- outfile->writeByte(_game.fGame[i]);
+ outfile->writeByte(_gameStateWinnie.fGame[i]);
for (i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++)
- outfile->writeByte(_game.iUsedObj[i]);
+ outfile->writeByte(_gameStateWinnie.iUsedObj[i]);
for (i = 0; i < IDI_WTP_MAX_ROOM_OBJ; i++)
- outfile->writeByte(_game.iObjRoom[i]);
+ outfile->writeByte(_gameStateWinnie.iObjRoom[i]);
outfile->finalize();
@@ -1180,11 +1229,11 @@ void Winnie::saveGame() {
delete outfile;
}
-void Winnie::loadGame() {
+void WinnieEngine::loadGame() {
int saveVersion = 0;
int i = 0;
- Common::InSaveFile *infile = _vm->getSaveFileMan()->openForLoading(IDS_WTP_FILE_SAVEGAME);
+ Common::InSaveFile *infile = getSaveFileMan()->openForLoading(IDS_WTP_FILE_SAVEGAME);
if (!infile)
return;
@@ -1194,11 +1243,11 @@ void Winnie::loadGame() {
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);
- _game.fSound = infile->readByte();
- _game.nMoves = infile->readByte();
- _game.nObjMiss = infile->readByte();
- _game.nObjRet = infile->readByte();
- _game.iObjHave = infile->readByte();
+ _gameStateWinnie.fSound = infile->readByte();
+ _gameStateWinnie.nMoves = infile->readByte();
+ _gameStateWinnie.nObjMiss = infile->readByte();
+ _gameStateWinnie.nObjRet = infile->readByte();
+ _gameStateWinnie.iObjHave = infile->readByte();
} else {
// This is probably a save from the original interpreter, throw a warning and attempt
// to read it as LE
@@ -1211,31 +1260,31 @@ void Winnie::loadGame() {
infile->readUint16LE(); // skip unused field
infile->readByte(); // first 8 bits of fSound
- _game.fSound = infile->readByte();
+ _gameStateWinnie.fSound = infile->readByte();
infile->readByte(); // first 8 bits of nMoves
- _game.nMoves = infile->readByte();
+ _gameStateWinnie.nMoves = infile->readByte();
infile->readByte(); // first 8 bits of nObjMiss
- _game.nObjMiss = infile->readByte();
+ _gameStateWinnie.nObjMiss = infile->readByte();
infile->readByte(); // first 8 bits of nObjRet
- _game.nObjRet = infile->readByte();
+ _gameStateWinnie.nObjRet = infile->readByte();
infile->readUint16LE(); // skip unused field
infile->readUint16LE(); // skip unused field
infile->readUint16LE(); // skip unused field
infile->readByte(); // first 8 bits of iObjHave
- _game.iObjHave = infile->readByte();
+ _gameStateWinnie.iObjHave = infile->readByte();
infile->readUint16LE(); // skip unused field
infile->readUint16LE(); // skip unused field
infile->readUint16LE(); // skip unused field
}
for (i = 0; i < IDI_WTP_MAX_FLAG; i++)
- _game.fGame[i] = infile->readByte();
+ _gameStateWinnie.fGame[i] = infile->readByte();
for (i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++)
- _game.iUsedObj[i] = infile->readByte();
+ _gameStateWinnie.iUsedObj[i] = infile->readByte();
for (i = 0; i < IDI_WTP_MAX_ROOM_OBJ; i++)
- _game.iObjRoom[i] = infile->readByte();
+ _gameStateWinnie.iObjRoom[i] = infile->readByte();
// Note that saved games from the original interpreter have 2 more 16-bit fields here
// which are ignored
@@ -1243,37 +1292,59 @@ void Winnie::loadGame() {
delete infile;
}
-void Winnie::printStrWinnie(char *szMsg) {
- if (_vm->getPlatform() != Common::kPlatformAmiga)
- _vm->printStrXOR(szMsg);
+void WinnieEngine::printStrWinnie(char *szMsg) {
+ if (getPlatform() != Common::kPlatformAmiga)
+ printStrXOR(szMsg);
else
- _vm->printStr(szMsg);
+ printStr(szMsg);
}
// Console-related functions
-void Winnie::debugCurRoom() {
- _vm->_console->DebugPrintf("Current Room = %d\n", _room);
+void WinnieEngine::debugCurRoom() {
+ _console->DebugPrintf("Current Room = %d\n", _room);
+}
+
+WinnieEngine::WinnieEngine(OSystem *syst, const AGIGameDescription *gameDesc) : PreAgiEngine(syst, gameDesc) {
+ _console = new WinnieConsole(this);
}
-Winnie::Winnie(PreAgiEngine* vm) : _vm(vm) {
- _vm->_console = new Winnie_Console(_vm, this);
+WinnieEngine::~WinnieEngine() {
+ delete _console;
}
-void Winnie::init() {
- memset(&_game, 0, sizeof(_game));
- _game.fSound = 1;
- _game.nObjMiss = IDI_WTP_MAX_OBJ_MISSING;
- _game.nObjRet = 0;
- _game.fGame[0] = 1;
- _game.fGame[1] = 1;
+void WinnieEngine::init() {
+ // Initialize sound
+
+ switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK|MDT_PCJR))) {
+ case MT_PCSPK:
+ _soundemu = SOUND_EMU_PC;
+ break;
+ case MT_PCJR:
+ _soundemu = SOUND_EMU_PCJR;
+ break;
+ default:
+ _soundemu = SOUND_EMU_NONE;
+ break;
+ }
+
+ _sound = new SoundMgr(this, _mixer);
+ _sound->initSound();
+ setflag(fSoundOn, true); // enable sound
+
+ memset(&_gameStateWinnie, 0, sizeof(_gameStateWinnie));
+ _gameStateWinnie.fSound = 1;
+ _gameStateWinnie.nObjMiss = IDI_WTP_MAX_OBJ_MISSING;
+ _gameStateWinnie.nObjRet = 0;
+ _gameStateWinnie.fGame[0] = 1;
+ _gameStateWinnie.fGame[1] = 1;
_room = IDI_WTP_ROOM_HOME;
_mist = -1;
_doWind = false;
_winnieEvent = false;
- if (_vm->getPlatform() != Common::kPlatformAmiga) {
+ if (getPlatform() != Common::kPlatformAmiga) {
_isBigEndian = false;
_roomOffset = IDI_WTP_OFS_ROOM;
_objOffset = IDI_WTP_OFS_OBJ;
@@ -1283,8 +1354,8 @@ void Winnie::init() {
_objOffset = 0;
}
- if (_vm->getPlatform() == Common::kPlatformC64 || _vm->getPlatform() == Common::kPlatformApple2GS)
- _vm->_picture->setPictureVersion(AGIPIC_C64);
+ if (getPlatform() == Common::kPlatformC64 || getPlatform() == Common::kPlatformApple2GS)
+ _picture->setPictureVersion(AGIPIC_C64);
hotspotNorth = Common::Rect(20, 0, (IDI_WTP_PIC_WIDTH + 10) * 2, 10);
hotspotSouth = Common::Rect(20, IDI_WTP_PIC_HEIGHT - 10, (IDI_WTP_PIC_WIDTH + 10) * 2, IDI_WTP_PIC_HEIGHT);
@@ -1292,11 +1363,17 @@ void Winnie::init() {
hotspotWest = Common::Rect(20, 0, 30, IDI_WTP_PIC_HEIGHT);
}
-void Winnie::run() {
+Common::Error WinnieEngine::go() {
+ init();
randomize();
- if (_vm->getPlatform() != Common::kPlatformC64 && _vm->getPlatform() != Common::kPlatformApple2GS)
+
+ // The intro is not supported on these platforms yet
+ if (getPlatform() != Common::kPlatformC64 && getPlatform() != Common::kPlatformApple2GS)
intro();
+
gameLoop();
-}
+ return Common::kNoError;
}
+
+} // End of namespace AGI
diff --git a/engines/agi/preagi_winnie.h b/engines/agi/preagi_winnie.h
index 002eada65c..96ae65997e 100644
--- a/engines/agi/preagi_winnie.h
+++ b/engines/agi/preagi_winnie.h
@@ -281,19 +281,22 @@ struct WTP_SAVE_GAME {
class PreAgiEngine;
-class Winnie {
+class WinnieEngine : public PreAgiEngine {
public:
- Winnie(PreAgiEngine *vm);
+ WinnieEngine(OSystem *syst, const AGIGameDescription *gameDesc);
+ ~WinnieEngine();
void init();
- void run();
+ Common::Error go();
void debugCurRoom();
+ GUI::Debugger *getDebugger() { return _console; }
+
private:
- PreAgiEngine *_vm;
+ WinnieConsole *_console;
- WTP_SAVE_GAME _game;
+ WTP_SAVE_GAME _gameStateWinnie;
int _room;
int _mist;
bool _doWind;
@@ -355,5 +358,3 @@ private:
} // End of namespace Agi
#endif
-
-
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index dae3dd42c1..28dd0a53dd 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -290,11 +290,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) {
if (saveVersion >= 4) {
// We don't need the thumbnail here, so just read it and discard it
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- Graphics::loadThumbnail(*in, *thumbnail);
- delete thumbnail;
- thumbnail = 0;
+ Graphics::skipThumbnail(*in);
in->readUint32BE(); // save date
in->readUint16BE(); // save time
@@ -478,8 +474,8 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) {
v->cycleTimeCount = in->readByte();
v->direction = in->readByte();
- v->motion = in->readByte();
- v->cycle = in->readByte();
+ v->motion = (MotionType)in->readByte();
+ v->cycle = (CycleType)in->readByte();
v->priority = in->readByte();
v->flags = in->readUint16BE();
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index f2d7af32da..ca3d799ecc 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -41,6 +41,10 @@ AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, S
return NULL;
uint16 type = READ_LE_UINT16(data);
+ // For V1 sound resources
+ if (type != AGI_SOUND_SAMPLE && (type & 0xFF) == 0x01)
+ return new PCjrSound(data, len, resnum, manager);
+
switch (type) { // Create a sound object based on the type
case AGI_SOUND_SAMPLE:
return new IIgsSample(data, len, resnum, manager);
@@ -62,6 +66,11 @@ PCjrSound::PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A
_data = data; // Save the resource pointer
_len = len; // Save the resource's length
_type = READ_LE_UINT16(data); // Read sound resource's type
+
+ // Detect V1 sound resources
+ if ((_type & 0xFF) == 0x01)
+ _type = AGI_SOUND_4CHN;
+
_isValid = (_type == AGI_SOUND_4CHN) && (_data != NULL) && (_len >= 2);
if (!_isValid) // Check for errors
@@ -127,7 +136,12 @@ void SoundMgr::startSound(int resnum, int flag) {
// Reset the flag
_endflag = flag;
- _vm->setflag(_endflag, false);
+
+ if (_vm->getVersion() < 0x2000) {
+ _vm->_game.vars[_endflag] = 0;
+ } else {
+ _vm->setflag(_endflag, false);
+ }
}
void SoundMgr::stopSound() {
@@ -142,8 +156,13 @@ void SoundMgr::stopSound() {
// This is probably not needed most of the time, but there also should
// not be any harm doing it, so do it anyway.
- if (_endflag != -1)
- _vm->setflag(_endflag, true);
+ if (_endflag != -1) {
+ if (_vm->getVersion() < 0x2000) {
+ _vm->_game.vars[_endflag] = 1;
+ } else {
+ _vm->setflag(_endflag, true);
+ }
+ }
_endflag = -1;
}
@@ -168,7 +187,7 @@ void SoundMgr::soundIsFinished() {
_endflag = -1;
}
-SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) {
+SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) {
_vm = agi;
_endflag = -1;
_playingSound = -1;
diff --git a/engines/agi/sound.h b/engines/agi/sound.h
index 0ee19878c4..6fd8dd516e 100644
--- a/engines/agi/sound.h
+++ b/engines/agi/sound.h
@@ -71,7 +71,7 @@ class SoundMgr;
class SoundGen {
public:
- SoundGen(AgiEngine *vm, Audio::Mixer *pMixer) : _vm(vm), _mixer(pMixer) {
+ SoundGen(AgiBase *vm, Audio::Mixer *pMixer) : _vm(vm), _mixer(pMixer) {
_sampleRate = pMixer->getOutputRate();
}
@@ -80,7 +80,7 @@ public:
virtual void play(int resnum) = 0;
virtual void stop(void) = 0;
- AgiEngine *_vm;
+ AgiBase *_vm;
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
@@ -122,6 +122,8 @@ public:
~PCjrSound() { free(_data); }
virtual uint16 type() { return _type; }
const uint8 *getVoicePointer(uint voiceNum);
+ uint8 *getData() { return _data; }
+ uint32 getLength() { return _len; }
protected:
uint8 *_data; ///< Raw sound resource data
uint32 _len; ///< Length of the raw sound resource
@@ -131,7 +133,7 @@ protected:
class SoundMgr {
public:
- SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer);
+ SoundMgr(AgiBase *agi, Audio::Mixer *pMixer);
~SoundMgr();
void setVolume(uint8 volume);
@@ -147,7 +149,7 @@ public:
private:
int _endflag;
- AgiEngine *_vm;
+ AgiBase *_vm;
SoundGen *_soundGen;
diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp
index 38e256aa4b..c5cfa125d6 100644
--- a/engines/agi/sound_2gs.cpp
+++ b/engines/agi/sound_2gs.cpp
@@ -33,7 +33,7 @@
namespace Agi {
-SoundGen2GS::SoundGen2GS(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
+SoundGen2GS::SoundGen2GS(AgiBase *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
// Allocate memory for the wavetable
_wavetable = new int8[SIERRASTANDARD_SIZE];
diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h
index 9123e18415..89ffc3fe11 100644
--- a/engines/agi/sound_2gs.h
+++ b/engines/agi/sound_2gs.h
@@ -215,7 +215,7 @@ private:
class SoundGen2GS : public SoundGen, public Audio::AudioStream {
public:
- SoundGen2GS(AgiEngine *vm, Audio::Mixer *pMixer);
+ SoundGen2GS(AgiBase *vm, Audio::Mixer *pMixer);
~SoundGen2GS();
void play(int resnum);
diff --git a/engines/agi/sound_coco3.cpp b/engines/agi/sound_coco3.cpp
index 281f2cb2d4..64818e4e34 100644
--- a/engines/agi/sound_coco3.cpp
+++ b/engines/agi/sound_coco3.cpp
@@ -34,7 +34,7 @@ static int cocoFrequencies[] = {
2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951
};
-SoundGenCoCo3::SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
+SoundGenCoCo3::SoundGenCoCo3(AgiBase *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
}
SoundGenCoCo3::~SoundGenCoCo3() {
diff --git a/engines/agi/sound_coco3.h b/engines/agi/sound_coco3.h
index 7058b770f5..d24acf5cc5 100644
--- a/engines/agi/sound_coco3.h
+++ b/engines/agi/sound_coco3.h
@@ -42,7 +42,7 @@ struct CoCoNote {
class SoundGenCoCo3 : public SoundGen, public Audio::AudioStream {
public:
- SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer);
+ SoundGenCoCo3(AgiBase *vm, Audio::Mixer *pMixer);
~SoundGenCoCo3();
void play(int resnum);
diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp
index 0cbaa4af86..47d354093b 100644
--- a/engines/agi/sound_midi.cpp
+++ b/engines/agi/sound_midi.cpp
@@ -69,7 +69,7 @@ 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), _isGM(false) {
+SoundGenMIDI::SoundGenMIDI(AgiBase *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _isGM(false) {
MidiPlayer::createDriver(MDT_MIDI | MDT_ADLIB);
int ret = _driver->open();
diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h
index 92a4002498..36bd66ee76 100644
--- a/engines/agi/sound_midi.h
+++ b/engines/agi/sound_midi.h
@@ -45,7 +45,7 @@ protected:
class SoundGenMIDI : public SoundGen, public Audio::MidiPlayer {
public:
- SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer);
+ SoundGenMIDI(AgiBase *vm, Audio::Mixer *pMixer);
void play(int resnum);
// We must overload stop() here to implement the pure virtual
diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp
index fdebf16b1a..d21baa450f 100644
--- a/engines/agi/sound_pcjr.cpp
+++ b/engines/agi/sound_pcjr.cpp
@@ -102,7 +102,7 @@ const int8 dissolveDataV3[] = {
};
-SoundGenPCJr::SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
+SoundGenPCJr::SoundGenPCJr(AgiBase *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
_chanAllocated = 10240; // preallocate something which will most likely fit
_chanData = (int16 *)malloc(_chanAllocated << 1);
@@ -126,6 +126,9 @@ SoundGenPCJr::SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, p
memset(_tchannel, 0, sizeof(_tchannel));
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+
+ _v1data = NULL;
+ _v1size = 0;
}
SoundGenPCJr::~SoundGenPCJr() {
@@ -153,6 +156,9 @@ void SoundGenPCJr::play(int resnum) {
_tchannel[i].genType = kGenTone;
_tchannel[i].genTypePrev = -1;
}
+
+ _v1data = pcjrSound->getData() + 1;
+ _v1size = pcjrSound->getLength() - 1;
}
void SoundGenPCJr::stop(void) {
@@ -201,7 +207,7 @@ int SoundGenPCJr::volumeCalc(SndGenChan *chan) {
chan->attenuationCopy = attenuation;
attenuation &= 0x0F;
- attenuation += _vm->getvar(vVolume);
+ attenuation += _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 17;
if (attenuation > 0x0F)
attenuation = 0x0F;
}
@@ -214,16 +220,25 @@ int SoundGenPCJr::volumeCalc(SndGenChan *chan) {
return attenuation;
}
+int SoundGenPCJr::getNextNote(int ch)
+{
+ if (_vm->getVersion() > 0x2001)
+ return getNextNote_v2(ch);
+ else
+ return getNextNote_v1(ch);
+
+ return -1;
+}
+
// read the next channel data.. fill it in *tone
// if tone isn't touched.. it should be inited so it just plays silence
// return 0 if it's passing more data
// return -1 if it's passing nothing (end of data)
-int SoundGenPCJr::getNextNote(int ch, Tone *tone) {
+int SoundGenPCJr::getNextNote_v2(int ch) {
ToneChan *tpcm;
SndGenChan *chan;
const byte *data;
- assert(tone);
assert(ch < CHAN_MAX);
if (!_vm->getflag(fSoundOn))
@@ -234,7 +249,7 @@ int SoundGenPCJr::getNextNote(int ch, Tone *tone) {
if (!chan->avail)
return -1;
- while ((chan->duration == 0) && (chan->duration != 0xFFFF)) {
+ while (chan->duration <= 0) {
data = chan->data;
// read the duration of the note
@@ -242,58 +257,32 @@ int SoundGenPCJr::getNextNote(int ch, Tone *tone) {
// if it's 0 then it's not going to be played
// if it's 0xFFFF then the channel data has finished.
- if ((chan->duration != 0) && (chan->duration != 0xFFFF)) {
+ if ((chan->duration == 0) || (chan->duration == 0xFFFF)) {
tpcm->genTypePrev = -1;
tpcm->freqCountPrev = -1;
- // only tone channels dissolve
- if ((ch != 3) && (_dissolveMethod != 0)) // != noise??
- chan->dissolveCount = 0;
+ break;
+ }
- // attenuation (volume)
- chan->attenuation = data[4] & 0xF;
+ _tchannel[ch].genTypePrev = -1;
+ _tchannel[ch].freqCountPrev = -1;
- // frequency
- if (ch < (CHAN_MAX - 1)) {
- chan->freqCount = (uint16)data[2] & 0x3F;
- chan->freqCount <<= 4;
- chan->freqCount |= data[3] & 0x0F;
+ // only tone channels dissolve
+ if ((ch != 3) && (_dissolveMethod != 0)) // != noise??
+ chan->dissolveCount = 0;
+
+ // attenuation (volume)
+ writeData(data[4]);
+
+ // frequency
+ writeData(data[3]);
+ writeData(data[2]);
- chan->genType = kGenTone;
- } else {
- int noiseFreq;
-
- // check for white noise (1) or periodic (0)
- chan->genType = (data[3] & 0x04) ? kGenWhite : kGenPeriod;
-
- noiseFreq = data[3] & 0x03;
-
- switch (noiseFreq) {
- case 0:
- chan->freqCount = 32;
- break;
- case 1:
- chan->freqCount = 64;
- break;
- case 2:
- chan->freqCount = 128;
- break;
- case 3:
- chan->freqCount = _channel[2].freqCount * 2;
- break;
- }
- }
- }
// data now points to the next data seg-a-ment
chan->data += 5;
}
- if (chan->duration != 0xFFFF) {
- tone->freqCount = chan->freqCount;
- tone->atten = volumeCalc(chan); // calc volume, sent vol is different from saved vol
- tone->type = chan->genType;
- chan->duration--;
- } else {
+ if (chan->duration == 0xFFFF) {
// kill channel
chan->avail = 0;
chan->attenuation = 0x0F; // silent
@@ -302,9 +291,80 @@ int SoundGenPCJr::getNextNote(int ch, Tone *tone) {
return -1;
}
+ chan->duration--;
+
return 0;
}
+int SoundGenPCJr::getNextNote_v1(int ch) {
+ static int duration = 0;
+
+ byte *data = _v1data;
+ uint32 len = _v1size;
+
+ if (len <= 0 || data == NULL) {
+ _channel[ch].avail = 0;
+ _channel[ch].attenuation = 0x0F;
+ _channel[ch].attenuationCopy = 0x0F;
+ return -1;
+ }
+
+ // In the V1 player the default duration for a row is 3 ticks
+ if (duration > 0) {
+ duration--;
+ return 0;
+ }
+ duration = 3 * CHAN_MAX;
+
+ // Otherwise fetch a row of data for all channels
+ while (*data) {
+ writeData(*data);
+ data++;
+ len--;
+ }
+ data++;
+ len--;
+
+ _v1data = data;
+ _v1size = len;
+
+ return 0;
+}
+
+void SoundGenPCJr::writeData(uint8 val) {
+ static int reg = 0;
+
+ debugC(5, kDebugLevelSound, "writeData(%.2X)", val);
+
+ if ((val & 0x90) == 0x90) {
+ reg = (val >> 5) & 0x3;
+ _channel[reg].attenuation = val & 0xF;
+ } else if ((val & 0xF0) == 0xE0) {
+ _channel[3].genType = (val & 0x4) ? kGenWhite : kGenPeriod;
+ int noiseFreq = val & 0x03;
+ switch (noiseFreq) {
+ case 0:
+ _channel[3].freqCount = 32;
+ break;
+ case 1:
+ _channel[3].freqCount = 64;
+ break;
+ case 2:
+ _channel[3].freqCount = 128;
+ break;
+ case 3:
+ _channel[3].freqCount = _channel[2].freqCount * 2;
+ break;
+ }
+ } else if (val & 0x80) {
+ reg = (val >> 5) & 0x3;
+ _channel[reg].freqCount = val & 0xF;
+ _channel[reg].genType = kGenTone;
+ } else {
+ _channel[reg].freqCount |= (val & 0x3F) << 4;
+ }
+}
+
// Formulas for noise generator
// bit0 = output
@@ -340,7 +400,6 @@ const int16 volTable[16] = {
// fill buff
int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) {
ToneChan *tpcm;
- Tone toneNew;
int fillSize;
int retVal;
@@ -351,13 +410,10 @@ int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) {
while (len > 0) {
if (tpcm->noteCount <= 0) {
// get new tone data
- toneNew.freqCount = 0;
- toneNew.atten = 0xF;
- toneNew.type = kGenTone;
- if ((tpcm->avail) && (getNextNote(chan, &toneNew) == 0)) {
- tpcm->atten = toneNew.atten;
- tpcm->freqCount = toneNew.freqCount;
- tpcm->genType = toneNew.type;
+ if ((tpcm->avail) && (getNextNote(chan) == 0)) {
+ tpcm->atten = _channel[chan].attenuation;
+ tpcm->freqCount = _channel[chan].freqCount;
+ tpcm->genType = _channel[chan].genType;
// setup counters 'n stuff
// SAMPLE_RATE samples per sec.. tone changes 60 times per sec
diff --git a/engines/agi/sound_pcjr.h b/engines/agi/sound_pcjr.h
index 4317e86516..1b4d1e9efb 100644
--- a/engines/agi/sound_pcjr.h
+++ b/engines/agi/sound_pcjr.h
@@ -71,15 +71,9 @@ struct ToneChan {
int feedback; /* noise feedback mask */
};
-struct Tone {
- int freqCount;
- int atten;
- GenType type;
-};
-
class SoundGenPCJr : public SoundGen, public Audio::AudioStream {
public:
- SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer);
+ SoundGenPCJr(AgiBase *vm, Audio::Mixer *pMixer);
~SoundGenPCJr();
void play(int resnum);
@@ -102,9 +96,13 @@ public:
}
private:
- int getNextNote(int ch, Tone *tone);
+ int getNextNote(int ch);
+ int getNextNote_v2(int ch);
+ int getNextNote_v1(int ch);
int volumeCalc(SndGenChan *chan);
+ void writeData(uint8 val);
+
int chanGen(int chan, int16 *stream, int len);
int fillNoise(ToneChan *t, int16 *buf, int len);
@@ -117,6 +115,9 @@ private:
int _chanAllocated;
int _dissolveMethod;
+
+ uint8 *_v1data;
+ uint32 _v1size;
};
} // End of namespace Agi
diff --git a/engines/agi/sound_sarien.cpp b/engines/agi/sound_sarien.cpp
index 9ea8569b81..a2baf89d12 100644
--- a/engines/agi/sound_sarien.cpp
+++ b/engines/agi/sound_sarien.cpp
@@ -65,7 +65,7 @@ static const int16 waveformMac[WAVEFORM_SIZE] = {
-175, -172, -165, -159, -137, -114, -67, -19
};
-SoundGenSarien::SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _chn() {
+SoundGenSarien::SoundGenSarien(AgiBase *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _chn() {
_sndBuffer = (int16 *)calloc(2, BUFFER_SIZE);
memset(_sndBuffer, 0, BUFFER_SIZE << 1);
diff --git a/engines/agi/sound_sarien.h b/engines/agi/sound_sarien.h
index 22bfff3395..04f274ca7d 100644
--- a/engines/agi/sound_sarien.h
+++ b/engines/agi/sound_sarien.h
@@ -68,7 +68,7 @@ struct ChannelInfo {
class SoundGenSarien : public SoundGen, public Audio::AudioStream {
public:
- SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer);
+ SoundGenSarien(AgiBase *vm, Audio::Mixer *pMixer);
~SoundGenSarien();
void play(int resnum);
diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp
index ea0b07f4da..cec0895073 100644
--- a/engines/agi/sprite.cpp
+++ b/engines/agi/sprite.cpp
@@ -257,7 +257,7 @@ bool SpritesMgr::testUpdating(VtEntry *v, AgiEngine *agi) {
if (~agi->_game.dirView[v->currentView].flags & RES_LOADED)
return false;
- return (v->flags & (ANIMATED | UPDATE | DRAWN)) == (ANIMATED | UPDATE | DRAWN);
+ return (v->flags & (fAnimated | fUpdate | fDrawn)) == (fAnimated | fUpdate | fDrawn);
}
/**
@@ -268,7 +268,7 @@ bool SpritesMgr::testNotUpdating(VtEntry *v, AgiEngine *vm) {
if (~vm->_game.dirView[v->currentView].flags & RES_LOADED)
return false;
- return (v->flags & (ANIMATED | UPDATE | DRAWN)) == (ANIMATED | DRAWN);
+ return (v->flags & (fAnimated | fUpdate | fDrawn)) == (fAnimated | fDrawn);
}
/**
@@ -332,7 +332,7 @@ void SpritesMgr::buildList(SpriteList &l, bool (*test)(VtEntry *, AgiEngine *))
for (v = _vm->_game.viewTable; v < &_vm->_game.viewTable[MAX_VIEWTABLE]; v++) {
if ((*test)(v, _vm)) {
entry[i] = v;
- yVal[i] = v->flags & FIXED_PRIORITY ? prioToY(v->priority) : v->yPos;
+ yVal[i] = v->flags & fFixedPriority ? prioToY(v->priority) : v->yPos;
i++;
}
}
@@ -407,13 +407,13 @@ void SpritesMgr::commitSprites(SpriteList &l, bool immediate) {
continue;
if (s->v->xPos == s->v->xPos2 && s->v->yPos == s->v->yPos2) {
- s->v->flags |= DIDNT_MOVE;
+ s->v->flags |= fDidntMove;
continue;
}
s->v->xPos2 = s->v->xPos;
s->v->yPos2 = s->v->yPos;
- s->v->flags &= ~DIDNT_MOVE;
+ s->v->flags &= ~fDidntMove;
}
}
@@ -604,7 +604,9 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in
// If margin is 0, 1, 2, or 3, the base of the cel is
// surrounded with a rectangle of the corresponding priority.
// If margin >= 4, this extra margin is not shown.
- if (mar < 4) {
+ //
+ // -1 indicates ignore and is set for V1
+ if (mar < 4 && mar != -1) {
// add rectangle around object, don't clobber control
// info in priority data. The box extends to the end of
// its priority band!
diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp
index 0d420caa81..3f3686561e 100644
--- a/engines/agi/view.cpp
+++ b/engines/agi/view.cpp
@@ -47,7 +47,7 @@ void AgiEngine::lSetCel(VtEntry *v, int n) {
// in the KQ4 introduction
// It seems there's either a bug with KQ4's logic script 120 (the intro script)
// or flag 64 is not set correctly, which causes the erroneous behavior from the actors
- if (getGameID() == GID_KQ4 && !(v->flags & UPDATE) && (v->currentView == 172))
+ if (getGameID() == GID_KQ4 && !(v->flags & fUpdate) && (v->currentView == 172))
return;
currentVc = &currentVl->cel[n];
@@ -78,8 +78,8 @@ void AgiEngine::lSetLoop(VtEntry *v, int n) {
void AgiEngine::updateView(VtEntry *v) {
int cel, lastCel;
- if (v->flags & DONTUPDATE) {
- v->flags &= ~DONTUPDATE;
+ if (v->flags & fDontupdate) {
+ v->flags &= ~fDontupdate;
return;
}
@@ -87,32 +87,32 @@ void AgiEngine::updateView(VtEntry *v) {
lastCel = v->numCels - 1;
switch (v->cycle) {
- case CYCLE_NORMAL:
+ case kCycleNormal:
if (++cel > lastCel)
cel = 0;
break;
- case CYCLE_END_OF_LOOP:
+ case kCycleEndOfLoop:
if (cel < lastCel) {
debugC(5, kDebugLevelResources, "cel %d (last = %d)", cel + 1, lastCel);
if (++cel != lastCel)
break;
}
setflag(v->parm1, true);
- v->flags &= ~CYCLING;
+ v->flags &= ~fCycling;
v->direction = 0;
- v->cycle = CYCLE_NORMAL;
+ v->cycle = kCycleNormal;
break;
- case CYCLE_REV_LOOP:
+ case kCycleRevLoop:
if (cel) {
if (--cel)
break;
}
setflag(v->parm1, true);
- v->flags &= ~CYCLING;
+ v->flags &= ~fCycling;
v->direction = 0;
- v->cycle = CYCLE_NORMAL;
+ v->cycle = kCycleNormal;
break;
- case CYCLE_REVERSE:
+ case kCycleReverse:
if (cel == 0) {
cel = lastCel;
} else {
@@ -259,17 +259,22 @@ void AgiEngine::setCel(VtEntry *v, int n) {
*/
void AgiEngine::clipViewCoordinates(VtEntry *v) {
if (v->xPos + v->xSize > _WIDTH) {
- v->flags |= UPDATE_POS;
+ v->flags |= fUpdatePos;
v->xPos = _WIDTH - v->xSize;
}
if (v->yPos - v->ySize + 1 < 0) {
- v->flags |= UPDATE_POS;
+ v->flags |= fUpdatePos;
v->yPos = v->ySize - 1;
}
- if (v->yPos <= _game.horizon && (~v->flags & IGNORE_HORIZON)) {
- v->flags |= UPDATE_POS;
+ if (v->yPos <= _game.horizon && (~v->flags & fIgnoreHorizon)) {
+ v->flags |= fUpdatePos;
v->yPos = _game.horizon + 1;
}
+
+ if (getVersion() < 0x2000) {
+ v->flags |= fDontupdate;
+ }
+
}
/**
@@ -294,6 +299,12 @@ void AgiEngine::setView(VtEntry *v, int n) {
v->currentView = n;
v->numLoops = v->viewData->numLoops;
v->viewReplaced = true;
+
+ if (getVersion() < 0x2000) {
+ v->stepSize = v->viewData->rdata[0];
+ v->cycleTime = v->viewData->rdata[1];
+ v->cycleTimeCount = 0;
+ }
setLoop(v, v->currentLoop >= v->numLoops ? 0 : v->currentLoop);
}
@@ -302,10 +313,10 @@ void AgiEngine::setView(VtEntry *v, int n) {
* @param v pointer to view table entry
*/
void AgiEngine::startUpdate(VtEntry *v) {
- if (~v->flags & UPDATE) {
+ if (~v->flags & fUpdate) {
_sprites->eraseBoth();
- v->flags |= UPDATE;
+ v->flags |= fUpdate;
_sprites->blitBoth();
_sprites->commitBoth();
}
@@ -316,10 +327,10 @@ void AgiEngine::startUpdate(VtEntry *v) {
* @param v pointer to view table entry
*/
void AgiEngine::stopUpdate(VtEntry *v) {
- if (v->flags & UPDATE) {
+ if (v->flags & fUpdate) {
_sprites->eraseBoth();
- v->flags &= ~UPDATE;
+ v->flags &= ~fUpdate;
_sprites->blitBoth();
_sprites->commitBoth();
}
@@ -346,14 +357,14 @@ void AgiEngine::updateViewtable() {
i = 0;
for (v = _game.viewTable; v < &_game.viewTable[MAX_VIEWTABLE]; v++) {
- if ((v->flags & (ANIMATED | UPDATE | DRAWN)) != (ANIMATED | UPDATE | DRAWN)) {
+ if ((v->flags & (fAnimated | fUpdate | fDrawn)) != (fAnimated | fUpdate | fDrawn)) {
continue;
}
i++;
loop = 4;
- if (~v->flags & FIX_LOOP) {
+ if (~v->flags & fFixLoop) {
switch (v->numLoops) {
case 2:
case 3:
@@ -378,7 +389,7 @@ void AgiEngine::updateViewtable() {
}
}
- if (~v->flags & CYCLING)
+ if (~v->flags & fCycling)
continue;
if (v->cycleTimeCount == 0)
@@ -395,7 +406,7 @@ void AgiEngine::updateViewtable() {
updatePosition();
_sprites->blitUpdSprites();
_sprites->commitUpdSprites();
- _game.viewTable[0].flags &= ~(ON_WATER | ON_LAND);
+ _game.viewTable[0].flags &= ~(fOnWater | fOnLand);
}
}
diff --git a/engines/agi/view.h b/engines/agi/view.h
index 0ef443f8e5..5cf59d7df5 100644
--- a/engines/agi/view.h
+++ b/engines/agi/view.h
@@ -50,6 +50,39 @@ struct AgiView {
uint8 *rdata;
};
+enum MotionType {
+ kMotionNormal = 0,
+ kMotionWander = 1,
+ kMotionFollowEgo = 2,
+ kMotionMoveObj = 3
+};
+
+enum CycleType {
+ kCycleNormal = 0,
+ kCycleEndOfLoop = 1,
+ kCycleRevLoop = 2,
+ kCycleReverse = 3
+ };
+
+enum ViewFlags {
+ fDrawn = (1 << 0),
+ fIgnoreBlocks = (1 << 1),
+ fFixedPriority = (1 << 2),
+ fIgnoreHorizon = (1 << 3),
+ fUpdate = (1 << 4),
+ fCycling = (1 << 5),
+ fAnimated = (1 << 6),
+ fMotion = (1 << 7),
+ fOnWater = (1 << 8),
+ fIgnoreObjects = (1 << 9),
+ fUpdatePos = (1 << 10),
+ fOnLand = (1 << 11),
+ fDontupdate = (1 << 12),
+ fFixLoop = (1 << 13),
+ fDidntMove = (1 << 14),
+ fAdjEgoXY = (1 << 15)
+};
+
/**
* AGI view table entry
*/
@@ -78,39 +111,10 @@ struct VtEntry {
uint8 cycleTime;
uint8 cycleTimeCount;
uint8 direction;
-
-#define MOTION_NORMAL 0
-#define MOTION_WANDER 1
-#define MOTION_FOLLOW_EGO 2
-#define MOTION_MOVE_OBJ 3
- uint8 motion;
-
-#define CYCLE_NORMAL 0
-#define CYCLE_END_OF_LOOP 1
-#define CYCLE_REV_LOOP 2
-#define CYCLE_REVERSE 3
- uint8 cycle;
-
+ MotionType motion;
+ CycleType cycle;
uint8 priority;
-
-#define DRAWN 0x0001
-#define IGNORE_BLOCKS 0x0002
-#define FIXED_PRIORITY 0x0004
-#define IGNORE_HORIZON 0x0008
-#define UPDATE 0x0010
-#define CYCLING 0x0020
-#define ANIMATED 0x0040
-#define MOTION 0x0080
-#define ON_WATER 0x0100
-#define IGNORE_OBJECTS 0x0200
-#define UPDATE_POS 0x0400
-#define ON_LAND 0x0800
-#define DONTUPDATE 0x1000
-#define FIX_LOOP 0x2000
-#define DIDNT_MOVE 0x4000
-#define ADJ_EGO_XY 0x8000
uint16 flags;
-
uint8 parm1;
uint8 parm2;
uint8 parm3;
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index 4b96fdf711..ec6928f8ed 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -20,19 +20,12 @@
*
*/
-//
-// New find_word algorithm by Thomas Akesson <tapilot@home.se>
-//
-
#include "agi/agi.h"
#include "common/textconsole.h"
namespace Agi {
-static uint8 *words; // words in the game
-static uint32 wordsFlen; // length of word memory
-
//
// Local implementation to avoid problems with strndup() used by
// gcc 3.2 Cygwin (see #635984)
@@ -43,12 +36,38 @@ static char *myStrndup(const char *src, int n) {
return tmp;
}
+int AgiEngine::loadWords_v1(Common::File &f) {
+ char str[64];
+ int k;
+
+ debug(0, "Loading dictionary");
+
+ // Loop through alphabet, as words in the dictionary file are sorted by
+ // first character
+ f.seek(f.pos() + 26 * 2, SEEK_SET);
+ do {
+ // Read next word
+ for (k = 0; k < (int)sizeof(str) - 1; k++) {
+ str[k] = f.readByte();
+ if (str[k] == 0 || (uint8)str[k] == 0xFF)
+ break;
+ }
+
+ // And store it in our internal dictionary
+ if (k > 0) {
+ AgiWord *w = new AgiWord;
+ w->word = myStrndup(str, k + 1);
+ w->id = f.readUint16LE();
+ _game.words[str[0] - 'a'].push_back(w);
+ debug(3, "'%s' (%d)", w->word, w->id);
+ }
+ } while((uint8)str[0] != 0xFF);
+
+ return errOK;
+}
+
int AgiEngine::loadWords(const char *fname) {
Common::File fp;
- uint32 flen;
- uint8 *mem = NULL;
-
- words = NULL;
if (!fp.open(fname)) {
warning("loadWords: can't open %s", fname);
@@ -56,85 +75,70 @@ int AgiEngine::loadWords(const char *fname) {
}
debug(0, "Loading dictionary: %s", fname);
- fp.seek(0, SEEK_END);
- flen = fp.pos();
- wordsFlen = flen;
- fp.seek(0, SEEK_SET);
-
- if ((mem = (uint8 *)calloc(1, flen + 32)) == NULL) {
- fp.close();
- return errNotEnoughMemory;
+ // Loop through alphabet, as words in the dictionary file are sorted by
+ // first character
+ for (int i = 0; i < 26; i++) {
+ fp.seek(i * 2, SEEK_SET);
+ int offset = fp.readUint16BE();
+ if (offset == 0)
+ continue;
+ fp.seek(offset, SEEK_SET);
+ int k = fp.readByte();
+ while (!fp.eos() && !fp.err()) {
+ // Read next word
+ char c, str[64];
+ do {
+ c = fp.readByte();
+ str[k++] = (c ^ 0x7F) & 0x7F;
+ } while (!(c & 0x80) && k < (int)sizeof(str) - 1);
+ str[k] = 0;
+
+ // And store it in our internal dictionary
+ AgiWord *w = new AgiWord;
+ w->word = myStrndup(str, k);
+ w->id = fp.readUint16BE();
+ _game.words[i].push_back(w);
+
+ // Are there more words with an already known prefix?
+ if (!(k = fp.readByte()))
+ break;
+ }
}
- fp.read(mem, flen);
- fp.close();
-
- words = mem;
-
return errOK;
}
void AgiEngine::unloadWords() {
- free(words);
- words = NULL;
+ for (int i = 0; i < 26; i++)
+ _game.words[i].clear();
}
/**
* Find a word in the dictionary
* Uses an algorithm hopefully like the one Sierra used. Returns the ID
* of the word and the length in flen. Returns -1 if not found.
- *
- * Thomas Akesson, November 2001
*/
int AgiEngine::findWord(const char *word, int *flen) {
- int mchr = 0; // matched chars
- int len, fchr, id = -1;
- const uint8 *p = words;
- const uint8 *q = words + wordsFlen;
- *flen = 0;
+ int c;
debugC(2, kDebugLevelScripts, "find_word(%s)", word);
if (word[0] >= 'a' && word[0] <= 'z')
- fchr = word[0] - 'a';
+ c = word[0] - 'a';
else
return -1;
- len = strlen(word);
-
- // Get the offset to the first word beginning with the
- // right character
- p += READ_BE_UINT16(p + 2 * fchr);
-
- while (p[0] >= mchr) {
- if (p[0] == mchr) {
- p++;
- // Loop through all matching characters
- while ((p[0] ^ word[mchr]) == 0x7F && mchr < len) {
- mchr++;
- p++;
- }
- // Check if this is the last character of the word
- // and if it matches
- if ((p[0] ^ word[mchr]) == 0xFF && mchr < len) {
- mchr++;
- if (word[mchr] == 0 || word[mchr] == 0x20) {
- id = READ_BE_UINT16(p + 1);
- *flen = mchr;
- }
- }
+ *flen = 0;
+ Common::Array<AgiWord*> &a = _game.words[c];
+ for (int i = 0; i < (int)a.size(); i++) {
+ int wlen = strlen(a[i]->word);
+ if (!strncmp(a[i]->word, word, wlen) && (word[wlen] == 0 || word[wlen] == 0x20)) {
+ *flen = wlen;
+ return a[i]->id;
}
- if (p >= q)
- return -1;
-
- // Step to the next word
- while (p[0] < 0x80)
- p++;
-
- p += 3;
}
- return id;
+ return -1;
}
void AgiEngine::dictionaryWords(char *msg) {
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index 4d879909c4..97c594684c 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -24,13 +24,13 @@
#include "common/file.h"
#include "common/fs.h"
#include "common/textconsole.h"
-#include "common/system.h"
#include "engines/util.h"
#include "agos/debugger.h"
#include "agos/intern.h"
#include "agos/agos.h"
+#include "agos/midi.h"
#include "backends/audiocd/audiocd.h"
@@ -541,16 +541,18 @@ Common::Error AGOSEngine::init() {
initGraphics(_screenWidth, _screenHeight, getGameType() == GType_FF || getGameType() == GType_PP);
+ _midi = new MidiPlayer();
+
if ((getGameType() == GType_SIMON2 && getPlatform() == Common::kPlatformWindows) ||
(getGameType() == GType_SIMON1 && getPlatform() == Common::kPlatformWindows) ||
((getFeatures() & GF_TALKIE) && getPlatform() == Common::kPlatformAcorn) ||
(getPlatform() == Common::kPlatformPC)) {
- int ret = _midi.open(getGameType());
+ int ret = _midi->open(getGameType());
if (ret)
warning("MIDI Player init failed: \"%s\"", MidiDriver::getErrorName(ret));
- _midi.setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
+ _midi->setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
_midiEnabled = true;
}
@@ -597,14 +599,14 @@ Common::Error AGOSEngine::init() {
if (ConfMan.hasKey("music_mute") && ConfMan.getBool("music_mute") == 1) {
_musicPaused = true;
if (_midiEnabled) {
- _midi.pause(_musicPaused);
+ _midi->pause(_musicPaused);
}
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, 0);
}
if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) {
if (getGameId() == GID_SIMON1DOS)
- _midi._enable_sfx = !_midi._enable_sfx;
+ _midi->_enable_sfx = !_midi->_enable_sfx;
else {
_effectsPaused = !_effectsPaused;
_sound->effectsPause(_effectsPaused);
@@ -640,14 +642,12 @@ Common::Error AGOSEngine::init() {
// TODO: Use special debug levels instead of the following hack.
_debugMode = (gDebugLevel >= 0);
- if (gDebugLevel == 2)
- _dumpOpcodes = true;
- if (gDebugLevel == 3)
- _dumpVgaOpcodes = true;
- if (gDebugLevel == 4)
- _dumpScripts = true;
- if (gDebugLevel == 5)
- _dumpVgaScripts = true;
+ switch (gDebugLevel) {
+ case 2: _dumpOpcodes = true; break;
+ case 3: _dumpVgaOpcodes = true; break;
+ case 4: _dumpScripts = true; break;
+ case 5: _dumpVgaScripts = true; break;
+ }
return Common::kNoError;
}
@@ -708,7 +708,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 && _midi.hasNativeMT32())
+ if (getGameType() == GType_SIMON2 && _midi->hasNativeMT32())
_musicIndexBase = (1128 + 612) / 4;
else
_musicIndexBase = 1128 / 4;
@@ -911,6 +911,8 @@ AGOSEngine::~AGOSEngine() {
_window6BackScn->free();
delete _window6BackScn;
+ delete _midi;
+
free(_firstTimeStruct);
free(_pendingDeleteTimeEvent);
@@ -938,12 +940,12 @@ void AGOSEngine::pauseEngineIntern(bool pauseIt) {
_keyPressed.reset();
_pause = true;
- _midi.pause(true);
+ _midi->pause(true);
_mixer->pauseAll(true);
} else {
_pause = false;
- _midi.pause(_musicPaused);
+ _midi->pause(_musicPaused);
_mixer->pauseAll(false);
}
}
@@ -1027,7 +1029,7 @@ void AGOSEngine::syncSoundSettings() {
int soundVolumeSFX = ConfMan.getInt("sfx_volume");
if (_midiEnabled)
- _midi.setVolume((mute ? 0 : soundVolumeMusic), (mute ? 0 : soundVolumeSFX));
+ _midi->setVolume((mute ? 0 : soundVolumeMusic), (mute ? 0 : soundVolumeSFX));
}
} // End of namespace AGOS
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index aa68a05eee..820bc0260b 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -33,7 +33,6 @@
#include "common/stack.h"
#include "common/util.h"
-#include "agos/midi.h"
#include "agos/sound.h"
#include "agos/vga.h"
@@ -50,6 +49,16 @@
* - Simon the Sorcerer 2
* - Simon the Sorcerer Puzzle Pack
*/
+
+namespace Common {
+class File;
+class SeekableReadStream;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
namespace AGOS {
uint fileReadItemID(Common::SeekableReadStream *in);
@@ -60,6 +69,8 @@ uint fileReadItemID(Common::SeekableReadStream *in);
class MoviePlayer;
#endif
+class MidiPlayer;
+
struct Child;
struct SubObject;
@@ -313,7 +324,7 @@ protected:
bool _backFlag;
uint16 _debugMode;
- uint16 _language;
+ Common::Language _language;
bool _copyProtection;
bool _pause;
bool _dumpScripts;
@@ -548,7 +559,7 @@ protected:
byte _lettersToPrintBuf[80];
- MidiPlayer _midi;
+ MidiPlayer *_midi;
bool _midiEnabled;
int _vgaTickCounter;
diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp
index b708b4890b..e6b81f54ee 100644
--- a/engines/agos/charset-fontdata.cpp
+++ b/engines/agos/charset-fontdata.cpp
@@ -20,8 +20,6 @@
*
*/
-
-
#include "common/system.h"
#include "common/textconsole.h"
@@ -2454,4 +2452,3 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
}
} // End of namespace AGOS
-
diff --git a/engines/agos/charset.cpp b/engines/agos/charset.cpp
index 9d27afaa27..54aef99a47 100644
--- a/engines/agos/charset.cpp
+++ b/engines/agos/charset.cpp
@@ -20,8 +20,7 @@
*
*/
-
-
+#include "common/endian.h"
#include "common/system.h"
#include "agos/agos.h"
@@ -655,4 +654,3 @@ void AGOSEngine::windowScroll(WindowBlock *window) {
_videoLockOut &= ~0x8000;
}
} // End of namespace AGOS
-
diff --git a/engines/agos/contain.cpp b/engines/agos/contain.cpp
index ba60c65ff3..173194d45e 100644
--- a/engines/agos/contain.cpp
+++ b/engines/agos/contain.cpp
@@ -20,8 +20,6 @@
*
*/
-
-
#include "agos/agos.h"
#include "agos/intern.h"
diff --git a/engines/agos/cursor.cpp b/engines/agos/cursor.cpp
index ef4a1406c9..7c64d68048 100644
--- a/engines/agos/cursor.cpp
+++ b/engines/agos/cursor.cpp
@@ -20,10 +20,8 @@
*
*/
-
-
+#include "common/endian.h"
#include "common/events.h"
-#include "common/system.h"
#include "graphics/cursorman.h"
diff --git a/engines/agos/debug.cpp b/engines/agos/debug.cpp
index 9c44342975..18c4736031 100644
--- a/engines/agos/debug.cpp
+++ b/engines/agos/debug.cpp
@@ -22,7 +22,6 @@
// AGOS debug functions
-
#include "common/file.h"
#include "common/textconsole.h"
diff --git a/engines/agos/debug.h b/engines/agos/debug.h
index fd5908997f..fe14ae4860 100644
--- a/engines/agos/debug.h
+++ b/engines/agos/debug.h
@@ -2843,4 +2843,3 @@ const char *const feeblefiles_videoOpcodeNameTable[] = {
} // End of namespace AGOS
#endif
-
diff --git a/engines/agos/debugger.cpp b/engines/agos/debugger.cpp
index a313dbbd1e..fc24c6d363 100644
--- a/engines/agos/debugger.cpp
+++ b/engines/agos/debugger.cpp
@@ -20,12 +20,11 @@
*
*/
-
-
#include "common/config-manager.h"
#include "agos/debugger.h"
#include "agos/agos.h"
+#include "agos/midi.h"
namespace AGOS {
@@ -58,7 +57,7 @@ bool Debugger::Cmd_DebugLevel(int argc, const char **argv) {
DebugPrintf("Debugging is currently set at level %d\n", gDebugLevel);
} else { // set level
gDebugLevel = atoi(argv[1]);
- if (gDebugLevel >= 0 && gDebugLevel < 10) {
+ if (0 <= gDebugLevel && gDebugLevel < 11) {
_vm->_debugMode = true;
DebugPrintf("Debug level set to level %d\n", gDebugLevel);
} else if (gDebugLevel < 0) {
@@ -79,7 +78,7 @@ bool Debugger::Cmd_PlayMusic(int argc, const char **argv) {
// TODO
} else if (_vm->getGameType() == GType_SIMON2) {
_vm->loadMusic(music);
- _vm->_midi.startTrack(0);
+ _vm->_midi->startTrack(0);
} else {
_vm->playMusic(music, 0);
}
@@ -287,4 +286,3 @@ bool Debugger::Cmd_dumpScript(int argc, const char **argv) {
}
} // End of namespace AGOS
-
diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h
index a43d581173..d9f321d98e 100644
--- a/engines/agos/detection_tables.h
+++ b/engines/agos/detection_tables.h
@@ -1040,7 +1040,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformAcorn,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NOSUBTITLES
},
@@ -1208,7 +1208,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NOSUBTITLES | GUIO_NOMIDI
},
@@ -1232,7 +1232,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformAmiga,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NOSUBTITLES | GUIO_NOMIDI
},
@@ -1546,7 +1546,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NOSUBTITLES
},
@@ -1571,7 +1571,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NOSUBTITLES
},
@@ -1596,7 +1596,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::RU_RUS,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -1621,7 +1621,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::FR_FRA,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -1671,7 +1671,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::HE_ISR,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -1696,7 +1696,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::IT_ITA,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -1722,7 +1722,7 @@ static const AGOSGameDescription gameDescriptions[] = {
// FIXME: DOS version which uses WAV format
Common::IT_ITA,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -1747,7 +1747,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::ES_ESP,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -1772,7 +1772,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NOSUBTITLES
},
@@ -1797,7 +1797,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::DE_DEU,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NOSUBTITLES
},
@@ -2022,7 +2022,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2047,7 +2047,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2072,7 +2072,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::FR_FRA,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2097,7 +2097,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::DE_DEU,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2122,7 +2122,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::DE_DEU,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2147,7 +2147,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::HE_ISR,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2173,7 +2173,7 @@ static const AGOSGameDescription gameDescriptions[] = {
// FIXME: DOS version which uses WAV format
Common::IT_ITA,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2198,7 +2198,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::ES_ESP,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2223,7 +2223,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::CZ_CZE,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2248,7 +2248,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2273,7 +2273,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::FR_FRA,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2298,7 +2298,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::DE_DEU,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
@@ -2323,7 +2323,7 @@ static const AGOSGameDescription gameDescriptions[] = {
},
Common::PL_POL,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp
index 4d66b56a96..9fc5cedbf9 100644
--- a/engines/agos/draw.cpp
+++ b/engines/agos/draw.cpp
@@ -20,8 +20,7 @@
*
*/
-
-
+#include "common/endian.h"
#include "common/system.h"
#include "graphics/surface.h"
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp
index 3411e6d632..ed26b96381 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -20,8 +20,6 @@
*
*/
-
-
#include "agos/agos.h"
#include "agos/animation.h"
#include "agos/debugger.h"
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index 0b045bae01..fbf7f416ed 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -20,8 +20,7 @@
*
*/
-
-
+#include "common/endian.h"
#include "common/system.h"
#include "common/textconsole.h"
diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp
index ead4e49ebb..7db2d85f21 100644
--- a/engines/agos/icons.cpp
+++ b/engines/agos/icons.cpp
@@ -20,8 +20,6 @@
*
*/
-
-
#include "common/file.h"
#include "common/system.h"
#include "common/textconsole.h"
diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp
index 2ab543a943..24e5339420 100644
--- a/engines/agos/input.cpp
+++ b/engines/agos/input.cpp
@@ -20,13 +20,12 @@
*
*/
-
-
#include "common/config-manager.h"
#include "common/file.h"
#include "agos/intern.h"
#include "agos/agos.h"
+#include "agos/midi.h"
#include "agos/vga.h"
namespace AGOS {
@@ -582,14 +581,14 @@ bool AGOSEngine::processSpecialKeys() {
break;
case '+':
if (_midiEnabled) {
- _midi.setVolume(_midi.getMusicVolume() + 16, _midi.getSFXVolume() + 16);
+ _midi->setVolume(_midi->getMusicVolume() + 16, _midi->getSFXVolume() + 16);
}
ConfMan.setInt("music_volume", _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 16);
syncSoundSettings();
break;
case '-':
if (_midiEnabled) {
- _midi.setVolume(_midi.getMusicVolume() - 16, _midi.getSFXVolume() - 16);
+ _midi->setVolume(_midi->getMusicVolume() - 16, _midi->getSFXVolume() - 16);
}
ConfMan.setInt("music_volume", _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) - 16);
syncSoundSettings();
@@ -597,13 +596,13 @@ bool AGOSEngine::processSpecialKeys() {
case 'm':
_musicPaused = !_musicPaused;
if (_midiEnabled) {
- _midi.pause(_musicPaused);
+ _midi->pause(_musicPaused);
}
syncSoundSettings();
break;
case 's':
if (getGameId() == GID_SIMON1DOS) {
- _midi._enable_sfx = !_midi._enable_sfx;
+ _midi->_enable_sfx = !_midi->_enable_sfx;
} else {
_effectsPaused = !_effectsPaused;
_sound->effectsPause(_effectsPaused);
diff --git a/engines/agos/input_pn.cpp b/engines/agos/input_pn.cpp
index 9cc97ff10f..b3a44f2b2f 100644
--- a/engines/agos/input_pn.cpp
+++ b/engines/agos/input_pn.cpp
@@ -20,8 +20,6 @@
*
*/
-
-
#include "agos/agos.h"
#include "agos/intern.h"
diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp
index 0fb873a733..3bb5a132ef 100644
--- a/engines/agos/items.cpp
+++ b/engines/agos/items.cpp
@@ -20,8 +20,6 @@
*
*/
-
-
#include "common/file.h"
#include "common/textconsole.h"
diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp
index 4d62e34820..a0d2bdcaa0 100644
--- a/engines/agos/menus.cpp
+++ b/engines/agos/menus.cpp
@@ -20,8 +20,6 @@
*
*/
-
-
#include "common/file.h"
#include "common/system.h"
#include "common/textconsole.h"
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index 88f6dd80d1..9a93e0a273 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -20,14 +20,12 @@
*
*/
-
-
#include "common/config-manager.h"
#include "common/file.h"
-#include "common/system.h"
#include "common/textconsole.h"
#include "agos/agos.h"
+#include "agos/midi.h"
namespace AGOS {
diff --git a/engines/agos/midiparser_s1d.cpp b/engines/agos/midiparser_s1d.cpp
index 01690247f0..9ca87436fc 100644
--- a/engines/agos/midiparser_s1d.cpp
+++ b/engines/agos/midiparser_s1d.cpp
@@ -31,20 +31,22 @@ namespace AGOS {
/**
* Simon 1 Demo version of MidiParser.
- *
- * This parser is the result of eyeballing the one MUS file that's included
- * with simon1demo. So there might be some things missing. I've tried to notate
- * question-mark areas where they occur.
*/
class MidiParser_S1D : public MidiParser {
-protected:
+private:
byte *_data;
bool _no_delta;
+ struct Loop {
+ uint16 timer;
+ byte *start, *end;
+ } _loops[16];
+
+ uint32 readVLQ2(byte *&data);
+ void chainEvent(EventInfo &info);
protected:
void parseNextEvent(EventInfo &info);
void resetTracking();
- uint32 readVLQ2(byte * &data);
public:
MidiParser_S1D() : _data(0), _no_delta(false) {}
@@ -52,145 +54,128 @@ public:
bool loadMusic(byte *data, uint32 size);
};
+uint32 MidiParser_S1D::readVLQ2(byte *&data) {
+ uint32 delta = 0;
-// The VLQs for simon1demo seem to be
-// in Little Endian format.
-uint32 MidiParser_S1D::readVLQ2(byte * &data) {
- byte str;
- uint32 value = 0;
- int i;
-
- for (i = 0; i < 4; ++i) {
- str = data[0];
- ++data;
- value |= (str & 0x7F) << (i * 7);
- if (!(str & 0x80))
- break;
+ // LE format VLQ, which is 2 bytes long at max.
+ delta = *data++;
+ if (delta & 0x80) {
+ delta &= 0x7F;
+ delta |= *data++ << 7;
}
- return value;
+
+ return delta;
+}
+
+void MidiParser_S1D::chainEvent(EventInfo &info) {
+ // When we chain an event, we add up the old delta.
+ uint32 delta = info.delta;
+ parseNextEvent(info);
+ info.delta += delta;
}
void MidiParser_S1D::parseNextEvent(EventInfo &info) {
info.start = _position._play_pos;
+ info.length = 0;
info.delta = _no_delta ? 0 : readVLQ2(_position._play_pos);
-
_no_delta = false;
- info.event = *(_position._play_pos++);
- if (info.command() < 0x8) {
+
+ info.event = *_position._play_pos++;
+ if (!(info.event & 0x80)) {
_no_delta = true;
- info.event += 0x80;
+ info.event |= 0x80;
}
- switch (info.command()) {
- case 0x8:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = 0;
- info.length = 0;
- break;
-
- case 0x9:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++); // I'm ASSUMING this byte is velocity!
- info.length = 0;
- break;
-
- case 0xA:
- case 0xB:
- // I'm not sure what these are meant to do, or what the
- // parameter is. Elvira 1 needs them, though, and who am I to
- // argue with her?
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = 0;
- break;
-
- case 0xC:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = 0;
- ++_position._play_pos; // I have NO IDEA what the second byte is for.
- break;
-
- case 0xD:
- // Triggered by MOD0/MOD1/MOD2/MOD3/MOD4/MOD6/MOD7/MOD8/MOD9 in Elvira 2
- // Triggered by MOD0/MOD2/MOD3/MOD5/MOD6/MOD7/MOD8/MOD9/MOD10/MOD12/MOD14/MOD15/MOD20 in Waxworks
- break;
-
- case 0xE:
- // Triggered by MOD9 in Elvira 1
- // Triggered by MOD3/MOD5 in Elvira 2
- // Triggered by MOD3/MOD7/MOD8/MOD13 in Waxworks
- break;
-
- case 0xF:
- switch (info.event & 0x0F) {
- case 0x0:
- // Trigged by MOD2/MOD6/MOD15 in Waxworks
- // Pure guesswork
- info.ext.type = *(_position._play_pos++);
- info.length = readVLQ(_position._play_pos);
- info.ext.data = _position._play_pos;
- break;
-
- case 0x3: // Not sure, Song Select?
- // Trigged by MOD1/MOD7/MOD10 in Elvira 1
- info.basic.param1 = *(_position._play_pos++);
+ if (info.event == 0xFC) {
+ // This means End of Track.
+ // Rewrite in SMF (MIDI transmission) form.
+ info.event = 0xFF;
+ info.ext.type = 0x2F;
+ } else {
+ switch (info.command()) {
+ case 0x8: // note off
+ info.basic.param1 = *_position._play_pos++;
info.basic.param2 = 0;
break;
- case 0x4:
- // Trigged by MOD8 in Elvira 1
- break;
-
- case 0x7:
- // Trigged by MOD6 in Elvira 2
- // Trigged by MOD5 in Waxworks
+ case 0x9: // note on
+ info.basic.param1 = *_position._play_pos++;
+ info.basic.param2 = *_position._play_pos++;
break;
- case 0x8: // Not sure, ?
- // Trigged by MOD19 in Waxworks
- info.basic.param1 = info.basic.param2 = 0;
+ case 0xA: { // loop control
+ // In case the stop mode(?) is set to 0x80 this will stop the
+ // track over here.
+
+ const int16 loopIterations = int8(*_position._play_pos++);
+ if (!loopIterations) {
+ _loops[info.channel()].start = _position._play_pos;
+ } else {
+ if (!_loops[info.channel()].timer) {
+ if (_loops[info.channel()].start) {
+ _loops[info.channel()].timer = uint16(loopIterations);
+ _loops[info.channel()].end = _position._play_pos;
+
+ // Go to the start of the loop
+ _position._play_pos = _loops[info.channel()].start;
+ }
+ } else {
+ if (_loops[info.channel()].timer)
+ _position._play_pos = _loops[info.channel()].start;
+ --_loops[info.channel()].timer;
+ }
+ }
+
+ // We need to read the next midi event here. Since we can not
+ // safely pass this event to the MIDI event processing.
+ chainEvent(info);
+ } break;
+
+ case 0xB: // auto stop marker(?)
+ // In case the stop mode(?) is set to 0x80 this will stop the
+ // track.
+
+ // We need to read the next midi event here. Since we can not
+ // safely pass this event to the MIDI event processing.
+ chainEvent(info);
break;
- case 0xA:
- // Trigged by MOD5 in Elvira 2
+ case 0xC: // program change
+ info.basic.param1 = *_position._play_pos++;
+ info.basic.param2 = 0;
break;
- case 0xC:
- // This means End of Track.
- // Rewrite in SMF (MIDI transmission) form.
- info.event = 0xFF;
- info.ext.type = 0x2F;
- info.length = 0;
- break;
+ case 0xD: // jump to loop end
+ if (_loops[info.channel()].end)
+ _position._play_pos = _loops[info.channel()].end;
- case 0xF: // Not sure, META event?
- // Trigged by MOD8/MOD9/MOD11/MOD12/MOD13 in Waxworks
- info.ext.type = *(_position._play_pos++);
- info.length = readVLQ(_position._play_pos);
- info.ext.data = _position._play_pos;
- _position._play_pos += info.length;
+ // We need to read the next midi event here. Since we can not
+ // safely pass this event to the MIDI event processing.
+ chainEvent(info);
break;
default:
- error("MidiParser_S1D: Unexpected type 0x%02X found", (int) info.event);
+ // The original called some other function from here, which seems
+ // not to be MIDI related.
+ warning("MidiParser_S1D: default case %d", info.channel());
+
+ // We need to read the next midi event here. Since we can not
+ // safely pass this event to the MIDI event processing.
+ chainEvent(info);
break;
}
- break;
- default:
- error("MidiParser_S1D: Unexpected event 0x%02X found", (int) info.command());
- break;
}
}
bool MidiParser_S1D::loadMusic(byte *data, uint32 size) {
unloadMusic();
+ // The original actually just ignores the first two bytes.
byte *pos = data;
if (*(pos++) != 0xFC)
debug(1, "Expected 0xFC header but found 0x%02X instead", (int) *pos);
- // The next 3 bytes MIGHT be tempo, but we skip them and use the default.
-// setTempo (*(pos++) | (*(pos++) << 8) | (*(pos++) << 16));
- pos += 3;
+ pos += 1;
// And now we're at the actual data. Only one track.
_num_tracks = 1;
@@ -208,7 +193,9 @@ bool MidiParser_S1D::loadMusic(byte *data, uint32 size) {
void MidiParser_S1D::resetTracking() {
MidiParser::resetTracking();
- _no_delta = false;
+ // The first event never contains any delta.
+ _no_delta = true;
+ memset(_loops, 0, sizeof(_loops));
}
MidiParser *MidiParser_createS1D() { return new MidiParser_S1D; }
diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp
index 2a3c668c08..025a833b77 100644
--- a/engines/agos/oracle.cpp
+++ b/engines/agos/oracle.cpp
@@ -25,7 +25,6 @@
#ifdef ENABLE_AGOS2
#include "common/savefile.h"
-#include "common/system.h"
#include "graphics/surface.h"
diff --git a/engines/agos/res_ami.cpp b/engines/agos/res_ami.cpp
index b83d10364a..32adfa29e6 100644
--- a/engines/agos/res_ami.cpp
+++ b/engines/agos/res_ami.cpp
@@ -26,6 +26,8 @@
#include "agos/agos.h"
#include "agos/intern.h"
+#include "common/endian.h"
+
namespace AGOS {
enum {
diff --git a/engines/agos/res_snd.cpp b/engines/agos/res_snd.cpp
index 819af4fa40..9a04ce2d26 100644
--- a/engines/agos/res_snd.cpp
+++ b/engines/agos/res_snd.cpp
@@ -27,12 +27,12 @@
#include "agos/intern.h"
#include "agos/agos.h"
+#include "agos/midi.h"
#include "agos/vga.h"
#include "backends/audiocd/audiocd.h"
#include "audio/audiostream.h"
-#include "audio/mididrv.h"
#include "audio/mods/protracker.h"
namespace AGOS {
@@ -125,10 +125,10 @@ void AGOSEngine::loadMusic(uint16 music) {
_gameFile->read(buf, 4);
if (!memcmp(buf, "FORM", 4)) {
_gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music - 1], SEEK_SET);
- _midi.loadXMIDI(_gameFile);
+ _midi->loadXMIDI(_gameFile);
} else {
_gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music - 1], SEEK_SET);
- _midi.loadMultipleSMF(_gameFile);
+ _midi->loadMultipleSMF(_gameFile);
}
_lastMusicPlayed = music;
@@ -242,20 +242,20 @@ void AGOSEngine_Simon1::playMusic(uint16 music, uint16 track) {
if (music == 35)
return;
- _midi.setLoop(true); // Must do this BEFORE loading music. (GMF may have its own override.)
+ _midi->setLoop(true); // Must do this BEFORE loading music. (GMF may have its own override.)
_gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET);
_gameFile->read(buf, 4);
if (!memcmp(buf, "GMF\x1", 4)) {
_gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET);
- _midi.loadSMF(_gameFile, music);
+ _midi->loadSMF(_gameFile, music);
} else {
_gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET);
- _midi.loadMultipleSMF(_gameFile);
+ _midi->loadMultipleSMF(_gameFile);
}
- _midi.startTrack(0);
- _midi.startTrack(track);
+ _midi->startTrack(0);
+ _midi->startTrack(track);
} else if (getPlatform() == Common::kPlatformAcorn) {
// TODO: Add support for Desktop Tracker format in Acorn disk version
} else {
@@ -266,15 +266,15 @@ void AGOSEngine_Simon1::playMusic(uint16 music, uint16 track) {
if (f.isOpen() == false)
error("playMusic: Can't load music from '%s'", filename);
- _midi.setLoop(true); // Must do this BEFORE loading music. (GMF may have its own override.)
+ _midi->setLoop(true); // Must do this BEFORE loading music. (GMF may have its own override.)
if (getFeatures() & GF_DEMO)
- _midi.loadS1D(&f);
+ _midi->loadS1D(&f);
else
- _midi.loadSMF(&f, music);
+ _midi->loadSMF(&f, music);
- _midi.startTrack(0);
- _midi.startTrack(track);
+ _midi->startTrack(0);
+ _midi->startTrack(track);
}
}
@@ -286,7 +286,7 @@ void AGOSEngine::playMusic(uint16 music, uint16 track) {
} else if (getPlatform() == Common::kPlatformAtariST) {
// TODO: Add support for music formats used
} else {
- _midi.setLoop(true); // Must do this BEFORE loading music.
+ _midi->setLoop(true); // Must do this BEFORE loading music.
char filename[15];
Common::File f;
@@ -295,21 +295,21 @@ void AGOSEngine::playMusic(uint16 music, uint16 track) {
if (f.isOpen() == false)
error("playMusic: Can't load music from '%s'", filename);
- _midi.loadS1D(&f);
- _midi.startTrack(0);
- _midi.startTrack(track);
+ _midi->loadS1D(&f);
+ _midi->startTrack(0);
+ _midi->startTrack(track);
}
}
void AGOSEngine::stopMusic() {
if (_midiEnabled) {
- _midi.stop();
+ _midi->stop();
}
_mixer->stopHandle(_modHandle);
}
void AGOSEngine::playSting(uint16 soundId) {
- if (!_midi._enable_sfx)
+ if (!_midi->_enable_sfx)
return;
char filename[15];
@@ -328,8 +328,8 @@ void AGOSEngine::playSting(uint16 soundId) {
error("playSting: Can't read sting %d offset", soundId);
mus_file.seek(mus_offset, SEEK_SET);
- _midi.loadSMF(&mus_file, soundId, true);
- _midi.startTrack(0);
+ _midi->loadSMF(&mus_file, soundId, true);
+ _midi->startTrack(0);
}
static const byte elvira1_soundTable[100] = {
diff --git a/engines/agos/rooms.cpp b/engines/agos/rooms.cpp
index f2629e419e..fb7b313e9c 100644
--- a/engines/agos/rooms.cpp
+++ b/engines/agos/rooms.cpp
@@ -401,9 +401,9 @@ bool AGOSEngine::loadRoomItems(uint16 room) {
filename[i] = 0;
p++;
- for (;;) {
- _roomsListPtr = p;
+ _roomsListPtr = p;
+ for (;;) {
minNum = READ_BE_UINT16(p); p += 2;
if (minNum == 0)
break;
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index e6cce36b22..10830db002 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -22,7 +22,6 @@
#include "common/file.h"
#include "common/savefile.h"
-#include "common/system.h"
#include "common/textconsole.h"
#include "common/translation.h"
diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp
index 68a90e405b..1c36454278 100644
--- a/engines/agos/script.cpp
+++ b/engines/agos/script.cpp
@@ -22,8 +22,7 @@
// Item script opcodes for Simon1/Simon2
-
-
+#include "common/endian.h"
#include "common/system.h"
#include "common/textconsole.h"
diff --git a/engines/agos/script_dp.cpp b/engines/agos/script_dp.cpp
index a4ee249f47..f51e15dc67 100644
--- a/engines/agos/script_dp.cpp
+++ b/engines/agos/script_dp.cpp
@@ -24,8 +24,6 @@
#ifdef ENABLE_AGOS2
-#include "common/system.h"
-
#include "agos/agos.h"
namespace AGOS {
diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp
index 3bd8ce19a3..196350b9bf 100644
--- a/engines/agos/script_pn.cpp
+++ b/engines/agos/script_pn.cpp
@@ -23,6 +23,7 @@
#include "agos/agos.h"
#include "agos/vga.h"
+#include "common/endian.h"
#include "common/textconsole.h"
namespace AGOS {
diff --git a/engines/agos/script_s1.cpp b/engines/agos/script_s1.cpp
index 0e7e66778e..a07c05b4fc 100644
--- a/engines/agos/script_s1.cpp
+++ b/engines/agos/script_s1.cpp
@@ -20,8 +20,8 @@
*
*/
-
#include "common/system.h"
+#include "common/localization.h"
#include "graphics/palette.h"
@@ -308,34 +308,9 @@ void AGOSEngine_Simon1::os1_pauseGame() {
// 135: pause game
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
- // If all else fails, use English as fallback.
- Common::KeyCode keyYes = Common::KEYCODE_y;
- Common::KeyCode keyNo = Common::KEYCODE_n;
-
- switch (_language) {
- case Common::RU_RUS:
- break;
- case Common::PL_POL:
- keyYes = Common::KEYCODE_t;
- break;
- case Common::HE_ISR:
- keyYes = Common::KEYCODE_f;
- break;
- case Common::ES_ESP:
- keyYes = Common::KEYCODE_s;
- break;
- case Common::IT_ITA:
- keyYes = Common::KEYCODE_s;
- break;
- case Common::FR_FRA:
- keyYes = Common::KEYCODE_o;
- break;
- case Common::DE_DEU:
- keyYes = Common::KEYCODE_j;
- break;
- default:
- break;
- }
+ Common::KeyCode keyYes, keyNo;
+
+ Common::getLanguageYesNo(_language, keyYes, keyNo);
while (!shouldQuit()) {
delay(1);
diff --git a/engines/agos/script_s2.cpp b/engines/agos/script_s2.cpp
index c646397ac3..c35771f8ec 100644
--- a/engines/agos/script_s2.cpp
+++ b/engines/agos/script_s2.cpp
@@ -23,6 +23,7 @@
#include "agos/agos.h"
+#include "agos/midi.h"
#include "common/textconsole.h"
@@ -342,11 +343,11 @@ void AGOSEngine_Simon2::os2_playTune() {
// effectively preloaded so there's no latency when
// starting playback).
- _midi.setLoop(loop != 0);
+ _midi->setLoop(loop != 0);
if (_lastMusicPlayed != music)
_nextMusicToPlay = music;
else
- _midi.startTrack(track);
+ _midi->startTrack(track);
}
void AGOSEngine_Simon2::os2_screenTextPObj() {
diff --git a/engines/agos/script_ww.cpp b/engines/agos/script_ww.cpp
index 29a91a15aa..873f258743 100644
--- a/engines/agos/script_ww.cpp
+++ b/engines/agos/script_ww.cpp
@@ -22,8 +22,6 @@
-#include "common/system.h"
-
#include "agos/agos.h"
namespace AGOS {
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index 03932aa4de..11a1cd792e 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -22,6 +22,7 @@
#include "common/file.h"
#include "common/memstream.h"
+#include "common/ptr.h"
#include "common/textconsole.h"
#include "common/util.h"
@@ -43,11 +44,10 @@ namespace AGOS {
class BaseSound : Common::NonCopyable {
protected:
- Common::File *_file;
+ Common::DisposablePtr<Common::File> _file;
uint32 *_offsets;
Audio::Mixer *_mixer;
bool _freeOffsets;
- DisposeAfterUse::Flag _disposeFile;
public:
BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 base, bool bigEndian, DisposeAfterUse::Flag disposeFileAfterUse = DisposeAfterUse::YES);
@@ -62,7 +62,7 @@ public:
};
BaseSound::BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 base, bool bigEndian, DisposeAfterUse::Flag disposeFileAfterUse)
- : _mixer(mixer), _file(file), _disposeFile(disposeFileAfterUse) {
+ : _mixer(mixer), _file(file, disposeFileAfterUse) {
uint res = 0;
uint32 size;
@@ -96,7 +96,7 @@ BaseSound::BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 base, bool
}
BaseSound::BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 *offsets, DisposeAfterUse::Flag disposeFileAfterUse)
- : _mixer(mixer), _file(file), _disposeFile(disposeFileAfterUse) {
+ : _mixer(mixer), _file(file, disposeFileAfterUse) {
_offsets = offsets;
_freeOffsets = false;
@@ -105,8 +105,6 @@ BaseSound::BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 *offsets, D
BaseSound::~BaseSound() {
if (_freeOffsets)
free(_offsets);
- if (_disposeFile == DisposeAfterUse::YES)
- delete _file;
}
///////////////////////////////////////////////////////////////////////////////
@@ -234,7 +232,7 @@ Audio::AudioStream *WavSound::makeAudioStream(uint sound) {
return NULL;
_file->seek(_offsets[sound], SEEK_SET);
- return Audio::makeWAVStream(_file, DisposeAfterUse::NO);
+ return Audio::makeWAVStream(_file.get(), DisposeAfterUse::NO);
}
void WavSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol) {
@@ -257,7 +255,7 @@ public:
Audio::AudioStream *VocSound::makeAudioStream(uint sound) {
assert(_offsets);
_file->seek(_offsets[sound], SEEK_SET);
- return Audio::makeVOCStream(_file, _flags);
+ return Audio::makeVOCStream(_file.get(), _flags);
}
void VocSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol) {
diff --git a/engines/agos/sound.h b/engines/agos/sound.h
index a7c4cd73db..ab4a3a963d 100644
--- a/engines/agos/sound.h
+++ b/engines/agos/sound.h
@@ -28,6 +28,10 @@
#include "agos/intern.h"
#include "common/str.h"
+namespace Common {
+class File;
+}
+
namespace AGOS {
class BaseSound;
diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp
index abc45c1ace..dec05f6703 100644
--- a/engines/agos/verb.cpp
+++ b/engines/agos/verb.cpp
@@ -22,7 +22,6 @@
// Verb and hitarea handling
-
#include "common/system.h"
#include "graphics/surface.h"
diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp
index de6a6976e5..8541f579d6 100644
--- a/engines/agos/vga.cpp
+++ b/engines/agos/vga.cpp
@@ -27,6 +27,7 @@
#include "agos/intern.h"
#include "agos/vga.h"
+#include "common/endian.h"
#include "common/system.h"
#include "common/textconsole.h"
diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp
index 1bde6945f0..d4aafd3d7b 100644
--- a/engines/agos/vga_e2.cpp
+++ b/engines/agos/vga_e2.cpp
@@ -26,6 +26,7 @@
#include "agos/agos.h"
#include "agos/intern.h"
+#include "common/endian.h"
#include "common/system.h"
#include "graphics/surface.h"
diff --git a/engines/agos/vga_s2.cpp b/engines/agos/vga_s2.cpp
index 1021ea8f94..9b9ed4e297 100644
--- a/engines/agos/vga_s2.cpp
+++ b/engines/agos/vga_s2.cpp
@@ -20,10 +20,9 @@
*
*/
-
-
#include "agos/agos.h"
#include "agos/intern.h"
+#include "agos/midi.h"
#include "graphics/surface.h"
@@ -146,8 +145,8 @@ void AGOSEngine::vc69_playSeq() {
// specifying a non-valid track number (999 or -1)
// as a means of stopping what music is currently
// playing.
- _midi.setLoop(loop != 0);
- _midi.startTrack(track);
+ _midi->setLoop(loop != 0);
+ _midi->startTrack(track);
}
void AGOSEngine::vc70_joinSeq() {
@@ -161,9 +160,9 @@ void AGOSEngine::vc70_joinSeq() {
// track and, if not, whether to switch to
// a different track upon completion.
if (track != 0xFFFF && track != 999)
- _midi.queueTrack(track, loop != 0);
+ _midi->queueTrack(track, loop != 0);
else
- _midi.setLoop(loop != 0);
+ _midi->setLoop(loop != 0);
}
void AGOSEngine::vc71_ifSeqWaiting() {
@@ -171,7 +170,7 @@ void AGOSEngine::vc71_ifSeqWaiting() {
// This command skips the next instruction
// unless (1) there is a track playing, AND
// (2) there is a track queued to play after it.
- if (!_midi.isPlaying(true))
+ if (!_midi->isPlaying(true))
vcSkipNextInstruction();
}
@@ -195,8 +194,8 @@ void AGOSEngine::vc72_segue() {
if (track == -1 || track == 999) {
stopMusic();
} else {
- _midi.setLoop(loop != 0);
- _midi.startTrack(track);
+ _midi->setLoop(loop != 0);
+ _midi->startTrack(track);
}
}
diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp
index c55e3dcdda..0365c736d8 100644
--- a/engines/agos/window.cpp
+++ b/engines/agos/window.cpp
@@ -21,7 +21,6 @@
*/
-
#include "common/system.h"
#include "common/textconsole.h"
diff --git a/engines/agos/zones.cpp b/engines/agos/zones.cpp
index 61efbcb89a..483b9949eb 100644
--- a/engines/agos/zones.cpp
+++ b/engines/agos/zones.cpp
@@ -214,5 +214,3 @@ void AGOSEngine::checkZonePtrs() {
}
} // End of namespace AGOS
-
-
diff --git a/engines/composer/composer.cpp b/engines/composer/composer.cpp
new file mode 100644
index 0000000000..085ce815dd
--- /dev/null
+++ b/engines/composer/composer.cpp
@@ -0,0 +1,527 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#include "common/scummsys.h"
+
+#include "common/config-manager.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/random.h"
+#include "common/fs.h"
+#include "common/keyboard.h"
+#include "common/substream.h"
+
+#include "graphics/cursorman.h"
+#include "graphics/surface.h"
+#include "graphics/pixelformat.h"
+
+#include "engines/util.h"
+#include "engines/advancedDetector.h"
+
+#include "audio/audiostream.h"
+
+#include "composer/composer.h"
+#include "composer/graphics.h"
+#include "composer/resource.h"
+
+namespace Composer {
+
+ComposerEngine::ComposerEngine(OSystem *syst, const ComposerGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
+ _rnd = new Common::RandomSource("composer");
+ _audioStream = NULL;
+}
+
+ComposerEngine::~ComposerEngine() {
+ DebugMan.clearAllDebugChannels();
+
+ for (Common::List<Library>::iterator i = _libraries.begin(); i != _libraries.end(); i++)
+ delete i->_archive;
+ for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++)
+ i->_surface.free();
+
+ delete _rnd;
+}
+
+Common::Error ComposerEngine::run() {
+ Common::Event event;
+
+ _vars.resize(1000);
+ for (uint i = 0; i < _vars.size(); i++)
+ _vars[i] = 0;
+
+ _queuedScripts.resize(10);
+ for (uint i = 0; i < _queuedScripts.size(); i++) {
+ _queuedScripts[i]._count = 0;
+ _queuedScripts[i]._scriptId = 0;
+ }
+
+ _mouseVisible = true;
+ _mouseEnabled = false;
+ _mouseSpriteId = 0;
+ _lastButton = NULL;
+
+ _directoriesToStrip = 1;
+ if (!_bookIni.loadFromFile("book.ini")) {
+ _directoriesToStrip = 0;
+ if (!_bookIni.loadFromFile("programs/book.ini")) {
+ // mac version?
+ if (!_bookIni.loadFromFile("Darby the Dragon.ini"))
+ if (!_bookIni.loadFromFile("Gregory.ini"))
+ error("failed to find book.ini");
+ }
+ }
+
+ uint width = 640;
+ if (_bookIni.hasKey("Width", "Common"))
+ width = atoi(getStringFromConfig("Common", "Width").c_str());
+ uint height = 480;
+ if (_bookIni.hasKey("Height", "Common"))
+ height = atoi(getStringFromConfig("Common", "Height").c_str());
+ initGraphics(width, height, true);
+ _surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ _needsUpdate = true;
+
+ loadLibrary(0);
+
+ _currentTime = 0;
+ _lastTime = 0;
+
+ uint fps = atoi(getStringFromConfig("Common", "FPS").c_str());
+ uint frameTime = 1000 / fps;
+ uint32 lastDrawTime = 0;
+
+ while (!shouldQuit()) {
+ for (uint i = 0; i < _pendingPageChanges.size(); i++) {
+ if (_pendingPageChanges[i]._remove)
+ unloadLibrary(_pendingPageChanges[i]._pageId);
+ else
+ loadLibrary(_pendingPageChanges[i]._pageId);
+
+ lastDrawTime = _system->getMillis();
+ }
+ _pendingPageChanges.clear();
+
+ uint32 thisTime = _system->getMillis();
+ // maintain our own internal timing, since otherwise we get
+ // confused when starved of CPU (for example when the user
+ // is dragging the scummvm window around)
+ if (thisTime > _lastTime + frameTime)
+ _currentTime += frameTime;
+ else
+ _currentTime += thisTime - _lastTime;
+ _lastTime = thisTime;
+
+ for (uint i = 0; i < _queuedScripts.size(); i++) {
+ QueuedScript &script = _queuedScripts[i];
+ if (!script._count)
+ continue;
+ if (script._baseTime + script._duration > _currentTime)
+ continue;
+ if (script._count != 0xffffffff)
+ script._count--;
+ script._baseTime = _currentTime;
+ runScript(script._scriptId, i, 0, 0);
+ }
+
+ if (lastDrawTime + frameTime <= thisTime) {
+ // catch up if we're more than 2 frames behind
+ if (lastDrawTime + (frameTime * 2) <= thisTime)
+ lastDrawTime = thisTime;
+ else
+ lastDrawTime += frameTime;
+
+ redraw();
+
+ processAnimFrame();
+ } else if (_needsUpdate) {
+ redraw();
+ }
+
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_LBUTTONDOWN:
+ onMouseDown(event.mouse);
+ break;
+
+ case Common::EVENT_LBUTTONUP:
+ break;
+
+ case Common::EVENT_RBUTTONDOWN:
+ break;
+
+ case Common::EVENT_MOUSEMOVE:
+ onMouseMove(event.mouse);
+ break;
+
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_d:
+ /*if (event.kbd.hasFlags(Common::KBD_CTRL)) {
+ // Start the debugger
+ getDebugger()->attach();
+ getDebugger()->onFrame();
+ }*/
+ break;
+
+ case Common::KEYCODE_q:
+ if (event.kbd.hasFlags(Common::KBD_CTRL))
+ quitGame();
+ break;
+
+ default:
+ break;
+ }
+
+ onKeyDown(event.kbd.keycode);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _system->delayMillis(20);
+ }
+
+ return Common::kNoError;
+}
+
+void ComposerEngine::onMouseDown(const Common::Point &pos) {
+ if (!_mouseEnabled || !_mouseVisible)
+ return;
+
+ const Sprite *sprite = getSpriteAtPos(pos);
+ const Button *button = getButtonFor(sprite, pos);
+ if (!button)
+ return;
+
+ // TODO: other buttons?
+ uint16 buttonsDown = 1; // MK_LBUTTON
+
+ uint16 spriteId = sprite ? sprite->_id : 0;
+ runScript(button->_scriptId, button->_id, buttonsDown, spriteId);
+}
+
+void ComposerEngine::onMouseMove(const Common::Point &pos) {
+ _lastMousePos = pos;
+
+ if (!_mouseEnabled || !_mouseVisible)
+ return;
+
+ // TODO: do we need to keep track of this?
+ uint buttonsDown = 0;
+
+ const Sprite *sprite = getSpriteAtPos(pos);
+ const Button *button = getButtonFor(sprite, pos);
+ if (_lastButton != button) {
+ if (_lastButton && _lastButton->_scriptIdRollOff)
+ runScript(_lastButton->_scriptIdRollOff, _lastButton->_id, buttonsDown, 0);
+ _lastButton = button;
+ if (_lastButton && _lastButton->_scriptIdRollOn)
+ runScript(_lastButton->_scriptIdRollOn, _lastButton->_id, buttonsDown, 0);
+ }
+
+ if (_mouseSpriteId) {
+ addSprite(_mouseSpriteId, 0, 0, _lastMousePos - _mouseOffset);
+ _needsUpdate = true;
+ }
+}
+
+void ComposerEngine::onKeyDown(uint16 keyCode) {
+ runEvent(kEventKeyDown, keyCode, 0, 0);
+ runEvent(kEventChar, keyCode, 0, 0);
+}
+
+void ComposerEngine::setCursor(uint16 id, const Common::Point &offset) {
+ _mouseOffset = offset;
+ if (_mouseSpriteId == id)
+ return;
+
+ if (_mouseSpriteId && _mouseVisible) {
+ removeSprite(_mouseSpriteId, 0);
+ }
+ _mouseSpriteId = id;
+ if (_mouseSpriteId && _mouseVisible) {
+ addSprite(_mouseSpriteId, 0, 0, _lastMousePos - _mouseOffset);
+ }
+}
+
+void ComposerEngine::setCursorVisible(bool visible) {
+ if (visible && !_mouseVisible) {
+ _mouseVisible = true;
+ if (_mouseSpriteId)
+ addSprite(_mouseSpriteId, 0, 0, _lastMousePos - _mouseOffset);
+ onMouseMove(_lastMousePos);
+ } else if (!visible && _mouseVisible) {
+ _mouseVisible = false;
+ if (_mouseSpriteId)
+ removeSprite(_mouseSpriteId, 0);
+ }
+}
+
+Common::String ComposerEngine::getStringFromConfig(const Common::String &section, const Common::String &key) {
+ Common::String value;
+ if (!_bookIni.getKey(key, section, value))
+ error("failed to find key '%s' in section '%s' of book config", key.c_str(), section.c_str());
+ return value;
+}
+
+Common::String ComposerEngine::getFilename(const Common::String &section, uint id) {
+ Common::String key = Common::String::format("%d", id);
+ Common::String filename = getStringFromConfig(section, key);
+
+ return mangleFilename(filename);
+}
+
+Common::String ComposerEngine::mangleFilename(Common::String filename) {
+ while (filename.size() && (filename[0] == '~' || filename[0] == ':' || filename[0] == '\\'))
+ filename = filename.c_str() + 1;
+
+ uint slashesToStrip = _directoriesToStrip;
+ while (slashesToStrip--) {
+ for (uint i = 0; i < filename.size(); i++) {
+ if (filename[i] != '\\' && filename[i] != ':')
+ continue;
+ filename = filename.c_str() + i + 1;
+ break;
+ }
+ }
+
+ Common::String outFilename;
+ for (uint i = 0; i < filename.size(); i++) {
+ if (filename[i] == '\\' || filename[i] == ':')
+ outFilename += '/';
+ else
+ outFilename += filename[i];
+ }
+ return outFilename;
+}
+
+void ComposerEngine::loadLibrary(uint id) {
+ if (!id)
+ id = atoi(getStringFromConfig("Common", "StartUp").c_str());
+ Common::String filename = getFilename("Libs", id);
+
+ Library library;
+
+ library._id = id;
+ library._archive = new ComposerArchive();
+ if (!library._archive->openFile(filename))
+ error("failed to open '%s'", filename.c_str());
+ _libraries.push_front(library);
+
+ Library &newLib = _libraries.front();
+
+ Common::Array<uint16> buttonResources = library._archive->getResourceIDList(ID_BUTN);
+ for (uint i = 0; i < buttonResources.size(); i++) {
+ uint16 buttonId = buttonResources[i];
+ Common::SeekableReadStream *stream = library._archive->getResource(ID_BUTN, buttonId);
+ Button button(stream, buttonId, getGameType());
+
+ bool inserted = false;
+ for (Common::List<Button>::iterator b = newLib._buttons.begin(); b != newLib._buttons.end(); b++) {
+ if (button._zorder < b->_zorder)
+ continue;
+ newLib._buttons.insert(b, button);
+ inserted = true;
+ break;
+ }
+ if (!inserted)
+ newLib._buttons.push_back(button);
+ }
+
+ // add background sprite, if it exists
+ if (hasResource(ID_BMAP, 1000))
+ setBackground(1000);
+
+ // TODO: better CTBL logic
+ loadCTBL(1000, 100);
+
+ // Run the startup script.
+ runScript(1000, 0, 0, 0);
+
+ _mouseEnabled = true;
+ onMouseMove(_lastMousePos);
+
+ runEvent(kEventLoad, id, 0, 0);
+}
+
+void ComposerEngine::unloadLibrary(uint id) {
+ for (Common::List<Library>::iterator i = _libraries.begin(); i != _libraries.end(); i++) {
+ if (i->_id != id)
+ continue;
+
+ for (Common::List<Animation *>::iterator j = _anims.begin(); j != _anims.end(); j++) {
+ delete *j;
+ }
+ _anims.clear();
+ for (Common::List<Pipe *>::iterator j = _pipes.begin(); j != _pipes.end(); j++) {
+ delete *j;
+ }
+ _pipes.clear();
+
+ for (Common::List<Sprite>::iterator j = _sprites.begin(); j != _sprites.end(); j++) {
+ j->_surface.free();
+ }
+ _sprites.clear();
+ i->_buttons.clear();
+
+ _lastButton = NULL;
+
+ _mixer->stopAll();
+ _audioStream = NULL;
+
+ for (uint j = 0; j < _queuedScripts.size(); j++) {
+ _queuedScripts[j]._count = 0;
+ _queuedScripts[j]._scriptId = 0;
+ }
+
+ delete i->_archive;
+ _libraries.erase(i);
+
+ runEvent(kEventUnload, id, 0, 0);
+
+ return;
+ }
+
+ error("tried to unload library %d, which isn't loaded", id);
+}
+
+bool ComposerEngine::hasResource(uint32 tag, uint16 id) {
+ for (Common::List<Library>::iterator i = _libraries.begin(); i != _libraries.end(); i++)
+ if (i->_archive->hasResource(tag, id))
+ return true;
+
+ return false;
+}
+
+Common::SeekableReadStream *ComposerEngine::getResource(uint32 tag, uint16 id) {
+ for (Common::List<Library>::iterator i = _libraries.begin(); i != _libraries.end(); i++)
+ if (i->_archive->hasResource(tag, id))
+ return i->_archive->getResource(tag, id);
+
+ error("No loaded library contains '%s' %04x", tag2str(tag), id);
+}
+
+Button::Button(Common::SeekableReadStream *stream, uint16 id, uint gameType) {
+ _id = id;
+
+ _type = stream->readUint16LE();
+ _active = (_type & 0x8000) ? true : false;
+ _type &= 0xfff;
+ debug(9, "button %d: type %d, active %d", id, _type, _active);
+
+ uint16 flags = 0;
+ uint16 size = 4;
+ if (gameType == GType_ComposerV1) {
+ flags = stream->readUint16LE();
+ _zorder = 0;
+ _scriptId = stream->readUint16LE();
+ _scriptIdRollOn = 0;
+ _scriptIdRollOff = 0;
+ } else {
+ _zorder = stream->readUint16LE();
+ _scriptId = stream->readUint16LE();
+ _scriptIdRollOn = stream->readUint16LE();
+ _scriptIdRollOff = stream->readUint16LE();
+
+ stream->skip(4);
+
+ size = stream->readUint16LE();
+ }
+
+ switch (_type) {
+ case kButtonRect:
+ case kButtonEllipse:
+ if (size != 4)
+ error("button %d of type %d had %d points, not 4", id, _type, size);
+ _rect.left = stream->readSint16LE();
+ _rect.top = stream->readSint16LE();
+ _rect.right = stream->readSint16LE();
+ _rect.bottom = stream->readSint16LE();
+ break;
+ case kButtonSprites:
+ if (gameType == GType_ComposerV1)
+ error("encountered kButtonSprites in V1 data");
+ for (uint i = 0; i < size; i++) {
+ _spriteIds.push_back(stream->readUint16LE());
+ }
+ break;
+ default:
+ error("unknown button type %d", _type);
+ }
+
+ if (flags & 0x40) {
+ _scriptIdRollOn = stream->readUint16LE();
+ _scriptIdRollOff = stream->readUint16LE();
+ }
+
+ delete stream;
+}
+
+bool Button::contains(const Common::Point &pos) const {
+ switch (_type) {
+ case kButtonRect:
+ return _rect.contains(pos);
+ case kButtonEllipse:
+ if (!_rect.contains(pos))
+ return false;
+ {
+ int16 a = _rect.width() / 2;
+ int16 b = _rect.height() / 2;
+ if (!a || !b)
+ return false;
+ Common::Point adjustedPos = pos - Common::Point(_rect.left + a, _rect.top + b);
+ return ((adjustedPos.x*adjustedPos.x)/(a*a) + (adjustedPos.y*adjustedPos.y)/(b*b) < 1);
+ }
+ case kButtonSprites:
+ return false;
+ default:
+ error("internal error (button type %d)", _type);
+ }
+}
+
+const Button *ComposerEngine::getButtonFor(const Sprite *sprite, const Common::Point &pos) {
+ for (Common::List<Library>::iterator l = _libraries.begin(); l != _libraries.end(); l++) {
+ for (Common::List<Button>::iterator i = l->_buttons.reverse_begin(); i != l->_buttons.end(); --i) {
+ if (!i->_active)
+ continue;
+
+ if (i->_spriteIds.empty()) {
+ if (i->contains(pos))
+ return &(*i);
+ continue;
+ }
+
+ if (!sprite)
+ continue;
+
+ for (uint j = 0; j < i->_spriteIds.size(); j++) {
+ if (i->_spriteIds[j] == sprite->_id)
+ return &(*i);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+} // End of namespace Composer
diff --git a/engines/composer/composer.h b/engines/composer/composer.h
new file mode 100644
index 0000000000..03e895b59e
--- /dev/null
+++ b/engines/composer/composer.h
@@ -0,0 +1,215 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef COMPOSER_H
+#define COMPOSER_H
+
+#include "common/config-file.h"
+#include "common/random.h"
+#include "common/system.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/textconsole.h"
+#include "common/rect.h"
+
+#include "engines/engine.h"
+#include "engines/util.h"
+
+#include "graphics/surface.h"
+
+#include "audio/mixer.h"
+
+#include "composer/resource.h"
+
+namespace Audio {
+ class QueuingAudioStream;
+}
+
+namespace Composer {
+
+struct ComposerGameDescription;
+
+enum GameType {
+ GType_ComposerV1,
+ GType_ComposerV2
+};
+
+class Archive;
+struct Animation;
+class ComposerEngine;
+class Pipe;
+struct Sprite;
+
+enum {
+ kButtonRect = 0,
+ kButtonEllipse = 1,
+ kButtonSprites = 4
+};
+
+class Button {
+public:
+ Button() { }
+ Button(Common::SeekableReadStream *stream, uint16 id, uint gameType);
+
+ bool contains(const Common::Point &pos) const;
+
+ uint16 _id;
+ uint16 _type;
+ uint16 _zorder;
+ uint16 _scriptId;
+ uint16 _scriptIdRollOn;
+ uint16 _scriptIdRollOff;
+ bool _active;
+
+ Common::Rect _rect;
+ Common::Array<uint16> _spriteIds;
+};
+
+enum {
+ kEventAnimStarted = 1,
+ kEventAnimDone = 2,
+ kEventLoad = 3,
+ kEventUnload = 4,
+ kEventKeyDown = 5,
+ kEventChar = 6,
+ kEventKeyUp = 7
+};
+
+struct Library {
+ uint _id;
+ Archive *_archive;
+
+ Common::List<Button> _buttons;
+};
+
+struct QueuedScript {
+ uint32 _baseTime;
+ uint32 _duration;
+ uint32 _count;
+ uint16 _scriptId;
+};
+
+struct PendingPageChange {
+ PendingPageChange() { }
+ PendingPageChange(uint16 id, bool remove) : _pageId(id), _remove(remove) { }
+
+ uint16 _pageId;
+ bool _remove;
+};
+
+class ComposerEngine : public Engine {
+protected:
+ Common::Error run();
+
+public:
+ ComposerEngine(OSystem *syst, const ComposerGameDescription *gameDesc);
+ virtual ~ComposerEngine();
+
+ virtual bool hasFeature(EngineFeature f) const;
+
+ int getGameType() const;
+ const char *getGameId() const;
+ uint32 getFeatures() const;
+ Common::Language getLanguage() const;
+
+ const ComposerGameDescription *_gameDescription;
+
+private:
+ Common::RandomSource *_rnd;
+
+ Audio::SoundHandle _soundHandle;
+ Audio::QueuingAudioStream *_audioStream;
+ uint16 _currSoundPriority;
+
+ uint32 _currentTime, _lastTime;
+
+ bool _needsUpdate;
+ Common::Array<Common::Rect> _dirtyRects;
+ Graphics::Surface _surface;
+ Common::List<Sprite> _sprites;
+
+ uint _directoriesToStrip;
+ Common::ConfigFile _bookIni;
+ Common::List<Library> _libraries;
+ Common::Array<PendingPageChange> _pendingPageChanges;
+
+ Common::Array<uint16> _stack;
+ Common::Array<uint16> _vars;
+
+ Common::Array<QueuedScript> _queuedScripts;
+ Common::List<Animation *> _anims;
+ Common::List<Pipe *> _pipes;
+
+ void onMouseDown(const Common::Point &pos);
+ void onMouseMove(const Common::Point &pos);
+ void onKeyDown(uint16 keyCode);
+ void setCursor(uint16 id, const Common::Point &offset);
+ void setCursorVisible(bool visible);
+
+ bool _mouseEnabled;
+ bool _mouseVisible;
+ Common::Point _lastMousePos;
+ const Button *_lastButton;
+ uint16 _mouseSpriteId;
+ Common::Point _mouseOffset;
+
+ Common::String getStringFromConfig(const Common::String &section, const Common::String &key);
+ Common::String getFilename(const Common::String &section, uint id);
+ Common::String mangleFilename(Common::String filename);
+ void loadLibrary(uint id);
+ void unloadLibrary(uint id);
+
+ bool hasResource(uint32 tag, uint16 id);
+ Common::SeekableReadStream *getResource(uint32 tag, uint16 id);
+
+ void runEvent(uint16 id, int16 param1, int16 param2, int16 param3);
+ int16 runScript(uint16 id, int16 param1, int16 param2, int16 param3);
+
+ int16 getArg(uint16 arg, uint16 type);
+ void setArg(uint16 arg, uint16 type, uint16 val);
+ void runScript(uint16 id);
+ int16 scriptFuncCall(uint16 id, int16 param1, int16 param2, int16 param3);
+
+ void playAnimation(uint16 animId, int16 param1, int16 param2, int16 param3);
+ void stopAnimation(Animation *anim, bool localOnly = false, bool pipesOnly = false);
+ void playWaveForAnim(uint16 id, uint16 priority, bool bufferingOnly);
+ void processAnimFrame();
+
+ bool spriteVisible(uint16 id, uint16 animId);
+ Sprite *addSprite(uint16 id, uint16 animId, uint16 zorder, const Common::Point &pos);
+ void removeSprite(uint16 id, uint16 animId);
+ const Sprite *getSpriteAtPos(const Common::Point &pos);
+ const Button *getButtonFor(const Sprite *sprite, const Common::Point &pos);
+
+ void dirtySprite(const Sprite &sprite);
+ void redraw();
+ void loadCTBL(uint16 id, uint fadePercent);
+ void setBackground(uint16 id);
+ void decompressBitmap(uint16 type, Common::SeekableReadStream *stream, byte *buffer, uint32 size, uint width, uint height);
+ bool initSprite(Sprite &sprite);
+ Common::SeekableReadStream *getStreamForSprite(uint16 id);
+ void drawSprite(const Sprite &sprite);
+};
+
+} // End of namespace Composer
+
+#endif
diff --git a/engines/composer/detection.cpp b/engines/composer/detection.cpp
new file mode 100644
index 0000000000..2ca00f9f53
--- /dev/null
+++ b/engines/composer/detection.cpp
@@ -0,0 +1,286 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "base/plugins.h"
+#include "engines/advancedDetector.h"
+
+#include "composer/composer.h"
+
+namespace Composer {
+
+struct ComposerGameDescription {
+ ADGameDescription desc;
+
+ int gameType;
+};
+
+int ComposerEngine::getGameType() const {
+ return _gameDescription->gameType;
+}
+
+const char *ComposerEngine::getGameId() const {
+ return _gameDescription->desc.gameid;
+}
+
+uint32 ComposerEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+Common::Language ComposerEngine::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
+}
+
+static const PlainGameDescriptor composerGames[] = {
+ {"composer", "Composer Game"},
+ {"darby", "Darby the Dragon"},
+ {"gregory", "Gregory and the Hot Air Balloon"},
+ {"liam", "Magic Tales: Liam Finds a Story"},
+ {"princess", "The Princess and the Crab"},
+ {"sleepingcub", "Sleeping Cub's Test of Courage"},
+ {0, 0}
+};
+
+namespace Composer {
+
+using Common::GUIO_NONE;
+
+static const ComposerGameDescription gameDescriptions[] = {
+ // from Liam Finds a Story CD
+ {
+ {
+ "magictales",
+ "Magic Tales Demo: Baby Yaga, Samurai, Imo",
+ AD_ENTRY1("book.ini", "dbc98c566f4ac61b544443524585dccb"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_USEEXTRAASTITLE | ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV1
+ },
+
+ {
+ {
+ "liam",
+ 0,
+ AD_ENTRY1s("book.ini", "fc9d9b9e72e7301d011b808606eaa15b", 834),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ // from Liam Finds a Story CD
+ {
+ {
+ "magictales",
+ "Magic Tales Demo: Sleeping Cub, Princess & Crab",
+ AD_ENTRY1("book.ini", "3dede2522bb0886c95667b082987a87f"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_USEEXTRAASTITLE | ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ {
+ {
+ "darby",
+ 0,
+ {
+ {"book.ini", 0, "7e3404c559d058521fff2aebe5c427a8", 2545},
+ {"page99.rsc", 0, "49cc6b16caa1c5ec7d94a3c47eed9a02", 1286480},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ {
+ {
+ "darby",
+ 0,
+ AD_ENTRY1("Darby the Dragon.ini", "d81f9214936fa70d42fc578908d4bb3d"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ { // Provided by Strangerke, "CD-Rom 100% Malin" Pack
+ {
+ "darby",
+ 0,
+ AD_ENTRY1("book.ini", "285308372f7dddff2ca5a25c9192cf5c"),
+ Common::FR_FRA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ {
+ {
+ "gregory",
+ 0,
+ {
+ {"book.ini", 0, "14a562dcf361773445255af9f3e94790", 2234},
+ {"page99.rsc", 0, "01f9381162467e052dfd4c704169ef3e", 388644},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ {
+ {
+ "gregory",
+ 0,
+ AD_ENTRY1("Gregory.ini", "fa82f14731f28c7379c5a106df07a0d6"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ { // Provided by Strangerke, "CD-Rom 100% Malin" Pack
+ {
+ "gregory",
+ 0,
+ AD_ENTRY1("book.ini", "e54fc5c00de5f94e908a969e445af5d0"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ { // Provided by sev
+ {
+ "princess",
+ 0,
+ {
+ {"book.ini", 0, "fb32572577b9a41ba299825ef1e3181e", 966},
+ {"page99.rsc", 0, "fd5ebd3b5e36c4651c50241619525355", 45418},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ { // Provided by sev
+ {
+ "sleepingcub",
+ 0,
+ {
+ {"book.ini", 0, "0d329e592387009c6387a733a3ea2235", 964},
+ {"page99.rsc", 0, "219fbd9bd2ff87c7023814405d753145", 46916},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_ComposerV2
+ },
+
+ { AD_TABLE_END_MARKER, 0 }
+};
+
+} // End of namespace Composer
+
+using namespace Composer;
+
+// we match from data too, to stop detection from a non-top-level directory
+const static char *directoryGlobs[] = {
+ "data",
+ "programs",
+ "princess",
+ "sleepcub",
+ 0
+};
+
+class ComposerMetaEngine : public AdvancedMetaEngine {
+public:
+ ComposerMetaEngine() : AdvancedMetaEngine(Composer::gameDescriptions, sizeof(Composer::ComposerGameDescription), composerGames) {
+ _singleid = "composer";
+ _maxScanDepth = 2;
+ _directoryGlobs = directoryGlobs;
+ }
+
+ virtual const char *getName() const {
+ return "Magic Composer Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Copyright (C) 1995-1999 Animation Magic";
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
+};
+
+bool ComposerMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const Composer::ComposerGameDescription *gd = (const Composer::ComposerGameDescription *)desc;
+ if (gd) {
+ *engine = new Composer::ComposerEngine(syst, gd);
+ }
+ return gd != 0;
+}
+
+bool ComposerMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return false;
+}
+
+bool Composer::ComposerEngine::hasFeature(EngineFeature f) const {
+ return (f == kSupportsRTL);
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(COMPOSER)
+REGISTER_PLUGIN_DYNAMIC(COMPOSER, PLUGIN_TYPE_ENGINE, ComposerMetaEngine);
+#else
+REGISTER_PLUGIN_STATIC(COMPOSER, PLUGIN_TYPE_ENGINE, ComposerMetaEngine);
+#endif
diff --git a/engines/composer/graphics.cpp b/engines/composer/graphics.cpp
new file mode 100644
index 0000000000..0768a86e7a
--- /dev/null
+++ b/engines/composer/graphics.cpp
@@ -0,0 +1,774 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#include "common/scummsys.h"
+
+#include "graphics/palette.h"
+
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+
+#include "composer/composer.h"
+#include "composer/graphics.h"
+#include "composer/resource.h"
+
+namespace Composer {
+
+bool Sprite::contains(const Common::Point &pos) const {
+ Common::Point adjustedPos = pos - _pos;
+
+ if (adjustedPos.x < 0 || adjustedPos.x >= _surface.w)
+ return false;
+ if (adjustedPos.y < 0 || adjustedPos.y >= _surface.h)
+ return false;
+ byte *pixels = (byte *)_surface.pixels;
+ return (pixels[(_surface.h - adjustedPos.y - 1) * _surface.w + adjustedPos.x] != 0);
+}
+
+enum {
+ kAnimOpEvent = 1,
+ kAnimOpPlayWave = 2,
+ kAnimOpPlayAnim = 3,
+ kAnimOpDrawSprite = 4
+};
+
+Animation::Animation(Common::SeekableReadStream *stream, uint16 id, Common::Point basePos, uint32 eventParam)
+ : _stream(stream), _id(id), _basePos(basePos), _eventParam(eventParam) {
+ uint32 size = _stream->readUint32LE();
+ _state = _stream->readUint32LE() + 1;
+
+ // probably total size?
+ uint32 unknown = _stream->readUint32LE();
+
+ debug(8, "anim: size %d, state %08x, unknown %08x", size, _state, unknown);
+
+ for (uint i = 0; i < size; i++) {
+ AnimationEntry entry;
+ entry.op = _stream->readUint16LE();
+ entry.priority = _stream->readUint16LE();
+ entry.state = _stream->readUint16LE();
+ entry.counter = 0;
+ entry.prevValue = 0;
+ debug(8, "anim entry: %04x, %04x, %04x", entry.op, entry.priority, entry.state);
+ _entries.push_back(entry);
+ }
+
+ _offset = _stream->pos();
+}
+
+Animation::~Animation() {
+ delete _stream;
+}
+
+void Animation::seekToCurrPos() {
+ _stream->seek(_offset, SEEK_SET);
+}
+
+void ComposerEngine::playAnimation(uint16 animId, int16 x, int16 y, int16 eventParam) {
+ // First, we check if this animation is already playing,
+ // and if it is, we sabotage that running one first.
+ for (Common::List<Animation *>::iterator i = _anims.begin(); i != _anims.end(); i++) {
+ Animation *anim = *i;
+ if (anim->_id != animId)
+ continue;
+
+ stopAnimation(*i);
+ }
+
+ Common::SeekableReadStream *stream = NULL;
+ Pipe *newPipe = NULL;
+
+ // First, check the existing pipes.
+ for (Common::List<Pipe *>::iterator j = _pipes.begin(); j != _pipes.end(); j++) {
+ Pipe *pipe = *j;
+ if (!pipe->hasResource(ID_ANIM, animId))
+ continue;
+ stream = pipe->getResource(ID_ANIM, animId, false);
+ break;
+ }
+
+ // If we didn't find it, try the libraries.
+ if (!stream) {
+ if (!hasResource(ID_ANIM, animId)) {
+ warning("ignoring attempt to play invalid anim %d", animId);
+ return;
+ }
+ stream = getResource(ID_ANIM, animId);
+
+ uint32 type = 0;
+ for (Common::List<Library>::iterator i = _libraries.begin(); i != _libraries.end(); i++)
+ if (i->_archive->hasResource(ID_ANIM, animId)) {
+ type = i->_archive->getResourceFlags(ID_ANIM, animId);
+ break;
+ }
+
+ // If the resource is a pipe itself, then load the pipe
+ // and then fish the requested animation out of it.
+ if (type != 1) {
+ newPipe = new Pipe(stream);
+ _pipes.push_front(newPipe);
+ stream = newPipe->getResource(ID_ANIM, animId, false);
+ }
+ }
+
+ Animation *anim = new Animation(stream, animId, Common::Point(x, y), eventParam);
+ _anims.push_back(anim);
+ runEvent(kEventAnimStarted, animId, eventParam, 0);
+ if (newPipe)
+ newPipe->_anim = anim;
+}
+
+void ComposerEngine::stopAnimation(Animation *anim, bool localOnly, bool pipesOnly) {
+ // disable the animation
+ anim->_state = 0;
+
+ // stop any animations it may have spawned
+ for (uint j = 0; j < anim->_entries.size(); j++) {
+ AnimationEntry &entry = anim->_entries[j];
+ if (!entry.prevValue)
+ continue;
+ if (localOnly) {
+ if (pipesOnly)
+ continue;
+ if (entry.op == kAnimOpDrawSprite) {
+ removeSprite(entry.prevValue, anim->_id);
+ } else if (entry.op == kAnimOpPlayWave) {
+ if (_currSoundPriority >= entry.priority) {
+ _mixer->stopAll();
+ _audioStream = NULL;
+ }
+ }
+ } else {
+ if (entry.op != kAnimOpPlayAnim)
+ continue;
+ for (Common::List<Animation *>::iterator i = _anims.begin(); i != _anims.end(); i++) {
+ if ((*i)->_id == entry.prevValue)
+ stopAnimation(*i);
+ }
+ }
+ }
+
+ // kill any pipe owned by the animation
+ for (Common::List<Pipe *>::iterator j = _pipes.begin(); j != _pipes.end(); j++) {
+ Pipe *pipe = *j;
+ if (pipe->_anim != anim)
+ continue;
+ j = _pipes.reverse_erase(j);
+ delete pipe;
+ break;
+ }
+}
+
+void ComposerEngine::playWaveForAnim(uint16 id, uint16 priority, bool bufferingOnly) {
+ if (_audioStream && _audioStream->numQueuedStreams() != 0) {
+ if (_currSoundPriority < priority)
+ return;
+ if (_currSoundPriority > priority) {
+ _mixer->stopAll();
+ _audioStream = NULL;
+ }
+ }
+ Common::SeekableReadStream *stream = NULL;
+ if (!bufferingOnly && hasResource(ID_WAVE, id)) {
+ stream = getResource(ID_WAVE, id);
+ } else {
+ for (Common::List<Pipe *>::iterator k = _pipes.begin(); k != _pipes.end(); k++) {
+ Pipe *pipe = *k;
+ if (!pipe->hasResource(ID_WAVE, id))
+ continue;
+ stream = pipe->getResource(ID_WAVE, id, true);
+ break;
+ }
+ }
+ if (!stream)
+ return;
+ // FIXME: non-pipe buffers have fixed wav header (data at +44, size at +40)
+ byte *buffer = (byte *)malloc(stream->size());
+ stream->read(buffer, stream->size());
+ if (!_audioStream)
+ _audioStream = Audio::makeQueuingAudioStream(22050, false);
+ _audioStream->queueBuffer(buffer, stream->size(), DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
+ _currSoundPriority = priority;
+ delete stream;
+ if (!_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream);
+}
+
+void ComposerEngine::processAnimFrame() {
+ for (Common::List<Animation *>::iterator i = _anims.begin(); i != _anims.end(); i++) {
+ Animation *anim = *i;
+
+ anim->seekToCurrPos();
+
+ if (anim->_state <= 1) {
+ bool normalEnd = (anim->_state == 1);
+ if (normalEnd) {
+ runEvent(kEventAnimDone, anim->_id, anim->_eventParam, 0);
+ }
+ stopAnimation(anim, true, normalEnd);
+ delete anim;
+ i = _anims.reverse_erase(i);
+
+ continue;
+ }
+
+ for (uint j = 0; j < anim->_entries.size(); j++) {
+ AnimationEntry &entry = anim->_entries[j];
+ if (entry.op != kAnimOpEvent)
+ break;
+ if (entry.counter) {
+ entry.counter--;
+ } else {
+ if ((anim->_state > 1) && (anim->_stream->pos() + 2 > anim->_stream->size())) {
+ warning("anim with id %d ended too soon", anim->_id);
+ anim->_state = 0;
+ break;
+ }
+
+ uint16 event = anim->_stream->readUint16LE();
+ anim->_offset += 2;
+ if (event == 0xffff) {
+ entry.counter = anim->_stream->readUint16LE() - 1;
+ anim->_offset += 2;
+ } else {
+ debug(4, "anim: event %d", event);
+ runEvent(event, anim->_id, 0, 0);
+ }
+ }
+ }
+ }
+
+ for (Common::List<Animation *>::iterator i = _anims.begin(); i != _anims.end(); i++) {
+ Animation *anim = *i;
+
+ // did the anim get disabled?
+ if (anim->_state == 0) {
+ stopAnimation(anim, true, false);
+ delete anim;
+ i = _anims.reverse_erase(i);
+ continue;
+ }
+
+ anim->_state--;
+
+ bool foundWait = false;
+ for (uint j = 0; j < anim->_entries.size(); j++) {
+ AnimationEntry &entry = anim->_entries[j];
+
+ // only skip these at the start
+ if (!foundWait && (entry.op == kAnimOpEvent))
+ continue;
+ foundWait = true;
+
+ if (entry.counter) {
+ entry.counter--;
+ if ((entry.op == kAnimOpPlayWave) && entry.prevValue) {
+ debug(4, "anim: continue play wave %d", entry.prevValue);
+ playWaveForAnim(entry.prevValue, entry.priority, true);
+ }
+ } else {
+ anim->seekToCurrPos();
+ if ((anim->_state > 1) && (anim->_stream->pos() + 2 > anim->_stream->size())) {
+ warning("anim with id %d ended too soon", anim->_id);
+ anim->_state = 0;
+ break;
+ }
+
+ uint16 data = anim->_stream->readUint16LE();
+ anim->_offset += 2;
+ if (data == 0xffff) {
+ entry.counter = anim->_stream->readUint16LE() - 1;
+ anim->_offset += 2;
+ } else {
+ switch (entry.op) {
+ case kAnimOpEvent:
+ debug(4, "anim: event %d", data);
+ runEvent(data, anim->_id, 0, 0);
+ break;
+ case kAnimOpPlayWave:
+ debug(4, "anim: play wave %d", data);
+ playWaveForAnim(data, entry.priority, false);
+ break;
+ case kAnimOpPlayAnim:
+ debug(4, "anim: play anim %d", data);
+ playAnimation(data, anim->_basePos.x, anim->_basePos.y, 1);
+ break;
+ case kAnimOpDrawSprite:
+ if (!data || (entry.prevValue && (data != entry.prevValue))) {
+ debug(4, "anim: erase sprite %d", entry.prevValue);
+ removeSprite(entry.prevValue, anim->_id);
+ }
+ if (data) {
+ int16 x = anim->_stream->readSint16LE();
+ int16 y = anim->_stream->readSint16LE();
+ Common::Point pos(x, y);
+ anim->_offset += 4;
+ uint16 animId = anim->_id;
+ if (anim->_state == entry.state)
+ animId = 0;
+ debug(4, "anim: draw sprite %d at (relative) %d,%d", data, x, y);
+ bool wasVisible = spriteVisible(data, animId);
+ addSprite(data, animId, entry.priority, anim->_basePos + pos);
+ if (wasVisible) {
+ // make sure modified sprite isn't removed by another entry
+ for (uint k = 0; k < anim->_entries.size(); k++) {
+ if (anim->_entries[k].op != kAnimOpDrawSprite)
+ continue;
+ if (anim->_entries[k].prevValue == data)
+ anim->_entries[k].prevValue = 1;
+ }
+ }
+ }
+ break;
+ default:
+ warning("unknown anim op %d", entry.op);
+ }
+
+ entry.prevValue = data;
+ }
+ }
+ }
+ }
+
+ for (Common::List<Pipe *>::iterator j = _pipes.begin(); j != _pipes.end(); j++) {
+ Pipe *pipe = *j;
+ pipe->nextFrame();
+ }
+}
+
+bool ComposerEngine::spriteVisible(uint16 id, uint16 animId) {
+ for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) {
+ if (i->_id != id)
+ continue;
+ if (i->_animId && animId && (i->_animId != animId))
+ continue;
+ return true;
+ }
+
+ return false;
+}
+
+Sprite *ComposerEngine::addSprite(uint16 id, uint16 animId, uint16 zorder, const Common::Point &pos) {
+ Sprite sprite;
+ bool foundSprite = false;
+
+ // re-use old sprite, if any (the BMAP for this id might well have
+ // changed in the meantime, but the scripts depend on that!)
+ for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) {
+ if (i->_id != id)
+ continue;
+ if (i->_animId && animId && (i->_animId != animId))
+ continue;
+
+ dirtySprite(*i);
+
+ // if the zordering is identical, modify it in-place
+ if (i->_zorder == zorder) {
+ i->_animId = animId;
+ i->_pos = pos;
+ dirtySprite(*i);
+ return &(*i);
+ }
+
+ // otherwise, take a copy and remove it from the list
+ sprite = *i;
+ foundSprite = true;
+ _sprites.erase(i);
+ break;
+ }
+
+ sprite._animId = animId;
+ sprite._zorder = zorder;
+ sprite._pos = pos;
+
+ if (!foundSprite) {
+ sprite._id = id;
+ if (!initSprite(sprite)) {
+ debug(1, "ignoring addSprite on invalid sprite %d", id);
+ return NULL;
+ }
+ }
+
+ dirtySprite(sprite);
+
+ for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) {
+ if (sprite._zorder <= i->_zorder)
+ continue;
+ // insert *before* this sprite
+ _sprites.insert(i, sprite);
+ --i;
+ return &(*i);
+ }
+ _sprites.push_back(sprite);
+ return &_sprites.back();
+}
+
+void ComposerEngine::removeSprite(uint16 id, uint16 animId) {
+ for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) {
+ if (!i->_id || (id && i->_id != id))
+ continue;
+ if (i->_animId && animId && (i->_animId != animId))
+ continue;
+ dirtySprite(*i);
+ i->_surface.free();
+ i = _sprites.reverse_erase(i);
+ if (id)
+ break;
+ }
+}
+
+const Sprite *ComposerEngine::getSpriteAtPos(const Common::Point &pos) {
+ for (Common::List<Sprite>::iterator i = _sprites.reverse_begin(); i != _sprites.end(); --i) {
+ // avoid highest-level objects (e.g. the cursor)
+ if (!i->_zorder)
+ continue;
+
+ if (i->contains(pos))
+ return &(*i);
+ }
+
+ return NULL;
+}
+
+void ComposerEngine::dirtySprite(const Sprite &sprite) {
+ Common::Rect rect(sprite._pos.x, sprite._pos.y, sprite._pos.x + sprite._surface.w, sprite._pos.y + sprite._surface.h);
+ rect.clip(_surface.w, _surface.h);
+ if (rect.isEmpty())
+ return;
+
+ for (uint i = 0; i < _dirtyRects.size(); i++) {
+ if (!_dirtyRects[i].intersects(rect))
+ continue;
+ _dirtyRects[i].extend(rect);
+ return;
+ }
+
+ _dirtyRects.push_back(rect);
+}
+
+void ComposerEngine::redraw() {
+ if (!_needsUpdate && _dirtyRects.empty())
+ return;
+
+ for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) {
+ Common::Rect rect(i->_pos.x, i->_pos.y, i->_pos.x + i->_surface.w, i->_pos.y + i->_surface.h);
+ bool intersects = false;
+ for (uint j = 0; j < _dirtyRects.size(); j++) {
+ if (!_dirtyRects[j].intersects(rect))
+ continue;
+ intersects = true;
+ break;
+ }
+ if (!intersects)
+ continue;
+ drawSprite(*i);
+ }
+
+ for (uint i = 0; i < _dirtyRects.size(); i++) {
+ const Common::Rect &rect = _dirtyRects[i];
+ byte *pixels = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+ _system->copyRectToScreen(pixels, _surface.pitch, rect.left, rect.top, rect.width(), rect.height());
+ }
+ _system->updateScreen();
+
+ _needsUpdate = false;
+ _dirtyRects.clear();
+}
+
+void ComposerEngine::loadCTBL(uint16 id, uint fadePercent) {
+ Common::SeekableReadStream *stream = getResource(ID_CTBL, id);
+
+ uint16 numEntries = stream->readUint16LE();
+ debug(1, "CTBL: %d entries", numEntries);
+
+ assert(numEntries <= 256);
+ assert(stream->size() == 2 + (numEntries * 3));
+
+ byte buffer[256 * 3];
+ stream->read(buffer, numEntries * 3);
+ delete stream;
+
+ for (uint16 i = 0; i < numEntries * 3; i++)
+ buffer[i] = ((unsigned int)buffer[i] * fadePercent) / 100;
+
+ _system->getPaletteManager()->setPalette(buffer, 0, numEntries);
+ _needsUpdate = true;
+}
+
+void ComposerEngine::setBackground(uint16 id) {
+ for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) {
+ if (i->_id)
+ continue;
+ dirtySprite(*i);
+ i->_surface.free();
+ i->_id = id;
+ if (!initSprite(*i))
+ error("failed to set background %d", id);
+ dirtySprite(*i);
+ i->_id = 0;
+ return;
+ }
+
+ Sprite *background = addSprite(id, 0, 0xffff, Common::Point());
+ if (background)
+ background->_id = 0;
+}
+
+static void decompressSLWM(byte *buffer, Common::SeekableReadStream *stream) {
+ uint bitsLeft = 0;
+ uint16 lastBits;
+ byte currBit;
+ while (true) {
+ if (bitsLeft == 0) { bitsLeft = 16; lastBits = stream->readUint16LE(); }
+ currBit = (lastBits & 1); lastBits >>= 1; bitsLeft--;
+
+ if (currBit) {
+ // single byte
+ *buffer++ = stream->readByte();
+ continue;
+ }
+
+ if (bitsLeft == 0) { bitsLeft = 16; lastBits = stream->readUint16LE(); }
+ currBit = (lastBits & 1); lastBits >>= 1; bitsLeft--;
+
+ uint start;
+ uint count;
+ if (currBit) {
+ uint orMask = stream->readByte();
+ uint in = stream->readByte();
+ count = in & 7;
+ start = ((in & ~7) << 5) | orMask;
+ if (!count) {
+ count = stream->readByte();
+ if (!count)
+ break;
+ count -= 2;
+ }
+ } else {
+ // count encoded in the next two bits
+ count = 0;
+
+ if (bitsLeft == 0) { bitsLeft = 16; lastBits = stream->readUint16LE(); }
+ currBit = (lastBits & 1); lastBits >>= 1; bitsLeft--;
+
+ count = (count << 1) | currBit;
+
+ if (bitsLeft == 0) { bitsLeft = 16; lastBits = stream->readUint16LE(); }
+ currBit = (lastBits & 1); lastBits >>= 1; bitsLeft--;
+
+ count = (count << 1) | currBit;
+
+ start = stream->readByte();
+ }
+
+ count += 2;
+ start++;
+ for (uint i = 0; i < count; i++) {
+ *buffer = *(buffer - start);
+ buffer++;
+ }
+ }
+}
+
+// bitmap compression types
+enum {
+ kBitmapUncompressed = 0,
+ kBitmapSpp32 = 1,
+ kBitmapSLW8 = 3,
+ kBitmapRLESLWM = 4,
+ kBitmapSLWM = 5
+};
+
+void ComposerEngine::decompressBitmap(uint16 type, Common::SeekableReadStream *stream, byte *buffer, uint32 size, uint width, uint height) {
+ uint outSize = width * height;
+
+ switch (type) {
+ case kBitmapUncompressed:
+ if (stream->size() - (uint)stream->pos() != size)
+ error("kBitmapUncompressed stream had %d bytes left, supposed to be %d",
+ stream->size() - (uint)stream->pos(), size);
+ if (size != outSize)
+ error("kBitmapUncompressed size %d doesn't match required size %d",
+ size, outSize);
+ stream->read(buffer, size);
+ break;
+ case kBitmapSpp32:
+ byte lookup[16];
+ stream->read(lookup, 16);
+ while (size--) {
+ uint in = stream->readByte();
+ byte lowBits = in & 0xF;
+ byte highBits = (in & 0xF0) >> 4;
+ if (highBits == 0xf) {
+ // run of a single color
+ uint count = (uint)stream->readByte() + 3;
+ size--;
+ if (outSize < count)
+ error("kBitmapSpp32 only needed %d bytes, but got run of %d",
+ outSize, count);
+ outSize -= count;
+ memset(buffer, lookup[lowBits], count);
+ buffer += count;
+ } else {
+ // two pixels
+ if (!outSize)
+ error("kBitmapSpp32 had too many pixels");
+ *buffer++ = lookup[highBits];
+ outSize--;
+ if (outSize) {
+ *buffer++ = lookup[lowBits];
+ outSize--;
+ }
+ }
+ }
+ break;
+ case kBitmapSLW8:
+ while (size--) {
+ byte val = stream->readByte();
+ if (val != 0xff) {
+ *buffer++ = val;
+ continue;
+ }
+ uint count = stream->readByte();
+ size--;
+
+ uint16 step;
+ if (!(count & 0x80)) {
+ step = stream->readByte();
+ size--;
+ } else {
+ count = (count ^ 0x80);
+ step = stream->readUint16LE();
+ size -= 2;
+ }
+ count += 4;
+ // this is often overlapping (for repeating patterns)
+ for (uint i = 0; i < count; i++) {
+ *buffer = *(buffer - step - 1);
+ buffer++;
+ }
+ }
+ break;
+ case kBitmapRLESLWM:
+ {
+ uint32 bufSize = stream->readUint32LE();
+ byte *tempBuf = new byte[bufSize];
+ decompressSLWM(tempBuf, stream);
+
+ uint instrPos = tempBuf[0] + 1;
+ instrPos += READ_LE_UINT16(tempBuf + instrPos) + 2;
+ byte *instr = tempBuf + instrPos;
+
+ uint line = 0;
+ while (line++ < height) {
+ uint pixels = 0;
+
+ while (pixels < width) {
+ byte data = *instr++;
+ byte color = tempBuf[(data & 0x7F) + 1];
+ if (!(data & 0x80)) {
+ *buffer++ = color;
+ pixels++;
+ } else {
+ byte count = *instr++;
+ if (!count) {
+ while (pixels++ < width)
+ *buffer++ = color;
+ break;
+ }
+ for (uint i = 0; i < count; i++) {
+ *buffer++ = color;
+ pixels++;
+ }
+ }
+ }
+ }
+ delete[] tempBuf;
+ }
+ break;
+ case kBitmapSLWM:
+ decompressSLWM(buffer, stream);
+ break;
+ default:
+ error("decompressBitmap can't handle type %d", type);
+ }
+}
+
+Common::SeekableReadStream *ComposerEngine::getStreamForSprite(uint16 id) {
+ for (Common::List<Pipe *>::iterator k = _pipes.begin(); k != _pipes.end(); k++) {
+ Pipe *pipe = *k;
+ if (!pipe->hasResource(ID_BMAP, id))
+ continue;
+ return pipe->getResource(ID_BMAP, id, true);
+ }
+ if (hasResource(ID_BMAP, id))
+ return getResource(ID_BMAP, id);
+ return NULL;
+}
+
+bool ComposerEngine::initSprite(Sprite &sprite) {
+ Common::SeekableReadStream *stream = getStreamForSprite(sprite._id);
+ if (!stream)
+ return false;
+
+ uint16 type = stream->readUint16LE();
+ int16 height = stream->readSint16LE();
+ int16 width = stream->readSint16LE();
+ uint32 size = stream->readUint32LE();
+ debug(1, "loading BMAP: type %d, width %d, height %d, size %d", type, width, height, size);
+
+ if (width > 0 && height > 0) {
+ sprite._surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ decompressBitmap(type, stream, (byte *)sprite._surface.pixels, size, width, height);
+ } else {
+ // there are some sprites (e.g. a -998x-998 one in Gregory's title screen)
+ // which have an invalid size, but the original engine doesn't notice for
+ // RLE sprites since the width/height is ignored until the actual draw
+ if (type != kBitmapRLESLWM)
+ error("sprite (type %d) had invalid size %dx%d", type, width, height);
+ delete stream;
+ return false;
+ }
+ delete stream;
+
+ return true;
+}
+
+void ComposerEngine::drawSprite(const Sprite &sprite) {
+ int x = sprite._pos.x;
+ int y = sprite._pos.y;
+
+ // incoming data is BMP-style (bottom-up), so flip it
+ byte *pixels = (byte *)_surface.pixels;
+ for (int j = 0; j < sprite._surface.h; j++) {
+ if (j + y < 0)
+ continue;
+ if (j + y >= _surface.h)
+ break;
+ byte *in = (byte *)sprite._surface.pixels + (sprite._surface.h - j - 1) * sprite._surface.w;
+ byte *out = pixels + ((j + y) * _surface.w) + x;
+ for (int i = 0; i < sprite._surface.w; i++)
+ if ((x + i >= 0) && (x + i < _surface.w) && in[i])
+ out[i] = in[i];
+ }
+}
+
+} // End of namespace Composer
diff --git a/engines/composer/graphics.h b/engines/composer/graphics.h
new file mode 100644
index 0000000000..e9d82920ba
--- /dev/null
+++ b/engines/composer/graphics.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef COMPOSER_GRAPHICS_H
+#define COMPOSER_GRAPHICS_H
+
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace Composer {
+
+class ComposerEngine;
+
+struct Sprite {
+ uint16 _id;
+ uint16 _animId;
+ uint16 _zorder;
+ Common::Point _pos;
+ Graphics::Surface _surface;
+
+ bool contains(const Common::Point &pos) const;
+};
+
+struct AnimationEntry {
+ uint32 state;
+ uint16 op;
+ uint16 priority;
+ uint16 counter;
+ uint16 prevValue;
+};
+
+struct Animation {
+ Animation(Common::SeekableReadStream *stream, uint16 id, Common::Point basePos, uint32 eventParam);
+ ~Animation();
+
+ void seekToCurrPos();
+
+ uint16 _id;
+ Common::Point _basePos;
+ uint32 _eventParam;
+
+ uint32 _state;
+
+ Common::Array<AnimationEntry> _entries;
+
+ uint32 _offset;
+ Common::SeekableReadStream *_stream;
+};
+
+} // End of namespace Composer
+
+#endif
diff --git a/engines/composer/module.mk b/engines/composer/module.mk
new file mode 100644
index 0000000000..8bfaf932e8
--- /dev/null
+++ b/engines/composer/module.mk
@@ -0,0 +1,16 @@
+MODULE := engines/composer
+
+MODULE_OBJS = \
+ composer.o \
+ detection.o \
+ graphics.o \
+ resource.o \
+ scripting.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_COMPOSER), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/composer/resource.cpp b/engines/composer/resource.cpp
new file mode 100644
index 0000000000..b40bdb379b
--- /dev/null
+++ b/engines/composer/resource.cpp
@@ -0,0 +1,337 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "composer/resource.h"
+
+#include "common/debug.h"
+#include "common/memstream.h"
+#include "common/substream.h"
+#include "common/util.h"
+#include "common/textconsole.h"
+
+namespace Composer {
+
+// Base Archive code
+// (copied from clone2727's mohawk code)
+
+Archive::Archive() {
+ _stream = 0;
+}
+
+Archive::~Archive() {
+ close();
+}
+
+bool Archive::openFile(const Common::String &fileName) {
+ Common::File *file = new Common::File();
+
+ if (!file->open(fileName)) {
+ delete file;
+ return false;
+ }
+
+ if (!openStream(file)) {
+ close();
+ return false;
+ }
+
+ return true;
+}
+
+void Archive::close() {
+ _types.clear();
+ delete _stream; _stream = 0;
+}
+
+bool Archive::hasResource(uint32 tag, uint16 id) const {
+ if (!_types.contains(tag))
+ return false;
+
+ return _types[tag].contains(id);
+}
+
+bool Archive::hasResource(uint32 tag, const Common::String &resName) const {
+ if (!_types.contains(tag) || resName.empty())
+ return false;
+
+ const ResourceMap &resMap = _types[tag];
+
+ for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+ if (it->_value.name.matchString(resName))
+ return true;
+
+ return false;
+}
+
+Common::SeekableReadStream *Archive::getResource(uint32 tag, uint16 id) {
+ if (!_types.contains(tag))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ const ResourceMap &resMap = _types[tag];
+
+ if (!resMap.contains(id))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ const Resource &res = resMap[id];
+
+ return new Common::SeekableSubReadStream(_stream, res.offset, res.offset + res.size);
+}
+
+uint32 Archive::getResourceFlags(uint32 tag, uint16 id) const {
+ if (!_types.contains(tag))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ const ResourceMap &resMap = _types[tag];
+
+ if (!resMap.contains(id))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ const Resource &res = resMap[id];
+
+ return res.flags;
+}
+
+uint32 Archive::getOffset(uint32 tag, uint16 id) const {
+ if (!_types.contains(tag))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ const ResourceMap &resMap = _types[tag];
+
+ if (!resMap.contains(id))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ return resMap[id].offset;
+}
+
+uint16 Archive::findResourceID(uint32 tag, const Common::String &resName) const {
+ if (!_types.contains(tag) || resName.empty())
+ return 0xFFFF;
+
+ const ResourceMap &resMap = _types[tag];
+
+ for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+ if (it->_value.name.matchString(resName))
+ return it->_key;
+
+ return 0xFFFF;
+}
+
+Common::String Archive::getName(uint32 tag, uint16 id) const {
+ if (!_types.contains(tag))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ const ResourceMap &resMap = _types[tag];
+
+ if (!resMap.contains(id))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ return resMap[id].name;
+}
+
+Common::Array<uint32> Archive::getResourceTypeList() const {
+ Common::Array<uint32> typeList;
+
+ for (TypeMap::const_iterator it = _types.begin(); it != _types.end(); it++)
+ typeList.push_back(it->_key);
+
+ return typeList;
+}
+
+Common::Array<uint16> Archive::getResourceIDList(uint32 type) const {
+ Common::Array<uint16> idList;
+
+ if (!_types.contains(type))
+ return idList;
+
+ const ResourceMap &resMap = _types[type];
+
+ for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+ idList.push_back(it->_key);
+
+ return idList;
+}
+
+// Composer Archive code
+
+bool ComposerArchive::openStream(Common::SeekableReadStream *stream) {
+ // Make sure no other file is open...
+ close();
+
+ bool newStyle = false;
+ uint32 headerSize = stream->readUint32LE();
+ if (headerSize == SWAP_CONSTANT_32(ID_LBRC)) {
+ // new-style file
+ newStyle = true;
+ headerSize = stream->readUint32LE();
+ uint32 zeros = stream->readUint32LE();
+ if (zeros != 0)
+ error("invalid LBRC header (%d instead of zeros)", zeros);
+ }
+
+ uint16 numResourceTypes = stream->readUint16LE();
+ if (newStyle) {
+ uint16 unknown = stream->readUint16LE();
+ debug(4, "skipping unknown %04x", unknown);
+ }
+
+ debug(4, "Reading LBRC resource table with %d entries", numResourceTypes);
+ for (uint i = 0; i < numResourceTypes; i++) {
+ uint32 tag = stream->readUint32BE();
+ uint32 tableOffset = stream->readUint32LE();
+ debug(4, "Type '%s' at offset %d", tag2str(tag), tableOffset);
+ // starting from the start of the resource table, which differs
+ // according to whether we have the 10 extra bytes for newStyle
+ if (newStyle)
+ tableOffset += 16;
+ else
+ tableOffset += 6;
+
+ ResourceMap &resMap = _types[tag];
+
+ uint32 oldPos = stream->pos();
+ stream->seek(tableOffset);
+
+ while (true) {
+ if (stream->eos())
+ error("LBRC file ran out of stream");
+
+ uint32 offset, size, id, flags;
+ if (newStyle) {
+ offset = stream->readUint32LE();
+ if (!offset)
+ break;
+ size = stream->readUint32LE();
+ id = stream->readUint16LE();
+ flags = stream->readUint16LE(); // set to 1 for preload, otherwise no preload
+ /*uint32 junk = */ stream->readUint32LE();
+ } else {
+ id = stream->readUint16LE();
+ if (!id)
+ break;
+ offset = stream->readUint32LE();
+ offset += headerSize;
+ size = stream->readUint32LE();
+ flags = stream->readUint16LE(); // FIXME
+
+ }
+
+ Resource &res = resMap[id];
+ res.offset = offset;
+ res.size = size;
+ res.flags = flags;
+ debug(4, "Id %d, offset %d, size %d, flags %08x", id, offset, size, flags);
+ }
+
+ stream->seek(oldPos);
+ }
+
+ _stream = stream;
+ return true;
+}
+
+Pipe::Pipe(Common::SeekableReadStream *stream) {
+ _offset = 0;
+ _stream = stream;
+ _anim = NULL;
+
+ nextFrame();
+}
+
+void Pipe::nextFrame() {
+ if (_offset == (uint)_stream->size())
+ return;
+
+ _stream->seek(_offset, SEEK_SET);
+
+ uint32 tagCount = _stream->readUint32LE();
+ _offset += 4;
+ for (uint i = 0; i < tagCount; i++) {
+ uint32 tag = _stream->readUint32BE();
+ uint32 count = _stream->readUint32LE();
+ _offset += 8;
+
+ ResourceMap &resMap = _types[tag];
+
+ _offset += (12 * count);
+ for (uint j = 0; j < count; j++) {
+ uint32 offset = _stream->readUint32LE();
+ uint32 size = _stream->readUint32LE();
+ uint16 id = _stream->readUint16LE();
+ uint32 unknown = _stream->readUint16LE(); // frame id?
+ debug(9, "pipe: %s/%d: offset %d, size %d, unknown %d", tag2str(tag), id, offset, size, unknown);
+
+ PipeResourceEntry entry;
+ entry.size = size;
+ entry.offset = _offset;
+ resMap[id].entries.push_back(entry);
+
+ _offset += size;
+ }
+ _stream->seek(_offset, SEEK_SET);
+ }
+}
+
+bool Pipe::hasResource(uint32 tag, uint16 id) const {
+ if (!_types.contains(tag))
+ return false;
+
+ return _types[tag].contains(id);
+}
+
+Common::SeekableReadStream *Pipe::getResource(uint32 tag, uint16 id, bool buffering) {
+ if (!_types.contains(tag))
+ error("Pipe does not contain '%s' %04x", tag2str(tag), id);
+
+ const ResourceMap &resMap = _types[tag];
+
+ if (!resMap.contains(id))
+ error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+ const PipeResource &res = resMap[id];
+
+ if (res.entries.size() == 1) {
+ Common::SeekableReadStream *stream = new Common::SeekableSubReadStream(_stream,
+ res.entries[0].offset, res.entries[0].offset + res.entries[0].size);
+ if (buffering)
+ _types[tag].erase(id);
+ return stream;
+ }
+
+ // If there are multiple entries in the pipe, we have to concaternate them together.
+
+ uint32 size = 0;
+ for (uint i = 0; i < res.entries.size(); i++)
+ size += res.entries[i].size;
+
+ byte *buffer = (byte *)malloc(size);
+ uint32 offset = 0;
+ for (uint i = 0; i < res.entries.size(); i++) {
+ _stream->seek(res.entries[i].offset, SEEK_SET);
+ _stream->read(buffer + offset, res.entries[i].size);
+ offset += res.entries[i].size;
+ }
+ if (buffering)
+ _types[tag].erase(id);
+ return new Common::MemoryReadStream(buffer, size, DisposeAfterUse::YES);
+}
+
+} // End of namespace Composer
diff --git a/engines/composer/resource.h b/engines/composer/resource.h
new file mode 100644
index 0000000000..9408cdffb8
--- /dev/null
+++ b/engines/composer/resource.h
@@ -0,0 +1,124 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/endian.h"
+#include "common/hashmap.h"
+#include "common/file.h"
+#include "common/str.h"
+
+#ifndef COMPOSER_RESOURCE_H
+#define COMPOSER_RESOURCE_H
+
+namespace Composer {
+
+struct Animation;
+
+#define ID_LBRC MKTAG('L','B','R','C') // Main FourCC
+
+#define ID_ANIM MKTAG('A','N','I','M') // Animation
+#define ID_BMAP MKTAG('B','M','A','P') // Bitmap
+#define ID_BUTN MKTAG('B','U','T','N') // Button
+#define ID_CTBL MKTAG('C','T','B','L') // Color Table
+#define ID_EVNT MKTAG('E','V','N','T') // Event
+#define ID_PIPE MKTAG('P','I','P','E') // Pipe
+#define ID_SCRP MKTAG('S','C','R','P') // Script
+#define ID_VARI MKTAG('V','A','R','I') // Variables
+#define ID_WAVE MKTAG('W','A','V','E') // Wave
+
+class Archive {
+public:
+ Archive();
+ virtual ~Archive();
+
+ bool openFile(const Common::String &fileName);
+ virtual bool openStream(Common::SeekableReadStream *stream) = 0;
+ void close();
+
+ bool isOpen() const { return _stream != 0; }
+
+ bool hasResource(uint32 tag, uint16 id) const;
+ bool hasResource(uint32 tag, const Common::String &resName) const;
+ Common::SeekableReadStream *getResource(uint32 tag, uint16 id);
+ uint32 getResourceFlags(uint32 tag, uint16 id) const;
+ uint32 getOffset(uint32 tag, uint16 id) const;
+ uint16 findResourceID(uint32 tag, const Common::String &resName) const;
+ Common::String getName(uint32 tag, uint16 id) const;
+
+ Common::Array<uint32> getResourceTypeList() const;
+ Common::Array<uint16> getResourceIDList(uint32 type) const;
+
+protected:
+ Common::SeekableReadStream *_stream;
+
+ struct Resource {
+ uint32 offset;
+ uint32 size;
+ Common::String name;
+ uint32 flags;
+ };
+
+ typedef Common::HashMap<uint16, Resource> ResourceMap;
+ typedef Common::HashMap<uint32, ResourceMap> TypeMap;
+ TypeMap _types;
+};
+
+class ComposerArchive : public Archive {
+public:
+ ComposerArchive() : Archive() {}
+ ~ComposerArchive() {}
+
+ bool openStream(Common::SeekableReadStream *stream);
+};
+
+struct PipeResourceEntry {
+ uint32 size;
+ uint32 offset;
+};
+
+struct PipeResource {
+ Common::Array<PipeResourceEntry> entries;
+};
+
+class Pipe {
+public:
+ Pipe(Common::SeekableReadStream *stream);
+ void nextFrame();
+
+ Animation *_anim;
+
+ bool hasResource(uint32 tag, uint16 id) const;
+ Common::SeekableReadStream *getResource(uint32 tag, uint16 id, bool buffering);
+
+protected:
+ Common::SeekableReadStream *_stream;
+
+ typedef Common::HashMap<uint16, PipeResource> ResourceMap;
+ typedef Common::HashMap<uint32, ResourceMap> TypeMap;
+ TypeMap _types;
+
+ uint32 _offset;
+};
+
+} // End of namespace Composer
+
+#endif
diff --git a/engines/composer/scripting.cpp b/engines/composer/scripting.cpp
new file mode 100644
index 0000000000..1989919233
--- /dev/null
+++ b/engines/composer/scripting.cpp
@@ -0,0 +1,729 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#include "common/scummsys.h"
+#include "common/savefile.h"
+
+#include "composer/composer.h"
+#include "composer/graphics.h"
+#include "composer/resource.h"
+
+namespace Composer {
+
+// new script ops
+enum {
+ kOpPlusPlus = 0x1,
+ kOpMinusMinus = 0x2,
+ kOpAssign = 0x3,
+ kOpAdd = 0x4,
+ kOpSubtract = 0x5,
+ kOpMultiply = 0x6,
+ kOpDivide = 0x7,
+ kOpModulo = 0x8,
+ kOpMaybeAlsoAssign = 0x9,
+ kOpBooleanAssign = 0xA,
+ kOpNegate = 0xB,
+ kOpAnd = 0xC,
+ kOpOr = 0xD,
+ kOpXor = 0xE,
+ kOpNot = 0xF,
+ kOpSqrt = 0x10,
+ kOpRandom = 0x11,
+ kOpExecuteScript = 0x12,
+ kOpCallFunc = 0x13,
+ kOpBoolLessThanEq = 0x17,
+ kOpBoolLessThan = 0x16,
+ kOpBoolGreaterThanEq = 0x15,
+ kOpBoolGreaterThan = 0x14,
+ kOpBoolEqual = 0x18,
+ kOpBoolNotEqual = 0x19,
+ kOpSaveArgs = 0x1A,
+ kOpRestoreArgs = 0x1B,
+ kOpReturn = 0x20,
+ kOpLessThanEq = 0x22,
+ kOpLessThan = 0x21,
+ kOpGreaterThanEq = 0x24,
+ kOpGreaterThan = 0x23,
+ kOpEqual = 0x25,
+ kOpNotEqual = 0x26,
+ kOpJump = 0x80,
+ kOpJumpIfNot = 0x81,
+ kOpJumpIf = 0x82,
+ kOpJumpIfNotValue = 0x83,
+ kOpJumpIfValue = 0x84
+};
+
+enum {
+ kFuncPlayAnim = 35001,
+ kFuncStopAnim = 35002,
+ // (no 35003)
+ kFuncQueueScript = 35004,
+ kFuncDequeueScript = 35005,
+ kFuncSetCursor = 35006,
+ kFuncGetCursor = 35007,
+ kFuncShowCursor = 35008,
+ kFuncHideCursor = 35009,
+ // (no 35010)
+ kFuncActivateButton = 35011,
+ kFuncDeactivateButton = 35012,
+ kFuncNewPage = 35013,
+ kFuncLoadPage = 35014,
+ kFuncUnloadPage = 35015,
+ kFuncSetPalette = 35016,
+ kFuncSaveVars = 35017,
+ kFuncLoadVars = 35018,
+ kFuncQueueScriptOnce = 35019,
+ kFuncGetMousePos = 35020,
+ kFuncChangeBackground = 35021,
+ kFuncSetBackgroundColor = 35022,
+ kFuncClearSprites = 35023,
+ kFuncAddSprite = 35024,
+ kFuncRemoveSprite = 35025,
+ kFuncQuit = 35026,
+ kFuncSaveData = 35027,
+ kFuncLoadData = 35028,
+ kFuncGetSpriteSize = 35029
+};
+
+void ComposerEngine::runEvent(uint16 id, int16 param1, int16 param2, int16 param3) {
+ if (!hasResource(ID_EVNT, id))
+ return;
+
+ Common::SeekableReadStream *stream = getResource(ID_EVNT, id);
+ if (stream->size() != 2)
+ error("bad EVNT size %d", stream->size());
+ uint16 scriptId = stream->readUint16LE();
+ delete stream;
+
+ if (!scriptId)
+ return;
+
+ debug(2, "running event %d via script %d(%d, %d, %d)", id, scriptId, param1, param2, param3);
+
+ runScript(scriptId, param1, param2, param3);
+}
+
+int16 ComposerEngine::runScript(uint16 id, int16 param1, int16 param2, int16 param3) {
+ _vars[1] = param1;
+ _vars[2] = param2;
+ _vars[3] = param3;
+
+ runScript(id);
+
+ return _vars[0];
+}
+
+int16 ComposerEngine::getArg(uint16 arg, uint16 type) {
+ switch (type) {
+ case 0:
+ return (int16)arg;
+ case 1:
+ return (int16)_vars[arg];
+ case 2:
+ return (int16)_vars[_vars[arg]];
+ default:
+ error("invalid argument type %d (getting arg %d)", type, arg);
+ }
+}
+
+void ComposerEngine::setArg(uint16 arg, uint16 type, uint16 val) {
+ switch (type) {
+ case 1:
+ _vars[arg] = val;
+ break;
+ case 2:
+ _vars[_vars[arg]] = val;
+ break;
+ default:
+ error("invalid argument type %d (setting arg %d)", type, arg);
+ }
+
+}
+
+void ComposerEngine::runScript(uint16 id) {
+ if (!hasResource(ID_SCRP, id)) {
+ debug(1, "ignoring attempt to run script %d, because it doesn't exist", id);
+ return;
+ }
+
+ uint stackBase = _stack.size();
+ _stack.resize(_stack.size() + 19);
+
+ Common::SeekableReadStream *stream = getResource(ID_SCRP, id);
+ if (stream->size() < 2)
+ error("SCRP was too small (%d)", stream->size());
+ uint16 size = stream->readUint16LE();
+ if (stream->size() < 2 + 2*size)
+ error("SCRP was too small (%d, but claimed %d entries)", stream->size(), size);
+ uint16 *script = new uint16[size];
+ for (uint i = 0; i < size; i++)
+ script[i] = stream->readUint16LE();
+ delete stream;
+
+ uint16 pos = 0;
+ bool lastResult = false;
+ while (pos < size) {
+ int16 val1, val2, val3;
+
+ byte op = (byte)script[pos];
+ uint numParams = (script[pos] & 0x300) >> 8; // 2 bits
+ if (pos + numParams >= size)
+ error("script ran out of content");
+ uint arg1 = (script[pos] & 0xc00) >> 10; // 2 bits
+ uint arg2 = (script[pos] & 0x3000) >> 12; // 2 bits
+ uint arg3 = (script[pos] & 0xC000) >> 14; // 2 bits
+ switch (op) {
+ case kOpPlusPlus:
+ if (numParams != 1)
+ error("kOpPlusPlus had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ debug(9, "[%d/%d]++ (now %d)", script[pos + 1], arg1, val1 + 1);
+ setArg(script[pos + 1], arg1, val1 + 1);
+ break;
+ case kOpMinusMinus:
+ if (numParams != 1)
+ error("kOpMinusMinus had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ debug(9, "[%d/%d]-- (now %d)", script[pos + 1], arg1, val1 - 1);
+ setArg(script[pos + 1], arg1, val1 - 1);
+ break;
+ case kOpAssign:
+ if (numParams != 2)
+ error("kOpAssign had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] = [%d/%d] (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2);
+ setArg(script[pos + 1], arg1, val2);
+ break;
+ case kOpAdd:
+ if (numParams != 3)
+ error("kOpAdd had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d]=%d + [%d/%d]=%d (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val2 + val3);
+ setArg(script[pos + 1], arg1, val2 + val3);
+ break;
+ case kOpSubtract:
+ if (numParams != 3)
+ error("kOpSubtract had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d]=%d - [%d/%d]=%d (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val2 - val3);
+ setArg(script[pos + 1], arg1, val2 - val3);
+ break;
+ case kOpMultiply:
+ if (numParams != 3)
+ error("kOpMultiply had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d]=%d * [%d/%d]=%d (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val2 * val3);
+ setArg(script[pos + 1], arg1, val2 * val3);
+ break;
+ case kOpDivide:
+ if (numParams != 3)
+ error("kOpDivide had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ if (val3 == 0)
+ error("script tried to divide by zero");
+ debug(9, "[%d/%d] = [%d/%d]=%d / [%d/%d]=%d (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val2 / val3);
+ setArg(script[pos + 1], arg1, val2 / val3);
+ break;
+ case kOpModulo:
+ if (numParams != 3)
+ error("kOpModulo had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ if (val3 == 0)
+ error("script tried to divide by zero (modulo)");
+ debug(9, "[%d/%d] = [%d/%d]=%d %% [%d/%d]=%d (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val2 % val3);
+ setArg(script[pos + 1], arg1, val2 % val3);
+ break;
+ case kOpMaybeAlsoAssign:
+ if (numParams != 2)
+ error("kOpMaybeAlsoAssign had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] =(?) [%d/%d] (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2);
+ setArg(script[pos + 1], arg1, val2);
+ break;
+ case kOpBooleanAssign:
+ if (numParams != 2)
+ error("kOpBooleanAssign had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] = [%d/%d] (%d) ? 1 : 0", script[pos + 1], arg1, script[pos + 2], arg2, val2);
+ setArg(script[pos + 1], arg1, val2 ? 1 : 0);
+ break;
+ case kOpNegate:
+ if (numParams != 2)
+ error("kOpNegate had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] = -[%d/%d] (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2);
+ setArg(script[pos + 1], arg1, -val2);
+ break;
+ case kOpAnd:
+ if (numParams != 3)
+ error("kOpAnd had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d]=%d & [%d/%d]=%d (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val2 & val3);
+ setArg(script[pos + 1], arg1, val2 & val3);
+ break;
+ case kOpOr:
+ if (numParams != 3)
+ error("kOpOr had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d]=%d | [%d/%d]=%d (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val2 | val3);
+ setArg(script[pos + 1], arg1, val2 | val3);
+ break;
+ case kOpXor:
+ if (numParams != 3)
+ error("kOpXor had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d]=%d ^ [%d/%d]=%d (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val2 ^ val3);
+ setArg(script[pos + 1], arg1, val2 ^ val3);
+ break;
+ case kOpNot:
+ if (numParams != 2)
+ error("kOpNot had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] = ![%d/%d] (!%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2);
+ setArg(script[pos + 1], arg1, val2 ? 0 : 1);
+ break;
+ case kOpSqrt:
+ if (numParams != 2)
+ error("kOpSqrt had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] = sqrt([%d/%d] (%d))", script[pos + 1], arg1, script[pos + 2], arg2, val2);
+ setArg(script[pos + 1], arg1, (int16)sqrt((double)val2));
+ break;
+ case kOpRandom:
+ if (numParams != 3)
+ error("kOpRandom had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ val1 = _rnd->getRandomNumberRng(val2, val3);
+ debug(9, "[%d/%d] = rnd([%d/%d]=%d, [%d/%d]=%d) (%d)", script[pos + 1], arg1, script[pos + 2], arg2, val2, script[pos+3], arg3, val3, val1);
+ setArg(script[pos + 1], arg1, val1);
+ break;
+ case kOpExecuteScript:
+ if (numParams != 1)
+ error("kOpExecuteScript had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ debug(8, "run script [%d/%d]=%d", script[pos + 1], arg1, val1);
+ runScript(val1);
+ debug(8, "done run script");
+ break;
+ case kOpCallFunc:
+ if (numParams != 1)
+ error("kOpCallFunc had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ debug(8, "%d(%d, %d, %d)", (uint16)val1, _vars[1], _vars[2], _vars[3]);
+ _vars[0] = scriptFuncCall(val1, _vars[1], _vars[2], _vars[3]);
+ break;
+ case kOpBoolLessThanEq:
+ if (numParams != 2)
+ error("kOpBoolLessThanEq had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] <= [%d/%d]? (%d <= %d)", script[pos + 1], arg1, script[pos + 2], arg2, val1, val2);
+ lastResult = (val1 <= val2);
+ break;
+ case kOpBoolLessThan:
+ if (numParams != 2)
+ error("kOpBoolLessThan had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] < [%d/%d]? (%d < %d)", script[pos + 1], arg1, script[pos + 2], arg2, val1, val2);
+ lastResult = (val1 < val2);
+ break;
+ case kOpBoolGreaterThanEq:
+ if (numParams != 2)
+ error("kOpBoolGreaterThanEq had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] >= [%d/%d]? (%d >= %d)", script[pos + 1], arg1, script[pos + 2], arg2, val1, val2);
+ lastResult = (val1 >= val2);
+ break;
+ case kOpBoolGreaterThan:
+ if (numParams != 2)
+ error("kOpBoolGreaterThan had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] > [%d/%d]? (%d > %d)", script[pos + 1], arg1, script[pos + 2], arg2, val1, val2);
+ lastResult = (val1 > val2);
+ break;
+ case kOpBoolEqual:
+ if (numParams != 2)
+ error("kOpBoolEqual had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] == [%d/%d]? (%d == %d)", script[pos + 1], arg1, script[pos + 2], arg2, val1, val2);
+ lastResult = (val1 == val2);
+ break;
+ case kOpBoolNotEqual:
+ if (numParams != 2)
+ error("kOpBoolNotEqual had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "[%d/%d] != [%d/%d]? (%d != %d)", script[pos + 1], arg1, script[pos + 2], arg2, val1, val2);
+ lastResult = (val1 != val2);
+ break;
+ case kOpSaveArgs:
+ if (numParams != 0)
+ error("kOpSaveArgs had wrong number of params (%d)", numParams);
+ debug(9, "save args");
+ for (uint i = 1; i < 19; i++)
+ _stack[stackBase + i] = _vars[i];
+ break;
+ case kOpRestoreArgs:
+ if (numParams != 0)
+ error("kOpRestoreArgs had wrong number of params (%d)", numParams);
+ debug(9, "restore args");
+ for (uint i = 1; i < 19; i++)
+ _vars[i] = _stack[stackBase + i];
+ break;
+ case kOpReturn:
+ if (numParams != 1)
+ error("kOpReturn had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ debug(9, "return [%d/%d]=%d", script[pos + 1], arg1, val1);
+ _vars[0] = val1;
+ break;
+ case kOpLessThanEq:
+ if (numParams != 3)
+ error("kOpLessThanEq had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d] <= [%d/%d]? (%d <= %d)", script[pos + 1], arg1, script[pos + 2], arg2, script[pos + 3], arg3, val3, val2);
+ setArg(script[pos + 1], arg1, (val3 <= val2) ? 1 : 0);
+ break;
+ case kOpLessThan:
+ if (numParams != 3)
+ error("kOpLessThan had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d] < [%d/%d]? (%d < %d)", script[pos + 1], arg1, script[pos + 2], arg2, script[pos + 3], arg3, val3, val2);
+ setArg(script[pos + 1], arg1, (val3 < val2) ? 1 : 0);
+ break;
+ case kOpGreaterThanEq:
+ if (numParams != 3)
+ error("kOpGreaterThanEq had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d] >= [%d/%d]? (%d >= %d)", script[pos + 1], arg1, script[pos + 2], arg2, script[pos + 3], arg3, val3, val2);
+ setArg(script[pos + 1], arg1, (val3 >= val2) ? 1 : 0);
+ break;
+ case kOpGreaterThan:
+ if (numParams != 3)
+ error("kOpGreaterThan had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d] > [%d/%d]? (%d > %d)", script[pos + 1], arg1, script[pos + 2], arg2, script[pos + 3], arg3, val3, val2);
+ setArg(script[pos + 1], arg1, (val3 > val2) ? 1 : 0);
+ break;
+ case kOpEqual:
+ if (numParams != 3)
+ error("kOpEqual had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d] == [%d/%d]? (%d == %d)", script[pos + 1], arg1, script[pos + 2], arg2, script[pos + 3], arg3, val2, val3);
+ setArg(script[pos + 1], arg1, (val3 == val2) ? 1 : 0);
+ break;
+ case kOpNotEqual:
+ if (numParams != 3)
+ error("kOpNotEqual had wrong number of params (%d)", numParams);
+ val2 = getArg(script[pos + 2], arg2);
+ val3 = getArg(script[pos + 3], arg3);
+ debug(9, "[%d/%d] = [%d/%d] != [%d/%d]? (%d != %d)", script[pos + 1], arg1, script[pos + 2], arg2, script[pos + 3], arg3, val2, val3);
+ setArg(script[pos + 1], arg1, (val3 != val2) ? 1 : 0);
+ break;
+ case kOpJump:
+ if (numParams != 1)
+ error("kOpJump had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ debug(9, "jump by [%d/%d]=%d", script[pos + 1], arg1, val1);
+ pos += val1;
+ break;
+ case kOpJumpIfNot:
+ if (numParams != 1)
+ error("kOpJumpIfNot had wrong number of params (%d)", numParams);
+ if (lastResult)
+ break;
+ val1 = getArg(script[pos + 1], arg1);
+ debug(9, "jump if not, by [%d/%d]=%d", script[pos + 1], arg1, val1);
+ pos += val1;
+ break;
+ case kOpJumpIf:
+ if (numParams != 1)
+ error("kOpJumpIf had wrong number of params (%d)", numParams);
+ if (!lastResult)
+ break;
+ val1 = getArg(script[pos + 1], arg1);
+ debug(9, "jump if, by [%d/%d]=%d", script[pos + 1], arg1, val1);
+ pos += val1;
+ break;
+ case kOpJumpIfNotValue:
+ if (numParams != 2)
+ error("kOpJumpIfNotValue had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "jump if not [%d/%d]=%d", script[pos + 1], arg1, val1);
+ if (val1)
+ break;
+ debug(9, "--> jump by [%d/%d]=%d", script[pos + 2], arg2, val2);
+ pos += val2;
+ break;
+ case kOpJumpIfValue:
+ if (numParams != 2)
+ error("kOpJumpIfValue had wrong number of params (%d)", numParams);
+ val1 = getArg(script[pos + 1], arg1);
+ val2 = getArg(script[pos + 2], arg2);
+ debug(9, "jump if [%d/%d]=%d", script[pos + 1], arg1, val1);
+ if (!val1)
+ break;
+ debug(9, "--> jump by [%d/%d]=%d", script[pos + 2], arg2, val2);
+ pos += val2;
+ break;
+ default:
+ error("unknown script op 0x%02x", op);
+ }
+ pos += (1 + numParams);
+
+ if (op == kOpReturn)
+ break;
+ }
+
+ delete[] script;
+ _stack.resize(_stack.size() - 19);
+}
+
+int16 ComposerEngine::scriptFuncCall(uint16 id, int16 param1, int16 param2, int16 param3) {
+ switch (id) {
+ case kFuncPlayAnim:
+ debug(3, "kFuncPlayAnim(%d, %d, %d)", param1, param2, param3);
+ playAnimation(param1, param2, param3, 0);
+ return 1; // TODO: return 0 on failure
+ case kFuncStopAnim:
+ debug(3, "kFuncStopAnim(%d)", param1);
+ for (Common::List<Animation *>::iterator i = _anims.begin(); i != _anims.end(); i++) {
+ if ((*i)->_id == param1)
+ stopAnimation(*i);
+ }
+ return 0;
+ case kFuncQueueScript:
+ debug(3, "kFuncQueueScript(%d, %d, %d)", param1, param2, param3);
+ _queuedScripts[param1]._baseTime = _currentTime;
+ _queuedScripts[param1]._duration = 10 * param2;
+ _queuedScripts[param1]._count = 0xffffffff;
+ _queuedScripts[param1]._scriptId = param3;
+ return 0;
+ case kFuncDequeueScript:
+ debug(3, "kFuncDequeueScript(%d)", param1);
+ _queuedScripts[param1]._count = 0;
+ _queuedScripts[param1]._scriptId = 0;
+ return 0;
+ case kFuncSetCursor:
+ debug(3, "kSetCursor(%d, (%d, %d))", param1, param2, param3);
+ {
+ uint16 oldCursor = _mouseSpriteId;
+ setCursor(param1, Common::Point(param2, param3));
+ return oldCursor;
+ }
+ case kFuncGetCursor:
+ debug(3, "kFuncGetCursor()");
+ return _mouseSpriteId;
+ case kFuncShowCursor:
+ debug(3, "kFuncShowCursor()");
+ setCursorVisible(true);
+ return 0;
+ case kFuncHideCursor:
+ debug(3, "kFuncHideCursor()");
+ setCursorVisible(false);
+ return 0;
+ case kFuncActivateButton:
+ debug(3, "kFuncActivateButton(%d)", param1);
+ for (Common::List<Library>::iterator l = _libraries.begin(); l != _libraries.end(); l++) {
+ for (Common::List<Button>::iterator i = l->_buttons.begin(); i != l->_buttons.end(); i++) {
+ if (i->_id != param1)
+ continue;
+ i->_active = true;
+ }
+ }
+ onMouseMove(_lastMousePos);
+ return 1;
+ case kFuncDeactivateButton:
+ debug(3, "kFuncDeactivateButton(%d)", param1);
+ for (Common::List<Library>::iterator l = _libraries.begin(); l != _libraries.end(); l++) {
+ for (Common::List<Button>::iterator i = l->_buttons.begin(); i != l->_buttons.end(); i++) {
+ if (i->_id != param1)
+ continue;
+ i->_active = false;
+ }
+ }
+ onMouseMove(_lastMousePos);
+ return 1;
+ case kFuncNewPage:
+ debug(3, "kFuncNewPage(%d, %d)", param1, param2);
+ _pendingPageChanges.push_back(PendingPageChange(param1, true));
+ _pendingPageChanges.push_back(PendingPageChange(param2, false));
+ return 1;
+ case kFuncLoadPage:
+ debug(3, "kFuncLoadPage(%d)", param1);
+ _pendingPageChanges.push_back(PendingPageChange(param1, false));
+ return 1;
+ case kFuncUnloadPage:
+ debug(3, "kFuncUnloadPage(%d)", param1);
+ _pendingPageChanges.push_back(PendingPageChange(param1, true));
+ return 1;
+ case kFuncSetPalette:
+ // TODO: return 0 if not disabling (0) and doesn't exist
+ debug(4, "kFuncSetPalette(%d, %d)", param1, param2);
+ // this seems only needed for a script bug in the Gregory credits, sigh
+ if ((uint16)param2 > 100)
+ param2 = 100;
+ loadCTBL(param1, param2);
+ return 1;
+ case kFuncSaveVars:
+ debug(3, "kFuncSaveVars(%d)", param1);
+ {
+ Common::String filename = _targetName + Common::String::format(".%03d", param1);
+ Common::WriteStream *stream = _saveFileMan->openForSaving(filename);
+ for (uint i = 0; i < 1000; i++) {
+ stream->writeUint16LE(_vars[i]);
+ }
+ delete stream;
+ }
+ return 1;
+ case kFuncLoadVars:
+ debug(3, "kFuncLoadVars(%d, %d, %d)", param1, param2, param3);
+ {
+ Common::String filename = _targetName + Common::String::format(".%03d", param1);
+ Common::SeekableReadStream *stream = _saveFileMan->openForLoading(filename);
+ if (!stream) {
+ if (!_bookIni.hasKey(Common::String::format("%d", param1), "Data"))
+ return 0;
+ filename = getFilename("Data", param1);
+ Common::File *file = new Common::File();
+ if (!file->open(filename))
+ error("couldn't open '%s' to get vars id '%d'", filename.c_str(), param1);
+ stream = file;
+ }
+ if (param3 == 0)
+ param3 = 1000;
+ if (param2 < 0 || param3 < 0 || param2 + param3 > 1000)
+ error("can't read %d entries into %d from file '%s' for vars id '%d'", param3, param2, filename.c_str(), param1);
+ stream->skip(param2 * 2);
+ for (uint i = 0; i < (uint)param3; i++) {
+ if (stream->pos() + 1 > stream->size())
+ break;
+ _vars[param2 + i] = stream->readUint16LE();
+ }
+ delete stream;
+ }
+ return 1;
+ case kFuncQueueScriptOnce:
+ debug(3, "kFuncQueueScriptOnce(%d, %d, %d)", param1, param2, param3);
+ _queuedScripts[param1]._baseTime = _currentTime;
+ _queuedScripts[param1]._duration = 10 * param2;
+ _queuedScripts[param1]._count = 1;
+ _queuedScripts[param1]._scriptId = param3;
+ return 0;
+ case kFuncGetMousePos:
+ debug(3, "kFuncGetMousePos(%d, %d)", param1, param2);
+ _vars[param1] = _lastMousePos.x;
+ _vars[param2] = _lastMousePos.y;
+ return 0;
+ case kFuncChangeBackground:
+ debug(3, "kFuncChangeBackground(%d)", param1);
+ // TODO: return 1 if background existed, else 0
+ setBackground(param1);
+ return 1;
+ case kFuncSetBackgroundColor:
+ // TODO
+ warning("ignoring kFuncSetBackgroundColor(%d)", param1);
+ return 0;
+ case kFuncClearSprites:
+ debug(3, "kFuncClearSprites()");
+ removeSprite(0, 0);
+ return 0;
+ case kFuncAddSprite:
+ {
+ Common::Point pos(_vars[param3], _vars[param3 + 1]);
+ int16 zorder = _vars[param3 + 2];
+ debug(3, "kFuncAddSprite(%d, %d, [%d = (%d, %d), %d])", param1, param2, param3, pos.x, pos.y, zorder);
+ addSprite(param1, param2, zorder, pos);
+ }
+ return 0;
+ case kFuncRemoveSprite:
+ debug(3, "kFuncRemoveSprite(%d, %d)", param1, param2);
+ removeSprite(param1, param2);
+ return 0;
+ case kFuncQuit:
+ debug(3, "kFuncQuit()");
+ quitGame();
+ return 0;
+ case kFuncSaveData:
+ // TODO
+ warning("ignoring kFuncSaveData(%d, %d, %d)", param1, param2, param3);
+ return 1;
+ case kFuncLoadData:
+ debug(3, "kFuncLoadData(%d, %d, %d)", param1, param2, param3);
+ {
+ Common::String filename = getFilename("Data", param1);
+ Common::File *file = new Common::File();
+ if (!file->open(filename))
+ error("couldn't open '%s' to get data id '%d'", filename.c_str(), param1);
+ if (param3 == 0)
+ param3 = 1000;
+ if (param2 < 0 || param3 < 0 || param2 + param3 > 1000)
+ error("can't read %d entries into %d from file '%s' for data id '%d'", param3, param2, filename.c_str(), param1);
+ for (uint i = 0; i < (uint)param3; i++) {
+ if (file->pos() + 1 > file->size())
+ break;
+ _vars[param2 + i] = file->readUint16LE();
+ }
+ delete file;
+ }
+ return 1;
+ case kFuncGetSpriteSize:
+ debug(3, "kFuncGetSpriteSize(%d, %d, %d)", param1, param2, param3);
+ int16 width, height;
+ width = 0;
+ height = 0;
+ {
+ Common::SeekableReadStream *stream = getStreamForSprite(param1);
+ if (stream) {
+ stream->readUint16LE();
+ height = stream->readSint16LE();
+ width = stream->readSint16LE();
+ delete stream;
+ }
+ }
+ _vars[param2] = width;
+ _vars[param3] = height;
+ return 0;
+ default:
+ error("unknown scriptFuncCall %d(%d, %d, %d)", (uint32)id, param1, param2, param3);
+ }
+}
+
+} // End of namespace Composer
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h
index 900f677975..94f8759d01 100644
--- a/engines/cruise/cruise.h
+++ b/engines/cruise/cruise.h
@@ -108,7 +108,15 @@ public:
Common::RandomSource _rnd;
- Common::List<byte *> _memList;
+ struct MemInfo {
+ int32 lineNum;
+ char fname[64];
+ uint32 magic;
+
+ static uint32 const cookie = 0x41424344;
+ };
+
+ Common::List<MemInfo*> _memList;
typedef Common::List<Common::Rect> RectList;
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index 031c53b96a..ff4669607d 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -40,19 +40,21 @@ unsigned int timer = 0;
gfxEntryStruct* linkedMsgList = NULL;
+typedef CruiseEngine::MemInfo MemInfo;
+
void MemoryList() {
if (!_vm->_memList.empty()) {
debug("Current list of un-freed memory blocks:");
- Common::List<byte *>::iterator i;
+ Common::List<MemInfo*>::iterator i;
for (i = _vm->_memList.begin(); i != _vm->_memList.end(); ++i) {
- byte *v = *i;
- debug("%s - %d", (const char *)(v - 68), *((int32 *)(v - 72)));
+ MemInfo const *const v = *i;
+ debug("%s - %d", v->fname, v->lineNum);
}
}
}
void *MemoryAlloc(uint32 size, bool clearFlag, int32 lineNum, const char *fname) {
- byte *result;
+ void *result;
if (gDebugLevel > 0) {
// Find the point after the final slash
@@ -61,17 +63,17 @@ void *MemoryAlloc(uint32 size, bool clearFlag, int32 lineNum, const char *fname)
--fnameP;
// Create the new memory block and add it to the memory list
- byte *v = (byte *)malloc(size + 64 + 8);
- *((int32 *) v) = lineNum;
- strncpy((char *)v + 4, fnameP, 63);
- *((char *)v + 4 + 63) = '\0';
- *((uint32 *) (v + 68)) = 0x41424344;
+ MemInfo *const v = (MemInfo *)malloc(sizeof(MemInfo) + size);
+ v->lineNum = lineNum;
+ strncpy(v->fname, fnameP, sizeof(v->fname));
+ v->fname[ARRAYSIZE(v->fname) - 1] = '\0';
+ v->magic = MemInfo::cookie;
// Add the block to the memory list
- result = v + 64 + 8;
- _vm->_memList.push_back(result);
+ _vm->_memList.push_back(v);
+ result = v + 1;
} else
- result = (byte *)malloc(size);
+ result = malloc(size);
if (clearFlag)
memset(result, 0, size);
@@ -84,11 +86,11 @@ void MemoryFree(void *v) {
return;
if (gDebugLevel > 0) {
- byte *p = (byte *)v;
- assert(*((uint32 *) (p - 4)) == 0x41424344);
+ MemInfo *const p = (MemInfo *)v - 1;
+ assert(p->magic == MemInfo::cookie);
_vm->_memList.remove(p);
- free(p - 8 - 64);
+ free(p);
} else
free(v);
}
diff --git a/engines/cruise/module.mk b/engines/cruise/module.mk
index 5c36b2a7c1..ae07d20956 100644
--- a/engines/cruise/module.mk
+++ b/engines/cruise/module.mk
@@ -40,4 +40,3 @@ endif
# Include common rules
include $(srcdir)/rules.mk
-
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index 6392009373..c3d1ea6643 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -62,12 +62,9 @@ bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header) {
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;
+ header.thumbnail = Graphics::loadThumbnail(*in);
+ if (!header.thumbnail)
return false;
- }
return true;
}
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 290cc220d4..21d9a75297 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -31,6 +31,7 @@
#include "audio/audiostream.h"
#include "audio/fmopl.h"
+#include "audio/mixer.h"
#include "audio/mods/soundfx.h"
namespace Cruise {
diff --git a/engines/cruise/sound.h b/engines/cruise/sound.h
index 11aec0b04e..c1975dc579 100644
--- a/engines/cruise/sound.h
+++ b/engines/cruise/sound.h
@@ -23,10 +23,6 @@
#ifndef CRUISE_SOUND_H
#define CRUISE_SOUND_H
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
-#include "audio/mixer.h"
-
#include "common/config-manager.h"
#include "common/serializer.h"
diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index 1a077e5bf7..58bf629dc4 100644
--- a/engines/dialogs.cpp
+++ b/engines/dialogs.cpp
@@ -338,4 +338,3 @@ void ConfigDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32
GUI::OptionsDialog::handleCommand (sender, cmd, data);
}
}
-
diff --git a/engines/draci/saveload.cpp b/engines/draci/saveload.cpp
index 1479dd3c77..78315d1a97 100644
--- a/engines/draci/saveload.cpp
+++ b/engines/draci/saveload.cpp
@@ -58,13 +58,9 @@ bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header) {
header.playtime = in->readUint32LE();
// Get the thumbnail
- header.thumbnail = new Graphics::Surface();
- if (!Graphics::loadThumbnail(*in, *header.thumbnail)) {
- header.thumbnail->free();
- delete header.thumbnail;
- header.thumbnail = NULL;
+ header.thumbnail = Graphics::loadThumbnail(*in);
+ if (!header.thumbnail)
return false;
- }
return true;
}
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index 2b6aa0f291..6f98c50fdc 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -30,6 +30,7 @@
#include "common/file.h"
#include "common/hash-str.h"
#include "common/keyboard.h"
+#include "common/ptr.h"
#include "common/random.h"
#include "common/savefile.h"
#include "common/system.h"
@@ -264,15 +265,13 @@ private:
};
class TextResourceParser {
- Common::SeekableReadStream *_stream;
- DisposeAfterUse::Flag _dispose;
+ Common::DisposablePtr<Common::SeekableReadStream> _stream;
int _maxLen;
void getLine(char *buf);
public:
TextResourceParser(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose);
- ~TextResourceParser();
void parseInt(int &result);
void parseString(char *result);
@@ -496,6 +495,8 @@ public:
void updateVolume(Audio::Mixer::SoundType soundType, int prevVolume);
void volumeControls();
bool saveLoadScreen();
+ void loadSaveNames();
+ void saveSaveNames();
void print_abc(const char *, int, int);
void delay(int ms);
bool confirmExit();
@@ -776,6 +777,7 @@ private:
RoomUpdate *_roomPreUpdates, *_roomUpdates;
RoomTalkAction *_roomActions;
TalkSequenceCommand *_talkSequences;
+ char _saveNames[10][23];
char **loadTexts(Common::File &in);
void freeTexts(char **ptr);
diff --git a/engines/drascula/resource.cpp b/engines/drascula/resource.cpp
index 6da43e7cba..95a95e3487 100644
--- a/engines/drascula/resource.cpp
+++ b/engines/drascula/resource.cpp
@@ -42,7 +42,7 @@ Common::SeekableReadStream *ArchiveMan::open(const Common::String &filename) {
}
TextResourceParser::TextResourceParser(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose) :
- _stream(stream), _dispose(dispose) {
+ _stream(stream, dispose) {
// NOTE: strangely enough, the code before this refactoring used the size of
// the stream as a fixed maximum length for the parser. Using an updated
@@ -50,12 +50,6 @@ TextResourceParser::TextResourceParser(Common::SeekableReadStream *stream, Dispo
_maxLen = _stream->size();
}
-TextResourceParser::~TextResourceParser() {
- if (_dispose == DisposeAfterUse::YES) {
- delete _stream;
- }
-}
-
void TextResourceParser::getLine(char *buf) {
byte c;
char *b;
@@ -101,4 +95,3 @@ void TextResourceParser::parseString(char* result) {
} // End of namespace Drascula
-
diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp
index 664a082eb4..c8622f3c92 100644
--- a/engines/drascula/saveload.cpp
+++ b/engines/drascula/saveload.cpp
@@ -26,20 +26,26 @@
namespace Drascula {
-bool DrasculaEngine::saveLoadScreen() {
- char names[10][23];
- Common::String file;
- int n, n2, num_sav = 0, y = 27;
+/**
+ * Loads the save names from the EPA index file.
+ *
+ * TODO: We should move the save names in their respective save files and get
+ * rid of this completely. A good example is the sword1 engine, which also used
+ * to have an index file for its saves, that has been removed.
+ * sword1 contains code that converts the old index-based saves into the new
+ * format without the index file, so we could apply this idea to drascula as
+ * well.
+ */
+void DrasculaEngine::loadSaveNames() {
Common::InSaveFile *sav;
-
- clearRoom();
-
Common::String fileEpa = Common::String::format("%s.epa", _targetName.c_str());
+
+ // Create and initialize the index file, if it doesn't exist
if (!(sav = _saveFileMan->openForLoading(fileEpa))) {
Common::OutSaveFile *epa;
if (!(epa = _saveFileMan->openForSaving(fileEpa)))
error("Can't open %s file", fileEpa.c_str());
- for (n = 0; n < NUM_SAVES; n++)
+ for (int n = 0; n < NUM_SAVES; n++)
epa->writeString("*\n");
epa->finalize();
delete epa;
@@ -47,11 +53,47 @@ bool DrasculaEngine::saveLoadScreen() {
error("Can't open %s file", fileEpa.c_str());
}
}
- for (n = 0; n < NUM_SAVES; n++) {
- strncpy(names[n], sav->readLine().c_str(), 23);
- names[n][22] = '\0'; // make sure the savegame name is 0-terminated
+
+ // Load the index file
+ for (int n = 0; n < NUM_SAVES; n++) {
+ strncpy(_saveNames[n], sav->readLine().c_str(), 23);
+ _saveNames[n][22] = '\0'; // make sure the savegame name is 0-terminated
}
delete sav;
+}
+
+/**
+ * Saves the save names into the EPA index file.
+ *
+ * TODO: We should move the save names in their respective save files and get
+ * rid of this completely. A good example is the sword1 engine, which also used
+ * to have an index file for its saves, that has been removed.
+ * sword1 contains code that converts the old index-based saves into the new
+ * format without the index file, so we could apply this idea to drascula as
+ * well.
+ */
+void DrasculaEngine::saveSaveNames() {
+ Common::OutSaveFile *tsav;
+ Common::String fileEpa = Common::String::format("%s.epa", _targetName.c_str());
+
+ if (!(tsav = _saveFileMan->openForSaving(fileEpa))) {
+ error("Can't open %s file", fileEpa.c_str());
+ }
+ for (int n = 0; n < NUM_SAVES; n++) {
+ tsav->writeString(_saveNames[n]);
+ tsav->writeString("\n");
+ }
+ tsav->finalize();
+ delete tsav;
+}
+
+bool DrasculaEngine::saveLoadScreen() {
+ Common::String file;
+ int n, n2, num_sav = 0, y = 27;
+
+ clearRoom();
+
+ loadSaveNames();
loadPic("savescr.alg", bgSurface, HALF_PAL);
@@ -66,7 +108,7 @@ bool DrasculaEngine::saveLoadScreen() {
y = 27;
copyBackground();
for (n = 0; n < NUM_SAVES; n++) {
- print_abc(names[n], 116, y);
+ print_abc(_saveNames[n], 116, y);
y = y + 9;
}
print_abc(select, 117, 15);
@@ -79,33 +121,24 @@ bool DrasculaEngine::saveLoadScreen() {
delay(50);
for (n = 0; n < NUM_SAVES; n++) {
if (mouseX > 115 && mouseY > y + (9 * n) && mouseX < 115 + 175 && mouseY < y + 10 + (9 * n)) {
- strcpy(select, names[n]);
+ strcpy(select, _saveNames[n]);
if (strcmp(select, "*"))
selectionMade = 1;
else {
enterName();
- strcpy(names[n], select);
+ strcpy(_saveNames[n], select);
if (selectionMade == 1) {
file = Common::String::format("%s%02d", _targetName.c_str(), n + 1);
saveGame(file.c_str());
- Common::OutSaveFile *tsav;
- if (!(tsav = _saveFileMan->openForSaving(fileEpa))) {
- error("Can't open %s file", fileEpa.c_str());
- }
- for (n = 0; n < NUM_SAVES; n++) {
- tsav->writeString(names[n]);
- tsav->writeString("\n");
- }
- tsav->finalize();
- delete tsav;
+ saveSaveNames();
}
}
print_abc(select, 117, 15);
y = 27;
for (n2 = 0; n2 < NUM_SAVES; n2++) {
- print_abc(names[n2], 116, y);
+ print_abc(_saveNames[n2], 116, y);
y = y + 9;
}
if (selectionMade == 1) {
@@ -117,27 +150,18 @@ bool DrasculaEngine::saveLoadScreen() {
if (mouseX > 117 && mouseY > 15 && mouseX < 295 && mouseY < 24 && selectionMade == 1) {
enterName();
- strcpy(names[num_sav], select);
+ strcpy(_saveNames[num_sav], select);
print_abc(select, 117, 15);
y = 27;
for (n2 = 0; n2 < NUM_SAVES; n2++) {
- print_abc(names[n2], 116, y);
+ print_abc(_saveNames[n2], 116, y);
y = y + 9;
}
if (selectionMade == 1) {
file = Common::String::format("%s%02d", _targetName.c_str(), n + 1);
saveGame(file.c_str());
- Common::OutSaveFile *tsav;
- if (!(tsav = _saveFileMan->openForSaving(fileEpa))) {
- error("Can't open %s file", fileEpa.c_str());
- }
- for (n = 0; n < NUM_SAVES; n++) {
- tsav->writeString(names[n]);
- tsav->writeString("\n");
- }
- tsav->finalize();
- delete tsav;
+ saveSaveNames();
}
}
@@ -149,16 +173,7 @@ bool DrasculaEngine::saveLoadScreen() {
break;
} else if (mouseX > 208 && mouseY > 123 && mouseX < 282 && mouseY < 149 && selectionMade == 1) {
saveGame(file.c_str());
- Common::OutSaveFile *tsav;
- if (!(tsav = _saveFileMan->openForSaving(fileEpa))) {
- error("Can't open %s file", fileEpa.c_str());
- }
- for (n = 0; n < NUM_SAVES; n++) {
- tsav->writeString(names[n]);
- tsav->writeString("\n");
- }
- tsav->finalize();
- delete tsav;
+ saveSaveNames();
} else if (mouseX > 168 && mouseY > 154 && mouseX < 242 && mouseY < 180)
break;
else if (selectionMade == 0) {
diff --git a/engines/dreamweb/backdrop.cpp b/engines/dreamweb/backdrop.cpp
new file mode 100644
index 0000000000..f667e7b73c
--- /dev/null
+++ b/engines/dreamweb/backdrop.cpp
@@ -0,0 +1,301 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "dreamweb/dreamweb.h"
+#include "engines/util.h"
+#include "graphics/surface.h"
+
+namespace DreamGen {
+
+void DreamGenContext::doblocks() {
+ uint16 dstOffset = data.word(kMapady) * 320 + data.word(kMapadx);
+ uint16 mapOffset = kMap + data.byte(kMapy) * kMapwidth + data.byte(kMapx);
+ ds = data.word(kMapdata);
+ const uint8 *mapData = ds.ptr(mapOffset, 0);
+ ds = data.word(kBackdrop);
+ const uint8 *blocks = ds.ptr(kBlocks, 0);
+ es = data.word(kWorkspace);
+ uint8 *dstBuffer = es.ptr(dstOffset, 0);
+
+ for (size_t i = 0; i < 10; ++i) {
+ for (size_t j = 0; j < 11; ++j) {
+ uint16 blockType = mapData[j];
+ if (blockType != 0) {
+ uint8 *dst = dstBuffer + i * 320 * 16 + j * 16;
+ const uint8 *block = blocks + blockType * 256;
+ for (size_t k = 0; k < 4; ++k) {
+ memcpy(dst, block, 16);
+ block += 16;
+ dst += 320;
+ }
+ for (size_t k = 0; k < 12; ++k) {
+ memcpy(dst, block, 16);
+ memset(dst + 16, 0xdf, 4);
+ block += 16;
+ dst += 320;
+ }
+ dst += 4;
+ ax = 0x0dfdf;
+ memset(dst, 0xdf, 16);
+ dst += 320;
+ memset(dst, 0xdf, 16);
+ dst += 320;
+ memset(dst, 0xdf, 16);
+ dst += 320;
+ memset(dst, 0xdf, 16);
+ }
+ }
+ mapData += kMapwidth;
+ }
+}
+
+uint8 DreamGenContext::getxad(const uint8 *setData, uint8 *result) {
+ uint8 v0 = setData[0];
+ uint8 v1 = setData[1];
+ uint8 v2 = setData[2];
+ if (v0 != 0)
+ return 0;
+ if (v1 < data.byte(kMapx))
+ return 0;
+ v1 -= data.byte(kMapx);
+ if (v1 >= 11)
+ return 0;
+ *result = (v1 << 4) | v2;
+ return 1;
+}
+
+uint8 DreamGenContext::getyad(const uint8 *setData, uint8 *result) {
+ uint8 v0 = setData[3];
+ uint8 v1 = setData[4];
+ if (v0 < data.byte(kMapy))
+ return 0;
+ v0 -= data.byte(kMapy);
+ if (v0 >= 10)
+ return 0;
+ *result = (v0 << 4) | v1;
+ return 1;
+}
+
+void DreamGenContext::getmapad() {
+ ch = getmapad((const uint8 *)es.ptr(si, 5));
+}
+
+uint8 DreamGenContext::getmapad(const uint8 *setData) {
+ uint8 xad, yad;
+ if (getxad(setData, &xad) == 0)
+ return 0;
+ data.word(kObjectx) = xad;
+ if (getyad(setData, &yad) == 0)
+ return 0;
+ data.word(kObjecty) = yad;
+ return 1;
+}
+
+void DreamGenContext::calcfrframe() {
+ uint8 width, height;
+ calcfrframe(&width, &height);
+ cl = width;
+ ch = height;
+}
+
+void DreamGenContext::calcfrframe(uint8* width, uint8* height) {
+ const Frame *frame = (const Frame *)segRef(data.word(kFrsegment)).ptr(data.word(kCurrentframe) * sizeof(Frame), sizeof(Frame));
+ data.word(kSavesource) = data.word(kFramesad) + frame->ptr();
+ data.byte(kSavesize+0) = frame->width;
+ data.byte(kSavesize+1) = frame->height;
+ data.word(kOffsetx) = frame->x;
+ data.word(kOffsety) = frame->y;
+ *width = frame->width;
+ *height = frame->height;
+}
+
+void DreamGenContext::finalframe() {
+ uint16 x, y;
+ finalframe(&x, &y);
+ di = x;
+ bx = y;
+}
+
+void DreamGenContext::finalframe(uint16 *x, uint16 *y) {
+ data.byte(kSavex) = (data.word(kObjectx) + data.word(kOffsetx)) & 0xff;
+ data.byte(kSavey) = (data.word(kObjecty) + data.word(kOffsety)) & 0xff;
+ *x = data.word(kObjectx);
+ *y = data.word(kObjecty);
+}
+
+void DreamGenContext::showallobs() {
+ data.word(kListpos) = kSetlist;
+ memset(segRef(data.word(kBuffers)).ptr(kSetlist, 0), 0xff, 128 * 5);
+ data.word(kFrsegment) = data.word(kSetframes);
+ data.word(kDataad) = kFramedata;
+ data.word(kFramesad) = kFrames;
+
+ const Frame *frames = (const Frame *)segRef(data.word(kFrsegment)).ptr(0, 0);
+ SetObject *setEntries = (SetObject *)segRef(data.word(kSetdat)).ptr(0, 128 * sizeof(SetObject));
+ for (size_t i = 0; i < 128; ++i) {
+ SetObject *setEntry = setEntries + i;
+ if (getmapad(setEntry->b58) == 0)
+ continue;
+ uint8 currentFrame = setEntry->b18[0];
+ data.word(kCurrentframe) = currentFrame;
+ if (currentFrame == 0xff)
+ continue;
+ calcfrframe();
+ uint16 x, y;
+ finalframe(&x, &y);
+ setEntry->b17 = setEntry->b18[0];
+ if ((setEntry->type == 0) && (setEntry->priority != 5) && (setEntry->priority != 6)) {
+ x += data.word(kMapadx);
+ y += data.word(kMapady);
+ showframe(frames, x, y, data.word(kCurrentframe), 0);
+ } else
+ makebackob(setEntry);
+
+ ObjPos *objPos = (ObjPos *)segRef(data.word(kBuffers)).ptr(data.word(kListpos), sizeof(ObjPos));
+ objPos->xMin = data.byte(kSavex);
+ objPos->yMin = data.byte(kSavey);
+ objPos->xMax = data.byte(kSavex) + data.byte(kSavesize+0);
+ objPos->yMax = data.byte(kSavey) + data.byte(kSavesize+1);
+ objPos->index = i;
+ data.word(kListpos) += sizeof(ObjPos);
+ }
+}
+
+void DreamGenContext::getdimension()
+{
+ uint8 mapXstart, mapYstart;
+ uint8 mapXsize, mapYsize;
+ getdimension(&mapXstart, &mapYstart, &mapXsize, &mapYsize);
+ cl = mapXstart;
+ ch = mapYstart;
+ dl = mapXsize;
+ dh = mapYsize;
+}
+
+bool DreamGenContext::addalong(const uint8 *mapFlags) {
+ for (size_t i = 0; i < 11; ++i) {
+ if (mapFlags[3 * i] != 0)
+ return true;
+ }
+ return false;
+}
+
+bool DreamGenContext::addlength(const uint8 *mapFlags) {
+ for (size_t i = 0; i < 10; ++i) {
+ if (mapFlags[3 * 11 * i] != 0)
+ return true;
+ }
+ return false;
+}
+
+void DreamGenContext::getdimension(uint8 *mapXstart, uint8 *mapYstart, uint8 *mapXsize, uint8 *mapYsize) {
+ const uint8 *mapFlags = segRef(data.word(kBuffers)).ptr(kMapflags, 0);
+
+ uint8 yStart = 0;
+ while (! addalong(mapFlags + 3 * 11 * yStart))
+ ++yStart;
+
+ uint8 xStart = 0;
+ while (! addlength(mapFlags + 3 * xStart))
+ ++xStart;
+
+ uint8 yEnd = 10;
+ while (! addalong(mapFlags + 3 * 11 * (yEnd - 1)))
+ --yEnd;
+
+ uint8 xEnd = 11;
+ while (! addlength(mapFlags + 3 * (xEnd - 1)))
+ --xEnd;
+
+ *mapXstart = xStart;
+ *mapYstart = yStart;
+ *mapXsize = xEnd - xStart;
+ *mapYsize = yEnd - yStart;
+ data.word(kMapxstart) = xStart << 4;
+ data.word(kMapystart) = yStart << 4;
+ data.byte(kMapxsize) = *mapXsize << 4;
+ data.byte(kMapysize) = *mapYsize << 4;
+}
+
+void DreamGenContext::calcmapad() {
+ uint8 mapXstart, mapYstart;
+ uint8 mapXsize, mapYsize;
+ getdimension(&mapXstart, &mapYstart, &mapXsize, &mapYsize);
+ data.word(kMapadx) = data.word(kMapoffsetx) - 8 * (mapXsize + 2 * mapXstart - 11);
+ data.word(kMapady) = data.word(kMapoffsety) - 8 * (mapYsize + 2 * mapYstart - 10);
+}
+
+void DreamGenContext::showallfree() {
+ data.word(kListpos) = kFreelist;
+ ObjPos *listPos = (ObjPos *)segRef(data.word(kBuffers)).ptr(kFreelist, 80 * sizeof(ObjPos));
+ memset(listPos, 0xff, 80 * sizeof(ObjPos));
+
+ data.word(kFrsegment) = data.word(kFreeframes);
+ data.word(kDataad) = kFrframedata;
+ data.word(kFramesad) = kFrframes;
+ data.byte(kCurrentfree) = 0;
+ const uint8 *mapData = segRef(data.word(kFreedat)).ptr(2, 0);
+ for(size_t i = 0; i < 80; ++i) {
+ uint8 mapad = getmapad(mapData);
+ if (mapad != 0) {
+ data.word(kCurrentframe) = 3 * data.byte(kCurrentfree);
+ uint8 width, height;
+ calcfrframe(&width, &height);
+ uint16 x, y;
+ finalframe(&x, &y);
+ if ((width != 0) || (height != 0)) {
+ x += data.word(kMapadx);
+ y += data.word(kMapady);
+ showframe((Frame *)segRef(data.word(kFrsegment)).ptr(0, 0), x, y, data.word(kCurrentframe) & 0xff, 0);
+ ObjPos *objPos = (ObjPos *)segRef(data.word(kBuffers)).ptr(data.word(kListpos), sizeof(ObjPos));
+ objPos->xMin = data.byte(kSavex);
+ objPos->yMin = data.byte(kSavey);
+ objPos->xMax = data.byte(kSavex) + data.byte(kSavesize+0);
+ objPos->yMax = data.byte(kSavey) + data.byte(kSavesize+1);
+ objPos->index = i;
+ data.word(kListpos) += sizeof(ObjPos);
+ }
+ }
+
+ ++data.byte(kCurrentfree);
+ mapData += 16;
+ }
+}
+
+void DreamGenContext::drawflags() {
+ uint8 *mapFlags = segRef(data.word(kBuffers)).ptr(kMapflags, 0);
+ const uint8 *mapData = segRef(data.word(kMapdata)).ptr(kMap + data.byte(kMapy) * kMapwidth + data.byte(kMapx), 0);
+ const uint8 *backdropFlags = segRef(data.word(kBackdrop)).ptr(kFlags, 0);
+
+ for (size_t i = 0; i < 10; ++i) {
+ for (size_t j = 0; j < 11; ++j) {
+ uint8 tile = mapData[i * kMapwidth + j];
+ mapFlags[0] = backdropFlags[2 * tile + 0];
+ mapFlags[1] = backdropFlags[2 * tile + 1];
+ mapFlags[2] = tile;
+ mapFlags += 3;
+ }
+ }
+}
+
+} /*namespace dreamgen */
+
diff --git a/engines/dreamweb/detection.cpp b/engines/dreamweb/detection.cpp
index 81a209de25..0ac61a3ac2 100644
--- a/engines/dreamweb/detection.cpp
+++ b/engines/dreamweb/detection.cpp
@@ -40,7 +40,7 @@ public:
AdvancedMetaEngine(DreamWeb::gameDescriptions,
sizeof(DreamWeb::DreamWebGameDescription), dreamWebGames) {
_singleid = "dreamweb";
- _guioptions = Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD;
+ _guioptions = Common::GUIO_NOMIDI;
}
virtual const char *getName() const {
@@ -61,8 +61,8 @@ public:
bool DreamWebMetaEngine::hasFeature(MetaEngineFeature f) const {
switch(f) {
case kSupportsListSaves:
- //case kSupportsLoadingDuringStartup:
- //case kSupportsDeleteSave:
+ case kSupportsLoadingDuringStartup:
+ case kSupportsDeleteSave:
return true;
default:
return false;
@@ -105,14 +105,15 @@ SaveStateList DreamWebMetaEngine::listSaves(const char *target) const {
stream->read(name, sizeof(name) - 1);
delete stream;
- SaveStateDescriptor sd(i, name);
+ int slotNum = atoi(file.c_str() + file.size() - 2);
+ SaveStateDescriptor sd(slotNum, name);
saveList.push_back(sd);
}
return saveList;
}
-int DreamWebMetaEngine::getMaximumSaveSlot() const { return 6; }
+int DreamWebMetaEngine::getMaximumSaveSlot() const { return 99; }
void DreamWebMetaEngine::removeSaveState(const char *target, int slot) const {
}
diff --git a/engines/dreamweb/dreamgen.cpp b/engines/dreamweb/dreamgen.cpp
index 3c10ea69d1..8d3518d5f6 100644
--- a/engines/dreamweb/dreamgen.cpp
+++ b/engines/dreamweb/dreamgen.cpp
@@ -1694,116 +1694,6 @@ notendtelly:
showgamereel();
}
-void DreamGenContext::madman() {
- STACK_CHECK;
- data.word(kWatchingtime) = 2;
- checkspeed();
- if (!flags.z())
- goto nomadspeed;
- ax = es.word(bx+3);
- _cmp(ax, 364);
- if (!flags.c())
- goto ryansded;
- _cmp(ax, 10);
- if (!flags.z())
- goto notfirstmad;
- push(es);
- push(bx);
- push(ax);
- dx = 2247;
- loadtemptext();
- ax = pop();
- bx = pop();
- es = pop();
- data.byte(kCombatcount) = -1;
- data.byte(kSpeechcount) = 0;
-notfirstmad:
- _inc(ax);
- _cmp(ax, 294);
- if (flags.z())
- goto madmanspoken;
- _cmp(ax, 66);
- if (!flags.z())
- goto nomadspeak;
- _inc(data.byte(kCombatcount));
- push(es);
- push(bx);
- madmantext();
- bx = pop();
- es = pop();
- ax = 53;
- _cmp(data.byte(kCombatcount), 64);
- if (flags.c())
- goto nomadspeak;
- _cmp(data.byte(kCombatcount), 70);
- if (flags.z())
- goto killryan;
- _cmp(data.byte(kLastweapon), 8);
- if (!flags.z())
- goto nomadspeak;
- data.byte(kCombatcount) = 72;
- data.byte(kLastweapon) = -1;
- data.byte(kMadmanflag) = 1;
- ax = 67;
- goto nomadspeak;
-killryan:
- ax = 310;
-nomadspeak:
- es.word(bx+3) = ax;
-nomadspeed:
- showgamereel();
- al = data.byte(kMapx);
- es.byte(bx+1) = al;
- madmode();
- return;
-madmanspoken:
- _cmp(data.byte(kWongame), 1);
- if (flags.z())
- return /* (alreadywon) */;
- data.byte(kWongame) = 1;
- push(es);
- push(bx);
- getridoftemptext();
- bx = pop();
- es = pop();
- return;
-ryansded:
- data.byte(kMandead) = 2;
- showgamereel();
-}
-
-void DreamGenContext::madmantext() {
- STACK_CHECK;
- _cmp(data.byte(kSpeechcount), 63);
- if (!flags.c())
- return /* (nomadtext) */;
- _cmp(data.byte(kCh1playing), 255);
- if (!flags.z())
- return /* (nomadtext) */;
- al = data.byte(kSpeechcount);
- _inc(data.byte(kSpeechcount));
- _add(al, 47);
- bl = 72;
- bh = 80;
- cx = 90;
- dx = 1;
- ah = 82;
- setuptimedtemp();
-}
-
-void DreamGenContext::madmode() {
- STACK_CHECK;
- data.word(kWatchingtime) = 2;
- data.byte(kPointermode) = 0;
- _cmp(data.byte(kCombatcount), 65);
- if (flags.c())
- return /* (iswatchmad) */;
- _cmp(data.byte(kCombatcount), 70);
- if (!flags.c())
- return /* (iswatchmad) */;
- data.byte(kPointermode) = 2;
-}
-
void DreamGenContext::priesttext() {
STACK_CHECK;
_cmp(es.word(bx+3), 2);
@@ -2160,22 +2050,6 @@ void DreamGenContext::addtopeoplelist() {
_add(data.word(kListpos), 5);
}
-void DreamGenContext::showgamereel() {
- STACK_CHECK;
- ax = es.word(bx+3);
- _cmp(ax, 512);
- if (!flags.c())
- return /* (noshow) */;
- data.word(kReelpointer) = ax;
- push(es);
- push(bx);
- plotreel();
- bx = pop();
- es = pop();
- ax = data.word(kReelpointer);
- es.word(bx+3) = ax;
-}
-
void DreamGenContext::checkspeed() {
STACK_CHECK;
_cmp(data.byte(kLastweapon), -1);
@@ -2202,217 +2076,6 @@ void DreamGenContext::delsprite() {
_stosb(cx, true);
}
-void DreamGenContext::checkone() {
- STACK_CHECK;
- push(cx);
- al = ch;
- ah = 0;
- cl = 4;
- _shr(ax, cl);
- dl = al;
- cx = pop();
- al = cl;
- ah = 0;
- cl = 4;
- _shr(ax, cl);
- ah = dl;
- push(ax);
- ch = 0;
- cl = al;
- push(cx);
- al = ah;
- ah = 0;
- cx = 11;
- _mul(cx);
- cx = pop();
- _add(ax, cx);
- cx = 3;
- _mul(cx);
- si = ax;
- ds = data.word(kBuffers);
- _add(si, (0+(228*13)+32+60+(32*32)));
- _lodsw();
- cx = ax;
- _lodsb();
- dx = pop();
-}
-
-void DreamGenContext::findsource() {
- STACK_CHECK;
- ax = data.word(kCurrentframe);
- _cmp(ax, 160);
- if (!flags.c())
- goto over1000;
- ds = data.word(kReel1);
- data.word(kTakeoff) = 0;
- return;
-over1000:
- _cmp(ax, 320);
- if (!flags.c())
- goto over1001;
- ds = data.word(kReel2);
- data.word(kTakeoff) = 160;
- return;
-over1001:
- ds = data.word(kReel3);
- data.word(kTakeoff) = 320;
-}
-
-void DreamGenContext::mainman() {
- STACK_CHECK;
- _cmp(data.byte(kResetmanxy), 1);
- if (!flags.z())
- goto notinnewroom;
- data.byte(kResetmanxy) = 0;
- al = data.byte(kRyanx);
- ah = data.byte(kRyany);
- es.word(bx+10) = ax;
- es.byte(bx+29) = 0;
- goto executewalk;
-notinnewroom:
- _dec(es.byte(bx+22));
- _cmp(es.byte(bx+22), -1);
- if (flags.z())
- goto executewalk;
- return;
-executewalk:
- es.byte(bx+22) = 0;
- al = data.byte(kTurntoface);
- _cmp(al, data.byte(kFacing));
- if (flags.z())
- goto facingok;
- aboutturn();
- goto notwalk;
-facingok:
- _cmp(data.byte(kTurndirection), 0);
- if (flags.z())
- goto alreadyturned;
- _cmp(data.byte(kLinepointer), 254);
- if (!flags.z())
- goto alreadyturned;
- data.byte(kReasseschanges) = 1;
- al = data.byte(kFacing);
- _cmp(al, data.byte(kLeavedirection));
- if (!flags.z())
- goto alreadyturned;
- checkforexit();
-alreadyturned:
- data.byte(kTurndirection) = 0;
- _cmp(data.byte(kLinepointer), 254);
- if (!flags.z())
- goto walkman;
- es.byte(bx+29) = 0;
- goto notwalk;
-walkman:
- al = es.byte(bx+29);
- _inc(al);
- _cmp(al, 11);
- if (!flags.z())
- goto notanimend1;
- al = 1;
-notanimend1:
- es.byte(bx+29) = al;
- walking();
- _cmp(data.byte(kLinepointer), 254);
- if (flags.z())
- goto afterwalk;
- al = data.byte(kFacing);
- _and(al, 1);
- if (flags.z())
- goto isdouble;
- al = es.byte(bx+29);
- _cmp(al, 2);
- if (flags.z())
- goto afterwalk;
- _cmp(al, 7);
- if (flags.z())
- goto afterwalk;
-isdouble:
- walking();
-afterwalk:
- _cmp(data.byte(kLinepointer), 254);
- if (!flags.z())
- goto notwalk;
- al = data.byte(kTurntoface);
- _cmp(al, data.byte(kFacing));
- if (!flags.z())
- goto notwalk;
- data.byte(kReasseschanges) = 1;
- al = data.byte(kFacing);
- _cmp(al, data.byte(kLeavedirection));
- if (!flags.z())
- goto notwalk;
- checkforexit();
-notwalk:
- al = data.byte(kFacing);
- ah = 0;
- di = 1105;
- _add(di, ax);
- al = cs.byte(di);
- _add(al, es.byte(bx+29));
- es.byte(bx+15) = al;
- ax = es.word(bx+10);
- data.byte(kRyanx) = al;
- data.byte(kRyany) = ah;
-}
-
-void DreamGenContext::aboutturn() {
- STACK_CHECK;
- _cmp(data.byte(kTurndirection), 1);
- if (flags.z())
- goto incdir;
- _cmp(data.byte(kTurndirection), -1);
- if (flags.z())
- goto decdir;
- al = data.byte(kFacing);
- _sub(al, data.byte(kTurntoface));
- if (!flags.c())
- goto higher;
- _neg(al);
- _cmp(al, 4);
- if (!flags.c())
- goto decdir;
- goto incdir;
-higher:
- _cmp(al, 4);
- if (!flags.c())
- goto incdir;
- goto decdir;
-incdir:
- data.byte(kTurndirection) = 1;
- al = data.byte(kFacing);
- _inc(al);
- _and(al, 7);
- data.byte(kFacing) = al;
- es.byte(bx+29) = 0;
- return;
-decdir:
- data.byte(kTurndirection) = -1;
- al = data.byte(kFacing);
- _dec(al);
- _and(al, 7);
- data.byte(kFacing) = al;
- es.byte(bx+29) = 0;
-}
-
-void DreamGenContext::facerightway() {
- STACK_CHECK;
- push(es);
- push(bx);
- getroomspaths();
- al = data.byte(kManspath);
- ah = 0;
- _add(ax, ax);
- _add(ax, ax);
- _add(ax, ax);
- _add(bx, ax);
- al = es.byte(bx+7);
- data.byte(kTurntoface) = al;
- data.byte(kLeavedirection) = al;
- bx = pop();
- es = pop();
-}
-
void DreamGenContext::checkforexit() {
STACK_CHECK;
cl = data.byte(kRyanx);
@@ -2629,7 +2292,7 @@ void DreamGenContext::initrain() {
STACK_CHECK;
es = data.word(kBuffers);
di = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30));
- bx = 1113;
+ bx = offset_rainlocations;
checkmorerain:
al = cs.byte(bx);
_cmp(al, 255);
@@ -2772,147 +2435,6 @@ failrain:
al = 0;
}
-void DreamGenContext::showrain() {
- STACK_CHECK;
- ds = data.word(kMainsprites);
- si = 6*58;
- ax = ds.word(si+2);
- si = ax;
- _add(si, 2080);
- bx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30));
- es = data.word(kBuffers);
- _cmp(es.byte(bx), 255);
- if (flags.z())
- return /* (nothunder) */;
-morerain:
- es = data.word(kBuffers);
- _cmp(es.byte(bx), 255);
- if (flags.z())
- goto finishrain;
- al = es.byte(bx+1);
- ah = 0;
- _add(ax, data.word(kMapady));
- _add(ax, data.word(kMapystart));
- cx = 320;
- _mul(cx);
- cl = es.byte(bx);
- ch = 0;
- _add(ax, cx);
- _add(ax, data.word(kMapadx));
- _add(ax, data.word(kMapxstart));
- di = ax;
- cl = es.byte(bx+2);
- ch = 0;
- ax = es.word(bx+3);
- dl = es.byte(bx+5);
- dh = 0;
- _sub(ax, dx);
- _and(ax, 511);
- es.word(bx+3) = ax;
- _add(bx, 6);
- push(si);
- _add(si, ax);
- es = data.word(kWorkspace);
- ah = 0;
- dx = 320-2;
-rainloop:
- _lodsb();
- _cmp(al, ah);
- if (flags.z())
- goto noplot;
- _stosb();
- _add(di, dx);
- if (--cx)
- goto rainloop;
- si = pop();
- goto morerain;
-noplot:
- _add(di, 320-1);
- if (--cx)
- goto rainloop;
- si = pop();
- goto morerain;
-finishrain:
- _cmp(data.word(kCh1blockstocopy), 0);
- if (!flags.z())
- return /* (nothunder) */;
- _cmp(data.byte(kReallocation), 2);
- if (!flags.z())
- goto notlouisthund;
- _cmp(data.byte(kBeenmugged), 1);
- if (!flags.z())
- return /* (nothunder) */;
-notlouisthund:
- _cmp(data.byte(kReallocation), 55);
- if (flags.z())
- return /* (nothunder) */;
- randomnum1();
- _cmp(al, 1);
- if (!flags.c())
- return /* (nothunder) */;
- al = 7;
- _cmp(data.byte(kCh0playing), 6);
- if (flags.z())
- goto isthunder1;
- al = 4;
-isthunder1:
- playchannel1();
-}
-
-void DreamGenContext::backobject() {
- STACK_CHECK;
- ds = data.word(kSetdat);
- di = es.word(bx+20);
- al = es.byte(bx+18);
- _cmp(al, 0);
- if (flags.z())
- goto _tmp48z;
- _dec(al);
- es.byte(bx+18) = al;
- return /* (finishback) */;
-_tmp48z:
- al = ds.byte(di+7);
- es.byte(bx+18) = al;
- al = ds.byte(di+8);
- _cmp(al, 6);
- if (!flags.z())
- goto notwidedoor;
- widedoor();
- return /* (finishback) */;
-notwidedoor:
- _cmp(al, 5);
- if (!flags.z())
- goto notrandom;
- random();
- return /* (finishback) */;
-notrandom:
- _cmp(al, 4);
- if (!flags.z())
- goto notlockdoor;
- lockeddoorway();
- return /* (finishback) */;
-notlockdoor:
- _cmp(al, 3);
- if (!flags.z())
- goto notlift;
- liftsprite();
- return /* (finishback) */;
-notlift:
- _cmp(al, 2);
- if (!flags.z())
- goto notdoor;
- doorway();
- return /* (finishback) */;
-notdoor:
- _cmp(al, 1);
- if (!flags.z())
- goto steadyob;
- constant();
- return /* (finishback) */;
-steadyob:
- steady();
-}
-
void DreamGenContext::liftnoise() {
STACK_CHECK;
_cmp(data.byte(kReallocation), 5);
@@ -2966,231 +2488,6 @@ gotconst:
ds.byte(di+17) = al;
}
-void DreamGenContext::doorway() {
- STACK_CHECK;
- data.byte(kDoorcheck1) = -24;
- data.byte(kDoorcheck2) = 10;
- data.byte(kDoorcheck3) = -30;
- data.byte(kDoorcheck4) = 10;
- dodoor();
-}
-
-void DreamGenContext::widedoor() {
- STACK_CHECK;
- data.byte(kDoorcheck1) = -24;
- data.byte(kDoorcheck2) = 24;
- data.byte(kDoorcheck3) = -30;
- data.byte(kDoorcheck4) = 24;
- dodoor();
-}
-
-void DreamGenContext::lockeddoorway() {
- STACK_CHECK;
- al = data.byte(kRyanx);
- ah = data.byte(kRyany);
- cl = es.byte(bx+10);
- ch = es.byte(bx+11);
- _cmp(al, cl);
- if (!flags.c())
- goto rtofdoor2;
- _sub(al, cl);
- _cmp(al, -24);
- if (!flags.c())
- goto upordown2;
- goto shutdoor2;
-rtofdoor2:
- _sub(al, cl);
- _cmp(al, 10);
- if (!flags.c())
- goto shutdoor2;
-upordown2:
- _cmp(ah, ch);
- if (!flags.c())
- goto botofdoor2;
- _sub(ah, ch);
- _cmp(ah, -30);
- if (flags.c())
- goto shutdoor2;
- goto opendoor2;
-botofdoor2:
- _sub(ah, ch);
- _cmp(ah, 12);
- if (!flags.c())
- goto shutdoor2;
-opendoor2:
- _cmp(data.byte(kThroughdoor), 1);
- if (flags.z())
- goto mustbeopen;
- _cmp(data.byte(kLockstatus), 1);
- if (flags.z())
- goto shutdoor;
-mustbeopen:
- cl = es.byte(bx+19);
- _cmp(cl, 1);
- if (!flags.z())
- goto notdoorsound4;
- al = 0;
- playchannel1();
-notdoorsound4:
- _cmp(cl, 6);
- if (!flags.z())
- goto noturnonyet;
- al = data.byte(kDoorpath);
- push(es);
- push(bx);
- turnpathon();
- bx = pop();
- es = pop();
-noturnonyet:
- cl = es.byte(bx+19);
- _cmp(data.byte(kThroughdoor), 1);
- if (!flags.z())
- goto notthrough2;
- _cmp(cl, 0);
- if (!flags.z())
- goto notthrough2;
- cl = 6;
-notthrough2:
- _inc(cl);
- ch = 0;
- push(di);
- _add(di, cx);
- al = ds.byte(di+18);
- _cmp(al, 255);
- if (!flags.z())
- goto atlast3;
- _dec(di);
- _dec(cl);
-atlast3:
- es.byte(bx+19) = cl;
- al = ds.byte(di+18);
- di = pop();
- es.byte(bx+15) = al;
- ds.byte(di+17) = al;
- _cmp(cl, 5);
- if (!flags.z())
- return /* (justshutting) */;
- data.byte(kThroughdoor) = 1;
- return;
-shutdoor2:
- cl = es.byte(bx+19);
- _cmp(cl, 5);
- if (!flags.z())
- goto notdoorsound3;
- al = 1;
- playchannel1();
-notdoorsound3:
- _cmp(cl, 0);
- if (flags.z())
- goto atlast4;
- _dec(cl);
- es.byte(bx+19) = cl;
-atlast4:
- ch = 0;
- data.byte(kThroughdoor) = 0;
- push(di);
- _add(di, cx);
- al = ds.byte(di+18);
- di = pop();
- es.byte(bx+15) = al;
- ds.byte(di+17) = al;
- _cmp(cl, 0);
- if (!flags.z())
- return /* (notlocky) */;
- al = data.byte(kDoorpath);
- push(es);
- push(bx);
- turnpathoff();
- bx = pop();
- es = pop();
- data.byte(kLockstatus) = 1;
- return;
-/*continuing to unbounded code: shutdoor from dodoor:60-87*/
-shutdoor:
- cl = es.byte(bx+19);
- _cmp(cl, 5);
- if (!flags.z())
- goto notdoorsound1;
- al = 1;
- _cmp(data.byte(kReallocation), 5);
- if (!flags.z())
- goto nothoteldoor1;
- al = 13;
-nothoteldoor1:
- playchannel1();
-notdoorsound1:
- _cmp(cl, 0);
- if (flags.z())
- goto atlast2;
- _dec(cl);
- es.byte(bx+19) = cl;
-atlast2:
- ch = 0;
- push(di);
- _add(di, cx);
- al = ds.byte(di+18);
- di = pop();
- es.byte(bx+15) = al;
- ds.byte(di+17) = al;
- _cmp(cl, 5);
- if (!flags.z())
- return /* (notnearly) */;
- data.byte(kThroughdoor) = 0;
-}
-
-void DreamGenContext::updatepeople() {
- STACK_CHECK;
- es = data.word(kBuffers);
- di = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5));
- data.word(kListpos) = di;
- cx = 12*5;
- al = 255;
- _stosb(cx, true);
- _inc(data.word(kMaintimer));
- es = cs;
- bx = 534;
- di = 991;
-updateloop:
- al = es.byte(bx);
- _cmp(al, 255);
- if (flags.z())
- return /* (endupdate) */;
- _cmp(al, data.byte(kReallocation));
- if (!flags.z())
- goto notinthisroom;
- cx = es.word(bx+1);
- _cmp(cl, data.byte(kMapx));
- if (!flags.z())
- goto notinthisroom;
- _cmp(ch, data.byte(kMapy));
- if (!flags.z())
- goto notinthisroom;
- push(di);
- ax = cs.word(di);
- __dispatch_call(ax);
- di = pop();
-notinthisroom:
- _add(bx, 8);
- _add(di, 2);
- goto updateloop;
-}
-
-void DreamGenContext::getreelframeax() {
- STACK_CHECK;
- push(ds);
- data.word(kCurrentframe) = ax;
- findsource();
- es = ds;
- ds = pop();
- ax = data.word(kCurrentframe);
- _sub(ax, data.word(kTakeoff));
- _add(ax, ax);
- cx = ax;
- _add(ax, ax);
- _add(ax, cx);
- bx = ax;
-}
-
void DreamGenContext::reelsonscreen() {
STACK_CHECK;
reconstruct();
@@ -3200,48 +2497,6 @@ void DreamGenContext::reelsonscreen() {
usetimedtext();
}
-void DreamGenContext::plotreel() {
- STACK_CHECK;
- getreelstart();
-retryreel:
- push(es);
- push(si);
- ax = es.word(si+2);
- _cmp(al, 220);
- if (flags.c())
- goto normalreel;
- _cmp(al, 255);
- if (flags.z())
- goto normalreel;
- dealwithspecial();
- _inc(data.word(kReelpointer));
- si = pop();
- es = pop();
- _add(si, 40);
- goto retryreel;
-normalreel:
- cx = 8;
-plotloop:
- push(cx);
- push(es);
- push(si);
- ax = es.word(si);
- _cmp(ax, 0x0ffff);
- if (flags.z())
- goto notplot;
- showreelframe();
-notplot:
- si = pop();
- es = pop();
- cx = pop();
- _add(si, 5);
- if (--cx)
- goto plotloop;
- soundonreels();
- bx = pop();
- es = pop();
-}
-
void DreamGenContext::soundonreels() {
STACK_CHECK;
bl = data.byte(kReallocation);
@@ -3307,126 +2562,6 @@ notfudge:
data.byte(kHavedoneobs) = 0;
}
-void DreamGenContext::dealwithspecial() {
- STACK_CHECK;
- _sub(al, 220);
- _cmp(al, 0);
- if (!flags.z())
- goto notplset;
- al = ah;
- placesetobject();
- data.byte(kHavedoneobs) = 1;
- return;
-notplset:
- _cmp(al, 1);
- if (!flags.z())
- goto notremset;
- al = ah;
- removesetobject();
- data.byte(kHavedoneobs) = 1;
- return;
-notremset:
- _cmp(al, 2);
- if (!flags.z())
- goto notplfree;
- al = ah;
- placefreeobject();
- data.byte(kHavedoneobs) = 1;
- return;
-notplfree:
- _cmp(al, 3);
- if (!flags.z())
- goto notremfree;
- al = ah;
- removefreeobject();
- data.byte(kHavedoneobs) = 1;
- return;
-notremfree:
- _cmp(al, 4);
- if (!flags.z())
- goto notryanoff;
- switchryanoff();
- return;
-notryanoff:
- _cmp(al, 5);
- if (!flags.z())
- goto notryanon;
- data.byte(kTurntoface) = ah;
- data.byte(kFacing) = ah;
- switchryanon();
- return;
-notryanon:
- _cmp(al, 6);
- if (!flags.z())
- goto notchangeloc;
- data.byte(kNewlocation) = ah;
- return;
-notchangeloc:
- movemap();
-}
-
-void DreamGenContext::movemap() {
- STACK_CHECK;
- _cmp(ah, 32);
- if (!flags.z())
- goto notmapup2;
- _sub(data.byte(kMapy), 20);
- data.byte(kNowinnewroom) = 1;
- return;
-notmapup2:
- _cmp(ah, 16);
- if (!flags.z())
- goto notmapupspec;
- _sub(data.byte(kMapy), 10);
- data.byte(kNowinnewroom) = 1;
- return;
-notmapupspec:
- _cmp(ah, 8);
- if (!flags.z())
- goto notmapdownspec;
- _add(data.byte(kMapy), 10);
- data.byte(kNowinnewroom) = 1;
- return;
-notmapdownspec:
- _cmp(ah, 2);
- if (!flags.z())
- goto notmaprightspec;
- _add(data.byte(kMapx), 11);
- data.byte(kNowinnewroom) = 1;
- return;
-notmaprightspec:
- _sub(data.byte(kMapx), 11);
- data.byte(kNowinnewroom) = 1;
-}
-
-void DreamGenContext::getreelstart() {
- STACK_CHECK;
- ax = data.word(kReelpointer);
- cx = 40;
- _mul(cx);
- es = data.word(kReels);
- si = ax;
- _add(si, (0+(36*144)));
-}
-
-void DreamGenContext::showreelframe() {
- STACK_CHECK;
- al = es.byte(si+2);
- ah = 0;
- di = ax;
- _add(di, data.word(kMapadx));
- al = es.byte(si+3);
- bx = ax;
- _add(bx, data.word(kMapady));
- ax = es.word(si);
- data.word(kCurrentframe) = ax;
- findsource();
- ax = data.word(kCurrentframe);
- _sub(ax, data.word(kTakeoff));
- ah = 8;
- showframe();
-}
-
void DreamGenContext::deleverything() {
STACK_CHECK;
al = data.byte(kMapysize);
@@ -3501,13 +2636,6 @@ dumpevery2:
goto dumpevery2;
}
-void DreamGenContext::allocatework() {
- STACK_CHECK;
- bx = 0x1000;
- allocatemem();
- data.word(kWorkspace) = ax;
-}
-
void DreamGenContext::loadpalfromiff() {
STACK_CHECK;
dx = 2481;
@@ -3669,68 +2797,6 @@ void DreamGenContext::createpanel2() {
showframe();
}
-void DreamGenContext::clearwork() {
- STACK_CHECK;
- ax = 0x0;
- es = data.word(kWorkspace);
- di = 0;
- cx = (200*320)/64;
-clearloop:
- _stosw(32);
- if (--cx)
- goto clearloop;
-}
-
-void DreamGenContext::zoom() {
- STACK_CHECK;
- _cmp(data.word(kWatchingtime), 0);
- if (!flags.z())
- return /* (inwatching) */;
- _cmp(data.byte(kZoomon), 1);
- if (flags.z())
- goto zoomswitch;
- return;
-zoomswitch:
- _cmp(data.byte(kCommandtype), 199);
- if (flags.c())
- goto zoomit;
- putunderzoom();
- return;
-zoomit:
- ax = data.word(kOldpointery);
- _sub(ax, 9);
- cx = (320);
- _mul(cx);
- _add(ax, data.word(kOldpointerx));
- _sub(ax, 11);
- si = ax;
- ax = (132)+4;
- cx = (320);
- _mul(cx);
- _add(ax, (8)+5);
- di = ax;
- es = data.word(kWorkspace);
- ds = data.word(kWorkspace);
- cx = 20;
-zoomloop:
- push(cx);
- cx = 23;
-zoomloop2:
- _lodsb();
- ah = al;
- _stosw();
- es.word(di+(320)-2) = ax;
- if (--cx)
- goto zoomloop2;
- _add(si, (320)-23);
- _add(di, (320)-46+(320));
- cx = pop();
- if (--cx)
- goto zoomloop;
- crosshair();
- data.byte(kDidzoom) = 1;
-}
-
void DreamGenContext::delthisone() {
STACK_CHECK;
push(ax);
@@ -3775,83 +2841,6 @@ deloneloop:
goto deloneloop;
}
-void DreamGenContext::doblocks() {
- STACK_CHECK;
- es = data.word(kWorkspace);
- ax = data.word(kMapady);
- cx = (320);
- _mul(cx);
- di = data.word(kMapadx);
- _add(di, ax);
- al = data.byte(kMapy);
- ah = 0;
- bx = (66);
- _mul(bx);
- bl = data.byte(kMapx);
- bh = 0;
- _add(ax, bx);
- si = (0);
- _add(si, ax);
- cx = 10;
-loop120:
- push(di);
- push(cx);
- cx = 11;
-loop124:
- push(cx);
- push(di);
- ds = data.word(kMapdata);
- _lodsb();
- ds = data.word(kBackdrop);
- push(si);
- _cmp(al, 0);
- if (flags.z())
- goto zeroblock;
- ah = al;
- al = 0;
- si = (0+192);
- _add(si, ax);
- bh = 14;
- bh = 4;
-firstbitofblock:
- _movsw(8);
- _add(di, (320)-16);
- _dec(bh);
- if (!flags.z())
- goto firstbitofblock;
- bh = 12;
-loop125:
- _movsw(8);
- ax = 0x0dfdf;
- _stosw(2);
- _add(di, (320)-20);
- _dec(bh);
- if (!flags.z())
- goto loop125;
- _add(di, 4);
- ax = 0x0dfdf;
- _stosw(8);
- _add(di, (320)-16);
- _stosw(8);
- _add(di, (320)-16);
- _stosw(8);
- _add(di, (320)-16);
- _stosw(8);
-zeroblock:
- si = pop();
- di = pop();
- cx = pop();
- _add(di, 16);
- if (--cx)
- goto loop124;
- _add(si, (66)-11);
- cx = pop();
- di = pop();
- _add(di, (320)*16);
- if (--cx)
- goto loop120;
-}
-
void DreamGenContext::transferinv() {
STACK_CHECK;
di = data.word(kExframepos);
@@ -4937,216 +3926,6 @@ realcreditsearly:
data.byte(kLasthardkey) = 0;
}
-void DreamGenContext::printchar() {
- STACK_CHECK;
- _cmp(al, 255);
- if (flags.z())
- return /* (ignoreit) */;
- push(si);
- push(bx);
- push(di);
- _cmp(data.byte(kForeignrelease), 0);
- if (flags.z())
- goto _tmp1;
- _sub(bx, 3);
-_tmp1:
- push(ax);
- _sub(al, 32);
- ah = 0;
- _add(ax, data.word(kCharshift));
- showframe();
- ax = pop();
- di = pop();
- bx = pop();
- si = pop();
- _cmp(data.byte(kKerning), 0);
- if (!flags.z())
- goto nokern;
- kernchars();
-nokern:
- push(cx);
- ch = 0;
- _add(di, cx);
- cx = pop();
-}
-
-void DreamGenContext::printslow() {
- STACK_CHECK;
- data.byte(kPointerframe) = 1;
- data.byte(kPointermode) = 3;
- ds = data.word(kCharset1);
-printloopslow6:
- push(bx);
- push(di);
- push(dx);
- getnumber();
- ch = 0;
-printloopslow5:
- push(cx);
- push(si);
- push(es);
- ax = es.word(si);
- push(bx);
- push(cx);
- push(es);
- push(si);
- push(ds);
- modifychar();
- printboth();
- ds = pop();
- si = pop();
- es = pop();
- cx = pop();
- bx = pop();
- ax = es.word(si+1);
- _inc(si);
- _cmp(al, 0);
- if (flags.z())
- goto finishslow;
- _cmp(al, ':');
- if (flags.z())
- goto finishslow;
- _cmp(cl, 1);
- if (flags.z())
- goto afterslow;
- push(di);
- push(ds);
- push(bx);
- push(cx);
- push(es);
- push(si);
- modifychar();
- data.word(kCharshift) = 91;
- printboth();
- data.word(kCharshift) = 0;
- si = pop();
- es = pop();
- cx = pop();
- bx = pop();
- ds = pop();
- di = pop();
- waitframes();
- _cmp(ax, 0);
- if (flags.z())
- goto keepgoing;
- _cmp(ax, data.word(kOldbutton));
- if (!flags.z())
- goto finishslow2;
-keepgoing:
- waitframes();
- _cmp(ax, 0);
- if (flags.z())
- goto afterslow;
- _cmp(ax, data.word(kOldbutton));
- if (!flags.z())
- goto finishslow2;
-afterslow:
- es = pop();
- si = pop();
- cx = pop();
- _inc(si);
- if (--cx)
- goto printloopslow5;
- dx = pop();
- di = pop();
- bx = pop();
- _add(bx, 10);
- goto printloopslow6;
-finishslow:
- es = pop();
- si = pop();
- cx = pop();
- dx = pop();
- di = pop();
- bx = pop();
- al = 0;
- return;
-finishslow2:
- es = pop();
- si = pop();
- cx = pop();
- dx = pop();
- di = pop();
- bx = pop();
- al = 1;
-}
-
-void DreamGenContext::waitframes() {
- STACK_CHECK;
- push(di);
- push(bx);
- push(es);
- push(si);
- push(ds);
- readmouse();
- showpointer();
- vsync();
- dumppointer();
- delpointer();
- ax = data.word(kMousebutton);
- ds = pop();
- si = pop();
- es = pop();
- bx = pop();
- di = pop();
-}
-
-void DreamGenContext::printboth() {
- STACK_CHECK;
- push(ax);
- push(cx);
- push(bx);
- push(di);
- printchar();
- ax = pop();
- push(di);
- di = ax;
- multidump();
- di = pop();
- bx = pop();
- cx = pop();
- ax = pop();
-}
-
-void DreamGenContext::printdirect() {
- STACK_CHECK;
- data.word(kLastxpos) = di;
- ds = data.word(kCurrentset);
-printloop6:
- push(bx);
- push(di);
- push(dx);
- getnumber();
- ch = 0;
-printloop5:
- ax = es.word(si);
- _inc(si);
- _cmp(al, 0);
- if (flags.z())
- goto finishdirct;
- _cmp(al, ':');
- if (flags.z())
- goto finishdirct;
- push(cx);
- push(es);
- modifychar();
- printchar();
- data.word(kLastxpos) = di;
- es = pop();
- cx = pop();
- if (--cx)
- goto printloop5;
- dx = pop();
- di = pop();
- bx = pop();
- _add(bx, data.word(kLinespacing));
- goto printloop6;
-finishdirct:
- dx = pop();
- di = pop();
- bx = pop();
-}
-
void DreamGenContext::monprint() {
STACK_CHECK;
data.byte(kKerning) = 1;
@@ -5233,114 +4012,6 @@ nottrigger2:
data.byte(kKerning) = 0;
}
-void DreamGenContext::getnumber() {
- STACK_CHECK;
- cx = 0;
- push(si);
- push(bx);
- push(di);
- push(ds);
- push(es);
- di = si;
-wordloop:
- push(cx);
- push(dx);
- getnextword();
- dx = pop();
- cx = pop();
- _cmp(al, 1);
- if (flags.z())
- goto endoftext;
- al = cl;
- ah = 0;
- push(bx);
- bh = 0;
- _add(ax, bx);
- bx = pop();
- _sub(ax, 10);
- dh = 0;
- _cmp(ax, dx);
- if (!flags.c())
- goto gotoverend;
- _add(cl, bl);
- _add(ch, bh);
- goto wordloop;
-gotoverend:
- al = dl;
- _and(al, 1);
- if (flags.z())
- goto notcentre;
- push(cx);
- al = dl;
- _and(al, 0xfe);
- ah = 0;
- ch = 0;
- _sub(ax, cx);
- _add(ax, 20);
- _shr(ax, 1);
- cx = pop();
- es = pop();
- ds = pop();
- di = pop();
- bx = pop();
- si = pop();
- _add(di, ax);
- cl = ch;
- return;
-notcentre:
- es = pop();
- ds = pop();
- di = pop();
- bx = pop();
- si = pop();
- cl = ch;
- return;
-endoftext:
- al = cl;
- ah = 0;
- push(bx);
- bh = 0;
- _add(ax, bx);
- bx = pop();
- _sub(ax, 10);
- dh = 0;
- _cmp(ax, dx);
- if (!flags.c())
- goto gotoverend2;
- _add(cl, bl);
- _add(ch, bh);
-gotoverend2:
- al = dl;
- _and(al, 1);
- if (flags.z())
- goto notcent2;
- push(cx);
- al = dl;
- _and(al, 0xfe);
- _add(al, 2);
- ah = 0;
- ch = 0;
- _add(ax, 20);
- _sub(ax, cx);
- _shr(ax, 1);
- cx = pop();
- es = pop();
- ds = pop();
- di = pop();
- bx = pop();
- si = pop();
- _add(di, ax);
- cl = ch;
- return;
-notcent2:
- es = pop();
- ds = pop();
- di = pop();
- bx = pop();
- si = pop();
- cl = ch;
-}
-
void DreamGenContext::fillryan() {
STACK_CHECK;
es = data.word(kBuffers);
@@ -5649,15 +4320,15 @@ waitexam:
dumptextline();
delpointer();
data.byte(kGetback) = 0;
- bx = 2494;
+ bx = offset_examlist;
_cmp(data.byte(kInvopen), 0);
if (flags.z())
goto notuseinv;
- bx = 2556;
+ bx = offset_invlist1;
_cmp(data.byte(kInvopen), 1);
if (flags.z())
goto notuseinv;
- bx = 2618;
+ bx = offset_withlist1;
notuseinv:
checkcoords();
_cmp(data.byte(kExamagain), 0);
@@ -5788,7 +4459,7 @@ void DreamGenContext::openob() {
STACK_CHECK;
al = data.byte(kOpenedob);
ah = data.byte(kOpenedtype);
- di = 5847;
+ di = offset_commandline;
copyname();
di = (80);
bx = (58)+86;
@@ -5799,7 +4470,7 @@ void DreamGenContext::openob() {
_add(di, 5);
bx = (58)+86;
es = cs;
- si = 5847;
+ si = offset_commandline;
dl = 220;
al = 0;
ah = 0;
@@ -5811,7 +4482,7 @@ void DreamGenContext::openob() {
cx = (44);
_mul(cx);
_add(ax, (80));
- bx = 2588;
+ bx = offset_openchangesize;
cs.word(bx) = ax;
}
@@ -6163,15 +4834,15 @@ waitexam:
dumptextline();
delpointer();
data.byte(kGetback) = 0;
- bx = 2494;
+ bx = offset_examlist;
_cmp(data.byte(kInvopen), 0);
if (flags.z())
goto notuseinv;
- bx = 2556;
+ bx = offset_invlist1;
_cmp(data.byte(kInvopen), 1);
if (flags.z())
goto notuseinv;
- bx = 2618;
+ bx = offset_withlist1;
notuseinv:
checkcoords();
_cmp(data.byte(kExamagain), 0);
@@ -6529,31 +5200,6 @@ doplace:
delpointer();
}
-void DreamGenContext::deletetaken() {
- STACK_CHECK;
- es = data.word(kFreedat);
- ah = data.byte(kReallocation);
- ds = data.word(kExtras);
- si = (0+2080+30000);
- cx = (114);
-takenloop:
- al = ds.byte(si+11);
- _cmp(al, ah);
- if (!flags.z())
- goto notinhere;
- bl = ds.byte(si+1);
- bh = 0;
- _add(bx, bx);
- _add(bx, bx);
- _add(bx, bx);
- _add(bx, bx);
- es.byte(bx+2) = 254;
-notinhere:
- _add(si, 16);
- if (--cx)
- goto takenloop;
-}
-
void DreamGenContext::outofinv() {
STACK_CHECK;
findinvpos();
@@ -7675,392 +6321,6 @@ void DreamGenContext::drawfloor() {
es = pop();
}
-void DreamGenContext::calcmapad() {
- STACK_CHECK;
- getdimension();
- push(cx);
- push(dx);
- al = 11;
- _sub(al, dl);
- _sub(al, cl);
- _sub(al, cl);
- ax.cbw();
- bx = 8;
- _mul(bx);
- _add(ax, data.word(kMapoffsetx));
- data.word(kMapadx) = ax;
- dx = pop();
- cx = pop();
- al = 10;
- _sub(al, dh);
- _sub(al, ch);
- _sub(al, ch);
- ax.cbw();
- bx = 8;
- _mul(bx);
- _add(ax, data.word(kMapoffsety));
- data.word(kMapady) = ax;
-}
-
-void DreamGenContext::getdimension() {
- STACK_CHECK;
- es = data.word(kBuffers);
- bx = (0+(228*13)+32+60+(32*32));
- ch = 0;
-dimloop1:
- addalong();
- _cmp(al, 0);
- if (!flags.z())
- goto finishdim1;
- _inc(ch);
- goto dimloop1;
-finishdim1:
- bx = (0+(228*13)+32+60+(32*32));
- cl = 0;
-dimloop2:
- push(bx);
- addlength();
- bx = pop();
- _cmp(al, 0);
- if (!flags.z())
- goto finishdim2;
- _inc(cl);
- _add(bx, 3);
- goto dimloop2;
-finishdim2:
- bx = (0+(228*13)+32+60+(32*32))+(11*3*9);
- dh = 10;
-dimloop3:
- push(bx);
- addalong();
- bx = pop();
- _cmp(al, 0);
- if (!flags.z())
- goto finishdim3;
- _dec(dh);
- _sub(bx, 11*3);
- goto dimloop3;
-finishdim3:
- bx = (0+(228*13)+32+60+(32*32))+(3*10);
- dl = 11;
-dimloop4:
- push(bx);
- addlength();
- bx = pop();
- _cmp(al, 0);
- if (!flags.z())
- goto finishdim4;
- _dec(dl);
- _sub(bx, 3);
- goto dimloop4;
-finishdim4:
- al = cl;
- ah = 0;
- _shl(ax, 1);
- _shl(ax, 1);
- _shl(ax, 1);
- _shl(ax, 1);
- data.word(kMapxstart) = ax;
- al = ch;
- ah = 0;
- _shl(ax, 1);
- _shl(ax, 1);
- _shl(ax, 1);
- _shl(ax, 1);
- data.word(kMapystart) = ax;
- _sub(dl, cl);
- _sub(dh, ch);
- al = dl;
- ah = 0;
- _shl(ax, 1);
- _shl(ax, 1);
- _shl(ax, 1);
- _shl(ax, 1);
- data.byte(kMapxsize) = al;
- al = dh;
- ah = 0;
- _shl(ax, 1);
- _shl(ax, 1);
- _shl(ax, 1);
- _shl(ax, 1);
- data.byte(kMapysize) = al;
-}
-
-void DreamGenContext::addalong() {
- STACK_CHECK;
- ah = 11;
-addloop:
- _cmp(es.byte(bx), 0);
- if (!flags.z())
- goto gotalong;
- _add(bx, 3);
- _dec(ah);
- if (!flags.z())
- goto addloop;
- al = 0;
- return;
-gotalong:
- al = 1;
-}
-
-void DreamGenContext::addlength() {
- STACK_CHECK;
- ah = 10;
-addloop2:
- _cmp(es.byte(bx), 0);
- if (!flags.z())
- goto gotlength;
- _add(bx, 3*11);
- _dec(ah);
- if (!flags.z())
- goto addloop2;
- al = 0;
- return;
-gotlength:
- al = 1;
-}
-
-void DreamGenContext::drawflags() {
- STACK_CHECK;
- es = data.word(kBuffers);
- di = (0+(228*13)+32+60+(32*32));
- al = data.byte(kMapy);
- ah = 0;
- cx = (66);
- _mul(cx);
- bl = data.byte(kMapx);
- bh = 0;
- _add(ax, bx);
- si = (0);
- _add(si, ax);
- cx = 10;
-_tmp28:
- push(cx);
- cx = 11;
-_tmp28a:
- ds = data.word(kMapdata);
- _lodsb();
- ds = data.word(kBackdrop);
- push(si);
- push(ax);
- ah = 0;
- _add(ax, ax);
- si = (0);
- _add(si, ax);
- _movsw();
- ax = pop();
- _stosb();
- si = pop();
- if (--cx)
- goto _tmp28a;
- _add(si, (66)-11);
- cx = pop();
- if (--cx)
- goto _tmp28;
-}
-
-void DreamGenContext::showallobs() {
- STACK_CHECK;
- es = data.word(kBuffers);
- bx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32));
- data.word(kListpos) = bx;
- di = bx;
- cx = 128*5;
- al = 255;
- _stosb(cx, true);
- es = data.word(kSetframes);
- data.word(kFrsegment) = es;
- ax = (0);
- data.word(kDataad) = ax;
- ax = (0+2080);
- data.word(kFramesad) = ax;
- data.byte(kCurrentob) = 0;
- ds = data.word(kSetdat);
- si = 0;
- cx = 128;
-showobsloop:
- push(cx);
- push(si);
- push(si);
- _add(si, 58);
- es = data.word(kSetdat);
- getmapad();
- si = pop();
- _cmp(ch, 0);
- if (flags.z())
- goto blankframe;
- al = es.byte(si+18);
- ah = 0;
- data.word(kCurrentframe) = ax;
- _cmp(al, 255);
- if (flags.z())
- goto blankframe;
- push(es);
- push(si);
- calcfrframe();
- finalframe();
- si = pop();
- es = pop();
- al = es.byte(si+18);
- es.byte(si+17) = al;
- _cmp(es.byte(si+8), 0);
- if (!flags.z())
- goto animating;
- _cmp(es.byte(si+5), 5);
- if (flags.z())
- goto animating;
- _cmp(es.byte(si+5), 6);
- if (flags.z())
- goto animating;
- ax = data.word(kCurrentframe);
- ah = 0;
- _add(di, data.word(kMapadx));
- _add(bx, data.word(kMapady));
- showframe();
- goto drawnsetob;
-animating:
- makebackob();
-drawnsetob:
- si = data.word(kListpos);
- es = data.word(kBuffers);
- al = data.byte(kSavex);
- ah = data.byte(kSavey);
- es.word(si) = ax;
- cx = ax;
- ax = data.word(kSavesize);
- _add(al, cl);
- _add(ah, ch);
- es.word(si+2) = ax;
- al = data.byte(kCurrentob);
- es.byte(si+4) = al;
- _add(si, 5);
- data.word(kListpos) = si;
-blankframe:
- _inc(data.byte(kCurrentob));
- si = pop();
- cx = pop();
- _add(si, 64);
- _dec(cx);
- if (flags.z())
- return /* (finishedsetobs) */;
- goto showobsloop;
-}
-
-void DreamGenContext::makebackob() {
- STACK_CHECK;
- _cmp(data.byte(kNewobs), 0);
- if (flags.z())
- return /* (nomake) */;
- al = es.byte(si+5);
- ah = es.byte(si+8);
- push(si);
- push(ax);
- push(si);
- ax = data.word(kObjectx);
- bx = data.word(kObjecty);
- ah = bl;
- si = ax;
- cx = 49520;
- dx = data.word(kSetframes);
- di = (0);
- makesprite();
- ax = pop();
- es.word(bx+20) = ax;
- ax = pop();
- _cmp(al, 255);
- if (!flags.z())
- goto usedpriority;
- al = 0;
-usedpriority:
- es.byte(bx+23) = al;
- es.byte(bx+30) = ah;
- es.byte(bx+16) = 0;
- es.byte(bx+18) = 0;
- es.byte(bx+19) = 0;
- si = pop();
-}
-
-void DreamGenContext::showallfree() {
- STACK_CHECK;
- es = data.word(kBuffers);
- bx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5));
- data.word(kListpos) = bx;
- di = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5));
- cx = 80*5;
- al = 255;
- _stosb(cx, true);
- es = data.word(kFreeframes);
- data.word(kFrsegment) = es;
- ax = (0);
- data.word(kDataad) = ax;
- ax = (0+2080);
- data.word(kFramesad) = ax;
- al = 0;
- data.byte(kCurrentfree) = al;
- ds = data.word(kFreedat);
- si = 2;
- cx = 0;
-loop127:
- push(cx);
- push(si);
- push(si);
- es = data.word(kFreedat);
- getmapad();
- si = pop();
- _cmp(ch, 0);
- if (flags.z())
- goto over138;
- al = data.byte(kCurrentfree);
- ah = 0;
- dx = ax;
- _add(ax, ax);
- _add(ax, dx);
- data.word(kCurrentframe) = ax;
- push(es);
- push(si);
- calcfrframe();
- es = data.word(kMapstore);
- ds = data.word(kFrsegment);
- finalframe();
- si = pop();
- es = pop();
- _cmp(cx, 0);
- if (flags.z())
- goto over138;
- ax = data.word(kCurrentframe);
- ah = 0;
- _add(di, data.word(kMapadx));
- _add(bx, data.word(kMapady));
- showframe();
- si = data.word(kListpos);
- es = data.word(kBuffers);
- al = data.byte(kSavex);
- ah = data.byte(kSavey);
- es.word(si) = ax;
- cx = ax;
- ax = data.word(kSavesize);
- _add(al, cl);
- _add(ah, ch);
- es.word(si+2) = ax;
- ax = pop();
- cx = pop();
- push(cx);
- push(ax);
- es.byte(si+4) = cl;
- _add(si, 5);
- data.word(kListpos) = si;
-over138:
- _inc(data.byte(kCurrentfree));
- si = pop();
- cx = pop();
- _add(si, 16);
- _inc(cx);
- _cmp(cx, 80);
- if (flags.z())
- return /* (finfree) */;
- goto loop127;
-}
-
void DreamGenContext::showallex() {
STACK_CHECK;
es = data.word(kBuffers);
@@ -8149,128 +6409,6 @@ blankex:
goto exloop;
}
-void DreamGenContext::calcfrframe() {
- STACK_CHECK;
- dx = data.word(kFrsegment);
- ax = data.word(kFramesad);
- push(ax);
- cx = data.word(kDataad);
- ax = data.word(kCurrentframe);
- ds = dx;
- bx = 6;
- _mul(bx);
- _add(ax, cx);
- bx = ax;
- cx = ds.word(bx);
- ax = ds.word(bx+2);
- dx = ds.word(bx+4);
- bx = pop();
- push(dx);
- _add(ax, bx);
- data.word(kSavesource) = ax;
- data.word(kSavesize) = cx;
- ax = pop();
- push(ax);
- ah = 0;
- data.word(kOffsetx) = ax;
- ax = pop();
- al = ah;
- ah = 0;
- data.word(kOffsety) = ax;
- return;
- ax = pop();
- cx = 0;
- data.word(kSavesize) = cx;
-}
-
-void DreamGenContext::finalframe() {
- STACK_CHECK;
- ax = data.word(kObjecty);
- _add(ax, data.word(kOffsety));
- bx = data.word(kObjectx);
- _add(bx, data.word(kOffsetx));
- data.byte(kSavex) = bl;
- data.byte(kSavey) = al;
- di = data.word(kObjectx);
- bx = data.word(kObjecty);
-}
-
-void DreamGenContext::adjustlen() {
- STACK_CHECK;
- ah = al;
- _add(al, ch);
- _cmp(al, 100);
- if (flags.c())
- return /* (over242) */;
- al = 224;
- _sub(al, ch);
- ch = al;
-}
-
-void DreamGenContext::getmapad() {
- STACK_CHECK;
- getxad();
- _cmp(ch, 0);
- if (flags.z())
- return /* (over146) */;
- data.word(kObjectx) = ax;
- getyad();
- _cmp(ch, 0);
- if (flags.z())
- return /* (over146) */;
- data.word(kObjecty) = ax;
- ch = 1;
-}
-
-void DreamGenContext::getxad() {
- STACK_CHECK;
- cl = es.byte(si);
- _inc(si);
- al = es.byte(si);
- _inc(si);
- ah = es.byte(si);
- _inc(si);
- _cmp(cl, 0);
- if (!flags.z())
- goto over148;
- _sub(al, data.byte(kMapx));
- if (flags.c())
- goto over148;
- _cmp(al, 11);
- if (!flags.c())
- goto over148;
- cl = 4;
- _shl(al, cl);
- _or(al, ah);
- ah = 0;
- ch = 1;
- return;
-over148:
- ch = 0;
-}
-
-void DreamGenContext::getyad() {
- STACK_CHECK;
- al = es.byte(si);
- _inc(si);
- ah = es.byte(si);
- _inc(si);
- _sub(al, data.byte(kMapy));
- if (flags.c())
- goto over147;
- _cmp(al, 10);
- if (!flags.c())
- goto over147;
- cl = 4;
- _shl(al, cl);
- _or(al, ah);
- ah = 0;
- ch = 1;
- return;
-over147:
- ch = 0;
-}
-
void DreamGenContext::autolook() {
STACK_CHECK;
ax = data.word(kMousex);
@@ -8426,7 +6564,7 @@ waittalk:
dumppointer();
dumptextline();
data.byte(kGetback) = 0;
- bx = 2660;
+ bx = offset_talklist;
checkcoords();
_cmp(data.byte(kQuitrequested), 0);
if (!flags.z())
@@ -8720,7 +6858,7 @@ hangloopq:
vsync();
dumppointer();
dumptextline();
- bx = 2692;
+ bx = offset_quitlist;
checkcoords();
bx = pop();
cx = pop();
@@ -8855,7 +6993,7 @@ select:
_cmp(data.byte(kGetback), 1);
if (flags.z())
goto quittravel;
- bx = 2714;
+ bx = offset_destlist;
checkcoords();
_cmp(data.byte(kNewlocation), 255);
if (flags.z())
@@ -9279,12 +7417,12 @@ void DreamGenContext::usemon() {
al = 32;
_stosb(cx, true);
es = cs;
- di = 2942+1;
+ di = offset_operand1+1;
cx = 12;
al = 32;
_stosb(cx, true);
es = cs;
- di = 2836;
+ di = offset_keys;
es.byte(di) = 1;
_add(di, 26);
cx = 3;
@@ -9782,7 +7920,7 @@ void DreamGenContext::delchar() {
void DreamGenContext::execcommand() {
STACK_CHECK;
es = cs;
- bx = 2776;
+ bx = offset_comlist;
ds = cs;
si = 8045;
al = ds.byte(si);
@@ -9881,7 +8019,7 @@ void DreamGenContext::dircom() {
dirroot:
data.byte(kLogonum) = 0;
ds = cs;
- si = 2956;
+ si = offset_rootdir;
_inc(si);
es = cs;
di = 2970;
@@ -9922,7 +8060,7 @@ void DreamGenContext::signon() {
parser();
_inc(di);
ds = cs;
- si = 2836;
+ si = offset_keys;
cx = 4;
signonloop:
push(cx);
@@ -10026,7 +8164,7 @@ void DreamGenContext::showkeys() {
al = 18;
monmessage();
es = cs;
- bx = 2836;
+ bx = offset_keys;
cx = 4;
keysloop:
push(cx);
@@ -10093,7 +8231,7 @@ foundfile2:
return;
keyok1:
es = cs;
- di = 2942;
+ di = offset_operand1;
ds = data.word(kMonsource);
searchforstring();
_cmp(al, 0);
@@ -10185,7 +8323,7 @@ keyok2:
push(es);
push(bx);
ds = cs;
- si = 2942+1;
+ si = offset_operand1+1;
es = cs;
di = 2970+1;
cx = 12;
@@ -10232,7 +8370,7 @@ void DreamGenContext::getkeyandlogo() {
cx = 26;
_mul(cx);
es = cs;
- bx = 2836;
+ bx = offset_keys;
_add(bx, ax);
al = es.byte(bx);
_cmp(al, 1);
@@ -10306,11 +8444,11 @@ notfound:
void DreamGenContext::parser() {
STACK_CHECK;
es = cs;
- di = 2942;
+ di = offset_operand1;
cx = 13;
al = 0;
_stosb(cx, true);
- di = 2942;
+ di = offset_operand1;
al = '=';
_stosb();
ds = cs;
@@ -10339,7 +8477,7 @@ copyin1:
if (!flags.z())
goto copyin1;
finishpars:
- di = 2942;
+ di = offset_operand1;
}
void DreamGenContext::scrollmonitor() {
@@ -10633,7 +8771,7 @@ nodream7:
getanyad();
dx = data;
ds = dx;
- si = 2984;
+ si = offset_uselist;
checkuselist:
push(si);
_lodsb();
@@ -12057,7 +10195,7 @@ _tmp1:
di = 160;
bx = 155;
es = cs;
- si = 3474;
+ si = offset_money1poke;
data.word(kCharshift) = 91*2+75;
al = 0;
ah = 0;
@@ -12066,7 +10204,7 @@ _tmp1:
di = 187;
bx = 155;
es = cs;
- si = 3479;
+ si = offset_money2poke;
data.word(kCharshift) = 91*2+85;
al = 0;
ah = 0;
@@ -12134,7 +10272,7 @@ void DreamGenContext::lookatcard() {
void DreamGenContext::moneypoke() {
STACK_CHECK;
- bx = 3474;
+ bx = offset_money1poke;
cl = 48-1;
numberpoke0:
_inc(cl);
@@ -12170,7 +10308,7 @@ numberpoke3:
goto numberpoke3;
_add(ax, 10);
cs.byte(bx) = cl;
- bx = 3479;
+ bx = offset_money2poke;
_add(al, 48);
cs.byte(bx) = al;
}
@@ -12633,7 +10771,7 @@ void DreamGenContext::withwhat() {
al = data.byte(kCommand);
ah = data.byte(kObjecttype);
es = cs;
- di = 5847;
+ di = offset_commandline;
copyname();
di = 100;
bx = 21;
@@ -12645,7 +10783,7 @@ void DreamGenContext::withwhat() {
_add(di, 5);
bx = 21;
es = cs;
- si = 5847;
+ si = offset_commandline;
dl = 220;
al = 0;
ah = 0;
@@ -12918,32 +11056,6 @@ void DreamGenContext::findpuztext() {
si = ax;
}
-void DreamGenContext::placesetobject() {
- STACK_CHECK;
- push(es);
- push(bx);
- cl = 0;
- ch = 0;
- findormake();
- getsetad();
- es.byte(bx+58) = 0;
- bx = pop();
- es = pop();
-}
-
-void DreamGenContext::removesetobject() {
- STACK_CHECK;
- push(es);
- push(bx);
- cl = 255;
- ch = 0;
- findormake();
- getsetad();
- es.byte(bx+58) = 255;
- bx = pop();
- es = pop();
-}
-
void DreamGenContext::issetobonmap() {
STACK_CHECK;
push(es);
@@ -12978,35 +11090,6 @@ void DreamGenContext::removefreeobject() {
es = pop();
}
-void DreamGenContext::findormake() {
- STACK_CHECK;
- bx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80));
- push(ax);
- es = data.word(kBuffers);
- ah = data.byte(kReallocation);
-changeloop:
- _cmp(es.byte(bx), 255);
- if (flags.z())
- goto haventfound;
- _cmp(ax, es.word(bx));
- if (!flags.z())
- goto nofoundchange;
- _cmp(ch, es.byte(bx+3));
- if (flags.z())
- goto foundchange;
-nofoundchange:
- _add(bx, 4);
- goto changeloop;
-foundchange:
- ax = pop();
- es.byte(bx+2) = cl;
- return;
-haventfound:
- es.word(bx) = ax;
- es.word(bx+2) = cx;
- ax = pop();
-}
-
void DreamGenContext::switchryanon() {
STACK_CHECK;
data.byte(kRyanon) = 255;
@@ -13017,70 +11100,6 @@ void DreamGenContext::switchryanoff() {
data.byte(kRyanon) = 1;
}
-void DreamGenContext::setallchanges() {
- STACK_CHECK;
- es = data.word(kBuffers);
- bx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80));
-setallloop:
- ax = es.word(bx);
- _cmp(al, 255);
- if (flags.z())
- return /* (endsetloop) */;
- cx = es.word(bx+2);
- _add(bx, 4);
- _cmp(ah, data.byte(kReallocation));
- if (!flags.z())
- goto setallloop;
- push(es);
- push(bx);
- dochange();
- bx = pop();
- es = pop();
- goto setallloop;
-}
-
-void DreamGenContext::dochange() {
- STACK_CHECK;
- _cmp(ch, 0);
- if (flags.z())
- goto object;
- _cmp(ch, 1);
- if (flags.z())
- goto freeobject;
- push(cx);
- ah = 0;
- _add(ax, ax);
- _add(ax, ax);
- _add(ax, ax);
- push(ax);
- al = ch;
- _sub(al, 100);
- ah = 0;
- cx = 144;
- _mul(cx);
- bx = pop();
- _add(bx, ax);
- _add(bx, (0));
- es = data.word(kReels);
- cx = pop();
- es.byte(bx+6) = cl;
- return;
-object:
- push(cx);
- getsetad();
- cx = pop();
- es.byte(bx+58) = cl;
- return;
-freeobject:
- push(cx);
- getfreead();
- cx = pop();
- _cmp(es.byte(bx+2), 255);
- if (!flags.z())
- return /* (beenpickedup) */;
- es.byte(bx+2) = cl;
-}
-
void DreamGenContext::autoappear() {
STACK_CHECK;
_cmp(data.byte(kLocation), 32);
@@ -13151,68 +11170,6 @@ notonsartroof:
placesetobject();
}
-void DreamGenContext::getundertimed() {
- STACK_CHECK;
- al = data.byte(kTimedy);
- _cmp(data.byte(kForeignrelease), 0);
- if (flags.z())
- goto _tmp1;
- _sub(al, 3);
-_tmp1:
- ah = 0;
- bx = ax;
- al = data.byte(kTimedx);
- ah = 0;
- di = ax;
- ch = (30);
- cl = 240;
- ds = data.word(kBuffers);
- si = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4));
- multiget();
-}
-
-void DreamGenContext::putundertimed() {
- STACK_CHECK;
- al = data.byte(kTimedy);
- _cmp(data.byte(kForeignrelease), 0);
- if (flags.z())
- goto _tmp1;
- _sub(al, 3);
-_tmp1:
- ah = 0;
- bx = ax;
- al = data.byte(kTimedx);
- ah = 0;
- di = ax;
- ch = (30);
- cl = 240;
- ds = data.word(kBuffers);
- si = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4));
- multiput();
-}
-
-void DreamGenContext::dumptimedtext() {
- STACK_CHECK;
- _cmp(data.byte(kNeedtodumptimed), 1);
- if (!flags.z())
- return /* (nodumptimed) */;
- al = data.byte(kTimedy);
- _cmp(data.byte(kForeignrelease), 0);
- if (flags.z())
- goto _tmp1;
- _sub(al, 3);
-_tmp1:
- ah = 0;
- bx = ax;
- al = data.byte(kTimedx);
- ah = 0;
- di = ax;
- cl = 240;
- ch = (30);
- multidump();
- data.byte(kNeedtodumptimed) = 0;
-}
-
void DreamGenContext::setuptimeduse() {
STACK_CHECK;
_cmp(data.word(kTimecount), 0);
@@ -13235,94 +11192,6 @@ void DreamGenContext::setuptimeduse() {
data.word(kTimedoffset) = bx;
}
-void DreamGenContext::setuptimedtemp() {
- STACK_CHECK;
- _cmp(ah, 0);
- if (flags.z())
- goto notloadspeech3;
- push(ax);
- push(bx);
- push(cx);
- push(dx);
- dl = 'T';
- dh = ah;
- cl = 'T';
- ah = 0;
- loadspeech();
- _cmp(data.byte(kSpeechloaded), 1);
- if (!flags.z())
- goto _tmp1;
- al = 50+12;
- playchannel1();
-_tmp1:
- dx = pop();
- cx = pop();
- bx = pop();
- ax = pop();
- _cmp(data.byte(kSpeechloaded), 1);
- if (!flags.z())
- goto notloadspeech3;
- _cmp(data.byte(kSubtitles), 1);
- if (flags.z())
- goto notloadspeech3;
- return;
-notloadspeech3:
- _cmp(data.word(kTimecount), 0);
- if (!flags.z())
- return /* (cantsetup2) */;
- data.byte(kTimedy) = bh;
- data.byte(kTimedx) = bl;
- data.word(kCounttotimed) = cx;
- _add(dx, cx);
- data.word(kTimecount) = dx;
- bl = al;
- bh = 0;
- _add(bx, bx);
- es = data.word(kTextfile1);
- cx = (66*2);
- ax = es.word(bx);
- _add(ax, cx);
- bx = ax;
- data.word(kTimedseg) = es;
- data.word(kTimedoffset) = bx;
-}
-
-void DreamGenContext::usetimedtext() {
- STACK_CHECK;
- _cmp(data.word(kTimecount), 0);
- if (flags.z())
- return /* (notext) */;
- _dec(data.word(kTimecount));
- _cmp(data.word(kTimecount), 0);
- if (flags.z())
- goto deltimedtext;
- ax = data.word(kTimecount);
- _cmp(ax, data.word(kCounttotimed));
- if (flags.z())
- goto firsttimed;
- if (!flags.c())
- return /* (notext) */;
- goto notfirsttimed;
-firsttimed:
- getundertimed();
-notfirsttimed:
- bl = data.byte(kTimedy);
- bh = 0;
- al = data.byte(kTimedx);
- ah = 0;
- di = ax;
- es = data.word(kTimedseg);
- si = data.word(kTimedoffset);
- dl = 237;
- ah = 0;
- printdirect();
- data.byte(kNeedtodumptimed) = 1;
- return;
-deltimedtext:
- putundertimed();
- data.byte(kNeedtodumptimed) = 1;
-}
-
void DreamGenContext::edenscdplayer() {
STACK_CHECK;
showfirstuse();
@@ -13781,7 +11650,7 @@ afterpress:
dumppointer();
dumpkeypad();
dumptextline();
- bx = 3482;
+ bx = offset_keypadlist;
checkcoords();
_cmp(data.byte(kGetback), 1);
if (flags.z())
@@ -14121,7 +11990,7 @@ menuloop:
dumppointer();
dumpmenu();
dumptextline();
- bx = 3614;
+ bx = offset_menulist;
checkcoords();
_cmp(data.byte(kGetback), 1);
if (!flags.z())
@@ -14234,7 +12103,7 @@ folderloop:
vsync();
dumppointer();
dumptextline();
- bx = 3636;
+ bx = offset_folderlist;
checkcoords();
_cmp(data.byte(kGetback), 0);
if (flags.z())
@@ -14278,7 +12147,7 @@ donextf:
delpointer();
showfolder();
data.word(kMousebutton) = 0;
- bx = 3636;
+ bx = offset_folderlist;
checkcoords();
worktoscreenm();
}
@@ -14365,7 +12234,7 @@ dolastf:
delpointer();
showfolder();
data.word(kMousebutton) = 0;
- bx = 3636;
+ bx = offset_folderlist;
checkcoords();
worktoscreenm();
}
@@ -14627,7 +12496,7 @@ symbolloop:
dumppointer();
dumptextline();
dumpsymbol();
- bx = 3678;
+ bx = offset_symbollist;
checkcoords();
_cmp(data.byte(kGetback), 0);
if (flags.z())
@@ -14998,7 +12867,7 @@ diaryloop:
dumppointer();
dumpdiarykeys();
dumptextline();
- bx = 3740;
+ bx = offset_diarylist;
checkcoords();
_cmp(data.byte(kGetback), 0);
if (flags.z())
@@ -15334,7 +13203,7 @@ waitops:
dumppointer();
dumptextline();
delpointer();
- bx = 3782;
+ bx = offset_opslist;
checkcoords();
_cmp(data.byte(kGetback), 0);
if (flags.z())
@@ -15424,71 +13293,6 @@ void DreamGenContext::loadsavebox() {
loadintotemp();
}
-void DreamGenContext::loadgame() {
- STACK_CHECK;
- _cmp(data.byte(kCommandtype), 246);
- if (flags.z())
- goto alreadyload;
- data.byte(kCommandtype) = 246;
- al = 41;
- commandonly();
-alreadyload:
- ax = data.word(kMousebutton);
- _cmp(ax, data.word(kOldbutton));
- if (flags.z())
- return /* (noload) */;
- _cmp(ax, 1);
- if (flags.z())
- goto doload;
- return;
-doload:
- data.byte(kLoadingorsave) = 1;
- showopbox();
- showloadops();
- data.byte(kCurrentslot) = 0;
- showslots();
- shownames();
- data.byte(kPointerframe) = 0;
- worktoscreenm();
- namestoold();
- data.byte(kGetback) = 0;
-loadops:
- _cmp(data.byte(kQuitrequested), 0);
- if (!flags.z())
- return /* (quitloaded) */;
- delpointer();
- readmouse();
- showpointer();
- vsync();
- dumppointer();
- dumptextline();
- bx = 3824;
- checkcoords();
- _cmp(data.byte(kGetback), 0);
- if (flags.z())
- goto loadops;
- _cmp(data.byte(kGetback), 2);
- if (flags.z())
- return /* (quitloaded) */;
- getridoftemp();
- dx = data;
- es = dx;
- bx = 7979;
- startloading();
- loadroomssample();
- data.byte(kRoomloaded) = 1;
- data.byte(kNewlocation) = 255;
- clearsprites();
- initman();
- initrain();
- data.word(kTextaddressx) = 13;
- data.word(kTextaddressy) = 182;
- data.byte(kTextlen) = 240;
- startup();
- worktoscreen();
- data.byte(kGetback) = 4;
-}
-
void DreamGenContext::getbacktoops() {
STACK_CHECK;
_cmp(data.byte(kCommandtype), 201);
@@ -15546,63 +13350,13 @@ discopsloop:
vsync();
dumppointer();
dumptextline();
- bx = 3866;
+ bx = offset_discopslist;
checkcoords();
_cmp(data.byte(kGetback), 0);
if (flags.z())
goto discopsloop;
}
-void DreamGenContext::savegame() {
- STACK_CHECK;
- _cmp(data.byte(kMandead), 2);
- if (!flags.z())
- goto cansaveok;
- blank();
- return;
-cansaveok:
- _cmp(data.byte(kCommandtype), 247);
- if (flags.z())
- goto alreadysave;
- data.byte(kCommandtype) = 247;
- al = 44;
- commandonly();
-alreadysave:
- ax = data.word(kMousebutton);
- _and(ax, 1);
- if (!flags.z())
- goto dosave;
- return;
-dosave:
- data.byte(kLoadingorsave) = 2;
- showopbox();
- showsaveops();
- data.byte(kCurrentslot) = 0;
- showslots();
- shownames();
- worktoscreenm();
- namestoold();
- data.word(kBufferin) = 0;
- data.word(kBufferout) = 0;
- data.byte(kGetback) = 0;
-saveops:
- _cmp(data.byte(kQuitrequested), 0);
- if (!flags.z())
- return /* (quitsavegame) */;
- delpointer();
- checkinput();
- readmouse();
- showpointer();
- vsync();
- dumppointer();
- dumptextline();
- bx = 3908;
- checkcoords();
- _cmp(data.byte(kGetback), 0);
- if (flags.z())
- goto saveops;
-}
-
void DreamGenContext::actualsave() {
STACK_CHECK;
_cmp(data.byte(kCommandtype), 222);
@@ -16129,21 +13883,6 @@ isntblank:
_stosw();
}
-void DreamGenContext::findlen() {
- STACK_CHECK;
- _dec(bx);
- _add(bx, ax);
-nextone:
- _cmp(cl, ds.byte(bx));
- if (!flags.z())
- return /* (foundlen) */;
- _dec(bx);
- _dec(ax);
- _cmp(ax, 0);
- if (!flags.z())
- goto nextone;
-}
-
void DreamGenContext::scanfornames() {
STACK_CHECK;
dx = data;
@@ -16223,7 +13962,7 @@ _tmp1:
dumppointer();
dumptextline();
delpointer();
- bx = 5057;
+ bx = offset_decidelist;
checkcoords();
_cmp(data.byte(kGetback), 0);
if (flags.z())
@@ -16267,55 +14006,6 @@ alreadynewgame:
data.byte(kGetback) = 3;
}
-void DreamGenContext::doload() {
- STACK_CHECK;
- data.byte(kLoadingorsave) = 1;
- showopbox();
- showloadops();
- data.byte(kCurrentslot) = 0;
- showslots();
- shownames();
- data.byte(kPointerframe) = 0;
- worktoscreenm();
- namestoold();
- data.byte(kGetback) = 0;
-loadops:
- _cmp(data.byte(kQuitrequested), 0);
- if (!flags.z())
- return /* (quitloaded) */;
- delpointer();
- readmouse();
- showpointer();
- vsync();
- dumppointer();
- dumptextline();
- bx = 3824;
- checkcoords();
- _cmp(data.byte(kGetback), 0);
- if (flags.z())
- goto loadops;
- _cmp(data.byte(kGetback), 2);
- if (flags.z())
- return /* (quitloaded) */;
- getridoftemp();
- dx = data;
- es = dx;
- bx = 7979;
- startloading();
- loadroomssample();
- data.byte(kRoomloaded) = 1;
- data.byte(kNewlocation) = 255;
- clearsprites();
- initman();
- initrain();
- data.word(kTextaddressx) = 13;
- data.word(kTextaddressy) = 182;
- data.byte(kTextlen) = 240;
- startup();
- worktoscreen();
- data.byte(kGetback) = 4;
-}
-
void DreamGenContext::loadold() {
STACK_CHECK;
_cmp(data.byte(kCommandtype), 252);
@@ -16329,6 +14019,7 @@ alreadyloadold:
_and(ax, 1);
if (flags.z())
return /* (noloadold) */;
+ ax = 0x0ffff;
doload();
_cmp(data.byte(kGetback), 4);
if (flags.z())
@@ -16344,7 +14035,7 @@ alreadyloadold:
void DreamGenContext::createname() {
STACK_CHECK;
push(ax);
- di = 5105;
+ di = offset_speechfile;
cs.byte(di+0) = dl;
cs.byte(di+3) = cl;
al = dh;
@@ -16511,46 +14202,6 @@ notsecondbank1:
es = pop();
}
-void DreamGenContext::makenextblock() {
- STACK_CHECK;
- volumeadjust();
- loopchannel0();
- _cmp(data.word(kCh1blockstocopy), 0);
- if (flags.z())
- goto mightbeonlych0;
- _cmp(data.word(kCh0blockstocopy), 0);
- if (flags.z())
- goto mightbeonlych1;
- _dec(data.word(kCh0blockstocopy));
- _dec(data.word(kCh1blockstocopy));
- bothchannels();
- return;
-mightbeonlych1:
- data.byte(kCh0playing) = 255;
- _cmp(data.word(kCh1blockstocopy), 0);
- if (flags.z())
- return /* (notch1only) */;
- _dec(data.word(kCh1blockstocopy));
- channel1only();
- return;
-mightbeonlych0:
- data.byte(kCh1playing) = 255;
- _cmp(data.word(kCh0blockstocopy), 0);
- if (flags.z())
- goto notch0only;
- _dec(data.word(kCh0blockstocopy));
- channel0only();
- return;
-notch0only:
- es = data.word(kSoundbuffer);
- di = data.word(kSoundbufferwrite);
- cx = 1024;
- ax = 0x7f7f;
- _stosw(cx, true);
- _and(di, 16384-1);
- data.word(kSoundbufferwrite) = di;
-}
-
void DreamGenContext::volumeadjust() {
STACK_CHECK;
al = data.byte(kVolumedirection);
@@ -16572,162 +14223,6 @@ volfinish:
data.byte(kVolumedirection) = 0;
}
-void DreamGenContext::loopchannel0() {
- STACK_CHECK;
- _cmp(data.word(kCh0blockstocopy), 0);
- if (!flags.z())
- return /* (notloop) */;
- _cmp(data.byte(kCh0repeat), 0);
- if (flags.z())
- return /* (notloop) */;
- _cmp(data.byte(kCh0repeat), 255);
- if (flags.z())
- goto endlessloop;
- _dec(data.byte(kCh0repeat));
-endlessloop:
- ax = data.word(kCh0oldemmpage);
- data.word(kCh0emmpage) = ax;
- ax = data.word(kCh0oldoffset);
- data.word(kCh0offset) = ax;
- ax = data.word(kCh0blockstocopy);
- _add(ax, data.word(kCh0oldblockstocopy));
- data.word(kCh0blockstocopy) = ax;
-}
-
-void DreamGenContext::channel0tran() {
- STACK_CHECK;
- _cmp(data.byte(kVolume), 0);
- if (!flags.z())
- goto lowvolumetran;
- cx = 1024;
- _movsw(cx, true);
- return;
-lowvolumetran:
- cx = 1024;
- bh = data.byte(kVolume);
- bl = 0;
- _add(bx, 16384-256);
-volloop:
- _lodsw();
- bl = al;
- al = es.byte(bx);
- bl = ah;
- ah = es.byte(bx);
- _stosw();
- if (--cx)
- goto volloop;
-}
-
-void DreamGenContext::domix() {
- STACK_CHECK;
- _cmp(data.byte(kVolume), 0);
- if (!flags.z())
- goto lowvolumemix;
-slow:
- _lodsb();
- ah = ds.byte(bx);
- _inc(bx);
- _cmp(al, dh);
- if (!flags.c())
- goto toplot;
- _cmp(ah, dh);
- if (!flags.c())
- goto nodistort;
- _add(al, ah);
- if (flags.s())
- goto botok;
- _xor(al, al);
- _stosb();
- if (--cx)
- goto slow;
- return /* (doneit) */;
-botok:
- _xor(al, dh);
- _stosb();
- if (--cx)
- goto slow;
- return /* (doneit) */;
-toplot:
- _cmp(ah, dh);
- if (flags.c())
- goto nodistort;
- _add(al, ah);
- if (!flags.s())
- goto topok;
- al = dl;
- _stosb();
- if (--cx)
- goto slow;
- return /* (doneit) */;
-topok:
- _xor(al, dh);
- _stosb();
- if (--cx)
- goto slow;
- return /* (doneit) */;
-nodistort:
- _add(al, ah);
- _xor(al, dh);
- _stosb();
- if (--cx)
- goto slow;
- return /* (doneit) */;
-lowvolumemix:
- _lodsb();
- push(bx);
- bh = data.byte(kVolume);
- _add(bh, 63);
- bl = al;
- al = es.byte(bx);
- bx = pop();
- ah = ds.byte(bx);
- _inc(bx);
- _cmp(al, dh);
- if (!flags.c())
- goto toplotv;
- _cmp(ah, dh);
- if (!flags.c())
- goto nodistortv;
- _add(al, ah);
- if (flags.s())
- goto botokv;
- _xor(al, al);
- _stosb();
- if (--cx)
- goto lowvolumemix;
- return /* (doneit) */;
-botokv:
- _xor(al, dh);
- _stosb();
- if (--cx)
- goto lowvolumemix;
- return /* (doneit) */;
-toplotv:
- _cmp(ah, dh);
- if (flags.c())
- goto nodistortv;
- _add(al, ah);
- if (!flags.s())
- goto topokv;
- al = dl;
- _stosb();
- if (--cx)
- goto lowvolumemix;
- return /* (doneit) */;
-topokv:
- _xor(al, dh);
- _stosb();
- if (--cx)
- goto lowvolumemix;
- return /* (doneit) */;
-nodistortv:
- _add(al, ah);
- _xor(al, dh);
- _stosb();
- if (--cx)
- goto lowvolumemix;
-}
-
void DreamGenContext::entrytexts() {
STACK_CHECK;
_cmp(data.byte(kLocation), 21);
@@ -17150,84 +14645,6 @@ void DreamGenContext::clearrest() {
deallocatemem();
}
-void DreamGenContext::parseblaster() {
- STACK_CHECK;
-lookattail:
- al = es.byte(bx);
- _cmp(al, 0);
- if (flags.z())
- return /* (endtail) */;
- _cmp(al, 13);
- if (flags.z())
- return /* (endtail) */;
- _cmp(al, 'i');
- if (flags.z())
- goto issoundint;
- _cmp(al, 'I');
- if (flags.z())
- goto issoundint;
- _cmp(al, 'b');
- if (flags.z())
- goto isbright;
- _cmp(al, 'B');
- if (flags.z())
- goto isbright;
- _cmp(al, 'a');
- if (flags.z())
- goto isbaseadd;
- _cmp(al, 'A');
- if (flags.z())
- goto isbaseadd;
- _cmp(al, 'n');
- if (flags.z())
- goto isnosound;
- _cmp(al, 'N');
- if (flags.z())
- goto isnosound;
- _cmp(al, 'd');
- if (flags.z())
- goto isdma;
- _cmp(al, 'D');
- if (flags.z())
- goto isdma;
- _inc(bx);
- if (--cx)
- goto lookattail;
- return;
-issoundint:
- al = es.byte(bx+1);
- _sub(al, '0');
- data.byte(kSoundint) = al;
- _inc(bx);
- goto lookattail;
-isdma:
- al = es.byte(bx+1);
- _sub(al, '0');
- data.byte(kSounddmachannel) = al;
- _inc(bx);
- goto lookattail;
-isbaseadd:
- push(cx);
- al = es.byte(bx+2);
- _sub(al, '0');
- ah = 0;
- cl = 4;
- _shl(ax, cl);
- _add(ax, 0x200);
- data.word(kSoundbaseadd) = ax;
- cx = pop();
- _inc(bx);
- goto lookattail;
-isbright:
- data.byte(kBrightness) = 1;
- _inc(bx);
- goto lookattail;
-isnosound:
- data.byte(kSoundint) = 255;
- _inc(bx);
- goto lookattail;
-}
-
void DreamGenContext::startup() {
STACK_CHECK;
data.byte(kCurrentkey) = 0;
@@ -17633,96 +15050,14 @@ notzeronum:
ch = 1;
}
-void DreamGenContext::walkandexamine() {
- STACK_CHECK;
- finishedwalking();
- if (!flags.z())
- return /* (noobselect) */;
- al = data.byte(kWalkexamtype);
- data.byte(kCommandtype) = al;
- al = data.byte(kWalkexamnum);
- data.byte(kCommand) = al;
- data.byte(kWalkandexam) = 0;
- _cmp(data.byte(kCommandtype), 5);
- if (flags.z())
- return /* (noobselect) */;
- examineob();
- return;
-wantstowalk:
- setwalk();
- data.byte(kReasseschanges) = 1;
- return;
-diff:
- data.byte(kCommand) = al;
- data.byte(kCommandtype) = ah;
- _cmp(data.byte(kLinepointer), 254);
- if (!flags.z())
- goto middleofwalk;
- _cmp(data.word(kWatchingtime), 0);
- if (!flags.z())
- goto middleofwalk;
- al = data.byte(kFacing);
- _cmp(al, data.byte(kTurntoface));
- if (!flags.z())
- goto middleofwalk;
- _cmp(data.byte(kCommandtype), 3);
- if (!flags.z())
- goto notblock;
- bl = data.byte(kManspath);
- _cmp(bl, data.byte(kPointerspath));
- if (!flags.z())
- goto dontcheck;
- cl = data.byte(kRyanx);
- _add(cl, 12);
- ch = data.byte(kRyany);
- _add(ch, 12);
- checkone();
- _cmp(cl, 2);
- if (flags.c())
- goto isblock;
-dontcheck:
- getflagunderp();
- _cmp(data.byte(kLastflag), 2);
- if (flags.c())
- goto isblock;
- _cmp(data.byte(kLastflag), 128);
- if (!flags.c())
- goto isblock;
- goto toofaraway;
-notblock:
- bl = data.byte(kManspath);
- _cmp(bl, data.byte(kPointerspath));
- if (!flags.z())
- goto toofaraway;
- _cmp(data.byte(kCommandtype), 3);
- if (flags.z())
- goto isblock;
- _cmp(data.byte(kCommandtype), 5);
- if (flags.z())
- goto isaperson;
- examineobtext();
- return;
-middleofwalk:
- blocknametext();
- return;
-isblock:
- blocknametext();
- return;
-isaperson:
- personnametext();
- return;
-toofaraway:
- walktotext();
-}
-
void DreamGenContext::mainscreen() {
STACK_CHECK;
data.byte(kInmaparea) = 0;
- bx = 5122;
+ bx = offset_mainlist;
_cmp(data.byte(kWatchon), 1);
if (flags.z())
goto checkmain;
- bx = 5184;
+ bx = offset_mainlist2;
checkmain:
checkcoords();
_cmp(data.byte(kWalkandexam), 0);
@@ -17762,43 +15097,6 @@ alreadyrun:
data.byte(kLastweapon) = 8;
}
-void DreamGenContext::checkcoords() {
- STACK_CHECK;
- _cmp(data.byte(kNewlocation), 255);
- if (flags.z())
- goto loop048;
- return;
-loop048:
- ax = cs.word(bx);
- _cmp(ax, 0x0ffff);
- if (flags.z())
- return /* (nonefound) */;
- push(bx);
- _cmp(data.word(kMousex), ax);
- if (flags.l())
- goto over045;
- ax = cs.word(bx+2);
- _cmp(data.word(kMousex), ax);
- if (!flags.l())
- goto over045;
- ax = cs.word(bx+4);
- _cmp(data.word(kMousey), ax);
- if (flags.l())
- goto over045;
- ax = cs.word(bx+6);
- _cmp(data.word(kMousey), ax);
- if (!flags.l())
- goto over045;
- ax = cs.word(bx+8);
- __dispatch_call(ax);
- ax = pop();
- return;
-over045:
- bx = pop();
- _add(bx, 10);
- goto loop048;
-}
-
void DreamGenContext::identifyob() {
STACK_CHECK;
_cmp(data.word(kWatchingtime), 0);
@@ -17862,69 +15160,6 @@ nothingund:
blank();
}
-void DreamGenContext::checkifperson() {
- STACK_CHECK;
- es = data.word(kBuffers);
- bx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5));
- cx = 12;
-identifyreel:
- push(cx);
- _cmp(es.byte(bx+4), 255);
- if (flags.z())
- goto notareelid;
- push(es);
- push(bx);
- push(ax);
- ax = es.word(bx+0);
- data.word(kReelpointer) = ax;
- getreelstart();
- _cmp(es.word(si+2), 0x0ffff);
- if (!flags.z())
- goto notblankpers;
- _add(si, 5);
-notblankpers:
- cx = es.word(si+2);
- ax = es.word(si+0);
- push(cx);
- getreelframeax();
- cx = pop();
- _add(cl, es.byte(bx+4));
- _add(ch, es.byte(bx+5));
- dx = cx;
- _add(dl, es.byte(bx+0));
- _add(dh, es.byte(bx+1));
- ax = pop();
- bx = pop();
- es = pop();
- _cmp(al, cl);
- if (flags.c())
- goto notareelid;
- _cmp(ah, ch);
- if (flags.c())
- goto notareelid;
- _cmp(al, dl);
- if (!flags.c())
- goto notareelid;
- _cmp(ah, dh);
- if (!flags.c())
- goto notareelid;
- cx = pop();
- ax = es.word(bx+2);
- data.word(kPersondata) = ax;
- al = es.byte(bx+4);
- ah = 5;
- obname();
- al = 0;
- _cmp(al, 1);
- return;
-notareelid:
- cx = pop();
- _add(bx, 5);
- _dec(cx);
- if (!flags.z())
- goto identifyreel;
-}
-
void DreamGenContext::checkifset() {
STACK_CHECK;
es = data.word(kBuffers);
@@ -18001,41 +15236,6 @@ notanexid:
goto identifyex;
}
-void DreamGenContext::checkiffree() {
- STACK_CHECK;
- es = data.word(kBuffers);
- bx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5))+(79*5);
- cx = 79;
-identifyfree:
- _cmp(es.byte(bx+4), 255);
- if (flags.z())
- goto notafreeid;
- _cmp(al, es.byte(bx));
- if (flags.c())
- goto notafreeid;
- _cmp(al, es.byte(bx+2));
- if (!flags.c())
- goto notafreeid;
- _cmp(ah, es.byte(bx+1));
- if (flags.c())
- goto notafreeid;
- _cmp(ah, es.byte(bx+3));
- if (!flags.c())
- goto notafreeid;
- al = es.byte(bx+4);
- ah = 2;
- obname();
- al = 0;
- _cmp(al, 1);
- return;
-notafreeid:
- _sub(bx, 5);
- _dec(cx);
- _cmp(cx, -1);
- if (!flags.z())
- goto identifyfree;
-}
-
void DreamGenContext::isitdescribed() {
STACK_CHECK;
push(ax);
@@ -18301,7 +15501,7 @@ void DreamGenContext::atmospheres() {
STACK_CHECK;
cl = data.byte(kMapx);
ch = data.byte(kMapy);
- bx = 5246;
+ bx = offset_atmospherelist;
nextatmos:
al = cs.byte(bx);
_cmp(al, 255);
@@ -18407,149 +15607,6 @@ void DreamGenContext::afterintroroom() {
data.byte(kNowinnewroom) = 0;
}
-void DreamGenContext::obname() {
- STACK_CHECK;
- _cmp(data.byte(kReasseschanges), 0);
- if (flags.z())
- goto notnewpath;
- data.byte(kReasseschanges) = 0;
- goto diff;
-notnewpath:
- _cmp(ah, data.byte(kCommandtype));
- if (flags.z())
- goto notdiffob;
- goto diff;
-notdiffob:
- _cmp(al, data.byte(kCommand));
- if (!flags.z())
- goto diff;
- _cmp(data.byte(kWalkandexam), 1);
- if (flags.z())
- goto walkandexamine;
- _cmp(data.word(kMousebutton), 0);
- if (flags.z())
- return /* (noobselect) */;
- _cmp(data.byte(kCommandtype), 3);
- if (!flags.z())
- goto isntblock;
- _cmp(data.byte(kLastflag), 2);
- if (flags.c())
- return /* (noobselect) */;
-isntblock:
- bl = data.byte(kManspath);
- _cmp(bl, data.byte(kPointerspath));
- if (!flags.z())
- goto wantstowalk;
- _cmp(data.byte(kCommandtype), 3);
- if (flags.z())
- goto wantstowalk;
- finishedwalking();
- if (!flags.z())
- return /* (noobselect) */;
- _cmp(data.byte(kCommandtype), 5);
- if (flags.z())
- goto wantstotalk;
- _cmp(data.word(kWatchingtime), 0);
- if (!flags.z())
- return /* (noobselect) */;
- examineob();
- return;
-wantstotalk:
- _cmp(data.word(kWatchingtime), 0);
- if (!flags.z())
- return /* (noobselect) */;
- talk();
- return;
-walkandexamine:
- finishedwalking();
- if (!flags.z())
- return /* (noobselect) */;
- al = data.byte(kWalkexamtype);
- data.byte(kCommandtype) = al;
- al = data.byte(kWalkexamnum);
- data.byte(kCommand) = al;
- data.byte(kWalkandexam) = 0;
- _cmp(data.byte(kCommandtype), 5);
- if (flags.z())
- return /* (noobselect) */;
- examineob();
- return;
-wantstowalk:
- setwalk();
- data.byte(kReasseschanges) = 1;
- return;
-diff:
- data.byte(kCommand) = al;
- data.byte(kCommandtype) = ah;
- _cmp(data.byte(kLinepointer), 254);
- if (!flags.z())
- goto middleofwalk;
- _cmp(data.word(kWatchingtime), 0);
- if (!flags.z())
- goto middleofwalk;
- al = data.byte(kFacing);
- _cmp(al, data.byte(kTurntoface));
- if (!flags.z())
- goto middleofwalk;
- _cmp(data.byte(kCommandtype), 3);
- if (!flags.z())
- goto notblock;
- bl = data.byte(kManspath);
- _cmp(bl, data.byte(kPointerspath));
- if (!flags.z())
- goto dontcheck;
- cl = data.byte(kRyanx);
- _add(cl, 12);
- ch = data.byte(kRyany);
- _add(ch, 12);
- checkone();
- _cmp(cl, 2);
- if (flags.c())
- goto isblock;
-dontcheck:
- getflagunderp();
- _cmp(data.byte(kLastflag), 2);
- if (flags.c())
- goto isblock;
- _cmp(data.byte(kLastflag), 128);
- if (!flags.c())
- goto isblock;
- goto toofaraway;
-notblock:
- bl = data.byte(kManspath);
- _cmp(bl, data.byte(kPointerspath));
- if (!flags.z())
- goto toofaraway;
- _cmp(data.byte(kCommandtype), 3);
- if (flags.z())
- goto isblock;
- _cmp(data.byte(kCommandtype), 5);
- if (flags.z())
- goto isaperson;
- examineobtext();
- return;
-middleofwalk:
- blocknametext();
- return;
-isblock:
- blocknametext();
- return;
-isaperson:
- personnametext();
- return;
-toofaraway:
- walktotext();
-}
-
-void DreamGenContext::finishedwalking() {
- STACK_CHECK;
- _cmp(data.byte(kLinepointer), 254);
- if (!flags.z())
- return /* (iswalking) */;
- al = data.byte(kFacing);
- _cmp(al, data.byte(kTurntoface));
-}
-
void DreamGenContext::examineobtext() {
STACK_CHECK;
bl = data.byte(kCommand);
@@ -18558,95 +15615,6 @@ void DreamGenContext::examineobtext() {
commandwithob();
}
-void DreamGenContext::commandwithob() {
- STACK_CHECK;
- push(ax);
- push(ax);
- push(bx);
- push(cx);
- push(dx);
- push(es);
- push(ds);
- push(si);
- push(di);
- deltextline();
- di = pop();
- si = pop();
- ds = pop();
- es = pop();
- dx = pop();
- cx = pop();
- bx = pop();
- ax = pop();
- push(bx);
- ah = 0;
- _add(ax, ax);
- bx = ax;
- es = data.word(kCommandtext);
- ax = es.word(bx);
- _add(ax, (66*2));
- si = ax;
- di = data.word(kTextaddressx);
- bx = data.word(kTextaddressy);
- dl = data.byte(kTextlen);
- al = 0;
- ah = 0;
- printdirect();
- ax = pop();
- di = 5847;
- copyname();
- ax = pop();
- di = data.word(kLastxpos);
- _cmp(al, 0);
- if (flags.z())
- goto noadd;
- _add(di, 5);
-noadd:
- bx = data.word(kTextaddressy);
- es = cs;
- si = 5847;
- dl = data.byte(kTextlen);
- al = 0;
- ah = 0;
- printdirect();
- data.byte(kNewtextline) = 1;
-}
-
-void DreamGenContext::commandonly() {
- STACK_CHECK;
- push(ax);
- push(bx);
- push(cx);
- push(dx);
- push(es);
- push(ds);
- push(si);
- push(di);
- deltextline();
- di = pop();
- si = pop();
- ds = pop();
- es = pop();
- dx = pop();
- cx = pop();
- bx = pop();
- ax = pop();
- ah = 0;
- _add(ax, ax);
- bx = ax;
- es = data.word(kCommandtext);
- ax = es.word(bx);
- _add(ax, (66*2));
- si = ax;
- di = data.word(kTextaddressx);
- bx = data.word(kTextaddressy);
- dl = data.byte(kTextlen);
- al = 0;
- ah = 0;
- printdirect();
- data.byte(kNewtextline) = 1;
-}
-
void DreamGenContext::printmessage() {
STACK_CHECK;
push(dx);
@@ -18696,43 +15664,6 @@ searchmess:
printdirect();
}
-void DreamGenContext::blocknametext() {
- STACK_CHECK;
- bl = data.byte(kCommand);
- bh = data.byte(kCommandtype);
- al = 0;
- commandwithob();
-}
-
-void DreamGenContext::personnametext() {
- STACK_CHECK;
- bl = data.byte(kCommand);
- _and(bl, 127);
- bh = data.byte(kCommandtype);
- al = 2;
- commandwithob();
-}
-
-void DreamGenContext::walktotext() {
- STACK_CHECK;
- bl = data.byte(kCommand);
- bh = data.byte(kCommandtype);
- al = 3;
- commandwithob();
-}
-
-void DreamGenContext::getflagunderp() {
- STACK_CHECK;
- cx = data.word(kMousex);
- _sub(cx, data.word(kMapadx));
- ax = data.word(kMousey);
- _sub(ax, data.word(kMapady));
- ch = al;
- checkone();
- data.byte(kLastflag) = cl;
- data.byte(kLastflagex) = ch;
-}
-
void DreamGenContext::setwalk() {
STACK_CHECK;
_cmp(data.byte(kLinepointer), 254);
@@ -18776,109 +15707,6 @@ holdingreel:
data.byte(kWatchmode) = 2;
}
-void DreamGenContext::autosetwalk() {
- STACK_CHECK;
- al = data.byte(kManspath);
- _cmp(data.byte(kFinaldest), al);
- if (!flags.z())
- goto notsamealready;
- return;
-notsamealready:
- getroomspaths();
- checkdest();
- push(bx);
- al = data.byte(kManspath);
- ah = 0;
- _add(ax, ax);
- _add(ax, ax);
- _add(ax, ax);
- _add(bx, ax);
- al = es.byte(bx);
- ah = 0;
- _sub(ax, 12);
- data.word(kLinestartx) = ax;
- al = es.byte(bx+1);
- ah = 0;
- _sub(ax, 12);
- data.word(kLinestarty) = ax;
- bx = pop();
- al = data.byte(kDestination);
- ah = 0;
- _add(ax, ax);
- _add(ax, ax);
- _add(ax, ax);
- _add(bx, ax);
- al = es.byte(bx);
- ah = 0;
- _sub(ax, 12);
- data.word(kLineendx) = ax;
- al = es.byte(bx+1);
- ah = 0;
- _sub(ax, 12);
- data.word(kLineendy) = ax;
- bresenhams();
- _cmp(data.byte(kLinedirection), 0);
- if (flags.z())
- goto normalline;
- al = data.byte(kLinelength);
- _dec(al);
- data.byte(kLinepointer) = al;
- data.byte(kLinedirection) = 1;
- return;
-normalline:
- data.byte(kLinepointer) = 0;
-}
-
-void DreamGenContext::checkdest() {
- STACK_CHECK;
- push(bx);
- _add(bx, 12*8);
- ah = data.byte(kManspath);
- cl = 4;
- _shl(ah, cl);
- al = data.byte(kDestination);
- cl = 24;
- ch = data.byte(kDestination);
-checkdestloop:
- dh = es.byte(bx);
- _and(dh, 0xf0);
- dl = es.byte(bx);
- _and(dl, 0xf);
- _cmp(ax, dx);
- if (!flags.z())
- goto nextcheck;
- al = es.byte(bx+1);
- _and(al, 15);
- data.byte(kDestination) = al;
- bx = pop();
- return;
-nextcheck:
- dl = es.byte(bx);
- _and(dl, 0xf0);
- _shr(dl, 1);
- _shr(dl, 1);
- _shr(dl, 1);
- _shr(dl, 1);
- dh = es.byte(bx);
- _and(dh, 0xf);
- _shl(dh, 1);
- _shl(dh, 1);
- _shl(dh, 1);
- _shl(dh, 1);
- _cmp(ax, dx);
- if (!flags.z())
- goto nextcheck2;
- ch = es.byte(bx+1);
- _and(ch, 15);
-nextcheck2:
- _add(bx, 2);
- _dec(cl);
- if (!flags.z())
- goto checkdestloop;
- data.byte(kDestination) = ch;
- bx = pop();
-}
-
void DreamGenContext::bresenhams() {
STACK_CHECK;
workoutframes();
@@ -19094,106 +15922,6 @@ success:
data.byte(kTurndirection) = 0;
}
-void DreamGenContext::getroomspaths() {
- STACK_CHECK;
- al = data.byte(kRoomnum);
- ah = 0;
- cx = 144;
- _mul(cx);
- es = data.word(kReels);
- bx = (0);
- _add(bx, ax);
-}
-
-void DreamGenContext::copyname() {
- STACK_CHECK;
- push(di);
- findobname();
- di = pop();
- es = cs;
- cx = 28;
-make:
- _lodsb();
- _cmp(al, ':');
- if (flags.z())
- goto finishmakename;
- _cmp(al, 0);
- if (flags.z())
- goto finishmakename;
- _stosb();
- if (--cx)
- goto make;
-finishmakename:
- _inc(cx);
- al = 0;
- _stosb();
- return;
- al = 255;
- _stosb(cx, true);
-}
-
-void DreamGenContext::findobname() {
- STACK_CHECK;
- push(ax);
- ah = 0;
- _add(ax, ax);
- bx = ax;
- ax = pop();
- _cmp(ah, 5);
- if (!flags.z())
- goto notpersonname;
- push(ax);
- _and(al, 127);
- ah = 0;
- bx = 64*2;
- _mul(bx);
- si = ax;
- ds = data.word(kPeople);
- _add(si, (0+24));
- cx = (0+24+(1026*2));
- ax = ds.word(si);
- _add(ax, cx);
- si = ax;
- ax = pop();
- return;
-notpersonname:
- _cmp(ah, 4);
- if (!flags.z())
- goto notextraname;
- ds = data.word(kExtras);
- _add(bx, (0+2080+30000+(16*114)));
- ax = ds.word(bx);
- _add(ax, (0+2080+30000+(16*114)+((114+2)*2)));
- si = ax;
- return;
-notextraname:
- _cmp(ah, 2);
- if (!flags.z())
- goto notfreename;
- ds = data.word(kFreedesc);
- _add(bx, (0));
- ax = ds.word(bx);
- _add(ax, (0+(82*2)));
- si = ax;
- return;
-notfreename:
- _cmp(ah, 1);
- if (!flags.z())
- goto notsetname;
- ds = data.word(kSetdesc);
- _add(bx, (0));
- ax = ds.word(bx);
- _add(ax, (0+(130*2)));
- si = ax;
- return;
-notsetname:
- ds = data.word(kBlockdesc);
- _add(bx, (0));
- ax = ds.word(bx);
- _add(ax, (0+(98*2)));
- si = ax;
-}
-
void DreamGenContext::showicon() {
STACK_CHECK;
_cmp(data.byte(kReallocation), 50);
@@ -19298,22 +16026,6 @@ void DreamGenContext::showman() {
showframe();
}
-void DreamGenContext::showpanel() {
- STACK_CHECK;
- ds = data.word(kIcons1);
- di = 72;
- bx = 0;
- al = 19;
- ah = 0;
- showframe();
- ds = data.word(kIcons1);
- di = 192;
- bx = 0;
- al = 19;
- ah = 0;
- showframe();
-}
-
void DreamGenContext::roomname() {
STACK_CHECK;
di = 88;
@@ -19430,63 +16142,6 @@ void DreamGenContext::zoomicon() {
showframe();
}
-void DreamGenContext::showblink() {
- STACK_CHECK;
- _cmp(data.byte(kManisoffscreen), 1);
- if (flags.z())
- return /* (finblink1) */;
- _inc(data.byte(kBlinkcount));
- _cmp(data.byte(kShadeson), 0);
- if (!flags.z())
- return /* (finblink1) */;
- _cmp(data.byte(kReallocation), 50);
- if (!flags.c())
- return /* (eyesshut) */;
- al = data.byte(kBlinkcount);
- _cmp(al, 3);
- if (!flags.z())
- return /* (finblink1) */;
- data.byte(kBlinkcount) = 0;
- al = data.byte(kBlinkframe);
- _inc(al);
- data.byte(kBlinkframe) = al;
- _cmp(al, 6);
- if (flags.c())
- goto nomorethan6;
- al = 6;
-nomorethan6:
- ah = 0;
- bx = 5888;
- _add(bx, ax);
- al = cs.byte(bx);
- ds = data.word(kIcons1);
- di = 44;
- bx = 32;
- ah = 0;
- showframe();
-}
-
-void DreamGenContext::dumpblink() {
- STACK_CHECK;
- _cmp(data.byte(kShadeson), 0);
- if (!flags.z())
- return /* (nodumpeye) */;
- _cmp(data.byte(kBlinkcount), 0);
- if (!flags.z())
- return /* (nodumpeye) */;
- al = data.byte(kBlinkframe);
- _cmp(al, 6);
- if (!flags.c())
- return /* (nodumpeye) */;
- push(ds);
- di = 44;
- bx = 32;
- cl = 16;
- ch = 12;
- multidump();
- ds = pop();
-}
-
void DreamGenContext::worktoscreenm() {
STACK_CHECK;
animpointer();
@@ -19622,188 +16277,6 @@ void DreamGenContext::putunderzoom() {
multiput();
}
-void DreamGenContext::crosshair() {
- STACK_CHECK;
- _cmp(data.byte(kCommandtype), 3);
- if (flags.z())
- goto nocross;
- _cmp(data.byte(kCommandtype), 10);
- if (!flags.c())
- goto nocross;
- es = data.word(kWorkspace);
- ds = data.word(kIcons1);
- di = (8)+24;
- bx = (132)+19;
- al = 9;
- ah = 0;
- showframe();
- return;
-nocross:
- es = data.word(kWorkspace);
- ds = data.word(kIcons1);
- di = (8)+24;
- bx = (132)+19;
- al = 29;
- ah = 0;
- showframe();
-}
-
-void DreamGenContext::showpointer() {
- STACK_CHECK;
- showblink();
- di = data.word(kMousex);
- data.word(kOldpointerx) = di;
- bx = data.word(kMousey);
- data.word(kOldpointery) = bx;
- _cmp(data.byte(kPickup), 1);
- if (flags.z())
- goto itsanobject;
- push(bx);
- push(di);
- ds = data.word(kIcons1);
- al = data.byte(kPointerframe);
- _add(al, 20);
- ah = 0;
- _add(ax, ax);
- si = ax;
- _add(ax, ax);
- _add(si, ax);
- cx = ds.word(si);
- _cmp(cl, 12);
- if (!flags.c())
- goto notsmallx;
- cl = 12;
-notsmallx:
- _cmp(ch, 12);
- if (!flags.c())
- goto notsmally;
- ch = 12;
-notsmally:
- data.byte(kPointerxs) = cl;
- data.byte(kPointerys) = ch;
- push(ds);
- ds = data.word(kBuffers);
- si = (0+(228*13)+32+60);
- multiget();
- ds = pop();
- di = pop();
- bx = pop();
- push(di);
- push(bx);
- al = data.byte(kPointerframe);
- _add(al, 20);
- ah = 0;
- showframe();
- bx = pop();
- di = pop();
- return;
-itsanobject:
- al = data.byte(kItemframe);
- ds = data.word(kExtras);
- _cmp(data.byte(kObjecttype), 4);
- if (flags.z())
- goto itsfrominv;
- ds = data.word(kFreeframes);
-itsfrominv:
- cl = al;
- _add(al, al);
- _add(al, cl);
- _inc(al);
- ah = 0;
- push(ax);
- _add(ax, ax);
- si = ax;
- _add(ax, ax);
- _add(si, ax);
- ax = 2080;
- cx = ds.word(si);
- _cmp(cl, 12);
- if (!flags.c())
- goto notsmallx2;
- cl = 12;
-notsmallx2:
- _cmp(ch, 12);
- if (!flags.c())
- goto notsmally2;
- ch = 12;
-notsmally2:
- data.byte(kPointerxs) = cl;
- data.byte(kPointerys) = ch;
- ax = pop();
- push(di);
- push(bx);
- push(ax);
- push(bx);
- push(di);
- push(ds);
- al = cl;
- ah = 0;
- _shr(ax, 1);
- _sub(data.word(kOldpointerx), ax);
- _sub(di, ax);
- al = ch;
- _shr(ax, 1);
- _sub(data.word(kOldpointery), ax);
- _sub(bx, ax);
- ds = data.word(kBuffers);
- si = (0+(228*13)+32+60);
- multiget();
- ds = pop();
- di = pop();
- bx = pop();
- ax = pop();
- ah = 128;
- showframe();
- bx = pop();
- di = pop();
- ds = data.word(kIcons1);
- al = 3;
- ah = 128;
- showframe();
-}
-
-void DreamGenContext::delpointer() {
- STACK_CHECK;
- ax = data.word(kOldpointerx);
- _cmp(ax, 0x0ffff);
- if (flags.z())
- return /* (nevershown) */;
- data.word(kDelherex) = ax;
- ax = data.word(kOldpointery);
- data.word(kDelherey) = ax;
- cl = data.byte(kPointerxs);
- data.byte(kDelxs) = cl;
- ch = data.byte(kPointerys);
- data.byte(kDelys) = ch;
- ds = data.word(kBuffers);
- si = (0+(228*13)+32+60);
- di = data.word(kDelherex);
- bx = data.word(kDelherey);
- multiput();
-}
-
-void DreamGenContext::dumppointer() {
- STACK_CHECK;
- dumpblink();
- cl = data.byte(kDelxs);
- ch = data.byte(kDelys);
- di = data.word(kDelherex);
- bx = data.word(kDelherey);
- multidump();
- bx = data.word(kOldpointery);
- di = data.word(kOldpointerx);
- _cmp(di, data.word(kDelherex));
- if (!flags.z())
- goto difffound;
- _cmp(bx, data.word(kDelherey));
- if (flags.z())
- return /* (notboth) */;
-difffound:
- cl = data.byte(kPointerxs);
- ch = data.byte(kPointerys);
- multidump();
-}
-
void DreamGenContext::undertextline() {
STACK_CHECK;
di = data.word(kTextaddressx);
@@ -19820,186 +16293,6 @@ _tmp1:
multiget();
}
-void DreamGenContext::deltextline() {
- STACK_CHECK;
- di = data.word(kTextaddressx);
- bx = data.word(kTextaddressy);
- _cmp(data.byte(kForeignrelease), 0);
- if (flags.z())
- goto _tmp1;
- _sub(bx, 3);
-_tmp1:
- ds = data.word(kBuffers);
- si = (0);
- cl = (228);
- ch = (13);
- multiput();
-}
-
-void DreamGenContext::dumptextline() {
- STACK_CHECK;
- _cmp(data.byte(kNewtextline), 1);
- if (!flags.z())
- return /* (nodumptextline) */;
- data.byte(kNewtextline) = 0;
- di = data.word(kTextaddressx);
- bx = data.word(kTextaddressy);
- _cmp(data.byte(kForeignrelease), 0);
- if (flags.z())
- goto _tmp1;
- _sub(bx, 3);
-_tmp1:
- cl = (228);
- ch = (13);
- multidump();
-}
-
-void DreamGenContext::animpointer() {
- STACK_CHECK;
- _cmp(data.byte(kPointermode), 2);
- if (flags.z())
- goto combathand;
- _cmp(data.byte(kPointermode), 3);
- if (flags.z())
- goto mousehand;
- _cmp(data.word(kWatchingtime), 0);
- if (flags.z())
- goto notwatchpoint;
- data.byte(kPointerframe) = 11;
- return;
-notwatchpoint:
- data.byte(kPointerframe) = 0;
- _cmp(data.byte(kInmaparea), 0);
- if (flags.z())
- return /* (gothand) */;
- _cmp(data.byte(kPointerfirstpath), 0);
- if (flags.z())
- return /* (gothand) */;
- getflagunderp();
- _cmp(cl, 2);
- if (flags.c())
- return /* (gothand) */;
- _cmp(cl, 128);
- if (!flags.c())
- return /* (gothand) */;
- data.byte(kPointerframe) = 3;
- _test(cl, 4);
- if (!flags.z())
- return /* (gothand) */;
- data.byte(kPointerframe) = 4;
- _test(cl, 16);
- if (!flags.z())
- return /* (gothand) */;
- data.byte(kPointerframe) = 5;
- _test(cl, 2);
- if (!flags.z())
- return /* (gothand) */;
- data.byte(kPointerframe) = 6;
- _test(cl, 8);
- if (!flags.z())
- return /* (gothand) */;
- data.byte(kPointerframe) = 8;
- return;
-mousehand:
- _cmp(data.byte(kPointerspeed), 0);
- if (flags.z())
- goto rightspeed3;
- _dec(data.byte(kPointerspeed));
- goto finflashmouse;
-rightspeed3:
- data.byte(kPointerspeed) = 5;
- _inc(data.byte(kPointercount));
- _cmp(data.byte(kPointercount), 16);
- if (!flags.z())
- goto finflashmouse;
- data.byte(kPointercount) = 0;
-finflashmouse:
- al = data.byte(kPointercount);
- ah = 0;
- bx = 5895;
- _add(bx, ax);
- al = cs.byte(bx);
- data.byte(kPointerframe) = al;
- return;
-combathand:
- data.byte(kPointerframe) = 0;
- _cmp(data.byte(kReallocation), 14);
- if (!flags.z())
- return /* (notarrow) */;
- _cmp(data.byte(kCommandtype), 211);
- if (!flags.z())
- return /* (notarrow) */;
- data.byte(kPointerframe) = 5;
-}
-
-void DreamGenContext::readmouse() {
- STACK_CHECK;
- ax = data.word(kMousebutton);
- data.word(kOldbutton) = ax;
- ax = data.word(kMousex);
- data.word(kOldx) = ax;
- ax = data.word(kMousey);
- data.word(kOldy) = ax;
- mousecall();
- data.word(kMousex) = cx;
- data.word(kMousey) = dx;
- data.word(kMousebutton) = bx;
-}
-
-void DreamGenContext::readmouse1() {
- STACK_CHECK;
- ax = data.word(kMousex);
- data.word(kOldx) = ax;
- ax = data.word(kMousey);
- data.word(kOldy) = ax;
- mousecall();
- data.word(kMousex) = cx;
- data.word(kMousey) = dx;
- data.word(kMousebutton1) = bx;
-}
-
-void DreamGenContext::readmouse2() {
- STACK_CHECK;
- ax = data.word(kMousex);
- data.word(kOldx) = ax;
- ax = data.word(kMousey);
- data.word(kOldy) = ax;
- mousecall();
- data.word(kMousex) = cx;
- data.word(kMousey) = dx;
- data.word(kMousebutton2) = bx;
-}
-
-void DreamGenContext::readmouse3() {
- STACK_CHECK;
- ax = data.word(kMousex);
- data.word(kOldx) = ax;
- ax = data.word(kMousey);
- data.word(kOldy) = ax;
- mousecall();
- data.word(kMousex) = cx;
- data.word(kMousey) = dx;
- data.word(kMousebutton3) = bx;
-}
-
-void DreamGenContext::readmouse4() {
- STACK_CHECK;
- ax = data.word(kMousebutton);
- data.word(kOldbutton) = ax;
- ax = data.word(kMousex);
- data.word(kOldx) = ax;
- ax = data.word(kMousey);
- data.word(kOldy) = ax;
- mousecall();
- data.word(kMousex) = cx;
- data.word(kMousey) = dx;
- ax = data.word(kMousebutton1);
- _or(ax, data.word(kMousebutton2));
- _or(ax, data.word(kMousebutton3));
- _or(bx, ax);
- data.word(kMousebutton) = bx;
-}
-
void DreamGenContext::readkey() {
STACK_CHECK;
bx = data.word(kBufferout);
@@ -20009,7 +16302,7 @@ void DreamGenContext::readkey() {
_inc(bx);
_and(bx, 15);
data.word(kBufferout) = bx;
- di = 5912;
+ di = offset_keybuffer;
_add(di, bx);
al = cs.byte(di);
data.byte(kCurrentkey) = al;
@@ -20333,142 +16626,6 @@ blimey:
es = pop();
}
-void DreamGenContext::startloading() {
- STACK_CHECK;
- data.byte(kCombatcount) = 0;
- al = cs.byte(bx+13);
- data.byte(kRoomssample) = al;
- al = cs.byte(bx+15);
- data.byte(kMapx) = al;
- al = cs.byte(bx+16);
- data.byte(kMapy) = al;
- al = cs.byte(bx+20);
- data.byte(kLiftflag) = al;
- al = cs.byte(bx+21);
- data.byte(kManspath) = al;
- data.byte(kDestination) = al;
- data.byte(kFinaldest) = al;
- al = cs.byte(bx+22);
- data.byte(kFacing) = al;
- data.byte(kTurntoface) = al;
- al = cs.byte(bx+23);
- data.byte(kCounttoopen) = al;
- al = cs.byte(bx+24);
- data.byte(kLiftpath) = al;
- al = cs.byte(bx+25);
- data.byte(kDoorpath) = al;
- data.byte(kLastweapon) = -1;
- al = cs.byte(bx+27);
- push(ax);
- al = cs.byte(bx+31);
- ah = data.byte(kReallocation);
- data.byte(kReallocation) = al;
- dx = bx;
- openfile();
- readheader();
- allocateload();
- ds = ax;
- data.word(kBackdrop) = ax;
- dx = (0);
- loadseg();
- ds = data.word(kWorkspace);
- dx = (0);
- cx = 132*66;
- al = 0;
- fillspace();
- loadseg();
- sortoutmap();
- allocateload();
- data.word(kSetframes) = ax;
- ds = ax;
- dx = (0);
- loadseg();
- ds = data.word(kSetdat);
- dx = 0;
- cx = (64*128);
- al = 255;
- fillspace();
- loadseg();
- allocateload();
- data.word(kReel1) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- allocateload();
- data.word(kReel2) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- allocateload();
- data.word(kReel3) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- allocateload();
- data.word(kReels) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- allocateload();
- data.word(kPeople) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- allocateload();
- data.word(kSetdesc) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- allocateload();
- data.word(kBlockdesc) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- allocateload();
- data.word(kRoomdesc) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- allocateload();
- data.word(kFreeframes) = ax;
- ds = ax;
- dx = 0;
- loadseg();
- ds = data.word(kFreedat);
- dx = 0;
- cx = (16*80);
- al = 255;
- fillspace();
- loadseg();
- allocateload();
- data.word(kFreedesc) = ax;
- ds = ax;
- dx = (0);
- loadseg();
- closefile();
- findroominloc();
- deletetaken();
- setallchanges();
- autoappear();
- al = data.byte(kNewlocation);
- getroomdata();
- data.byte(kLastweapon) = -1;
- data.byte(kMandead) = 0;
- data.word(kLookcounter) = 160;
- data.byte(kNewlocation) = 255;
- data.byte(kLinepointer) = 254;
- ax = pop();
- _cmp(al, 255);
- if (flags.z())
- goto dontwalkin;
- data.byte(kManspath) = al;
- push(bx);
- autosetwalk();
- bx = pop();
-dontwalkin:
- findxyfrompath();
-}
-
void DreamGenContext::disablepath() {
STACK_CHECK;
push(cx);
@@ -20503,22 +16660,6 @@ lookx2:
es.byte(bx+6) = al;
}
-void DreamGenContext::findxyfrompath() {
- STACK_CHECK;
- getroomspaths();
- al = data.byte(kManspath);
- ah = 0;
- _add(ax, ax);
- _add(ax, ax);
- _add(ax, ax);
- _add(bx, ax);
- ax = es.word(bx);
- _sub(al, 12);
- _sub(ah, 12);
- data.byte(kRyanx) = al;
- data.byte(kRyany) = ah;
-}
-
void DreamGenContext::findroominloc() {
STACK_CHECK;
al = data.byte(kMapy);
@@ -20538,25 +16679,6 @@ lookx:
data.byte(kRoomnum) = cl;
}
-void DreamGenContext::getroomdata() {
- STACK_CHECK;
- ah = 0;
- cx = 32;
- _mul(cx);
- bx = 6187;
- _add(bx, ax);
-}
-
-void DreamGenContext::readheader() {
- STACK_CHECK;
- ds = cs;
- dx = 6091;
- cx = (6187-6091);
- readfromfile();
- es = cs;
- di = 6141;
-}
-
void DreamGenContext::allocateload() {
STACK_CHECK;
push(es);
@@ -20569,23 +16691,6 @@ void DreamGenContext::allocateload() {
es = pop();
}
-void DreamGenContext::fillspace() {
- STACK_CHECK;
- push(es);
- push(ds);
- push(dx);
- push(di);
- push(bx);
- di = dx;
- es = ds;
- _stosb(cx, true);
- bx = pop();
- di = pop();
- dx = pop();
- ds = pop();
- es = pop();
-}
-
void DreamGenContext::getridoftemp() {
STACK_CHECK;
es = data.word(kTempgraphics);
@@ -20656,723 +16761,1142 @@ void DreamGenContext::readsetdata() {
closefile();
}
-void DreamGenContext::makename() {
- STACK_CHECK;
- si = dx;
- di = 6061;
-transfer:
- al = cs.byte(si);
- cs.byte(di) = al;
- _inc(si);
- _inc(di);
- _cmp(al, 0);
- if (!flags.z())
- goto transfer;
- dx = 6059;
-}
-
-void DreamGenContext::dreamweb() {
- STACK_CHECK;
- seecommandtail();
- checkbasemem();
- soundstartup();
- setkeyboardint();
- setupemm();
- allocatebuffers();
- setmouse();
- fadedos();
- gettime();
- clearbuffers();
- clearpalette();
- set16colpalette();
- readsetdata();
- data.byte(kWongame) = 0;
- dx = 1909;
- loadsample();
- setsoundoff();
- scanfornames();
- _cmp(al, 0);
- if (!flags.z())
- goto dodecisions;
- setmode();
- loadpalfromiff();
- titles();
- credits();
- goto playgame;
-dodecisions:
- cls();
- setmode();
- decide();
- _cmp(data.byte(kQuitrequested), 0);
- if (!flags.z())
- return /* (exitgame) */;
- _cmp(data.byte(kGetback), 4);
- if (flags.z())
- goto mainloop;
- titles();
- _cmp(data.byte(kQuitrequested), 0);
- if (!flags.z())
- return /* (exitgame) */;
- credits();
-playgame:
- _cmp(data.byte(kQuitrequested), 0);
- if (!flags.z())
- return /* (exitgame) */;
- clearchanges();
- setmode();
- loadpalfromiff();
- data.byte(kLocation) = 255;
- data.byte(kRoomafterdream) = 1;
- data.byte(kNewlocation) = 35;
- data.byte(kVolume) = 7;
- loadroom();
- clearsprites();
- initman();
- entrytexts();
- entryanims();
- data.byte(kDestpos) = 3;
- initialinv();
- data.byte(kLastflag) = 32;
- startup1();
- data.byte(kVolumeto) = 0;
- data.byte(kVolumedirection) = -1;
- data.byte(kCommandtype) = 255;
- goto mainloop;
-loadnew:
- clearbeforeload();
- loadroom();
- clearsprites();
- initman();
- entrytexts();
- entryanims();
- data.byte(kNewlocation) = 255;
- startup();
- data.byte(kCommandtype) = 255;
- worktoscreenm();
- goto mainloop;
- data.byte(kNewlocation) = 255;
- clearsprites();
- initman();
- startup();
- data.byte(kCommandtype) = 255;
-mainloop:
- _cmp(data.byte(kQuitrequested), 0);
- if (!flags.z())
- return /* (exitgame) */;
- screenupdate();
- _cmp(data.byte(kWongame), 0);
- if (!flags.z())
- goto endofgame;
- _cmp(data.byte(kMandead), 1);
- if (flags.z())
- goto gameover;
- _cmp(data.byte(kMandead), 2);
- if (flags.z())
- goto gameover;
- _cmp(data.word(kWatchingtime), 0);
- if (flags.z())
- goto notwatching;
- al = data.byte(kFinaldest);
- _cmp(al, data.byte(kManspath));
- if (!flags.z())
- goto mainloop;
- _dec(data.word(kWatchingtime));
- if (!flags.z())
- goto mainloop;
-notwatching:
- _cmp(data.byte(kMandead), 4);
- if (flags.z())
- goto gameover;
- _cmp(data.byte(kNewlocation), 255);
- if (!flags.z())
- goto loadnew;
- goto mainloop;
-gameover:
- clearbeforeload();
- showgun();
- fadescreendown();
- cx = 100;
- hangon();
- goto dodecisions;
-endofgame:
- clearbeforeload();
- fadescreendowns();
- cx = 200;
- hangon();
- endgame();
- { quickquit2(); return; };
-}
-
void DreamGenContext::__start() {
static const uint8 src[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0000: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x0010: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0020: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0xff, 0x00,
+ //0x0030: .... .... .... ....
0xff, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0xb6,
+ //0x0040: ...0 .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0050: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0060: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0070: .... ...h .&.. ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0080: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0090: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x00a0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
+ //0x00b0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x00c0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x00d0: .... .... .... ....
0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x00e0: .. .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x00f0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0100: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0110: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0120: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0130: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0140: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0150: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+ //0x0160: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ //0x0170: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0180: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0190: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ //0x01a0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x01b0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x01c0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x01d0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x01e0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x01f0: .... .... .... ....
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x0200: .... .... .... ....
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x14, 0x00, 0x02, 0x00, 0x01, 0x01, 0x37,
+ //0x0210: .... ..., .... ...7
0x00, 0x00, 0x00, 0x32, 0x14, 0x00, 0x18, 0x16, 0x00, 0x4a, 0x00, 0x01, 0x00, 0x00, 0x18, 0x21,
+ //0x0220: ...2 .... .J.. ...!
0x0a, 0x4b, 0x00, 0x01, 0x00, 0x01, 0x01, 0x2c, 0x00, 0x1b, 0x00, 0x02, 0x00, 0x02, 0x01, 0x2c,
+ //0x0230: .K.. ..., .... ...,
0x00, 0x60, 0x00, 0x03, 0x00, 0x04, 0x01, 0x2c, 0x00, 0x76, 0x00, 0x02, 0x00, 0x05, 0x01, 0x2c,
+ //0x0240: .`.. ..., .v.. ...,
0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x16, 0x14, 0x35, 0x00, 0x03, 0x00, 0x00, 0x05, 0x16,
+ //0x0250: .... .... .5.. ....
0x14, 0x28, 0x00, 0x01, 0x00, 0x02, 0x05, 0x16, 0x14, 0x32, 0x00, 0x01, 0x00, 0x03, 0x02, 0x0b,
+ //0x0260: .(.. .... .2.. ....
0x0a, 0xc0, 0x00, 0x01, 0x00, 0x00, 0x02, 0x0b, 0x0a, 0xb6, 0x00, 0x02, 0x00, 0x01, 0x08, 0x0b,
+ //0x0270: .... .... .... ....
0x0a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x17, 0x00, 0x32, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1c, 0x0b,
+ //0x0280: .... .... 2... ....
0x14, 0xfa, 0x00, 0x04, 0x00, 0x00, 0x17, 0x00, 0x32, 0x2b, 0x00, 0x02, 0x00, 0x08, 0x17, 0x0b,
+ //0x0290: .... .... 2+.. ....
0x28, 0x82, 0x00, 0x02, 0x00, 0x01, 0x17, 0x16, 0x28, 0x7a, 0x00, 0x02, 0x00, 0x02, 0x17, 0x16,
+ //0x02a0: (... .... (z.. ....
0x28, 0x69, 0x00, 0x02, 0x00, 0x03, 0x17, 0x16, 0x28, 0x51, 0x00, 0x02, 0x00, 0x04, 0x17, 0x0b,
+ //0x02b0: (i.. .... (Q.. ....
0x28, 0x87, 0x00, 0x02, 0x00, 0x05, 0x17, 0x16, 0x28, 0x91, 0x00, 0x02, 0x00, 0x06, 0x04, 0x16,
+ //0x02c0: (... .... (... ....
0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x2d, 0x16, 0x1e, 0xc8, 0x00, 0x00, 0x00, 0x14, 0x2d, 0x16,
+ //0x02d0: .... ..-. .... ..-.
0x1e, 0x27, 0x00, 0x02, 0x00, 0x00, 0x2d, 0x16, 0x1e, 0x19, 0x00, 0x02, 0x00, 0x00, 0x08, 0x16,
+ //0x02e0: .'.. ..-. .... ....
0x28, 0x20, 0x00, 0x02, 0x00, 0x00, 0x07, 0x0b, 0x14, 0x40, 0x00, 0x02, 0x00, 0x00, 0x16, 0x16,
+ //0x02f0: ( .. .... .@.. ....
0x14, 0x52, 0x00, 0x02, 0x00, 0x00, 0x1b, 0x0b, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x14, 0x00,
+ //0x0300: .R.. .... .... ....
0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0e, 0x21, 0x28, 0x15, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x0b,
+ //0x0310: .... ...! (... ....
0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x16, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
+ //0x0320: .... .... .... ....
0x32, 0x04, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x1e, 0x79, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16,
+ //0x0330: 2... ..2. .y.. ..2.
0x1e, 0x00, 0x00, 0x14, 0x00, 0x00, 0x34, 0x16, 0x1e, 0xc0, 0x00, 0x02, 0x00, 0x00, 0x34, 0x16,
+ //0x0340: .... ..4. .... ..4.
0x1e, 0xe9, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x28, 0x68, 0x00, 0x37, 0x00, 0x00, 0x35, 0x21,
+ //0x0350: .... ..2. (h.7 ..5!
0x00, 0x63, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x28, 0x00, 0x00, 0x03, 0x00, 0x00, 0x32, 0x16,
+ //0x0360: .c.. ..2. (... ..2.
0x1e, 0xa2, 0x00, 0x02, 0x00, 0x00, 0x34, 0x16, 0x1e, 0x39, 0x00, 0x02, 0x00, 0x00, 0x34, 0x16,
+ //0x0370: .... ..4. .9.. ..4.
0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x48, 0x00, 0x03, 0x00, 0x00, 0x37, 0x2c,
+ //0x0380: .... ..6. .H.. ..7,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x0e, 0x16,
+ //0x0390: .... .... .... ....
0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x0e, 0x16, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x00, 0x0a, 0x16,
+ //0x03a0: .... .... .,.. ....
0x1e, 0xae, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x16, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0b,
+ //0x03b0: .... .... .... ....
0x14, 0x00, 0x00, 0x32, 0x14, 0x00, 0x0b, 0x0b, 0x1e, 0x00, 0x00, 0x32, 0x14, 0x00, 0x0b, 0x16,
+ //0x03c0: ...2 .... ...2 ....
0x14, 0x00, 0x00, 0x32, 0x14, 0x00, 0x0e, 0x21, 0x28, 0x00, 0x00, 0x32, 0x14, 0x00, 0xff, 0x7c,
+ //0x03d0: ...2 ...! (..2 ...|
0xc0, 0x80, 0xc0, 0x1c, 0xc0, 0x20, 0xc0, 0x00, 0xc1, 0x10, 0xc0, 0x18, 0xc0, 0xf4, 0xc0, 0x0c,
+ //0x03e0: .... . .. .... ....
0xc0, 0x24, 0xc0, 0x28, 0xc0, 0x2c, 0xc0, 0x30, 0xc0, 0x54, 0xc0, 0x78, 0xc0, 0x50, 0xc0, 0x74,
+ //0x03f0: .$.( .,.0 .T.x .P.t
0xc0, 0x34, 0xc0, 0x38, 0xc0, 0x40, 0xc0, 0x44, 0xc0, 0x48, 0xc0, 0x3c, 0xc0, 0x14, 0xc0, 0x88,
+ //0x0400: .4.8 .@.D .H.< ....
0xc0, 0x8c, 0xc0, 0x90, 0xc0, 0x70, 0xc0, 0xfc, 0xc0, 0x6c, 0xc0, 0x58, 0xc0, 0x68, 0xc0, 0x04,
+ //0x0410: .... .p.. .l.X .h..
0xc1, 0x64, 0xc0, 0x60, 0xc0, 0x5c, 0xc0, 0x94, 0xc0, 0x04, 0xc0, 0xa4, 0xc0, 0x9c, 0xc0, 0xa0,
+ //0x0420: .d.` .... .... ....
0xc0, 0xa8, 0xc0, 0xac, 0xc0, 0x98, 0xc0, 0xb0, 0xc0, 0xb4, 0xc0, 0xc8, 0xc0, 0xcc, 0xc0, 0xd4,
+ //0x0430: .... .... .... ....
0xc0, 0xdc, 0xc0, 0xd8, 0xc0, 0x00, 0xc0, 0x08, 0xc0, 0x84, 0xc0, 0x84, 0xc0, 0x84, 0xc0, 0x84,
+ //0x0440: .... .... .... ....
0xc0, 0x00, 0x3c, 0x21, 0x47, 0x0b, 0x52, 0x16, 0x5d, 0x01, 0x2c, 0x0a, 0x10, 0x04, 0x0b, 0x1e,
+ //0x0450: ..<! G.R. ].,. ....
0x0e, 0x04, 0x16, 0x1e, 0x0e, 0x03, 0x21, 0x0a, 0x0e, 0x0a, 0x21, 0x1e, 0x0e, 0x0a, 0x16, 0x1e,
+ //0x0460: .... ..!. ..!. ....
0x18, 0x09, 0x16, 0x0a, 0x0e, 0x02, 0x21, 0x00, 0x0e, 0x02, 0x16, 0x00, 0x0e, 0x06, 0x0b, 0x1e,
+ //0x0470: .... ..!. .... ....
0x0e, 0x07, 0x0b, 0x14, 0x12, 0x07, 0x00, 0x14, 0x12, 0x07, 0x00, 0x1e, 0x12, 0x37, 0x2c, 0x00,
+ //0x0480: .... .... .... .7,.
0x0e, 0x05, 0x16, 0x1e, 0x0e, 0x08, 0x00, 0x0a, 0x12, 0x08, 0x0b, 0x0a, 0x12, 0x08, 0x16, 0x0a,
+ //0x0490: .... .... .... ....
0x12, 0x08, 0x21, 0x0a, 0x12, 0x08, 0x21, 0x14, 0x12, 0x08, 0x21, 0x1e, 0x12, 0x08, 0x21, 0x28,
+ //0x04a0: ..!. ..!. ..!. ..!(
0x12, 0x08, 0x16, 0x28, 0x12, 0x08, 0x0b, 0x28, 0x12, 0x15, 0x2c, 0x14, 0x12, 0xff, 0x2e, 0x05,
+ //0x04b0: ...( ...( ..,. ....
0x2f, 0x05, 0x33, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x46, 0x05, 0x2e, 0x05, 0x4d, 0x05,
+ //0x04c0: /.3. .... ..F. ..M.
0x5d, 0x05, 0x64, 0x05, 0x68, 0x05, 0x6c, 0x05, 0x70, 0x05, 0x7d, 0x05, 0x2e, 0x05, 0x2e, 0x05,
+ //0x04d0: ].d. h.l. p.}. ....
0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x9f, 0x05, 0x2e, 0x05, 0xb5, 0x05, 0xd4, 0x05, 0x2e, 0x05,
+ //0x04e0: .... .... .... ....
0xe1, 0x05, 0xf7, 0x05, 0x0d, 0x06, 0x26, 0x06, 0x39, 0x06, 0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05,
+ //0x04f0: .... ..&. 9... ....
0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05,
+ //0x0500: .... .... .... ....
0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x49, 0x06, 0x50, 0x06, 0x75, 0x06, 0x2e, 0x05,
+ //0x0510: .... .... I.P. u...
0x2e, 0x05, 0x2e, 0x05, 0x2e, 0x05, 0x82, 0x06, 0x86, 0x06, 0x2e, 0x05, 0x8d, 0x06, 0xff, 0x0f,
+ //0x0520: .... .... .... ....
0x01, 0x01, 0xff, 0x0c, 0x05, 0x00, 0x0d, 0x15, 0x00, 0x0f, 0x23, 0x00, 0x11, 0x32, 0x00, 0x12,
+ //0x0530: .... .... ..#. .2..
0x67, 0x00, 0x13, 0x6c, 0x00, 0xff, 0x12, 0x13, 0x00, 0x13, 0x17, 0x00, 0xff, 0x0c, 0x33, 0x00,
+ //0x0540: g..l .... .... ..3.
0x0d, 0x35, 0x00, 0x0e, 0x0e, 0x00, 0x0f, 0x14, 0x00, 0x00, 0x4e, 0x00, 0xff, 0x0c, 0x77, 0x00,
+ //0x0550: .5.. .... ..N. ..w.
0x0c, 0x91, 0x00, 0xff, 0x0d, 0x10, 0x00, 0xff, 0x0d, 0x14, 0x00, 0xff, 0x0e, 0x10, 0x00, 0xff,
+ //0x0560: .... .... .... ....
0x0f, 0x04, 0x00, 0x10, 0x08, 0x00, 0x11, 0x86, 0x00, 0x12, 0x99, 0x00, 0xff, 0x0d, 0x6c, 0x00,
+ //0x0570: .... .... .... ..l.
0x0f, 0x46, 0x01, 0x0f, 0x4b, 0x01, 0x0f, 0x50, 0x01, 0x0f, 0x56, 0x01, 0x0f, 0x5c, 0x01, 0x0f,
+ //0x0580: .F.. K..P ..V. ....
0x62, 0x01, 0x12, 0x9f, 0x00, 0x12, 0xb2, 0x00, 0x93, 0xd9, 0x00, 0x54, 0xe4, 0x00, 0xff, 0x0d,
+ //0x0590: b... .... ...T ....
0x14, 0x00, 0x0d, 0x15, 0x00, 0x0f, 0x22, 0x00, 0x0d, 0x34, 0x00, 0x0d, 0x37, 0x00, 0x19, 0x39,
+ //0x05a0: .... ..". .4.. 7..9
0x00, 0x15, 0x49, 0x00, 0xff, 0x0d, 0xc4, 0x00, 0x0d, 0xea, 0x00, 0x0d, 0x9c, 0x00, 0x0e, 0x81,
+ //0x05b0: ..I. .... .... ....
0x00, 0x0d, 0x7c, 0x00, 0x0f, 0xa2, 0x00, 0x0f, 0xc8, 0x00, 0x0f, 0xef, 0x00, 0x11, 0x63, 0x00,
+ //0x05c0: ..|. .... .... ..c.
0x0c, 0x34, 0x00, 0xff, 0x0f, 0x38, 0x00, 0x10, 0x40, 0x00, 0x13, 0x16, 0x00, 0x14, 0x21, 0x00,
+ //0x05d0: .4.. .8.. @... ..!.
0xff, 0x14, 0x0b, 0x00, 0x14, 0x0f, 0x00, 0x0f, 0x1c, 0x00, 0x0d, 0x50, 0x00, 0x15, 0x52, 0x00,
+ //0x05e0: .... .... ...P ..R.
0x93, 0x57, 0x00, 0x57, 0x80, 0x00, 0xff, 0x0c, 0x0d, 0x00, 0x0e, 0x27, 0x00, 0x0c, 0x43, 0x00,
+ //0x05f0: .W.W .... ...' ..C.
0x0c, 0x4b, 0x00, 0x0c, 0x53, 0x00, 0x0c, 0x5b, 0x00, 0x0f, 0x66, 0x00, 0xff, 0x16, 0x24, 0x00,
+ //0x0600: .K.. S..[ ..f. ..$.
0x0d, 0x7d, 0x00, 0x12, 0x58, 0x00, 0x0f, 0x6b, 0x00, 0x0e, 0x7f, 0x00, 0x0e, 0x9a, 0x00, 0x93,
+ //0x0610: .}.. X..k .... ....
0xaa, 0x00, 0x57, 0xe8, 0x00, 0xff, 0x15, 0x10, 0x00, 0x15, 0x48, 0x00, 0x15, 0xcd, 0x00, 0x16,
+ //0x0620: ..W. .... ..H. ....
0x3f, 0x00, 0x97, 0x63, 0x00, 0x58, 0x9e, 0x00, 0xff, 0x0d, 0x15, 0x00, 0x0e, 0x18, 0x00, 0x93,
+ //0x0630: ?..c .X.. .... ....
0x32, 0x00, 0x57, 0x4b, 0x00, 0x18, 0x80, 0x00, 0xff, 0x53, 0x2e, 0x00, 0x10, 0xa7, 0x00, 0xff,
+ //0x0640: 2.WK .... .S.. ....
0x10, 0x13, 0x00, 0x0e, 0x24, 0x00, 0x10, 0x32, 0x00, 0x0e, 0x41, 0x00, 0x10, 0x51, 0x00, 0x0e,
+ //0x0650: .... $..2 ..A. .Q..
0x60, 0x00, 0x10, 0x72, 0x00, 0x0e, 0x81, 0x00, 0x10, 0x93, 0x00, 0x0e, 0xa2, 0x00, 0x10, 0xb1,
+ //0x0660: `..r .... .... ....
0x00, 0x0e, 0xbf, 0x00, 0xff, 0x0d, 0x30, 0x00, 0x0e, 0x29, 0x00, 0x0f, 0x4e, 0x00, 0x10, 0x5c,
+ //0x0670: .... ..0. .).. N...
0x00, 0xff, 0x10, 0x73, 0x00, 0xff, 0x15, 0x67, 0x00, 0x14, 0xc7, 0x00, 0xff, 0x11, 0x35, 0x00,
+ //0x0680: ...s ...g .... ..5.
0x11, 0x36, 0x00, 0x11, 0x37, 0x00, 0x11, 0x38, 0x00, 0x11, 0x39, 0x00, 0x11, 0x3a, 0x00, 0x11,
+ //0x0690: .6.. 7..8 ..9. .:..
0x3b, 0x00, 0x11, 0x3d, 0x00, 0x11, 0x3f, 0x00, 0x11, 0x40, 0x00, 0x11, 0x41, 0x00, 0xff, 0x9c,
+ //0x06a0: ;..= ..?. .@.. A...
0x9a, 0x9f, 0x9a, 0x9c, 0x9e, 0xa0, 0x9b, 0x9d, 0x99, 0x9f, 0x9e, 0x9c, 0x9a, 0x9f, 0x9a, 0x9c,
+ //0x06b0: .... .... .... ....
0x9e, 0xa0, 0x9b, 0x9d, 0x99, 0x9f, 0x9e, 0x9c, 0x9a, 0x9f, 0x9a, 0x9c, 0x9e, 0xa0, 0x9b, 0x9d,
+ //0x06c0: .... .... .... ....
0x99, 0x9f, 0x9e, 0x9c, 0x9a, 0x9f, 0x9a, 0x9c, 0x9e, 0xa0, 0x9b, 0x9d, 0x99, 0x9f, 0x9e, 0x9c,
+ //0x06d0: .... .... .... ....
0x9a, 0x9f, 0x9a, 0x9c, 0x9e, 0xa0, 0x9b, 0x9d, 0x99, 0x9f, 0x9e, 0x9c, 0x9a, 0x9f, 0x9a, 0x9c,
+ //0x06e0: .... .... .... ....
0x9e, 0xa0, 0x9b, 0x9d, 0x99, 0x9f, 0x9e, 0x9c, 0x9a, 0x9f, 0x9a, 0x9c, 0x9e, 0xa0, 0x9b, 0x9d,
+ //0x06f0: .... .... .... ....
0x99, 0x9f, 0x9e, 0x9c, 0x9a, 0x9f, 0x9a, 0x9c, 0x9e, 0xa0, 0x9b, 0x9d, 0x99, 0x9f, 0x9e, 0x9c,
+ //0x0700: .... .... .... ....
0x9a, 0x9f, 0x9a, 0x9c, 0x9e, 0xa0, 0x9b, 0x9d, 0x99, 0x9f, 0x9c, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x0710: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x53, 0x30, 0x30, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42,
+ //0x0720: WEB. S00. DREA MWEB
0x2e, 0x53, 0x30, 0x32, 0x00, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x2e, 0x44, 0x41, 0x54,
+ //0x0730: .S02 .INS TALL .DAT
0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x43, 0x30, 0x30, 0x00, 0x44, 0x52,
+ //0x0740: .DRE AMWE B.C0 0.DR
0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x43, 0x30, 0x31, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x0750: EAMW EB.C 01.D REAM
0x57, 0x45, 0x42, 0x2e, 0x43, 0x30, 0x32, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42,
+ //0x0760: WEB. C02. DREA MWEB
0x2e, 0x56, 0x30, 0x30, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x56, 0x39,
+ //0x0770: .V00 .DRE AMWE B.V9
0x39, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x30, 0x30, 0x00, 0x44,
+ //0x0780: 9.DR EAMW EB.G 00.D
0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x30, 0x31, 0x00, 0x44, 0x52, 0x45, 0x41,
+ //0x0790: REAM WEB. G01. DREA
0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x30, 0x32, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45,
+ //0x07a0: MWEB .G02 .DRE AMWE
0x42, 0x2e, 0x47, 0x30, 0x38, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47,
+ //0x07b0: B.G0 8.DR EAMW EB.G
0x30, 0x33, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x30, 0x37, 0x00,
+ //0x07c0: 03.D REAM WEB. G07.
0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x30, 0x34, 0x00, 0x44, 0x52, 0x45,
+ //0x07d0: DREA MWEB .G04 .DRE
0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x30, 0x35, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57,
+ //0x07e0: AMWE B.G0 5.DR EAMW
0x45, 0x42, 0x2e, 0x47, 0x30, 0x36, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e,
+ //0x07f0: EB.G 06.D REAM WEB.
0x47, 0x31, 0x34, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x30, 0x31,
+ //0x0800: G14. DREA MWEB .T01
0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x30, 0x32, 0x00, 0x44, 0x52,
+ //0x0810: .DRE AMWE B.T0 2.DR
0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x31, 0x30, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x0820: EAMW EB.T 10.D REAM
0x57, 0x45, 0x42, 0x2e, 0x54, 0x31, 0x31, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42,
+ //0x0830: WEB. T11. DREA MWEB
0x2e, 0x54, 0x31, 0x32, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x31,
+ //0x0840: .T12 .DRE AMWE B.T1
0x33, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x32, 0x30, 0x00, 0x44,
+ //0x0850: 3.DR EAMW EB.T 20.D
0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x32, 0x31, 0x00, 0x44, 0x52, 0x45, 0x41,
+ //0x0860: REAM WEB. T21. DREA
0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x32, 0x32, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45,
+ //0x0870: MWEB .T22 .DRE AMWE
0x42, 0x2e, 0x54, 0x32, 0x33, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54,
+ //0x0880: B.T2 3.DR EAMW EB.T
0x32, 0x34, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x35, 0x30, 0x00,
+ //0x0890: 24.D REAM WEB. T50.
0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x35, 0x31, 0x00, 0x44, 0x52, 0x45,
+ //0x08a0: DREA MWEB .T51 .DRE
0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x38, 0x30, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57,
+ //0x08b0: AMWE B.T8 0.DR EAMW
0x45, 0x42, 0x2e, 0x54, 0x38, 0x31, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e,
+ //0x08c0: EB.T 81.D REAM WEB.
0x54, 0x38, 0x32, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x38, 0x33,
+ //0x08d0: T82. DREA MWEB .T83
0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x54, 0x38, 0x34, 0x00, 0x44, 0x52,
+ //0x08e0: .DRE AMWE B.T8 4.DR
0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x56, 0x4f, 0x4c, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x08f0: EAMW EB.V OL.D REAM
0x57, 0x45, 0x42, 0x2e, 0x47, 0x30, 0x39, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42,
+ //0x0900: WEB. G09. DREA MWEB
0x2e, 0x47, 0x31, 0x30, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x31,
+ //0x0910: .G10 .DRE AMWE B.G1
0x31, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x31, 0x32, 0x00, 0x44,
+ //0x0920: 1.DR EAMW EB.G 12.D
0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x31, 0x33, 0x00, 0x44, 0x52, 0x45, 0x41,
+ //0x0930: REAM WEB. G13. DREA
0x4d, 0x57, 0x45, 0x42, 0x2e, 0x47, 0x31, 0x35, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45,
+ //0x0940: MWEB .G15 .DRE AMWE
0x42, 0x2e, 0x49, 0x30, 0x30, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x49,
+ //0x0950: B.I0 0.DR EAMW EB.I
0x30, 0x31, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x49, 0x30, 0x32, 0x00,
+ //0x0960: 01.D REAM WEB. I02.
0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x49, 0x30, 0x33, 0x00, 0x44, 0x52, 0x45,
+ //0x0970: DREA MWEB .I03 .DRE
0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x49, 0x30, 0x34, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57,
+ //0x0980: AMWE B.I0 4.DR EAMW
0x45, 0x42, 0x2e, 0x49, 0x30, 0x35, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e,
+ //0x0990: EB.I 05.D REAM WEB.
0x49, 0x30, 0x36, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x49, 0x30, 0x37,
+ //0x09a0: I06. DREA MWEB .I07
0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x50, 0x41, 0x4c, 0x00, 0x11, 0x01,
+ //0x09b0: .DRE AMWE B.PA L...
0x40, 0x01, 0x9d, 0x00, 0xc6, 0x00, 0x44, 0xc3, 0x04, 0x01, 0x2c, 0x01, 0x00, 0x00, 0x2c, 0x00,
+ //0x09c0: @... ..D. ..,. ..,.
0x80, 0xc5, 0xd2, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x2c, 0x00, 0xdc, 0xc3, 0x90, 0x00, 0xb0, 0x00,
+ //0x09d0: .... .... ,... ....
0x40, 0x00, 0x60, 0x00, 0x80, 0xc3, 0x00, 0x00, 0x32, 0x00, 0x32, 0x00, 0xc8, 0x00, 0x84, 0xc3,
+ //0x09e0: @.`. .... 2.2. ....
0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0x11, 0x01, 0x40, 0x01,
+ //0x09f0: ..@. .... .... ..@.
0x9d, 0x00, 0xc6, 0x00, 0x44, 0xc3, 0xff, 0x00, 0x26, 0x01, 0x00, 0x00, 0x18, 0x00, 0xc8, 0xc3,
+ //0x0a00: .... D... &... ....
0xf7, 0x00, 0x2d, 0x01, 0x28, 0x00, 0x38, 0x00, 0x48, 0xc3, 0x50, 0x00, 0x00, 0x01, 0x9e, 0x00,
+ //0x0a10: ..-. (.8. H.P. ....
0xca, 0x00, 0xe0, 0xc3, 0x50, 0x00, 0x2c, 0x01, 0x3a, 0x00, 0x92, 0x00, 0x98, 0xc3, 0x00, 0x00,
+ //0x0a20: .... P.,. :... ....
0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0x11, 0x01, 0x40, 0x01, 0x9d, 0x00,
+ //0x0a30: @... .... .... @...
0xc6, 0x00, 0x44, 0xc3, 0xf7, 0x00, 0x2d, 0x01, 0x28, 0x00, 0x38, 0x00, 0x48, 0xc3, 0x50, 0x00,
+ //0x0a40: ..D. ..-. (.8. H.P.
0x2c, 0x01, 0x3a, 0x00, 0x92, 0x00, 0xbc, 0xc6, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00,
+ //0x0a50: ,.:. .... ..@. ....
0xa0, 0xca, 0xff, 0xff, 0x11, 0x01, 0x40, 0x01, 0x9d, 0x00, 0xc6, 0x00, 0x7c, 0xc4, 0xf0, 0x00,
+ //0x0a60: .... ..@. .... |...
0x22, 0x01, 0x02, 0x00, 0x2c, 0x00, 0x94, 0xc4, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00,
+ //0x0a70: "... ,... ..@. ....
0xa0, 0xca, 0xff, 0xff, 0x11, 0x01, 0x40, 0x01, 0x9d, 0x00, 0xc6, 0x00, 0x7c, 0xc4, 0x00, 0x00,
+ //0x0a80: .... ..@. .... |...
0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0xee, 0x00, 0x02, 0x01, 0x04, 0x00,
+ //0x0a90: @... .... .... ....
0x2c, 0x00, 0xc8, 0xc4, 0x68, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x2c, 0x00, 0xcc, 0xc4, 0x18, 0x01,
+ //0x0aa0: ,... h.|. ..,. ....
0x34, 0x01, 0x04, 0x00, 0x2c, 0x00, 0xb0, 0xc4, 0x68, 0x00, 0xd8, 0x00, 0x8a, 0x00, 0xc0, 0x00,
+ //0x0ab0: 4... ,... h... ....
0xd0, 0xc4, 0x11, 0x01, 0x40, 0x01, 0x9d, 0x00, 0xc6, 0x00, 0x7c, 0xc4, 0x00, 0x00, 0x40, 0x01,
+ //0x0ac0: .... @... ..|. ..@.
0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0x45, 0x58, 0x49, 0x54, 0x20, 0x20, 0x20, 0x20,
+ //0x0ad0: .... .... EXIT
0x20, 0x20, 0x48, 0x45, 0x4c, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x49, 0x53, 0x54,
+ //0x0ae0: HE LP LIST
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x45, 0x41, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x0af0: RE AD
0x4c, 0x4f, 0x47, 0x4f, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4b, 0x45, 0x59, 0x53, 0x20, 0x20,
+ //0x0b00: LOGO N KE YS
0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20,
+ //0x0b10: ..PU BLIC
0x20, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00,
+ //0x0b20: PU BLIC ...
0x42, 0x4c, 0x41, 0x43, 0x4b, 0x44, 0x52, 0x41, 0x47, 0x4f, 0x4e, 0x20, 0x52, 0x59, 0x41, 0x4e,
+ //0x0b30: BLAC KDRA GON RYAN
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x48, 0x45, 0x4e, 0x44, 0x52, 0x49,
+ //0x0b40: . ..HE NDRI
0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x4f, 0x55, 0x49, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x0b50: X LO UIS
0x20, 0x00, 0x00, 0x00, 0x53, 0x45, 0x50, 0x54, 0x49, 0x4d, 0x55, 0x53, 0x20, 0x20, 0x20, 0x20,
+ //0x0b60: ... SEPT IMUS
0x42, 0x45, 0x43, 0x4b, 0x45, 0x54, 0x54, 0x20, 0x20, 0x20, 0x20, 0x00, 0xff, 0xff, 0x20, 0x20,
+ //0x0b70: BECK ETT . ..
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x22, 0x52, 0x4f, 0x4f,
+ //0x0b80: . "ROO
0x54, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x0b90: T ."
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x4e, 0x45, 0x54, 0x57, 0xe8, 0xc4, 0x45, 0x4c,
+ //0x0ba0: . NETW ..EL
0x56, 0x41, 0x8c, 0xc6, 0x45, 0x4c, 0x56, 0x42, 0x9c, 0xc6, 0x45, 0x4c, 0x56, 0x43, 0x94, 0xc6,
+ //0x0bb0: VA.. ELVB ..EL VC..
0x45, 0x4c, 0x56, 0x45, 0x98, 0xc6, 0x45, 0x4c, 0x56, 0x46, 0xa0, 0xc6, 0x43, 0x47, 0x41, 0x54,
+ //0x0bc0: ELVE ..EL VF.. CGAT
0x30, 0xc7, 0x52, 0x45, 0x4d, 0x4f, 0xa8, 0xc6, 0x42, 0x55, 0x54, 0x41, 0x3c, 0xc7, 0x43, 0x42,
+ //0x0bd0: 0.RE MO.. BUTA <.CB
0x4f, 0x58, 0x44, 0xc7, 0x4c, 0x49, 0x54, 0x45, 0x5c, 0xc6, 0x50, 0x4c, 0x41, 0x54, 0x40, 0xc7,
+ //0x0be0: OXD. LITE ..PL AT@.
0x4c, 0x49, 0x46, 0x54, 0x7c, 0xc6, 0x57, 0x49, 0x52, 0x45, 0x84, 0xc6, 0x48, 0x4e, 0x44, 0x4c,
+ //0x0bf0: LIFT |.WI RE.. HNDL
0x88, 0xc6, 0x48, 0x41, 0x43, 0x48, 0x80, 0xc6, 0x44, 0x4f, 0x4f, 0x52, 0xb4, 0xc6, 0x43, 0x53,
+ //0x0c00: ..HA CH.. DOOR ..CS
0x48, 0x52, 0x70, 0xc6, 0x47, 0x55, 0x4e, 0x41, 0x34, 0xc7, 0x43, 0x52, 0x41, 0x41, 0x64, 0xc6,
+ //0x0c10: HRp. GUNA 4.CR AAd.
0x43, 0x52, 0x42, 0x42, 0x68, 0xc6, 0x43, 0x52, 0x43, 0x43, 0x6c, 0xc6, 0x53, 0x45, 0x41, 0x54,
+ //0x0c20: CRBB h.CR CCl. SEAT
0xf8, 0xc5, 0x4d, 0x45, 0x4e, 0x55, 0x98, 0xc7, 0x43, 0x4f, 0x4f, 0x4b, 0xac, 0xc6, 0x45, 0x4c,
+ //0x0c30: ..ME NU.. COOK ..EL
0x43, 0x41, 0x4c, 0xc6, 0x45, 0x44, 0x43, 0x41, 0x50, 0xc6, 0x44, 0x44, 0x43, 0x41, 0x54, 0xc6,
+ //0x0c40: CAL. EDCA P.DD CAT.
0x41, 0x4c, 0x54, 0x52, 0x04, 0xc6, 0x4c, 0x4f, 0x4b, 0x41, 0x3c, 0xc6, 0x4c, 0x4f, 0x4b, 0x42,
+ //0x0c50: ALTR ..LO KA<. LOKB
0x40, 0xc6, 0x45, 0x4e, 0x54, 0x41, 0x10, 0xc6, 0x45, 0x4e, 0x54, 0x42, 0x24, 0xc6, 0x45, 0x4e,
+ //0x0c60: @.EN TA.. ENTB $.EN
0x54, 0x45, 0x28, 0xc6, 0x45, 0x4e, 0x54, 0x43, 0x18, 0xc6, 0x45, 0x4e, 0x54, 0x44, 0x2c, 0xc6,
+ //0x0c70: TE(. ENTC ..EN TD,.
0x45, 0x4e, 0x54, 0x48, 0x30, 0xc6, 0x57, 0x57, 0x41, 0x54, 0xf0, 0xc5, 0x50, 0x4f, 0x4f, 0x4c,
+ //0x0c80: ENTH 0.WW AT.. POOL
0x58, 0xc6, 0x57, 0x53, 0x48, 0x44, 0xf4, 0xc5, 0x47, 0x52, 0x41, 0x46, 0x44, 0xc6, 0x54, 0x52,
+ //0x0c90: X.WS HD.. GRAF D.TR
0x41, 0x50, 0x48, 0xc6, 0x43, 0x44, 0x50, 0x45, 0x28, 0xc7, 0x44, 0x4c, 0x4f, 0x4b, 0x08, 0xc6,
+ //0x0ca0: APH. CDPE (.DL OK..
0x48, 0x4f, 0x4c, 0x45, 0x00, 0xc6, 0x44, 0x52, 0x59, 0x52, 0x0c, 0xc6, 0x48, 0x4f, 0x4c, 0x59,
+ //0x0cb0: HOLE ..DR YR.. HOLY
0xfc, 0xc5, 0x57, 0x41, 0x4c, 0x4c, 0x2c, 0xc7, 0x42, 0x4f, 0x4f, 0x4b, 0x08, 0xc8, 0x41, 0x58,
+ //0x0cc0: ..WA LL,. BOOK ..AX
0x45, 0x44, 0xb0, 0xc6, 0x53, 0x48, 0x4c, 0x44, 0x38, 0xc7, 0x42, 0x43, 0x4e, 0x59, 0xe8, 0xc5,
+ //0x0cd0: ED.. SHLD 8.BC NY..
0x4c, 0x49, 0x44, 0x43, 0xe4, 0xc5, 0x4c, 0x49, 0x44, 0x55, 0xe0, 0xc5, 0x4c, 0x49, 0x44, 0x4f,
+ //0x0ce0: LIDC ..LI DU.. LIDO
0xec, 0xc5, 0x50, 0x49, 0x50, 0x45, 0xa8, 0xc5, 0x42, 0x41, 0x4c, 0x43, 0x20, 0xc6, 0x57, 0x49,
+ //0x0cf0: ..PI PE.. BALC .WI
0x4e, 0x44, 0x1c, 0xc6, 0x50, 0x41, 0x50, 0x52, 0xb4, 0xc7, 0x55, 0x57, 0x54, 0x41, 0xa0, 0xc5,
+ //0x0d00: ND.. PAPR ..UW TA..
0x55, 0x57, 0x54, 0x42, 0xa0, 0xc5, 0x53, 0x54, 0x41, 0x54, 0xd8, 0xc7, 0x54, 0x4c, 0x49, 0x44,
+ //0x0d10: UWTB ..ST AT.. TLID
0x9c, 0xc5, 0x53, 0x4c, 0x41, 0x42, 0xd8, 0xc5, 0x43, 0x41, 0x52, 0x54, 0xdc, 0xc5, 0x46, 0x43,
+ //0x0d20: ..SL AB.. CART ..FC
0x41, 0x52, 0xac, 0xc5, 0x53, 0x4c, 0x42, 0x41, 0xc0, 0xc5, 0x53, 0x4c, 0x42, 0x42, 0xc4, 0xc5,
+ //0x0d30: AR.. SLBA ..SL BB..
0x53, 0x4c, 0x42, 0x43, 0xcc, 0xc5, 0x53, 0x4c, 0x42, 0x44, 0xc8, 0xc5, 0x53, 0x4c, 0x42, 0x45,
+ //0x0d40: SLBC ..SL BD.. SLBE
0xd0, 0xc5, 0x53, 0x4c, 0x42, 0x46, 0xd4, 0xc5, 0x50, 0x4c, 0x49, 0x4e, 0xb0, 0xc5, 0x4c, 0x41,
+ //0x0d50: ..SL BF.. PLIN ..LA
0x44, 0x44, 0xb8, 0xc5, 0x4c, 0x41, 0x44, 0x42, 0xbc, 0xc5, 0x47, 0x55, 0x4d, 0x41, 0xb4, 0xc5,
+ //0x0d60: DD.. LADB ..GU MA..
0x53, 0x51, 0x45, 0x45, 0x88, 0xc5, 0x54, 0x41, 0x50, 0x50, 0x8c, 0xc5, 0x47, 0x55, 0x49, 0x54,
+ //0x0d70: SQEE ..TA PP.. GUIT
0x90, 0xc5, 0x43, 0x4f, 0x4e, 0x54, 0x94, 0xc5, 0x42, 0x45, 0x4c, 0x4c, 0x98, 0xc5, 0x8c, 0x8c,
+ //0x0d80: ..CO NT.. BELL ....
0x8c, 0x8c, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x9d, 0x00, 0xb2, 0x00, 0x51, 0x00,
+ //0x0d90: ..00 00.0 0... ..Q.
0x5e, 0x00, 0x58, 0xc7, 0xb3, 0x00, 0xc8, 0x00, 0x51, 0x00, 0x5e, 0x00, 0x5c, 0xc7, 0xc9, 0x00,
+ //0x0da0: ^.X. .... Q.^. ....
0xde, 0x00, 0x51, 0x00, 0x5e, 0x00, 0x60, 0xc7, 0x9d, 0x00, 0xb2, 0x00, 0x5f, 0x00, 0x70, 0x00,
+ //0x0db0: ..Q. ^.`. .... _.p.
0x64, 0xc7, 0xb3, 0x00, 0xc8, 0x00, 0x5f, 0x00, 0x70, 0x00, 0x68, 0xc7, 0xc9, 0x00, 0xde, 0x00,
+ //0x0dc0: d... .._. p.h. ....
0x5f, 0x00, 0x70, 0x00, 0x6c, 0xc7, 0x9d, 0x00, 0xb2, 0x00, 0x71, 0x00, 0x82, 0x00, 0x70, 0xc7,
+ //0x0dd0: _.p. l... ..q. ..p.
0xb3, 0x00, 0xc8, 0x00, 0x71, 0x00, 0x82, 0x00, 0x74, 0xc7, 0xc9, 0x00, 0xde, 0x00, 0x71, 0x00,
+ //0x0de0: .... q... t... ..q.
0x82, 0x00, 0x78, 0xc7, 0x9d, 0x00, 0xb2, 0x00, 0x83, 0x00, 0x91, 0x00, 0x7c, 0xc7, 0xb3, 0x00,
+ //0x0df0: ..x. .... .... |...
0xde, 0x00, 0x83, 0x00, 0x91, 0x00, 0x80, 0xc7, 0xdc, 0x00, 0xea, 0x00, 0x98, 0x00, 0xa6, 0x00,
+ //0x0e00: .... .... .... ....
0x50, 0xc7, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0xae, 0x00,
+ //0x0e10: P... @... .... ....
0xbc, 0x00, 0x84, 0x00, 0x94, 0x00, 0x50, 0xc7, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00,
+ //0x0e20: .... ..P. ..@. ....
0xa0, 0xca, 0xff, 0xff, 0x18, 0x01, 0x40, 0x01, 0xa0, 0x00, 0xc8, 0x00, 0x50, 0xc7, 0x8f, 0x00,
+ //0x0e30: .... ..@. .... P...
0x2c, 0x01, 0x06, 0x00, 0xc2, 0x00, 0xb8, 0xc7, 0x00, 0x00, 0x8f, 0x00, 0x06, 0x00, 0xc2, 0x00,
+ //0x0e40: ,... .... .... ....
0xc0, 0xc7, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0x68, 0x00,
+ //0x0e50: .... @... .... ..h.
0x80, 0x00, 0x3a, 0x00, 0x48, 0x00, 0xdc, 0xc7, 0x40, 0x00, 0x74, 0x00, 0x4c, 0x00, 0x6a, 0x00,
+ //0x0e60: ..:. H... @.t. L.j.
0xe0, 0xc7, 0x74, 0x00, 0xa8, 0x00, 0x4c, 0x00, 0x6a, 0x00, 0xe4, 0xc7, 0x40, 0x00, 0x74, 0x00,
+ //0x0e70: ..t. ..L. j... @.t.
0x6a, 0x00, 0x88, 0x00, 0xe8, 0xc7, 0x74, 0x00, 0xa8, 0x00, 0x6a, 0x00, 0x88, 0x00, 0xec, 0xc7,
+ //0x0e80: j... ..t. ..j. ....
0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0xba, 0x00, 0xca, 0x00,
+ //0x0e90: ..@. .... .... ....
0x9d, 0x00, 0xad, 0x00, 0x1c, 0xc8, 0xf3, 0x00, 0x03, 0x01, 0x83, 0x00, 0x93, 0x00, 0x18, 0xc8,
+ //0x0ea0: .... .... .... ....
0x0c, 0x01, 0x1c, 0x01, 0xa8, 0x00, 0xb8, 0x00, 0x50, 0xc7, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00,
+ //0x0eb0: .... .... P... @...
0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0x77, 0x00, 0xae, 0x00, 0x52, 0x00, 0x80, 0x00, 0x34, 0xc8,
+ //0x0ec0: .... ..w. ..R. ..4.
0x46, 0x00, 0x89, 0x00, 0x3e, 0x00, 0x6f, 0x00, 0x80, 0xc8, 0xbc, 0x00, 0xfa, 0x00, 0x44, 0x00,
+ //0x0ed0: F... >.o. .... ..D.
0x98, 0x00, 0x4c, 0xc8, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff,
+ //0x0ee0: ..L. ..@. .... ....
0xec, 0x00, 0xfc, 0x00, 0x70, 0x00, 0x80, 0x00, 0x48, 0xc8, 0xbc, 0x00, 0xfa, 0x00, 0x40, 0x00,
+ //0x0ef0: .... p... H... ..@.
0x98, 0x00, 0x58, 0xc8, 0x3e, 0x00, 0x98, 0x00, 0x38, 0x00, 0x85, 0x00, 0x74, 0xc8, 0x00, 0x00,
+ //0x0f00: ..X. >... 8... t...
0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0x77, 0x00, 0xae, 0x00, 0x52, 0x00,
+ //0x0f10: @... .... ..w. ..R.
0x80, 0x00, 0x44, 0xc8, 0x46, 0x00, 0x8b, 0x00, 0x3e, 0x00, 0x6f, 0x00, 0x50, 0xc8, 0xec, 0x00,
+ //0x0f20: ..D. F... >.o. P...
0xfc, 0x00, 0x70, 0x00, 0x80, 0x00, 0x48, 0xc8, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00,
+ //0x0f30: ..p. ..H. ..@. ....
0xa0, 0xca, 0xff, 0xff, 0xec, 0x00, 0xfc, 0x00, 0x70, 0x00, 0x80, 0x00, 0x48, 0xc8, 0xbc, 0x00,
+ //0x0f40: .... .... p... H...
0xfa, 0x00, 0x40, 0x00, 0x98, 0x00, 0x54, 0xc8, 0x3e, 0x00, 0x98, 0x00, 0x38, 0x00, 0x85, 0x00,
+ //0x0f50: ..@. ..T. >... 8...
0x74, 0xc8, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0x0d, 0x0a,
+ //0x0f60: t... @... .... ....
0x0d, 0x0a, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62, 0x20, 0x68, 0x61, 0x73, 0x20, 0x61,
+ //0x0f70: ..Dr eamw eb h as a
0x6e, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x0d, 0x0a, 0x55, 0x6e, 0x61, 0x62, 0x6c, 0x65,
+ //0x0f80: n Er ror: ..Un able
0x20, 0x74, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20, 0x45, 0x78, 0x70,
+ //0x0f90: to allo cate Exp
0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x2e, 0x0d, 0x0a, 0x0d,
+ //0x0fa0: ande d Me mory ....
0x0a, 0x24, 0x0d, 0x0a, 0x0d, 0x0a, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62, 0x20, 0x68,
+ //0x0fb0: .$.. ..Dr eamw eb h
0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x0d, 0x0a, 0x53, 0x6f,
+ //0x0fc0: as a n Er ror: ..So
0x75, 0x6e, 0x64, 0x20, 0x42, 0x6c, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x63, 0x61, 0x72, 0x64,
+ //0x0fd0: und Blas ter card
0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x74, 0x20, 0x61, 0x64,
+ //0x0fe0: not fou nd a t ad
0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x32, 0x32, 0x30, 0x20, 0x48, 0x65, 0x78, 0x2e, 0x0d, 0x0a,
+ //0x0ff0: dres s 22 0 He x...
0x0d, 0x0a, 0x24, 0x0d, 0x0a, 0x0d, 0x0a, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62, 0x20,
+ //0x1000: ..$. ...D ream web
0x68, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x0d, 0x0a, 0x4f,
+ //0x1010: has an E rror :..O
0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x61, 0x73, 0x65, 0x20, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
+ //0x1020: ut o f Ba se M emor
0x79, 0x2e, 0x0d, 0x0a, 0x0d, 0x0a, 0x24, 0x0d, 0x0a, 0x0d, 0x0a, 0x44, 0x72, 0x65, 0x61, 0x6d,
+ //0x1030: y... ..$. ...D ream
0x77, 0x65, 0x62, 0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72,
+ //0x1040: web has an E rror
0x3a, 0x0d, 0x0a, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x44, 0x65, 0x61, 0x6c, 0x6c, 0x6f,
+ //0x1050: :..M emor y De allo
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2e, 0x0d,
+ //0x1060: cati on p robl em..
0x0a, 0x0d, 0x0a, 0x24, 0x0d, 0x0a, 0x0d, 0x0a, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62,
+ //0x1070: ...$ .... Drea mweb
0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x0d, 0x0a,
+ //0x1080: has an Erro r:..
0x41, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x35, 0x39, 0x30, 0x4b, 0x20, 0x6f, 0x66,
+ //0x1090: At l east 590 K of
0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20,
+ //0x10a0: bas e me mory is
0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x2e, 0x0d, 0x0a, 0x0d, 0x0a, 0x24, 0x0d, 0x0a,
+ //0x10b0: requ ired .... .$..
0x0d, 0x0a, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62, 0x20, 0x68, 0x61, 0x73, 0x20, 0x61,
+ //0x10c0: ..Dr eamw eb h as a
0x6e, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x0d, 0x0a, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ //0x10d0: n Er ror: ..So und
0x42, 0x6c, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e,
+ //0x10e0: Blas ter not foun
0x64, 0x20, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x75, 0x70, 0x74, 0x20, 0x30, 0x0d,
+ //0x10f0: d on int erup t 0.
0x0a, 0x0d, 0x0a, 0x24, 0x0d, 0x0a, 0x0d, 0x0a, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62,
+ //0x1100: ...$ .... Drea mweb
0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x0d, 0x0a,
+ //0x1110: has an Erro r:..
0x55, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ //0x1120: Unab le t o se lect
0x20, 0x45, 0x4d, 0x4d, 0x20, 0x70, 0x61, 0x67, 0x65, 0x2e, 0x0d, 0x0a, 0x0d, 0x0a, 0x24, 0x0d,
+ //0x1130: EMM pag e... ..$.
0x0a, 0x0d, 0x0a, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62, 0x20, 0x68, 0x61, 0x73, 0x20,
+ //0x1140: ...D ream web has
0x61, 0x6e, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x0d, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x20,
+ //0x1150: an E rror :..F ile
0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x63, 0x0d, 0x0a, 0x0d, 0x0a, 0x24,
+ //0x1160: not foun d.c. ...$
0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x66,
+ //0x1170: Drea mweb loo ks f
0x6f, 0x72, 0x20, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x42, 0x6c, 0x61, 0x73, 0x74, 0x65, 0x72,
+ //0x1180: or S ound Bla ster
0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x0d,
+ //0x1190: inf orma tion in.
0x0a, 0x74, 0x68, 0x65, 0x20, 0x42, 0x4c, 0x41, 0x53, 0x54, 0x45, 0x52, 0x20, 0x65, 0x6e, 0x76,
+ //0x11a0: .the BLA STER env
0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c,
+ //0x11b0: iron ment var iabl
0x65, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x41, 0x55, 0x54, 0x4f, 0x45,
+ //0x11c0: e (i n yo ur A UTOE
0x58, 0x45, 0x43, 0x2e, 0x42, 0x41, 0x54, 0x29, 0x0d, 0x0a, 0x0d, 0x0a, 0x49, 0x66, 0x20, 0x74,
+ //0x11d0: XEC. BAT) .... If t
0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64,
+ //0x11e0: his is n ot f ound
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x52, 0x51, 0x20, 0x37, 0x2c, 0x20, 0x44, 0x4d, 0x41,
+ //0x11f0: the n IR Q 7, DMA
0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ //0x1200: cha nnel 1 a nd b
0x61, 0x73, 0x65, 0x0d, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x32, 0x32, 0x30,
+ //0x1210: ase. .add ress 220
0x68, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x2e, 0x0d, 0x0a,
+ //0x1220: h ar e as sume d...
0x0d, 0x0a, 0x54, 0x6f, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6f,
+ //0x1230: ..To alt er a ny o
0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x73,
+ //0x1240: r al l of the se s
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20,
+ //0x1250: etti ngs you can
0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x0d, 0x0a, 0x6f, 0x6e,
+ //0x1260: spec ify them ..on
0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e,
+ //0x1270: the com mand lin
0x65, 0x2e, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x0d,
+ //0x1280: e. F or e xamp le:.
0x0a, 0x0d, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1290: ...T ype D REAM
0x57, 0x45, 0x42, 0x20, 0x49, 0x37, 0x20, 0x41, 0x32, 0x32, 0x30, 0x20, 0x44, 0x31, 0x20, 0x20,
+ //0x12a0: WEB I7 A 220 D1
0x20, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65,
+ //0x12b0: to run Dre amwe
0x62, 0x20, 0x6f, 0x6e, 0x20, 0x49, 0x52, 0x51, 0x20, 0x37, 0x2c, 0x20, 0x44, 0x4d, 0x41, 0x0d,
+ //0x12c0: b on IRQ 7, DMA.
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x12d0: .
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x12e0:
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61,
+ //0x12f0: chan nel 1 an d ba
0x73, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x32, 0x32, 0x30, 0x68, 0x0d,
+ //0x1300: se a ddre ss 2 20h.
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45,
+ //0x1310: . DRE AMWE
0x42, 0x20, 0x49, 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x1320: B I5
0x74, 0x6f, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x77, 0x65, 0x62, 0x20,
+ //0x1330: to r un D ream web
0x6f, 0x6e, 0x20, 0x49, 0x52, 0x51, 0x20, 0x35, 0x20, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x20, 0x20,
+ //0x1340: on I RQ 5 and ..
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x1350:
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x66,
+ //0x1360: def
0x61, 0x75, 0x6c, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ //0x1370: ault add ress of
0x32, 0x32, 0x30, 0x68, 0x2c, 0x20, 0x44, 0x4d, 0x41, 0x20, 0x31, 0x0d, 0x0a, 0x0d, 0x0a, 0x24,
+ //0x1380: 220h , DM A 1. ...$
0x0d, 0x0a, 0x0d, 0x0a, 0x54, 0x72, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x44, 0x72, 0x65, 0x61,
+ //0x1390: .... Try the Drea
0x6d, 0x77, 0x65, 0x62, 0x20, 0x43, 0x44, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20,
+ //0x13a0: mweb CD in y our
0x73, 0x74, 0x65, 0x72, 0x65, 0x6f, 0x2e, 0x2e, 0x2e, 0x2e, 0x0d, 0x0a, 0x0d, 0x0a, 0x0d, 0x0a,
+ //0x13b0: ster eo.. .... ....
0x24, 0x81, 0x00, 0xb8, 0x00, 0x52, 0x00, 0x80, 0x00, 0xc0, 0xc8, 0x50, 0x00, 0x93, 0x00, 0x3e,
+ //0x13c0: $... .R.. ...P ...>
0x00, 0x6f, 0x00, 0x80, 0xc8, 0xb7, 0x00, 0xfa, 0x00, 0x3e, 0x00, 0x6f, 0x00, 0xc4, 0xc8, 0x00,
+ //0x13d0: .o.. .... .>.o ....
0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xa0, 0xca, 0xff, 0xff, 0x53, 0x50, 0x45, 0x45, 0x43,
+ //0x13e0: .@.. .... ...S PEEC
0x48, 0x52, 0x32, 0x34, 0x43, 0x30, 0x30, 0x30, 0x35, 0x2e, 0x52, 0x41, 0x57, 0x00, 0x87, 0x83,
+ //0x13f0: HR24 C000 5.RA W...
0x81, 0x82, 0x2c, 0x00, 0x46, 0x00, 0x20, 0x00, 0x2e, 0x00, 0x70, 0xc4, 0x00, 0x00, 0x32, 0x00,
+ //0x1400: ..,. F. . ..p. ..2.
0x00, 0x00, 0xb4, 0x00, 0x7c, 0xc3, 0xe2, 0x00, 0xf4, 0x00, 0x0a, 0x00, 0x1a, 0x00, 0x28, 0xc8,
+ //0x1410: .... |... .... ..(.
0xe2, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x28, 0x00, 0x2c, 0xc8, 0xf0, 0x00, 0x04, 0x01, 0x64, 0x00,
+ //0x1420: .... ..(. ,... ..d.
0x7c, 0x00, 0xcc, 0xc9, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xd4, 0xc9, 0xff, 0xff,
+ //0x1430: |... ..@. .... ....
0x2c, 0x00, 0x46, 0x00, 0x20, 0x00, 0x2e, 0x00, 0x70, 0xc4, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
+ //0x1440: ,.F. ... p... 2...
0xb4, 0x00, 0x7c, 0xc3, 0x12, 0x01, 0x24, 0x01, 0x0a, 0x00, 0x1a, 0x00, 0x28, 0xc8, 0x12, 0x01,
+ //0x1450: ..|. ..$. .... (...
0x24, 0x01, 0x1a, 0x00, 0x28, 0x00, 0x2c, 0xc8, 0xf0, 0x00, 0x04, 0x01, 0x64, 0x00, 0x7c, 0x00,
+ //0x1460: $... (.,. .... d.|.
0xcc, 0xc9, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xc8, 0x00, 0xd4, 0xc9, 0xff, 0xff, 0x00, 0x21,
+ //0x1470: .... @... .... ...!
0x0a, 0x0f, 0xff, 0x00, 0x16, 0x0a, 0x0f, 0xff, 0x00, 0x16, 0x00, 0x0f, 0xff, 0x00, 0x0b, 0x00,
+ //0x1480: .... .... .... ....
0x0f, 0xff, 0x00, 0x0b, 0x0a, 0x0f, 0xff, 0x00, 0x00, 0x0a, 0x0f, 0xff, 0x01, 0x2c, 0x0a, 0x06,
+ //0x1490: .... .... .... .,..
0xff, 0x01, 0x2c, 0x00, 0x0d, 0xff, 0x02, 0x21, 0x00, 0x06, 0xff, 0x02, 0x16, 0x00, 0x05, 0xff,
+ //0x14a0: ..,. ...! .... ....
0x02, 0x16, 0x0a, 0x10, 0xff, 0x02, 0x0b, 0x0a, 0x10, 0xff, 0x03, 0x2c, 0x00, 0x0f, 0xff, 0x03,
+ //0x14b0: .... .... ..., ....
0x21, 0x0a, 0x06, 0xff, 0x03, 0x21, 0x00, 0x05, 0xff, 0x04, 0x0b, 0x1e, 0x06, 0xff, 0x04, 0x16,
+ //0x14c0: !... .!.. .... ....
0x1e, 0x05, 0xff, 0x04, 0x16, 0x14, 0x0d, 0xff, 0x0a, 0x21, 0x1e, 0x06, 0xff, 0x0a, 0x16, 0x1e,
+ //0x14d0: .... .... .!.. ....
0x06, 0xff, 0x09, 0x16, 0x0a, 0x06, 0xff, 0x09, 0x16, 0x14, 0x10, 0xff, 0x09, 0x16, 0x1e, 0x10,
+ //0x14e0: .... .... .... ....
0xff, 0x09, 0x16, 0x28, 0x10, 0xff, 0x09, 0x16, 0x32, 0x10, 0xff, 0x06, 0x0b, 0x1e, 0x06, 0xff,
+ //0x14f0: ...( .... 2... ....
0x06, 0x00, 0x0a, 0x0f, 0xff, 0x06, 0x00, 0x14, 0x0f, 0xff, 0x06, 0x0b, 0x14, 0x0f, 0xff, 0x06,
+ //0x1500: .... .... .... ....
0x16, 0x14, 0x0f, 0xff, 0x07, 0x0b, 0x14, 0x06, 0xff, 0x07, 0x00, 0x14, 0x06, 0xff, 0x07, 0x00,
+ //0x1510: .... .... .... ....
0x1e, 0x06, 0xff, 0x37, 0x2c, 0x00, 0x05, 0xff, 0x37, 0x2c, 0x0a, 0x05, 0xff, 0x05, 0x16, 0x1e,
+ //0x1520: ...7 ,... 7,.. ....
0x06, 0xff, 0x05, 0x16, 0x14, 0x0f, 0xff, 0x05, 0x16, 0x0a, 0x0f, 0xff, 0x18, 0x16, 0x00, 0x0f,
+ //0x1530: .... .... .... ....
0xff, 0x18, 0x21, 0x00, 0x0f, 0xff, 0x18, 0x2c, 0x00, 0x0f, 0xff, 0x18, 0x21, 0x0a, 0x0f, 0xff,
+ //0x1540: ..!. ..., .... !...
0x08, 0x00, 0x0a, 0x06, 0xff, 0x08, 0x0b, 0x0a, 0x06, 0xff, 0x08, 0x16, 0x0a, 0x06, 0xff, 0x08,
+ //0x1550: .... .... .... ....
0x21, 0x0a, 0x06, 0xff, 0x08, 0x21, 0x14, 0x06, 0xff, 0x08, 0x21, 0x1e, 0x06, 0xff, 0x08, 0x21,
+ //0x1560: !... .!.. ..!. ...!
0x28, 0x06, 0xff, 0x08, 0x16, 0x28, 0x06, 0xff, 0x08, 0x0b, 0x28, 0x06, 0xff, 0x0b, 0x0b, 0x14,
+ //0x1570: (... .(.. ..(. ....
0x0c, 0xff, 0x0b, 0x0b, 0x1e, 0x0c, 0xff, 0x0b, 0x16, 0x14, 0x0c, 0xff, 0x0b, 0x16, 0x1e, 0x0c,
+ //0x1580: .... .... .... ....
0xff, 0x0c, 0x16, 0x14, 0x0c, 0xff, 0x0d, 0x16, 0x14, 0x0c, 0xff, 0x0d, 0x21, 0x14, 0x0c, 0xff,
+ //0x1590: .... .... .... !...
0x0e, 0x2c, 0x14, 0x0c, 0xff, 0x0e, 0x21, 0x00, 0x0c, 0xff, 0x0e, 0x21, 0x0a, 0x0c, 0xff, 0x0e,
+ //0x15a0: .,.. ..!. ...! ....
0x21, 0x14, 0x0c, 0xff, 0x0e, 0x21, 0x1e, 0x0c, 0xff, 0x0e, 0x21, 0x28, 0x0c, 0xff, 0x0e, 0x16,
+ //0x15b0: !... .!.. ..!( ....
0x00, 0x10, 0xff, 0x13, 0x00, 0x00, 0x0c, 0xff, 0x14, 0x00, 0x14, 0x10, 0xff, 0x14, 0x00, 0x1e,
+ //0x15c0: .... .... .... ....
0x10, 0xff, 0x14, 0x0b, 0x1e, 0x10, 0xff, 0x14, 0x00, 0x28, 0x10, 0xff, 0x14, 0x0b, 0x28, 0x10,
+ //0x15d0: .... .... .(.. ..(.
0xff, 0x15, 0x0b, 0x0a, 0x0f, 0xff, 0x15, 0x0b, 0x14, 0x0f, 0xff, 0x15, 0x00, 0x14, 0x0f, 0xff,
+ //0x15e0: .... .... .... ....
0x15, 0x16, 0x14, 0x0f, 0xff, 0x15, 0x21, 0x14, 0x0f, 0xff, 0x15, 0x2c, 0x14, 0x0f, 0xff, 0x15,
+ //0x15f0: .... ..!. ..., ....
0x2c, 0x0a, 0x0f, 0xff, 0x16, 0x16, 0x0a, 0x10, 0xff, 0x16, 0x16, 0x14, 0x10, 0xff, 0x17, 0x16,
+ //0x1600: ,... .... .... ....
0x1e, 0x0d, 0xff, 0x17, 0x16, 0x28, 0x0d, 0xff, 0x17, 0x21, 0x28, 0x0d, 0xff, 0x17, 0x0b, 0x28,
+ //0x1610: .... .(.. .!(. ...(
0x0d, 0xff, 0x17, 0x00, 0x28, 0x0d, 0xff, 0x17, 0x00, 0x32, 0x0d, 0xff, 0x19, 0x0b, 0x28, 0x10,
+ //0x1620: .... (... .2.. ..(.
0xff, 0x19, 0x0b, 0x32, 0x10, 0xff, 0x19, 0x00, 0x32, 0x10, 0xff, 0x1b, 0x0b, 0x14, 0x10, 0xff,
+ //0x1630: ...2 .... 2... ....
0x1b, 0x0b, 0x1e, 0x10, 0xff, 0x1d, 0x0b, 0x0a, 0x10, 0xff, 0x2d, 0x16, 0x1e, 0x0c, 0xff, 0x2d,
+ //0x1640: .... .... ..-. ...-
0x16, 0x28, 0x0c, 0xff, 0x2d, 0x16, 0x32, 0x0c, 0xff, 0x2e, 0x16, 0x28, 0x0c, 0xff, 0x2e, 0x0b,
+ //0x1650: .(.. -.2. ...( ....
0x32, 0x0c, 0xff, 0x2e, 0x16, 0x32, 0x0c, 0xff, 0x2e, 0x21, 0x32, 0x0c, 0xff, 0x2f, 0x00, 0x00,
+ //0x1660: 2... .2.. .!2. ./..
0x0c, 0xff, 0x1a, 0x16, 0x14, 0x10, 0xff, 0x1a, 0x21, 0x0a, 0x10, 0xff, 0x1a, 0x21, 0x14, 0x10,
+ //0x1670: .... .... !... .!..
0xff, 0x1a, 0x21, 0x1e, 0x10, 0xff, 0x1a, 0x2c, 0x1e, 0x10, 0xff, 0x1a, 0x16, 0x1e, 0x10, 0xff,
+ //0x1680: ..!. ..., .... ....
0x1a, 0x0b, 0x1e, 0x10, 0xff, 0x1a, 0x0b, 0x14, 0x10, 0xff, 0x1a, 0x00, 0x14, 0x10, 0xff, 0x1a,
+ //0x1690: .... .... .... ....
0x0b, 0x28, 0x10, 0xff, 0x1a, 0x00, 0x28, 0x10, 0xff, 0x1a, 0x16, 0x28, 0x10, 0xff, 0x1a, 0x0b,
+ //0x16a0: .(.. ..(. ...( ....
0x32, 0x10, 0xff, 0x1c, 0x00, 0x1e, 0x0f, 0xff, 0x1c, 0x00, 0x14, 0x0f, 0xff, 0x1c, 0x00, 0x28,
+ //0x16b0: 2... .... .... ...(
0x0f, 0xff, 0x1c, 0x0b, 0x1e, 0x0f, 0xff, 0x1c, 0x0b, 0x14, 0x0f, 0xff, 0x1c, 0x16, 0x1e, 0x0f,
+ //0x16c0: .... .... .... ....
0xff, 0x1c, 0x16, 0x14, 0x0f, 0xff, 0xff, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x20, 0x4e, 0x41,
+ //0x16d0: .... ...O BJEC T NA
0x4d, 0x45, 0x20, 0x4f, 0x4e, 0x45, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x16e0: ME O NE
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00,
+ //0x16f0: .
0x10, 0x12, 0x12, 0x11, 0x10, 0x10, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x1700: .... .... .... ....
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1710: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+ //0x1720: .... .... ..12 3456
0x37, 0x38, 0x39, 0x30, 0x2d, 0x00, 0x08, 0x00, 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49,
+ //0x1730: 7890 -... QWER TYUI
0x4f, 0x50, 0x00, 0x00, 0x0d, 0x00, 0x41, 0x53, 0x44, 0x46, 0x47, 0x48, 0x4a, 0x4b, 0x4c, 0x00,
+ //0x1740: OP.. ..AS DFGH JKL.
0x00, 0x00, 0x00, 0x00, 0x5a, 0x58, 0x43, 0x56, 0x42, 0x4e, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1750: .... ZXCV BNM. ....
0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1760: . .. .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1770: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1780: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1790: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3a, 0x00, 0x00, 0x00,
+ //0x17a0: .... .... ...D :...
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x17b0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x17c0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x20, 0x44, 0x41, 0x54, 0x41, 0x20, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x43, 0x4f,
+ //0x17d0: WEB DATA FIL E CO
0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, 0x31, 0x39, 0x39, 0x32, 0x20, 0x43, 0x52, 0x45,
+ //0x17e0: PYRI GHT 1992 CRE
0x41, 0x54, 0x49, 0x56, 0x45, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x00, 0x00, 0x00,
+ //0x17f0: ATIV E RE ALIT Y...
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1800: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1810: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1820: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x30, 0x00, 0x05, 0xff, 0x21, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1830: WEB. R00. ..!. ....
0x01, 0x06, 0x02, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1840: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x31, 0x00, 0x01, 0xff, 0x2c, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1850: WEB. R01. ..,. ....
0x07, 0x02, 0xff, 0xff, 0xff, 0xff, 0x06, 0xff, 0xff, 0xff, 0x01, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1860: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x32, 0x00, 0x02, 0xff, 0x21, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1870: WEB. R02. ..!. ....
0x01, 0x00, 0xff, 0xff, 0x01, 0xff, 0x03, 0xff, 0xff, 0xff, 0x02, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1880: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x33, 0x00, 0x05, 0xff, 0x21, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1890: WEB. R03. ..!. ....
0x02, 0x02, 0x00, 0x02, 0x04, 0xff, 0x00, 0xff, 0xff, 0xff, 0x03, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x18a0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x34, 0x00, 0x17, 0xff, 0x0b, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x18b0: WEB. R04. .... ....
0x01, 0x04, 0x00, 0x05, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x04, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x18c0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x35, 0x00, 0x05, 0xff, 0x16, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x18d0: WEB. R05. .... ....
0x01, 0x02, 0x00, 0x04, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x05, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x18e0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x36, 0x00, 0x05, 0xff, 0x0b, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x18f0: WEB. R06. .... ....
0x01, 0x00, 0x00, 0x01, 0x02, 0xff, 0x00, 0xff, 0xff, 0xff, 0x06, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1900: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x37, 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1910: WEB. R07. .... ....
0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x07, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1920: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x38, 0x00, 0x08, 0xff, 0x00, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1930: WEB. R08. .... ....
0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0b, 0x28, 0x00, 0x08, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1940: .... .... (..D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x39, 0x00, 0x09, 0xff, 0x16, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1950: WEB. R09. .... ....
0x04, 0x06, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x09, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1960: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x30, 0x00, 0x0a, 0xff, 0x21, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1970: WEB. R10. ..!. ....
0x02, 0x00, 0xff, 0xff, 0x02, 0x02, 0x04, 0x16, 0x1e, 0xff, 0x0a, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1980: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x31, 0x00, 0x0b, 0xff, 0x0b, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1990: WEB. R11. .... ....
0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x19a0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x32, 0x00, 0x0c, 0xff, 0x16, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x19b0: WEB. R12. .... ....
0x01, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x19c0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x33, 0x00, 0x0c, 0xff, 0x16, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x19d0: WEB. R13. .... ....
0x01, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x19e0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x34, 0x00, 0x0e, 0xff, 0x2c, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x19f0: WEB. R14. ..,. ....
0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1a00: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1a10: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1a20: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1a30: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1a40: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1a50: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1a60: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1a70: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1a80: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x39, 0x00, 0x13, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1a90: WEB. R19. .... ....
0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1aa0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x30, 0x00, 0x16, 0xff, 0x00, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1ab0: WEB. R20. .... ....
0x01, 0x04, 0x02, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1ac0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x31, 0x00, 0x05, 0xff, 0x0b, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1ad0: WEB. R21. .... ....
0x01, 0x04, 0x02, 0x0f, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1ae0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x32, 0x00, 0x16, 0xff, 0x16, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1af0: WEB. R22. .... ....
0x00, 0x04, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1b00: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x33, 0x00, 0x17, 0xff, 0x16, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1b10: WEB. R23. .... ....
0x01, 0x04, 0x02, 0x0f, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0x17, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1b20: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x34, 0x00, 0x05, 0xff, 0x2c, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1b30: WEB. R24. ..,. ....
0x01, 0x06, 0x02, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x18, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1b40: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x35, 0x00, 0x16, 0xff, 0x0b, 0x28, 0xff, 0xff, 0xff, 0x00,
+ //0x1b50: WEB. R25. ...( ....
0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1b60: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x36, 0x00, 0x09, 0xff, 0x16, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1b70: WEB. R26. .... ....
0x04, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1b80: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x37, 0x00, 0x16, 0xff, 0x0b, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1b90: WEB. R27. .... ....
0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1ba0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x38, 0x00, 0x05, 0xff, 0x0b, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1bb0: WEB. R28. .... ....
0x00, 0x00, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1bc0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x39, 0x00, 0x16, 0xff, 0x0b, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1bd0: WEB. R29. .... ....
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1d, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1be0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x35, 0x00, 0x05, 0xff, 0x16, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1bf0: WEB. R05. .... ....
0x01, 0x04, 0x01, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1c00: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x34, 0x00, 0x17, 0xff, 0x16, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1c10: WEB. R04. .... ....
0x01, 0x04, 0x02, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1c20: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x30, 0x00, 0x0a, 0xff, 0x16, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1c30: WEB. R10. .... ....
0x03, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1c40: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x32, 0x00, 0x0c, 0xff, 0x16, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1c50: WEB. R12. .... ....
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1c60: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x33, 0x00, 0x05, 0xff, 0x2c, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1c70: WEB. R03. ..,. ....
0x01, 0x06, 0x02, 0xff, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1c80: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x34, 0x00, 0x05, 0xff, 0x16, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1c90: WEB. R24. .... ....
0x03, 0x06, 0x00, 0xff, 0xff, 0xff, 0xff, 0x21, 0x00, 0x03, 0x18, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1ca0: .... ...! ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x32, 0x00, 0x16, 0xff, 0x16, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1cb0: WEB. R22. .... ....
0x01, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1cc0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x32, 0x00, 0x16, 0xff, 0x16, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1cd0: WEB. R22. .... ....
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1ce0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x31, 0x00, 0x0b, 0xff, 0x16, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1cf0: WEB. R11. .... ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1d00: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x38, 0x00, 0x05, 0xff, 0x0b, 0x14, 0xff, 0xff, 0xff, 0x00,
+ //0x1d10: WEB. R28. .... ....
0x00, 0x06, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1d20: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x31, 0x00, 0x05, 0xff, 0x0b, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1d30: WEB. R21. .... ....
0x01, 0x04, 0x02, 0x0f, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1d40: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x32, 0x36, 0x00, 0x09, 0xff, 0x00, 0x28, 0xff, 0xff, 0xff, 0x00,
+ //0x1d50: WEB. R26. ...( ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1d60: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x31, 0x39, 0x00, 0x13, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1d70: WEB. R19. .... ....
0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1d80: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x38, 0x00, 0x08, 0xff, 0x0b, 0x28, 0xff, 0xff, 0xff, 0x00,
+ //0x1d90: WEB. R08. ...( ....
0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1da0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x30, 0x31, 0x00, 0x01, 0xff, 0x2c, 0x0a, 0xff, 0xff, 0xff, 0x00,
+ //0x1db0: WEB. R01. ..,. ....
0x03, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1dc0: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x34, 0x35, 0x00, 0x23, 0xff, 0x16, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1dd0: WEB. R45. #... ....
0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2d, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1de0: .... .... ..-D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x34, 0x36, 0x00, 0x23, 0xff, 0x16, 0x28, 0xff, 0xff, 0xff, 0x00,
+ //0x1df0: WEB. R46. #..( ....
0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2e, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1e00: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x34, 0x37, 0x00, 0x23, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1e10: WEB. R47. #... ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1e20: .... .... ../D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x34, 0x35, 0x00, 0x23, 0xff, 0x16, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1e30: WEB. R45. #... ....
0x04, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2d, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1e40: .... .... ..-D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x34, 0x36, 0x00, 0x23, 0xff, 0x16, 0x32, 0xff, 0xff, 0xff, 0x00,
+ //0x1e50: WEB. R46. #..2 ....
0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2e, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1e60: .... .... ...D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x35, 0x30, 0x00, 0x23, 0xff, 0x16, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1e70: WEB. R50. #... ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x32, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1e80: .... .... ..2D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x35, 0x31, 0x00, 0x23, 0xff, 0x0b, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1e90: WEB. R51. #... ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1ea0: .... .... ..3D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x35, 0x32, 0x00, 0x23, 0xff, 0x16, 0x1e, 0xff, 0xff, 0xff, 0x00,
+ //0x1eb0: WEB. R52. #... ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x34, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1ec0: .... .... ..4D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x35, 0x33, 0x00, 0x23, 0xff, 0x21, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1ed0: WEB. R53. #.!. ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x35, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1ee0: .... .... ..5D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x35, 0x34, 0x00, 0x23, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1ef0: WEB. R54. #... ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x36, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x1f00: .... .... ..6D REAM
0x57, 0x45, 0x42, 0x2e, 0x52, 0x35, 0x35, 0x00, 0x0e, 0xff, 0x2c, 0x00, 0xff, 0xff, 0xff, 0x00,
+ //0x1f10: WEB. R55. ..,. ....
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1f20: .... .... ..7. ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1f30: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00,
+ //0x1f40: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x02, 0x04,
+ //0x1f50: .... .... .... ....
0x01, 0x0a, 0x09, 0x08, 0x06, 0x0b, 0x04, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1f60: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1f70: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1f80: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1f90: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1fa0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1fb0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1fc0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x1fd0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ //0x1fe0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x1ff0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2000: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2010: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2020: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2030: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2040: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2050: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2060: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2070: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2080: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2090: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x20a0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x20b0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x20c0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x20d0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x20e0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x20f0: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2100: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2110: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2120: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2130: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2140: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2150: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2160: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ //0x2170: .... .... .... ....
0xff, 0xff, 0xff, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x2180: .... .... .... ....
0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x2190: .... .... .... ....
0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x21a0: .... .... .... ....
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x21b0: .... .... .... ....
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x21c0: .... .... .... ....
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x21d0: .... .... .... ....
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x21e0: .... .... .... ....
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57,
+ //0x21f0: .... .... ..DR EAMW
0x45, 0x42, 0x2e, 0x44, 0x30, 0x30, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e,
+ //0x2200: EB.D 00.D REAM WEB.
0x44, 0x30, 0x31, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x44, 0x30, 0x32,
+ //0x2210: D01. DREA MWEB .D02
0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x44, 0x30, 0x33, 0x00, 0x44, 0x52,
+ //0x2220: .DRE AMWE B.D0 3.DR
0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x44, 0x30, 0x34, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d,
+ //0x2230: EAMW EB.D 04.D REAM
0x57, 0x45, 0x42, 0x2e, 0x44, 0x30, 0x35, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42,
+ //0x2240: WEB. D05. DREA MWEB
0x2e, 0x44, 0x30, 0x36, 0x00, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x44, 0x45,
+ //0x2250: .D06 .DRE AMWE B.DE
0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2260: M... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2270: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2280: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2290: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x22a0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x22b0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x22c0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x22d0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x22e0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x22f0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2300: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2310: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2320: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2330: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2340: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x2350: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, };
ds.assign(src, src + sizeof(src));
dreamweb();
@@ -21436,8 +17960,6 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_priest: priest(); break;
case addr_madmanstelly: madmanstelly(); break;
case addr_madman: madman(); break;
- case addr_madmantext: madmantext(); break;
- case addr_madmode: madmode(); break;
case addr_priesttext: priesttext(); break;
case addr_textforend: textforend(); break;
case addr_textformonk: textformonk(); break;
@@ -21447,14 +17969,9 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_sparky: sparky(); break;
case addr_train: train(); break;
case addr_addtopeoplelist: addtopeoplelist(); break;
- case addr_showgamereel: showgamereel(); break;
case addr_checkspeed: checkspeed(); break;
case addr_delsprite: delsprite(); break;
- case addr_checkone: checkone(); break;
- case addr_findsource: findsource(); break;
case addr_mainman: mainman(); break;
- case addr_aboutturn: aboutturn(); break;
- case addr_facerightway: facerightway(); break;
case addr_checkforexit: checkforexit(); break;
case addr_adjustdown: adjustdown(); break;
case addr_adjustup: adjustup(); break;
@@ -21464,28 +17981,16 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_initrain: initrain(); break;
case addr_splitintolines: splitintolines(); break;
case addr_getblockofpixel: getblockofpixel(); break;
- case addr_showrain: showrain(); break;
case addr_backobject: backobject(); break;
case addr_liftnoise: liftnoise(); break;
case addr_random: random(); break;
case addr_steady: steady(); break;
case addr_constant: constant(); break;
- case addr_doorway: doorway(); break;
- case addr_widedoor: widedoor(); break;
- case addr_lockeddoorway: lockeddoorway(); break;
- case addr_updatepeople: updatepeople(); break;
- case addr_getreelframeax: getreelframeax(); break;
case addr_reelsonscreen: reelsonscreen(); break;
- case addr_plotreel: plotreel(); break;
case addr_soundonreels: soundonreels(); break;
case addr_reconstruct: reconstruct(); break;
- case addr_dealwithspecial: dealwithspecial(); break;
- case addr_movemap: movemap(); break;
- case addr_getreelstart: getreelstart(); break;
- case addr_showreelframe: showreelframe(); break;
case addr_deleverything: deleverything(); break;
case addr_dumpeverything: dumpeverything(); break;
- case addr_allocatework: allocatework(); break;
case addr_showpcx: showpcx(); break;
case addr_loadpalfromiff: loadpalfromiff(); break;
case addr_setmode: setmode(); break;
@@ -21495,12 +18000,9 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_pixelcheckset: pixelcheckset(); break;
case addr_createpanel: createpanel(); break;
case addr_createpanel2: createpanel2(); break;
- case addr_clearwork: clearwork(); break;
case addr_vsync: vsync(); break;
case addr_doshake: doshake(); break;
- case addr_zoom: zoom(); break;
case addr_delthisone: delthisone(); break;
- case addr_doblocks: doblocks(); break;
case addr_transferinv: transferinv(); break;
case addr_transfermap: transfermap(); break;
case addr_fadedos: fadedos(); break;
@@ -21548,13 +18050,7 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_mode640x480: mode640x480(); break;
case addr_set16colpalette: set16colpalette(); break;
case addr_realcredits: realcredits(); break;
- case addr_printchar: printchar(); break;
- case addr_printslow: printslow(); break;
- case addr_waitframes: waitframes(); break;
- case addr_printboth: printboth(); break;
- case addr_printdirect: printdirect(); break;
case addr_monprint: monprint(); break;
- case addr_getnumber: getnumber(); break;
case addr_fillryan: fillryan(); break;
case addr_fillopen: fillopen(); break;
case addr_findallryan: findallryan(); break;
@@ -21586,7 +18082,6 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_swapwithinv: swapwithinv(); break;
case addr_swapwithopen: swapwithopen(); break;
case addr_intoinv: intoinv(); break;
- case addr_deletetaken: deletetaken(); break;
case addr_outofinv: outofinv(); break;
case addr_getfreead: getfreead(); break;
case addr_getexad: getexad(); break;
@@ -21622,21 +18117,7 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_deleteextext: deleteextext(); break;
case addr_blockget: blockget(); break;
case addr_drawfloor: drawfloor(); break;
- case addr_calcmapad: calcmapad(); break;
- case addr_getdimension: getdimension(); break;
- case addr_addalong: addalong(); break;
- case addr_addlength: addlength(); break;
- case addr_drawflags: drawflags(); break;
- case addr_showallobs: showallobs(); break;
- case addr_makebackob: makebackob(); break;
- case addr_showallfree: showallfree(); break;
case addr_showallex: showallex(); break;
- case addr_calcfrframe: calcfrframe(); break;
- case addr_finalframe: finalframe(); break;
- case addr_adjustlen: adjustlen(); break;
- case addr_getmapad: getmapad(); break;
- case addr_getxad: getxad(); break;
- case addr_getyad: getyad(); break;
case addr_autolook: autolook(); break;
case addr_look: look(); break;
case addr_dolook: dolook(); break;
@@ -21794,23 +18275,13 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_putbackobstuff: putbackobstuff(); break;
case addr_showpuztext: showpuztext(); break;
case addr_findpuztext: findpuztext(); break;
- case addr_placesetobject: placesetobject(); break;
- case addr_removesetobject: removesetobject(); break;
case addr_issetobonmap: issetobonmap(); break;
case addr_placefreeobject: placefreeobject(); break;
case addr_removefreeobject: removefreeobject(); break;
- case addr_findormake: findormake(); break;
case addr_switchryanon: switchryanon(); break;
case addr_switchryanoff: switchryanoff(); break;
- case addr_setallchanges: setallchanges(); break;
- case addr_dochange: dochange(); break;
case addr_autoappear: autoappear(); break;
- case addr_getundertimed: getundertimed(); break;
- case addr_putundertimed: putundertimed(); break;
- case addr_dumptimedtext: dumptimedtext(); break;
case addr_setuptimeduse: setuptimeduse(); break;
- case addr_setuptimedtemp: setuptimedtemp(); break;
- case addr_usetimedtext: usetimedtext(); break;
case addr_edenscdplayer: edenscdplayer(); break;
case addr_usewall: usewall(); break;
case addr_usechurchgate: usechurchgate(); break;
@@ -21909,7 +18380,6 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_makeheader: makeheader(); break;
case addr_storeit: storeit(); break;
case addr_saveseg: saveseg(); break;
- case addr_findlen: findlen(); break;
case addr_scanfornames: scanfornames(); break;
case addr_decide: decide(); break;
case addr_showdecisions: showdecisions(); break;
@@ -21930,16 +18400,12 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_out22c: out22c(); break;
case addr_playchannel0: playchannel0(); break;
case addr_playchannel1: playchannel1(); break;
- case addr_makenextblock: makenextblock(); break;
case addr_volumeadjust: volumeadjust(); break;
- case addr_loopchannel0: loopchannel0(); break;
case addr_channel0only: channel0only(); break;
case addr_channel1only: channel1only(); break;
- case addr_channel0tran: channel0tran(); break;
case addr_bothchannels: bothchannels(); break;
case addr_saveems: saveems(); break;
case addr_restoreems: restoreems(); break;
- case addr_domix: domix(); break;
case addr_dmaend: dmaend(); break;
case addr_startdmablock: startdmablock(); break;
case addr_setuppit: setuppit(); break;
@@ -21962,7 +18428,6 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_clearrest: clearrest(); break;
case addr_deallocatemem: deallocatemem(); break;
case addr_allocatemem: allocatemem(); break;
- case addr_parseblaster: parseblaster(); break;
case addr_startup: startup(); break;
case addr_startup1: startup1(); break;
case addr_screenupdate: screenupdate(); break;
@@ -21978,12 +18443,9 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_convnum: convnum(); break;
case addr_mainscreen: mainscreen(); break;
case addr_madmanrun: madmanrun(); break;
- case addr_checkcoords: checkcoords(); break;
case addr_identifyob: identifyob(); break;
- case addr_checkifperson: checkifperson(); break;
case addr_checkifset: checkifset(); break;
case addr_checkifex: checkifex(); break;
- case addr_checkiffree: checkiffree(); break;
case addr_isitdescribed: isitdescribed(); break;
case addr_findpathofpoint: findpathofpoint(); break;
case addr_findfirstpath: findfirstpath(); break;
@@ -21996,29 +18458,15 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_atmospheres: atmospheres(); break;
case addr_walkintoroom: walkintoroom(); break;
case addr_afterintroroom: afterintroroom(); break;
- case addr_obname: obname(); break;
- case addr_finishedwalking: finishedwalking(); break;
case addr_examineobtext: examineobtext(); break;
- case addr_commandwithob: commandwithob(); break;
- case addr_commandonly: commandonly(); break;
case addr_printmessage: printmessage(); break;
case addr_printmessage2: printmessage2(); break;
- case addr_blocknametext: blocknametext(); break;
- case addr_personnametext: personnametext(); break;
- case addr_walktotext: walktotext(); break;
- case addr_getflagunderp: getflagunderp(); break;
case addr_setwalk: setwalk(); break;
- case addr_autosetwalk: autosetwalk(); break;
- case addr_checkdest: checkdest(); break;
case addr_bresenhams: bresenhams(); break;
case addr_workoutframes: workoutframes(); break;
- case addr_getroomspaths: getroomspaths(); break;
- case addr_copyname: copyname(); break;
- case addr_findobname: findobname(); break;
case addr_showicon: showicon(); break;
case addr_middlepanel: middlepanel(); break;
case addr_showman: showman(); break;
- case addr_showpanel: showpanel(); break;
case addr_roomname: roomname(); break;
case addr_usecharset1: usecharset1(); break;
case addr_usetempcharset: usetempcharset(); break;
@@ -22027,8 +18475,6 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_showwatch: showwatch(); break;
case addr_gettime: gettime(); break;
case addr_zoomicon: zoomicon(); break;
- case addr_showblink: showblink(); break;
- case addr_dumpblink: dumpblink(); break;
case addr_worktoscreenm: worktoscreenm(); break;
case addr_blank: blank(); break;
case addr_allpointer: allpointer(); break;
@@ -22038,21 +18484,9 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_getunderzoom: getunderzoom(); break;
case addr_dumpzoom: dumpzoom(); break;
case addr_putunderzoom: putunderzoom(); break;
- case addr_crosshair: crosshair(); break;
- case addr_showpointer: showpointer(); break;
- case addr_delpointer: delpointer(); break;
- case addr_dumppointer: dumppointer(); break;
case addr_undertextline: undertextline(); break;
- case addr_deltextline: deltextline(); break;
- case addr_dumptextline: dumptextline(); break;
- case addr_animpointer: animpointer(); break;
case addr_setmouse: setmouse(); break;
- case addr_readmouse: readmouse(); break;
case addr_mousecall: mousecall(); break;
- case addr_readmouse1: readmouse1(); break;
- case addr_readmouse2: readmouse2(); break;
- case addr_readmouse3: readmouse3(); break;
- case addr_readmouse4: readmouse4(); break;
case addr_readkey: readkey(); break;
case addr_randomnum1: randomnum1(); break;
case addr_randomnum2: randomnum2(); break;
@@ -22071,15 +18505,10 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_restorereels: restorereels(); break;
case addr_restoreall: restoreall(); break;
case addr_sortoutmap: sortoutmap(); break;
- case addr_startloading: startloading(); break;
case addr_disablepath: disablepath(); break;
- case addr_findxyfrompath: findxyfrompath(); break;
case addr_findroominloc: findroominloc(); break;
- case addr_getroomdata: getroomdata(); break;
- case addr_readheader: readheader(); break;
case addr_dontloadseg: dontloadseg(); break;
case addr_allocateload: allocateload(); break;
- case addr_fillspace: fillspace(); break;
case addr_getridoftemp: getridoftemp(); break;
case addr_getridoftemptext: getridoftemptext(); break;
case addr_getridoftemp2: getridoftemp2(); break;
@@ -22090,7 +18519,6 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_createfile: createfile(); break;
case addr_openfile: openfile(); break;
case addr_openfilefromc: openfilefromc(); break;
- case addr_makename: makename(); break;
case addr_openfilenocheck: openfilenocheck(); break;
case addr_openforsave: openforsave(); break;
case addr_closefile: closefile(); break;
@@ -22098,7 +18526,6 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case addr_setkeyboardint: setkeyboardint(); break;
case addr_resetkeyboard: resetkeyboard(); break;
case addr_keyboardread: keyboardread(); break;
- case addr_walkandexamine: walkandexamine(); break;
case addr_doload: doload(); break;
case addr_generalerror: generalerror(); break;
default: ::error("invalid call to %04x dispatched", (uint16)ax);
diff --git a/engines/dreamweb/dreamgen.h b/engines/dreamweb/dreamgen.h
index 88ecfd53d4..fc4deeb488 100644
--- a/engines/dreamweb/dreamgen.h
+++ b/engines/dreamweb/dreamgen.h
@@ -46,7 +46,6 @@ public:
static const uint16 addr_closefile = 0xcba4;
static const uint16 addr_openforsave = 0xcba0;
static const uint16 addr_openfilenocheck = 0xcb9c;
- static const uint16 addr_makename = 0xcb98;
static const uint16 addr_openfilefromc = 0xcb94;
static const uint16 addr_openfile = 0xcb90;
static const uint16 addr_createfile = 0xcb8c;
@@ -57,15 +56,10 @@ public:
static const uint16 addr_getridoftemp2 = 0xcb78;
static const uint16 addr_getridoftemptext = 0xcb74;
static const uint16 addr_getridoftemp = 0xcb70;
- static const uint16 addr_fillspace = 0xcb6c;
static const uint16 addr_allocateload = 0xcb68;
static const uint16 addr_dontloadseg = 0xcb64;
- static const uint16 addr_readheader = 0xcb60;
- static const uint16 addr_getroomdata = 0xcb5c;
static const uint16 addr_findroominloc = 0xcb58;
- static const uint16 addr_findxyfrompath = 0xcb54;
static const uint16 addr_disablepath = 0xcb50;
- static const uint16 addr_startloading = 0xcb4c;
static const uint16 addr_sortoutmap = 0xcb48;
static const uint16 addr_restoreall = 0xcb44;
static const uint16 addr_restorereels = 0xcb40;
@@ -84,21 +78,9 @@ public:
static const uint16 addr_randomnum2 = 0xcb08;
static const uint16 addr_randomnum1 = 0xcb04;
static const uint16 addr_readkey = 0xcafc;
- static const uint16 addr_readmouse4 = 0xcaf8;
- static const uint16 addr_readmouse3 = 0xcaf4;
- static const uint16 addr_readmouse2 = 0xcaf0;
- static const uint16 addr_readmouse1 = 0xcaec;
static const uint16 addr_mousecall = 0xcae8;
- static const uint16 addr_readmouse = 0xcae4;
static const uint16 addr_setmouse = 0xcae0;
- static const uint16 addr_animpointer = 0xcadc;
- static const uint16 addr_dumptextline = 0xcad8;
- static const uint16 addr_deltextline = 0xcad4;
static const uint16 addr_undertextline = 0xcad0;
- static const uint16 addr_dumppointer = 0xcacc;
- static const uint16 addr_delpointer = 0xcac8;
- static const uint16 addr_showpointer = 0xcac4;
- static const uint16 addr_crosshair = 0xcac0;
static const uint16 addr_putunderzoom = 0xcabc;
static const uint16 addr_dumpzoom = 0xcab8;
static const uint16 addr_getunderzoom = 0xcab4;
@@ -108,8 +90,6 @@ public:
static const uint16 addr_allpointer = 0xcaa4;
static const uint16 addr_blank = 0xcaa0;
static const uint16 addr_worktoscreenm = 0xca9c;
- static const uint16 addr_dumpblink = 0xca98;
- static const uint16 addr_showblink = 0xca94;
static const uint16 addr_zoomicon = 0xca90;
static const uint16 addr_gettime = 0xca8c;
static const uint16 addr_showwatch = 0xca88;
@@ -118,29 +98,15 @@ public:
static const uint16 addr_usetempcharset = 0xca7c;
static const uint16 addr_usecharset1 = 0xca78;
static const uint16 addr_roomname = 0xca74;
- static const uint16 addr_showpanel = 0xca70;
static const uint16 addr_showman = 0xca6c;
static const uint16 addr_middlepanel = 0xca68;
static const uint16 addr_showicon = 0xca64;
- static const uint16 addr_findobname = 0xca60;
- static const uint16 addr_copyname = 0xca5c;
- static const uint16 addr_getroomspaths = 0xca58;
static const uint16 addr_workoutframes = 0xca54;
static const uint16 addr_bresenhams = 0xca50;
- static const uint16 addr_checkdest = 0xca4c;
- static const uint16 addr_autosetwalk = 0xca48;
static const uint16 addr_setwalk = 0xca44;
- static const uint16 addr_getflagunderp = 0xca40;
- static const uint16 addr_walktotext = 0xca3c;
- static const uint16 addr_personnametext = 0xca38;
- static const uint16 addr_blocknametext = 0xca34;
static const uint16 addr_printmessage2 = 0xca30;
static const uint16 addr_printmessage = 0xca2c;
- static const uint16 addr_commandonly = 0xca28;
- static const uint16 addr_commandwithob = 0xca24;
static const uint16 addr_examineobtext = 0xca20;
- static const uint16 addr_finishedwalking = 0xca1c;
- static const uint16 addr_obname = 0xca18;
static const uint16 addr_afterintroroom = 0xca14;
static const uint16 addr_walkintoroom = 0xca10;
static const uint16 addr_atmospheres = 0xca0c;
@@ -153,15 +119,11 @@ public:
static const uint16 addr_findfirstpath = 0xc9f0;
static const uint16 addr_findpathofpoint = 0xc9ec;
static const uint16 addr_isitdescribed = 0xc9e8;
- static const uint16 addr_checkiffree = 0xc9e4;
static const uint16 addr_checkifex = 0xc9e0;
static const uint16 addr_checkifset = 0xc9dc;
- static const uint16 addr_checkifperson = 0xc9d8;
static const uint16 addr_identifyob = 0xc9d4;
- static const uint16 addr_checkcoords = 0xc9d0;
static const uint16 addr_madmanrun = 0xc9cc;
static const uint16 addr_mainscreen = 0xc9c8;
- static const uint16 addr_walkandexamine = 0xcbb8;
static const uint16 addr_convnum = 0xc9c4;
static const uint16 addr_showword = 0xc9c0;
static const uint16 addr_twodigitnum = 0xc9bc;
@@ -175,7 +137,6 @@ public:
static const uint16 addr_screenupdate = 0xc99c;
static const uint16 addr_startup1 = 0xc998;
static const uint16 addr_startup = 0xc994;
- static const uint16 addr_parseblaster = 0xc990;
static const uint16 addr_allocatemem = 0xc988;
static const uint16 addr_deallocatemem = 0xc984;
static const uint16 addr_clearrest = 0xc980;
@@ -197,16 +158,12 @@ public:
static const uint16 addr_setuppit = 0xc93c;
static const uint16 addr_startdmablock = 0xc938;
static const uint16 addr_dmaend = 0xc934;
- static const uint16 addr_domix = 0xc930;
static const uint16 addr_restoreems = 0xc92c;
static const uint16 addr_saveems = 0xc928;
static const uint16 addr_bothchannels = 0xc924;
- static const uint16 addr_channel0tran = 0xc920;
static const uint16 addr_channel1only = 0xc91c;
static const uint16 addr_channel0only = 0xc918;
- static const uint16 addr_loopchannel0 = 0xc90c;
static const uint16 addr_volumeadjust = 0xc908;
- static const uint16 addr_makenextblock = 0xc904;
static const uint16 addr_playchannel1 = 0xc900;
static const uint16 addr_playchannel0 = 0xc8fc;
static const uint16 addr_out22c = 0xc8f8;
@@ -223,12 +180,11 @@ public:
static const uint16 addr_createname = 0xc8cc;
static const uint16 addr_loadspeech = 0xc8c8;
static const uint16 addr_loadold = 0xc8c4;
- static const uint16 addr_doload = 0xcbbc;
+ static const uint16 addr_doload = 0xcbb8;
static const uint16 addr_newgame = 0xc8c0;
static const uint16 addr_showdecisions = 0xc8bc;
static const uint16 addr_decide = 0xc8b8;
static const uint16 addr_scanfornames = 0xc8b4;
- static const uint16 addr_findlen = 0xc8b0;
static const uint16 addr_saveseg = 0xc8ac;
static const uint16 addr_storeit = 0xc8a8;
static const uint16 addr_makeheader = 0xc8a4;
@@ -240,7 +196,7 @@ public:
static const uint16 addr_oldtonames = 0xc88c;
static const uint16 addr_namestoold = 0xc888;
static const uint16 addr_error = 0xc884;
- static const uint16 addr_generalerror = 0xcbc0;
+ static const uint16 addr_generalerror = 0xcbbc;
static const uint16 addr_dosreturn = 0xc880;
static const uint16 addr_shownames = 0xc87c;
static const uint16 addr_showslots = 0xc878;
@@ -328,23 +284,13 @@ public:
static const uint16 addr_usechurchgate = 0xc730;
static const uint16 addr_usewall = 0xc72c;
static const uint16 addr_edenscdplayer = 0xc728;
- static const uint16 addr_usetimedtext = 0xc724;
- static const uint16 addr_setuptimedtemp = 0xc720;
static const uint16 addr_setuptimeduse = 0xc71c;
- static const uint16 addr_dumptimedtext = 0xc718;
- static const uint16 addr_putundertimed = 0xc714;
- static const uint16 addr_getundertimed = 0xc710;
static const uint16 addr_autoappear = 0xc70c;
- static const uint16 addr_dochange = 0xc708;
- static const uint16 addr_setallchanges = 0xc704;
static const uint16 addr_switchryanoff = 0xc700;
static const uint16 addr_switchryanon = 0xc6fc;
- static const uint16 addr_findormake = 0xc6f8;
static const uint16 addr_removefreeobject = 0xc6f4;
static const uint16 addr_placefreeobject = 0xc6f0;
static const uint16 addr_issetobonmap = 0xc6ec;
- static const uint16 addr_removesetobject = 0xc6e8;
- static const uint16 addr_placesetobject = 0xc6e4;
static const uint16 addr_findpuztext = 0xc6e0;
static const uint16 addr_showpuztext = 0xc6dc;
static const uint16 addr_putbackobstuff = 0xc6d8;
@@ -502,21 +448,7 @@ public:
static const uint16 addr_dolook = 0xc474;
static const uint16 addr_look = 0xc470;
static const uint16 addr_autolook = 0xc46c;
- static const uint16 addr_getyad = 0xc468;
- static const uint16 addr_getxad = 0xc464;
- static const uint16 addr_getmapad = 0xc460;
- static const uint16 addr_adjustlen = 0xc45c;
- static const uint16 addr_finalframe = 0xc458;
- static const uint16 addr_calcfrframe = 0xc454;
static const uint16 addr_showallex = 0xc450;
- static const uint16 addr_showallfree = 0xc44c;
- static const uint16 addr_makebackob = 0xc448;
- static const uint16 addr_showallobs = 0xc444;
- static const uint16 addr_drawflags = 0xc43c;
- static const uint16 addr_addlength = 0xc438;
- static const uint16 addr_addalong = 0xc434;
- static const uint16 addr_getdimension = 0xc430;
- static const uint16 addr_calcmapad = 0xc42c;
static const uint16 addr_drawfloor = 0xc428;
static const uint16 addr_blockget = 0xc424;
static const uint16 addr_deleteextext = 0xc420;
@@ -552,7 +484,6 @@ public:
static const uint16 addr_getexad = 0xc3a8;
static const uint16 addr_getfreead = 0xc3a4;
static const uint16 addr_outofinv = 0xc3a0;
- static const uint16 addr_deletetaken = 0xc39c;
static const uint16 addr_intoinv = 0xc398;
static const uint16 addr_swapwithopen = 0xc394;
static const uint16 addr_swapwithinv = 0xc390;
@@ -584,13 +515,7 @@ public:
static const uint16 addr_findallryan = 0xc328;
static const uint16 addr_fillopen = 0xc324;
static const uint16 addr_fillryan = 0xc320;
- static const uint16 addr_getnumber = 0xc318;
static const uint16 addr_monprint = 0xc314;
- static const uint16 addr_printdirect = 0xc310;
- static const uint16 addr_printboth = 0xc30c;
- static const uint16 addr_waitframes = 0xc308;
- static const uint16 addr_printslow = 0xc304;
- static const uint16 addr_printchar = 0xc2fc;
static const uint16 addr_realcredits = 0xc2f8;
static const uint16 addr_set16colpalette = 0xc2f4;
static const uint16 addr_mode640x480 = 0xc2f0;
@@ -638,12 +563,9 @@ public:
static const uint16 addr_fadedos = 0xc248;
static const uint16 addr_transfermap = 0xc244;
static const uint16 addr_transferinv = 0xc240;
- static const uint16 addr_doblocks = 0xc228;
static const uint16 addr_delthisone = 0xc214;
- static const uint16 addr_zoom = 0xc210;
static const uint16 addr_doshake = 0xc20c;
static const uint16 addr_vsync = 0xc208;
- static const uint16 addr_clearwork = 0xc204;
static const uint16 addr_createpanel2 = 0xc200;
static const uint16 addr_createpanel = 0xc1fc;
static const uint16 addr_pixelcheckset = 0xc1f8;
@@ -653,28 +575,16 @@ public:
static const uint16 addr_setmode = 0xc1dc;
static const uint16 addr_loadpalfromiff = 0xc1d8;
static const uint16 addr_showpcx = 0xc1cc;
- static const uint16 addr_allocatework = 0xc1c8;
static const uint16 addr_dumpeverything = 0xc1c4;
static const uint16 addr_deleverything = 0xc1c0;
- static const uint16 addr_showreelframe = 0xc1bc;
- static const uint16 addr_getreelstart = 0xc1b8;
- static const uint16 addr_movemap = 0xc1b4;
- static const uint16 addr_dealwithspecial = 0xc1b0;
static const uint16 addr_reconstruct = 0xc1ac;
static const uint16 addr_soundonreels = 0xc1a8;
- static const uint16 addr_plotreel = 0xc1a4;
static const uint16 addr_reelsonscreen = 0xc1a0;
- static const uint16 addr_getreelframeax = 0xc19c;
- static const uint16 addr_updatepeople = 0xc198;
- static const uint16 addr_lockeddoorway = 0xc194;
- static const uint16 addr_widedoor = 0xc18c;
- static const uint16 addr_doorway = 0xc188;
static const uint16 addr_constant = 0xc184;
static const uint16 addr_steady = 0xc180;
static const uint16 addr_random = 0xc17c;
static const uint16 addr_liftnoise = 0xc178;
static const uint16 addr_backobject = 0xc170;
- static const uint16 addr_showrain = 0xc16c;
static const uint16 addr_getblockofpixel = 0xc168;
static const uint16 addr_splitintolines = 0xc164;
static const uint16 addr_initrain = 0xc160;
@@ -684,14 +594,9 @@ public:
static const uint16 addr_adjustup = 0xc150;
static const uint16 addr_adjustdown = 0xc14c;
static const uint16 addr_checkforexit = 0xc148;
- static const uint16 addr_facerightway = 0xc144;
- static const uint16 addr_aboutturn = 0xc13c;
static const uint16 addr_mainman = 0xc138;
- static const uint16 addr_findsource = 0xc130;
- static const uint16 addr_checkone = 0xc12c;
static const uint16 addr_delsprite = 0xc11c;
static const uint16 addr_checkspeed = 0xc110;
- static const uint16 addr_showgamereel = 0xc10c;
static const uint16 addr_addtopeoplelist = 0xc108;
static const uint16 addr_train = 0xc104;
static const uint16 addr_sparky = 0xc100;
@@ -701,8 +606,6 @@ public:
static const uint16 addr_textformonk = 0xc0f0;
static const uint16 addr_textforend = 0xc0ec;
static const uint16 addr_priesttext = 0xc0e8;
- static const uint16 addr_madmode = 0xc0e4;
- static const uint16 addr_madmantext = 0xc0e0;
static const uint16 addr_madman = 0xc0dc;
static const uint16 addr_madmanstelly = 0xc0d8;
static const uint16 addr_priest = 0xc0d4;
@@ -759,583 +662,628 @@ public:
static const uint16 addr_foghornsound = 0xc008;
static const uint16 addr_intromusic = 0xc004;
static const uint16 addr_alleybarksound = 0xc000;
- const static uint16 kStartvars = 0;
- const static uint16 kProgresspoints = 1;
- const static uint16 kWatchon = 2;
- const static uint16 kShadeson = 3;
- const static uint16 kSecondcount = 4;
- const static uint16 kMinutecount = 5;
- const static uint16 kHourcount = 6;
- const static uint16 kZoomon = 7;
- const static uint16 kLocation = 8;
- const static uint16 kExpos = 9;
- const static uint16 kExframepos = 10;
- const static uint16 kExtextpos = 12;
- const static uint16 kCard1money = 14;
- const static uint16 kListpos = 16;
- const static uint16 kRyanpage = 18;
- const static uint16 kWatchingtime = 19;
- const static uint16 kReeltowatch = 21;
- const static uint16 kEndwatchreel = 23;
- const static uint16 kSpeedcount = 25;
- const static uint16 kWatchspeed = 26;
- const static uint16 kReeltohold = 27;
- const static uint16 kEndofholdreel = 29;
- const static uint16 kWatchmode = 31;
- const static uint16 kDestafterhold = 32;
- const static uint16 kNewsitem = 33;
- const static uint16 kLiftflag = 34;
- const static uint16 kLiftpath = 35;
- const static uint16 kLockstatus = 36;
- const static uint16 kDoorpath = 37;
- const static uint16 kCounttoopen = 38;
- const static uint16 kCounttoclose = 39;
- const static uint16 kRockstardead = 40;
- const static uint16 kGeneraldead = 41;
- const static uint16 kSartaindead = 42;
- const static uint16 kAidedead = 43;
- const static uint16 kBeenmugged = 44;
- const static uint16 kGunpassflag = 45;
- const static uint16 kCanmovealtar = 46;
- const static uint16 kTalkedtoattendant = 47;
- const static uint16 kTalkedtosparky = 48;
- const static uint16 kTalkedtoboss = 49;
- const static uint16 kTalkedtorecep = 50;
- const static uint16 kCardpassflag = 51;
- const static uint16 kMadmanflag = 52;
- const static uint16 kKeeperflag = 53;
- const static uint16 kLasttrigger = 54;
- const static uint16 kMandead = 55;
- const static uint16 kSeed = 56;
- const static uint16 kNeedtotravel = 59;
- const static uint16 kThroughdoor = 60;
- const static uint16 kNewobs = 61;
- const static uint16 kRyanon = 62;
- const static uint16 kCombatcount = 63;
- const static uint16 kLastweapon = 64;
- const static uint16 kDreamnumber = 65;
- const static uint16 kRoomafterdream = 66;
- const static uint16 kShakecounter = 67;
- const static uint16 kSpeechcount = 68;
- const static uint16 kCharshift = 69;
- const static uint16 kKerning = 71;
- const static uint16 kBrightness = 72;
- const static uint16 kRoomloaded = 73;
- const static uint16 kDidzoom = 74;
- const static uint16 kLinespacing = 75;
- const static uint16 kTextaddressx = 77;
- const static uint16 kTextaddressy = 79;
- const static uint16 kTextlen = 81;
- const static uint16 kLastxpos = 82;
- const static uint16 kIcontop = 84;
- const static uint16 kIconleft = 86;
- const static uint16 kItemframe = 88;
- const static uint16 kItemtotran = 89;
- const static uint16 kRoomad = 90;
- const static uint16 kOldsubject = 92;
- const static uint16 kWithobject = 94;
- const static uint16 kWithtype = 95;
- const static uint16 kLookcounter = 96;
- const static uint16 kCommand = 98;
- const static uint16 kCommandtype = 99;
- const static uint16 kOldcommandtype = 100;
- const static uint16 kObjecttype = 101;
- const static uint16 kGetback = 102;
- const static uint16 kInvopen = 103;
- const static uint16 kMainmode = 104;
- const static uint16 kPickup = 105;
- const static uint16 kLastinvpos = 106;
- const static uint16 kExamagain = 107;
- const static uint16 kNewtextline = 108;
- const static uint16 kOpenedob = 109;
- const static uint16 kOpenedtype = 110;
- const static uint16 kOldmapadx = 111;
- const static uint16 kOldmapady = 113;
- const static uint16 kMapadx = 115;
- const static uint16 kMapady = 117;
- const static uint16 kMapoffsetx = 119;
- const static uint16 kMapoffsety = 121;
- const static uint16 kMapxstart = 123;
- const static uint16 kMapystart = 125;
- const static uint16 kMapxsize = 127;
- const static uint16 kMapysize = 128;
- const static uint16 kHavedoneobs = 129;
- const static uint16 kManisoffscreen = 130;
- const static uint16 kRainspace = 131;
- const static uint16 kFacing = 132;
- const static uint16 kLeavedirection = 133;
- const static uint16 kTurntoface = 134;
- const static uint16 kTurndirection = 135;
- const static uint16 kMaintimer = 136;
- const static uint16 kIntrocount = 138;
- const static uint16 kArrowad = 139;
- const static uint16 kCurrentkey = 141;
- const static uint16 kOldkey = 142;
- const static uint16 kUseddirection = 143;
- const static uint16 kCurrentkey2 = 144;
- const static uint16 kTimercount = 145;
- const static uint16 kOldtimercount = 146;
- const static uint16 kMapx = 147;
- const static uint16 kMapy = 148;
- const static uint16 kNewscreen = 149;
- const static uint16 kRyanx = 150;
- const static uint16 kRyany = 151;
- const static uint16 kLastflag = 152;
- const static uint16 kLastflagex = 153;
- const static uint16 kFlagx = 154;
- const static uint16 kFlagy = 155;
- const static uint16 kCurrentex = 156;
- const static uint16 kCurrentfree = 157;
- const static uint16 kCurrentframe = 158;
- const static uint16 kFramesad = 160;
- const static uint16 kDataad = 162;
- const static uint16 kFrsegment = 164;
- const static uint16 kObjectx = 166;
- const static uint16 kObjecty = 168;
- const static uint16 kOffsetx = 170;
- const static uint16 kOffsety = 172;
- const static uint16 kSavesize = 174;
- const static uint16 kSavesource = 176;
- const static uint16 kSavex = 178;
- const static uint16 kSavey = 179;
- const static uint16 kCurrentob = 180;
- const static uint16 kPrioritydep = 181;
- const static uint16 kDestpos = 182;
- const static uint16 kReallocation = 183;
- const static uint16 kRoomnum = 184;
- const static uint16 kNowinnewroom = 185;
- const static uint16 kResetmanxy = 186;
- const static uint16 kNewlocation = 187;
- const static uint16 kAutolocation = 188;
- const static uint16 kMustload = 189;
- const static uint16 kAnswered = 190;
- const static uint16 kSaidno = 191;
- const static uint16 kDoorcheck1 = 192;
- const static uint16 kDoorcheck2 = 193;
- const static uint16 kDoorcheck3 = 194;
- const static uint16 kDoorcheck4 = 195;
- const static uint16 kMousex = 196;
- const static uint16 kMousey = 198;
- const static uint16 kMousebutton = 200;
- const static uint16 kMousebutton1 = 202;
- const static uint16 kMousebutton2 = 204;
- const static uint16 kMousebutton3 = 206;
- const static uint16 kMousebutton4 = 208;
- const static uint16 kOldbutton = 210;
- const static uint16 kOldx = 212;
- const static uint16 kOldy = 214;
- const static uint16 kLastbutton = 216;
- const static uint16 kOldpointerx = 218;
- const static uint16 kOldpointery = 220;
- const static uint16 kDelherex = 222;
- const static uint16 kDelherey = 224;
- const static uint16 kPointerxs = 226;
- const static uint16 kPointerys = 227;
- const static uint16 kDelxs = 228;
- const static uint16 kDelys = 229;
- const static uint16 kPointerframe = 230;
- const static uint16 kPointerpower = 231;
- const static uint16 kAuxpointerframe = 232;
- const static uint16 kPointermode = 233;
- const static uint16 kPointerspeed = 234;
- const static uint16 kPointercount = 235;
- const static uint16 kInmaparea = 236;
- const static uint16 kReelpointer = 237;
- const static uint16 kSlotdata = 239;
- const static uint16 kThisslot = 240;
- const static uint16 kSlotflags = 241;
- const static uint16 kTakeoff = 242;
- const static uint16 kTalkmode = 244;
- const static uint16 kTalkpos = 245;
- const static uint16 kCharacter = 246;
- const static uint16 kPersondata = 247;
- const static uint16 kTalknum = 249;
- const static uint16 kNumberinroom = 250;
- const static uint16 kCurrentcel = 251;
- const static uint16 kOldselection = 252;
- const static uint16 kStopwalking = 253;
- const static uint16 kMouseon = 254;
- const static uint16 kPlayed = 255;
- const static uint16 kTimer1 = 257;
- const static uint16 kTimer2 = 258;
- const static uint16 kTimer3 = 259;
- const static uint16 kWholetimer = 260;
- const static uint16 kTimer1to = 262;
- const static uint16 kTimer2to = 263;
- const static uint16 kTimer3to = 264;
- const static uint16 kWatchdump = 265;
- const static uint16 kCurrentset = 266;
- const static uint16 kLogonum = 268;
- const static uint16 kOldlogonum = 269;
- const static uint16 kNewlogonum = 270;
- const static uint16 kNetseg = 271;
- const static uint16 kNetpoint = 273;
- const static uint16 kKeynum = 275;
- const static uint16 kCursorstate = 276;
- const static uint16 kPressed = 277;
- const static uint16 kPresspointer = 278;
- const static uint16 kGraphicpress = 280;
- const static uint16 kPresscount = 281;
- const static uint16 kKeypadax = 282;
- const static uint16 kKeypadcx = 284;
- const static uint16 kLightcount = 286;
- const static uint16 kFolderpage = 287;
- const static uint16 kDiarypage = 288;
- const static uint16 kMenucount = 289;
- const static uint16 kSymboltopx = 290;
- const static uint16 kSymboltopnum = 291;
- const static uint16 kSymboltopdir = 292;
- const static uint16 kSymbolbotx = 293;
- const static uint16 kSymbolbotnum = 294;
- const static uint16 kSymbolbotdir = 295;
- const static uint16 kSymboltolight = 296;
- const static uint16 kSymbol1 = 297;
- const static uint16 kSymbol2 = 298;
- const static uint16 kSymbol3 = 299;
- const static uint16 kSymbolnum = 300;
- const static uint16 kDumpx = 301;
- const static uint16 kDumpy = 303;
- const static uint16 kWalkandexam = 305;
- const static uint16 kWalkexamtype = 306;
- const static uint16 kWalkexamnum = 307;
- const static uint16 kCursloc = 308;
- const static uint16 kCurslocx = 310;
- const static uint16 kCurslocy = 312;
- const static uint16 kCurpos = 314;
- const static uint16 kMonadx = 316;
- const static uint16 kMonady = 318;
- const static uint16 kGotfrom = 320;
- const static uint16 kMonsource = 322;
- const static uint16 kNumtodo = 324;
- const static uint16 kTimecount = 326;
- const static uint16 kCounttotimed = 328;
- const static uint16 kTimedseg = 330;
- const static uint16 kTimedoffset = 332;
- const static uint16 kTimedy = 334;
- const static uint16 kTimedx = 335;
- const static uint16 kNeedtodumptimed = 336;
- const static uint16 kHandle = 337;
- const static uint16 kLoadingorsave = 339;
- const static uint16 kCurrentslot = 340;
- const static uint16 kCursorpos = 341;
- const static uint16 kColourpos = 342;
- const static uint16 kFadedirection = 343;
- const static uint16 kNumtofade = 344;
- const static uint16 kFadecount = 345;
- const static uint16 kAddtogreen = 346;
- const static uint16 kAddtored = 347;
- const static uint16 kAddtoblue = 348;
- const static uint16 kLastsoundreel = 349;
- const static uint16 kSoundbuffer = 351;
- const static uint16 kSoundbufferad = 353;
- const static uint16 kSoundbufferpage = 355;
- const static uint16 kSoundtimes = 356;
- const static uint16 kNeedsoundbuff = 357;
- const static uint16 kOldint9seg = 358;
- const static uint16 kOldint9add = 360;
- const static uint16 kOldint8seg = 362;
- const static uint16 kOldint8add = 364;
- const static uint16 kOldsoundintseg = 366;
- const static uint16 kOldsoundintadd = 368;
- const static uint16 kSoundbaseadd = 370;
- const static uint16 kDsp_status = 372;
- const static uint16 kDsp_write = 374;
- const static uint16 kDmaaddress = 376;
- const static uint16 kSoundint = 377;
- const static uint16 kSounddmachannel = 378;
- const static uint16 kSampleplaying = 379;
- const static uint16 kTestresult = 380;
- const static uint16 kCurrentirq = 381;
- const static uint16 kSpeechloaded = 382;
- const static uint16 kSpeechlength = 383;
- const static uint16 kVolume = 385;
- const static uint16 kVolumeto = 386;
- const static uint16 kVolumedirection = 387;
- const static uint16 kVolumecount = 388;
- const static uint16 kPlayblock = 389;
- const static uint16 kWongame = 390;
- const static uint16 kLasthardkey = 391;
- const static uint16 kBufferin = 392;
- const static uint16 kBufferout = 394;
- const static uint16 kExtras = 396;
- const static uint16 kWorkspace = 398;
- const static uint16 kMapstore = 400;
- const static uint16 kCharset1 = 402;
- const static uint16 kTempcharset = 404;
- const static uint16 kIcons1 = 406;
- const static uint16 kIcons2 = 408;
- const static uint16 kBuffers = 410;
- const static uint16 kMainsprites = 412;
- const static uint16 kBackdrop = 414;
- const static uint16 kMapdata = 416;
- const static uint16 kSounddata = 418;
- const static uint16 kSounddata2 = 420;
- const static uint16 kRecordspace = 422;
- const static uint16 kFreedat = 424;
- const static uint16 kSetdat = 426;
- const static uint16 kReel1 = 428;
- const static uint16 kReel2 = 430;
- const static uint16 kReel3 = 432;
- const static uint16 kRoomdesc = 434;
- const static uint16 kFreedesc = 436;
- const static uint16 kSetdesc = 438;
- const static uint16 kBlockdesc = 440;
- const static uint16 kSetframes = 442;
- const static uint16 kFreeframes = 444;
- const static uint16 kPeople = 446;
- const static uint16 kReels = 448;
- const static uint16 kCommandtext = 450;
- const static uint16 kPuzzletext = 452;
- const static uint16 kTraveltext = 454;
- const static uint16 kTempgraphics = 456;
- const static uint16 kTempgraphics2 = 458;
- const static uint16 kTempgraphics3 = 460;
- const static uint16 kTempsprites = 462;
- const static uint16 kTextfile1 = 464;
- const static uint16 kTextfile2 = 466;
- const static uint16 kTextfile3 = 468;
- const static uint16 kBlinkframe = 470;
- const static uint16 kBlinkcount = 471;
- const static uint16 kReasseschanges = 472;
- const static uint16 kPointerspath = 473;
- const static uint16 kManspath = 474;
- const static uint16 kPointerfirstpath = 475;
- const static uint16 kFinaldest = 476;
- const static uint16 kDestination = 477;
- const static uint16 kLinestartx = 478;
- const static uint16 kLinestarty = 480;
- const static uint16 kLineendx = 482;
- const static uint16 kLineendy = 484;
- const static uint16 kIncrement1 = 486;
- const static uint16 kIncrement2 = 488;
- const static uint16 kLineroutine = 490;
- const static uint16 kLinepointer = 491;
- const static uint16 kLinedirection = 492;
- const static uint16 kLinelength = 493;
- const static uint16 kLiftsoundcount = 494;
- const static uint16 kEmmhandle = 495;
- const static uint16 kEmmpageframe = 497;
- const static uint16 kEmmhardwarepage = 499;
- const static uint16 kCh0emmpage = 500;
- const static uint16 kCh0offset = 502;
- const static uint16 kCh0blockstocopy = 504;
- const static uint16 kCh0playing = 506;
- const static uint16 kCh0repeat = 507;
- const static uint16 kCh0oldemmpage = 508;
- const static uint16 kCh0oldoffset = 510;
- const static uint16 kCh0oldblockstocopy = 512;
- const static uint16 kCh1playing = 514;
- const static uint16 kCh1emmpage = 515;
- const static uint16 kCh1offset = 517;
- const static uint16 kCh1blockstocopy = 519;
- const static uint16 kCh1blocksplayed = 521;
- const static uint16 kSoundbufferwrite = 523;
- const static uint16 kSoundemmpage = 525;
- const static uint16 kSpeechemmpage = 527;
- const static uint16 kCurrentsample = 529;
- const static uint16 kRoomssample = 530;
- const static uint16 kGameerror = 531;
- const static uint16 kHowmuchalloc = 532;
- const static uint16 kReelroutines = 534;
- const static uint16 kReelcalls = 991;
- const static uint16 kRoombyroom = 1214;
- const static uint16 kR0 = 1326;
- const static uint16 kR1 = 1327;
- const static uint16 kR2 = 1331;
- const static uint16 kR6 = 1350;
- const static uint16 kR8 = 1357;
- const static uint16 kR9 = 1373;
- const static uint16 kR10 = 1380;
- const static uint16 kR11 = 1384;
- const static uint16 kR12 = 1388;
- const static uint16 kR13 = 1392;
- const static uint16 kR14 = 1405;
- const static uint16 kR20 = 1439;
- const static uint16 kR22 = 1461;
- const static uint16 kR23 = 1492;
- const static uint16 kR25 = 1505;
- const static uint16 kR26 = 1527;
- const static uint16 kR27 = 1549;
- const static uint16 kR28 = 1574;
- const static uint16 kR29 = 1593;
- const static uint16 kR45 = 1609;
- const static uint16 kR46 = 1616;
- const static uint16 kR47 = 1653;
- const static uint16 kR52 = 1666;
- const static uint16 kR53 = 1670;
- const static uint16 kR55 = 1677;
- const static uint16 kSpritename1 = 1819;
- const static uint16 kSpritename3 = 1832;
- const static uint16 kIdname = 1845;
- const static uint16 kCharacterset1 = 1857;
- const static uint16 kCharacterset2 = 1870;
- const static uint16 kCharacterset3 = 1883;
- const static uint16 kSamplename = 1896;
- const static uint16 kBasicsample = 1909;
- const static uint16 kIcongraphics0 = 1922;
- const static uint16 kIcongraphics1 = 1935;
- const static uint16 kExtragraphics1 = 1948;
- const static uint16 kIcongraphics8 = 1961;
- const static uint16 kMongraphicname = 1974;
- const static uint16 kMongraphics2 = 1987;
- const static uint16 kCityname = 2000;
- const static uint16 kTravelgraphic1 = 2013;
- const static uint16 kTravelgraphic2 = 2026;
- const static uint16 kDiarygraphic = 2039;
- const static uint16 kMonitorfile1 = 2052;
- const static uint16 kMonitorfile2 = 2065;
- const static uint16 kMonitorfile10 = 2078;
- const static uint16 kMonitorfile11 = 2091;
- const static uint16 kMonitorfile12 = 2104;
- const static uint16 kMonitorfile13 = 2117;
- const static uint16 kMonitorfile20 = 2130;
- const static uint16 kMonitorfile21 = 2143;
- const static uint16 kMonitorfile22 = 2156;
- const static uint16 kMonitorfile23 = 2169;
- const static uint16 kMonitorfile24 = 2182;
- const static uint16 kFoldertext = 2195;
- const static uint16 kDiarytext = 2208;
- const static uint16 kPuzzletextname = 2221;
- const static uint16 kTraveltextname = 2234;
- const static uint16 kIntrotextname = 2247;
- const static uint16 kEndtextname = 2260;
- const static uint16 kCommandtextname = 2273;
- const static uint16 kVolumetabname = 2286;
- const static uint16 kFoldergraphic1 = 2299;
- const static uint16 kFoldergraphic2 = 2312;
- const static uint16 kFoldergraphic3 = 2325;
- const static uint16 kSymbolgraphic = 2338;
- const static uint16 kGungraphic = 2351;
- const static uint16 kMonkface = 2364;
- const static uint16 kTitle0graphics = 2377;
- const static uint16 kTitle1graphics = 2390;
- const static uint16 kTitle2graphics = 2403;
- const static uint16 kTitle3graphics = 2416;
- const static uint16 kTitle4graphics = 2429;
- const static uint16 kTitle5graphics = 2442;
- const static uint16 kTitle6graphics = 2455;
- const static uint16 kTitle7graphics = 2468;
- const static uint16 kPalettescreen = 2481;
- const static uint16 kCurrentfile = 2970;
- const static uint16 kDmaaddresses = 5118;
- const static uint16 kFileheader = 6091;
- const static uint16 kFiledata = 6141;
- const static uint16 kExtradata = 6181;
- const static uint16 kRoomdata = 6187;
- const static uint16 kMadeuproomdat = 7979;
- const static uint16 kRoomscango = 8011;
- const static uint16 kRoompics = 8027;
- const static uint16 kOplist = 8042;
- const static uint16 kInputline = 8045;
- const static uint16 kLinedata = 8173;
- const static uint16 kPresslist = 8573;
- const static uint16 kSavenames = 8579;
- const static uint16 kSavefiles = 8698;
- const static uint16 kRecname = 8789;
- const static uint16 kQuitrequested = 8802;
- const static uint16 kSubtitles = 8803;
- const static uint16 kForeignrelease = 8804;
- const static uint16 kStak = 8805;
- const static uint16 kBlocktextdat = (0);
- const static uint16 kPersonframes = (0);
- const static uint16 kDebuglevel1 = (0);
- const static uint16 kDebuglevel2 = (0);
- const static uint16 kPlayback = (0);
- const static uint16 kMap = (0);
- const static uint16 kSettextdat = (0);
- const static uint16 kSpanish = (0);
- const static uint16 kFramedata = (0);
- const static uint16 kRecording = (0);
- const static uint16 kFlags = (0);
- const static uint16 kGerman = (0);
- const static uint16 kTextunder = (0);
- const static uint16 kPathdata = (0);
- const static uint16 kDemo = (0);
- const static uint16 kExframedata = (0);
- const static uint16 kIntextdat = (0);
- const static uint16 kFreetextdat = (0);
- const static uint16 kFrframedata = (0);
- const static uint16 kSettext = (0+(130*2));
- const static uint16 kOpeninvlist = (0+(228*13));
- const static uint16 kRyaninvlist = (0+(228*13)+32);
- const static uint16 kPointerback = (0+(228*13)+32+60);
- const static uint16 kMapflags = (0+(228*13)+32+60+(32*32));
- const static uint16 kStartpal = (0+(228*13)+32+60+(32*32)+(11*10*3));
- const static uint16 kEndpal = (0+(228*13)+32+60+(32*32)+(11*10*3)+768);
- const static uint16 kMaingamepal = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768);
- const static uint16 kSpritetable = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768);
- const static uint16 kSetlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32));
- const static uint16 kFreelist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5));
- const static uint16 kExlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5));
- const static uint16 kPeoplelist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5));
- const static uint16 kZoomspace = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5));
- const static uint16 kPrintedlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40));
- const static uint16 kListofchanges = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80));
- const static uint16 kUndertimedtext = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4));
- const static uint16 kRainlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30));
- const static uint16 kInitialreelrouts = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64));
- const static uint16 kInitialvars = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+991-534);
- const static uint16 kLengthofbuffer = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+991-534+68-0);
- const static uint16 kReellist = (0+(36*144));
- const static uint16 kIntext = (0+(38*2));
- const static uint16 kLengthofmap = (0+(66*60));
- const static uint16 kFreetext = (0+(82*2));
- const static uint16 kBlocktext = (0+(98*2));
- const static uint16 kBlocks = (0+192);
- const static uint16 kFrframes = (0+2080);
- const static uint16 kExframes = (0+2080);
- const static uint16 kFrames = (0+2080);
- const static uint16 kExdata = (0+2080+30000);
- const static uint16 kExtextdat = (0+2080+30000+(16*114));
- const static uint16 kExtext = (0+2080+30000+(16*114)+((114+2)*2));
- const static uint16 kLengthofextra = (0+2080+30000+(16*114)+((114+2)*2)+18000);
- const static uint16 kPersontxtdat = (0+24);
- const static uint16 kPersontext = (0+24+(1026*2));
- const static uint16 kInputport = (0x63);
- const static uint16 kForeign = (1);
- const static uint16 kCd = (1);
- const static uint16 kNumexobjects = (114);
- const static uint16 kUndertextsizey = (13);
- const static uint16 kZoomy = (132);
- const static uint16 kFreedatlen = (16*80);
- const static uint16 kExtextlen = (18000);
- const static uint16 kLenofmapstore = (22*8*20*8);
- const static uint16 kUndertextsizex = (228);
- const static uint16 kNumchanges = (250);
- const static uint16 kUndertimedysize = (30);
- const static uint16 kExframeslen = (30000);
- const static uint16 kTablesize = (32);
- const static uint16 kScreenwidth = (320);
- const static uint16 kKeypadx = (36+112);
- const static uint16 kItempicsize = (44);
- const static uint16 kDiaryy = (48+12);
- const static uint16 kOpsy = (52);
- const static uint16 kSymboly = (56);
- const static uint16 kInventy = (58);
- const static uint16 kMenuy = (60);
- const static uint16 kOpsx = (60);
- const static uint16 kMaplength = (60);
- const static uint16 kHeaderlen = (6187-6091);
- const static uint16 kSymbolx = (64);
- const static uint16 kSetdatlen = (64*128);
- const static uint16 kMapwidth = (66);
- const static uint16 kTextstart = (66*2);
- const static uint16 kMaplen = (66*60);
- const static uint16 kDiaryx = (68+24);
- const static uint16 kLengthofvars = (68-0);
- const static uint16 kKeypady = (72);
- const static uint16 kZoomx = (8);
- const static uint16 kInventx = (80);
- const static uint16 kMenux = (80+40);
- const static uint16 kLenofreelrouts = (991-534);
+ static const uint16 offset_quitlist = 0x0a84;
+ static const uint16 offset_savelist = 0x0f44;
+ static const uint16 offset_mainlist = 0x1402;
+ static const uint16 offset_gameerror8 = 0x113f;
+ static const uint16 offset_gameerror5 = 0x1074;
+ static const uint16 offset_error2patch = 0x0ff6;
+ static const uint16 offset_openchangesize = 0x0a1c;
+ static const uint16 offset_keys = 0x0b14;
+ static const uint16 offset_mainlist2 = 0x1440;
+ static const uint16 offset_uselist = 0x0ba8;
+ static const uint16 offset_gameerror2 = 0x0fb2;
+ static const uint16 offset_loadlist = 0x0ef0;
+ static const uint16 offset_gameerror6 = 0x10be;
+ static const uint16 offset_speechfile = 0x13f1;
+ static const uint16 offset_atmospherelist = 0x147e;
+ static const uint16 offset_gameerror4 = 0x1037;
+ static const uint16 offset_gameerror1 = 0x0f6e;
+ static const uint16 offset_examlist = 0x09be;
+ static const uint16 offset_gameinfo = 0x1170;
+ static const uint16 offset_opslist = 0x0ec6;
+ static const uint16 offset_invlist1 = 0x09fc;
+ static const uint16 offset_money2poke = 0x0d97;
+ static const uint16 offset_talklist = 0x0a64;
+ static const uint16 offset_menulist = 0x0e1e;
+ static const uint16 offset_comlist = 0x0ad8;
+ static const uint16 offset_withlist1 = 0x0a3a;
+ static const uint16 offset_money1poke = 0x0d92;
+ static const uint16 offset_gameerror7 = 0x1104;
+ static const uint16 offset_discopslist = 0x0f1a;
+ static const uint16 offset_commandline = 0x16d7;
+ static const uint16 offset_destlist = 0x0a9a;
+ static const uint16 offset_shaketable = 0x06af;
+ static const uint16 offset_error6patch = 0x10fe;
+ static const uint16 offset_keybuffer = 0x1718;
+ static const uint16 offset_speechfilename = 0x13eb;
+ static const uint16 offset_rootdir = 0x0b8c;
+ static const uint16 offset_gameerror3 = 0x1003;
+ static const uint16 offset_rainlocations = 0x0459;
+ static const uint16 offset_diarylist = 0x0e9c;
+ static const uint16 offset_decidelist = 0x13c1;
+ static const uint16 offset_symbollist = 0x0e5e;
+ static const uint16 offset_folderlist = 0x0e34;
+ static const uint16 offset_facelist = 0x0451;
+ static const uint16 offset_operand1 = 0x0b7e;
+ static const uint16 offset_keypadlist = 0x0d9a;
+ static const uint16 kStartvars = 0;
+ static const uint16 kProgresspoints = 1;
+ static const uint16 kWatchon = 2;
+ static const uint16 kShadeson = 3;
+ static const uint16 kSecondcount = 4;
+ static const uint16 kMinutecount = 5;
+ static const uint16 kHourcount = 6;
+ static const uint16 kZoomon = 7;
+ static const uint16 kLocation = 8;
+ static const uint16 kExpos = 9;
+ static const uint16 kExframepos = 10;
+ static const uint16 kExtextpos = 12;
+ static const uint16 kCard1money = 14;
+ static const uint16 kListpos = 16;
+ static const uint16 kRyanpage = 18;
+ static const uint16 kWatchingtime = 19;
+ static const uint16 kReeltowatch = 21;
+ static const uint16 kEndwatchreel = 23;
+ static const uint16 kSpeedcount = 25;
+ static const uint16 kWatchspeed = 26;
+ static const uint16 kReeltohold = 27;
+ static const uint16 kEndofholdreel = 29;
+ static const uint16 kWatchmode = 31;
+ static const uint16 kDestafterhold = 32;
+ static const uint16 kNewsitem = 33;
+ static const uint16 kLiftflag = 34;
+ static const uint16 kLiftpath = 35;
+ static const uint16 kLockstatus = 36;
+ static const uint16 kDoorpath = 37;
+ static const uint16 kCounttoopen = 38;
+ static const uint16 kCounttoclose = 39;
+ static const uint16 kRockstardead = 40;
+ static const uint16 kGeneraldead = 41;
+ static const uint16 kSartaindead = 42;
+ static const uint16 kAidedead = 43;
+ static const uint16 kBeenmugged = 44;
+ static const uint16 kGunpassflag = 45;
+ static const uint16 kCanmovealtar = 46;
+ static const uint16 kTalkedtoattendant = 47;
+ static const uint16 kTalkedtosparky = 48;
+ static const uint16 kTalkedtoboss = 49;
+ static const uint16 kTalkedtorecep = 50;
+ static const uint16 kCardpassflag = 51;
+ static const uint16 kMadmanflag = 52;
+ static const uint16 kKeeperflag = 53;
+ static const uint16 kLasttrigger = 54;
+ static const uint16 kMandead = 55;
+ static const uint16 kSeed = 56;
+ static const uint16 kNeedtotravel = 59;
+ static const uint16 kThroughdoor = 60;
+ static const uint16 kNewobs = 61;
+ static const uint16 kRyanon = 62;
+ static const uint16 kCombatcount = 63;
+ static const uint16 kLastweapon = 64;
+ static const uint16 kDreamnumber = 65;
+ static const uint16 kRoomafterdream = 66;
+ static const uint16 kShakecounter = 67;
+ static const uint16 kSpeechcount = 68;
+ static const uint16 kCharshift = 69;
+ static const uint16 kKerning = 71;
+ static const uint16 kBrightness = 72;
+ static const uint16 kRoomloaded = 73;
+ static const uint16 kDidzoom = 74;
+ static const uint16 kLinespacing = 75;
+ static const uint16 kTextaddressx = 77;
+ static const uint16 kTextaddressy = 79;
+ static const uint16 kTextlen = 81;
+ static const uint16 kLastxpos = 82;
+ static const uint16 kIcontop = 84;
+ static const uint16 kIconleft = 86;
+ static const uint16 kItemframe = 88;
+ static const uint16 kItemtotran = 89;
+ static const uint16 kRoomad = 90;
+ static const uint16 kOldsubject = 92;
+ static const uint16 kWithobject = 94;
+ static const uint16 kWithtype = 95;
+ static const uint16 kLookcounter = 96;
+ static const uint16 kCommand = 98;
+ static const uint16 kCommandtype = 99;
+ static const uint16 kOldcommandtype = 100;
+ static const uint16 kObjecttype = 101;
+ static const uint16 kGetback = 102;
+ static const uint16 kInvopen = 103;
+ static const uint16 kMainmode = 104;
+ static const uint16 kPickup = 105;
+ static const uint16 kLastinvpos = 106;
+ static const uint16 kExamagain = 107;
+ static const uint16 kNewtextline = 108;
+ static const uint16 kOpenedob = 109;
+ static const uint16 kOpenedtype = 110;
+ static const uint16 kOldmapadx = 111;
+ static const uint16 kOldmapady = 113;
+ static const uint16 kMapadx = 115;
+ static const uint16 kMapady = 117;
+ static const uint16 kMapoffsetx = 119;
+ static const uint16 kMapoffsety = 121;
+ static const uint16 kMapxstart = 123;
+ static const uint16 kMapystart = 125;
+ static const uint16 kMapxsize = 127;
+ static const uint16 kMapysize = 128;
+ static const uint16 kHavedoneobs = 129;
+ static const uint16 kManisoffscreen = 130;
+ static const uint16 kRainspace = 131;
+ static const uint16 kFacing = 132;
+ static const uint16 kLeavedirection = 133;
+ static const uint16 kTurntoface = 134;
+ static const uint16 kTurndirection = 135;
+ static const uint16 kMaintimer = 136;
+ static const uint16 kIntrocount = 138;
+ static const uint16 kArrowad = 139;
+ static const uint16 kCurrentkey = 141;
+ static const uint16 kOldkey = 142;
+ static const uint16 kUseddirection = 143;
+ static const uint16 kCurrentkey2 = 144;
+ static const uint16 kTimercount = 145;
+ static const uint16 kOldtimercount = 146;
+ static const uint16 kMapx = 147;
+ static const uint16 kMapy = 148;
+ static const uint16 kNewscreen = 149;
+ static const uint16 kRyanx = 150;
+ static const uint16 kRyany = 151;
+ static const uint16 kLastflag = 152;
+ static const uint16 kLastflagex = 153;
+ static const uint16 kFlagx = 154;
+ static const uint16 kFlagy = 155;
+ static const uint16 kCurrentex = 156;
+ static const uint16 kCurrentfree = 157;
+ static const uint16 kCurrentframe = 158;
+ static const uint16 kFramesad = 160;
+ static const uint16 kDataad = 162;
+ static const uint16 kFrsegment = 164;
+ static const uint16 kObjectx = 166;
+ static const uint16 kObjecty = 168;
+ static const uint16 kOffsetx = 170;
+ static const uint16 kOffsety = 172;
+ static const uint16 kSavesize = 174;
+ static const uint16 kSavesource = 176;
+ static const uint16 kSavex = 178;
+ static const uint16 kSavey = 179;
+ static const uint16 kCurrentob = 180;
+ static const uint16 kPrioritydep = 181;
+ static const uint16 kDestpos = 182;
+ static const uint16 kReallocation = 183;
+ static const uint16 kRoomnum = 184;
+ static const uint16 kNowinnewroom = 185;
+ static const uint16 kResetmanxy = 186;
+ static const uint16 kNewlocation = 187;
+ static const uint16 kAutolocation = 188;
+ static const uint16 kMustload = 189;
+ static const uint16 kAnswered = 190;
+ static const uint16 kSaidno = 191;
+ static const uint16 kDoorcheck1 = 192;
+ static const uint16 kDoorcheck2 = 193;
+ static const uint16 kDoorcheck3 = 194;
+ static const uint16 kDoorcheck4 = 195;
+ static const uint16 kMousex = 196;
+ static const uint16 kMousey = 198;
+ static const uint16 kMousebutton = 200;
+ static const uint16 kMousebutton1 = 202;
+ static const uint16 kMousebutton2 = 204;
+ static const uint16 kMousebutton3 = 206;
+ static const uint16 kMousebutton4 = 208;
+ static const uint16 kOldbutton = 210;
+ static const uint16 kOldx = 212;
+ static const uint16 kOldy = 214;
+ static const uint16 kLastbutton = 216;
+ static const uint16 kOldpointerx = 218;
+ static const uint16 kOldpointery = 220;
+ static const uint16 kDelherex = 222;
+ static const uint16 kDelherey = 224;
+ static const uint16 kPointerxs = 226;
+ static const uint16 kPointerys = 227;
+ static const uint16 kDelxs = 228;
+ static const uint16 kDelys = 229;
+ static const uint16 kPointerframe = 230;
+ static const uint16 kPointerpower = 231;
+ static const uint16 kAuxpointerframe = 232;
+ static const uint16 kPointermode = 233;
+ static const uint16 kPointerspeed = 234;
+ static const uint16 kPointercount = 235;
+ static const uint16 kInmaparea = 236;
+ static const uint16 kReelpointer = 237;
+ static const uint16 kSlotdata = 239;
+ static const uint16 kThisslot = 240;
+ static const uint16 kSlotflags = 241;
+ static const uint16 kTakeoff = 242;
+ static const uint16 kTalkmode = 244;
+ static const uint16 kTalkpos = 245;
+ static const uint16 kCharacter = 246;
+ static const uint16 kPersondata = 247;
+ static const uint16 kTalknum = 249;
+ static const uint16 kNumberinroom = 250;
+ static const uint16 kCurrentcel = 251;
+ static const uint16 kOldselection = 252;
+ static const uint16 kStopwalking = 253;
+ static const uint16 kMouseon = 254;
+ static const uint16 kPlayed = 255;
+ static const uint16 kTimer1 = 257;
+ static const uint16 kTimer2 = 258;
+ static const uint16 kTimer3 = 259;
+ static const uint16 kWholetimer = 260;
+ static const uint16 kTimer1to = 262;
+ static const uint16 kTimer2to = 263;
+ static const uint16 kTimer3to = 264;
+ static const uint16 kWatchdump = 265;
+ static const uint16 kCurrentset = 266;
+ static const uint16 kLogonum = 268;
+ static const uint16 kOldlogonum = 269;
+ static const uint16 kNewlogonum = 270;
+ static const uint16 kNetseg = 271;
+ static const uint16 kNetpoint = 273;
+ static const uint16 kKeynum = 275;
+ static const uint16 kCursorstate = 276;
+ static const uint16 kPressed = 277;
+ static const uint16 kPresspointer = 278;
+ static const uint16 kGraphicpress = 280;
+ static const uint16 kPresscount = 281;
+ static const uint16 kKeypadax = 282;
+ static const uint16 kKeypadcx = 284;
+ static const uint16 kLightcount = 286;
+ static const uint16 kFolderpage = 287;
+ static const uint16 kDiarypage = 288;
+ static const uint16 kMenucount = 289;
+ static const uint16 kSymboltopx = 290;
+ static const uint16 kSymboltopnum = 291;
+ static const uint16 kSymboltopdir = 292;
+ static const uint16 kSymbolbotx = 293;
+ static const uint16 kSymbolbotnum = 294;
+ static const uint16 kSymbolbotdir = 295;
+ static const uint16 kSymboltolight = 296;
+ static const uint16 kSymbol1 = 297;
+ static const uint16 kSymbol2 = 298;
+ static const uint16 kSymbol3 = 299;
+ static const uint16 kSymbolnum = 300;
+ static const uint16 kDumpx = 301;
+ static const uint16 kDumpy = 303;
+ static const uint16 kWalkandexam = 305;
+ static const uint16 kWalkexamtype = 306;
+ static const uint16 kWalkexamnum = 307;
+ static const uint16 kCursloc = 308;
+ static const uint16 kCurslocx = 310;
+ static const uint16 kCurslocy = 312;
+ static const uint16 kCurpos = 314;
+ static const uint16 kMonadx = 316;
+ static const uint16 kMonady = 318;
+ static const uint16 kGotfrom = 320;
+ static const uint16 kMonsource = 322;
+ static const uint16 kNumtodo = 324;
+ static const uint16 kTimecount = 326;
+ static const uint16 kCounttotimed = 328;
+ static const uint16 kTimedseg = 330;
+ static const uint16 kTimedoffset = 332;
+ static const uint16 kTimedy = 334;
+ static const uint16 kTimedx = 335;
+ static const uint16 kNeedtodumptimed = 336;
+ static const uint16 kHandle = 337;
+ static const uint16 kLoadingorsave = 339;
+ static const uint16 kCurrentslot = 340;
+ static const uint16 kCursorpos = 341;
+ static const uint16 kColourpos = 342;
+ static const uint16 kFadedirection = 343;
+ static const uint16 kNumtofade = 344;
+ static const uint16 kFadecount = 345;
+ static const uint16 kAddtogreen = 346;
+ static const uint16 kAddtored = 347;
+ static const uint16 kAddtoblue = 348;
+ static const uint16 kLastsoundreel = 349;
+ static const uint16 kSoundbuffer = 351;
+ static const uint16 kSoundbufferad = 353;
+ static const uint16 kSoundbufferpage = 355;
+ static const uint16 kSoundtimes = 356;
+ static const uint16 kNeedsoundbuff = 357;
+ static const uint16 kOldint9seg = 358;
+ static const uint16 kOldint9add = 360;
+ static const uint16 kOldint8seg = 362;
+ static const uint16 kOldint8add = 364;
+ static const uint16 kOldsoundintseg = 366;
+ static const uint16 kOldsoundintadd = 368;
+ static const uint16 kSoundbaseadd = 370;
+ static const uint16 kDsp_status = 372;
+ static const uint16 kDsp_write = 374;
+ static const uint16 kDmaaddress = 376;
+ static const uint16 kSoundint = 377;
+ static const uint16 kSounddmachannel = 378;
+ static const uint16 kSampleplaying = 379;
+ static const uint16 kTestresult = 380;
+ static const uint16 kCurrentirq = 381;
+ static const uint16 kSpeechloaded = 382;
+ static const uint16 kSpeechlength = 383;
+ static const uint16 kVolume = 385;
+ static const uint16 kVolumeto = 386;
+ static const uint16 kVolumedirection = 387;
+ static const uint16 kVolumecount = 388;
+ static const uint16 kPlayblock = 389;
+ static const uint16 kWongame = 390;
+ static const uint16 kLasthardkey = 391;
+ static const uint16 kBufferin = 392;
+ static const uint16 kBufferout = 394;
+ static const uint16 kExtras = 396;
+ static const uint16 kWorkspace = 398;
+ static const uint16 kMapstore = 400;
+ static const uint16 kCharset1 = 402;
+ static const uint16 kTempcharset = 404;
+ static const uint16 kIcons1 = 406;
+ static const uint16 kIcons2 = 408;
+ static const uint16 kBuffers = 410;
+ static const uint16 kMainsprites = 412;
+ static const uint16 kBackdrop = 414;
+ static const uint16 kMapdata = 416;
+ static const uint16 kSounddata = 418;
+ static const uint16 kSounddata2 = 420;
+ static const uint16 kRecordspace = 422;
+ static const uint16 kFreedat = 424;
+ static const uint16 kSetdat = 426;
+ static const uint16 kReel1 = 428;
+ static const uint16 kReel2 = 430;
+ static const uint16 kReel3 = 432;
+ static const uint16 kRoomdesc = 434;
+ static const uint16 kFreedesc = 436;
+ static const uint16 kSetdesc = 438;
+ static const uint16 kBlockdesc = 440;
+ static const uint16 kSetframes = 442;
+ static const uint16 kFreeframes = 444;
+ static const uint16 kPeople = 446;
+ static const uint16 kReels = 448;
+ static const uint16 kCommandtext = 450;
+ static const uint16 kPuzzletext = 452;
+ static const uint16 kTraveltext = 454;
+ static const uint16 kTempgraphics = 456;
+ static const uint16 kTempgraphics2 = 458;
+ static const uint16 kTempgraphics3 = 460;
+ static const uint16 kTempsprites = 462;
+ static const uint16 kTextfile1 = 464;
+ static const uint16 kTextfile2 = 466;
+ static const uint16 kTextfile3 = 468;
+ static const uint16 kBlinkframe = 470;
+ static const uint16 kBlinkcount = 471;
+ static const uint16 kReasseschanges = 472;
+ static const uint16 kPointerspath = 473;
+ static const uint16 kManspath = 474;
+ static const uint16 kPointerfirstpath = 475;
+ static const uint16 kFinaldest = 476;
+ static const uint16 kDestination = 477;
+ static const uint16 kLinestartx = 478;
+ static const uint16 kLinestarty = 480;
+ static const uint16 kLineendx = 482;
+ static const uint16 kLineendy = 484;
+ static const uint16 kIncrement1 = 486;
+ static const uint16 kIncrement2 = 488;
+ static const uint16 kLineroutine = 490;
+ static const uint16 kLinepointer = 491;
+ static const uint16 kLinedirection = 492;
+ static const uint16 kLinelength = 493;
+ static const uint16 kLiftsoundcount = 494;
+ static const uint16 kEmmhandle = 495;
+ static const uint16 kEmmpageframe = 497;
+ static const uint16 kEmmhardwarepage = 499;
+ static const uint16 kCh0emmpage = 500;
+ static const uint16 kCh0offset = 502;
+ static const uint16 kCh0blockstocopy = 504;
+ static const uint16 kCh0playing = 506;
+ static const uint16 kCh0repeat = 507;
+ static const uint16 kCh0oldemmpage = 508;
+ static const uint16 kCh0oldoffset = 510;
+ static const uint16 kCh0oldblockstocopy = 512;
+ static const uint16 kCh1playing = 514;
+ static const uint16 kCh1emmpage = 515;
+ static const uint16 kCh1offset = 517;
+ static const uint16 kCh1blockstocopy = 519;
+ static const uint16 kCh1blocksplayed = 521;
+ static const uint16 kSoundbufferwrite = 523;
+ static const uint16 kSoundemmpage = 525;
+ static const uint16 kSpeechemmpage = 527;
+ static const uint16 kCurrentsample = 529;
+ static const uint16 kRoomssample = 530;
+ static const uint16 kGameerror = 531;
+ static const uint16 kHowmuchalloc = 532;
+ static const uint16 kReelroutines = 534;
+ static const uint16 kReelcalls = 991;
+ static const uint16 kRoombyroom = 1214;
+ static const uint16 kR0 = 1326;
+ static const uint16 kR1 = 1327;
+ static const uint16 kR2 = 1331;
+ static const uint16 kR6 = 1350;
+ static const uint16 kR8 = 1357;
+ static const uint16 kR9 = 1373;
+ static const uint16 kR10 = 1380;
+ static const uint16 kR11 = 1384;
+ static const uint16 kR12 = 1388;
+ static const uint16 kR13 = 1392;
+ static const uint16 kR14 = 1405;
+ static const uint16 kR20 = 1439;
+ static const uint16 kR22 = 1461;
+ static const uint16 kR23 = 1492;
+ static const uint16 kR25 = 1505;
+ static const uint16 kR26 = 1527;
+ static const uint16 kR27 = 1549;
+ static const uint16 kR28 = 1574;
+ static const uint16 kR29 = 1593;
+ static const uint16 kR45 = 1609;
+ static const uint16 kR46 = 1616;
+ static const uint16 kR47 = 1653;
+ static const uint16 kR52 = 1666;
+ static const uint16 kR53 = 1670;
+ static const uint16 kR55 = 1677;
+ static const uint16 kSpritename1 = 1819;
+ static const uint16 kSpritename3 = 1832;
+ static const uint16 kIdname = 1845;
+ static const uint16 kCharacterset1 = 1857;
+ static const uint16 kCharacterset2 = 1870;
+ static const uint16 kCharacterset3 = 1883;
+ static const uint16 kSamplename = 1896;
+ static const uint16 kBasicsample = 1909;
+ static const uint16 kIcongraphics0 = 1922;
+ static const uint16 kIcongraphics1 = 1935;
+ static const uint16 kExtragraphics1 = 1948;
+ static const uint16 kIcongraphics8 = 1961;
+ static const uint16 kMongraphicname = 1974;
+ static const uint16 kMongraphics2 = 1987;
+ static const uint16 kCityname = 2000;
+ static const uint16 kTravelgraphic1 = 2013;
+ static const uint16 kTravelgraphic2 = 2026;
+ static const uint16 kDiarygraphic = 2039;
+ static const uint16 kMonitorfile1 = 2052;
+ static const uint16 kMonitorfile2 = 2065;
+ static const uint16 kMonitorfile10 = 2078;
+ static const uint16 kMonitorfile11 = 2091;
+ static const uint16 kMonitorfile12 = 2104;
+ static const uint16 kMonitorfile13 = 2117;
+ static const uint16 kMonitorfile20 = 2130;
+ static const uint16 kMonitorfile21 = 2143;
+ static const uint16 kMonitorfile22 = 2156;
+ static const uint16 kMonitorfile23 = 2169;
+ static const uint16 kMonitorfile24 = 2182;
+ static const uint16 kFoldertext = 2195;
+ static const uint16 kDiarytext = 2208;
+ static const uint16 kPuzzletextname = 2221;
+ static const uint16 kTraveltextname = 2234;
+ static const uint16 kIntrotextname = 2247;
+ static const uint16 kEndtextname = 2260;
+ static const uint16 kCommandtextname = 2273;
+ static const uint16 kVolumetabname = 2286;
+ static const uint16 kFoldergraphic1 = 2299;
+ static const uint16 kFoldergraphic2 = 2312;
+ static const uint16 kFoldergraphic3 = 2325;
+ static const uint16 kSymbolgraphic = 2338;
+ static const uint16 kGungraphic = 2351;
+ static const uint16 kMonkface = 2364;
+ static const uint16 kTitle0graphics = 2377;
+ static const uint16 kTitle1graphics = 2390;
+ static const uint16 kTitle2graphics = 2403;
+ static const uint16 kTitle3graphics = 2416;
+ static const uint16 kTitle4graphics = 2429;
+ static const uint16 kTitle5graphics = 2442;
+ static const uint16 kTitle6graphics = 2455;
+ static const uint16 kTitle7graphics = 2468;
+ static const uint16 kPalettescreen = 2481;
+ static const uint16 kCurrentfile = 2970;
+ static const uint16 kDmaaddresses = 5118;
+ static const uint16 kFileheader = 6091;
+ static const uint16 kFiledata = 6141;
+ static const uint16 kExtradata = 6181;
+ static const uint16 kRoomdata = 6187;
+ static const uint16 kMadeuproomdat = 7979;
+ static const uint16 kRoomscango = 8011;
+ static const uint16 kRoompics = 8027;
+ static const uint16 kOplist = 8042;
+ static const uint16 kInputline = 8045;
+ static const uint16 kLinedata = 8173;
+ static const uint16 kPresslist = 8573;
+ static const uint16 kSavenames = 8579;
+ static const uint16 kSavefiles = 8698;
+ static const uint16 kRecname = 8789;
+ static const uint16 kQuitrequested = 8802;
+ static const uint16 kSubtitles = 8803;
+ static const uint16 kForeignrelease = 8804;
+ static const uint16 kStak = 8805;
+ static const uint16 kBlocktextdat = (0);
+ static const uint16 kPersonframes = (0);
+ static const uint16 kDebuglevel1 = (0);
+ static const uint16 kDebuglevel2 = (0);
+ static const uint16 kPlayback = (0);
+ static const uint16 kMap = (0);
+ static const uint16 kSettextdat = (0);
+ static const uint16 kSpanish = (0);
+ static const uint16 kFramedata = (0);
+ static const uint16 kRecording = (0);
+ static const uint16 kFlags = (0);
+ static const uint16 kGerman = (0);
+ static const uint16 kTextunder = (0);
+ static const uint16 kPathdata = (0);
+ static const uint16 kDemo = (0);
+ static const uint16 kExframedata = (0);
+ static const uint16 kIntextdat = (0);
+ static const uint16 kFreetextdat = (0);
+ static const uint16 kFrframedata = (0);
+ static const uint16 kSettext = (0+(130*2));
+ static const uint16 kOpeninvlist = (0+(228*13));
+ static const uint16 kRyaninvlist = (0+(228*13)+32);
+ static const uint16 kPointerback = (0+(228*13)+32+60);
+ static const uint16 kMapflags = (0+(228*13)+32+60+(32*32));
+ static const uint16 kStartpal = (0+(228*13)+32+60+(32*32)+(11*10*3));
+ static const uint16 kEndpal = (0+(228*13)+32+60+(32*32)+(11*10*3)+768);
+ static const uint16 kMaingamepal = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768);
+ static const uint16 kSpritetable = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768);
+ static const uint16 kSetlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32));
+ static const uint16 kFreelist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5));
+ static const uint16 kExlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5));
+ static const uint16 kPeoplelist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5));
+ static const uint16 kZoomspace = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5));
+ static const uint16 kPrintedlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40));
+ static const uint16 kListofchanges = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80));
+ static const uint16 kUndertimedtext = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4));
+ static const uint16 kRainlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30));
+ static const uint16 kInitialreelrouts = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64));
+ static const uint16 kInitialvars = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+991-534);
+ static const uint16 kLengthofbuffer = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+991-534+68-0);
+ static const uint16 kReellist = (0+(36*144));
+ static const uint16 kIntext = (0+(38*2));
+ static const uint16 kLengthofmap = (0+(66*60));
+ static const uint16 kFreetext = (0+(82*2));
+ static const uint16 kBlocktext = (0+(98*2));
+ static const uint16 kBlocks = (0+192);
+ static const uint16 kFrframes = (0+2080);
+ static const uint16 kExframes = (0+2080);
+ static const uint16 kFrames = (0+2080);
+ static const uint16 kExdata = (0+2080+30000);
+ static const uint16 kExtextdat = (0+2080+30000+(16*114));
+ static const uint16 kExtext = (0+2080+30000+(16*114)+((114+2)*2));
+ static const uint16 kLengthofextra = (0+2080+30000+(16*114)+((114+2)*2)+18000);
+ static const uint16 kPersontxtdat = (0+24);
+ static const uint16 kPersontext = (0+24+(1026*2));
+ static const uint16 kInputport = (0x63);
+ static const uint16 kForeign = (1);
+ static const uint16 kCd = (1);
+ static const uint16 kNumexobjects = (114);
+ static const uint16 kUndertextsizey = (13);
+ static const uint16 kZoomy = (132);
+ static const uint16 kFreedatlen = (16*80);
+ static const uint16 kExtextlen = (18000);
+ static const uint16 kLenofmapstore = (22*8*20*8);
+ static const uint16 kUndertextsizex = (228);
+ static const uint16 kNumchanges = (250);
+ static const uint16 kUndertimedysize = (30);
+ static const uint16 kExframeslen = (30000);
+ static const uint16 kTablesize = (32);
+ static const uint16 kScreenwidth = (320);
+ static const uint16 kKeypadx = (36+112);
+ static const uint16 kItempicsize = (44);
+ static const uint16 kDiaryy = (48+12);
+ static const uint16 kOpsy = (52);
+ static const uint16 kSymboly = (56);
+ static const uint16 kInventy = (58);
+ static const uint16 kMenuy = (60);
+ static const uint16 kOpsx = (60);
+ static const uint16 kMaplength = (60);
+ static const uint16 kHeaderlen = (6187-6091);
+ static const uint16 kSymbolx = (64);
+ static const uint16 kSetdatlen = (64*128);
+ static const uint16 kMapwidth = (66);
+ static const uint16 kTextstart = (66*2);
+ static const uint16 kMaplen = (66*60);
+ static const uint16 kDiaryx = (68+24);
+ static const uint16 kLengthofvars = (68-0);
+ static const uint16 kKeypady = (72);
+ static const uint16 kZoomx = (8);
+ static const uint16 kInventx = (80);
+ static const uint16 kMenux = (80+40);
+ static const uint16 kLenofreelrouts = (991-534);
void bothchannels();
void usewire();
void getnamepos();
- void drawitall();
+ void loadtemptext();
void clearstartpal();
void femalefan();
- void showgamereel();
+ //void showgamereel();
void identifyob();
void trysoundalloc();
void uselighter();
@@ -1345,10 +1293,12 @@ public:
void startdmablock();
void useopenbox();
void clearbuffers();
+ //void getyad();
void neterror();
void storeit();
+ //void lockeddoorway();
void isitworn();
- void putundertimed();
+ //void putundertimed();
void dumpmap();
//void multidump();
void channel0only();
@@ -1358,27 +1308,27 @@ public:
void getobtextstart();
void loadfolder();
void decide();
- void dumppointer();
+ //void dumppointer();
void reelsonscreen();
void getridofreels();
void readkey();
void louis();
void entrytexts();
- void getreelstart();
+ //void getreelstart();
void buttonenter();
void checkinput();
- void crosshair();
+ //void crosshair();
void bresenhams();
void getbackfromops();
//void frameoutv();
- void restoreall();
+ void opensarters();
void screenupdate();
- void addlength();
- void usetimedtext();
+ //void addlength();
+ void wornerror();
void putundercentre();
void checkobjectsize();
- void commandonly();
- void adjustlen();
+ //void commandonly();
+ void titles();
void deallocatemem();
void mainscreen();
void watchreel();
@@ -1386,28 +1336,33 @@ public:
void turnanypathoff();
void openfilefromc();
void gettime();
- void clearwork();
+ //void clearwork();
void loadtraveltext();
//void worktoscreen();
void getexpos();
void fadedos();
+ //void fillspace();
+ void selectlocation();
//void multiget();
+ //void autosetwalk();
void fadeupmonfirst();
void drawfloor();
void loadkeypad();
- void findsource();
+ //void findsource();
void clearendpal();
void findtext1();
void isryanholding();
- void interupttest();
+ void showslots();
void usecashcard();
void usewall();
void opentomb();
+ //void makename();
void buttonfour();
- void animpointer();
+ void dosometalk();
//void lockmon();
- void dochange();
+ //void dochange();
void getanyaddir();
+ //void dumpblink();
void showsaveops();
void intromonks1();
void resetlocation();
@@ -1417,24 +1372,24 @@ public:
void additionaltext();
//void kernchars();
void othersmoker();
- void autosetwalk();
- void setuptimedtemp();
- void blocknametext();
+ void dofade();
+ //void setuptimedtemp();
+ //void blocknametext();
void useelevator5();
void useelevator4();
void useelevator1();
- void attendant();
+ //void findormake();
void useelevator3();
void useelevator2();
void buttonone();
void keyboardread();
- void deltextline();
+ //void deltextline();
void entercode();
void getopenedsize();
void getpersframe();
void doshake();
void resetkeyboard();
- void showpanel();
+ //void showpanel();
void soundstartup();
void slabdoora();
void fadeupyellows();
@@ -1443,52 +1398,52 @@ public:
void slabdoore();
void slabdoord();
void adjustup();
- void readsetdata();
+ void slabdoorf();
void loadintotemp();
void loadintroroom();
void saveseg();
- void showblink();
+ //void showblink();
void mousecall();
void train();
void watchcount();
void fadedownmon();
void loadcart();
- void splitintolines();
+ //void calcfrframe();
void bartender();
void eden();
void showdiary();
void purgealocation();
- void updatepeople();
- void slabdoorf();
+ //void updatepeople();
void addtopeoplelist();
void hangoncurs();
void sparkydrip();
- //void modifychar();
void compare();
void printcurs();
//void convertkey();
void outofopen();
- void dealwithspecial();
+ //void dealwithspecial();
//void eraseoldobs();
void dircom();
//void liftsprite();
void dumpkeypad();
- void dumpzoom();
+ void showsymbol();
void endgameseq();
//void cancelch0();
void setbotleft();
void findfirstpath();
- void fadescreenup();
+ //void cancelch1();
void loadold();
void loadtempcharset();
+ void showbyte();
void useslab();
- void aboutturn();
+ void dumpzoom();
+ //void aboutturn();
void usealtar();
void createpanel2();
void turnonpower();
void manasleep2();
void moretalk();
- void printslow();
+ //void printslow();
void loadroom();
void starttalk();
void delchar();
@@ -1496,7 +1451,7 @@ public:
void endgame();
void monprint();
void usepipe();
- void startloading();
+ //void startloading();
void getunderzoom();
void candles();
void backobject();
@@ -1504,10 +1459,10 @@ public:
void reminders();
void selectslot2();
void runtap();
- void domix();
+ //void domix();
void priesttext();
void paneltomap();
- void obname();
+ //void obname();
void getridoftemp3();
void getridoftemp2();
void usebalcony();
@@ -1516,13 +1471,12 @@ public:
void disablesoundint();
void checkifset();
void showallex();
- void showrain();
void openpoolboss();
void buttontwo();
- void fillopen();
+ //void usetimedtext();
void delsprite();
- void getroomspaths();
- void dumptextline();
+ //void getroomspaths();
+ //void dumptextline();
void fadescreendownhalf();
void useplate();
void candles1();
@@ -1531,11 +1485,12 @@ public:
void isitdescribed();
void hotelbell();
void loadspeech();
+ void interupttest();
//void cls();
//void printsprites();
- void checkifperson();
- void showallobs();
- void getnumber();
+ //void checkifperson();
+ //void showallobs();
+ //void getnumber();
void adjustleft();
void calledenslift();
void useclearbox();
@@ -1544,15 +1499,16 @@ public:
void getfreead();
void showarrows();
void walkintoroom();
- void getridoftemptext();
+ void usehatch();
void printoutermon();
void setuppit();
void showpcx();
void showdecisions();
void checkspeed();
- void printchar();
+ //void printchar();
void showkeypad();
void obtoinv();
+ //void getroomdata();
void removeobfrominv();
void usecoveredbox();
void openyourneighbour();
@@ -1567,55 +1523,53 @@ public:
//void spriteupdate();
void usetempcharset();
void discops();
- void printdirect();
+ //void printdirect();
void delthisone();
- void makebackob();
+ //void makebackob();
void middlepanel();
void dumpwatch();
void saveload();
void monitorlogo();
void loadposition();
- void wornerror();
void entersymbol();
void showword();
void dirfile();
void setmode();
- void walktotext();
+ //void walktotext();
void pickupconts();
void locklightoff();
void wearwatch();
void runintroseq();
- void doblocks();
- void showbyte();
- void allpalette();
- void findormake();
+ //void doblocks();
+ void restoreall();
+ //void delpointer();
+ void attendant();
void nextsymbol();
void monks2text();
- void poolguard();
void clearpalette();
void cantdrop();
void maptopanel();
- void calcmapad();
+ //void calcmapad();
void getridofall();
void copper();
void folderhints();
void openhoteldoor();
- void removesetobject();
- void dumptimedtext();
+ //void removesetobject();
+ //void dumptimedtext();
//void frameoutfx();
void blank();
void drinker();
void nextcolon();
void placefreeobject();
- void delpointer();
- void loopchannel0();
+ void allpalette();
+ //void loopchannel0();
void initrain();
void showleftpage();
void rockstar();
void adjustright();
void putunderzoom();
void vsync();
- void turnpathoff();
+ //void finishedwalking();
void findinvpos();
void usetext();
void hangonpq();
@@ -1633,38 +1587,37 @@ public:
void showouterpad();
void getkeyandlogo();
void selectob();
- void checkcoords();
+ //void checkcoords();
void dumpmenu();
void chewy();
void accesslighton();
- void dosreturn();
- void titles();
+ void useplinth();
+ //void adjustlen();
//void quickquit();
- void showpointer();
+ //void showpointer();
void usecooker();
void loadmenu();
void checkforemm();
void checkifpathison();
- void smallcandle();
+ //void finalframe();
void receptionist();
void selectslot();
- void edenscdplayer();
+ void openfilenocheck();
//void readoneblock();
void fadeupmon();
void paltoendpal();
void fadetowhite();
- void textformonk();
void loadsavebox();
void soundend();
void redes();
void errormessage1();
void clearchanges();
void errormessage3();
- void deletetaken();
+ //void deletetaken();
void putundermenu();
void checkifex();
void intromagic2();
- void findobname();
+ void intromagic3();
void edeninbath();
void intromagic1();
void showdiarypage();
@@ -1672,19 +1625,19 @@ public:
void getbacktoops();
void rollendcredits();
void intro1text();
- void getmapad();
+ void transfertoex();
void playchannel1();
void playchannel0();
void usemon();
void steady();
void pixelcheckset();
void reexfrominv();
- void fillspace();
+ void examinventory();
void talk();
void usedryer();
void dumpeverything();
- void usehatch();
- void zoom();
+ //void readmouse2();
+ //void zoom();
void outofinv();
void viewfolder();
//void walking();
@@ -1695,20 +1648,21 @@ public:
void obicons();
void mansatstill();
void channel1only();
- void playguitar();
+ void checkbasemem();
void lastfolder();
void transfermap();
- void showreelframe();
+ //void showreelframe();
void showmonk();
void diarykeyn();
void set16colpalette();
- void sparky();
+ void convicons();
void interviewer();
+ void sparky();
void purgeanitem();
void madman();
void createpanel();
void turnpathon();
- void showmainops();
+ void enablesoundint();
void madmanstelly();
void constant();
void loadroomssample();
@@ -1718,21 +1672,23 @@ public:
void getridofpit();
void convnum();
void nothelderror();
- void readheader();
+ //void readheader();
void getsetad();
- void getyad();
+ void textformonk();
void reconstruct();
void soldier1();
+ //void animpointer();
void getundercentre();
void checkforexit();
void loadseg();
void makeheader();
void setkeyboardint();
void priest();
- void readmouse();
+ //void readmouse();
void powerlighton();
void savefilewrite();
void printmessage2();
+ //void showallfree();
void loadnews();
void rollem();
void makeworn();
@@ -1745,14 +1701,14 @@ public:
void describeob();
void deleteexframe();
void folderexit();
- void useplinth();
+ void dosreturn();
void wheelsound();
void actualsave();
void autolook();
- void checkbasemem();
+ void playguitar();
void transfertext();
void searchforsame();
- void enablesoundint();
+ void showmainops();
void getback1();
void setlocation();
void fadefromwhite();
@@ -1763,9 +1719,9 @@ public:
void pitinterupt();
void deleverything();
void fadescreendown();
- void findxyfrompath();
+ //void findxyfrompath();
void namestoold();
- void getxad();
+ //void getxad();
void openinv();
void lookatplace();
void useaxe();
@@ -1777,25 +1733,24 @@ public:
void realcredits();
void handclap();
void smokebloke();
- void showexit();
+ void afterintroroom();
//void printundermon();
void buttonnine();
void findallopen();
void loadintotemp3();
void loadintotemp2();
void gamer();
- void personnametext();
- void quitsymbol();
+ void poolguard();
void readfromfile();
void initialinv();
- void showslots();
- void dofade();
+ void quitsymbol();
+ //void modifychar();
void hangon();
void settopright();
void findsetobject();
void singlekey();
//void seecommandtail();
- void getundertimed();
+ //void getundertimed();
void hangone();
void carparkdrip();
void usediary();
@@ -1816,104 +1771,103 @@ public:
void scrollmonitor();
void setsoundoff();
void setpickup();
+ //void doorway();
void dropobject();
- void printmessage();
+ void isitright();
void reexfromopen();
void fillryan();
- void loadtemptext();
+ void drawitall();
void usestereo();
void showcurrentfile();
- void copyname();
+ //void copyname();
void look();
void setmouse();
- void checkone();
+ //void checkone();
void transferinv();
void candles2();
void pickupob();
void error();
void showopbox();
- //void cancelch1();
void clearbeforeload();
void biblequote();
void doload();
- void afterintroroom();
+ void showexit();
void blockget();
void usetrainer();
- void allocatework();
+ //void allocatework();
void addtopresslist();
- void walkandexamine();
+ //void walkandexamine();
void dmaend();
//void quickquit2();
void twodigitnum();
- void madmantext();
+ //void madmantext();
void dumpcurrent();
void textforend();
void showdiarykeys();
void dontloadseg();
- void madmode();
+ //void madmode();
void intro3text();
void allocatemem();
void sortoutmap();
- void doorway();
+ //void showrain();
void useopened();
void inventory();
void powerlightoff();
- void getroomdata();
+ void fillopen();
void showoutermenu();
void signon();
void deleteextext();
void foghornsound();
void showrightpage();
- void openhoteldoor2();
+ void showloadops();
void examicon();
void showgun();
void switchryanon();
+ //void personnametext();
void louischair();
void saveems();
void locationpic();
- void getflagunderp();
+ //void getflagunderp();
void dolook();
void opentvdoor();
void triggermessage();
- void finalframe();
- void plotreel();
+ void smallcandle();
+ //void plotreel();
void swapwithopen();
//void makesprite();
void dreamweb();
void droperror();
- void openfilenocheck();
+ void edenscdplayer();
void calledensdlift();
void checkinside();
void gates();
- void selectlocation();
+ void newgame();
void showwatch();
void turnanypathon();
void restorereels();
void setwalk();
- void printboth();
void useroutine();
void zoomicon();
- void hotelcontrol();
+ //void findlen();
void findpathofpoint();
void issetobonmap();
void getdestinfo();
void drunk();
- void dumpblink();
+ void getridoftemptext();
void setuptimeduse();
void grafittidoor();
void input();
void nextdest();
- void getdimension();
+ //void getdimension();
void makecaps();
void read();
void fadescreenups();
- void checkdest();
+ //void checkdest();
//void initman();
void loadpalfromiff();
- void facerightway();
+ //void facerightway();
void startup1();
- void findlen();
- void showsymbol();
+ void hotelcontrol();
void mugger();
void atmospheres();
void out22c();
@@ -1924,7 +1878,7 @@ public:
//void clearsprites();
void obpicture();
void selectopenob();
- void widedoor();
+ //void widedoor();
void security();
//void printasprite();
void buttonfive();
@@ -1932,40 +1886,38 @@ public:
void usegun();
void autoappear();
void findnextcolon();
- void readmouse4();
+ //void readmouse4();
void openryan();
- void readmouse1();
+ void callhotellift();
void showman();
- void readmouse2();
+ void usefullcart();
void newplace();
- void movemap();
+ //void movemap();
void loadsample();
void usecardreader1();
void usecardreader2();
void usecardreader3();
void tattooman();
void usehandle();
- void quitkey();
void openfile();
void usecharset1();
- void makenextblock();
+ //void makenextblock();
void showpuztext();
- void addalong();
+ //void addalong();
//void width160();
void incryanpage();
//void dodoor();
void greyscalesum();
void buttoneight();
- void opensarters();
void findexobject();
void errormessage2();
void usechurchhole();
void searchforfiles();
void monkspeaking();
void fadecalculation();
- void waitframes();
+ //void waitframes();
void clearrest();
- void getreelframeax();
+ //void getreelframeax();
void barwoman();
void roomname();
void credits();
@@ -1974,17 +1926,16 @@ public:
void keeper();
void afternewroom();
void getexad();
- void aide();
void openforsave();
void closefile();
void delcurs();
void randomaccess();
- void calcfrframe();
- void intromagic3();
+ void splitintolines();
+ //void findobname();
void initialmoncols();
void checkforshake();
void usebuttona();
- void showallfree();
+ void fadescreenup();
//void getnextword();
void generalerror();
void actualload();
@@ -1999,31 +1950,29 @@ public:
void usechurchgate();
void monkandryan();
void allocatebuffers();
- void convicons();
void swapwithinv();
void usecontrol();
void buttonseven();
void redrawmainscrn();
- void finishedwalking();
+ void turnpathoff();
void findallryan();
- void lockeddoorway();
- void channel0tran();
+ //void channel0tran();
void buttonpress();
- void parseblaster();
- void callhotellift();
+ //void parseblaster();
+ //void readmouse1();
void makemainscreen();
void intromonks2();
void usewinch();
void setbotright();
- void readmouse3();
+ //void readmouse3();
void showfirstuse();
void setupemm();
- void usefullcart();
- void transfertoex();
+ void aide();
+ //void getmapad();
void getlocation();
void geteitherad();
- void placesetobject();
- void drawflags();
+ //void placesetobject();
+ //void drawflags();
void zoomonoff();
void updatesymboltop();
void showryanpage();
@@ -2043,12 +1992,12 @@ public:
void intro();
void hangonp();
void fadescreendowns();
- void showloadops();
+ void openhoteldoor2();
void getridoftempsp();
void scanfornames();
- void setallchanges();
- void newgame();
- void examinventory();
+ //void setallchanges();
+ void readsetdata();
+ //void printboth();
void standardload();
void undertextline();
void findroominloc();
@@ -2058,10 +2007,9 @@ public:
void emergencypurge();
void usemenu();
void alleybarksound();
- void dosometalk();
void usecart();
void intromusic();
- void makename();
+ void quitkey();
void processtrigger();
void monmessage();
void readdesticon();
@@ -2069,10 +2017,10 @@ public:
void loadsecondsample();
void transfercontoex();
//void multiput();
- void isitright();
+ void printmessage();
void businessman();
void switchryanoff();
- void commandwithob();
+ //void commandwithob();
void panelicons1();
void adjustdown();
void withwhat();
@@ -2084,7 +2032,7 @@ public:
void useobject();
void mainman();
void volumeadjust();
- void checkiffree();
+ //void checkiffree();
};
}
diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp
index caf3a987c4..0e43f18db6 100644
--- a/engines/dreamweb/dreamweb.cpp
+++ b/engines/dreamweb/dreamweb.cpp
@@ -110,14 +110,6 @@ void DreamWebEngine::processEvents() {
return;
}
- if (_enableSavingOrLoading && _loadSavefile >= 0 && _loadSavefile <= 6) {
- debug(1, "loading save state %d", _loadSavefile);
- _context.data.byte(_context.kCurrentslot) = _loadSavefile;
- _loadSavefile = -1;
- _context.loadposition();
- _context.data.byte(_context.kGetback) = 1;
- }
-
soundHandler();
Common::Event event;
int softKey, hardKey;
@@ -216,15 +208,9 @@ Common::Error DreamWebEngine::run() {
syncSoundSettings();
_console = new DreamWebConsole(this);
- if (ConfMan.hasKey("save_slot")) {
- _enableSavingOrLoading = true;
- _loadSavefile = ConfMan.getInt("save_slot");
- } else {
- _enableSavingOrLoading = false;
- _loadSavefile = -1;
- }
+ ConfMan.registerDefault("dreamweb_originalsaveload", "true");
- getTimerManager()->installTimerProc(vSyncInterrupt, 1000000 / 70, this);
+ getTimerManager()->installTimerProc(vSyncInterrupt, 1000000 / 70, this, "dreamwebVSync");
_context.__start();
_context.data.byte(DreamGen::DreamGenContext::kQuitrequested) = 0;
@@ -237,7 +223,7 @@ void DreamWebEngine::setSpeed(uint speed) {
debug(0, "setting speed %u", speed);
_speed = speed;
getTimerManager()->removeTimerProc(vSyncInterrupt);
- getTimerManager()->installTimerProc(vSyncInterrupt, 1000000 / 70 / speed, this);
+ getTimerManager()->installTimerProc(vSyncInterrupt, 1000000 / 70 / speed, this, "dreamwebVSync");
}
void DreamWebEngine::openFile(const Common::String &name) {
@@ -317,7 +303,7 @@ void DreamWebEngine::keyPressed(uint16 ascii) {
keybuf[in] = ascii;
}
-void DreamWebEngine::mouseCall() {
+void DreamWebEngine::mouseCall(uint16 *x, uint16 *y, uint16 *state) {
processEvents();
Common::EventManager *eventMan = _system->getEventManager();
Common::Point pos = eventMan->getMousePos();
@@ -329,13 +315,12 @@ void DreamWebEngine::mouseCall() {
pos.y = 15;
if (pos.y > 184)
pos.y = 184;
- _context.cx = pos.x;
- _context.dx = pos.y;
+ *x = pos.x;
+ *y = pos.y;
- unsigned state = eventMan->getButtonState();
- _context.bx = state == _oldMouseState? 0: state;
- _oldMouseState = state;
- _context.flags._c = false;
+ unsigned newState = eventMan->getButtonState();
+ *state = (newState == _oldMouseState? 0 : newState);
+ _oldMouseState = newState;
}
void DreamWebEngine::fadeDos() {
@@ -644,5 +629,3 @@ uint8 DreamWebEngine::modifyChar(uint8 c) const {
}
} // End of namespace DreamWeb
-
-
diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h
index 6ada207496..97f6007f9d 100644
--- a/engines/dreamweb/dreamweb.h
+++ b/engines/dreamweb/dreamweb.h
@@ -82,7 +82,7 @@ public:
uint32 skipBytes(uint32 bytes);
void closeFile();
- void mouseCall(); //fill mouse pos and button state
+ void mouseCall(uint16 *x, uint16 *y, uint16 *state); //fill mouse pos and button state
void processEvents();
void setPalette();
void fadeDos();
@@ -129,7 +129,6 @@ private:
uint _speed;
bool _turbo;
uint _oldMouseState;
- int _loadSavefile;
bool _enableSavingOrLoading;
Common::Language _language;
diff --git a/engines/dreamweb/module.mk b/engines/dreamweb/module.mk
index 3b0c7f3325..bdacbe79f3 100644
--- a/engines/dreamweb/module.mk
+++ b/engines/dreamweb/module.mk
@@ -1,11 +1,17 @@
MODULE := engines/dreamweb
MODULE_OBJS := \
+ backdrop.o \
console.o \
detection.o \
dreamweb.o \
dreamgen.o \
- stubs.o
+ pathfind.o \
+ print.o \
+ saveload.o \
+ sprite.o \
+ stubs.o \
+ vgagrafx.o
# This module can be built as a plugin
ifeq ($(ENABLE_DREAMWEB), DYNAMIC_PLUGIN)
diff --git a/engines/dreamweb/pathfind.cpp b/engines/dreamweb/pathfind.cpp
new file mode 100644
index 0000000000..2579105c6f
--- /dev/null
+++ b/engines/dreamweb/pathfind.cpp
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "dreamweb/dreamweb.h"
+#include "engines/util.h"
+#include "graphics/surface.h"
+#include "common/config-manager.h"
+
+namespace DreamGen {
+
+void DreamGenContext::turnpathonCPP(uint8 param) {
+ al = param;
+ push(es);
+ push(bx);
+ turnpathon();
+ bx = pop();
+ es = pop();
+}
+
+void DreamGenContext::turnpathoffCPP(uint8 param) {
+ al = param;
+ push(es);
+ push(bx);
+ turnpathoff();
+ bx = pop();
+ es = pop();
+}
+
+void DreamGenContext::getroomspaths() {
+ es = data.word(kReels);
+ bx = data.byte(kRoomnum) * 144;
+}
+
+uint8 *DreamGenContext::getroomspathsCPP() {
+ void *result = segRef(data.word(kReels)).ptr(data.byte(kRoomnum) * 144, 144);
+ return (uint8 *)result;
+}
+
+void DreamGenContext::autosetwalk() {
+ al = data.byte(kManspath);
+ if (data.byte(kFinaldest) == al)
+ return;
+ const uint8 *roomsPaths = getroomspathsCPP();
+ checkdest(roomsPaths);
+ data.word(kLinestartx) = roomsPaths[data.byte(kManspath) * 8 + 0] - 12;
+ data.word(kLinestarty) = roomsPaths[data.byte(kManspath) * 8 + 1] - 12;
+ data.word(kLineendx) = roomsPaths[data.byte(kDestination) * 8 + 0] - 12;
+ data.word(kLineendy) = roomsPaths[data.byte(kDestination) * 8 + 1] - 12;
+ bresenhams();
+ if (data.byte(kLinedirection) != 0) {
+ data.byte(kLinepointer) = data.byte(kLinelength) - 1;
+ data.byte(kLinedirection) = 1;
+ return;
+ }
+ data.byte(kLinepointer) = 0;
+}
+
+void DreamGenContext::checkdest(const uint8 *roomsPaths) {
+ const uint8 *p = roomsPaths + 12 * 8;
+ ah = data.byte(kManspath) << 4;
+ al = data.byte(kDestination);
+ uint8 destination = data.byte(kDestination);
+ for (size_t i = 0; i < 24; ++i) {
+ dh = p[0] & 0xf0;
+ dl = p[0] & 0x0f;
+ if (ax == dx) {
+ data.byte(kDestination) = p[1] & 0x0f;
+ return;
+ }
+ dl = (p[0] & 0xf0) >> 4;
+ dh = (p[0] & 0x0f) << 4;
+ if (ax == dx) {
+ destination = p[1] & 0x0f;
+ }
+ p += 2;
+ }
+ data.byte(kDestination) = destination;
+}
+
+void DreamGenContext::findxyfrompath() {
+ const uint8 *roomsPaths = getroomspathsCPP();
+ data.byte(kRyanx) = roomsPaths[data.byte(kManspath) * 8 + 0] - 12;
+ data.byte(kRyany) = roomsPaths[data.byte(kManspath) * 8 + 1] - 12;
+}
+
+} /*namespace dreamgen */
+
diff --git a/engines/dreamweb/print.cpp b/engines/dreamweb/print.cpp
new file mode 100644
index 0000000000..c1dbfc0a87
--- /dev/null
+++ b/engines/dreamweb/print.cpp
@@ -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.
+ *
+ */
+
+#include "dreamweb/dreamweb.h"
+#include "engines/util.h"
+#include "graphics/surface.h"
+
+namespace DreamGen {
+
+void DreamGenContext::printboth(const Frame *charSet, uint16 *x, uint16 y, uint8 c, uint8 nextChar) {
+ uint16 newX = *x;
+ uint8 width, height;
+ printchar(charSet, &newX, y, c, nextChar, &width, &height);
+ multidump(*x, y, width, height);
+ *x = newX;
+}
+
+uint8 DreamGenContext::getnextword(const Frame *charSet, const uint8 *string, uint8 *totalWidth, uint8 *charCount) {
+ *totalWidth = 0;
+ *charCount = 0;
+ while(true) {
+ uint8 firstChar = *string;
+ ++string;
+ ++*charCount;
+ if ((firstChar == ':') || (firstChar == 0)) { //endall
+ *totalWidth += 6;
+ return 1;
+ }
+ if (firstChar == 32) { //endword
+ *totalWidth += 6;
+ return 0;
+ }
+ firstChar = engine->modifyChar(firstChar);
+ if (firstChar != 255) {
+ uint8 secondChar = *string;
+ uint8 width = charSet[firstChar - 32 + data.word(kCharshift)].width;
+ width = kernchars(firstChar, secondChar, width);
+ *totalWidth += width;
+ }
+ }
+}
+
+void DreamGenContext::printchar() {
+ uint16 x = di;
+ uint8 width, height;
+ printchar((const Frame *)ds.ptr(0, 0), &x, bx, al, ah, &width, &height);
+ di = x;
+ cl = width;
+ ch = height;
+}
+
+void DreamGenContext::printchar(const Frame *charSet, uint16* x, uint16 y, uint8 c, uint8 nextChar, uint8 *width, uint8 *height) {
+ if (c == 255)
+ return;
+ push(si);
+ push(di);
+ if (data.byte(kForeignrelease) != 0)
+ y -= 3;
+ uint16 tmp = c - 32 + data.word(kCharshift);
+ showframe(charSet, *x, y, tmp & 0x1ff, (tmp >> 8) & 0xfe, width, height);
+ di = pop();
+ si = pop();
+ _cmp(data.byte(kKerning), 0);
+ if (flags.z())
+ *width = kernchars(c, nextChar, *width);
+ (*x) += *width;
+}
+
+void DreamGenContext::printslow() {
+ al = printslow(es.ptr(si, 0), di, bx, dl, (bool)(dl & 1));
+}
+
+uint8 DreamGenContext::printslow(const uint8 *string, uint16 x, uint16 y, uint8 maxWidth, bool centered) {
+ data.byte(kPointerframe) = 1;
+ data.byte(kPointermode) = 3;
+ const Frame* charSet = (const Frame *)segRef(data.word(kCharset1)).ptr(0, 0);
+ do {
+ uint16 offset = x;
+ uint16 charCount = getnumber(charSet, string, maxWidth, centered, &offset);
+ do {
+ uint8 c0 = string[0];
+ uint8 c1 = string[1];
+ uint8 c2 = string[2];
+ c0 = engine->modifyChar(c0);
+ printboth(charSet, &offset, y, c0, c1);
+ if ((c1 == 0) || (c1 == ':')) {
+ return 0;
+ }
+ if (charCount != 1) {
+ c1 = engine->modifyChar(c1);
+ data.word(kCharshift) = 91;
+ uint16 offset2 = offset;
+ printboth(charSet, &offset2, y, c1, c2);
+ data.word(kCharshift) = 0;
+ for (int i=0; i<2; ++i) {
+ uint16 mouseState = waitframes();
+ if (mouseState == 0)
+ continue;
+ if (mouseState != data.word(kOldbutton)) {
+ return 1;
+ }
+ }
+ }
+
+ ++string;
+ --charCount;
+ } while (charCount);
+ y += 10;
+ } while (true);
+}
+
+void DreamGenContext::printdirect() {
+ uint16 y = bx;
+ uint16 initialSi = si;
+ const uint8 *initialString = es.ptr(si, 0);
+ const uint8 *string = initialString;
+ printdirect(&string, di, &y, dl, (bool)(dl & 1));
+ si = initialSi + (string - initialString);
+ bx = y;
+}
+
+void DreamGenContext::printdirect(const uint8** string, uint16 x, uint16 *y, uint8 maxWidth, bool centered) {
+ data.word(kLastxpos) = x;
+ const Frame *charSet = (const Frame *)segRef(data.word(kCurrentset)).ptr(0, 0);
+ while (true) {
+ uint16 offset = x;
+ uint8 charCount = getnumber(charSet, *string, maxWidth, centered, &offset);
+ uint16 i = offset;
+ do {
+ uint8 c = (*string)[0];
+ uint8 nextChar = (*string)[1];
+ ++(*string);
+ if ((c == 0) || (c == ':')) {
+ return;
+ }
+ c = engine->modifyChar(c);
+ uint8 width, height;
+ printchar(charSet, &i, *y, c, nextChar, &width, &height);
+ data.word(kLastxpos) = i;
+ --charCount;
+ } while(charCount);
+ *y += data.word(kLinespacing);
+ }
+}
+
+void DreamGenContext::getnumber() {
+ uint16 offset = di;
+ cl = getnumber((Frame *)ds.ptr(0, 0), es.ptr(si, 0), dl, (bool)(dl & 1), &offset);
+ di = offset;
+}
+
+uint8 DreamGenContext::getnumber(const Frame *charSet, const uint8 *string, uint16 maxWidth, bool centered, uint16* offset) {
+ uint8 totalWidth = 0;
+ uint8 charCount = 0;
+ while (true) {
+ uint8 wordTotalWidth, wordCharCount;
+ uint8 done = getnextword(charSet, string, &wordTotalWidth, &wordCharCount);
+ string += wordCharCount;
+
+ if (done == 1) { //endoftext
+ ax = totalWidth + wordTotalWidth - 10;
+ if (ax < maxWidth) {
+ totalWidth += wordTotalWidth;
+ charCount += wordCharCount;
+ }
+
+ if (centered) {
+ ax = (maxWidth & 0xfe) + 2 + 20 - totalWidth;
+ ax /= 2;
+ } else {
+ ax = 0;
+ }
+ *offset += ax;
+ return charCount;
+ }
+ ax = totalWidth + wordTotalWidth - 10;
+ if (ax >= maxWidth) { //gotoverend
+ if (centered) {
+ ax = (maxWidth & 0xfe) - totalWidth + 20;
+ ax /= 2;
+ } else {
+ ax = 0;
+ }
+ *offset += ax;
+ return charCount;
+ }
+ totalWidth += wordTotalWidth;
+ charCount += wordCharCount;
+ }
+}
+
+uint8 DreamGenContext::kernchars(uint8 firstChar, uint8 secondChar, uint8 width) {
+ if ((firstChar == 'a') || (al == 'u')) {
+ if ((secondChar == 'n') || (secondChar == 't') || (secondChar == 'r') || (secondChar == 'i') || (secondChar == 'l'))
+ return width-1;
+ }
+ return width;
+}
+
+uint16 DreamGenContext::waitframes() {
+ readmouse();
+ showpointer();
+ vsync();
+ dumppointer();
+ delpointer();
+ return data.word(kMousebutton);
+}
+
+} /*namespace dreamgen */
+
diff --git a/engines/dreamweb/runtime.h b/engines/dreamweb/runtime.h
index decd1cddd8..8aa71b285c 100644
--- a/engines/dreamweb/runtime.h
+++ b/engines/dreamweb/runtime.h
@@ -133,7 +133,7 @@ struct Segment {
return WordRef(data, index);
}
- inline uint8* ptr(unsigned index, unsigned size) {
+ inline uint8 *ptr(unsigned index, unsigned size) {
assert(index + size <= data.size());
return data.begin() + index;
}
@@ -186,7 +186,7 @@ public:
_segment->assign(b, e);
}
- inline uint8* ptr(unsigned index, unsigned size) {
+ inline uint8 *ptr(unsigned index, unsigned size) {
assert(_segment != 0);
return _segment->ptr(index, size);
}
@@ -287,6 +287,12 @@ public:
_freeSegments.push_back(id);
}
+ SegmentRef segRef(uint16 seg) {
+ SegmentRef result(this);
+ result = seg;
+ return result;
+ }
+
inline void _cmp(uint8 a, uint8 b) {
_sub(a, b);
}
@@ -487,7 +493,7 @@ public:
inline void _movsb(uint size, bool clear_cx = false) {
assert(size != 0xffff);
//fixme: add overlap and segment boundary check and rewrite
- while(size--)
+ while (size--)
_movsb();
if (clear_cx)
cx = 0;
@@ -525,7 +531,7 @@ public:
assert(size != 0xffff);
uint8 *dst = es.ptr(di, size * 2);
di += 2 * size;
- while(size--) {
+ while (size--) {
*dst++ = al;
*dst++ = ah;
}
@@ -580,4 +586,3 @@ public:
}
#endif
-
diff --git a/engines/dreamweb/saveload.cpp b/engines/dreamweb/saveload.cpp
new file mode 100644
index 0000000000..636182dc83
--- /dev/null
+++ b/engines/dreamweb/saveload.cpp
@@ -0,0 +1,343 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "dreamweb/dreamweb.h"
+#include "engines/metaengine.h"
+#include "gui/saveload.h"
+#include "common/config-manager.h"
+#include "common/translation.h"
+
+namespace DreamGen {
+
+void DreamGenContext::loadgame() {
+ STACK_CHECK;
+ if (data.byte(kCommandtype) != 246) {
+ data.byte(kCommandtype) = 246;
+ al = 41;
+ commandonly();
+ }
+ if (data.word(kMousebutton) == data.word(kOldbutton))
+ return; // "noload"
+ if (data.word(kMousebutton) == 1) {
+ ax = 0xFFFF;
+ doload();
+ }
+}
+
+// input: ax = savegameId
+// if -1, open menu to ask for slot to load
+// if >= 0, directly load from that slot
+void DreamGenContext::doload() {
+ STACK_CHECK;
+ int savegameId = (int16)ax;
+
+ data.byte(kLoadingorsave) = 1;
+
+ if (ConfMan.getBool("dreamweb_originalsaveload") && savegameId == -1) {
+ showopbox();
+ showloadops();
+ data.byte(kCurrentslot) = 0;
+ showslots();
+ shownames();
+ data.byte(kPointerframe) = 0;
+ worktoscreenm();
+ namestoold();
+ data.byte(kGetback) = 0;
+
+ while (true) {
+ if (data.byte(kQuitrequested))
+ return; // "quitloaded"
+ delpointer();
+ readmouse();
+ showpointer();
+ vsync();
+ dumppointer();
+ dumptextline();
+ bx = offset_loadlist;
+ checkcoords();
+ if (data.byte(kGetback) == 1)
+ break;
+ if (data.byte(kGetback) == 2)
+ return; // "quitloaded"
+ }
+ } else {
+
+ if (savegameId == -1) {
+ // Open dialog to get savegameId
+
+ const EnginePlugin *plugin = NULL;
+ Common::String gameId = ConfMan.get("gameid");
+ EngineMan.findGame(gameId, &plugin);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"));
+ dialog->setSaveMode(false);
+ savegameId = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+ delete dialog;
+ }
+
+ if (savegameId < 0) {
+ data.byte(kGetback) = 0;
+ return;
+ }
+
+
+ // TODO: proper scheme for filename, in a separate function
+ //Common::String filename = ConfMan.getActiveDomainName() + Common::String::format(".d%02d", savegameId);
+ Common::String filename = Common::String::format("DREAMWEB.D%02d", savegameId);
+ debug(1, "Loading from filename: %s", filename.c_str());
+ engine->openSaveFileForReading(filename);
+
+ // TODO: The below is duplicated from Loadposition
+ data.word(kTimecount) = 0;
+ clearchanges();
+
+ ds = cs;
+ dx = kFileheader;
+ cx = kHeaderlen;
+ savefileread();
+ es = cs;
+ di = kFiledata;
+ ax = savegameId;
+ if (savegameId < 7) {
+ cx = 17;
+ _mul(cx);
+ ds = data;
+ dx = kSavenames;
+ _add(dx, ax);
+ loadseg();
+ } else {
+ // For potential support of more than 7 savegame slots,
+ // loading into the savenames buffer isn't always possible
+ // Emulate a loadseg call:
+ uint8 namebuf[17];
+ engine->readFromFile(namebuf, 17);
+ _add(di, 2);
+ }
+ ds = data;
+ dx = kStartvars;
+ loadseg();
+ ds = data.word(kExtras);
+ dx = kExframedata;
+ loadseg();
+ ds = data.word(kBuffers);
+ dx = kListofchanges;
+ loadseg();
+ ds = data;
+ dx = kMadeuproomdat;
+ loadseg();
+ ds = cs;
+ dx = kReelroutines;
+ loadseg();
+ closefile();
+ data.byte(kGetback) = 1;
+ }
+
+ // kTempgraphics might not have been allocated if we bypassed all menus
+ if (data.word(kTempgraphics) != 0xFFFF)
+ getridoftemp();
+
+ dx = data;
+ es = dx;
+ bx = kMadeuproomdat;
+ startloading();
+ loadroomssample();
+ data.byte(kRoomloaded) = 1;
+ data.byte(kNewlocation) = 255;
+ clearsprites();
+ initman();
+ initrain();
+ data.word(kTextaddressx) = 13;
+ data.word(kTextaddressy) = 182;
+ data.byte(kTextlen) = 240;
+ startup();
+ worktoscreen();
+ data.byte(kGetback) = 4;
+}
+
+
+void DreamGenContext::savegame() {
+ STACK_CHECK;
+ if (data.byte(kMandead) == 2) {
+ blank();
+ return;
+ }
+
+ if (data.byte(kCommandtype) != 247) {
+ data.byte(kCommandtype) = 247;
+ al = 44;
+ commandonly();
+ }
+ if (data.word(kMousebutton) != 1)
+ return;
+
+ data.byte(kLoadingorsave) = 2;
+
+ if (ConfMan.getBool("dreamweb_originalsaveload")) {
+ showopbox();
+ showsaveops();
+ data.byte(kCurrentslot) = 0;
+ showslots();
+ shownames();
+ worktoscreenm();
+ namestoold();
+ data.word(kBufferin) = 0;
+ data.word(kBufferout) = 0;
+ data.byte(kGetback) = 0;
+
+ while (true) {
+ _cmp(data.byte(kQuitrequested), 0);
+ if (!flags.z())
+ return /* (quitsavegame) */;
+ delpointer();
+ checkinput();
+ readmouse();
+ showpointer();
+ vsync();
+ dumppointer();
+ dumptextline();
+ bx = offset_savelist;
+ checkcoords();
+ _cmp(data.byte(kGetback), 0);
+ if (flags.z())
+ continue;
+ break;
+ }
+ return;
+ } else {
+ const EnginePlugin *plugin = NULL;
+ Common::String gameId = ConfMan.get("gameid");
+ EngineMan.findGame(gameId, &plugin);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"));
+ dialog->setSaveMode(true);
+ int savegameId = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+ Common::String game_description = dialog->getResultString();
+ if (game_description.empty())
+ game_description = "Untitled";
+ delete dialog;
+
+ if (savegameId < 0) {
+ data.byte(kGetback) = 0;
+ return;
+ }
+
+ // TODO: The below is copied from actualsave
+ al = data.byte(kLocation);
+ ah = 0;
+ cx = 32;
+ _mul(cx);
+ ds = cs;
+ si = kRoomdata;
+ _add(si, ax);
+ di = kMadeuproomdat;
+ bx = di;
+ es = cs;
+ cx = 16;
+ _movsw(cx, true);
+ al = data.byte(kRoomssample);
+ es.byte(bx+13) = al;
+ al = data.byte(kMapx);
+ es.byte(bx+15) = al;
+ al = data.byte(kMapy);
+ es.byte(bx+16) = al;
+ al = data.byte(kLiftflag);
+ es.byte(bx+20) = al;
+ al = data.byte(kManspath);
+ es.byte(bx+21) = al;
+ al = data.byte(kFacing);
+ es.byte(bx+22) = al;
+ al = 255;
+ es.byte(bx+27) = al;
+
+ // TODO: The below is copied from saveposition
+ makeheader();
+
+ //Common::String filename = ConfMan.getActiveDomainName() + Common::String::format(".d%02d", savegameId);
+ Common::String filename = Common::String::format("DREAMWEB.D%02d", savegameId);
+ debug(1, "Saving to filename: %s (%s)", filename.c_str(), game_description.c_str());
+
+ engine->openSaveFileForWriting(filename.c_str());
+
+ dx = data;
+ ds = dx;
+ dx = kFileheader;
+ cx = kHeaderlen;
+ savefilewrite();
+ dx = data;
+ es = dx;
+ di = kFiledata;
+
+ // TODO: Check if this 2 is a constant
+ uint8 descbuf[17] = { 2, 0 };
+ strncpy((char*)descbuf+1, game_description.c_str(), 16);
+ unsigned int desclen = game_description.size();
+ if (desclen > 15)
+ desclen = 15;
+ // zero terminate, and pad with ones
+ descbuf[++desclen] = 0;
+ while (desclen < 17)
+ descbuf[++desclen] = 1;
+ if (savegameId < 7) {
+ ax = savegameId;
+ cx = 17;
+ _mul(cx);
+ ds = data;
+ dx = kSavenames;
+ _add(dx, ax);
+ memcpy(data.ptr(dx,17), descbuf, 17);
+ saveseg();
+ } else {
+ // savenames only has room for descriptions for 7 slots
+ uint16 len = es.word(di);
+ _add(di, 2);
+ assert(len == 17);
+ engine->writeToSaveFile(descbuf, len);
+ }
+
+ ds = data;
+ dx = kStartvars;
+ saveseg();
+ ds = data.word(kExtras);
+ dx = kExframedata;
+ saveseg();
+ ds = data.word(kBuffers);
+ dx = kListofchanges;
+ saveseg();
+ ds = data;
+ dx = kMadeuproomdat;
+ saveseg();
+ ds = data;
+ dx = kReelroutines;
+ saveseg();
+ closefile();
+
+ getridoftemp();
+ restoreall();
+ data.word(kTextaddressx) = 13;
+ data.word(kTextaddressy) = 182;
+ data.byte(kTextlen) = 240;
+ redrawmainscrn();
+ worktoscreenm();
+ data.byte(kGetback) = 4;
+ }
+}
+
+
+} /*namespace dreamgen */
diff --git a/engines/dreamweb/sprite.cpp b/engines/dreamweb/sprite.cpp
new file mode 100644
index 0000000000..17d4ddbbed
--- /dev/null
+++ b/engines/dreamweb/sprite.cpp
@@ -0,0 +1,893 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "dreamweb/dreamweb.h"
+#include "engines/util.h"
+#include "graphics/surface.h"
+
+namespace DreamGen {
+
+Sprite *DreamGenContext::spritetable() {
+ Sprite *sprite = (Sprite *)segRef(data.word(kBuffers)).ptr(kSpritetable, 16 * sizeof(Sprite));
+ return sprite;
+}
+
+void DreamGenContext::printsprites() {
+ for (size_t priority = 0; priority < 7; ++priority) {
+ Sprite *sprites = spritetable();
+ for (size_t j = 0; j < 16; ++j) {
+ const Sprite &sprite = sprites[j];
+ if (sprite.updateCallback() == 0x0ffff)
+ continue;
+ if (priority != sprite.priority)
+ continue;
+ if (sprite.hidden == 1)
+ continue;
+ printasprite(&sprite);
+ }
+ }
+}
+
+void DreamGenContext::printasprite(const Sprite *sprite) {
+ uint16 x, y;
+ if (sprite->y >= 220) {
+ y = data.word(kMapady) - (256 - sprite->y);
+ } else {
+ y = sprite->y + data.word(kMapady);
+ }
+
+ if (sprite->x >= 220) {
+ x = data.word(kMapadx) - (256 - sprite->x);
+ } else {
+ x = sprite->x + data.word(kMapadx);
+ }
+
+ uint8 c;
+ if (sprite->b29 != 0)
+ c = 8;
+ else
+ c = 0;
+ showframe((const Frame *)segRef(sprite->frameData()).ptr(0, 0), x, y, sprite->b15, c);
+}
+
+void DreamGenContext::clearsprites() {
+ memset(spritetable(), 0xff, sizeof(Sprite) * 16);
+}
+
+Sprite *DreamGenContext::makesprite(uint8 x, uint8 y, uint16 updateCallback, uint16 frameData, uint16 somethingInDi) {
+ Sprite *sprite = spritetable();
+ while (sprite->b15 != 0xff) { // NB: No boundchecking in the original code either
+ ++sprite;
+ }
+
+ sprite->setUpdateCallback(updateCallback);
+ sprite->x = x;
+ sprite->y = y;
+ sprite->setFrameData(frameData);
+ WRITE_LE_UINT16(&sprite->w8, somethingInDi);
+ sprite->w2 = 0xffff;
+ sprite->b15 = 0;
+ sprite->delay = 0;
+ return sprite;
+}
+
+void DreamGenContext::makesprite() { // NB: returns new sprite in es:bx
+ Sprite *sprite = makesprite(si & 0xff, si >> 8, cx, dx, di);
+
+ // Recover es:bx from sprite
+ es = data.word(kBuffers);
+ bx = kSpritetable;
+ Sprite *sprites = (Sprite *)es.ptr(bx, sizeof(Sprite) * 16);
+ bx += sizeof(Sprite) * (sprite - sprites);
+ //
+}
+
+void DreamGenContext::spriteupdate() {
+ Sprite *sprites = spritetable();
+ sprites[0].hidden = data.byte(kRyanon);
+
+ Sprite *sprite = sprites;
+ for (size_t i=0; i < 16; ++i) {
+ uint16 updateCallback = sprite->updateCallback();
+ if (updateCallback != 0xffff) {
+ sprite->w24 = sprite->w2;
+ if (updateCallback == addr_mainman) // NB : Let's consider the callback as an enum while more code is not ported to C++
+ mainman(sprite);
+ else {
+ assert(updateCallback == addr_backobject);
+ backobject(sprite);
+ }
+ }
+
+ if (data.byte(kNowinnewroom) == 1)
+ break;
+ ++sprite;
+ }
+}
+
+void DreamGenContext::initman() {
+ Sprite *sprite = makesprite(data.byte(kRyanx), data.byte(kRyany), addr_mainman, data.word(kMainsprites), 0);
+ sprite->priority = 4;
+ sprite->b22 = 0;
+ sprite->b29 = 0;
+}
+
+void DreamGenContext::mainman() {
+ assert(false);
+}
+
+void DreamGenContext::mainman(Sprite *sprite) {
+ push(es);
+ push(ds);
+
+ // Recover es:bx from sprite
+ es = data.word(kBuffers);
+ bx = kSpritetable;
+ Sprite *sprites = (Sprite *)es.ptr(bx, sizeof(Sprite) * 16);
+ bx += 32 * (sprite - sprites);
+ //
+
+ if (data.byte(kResetmanxy) == 1) {
+ data.byte(kResetmanxy) = 0;
+ sprite->x = data.byte(kRyanx);
+ sprite->y = data.byte(kRyany);
+ sprite->b29 = 0;
+ }
+ --sprite->b22;
+ if (sprite->b22 != 0xff) {
+ ds = pop();
+ es = pop();
+ return;
+ }
+ sprite->b22 = 0;
+ if (data.byte(kTurntoface) != data.byte(kFacing)) {
+ aboutturn(sprite);
+ } else {
+ if ((data.byte(kTurndirection) != 0) && (data.byte(kLinepointer) == 254)) {
+ data.byte(kReasseschanges) = 1;
+ if (data.byte(kFacing) == data.byte(kLeavedirection))
+ checkforexit();
+ }
+ data.byte(kTurndirection) = 0;
+ if (data.byte(kLinepointer) == 254) {
+ sprite->b29 = 0;
+ } else {
+ ++sprite->b29;
+ if (sprite->b29 == 11)
+ sprite->b29 = 1;
+ walking(sprite);
+ if (data.byte(kLinepointer) != 254) {
+ if ((data.byte(kFacing) & 1) == 0)
+ walking(sprite);
+ else if ((sprite->b29 != 2) && (sprite->b29 != 7))
+ walking(sprite);
+ }
+ if (data.byte(kLinepointer) == 254) {
+ if (data.byte(kTurntoface) == data.byte(kFacing)) {
+ data.byte(kReasseschanges) = 1;
+ if (data.byte(kFacing) == data.byte(kLeavedirection))
+ checkforexit();
+ }
+ }
+ }
+ }
+ static const uint8 facelist[] = { 0,60,33,71,11,82,22,93 };
+ sprite->b15 = sprite->b29 + facelist[data.byte(kFacing)];
+ data.byte(kRyanx) = sprite->x;
+ data.byte(kRyany) = sprite->y;
+
+ ds = pop();
+ es = pop();
+}
+
+void DreamGenContext::walking(Sprite *sprite) {
+ uint8 comp;
+ if (data.byte(kLinedirection) != 0) {
+ --data.byte(kLinepointer);
+ comp = 200;
+ } else {
+ ++data.byte(kLinepointer);
+ comp = data.byte(kLinelength);
+ }
+ if (data.byte(kLinepointer) < comp) {
+ sprite->x = data.byte(kLinedata + data.byte(kLinepointer) * 2 + 0);
+ sprite->y = data.byte(kLinedata + data.byte(kLinepointer) * 2 + 1);
+ return;
+ }
+
+ data.byte(kLinepointer) = 254;
+ data.byte(kManspath) = data.byte(kDestination);
+ if (data.byte(kDestination) == data.byte(kFinaldest)) {
+ facerightway();
+ return;
+ }
+ data.byte(kDestination) = data.byte(kFinaldest);
+ push(es);
+ push(bx);
+ autosetwalk();
+ bx = pop();
+ es = pop();
+}
+
+void DreamGenContext::aboutturn(Sprite *sprite) {
+ bool incdir = true;
+
+ if (data.byte(kTurndirection) == 1)
+ incdir = true;
+ else if ((int8)data.byte(kTurndirection) == -1)
+ incdir = false;
+ else {
+ if (data.byte(kFacing) < data.byte(kTurntoface)) {
+ uint8 delta = data.byte(kTurntoface) - data.byte(kFacing);
+ if (delta >= 4)
+ incdir = false;
+ else
+ incdir = true;
+ } else {
+ uint8 delta = data.byte(kFacing) - data.byte(kTurntoface);
+ if (delta >= 4)
+ incdir = true;
+ else
+ incdir = false;
+ }
+ }
+
+ if (incdir) {
+ data.byte(kTurndirection) = 1;
+ data.byte(kFacing) = (data.byte(kFacing) + 1) & 7;
+ sprite->b29 = 0;
+ } else {
+ data.byte(kTurndirection) = -1;
+ data.byte(kFacing) = (data.byte(kFacing) - 1) & 7;
+ sprite->b29 = 0;
+ }
+}
+
+void DreamGenContext::backobject() {
+ assert(false);
+}
+
+void DreamGenContext::backobject(Sprite *sprite) {
+ SetObject *objData = (SetObject *)segRef(data.word(kSetdat)).ptr(sprite->objData(), 0);
+
+ if (sprite->delay != 0) {
+ --sprite->delay;
+ return;
+ }
+
+ sprite->delay = objData->delay;
+ if (objData->type == 6)
+ widedoor(sprite, objData);
+ else if (objData->type == 5)
+ random(sprite, objData);
+ else if (objData->type == 4)
+ lockeddoorway(sprite, objData);
+ else if (objData->type == 3)
+ liftsprite(sprite, objData);
+ else if (objData->type == 2)
+ doorway(sprite, objData);
+ else if (objData->type == 1)
+ constant(sprite, objData);
+ else
+ steady(sprite, objData);
+}
+
+void DreamGenContext::constant(Sprite *sprite, SetObject *objData) {
+ ++sprite->frame;
+ if (objData->b18[sprite->frame] == 255) {
+ sprite->frame = 0;
+ }
+ uint8 b18 = objData->b18[sprite->frame];
+ objData->b17 = b18;
+ sprite->b15 = b18;
+}
+
+void DreamGenContext::random(Sprite *sprite, SetObject *objData) {
+ randomnum1();
+ uint16 r = ax;
+ sprite->b15 = objData->b18[r&7];
+}
+
+void DreamGenContext::doorway(Sprite *sprite, SetObject *objData) {
+ data.byte(kDoorcheck1) = -24;
+ data.byte(kDoorcheck2) = 10;
+ data.byte(kDoorcheck3) = -30;
+ data.byte(kDoorcheck4) = 10;
+ dodoor(sprite, objData);
+}
+
+void DreamGenContext::widedoor(Sprite *sprite, SetObject *objData) {
+ data.byte(kDoorcheck1) = -24;
+ data.byte(kDoorcheck2) = 24;
+ data.byte(kDoorcheck3) = -30;
+ data.byte(kDoorcheck4) = 24;
+ dodoor(sprite, objData);
+}
+
+void DreamGenContext::dodoor() {
+ Sprite *sprite = (Sprite *)es.ptr(bx, sizeof(Sprite));
+ SetObject *objData = (SetObject *)ds.ptr(di, 0);
+ dodoor(sprite, objData);
+}
+
+void DreamGenContext::dodoor(Sprite *sprite, SetObject *objData) {
+ uint8 ryanx = data.byte(kRyanx);
+ uint8 ryany = data.byte(kRyany);
+ if (ryanx < sprite->x) {
+ if (ryanx < sprite->x + (int8)data.byte(kDoorcheck1))
+ goto shutdoor;
+ } else {
+ if (ryanx >= sprite->x + data.byte(kDoorcheck2))
+ goto shutdoor;
+ }
+ if (ryany < sprite->y) {
+ if (ryany < sprite->y + (int8)data.byte(kDoorcheck3))
+ goto shutdoor;
+ } else {
+ if (ryany >= sprite->y + data.byte(kDoorcheck4))
+ goto shutdoor;
+ }
+//opendoor:
+ if ((data.byte(kThroughdoor) == 1) && (sprite->frame == 0))
+ sprite->frame = 6;
+
+ ++sprite->frame;
+ if (sprite->frame == 1) { //doorsound2
+ if (data.byte(kReallocation) == 5) //hoteldoor2
+ al = 13;
+ else
+ al = 0;
+ playchannel1();
+ }
+ if (objData->b18[sprite->frame] == 255) {
+ --sprite->frame;
+ }
+ sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ data.byte(kThroughdoor) = 1;
+ return;
+shutdoor:
+ if (sprite->frame == 5) { //doorsound1;
+ if (data.byte(kReallocation) == 5) //hoteldoor1
+ al = 13;
+ else
+ al = 1;
+ playchannel1();
+ }
+ if (sprite->frame != 0) {
+ --sprite->frame;
+ }
+ sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ if (sprite->frame == 5) //nearly
+ data.byte(kThroughdoor) = 0;
+}
+
+void DreamGenContext::steady(Sprite *sprite, SetObject *objData) {
+ uint8 b18 = objData->b18[0];
+ objData->b17 = b18;
+ sprite->b15 = b18;
+}
+
+void DreamGenContext::lockeddoorway(Sprite *sprite, SetObject *objData) {
+ if (data.byte(kRyanx) < sprite->x) {
+ if (sprite->x - data.byte(kRyanx) > 24)
+ goto shutdoor2;
+ } else {
+ if (data.byte(kRyanx) - sprite->x >= 10)
+ goto shutdoor2;
+ }
+
+ if (data.byte(kRyany) < sprite->y) {
+ if (sprite->y - data.byte(kRyany) > 30)
+ goto shutdoor2;
+ } else {
+ if (data.byte(kRyany) - sprite->y >= 12)
+ goto shutdoor2;
+ }
+
+ if (data.byte(kThroughdoor) != 1) {
+ if (data.byte(kLockstatus) == 1)
+ goto shutdoor2;
+ }
+
+ if (sprite->frame == 1) {
+ al = 0;
+ playchannel1();
+ }
+
+ if (sprite->frame == 6) {
+ turnpathonCPP(data.byte(kDoorpath));
+ }
+
+ if ((data.byte(kThroughdoor) == 1) && (sprite->frame == 0)) {
+ sprite->frame = 6;
+ }
+
+ ++sprite->frame;
+ if (objData->b18[sprite->frame] == 255) {
+ --sprite->frame;
+ }
+
+ sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ if (sprite->frame == 5)
+ data.byte(kThroughdoor) = 1;
+ return;
+
+shutdoor2:
+ if (sprite->frame == 5) {
+ al = 1;
+ playchannel1();
+ }
+
+ if (sprite->frame != 0) {
+ --sprite->frame;
+ }
+
+ data.byte(kThroughdoor) = 0;
+ sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+
+ if (sprite->frame == 0) {
+ turnpathoffCPP(data.byte(kDoorpath));
+ data.byte(kLockstatus) = 1;
+ }
+}
+
+void DreamGenContext::liftsprite(Sprite *sprite, SetObject *objData) {
+ uint8 liftFlag = data.byte(kLiftflag);
+ if (liftFlag == 0) { //liftclosed
+ turnpathoffCPP(data.byte(kLiftpath));
+
+ if (data.byte(kCounttoopen) != 0) {
+ _dec(data.byte(kCounttoopen));
+ if (data.byte(kCounttoopen) == 0)
+ data.byte(kLiftflag) = 3;
+ }
+ sprite->frame = 0;
+ sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ }
+ else if (liftFlag == 1) { //liftopen
+ turnpathonCPP(data.byte(kLiftpath));
+
+ if (data.byte(kCounttoclose) != 0) {
+ _dec(data.byte(kCounttoclose));
+ if (data.byte(kCounttoclose) == 0)
+ data.byte(kLiftflag) = 2;
+ }
+ sprite->frame = 12;
+ sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ }
+ else if (liftFlag == 3) { //openlift
+ if (sprite->frame == 12) {
+ data.byte(kLiftflag) = 1;
+ return;
+ }
+ ++sprite->frame;
+ if (sprite->frame == 1) {
+ al = 2;
+ liftnoise();
+ }
+ sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ } else { //closeLift
+ assert(liftFlag == 2);
+ if (sprite->frame == 0) {
+ data.byte(kLiftflag) = 0;
+ return;
+ }
+ --sprite->frame;
+ if (sprite->frame == 11) {
+ al = 3;
+ liftnoise();
+ }
+ sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ }
+}
+
+void DreamGenContext::facerightway() {
+ uint8 *paths = getroomspathsCPP();
+ uint8 dir = paths[8 * data.byte(kManspath) + 7];
+ data.byte(kTurntoface) = dir;
+ data.byte(kLeavedirection) = dir;
+}
+
+void DreamGenContext::findsource() {
+ uint16 currentFrame = data.word(kCurrentframe);
+ if (currentFrame < 160) {
+ ds = data.word(kReel1);
+ data.word(kTakeoff) = 0;
+ } else if (currentFrame < 320) {
+ ds = data.word(kReel2);
+ data.word(kTakeoff) = 160;
+ } else {
+ ds = data.word(kReel3);
+ data.word(kTakeoff) = 320;
+ }
+}
+
+Frame *DreamGenContext::findsourceCPP() {
+ push(ds);
+ findsource();
+ Frame *result = (Frame *)ds.ptr(0, 0);
+ ds = pop();
+ return result;
+}
+
+Reel *DreamGenContext::getreelstart() {
+ Reel *reel = (Reel *)segRef(data.word(kReels)).ptr(kReellist + data.word(kReelpointer) * sizeof(Reel) * 8, sizeof(Reel));
+ return reel;
+}
+
+void DreamGenContext::showreelframe() {
+ Reel *reel = (Reel *)es.ptr(si, sizeof(Reel));
+ showreelframe(reel);
+}
+
+void DreamGenContext::showreelframe(Reel *reel) {
+ uint16 x = reel->x + data.word(kMapadx);
+ uint16 y = reel->y + data.word(kMapady);
+ data.word(kCurrentframe) = reel->frame();
+ Frame *source = findsourceCPP();
+ uint16 frame = data.word(kCurrentframe) - data.word(kTakeoff);
+ showframe(source, x, y, frame, 8);
+}
+
+void DreamGenContext::showgamereel() {
+ uint16 reelpointer = es.word(bx+3);
+ if (reelpointer >= 512)
+ return;
+ data.word(kReelpointer) = reelpointer;
+ push(es);
+ push(bx);
+ plotreel();
+ bx = pop();
+ es = pop();
+ es.word(bx+3) = data.word(kReelpointer);
+}
+
+const Frame *DreamGenContext::getreelframeax(uint16 frame) {
+ data.word(kCurrentframe) = frame;
+ Frame *source = findsourceCPP();
+ uint16 offset = data.word(kCurrentframe) - data.word(kTakeoff);
+ return source + offset;
+}
+
+void DreamGenContext::showrain() {
+ ds = data.word(kMainsprites);
+ si = 6*58;
+ ax = ds.word(si+2);
+ si = ax + 2080;
+ Rain *rain = (Rain *)segRef(data.word(kBuffers)).ptr(kRainlist, 0);
+ if (rain->x == 255)
+ return;
+ while (true) {
+ if (rain->x == 255) {
+ if (data.word(kCh1blockstocopy) != 0)
+ return;
+ if ((data.byte(kReallocation) == 2) && (data.byte(kBeenmugged) != 1))
+ return;
+ if (data.byte(kReallocation) == 55)
+ return;
+ randomnum1();
+ if (al >= 1)
+ return;
+ if (data.byte(kCh0playing) != 6)
+ al = 4;
+ else
+ al = 7;
+ playchannel1();
+ return;
+ }
+ uint16 y = rain->y + data.word(kMapady) + data.word(kMapystart);
+ uint16 x = rain->x + data.word(kMapadx) + data.word(kMapxstart);
+ uint16 size = rain->size;
+ ax = ((uint16)(rain->w3() - rain->b5)) & 511;
+ rain->setW3(ax);
+ ++rain;
+ const uint8 *src = ds.ptr(si, 0) + ax;
+ uint8 *dst = workspace() + y * 320 + x;
+ for(uint16 i = 0; i < size; ++i) {
+ uint8 v = src[i];
+ if (v != 0)
+ *dst = v;
+ dst += 320-1;
+ }
+ }
+}
+
+void DreamGenContext::updatepeople() {
+ data.word(kListpos) = kPeoplelist;
+ memset(segRef(data.word(kBuffers)).ptr(kPeoplelist, 12 * sizeof(People)), 0xff, 12 * sizeof(People));
+ ++data.word(kMaintimer);
+ es = cs;
+ bx = kReelroutines;
+ const ReelRoutine *reelRoutine = (const ReelRoutine *)cs.ptr(bx, 0);
+ const uint16 *callbacks = (const uint16 *)cs.ptr(kReelcalls, 0);
+ while (true) {
+ uint8 realLocation = reelRoutine->reallocation;
+ if (realLocation == 255)
+ return;
+ if ((realLocation == data.byte(kReallocation)) &&
+ (reelRoutine->mapX == data.byte(kMapx)) &&
+ (reelRoutine->mapY == data.byte(kMapy))) {
+ uint16 callback = READ_LE_UINT16(callbacks);
+ //dw gamer,sparkydrip,eden,edeninbath,sparky,smokebloke
+ if (callback == addr_gamer)
+ gamer();
+ else if (callback == addr_sparkydrip)
+ sparkydrip();
+ else if (callback == addr_eden)
+ eden();
+ else if (callback == addr_edeninbath)
+ edeninbath();
+ else if (callback == addr_sparky)
+ sparky();
+ else if (callback == addr_smokebloke)
+ smokebloke();
+ //dw manasleep,drunk,receptionist,malefan,femalefan
+ else if (callback == addr_manasleep)
+ manasleep();
+ else if (callback == addr_drunk)
+ drunk();
+ else if (callback == addr_receptionist)
+ receptionist();
+ else if (callback == addr_malefan)
+ malefan();
+ else if (callback == addr_femalefan)
+ femalefan();
+ //dw louis,louischair,soldier1,bossman,interviewer
+ else if (callback == addr_louis)
+ louis();
+ else if (callback == addr_louischair)
+ louischair();
+ else if (callback == addr_soldier1)
+ soldier1();
+ else if (callback == addr_bossman)
+ bossman();
+ else if (callback == addr_interviewer)
+ interviewer();
+ //dw heavy,manasleep2,mansatstill,drinker,bartender
+ else if (callback == addr_heavy)
+ heavy();
+ else if (callback == addr_manasleep2)
+ manasleep2();
+ else if (callback == addr_mansatstill)
+ mansatstill();
+ else if (callback == addr_drinker)
+ drinker();
+ else if (callback == addr_bartender)
+ bartender();
+ //dw othersmoker,tattooman,attendant,keeper,candles1
+ else if (callback == addr_othersmoker)
+ othersmoker();
+ else if (callback == addr_tattooman)
+ tattooman();
+ else if (callback == addr_attendant)
+ attendant();
+ else if (callback == addr_keeper)
+ keeper();
+ else if (callback == addr_candles1)
+ candles1();
+ //dw smallcandle,security,copper,poolguard,rockstar
+ else if (callback == addr_smallcandle)
+ smallcandle();
+ else if (callback == addr_security)
+ security();
+ else if (callback == addr_copper)
+ copper();
+ else if (callback == addr_poolguard)
+ poolguard();
+ else if (callback == addr_rockstar)
+ rockstar();
+ //dw businessman,train,aide,mugger,helicopter
+ else if (callback == addr_businessman)
+ businessman();
+ else if (callback == addr_train)
+ train();
+ else if (callback == addr_aide)
+ aide();
+ else if (callback == addr_mugger)
+ mugger();
+ else if (callback == addr_helicopter)
+ helicopter();
+ //dw intromagic1,intromusic,intromagic2,candles2,gates
+ else if (callback == addr_intromagic1)
+ intromagic1();
+ else if (callback == addr_intromusic)
+ intromusic();
+ else if (callback == addr_intromagic2)
+ intromagic2();
+ else if (callback == addr_candles2)
+ candles2();
+ else if (callback == addr_gates)
+ gates();
+ //dw intromagic3,intromonks1,candles,intromonks2
+ else if (callback == addr_intromagic3)
+ intromagic3();
+ else if (callback == addr_intromonks1)
+ intromonks1();
+ else if (callback == addr_candles)
+ candles();
+ else if (callback == addr_intromonks2)
+ intromonks2();
+ //dw handclap,monkandryan,endgameseq,priest,madman
+ else if (callback == addr_handclap)
+ handclap();
+ else if (callback == addr_monkandryan)
+ monkandryan();
+ else if (callback == addr_endgameseq)
+ endgameseq();
+ else if (callback == addr_priest)
+ priest();
+ else if (callback == addr_madman)
+ madman();
+ //dw madmanstelly,alleybarksound,foghornsound
+ else if (callback == addr_madmanstelly)
+ madmanstelly();
+ else if (callback == addr_alleybarksound)
+ alleybarksound();
+ else if (callback == addr_foghornsound)
+ foghornsound();
+ //dw carparkdrip,carparkdrip,carparkdrip,carparkdrip
+ else if (callback == addr_carparkdrip)
+ carparkdrip();
+ else
+ assert(false); // Oops I forgot something in the dispatch table
+ }
+ bx += 8;
+ ++reelRoutine;
+ ++callbacks;
+ }
+}
+
+void DreamGenContext::madmantext() {
+ if (isCD()) {
+ if (data.byte(kSpeechcount) >= 63)
+ return;
+ if (data.byte(kCh1playing) != 255)
+ return;
+ al = data.byte(kSpeechcount);
+ ++data.byte(kSpeechcount);
+ } else {
+ if (data.byte(kCombatcount) >= 61)
+ return;
+ al = data.byte(kCombatcount);
+ _and(al, 3);
+ if (!flags.z())
+ return;
+ al = data.byte(kCombatcount) / 4;
+ }
+ setuptimedtemp(47 + al, 82, 72, 80, 90, 1);
+}
+
+void DreamGenContext::madman() {
+ data.word(kWatchingtime) = 2;
+ checkspeed();
+ if (flags.z()) {
+ ax = es.word(bx+3);
+ if (ax >= 364) {
+ data.byte(kMandead) = 2;
+ showgamereel();
+ return;
+ }
+ if (ax == 10) {
+ push(es);
+ push(bx);
+ push(ax);
+ dx = kIntrotextname;
+ loadtemptext();
+ ax = pop();
+ bx = pop();
+ es = pop();
+ data.byte(kCombatcount) = -1;
+ data.byte(kSpeechcount) = 0;
+ }
+ ++ax;
+ if (ax == 294) {
+ if (data.byte(kWongame) == 1)
+ return;
+ data.byte(kWongame) = 1;
+ push(es);
+ push(bx);
+ getridoftemptext();
+ bx = pop();
+ es = pop();
+ return;
+ }
+ if (ax == 66) {
+ ++data.byte(kCombatcount);
+ push(es);
+ push(bx);
+ madmantext();
+ bx = pop();
+ es = pop();
+ ax = 53;
+ if (data.byte(kCombatcount) >= (isCD() ? 64 : 62)) {
+ if (data.byte(kCombatcount) == (isCD() ? 70 : 68))
+ ax = 310;
+ else {
+ if (data.byte(kLastweapon) == 8) {
+ data.byte(kCombatcount) = isCD() ? 72 : 70;
+ data.byte(kLastweapon) = -1;
+ data.byte(kMadmanflag) = 1;
+ ax = 67;
+ }
+ }
+ }
+ }
+ es.word(bx+3) = ax;
+ }
+ showgamereel();
+ es.byte(bx+1) = data.byte(kMapx);
+ madmode();
+}
+
+void DreamGenContext::madmode() {
+ data.word(kWatchingtime) = 2;
+ data.byte(kPointermode) = 0;
+ if (data.byte(kCombatcount) < (isCD() ? 65 : 63))
+ return;
+ if (data.byte(kCombatcount) >= (isCD() ? 70 : 68))
+ return;
+ data.byte(kPointermode) = 2;
+}
+
+void DreamGenContext::movemap(uint8 param) {
+ switch (param) {
+ case 32:
+ data.byte(kMapy) -= 20;
+ break;
+ case 16:
+ data.byte(kMapy) -= 10;
+ break;
+ case 8:
+ data.byte(kMapy) += 10;
+ break;
+ case 2:
+ data.byte(kMapx) += 11;
+ break;
+ default:
+ data.byte(kMapx) -= 11;
+ break;
+ }
+ data.byte(kNowinnewroom) = 1;
+}
+
+void DreamGenContext::checkone() {
+ uint8 flag, flagEx, type, flagX, flagY;
+ checkone(cl, ch, &flag, &flagEx, &type, &flagX, &flagY);
+
+ cl = flag;
+ ch = flagEx;
+ dl = flagX;
+ dh = flagY;
+ al = type;
+}
+
+void DreamGenContext::checkone(uint8 x, uint8 y, uint8 *flag, uint8 *flagEx, uint8 *type, uint8 *flagX, uint8 *flagY) {
+ *flagX = x / 16;
+ *flagY = y / 16;
+ const uint8 *tileData = segRef(data.word(kBuffers)).ptr(kMapflags + (*flagY * 11 + *flagX) * 3, 3);
+ *flag = tileData[0];
+ *flagEx = tileData[1];
+ *type = tileData[2];
+}
+
+} /*namespace dreamgen */
+
diff --git a/engines/dreamweb/structs.h b/engines/dreamweb/structs.h
index e274375cf4..1cb52eccea 100644
--- a/engines/dreamweb/structs.h
+++ b/engines/dreamweb/structs.h
@@ -20,21 +20,30 @@
*
*/
+#include "common/endian.h"
+
struct Sprite {
- uint16 updateCallback;
+ uint16 _updateCallback;
+ uint16 updateCallback() const { return READ_LE_UINT16(&_updateCallback); }
+ void setUpdateCallback(uint16 v) { WRITE_LE_UINT16(&_updateCallback, v); }
uint16 w2;
uint16 w4;
- uint16 w6;
+ uint16 _frameData;
+ uint16 frameData() const { return READ_LE_UINT16(&_frameData); }
+ void setFrameData(uint16 v) { WRITE_LE_UINT16(&_frameData, v); }
uint16 w8;
uint8 x;
uint8 y;
uint16 w12;
uint8 b14;
uint8 b15;
- uint16 w16;
+ uint8 b16;
+ uint8 b17;
uint8 delay;
uint8 frame;
- uint16 obj_data;
+ uint16 _objData;
+ uint16 objData() const { return READ_LE_UINT16(&_objData); }
+ void setObjData(uint16 v) { WRITE_LE_UINT16(&_objData, v); }
uint8 b22;
uint8 priority;
uint16 w24;
@@ -45,24 +54,180 @@ struct Sprite {
uint8 hidden;
};
-struct ObjData {
+struct RectWithCallback {
+ uint16 _xMin, _xMax;
+ uint16 _yMin, _yMax;
+ uint16 _callback;
+
+ uint16 xMin() const { return READ_LE_UINT16(&_xMin); }
+ uint16 xMax() const { return READ_LE_UINT16(&_xMax); }
+ uint16 yMin() const { return READ_LE_UINT16(&_yMin); }
+ uint16 yMax() const { return READ_LE_UINT16(&_yMax); }
+ uint16 callback() const { return READ_LE_UINT16(&_callback); }
+
+ bool contains(uint16 x, uint16 y) const {
+ return (x >= xMin()) && (x < xMax()) && (y >= yMin()) && (y < yMax());
+ }
+};
+
+struct SetObject {
uint8 b0;
uint8 b1;
uint8 b2;
uint8 b3;
uint8 b4;
- uint8 b5;
+ uint8 priority;
uint8 b6;
uint8 delay;
uint8 type;
uint8 b9;
uint8 b10;
uint8 b11;
+ uint8 name[4];
+ uint8 b16;
+ uint8 b17;
+ uint8 b18[13]; // NB: Don't know the size yet
+ uint8 b31;
+ uint8 b32;
+ uint8 b33;
+ uint8 b34;
+ uint8 b35;
+ uint8 b36;
+ uint8 b37;
+ uint8 b38;
+ uint8 b39;
+ uint8 b40;
+ uint8 b41;
+ uint8 b42;
+ uint8 b43;
+ uint8 b44;
+ uint8 b45;
+ uint8 b46;
+ uint8 b47;
+ uint8 b48;
+ uint8 b49;
+ uint8 b50;
+ uint8 b51;
+ uint8 b52;
+ uint8 b53;
+ uint8 b54;
+ uint8 b55;
+ uint8 b56;
+ uint8 b57;
+ uint8 b58[5];
+ uint8 b63;
+};
+
+struct DynObject {
+ uint8 b0;
+ uint8 index;
+ uint8 b2;
+ uint8 b3;
+ uint8 b4;
+ uint8 b5;
+ uint8 b6;
+ uint8 b7;
+ uint8 b8;
+ uint8 b9;
+ uint8 b10;
+ uint8 location;
+ uint8 id[4];
+};
+
+struct ObjPos {
+ uint8 xMin;
+ uint8 yMin;
+ uint8 xMax;
+ uint8 yMax;
+ uint8 index;
+};
+
+struct Frame {
+ uint8 width;
+ uint8 height;
+ uint16 _ptr;
+ uint16 ptr() const { return READ_LE_UINT16(&_ptr); }
+ void setPtr(uint16 v) { WRITE_LE_UINT16(&_ptr, v); }
+ uint8 x;
+ uint8 y;
+};
+
+struct Reel {
+ uint8 frame_lo;
+ uint8 frame_hi;
+ uint16 frame() const { return READ_LE_UINT16(&frame_lo); }
+ void setFrame(uint16 v) { WRITE_LE_UINT16(&frame_lo, v); }
+ uint8 x;
+ uint8 y;
+ uint8 b4;
+};
+
+struct ReelRoutine {
+ uint8 reallocation;
+ uint8 mapX;
+ uint8 mapY;
+ uint8 b3;
+ uint8 b4;
+ uint8 b5;
+ uint8 b6;
+ uint8 b7;
+};
+
+struct People {
+ uint8 b0;
+ uint8 b1;
+ uint16 w0() const { return READ_LE_UINT16(&b0); }
+ void setW0(uint16 v) { WRITE_LE_UINT16(&b0, v); }
+ uint8 b2;
+ uint8 b3;
+ uint16 w2() const { return READ_LE_UINT16(&b2); }
+ void setW2(uint16 v) { WRITE_LE_UINT16(&b2, v); }
+ uint8 b4;
+
+};
+
+struct Room {
+ uint8 name[10];
+ uint8 b10;
+ uint8 b11;
uint8 b12;
- uint8 b13;
+ uint8 roomsSample;
uint8 b14;
- uint8 b15;
- uint8 b16;
+ uint8 mapX;
+ uint8 mapY;
uint8 b17;
- uint8 b18[256]; // NB: Don't know the size yet
+ uint8 b18;
+ uint8 b19;
+ uint8 liftFlag;
+ uint8 b21;
+ uint8 b22;
+ uint8 countToOpen;
+ uint8 liftPath;
+ uint8 doorPath;
+ uint8 b26;
+ uint8 b27;
+ uint8 b28;
+ uint8 b29;
+ uint8 b30;
+ uint8 b31;
};
+
+struct Rain {
+ uint8 x;
+ uint8 y;
+ uint8 size;
+ uint8 w3_lo;
+ uint8 w3_hi;
+ uint16 w3() const { return READ_LE_UINT16(&w3_lo); }
+ void setW3(uint16 v) { WRITE_LE_UINT16(&w3_lo, v); }
+ uint8 b5;
+};
+
+struct Change {
+ uint8 index;
+ uint8 location;
+ uint8 value;
+ uint8 type;
+};
+
+
diff --git a/engines/dreamweb/stubs.cpp b/engines/dreamweb/stubs.cpp
index 54685a018a..9b85cbb9f4 100644
--- a/engines/dreamweb/stubs.cpp
+++ b/engines/dreamweb/stubs.cpp
@@ -23,131 +23,184 @@
#include "dreamweb/dreamweb.h"
#include "engines/util.h"
#include "graphics/surface.h"
+#include "common/config-manager.h"
namespace DreamGen {
-Common::String getFilename(Context &context) {
- uint16 name_ptr = context.dx;
- Common::String name;
- uint8 c;
- while((c = context.cs.byte(name_ptr++)) != 0)
- name += (char)c;
- return name;
-}
+void DreamGenContext::dreamweb() {
+ STACK_CHECK;
+ seecommandtail();
+ checkbasemem();
+ soundstartup();
+ setkeyboardint();
+ setupemm();
+ allocatebuffers();
+ setmouse();
+ fadedos();
+ gettime();
+ clearbuffers();
+ clearpalette();
+ set16colpalette();
+ readsetdata();
+ data.byte(kWongame) = 0;
-void DreamGenContext::multiget() {
- unsigned w = (uint8)cl, h = (uint8)ch;
- unsigned x = (uint16)di, y = (uint16)bx;
- unsigned src = x + y * kScreenwidth;
- unsigned dst = (uint16)si;
- es = ds;
- ds = data.word(kWorkspace);
- if (y + h > 200)
- h = 200 - y;
- if (x + w > 320)
- w = 320 - x;
- //debug(1, "multiget %u,%u %ux%u -> segment: %04x->%04x", x, y, w, h, (uint16)ds, (uint16)es);
- for(unsigned l = 0; l < h; ++l) {
- uint8 *src_p = ds.ptr(src + kScreenwidth * l, w);
- uint8 *dst_p = es.ptr(dst + w * l, w);
- memcpy(dst_p, src_p, w);
- }
- si += w * h;
- di = src + kScreenwidth * h;
- cx = 0;
-}
+ dx = 1909;
+ loadsample();
+ setsoundoff();
-void DreamGenContext::multiput() {
- unsigned w = (uint8)cl, h = (uint8)ch;
- unsigned x = (uint16)di, y = (uint16)bx;
- unsigned src = (uint16)si;
- unsigned dst = x + y * kScreenwidth;
- es = data.word(kWorkspace);
- if (y + h > 200)
- h = 200 - y;
- if (x + w > 320)
- w = 320 - x;
- //debug(1, "multiput %ux%u -> segment: %04x->%04x", w, h, (uint16)ds, (uint16)es);
- for(unsigned l = 0; l < h; ++l) {
- uint8 *src_p = ds.ptr(src + w * l, w);
- uint8 *dst_p = es.ptr(dst + kScreenwidth * l, w);
- memcpy(dst_p, src_p, w);
- }
- si += w * h;
- di = dst + kScreenwidth * h;
- cx = 0;
-}
+ bool firstLoop = true;
-void DreamGenContext::multidump() {
- ds = data.word(kWorkspace);
- int w = (uint8)cl, h = (uint8)ch;
- int x = (int16)di, y = (int16)bx;
- unsigned offset = x + y * kScreenwidth;
- //debug(1, "multidump %ux%u(segment: %04x) -> %d,%d(address: %d)", w, h, (uint16)ds, x, y, offset);
- engine->blit(ds.ptr(offset, w * h), kScreenwidth, x, y, w, h);
- si = di = offset + h * kScreenwidth;
- cx = 0;
-}
+ int savegameId = Common::ConfigManager::instance().getInt("save_slot");
-void DreamGenContext::worktoscreen() {
- ds = data.word(kWorkspace);
- uint size = 320 * 200;
- engine->blit(ds.ptr(0, size), 320, 0, 0, 320, 200);
- di = si = size;
- cx = 0;
-}
+ while (true) {
-void DreamGenContext::printundermon() {
- engine->printUnderMonitor();
-}
+ scanfornames();
-void DreamGenContext::cls() {
- engine->cls();
-}
+ bool startNewGame = true;
-void DreamGenContext::frameoutnm(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
- dst += pitch * y + x;
+ if (firstLoop && savegameId >= 0) {
- for (uint16 j = 0; j < height; ++j) {
- memcpy(dst, src, width);
- dst += pitch;
- src += width;
- }
-}
+ // loading a savegame requested from launcher/command line
-void DreamGenContext::frameoutbh(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
- uint16 stride = pitch - width;
- dst += y * pitch + x;
+ cls();
+ setmode();
+ loadpalfromiff();
+ clearpalette();
+
+ ax = savegameId;
+ doload();
+ worktoscreen();
+ fadescreenup();
+ startNewGame = false;
+
+ } else if (al == 0 && firstLoop) {
+
+ // no savegames found, and we're not restarting.
+
+ setmode();
+ loadpalfromiff();
+
+ } else {
+ // "dodecisions"
+
+ // Savegames found, so ask if we should load one.
+ // (If we're restarting after game over, we also always show these
+ // options.)
+
+ cls();
+ setmode();
+ decide();
+ if (data.byte(kQuitrequested))
+ return; // exit game
+
+ if (data.byte(kGetback) == 4)
+ startNewGame = false; // savegame has been loaded
- for (uint16 i = 0; i < height; ++i) {
- for (uint16 j = 0; j < width; ++j) {
- if (*dst == 0xff) {
- *dst = *src;
- }
- ++src;
- ++dst;
}
- dst += stride;
- }
-}
-void DreamGenContext::frameoutfx(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
- uint16 stride = pitch - width;
- dst += y * pitch + x;
- dst -= width;
+ firstLoop = false;
+
+ if (startNewGame) {
+ // "playgame"
+
+ titles();
+ if (data.byte(kQuitrequested))
+ return; // exit game
+ credits();
+
+ if (data.byte(kQuitrequested))
+ return; // exit game
+
+ clearchanges();
+ setmode();
+ loadpalfromiff();
+ data.byte(kLocation) = 255;
+ data.byte(kRoomafterdream) = 1;
+ data.byte(kNewlocation) = 35;
+ data.byte(kVolume) = 7;
+ loadroom();
+ clearsprites();
+ initman();
+ entrytexts();
+ entryanims();
+ data.byte(kDestpos) = 3;
+ initialinv();
+ data.byte(kLastflag) = 32;
+ startup1();
+ data.byte(kVolumeto) = 0;
+ data.byte(kVolumedirection) = -1;
+ data.byte(kCommandtype) = 255;
- for (uint16 j = 0; j < height; ++j) {
- for (uint16 i = 0; i < width; ++i) {
- uint8 pixel = src[width - i - 1];
- if (pixel)
- *dst = pixel;
- ++dst;
}
- src += width;
- dst += stride;
+
+ // main loop
+ while (true) {
+
+ if (data.byte(kQuitrequested))
+ return; // exit game
+
+ screenupdate();
+
+ if (data.byte(kWongame) != 0) {
+ // "endofgame"
+ clearbeforeload();
+ fadescreendowns();
+ cx = 200;
+ hangon();
+ endgame();
+ quickquit2();
+ return;
+ }
+
+ if (data.byte(kMandead) == 1 || data.byte(kMandead) == 2)
+ break;
+
+ if (data.word(kWatchingtime) > 0) {
+ if (data.byte(kFinaldest) == data.byte(kManspath))
+ data.word(kWatchingtime)--;
+ }
+
+ if (data.word(kWatchingtime) == 0) {
+ // "notwatching"
+
+ if (data.byte(kMandead) == 4)
+ break;
+
+ if (data.byte(kNewlocation) != 255) {
+ // "loadnew"
+ clearbeforeload();
+ loadroom();
+ clearsprites();
+ initman();
+ entrytexts();
+ entryanims();
+ data.byte(kNewlocation) = 255;
+ startup();
+ data.byte(kCommandtype) = 255;
+ worktoscreenm();
+ }
+ }
+ }
+
+ // "gameover"
+ clearbeforeload();
+ showgun();
+ fadescreendown();
+ cx = 100;
+ hangon();
+
}
}
+static Common::String getFilename(Context &context) {
+ uint16 name_ptr = context.dx;
+ Common::String name;
+ uint8 c;
+ while((c = context.cs.byte(name_ptr++)) != 0)
+ name += (char)c;
+ return name;
+}
+
void DreamGenContext::seecommandtail() {
data.word(kSoundbaseadd) = 0x220;
data.byte(kSoundint) = 5;
@@ -232,55 +285,171 @@ void DreamGenContext::dontloadseg() {
}
void DreamGenContext::mousecall() {
- engine->mouseCall();
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ cx = x;
+ dx = y;
+ bx = state;
+}
+
+void DreamGenContext::readmouse() {
+ data.word(kOldbutton) = data.word(kMousebutton);
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton) = state;
+}
+
+void DreamGenContext::readmouse1() {
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton1) = state;
+}
+
+void DreamGenContext::readmouse2() {
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton2) = state;
+}
+
+void DreamGenContext::readmouse3() {
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton3) = state;
+}
+
+void DreamGenContext::readmouse4() {
+ data.word(kOldbutton) = data.word(kMousebutton);
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton) = state | data.word(kMousebutton1) | data.word(kMousebutton2) | data.word(kMousebutton3);
}
void DreamGenContext::setmouse() {
data.word(kOldpointerx) = 0xffff;
}
-uint8 DreamGenContext::getnextword(uint8 *totalWidth, uint8 *charCount) {
- *totalWidth = 0;
- *charCount = 0;
- while(true) {
- uint8 firstChar = es.byte(di);
- ++di;
- ++*charCount;
- if ((firstChar == ':') || (firstChar == 0)) { //endall
- *totalWidth += 6;
- return 1;
- }
- if (firstChar == 32) { //endword
- *totalWidth += 6;
- return 0;
- }
- firstChar = engine->modifyChar(firstChar);
- if (firstChar != 255) {
- uint8 secondChar = es.byte(di);
- uint8 width = ds.byte(6*(firstChar - 32 + data.word(kCharshift)));
- width = kernchars(firstChar, secondChar, width);
- *totalWidth += width;
- }
+void DreamGenContext::dumptextline() {
+ if (data.byte(kNewtextline) != 1)
+ return;
+ data.byte(kNewtextline) = 0;
+ uint16 x = data.word(kTextaddressx);
+ uint16 y = data.word(kTextaddressy);
+ if (data.byte(kForeignrelease) != 0)
+ y -= 3;
+ multidump(x, y, 228, 13);
+}
+
+void DreamGenContext::getundertimed() {
+ uint16 y = data.byte(kTimedy);
+ if (data.byte(kForeignrelease))
+ y -= 3;
+ ds = data.word(kBuffers);
+ si = kUndertimedtext;
+ multiget(ds.ptr(si, 0), data.byte(kTimedx), y, 240, kUndertimedysize);
+}
+
+void DreamGenContext::putundertimed() {
+ uint16 y = data.byte(kTimedy);
+ if (data.byte(kForeignrelease))
+ y -= 3;
+ ds = data.word(kBuffers);
+ si = kUndertimedtext;
+ multiput(ds.ptr(si, 0), data.byte(kTimedx), y, 240, kUndertimedysize);
+}
+
+void DreamGenContext::usetimedtext() {
+ if (data.word(kTimecount) == 0)
+ return;
+ --data.word(kTimecount);
+ if (data.word(kTimecount) == 0) {
+ putundertimed();
+ data.byte(kNeedtodumptimed) = 1;
+ return;
}
-}
-void DreamGenContext::getnextword() {
- uint8 totalWidth, charCount;
- al = getnextword(&totalWidth, &charCount);
- bl = totalWidth;
- bh = charCount;
-}
+ if (data.word(kTimecount) == data.word(kCounttotimed))
+ getundertimed();
+ else if (data.word(kTimecount) > data.word(kCounttotimed))
+ return;
-uint8 DreamGenContext::kernchars(uint8 firstChar, uint8 secondChar, uint8 width) {
- if ((firstChar == 'a') || (al == 'u')) {
- if ((secondChar == 'n') || (secondChar == 't') || (secondChar == 'r') || (secondChar == 'i') || (secondChar == 'l'))
- return width-1;
+ es = data.word(kTimedseg);
+ si = data.word(kTimedoffset);
+ const uint8 *string = es.ptr(si, 0);
+ uint16 y = data.byte(kTimedy);
+ printdirect(&string, data.byte(kTimedx), &y, 237, true);
+ data.byte(kNeedtodumptimed) = 1;
+}
+
+void DreamGenContext::setuptimedtemp() {
+ setuptimedtemp(al, ah, bl, bh, cx, dx);
+}
+
+void DreamGenContext::setuptimedtemp(uint8 textIndex, uint8 voiceIndex, uint8 x, uint8 y, uint16 countToTimed, uint16 timeCount) {
+#if 1 // if cd
+ if (voiceIndex != 0) {
+ push(ax);
+ push(bx);
+ push(cx);
+ push(dx);
+ dl = 'T';
+ dh = voiceIndex;
+ cl = 'T';
+ ah = 0;
+ loadspeech();
+ if (data.byte(kSpeechloaded) == 1) {
+ al = 50+12;
+ playchannel1();
+ }
+ dx = pop();
+ cx = pop();
+ bx = pop();
+ ax = pop();
+ if ((data.byte(kSpeechloaded) == 1) && (data.byte(kSubtitles) != 1))
+ return;
}
- return width;
-}
+#endif
-void DreamGenContext::kernchars() {
- cl = kernchars(al, ah, cl);
+ if (data.word(kTimecount) != 0)
+ return;
+ data.byte(kTimedy) = y;
+ data.byte(kTimedx) = x;
+ data.word(kCounttotimed) = countToTimed;
+ data.word(kTimecount) = timeCount + countToTimed;
+ data.word(kTimedseg) = data.word(kTextfile1);
+ data.word(kTimedoffset) = kTextstart + segRef(data.word(kTextfile1)).word(textIndex * 2);
+ const uint8 *string = segRef(data.word(kTextfile1)).ptr(data.word(kTimedoffset), 0);
+ debug(1, "setuptimedtemp: (%d, %d) => '%s'", textIndex, voiceIndex, string);
+}
+
+void DreamGenContext::dumptimedtext() {
+ if (data.byte(kNeedtodumptimed) != 1)
+ return;
+ uint8 y = data.byte(kTimedy);
+ if (data.byte(kForeignrelease) != 0)
+ y -= 3;
+
+ multidump(data.byte(kTimedx), y, 240, kUndertimedysize);
+ data.byte(kNeedtodumptimed) = 0;
}
void DreamGenContext::gettime() {
@@ -296,12 +465,17 @@ void DreamGenContext::gettime() {
}
void DreamGenContext::allocatemem() {
- uint size = (bx + 2) * 16;
+ ax = allocatemem(bx);
+}
+
+uint16 DreamGenContext::allocatemem(uint16 paragraphs) {
+ uint size = (paragraphs + 2) * 16;
debug(1, "allocate mem, %u bytes", size);
flags._c = false;
SegmentRef seg = allocateSegment(size);
- ax = (uint16)seg;
- debug(1, "\tsegment address -> %04x", (uint16)ax);
+ uint16 result = (uint16)seg;
+ debug(1, "\tsegment address -> %04x", result);
+ return result;
}
void DreamGenContext::deallocatemem() {
@@ -476,8 +650,6 @@ void DreamGenContext::dosreturn() {
}
void DreamGenContext::set16colpalette() {
- //fixme: this is a bit hackish, set16colpalette called after initialization and nearly before main loop.
- engine->enableSavingOrLoading();
}
void DreamGenContext::mode640x480() {
@@ -495,764 +667,963 @@ void DreamGenContext::fadedos() {
engine->fadeDos();
}
-void DreamGenContext::doshake() {
- uint8 &counter = data.byte(kShakecounter);
- _cmp(counter, 48);
- if (flags.z())
+void DreamGenContext::eraseoldobs() {
+ if (data.byte(kNewobs) == 0)
return;
- _add(counter, 1);
- static const int shakeTable[] = {
- 0, -2, 3, -2, 0, 2, 4, -1,
- 1, -3, 3, 2, 0, -2, 3, -2,
- 0, 2, 4, -1, 1, -3, 3, 2,
- 0, -2, 3, -2, 0, 2, 4, -1,
-
- 1, -3, 3, 2, 0, -2, 3, -2,
- 0, 2, 4, -1, 1, -3, 3, 2,
- 0, -2, 3, -2, 0, 2, 4, -1,
- 1, -3, 3, 2, 0, -2, 3, -2,
-
- 0, 2, 4, -1, 1, -3, 3, 2,
- 0, -2, 3, -2, 0, 2, 4, -1,
- 1, -3, 3, 2, 0, -2, 3, -2,
- 0, 2, 4, -1, 1, -3, 3, 2,
-
- 0, -2, 3, -2, 0, 2, 4, -1,
- 1, -3, 3, 0,
- };
- int offset = shakeTable[counter];
- engine->setShakePos(offset >= 0? offset: -offset);
-}
-
-void DreamGenContext::vsync() {
- push(ax);
- push(bx);
- push(cx);
- push(dx);
- push(si);
- push(di);
- push(es);
- push(ds);
- engine->waitForVSync();
- ds = pop();
- es = pop();
- di = pop();
- si = pop();
- dx = pop();
- cx = pop();
- bx = pop();
- ax = pop();
+ Sprite *sprites = spritetable();
+ for (size_t i=0; i < 16; ++i) {
+ Sprite &sprite = sprites[i];
+ if (sprite.objData() != 0xffff) {
+ memset(&sprite, 0xff, sizeof(Sprite));
+ }
+ }
}
-void DreamGenContext::setmode() {
- vsync();
- initGraphics(320, 200, false);
+void DreamGenContext::modifychar() {
+ al = engine->modifyChar(al);
}
-void DreamGenContext::showpcx() {
- Common::String name = getFilename(*this);
- Common::File pcxFile;
-
- if (!pcxFile.open(name)) {
- warning("showpcx: Could not open '%s'", name.c_str());
- return;
- }
-
- uint8 *maingamepal;
- int i, j;
-
- // Read the 16-color palette into the 'maingamepal' buffer. Note that
- // the color components have to be adjusted from 8 to 6 bits.
-
- pcxFile.seek(16, SEEK_SET);
- es = data.word(kBuffers);
- maingamepal = es.ptr(kMaingamepal, 768);
- pcxFile.read(maingamepal, 48);
-
- memset(maingamepal + 48, 0xff, 720);
- for (i = 0; i < 48; i++) {
- maingamepal[i] >>= 2;
- }
-
- // Decode the image data.
-
- Graphics::Surface *s = g_system->lockScreen();
- Common::Rect rect(640, 480);
-
- s->fillRect(rect, 0);
- pcxFile.seek(128, SEEK_SET);
-
- for (int y = 0; y < 480; y++) {
- byte *dst = (byte *)s->getBasePtr(0, y);
- int decoded = 0;
-
- while (decoded < 320) {
- byte col = pcxFile.readByte();
- byte len;
-
- if ((col & 0xc0) == 0xc0) {
- len = col & 0x3f;
- col = pcxFile.readByte();
- } else {
- len = 1;
- }
-
- // The image uses 16 colors and is stored as four bit
- // planes, one for each bit of the color, least
- // significant bit plane first.
-
- for (i = 0; i < len; i++) {
- int plane = decoded / 80;
- int pos = decoded % 80;
-
- for (j = 0; j < 8; j++) {
- byte bit = (col >> (7 - j)) & 1;
- dst[8 * pos + j] |= (bit << plane);
- }
+void DreamGenContext::lockmon() {
+ // Pressing space pauses text output in the monitor. We use the "hard"
+ // key because calling readkey() drains characters from the input
+ // buffer, we we want the user to be able to type ahead while the text
+ // is being printed.
+ if (data.byte(kLasthardkey) == 57) {
+ // Clear the keyboard buffer. Otherwise the space that caused
+ // the pause will be read immediately unpause the game.
+ do {
+ readkey();
+ } while (data.byte(kCurrentkey) != 0);
- decoded++;
- }
+ locklighton();
+ while (!engine->shouldQuit()) {
+ engine->waitForVSync();
+ readkey();
+ if (data.byte(kCurrentkey) == ' ')
+ break;
}
+ // Forget the last "hard" key, otherwise the space that caused
+ // the unpausing will immediately re-pause the game.
+ data.byte(kLasthardkey) = 0;
+ locklightoff();
}
-
- g_system->unlockScreen();
- pcxFile.close();
}
-/*
-void DreamGenContext::frameoutv() {
- uint16 pitch = dx;
- uint16 width = cx & 0xff;
- uint16 height = cx >> 8;
-
- const uint8* src = ds.ptr(si, width * height);
- uint8* dst = es.ptr(0, pitch * height);
-
- frameoutv(dst, src, pitch, width, height, di, bx);
+void DreamGenContext::cancelch0() {
+ data.byte(kCh0repeat) = 0;
+ data.word(kCh0blockstocopy) = 0;
+ data.byte(kCh0playing) = 255;
+ engine->stopSound(0);
}
-*/
-void DreamGenContext::frameoutv(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
- // NB : These resilience checks were not in the original engine, but did they result in undefined behaviour
- // or was something broken during porting to C++?
- assert(pitch == 320);
+void DreamGenContext::cancelch1() {
+ data.word(kCh1blockstocopy) = 0;
+ data.byte(kCh1playing) = 255;
+ engine->stopSound(1);
+}
- if(x >= 320)
- return;
- if(y >= 200)
+void DreamGenContext::makebackob(SetObject *objData) {
+ if (data.byte(kNewobs) == 0)
return;
- if(x + width > 320) {
- width = 320 - x;
- }
- if(y + height > 200) {
- height = 200 - y;
- }
-
- uint16 stride = pitch - width;
- dst += pitch * y + x;
-
- for (uint16 j = 0; j < height; ++j) {
- for (uint16 i = 0; i < width; ++i) {
- uint8 pixel = *src++;
- if (pixel)
- *dst = pixel;
- ++dst;
- }
- dst += stride;
- }
+ uint8 priority = objData->priority;
+ uint8 type = objData->type;
+ Sprite *sprite = makesprite(data.word(kObjectx), data.word(kObjecty), addr_backobject, data.word(kSetframes), 0);
+
+ uint16 objDataOffset = (uint8 *)objData - segRef(data.word(kSetdat)).ptr(0, 0);
+ assert(objDataOffset % sizeof(SetObject) == 0);
+ assert(objDataOffset < 128 * sizeof(SetObject));
+ sprite->setObjData(objDataOffset);
+ if (priority == 255)
+ priority = 0;
+ sprite->priority = priority;
+ sprite->type = type;
+ sprite->b16 = 0;
+ sprite->delay = 0;
+ sprite->frame = 0;
}
-Sprite* DreamGenContext::spritetable() {
- push(es);
- push(bx);
-
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprite = (Sprite*)es.ptr(bx, 16*sizeof(Sprite));
-
- bx = pop();
- es = pop();
+void DreamGenContext::getroomdata() {
+ bx = kRoomdata + sizeof(Room) * al;
+}
- return sprite;
+void DreamGenContext::startloading() {
+ const Room *room = (Room *)cs.ptr(bx, sizeof(Room));
+ startloading(room);
}
-uint16 DreamGenContext::showframeCPP(uint16 dst, uint16 src, uint16 x, uint16 y, uint8 frameNumber, uint8 effectsFlag) {
- es = dst;
- ds = src;
- di = x;
- bx = y;
- al = frameNumber;
- ah = effectsFlag;
+void DreamGenContext::readheader() {
+ ax = engine->readFromFile(cs.ptr(kFileheader, kHeaderlen), kHeaderlen);
+ es = cs;
+ di = kFiledata;
+}
- si = (ax & 0x1ff) * 6;
- if (ds.word(si) == 0) {
- return 0;
+void DreamGenContext::startloading(const Room *room) {
+ data.byte(kCombatcount) = 0;
+ data.byte(kRoomssample) = room->roomsSample;
+ data.byte(kMapx) = room->mapX;
+ data.byte(kMapy) = room->mapY;
+ data.byte(kLiftflag) = room->liftFlag;
+ data.byte(kManspath) = room->b21;
+ data.byte(kDestination) = room->b21;
+ data.byte(kFinaldest) = room->b21;
+ data.byte(kFacing) = room->b22;
+ data.byte(kTurntoface) = room->b22;
+ data.byte(kCounttoopen) = room->countToOpen;
+ data.byte(kLiftpath) = room->liftPath;
+ data.byte(kDoorpath) = room->doorPath;
+ data.byte(kLastweapon) = -1;
+ al = room->b27;
+ push(ax);
+ al = room->b31;
+ ah = data.byte(kReallocation);
+ data.byte(kReallocation) = al;
+ dx = bx;
+ Common::String name = getFilename(*this);
+ engine->openFile(name);
+ cs.word(kHandle) = 1; //only one handle
+ flags._c = false;
+ readheader();
+ allocateload();
+ ds = ax;
+ data.word(kBackdrop) = ax;
+ dx = (0);
+ loadseg();
+ ds = data.word(kWorkspace);
+ dx = (0);
+ cx = 132*66;
+ al = 0;
+ fillspace();
+ loadseg();
+ sortoutmap();
+ allocateload();
+ data.word(kSetframes) = ax;
+ ds = ax;
+ dx = (0);
+ loadseg();
+ ds = data.word(kSetdat);
+ dx = 0;
+ cx = (64*128);
+ al = 255;
+ fillspace();
+ loadseg();
+ allocateload();
+ data.word(kReel1) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kReel2) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kReel3) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kReels) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kPeople) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kSetdesc) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kBlockdesc) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kRoomdesc) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kFreeframes) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ ds = data.word(kFreedat);
+ dx = 0;
+ cx = (16*80);
+ al = 255;
+ fillspace();
+ loadseg();
+ allocateload();
+ data.word(kFreedesc) = ax;
+ ds = ax;
+ dx = (0);
+ loadseg();
+ closefile();
+ findroominloc();
+ deletetaken();
+ setallchanges();
+ autoappear();
+ al = data.byte(kNewlocation);
+ getroomdata();
+ data.byte(kLastweapon) = -1;
+ data.byte(kMandead) = 0;
+ data.word(kLookcounter) = 160;
+ data.byte(kNewlocation) = 255;
+ data.byte(kLinepointer) = 254;
+ ax = pop();
+ if (al != 255) {
+ data.byte(kManspath) = al;
+ push(bx);
+ autosetwalk();
+ bx = pop();
}
-
-//notblankshow:
- if ((effectsFlag & 128) == 0) {
- di += ds.byte(si+4);
- bx += ds.byte(si+5);
+ findxyfrompath();
+}
+
+void DreamGenContext::fillspace() {
+ memset(ds.ptr(dx, cx), al, cx);
+}
+
+void DreamGenContext::dealwithspecial(uint8 firstParam, uint8 secondParam) {
+ uint8 type = firstParam - 220;
+ if (type == 0) {
+ placesetobject(secondParam);
+ data.byte(kHavedoneobs) = 1;
+ } else if (type == 1) {
+ removesetobject(secondParam);
+ data.byte(kHavedoneobs) = 1;
+ } else if (type == 2) {
+ al = secondParam;
+ placefreeobject();
+ data.byte(kHavedoneobs) = 1;
+ } else if (type == 3) {
+ al = secondParam;
+ removefreeobject();
+ data.byte(kHavedoneobs) = 1;
+ } else if (type == 4) {
+ switchryanoff();
+ } else if (type == 5) {
+ data.byte(kTurntoface) = secondParam;
+ data.byte(kFacing) = secondParam;
+ switchryanon();
+ } else if (type == 6) {
+ data.byte(kNewlocation) = secondParam;
+ } else {
+ movemap(secondParam);
}
-//skipoffsets:
- cx = ds.word(si+0);
- uint8 width = cl;
- uint8 height = ch;
- uint16 written = cx;
- si = ds.word(si+2) + 2080;
-
- if (effectsFlag) {
- if (effectsFlag & 128) { //centred
- di -= width / 2;
- bx -= height / 2;
- }
- if (effectsFlag & 64) { //diffdest
- frameoutfx(es.ptr(0, dx * height), ds.ptr(si, width * height), dx, width, height, di, bx);
- return written;
- }
- if (effectsFlag & 8) { //printlist
- push(ax);
- ax = di - data.word(kMapadx);
- push(bx);
- bx -= data.word(kMapady);
- ah = bl;
- bx = pop();
- //addtoprintlist(); // NB: Commented in the original asm
- ax = pop();
- }
- if (effectsFlag & 4) { //flippedx
- es = data.word(kWorkspace);
- frameoutfx(es.ptr(0, 320 * height), ds.ptr(si, width * height), 320, width, height, di, bx);
- return written;
- }
- if (effectsFlag & 2) { //nomask
- es = data.word(kWorkspace);
- frameoutnm(es.ptr(0, 320 * height), ds.ptr(si, width * height), 320, width, height, di, bx);
- return written;
- }
- if (effectsFlag & 32) {
- es = data.word(kWorkspace);
- frameoutbh(es.ptr(0, 320 * height), ds.ptr(si, width * height), 320, width, height, di, bx);
- return written;
- }
+}
+
+void DreamGenContext::plotreel() {
+ Reel *reel = getreelstart();
+ while (true) {
+ if (reel->x < 220)
+ break;
+ if (reel->x == 255)
+ break;
+ dealwithspecial(reel->x, reel->y);
+ ++data.word(kReelpointer);
+ reel += 8;
}
-//noeffects:
- es = data.word(kWorkspace);
- frameoutv(es.ptr(0, 65536), ds.ptr(si, width * height), 320, width, height, di, bx);
- return written;
-}
-
-void DreamGenContext::showframe() {
- cx = showframeCPP(es, ds, di, bx, al, ah);
-}
-
-void DreamGenContext::printsprites() {
- for (size_t priority = 0; priority < 7; ++priority) {
- Sprite *sprites = spritetable();
- for (size_t j = 0; j < 16; ++j) {
- const Sprite &sprite = sprites[j];
- if (READ_LE_UINT16(&sprite.updateCallback) == 0x0ffff)
- continue;
- if (priority != sprite.priority)
- continue;
- if (sprite.hidden == 1)
- continue;
- printasprite(&sprite);
- }
+
+ for (size_t i = 0; i < 8; ++i) {
+ if (reel->frame() != 0xffff)
+ showreelframe(reel);
+ ++reel;
}
+ soundonreels();
}
-void DreamGenContext::printasprite(const Sprite* sprite) {
- push(es);
- push(bx);
- ds = READ_LE_UINT16(&sprite->w6);
- ax = sprite->y;
- if (al >= 220) {
- bx = data.word(kMapady) - (256 - al);
+void DreamGenContext::crosshair() {
+ uint8 frame;
+ if ((data.byte(kCommandtype) != 3) && (data.byte(kCommandtype) < 10)) {
+ frame = 9;
} else {
- bx = ax + data.word(kMapady);
+ frame = 29;
}
-
- ax = sprite->x;
- if (al >= 220) {
- di = data.word(kMapadx) - (256 - al);
+ const Frame *src = (const Frame *)segRef(data.word(kIcons1)).ptr(0, 0);
+ showframe(src, kZoomx + 24, kZoomy + 19, frame, 0);
+}
+
+void DreamGenContext::deltextline() {
+ uint16 x = data.word(kTextaddressx);
+ uint16 y = data.word(kTextaddressy);
+ if (data.byte(kForeignrelease) != 0)
+ y -= 3;
+ multiput(segRef(data.word(kBuffers)).ptr(kTextunder, 0), x, y, kUndertextsizex, kUndertextsizey);
+}
+
+void DreamGenContext::commandonly() {
+ commandonly(al);
+}
+
+void DreamGenContext::commandonly(uint8 command) {
+ deltextline();
+ uint16 index = command * 2;
+ uint16 offset = kTextstart + segRef(data.word(kCommandtext)).word(index);
+ uint16 y = data.word(kTextaddressy);
+ const uint8 *string = segRef(data.word(kCommandtext)).ptr(offset, 0);
+ printdirect(&string, data.word(kTextaddressx), &y, data.byte(kTextlen), (bool)(data.byte(kTextlen) & 1));
+ data.byte(kNewtextline) = 1;
+}
+
+void DreamGenContext::checkifperson() {
+ flags._z = not checkifperson(al, ah);
+}
+
+bool DreamGenContext::checkifperson(uint8 x, uint8 y) {
+ People *people = (People *)segRef(data.word(kBuffers)).ptr(kPeoplelist, 0);
+
+ for (size_t i = 0; i < 12; ++i, ++people) {
+ if (people->b4 == 255)
+ continue;
+ data.word(kReelpointer) = people->w0();
+ Reel *reel = getreelstart();
+ if (reel->frame() == 0xffff)
+ ++reel;
+ const Frame *frame = getreelframeax(reel->frame());
+ uint8 xmin = reel->x + frame->x;
+ uint8 ymin = reel->y + frame->y;
+ uint8 xmax = xmin + frame->width;
+ uint8 ymax = ymin + frame->height;
+ if (x < xmin)
+ continue;
+ if (y < ymin)
+ continue;
+ if (x >= xmax)
+ continue;
+ if (y >= ymax)
+ continue;
+ data.word(kPersondata) = people->w2();
+ obname(people->b4, 5);
+ return true;
+ }
+ return false;
+}
+
+void DreamGenContext::checkiffree() {
+ flags._z = not checkiffree(al, ah);
+}
+
+bool DreamGenContext::checkiffree(uint8 x, uint8 y) {
+ const ObjPos *freeList = (const ObjPos *)segRef(data.word(kBuffers)).ptr(kFreelist, 80 * sizeof(ObjPos));
+ for (size_t i = 0; i < 80; ++i) {
+ const ObjPos *objPos = freeList + 79 - i;
+ if (objPos->index == 0xff)
+ continue;
+ if (x < objPos->xMin)
+ continue;
+ if (x >= objPos->xMax)
+ continue;
+ if (y < objPos->yMin)
+ continue;
+ if (y >= objPos->yMax)
+ continue;
+ obname(objPos->index, 2);
+ return true;
+ }
+ return false;
+}
+
+const uint8 *DreamGenContext::findobname(uint8 type, uint8 index) {
+ if (type == 5) {
+ uint16 i = 64 * 2 * (index & 127);
+ uint16 offset = segRef(data.word(kPeople)).word(kPersontxtdat + i) + kPersontext;
+ return segRef(data.word(kPeople)).ptr(offset, 0);
+ } else if (type == 4) {
+ uint16 offset = segRef(data.word(kExtras)).word(kExtextdat + index * 2) + kExtext;
+ return segRef(data.word(kExtras)).ptr(offset, 0);
+ } else if (type == 2) {
+ uint16 offset = segRef(data.word(kFreedesc)).word(kFreetextdat + index * 2) + kFreetext;
+ return segRef(data.word(kFreedesc)).ptr(offset, 0);
+ } else if (type == 1) {
+ uint16 offset = segRef(data.word(kSetdesc)).word(kSettextdat + index * 2) + kSettext;
+ return segRef(data.word(kSetdesc)).ptr(offset, 0);
} else {
- di = ax + data.word(kMapadx);
+ uint16 offset = segRef(data.word(kBlockdesc)).word(kBlocktextdat + index * 2) + kBlocktext;
+ return segRef(data.word(kBlockdesc)).ptr(offset, 0);
}
-
- ax = sprite->b15;
- if (sprite->b29 != 0)
- ah = 8;
- showframe();
-
- bx = pop();
- es = pop();
}
-void DreamGenContext::eraseoldobs() {
- if (data.byte(kNewobs) == 0)
- return;
+void DreamGenContext::copyname() {
+ copyname(ah, al, cs.ptr(di, 0));
+}
- Sprite *sprites = spritetable();
- for (size_t i=0; i<16; ++i) {
- Sprite &sprite = sprites[i];
- if (READ_LE_UINT16(&sprite.obj_data) != 0xffff) {
- memset(&sprite, 0xff, sizeof(Sprite));
- }
+void DreamGenContext::copyname(uint8 type, uint8 index, uint8 *dst) {
+ const uint8 *src = findobname(type, index);
+ size_t i;
+ for (i = 0; i < 28; ++i) {
+ char c = src[i];
+ if (c == ':')
+ break;
+ if (c == 0)
+ break;
+ dst[i] = c;
}
+ dst[i] = 0;
}
-void DreamGenContext::clearsprites() {
- memset(spritetable(), 0xff, sizeof(Sprite)*16);
+void DreamGenContext::commandwithob() {
+ commandwithob(al, bh, bl);
}
-Sprite* DreamGenContext::makesprite(uint8 x, uint8 y, uint16 updateCallback, uint16 somethingInDx, uint16 somethingInDi) {
- Sprite *sprite = spritetable();
- while (sprite->b15 != 0xff) { // NB: No boundchecking in the original code either
- ++sprite;
+void DreamGenContext::commandwithob(uint8 command, uint8 type, uint8 index) {
+ uint8 commandLine[64] = "OBJECT NAME ONE ";
+ deltextline();
+ uint16 commandText = kTextstart + segRef(data.word(kCommandtext)).word(command * 2);
+ uint8 textLen = data.byte(kTextlen);
+ {
+ uint16 y = data.word(kTextaddressy);
+ const uint8 *string = segRef(data.word(kCommandtext)).ptr(commandText, 0);
+ printdirect(&string, data.word(kTextaddressx), &y, textLen, (bool)(textLen & 1));
}
+ copyname(type, index, commandLine);
+ uint16 x = data.word(kLastxpos);
+ if (command != 0)
+ x += 5;
+ {
+ uint16 y = data.word(kTextaddressy);
+ const uint8 *string = commandLine;
+ printdirect(&string, x, &y, textLen, (bool)(textLen & 1));
+ }
+ data.byte(kNewtextline) = 1;
+}
- WRITE_LE_UINT16(&sprite->updateCallback, updateCallback);
- sprite->x = x;
- sprite->y = y;
- WRITE_LE_UINT16(&sprite->w6, somethingInDx);
- WRITE_LE_UINT16(&sprite->w8, somethingInDi);
- sprite->w2 = 0xffff;
- sprite->b15 = 0;
- sprite->delay = 0;
- return sprite;
+void DreamGenContext::showpanel() {
+ Frame *frame = (Frame *)segRef(data.word(kIcons1)).ptr(0, sizeof(Frame));
+ showframe(frame, 72, 0, 19, 0);
+ showframe(frame, 192, 0, 19, 0);
}
-void DreamGenContext::makesprite() { // NB: returns new sprite in es:bx
- Sprite *sprite = makesprite(si & 0xff, si >> 8, cx, dx, di);
+void DreamGenContext::blocknametext() {
+ commandwithob(0, data.byte(kCommandtype), data.byte(kCommand));
+}
- // Recover es:bx from sprite
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprites = (Sprite*)es.ptr(bx, sizeof(Sprite)*16);
- bx += sizeof(Sprite)*(sprite-sprites);
- //
+void DreamGenContext::personnametext() {
+ commandwithob(2, data.byte(kCommandtype), data.byte(kCommand) & 127);
}
-void DreamGenContext::spriteupdate() {
- Sprite *sprites = spritetable();
- sprites[0].hidden = data.byte(kRyanon);
-
- Sprite *sprite = sprites;
- for (size_t i=0; i<16; ++i) {
- uint16 updateCallback = READ_LE_UINT16(&sprite->updateCallback);
- if (updateCallback != 0xffff) {
- sprite->w24 = sprite->w2;
- if (updateCallback == addr_mainman) // NB : Let's consider the callback as an enum while more code is not ported to C++
- mainmanCPP(sprite);
- else {
- assert(updateCallback == addr_backobject);
- backobject(sprite);
- }
- }
-
- if (data.byte(kNowinnewroom) == 1)
- break;
- ++sprite;
- }
+void DreamGenContext::walktotext() {
+ commandwithob(3, data.byte(kCommandtype), data.byte(kCommand));
}
-void DreamGenContext::initman() {
- Sprite *sprite = makesprite(data.byte(kRyanx), data.byte(kRyany), addr_mainman, data.word(kMainsprites), 0);
- sprite->priority = 4;
- sprite->b22 = 0;
- sprite->b29 = 0;
-
- // Recover es:bx from sprite
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprites = (Sprite*)es.ptr(bx, sizeof(Sprite)*16);
- bx += 32*(sprite-sprites);
- //
-}
-
-void DreamGenContext::mainmanCPP(Sprite* sprite) {
- push(es);
- push(ds);
-
- // Recover es:bx from sprite
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprites = (Sprite*)es.ptr(bx, sizeof(Sprite)*16);
- bx += 32*(sprite-sprites);
- //
-
- if (data.byte(kResetmanxy) == 1) {
- data.byte(kResetmanxy) = 0;
- sprite->x = data.byte(kRyanx);
- sprite->y = data.byte(kRyany);
- sprite->b29 = 0;
- }
- --sprite->b22;
- if (sprite->b22 != 0xff) {
- ds = pop();
- es = pop();
- return;
- }
- sprite->b22 = 0;
- if (data.byte(kTurntoface) != data.byte(kFacing)) {
- aboutturn(sprite);
- } else {
- if ((data.byte(kTurndirection) != 0) && (data.byte(kLinepointer) == 254)) {
- data.byte(kReasseschanges) = 1;
- if (data.byte(kFacing) == data.byte(kLeavedirection))
- checkforexit();
+void DreamGenContext::findormake() {
+ uint8 b0 = al;
+ uint8 b2 = cl;
+ uint8 b3 = ch;
+ findormake(b0, b2, b3);
+}
+
+void DreamGenContext::findormake(uint8 index, uint8 value, uint8 type) {
+ Change *change = (Change *)segRef(data.word(kBuffers)).ptr(kListofchanges, sizeof(Change));
+ while (true) {
+ if (change->index == 0xff) {
+ change->index = index;
+ change->location = data.byte(kReallocation);
+ change->value = value;
+ change->type = type;
+ return;
}
- data.byte(kTurndirection) = 0;
- if (data.byte(kLinepointer) == 254) {
- sprite->b29 = 0;
- } else {
- ++sprite->b29;
- if (sprite->b29 == 11)
- sprite->b29 = 1;
- walking();
- if (data.byte(kLinepointer) != 254) {
- if ((data.byte(kFacing) & 1) == 0)
- walking();
- else if ((sprite->b29 != 2) && (sprite->b29 != 7))
- walking();
- }
- if (data.byte(kLinepointer) == 254) {
- if (data.byte(kTurntoface) == data.byte(kFacing)) {
- data.byte(kReasseschanges) = 1;
- if (data.byte(kFacing) == data.byte(kLeavedirection))
- checkforexit();
- }
- }
+ if ((index == change->index) && (data.byte(kReallocation) == change->location) && (type == change->type)) {
+ change->value = value;
+ return;
}
+ ++change;
}
- static const uint8 facelist[] = { 0,60,33,71,11,82,22,93 };
- sprite->b15 = sprite->b29 + facelist[data.byte(kFacing)];
- data.byte(kRyanx) = sprite->x;
- data.byte(kRyany) = sprite->y;
-
- ds = pop();
- es = pop();
}
-void DreamGenContext::walking() {
- Sprite *sprite = (Sprite*)es.ptr(bx, sizeof(Sprite));
-
- uint8 comp;
- if (data.byte(kLinedirection) != 0) {
- --data.byte(kLinepointer);
- comp = 200;
- } else {
- ++data.byte(kLinepointer);
- comp = data.byte(kLinelength);
- }
- if (data.byte(kLinepointer) < comp) {
- sprite->x = data.byte(kLinedata + data.byte(kLinepointer) * 2 + 0);
- sprite->y = data.byte(kLinedata + data.byte(kLinepointer) * 2 + 1);
- return;
- }
-
- data.byte(kLinepointer) = 254;
- data.byte(kManspath) = data.byte(kDestination);
- if (data.byte(kDestination) == data.byte(kFinaldest)) {
- facerightway();
- return;
- }
- data.byte(kDestination) = data.byte(kFinaldest);
- push(es);
- push(bx);
- autosetwalk();
- bx = pop();
- es = pop();
-}
-
-void DreamGenContext::aboutturn(Sprite* sprite) {
- if (data.byte(kTurndirection) == 1)
- goto incdir;
- else if ((int8)data.byte(kTurndirection) == -1)
- goto decdir;
- else {
- if (data.byte(kFacing) < data.byte(kTurntoface)) {
- uint8 delta = data.byte(kTurntoface) - data.byte(kFacing);
- if (delta >= 4)
- goto decdir;
- else
- goto incdir;
- } else {
- uint8 delta = data.byte(kFacing) - data.byte(kTurntoface);
- if (delta >= 4)
- goto incdir;
- else
- goto decdir;
- }
+void DreamGenContext::setallchanges() {
+ Change *change = (Change *)segRef(data.word(kBuffers)).ptr(kListofchanges, sizeof(Change));
+ while (change->index != 0xff) {
+ if (change->location == data.byte(kReallocation))
+ dochange(change->index, change->value, change->type);
+ ++change;
}
-incdir:
- data.byte(kTurndirection) = 1;
- data.byte(kFacing) = (data.byte(kFacing) + 1) & 7;
- sprite->b29 = 0;
- return;
-decdir:
- data.byte(kTurndirection) = -1;
- data.byte(kFacing) = (data.byte(kFacing) - 1) & 7;
- sprite->b29 = 0;
-}
-
-void DreamGenContext::backobject(Sprite* sprite) {
- push(es);
- push(ds);
-
- // Recover es:bx from sprite
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprites = (Sprite*)es.ptr(bx, sizeof(Sprite)*16);
- bx += 32*(sprite-sprites);
- //
+}
- ds = data.word(kSetdat);
- di = READ_LE_UINT16(&sprite->obj_data);
- ObjData* objData = (ObjData*)ds.ptr(di, 0);
+DynObject *DreamGenContext::getfreead(uint8 index) {
+ return (DynObject *)segRef(data.word(kFreedat)).ptr(0, 0) + index;
+}
- if (sprite->delay != 0) {
- --sprite->delay;
- ds = pop();
- es = pop();
- return;
- }
+DynObject *DreamGenContext::getexad(uint8 index) {
+ return (DynObject *)segRef(data.word(kExtras)).ptr(kExdata, 0) + index;
+}
- sprite->delay = objData->delay;
- if (objData->type == 6)
- widedoor(sprite, objData);
- else if (objData->type == 5)
- random(sprite, objData);
- else if (objData->type == 4)
- lockeddoorway();
- else if (objData->type == 3)
- liftsprite(sprite, objData);
- else if (objData->type == 2)
- doorway(sprite, objData);
- else if (objData->type == 1)
- constant(sprite, objData);
+DynObject *DreamGenContext::geteitheradCPP() {
+ if (data.byte(kObjecttype) == 4)
+ return getexad(data.byte(kItemframe));
else
- steady(sprite, objData);
+ return getfreead(data.byte(kItemframe));
+}
- ds = pop();
- es = pop();
+SetObject *DreamGenContext::getsetad(uint8 index) {
+ return (SetObject *)segRef(data.word(kSetdat)).ptr(0, 0) + index;
}
-void DreamGenContext::constant(Sprite* sprite, ObjData* objData) {
- ++sprite->frame;
- if (objData->b18[sprite->frame] == 255) {
- sprite->frame = 0;
- }
- uint8 b18 = objData->b18[sprite->frame];
- objData->b17 = b18;
- sprite->b15 = b18;
+void DreamGenContext::dochange() {
+ dochange(al, cl, ch);
}
-void DreamGenContext::random(Sprite* sprite, ObjData* objData) {
- randomnum1();
- uint16 r = ax;
- sprite->b15 = objData->b18[r&7];
+void DreamGenContext::dochange(uint8 index, uint8 value, uint8 type) {
+ if (type == 0) { //object
+ getsetad(index)->b58[0] = value;
+ } else if (type == 1) { //freeobject
+ DynObject *freeObject = getfreead(index);
+ if (freeObject->b2 == 0xff)
+ freeObject->b2 = value;
+ } else { //path
+ bx = kPathdata + (type - 100) * 144 + index * 8;
+ es = data.word(kReels);
+ es.byte(bx+6) = value;
+ }
}
-void DreamGenContext::doorway(Sprite* sprite, ObjData* objData) {
- data.byte(kDoorcheck1) = -24;
- data.byte(kDoorcheck2) = 10;
- data.byte(kDoorcheck3) = -30;
- data.byte(kDoorcheck4) = 10;
- dodoor(sprite, objData);
+void DreamGenContext::deletetaken() {
+ const DynObject *extraObjects = (const DynObject *)segRef(data.word(kExtras)).ptr(kExdata, 0);
+ DynObject *freeObjects = (DynObject *)segRef(data.word(kFreedat)).ptr(0, 0);
+ for(size_t i = 0; i < kNumexobjects; ++i) {
+ uint8 location = extraObjects[i].location;
+ if (location == data.byte(kReallocation)) {
+ uint8 index = extraObjects[i].index;
+ freeObjects[index].b2 = 254;
+ }
+ }
}
-void DreamGenContext::widedoor(Sprite* sprite, ObjData* objData) {
- data.byte(kDoorcheck1) = -24;
- data.byte(kDoorcheck2) = 24;
- data.byte(kDoorcheck3) = -30;
- data.byte(kDoorcheck4) = 24;
- dodoor(sprite, objData);
+void DreamGenContext::placesetobject() {
+ placesetobject(al);
}
-void DreamGenContext::dodoor() {
- Sprite *sprite = (Sprite*)es.ptr(bx, sizeof(Sprite));
- ObjData *objData = (ObjData*)ds.ptr(di, 0);
- dodoor(sprite, objData);
+void DreamGenContext::placesetobject(uint8 index) {
+ findormake(index, 0, 0);
+ getsetad(index)->b58[0] = 0;
}
-void DreamGenContext::dodoor(Sprite* sprite, ObjData* objData) {
- uint8 ryanx = data.byte(kRyanx);
- uint8 ryany = data.byte(kRyany);
- int8 deltax = ryanx - sprite->x;
- int8 deltay = ryany - sprite->y;
- if (ryanx < sprite->x) {
- if (deltax < (int8)data.byte(kDoorcheck1))
- goto shutdoor;
- } else {
- if (deltax >= data.byte(kDoorcheck2))
- goto shutdoor;
- }
- if (ryany < sprite->y) {
- if (deltay < (int8)data.byte(kDoorcheck3))
- goto shutdoor;
- } else {
- if (deltay >= data.byte(kDoorcheck4))
- goto shutdoor;
- }
-//opendoor:
- if ((data.byte(kThroughdoor) == 1) && (sprite->frame == 0))
- sprite->frame = 6;
-
- ++sprite->frame;
- if (sprite->frame == 1) { //doorsound2
- if (data.byte(kReallocation) == 5) //hoteldoor2
- al = 13;
- else
- al = 0;
- playchannel1();
- }
- if (objData->b18[sprite->frame] == 255) {
- --sprite->frame;
- }
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- data.byte(kThroughdoor) = 1;
- return;
-shutdoor:
- if (sprite->frame == 5) { //doorsound1;
- if (data.byte(kReallocation) == 5) //hoteldoor1
- al = 13;
- else
- al = 1;
- playchannel1();
- }
- if (sprite->frame != 0) {
- --sprite->frame;
- }
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- if (sprite->frame == 5) //nearly
- data.byte(kThroughdoor) = 0;
+void DreamGenContext::removesetobject() {
+ removesetobject(al);
}
-void DreamGenContext::steady(Sprite* sprite, ObjData* objData) {
- uint8 b18 = objData->b18[0];
- objData->b17 = b18;
- sprite->b15 = b18;
+void DreamGenContext::removesetobject(uint8 index) {
+ findormake(index, 0xff, 0);
+ getsetad(index)->b58[0] = 0xff;
}
-void DreamGenContext::turnpathonCPP(uint8 param) {
- al = param;
- push(es);
- push(bx);
- turnpathon();
- bx = pop();
- es = pop();
+void DreamGenContext::finishedwalking() {
+ flags._z = finishedwalkingCPP();
}
-void DreamGenContext::turnpathoffCPP(uint8 param) {
- al = param;
- push(es);
- push(bx);
- turnpathoff();
- bx = pop();
- es = pop();
+bool DreamGenContext::finishedwalkingCPP() {
+ return (data.byte(kLinepointer) == 254) && (data.byte(kFacing) == data.byte(kTurntoface));
}
-void DreamGenContext::liftsprite() {
- Sprite *sprite = (Sprite*)es.ptr(bx, sizeof(Sprite));
- ObjData *objData = (ObjData*)ds.ptr(di, 0);
- liftsprite(sprite, objData);
+void DreamGenContext::getflagunderp() {
+ uint8 flag, flagEx;
+ getflagunderp(&flag, &flagEx);
+ cl = flag;
+ ch = flagEx;
}
-void DreamGenContext::liftsprite(Sprite* sprite, ObjData* objData) {
- uint8 liftFlag = data.byte(kLiftflag);
- if (liftFlag == 0) { //liftclosed
- turnpathoffCPP(data.byte(kLiftpath));
+void DreamGenContext::getflagunderp(uint8 *flag, uint8 *flagEx) {
+ uint8 type, flagX, flagY;
+ checkone(data.word(kMousex) - data.word(kMapadx), data.word(kMousey) - data.word(kMapady), flag, flagEx, &type, &flagX, &flagY);
+ cl = data.byte(kLastflag) = *flag;
+ ch = data.byte(kLastflagex) = *flagEx;
+}
- if (data.byte(kCounttoopen) != 0) {
- _dec(data.byte(kCounttoopen));
- if (data.byte(kCounttoopen) == 0)
- data.byte(kLiftflag) = 3;
+void DreamGenContext::walkandexamine() {
+ if (! finishedwalkingCPP())
+ return;
+ data.byte(kCommandtype) = data.byte(kWalkexamtype);
+ data.byte(kCommand) = data.byte(kWalkexamnum);
+ data.byte(kWalkandexam) = 0;
+ if (data.byte(kCommandtype) != 5)
+ examineob();
+}
+
+void DreamGenContext::obname() {
+ obname(al, ah);
+}
+
+void DreamGenContext::obname(uint8 command, uint8 commandType) {
+ if (data.byte(kReasseschanges) == 0) {
+ if ((commandType == data.byte(kCommandtype)) && (command == data.byte(kCommand))) {
+ if (data.byte(kWalkandexam) == 1) {
+ walkandexamine();
+ return;
+ } else if (data.word(kMousebutton) == 0)
+ return;
+ else if ((data.byte(kCommandtype) == 3) && (data.byte(kLastflag) < 2))
+ return;
+ else if ((data.byte(kManspath) != data.byte(kPointerspath)) || (data.byte(kCommandtype) == 3)) {
+ setwalk();
+ data.byte(kReasseschanges) = 1;
+ return;
+ } else if (! finishedwalkingCPP())
+ return;
+ else if (data.byte(kCommandtype) == 5) {
+ if (data.word(kWatchingtime) == 0)
+ talk();
+ return;
+ } else {
+ if (data.word(kWatchingtime) == 0)
+ examineob();
+ return;
+ }
}
- sprite->frame = 0;
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- }
- else if (liftFlag == 1) { //liftopen
- turnpathonCPP(data.byte(kLiftpath));
+ } else
+ data.byte(kReasseschanges) = 0;
- if (data.byte(kCounttoclose) != 0) {
- _dec(data.byte(kCounttoclose));
- if (data.byte(kCounttoclose) == 0)
- data.byte(kLiftflag) = 2;
- }
- sprite->frame = 12;
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- }
- else if (liftFlag == 3) { //openlift
- if (sprite->frame == 12) {
- data.byte(kLiftflag) = 1;
+ data.byte(kCommand) = command;
+ data.byte(kCommandtype) = commandType;
+ if ((data.byte(kLinepointer) != 254) || (data.word(kWatchingtime) != 0) || (data.byte(kFacing) != data.byte(kTurntoface))) {
+ blocknametext();
+ return;
+ } else if (data.byte(kCommandtype) != 3) {
+ if (data.byte(kManspath) != data.byte(kPointerspath)) {
+ walktotext();
return;
- }
- ++sprite->frame;
- if (sprite->frame == 1) {
- al = 2;
- liftnoise();
- }
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- } else { //closeLift
- assert(liftFlag == 2);
- if (sprite->frame == 0) {
- data.byte(kLiftflag) = 0;
+ } else if (data.byte(kCommandtype) == 3) {
+ blocknametext();
+ return;
+ } else if (data.byte(kCommandtype) == 5) {
+ personnametext();
+ return;
+ } else {
+ examineobtext();
return;
}
- --sprite->frame;
- if (sprite->frame == 11) {
- al = 3;
- liftnoise();
+ }
+ if (data.byte(kManspath) == data.byte(kPointerspath)) {
+ uint8 flag, flagEx, type, flagX, flagY;
+ checkone(data.byte(kRyanx) + 12, data.byte(kRyany) + 12, &flag, &flagEx, &type, &flagX, &flagY);
+ if (flag < 2) {
+ blocknametext();
+ return;
}
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ }
+
+ getflagunderp();
+ if (data.byte(kLastflag) < 2) {
+ blocknametext();
+ return;
+ } else if (data.byte(kLastflag) >= 128) {
+ blocknametext();
+ return;
+ } else {
+ walktotext();
+ return;
}
}
-void DreamGenContext::modifychar() {
- al = engine->modifyChar(al);
+void DreamGenContext::delpointer() {
+ if (data.word(kOldpointerx) == 0xffff)
+ return;
+ data.word(kDelherex) = data.word(kOldpointerx);
+ data.word(kDelherey) = data.word(kOldpointery);
+ data.byte(kDelxs) = data.byte(kPointerxs);
+ data.byte(kDelys) = data.byte(kPointerys);
+ multiput(segRef(data.word(kBuffers)).ptr(kPointerback, 0), data.word(kDelherex), data.word(kDelherey), data.byte(kPointerxs), data.byte(kPointerys));
}
-void DreamGenContext::lockmon() {
- // Pressing space pauses text output in the monitor. We use the "hard"
- // key because calling readkey() drains characters from the input
- // buffer, we we want the user to be able to type ahead while the text
- // is being printed.
- if (data.byte(kLasthardkey) == 57) {
- // Clear the keyboard buffer. Otherwise the space that caused
- // the pause will be read immediately unpause the game.
- do {
- readkey();
- } while (data.byte(kCurrentkey) != 0);
+void DreamGenContext::showblink() {
+ if (data.byte(kManisoffscreen) == 1)
+ return;
+ ++data.byte(kBlinkcount);
+ if (data.byte(kShadeson) != 0)
+ return;
+ if (data.byte(kReallocation) >= 50) // eyesshut
+ return;
+ if (data.byte(kBlinkcount) != 3)
+ return;
+ data.byte(kBlinkcount) = 0;
+ uint8 blinkFrame = data.byte(kBlinkframe);
+ ++blinkFrame; // Implicit %256
+ data.byte(kBlinkframe) = blinkFrame;
+ if (blinkFrame > 6)
+ blinkFrame = 6;
+ static const uint8 blinkTab[] = { 16,18,18,17,16,16,16 };
+ uint8 width, height;
+ showframe((Frame *)segRef(data.word(kIcons1)).ptr(0, 0), 44, 32, blinkTab[blinkFrame], 0, &width, &height);
+}
+
+void DreamGenContext::dumpblink() {
+ if (data.byte(kShadeson) != 0)
+ return;
+ if (data.byte(kBlinkcount) != 0)
+ return;
+ if (data.byte(kBlinkframe) >= 6)
+ return;
+ multidump(44, 32, 16, 12);
+}
- locklighton();
- while (!engine->shouldQuit()) {
- engine->waitForVSync();
- readkey();
- if (data.byte(kCurrentkey) == ' ')
- break;
+void DreamGenContext::dumppointer() {
+ dumpblink();
+ multidump(data.word(kDelherex), data.word(kDelherey), data.byte(kDelxs), data.byte(kDelys));
+ if ((data.word(kOldpointerx) != data.word(kDelherex)) || (data.word(kOldpointery) != data.word(kDelherey)))
+ multidump(data.word(kOldpointerx), data.word(kOldpointery), data.byte(kPointerxs), data.byte(kPointerys));
+}
+
+void DreamGenContext::checkcoords() {
+ checkcoords((const RectWithCallback *)cs.ptr(bx, 0));
+}
+
+void DreamGenContext::checkcoords(const RectWithCallback *rectWithCallbacks) {
+ if (data.byte(kNewlocation) != 0xff)
+ return;
+
+ const RectWithCallback *rectWithCallback = rectWithCallbacks;
+ while (rectWithCallback->xMin() != 0xffff) {
+ if (rectWithCallback->contains(data.word(kMousex), data.word(kMousey))) {
+ uint16 callback = rectWithCallback->callback();
+
+ // common
+ if(callback == addr_blank)
+ blank();
+ else if(callback == addr_getbackfromob)
+ getbackfromob();
+ else if(callback == addr_incryanpage)
+ incryanpage();
+ else if(callback == addr_getback1)
+ getback1();
+ else if(callback == addr_quitkey)
+ quitkey();
+ else if(callback == addr_dosreturn)
+ dosreturn();
+ else if(callback == addr_getbacktoops)
+ getbacktoops();
+ else if(callback == addr_selectslot)
+ selectslot();
+ // examlist
+ else if(callback == addr_useobject)
+ useobject();
+ else if(callback == addr_selectopenob)
+ selectopenob();
+ else if(callback == addr_setpickup)
+ setpickup();
+ else if(callback == addr_examinventory)
+ examinventory();
+ // invlist1
+ else if(callback == addr_dropobject)
+ dropobject();
+ else if(callback == addr_useopened)
+ useopened();
+ else if(callback == addr_setpickup)
+ setpickup();
+ else if(callback == addr_intoinv)
+ intoinv();
+ // withlist1
+ else if(callback == addr_selectob)
+ selectob();
+ // talklist
+ else if(callback == addr_moretalk)
+ moretalk();
+ // quitlist
+ // destlist
+ else if(callback == addr_nextdest)
+ nextdest();
+ else if(callback == addr_lastdest)
+ lastdest();
+ else if(callback == addr_lookatplace)
+ lookatplace();
+ else if(callback == addr_destselect)
+ destselect();
+ // keypadlist
+ else if(callback == addr_buttonone)
+ buttonone();
+ else if(callback == addr_buttontwo)
+ buttontwo();
+ else if(callback == addr_buttonthree)
+ buttonthree();
+ else if(callback == addr_buttonfour)
+ buttonfour();
+ else if(callback == addr_buttonfive)
+ buttonfive();
+ else if(callback == addr_buttonsix)
+ buttonsix();
+ else if(callback == addr_buttonseven)
+ buttonseven();
+ else if(callback == addr_buttoneight)
+ buttoneight();
+ else if(callback == addr_buttonnine)
+ buttonnine();
+ else if(callback == addr_buttonnought)
+ buttonnought();
+ else if(callback == addr_buttonenter)
+ buttonenter();
+ // menulist
+ // folderlist
+ else if(callback == addr_nextfolder)
+ nextfolder();
+ else if(callback == addr_lastfolder)
+ lastfolder();
+ // symbollist
+ else if(callback == addr_quitsymbol)
+ quitsymbol();
+ else if(callback == addr_settopleft)
+ settopleft();
+ else if(callback == addr_settopright)
+ settopright();
+ else if(callback == addr_setbotleft)
+ setbotleft();
+ else if(callback == addr_setbotright)
+ setbotright();
+ // diarylist
+ else if(callback == addr_diarykeyn)
+ diarykeyn();
+ else if(callback == addr_diarykeyp)
+ diarykeyp();
+ else if(callback == addr_quitkey)
+ quitkey();
+ // opslist
+ else if(callback == addr_getbackfromops)
+ getbackfromops();
+ else if(callback == addr_discops)
+ discops();
+ // discopslist
+ else if(callback == addr_loadgame)
+ loadgame();
+ else if(callback == addr_savegame)
+ savegame();
+ // mainlist, mainlist2
+ else if(callback == addr_look)
+ look();
+ else if(callback == addr_inventory)
+ inventory();
+ else if(callback == addr_zoomonoff)
+ zoomonoff();
+ else if(callback == addr_saveload)
+ saveload();
+ else if(callback == addr_madmanrun)
+ madmanrun();
+ else if(callback == addr_identifyob)
+ identifyob();
+ // decidelist
+ else if(callback == addr_newgame)
+ newgame();
+ else if(callback == addr_loadold)
+ loadold();
+ // loadlist
+ else if(callback == addr_actualload)
+ actualload();
+ // savelist
+ else if(callback == addr_actualsave)
+ actualsave();
+ else {
+ debug("__dispatch_call remaining in checkcoords! %d", (int)callback);
+ __dispatch_call(callback);
+ }
+ return;
}
- // Forget the last "hard" key, otherwise the space that caused
- // the unpausing will immediately re-pause the game.
- data.byte(kLasthardkey) = 0;
- locklightoff();
+ ++rectWithCallback;
}
}
-void DreamGenContext::cancelch0() {
- data.byte(kCh0repeat) = 0;
- data.word(kCh0blockstocopy) = 0;
- data.byte(kCh0playing) = 255;
- engine->stopSound(0);
+void DreamGenContext::showpointer() {
+ showblink();
+ const Frame *icons1 = ((const Frame *)segRef(data.word(kIcons1)).ptr(0, 0));
+ uint16 x = data.word(kMousex);
+ data.word(kOldpointerx) = data.word(kMousex);
+ uint16 y = data.word(kMousey);
+ data.word(kOldpointery) = data.word(kMousey);
+ if (data.byte(kPickup) == 1) {
+ const Frame *frames;
+ if (data.byte(kObjecttype) != 4)
+ frames = (const Frame *)segRef(data.word(kFreeframes)).ptr(0, 0);
+ else
+ frames = (const Frame *)segRef(data.word(kExtras)).ptr(0, 0);
+ const Frame *frame = frames + (3 * data.byte(kItemframe) + 1);
+ uint8 width = frame->width;
+ uint8 height = frame->height;
+ if (width < 12)
+ width = 12;
+ if (height < 12)
+ height = 12;
+ data.byte(kPointerxs) = width;
+ data.byte(kPointerys) = height;
+ data.word(kOldpointerx) -= width / 2;
+ data.word(kOldpointery) -= height / 2;
+ multiget(segRef(data.word(kBuffers)).ptr(kPointerback, 0), x - width / 2, y - height / 2, width, height);
+ showframe(frames, x, y, 3 * data.byte(kItemframe) + 1, 128);
+ showframe(icons1, x, y, 3, 128);
+ } else {
+ const Frame *frame = icons1 + (data.byte(kPointerframe) + 20);
+ uint8 width = frame->width;
+ uint8 height = frame->height;
+ if (width < 12)
+ width = 12;
+ if (height < 12)
+ height = 12;
+ data.byte(kPointerxs) = width;
+ data.byte(kPointerys) = height;
+ multiget(segRef(data.word(kBuffers)).ptr(kPointerback, 0), x, y, width, height);
+ showframe(icons1, x, y, data.byte(kPointerframe) + 20, 0);
+ }
}
-void DreamGenContext::cancelch1() {
- data.word(kCh1blockstocopy) = 0;
- data.byte(kCh1playing) = 255;
- engine->stopSound(1);
+void DreamGenContext::animpointer() {
+
+ if (data.byte(kPointermode) == 2) {
+ data.byte(kPointerframe) = 0;
+ if ((data.byte(kReallocation) == 14) && (data.byte(kCommandtype) == 211))
+ data.byte(kPointerframe) = 5;
+ return;
+ } else if (data.byte(kPointermode) == 3) {
+ if (data.byte(kPointerspeed) != 0) {
+ --data.byte(kPointerspeed);
+ } else {
+ data.byte(kPointerspeed) = 5;
+ ++data.byte(kPointercount);
+ if (data.byte(kPointercount) == 16)
+ data.byte(kPointercount) = 0;
+ }
+ static const uint8 flashMouseTab[] = { 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2 };
+ data.byte(kPointerframe) = flashMouseTab[data.byte(kPointercount)];
+ return;
+ }
+ if (data.word(kWatchingtime) != 0) {
+ data.byte(kPointerframe) = 11;
+ return;
+ }
+ data.byte(kPointerframe) = 0;
+ if (data.byte(kInmaparea) == 0)
+ return;
+ if (data.byte(kPointerfirstpath) == 0)
+ return;
+ uint8 flag, flagEx;
+ getflagunderp(&flag, &flagEx);
+ if (flag < 2)
+ return;
+ if (flag >= 128)
+ return;
+ if (flag & 4) {
+ data.byte(kPointerframe) = 3;
+ return;
+ }
+ if (flag & 16) {
+ data.byte(kPointerframe) = 4;
+ return;
+ }
+ if (flag & 2) {
+ data.byte(kPointerframe) = 5;
+ return;
+ }
+ if (flag & 8) {
+ data.byte(kPointerframe) = 6;
+ return;
+ }
+ data.byte(kPointerframe) = 8;
}
+bool DreamGenContext::isCD() {
+ // The original sources has two codepaths depending if the game is 'if cd' or not
+ // This is a hack to guess which version to use with the assumption that if we have a cd version
+ // we managed to load the speech. At least it is isolated in this function and can be changed.
+ // Maybe detect the version during game id?
+ return (data.byte(kSpeechloaded) == 1);
+}
} /*namespace dreamgen */
diff --git a/engines/dreamweb/stubs.h b/engines/dreamweb/stubs.h
index a3cb680cca..7c8cee4690 100644
--- a/engines/dreamweb/stubs.h
+++ b/engines/dreamweb/stubs.h
@@ -19,14 +19,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
-
+ uint16 allocatemem(uint16 paragraphs);
+ uint8 *workspace();
+ void allocatework();
+ void clearwork();
void multidump();
- void frameoutv(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y);
- void frameoutnm(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y);
- void frameoutbh(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y);
- void frameoutfx(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y);
+ void multidump(uint16 x, uint16 y, uint8 width, uint8 height);
+ void frameoutv(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y);
+ void frameoutnm(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y);
+ void frameoutbh(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y);
+ void frameoutfx(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y);
void worktoscreen();
void multiget();
+ void multiget(uint8 *dst, uint16 x, uint16 y, uint8 width, uint8 height);
void convertkey();
void cls();
void printsprites();
@@ -36,38 +41,154 @@
void seecommandtail();
void randomnumber();
void quickquit2();
- void getnextword();
- uint8 getnextword(uint8 *totalWidth, uint8 *charCount);
- void kernchars();
+ uint8 getnextword(const Frame *charSet, const uint8 *string, uint8 *totalWidth, uint8 *charCount);
+ void printboth(const Frame* charSet, uint16 *x, uint16 y, uint8 c, uint8 nextChar);
+ void printchar();
+ void printchar(const Frame* charSet, uint16 *x, uint16 y, uint8 c, uint8 nextChar, uint8 *width, uint8 *height);
+ void printdirect();
+ void printdirect(const uint8** string, uint16 x, uint16 *y, uint8 maxWidth, bool centered);
+ void usetimedtext();
+ void dumptimedtext();
+ void setuptimedtemp();
+ void setuptimedtemp(uint8 textIndex, uint8 voiceIndex, uint8 x, uint8 y, uint16 countToTimed, uint16 timeCount);
+ void getundertimed();
+ void putundertimed();
+ uint8 printslow(const uint8 *string, uint16 x, uint16 y, uint8 maxWidth, bool centered);
+ void printslow();
+ void dumptextline();
+ void getnumber();
+ uint8 getnumber(const Frame *charSet, const uint8 *string, uint16 maxWidth, bool centered, uint16 *offset);
uint8 kernchars(uint8 firstChar, uint8 secondChar, uint8 width);
- Sprite* spritetable();
+ void getroomdata();
+ void readheader();
+ void fillspace();
+ void startloading();
+ void startloading(const Room *room);
+ Sprite *spritetable();
void showframe();
- uint16 showframeCPP(uint16 dst, uint16 src, uint16 x, uint16 y, uint8 frameNumber, uint8 effectsFlag);
- void printasprite(const Sprite* sprite);
+ void showframe(const Frame *frameData, uint16 x, uint16 y, uint16 frameNumber, uint8 effectsFlag, uint8 *width, uint8 *height);
+ void showframe(const Frame *frameData, uint16 x, uint16 y, uint16 frameNumber, uint8 effectsFlag);
+ void printasprite(const Sprite *sprite);
void width160();
+ void multiput(const uint8 *src, uint16 x, uint16 y, uint8 width, uint8 height);
void multiput();
void eraseoldobs();
void clearsprites();
void makesprite();
- Sprite* makesprite(uint8 x, uint8 y, uint16 updateCallback, uint16 somethingInDx, uint16 somethingInDi);
+ Sprite *makesprite(uint8 x, uint8 y, uint16 updateCallback, uint16 frameData, uint16 somethingInDi);
void spriteupdate();
void initman();
- void mainmanCPP(Sprite* sprite);
- void walking();
- void aboutturn(Sprite* sprite);
- void backobject(Sprite* sprite);
- void constant(Sprite* sprite, ObjData* objData);
- void steady(Sprite* sprite, ObjData* objData);
- void random(Sprite* sprite, ObjData* objData);
+ void mainman(Sprite *sprite);
+ void facerightway();
+ void walking(Sprite *sprite);
+ void autosetwalk();
+ void checkdest(const uint8 *roomsPaths);
+ void aboutturn(Sprite *sprite);
+ void backobject(Sprite *sprite);
+ void constant(Sprite *sprite, SetObject *objData);
+ void steady(Sprite *sprite, SetObject *objData);
+ void random(Sprite *sprite, SetObject *objData);
void dodoor();
- void dodoor(Sprite* sprite, ObjData* objData);
- void doorway(Sprite* sprite, ObjData* objData);
- void widedoor(Sprite* sprite, ObjData* objData);
- void liftsprite();
- void liftsprite(Sprite* sprite, ObjData* objData);
+ void dodoor(Sprite *sprite, SetObject *objData);
+ void doorway(Sprite *sprite, SetObject *objData);
+ void widedoor(Sprite *sprite, SetObject *objData);
+ void lockeddoorway(Sprite *sprite, SetObject *objData);
+ void liftsprite(Sprite *sprite, SetObject *objData);
+ void findsource();
+ Frame *findsourceCPP();
+ void showgamereel();
+ void showreelframe();
+ void showreelframe(Reel *reel);
+ const Frame *getreelframeax(uint16 frame);
void turnpathonCPP(uint8 param);
void turnpathoffCPP(uint8 param);
+ void getroomspaths();
+ uint8 *getroomspathsCPP();
+ void makebackob(SetObject *objData);
void modifychar();
void lockmon();
void cancelch0();
void cancelch1();
+ void plotreel();
+ Reel *getreelstart();
+ void dealwithspecial(uint8 firstParam, uint8 secondParam);
+ void zoom();
+ void crosshair();
+ void showrain();
+ void deltextline();
+ void commandonly();
+ void commandonly(uint8 command);
+ void doblocks();
+ void checkifperson();
+ bool checkifperson(uint8 x, uint8 y);
+ void checkiffree();
+ bool checkiffree(uint8 x, uint8 y);
+ const uint8 *findobname(uint8 type, uint8 index);
+ void copyname();
+ void copyname(uint8 type, uint8 index, uint8 *dst);
+ void commandwithob();
+ void commandwithob(uint8 command, uint8 type, uint8 index);
+ void showpanel();
+ void updatepeople();
+ void madmantext();
+ void madmode();
+ void movemap(uint8 param);
+ bool addalong(const uint8 *mapFlags);
+ bool addlength(const uint8 *mapFlags);
+ void getdimension();
+ void getdimension(uint8 *mapXstart, uint8 *mapYstart, uint8 *mapXsize, uint8 *mapYsize);
+ void getmapad();
+ void calcmapad();
+ uint8 getmapad(const uint8 *setData);
+ uint8 getxad(const uint8 *setData, uint8 *result);
+ uint8 getyad(const uint8 *setData, uint8 *result);
+ void calcfrframe();
+ void calcfrframe(uint8* width, uint8* height);
+ void finalframe();
+ void finalframe(uint16 *x, uint16 *y);
+ void showallobs();
+ void blocknametext();
+ void walktotext();
+ void personnametext();
+ void findxyfrompath();
+ void findormake();
+ void findormake(uint8 index, uint8 value, uint8 type);
+ DynObject *getfreead(uint8 index);
+ DynObject *getexad(uint8 index);
+ DynObject *geteitheradCPP();
+ SetObject *getsetad(uint8 index);
+ void setallchanges();
+ void dochange();
+ void dochange(uint8 index, uint8 value, uint8 type);
+ void deletetaken();
+ bool isCD();
+ void placesetobject();
+ void placesetobject(uint8 index);
+ void removesetobject();
+ void removesetobject(uint8 index);
+ void showallfree();
+ bool finishedwalkingCPP();
+ void finishedwalking();
+ void checkone();
+ void checkone(uint8 x, uint8 y, uint8 *flag, uint8 *flagEx, uint8 *type, uint8 *flagX, uint8 *flagY);
+ void getflagunderp();
+ void getflagunderp(uint8 *flag, uint8 *flagEx);
+ void walkandexamine();
+ void obname();
+ void obname(uint8 command, uint8 commandType);
+ void delpointer();
+ void showblink();
+ void dumpblink();
+ void dumppointer();
+ void showpointer();
+ void animpointer();
+ void checkcoords();
+ void checkcoords(const RectWithCallback *rectWithCallbacks);
+ void readmouse();
+ void readmouse1();
+ void readmouse2();
+ void readmouse3();
+ void readmouse4();
+ uint16 waitframes();
+ void drawflags();
+
diff --git a/engines/dreamweb/vgagrafx.cpp b/engines/dreamweb/vgagrafx.cpp
new file mode 100644
index 0000000000..3c92640768
--- /dev/null
+++ b/engines/dreamweb/vgagrafx.cpp
@@ -0,0 +1,415 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "dreamweb/dreamweb.h"
+#include "engines/util.h"
+#include "graphics/surface.h"
+
+namespace DreamGen {
+
+uint8 *DreamGenContext::workspace() {
+ uint8 *result = segRef(data.word(kWorkspace)).ptr(0, 0);
+ return result;
+}
+
+void DreamGenContext::allocatework() {
+ data.word(kWorkspace) = allocatemem(0x1000);
+}
+
+void DreamGenContext::multiget() {
+ multiget(ds.ptr(si, 0), di, bx, cl, ch);
+ si += cl * ch;
+ di += bx * kScreenwidth + kScreenwidth * ch;
+ cx = 0;
+}
+
+void DreamGenContext::multiget(uint8 *dst, uint16 x, uint16 y, uint8 w, uint8 h) {
+ const uint8 *src = workspace() + x + y * kScreenwidth;
+ if (y + h > 200)
+ h = 200 - y;
+ if (x + w > 320)
+ w = 320 - x;
+ //debug(1, "multiget %u,%u %ux%u -> segment: %04x->%04x", x, y, w, h, (uint16)ds, (uint16)es);
+ for(unsigned l = 0; l < h; ++l) {
+ const uint8 *src_p = src + kScreenwidth * l;
+ uint8 *dst_p = dst + w * l;
+ memcpy(dst_p, src_p, w);
+ }
+}
+
+void DreamGenContext::multiput() {
+ multiput(ds.ptr(si, 0), di, bx, cl, ch);
+ si += cl * ch;
+ di += bx * kScreenwidth + kScreenwidth * ch;
+ cx = 0;
+}
+
+void DreamGenContext::multiput(const uint8 *src, uint16 x, uint16 y, uint8 w, uint8 h) {
+ uint8 *dst = workspace() + x + y * kScreenwidth;
+ if (y + h > 200)
+ h = 200 - y;
+ if (x + w > 320)
+ w = 320 - x;
+ //debug(1, "multiput %ux%u -> segment: %04x->%04x", w, h, (uint16)ds, (uint16)es);
+ for(unsigned l = 0; l < h; ++l) {
+ const uint8 *src_p = src + w * l;
+ uint8 *dst_p = dst + kScreenwidth * l;
+ memcpy(dst_p, src_p, w);
+ }
+}
+
+void DreamGenContext::multidump(uint16 x, uint16 y, uint8 width, uint8 height) {
+ unsigned offset = x + y * kScreenwidth;
+ //debug(1, "multidump %ux%u(segment: %04x) -> %d,%d(address: %d)", w, h, (uint16)ds, x, y, offset);
+ engine->blit(workspace() + offset, kScreenwidth, x, y, width, height);
+}
+
+void DreamGenContext::multidump() {
+ multidump(di, bx, cl, ch);
+ unsigned offset = di + bx * kScreenwidth;
+ si = di = offset + ch * kScreenwidth;
+ cx = 0;
+}
+
+void DreamGenContext::worktoscreen() {
+ uint size = 320 * 200;
+ engine->blit(workspace(), 320, 0, 0, 320, 200);
+ di = si = size;
+ cx = 0;
+}
+
+void DreamGenContext::printundermon() {
+ engine->printUnderMonitor();
+}
+
+void DreamGenContext::cls() {
+ engine->cls();
+}
+
+void DreamGenContext::frameoutnm(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
+ dst += pitch * y + x;
+
+ for (uint16 j = 0; j < height; ++j) {
+ memcpy(dst, src, width);
+ dst += pitch;
+ src += width;
+ }
+}
+
+void DreamGenContext::frameoutbh(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
+ uint16 stride = pitch - width;
+ dst += y * pitch + x;
+
+ for (uint16 i = 0; i < height; ++i) {
+ for (uint16 j = 0; j < width; ++j) {
+ if (*dst == 0xff) {
+ *dst = *src;
+ }
+ ++src;
+ ++dst;
+ }
+ dst += stride;
+ }
+}
+
+void DreamGenContext::frameoutfx(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
+ uint16 stride = pitch - width;
+ dst += y * pitch + x;
+ dst -= width;
+
+ for (uint16 j = 0; j < height; ++j) {
+ for (uint16 i = 0; i < width; ++i) {
+ uint8 pixel = src[width - i - 1];
+ if (pixel)
+ *dst = pixel;
+ ++dst;
+ }
+ src += width;
+ dst += stride;
+ }
+}
+
+void DreamGenContext::doshake() {
+ uint8 &counter = data.byte(kShakecounter);
+ _cmp(counter, 48);
+ if (flags.z())
+ return;
+
+ _add(counter, 1);
+ static const int shakeTable[] = {
+ 0, -2, 3, -2, 0, 2, 4, -1,
+ 1, -3, 3, 2, 0, -2, 3, -2,
+ 0, 2, 4, -1, 1, -3, 3, 2,
+ 0, -2, 3, -2, 0, 2, 4, -1,
+
+ 1, -3, 3, 2, 0, -2, 3, -2,
+ 0, 2, 4, -1, 1, -3, 3, 2,
+ 0, -2, 3, -2, 0, 2, 4, -1,
+ 1, -3, 3, 2, 0, -2, 3, -2,
+
+ 0, 2, 4, -1, 1, -3, 3, 2,
+ 0, -2, 3, -2, 0, 2, 4, -1,
+ 1, -3, 3, 2, 0, -2, 3, -2,
+ 0, 2, 4, -1, 1, -3, 3, 2,
+
+ 0, -2, 3, -2, 0, 2, 4, -1,
+ 1, -3, 3, 0,
+ };
+ int offset = shakeTable[counter];
+ engine->setShakePos(offset >= 0 ? offset : -offset);
+}
+
+void DreamGenContext::vsync() {
+ push(ax);
+ push(bx);
+ push(cx);
+ push(dx);
+ push(si);
+ push(di);
+ push(es);
+ push(ds);
+ engine->waitForVSync();
+ ds = pop();
+ es = pop();
+ di = pop();
+ si = pop();
+ dx = pop();
+ cx = pop();
+ bx = pop();
+ ax = pop();
+}
+
+void DreamGenContext::setmode() {
+ vsync();
+ initGraphics(320, 200, false);
+}
+
+static Common::String getFilename(Context &context) {
+ uint16 name_ptr = context.dx;
+ Common::String name;
+ uint8 c;
+ while((c = context.cs.byte(name_ptr++)) != 0)
+ name += (char)c;
+ return name;
+}
+
+void DreamGenContext::showpcx() {
+ Common::String name = getFilename(*this);
+ Common::File pcxFile;
+
+ if (!pcxFile.open(name)) {
+ warning("showpcx: Could not open '%s'", name.c_str());
+ return;
+ }
+
+ uint8 *maingamepal;
+ int i, j;
+
+ // Read the 16-color palette into the 'maingamepal' buffer. Note that
+ // the color components have to be adjusted from 8 to 6 bits.
+
+ pcxFile.seek(16, SEEK_SET);
+ es = data.word(kBuffers);
+ maingamepal = es.ptr(kMaingamepal, 768);
+ pcxFile.read(maingamepal, 48);
+
+ memset(maingamepal + 48, 0xff, 720);
+ for (i = 0; i < 48; i++) {
+ maingamepal[i] >>= 2;
+ }
+
+ // Decode the image data.
+
+ Graphics::Surface *s = g_system->lockScreen();
+ Common::Rect rect(640, 480);
+
+ s->fillRect(rect, 0);
+ pcxFile.seek(128, SEEK_SET);
+
+ for (int y = 0; y < 480; y++) {
+ byte *dst = (byte *)s->getBasePtr(0, y);
+ int decoded = 0;
+
+ while (decoded < 320) {
+ byte col = pcxFile.readByte();
+ byte len;
+
+ if ((col & 0xc0) == 0xc0) {
+ len = col & 0x3f;
+ col = pcxFile.readByte();
+ } else {
+ len = 1;
+ }
+
+ // The image uses 16 colors and is stored as four bit
+ // planes, one for each bit of the color, least
+ // significant bit plane first.
+
+ for (i = 0; i < len; i++) {
+ int plane = decoded / 80;
+ int pos = decoded % 80;
+
+ for (j = 0; j < 8; j++) {
+ byte bit = (col >> (7 - j)) & 1;
+ dst[8 * pos + j] |= (bit << plane);
+ }
+
+ decoded++;
+ }
+ }
+ }
+
+ g_system->unlockScreen();
+ pcxFile.close();
+}
+
+void DreamGenContext::frameoutv(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
+ // NB : These resilience checks were not in the original engine, but did they result in undefined behaviour
+ // or was something broken during porting to C++?
+ assert(pitch == 320);
+
+ if(x >= 320)
+ return;
+ if(y >= 200)
+ return;
+ if(x + width > 320) {
+ width = 320 - x;
+ }
+ if(y + height > 200) {
+ height = 200 - y;
+ }
+
+ uint16 stride = pitch - width;
+ dst += pitch * y + x;
+
+ for (uint16 j = 0; j < height; ++j) {
+ for (uint16 i = 0; i < width; ++i) {
+ uint8 pixel = *src++;
+ if (pixel)
+ *dst = pixel;
+ ++dst;
+ }
+ dst += stride;
+ }
+}
+
+void DreamGenContext::showframe(const Frame *frameData, uint16 x, uint16 y, uint16 frameNumber, uint8 effectsFlag) {
+ uint8 width, height;
+ showframe(frameData, x, y, frameNumber, effectsFlag, &width, &height);
+}
+
+void DreamGenContext::showframe(const Frame *frameData, uint16 x, uint16 y, uint16 frameNumber, uint8 effectsFlag, uint8 *width, uint8 *height) {
+ const Frame *frame = frameData + frameNumber;
+ if ((frame->width == 0) && (frame->height == 0)) {
+ *width = 0;
+ *height = 0;
+ return;
+ }
+
+//notblankshow:
+ if ((effectsFlag & 128) == 0) {
+ x += frame->x;
+ y += frame->y;
+ }
+//skipoffsets:
+
+ *width = frame->width;
+ *height = frame->height;
+ const uint8 *pSrc = ((const uint8 *)frameData) + frame->ptr() + 2080;
+
+ if (effectsFlag) {
+ if (effectsFlag & 128) { //centred
+ x -= *width / 2;
+ y -= *height / 2;
+ }
+ if (effectsFlag & 64) { //diffdest
+ frameoutfx(es.ptr(0, dx * *height), pSrc, dx, *width, *height, x, y);
+ return;
+ }
+ if (effectsFlag & 8) { //printlist
+ /*
+ push(ax);
+ al = x - data.word(kMapadx);
+ ah = y - data.word(kMapady);
+ //addtoprintlist(); // NB: Commented in the original asm
+ ax = pop();
+ */
+ }
+ if (effectsFlag & 4) { //flippedx
+ frameoutfx(workspace(), pSrc, 320, *width, *height, x, y);
+ return;
+ }
+ if (effectsFlag & 2) { //nomask
+ frameoutnm(workspace(), pSrc, 320, *width, *height, x, y);
+ return;
+ }
+ if (effectsFlag & 32) {
+ frameoutbh(workspace(), pSrc, 320, *width, *height, x, y);
+ return;
+ }
+ }
+//noeffects:
+ frameoutv(workspace(), pSrc, 320, *width, *height, x, y);
+ return;
+}
+
+void DreamGenContext::showframe() {
+ uint8 width, height;
+ showframe((Frame *)ds.ptr(0, 0), di, bx, ax & 0x1ff, ah & 0xfe, &width, &height);
+ cl = width;
+ ch = height;
+}
+
+void DreamGenContext::clearwork() {
+ memset(workspace(), 0, 320*200);
+}
+
+void DreamGenContext::zoom() {
+ if (data.word(kWatchingtime) != 0)
+ return;
+ if (data.byte(kZoomon) != 1)
+ return;
+ if (data.byte(kCommandtype) >= 199) {
+ putunderzoom();
+ return;
+ }
+ uint16 srcOffset = (data.word(kOldpointery) - 9) * 320 + (data.word(kOldpointerx) - 11);
+ uint16 dstOffset = (kZoomy + 4) * 320 + (kZoomx + 5);
+ const uint8 *src = workspace() + srcOffset;
+ uint8 *dst = workspace() + dstOffset;
+ for(size_t i=0; i<20; ++i) {
+ for(size_t j=0; j<23; ++j) {
+ uint8 v = src[j];
+ dst[2*j+0] = v;
+ dst[2*j+1] = v;
+ dst[2*j+320] = v;
+ dst[2*j+321] = v;
+ }
+ src += 320;
+ dst += 320*2;
+ }
+ crosshair();
+ data.byte(kDidzoom) = 1;
+}
+
+} /*namespace dreamgen */
+
diff --git a/engines/engine.cpp b/engines/engine.cpp
index b19daa2611..ee1d53fa9c 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -41,6 +41,7 @@
#include "common/list.h"
#include "common/list_intern.h"
#include "common/scummsys.h"
+#include "common/taskbar.h"
#include "common/textconsole.h"
#include "common/translation.h"
@@ -79,10 +80,21 @@ static void defaultErrorHandler(const char *msg) {
if (isSmartphone())
debugger = 0;
#endif
+
+#if defined(USE_TASKBAR)
+ g_system->getTaskbarManager()->notifyError();
+#endif
+
if (debugger && !debugger->isActive()) {
debugger->attach(msg);
debugger->onFrame();
}
+
+
+#if defined(USE_TASKBAR)
+ g_system->getTaskbarManager()->clearError();
+#endif
+
}
}
diff --git a/engines/engines.mk b/engines/engines.mk
index 7a94288538..a822ab4ba3 100644
--- a/engines/engines.mk
+++ b/engines/engines.mk
@@ -31,6 +31,11 @@ DEFINES += -DENABLE_CINE=$(ENABLE_CINE)
MODULES += engines/cine
endif
+ifdef ENABLE_COMPOSER
+DEFINES += -DENABLE_COMPOSER=$(ENABLE_COMPOSER)
+MODULES += engines/composer
+endif
+
ifdef ENABLE_CRUISE
DEFINES += -DENABLE_CRUISE=$(ENABLE_CRUISE)
MODULES += engines/cruise
@@ -207,4 +212,3 @@ ifdef ENABLE_TUCKER
DEFINES += -DENABLE_TUCKER=$(ENABLE_TUCKER)
MODULES += engines/tucker
endif
-
diff --git a/engines/gob/console.cpp b/engines/gob/console.cpp
index b8aed37727..e7296fb81b 100644
--- a/engines/gob/console.cpp
+++ b/engines/gob/console.cpp
@@ -29,6 +29,7 @@ namespace Gob {
GobConsole::GobConsole(GobEngine *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("varSize", WRAP_METHOD(GobConsole, cmd_varSize));
+ DCmd_Register("dumpVars", WRAP_METHOD(GobConsole, cmd_dumpVars));
DCmd_Register("var8", WRAP_METHOD(GobConsole, cmd_var8));
DCmd_Register("var16", WRAP_METHOD(GobConsole, cmd_var16));
DCmd_Register("var32", WRAP_METHOD(GobConsole, cmd_var32));
@@ -44,6 +45,23 @@ bool GobConsole::cmd_varSize(int argc, const char **argv) {
return true;
}
+bool GobConsole::cmd_dumpVars(int argc, const char **argv) {
+ if (!_vm->_inter->_variables)
+ return true;
+
+ Common::DumpFile file;
+
+ if (!file.open("variables.dmp"))
+ return true;
+
+ file.write(_vm->_inter->_variables->getAddressOff8(0), _vm->_inter->_variables->getSize());
+
+ file.flush();
+ file.close();
+
+ return true;
+}
+
bool GobConsole::cmd_var8(int argc, const char **argv) {
if (argc == 1) {
DebugPrintf("Usage: var8 <var offset> (<value>)\n");
diff --git a/engines/gob/console.h b/engines/gob/console.h
index b9f9b81d0e..b9c3f5ed70 100644
--- a/engines/gob/console.h
+++ b/engines/gob/console.h
@@ -38,6 +38,7 @@ private:
GobEngine *_vm;
bool cmd_varSize(int argc, const char **argv);
+ bool cmd_dumpVars(int argc, const char **argv);
bool cmd_var8(int argc, const char **argv);
bool cmd_var16(int argc, const char **argv);
bool cmd_var32(int argc, const char **argv);
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index a576cf9487..1633a1edb7 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -32,11 +32,11 @@
namespace Gob {
-DataIO::File::File() : size(0), offset(0), packed(false), archive(0) {
+DataIO::File::File() : size(0), offset(0), compression(0), archive(0) {
}
-DataIO::File::File(const Common::String &n, uint32 s, uint32 o, bool p, Archive &a) :
- name(n), size(s), offset(o), packed(p), archive(&a) {
+DataIO::File::File(const Common::String &n, uint32 s, uint32 o, uint8 c, Archive &a) :
+ name(n), size(s), offset(o), compression(c), archive(&a) {
}
@@ -71,26 +71,92 @@ void DataIO::getArchiveInfo(Common::Array<ArchiveInfo> &info) const {
}
}
-byte *DataIO::unpack(const byte *src, uint32 srcSize, int32 &size) {
- size = READ_LE_UINT32(src);
+uint32 DataIO::getSizeChunks(Common::SeekableReadStream &src) {
+ uint32 size = 0;
- byte *data = new byte[size];
+ uint32 chunkSize = 2, realSize;
+ while (chunkSize != 0xFFFF) {
+ src.skip(chunkSize - 2);
+
+ chunkSize = src.readUint16LE();
+ realSize = src.readUint16LE();
+
+ assert(chunkSize >= 4);
+
+ size += realSize;
+ }
+
+ assert(!src.eos());
+
+ src.seek(0);
+
+ return size;
+}
+
+byte *DataIO::unpack(Common::SeekableReadStream &src, int32 &size, uint8 compression, bool useMalloc) {
+ assert((compression == 1) || (compression == 2));
+
+ if (compression == 1)
+ size = src.readUint32LE();
+ else if (compression == 2)
+ size = getSizeChunks(src);
+
+ assert(size > 0);
+
+ byte *data = 0;
+ if (useMalloc)
+ data = (byte *) malloc(size);
+ else
+ data = new byte[size];
+
+ if (compression == 1)
+ unpackChunk(src, data, size);
+ else if (compression == 2)
+ unpackChunks(src, data, size);
- Common::MemoryReadStream srcStream(src + 4, srcSize - 4);
- unpack(srcStream, data, size);
return data;
}
-Common::SeekableReadStream *DataIO::unpack(Common::SeekableReadStream &src) {
- uint32 size = src.readUint32LE();
+byte *DataIO::unpack(const byte *src, uint32 srcSize, int32 &size, uint8 compression) {
+ Common::MemoryReadStream srcStream(src, srcSize);
- byte *data = (byte *) malloc(size);
+ return unpack(srcStream, size, compression, false);
+}
+
+Common::SeekableReadStream *DataIO::unpack(Common::SeekableReadStream &src, uint8 compression) {
+ int32 size;
+
+ byte *data = unpack(src, size, compression, true);
+ if (!data)
+ return 0;
- unpack(src, data, size);
return new Common::MemoryReadStream(data, size, DisposeAfterUse::YES);
}
-void DataIO::unpack(Common::SeekableReadStream &src, byte *dest, uint32 size) {
+void DataIO::unpackChunks(Common::SeekableReadStream &src, byte *dest, uint32 size) {
+ uint32 chunkSize = 0, realSize;
+ while (chunkSize != 0xFFFF) {
+ uint32 pos = src.pos();
+
+ chunkSize = src.readUint16LE();
+ realSize = src.readUint16LE();
+
+ assert(chunkSize >= 4);
+ assert(size >= realSize);
+
+ src.skip(2);
+
+ unpackChunk(src, dest, realSize);
+
+ if (chunkSize != 0xFFFF)
+ src.seek(pos + chunkSize + 2);
+
+ size -= realSize;
+ dest += realSize;
+ }
+}
+
+void DataIO::unpackChunk(Common::SeekableReadStream &src, byte *dest, uint32 size) {
byte *tmpBuf = new byte[4114];
assert(tmpBuf);
@@ -194,9 +260,9 @@ DataIO::Archive *DataIO::openArchive(const Common::String &name) {
archive->file.read(fileName, 13);
fileName[13] = '\0';
- file.size = archive->file.readUint32LE();
- file.offset = archive->file.readUint32LE();
- file.packed = archive->file.readByte() != 0;
+ file.size = archive->file.readUint32LE();
+ file.offset = archive->file.readUint32LE();
+ file.compression = archive->file.readByte() != 0;
// Replacing cyrillic characters
Util::replaceChar(fileName, (char) 0x85, 'E');
@@ -209,8 +275,8 @@ DataIO::Archive *DataIO::openArchive(const Common::String &name) {
// Geisha use 0ot files, which are compressed TOT files without the packed byte set.
if (file.name.hasSuffix(".0OT")) {
- file.name.setChar(file.name.size() - 3, 'T');
- file.packed = true;
+ file.name.setChar('T', file.name.size() - 3);
+ file.compression = 2;
}
file.archive = archive;
@@ -254,7 +320,7 @@ int32 DataIO::fileSize(const Common::String &name) {
// Try to find the file in the archives
File *file = findFile(name);
if (file) {
- if (!file->packed)
+ if (file->compression == 0)
return file->size;
// Sanity checks
@@ -264,6 +330,10 @@ int32 DataIO::fileSize(const Common::String &name) {
// Read the full, unpacked size
file->archive->file.seek(file->offset);
+
+ if (file->compression == 2)
+ file->archive->file.skip(4);
+
return file->archive->file.readUint32LE();
}
@@ -346,10 +416,10 @@ Common::SeekableReadStream *DataIO::getFile(File &file) {
Common::SeekableReadStream *rawData =
new Common::SafeSubReadStream(&file.archive->file, file.offset, file.offset + file.size);
- if (!file.packed)
+ if (file.compression == 0)
return rawData;
- Common::SeekableReadStream *unpackedData = unpack(*rawData);
+ Common::SeekableReadStream *unpackedData = unpack(*rawData, file.compression);
delete rawData;
@@ -374,10 +444,10 @@ byte *DataIO::getFile(File &file, int32 &size) {
return 0;
}
- if (!file.packed)
+ if (file.compression == 0)
return rawData;
- byte *unpackedData = unpack(rawData, file.size, size);
+ byte *unpackedData = unpack(rawData, file.size, size, file.compression);
delete[] rawData;
diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h
index d95f001097..adf0786389 100644
--- a/engines/gob/dataio.h
+++ b/engines/gob/dataio.h
@@ -58,8 +58,8 @@ public:
Common::SeekableReadStream *getFile(const Common::String &name);
byte *getFile(const Common::String &name, int32 &size);
- static byte *unpack(const byte *src, uint32 srcSize, int32 &size);
- static Common::SeekableReadStream *unpack(Common::SeekableReadStream &src);
+ static byte *unpack(const byte *src, uint32 srcSize, int32 &size, uint8 compression = 1);
+ static Common::SeekableReadStream *unpack(Common::SeekableReadStream &src, uint8 compression = 1);
private:
static const int kMaxArchives = 8;
@@ -70,12 +70,12 @@ private:
Common::String name;
uint32 size;
uint32 offset;
- bool packed;
+ uint8 compression;
Archive *archive;
File();
- File(const Common::String &n, uint32 s, uint32 o, bool p, Archive &a);
+ File(const Common::String &n, uint32 s, uint32 o, uint8 c, Archive &a);
};
typedef Common::HashMap<Common::String, File, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
@@ -99,7 +99,12 @@ private:
Common::SeekableReadStream *getFile(File &file);
byte *getFile(File &file, int32 &size);
- static void unpack(Common::SeekableReadStream &src, byte *dest, uint32 size);
+ static byte *unpack(Common::SeekableReadStream &src, int32 &size, uint8 compression, bool useMalloc);
+
+ static uint32 getSizeChunks(Common::SeekableReadStream &src);
+
+ static void unpackChunks(Common::SeekableReadStream &src, byte *dest, uint32 size);
+ static void unpackChunk (Common::SeekableReadStream &src, byte *dest, uint32 size);
};
} // End of namespace Gob
diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h
index 1c9811fe9e..4c1ff9a8e3 100644
--- a/engines/gob/detection_tables.h
+++ b/engines/gob/detection_tables.h
@@ -2496,7 +2496,7 @@ static const GOBGameDescription gameDescriptions[] = {
GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGeisha,
- kFeaturesNone,
+ kFeaturesEGA | kFeaturesAdLib,
"disk1.stk", "intro.tot", 0
},
{
@@ -2510,7 +2510,7 @@ static const GOBGameDescription gameDescriptions[] = {
GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGeisha,
- kFeaturesNone,
+ kFeaturesEGA | kFeaturesAdLib,
"disk1.stk", "intro.tot", 0
},
{
@@ -5154,7 +5154,7 @@ static const GOBGameDescription fallbackDescs[] = {
GUIO_NOSUBTITLES | GUIO_NOSPEECH
},
kGameTypeGeisha,
- kFeaturesNone,
+ kFeaturesEGA,
"disk1.stk", "intro.tot", 0
},
{ //22
diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp
index 3873a99d5f..064c74958a 100644
--- a/engines/gob/draw_v1.cpp
+++ b/engines/gob/draw_v1.cpp
@@ -44,8 +44,8 @@ void Draw_v1::initScreen() {
_backSurface = _vm->_video->initSurfDesc(320, 200);
_frontSurface = _vm->_global->_primarySurfDesc;
- _cursorSprites = _vm->_video->initSurfDesc(32, 16, 2);
- _scummvmCursor = _vm->_video->initSurfDesc(16, 16, SCUMMVM_CURSOR);
+ _cursorSprites = _vm->_video->initSurfDesc(_cursorWidth * 2, _cursorHeight, 2);
+ _scummvmCursor = _vm->_video->initSurfDesc(_cursorWidth , _cursorHeight, SCUMMVM_CURSOR);
}
void Draw_v1::closeScreen() {
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index cc8f6b5e3c..151ed42526 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -916,4 +916,3 @@ void Draw_v2::spriteOperation(int16 operation) {
}
} // End of namespace Gob
-
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 926027e15d..7b43e9c4d7 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -492,9 +492,6 @@ void Game::prepareStart() {
_vm->_draw->_noInvalidated = true;
_vm->_draw->_applyPal = false;
_vm->_draw->_paletteCleared = false;
- _vm->_draw->_cursorWidth = 16;
- _vm->_draw->_cursorHeight = 16;
- _vm->_draw->_transparentCursor = 1;
for (int i = 0; i < 40; i++) {
_vm->_draw->_cursorAnimLow[i] = -1;
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index ea7e329480..7bb7928406 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -402,7 +402,6 @@ bool GobEngine::initGameParts() {
_game = new Game(this);
switch (_gameType) {
- case kGameTypeGeisha:
case kGameTypeGob1:
_init = new Init_v1(this);
_video = new Video_v1(this);
@@ -414,6 +413,17 @@ bool GobEngine::initGameParts() {
_scenery = new Scenery_v1(this);
break;
+ case kGameTypeGeisha:
+ _init = new Init_Geisha(this);
+ _video = new Video_v1(this);
+ _inter = new Inter_Geisha(this);
+ _mult = new Mult_v1(this);
+ _draw = new Draw_v1(this);
+ _map = new Map_v1(this);
+ _goblin = new Goblin_v1(this);
+ _scenery = new Scenery_v1(this);
+ break;
+
case kGameTypeFascination:
_init = new Init_Fascination(this);
_video = new Video_v2(this);
diff --git a/engines/gob/init.h b/engines/gob/init.h
index 1cb2904099..e8c948c72e 100644
--- a/engines/gob/init.h
+++ b/engines/gob/init.h
@@ -56,6 +56,14 @@ public:
void initVideo();
};
+class Init_Geisha : public Init_v1 {
+public:
+ Init_Geisha(GobEngine *vm);
+ ~Init_Geisha();
+
+ void initVideo();
+};
+
class Init_v2 : public Init_v1 {
public:
Init_v2(GobEngine *vm);
diff --git a/engines/agi/preagi_common.h b/engines/gob/init_geisha.cpp
index a557f69977..01081a5af6 100644
--- a/engines/agi/preagi_common.h
+++ b/engines/gob/init_geisha.cpp
@@ -20,32 +20,28 @@
*
*/
+#include "common/endian.h"
+#include "gob/gob.h"
+#include "gob/init.h"
+#include "gob/global.h"
+#include "gob/draw.h"
+#include "gob/video.h"
-#ifndef AGI_PREAGI_COMMON_H
-#define AGI_PREAGI_COMMON_H
+namespace Gob {
-namespace Agi {
+Init_Geisha::Init_Geisha(GobEngine *vm) : Init_v1(vm) {
+}
-// default attributes
-#define IDA_DEFAULT 0x0F
-#define IDA_DEFAULT_REV 0xF0
+Init_Geisha::~Init_Geisha() {
+}
-#define IDI_SND_OSCILLATOR_FREQUENCY 1193180
-#define IDI_SND_TIMER_RESOLUTION 0.0182
+void Init_Geisha::initVideo() {
+ Init_v1::initVideo();
-#define kColorDefault 0x1337
+ _vm->_draw->_cursorWidth = 16;
+ _vm->_draw->_cursorHeight = 23;
+ _vm->_draw->_transparentCursor = 1;
+}
-#define IDI_MAX_ROW_PIC 20
-
-enum SelectionTypes {
- kSelYesNo,
- kSelNumber,
- kSelSpace,
- kSelAnyKey,
- kSelBackspace
-};
-
-} // End of namespace Agi
-
-#endif
+} // End of namespace Gob
diff --git a/engines/gob/init_v1.cpp b/engines/gob/init_v1.cpp
index 6772a13eb0..25d521aca6 100644
--- a/engines/gob/init_v1.cpp
+++ b/engines/gob/init_v1.cpp
@@ -52,6 +52,10 @@ void Init_v1::initVideo() {
_vm->_global->_pPaletteDesc->unused2 = _vm->_global->_unusedPalette2;
_vm->_video->initSurfDesc(320, 200, PRIMARY_SURFACE);
+
+ _vm->_draw->_cursorWidth = 16;
+ _vm->_draw->_cursorHeight = 16;
+ _vm->_draw->_transparentCursor = 1;
}
} // End of namespace Gob
diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp
index f10d586a34..1289d561ea 100644
--- a/engines/gob/init_v2.cpp
+++ b/engines/gob/init_v2.cpp
@@ -62,6 +62,10 @@ void Init_v2::initVideo() {
_vm->_global->_pPaletteDesc->unused2 = _vm->_global->_unusedPalette2;
_vm->_video->initSurfDesc(_vm->_video->_surfWidth, _vm->_video->_surfHeight, PRIMARY_SURFACE);
+
+ _vm->_draw->_cursorWidth = 16;
+ _vm->_draw->_cursorHeight = 16;
+ _vm->_draw->_transparentCursor = 1;
}
} // End of namespace Gob
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 78d5e34271..84180f407d 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -334,6 +334,33 @@ protected:
void manipulateMap(int16 xPos, int16 yPos, int16 item);
};
+class Inter_Geisha : public Inter_v1 {
+public:
+ Inter_Geisha(GobEngine *vm);
+ virtual ~Inter_Geisha() {}
+
+protected:
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
+
+ void oGeisha_loadCursor(OpFuncParams &params);
+ void oGeisha_goblinFunc(OpFuncParams &params);
+ void oGeisha_loadSound(OpFuncParams &params);
+ void oGeisha_checkData(OpFuncParams &params);
+
+ void oGeisha_gamePenetration(OpGobParams &params);
+ void oGeisha_gameDiving(OpGobParams &params);
+ void oGeisha_loadTitleMusic(OpGobParams &params);
+ void oGeisha_playMusic(OpGobParams &params);
+ void oGeisha_stopMusic(OpGobParams &params);
+
+ void oGeisha_caress1(OpGobParams &params);
+ void oGeisha_caress2(OpGobParams &params);
+
+ int16 loadSound(int16 slot);
+};
+
class Inter_v2 : public Inter_v1 {
public:
Inter_v2(GobEngine *vm);
@@ -477,9 +504,14 @@ protected:
virtual void setupOpcodesGob();
void o3_getTotTextItemPart(OpFuncParams &params);
+ void o3_speakerOn(OpFuncParams &params);
+ void o3_speakerOff(OpFuncParams &params);
void o3_copySprite(OpFuncParams &params);
void o3_wobble(OpGobParams &params);
+
+private:
+ bool _ignoreSpeakerOff;
};
class Inter_Inca2 : public Inter_v3 {
diff --git a/engines/gob/inter_geisha.cpp b/engines/gob/inter_geisha.cpp
new file mode 100644
index 0000000000..658f2346f4
--- /dev/null
+++ b/engines/gob/inter_geisha.cpp
@@ -0,0 +1,186 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/endian.h"
+
+#include "gob/gob.h"
+#include "gob/inter.h"
+#include "gob/dataio.h"
+#include "gob/script.h"
+#include "gob/resources.h"
+#include "gob/game.h"
+#include "gob/draw.h"
+#include "gob/video.h"
+#include "gob/sound/sound.h"
+#include "gob/sound/sounddesc.h"
+
+namespace Gob {
+
+#define OPCODEVER Inter_Geisha
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
+
+Inter_Geisha::Inter_Geisha(GobEngine *vm) : Inter_v1(vm) {
+}
+
+void Inter_Geisha::setupOpcodesDraw() {
+ Inter_v1::setupOpcodesDraw();
+}
+
+void Inter_Geisha::setupOpcodesFunc() {
+ Inter_v1::setupOpcodesFunc();
+
+ OPCODEFUNC(0x03, oGeisha_loadCursor);
+ OPCODEFUNC(0x25, oGeisha_goblinFunc);
+ OPCODEFUNC(0x3A, oGeisha_loadSound);
+ OPCODEFUNC(0x3F, oGeisha_checkData);
+
+ OPCODEGOB(0, oGeisha_gamePenetration);
+ OPCODEGOB(1, oGeisha_gameDiving);
+ OPCODEGOB(2, oGeisha_loadTitleMusic);
+ OPCODEGOB(3, oGeisha_playMusic);
+ OPCODEGOB(4, oGeisha_stopMusic);
+ OPCODEGOB(6, oGeisha_caress1);
+ OPCODEGOB(7, oGeisha_caress2);
+}
+
+void Inter_Geisha::setupOpcodesGob() {
+}
+
+void Inter_Geisha::oGeisha_loadCursor(OpFuncParams &params) {
+ if (_vm->_game->_script->peekByte(1) & 0x80)
+ warning("Geisha Stub: oGeisha_loadCursor: script[1] & 0x80");
+
+ o1_loadCursor(params);
+}
+
+void Inter_Geisha::oGeisha_loadSound(OpFuncParams &params) {
+ loadSound(-1);
+}
+
+void Inter_Geisha::oGeisha_goblinFunc(OpFuncParams &params) {
+ OpGobParams gobParams;
+ int16 cmd;
+
+ cmd = _vm->_game->_script->readInt16();
+
+ gobParams.paramCount = _vm->_game->_script->readInt16();
+ gobParams.extraData = cmd;
+
+ executeOpcodeGob(cmd, gobParams);
+}
+
+int16 Inter_Geisha::loadSound(int16 slot) {
+ const char *sndFile = _vm->_game->_script->evalString();
+
+ if (slot == -1)
+ slot = _vm->_game->_script->readValExpr();
+
+ SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot);
+ if (!sample)
+ return 0;
+
+ int32 dataSize;
+ byte *dataPtr = _vm->_dataIO->getFile(sndFile, dataSize);
+ if (!dataPtr)
+ return 0;
+
+ if (!sample->load(SOUND_SND, dataPtr, dataSize)) {
+ delete[] dataPtr;
+ return 0;
+ }
+
+ return 0;
+}
+
+void Inter_Geisha::oGeisha_checkData(OpFuncParams &params) {
+ const char *file = _vm->_game->_script->evalString();
+ int16 varOff = _vm->_game->_script->readVarIndex();
+
+ Common::String fileName(file);
+
+ fileName.toLowercase();
+ if (fileName.hasSuffix(".0ot"))
+ fileName.setChar('t', fileName.size() - 3);
+
+ if (!_vm->_dataIO->hasFile(fileName)) {
+ warning("File \"%s\" not found", fileName.c_str());
+ WRITE_VAR_OFFSET(varOff, (uint32) -1);
+ } else
+ WRITE_VAR_OFFSET(varOff, 50); // "handle" between 50 and 128 = in archive
+}
+
+void Inter_Geisha::oGeisha_gamePenetration(OpGobParams &params) {
+ uint16 var1 = _vm->_game->_script->readUint16();
+ uint16 var2 = _vm->_game->_script->readUint16();
+ uint16 var3 = _vm->_game->_script->readUint16();
+ uint16 var4 = _vm->_game->_script->readUint16();
+
+ WRITE_VAR_UINT32(var4, 0);
+
+ warning("Geisha Stub: Minigame \"Penetration\": %d, %d, %d, %d", var1, var2, var3, var4);
+
+ // Fudge a win for now
+ WRITE_VAR_UINT32(var4, 1);
+}
+
+void Inter_Geisha::oGeisha_gameDiving(OpGobParams &params) {
+ uint16 var1 = _vm->_game->_script->readUint16();
+ uint16 var2 = _vm->_game->_script->readUint16();
+ uint16 var3 = _vm->_game->_script->readUint16();
+
+ WRITE_VAR_UINT32(var3, 1);
+
+ warning("Geisha Stub: Minigame \"Diving\": %d, %d, %d", var1, var2, var3);
+
+ // Fudge a win for now
+ WRITE_VAR_UINT32(var3, 0);
+}
+
+void Inter_Geisha::oGeisha_loadTitleMusic(OpGobParams &params) {
+ _vm->_sound->adlibLoadTBR("geisha.tbr");
+ _vm->_sound->adlibLoadMDY("geisha.mdy");
+}
+
+void Inter_Geisha::oGeisha_playMusic(OpGobParams &params) {
+ // TODO: The MDYPlayer is still broken!
+ warning("Geisha Stub: oGeisha_playMusic");
+ // _vm->_sound->adlibPlay();
+}
+
+void Inter_Geisha::oGeisha_stopMusic(OpGobParams &params) {
+ _vm->_sound->adlibStop();
+ _vm->_sound->adlibUnload();
+}
+
+void Inter_Geisha::oGeisha_caress1(OpGobParams &params) {
+ if (_vm->_draw->_spritesArray[0])
+ _vm->_video->drawPackedSprite("hp1.cmp", *_vm->_draw->_spritesArray[0]);
+}
+
+void Inter_Geisha::oGeisha_caress2(OpGobParams &params) {
+ if (_vm->_draw->_spritesArray[1])
+ _vm->_video->drawPackedSprite("hpsc1.cmp", *_vm->_draw->_spritesArray[1]);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index 47b0beaf63..0eb8be1a03 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -658,6 +658,20 @@ void Inter_v1::o1_callSub(OpFuncParams &params) {
return;
}
+ // A cheat to get around the stupid mastermind puzzle in Geisha,
+ // while we're still testing it
+ if ((_vm->getGameType() == kGameTypeGeisha) && (offset == 12934) &&
+ _vm->isCurrentTot("hard.tot") && _vm->_inter->_variables) {
+
+ uint32 digit1 = READ_VARO_UINT32(0x768);
+ uint32 digit2 = READ_VARO_UINT32(0x76C);
+ uint32 digit3 = READ_VARO_UINT32(0x770);
+ uint32 digit4 = READ_VARO_UINT32(0x774);
+ uint32 digit5 = READ_VARO_UINT32(0x778);
+
+ warning("Mastermind solution: %d %d %d %d %d", digit1, digit2, digit3, digit4, digit5);
+ }
+
// Skipping the copy protection screen in Gobliiins
if (!_vm->_copyProtection && (_vm->getGameType() == kGameTypeGob1) && (offset == 3905) &&
_vm->isCurrentTot(_vm->_startTot)) {
@@ -1094,6 +1108,8 @@ void Inter_v1::o1_palLoad(OpFuncParams &params) {
_vm->_draw->_vgaPalette[i].green = _vm->_game->_script->readByte();
_vm->_draw->_vgaPalette[i].blue = _vm->_game->_script->readByte();
}
+
+ memcpy(_vm->_draw->_vgaSmallPalette, _vm->_draw->_vgaPalette, 16 * 3);
break;
case 53:
diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp
index 47486b0899..edf56012d9 100644
--- a/engines/gob/inter_v3.cpp
+++ b/engines/gob/inter_v3.cpp
@@ -31,6 +31,7 @@
#include "gob/game.h"
#include "gob/script.h"
#include "gob/resources.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -39,7 +40,7 @@ namespace Gob {
#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
-Inter_v3::Inter_v3(GobEngine *vm) : Inter_v2(vm) {
+Inter_v3::Inter_v3(GobEngine *vm) : Inter_v2(vm), _ignoreSpeakerOff(false) {
}
void Inter_v3::setupOpcodesDraw() {
@@ -50,6 +51,8 @@ void Inter_v3::setupOpcodesFunc() {
Inter_v2::setupOpcodesFunc();
OPCODEFUNC(0x1A, o3_getTotTextItemPart);
+ OPCODEFUNC(0x22, o3_speakerOn);
+ OPCODEFUNC(0x23, o3_speakerOff);
OPCODEFUNC(0x32, o3_copySprite);
}
@@ -245,6 +248,36 @@ void Inter_v3::o3_getTotTextItemPart(OpFuncParams &params) {
delete textItem;
}
+void Inter_v3::o3_speakerOn(OpFuncParams &params) {
+ int16 frequency = _vm->_game->_script->readValExpr();
+ int32 length = -1;
+
+ _ignoreSpeakerOff = false;
+
+ // WORKAROUND: This is the footsteps sound. The scripts just fire
+ // speaker on" and then a "speaker off" after a short while. Since
+ // we have delay in certain places avoid 100% CPU all the time and
+ // our PC speaker emulator sometimes "swallows" very short beeper
+ // bursts issued in this way, this is in general quite wonky and
+ // prone to fail, as can be seen in bug report #3376547. Therefore,
+ // we explicitely set a length in this case and ignore the next
+ // speaker off command.
+ if (frequency == 50) {
+ length = 5;
+
+ _ignoreSpeakerOff = true;
+ }
+
+ _vm->_sound->speakerOn(frequency, length);
+}
+
+void Inter_v3::o3_speakerOff(OpFuncParams &params) {
+ if (!_ignoreSpeakerOff)
+ _vm->_sound->speakerOff();
+
+ _ignoreSpeakerOff = false;
+}
+
void Inter_v3::o3_copySprite(OpFuncParams &params) {
o1_copySprite(params);
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index cdad1e6c46..b85c387734 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -25,6 +25,7 @@ MODULE_OBJS := \
iniconfig.o \
init.o \
init_v1.o \
+ init_geisha.o \
init_v2.o \
init_fascin.o \
init_v3.o \
@@ -33,6 +34,7 @@ MODULE_OBJS := \
init_v7.o \
inter.o \
inter_v1.o \
+ inter_geisha.o \
inter_v2.o \
inter_bargon.o \
inter_fascin.o \
diff --git a/engines/gob/palanim.cpp b/engines/gob/palanim.cpp
index 42aeaf63eb..8a5327c3f1 100644
--- a/engines/gob/palanim.cpp
+++ b/engines/gob/palanim.cpp
@@ -79,9 +79,6 @@ bool PalAnim::fadeStep(int16 oper) {
byte newGreen;
byte newBlue;
- if (_vm->_global->_colorCount != 256)
- error("PalAnim::fadeStep(): Only 256 color mode is supported");
-
if (oper == 0) {
if (_vm->_global->_setAllPalette) {
if (_vm->_global->_inVM != 0)
@@ -134,12 +131,6 @@ void PalAnim::fade(Video::PalDesc *palDesc, int16 fadeV, int16 allColors) {
_fadeValue = (fadeV < 0) ? -fadeV : 2;
- if (_vm->_global->_colorCount < 256) {
- if (palDesc)
- _vm->_video->setFullPalette(palDesc);
- return;
- }
-
if (!_vm->_global->_setAllPalette) {
if (!palDesc) {
for (i = 0; i < 16; i++) {
diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp
index bb50818ed8..33fdfcaa2a 100644
--- a/engines/gob/scenery.cpp
+++ b/engines/gob/scenery.cpp
@@ -622,7 +622,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
if (frame >= (int32)_vm->_vidPlayer->getFrameCount(obj.videoSlot - 1))
frame = _vm->_vidPlayer->getFrameCount(obj.videoSlot - 1) - 1;
- if (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) >= 255) {
+ if ((int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) >= 255) {
// Allow for object videos with more than 255 frames, although the
// object frame counter is just a byte.
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 5f95de649a..f5f02b5cdd 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -20,6 +20,9 @@
*
*/
+#include "audio/mididrv.h"
+#include "audio/mixer.h"
+
#include "groovie/groovie.h"
#include "groovie/cursor.h"
#include "groovie/detection.h"
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index c6e990dfcf..af929d439b 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -20,6 +20,9 @@
*
*/
+#include "audio/mididrv.h"
+#include "audio/mixer.h"
+
#include "groovie/music.h"
#include "groovie/groovie.h"
#include "groovie/resource.h"
@@ -766,7 +769,7 @@ Common::SeekableReadStream *MusicPlayerMac::decompressMidi(Common::SeekableReadS
}
MusicPlayerIOS::MusicPlayerIOS(GroovieEngine *vm) : MusicPlayer(vm) {
- vm->getTimerManager()->installTimerProc(&onTimer, 50 * 1000, this);
+ vm->getTimerManager()->installTimerProc(&onTimer, 50 * 1000, this, "groovieMusic");
}
MusicPlayerIOS::~MusicPlayerIOS() {
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index 7af482e45d..cc852aa8dc 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -25,8 +25,6 @@
#include "common/array.h"
#include "common/mutex.h"
-#include "audio/mididrv.h"
-#include "audio/mixer.h"
class MidiParser;
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 5a24559e8b..9003a58ab8 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -20,6 +20,9 @@
*
*/
+#include "audio/mididrv.h"
+#include "audio/mixer.h"
+
#include "groovie/script.h"
#include "groovie/cell.h"
#include "groovie/cursor.h"
diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp
index f70a21aa8f..5d972f5658 100644
--- a/engines/hugo/detection.cpp
+++ b/engines/hugo/detection.cpp
@@ -241,12 +241,7 @@ SaveStateDescriptor HugoMetaEngine::querySaveMetaInfos(const char *target, int s
SaveStateDescriptor desc(slot, saveName);
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- if (!Graphics::loadThumbnail(*file, *thumbnail)) {
- delete thumbnail;
- thumbnail = 0;
- }
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*file);
desc.setThumbnail(thumbnail);
desc.setDeletableFlag(true);
diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp
index 2d35bb0448..fa18d6b791 100644
--- a/engines/hugo/display.cpp
+++ b/engines/hugo/display.cpp
@@ -813,4 +813,3 @@ overlayState_t Screen_v1w::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 cde6e108ea..2217cef92a 100644
--- a/engines/hugo/file.cpp
+++ b/engines/hugo/file.cpp
@@ -695,4 +695,3 @@ void FileManager::readUIFImages() {
}
} // End of namespace Hugo
-
diff --git a/engines/hugo/file_v1d.cpp b/engines/hugo/file_v1d.cpp
index 0795923536..c3bb0e275f 100644
--- a/engines/hugo/file_v1d.cpp
+++ b/engines/hugo/file_v1d.cpp
@@ -128,4 +128,3 @@ void FileManager_v1d::instructions() const {
}
} // End of namespace Hugo
-
diff --git a/engines/hugo/file_v1w.cpp b/engines/hugo/file_v1w.cpp
index 162019dd2e..8a06cef939 100644
--- a/engines/hugo/file_v1w.cpp
+++ b/engines/hugo/file_v1w.cpp
@@ -87,4 +87,3 @@ void FileManager_v1w::readOverlay(const int screenNum, image_pt image, ovl_t ove
}
} // End of namespace Hugo
-
diff --git a/engines/hugo/file_v2d.cpp b/engines/hugo/file_v2d.cpp
index 7e44e756d5..520e1b77b6 100644
--- a/engines/hugo/file_v2d.cpp
+++ b/engines/hugo/file_v2d.cpp
@@ -187,4 +187,3 @@ const char *FileManager_v2d::fetchString(const int index) {
return _fetchStringBuf;
}
} // End of namespace Hugo
-
diff --git a/engines/hugo/file_v2w.cpp b/engines/hugo/file_v2w.cpp
index 1384f02df6..98a15526fa 100644
--- a/engines/hugo/file_v2w.cpp
+++ b/engines/hugo/file_v2w.cpp
@@ -49,4 +49,3 @@ void FileManager_v2w::instructions() const {
}
} // End of namespace Hugo
-
diff --git a/engines/hugo/file_v3d.cpp b/engines/hugo/file_v3d.cpp
index 69371bb030..d86003a040 100644
--- a/engines/hugo/file_v3d.cpp
+++ b/engines/hugo/file_v3d.cpp
@@ -205,4 +205,3 @@ void FileManager_v3d::readOverlay(const int screenNum, image_pt image, ovl_t ove
}
}
} // End of namespace Hugo
-
diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp
index c66c0ef624..72f718fe8e 100644
--- a/engines/hugo/intro.cpp
+++ b/engines/hugo/intro.cpp
@@ -317,7 +317,7 @@ void intro_v3d::introInit() {
_vm->_file->readBackground(22); // display screen MAP_3d
_vm->_screen->displayBackground();
introTicks = 0;
- _vm->_sound->DOSSongPtr = _vm->_sound->DOSIntroSong;
+ _vm->_sound->_DOSSongPtr = _vm->_sound->_DOSIntroSong;
}
/**
diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp
index d1b4aa6a9c..dc20ca117d 100644
--- a/engines/hugo/schedule.cpp
+++ b/engines/hugo/schedule.cpp
@@ -1416,7 +1416,7 @@ event_t *Scheduler::doAction(event_t *curEvent) {
break;
case OLD_SONG:
// Replaces ACT26 for DOS games.
- _vm->_sound->DOSSongPtr = _vm->_text->getTextData(action->a49.songIndex);
+ _vm->_sound->_DOSSongPtr = _vm->_text->getTextData(action->a49.songIndex);
break;
default:
error("An error has occurred: %s", "doAction");
diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index 1fea1f4343..79ec066b7f 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -123,11 +123,11 @@ SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) {
_speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate());
_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
- DOSSongPtr = 0;
- curPriority = 0;
- pcspkrTimer = 0;
- pcspkrOctave = 3;
- pcspkrNoteDuration = 2;
+ _DOSSongPtr = 0;
+ _curPriority = 0;
+ _pcspkrTimer = 0;
+ _pcspkrOctave = 3;
+ _pcspkrNoteDuration = 2;
}
SoundHandler::~SoundHandler() {
@@ -207,7 +207,7 @@ void SoundHandler::playSound(int16 sound, const byte priority) {
return;
syncVolume();
- curPriority = priority;
+ _curPriority = priority;
// Get sound data
if ((sound_p = _vm->_file->getSound(sound, &size)) == 0)
@@ -270,63 +270,60 @@ void SoundHandler::pcspkr_player() {
static const uint16 pcspkrFlats[8] = {1435, 1279, 2342, 2150, 1916, 1755, 1611}; // The flats, Ab to Bb
_vm->getTimerManager()->removeTimerProc(&loopPlayer);
- _vm->getTimerManager()->installTimerProc(&loopPlayer, 1000000 / 9, this);
-
- uint16 count; // Value to set timer chip to for note
- bool cmd_note;
+ _vm->getTimerManager()->installTimerProc(&loopPlayer, 1000000 / 9, this, "hugoSoundLoop");
if (!_vm->_config.soundFl || !_vm->_mixer->isReady())
return; // Poo! User doesn't want sound!
- if (!DOSSongPtr)
+ if (!_DOSSongPtr)
return;
- if (!*DOSSongPtr) // Song has finished
+ if (!*_DOSSongPtr) // Song has finished
return;
- if (!--pcspkrTimer) { // timer zero, stop note
+ if (!--_pcspkrTimer) { // timer zero, stop note
_speakerStream->stop();
return;
- } else if (pcspkrTimer >= 0) { // Note still going
+ } else if (_pcspkrTimer >= 0) { // Note still going
return;
}
// Time to play next note
+ bool cmdNote = true;
do {
- cmd_note = true;
- switch (*DOSSongPtr) {
+ switch (*_DOSSongPtr) {
case 'O': // Switch to new octave 1..7
- DOSSongPtr++;
- pcspkrOctave = *DOSSongPtr - '0';
- if ((pcspkrOctave < 0) || (pcspkrOctave > 7))
+ _DOSSongPtr++;
+ _pcspkrOctave = *_DOSSongPtr - '0';
+ if ((_pcspkrOctave < 0) || (_pcspkrOctave > 7))
error("pcspkr_player() - Bad octave");
- DOSSongPtr++;
+ _DOSSongPtr++;
break;
case 'L': // Switch to new duration (in ticks)
- DOSSongPtr++;
- pcspkrNoteDuration = *DOSSongPtr - '0';
- if (pcspkrNoteDuration < 0)
+ _DOSSongPtr++;
+ _pcspkrNoteDuration = *_DOSSongPtr - '0';
+ if (_pcspkrNoteDuration < 0)
error("pcspkr_player() - Bad duration");
- pcspkrNoteDuration--;
- DOSSongPtr++;
+ _pcspkrNoteDuration--;
+ _DOSSongPtr++;
break;
case '<':
case '^': // Move up an octave
- pcspkrOctave++;
- DOSSongPtr++;
+ _pcspkrOctave++;
+ _DOSSongPtr++;
break;
case '>':
case 'v': // Move down an octave
- pcspkrOctave--;
- DOSSongPtr++;
+ _pcspkrOctave--;
+ _DOSSongPtr++;
break;
default:
- cmd_note = false;
+ cmdNote = false;
break;
}
- } while (cmd_note);
+ } while (cmdNote);
- switch (*DOSSongPtr) {
+ switch (*_DOSSongPtr) {
case 'A': // The notes.
case 'B':
case 'C':
@@ -334,29 +331,30 @@ void SoundHandler::pcspkr_player() {
case 'E':
case 'F':
case 'G':
- count = pcspkrNotes[*DOSSongPtr - 'A'];
- switch (DOSSongPtr[1]) { // Check for sharp or flat (#, -)
+ uint16 count; // Value to set timer chip to for note
+ count = pcspkrNotes[*_DOSSongPtr - 'A'];
+ switch (_DOSSongPtr[1]) { // Check for sharp or flat (#, -)
case '#':
- count = pcspkrSharps[*DOSSongPtr++ - 'A'];
+ count = pcspkrSharps[*_DOSSongPtr++ - 'A'];
break;
case 'b':
- count = pcspkrFlats[*DOSSongPtr++ - 'A'];
+ count = pcspkrFlats[*_DOSSongPtr++ - 'A'];
break;
default:
break;
}
- if (pcspkrOctave > 3) // Adjust for octave
- count /= (1 << (pcspkrOctave - 3));
- else if (pcspkrOctave < 3)
- count *= (1 << (3 - pcspkrOctave));
- _speakerStream->play(Audio::PCSpeaker::kWaveFormSaw, kHugoCNT / count, (int32) ((1 + pcspkrNoteDuration) * _vm->_normalTPS) * 8);
- pcspkrTimer = pcspkrNoteDuration;
- DOSSongPtr++;
+ if (_pcspkrOctave > 3) // Adjust for octave
+ count /= (1 << (_pcspkrOctave - 3));
+ else if (_pcspkrOctave < 3)
+ count *= (1 << (3 - _pcspkrOctave));
+ _speakerStream->play(Audio::PCSpeaker::kWaveFormSaw, kHugoCNT / count, (int32) ((1 + _pcspkrNoteDuration) * _vm->_normalTPS) * 8);
+ _pcspkrTimer = _pcspkrNoteDuration;
+ _DOSSongPtr++;
break;
case '.': // A rest note
_speakerStream->stop();
- pcspkrTimer = pcspkrNoteDuration;
- DOSSongPtr++;
+ _pcspkrTimer = _pcspkrNoteDuration;
+ _DOSSongPtr++;
break;
default:
warning("pcspkr_player() - Unhandled note");
@@ -367,12 +365,12 @@ void SoundHandler::loadIntroSong(Common::ReadStream &in) {
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
uint16 numBuf = in.readUint16BE();
if (varnt == _vm->_gameVariant)
- DOSIntroSong = _vm->_text->getTextData(numBuf);
+ _DOSIntroSong = _vm->_text->getTextData(numBuf);
}
}
void SoundHandler::initPcspkrPlayer() {
- _vm->getTimerManager()->installTimerProc(&loopPlayer, 1000000 / 9, this);
+ _vm->getTimerManager()->installTimerProc(&loopPlayer, 1000000 / 9, this, "hugoSoundLoop");
}
} // End of namespace Hugo
diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h
index 33dba9f2a8..1e504fbdea 100644
--- a/engines/hugo/sound.h
+++ b/engines/hugo/sound.h
@@ -60,12 +60,12 @@ public:
static const int kHugoCNT = 1190000;
- int8 pcspkrTimer; // Timer (ticks) for note being played
- int8 pcspkrOctave; // Current octave 1..7
- int8 pcspkrNoteDuration; // Current length of note (ticks)
+ int8 _pcspkrTimer; // Timer (ticks) for note being played
+ int8 _pcspkrOctave; // Current octave 1..7
+ int8 _pcspkrNoteDuration; // Current length of note (ticks)
- const char *DOSSongPtr;
- const char *DOSIntroSong;
+ const char *_DOSSongPtr;
+ const char *_DOSIntroSong;
void toggleMusic();
void toggleSound();
@@ -80,7 +80,7 @@ public:
void loadIntroSong(Common::ReadStream &in);
void initPcspkrPlayer();
protected:
- byte curPriority; // Priority of currently playing sound
+ byte _curPriority; // Priority of currently playing sound
private:
HugoEngine *_vm;
diff --git a/engines/kyra/animator_hof.cpp b/engines/kyra/animator_hof.cpp
index 4cdb622501..741e358143 100644
--- a/engines/kyra/animator_hof.cpp
+++ b/engines/kyra/animator_hof.cpp
@@ -314,4 +314,3 @@ void KyraEngine_HoF::resetCharacterAnimDim() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/animator_lok.cpp b/engines/kyra/animator_lok.cpp
index 3e9dd7aa66..4126681bbe 100644
--- a/engines/kyra/animator_lok.cpp
+++ b/engines/kyra/animator_lok.cpp
@@ -649,4 +649,3 @@ void Animator_LoK::setCharactersHeight() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/animator_lok.h b/engines/kyra/animator_lok.h
index 21d24866c8..74b8305468 100644
--- a/engines/kyra/animator_lok.h
+++ b/engines/kyra/animator_lok.h
@@ -125,4 +125,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp
index 84bda3f3fd..6414b99ffd 100644
--- a/engines/kyra/animator_mr.cpp
+++ b/engines/kyra/animator_mr.cpp
@@ -459,4 +459,3 @@ void KyraEngine_MR::showIdleAnim() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/animator_v2.cpp b/engines/kyra/animator_v2.cpp
index ad7057f11a..334356e261 100644
--- a/engines/kyra/animator_v2.cpp
+++ b/engines/kyra/animator_v2.cpp
@@ -185,4 +185,3 @@ void KyraEngine_v2::deleteItemAnimEntry(int item) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index 4a48ac0674..dfc2a9f868 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -461,4 +461,3 @@ Debugger_LoL::Debugger_LoL(LoLEngine *vm) : Debugger(vm), _vm(vm) {
#endif // ENABLE_LOL
} // End of namespace Kyra
-
diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h
index 70c547381e..09ddd89a7a 100644
--- a/engines/kyra/debugger.h
+++ b/engines/kyra/debugger.h
@@ -106,4 +106,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index a6af584fb8..0a49483f12 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -221,4 +221,3 @@ SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int s
#else
REGISTER_PLUGIN_STATIC(KYRA, PLUGIN_TYPE_ENGINE, KyraMetaEngine);
#endif
-
diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
index 165eddf599..c224c8f46d 100644
--- a/engines/kyra/detection_tables.h
+++ b/engines/kyra/detection_tables.h
@@ -21,38 +21,41 @@
namespace {
-#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
-#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
-
-#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1)
-#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, Kyra::GI_KYRA1)
-
-#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2)
-#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2)
-
-#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3)
-#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3)
-#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3)
-
-#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL)
-#define LOL_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL)
-#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL)
-#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define FLAGS(x, y, z, a, b, c, d, e, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, id }
+#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, e, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, id }
+
+#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_KYRA1)
+#define KYRA1_OLDFLOPPY_FLAGS FLAGS(false, false, false, true, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, false, true, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, false, Kyra::GI_KYRA1)
+
+#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_KYRA2)
+#define KYRA2_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_KYRA2)
+
+#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, false, true, true, Kyra::GI_KYRA3)
+#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, false, true, false, Kyra::GI_KYRA3)
+#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, true, false, Kyra::GI_KYRA3)
+
+#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_LOL)
+#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, false, true, true, false, false, Kyra::GI_LOL)
+#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
const KYRAGameDescription adGameDescs[] = {
/* disable these targets until they get supported
@@ -95,18 +98,7 @@ const KYRAGameDescription adGameDescs[] = {
},
KYRA1_FLOPPY_FLAGS
},
- {
- {
- "kyra1",
- "Extracted",
- AD_ENTRY1("GEMCUT.EMC", "689b62b7519215c1b2571d466c95624c"),
- Common::RU_RUS,
- Common::kPlatformPC,
- ADGF_NO_FLAGS,
- Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
- },
- KYRA1_FLOPPY_FLAGS
- },
+
{
{
"kyra1",
@@ -155,6 +147,18 @@ const KYRAGameDescription adGameDescs[] = {
},
KYRA1_FLOPPY_FLAGS
},
+ {
+ {
+ "kyra1",
+ "Extracted",
+ AD_ENTRY1("GEMCUT.EMC", "689b62b7519215c1b2571d466c95624c"),
+ Common::RU_RUS,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK
+ },
+ KYRA1_OLDFLOPPY_FLAGS
+ },
{ // from VooD
{
"kyra1",
@@ -498,6 +502,32 @@ const KYRAGameDescription adGameDescs[] = {
KYRA2_FLOPPY_FLAGS
},
+ { // Floppy version extracted
+ {
+ "kyra2",
+ "Extracted",
+ AD_ENTRY1("CH01-S00.DLG", "54b7a5a94f6e1ec91f0fb1311eec09ab"),
+ Common::RU_RUS,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_FLOPPY_FAN_FLAGS(Common::RU_RUS, Common::EN_ANY)
+ },
+
+ { // Floppy version extracted
+ {
+ "kyra2",
+ "Extracted",
+ AD_ENTRY1("CH01-S00.DLG", "7c36c0e63ab8c81cbb3ea58681331366"),
+ Common::RU_RUS,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ KYRA2_FLOPPY_FAN_FLAGS(Common::RU_RUS, Common::EN_ANY)
+ },
+
{ // CD version
{
"kyra2",
@@ -989,12 +1019,11 @@ const KYRAGameDescription adGameDescs[] = {
"lol",
"CD",
{
- { "GENERAL.PAK", 0, "19354b0f464295c38c801d30588df062", -1 },
- { "L01.PAK", 0, "174d37f21e0336c5d91020f8c58717ef", -1 },
- { "VOC.PAK", 0, "eb398f09ba3321d872b6174a68a987d9", -1 },
+ { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 },
+ { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
{ 0, 0, 0, 0 }
},
- Common::RU_RUS,
+ Common::DE_DEU,
Common::kPlatformPC,
ADGF_DROPLANGUAGE | ADGF_CD,
Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
@@ -1011,7 +1040,7 @@ const KYRAGameDescription adGameDescs[] = {
{ "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
{ 0, 0, 0, 0 }
},
- Common::DE_DEU,
+ Common::FR_FRA,
Common::kPlatformPC,
ADGF_DROPLANGUAGE | ADGF_CD,
Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
@@ -1024,11 +1053,11 @@ const KYRAGameDescription adGameDescs[] = {
"lol",
"CD",
{
- { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 },
+ { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 },
{ "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
{ 0, 0, 0, 0 }
},
- Common::FR_FRA,
+ Common::EN_ANY,
Common::kPlatformPC,
ADGF_DROPLANGUAGE | ADGF_CD,
Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
@@ -1045,7 +1074,7 @@ const KYRAGameDescription adGameDescs[] = {
{ "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
{ 0, 0, 0, 0 }
},
- Common::EN_ANY,
+ Common::DE_DEU,
Common::kPlatformPC,
ADGF_DROPLANGUAGE | ADGF_CD,
Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
@@ -1062,7 +1091,7 @@ const KYRAGameDescription adGameDescs[] = {
{ "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
{ 0, 0, 0, 0 }
},
- Common::DE_DEU,
+ Common::FR_FRA,
Common::kPlatformPC,
ADGF_DROPLANGUAGE | ADGF_CD,
Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
@@ -1070,13 +1099,32 @@ const KYRAGameDescription adGameDescs[] = {
LOL_CD_FLAGS
},
+ // Russian fan translation
{
{
"lol",
"CD",
{
- { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 },
- { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 },
+ { "GENERAL.PAK", 0, "19354b0f464295c38c801d30588df062", -1 },
+ { "L01.PAK", 0, "174d37f21e0336c5d91020f8c58717ef", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_CD_FAN_FLAGS(Common::RU_RUS, Common::DE_DEU)
+ },
+
+ {
+ {
+ "lol",
+ "CD",
+ {
+
+ { "GENERAL.PAK", 0, "19354b0f464295c38c801d30588df062", -1 },
+ { "L01.PAK", 0, "174d37f21e0336c5d91020f8c58717ef", -1 },
{ 0, 0, 0, 0 }
},
Common::FR_FRA,
@@ -1084,7 +1132,24 @@ const KYRAGameDescription adGameDescs[] = {
ADGF_DROPLANGUAGE | ADGF_CD,
Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
},
- LOL_CD_FLAGS
+ LOL_CD_FAN_FLAGS(Common::RU_RUS, Common::DE_DEU)
+ },
+
+ {
+ {
+ "lol",
+ "CD",
+ {
+ { "GENERAL.PAK", 0, "19354b0f464295c38c801d30588df062", -1 },
+ { "L01.PAK", 0, "174d37f21e0336c5d91020f8c58717ef", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::RU_RUS,
+ Common::kPlatformPC,
+ ADGF_DROPLANGUAGE | ADGF_CD,
+ Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_CD_FAN_FLAGS(Common::RU_RUS, Common::DE_DEU)
},
// Italian fan translation
@@ -1306,6 +1371,24 @@ const KYRAGameDescription adGameDescs[] = {
LOL_FLOPPY_FLAGS
},
+ // Russian fan translation
+ {
+ {
+ "lol",
+ "Extracted",
+ {
+ { "GENERAL.PAK", 0, "d8f4c1153aed2418f41f886c3fb27543", -1 },
+ { "CHAPTER7.PAK", 0, "f0b8a2fdff951738834fadc12248ac1f", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::RU_RUS,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK
+ },
+ LOL_FLOPPY_FAN_FLAGS(Common::RU_RUS, Common::EN_ANY)
+ },
+
{
{
"lol",
@@ -1356,7 +1439,7 @@ const KYRAGameDescription adGameDescs[] = {
LOL_KYRA2_DEMO_FLAGS
},
#endif // ENABLE_LOL
- { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) }
+ { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0) }
};
const PlainGameDescriptor gameList[] = {
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp
index 29cbe20b23..7fd9880dce 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui.cpp
@@ -415,7 +415,7 @@ void GUI::checkTextfieldInput() {
bool running = true;
int keys = 0;
- while (_vm->_eventMan->pollEvent(event) && running) {
+ while (running && _vm->_eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
if (event.kbd.keycode == Common::KEYCODE_q && event.kbd.hasFlags(Common::KBD_CTRL))
@@ -671,4 +671,3 @@ void MainMenu::printString(const char *format, int x, int y, int col1, int col2,
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h
index 6afdc431ed..1efbdde394 100644
--- a/engines/kyra/gui.h
+++ b/engines/kyra/gui.h
@@ -263,4 +263,3 @@ private:
} // end of namesapce Kyra
#endif
-
diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp
index 1666cdd0e4..a1e0ce66bf 100644
--- a/engines/kyra/gui_hof.cpp
+++ b/engines/kyra/gui_hof.cpp
@@ -1195,4 +1195,3 @@ int GUI_HoF::loadMenu(Button *caller) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/gui_hof.h b/engines/kyra/gui_hof.h
index a02d14e9f1..c228c35551 100644
--- a/engines/kyra/gui_hof.h
+++ b/engines/kyra/gui_hof.h
@@ -82,4 +82,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp
index eba2f8f279..4a2d51faa3 100644
--- a/engines/kyra/gui_lok.cpp
+++ b/engines/kyra/gui_lok.cpp
@@ -1137,4 +1137,3 @@ void KyraEngine_LoK::drawAmulet() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h
index 4d7bfa1ada..5a8d6ab532 100644
--- a/engines/kyra/gui_lok.h
+++ b/engines/kyra/gui_lok.h
@@ -182,4 +182,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index c64d3e7723..3ab52b9940 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -395,8 +395,8 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
} else {
gui_drawLiveMagicBar(33, 32, _characters[charNum].magicPointsCur, 0, _characters[charNum].magicPointsMax, 5, 32, 162, 1, 0);
gui_drawLiveMagicBar(39, 32, _characters[charNum].hitPointsCur, 0, _characters[charNum].hitPointsMax, 5, 32, 154, 1, 1);
- _screen->printText(getLangString(0x4253), 33, 1, 160, 0);
- _screen->printText(getLangString(0x4254), 39, 1, 152, 0);
+ _screen->printText((_flags.platform == Common::kPlatformPC && !_flags.isTalkie) ? "M" : getLangString(0x4253), 33, 1, 160, 0);
+ _screen->printText((_flags.platform == Common::kPlatformPC && !_flags.isTalkie) ? "H" : getLangString(0x4254), 39, 1, 152, 0);
}
int spellLevels = 0;
@@ -3007,4 +3007,3 @@ const char *GUI_LoL::getMenuItemLabel(const MenuItem &menuItem) {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/gui_lol.h b/engines/kyra/gui_lol.h
index bc49b21299..0686926534 100644
--- a/engines/kyra/gui_lol.h
+++ b/engines/kyra/gui_lol.h
@@ -182,4 +182,3 @@ private:
#endif
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp
index 32eb02e06d..82082961e9 100644
--- a/engines/kyra/gui_mr.cpp
+++ b/engines/kyra/gui_mr.cpp
@@ -1607,4 +1607,3 @@ void GUI_MR::drawSliderBar(int slider, const uint8 *shape) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/gui_mr.h b/engines/kyra/gui_mr.h
index 9c8d79b321..6303dff83f 100644
--- a/engines/kyra/gui_mr.h
+++ b/engines/kyra/gui_mr.h
@@ -85,4 +85,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp
index dcc53b7c9e..c0477f29f1 100644
--- a/engines/kyra/gui_v2.cpp
+++ b/engines/kyra/gui_v2.cpp
@@ -887,4 +887,3 @@ int GUI_v2::choiceNo(Button *caller) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/gui_v2.h b/engines/kyra/gui_v2.h
index 0009bf8e54..ef95c0301a 100644
--- a/engines/kyra/gui_v2.h
+++ b/engines/kyra/gui_v2.h
@@ -231,4 +231,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/item.h b/engines/kyra/item.h
index 86b6fc7d46..4b236372a2 100644
--- a/engines/kyra/item.h
+++ b/engines/kyra/item.h
@@ -39,4 +39,3 @@ enum {
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/items_hof.cpp b/engines/kyra/items_hof.cpp
index 73aed2e067..711e1b8f7c 100644
--- a/engines/kyra/items_hof.cpp
+++ b/engines/kyra/items_hof.cpp
@@ -427,4 +427,3 @@ void KyraEngine_HoF::setMouseCursor(Item item) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/items_lok.cpp b/engines/kyra/items_lok.cpp
index d66eb553f2..d598a17cf1 100644
--- a/engines/kyra/items_lok.cpp
+++ b/engines/kyra/items_lok.cpp
@@ -575,7 +575,14 @@ void KyraEngine_LoK::dropItem(int unk1, int item, int x, int y, int unk2) {
if (processItemDrop(_currentCharacter->sceneId, item, x, y, unk1, unk2))
return;
snd_playSoundEffect(54);
+
+ // Old floppy versions don't print warning messages and don't have the necessary string resources.
+ // These versions will only play the warning sound effect.
+ if (_flags.isOldFloppy && !_noDropList)
+ return;
+
assert(_noDropList);
+
if (12 == countItemsInScene(_currentCharacter->sceneId))
drawSentenceCommand(_noDropList[0], 6);
else
@@ -969,4 +976,3 @@ int KyraEngine_LoK::getItemListIndex(Item item) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index 2cf2cb2c70..7e9ae439fc 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -551,4 +551,3 @@ int LoLEngine::checkSceneForItems(uint16 *blockDrawObjects, int color) {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/items_mr.cpp b/engines/kyra/items_mr.cpp
index 88c02f56c8..c731627026 100644
--- a/engines/kyra/items_mr.cpp
+++ b/engines/kyra/items_mr.cpp
@@ -544,4 +544,3 @@ int KyraEngine_MR::getItemCommandStringInv(uint16 item) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/items_v2.cpp b/engines/kyra/items_v2.cpp
index 29dddc6772..c191c2e62b 100644
--- a/engines/kyra/items_v2.cpp
+++ b/engines/kyra/items_v2.cpp
@@ -105,4 +105,3 @@ void KyraEngine_v2::removeHandItem() {
}
} // end of namesapce Kyra
-
diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp
index 5c58e6e3ed..b82099f058 100644
--- a/engines/kyra/kyra_hof.cpp
+++ b/engines/kyra/kyra_hof.cpp
@@ -1052,8 +1052,7 @@ void KyraEngine_HoF::runStartScript(int script, int unk1) {
void KyraEngine_HoF::loadNPCScript() {
_emc->unload(&_npcScriptData);
- char filename[12];
- strcpy(filename, "_NPC.EMC");
+ char filename[] = "_NPC.EMC";
if (_flags.platform != Common::kPlatformPC || _flags.isTalkie) {
switch (_lang) {
@@ -1084,7 +1083,7 @@ void KyraEngine_HoF::loadNPCScript() {
#pragma mark -
void KyraEngine_HoF::resetScaleTable() {
- Common::set_to(_scaleTable, _scaleTable + ARRAYSIZE(_scaleTable), 0x100);
+ Common::set_to(_scaleTable, ARRAYEND(_scaleTable), 0x100);
}
void KyraEngine_HoF::setScaleTableItem(int item, int data) {
@@ -1674,7 +1673,7 @@ void KyraEngine_HoF::setCauldronState(uint8 state, bool paletteFade) {
}
void KyraEngine_HoF::clearCauldronTable() {
- Common::set_to(_cauldronTable, _cauldronTable+ARRAYSIZE(_cauldronTable), -1);
+ Common::set_to(_cauldronTable, ARRAYEND(_cauldronTable), -1);
}
void KyraEngine_HoF::addFrontCauldronTable(int item) {
@@ -1998,4 +1997,3 @@ void KyraEngine_HoF::readSettings() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h
index da7486bc29..2561171598 100644
--- a/engines/kyra/kyra_hof.h
+++ b/engines/kyra/kyra_hof.h
@@ -925,4 +925,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp
index 7f356f34c1..27d0849e5f 100644
--- a/engines/kyra/kyra_lok.cpp
+++ b/engines/kyra/kyra_lok.cpp
@@ -98,6 +98,8 @@ KyraEngine_LoK::KyraEngine_LoK(OSystem *system, const GameFlags &flags)
_malcolmFrame = 0;
_malcolmTimer1 = _malcolmTimer2 = 0;
+
+ _soundFiles = 0;
}
KyraEngine_LoK::~KyraEngine_LoK() {
@@ -121,6 +123,8 @@ KyraEngine_LoK::~KyraEngine_LoK() {
delete _animator;
delete _seq;
+ delete[] _soundFiles;
+
delete[] _characterList;
delete[] _roomTable;
diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h
index 066c27c69a..57e6bd39ab 100644
--- a/engines/kyra/kyra_lok.h
+++ b/engines/kyra/kyra_lok.h
@@ -826,4 +826,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index f5bcd04ea0..5798e99a1f 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -1426,4 +1426,3 @@ void KyraEngine_MR::readSettings() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h
index b762648d29..ec76340638 100644
--- a/engines/kyra/kyra_mr.h
+++ b/engines/kyra/kyra_mr.h
@@ -668,4 +668,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index 3b2c9b67eb..c950612a42 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -650,4 +650,3 @@ void KyraEngine_v1::syncSoundSettings() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index 83455f3922..584176e08c 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -109,6 +109,7 @@ struct GameFlags {
bool isDemo : 1;
bool useAltShapeHeader : 1; // alternative shape header (uses 2 bytes more, those are unused though)
bool isTalkie : 1;
+ bool isOldFloppy : 1;
bool useHiResOverlay : 1;
bool use16ColorMode : 1;
bool useDigSound : 1;
@@ -422,4 +423,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index d0f8d78bd1..e8cb9b4370 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -243,4 +243,3 @@ int KyraEngine_v2::updateCharPos(int *table, int force) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index f21458ab5d..56391d151a 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -398,4 +398,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 2cca4fd4e3..5aba264ceb 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -1038,11 +1038,14 @@ char *LoLEngine::getLangString(uint16 id) {
char *string = (char *)getTableEntry(buffer, realId);
char *srcBuffer = _stringBuffer[_lastUsedStringBuffer];
- if (_flags.lang != Common::JA_JPN) {
- Util::decodeString1(string, srcBuffer);
+ if (_flags.lang == Common::JA_JPN) {
+ decodeSjis(string, srcBuffer);
+ } else if (_flags.lang == Common::RU_RUS && !_flags.isTalkie) {
+ decodeCyrillic(string, srcBuffer);
Util::decodeString2(srcBuffer, srcBuffer);
} else {
- decodeSjis(string, srcBuffer);
+ Util::decodeString1(string, srcBuffer);
+ Util::decodeString2(srcBuffer, srcBuffer);
}
++_lastUsedStringBuffer;
@@ -1081,6 +1084,54 @@ void LoLEngine::decodeSjis(const char *src, char *dst) {
*dst = 0;
}
+int LoLEngine::decodeCyrillic(const char *src, char *dst) {
+ static const uint8 decodeTable1[] = {
+ 0x20, 0xAE, 0xA5, 0xA0, 0xE2, 0xAD, 0xA8, 0xE0, 0xE1, 0xAB, 0xA2,
+ 0xA4, 0xAC, 0xAA, 0xE3, 0x2E
+ };
+
+ static const uint8 decodeTable2[] = {
+ 0xAD, 0xAF, 0xA2, 0xE1, 0xAC, 0xAA, 0x20, 0xA4, 0xAB, 0x20,
+ 0xE0, 0xE2, 0xA4, 0xA2, 0xA6, 0xAA, 0x20, 0xAD, 0xE2, 0xE0,
+ 0xAB, 0xAC, 0xE1, 0xA1, 0x20, 0xAC, 0xE1, 0xAA, 0xAB, 0xE0,
+ 0xE2, 0xAD, 0xAE, 0xEC, 0xA8, 0xA5, 0xA0, 0x20, 0xE0, 0xEB,
+ 0xAE, 0xA0, 0xA8, 0xA5, 0xEB, 0xEF, 0x20, 0xE3, 0xE2, 0x20,
+ 0xAD, 0xE7, 0xAB, 0xAC, 0xA5, 0xE0, 0xAE, 0xA0, 0xA5, 0xA8,
+ 0xE3, 0xEB, 0xEF, 0xAA, 0xE2, 0xEF, 0xA5, 0xEC, 0xAB, 0xAE,
+ 0xAA, 0xAF, 0xA8, 0xA0, 0xA5, 0xEF, 0xAE, 0xEE, 0xEC, 0xE3,
+ 0xA0, 0xAE, 0xA5, 0xA8, 0xEB, 0x20, 0xE0, 0xE3, 0xA0, 0xA5,
+ 0xAE, 0xA8, 0xE3, 0xE1, 0xAD, 0xAB, 0x20, 0xAE, 0xA5, 0xA0,
+ 0xA8, 0xAD, 0x2E, 0xE3, 0xAE, 0xA0, 0xA8, 0x20, 0xE0, 0xE3,
+ 0xAB, 0xE1, 0x20, 0xA4, 0xAD, 0xE2, 0xA1, 0xA6, 0xAC, 0xE1,
+ 0x0D, 0x20, 0x2E, 0x09, 0xA0, 0xA1, 0x9D, 0xA5
+ };
+
+ int size = 0;
+ uint cChar = 0;
+ while ((cChar = *src++) != 0) {
+ if (cChar & 0x80) {
+ cChar &= 0x7F;
+ int index = (cChar & 0x78) >> 3;
+ *dst++ = decodeTable1[index];
+ ++size;
+ assert(cChar < sizeof(decodeTable2));
+ cChar = decodeTable2[cChar];
+ } else if (cChar >= 0x70) {
+ cChar = *src++;
+ } else if (cChar >= 0x30) {
+ if (cChar < 0x60)
+ cChar -= 0x30;
+ cChar |= 0x80;
+ }
+
+ *dst++ = cChar;
+ ++size;
+ }
+
+ *dst++ = 0;
+ return size;
+}
+
bool LoLEngine::addCharacter(int id) {
const uint16 *cdf[] = { _charDefsMan, _charDefsMan, _charDefsMan, _charDefsWoman,
_charDefsMan, _charDefsMan, _charDefsWoman, _charDefsKieran, _charDefsAkshel };
@@ -4547,4 +4598,3 @@ void LoLEngine::generateTempData() {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index 06a4f29f63..164f030a1d 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -363,12 +363,13 @@ private:
void showIntro();
struct CharacterPrev {
- const char *name;
int x, y;
int attrib[3];
};
static const CharacterPrev _charPreviews[];
+ static const char *const _charPreviewNamesDefault[];
+ static const char *const _charPreviewNamesRussianFloppy[];
// PC98 specific data
static const uint16 _charPosXPC98[];
@@ -875,6 +876,7 @@ private:
char *getLangString(uint16 id);
uint8 *getTableEntry(uint8 *buffer, uint16 id);
void decodeSjis(const char *src, char *dst);
+ int decodeCyrillic(const char *src, char *dst);
static const char * const _languageExt[];
@@ -1525,4 +1527,3 @@ private:
#endif
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index bc9c93f8ca..a35ec3d81b 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -366,6 +366,3 @@ void Resource::initializeLoaders() {
}
} // End of namespace Kyra
-
-
-
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 1c69362bfd..c2a697f18d 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -202,6 +202,7 @@ enum KyraResources {
k1ConfigStrings,
k1AudioTracks,
+ k1AudioTracks2,
k1AudioTracksIntro,
k1CreditsStrings,
@@ -479,7 +480,3 @@ private:
} // End of namespace Kyra
#endif
-
-
-
-
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index 80182d949b..42c5d3e8a8 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -113,12 +113,7 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
if (header.version >= 14) {
if (loadThumbnail) {
- header.thumbnail = new Graphics::Surface();
- assert(header.thumbnail);
- if (!Graphics::loadThumbnail(*in, *header.thumbnail)) {
- delete header.thumbnail;
- header.thumbnail = 0;
- }
+ header.thumbnail = Graphics::loadThumbnail(*in);
} else {
Graphics::skipThumbnail(*in);
}
@@ -268,4 +263,3 @@ void KyraEngine_v1::loadGameStateCheck(int slot) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/saveload_hof.cpp b/engines/kyra/saveload_hof.cpp
index 645bd2903f..1d28b6bc13 100644
--- a/engines/kyra/saveload_hof.cpp
+++ b/engines/kyra/saveload_hof.cpp
@@ -329,4 +329,3 @@ Common::Error KyraEngine_HoF::loadGameState(int slot) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp
index 34762d4c92..22d412e7f6 100644
--- a/engines/kyra/saveload_lok.cpp
+++ b/engines/kyra/saveload_lok.cpp
@@ -317,4 +317,3 @@ Common::Error KyraEngine_LoK::saveGameStateIntern(int slot, const char *saveName
return Common::kNoError;
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/saveload_lol.cpp b/engines/kyra/saveload_lol.cpp
index 07842ea358..1bf26477e6 100644
--- a/engines/kyra/saveload_lol.cpp
+++ b/engines/kyra/saveload_lol.cpp
@@ -472,4 +472,3 @@ Graphics::Surface *LoLEngine::generateSaveThumbnail() const {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/saveload_mr.cpp b/engines/kyra/saveload_mr.cpp
index 139375264f..c49a528d02 100644
--- a/engines/kyra/saveload_mr.cpp
+++ b/engines/kyra/saveload_mr.cpp
@@ -327,4 +327,3 @@ Common::Error KyraEngine_MR::loadGameState(int slot) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp
index 197ef38bf1..f6cd77ca89 100644
--- a/engines/kyra/scene_hof.cpp
+++ b/engines/kyra/scene_hof.cpp
@@ -95,7 +95,7 @@ void KyraEngine_HoF::enterNewScene(uint16 newScene, int facing, int unk1, int un
_emc->run(&_sceneScriptState);
}
- Common::for_each(_wsaSlots, _wsaSlots+ARRAYSIZE(_wsaSlots), Common::mem_fun(&WSAMovie_v2::close));
+ Common::for_each(_wsaSlots, ARRAYEND(_wsaSlots), Common::mem_fun(&WSAMovie_v2::close));
_specialExitCount = 0;
memset(_specialExitTable, -1, sizeof(_specialExitTable));
@@ -735,4 +735,3 @@ bool KyraEngine_HoF::lineIsPassable(int x, int y) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp
index 6cb3e2a98a..a926f8493f 100644
--- a/engines/kyra/scene_lok.cpp
+++ b/engines/kyra/scene_lok.cpp
@@ -1299,4 +1299,3 @@ void KyraEngine_LoK::setupSceneResource(int sceneId) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index 165919dff2..a5a2562448 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -2192,4 +2192,3 @@ void LoLEngine::drawSpecialGuiShape(int pageNum) {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp
index 6b234d9a73..74d2e89e6e 100644
--- a/engines/kyra/scene_mr.cpp
+++ b/engines/kyra/scene_mr.cpp
@@ -83,7 +83,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2
}
_specialExitCount = 0;
- Common::set_to(_specialExitTable, _specialExitTable+ARRAYSIZE(_specialExitTable), 0xFFFF);
+ Common::set_to(_specialExitTable, ARRAYEND(_specialExitTable), 0xFFFF);
_mainCharacter.sceneId = sceneId;
_sceneList[sceneId].flags &= ~1;
@@ -388,7 +388,7 @@ void KyraEngine_MR::initSceneScript(int unk1) {
strcat(filename, ".CPS");
_screen->loadBitmap(filename, 3, 3, 0);
- Common::set_to(_specialSceneScriptState, _specialSceneScriptState+ARRAYSIZE(_specialSceneScriptState), false);
+ Common::set_to(_specialSceneScriptState, ARRAYEND(_specialSceneScriptState), false);
_sceneEnterX1 = 160;
_sceneEnterY1 = 0;
_sceneEnterX2 = 296;
diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp
index fbddb6604e..061ce4c21a 100644
--- a/engines/kyra/scene_v2.cpp
+++ b/engines/kyra/scene_v2.cpp
@@ -225,4 +225,3 @@ void KyraEngine_v2::pathfinderFinializePath(int *moveTable, int tableLen, int x,
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 8f008a58b6..4eae89e0d4 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -3459,4 +3459,3 @@ uint8 *Palette::fetchRealPalette() const {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index e23f104760..51a9a7f744 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -616,4 +616,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/screen_hof.cpp b/engines/kyra/screen_hof.cpp
index 1282447411..24e0751c0e 100644
--- a/engines/kyra/screen_hof.cpp
+++ b/engines/kyra/screen_hof.cpp
@@ -146,4 +146,3 @@ void Screen_HoF::copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/screen_hof.h b/engines/kyra/screen_hof.h
index 08a9133809..edcb339da9 100644
--- a/engines/kyra/screen_hof.h
+++ b/engines/kyra/screen_hof.h
@@ -53,4 +53,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index c6874ca0ed..6d0460e0a1 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -959,4 +959,3 @@ void Screen_LoL::postProcessCursor(uint8 *data, int w, int h, int pitch) {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index 926183225f..02b78606b9 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -119,4 +119,3 @@ private:
#endif
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp
index 64fbe2b834..57581fa750 100644
--- a/engines/kyra/screen_v2.cpp
+++ b/engines/kyra/screen_v2.cpp
@@ -388,4 +388,3 @@ void Screen_v2::checkedPageUpdate(int srcPage, int dstPage) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h
index eb8415be78..d85c762038 100644
--- a/engines/kyra/screen_v2.h
+++ b/engines/kyra/screen_v2.h
@@ -73,4 +73,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index b185b8ed6f..303cbb45aa 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -443,4 +443,3 @@ void EMCInterpreter::op_setRetAndJmp(EMCState *script) {
}
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index 4250732c7c..5bd75f7b80 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -140,4 +140,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp
index 27cfc808cc..296cd4002b 100644
--- a/engines/kyra/script_hof.cpp
+++ b/engines/kyra/script_hof.cpp
@@ -1730,4 +1730,3 @@ void KyraEngine_HoF::setupOpcodeTable() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp
index 2b90d001ca..4d40971124 100644
--- a/engines/kyra/script_lok.cpp
+++ b/engines/kyra/script_lok.cpp
@@ -558,7 +558,10 @@ int KyraEngine_LoK::o1_setCustomPaletteRange(EMCState *script) {
_screen->copyPalette(0, 12);
}
} else {
- _screen->getPalette(1).copy(_specialPalettes[stackPos(0)], 0, stackPos(2), stackPos(1));
+ if (!_specialPalettes[stackPos(0)])
+ warning("KyraEngine_LoK::o1_setCustomPaletteRange(): Trying to use missing special palette %d", stackPos(0));
+ else
+ _screen->getPalette(1).copy(_specialPalettes[stackPos(0)], 0, stackPos(2), stackPos(1));
}
return 0;
}
@@ -1956,4 +1959,3 @@ void KyraEngine_LoK::setupOpcodeTable() {
#undef Opcode
} // End of namespace Kyra
-
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index 1afefcffa4..b4b8f00022 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -3071,4 +3071,3 @@ void LoLEngine::setupOpcodeTable() {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 6f0f0ab083..83d03d1f63 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -1246,4 +1246,3 @@ int TIMInterpreter_LoL::cmd_dialogueBox(const uint16 *param) {
#endif // ENABLE_LOL
} // End of namespace Kyra
-
diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h
index 89040720c2..11b716c3a9 100644
--- a/engines/kyra/script_tim.h
+++ b/engines/kyra/script_tim.h
@@ -317,4 +317,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp
index b12a08a417..4cfbdf8ab8 100644
--- a/engines/kyra/script_v1.cpp
+++ b/engines/kyra/script_v1.cpp
@@ -123,4 +123,3 @@ int KyraEngine_v1::o1_playSoundEffect(EMCState *script) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp
index 2e3a3d2bc4..e42cdf9ff4 100644
--- a/engines/kyra/script_v2.cpp
+++ b/engines/kyra/script_v2.cpp
@@ -340,4 +340,3 @@ int KyraEngine_v2::o2a_setResetFrame(EMCState *script) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp
index ce2eafcea5..531d864293 100644
--- a/engines/kyra/seqplayer.cpp
+++ b/engines/kyra/seqplayer.cpp
@@ -657,4 +657,3 @@ bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) {
} // End of namespace Kyra
-
diff --git a/engines/kyra/seqplayer.h b/engines/kyra/seqplayer.h
index 1f030cde19..12d94e3f6d 100644
--- a/engines/kyra/seqplayer.h
+++ b/engines/kyra/seqplayer.h
@@ -122,4 +122,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp
index e504278047..50b5db78fc 100644
--- a/engines/kyra/sequences_hof.cpp
+++ b/engines/kyra/sequences_hof.cpp
@@ -2920,5 +2920,3 @@ void KyraEngine_HoF::seq_makeBookAppear() {
}
} // End of namespace Kyra
-
-
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index 5f9bd86724..2de0565a74 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -250,7 +250,7 @@ bool KyraEngine_LoK::seq_introStory() {
if (!textEnabled() && speechEnabled() && _flags.lang != Common::IT_ITA)
return false;
- if ((_flags.lang == Common::EN_ANY && !_flags.isTalkie && _flags.platform == Common::kPlatformPC) || _flags.platform == Common::kPlatformAmiga)
+ if (((_flags.lang == Common::EN_ANY || _flags.lang == Common::RU_RUS) && !_flags.isTalkie && _flags.platform == Common::kPlatformPC) || _flags.platform == Common::kPlatformAmiga)
_screen->loadBitmap("TEXT.CPS", 3, 3, &_screen->getPalette(0));
else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN)
_screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0));
@@ -2112,4 +2112,3 @@ void KyraEngine_LoK::drawJewelsFadeOutEnd(int jewel) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp
index 27f3951faf..83d525d400 100644
--- a/engines/kyra/sequences_lol.cpp
+++ b/engines/kyra/sequences_lol.cpp
@@ -316,8 +316,9 @@ int LoLEngine::chooseCharacter() {
_screen->printText(_tim->getCTableEntry(53), 72, 184, 0x81, 0x00);
_screen->printText(_tim->getCTableEntry(55), 72, 192, 0x81, 0x00);
} else {
+ const char *const *previewNames = (_flags.lang == Common::RU_RUS && !_flags.isTalkie) ? _charPreviewNamesRussianFloppy : _charPreviewNamesDefault;
for (int i = 0; i < 4; ++i) {
- _screen->fprintStringIntro("%s", _charPreviews[i].x + 16, _charPreviews[i].y + 36, 0xC0, 0x00, 0x9C, 0x120, _charPreviews[i].name);
+ _screen->fprintStringIntro("%s", _charPreviews[i].x + 16, _charPreviews[i].y + 36, 0xC0, 0x00, 0x9C, 0x120, previewNames[i]);
_screen->fprintStringIntro("%d", _charPreviews[i].x + 21, _charPreviews[i].y + 48, 0x98, 0x00, 0x9C, 0x220, _charPreviews[i].attrib[0]);
_screen->fprintStringIntro("%d", _charPreviews[i].x + 21, _charPreviews[i].y + 56, 0x98, 0x00, 0x9C, 0x220, _charPreviews[i].attrib[1]);
_screen->fprintStringIntro("%d", _charPreviews[i].x + 21, _charPreviews[i].y + 64, 0x98, 0x00, 0x9C, 0x220, _charPreviews[i].attrib[2]);
@@ -1518,4 +1519,3 @@ void LoLEngine::loadOutroShapes(int file, uint8 **storage) {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/sequences_mr.cpp b/engines/kyra/sequences_mr.cpp
index b3adc687c2..d546d9c25b 100644
--- a/engines/kyra/sequences_mr.cpp
+++ b/engines/kyra/sequences_mr.cpp
@@ -235,4 +235,3 @@ void KyraEngine_MR::uninitAnimationShapes(int count, uint8 *filedata) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/sequences_v2.cpp b/engines/kyra/sequences_v2.cpp
index fb61d7cddf..e431e45f10 100644
--- a/engines/kyra/sequences_v2.cpp
+++ b/engines/kyra/sequences_v2.cpp
@@ -128,4 +128,3 @@ void KyraEngine_v2::processAnimationScript(int allowSkip, int resetChar) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index 4da35cc28b..b4fcea784e 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -276,5 +276,3 @@ const Sound::SpeechCodecs Sound::_supportedCodecs[] = {
};
} // End of namespace Kyra
-
-
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index 75041b8161..12c980486c 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -2445,4 +2445,3 @@ void SoundAdLibPC::unk2() {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/sound_adlib.h b/engines/kyra/sound_adlib.h
index 58b97e3474..962df40de8 100644
--- a/engines/kyra/sound_adlib.h
+++ b/engines/kyra/sound_adlib.h
@@ -108,4 +108,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/sound_amiga.cpp b/engines/kyra/sound_amiga.cpp
index dc09670408..dfb0aa8bf3 100644
--- a/engines/kyra/sound_amiga.cpp
+++ b/engines/kyra/sound_amiga.cpp
@@ -214,4 +214,3 @@ void SoundAmiga::playSoundEffect(uint8 track) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp
index 3f8eddbb0d..fe0f1fb9bc 100644
--- a/engines/kyra/sound_digital.cpp
+++ b/engines/kyra/sound_digital.cpp
@@ -544,4 +544,3 @@ const SoundDigital::AudioCodecs SoundDigital::_supportedCodecs[] = {
} // End of namespace Kyra
-
diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp
index 7262635728..efa844968d 100644
--- a/engines/kyra/sound_lol.cpp
+++ b/engines/kyra/sound_lol.cpp
@@ -312,4 +312,3 @@ int LoLEngine::convertVolumeFromMixer(int value) {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp
index 26b6b31d0a..1a5c2f94ac 100644
--- a/engines/kyra/sound_midi.cpp
+++ b/engines/kyra/sound_midi.cpp
@@ -787,4 +787,3 @@ Common::String SoundMidiPC::getFileName(const Common::String &str) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/sound_pcspk.cpp b/engines/kyra/sound_pcspk.cpp
index 051f36dd1b..8664e2a22e 100644
--- a/engines/kyra/sound_pcspk.cpp
+++ b/engines/kyra/sound_pcspk.cpp
@@ -364,4 +364,3 @@ const uint8 MidiDriver_PCSpeaker::_noteTable2[] = {
};
} // End of namespace Kyra
-
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index 012f1f5d7d..c851842f22 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -673,4 +673,3 @@ void SoundTownsPC98_v2::updateVolumeSettings() {
} // End of namespace Kyra
#undef EUPHONY_FADEOUT_TICKS
-
diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp
index e0d1142905..f4cebf6470 100644
--- a/engines/kyra/sprites.cpp
+++ b/engines/kyra/sprites.cpp
@@ -573,4 +573,3 @@ int Sprites::getDrawLayer(int y) {
return returnValue;
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/sprites.h b/engines/kyra/sprites.h
index 6a4241f13e..93cdcdbbcb 100644
--- a/engines/kyra/sprites.h
+++ b/engines/kyra/sprites.h
@@ -97,4 +97,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp
index a77fda043c..fbf4c7c5c2 100644
--- a/engines/kyra/sprites_lol.cpp
+++ b/engines/kyra/sprites_lol.cpp
@@ -1632,4 +1632,3 @@ void LoLEngine::killMonster(MonsterInPlay *monster) {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index d56abc5d47..f6d59922b1 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -38,7 +38,7 @@
namespace Kyra {
-#define RESFILE_VERSION 74
+#define RESFILE_VERSION 78
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -80,7 +80,7 @@ const IndexTable iGameTable[] = {
};
byte getGameID(const GameFlags &flags) {
- return Common::find(iGameTable, iGameTable + ARRAYSIZE(iGameTable) - 1, flags.gameID)->value;
+ return Common::find(iGameTable, ARRAYEND(iGameTable) - 1, flags.gameID)->value;
}
const IndexTable iLanguageTable[] = {
@@ -90,11 +90,12 @@ const IndexTable iLanguageTable[] = {
{ Common::ES_ESP, 4 },
{ Common::IT_ITA, 5 },
{ Common::JA_JPN, 6 },
+ { Common::RU_RUS, 7 },
{ -1, -1 }
};
byte getLanguageID(const GameFlags &flags) {
- return Common::find(iLanguageTable, iLanguageTable + ARRAYSIZE(iLanguageTable) - 1, flags.lang)->value;
+ return Common::find(iLanguageTable, ARRAYEND(iLanguageTable) - 1, flags.lang)->value;
}
const IndexTable iPlatformTable[] = {
@@ -107,11 +108,13 @@ const IndexTable iPlatformTable[] = {
};
byte getPlatformID(const GameFlags &flags) {
- return Common::find(iPlatformTable, iPlatformTable + ARRAYSIZE(iPlatformTable) - 1, flags.platform)->value;
+ return Common::find(iPlatformTable, ARRAYEND(iPlatformTable) - 1, flags.platform)->value;
}
byte getSpecialID(const GameFlags &flags) {
- if (flags.isDemo && flags.isTalkie)
+ if (flags.isOldFloppy)
+ return 4;
+ else if (flags.isDemo && flags.isTalkie)
return 3;
else if (flags.isDemo)
return 2;
@@ -748,7 +751,17 @@ void KyraEngine_LoK::initStaticResource() {
_storyStrings = _staticres->loadStrings(k1PC98StoryStrings, _storyStringsSize);
- _soundFiles = _staticres->loadStrings(k1AudioTracks, _soundFilesSize);
+ int size1, size2;
+ const char *const *soundfiles1 = _staticres->loadStrings(k1AudioTracks, size1);
+ const char *const *soundfiles2 = _staticres->loadStrings(k1AudioTracks2, size2);
+ _soundFilesSize = size1 + size2;
+ if (_soundFilesSize) {
+ delete[] _soundFiles;
+ const char **soundfiles = new const char*[_soundFilesSize];
+ for (int i = 0; i < _soundFilesSize; i++)
+ soundfiles[i] = (i < size1) ? soundfiles1[i] : soundfiles2[i - size1];
+ _soundFiles = soundfiles;
+ }
_soundFilesIntro = _staticres->loadStrings(k1AudioTracksIntro, _soundFilesIntroSize);
_cdaTrackTable = (const int32 *)_staticres->loadRawData(k1TownsCDATable, _cdaTrackTableSize);
@@ -926,7 +939,7 @@ void KyraEngine_LoK::loadButtonShapes() {
void KyraEngine_LoK::loadMainScreen(int page) {
_screen->clearPage(page);
- if ((_flags.lang == Common::EN_ANY && !_flags.isTalkie && _flags.platform == Common::kPlatformPC) || _flags.platform == Common::kPlatformAmiga)
+ if (((_flags.lang == Common::EN_ANY || _flags.lang == Common::RU_RUS) && !_flags.isTalkie && _flags.platform == Common::kPlatformPC) || _flags.platform == Common::kPlatformAmiga)
_screen->loadBitmap("MAIN15.CPS", page, page, &_screen->getPalette(0));
else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN || (_flags.isTalkie && _flags.lang == Common::IT_ITA))
_screen->loadBitmap("MAIN_ENG.CPS", page, page, 0);
@@ -2129,4 +2142,3 @@ const int8 KyraEngine_MR::_albumWSAY[] = {
};
} // End of namespace Kyra
-
diff --git a/engines/kyra/staticres_lol.cpp b/engines/kyra/staticres_lol.cpp
index cf75a317e1..ca35569afa 100644
--- a/engines/kyra/staticres_lol.cpp
+++ b/engines/kyra/staticres_lol.cpp
@@ -687,11 +687,25 @@ const char * const LoLEngine::_languageExt[] = {
"GER"
};
+const char *const LoLEngine::_charPreviewNamesDefault[] = {
+ "Ak\'shel",
+ "Michael",
+ "Kieran",
+ "Conrad"
+};
+
+const char *const LoLEngine::_charPreviewNamesRussianFloppy[] = {
+ "\x80\xAA\xE8\xA5\xAB\0",
+ "\x8C\xA0\xA9\xAA\xAB\0",
+ "\x8A\xA8\xE0\xA0\xAD\0",
+ "\x8A\xAE\xAD\xE0\xA0\xA4\0"
+};
+
const LoLEngine::CharacterPrev LoLEngine::_charPreviews[] = {
- { "Ak\'shel", 0x060, 0x7F, { 0x0F, 0x08, 0x05 } },
- { "Michael", 0x09A, 0x7F, { 0x06, 0x0A, 0x0F } },
- { "Kieran", 0x0D4, 0x7F, { 0x08, 0x06, 0x08 } },
- { "Conrad", 0x10F, 0x7F, { 0x0A, 0x0C, 0x0A } }
+ { 0x060, 0x7F, { 0x0F, 0x08, 0x05 } },
+ { 0x09A, 0x7F, { 0x06, 0x0A, 0x0F } },
+ { 0x0D4, 0x7F, { 0x08, 0x06, 0x08 } },
+ { 0x10F, 0x7F, { 0x0A, 0x0C, 0x0A } }
};
const uint16 LoLEngine::_charPosXPC98[] = {
@@ -877,4 +891,3 @@ const int LoLEngine::_outroMonsterScaleTableY[] = {
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/text.h b/engines/kyra/text.h
index a95c2c4abc..199029469e 100644
--- a/engines/kyra/text.h
+++ b/engines/kyra/text.h
@@ -79,4 +79,3 @@ protected:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/text_hof.h b/engines/kyra/text_hof.h
index f371fb1898..414d02fe4b 100644
--- a/engines/kyra/text_hof.h
+++ b/engines/kyra/text_hof.h
@@ -50,4 +50,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp
index 346d5100b8..1c2167b892 100644
--- a/engines/kyra/text_lol.cpp
+++ b/engines/kyra/text_lol.cpp
@@ -830,4 +830,3 @@ void TextDisplayer_LoL::clearCurDim() {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h
index 020d4b5e89..3e59bc90fe 100644
--- a/engines/kyra/text_lol.h
+++ b/engines/kyra/text_lol.h
@@ -97,4 +97,3 @@ private:
#endif
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp
index d690b70266..fd4a00b73c 100644
--- a/engines/kyra/text_mr.cpp
+++ b/engines/kyra/text_mr.cpp
@@ -898,4 +898,3 @@ void KyraEngine_MR::doDialog(int dlgIndex, int funcNum) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/timer.h b/engines/kyra/timer.h
index e9cb8b2b0c..205be5957d 100644
--- a/engines/kyra/timer.h
+++ b/engines/kyra/timer.h
@@ -104,4 +104,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/timer_lok.cpp b/engines/kyra/timer_lok.cpp
index e1825d027d..555b3680e2 100644
--- a/engines/kyra/timer_lok.cpp
+++ b/engines/kyra/timer_lok.cpp
@@ -190,4 +190,3 @@ void KyraEngine_LoK::setWalkspeed(uint8 newSpeed) {
}
} // End of namespace Kyra
-
diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp
index 4f450f570f..3221556e6d 100644
--- a/engines/kyra/timer_lol.cpp
+++ b/engines/kyra/timer_lol.cpp
@@ -255,4 +255,3 @@ void LoLEngine::timerFadeMessageText(int timerNum) {
} // End of namespace Kyra
#endif // ENABLE_LOL
-
diff --git a/engines/kyra/util.cpp b/engines/kyra/util.cpp
index 3776bdc705..f71978d03e 100644
--- a/engines/kyra/util.cpp
+++ b/engines/kyra/util.cpp
@@ -146,4 +146,3 @@ const uint8 Util::_charMapISOToDOS[128] = {
};
} // End of namespace Kyra
-
diff --git a/engines/kyra/util.h b/engines/kyra/util.h
index 042da74cd9..b91f84ad36 100644
--- a/engines/kyra/util.h
+++ b/engines/kyra/util.h
@@ -46,4 +46,3 @@ private:
} // End of namespace Kyra
#endif
-
diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp
index 37102744a8..21ff80f033 100644
--- a/engines/kyra/wsamovie.cpp
+++ b/engines/kyra/wsamovie.cpp
@@ -459,5 +459,3 @@ int WSAMovie_v2::open(const char *filename, int unk1, Palette *palBuf) {
}
} // End of namespace Kyra
-
-
diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h
index 0d8bfdc869..7dadc9319b 100644
--- a/engines/kyra/wsamovie.h
+++ b/engines/kyra/wsamovie.h
@@ -132,5 +132,3 @@ protected:
} // End of namespace Kyra
#endif
-
-
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index 885ca8b212..250fa0f2d0 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -42,6 +42,7 @@
#include "common/debug-channels.h"
#include "common/error.h"
#include "common/fs.h"
+#include "common/timer.h"
#include "engines/util.h"
@@ -146,7 +147,7 @@ Common::Error LastExpressEngine::run() {
// Start sound manager and setup timer
_soundMan = new SoundManager(this);
- _timer->installTimerProc(&soundTimer, 17000, this);
+ _timer->installTimerProc(&soundTimer, 17000, this, "lastexpressSound");
// Menu
_menu = new Menu(this);
diff --git a/engines/lastexpress/lastexpress.h b/engines/lastexpress/lastexpress.h
index f8f38788a0..1431b79b9f 100644
--- a/engines/lastexpress/lastexpress.h
+++ b/engines/lastexpress/lastexpress.h
@@ -27,7 +27,6 @@
#include "lastexpress/eventhandler.h"
#include "common/random.h"
-#include "common/timer.h"
#include "engines/engine.h"
diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk
index a11a7c4b67..8b3287d5d7 100644
--- a/engines/lastexpress/module.mk
+++ b/engines/lastexpress/module.mk
@@ -80,4 +80,4 @@ PLUGIN := 1
endif
# Include common rules
-include $(srcdir)/rules.mk \ No newline at end of file
+include $(srcdir)/rules.mk
diff --git a/engines/lure/module.mk b/engines/lure/module.mk
index ba158756b4..57126a6491 100644
--- a/engines/lure/module.mk
+++ b/engines/lure/module.mk
@@ -31,4 +31,3 @@ endif
# Include common rules
include $(srcdir)/rules.mk
-
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index 9fa9a91260..365a7ccdb6 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -30,10 +30,11 @@
#include "common/mutex.h"
#include "common/singleton.h"
#include "common/ptr.h"
+
#include "audio/mididrv.h"
-#include "audio/mixer.h"
class MidiParser;
+class MidiChannel;
namespace Lure {
diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp
index 4630d2e2d6..bdce7928ac 100644
--- a/engines/m4/converse.cpp
+++ b/engines/m4/converse.cpp
@@ -609,7 +609,7 @@ void Converse::loadConversation(const char *convName) {
// ----------------------------------------------------------------------------
// Entry action chunks
case CHUNK_CASN: // Conditional assign
- case CHUNK_ASGN: // Assign
+ case CHUNK_ASGN: { // Assign
curAction = new EntryAction();
if (debugFlag) debugCN(kDebugConversations, "ASGN chunk\n");
curAction->actionType = kAssignValue;
@@ -625,9 +625,11 @@ void Converse::loadConversation(const char *convName) {
}
curAction->targetOffset = convS->readUint32LE();
- assert(convS->readUint32LE() == kOpAssign);
+ int op = convS->readUint32LE();
+ assert(op == kOpAssign);
curAction->value = convS->readUint32LE();
break;
+ }
case CHUNK_CCGO: // Conditional go to entry
case CHUNK_CHDE: // Conditional hide entry
case CHUNK_CUHD: // Conditional unhide entry
diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp
index f4aab8ae8f..7a0b776eb8 100644
--- a/engines/m4/globals.cpp
+++ b/engines/m4/globals.cpp
@@ -380,6 +380,15 @@ void MadsGlobals::loadMadsObjects() {
_vm->res()->toss("objects.dat");
}
+int MadsGlobals::getObjectIndex(uint16 descId) {
+ for (uint i = 0; i < _madsObjects.size(); ++i) {
+ if (_madsObjects[i].get()->_descId == descId)
+ return i;
+ }
+
+ return -1;
+}
+
int MadsGlobals::messageIndexOf(uint32 messageId) {
for (uint i = 0; i < _madsMessages.size(); ++i)
{
diff --git a/engines/m4/globals.h b/engines/m4/globals.h
index ae2941c169..693dc9d6c9 100644
--- a/engines/m4/globals.h
+++ b/engines/m4/globals.h
@@ -297,6 +297,8 @@ public:
void loadMadsObjects();
uint32 getObjectsSize() { return _madsObjects.size(); }
MadsObject *getObject(uint32 index) { return _madsObjects[index].get(); }
+ int getObjectIndex(uint16 descId);
+ int getObjectFolder(uint32 folderId) { warning("TODO: getObjectFolder"); return -1; }
void addVisitedScene(int sceneNumber);
bool isSceneVisited(int sceneNumber);
diff --git a/engines/m4/m4.h b/engines/m4/m4.h
index 46107cb20a..b40ba0e878 100644
--- a/engines/m4/m4.h
+++ b/engines/m4/m4.h
@@ -26,7 +26,6 @@
#include "common/scummsys.h"
#include "common/util.h"
#include "common/random.h"
-#include "audio/mididrv.h"
#include "engines/engine.h"
diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp
index cc28a26e68..335127393e 100644
--- a/engines/m4/mads_logic.cpp
+++ b/engines/m4/mads_logic.cpp
@@ -199,6 +199,10 @@ uint32 MadsSceneLogic::getDataValue(int dataId) {
return getActiveAnimationBool();
case 11:
return getAnimationCurrentFrame();
+ case 12:
+ return _madsVm->scene()->_action._inProgress;
+ case 13:
+ return _madsVm->globals()->_difficultyLevel;
default:
// All other data variables get stored in the hash table
return _madsVm->globals()->_dataMap[dataId];
@@ -239,6 +243,12 @@ void MadsSceneLogic::setDataValue(int dataId, uint16 dataValue) {
case 11:
error("Tried to set read only data field %d", dataId);
break;
+ case 12:
+ _madsVm->scene()->_action._inProgress = dataValue != 0;
+ break;
+ case 13:
+ _madsVm->globals()->_difficultyLevel = dataValue;
+ break;
default:
// All other data variables get stored in the hash table
_madsVm->globals()->_dataMap[dataId] = dataValue;
@@ -986,6 +996,37 @@ void MadsSceneLogic::callSubroutine(int subIndex, Common::Stack<ScriptVar> &stac
break;
}
+ case 27: {
+ // object_get_id_from_desc
+ EXTRACT_PARAMS(1);
+ stack.push(_madsVm->globals()->getObjectIndex(p[0]));
+ break;
+ }
+
+ case 28: {
+ // object_get_folder
+ EXTRACT_PARAMS(1);
+ stack.push(_madsVm->globals()->getObjectFolder(p[0]));
+ break;
+ }
+
+ case 29:
+ // inventory_remove
+ EXTRACT_PARAMS(1);
+ _madsVm->scene()->getInterface()->addObjectToInventory(p[0]);
+ break;
+
+ case 30:
+ // image_inter_list_call
+ EXTRACT_PARAMS(1);
+ warning("TODO: image_inter_list_call");
+ break;
+
+ case 31:
+ // dialog_flags_show
+ warning("todo: dialog_flags_show");
+ break;
+
default:
error("Unknown subroutine %d called", subIndex);
break;
diff --git a/engines/m4/midi.h b/engines/m4/midi.h
index 6eef907ce3..817150fd81 100644
--- a/engines/m4/midi.h
+++ b/engines/m4/midi.h
@@ -57,4 +57,3 @@ protected:
} // End of namespace M4
#endif
-
diff --git a/engines/m4/saveload.cpp b/engines/m4/saveload.cpp
index aa35385bfe..a7615fa4b6 100644
--- a/engines/m4/saveload.cpp
+++ b/engines/m4/saveload.cpp
@@ -96,7 +96,8 @@ SaveGameList *SaveLoad::getSaves() {
result->push_back(Common::String());
} else {
// Skip over byte offset
- assert(saveFile->readUint32LE() < 0x100);
+ uint32 offset = saveFile->readUint32LE();
+ assert(offset < 0x100);
// Read in savegame name
saveFile->read(&saveName[0], MAX_SAVEGAME_NAME);
diff --git a/engines/m4/scripttab.h b/engines/m4/scripttab.h
index b6156f0b82..3264ae743c 100644
--- a/engines/m4/scripttab.h
+++ b/engines/m4/scripttab.h
@@ -133,4 +133,3 @@
VARIABLE(kInterfaceVisible)
};
#undef VARIABLE
-
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index 1320daaf9d..fa08923e44 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -104,7 +104,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1("rtzcd.red", "cd8b62ece4677c438688c1de3f5379b9"),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -121,7 +121,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.dat", "a1db8c97a78dae10f91d356f16ad07b8", 536064),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -138,7 +138,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.red", "c4e2430e6b6c6ff1562a80fb4a9df24c", 276177),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -156,7 +156,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1("rtzcd.dat", "9d740378da2d16e83d0d0efff01bf83a"),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -173,7 +173,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 276584),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -191,7 +191,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.dat", "9d740378da2d16e83d0d0efff01bf83a", 525824),
Common::DE_DEU,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -209,7 +209,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 355442),
Common::DE_DEU,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -227,7 +227,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.dat", "5b86035aed0277f96e3d173542b5364a", 523776),
Common::IT_ITA,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -245,7 +245,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 354971),
Common::IT_ITA,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -263,7 +263,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.dat", "bde8251a8e34e87c54e3f93147d56c9e", 523776),
Common::FR_FRA,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -281,7 +281,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 354614),
Common::FR_FRA,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -333,7 +333,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1("rtzcd.dat", "c4fccf67ad247f09b94c3c808b138576"),
Common::JA_JPN,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -351,7 +351,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1("rtzcd.dat", "e949a6a42d82daabfa7d4dc0a87a9843"),
Common::JA_JPN,
Common::kPlatformFMTowns,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -369,7 +369,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1("rtzcd.dat", "0c0117e98530c736a141c2aad6834dc5"),
Common::JA_JPN,
Common::kPlatformPC98,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_RTZ,
@@ -386,7 +386,7 @@ static const MadeGameDescription gameDescriptions[] = {
AD_ENTRY1("manhole.dat", "cb21e31ed35c963208343bc995225b73"),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NOSPEECH
},
GID_MANHOLE,
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index e7dc84606c..0234c86c7e 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -117,7 +117,7 @@ static const char *mystStackNames[12] = {
static const uint16 default_start_card[12] = {
3137,
10000,
- 2001, // TODO: Should be 2000?
+ 2000,
5038,
2, // TODO: Should be 1?
1,
diff --git a/engines/mohawk/cstime.h b/engines/mohawk/cstime.h
index 3a1de6a137..0bc236f930 100644
--- a/engines/mohawk/cstime.h
+++ b/engines/mohawk/cstime.h
@@ -30,8 +30,6 @@
#include "common/random.h"
#include "common/list.h"
-#include "audio/mixer.h"
-
namespace Mohawk {
class CSTimeCase;
diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp
index 78e099ccfe..cbd17e0b86 100644
--- a/engines/mohawk/cursors.cpp
+++ b/engines/mohawk/cursors.cpp
@@ -49,36 +49,13 @@ void CursorManager::hideCursor() {
}
void CursorManager::setDefaultCursor() {
- static const byte defaultCursor[] = {
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0,
- 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
- 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
- 1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0,
- 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0,
- 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0,
- 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0,
- 1, 2, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0,
- 1, 2, 1, 0, 1, 1, 2, 2, 1, 0, 0, 0,
- 1, 1, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0
- };
-
- static const byte bwPalette[] = {
- 0x00, 0x00, 0x00, // Black
- 0xFF, 0xFF, 0xFF // White
- };
-
- CursorMan.replaceCursor(defaultCursor, 12, 20, 0, 0, 0);
- CursorMan.replaceCursorPalette(bwPalette, 1, 2);
+ Graphics::Cursor *cursor = Graphics::makeDefaultWinCursor();
+
+ CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(),
+ cursor->getHotspotY(), cursor->getKeyColor());
+ CursorMan.replaceCursorPalette(cursor->getPalette(), cursor->getPaletteStartIndex(), cursor->getPaletteCount());
+
+ delete cursor;
}
void CursorManager::setCursor(uint16 id) {
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index 01eac0aaba..a587d06760 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -653,6 +653,23 @@ static const MohawkGameDescription gameDescriptions[] = {
"HARRY.EXE"
},
+ // part of "Super Living Books" compilation
+ // from rgemini, bug #3309343
+ {
+ {
+ "harryhh",
+ "",
+ AD_ENTRY1("HARRY.512", "39d11399796dfa36d3f631d2d87e8b85"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ "HARRY.EXE"
+ },
+
{
{
"carmentq",
@@ -929,6 +946,23 @@ static const MohawkGameDescription gameDescriptions[] = {
"TORTOISE.EXE"
},
+ // part of "Super Living Books" compilation
+ // from rgemini, bug #3309343
+ {
+ {
+ "tortoise",
+ "",
+ AD_ENTRY1("TORTOISE.512", "e9ec7a6bc6b451c9e85e5b4f072d5143"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ "TORTOISE.EXE"
+ },
+
// From afholman in bug#3309308
{
{
@@ -1053,6 +1087,23 @@ static const MohawkGameDescription gameDescriptions[] = {
"ARTHUR.EXE"
},
+ // part of "Super Living Books" compilation
+ // from rgemini, bug #3309343
+ {
+ {
+ "arthur",
+ "",
+ AD_ENTRY1("PAGES.512", "cd995d20d0d7b4642476fd76044b4e5b"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_LB_10,
+ "ARTHUR.EXE"
+ },
+
// From afholman in bug#3309308
{
{
@@ -1195,6 +1246,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"GRANDMA.EXE"
},
+ // from jjnryan in bug #3389857
+ {
+ {
+ "grandma",
+ "v1.0",
+ AD_ENTRY1("PAGES.512", "613ca946bc8d91087fb7c10e9b84e88b"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ GF_LB_10,
+ "GRANDMA.EXE"
+ },
+
{
{
"grandma",
@@ -1366,6 +1433,23 @@ static const MohawkGameDescription gameDescriptions[] = {
"NEWKID.EXE"
},
+ // part of "Super Living Books" compilation
+ // from rgemini, bug #3309343
+ {
+ {
+ "newkid",
+ "",
+ AD_ENTRY1("NEWKID.512", "28a5aef3e6ef7e2ed7742485c25bdff6"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ GType_LIVINGBOOKSV1,
+ 0,
+ "NEWKID.EXE"
+ },
+
// From aluff in bug#3309981
{
{
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index 6cb455917e..4461a30ad4 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -81,14 +81,17 @@ enum {
kTransCmd = 'TRAN',
kWaterCmd = 'WATR',
kDropCmd = 'DROP',
- kMapCmd = 'SMAP'
+ kMapCmd = 'SMAP',
+ kMenuCmd = 'MENU'
};
#ifdef ENABLE_MYST
MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
+ // I18N: Option for fast scene switching
_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);
+ // I18N: Drop book page
_dropPageButton = new GUI::ButtonWidget(this, 15, 60, 100, 25, _("~D~rop Page"), 0, kDropCmd);
// Myst ME only has maps
@@ -97,6 +100,12 @@ MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog
else
_showMapButton = 0;
+ // Myst demo only has a menu
+ if (_vm->getFeatures() & GF_DEMO)
+ _returnToMenuButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("~M~ain Menu"), 0, kMenuCmd);
+ else
+ _returnToMenuButton = 0;
+
new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd);
new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd);
}
@@ -113,6 +122,15 @@ void MystOptionsDialog::open() {
_showMapButton->setEnabled(_vm->_scriptParser &&
_vm->_scriptParser->getMap());
+ // Return to menu button is not enabled on the menu
+ if (_returnToMenuButton)
+ _returnToMenuButton->setEnabled(_vm->_scriptParser &&
+ _vm->getCurStack() != kDemoStack);
+
+ // Zip mode is disabled in the demo
+ if (_vm->getFeatures() & GF_DEMO)
+ _zipModeCheckbox->setEnabled(false);
+
_zipModeCheckbox->setState(_vm->_gameState->_globals.zipMode);
_transitionsCheckbox->setState(_vm->_gameState->_globals.transitions);
}
@@ -133,6 +151,10 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
_vm->_needsShowMap = true;
close();
break;
+ case kMenuCmd:
+ _vm->_needsShowDemoMenu = true;
+ close();
+ break;
case GUI::kCloseCmd:
close();
break;
diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h
index 853ff30813..844c01ad26 100644
--- a/engines/mohawk/dialogs.h
+++ b/engines/mohawk/dialogs.h
@@ -83,6 +83,7 @@ private:
GUI::CheckboxWidget *_transitionsCheckbox;
GUI::ButtonWidget *_dropPageButton;
GUI::ButtonWidget *_showMapButton;
+ GUI::ButtonWidget *_returnToMenuButton;
};
#endif
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index b3653b1fdf..35c9d478d8 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -672,6 +672,14 @@ void MystGraphics::simulatePreviousDrawDelay(const Common::Rect &dest) {
_nextAllowedDrawTime = time + _constantDrawDelay + dest.height() * dest.width() / _proportionalDrawDelay;
}
+void MystGraphics::fadeToBlack() {
+ // TODO: Implement
+}
+
+void MystGraphics::fadeFromBlack() {
+ // TODO: Implement
+}
+
#endif // ENABLE_MYST
#ifdef ENABLE_RIVEN
@@ -913,7 +921,8 @@ void RivenGraphics::clearMainScreen() {
}
void RivenGraphics::fadeToBlack() {
- // Self-explanatory
+ // The transition speed is forced to best here
+ setTransitionSpeed(kRivenTransitionSpeedBest);
scheduleTransition(16);
clearMainScreen();
runScheduledTransition();
diff --git a/engines/mohawk/graphics.h b/engines/mohawk/graphics.h
index d7057f48cf..96357bbff1 100644
--- a/engines/mohawk/graphics.h
+++ b/engines/mohawk/graphics.h
@@ -129,6 +129,8 @@ public:
void drawRect(Common::Rect rect, RectState state);
void drawLine(const Common::Point &p1, const Common::Point &p2, uint32 color);
void enableDrawingTimeSimulation(bool enable);
+ void fadeToBlack();
+ void fadeFromBlack();
protected:
MohawkSurface *decodeImage(uint16 id);
@@ -194,6 +196,7 @@ public:
void scheduleTransition(uint16 id, Common::Rect rect = Common::Rect(0, 0, 608, 392));
void runScheduledTransition();
void fadeToBlack();
+ void setTransitionSpeed(uint32 speed) { _transitionSpeed = speed; }
// Inventory
void showInventory();
@@ -229,6 +232,7 @@ private:
// Transitions
int16 _scheduledTransition;
Common::Rect _transitionRect;
+ uint32 _transitionSpeed;
// Inventory
void clearInventoryArea();
diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h
index 27e703a578..008a7dbf23 100644
--- a/engines/mohawk/livingbooks.h
+++ b/engines/mohawk/livingbooks.h
@@ -33,8 +33,6 @@
#include "common/queue.h"
#include "common/random.h"
-#include "audio/mixer.h"
-
#include "livingbooks_code.h"
namespace Common {
diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp
index faf52595b7..cb419064c0 100644
--- a/engines/mohawk/mohawk.cpp
+++ b/engines/mohawk/mohawk.cpp
@@ -31,8 +31,6 @@
#include "mohawk/sound.h"
#include "mohawk/video.h"
-#include "audio/mixer.h"
-
namespace Mohawk {
MohawkEngine::MohawkEngine(OSystem *syst, const MohawkGameDescription *gamedesc) : Engine(syst), _gameDescription(gamedesc) {
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 6bdf163a91..eeb4594f3c 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -343,6 +343,7 @@ Common::Error MohawkEngine_Myst::run() {
case Common::KEYCODE_F5:
_needsPageDrop = false;
_needsShowMap = false;
+ _needsShowDemoMenu = false;
runDialog(*_optionsDialog);
@@ -355,6 +356,11 @@ Common::Error MohawkEngine_Myst::run() {
_scriptParser->showMap();
_needsShowMap = false;
}
+
+ if (_needsShowDemoMenu) {
+ changeToStack(kDemoStack, 2002, 0, 0);
+ _needsShowDemoMenu = false;
+ }
break;
default:
break;
@@ -441,6 +447,7 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
_scriptParser = new MystStacks::Credits(this);
break;
case kDemoStack:
+ _gameState->_globals.currentAge = 0;
_scriptParser = new MystStacks::Demo(this);
break;
case kDniStack:
@@ -469,6 +476,7 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
_scriptParser = new MystStacks::Selenitic(this);
break;
case kDemoSlidesStack:
+ _gameState->_globals.currentAge = 1;
_scriptParser = new MystStacks::Slides(this);
break;
case kStoneshipStack:
@@ -645,7 +653,11 @@ void MohawkEngine_Myst::changeToCard(uint16 card, bool updateScreen) {
for (uint16 i = 0; i < _resources.size(); i++)
_resources[i]->handleCardChange();
- // TODO: Handle Script Resources
+ // The demo resets the cursor at each card change except when in the library
+ if (getFeatures() & GF_DEMO
+ && _gameState->_globals.currentAge != 2) {
+ _cursor->setDefaultCursor();
+ }
// Make sure the screen is updated
if (updateScreen) {
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index ebcc3b445c..02f0a46e3f 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -167,6 +167,7 @@ public:
bool _needsUpdate;
bool _needsPageDrop;
bool _needsShowMap;
+ bool _needsShowDemoMenu;
MystView _view;
MystGraphics *_gfx;
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index 307be2dd05..ca8e985491 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -500,7 +500,7 @@ void MystScriptParser::o_disableAreas(uint16 op, uint16 var, uint16 argc, uint16
resource = _vm->_resources[argv[i + 1]];
if (resource)
- resource->setEnabled(true);
+ resource->setEnabled(false);
else
warning("Unknown Resource in disableAreas script Opcode");
}
diff --git a/engines/mohawk/myst_stacks/demo.cpp b/engines/mohawk/myst_stacks/demo.cpp
index 5788f4b3a3..c9e806655e 100644
--- a/engines/mohawk/myst_stacks/demo.cpp
+++ b/engines/mohawk/myst_stacks/demo.cpp
@@ -20,16 +20,20 @@
*
*/
+#include "mohawk/cursors.h"
+#include "mohawk/graphics.h"
#include "mohawk/myst.h"
#include "mohawk/myst_stacks/demo.h"
-#include "gui/message.h"
+#include "common/system.h"
namespace Mohawk {
namespace MystStacks {
Demo::Demo(MohawkEngine_Myst *vm) : Intro(vm) {
setupOpcodes();
+
+ _returnToMenuStep = 0;
}
Demo::~Demo() {
@@ -47,15 +51,12 @@ Demo::~Demo() {
void Demo::setupOpcodes() {
// "Stack-Specific" Opcodes
- OVERRIDE_OPCODE(100, opcode_100);
- OPCODE(101, opcode_101);
- OPCODE(102, opcode_102);
+ OVERRIDE_OPCODE(100, o_stopIntro);
+ OPCODE(101, o_fadeFromBlack);
+ OPCODE(102, o_fadeToBlack);
// "Init" Opcodes
- OVERRIDE_OPCODE(201, opcode_201);
-
- // "Exit" Opcodes
- OVERRIDE_OPCODE(300, opcode_300);
+ OVERRIDE_OPCODE(201, o_returnToMenu_init);
}
#undef OPCODE
@@ -64,61 +65,66 @@ void Demo::setupOpcodes() {
void Demo::disablePersistentScripts() {
Intro::disablePersistentScripts();
- _enabled201 = false;
+ _returnToMenuRunning = false;
}
void Demo::runPersistentScripts() {
Intro::runPersistentScripts();
- if (_enabled201) {
- // Used on Card 2001, 2002 and 2003
-
- // TODO: Fill in Function...
+ if (_returnToMenuRunning) {
+ returnToMenu_run();
}
}
-void Demo::opcode_100(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- // TODO: Fill in Function...
+void Demo::o_stopIntro(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Unk", op);
+ // The original also seems to stop the movies. Not needed with this engine.
+ _vm->_gfx->fadeToBlack();
}
-void Demo::opcode_101(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
-
- // Used on Card 2000, 2002 and 2003
- // Triggered by Click
- if (argc == 0) {
- // TODO: Fill in Logic.. Fade in?
- } else
- unknown(op, var, argc, argv);
+void Demo::o_fadeFromBlack(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Fade from black", op);
+ _vm->_gfx->fadeFromBlack();
}
-void Demo::opcode_102(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
-
- // Used on Card 2002 and 2003
- // Triggered by Click
- if (argc == 0) {
- // TODO: Fill in Logic.. Fade out?
- } else
- unknown(op, var, argc, argv);
+void Demo::o_fadeToBlack(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Fade to black", op);
+ _vm->_gfx->fadeToBlack();
}
-void Demo::opcode_201(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
-
- // Used on Card 2001, 2002 and 2003
- if (argc == 0)
- _enabled201 = true;
- else
- unknown(op, var, argc, argv);
+void Demo::returnToMenu_run() {
+ uint32 time = _vm->_system->getMillis();
+
+ if (time < _returnToMenuNextTime)
+ return;
+
+ switch (_returnToMenuStep){
+ case 0:
+ _vm->_gfx->fadeToBlack();
+ _vm->changeToCard(2003, true);
+ _vm->_gfx->fadeFromBlack();
+
+ _returnToMenuStep++;
+ break;
+ case 1:
+ _vm->_gfx->fadeToBlack();
+ _vm->changeToCard(2001, true);
+ _vm->_gfx->fadeFromBlack();
+ _vm->_cursor->showCursor();
+
+ _returnToMenuStep++;
+ break;
+ default:
+ break;
+ }
}
+void Demo::o_returnToMenu_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Return to menu init", op);
-void Demo::opcode_300(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- // Used on Card 2000
- varUnusedCheck(op, var);
-
- // TODO: Fill in Function...
+ // Used on Card 2001, 2002 and 2003
+ _returnToMenuNextTime = _vm->_system->getMillis() + 5000;
+ _returnToMenuRunning = true;
}
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/demo.h b/engines/mohawk/myst_stacks/demo.h
index 4f8d68759b..c3e57cf7ae 100644
--- a/engines/mohawk/myst_stacks/demo.h
+++ b/engines/mohawk/myst_stacks/demo.h
@@ -46,15 +46,19 @@ public:
private:
void setupOpcodes();
- DECLARE_OPCODE(opcode_100);
- DECLARE_OPCODE(opcode_101);
- DECLARE_OPCODE(opcode_102);
+ DECLARE_OPCODE(o_stopIntro);
+ DECLARE_OPCODE(o_fadeFromBlack);
+ DECLARE_OPCODE(o_fadeToBlack);
- DECLARE_OPCODE(opcode_201);
+ DECLARE_OPCODE(o_returnToMenu_init);
DECLARE_OPCODE(opcode_300);
- bool _enabled201;
+ bool _returnToMenuRunning;
+ uint16 _returnToMenuStep; // 42
+ uint32 _returnToMenuNextTime; // 6
+
+ void returnToMenu_run();
};
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h
index 9510d371d7..e9bff08cb4 100644
--- a/engines/mohawk/myst_stacks/myst.h
+++ b/engines/mohawk/myst_stacks/myst.h
@@ -40,8 +40,8 @@ public:
Myst(MohawkEngine_Myst *vm);
~Myst();
- void disablePersistentScripts();
- void runPersistentScripts();
+ virtual void disablePersistentScripts();
+ virtual void runPersistentScripts();
private:
void setupOpcodes();
diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp
index 37b749f100..1b72c85d96 100644
--- a/engines/mohawk/myst_stacks/preview.cpp
+++ b/engines/mohawk/myst_stacks/preview.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "mohawk/cursors.h"
#include "mohawk/myst.h"
#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
@@ -35,6 +36,7 @@ namespace MystStacks {
Preview::Preview(MohawkEngine_Myst *vm) : Myst(vm) {
setupOpcodes();
+ _vm->_cursor->hideCursor();
}
Preview::~Preview() {
@@ -52,86 +54,187 @@ Preview::~Preview() {
void Preview::setupOpcodes() {
// "Stack-Specific" Opcodes
- OVERRIDE_OPCODE(196, opcode_196);
- OVERRIDE_OPCODE(197, opcode_197);
- OVERRIDE_OPCODE(198, opcode_198);
- OVERRIDE_OPCODE(199, opcode_199);
+ OVERRIDE_OPCODE(196, o_fadeToBlack);
+ OVERRIDE_OPCODE(197, o_fadeFromBlack);
+ OVERRIDE_OPCODE(198, o_stayHere);
+ OVERRIDE_OPCODE(199, o_speechStop);
// "Init" Opcodes
- OPCODE(298, opcode_298);
- OPCODE(299, opcode_299);
+ OPCODE(298, o_speech_init);
+ OPCODE(299, o_library_init);
}
#undef OPCODE
#undef OVERRIDE_OPCODE
-void Preview::opcode_196(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Preview::disablePersistentScripts() {
+ Myst::disablePersistentScripts();
+}
+
+void Preview::runPersistentScripts() {
+ Myst::runPersistentScripts();
- // Used on Card ...
- // TODO: Finish Implementation...
- // Voice Over and Card Advance?
+ if (_speechRunning)
+ speech_run();
}
-void Preview::opcode_197(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Preview::o_fadeToBlack(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Fade to black", op);
+ _vm->_gfx->fadeToBlack();
+}
- // Used on Card ...
- // TODO: Finish Implementation...
- // Voice Over and Card Advance?
+void Preview::o_fadeFromBlack(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Fade from black", op);
+ _vm->_gfx->fadeFromBlack();
}
-// TODO: Merge with Opcode 42?
-void Preview::opcode_198(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Preview::o_stayHere(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Stay here dialog", op);
- if (argc == 0) {
- // Nuh-uh! No leaving the library in the demo!
- GUI::MessageDialog dialog("You can't leave the library in the demo.");
- dialog.runModal();
- } else
- unknown(op, var, argc, argv);
+ // Nuh-uh! No leaving the library in the demo!
+ GUI::MessageDialog dialog("You can't leave the library in the demo.");
+ dialog.runModal();
}
-void Preview::opcode_199(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Preview::o_speechStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Speech stop", op);
- // Used on Card ...
- // TODO: Finish Implementation...
- // Voice Over and Card Advance?
+ _speechRunning = false;
+ _globals.currentAge = 2;
}
-void Preview::opcode_298(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Preview::speechUpdateCue() {
+ // This is a callback in the original, handling audio events.
+ if (!_vm->_sound->isPlaying(3001)) {
+ return;
+ }
- // Used for Card 3000 (Closed Myst Book)
- // TODO: Fill in logic.
- // Start Voice Over... which controls book opening
- _vm->_sound->replaceSoundMyst(3001);
-
- // then link to Myst - Trigger of Hotspot? then opcode 199/196/197 for voice over continue?
- // TODO: Sync Voice and Actions to Original
- // TODO: Flash Library Red
- // TODO: Move to run process based delay to prevent
- // blocking...
- _vm->_system->updateScreen();
- _vm->_system->delayMillis(20 * 1000);
-
- for (uint16 imageId = 3001; imageId <= 3012; imageId++) {
- _vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333));
- _vm->_system->updateScreen();
- _vm->_system->delayMillis(5 * 1000);
+ uint samples = _vm->_sound->getNumSamplesPlayed(3001);
+ for (int16 i = 0; i < _cueList.pointCount; i++) {
+ if (_cueList.points[i].sampleFrame > samples)
+ return;
+ if (i > _currentCue - 1) {
+ _currentCue++;
+ debugC(kDebugScript, "Sneak speech advanced to cue %d", _currentCue);
+ }
}
}
-void Preview::opcode_299(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- varUnusedCheck(op, var);
+void Preview::speech_run() {
+ uint32 time = _vm->_system->getMillis();
+
+ // Update current speech sound cue
+ speechUpdateCue();
+
+ switch (_speechStep) {
+ case 0: // Start Voice Over... which controls book opening
+ _currentCue = 0;
+ _vm->_sound->playSound(3001, Audio::Mixer::kMaxChannelVolume, false, &_cueList);
+
+ _speechStep++;
+ break;
+ case 1: // Open book
+ if (_currentCue >= 1) {
+ _vm->changeToCard(3001, true);
+
+ _speechStep++;
+ }
+ break;
+ case 2: // Go to Myst
+ if (_currentCue >= 2) {
+ _vm->_gfx->fadeToBlack();
+ _vm->changeToCard(3002, true);
+ _vm->_gfx->fadeFromBlack();
+
+ _speechStep++;
+ }
+ break;
+ case 3: // Start blinking the library
+ if (_currentCue >= 3) {
+ _libraryState = 1;
+ _speechNextTime = 0;
+ _speechStep++;
+ }
+ break;
+ case 4: // Library blinking, zoom in library
+ if (_currentCue >= 4) {
+ _library->drawConditionalDataToScreen(0);
+
+ _vm->changeToCard(3003, true);
+
+ _speechNextTime = time + 2000;
+ _speechStep++;
+ } else {
+ if (time < _speechNextTime)
+ break;
+
+ _library->drawConditionalDataToScreen(_libraryState);
+ _libraryState = (_libraryState + 1) % 2;
+ _speechNextTime = time + 500;
+ }
+ break;
+ case 5: // Go to library near view
+ if (time < _speechNextTime)
+ break;
+
+ _vm->changeToCard(3004, true);
+ _speechNextTime = time + 2000;
+ _speechStep++;
+ break;
+ case 6: // Fade to courtyard
+ if (time < _speechNextTime)
+ break;
+
+ _vm->_gfx->fadeToBlack();
+ _vm->changeToCard(3005, true);
+ _vm->_gfx->fadeFromBlack();
+ _speechNextTime = time + 1000;
+ _speechStep++;
+ break;
+ case 7: // Walk to library
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ if (time < _speechNextTime)
+ break;
+
+ _vm->changeToCard(3006 + _speechStep - 7, true);
+ _speechNextTime = time + 2000;
+ _speechStep++;
+ break;
+ case 14: // Go to playable library card
+ if (time < _speechNextTime)
+ break;
+
+ _vm->changeToCard(4329, true);
+
+ _speechRunning = false;
+ _globals.currentAge = 2;
+
+ _vm->_cursor->showCursor();
+ break;
+ default:
+ warning("Unknown speech step");
+ break;
+ }
+}
+
+void Preview::o_speech_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Speech init", op);
+
+ // Used for Card 3000 (Closed Myst Book)
+ _speechStep = 0;
+ _speechRunning = true;
+}
+
+void Preview::o_library_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Library init", op);
// Used for Card 3002 (Myst Island Overview)
- // TODO: Fill in logic.
- // Zoom into Island?
- // On this card is a Type 8 controlled by Var 0, which
- // can change the Myst Library to Red..
+ _library = static_cast<MystResourceType8 *>(_invokingResource);
}
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/preview.h b/engines/mohawk/myst_stacks/preview.h
index 7e4e418eef..1e4ff3efb4 100644
--- a/engines/mohawk/myst_stacks/preview.h
+++ b/engines/mohawk/myst_stacks/preview.h
@@ -40,16 +40,31 @@ public:
Preview(MohawkEngine_Myst *vm);
~Preview();
+ void disablePersistentScripts();
+ void runPersistentScripts();
+
private:
void setupOpcodes();
- DECLARE_OPCODE(opcode_196);
- DECLARE_OPCODE(opcode_197);
- DECLARE_OPCODE(opcode_198);
- DECLARE_OPCODE(opcode_199);
+ DECLARE_OPCODE(o_fadeToBlack);
+ DECLARE_OPCODE(o_fadeFromBlack);
+ DECLARE_OPCODE(o_stayHere);
+ DECLARE_OPCODE(o_speechStop);
+
+ DECLARE_OPCODE(o_speech_init);
+ DECLARE_OPCODE(o_library_init);
+
+ uint16 _libraryState; // 4
+ MystResourceType8 *_library; // 32
+
+ bool _speechRunning;
+ uint _speechStep;
+ CueList _cueList;
+ int16 _currentCue;
+ uint32 _speechNextTime; // 6
- DECLARE_OPCODE(opcode_298);
- DECLARE_OPCODE(opcode_299);
+ void speech_run();
+ void speechUpdateCue();
};
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp
index 72b299ee6d..943cb90071 100644
--- a/engines/mohawk/myst_stacks/slides.cpp
+++ b/engines/mohawk/myst_stacks/slides.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "mohawk/cursors.h"
#include "mohawk/myst.h"
#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
@@ -35,6 +36,7 @@ namespace MystStacks {
Slides::Slides(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
setupOpcodes();
+ _vm->_cursor->hideCursor();
}
Slides::~Slides() {
@@ -59,23 +61,28 @@ void Slides::disablePersistentScripts() {
void Slides::runPersistentScripts() {
if (_cardSwapEnabled) {
// Used on Cards...
- if (_vm->_system->getMillis() - _lastCardTime >= 2 * 1000)
+ if (_vm->_system->getMillis() > _nextCardTime) {
+ _vm->_gfx->fadeToBlack();
_vm->changeToCard(_nextCardID, true);
+ _vm->_gfx->fadeFromBlack();
+ }
}
}
void Slides::o_returnToMenu(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- _vm->changeToStack(kDemoStack, 2001, 0, 0);
+ debugC(kDebugScript, "Opcode %d: Return to menu", op);
+
+ // Go to the information screens of the menu
+ _vm->changeToStack(kDemoStack, 2002, 0, 0);
}
void Slides::o_setCardSwap(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- // Used on Cards...
- if (argc == 1) {
- _nextCardID = argv[0];
- _lastCardTime = _vm->_system->getMillis();
- _cardSwapEnabled = true;
- } else
- unknown(op, var, argc, argv);
+ _nextCardID = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Set next card %d", op, _nextCardID);
+
+ _nextCardTime = _vm->_system->getMillis() + 5000;
+ _cardSwapEnabled = true;
}
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/slides.h b/engines/mohawk/myst_stacks/slides.h
index 8bc61d0e24..9fb76728b6 100644
--- a/engines/mohawk/myst_stacks/slides.h
+++ b/engines/mohawk/myst_stacks/slides.h
@@ -52,7 +52,7 @@ private:
bool _cardSwapEnabled;
uint16 _nextCardID;
- uint32 _lastCardTime;
+ uint32 _nextCardTime;
};
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_state.cpp b/engines/mohawk/myst_state.cpp
index bab4b8dd51..3a8d233a26 100644
--- a/engines/mohawk/myst_state.cpp
+++ b/engines/mohawk/myst_state.cpp
@@ -320,6 +320,10 @@ void MystGameState::deleteSave(const Common::String &saveName) {
void MystGameState::addZipDest(uint16 stack, uint16 view) {
ZipDests *zipDests = 0;
+ // The demo has no zip dest storage
+ if (_vm->getFeatures() & GF_DEMO)
+ return;
+
// Select stack
switch (stack) {
case kChannelwoodStack:
@@ -362,6 +366,10 @@ bool MystGameState::isReachableZipDest(uint16 stack, uint16 view) {
if (!_globals.zipMode)
return false;
+ // The demo has no zip dest storage
+ if (_vm->getFeatures() & GF_DEMO)
+ return false;
+
// Select stack
ZipDests *zipDests;
switch (stack) {
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 612b8b3685..3e2fa4f979 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -150,6 +150,9 @@ Common::Error MohawkEngine_Riven::run() {
return Common::kNoGameDataFoundError;
}
+ // Set the transition speed
+ _gfx->setTransitionSpeed(_vars["transitionmode"]);
+
// Start at main cursor
_cursor->setCursor(kRivenMainCursor);
_cursor->showCursor();
@@ -209,8 +212,10 @@ void MohawkEngine_Riven::handleEvents() {
needsUpdate = true;
break;
case Common::EVENT_LBUTTONDOWN:
- if (_curHotspot >= 0)
+ if (_curHotspot >= 0) {
+ checkSunnerAlertClick();
runHotspotScript(_curHotspot, kMouseDownScript);
+ }
break;
case Common::EVENT_LBUTTONUP:
// See RivenScript::switchCard() for more information on why we sometimes
@@ -812,6 +817,138 @@ static void catherineIdleTimer(MohawkEngine_Riven *vm) {
vm->installTimer(&catherineIdleTimer, timeUntilNextMovie);
}
+static void sunnersTopStairsTimer(MohawkEngine_Riven *vm) {
+ // If the sunners are gone, we have no video to play
+ if (vm->_vars["jsunners"] != 0) {
+ vm->removeTimer();
+ return;
+ }
+
+ // Play a random sunners video if the script one is not playing already
+ // and then set a new timer for when the new video should be played
+
+ VideoHandle oldHandle = vm->_video->findVideoHandleRiven(1);
+ uint32 timerTime = 500;
+
+ if (oldHandle == NULL_VID_HANDLE || vm->_video->endOfVideo(oldHandle)) {
+ uint32 &sunnerTime = vm->_vars["jsunnertime"];
+
+ if (sunnerTime == 0) {
+ timerTime = vm->_rnd->getRandomNumberRng(2, 15) * 1000;
+ } else if (sunnerTime < vm->getTotalPlayTime()) {
+ VideoHandle handle = vm->_video->playMovieRiven(vm->_rnd->getRandomNumberRng(1, 3));
+
+ timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(2, 15) * 1000;
+ }
+
+ sunnerTime = timerTime + vm->getTotalPlayTime();
+ }
+
+ vm->installTimer(&sunnersTopStairsTimer, timerTime);
+}
+
+static void sunnersMidStairsTimer(MohawkEngine_Riven *vm) {
+ // If the sunners are gone, we have no video to play
+ if (vm->_vars["jsunners"] != 0) {
+ vm->removeTimer();
+ return;
+ }
+
+ // Play a random sunners video if the script one is not playing already
+ // and then set a new timer for when the new video should be played
+
+ VideoHandle oldHandle = vm->_video->findVideoHandleRiven(1);
+ uint32 timerTime = 500;
+
+ if (oldHandle == NULL_VID_HANDLE || vm->_video->endOfVideo(oldHandle)) {
+ uint32 &sunnerTime = vm->_vars["jsunnertime"];
+
+ if (sunnerTime == 0) {
+ timerTime = vm->_rnd->getRandomNumberRng(1, 10) * 1000;
+ } else if (sunnerTime < vm->getTotalPlayTime()) {
+ // Randomize the video
+ int randValue = vm->_rnd->getRandomNumber(5);
+ uint16 movie = 4;
+ if (randValue == 4)
+ movie = 2;
+ else if (randValue == 5)
+ movie = 3;
+
+ VideoHandle handle = vm->_video->playMovieRiven(movie);
+
+ timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 10) * 1000;
+ }
+
+ sunnerTime = timerTime + vm->getTotalPlayTime();
+ }
+
+ vm->installTimer(&sunnersMidStairsTimer, timerTime);
+}
+
+static void sunnersLowerStairsTimer(MohawkEngine_Riven *vm) {
+ // If the sunners are gone, we have no video to play
+ if (vm->_vars["jsunners"] != 0) {
+ vm->removeTimer();
+ return;
+ }
+
+ // Play a random sunners video if the script one is not playing already
+ // and then set a new timer for when the new video should be played
+
+ VideoHandle oldHandle = vm->_video->findVideoHandleRiven(1);
+ uint32 timerTime = 500;
+
+ if (oldHandle == NULL_VID_HANDLE || vm->_video->endOfVideo(oldHandle)) {
+ uint32 &sunnerTime = vm->_vars["jsunnertime"];
+
+ if (sunnerTime == 0) {
+ timerTime = vm->_rnd->getRandomNumberRng(1, 30) * 1000;
+ } else if (sunnerTime < vm->getTotalPlayTime()) {
+ VideoHandle handle = vm->_video->playMovieRiven(vm->_rnd->getRandomNumberRng(3, 5));
+
+ timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 30) * 1000;
+ }
+
+ sunnerTime = timerTime + vm->getTotalPlayTime();
+ }
+
+ vm->installTimer(&sunnersLowerStairsTimer, timerTime);
+}
+
+static void sunnersBeachTimer(MohawkEngine_Riven *vm) {
+ // If the sunners are gone, we have no video to play
+ if (vm->_vars["jsunners"] != 0) {
+ vm->removeTimer();
+ return;
+ }
+
+ // Play a random sunners video if the script one is not playing already
+ // and then set a new timer for when the new video should be played
+
+ VideoHandle oldHandle = vm->_video->findVideoHandleRiven(3);
+ uint32 timerTime = 500;
+
+ if (oldHandle == NULL_VID_HANDLE || vm->_video->endOfVideo(oldHandle)) {
+ uint32 &sunnerTime = vm->_vars["jsunnertime"];
+
+ if (sunnerTime == 0) {
+ timerTime = vm->_rnd->getRandomNumberRng(1, 30) * 1000;
+ } else if (sunnerTime < vm->getTotalPlayTime()) {
+ // Unlike the other cards' scripts which automatically
+ // activate the MLST, we have to set it manually here.
+ uint16 mlstID = vm->_rnd->getRandomNumberRng(3, 8);
+ vm->_video->activateMLST(mlstID, vm->getCurCard());
+ VideoHandle handle = vm->_video->playMovieRiven(mlstID);
+
+ timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 30) * 1000;
+ }
+
+ sunnerTime = timerTime + vm->getTotalPlayTime();
+ }
+
+ vm->installTimer(&sunnersBeachTimer, timerTime);
+}
+
void MohawkEngine_Riven::installCardTimer() {
switch (getCurCardRMAP()) {
case 0x3a85: // Top of elevator on prison island
@@ -819,16 +956,16 @@ void MohawkEngine_Riven::installCardTimer() {
installTimer(&catherineIdleTimer, _rnd->getRandomNumberRng(1, 33) * 1000);
break;
case 0x77d6: // Sunners, top of stairs
- // TODO: Background Sunner videos
+ installTimer(&sunnersTopStairsTimer, 500);
break;
case 0x79bd: // Sunners, middle of stairs
- // TODO: Background Sunner videos
+ installTimer(&sunnersMidStairsTimer, 500);
break;
case 0x7beb: // Sunners, bottom of stairs
- // TODO: Background Sunner videos
+ installTimer(&sunnersLowerStairsTimer, 500);
break;
case 0xb6ca: // Sunners, shoreline
- // TODO: Background Sunner videos
+ installTimer(&sunnersBeachTimer, 500);
break;
}
}
@@ -846,6 +983,34 @@ void MohawkEngine_Riven::doVideoTimer(VideoHandle handle, bool force) {
_scriptMan->runStoredMovieOpcode();
}
+void MohawkEngine_Riven::checkSunnerAlertClick() {
+ // We need to do a manual hardcoded check for the sunners'
+ // alert movies.
+
+ uint32 &sunners = _vars["jsunners"];
+
+ // If the sunners are gone, there's nothing for us to do
+ if (sunners != 0)
+ return;
+
+ uint32 rmapCode = getCurCardRMAP();
+
+ // This is only for the mid/lower staircase sections
+ if (rmapCode != 0x79bd && rmapCode != 0x7beb)
+ return;
+
+ // Only set the sunners variable on the forward hotspot
+ if ((rmapCode == 0x79bd && _curHotspot != 1) || (rmapCode == 0x7beb && _curHotspot != 2))
+ return;
+
+ // If the alert video is no longer playing, we have nothing left to do
+ VideoHandle handle = _video->findVideoHandleRiven(1);
+ if (handle == NULL_VID_HANDLE || _video->endOfVideo(handle))
+ return;
+
+ sunners = 1;
+}
+
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 c7d36e585d..e99a9f78fc 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -67,6 +67,13 @@ enum {
StackNames = 5
};
+enum RivenTransitionSpeed {
+ kRivenTransitionSpeedNone = 5000,
+ kRivenTransitionSpeedFastest = 5001,
+ kRivenTransitionSpeedNormal = 5002,
+ kRivenTransitionSpeedBest = 5003
+};
+
// Rects for the inventory object positions (initialized in
// MohawkEngine_Riven's constructor).
extern Common::Rect *g_atrusJournalRect1;
@@ -164,6 +171,7 @@ private:
// Miscellaneous
bool _gameOver;
bool _ignoreNextMouseUp;
+ void checkSunnerAlertClick();
public:
// Stack/card/script funtions
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 60e94ea795..9e1365f8da 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -234,10 +234,10 @@ void RivenExternal::runCredits(uint16 video, uint32 delay) {
// 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 first two frames stay on for 4 seconds
// the rest of the scroll updates happen at 30Hz
if (_vm->_gfx->getCurCreditsImage() < 304)
- nextCreditsFrameStart = _vm->_system->getMillis() + 5000;
+ nextCreditsFrameStart = _vm->_system->getMillis() + 4000;
else
nextCreditsFrameStart = _vm->_system->getMillis() + 1000 / 30;
@@ -1889,21 +1889,42 @@ void RivenExternal::xjplaybeetle_1450(uint16 argc, uint16 *argv) {
}
void RivenExternal::xjlagoon700_alert(uint16 argc, uint16 *argv) {
- // TODO: Sunner related
+ // Handle sunner reactions (mid-staircase)
+
+ if (_vm->_vars["jsunners"] == 0)
+ _vm->_video->playMovieRiven(1);
}
void RivenExternal::xjlagoon800_alert(uint16 argc, uint16 *argv) {
- // TODO: Sunner related
+ // Handle sunner reactions (lower-staircase)
+
+ uint32 &sunners = _vm->_vars["jsunners"];
+
+ if (sunners == 0) {
+ // Show the sunners alert video
+ _vm->_video->playMovieRiven(1);
+ } else if (sunners == 1) {
+ // Show the sunners leaving if you moved forward in their "alert" status
+ _vm->_video->playMovieBlockingRiven(2);
+ _vm->_video->playMovieBlockingRiven(6);
+ sunners = 2;
+ _vm->refreshCard();
+ }
}
void RivenExternal::xjlagoon1500_alert(uint16 argc, uint16 *argv) {
- // Have the sunners move a bit as you get closer ;)
+ // Handle sunner reactions (beach)
+
uint32 &sunners = _vm->_vars["jsunners"];
+
if (sunners == 0) {
+ // Show the sunners alert video
_vm->_video->playMovieBlockingRiven(3);
} else if (sunners == 1) {
+ // Show the sunners leaving if you moved forward in their "alert" status
_vm->_video->playMovieBlockingRiven(2);
sunners = 2;
+ _vm->refreshCard();
}
}
@@ -2726,6 +2747,7 @@ void RivenExternal::xtatboundary(uint16 argc, uint16 *argv) {
void RivenExternal::xflies(uint16 argc, uint16 *argv) {
// TODO: Activate the "flies" effect
+ debug(1, "STUB: xflies(): create %d %s fl%s", argv[1], (argv[0] == 0) ? "black" : "glowing", (argv[1] == 1) ? "y" : "ies");
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp
index 946e2e0496..ba5c343e07 100644
--- a/engines/mohawk/riven_vars.cpp
+++ b/engines/mohawk/riven_vars.cpp
@@ -268,7 +268,12 @@ static const char *variableNames[] = {
};
uint32 &MohawkEngine_Riven::getStackVar(uint32 index) {
- return _vars[getName(VariableNames, index)];
+ Common::String name = getName(VariableNames, index);
+
+ if (!_vars.contains(name))
+ error("Could not find variable '%s' (stack variable %d)", name.c_str(), index);
+
+ return _vars[name];
}
void MohawkEngine_Riven::initVars() {
@@ -299,6 +304,7 @@ void MohawkEngine_Riven::initVars() {
_vars["bmagcar"] = 1;
_vars["gnmagcar"] = 1;
_vars["omusicplayer"] = 1;
+ _vars["transitionmode"] = kRivenTransitionSpeedFastest;
// Randomize the telescope combination
uint32 &teleCombo = _vars["tcorrectorder"];
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index 791b18db49..f92bebf10e 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -20,19 +20,20 @@
*
*/
-#include "mohawk/sound.h"
-
#include "common/debug.h"
#include "common/system.h"
#include "common/util.h"
#include "common/textconsole.h"
+#include "audio/midiparser.h"
#include "audio/musicplugin.h"
#include "audio/audiostream.h"
#include "audio/decoders/mp3.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/wave.h"
+#include "mohawk/sound.h"
+
namespace Mohawk {
Sound::Sound(MohawkEngine* vm) : _vm(vm) {
@@ -84,7 +85,7 @@ Audio::AudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
if (_vm->getFeatures() & GF_ME)
audStream = Audio::makeWAVStream(_vm->getResource(ID_MSND, convertMystID(id)), DisposeAfterUse::YES);
else
- audStream = makeMohawkWaveStream(_vm->getResource(ID_MSND, id));
+ audStream = makeMohawkWaveStream(_vm->getResource(ID_MSND, id), cueList);
break;
case GType_ZOOMBINI:
audStream = makeMohawkWaveStream(_vm->getResource(ID_SND, id));
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 593f2fcd0b..12a59cdedf 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -27,14 +27,15 @@
#include "common/str.h"
#include "audio/audiostream.h"
-#include "audio/decoders/adpcm.h"
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
#include "audio/mixer.h"
+#include "audio/decoders/adpcm.h"
#include "mohawk/mohawk.h"
#include "mohawk/resource.h"
+class MidiDriver;
+class MidiParser;
+
namespace Mohawk {
#define MAX_CHANNELS 2 // Can there be more than 2?
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index 3eea1e871a..dacf7715ae 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -560,12 +560,3 @@ protected:
#endif
-
-
-
-
-
-
-
-
-
diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp
index d1361a6e8c..56148d78d8 100644
--- a/engines/parallaction/gui_br.cpp
+++ b/engines/parallaction/gui_br.cpp
@@ -548,4 +548,3 @@ void Parallaction_br::startIngameMenu() {
} // namespace Parallaction
-
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index d0b5e5c175..e875e69334 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -26,10 +26,9 @@
#include "common/util.h"
#include "common/mutex.h"
+#include "audio/mixer.h"
#include "audio/audiostream.h"
#include "audio/decoders/iff_sound.h"
-#include "audio/mixer.h"
-#include "audio/mididrv.h"
#define PATH_LEN 200
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 5d5695ace4..53237db4ef 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -26,8 +26,6 @@
namespace Parallaction {
-#define IS_PATH_CLEAR(x,y) _vm->_gfx->_backgroundInfo->_path->getValue((x), (y))
-
enum {
WALK_LEFT = 0,
WALK_RIGHT = 1,
@@ -56,21 +54,45 @@ WalkFrames _char24WalkFrames_NS = {
{ 2, 2, 4, 4 }
};
+static int getPathWidth() {
+ if (!_vm->_gfx->_backgroundInfo->_path) {
+ warning("getPathWidth() _path is NULL!");
+ return 0;
+ } else
+ return _vm->_gfx->_backgroundInfo->_path->w;
+}
+
+static int getPathHeight() {
+ if (!_vm->_gfx->_backgroundInfo->_path) {
+ warning("getPathHeight() _path is NULL!");
+ return 0;
+ } else
+ return _vm->_gfx->_backgroundInfo->_path->h;
+}
+
+static bool isPathClear(uint16 x, uint16 y) {
+ if (!_vm->_gfx->_backgroundInfo->_path) {
+ warning("isPathClear() _path is NULL!");
+ return false;
+ } else
+ return (_vm->_gfx->_backgroundInfo->_path->getValue(x, y) ? true : false);
+}
+
// adjusts position towards nearest walkable point
void PathWalker_NS::correctPathPoint(Common::Point &to) {
- if (IS_PATH_CLEAR(to.x, to.y)) return;
+ if (isPathClear(to.x, to.y)) return;
- int maxX = _vm->_gfx->_backgroundInfo->_path->w;
- int maxY = _vm->_gfx->_backgroundInfo->_path->h;
+ int maxX = getPathWidth();
+ int maxY = getPathHeight();
int16 right = to.x;
int16 left = to.x;
do {
right++;
- } while ((right < maxX) && !IS_PATH_CLEAR(right, to.y));
+ } while ((right < maxX) && !isPathClear(right, to.y));
do {
left--;
- } while ((left > 0) && !IS_PATH_CLEAR(left, to.y));
+ } while ((left > 0) && !isPathClear(left, to.y));
right = (right == maxX) ? 1000 : right - to.x;
left = (left == 0) ? 1000 : to.x - left;
@@ -78,10 +100,10 @@ void PathWalker_NS::correctPathPoint(Common::Point &to) {
int16 bottom = to.y;
do {
top--;
- } while ((top > 0) && !IS_PATH_CLEAR(to.x, top));
+ } while ((top > 0) && !isPathClear(to.x, top));
do {
bottom++;
- } while ((bottom < maxY) && !IS_PATH_CLEAR(to.x, bottom));
+ } while ((bottom < maxY) && !isPathClear(to.x, bottom));
top = (top == 0) ? 1000 : to.y - top;
bottom = (bottom == maxY) ? 1000 : bottom - to.y;
@@ -203,10 +225,10 @@ uint16 PathWalker_NS::walkFunc1(const Common::Point &to, Common::Point& node) {
while (foot != arg) {
- if (foot.x < to.x && IS_PATH_CLEAR(foot.x + 1, foot.y)) foot.x++;
- if (foot.x > to.x && IS_PATH_CLEAR(foot.x - 1, foot.y)) foot.x--;
- if (foot.y < to.y && IS_PATH_CLEAR(foot.x, foot.y + 1)) foot.y++;
- if (foot.y > to.y && IS_PATH_CLEAR(foot.x, foot.y - 1)) foot.y--;
+ if (foot.x < to.x && isPathClear(foot.x + 1, foot.y)) foot.x++;
+ if (foot.x > to.x && isPathClear(foot.x - 1, foot.y)) foot.x--;
+ if (foot.y < to.y && isPathClear(foot.x, foot.y + 1)) foot.y++;
+ if (foot.y > to.y && isPathClear(foot.x, foot.y - 1)) foot.y--;
if (foot == v8 && foot != arg) {
// foot couldn't move and still away from target
@@ -215,10 +237,10 @@ uint16 PathWalker_NS::walkFunc1(const Common::Point &to, Common::Point& node) {
while (foot != arg) {
- if (foot.x < to.x && !IS_PATH_CLEAR(foot.x + 1, foot.y)) foot.x++;
- if (foot.x > to.x && !IS_PATH_CLEAR(foot.x - 1, foot.y)) foot.x--;
- if (foot.y < to.y && !IS_PATH_CLEAR(foot.x, foot.y + 1)) foot.y++;
- if (foot.y > to.y && !IS_PATH_CLEAR(foot.x, foot.y - 1)) foot.y--;
+ if (foot.x < to.x && !isPathClear(foot.x + 1, foot.y)) foot.x++;
+ if (foot.x > to.x && !isPathClear(foot.x - 1, foot.y)) foot.x--;
+ if (foot.y < to.y && !isPathClear(foot.x, foot.y + 1)) foot.y++;
+ if (foot.y > to.y && !isPathClear(foot.x, foot.y - 1)) foot.y--;
if (foot == v8 && foot != arg)
return 0;
@@ -238,19 +260,19 @@ uint16 PathWalker_NS::walkFunc1(const Common::Point &to, Common::Point& node) {
}
void PathWalker_NS::clipMove(Common::Point& pos, const Common::Point& to) {
- if ((pos.x < to.x) && (pos.x < _vm->_gfx->_backgroundInfo->_path->w) && IS_PATH_CLEAR(pos.x + 2, pos.y)) {
+ if ((pos.x < to.x) && (pos.x < getPathWidth()) && isPathClear(pos.x + 2, pos.y)) {
pos.x = (pos.x + 2 < to.x) ? pos.x + 2 : to.x;
}
- if ((pos.x > to.x) && (pos.x > 0) && IS_PATH_CLEAR(pos.x - 2, pos.y)) {
+ if ((pos.x > to.x) && (pos.x > 0) && isPathClear(pos.x - 2, pos.y)) {
pos.x = (pos.x - 2 > to.x) ? pos.x - 2 : to.x;
}
- if ((pos.y < to.y) && (pos.y < _vm->_gfx->_backgroundInfo->_path->h) && IS_PATH_CLEAR(pos.x, pos.y + 2)) {
+ if ((pos.y < to.y) && (pos.y < getPathHeight()) && isPathClear(pos.x, pos.y + 2)) {
pos.y = (pos.y + 2 <= to.y) ? pos.y + 2 : to.y;
}
- if ((pos.y > to.y) && (pos.y > 0) && IS_PATH_CLEAR(pos.x, pos.y - 2)) {
+ if ((pos.y > to.y) && (pos.y > 0) && isPathClear(pos.x, pos.y - 2)) {
pos.y = (pos.y - 2 >= to.y) ? pos.y - 2 : to.y;
}
}
@@ -368,10 +390,10 @@ bool PathWalker_BR::directPathExists(const Common::Point &from, const Common::Po
Common::Point p(copy);
while (p != to) {
- if (p.x < to.x && IS_PATH_CLEAR(p.x + 1, p.y)) p.x++;
- if (p.x > to.x && IS_PATH_CLEAR(p.x - 1, p.y)) p.x--;
- if (p.y < to.y && IS_PATH_CLEAR(p.x, p.y + 1)) p.y++;
- if (p.y > to.y && IS_PATH_CLEAR(p.x, p.y - 1)) p.y--;
+ if (p.x < to.x && isPathClear(p.x + 1, p.y)) p.x++;
+ if (p.x > to.x && isPathClear(p.x - 1, p.y)) p.x--;
+ if (p.y < to.y && isPathClear(p.x, p.y + 1)) p.y++;
+ if (p.y > to.y && isPathClear(p.x, p.y - 1)) p.y--;
if (p == copy && p != to)
return false;
@@ -620,7 +642,7 @@ void PathWalker_BR::doWalk(State &s) {
assert (!s._walkPath.empty());
Common::Point p(*s._walkPath.begin());
- if (s._startFoot.y < p.y && (s._startFoot.y + yStep) < maxY && IS_PATH_CLEAR(s._startFoot.x, s._startFoot.y + yStep)) {
+ if (s._startFoot.y < p.y && (s._startFoot.y + yStep) < maxY && isPathClear(s._startFoot.x, s._startFoot.y + yStep)) {
if (yStep + s._startFoot.y <= p.y) {
s._stillWalkingTowardsNode = true;
delta.y = yStep;
@@ -631,7 +653,7 @@ void PathWalker_BR::doWalk(State &s) {
}
s._dirFrame = 9;
} else
- if (s._startFoot.y > p.y && (s._startFoot.y - yStep) > minY && IS_PATH_CLEAR(s._startFoot.x, s._startFoot.y - yStep)) {
+ if (s._startFoot.y > p.y && (s._startFoot.y - yStep) > minY && isPathClear(s._startFoot.x, s._startFoot.y - yStep)) {
if (s._startFoot.y - yStep >= p.y) {
s._stillWalkingTowardsNode = true;
delta.y = yStep;
@@ -643,7 +665,7 @@ void PathWalker_BR::doWalk(State &s) {
s._dirFrame = 0;
}
- if (s._startFoot.x < p.x && (s._startFoot.x + xStep) < maxX && IS_PATH_CLEAR(s._startFoot.x + xStep, s._startFoot.y)) {
+ if (s._startFoot.x < p.x && (s._startFoot.x + xStep) < maxX && isPathClear(s._startFoot.x + xStep, s._startFoot.y)) {
if (s._startFoot.x + xStep <= p.x) {
s._stillWalkingTowardsNode = true;
delta.x = xStep;
@@ -656,7 +678,7 @@ void PathWalker_BR::doWalk(State &s) {
s._dirFrame = 18; // right
}
} else
- if (s._startFoot.x > p.x && (s._startFoot.x - xStep) > minX && IS_PATH_CLEAR(s._startFoot.x - xStep, s._startFoot.y)) {
+ if (s._startFoot.x > p.x && (s._startFoot.x - xStep) > minX && isPathClear(s._startFoot.x - xStep, s._startFoot.y)) {
if (s._startFoot.x - xStep >= p.x) {
s._stillWalkingTowardsNode = true;
delta.x = xStep;
diff --git a/engines/queen/command.h b/engines/queen/command.h
index aa72537a9f..6865aa80a2 100644
--- a/engines/queen/command.h
+++ b/engines/queen/command.h
@@ -234,4 +234,3 @@ private:
} // End of namespace Queen
#endif
-
diff --git a/engines/queen/credits.cpp b/engines/queen/credits.cpp
index d503562601..43e3bc7c6a 100644
--- a/engines/queen/credits.cpp
+++ b/engines/queen/credits.cpp
@@ -141,4 +141,3 @@ void Credits::update() {
} // End of namespace Queen
-
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 2f1b61eed8..091ec8d427 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -256,13 +256,7 @@ SaveStateDescriptor SagaMetaEngine::querySaveMetaInfos(const char *target, int s
desc.setWriteProtectedFlag(false);
if (version >= 6) {
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- if (!Graphics::loadThumbnail(*in, *thumbnail)) {
- delete thumbnail;
- thumbnail = 0;
- }
-
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
desc.setThumbnail(thumbnail);
uint32 saveDate = in->readUint32BE();
diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index a29d835a54..3e83c30eef 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -328,7 +328,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformMacintosh,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_ITE,
@@ -352,7 +352,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformMacintosh,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_ITE,
@@ -384,7 +384,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformUnknown,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_ITE,
@@ -414,7 +414,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
Common::IT_ITA,
Common::kPlatformUnknown,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_ITE,
@@ -438,7 +438,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_ITE,
@@ -462,7 +462,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
Common::IT_ITA,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_ITE,
@@ -486,7 +486,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_ITE,
@@ -511,7 +511,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
Common::DE_DEU,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_ITE,
diff --git a/engines/saga/input.cpp b/engines/saga/input.cpp
index 69a353da9f..8576a3e536 100644
--- a/engines/saga/input.cpp
+++ b/engines/saga/input.cpp
@@ -158,4 +158,3 @@ Point SagaEngine::mousePos() const {
}
} // End of namespace Saga
-
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 08c5ddc6f9..fe37ed8995 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -320,7 +320,7 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) {
_disableAbortSpeeches = false;
// set save game reminder alarm
- _vm->getTimerManager()->installTimerProc(&saveReminderCallback, TIMETOSAVE, this);
+ _vm->getTimerManager()->installTimerProc(&saveReminderCallback, TIMETOSAVE, this, "sagaSaveReminder");
}
Interface::~Interface() {
@@ -335,7 +335,7 @@ void Interface::updateSaveReminder() {
_saveReminderState = _saveReminderState % _vm->getDisplayInfo().saveReminderNumSprites + 1;
drawStatusBar();
_vm->getTimerManager()->removeTimerProc(&saveReminderCallback);
- _vm->getTimerManager()->installTimerProc(&saveReminderCallback, ((_vm->getGameId() == GID_ITE) ? TIMETOBLINK_ITE : TIMETOBLINK_IHNM), this);
+ _vm->getTimerManager()->installTimerProc(&saveReminderCallback, ((_vm->getGameId() == GID_ITE) ? TIMETOBLINK_ITE : TIMETOBLINK_IHNM), this, "sagaSaveReminder");
}
}
@@ -1390,7 +1390,7 @@ void Interface::setSave(PanelButton *panelButton) {
void Interface::resetSaveReminder() {
_vm->getTimerManager()->removeTimerProc(&saveReminderCallback);
- _vm->getTimerManager()->installTimerProc(&saveReminderCallback, TIMETOSAVE, this);
+ _vm->getTimerManager()->installTimerProc(&saveReminderCallback, TIMETOSAVE, this, "sagaSaveReminder");
setSaveReminderState(1);
}
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 49d3f91d77..13850a0b6d 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -213,7 +213,7 @@ void Music::setVolume(int volume, int time) {
return;
}
- _vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 3000L, this);
+ _vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 3000L, this, "sagaMusicVolume");
}
bool Music::isPlaying() {
@@ -386,4 +386,3 @@ void Music::stop() {
}
} // End of namespace Saga
-
diff --git a/engines/saga/palanim.h b/engines/saga/palanim.h
index 9959d08e2f..920cbec65a 100644
--- a/engines/saga/palanim.h
+++ b/engines/saga/palanim.h
@@ -53,4 +53,3 @@ class PalAnim {
} // End of namespace Saga
#endif
-
diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp
index d5d83c706f..63d9a88fee 100644
--- a/engines/saga/puzzle.cpp
+++ b/engines/saga/puzzle.cpp
@@ -140,7 +140,7 @@ void Puzzle::initPieceInfo(int i, int16 curX, int16 curY, byte offX, byte offY,
void Puzzle::execute() {
_active = true;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this, "sagaPuzzleHint");
initPieces();
@@ -408,12 +408,12 @@ void Puzzle::solicitHint() {
switch (_hintRqState) {
case kRQSpeaking:
if (_vm->_actor->isSpeaking()) {
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50 * 1000000, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50 * 1000000, this, "sagaPuzzleHint");
break;
}
_hintRqState = _hintNextRqState;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 100*1000000/3, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 100*1000000/3, this, "sagaPuzzleHint");
break;
case kRQNoHint:
@@ -436,11 +436,11 @@ void Puzzle::solicitHint() {
// Roll to see if Sakka scolds
if (_vm->_rnd.getRandomNumber(1)) {
_hintRqState = kRQSakkaDenies;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 200*1000000, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 200*1000000, this, "sagaPuzzleHint");
} else {
_hintRqState = kRQSpeaking;
_hintNextRqState = kRQHintRequested;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this, "sagaPuzzleHint");
}
break;
@@ -453,7 +453,7 @@ void Puzzle::solicitHint() {
_hintRqState = kRQSpeaking;
_hintNextRqState = kRQHintRequestedStage2;
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this, "sagaPuzzleHint");
_vm->_interface->converseClear();
_vm->_interface->converseAddText(optionsStr[_lang][kROAccept], 0, 1, 0, 0);
@@ -480,7 +480,7 @@ void Puzzle::solicitHint() {
_vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0, 0);
_vm->_interface->converseDisplayText();
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this, "sagaPuzzleHint");
_hintRqState = kRQSkipEverything;
break;
@@ -504,7 +504,7 @@ void Puzzle::handleReply(int reply) {
_vm->_actor->abortSpeech();
_hintRqState = kRQNoHint;
_vm->getTimerManager()->removeTimerProc(&hintTimerCallback);
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, kPuzzleHintTime * 2, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, kPuzzleHintTime * 2, this, "sagaPuzzleHint");
clearHint();
break;
}
@@ -566,7 +566,7 @@ void Puzzle::giveHint() {
_vm->_interface->converseDisplayText();
_vm->getTimerManager()->removeTimerProc(&hintTimerCallback);
- _vm->getTimerManager()->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
+ _vm->getTimerManager()->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this, "sagaPuzzleHint");
}
void Puzzle::clearHint() {
diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp
index 757374a3a3..a9ef23381e 100644
--- a/engines/saga/render.cpp
+++ b/engines/saga/render.cpp
@@ -50,7 +50,7 @@ Render::Render(SagaEngine *vm, OSystem *system) {
#ifdef SAGA_DEBUG
// Initialize FPS timer callback
- _vm->getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this);
+ _vm->getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this, "sagaFPS");
#endif
_backGroundSurface.create(_vm->getDisplayInfo().width, _vm->getDisplayInfo().height, Graphics::PixelFormat::createFormatCLUT8());
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 336883680a..fb01b1ac5d 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -29,7 +29,6 @@
#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 8d7b718c09..9e0789fdaf 100644
--- a/engines/saga/saveload.cpp
+++ b/engines/saga/saveload.cpp
@@ -295,12 +295,7 @@ void SagaEngine::load(const char *fileName) {
if (_saveHeader.version >= 6) {
// We don't need the thumbnail here, so just read it and discard it
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- Graphics::loadThumbnail(*in, *thumbnail);
- thumbnail->free();
- delete thumbnail;
- thumbnail = 0;
+ Graphics::skipThumbnail(*in);
in->readUint32BE(); // save date
in->readUint16BE(); // save time
diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp
index 39af7aa3db..5efc8d1f67 100644
--- a/engines/saga/shorten.cpp
+++ b/engines/saga/shorten.cpp
@@ -541,4 +541,3 @@ Audio::AudioStream *makeShortenStream(Common::SeekableReadStream &stream) {
} // End of namespace Audio
#endif // defined(SOUND_SHORTEN_H)
-
diff --git a/engines/saga/shorten.h b/engines/saga/shorten.h
index f2114bedeb..77feafa54d 100644
--- a/engines/saga/shorten.h
+++ b/engines/saga/shorten.h
@@ -57,4 +57,3 @@ Audio::AudioStream *makeShortenStream(Common::ReadStream &stream);
#endif
#endif // engine and dynamic plugins guard
-
diff --git a/engines/saga/sthread.cpp b/engines/saga/sthread.cpp
index ec81d8d733..afd528f4b5 100644
--- a/engines/saga/sthread.cpp
+++ b/engines/saga/sthread.cpp
@@ -236,4 +236,3 @@ bool Script::runThread(ScriptThread &thread) {
}
} // End of namespace Saga
-
diff --git a/engines/savestate.cpp b/engines/savestate.cpp
index 0b187ce630..260c7cd3ff 100644
--- a/engines/savestate.cpp
+++ b/engines/savestate.cpp
@@ -58,4 +58,3 @@ void SaveStateDescriptor::setPlayTime(uint32 msecs) {
uint minutes = msecs / 60000;
setPlayTime(minutes / 60, minutes % 60);
}
-
diff --git a/engines/sci/decompressor.h b/engines/sci/decompressor.h
index 37a5b5d7cb..5753026709 100644
--- a/engines/sci/decompressor.h
+++ b/engines/sci/decompressor.h
@@ -197,4 +197,3 @@ protected:
} // End of namespace Sci
#endif // SCI_SCICORE_DECOMPRESSOR_H
-
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 2285e512bd..33ca3a6c9c 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -285,7 +285,7 @@ static const OldNewIdTableEntry s_oldNewTable[] = {
* @param[in] gameFlags The game's flags, which are adjusted accordingly for demos
* @return The equivalent ScummVM game id
*/
-Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, ResourceManager *resMan) {
+Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, ResourceManager &resMan) {
// Convert the id to lower case, so that we match all upper/lower case variants.
sierraId.toLowercase();
@@ -301,7 +301,7 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R
if (sierraId == "fp" || sierraId == "gk" || sierraId == "pq4")
demoThreshold = 150;
- Common::ScopedPtr<Common::List<ResourceId> > resources(resMan->listResources(kResourceTypeScript, -1));
+ Common::ScopedPtr<Common::List<ResourceId> > resources(resMan.listResources(kResourceTypeScript, -1));
if (resources->size() < demoThreshold) {
*gameFlags |= ADGF_DEMO;
@@ -337,7 +337,7 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R
// This could either be qfg1 VGA, qfg3 or qfg4 demo (all SCI1.1),
// or qfg4 full (SCI2)
// qfg1 VGA doesn't have view 1
- if (!resMan->testResource(ResourceId(kResourceTypeView, 1)))
+ if (!resMan.testResource(ResourceId(kResourceTypeView, 1)))
return "qfg1vga";
// qfg4 full is SCI2
@@ -480,10 +480,9 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
return 0;
}
- Common::ScopedPtr<ResourceManager> resMan(new ResourceManager());
- assert(resMan);
- resMan->addAppropriateSources(fslist);
- resMan->init(true);
+ ResourceManager resMan;
+ resMan.addAppropriateSources(fslist);
+ resMan.init(true);
// TODO: Add error handling.
#ifndef ENABLE_SCI32
@@ -494,7 +493,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
}
#endif
- ViewType gameViews = resMan->getViewType();
+ ViewType gameViews = resMan.getViewType();
// Have we identified the game views? If not, stop here
// Can't be SCI (or unsupported SCI views). Pinball Creep by sierra also uses resource.map/resource.000 files
@@ -508,7 +507,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
s_fallbackDesc.platform = Common::kPlatformAmiga;
// Determine the game id
- Common::String sierraGameId = resMan->findSierraGameId();
+ Common::String sierraGameId = resMan.findSierraGameId();
// If we don't have a game id, the game is not SCI
if (sierraGameId.empty()) {
@@ -530,7 +529,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
// As far as we know, these games store the messages of each language in separate
// resources, and it's not possible to detect that easily
// Also look for "%J" which is used in japanese games
- Resource *text = resMan->findResource(ResourceId(kResourceTypeText, 0), 0);
+ Resource *text = resMan.findResource(ResourceId(kResourceTypeText, 0), 0);
uint seeker = 0;
if (text) {
while (seeker < text->size) {
@@ -588,7 +587,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
s_fallbackDesc.extra = "CD";
}
- return (const ADGameDescription *)&s_fallbackDesc;
+ return &s_fallbackDesc;
}
bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
@@ -677,13 +676,7 @@ SaveStateDescriptor SciMetaEngine::querySaveMetaInfos(const char *target, int sl
SaveStateDescriptor desc(slot, meta.name);
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- if (!Graphics::loadThumbnail(*in, *thumbnail)) {
- delete thumbnail;
- thumbnail = 0;
- }
-
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
desc.setThumbnail(thumbnail);
desc.setDeletableFlag(true);
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 3b18a1f68d..a3dd305222 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -2649,6 +2649,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO_NONE },
+ // Police Quest 4 - German DOS CD (German text, English speech)
+ // Supplied by markcoolio in bug report #3392955
+ {"pq4", "CD", {
+ {"resource.map", 0, "a398076371ed0e1e706c8f9fb9fc7ac5", 11386},
+ {"resource.000", 0, "6ff21954e0a2c5992279e7eb787c8d56", 18918747},
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformPC, ADGF_CD | ADGF_UNSTABLE, GUIO_NONE },
+
// Police Quest 4 - English DOS
// SCI interpreter version 2.000.000 (a guess?)
{"pq4", "", {
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index b383f88840..783845bb76 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -42,6 +42,14 @@ reg_t kStrCat(EngineState *s, int argc, reg_t *argv) {
Common::String s1 = s->_segMan->getString(argv[0]);
Common::String s2 = s->_segMan->getString(argv[1]);
+ // The Japanese version of PQ2 splits the two strings here
+ // (check bug #3396887).
+ if (g_sci->getGameId() == GID_PQ2 &&
+ g_sci->getLanguage() == Common::JA_JPN) {
+ s1 = g_sci->strSplit(s1.c_str(), NULL);
+ s2 = g_sci->strSplit(s2.c_str(), NULL);
+ }
+
s1 += s2;
s->_segMan->strcpy(argv[0], s1.c_str());
return argv[0];
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index a714980a35..7efcb42f4b 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -855,26 +855,8 @@ const uint16 qfg3PatchImportDialog[] = {
PATCH_END
};
-// Script 23 in QFG3 has a typo/bug which makes it loop endlessly and
-// read garbage. Fixes bug #3040722.
-const byte qfg3DialogCrash[] = {
- 5,
- 0x34, 0xe7, 0x03, // ldi 3e7 (999)
- 0x22, // lt?
- 0x33, // jmp [back] ---> BUG! Infinite loop
- 0
-};
-
-const uint16 qfg3PatchDialogCrash[] = {
- 0x34, 0xe7, 0x03, // ldi 3e7 (999)
- 0x22, // lt?
- 0x31, // bnt [back]
- PATCH_END
-};
-
// script, description, magic DWORD, adjust
const SciScriptSignature qfg3Signatures[] = {
- { 23, "dialog crash", 1, PATCH_MAGICDWORD(0xe7, 0x03, 0x22, 0x33), -1, qfg3DialogCrash, qfg3PatchDialogCrash },
{ 944, "import dialog continuous calls", 1, PATCH_MAGICDWORD(0x2a, 0x31, 0x0b, 0x7a), -1, qfg3SignatureImportDialog, qfg3PatchImportDialog },
SCI_SIGNATUREENTRY_TERMINATOR
};
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index ab67da32db..1510af8508 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -28,12 +28,6 @@
namespace Sci {
-enum {
- DEFAULT_SCRIPTS = 32,
- DEFAULT_OBJECTS = 8, ///< default number of objects per script
- DEFAULT_OBJECTS_INCREMENT = 4 ///< Number of additional objects to instantiate if we're running out of them
-};
-
SegManager::SegManager(ResourceManager *resMan) {
_heap.push_back(0);
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index b2cde47f4a..968afcb11c 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -209,6 +209,8 @@ const SciWorkaroundEntry kDeviceInfo_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kDisplay_workarounds[] = {
{ GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object
+ { GID_PQ1, 500, 500, 0, "endInter", "changeState", 0x3e8, 0, { WORKAROUND_IGNORE, 0 } }, // restoring a game at the map scene (bug #3389579)
+ { GID_PQ1, 500, 500, 0, "endInter", "changeState", 0x46b, 0, { WORKAROUND_IGNORE, 0 } }, // restoring a game at the map scene (bug #3389579)
{ GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4ae, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id
{ GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4c1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id (another pq2 version, bug #3043904)
{ GID_QFG1, 11, 11, 0, "battle", "<noname90>", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index c5a3545701..38919593b4 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -683,7 +683,7 @@ bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) {
void GfxPalette::palVaryInstallTimer() {
int16 ticks = _palVaryTicks > 0 ? _palVaryTicks : 1;
// Call signal increase every [ticks]
- g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this);
+ g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this, "sciPalette");
}
void GfxPalette::palVaryRemoveTimer() {
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index dbe2135143..6469bc0cb3 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -20,9 +20,9 @@
*
*/
-#include "common/timer.h"
#include "common/util.h"
#include "common/system.h"
+#include "common/timer.h"
#include "graphics/surface.h"
#include "engines/util.h"
diff --git a/engines/sci/parser/said.cpp b/engines/sci/parser/said.cpp
index 01c25ef401..d44109faec 100644
--- a/engines/sci/parser/said.cpp
+++ b/engines/sci/parser/said.cpp
@@ -1147,4 +1147,3 @@ True
} // End of namespace Sci
-
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index f18b6c91f5..1b8b7b2f0e 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -1721,15 +1721,19 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
if (!resource) {
addResource(resId, source, fileOffset);
} else {
- // if resource is already present, change it to new content
- // this is needed at least for pharkas/german. This version
- // contains several duplicate resources INSIDE the resource
- // data files like fonts, views, scripts, etc. And if we use
- // the first entries, half of the game will be english and
- // umlauts will also be missing :P
- resource->_source = source;
- resource->_fileOffset = fileOffset;
- resource->size = 0;
+ // If the resource is already present in a volume, change it to
+ // the new content (but only in a volume, so as not to overwrite
+ // external patches - refer to bug #3366295).
+ // This is needed at least for the German version of Pharkas.
+ // That version contains several duplicate resources INSIDE the
+ // resource data files like fonts, views, scripts, etc. Thus,
+ // if we use the first entries in the resource file, half of the
+ // game will be English and umlauts will also be missing :P
+ if (resource->_source->getSourceType() == kSourceVolume) {
+ resource->_source = source;
+ resource->_fileOffset = fileOffset;
+ resource->size = 0;
+ }
}
}
}
diff --git a/engines/sci/sound/drivers/cms.cpp b/engines/sci/sound/drivers/cms.cpp
index ace96ba499..dbcbf3d431 100644
--- a/engines/sci/sound/drivers/cms.cpp
+++ b/engines/sci/sound/drivers/cms.cpp
@@ -813,4 +813,3 @@ MidiPlayer *MidiPlayer_CMS_create(SciVersion version) {
}
} // End of namespace SCI
-
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index 95b165468d..f48a68dc66 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -626,7 +626,11 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
if (info.ext.type == 0x2F) {// end of track reached
if (_pSnd->loop)
_pSnd->loop--;
- if (_pSnd->loop) {
+ // QFG3 abuses the hold flag. Its scripts call kDoSoundSetHold,
+ // but sometimes there's no hold marker in the associated songs
+ // (e.g. song 110, during the intro). The original interpreter
+ // treats this case as an infinite loop (bug #3311911).
+ if (_pSnd->loop || _pSnd->hold > 0) {
// We need to play it again...
jumpToTick(_loopTick);
} else {
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 4ea290ff9e..d4cff7614c 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -49,11 +49,22 @@ reg_t SoundCommandParser::kDoSoundInit(int argc, reg_t *argv, reg_t acc) {
return acc;
}
-void SoundCommandParser::processInitSound(reg_t obj) {
- int resourceId = readSelectorValue(_segMan, obj, SELECTOR(number));
+int SoundCommandParser::getSoundResourceId(reg_t obj) {
+ int resourceId = obj.segment ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1;
// Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did.
- if (g_sci && g_sci->_features->useAltWinGMSound())
- resourceId += 1000;
+ if (g_sci && g_sci->_features->useAltWinGMSound()) {
+ // Check if the alternate MIDI song actually exists...
+ // There are cases where it just doesn't exist (e.g. SQ4, room 530 -
+ // bug #3392767). In these cases, use the DOS tracks instead.
+ if (resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, resourceId + 1000)))
+ resourceId += 1000;
+ }
+
+ return resourceId;
+}
+
+void SoundCommandParser::processInitSound(reg_t obj) {
+ int resourceId = getSoundResourceId(obj);
// Check if a track with the same sound object is already playing
MusicEntry *oldSound = _music->getSlot(obj);
@@ -123,10 +134,7 @@ void SoundCommandParser::processPlaySound(reg_t obj) {
return;
}
- int resourceId = obj.segment ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1;
- // Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did.
- if (g_sci && g_sci->_features->useAltWinGMSound())
- resourceId += 1000;
+ int resourceId = getSoundResourceId(obj);
if (musicSlot->resourceId != resourceId) { // another sound loaded into struct
processDisposeSound(obj);
@@ -618,13 +626,10 @@ reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc)
}
if (value == -1) {
- uint16 resourceNr = musicSlot->resourceId;
- // Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did.
- if (g_sci && g_sci->_features->useAltWinGMSound())
- resourceNr += 1000;
+ uint16 resourceId = musicSlot->resourceId;
// Set priority from the song data
- Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceNr), 0);
+ Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceId), 0);
if (song->data[0] == 0xf0)
_music->soundSetPriority(musicSlot, song->data[1]);
else
diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h
index a542a8b384..7f6e2a0fe8 100644
--- a/engines/sci/sound/soundcmd.h
+++ b/engines/sci/sound/soundcmd.h
@@ -113,6 +113,7 @@ private:
void processInitSound(reg_t obj);
void processDisposeSound(reg_t obj);
void processUpdateCues(reg_t obj);
+ int getSoundResourceId(reg_t obj);
};
} // End of namespace Sci
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index a8adb4d5c5..6739282c9d 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -22,6 +22,9 @@
#include "common/system.h"
#include "common/util.h"
#include "graphics/cursorman.h"
+#ifdef ENABLE_HE
+#include "graphics/wincursor.h"
+#endif
#include "scumm/bomp.h"
#include "scumm/charset.h"
#include "scumm/he/intern_he.h"
@@ -177,12 +180,8 @@ void ScummEngine_v70he::setDefaultCursor() {
0xff, 0xff, 0xff,
0, 0, 0, };
- if (_bytesPerPixel == 2) {
- for (i = 0; i < 1024; i++)
- WRITE_UINT16(_grabbedCursor + i * 2, 5);
- } else {
- memset(_grabbedCursor, 5, sizeof(_grabbedCursor));
- }
+
+ memset(_grabbedCursor, 5, sizeof(_grabbedCursor));
_cursor.hotspotX = _cursor.hotspotY = 2;
src = default_he_cursor;
@@ -195,16 +194,10 @@ void ScummEngine_v70he::setDefaultCursor() {
for (j = 0; j < 32; j++) {
switch ((p & (0x3 << 14)) >> 14) {
case 1:
- if (_bytesPerPixel == 2)
- WRITE_UINT16(_grabbedCursor + 64 * i + j * 2, get16BitColor(palette[4], palette[5], palette[6]));
- else
- _grabbedCursor[32 * i + j] = 0xfe;
+ _grabbedCursor[32 * i + j] = 0xfe;
break;
case 2:
- if (_bytesPerPixel == 2)
- WRITE_UINT16(_grabbedCursor + 64 * i + j * 2, get16BitColor(palette[0], palette[1], palette[2]));
- else
- _grabbedCursor[32 * i + j] = 0xfd;
+ _grabbedCursor[32 * i + j] = 0xfd;
break;
default:
break;
@@ -216,15 +209,63 @@ void ScummEngine_v70he::setDefaultCursor() {
}
}
+ // Since white color position is not guaranteed
+ // we setup our own palette if supported by backend
+ CursorMan.disableCursorPalette(false);
+ CursorMan.replaceCursorPalette(palette, 0xfd, 3);
+
+ updateCursor();
+}
+
+#ifdef ENABLE_HE
+void ScummEngine_v80he::setDefaultCursor() {
+ // v80+ games use the default Windows cursor instead of the usual
+ // default HE cursor.
+ Graphics::Cursor *cursor = Graphics::makeDefaultWinCursor();
+
+ // Clear the cursor
+ if (_bytesPerPixel == 2) {
+ for (int i = 0; i < 1024; i++)
+ WRITE_UINT16(_grabbedCursor + i * 2, 5);
+ } else {
+ memset(_grabbedCursor, 5, sizeof(_grabbedCursor));
+ }
+
+ _cursor.width = cursor->getWidth();
+ _cursor.height = cursor->getHeight();
+ _cursor.hotspotX = cursor->getHotspotX();
+ _cursor.hotspotY = cursor->getHotspotY();
+
+ const byte *surface = cursor->getSurface();
+ const byte *palette = cursor->getPalette();
+
+ for (uint16 y = 0; y < _cursor.height; y++) {
+ for (uint16 x = 0; x < _cursor.width; x++) {
+ byte pixel = *surface++;
+
+ if (pixel != cursor->getKeyColor()) {
+ pixel -= cursor->getPaletteStartIndex();
+
+ if (_bytesPerPixel == 2)
+ WRITE_UINT16(_grabbedCursor + (y * _cursor.width + x) * 2, get16BitColor(palette[pixel * 3], palette[pixel * 3 + 1], palette[pixel * 3 + 2]));
+ else
+ _grabbedCursor[y * _cursor.width + x] = (pixel == 0) ? 0xfd : 0xfe;
+ }
+ }
+ }
+
if (_bytesPerPixel == 1) {
// Since white color position is not guaranteed
// we setup our own palette if supported by backend
CursorMan.disableCursorPalette(false);
- CursorMan.replaceCursorPalette(palette, 0xfd, 3);
+ CursorMan.replaceCursorPalette(palette, 0xfd, cursor->getPaletteCount());
}
+ delete cursor;
+
updateCursor();
}
+#endif
void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) {
int w, h;
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index d3514645d3..037c12bdbf 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -33,6 +33,8 @@
#include "common/savefile.h"
#include "common/system.h"
+#include "audio/mididrv.h"
+
#include "scumm/detection.h"
#include "scumm/detection_tables.h"
#include "scumm/he/intern_he.h"
@@ -145,7 +147,7 @@ Common::String ScummEngine_v70he::generateFilename(const int room) const {
Common::String bPattern = _filenamePattern.pattern;
// Special cases for Blue's games, which share common (b) files
- if (_game.id == GID_BIRTHDAY && !(_game.features & GF_DEMO))
+ if (_game.id == GID_BIRTHDAYYELLOW || _game.id == GID_BIRTHDAYRED)
bPattern = "Blue'sBirthday";
else if (_game.id == GID_TREASUREHUNT)
bPattern = "Blue'sTreasureHunt";
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 11901f7565..78645ea8d5 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -222,7 +222,7 @@ static const GameSettings gameVariantsTable[] = {
{"indy3", "EGA", "ega", GID_INDY3, 3, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
{"indy3", "No AdLib", "ega", GID_INDY3, 3, 0, MDT_PCSPK | MDT_PCJR, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
- {"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_PCJR | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
+ {"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
{"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI | GUIO_MIDITOWNS},
{"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
@@ -233,9 +233,9 @@ static const GameSettings gameVariantsTable[] = {
{"loom", "FM-TOWNS", 0, GID_LOOM, 3, 0, MDT_TOWNS, GF_AUDIOTRACKS | GF_OLD256, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI | GUIO_MIDITOWNS},
{"loom", "VGA", "vga", GID_LOOM, 4, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
- {"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
+ {"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
- {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
+ {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
{"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH},
{"monkey", "No AdLib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR, GF_16COLOR, Common::kPlatformAtariST, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
@@ -343,7 +343,9 @@ static const GameSettings gameVariantsTable[] = {
{"puttrace", "HE 99", 0, GID_PUTTRACE, 6, 99, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
{"bluesabctime", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
- {"BluesBirthday", 0, 0, GID_BIRTHDAY, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
+ {"BluesBirthday", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
+ {"BluesBirthday", "Red", 0, GID_BIRTHDAYRED, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
+ {"BluesBirthday", "Yellow", 0, GID_BIRTHDAYYELLOW, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
{"soccer", "", 0, GID_SOCCER, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOLAUNCHLOAD | GUIO_NOMIDI},
// Global scripts increased to 2048
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index f7f0c7d7ec..74a92f2204 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -23,6 +23,7 @@
#include "common/savefile.h"
#include "common/system.h"
#include "common/events.h"
+#include "common/localization.h"
#include "common/translation.h"
#include "graphics/scaler.h"
@@ -171,29 +172,33 @@ static const ResString string_map_table_v6[] = {
};
static const ResString string_map_table_v345[] = {
- {1, "Insert Disk %c and Press Button to Continue."},
- {2, "Unable to Find %s, (%c%d) Press Button."},
- {3, "Error reading disk %c, (%c%d) Press Button."},
- {4, "Game Paused. Press SPACE to Continue."},
- {5, "Are you sure you want to restart? (Y/N)"},
- {6, "Are you sure you want to quit? (Y/N)"},
+ {1, _s("Insert Disk %c and Press Button to Continue.")},
+ {2, _s("Unable to Find %s, (%c%d) Press Button.")},
+ {3, _s("Error reading disk %c, (%c%d) Press Button.")},
+ {4, _s("Game Paused. Press SPACE to Continue.")},
+ // I18N: You may specify 'Yes' symbol at the end of the line, like this:
+ // "Moechten Sie wirklich neu starten? (J/N)J"
+ // Will react to J as 'Yes'
+ {5, _s("Are you sure you want to restart? (Y/N)")},
+ // I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
+ {6, _s("Are you sure you want to quit? (Y/N)")},
// Added in SCUMM4
- {7, "Save"},
- {8, "Load"},
- {9, "Play"},
- {10, "Cancel"},
- {11, "Quit"},
- {12, "OK"},
- {13, "Insert save/load game disk"},
- {14, "You must enter a name"},
- {15, "The game was NOT saved (disk full?)"},
- {16, "The game was NOT loaded"},
- {17, "Saving '%s'"},
- {18, "Loading '%s'"},
- {19, "Name your SAVE game"},
- {20, "Select a game to LOAD"},
- {28, "Game title"}
+ {7, _s("Save")},
+ {8, _s("Load")},
+ {9, _s("Play")},
+ {10, _s("Cancel")},
+ {11, _s("Quit")},
+ {12, _s("OK")},
+ {13, _s("Insert save/load game disk")},
+ {14, _s("You must enter a name")},
+ {15, _s("The game was NOT saved (disk full?)")},
+ {16, _s("The game was NOT loaded")},
+ {17, _s("Saving '%s'")},
+ {18, _s("Loading '%s'")},
+ {19, _s("Name your SAVE game")},
+ {20, _s("Select a game to LOAD")},
+ {28, _s("Game title)")}
};
#pragma mark -
@@ -278,7 +283,9 @@ HelpDialog::HelpDialog(const GameSettings &game)
_numPages = ScummHelp::numPages(_game.id);
+ // I18N: Previous page button
_prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", _("~P~revious"), 0, kPrevCmd);
+ // I18N: Next page button
_nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", _("~N~ext"), 0, kNextCmd);
new GUI::ButtonWidget(this, "ScummHelp.Close", _("~C~lose"), 0, GUI::kCloseCmd);
_prevButton->clearFlags(WIDGET_ENABLED);
@@ -429,7 +436,7 @@ const Common::String InfoDialog::queryResString(int stringno) {
else if (_vm->_game.version >= 3)
result = _vm->getStringAddress(string_map_table_v345[stringno - 1].num);
else
- return string_map_table_v345[stringno - 1].string;
+ return _(string_map_table_v345[stringno - 1].string);
if (result && *result == '/') {
_vm->translateText(result, buf);
@@ -437,7 +444,7 @@ const Common::String InfoDialog::queryResString(int stringno) {
}
if (!result || *result == '\0') { // Gracelessly degrade to english :)
- return string_map_table_v345[stringno - 1].string;
+ return _(string_map_table_v345[stringno - 1].string);
}
// Convert to a proper string (take care of FF codes)
@@ -482,10 +489,14 @@ ConfirmDialog::ConfirmDialog(ScummEngine *scumm, int res)
}
void ConfirmDialog::handleKeyDown(Common::KeyState state) {
- if (state.keycode == Common::KEYCODE_n || state.ascii == _noKey) {
+ Common::KeyCode keyYes, keyNo;
+
+ Common::getLanguageYesNo(keyYes, keyNo);
+
+ if (state.keycode == Common::KEYCODE_n || state.ascii == _noKey || state.ascii == keyNo) {
setResult(0);
close();
- } else if (state.keycode == Common::KEYCODE_y || state.ascii == _yesKey) {
+ } else if (state.keycode == Common::KEYCODE_y || state.ascii == _yesKey || state.ascii == keyYes) {
setResult(1);
close();
} else
@@ -583,9 +594,9 @@ void SubtitleSettingsDialog::open() {
void SubtitleSettingsDialog::cycleValue() {
static const char* subtitleDesc[] = {
- "Speech Only",
- "Speech and Subtitles",
- "Subtitles Only"
+ _s("Speech Only"),
+ _s("Speech and Subtitles"),
+ _s("Subtitles Only")
};
_value += 1;
@@ -593,9 +604,9 @@ void SubtitleSettingsDialog::cycleValue() {
_value = 0;
if (_value == 1 && g_system->getOverlayWidth() <= 320)
- setInfoText("Speech & Subs");
+ setInfoText(_sc("Speech & Subs", "lowres"));
else
- setInfoText(subtitleDesc[_value]);
+ setInfoText(_(subtitleDesc[_value]));
_timer = g_system->getMillis() + 1500;
}
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index f22547f193..8a32b963cd 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -4111,4 +4111,3 @@ void ScummEngine::unkScreenEffect6() {
}
} // End of namespace Scumm
-
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index c49217b650..f4df6571fa 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -383,6 +383,8 @@ protected:
void drawLine(int x1, int y1, int x, int unk1, int unk2, int type, int id);
void drawPixel(int x, int y, int flags);
+ virtual void setDefaultCursor();
+
/* HE version 80 script opcodes */
void o80_createSound();
void o80_getFileSize();
diff --git a/engines/scumm/he/logic/baseball2001.cpp b/engines/scumm/he/logic/baseball2001.cpp
new file mode 100644
index 0000000000..342423fd79
--- /dev/null
+++ b/engines/scumm/he/logic/baseball2001.cpp
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/he/intern_he.h"
+#include "scumm/he/logic_he.h"
+
+namespace Scumm {
+
+/**
+ * Logic code for:
+ * Backyard Baseball 2001
+ */
+class LogicHEbaseball2001 : public LogicHE {
+public:
+ LogicHEbaseball2001(ScummEngine_v90he *vm) : LogicHE(vm) {}
+
+ int versionID();
+ int32 dispatch(int op, int numArgs, int32 *args);
+};
+
+int LogicHEbaseball2001::versionID() {
+ return 1;
+}
+
+int32 LogicHEbaseball2001::dispatch(int op, int numArgs, int32 *args) {
+ int res = 0;
+
+ switch (op) {
+ case 3001:
+ // Check network status
+ break;
+
+ default:
+ LogicHE::dispatch(op, numArgs, args);
+ }
+
+ return res;
+}
+
+LogicHE *makeLogicHEbaseball2001(ScummEngine_v90he *vm) {
+ return new LogicHEbaseball2001(vm);
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/logic/basketball.cpp b/engines/scumm/he/logic/basketball.cpp
new file mode 100644
index 0000000000..8352aa4357
--- /dev/null
+++ b/engines/scumm/he/logic/basketball.cpp
@@ -0,0 +1,230 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/he/intern_he.h"
+#include "scumm/he/logic_he.h"
+
+namespace Scumm {
+
+/**
+ * Logic code for:
+ * Backyard Basketball
+ */
+class LogicHEbasketball : public LogicHE {
+public:
+ LogicHEbasketball(ScummEngine_v90he *vm) : LogicHE(vm) {}
+
+ int versionID();
+ int32 dispatch(int op, int numArgs, int32 *args);
+
+private:
+ int op_1012();
+ int op_1050(int32 *args);
+ int op_1053();
+
+ // op_1050 loads court object data
+ enum CourtObjectType {
+ kObjectTypeBackboard = 1,
+ kObjectTypeRim = 2,
+ kObjectTypeOther = 3,
+ kObjectTypeFloor = 4
+ };
+
+ struct CourtObject {
+ Common::String name;
+ CourtObjectType type;
+ uint32 data[10];
+ };
+
+ Common::Array<CourtObject> _courtObjects;
+ uint32 _backboardObjectLeft, _backboardObjectRight;
+};
+
+int LogicHEbasketball::versionID() {
+ return 1;
+}
+
+int32 LogicHEbasketball::dispatch(int op, int numArgs, int32 *args) {
+ int res = 0;
+
+ switch (op) {
+ case 1001:
+ break;
+
+ case 1006:
+ break;
+
+ case 1011:
+ break;
+
+ case 1012:
+ res = op_1012();
+ break;
+
+ case 1035:
+ break;
+
+ case 1050:
+ res = op_1050(args);
+ break;
+
+ case 1051:
+ break;
+
+ case 1052:
+ break;
+
+ case 1053:
+ res = op_1053();
+ break;
+
+ case 1056:
+ break;
+
+ case 1057:
+ break;
+
+ case 1058:
+ break;
+
+ case 1060:
+ break;
+
+ case 1064:
+ break;
+
+ case 1067:
+ break;
+
+ case 1073:
+ break;
+
+ case 1075:
+ break;
+
+ case 1076:
+ break;
+
+ case 1080:
+ break;
+
+ case 1081:
+ break;
+
+ case 1090:
+ break;
+
+ case 1091:
+ break;
+
+ case 1513:
+ break;
+
+ default:
+ LogicHE::dispatch(op, numArgs, args);
+ }
+
+ return res;
+}
+
+int LogicHEbasketball::op_1012() {
+ writeScummVar(108, 12000);
+ writeScummVar(109, 8000);
+ writeScummVar(110, 760);
+ writeScummVar(111, 4000);
+ writeScummVar(112, 1600);
+ return 1;
+}
+
+int LogicHEbasketball::op_1050(int32 *args) {
+ // This function loads the court data
+ static const char *courtNames[] = {
+ "Dobbaguchi", "Jocindas", "SandyFlats", "Queens",
+ "Park", "Scheffler", "Polk", "McMillan",
+ "CrownHill", "Memorial", "TechState", "Garden",
+ "Moon", "Barn"
+ };
+
+ Common::String courtFileName = Common::String::format("data/courts/%s.cof", courtNames[args[0] - 1]);
+
+ Common::File file;
+ if (!file.open(courtFileName))
+ error("Could not open file '%s'", courtFileName.c_str());
+
+ debug(0, "Loading court data from '%s'", courtFileName.c_str());
+
+ // First, read in the header
+ file.readUint32LE(); // Header size (?)
+
+ char version[6];
+ file.read(version, 5);
+ version[5] = 0;
+
+ if (strcmp(version, "01.05"))
+ error("Invalid court version field: %s", version);
+
+ uint32 objectCount = file.readUint32LE();
+
+ for (uint32 i = 0; i < objectCount; i++) {
+ char nameBuf[100];
+ memset(nameBuf, 0, sizeof(nameBuf));
+
+ uint32 nameLength = file.readUint32LE();
+ assert(nameLength < sizeof(nameBuf) - 1);
+ file.read(nameBuf, nameLength);
+
+ CourtObject object;
+ object.name = nameBuf;
+ object.type = (CourtObjectType)file.readUint32LE();
+ for (uint32 j = 0; j < 10; j++)
+ object.data[j] = file.readUint32LE();
+
+ debug(1, "Found court object '%s' - Type %d", nameBuf, object.type);
+
+ // Store backboard object indices for later
+ if (object.type == kObjectTypeBackboard) {
+ if (object.data[7] + object.data[4] / 2 >= 6000)
+ _backboardObjectRight = i;
+ else
+ _backboardObjectLeft = i;
+ }
+
+ _courtObjects.push_back(object);
+ }
+
+ // TODO: Some other variables are initialized with constants here
+
+ return 1;
+}
+
+int LogicHEbasketball::op_1053() {
+ _courtObjects.clear();
+ // TODO: This also calls op_1065 with one argument (5)
+
+ return 1;
+}
+
+LogicHE *makeLogicHEbasketball(ScummEngine_v90he *vm) {
+ return new LogicHEbasketball(vm);
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/logic/football.cpp b/engines/scumm/he/logic/football.cpp
new file mode 100644
index 0000000000..f86f97eaf7
--- /dev/null
+++ b/engines/scumm/he/logic/football.cpp
@@ -0,0 +1,288 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/he/intern_he.h"
+#include "scumm/he/logic_he.h"
+
+namespace Scumm {
+
+/**
+ * Logic code for:
+ * Backyard Football
+ * Backyard Football 2002
+ */
+class LogicHEfootball : public LogicHE {
+public:
+ LogicHEfootball(ScummEngine_v90he *vm) : LogicHE(vm) {}
+
+ int versionID();
+ int32 dispatch(int op, int numArgs, int32 *args);
+
+private:
+ int op_1004(int32 *args);
+ int op_1006(int32 *args);
+ int op_1007(int32 *args);
+ int op_1010(int32 *args);
+ int op_1022(int32 *args);
+ int op_1023(int32 *args);
+ int op_1024(int32 *args);
+};
+
+int LogicHEfootball::versionID() {
+ return 1;
+}
+
+int32 LogicHEfootball::dispatch(int op, int numArgs, int32 *args) {
+ int res = 0;
+
+ switch (op) {
+ case 1004:
+ res = op_1004(args);
+ break;
+
+ case 1006:
+ res = op_1006(args);
+ break;
+
+ case 1007:
+ res = op_1007(args);
+ break;
+
+ case 1010:
+ res = op_1010(args);
+ break;
+
+ case 1022:
+ res = op_1022(args);
+ break;
+
+ case 1023:
+ res = op_1023(args);
+ break;
+
+ case 1024:
+ res = op_1024(args);
+ break;
+
+ case 8221968:
+ // Someone had a fun and used his birthday as opcode number
+ res = getFromArray(args[0], args[1], args[2]);
+ break;
+
+ case 1492: case 1493: case 1494: case 1495: case 1496:
+ case 1497: case 1498: case 1499: case 1500: case 1501:
+ case 1502: case 1503: case 1504: case 1505: case 1506:
+ case 1507: case 1508: case 1509: case 1510: case 1511:
+ case 1512: case 1513: case 1514: case 1555:
+ // DirectPlay-related
+ // 1513: initialize
+ // 1555: set fake lag
+ break;
+
+ case 2200: case 2201: case 2202: case 2203: case 2204:
+ case 2205: case 2206: case 2207: case 2208: case 2209:
+ case 2210: case 2211: case 2212: case 2213: case 2214:
+ case 2215: case 2216: case 2217: case 2218: case 2219:
+ case 2220: case 2221: case 2222: case 2223: case 2224:
+ case 2225: case 2226: case 2227: case 2228:
+ // Boneyards-related
+ break;
+
+ case 3000: case 3001: case 3002: case 3003: case 3004:
+ // Internet-related
+ // 3000: check for updates
+ // 3001: check network status
+ // 3002: autoupdate
+ // 3003: close connection
+ break;
+
+ default:
+ LogicHE::dispatch(op, numArgs, args);
+ warning("Tell sev how to reproduce it (%d)", op);
+ }
+
+ return res;
+}
+
+int LogicHEfootball::op_1004(int32 *args) {
+ // Identical to LogicHEsoccer::op_1004
+ double res, a2, a4, a5;
+
+ a5 = ((double)args[4] - (double)args[1]) / ((double)args[5] - (double)args[2]);
+ a4 = ((double)args[3] - (double)args[0]) / ((double)args[5] - (double)args[2]);
+ a2 = (double)args[2] - (double)args[0] * a4 - args[1] * a5;
+
+ res = (double)args[6] * a4 + (double)args[7] * a5 + a2;
+ writeScummVar(108, (int32)res);
+
+ writeScummVar(109, (int32)a2);
+ writeScummVar(110, (int32)a5);
+ writeScummVar(111, (int32)a4);
+
+ return 1;
+}
+
+int LogicHEfootball::op_1006(int32 *args) {
+ // This seems to be more or less the inverse of op_1010
+ const double a1 = args[1];
+ double res;
+
+ // 2.9411764e-4 = 1/3400
+ // 5.3050399e-2 = 1/18.85 = 20/377
+ // 1.1764706e-2 = 1/85 = 40/3400
+ // 1.2360656e-1 = 377/3050
+ res = (1.0 - a1 * 2.9411764e-4 * 5.3050399e-2) * 1.2360656e-1 * args[0] +
+ a1 * 1.1764706e-2 + 46;
+
+ // Shortened / optimized version of that formula:
+ // res = (377.0 - a1 / 170.0) / 3050.0 * args[0] + a1 / 85.0 + 46;
+
+ writeScummVar(108, (int32)res);
+
+ // 1.2360656e-1 = 377/3050
+ // 1.1588235e-1 = 197/1700 = 394/3400
+ res = 640.0 - args[2] * 1.2360656e-1 - a1 * 1.1588235e-1 - 26;
+
+ writeScummVar(109, (int32)res);
+
+ return 1;
+}
+
+int LogicHEfootball::op_1007(int32 *args) {
+ double res, temp;
+
+ temp = (double)args[1] * 0.32;
+
+ if (temp > 304.0)
+ res = -args[2] * 0.142;
+ else
+ res = args[2] * 0.142;
+
+ res += temp;
+
+ writeScummVar(108, (int32)res);
+
+ res = (1000.0 - args[2]) * 0.48;
+
+ writeScummVar(109, (int32)res);
+
+ return 1;
+}
+
+int LogicHEfootball::op_1010(int32 *args) {
+ // This seems to be more or less the inverse of op_1006
+ double a1 = (640.0 - (double)args[1] - 26.0) / 1.1588235e-1;
+
+ // 2.9411764e-4 = 1/3400
+ // 5.3050399e-2 = 1/18.85 = 20/377
+ // 1.1764706e-2 = 1/85 = 40/3400
+ // 1.2360656e-1 = 377/3050
+ double a0 = ((double)args[0] - 46 - a1 * 1.1764706e-2) /
+ ((1.0 - a1 * 2.9411764e-4 * 5.3050399e-2) * 1.2360656e-1);
+
+ writeScummVar(108, (int32)a0);
+ writeScummVar(109, (int32)a1);
+
+ return 1;
+}
+
+int LogicHEfootball::op_1022(int32 *args) {
+ double res;
+ double var10 = args[4] - args[1];
+ double var8 = args[5] - args[2];
+ double var6 = args[3] - args[0];
+
+ res = sqrt(var8 * var8 + var6 * var6 + var10 * var10);
+
+ if (res >= (double)args[6]) {
+ var8 = (double)args[6] * var8 / res;
+ var10 = (double)args[6] * var10 / res;
+ res = (double)args[6] * var6 / res;
+ }
+
+ writeScummVar(108, (int32)res);
+ writeScummVar(109, (int32)var10);
+ writeScummVar(110, (int32)var8);
+
+ return 1;
+}
+
+int LogicHEfootball::op_1023(int32 *args) {
+ double var10, var18, var20, var28, var30, var30_;
+ double argf[7];
+
+ for (int i = 0; i < 7; i++)
+ argf[i] = args[i];
+
+ var10 = (argf[3] - argf[1]) / (argf[2] - argf[0]);
+ var28 = var10 * var10 + 1;
+ var20 = argf[0] * var10;
+ var18 = (argf[5] + argf[1] + var20) * argf[4] * var10 * 2 +
+ argf[6] * argf[6] * var28 + argf[4] * argf[4] -
+ argf[0] * argf[0] * var10 * var10 -
+ argf[5] * argf[0] * var10 * 2 -
+ argf[5] * argf[1] * 2 -
+ argf[1] * argf[1] - argf[5] * argf[5];
+
+ if (var18 >= 0) {
+ var18 = sqrt(var18);
+
+ var30_ = argf[4] + argf[5] * var10 + argf[1] * var10 + argf[0] * var10 * var10;
+ var30 = (var30_ - var18) / var28;
+ var18 = (var30_ + var18) / var28;
+
+ if ((argf[0] - var30 < 0) && (argf[0] - var18 < 0)) {
+ var30_ = var30;
+ var30 = var18;
+ var18 = var30_;
+ }
+ var28 = var18 * var10 - var20 - argf[1];
+ var20 = var30 * var10 - var20 - argf[1];
+ } else {
+ var18 = 0;
+ var20 = 0;
+ var28 = 0;
+ var30 = 0;
+ }
+
+ writeScummVar(108, (int32)var18);
+ writeScummVar(109, (int32)var28);
+ writeScummVar(110, (int32)var30);
+ writeScummVar(111, (int32)var20);
+
+ return 1;
+}
+
+int LogicHEfootball::op_1024(int32 *args) {
+ writeScummVar(108, 0);
+ writeScummVar(109, 0);
+ writeScummVar(110, 0);
+ writeScummVar(111, 0);
+
+ return 1;
+}
+
+LogicHE *makeLogicHEfootball(ScummEngine_v90he *vm) {
+ return new LogicHEfootball(vm);
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/logic/funshop.cpp b/engines/scumm/he/logic/funshop.cpp
new file mode 100644
index 0000000000..8993fedad2
--- /dev/null
+++ b/engines/scumm/he/logic/funshop.cpp
@@ -0,0 +1,216 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/he/intern_he.h"
+#include "scumm/he/logic_he.h"
+
+namespace Scumm {
+
+/**
+ * Logic code for:
+ * Freddi Fish's One-Stop Fun Shop
+ * Pajama Sam's One-Stop Fun Shop
+ * Putt-Putt's One-Stop Fun Shop
+ */
+class LogicHEfunshop : public LogicHE {
+public:
+ LogicHEfunshop(ScummEngine_v90he *vm) : LogicHE(vm) {}
+
+ int versionID();
+ int32 dispatch(int op, int numArgs, int32 *args);
+
+private:
+ void op_1004(int32 *args);
+ void op_1005(int32 *args);
+ int checkShape(int32 data0, int32 data1, int32 data4, int32 data5, int32 data2, int32 data3, int32 data6, int32 data7, int32 *x, int32 *y);
+};
+
+int LogicHEfunshop::versionID() {
+ return 1;
+}
+
+int32 LogicHEfunshop::dispatch(int op, int numArgs, int32 *args) {
+ switch (op) {
+ case 1004:
+ op_1004(args);
+ break;
+
+ case 1005:
+ op_1005(args);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void LogicHEfunshop::op_1004(int32 *args) {
+ double data[8], at, sq;
+ int32 x, y;
+ int i=0;
+
+ for (i = 0; i <= 6; i += 2) {
+ data[i] = getFromArray(args[0], 0, 519 + i);
+ data[i + 1] = getFromArray(args[0], 0, 519 + i + 1);
+ }
+ int s = checkShape((int32)data[0], (int32)data[1], (int32)data[4], (int32)data[5],
+ (int32)data[2], (int32)data[3], (int32)data[6], (int32)data[7], &x, &y);
+
+ if (s != 1) {
+ error("LogicHEfunshop::op_1004: Your shape has defied the laws of physics");
+ return;
+ }
+
+ for (i = 0; i <= 6; i += 2) {
+ data[i] -= (double)x;
+ data[i + 1] -= (double)y;
+ }
+
+ double a1 = (double)args[1] * DEG2RAD;
+
+ for (i = 0; i <= 6; i += 2) {
+ at = atan2(data[i + 1], data[i]);
+ sq = sqrt(data[i + 1] * data[i + 1] + data[i] * data[i]);
+
+ if (at <= 0)
+ at += 2 * M_PI;
+
+ data[i] = cos(at + a1) * sq;
+ data[i + 1] = sin(at + a1) * sq;
+ }
+
+ double minx = data[0];
+ double miny = data[1];
+
+ for (i = 0; i <= 6; i += 2) {
+ if (data[i] < minx)
+ minx = data[i];
+ if (data[i + 1] < miny)
+ miny = data[i + 1];
+ }
+
+ for (i = 0; i <= 6; i += 2) {
+ data[i] -= minx;
+ data[i + 1] -= miny;
+
+ putInArray(args[0], 0, 519 + i, scummRound(data[i]));
+ putInArray(args[0], 0, 519 + i + 1, scummRound(data[i + 1]));
+ }
+}
+
+void LogicHEfunshop::op_1005(int32 *args) {
+ double data[8];
+ double args1, args2;
+ int i;
+ for (i = 520; i <= 526; i += 2) {
+ data[i - 520] = getFromArray(args[0], 0, i - 1);
+ data[i - 520 + 1] = getFromArray(args[0], 0, i);
+ }
+
+ args1 = (double)args[1] * 0.01 + 1;
+ args2 = (double)args[2] * 0.01 + 1;
+
+ for (i = 0; i < 4; i++) {
+ data[2 * i] *= args1;
+ data[2 * i + 1] *= args2;
+ }
+
+ for (i = 520; i <= 526; i += 2) {
+ putInArray(args[0], 0, i - 1, scummRound(data[i - 520]));
+ putInArray(args[0], 0, i, scummRound(data[i - 520 + 1]));
+ }
+}
+
+int LogicHEfunshop::checkShape(int32 data0, int32 data1, int32 data4, int32 data5, int32 data2, int32 data3, int32 data6, int32 data7, int32 *x, int32 *y) {
+ int32 diff5_1, diff0_4, diff7_3, diff2_6;
+ int32 diff1, diff2;
+ int32 delta, delta2;
+ int32 sum1, sum2;
+
+ diff0_4 = data0 - data4;
+ diff5_1 = data5 - data1;
+ diff1 = data1 * data4 - data0 * data5;
+ sum1 = diff0_4 * data3 + diff1 + diff5_1 * data2;
+ sum2 = diff0_4 * data7 + diff1 + diff5_1 * data6;
+
+ if (sum1 != 0 && sum2 != 0) {
+ sum2 ^= sum1;
+
+ if (sum2 >= 0)
+ return 0;
+ }
+
+ diff2_6 = data2 - data6;
+ diff7_3 = data7 - data3;
+ diff2 = data3 * data6 - data2 * data7;
+ sum1 = diff2_6 * data1 + diff2 + diff7_3 * data0;
+ sum2 = diff2_6 * data5 + diff2 + diff7_3 * data4;
+
+ if (sum1 != 0 && sum2 != 0) {
+ sum2 ^= sum1;
+
+ if (sum2 >= 0)
+ return 0;
+ }
+
+ delta = diff2_6 * diff5_1 - diff0_4 * diff7_3;
+
+ if (delta == 0) {
+ return 2;
+ }
+
+ if (delta < 0) {
+ data7 = -((delta + 1) >> 1);
+ } else {
+ data7 = delta >> 1;
+ }
+
+ delta2 = diff2 * diff0_4 - diff1 * diff2_6;
+
+ if (delta2 < 0) {
+ delta2 -= data7;
+ } else {
+ delta2 += data7;
+ }
+
+ *x = delta2 / delta;
+
+ delta2 = diff1 * diff7_3 - diff2 * diff5_1;
+
+ if (delta2 < 0) {
+ delta2 -= data7;
+ } else {
+ delta2 += data7;
+ }
+
+ *y = delta2 / delta;
+
+ return 1;
+}
+
+LogicHE *makeLogicHEfunshop(ScummEngine_v90he *vm) {
+ return new LogicHEfunshop(vm);
+}
+
+} // End of namespace Scumm
diff --git a/engines/tsage/blueforce_logic.h b/engines/scumm/he/logic/moonbase.cpp
index 9237e50a13..fac2ea27ff 100644
--- a/engines/tsage/blueforce_logic.h
+++ b/engines/scumm/he/logic/moonbase.cpp
@@ -11,7 +11,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
@@ -20,23 +20,31 @@
*
*/
-#ifndef TSAGE_BLUEFORCE_LOGIC_H
-#define TSAGE_BLUEFORCE_LOGIC_H
+#include "scumm/he/intern_he.h"
+#include "scumm/he/logic_he.h"
-#include "common/scummsys.h"
-#include "tsage/events.h"
-#include "tsage/core.h"
-#include "tsage/scenes.h"
-#include "tsage/globals.h"
+namespace Scumm {
-namespace tSage {
-
-class BlueForceGame: public Game {
+/**
+ * Logic code for:
+ * Moonbase Commander
+ */
+class LogicHEmoonbase : public LogicHE {
public:
- virtual void start();
- virtual Scene *createScene(int sceneNumber);
+ LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {}
+
+ int versionID();
};
-} // End of namespace tSage
+int LogicHEmoonbase::versionID() {
+ if (_vm->_game.features & GF_DEMO)
+ return -100;
+ else
+ return 100;
+}
+
+LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) {
+ return new LogicHEmoonbase(vm);
+}
-#endif
+} // End of namespace Scumm
diff --git a/engines/scumm/he/logic/puttrace.cpp b/engines/scumm/he/logic/puttrace.cpp
new file mode 100644
index 0000000000..ea4397cd97
--- /dev/null
+++ b/engines/scumm/he/logic/puttrace.cpp
@@ -0,0 +1,376 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/he/intern_he.h"
+#include "scumm/he/logic_he.h"
+
+namespace Scumm {
+
+/**
+ * Logic code for:
+ * Putt-Putt Enters the Race
+ */
+class LogicHErace : public LogicHE {
+private:
+ float *_userData;
+ double *_userDataD;
+public:
+ LogicHErace(ScummEngine_v90he *vm);
+ ~LogicHErace();
+
+ int versionID();
+ int32 dispatch(int op, int numArgs, int32 *args);
+
+private:
+ int32 op_1003(int32 *args);
+ int32 op_1004(int32 *args);
+ int32 op_1100(int32 *args);
+ int32 op_1101(int32 *args);
+ int32 op_1102(int32 *args);
+ int32 op_1103(int32 *args);
+ int32 op_1110();
+ int32 op_1120(int32 *args);
+ int32 op_1130(int32 *args);
+ int32 op_1140(int32 *args);
+
+ void op_sub1(float arg);
+ void op_sub2(float arg);
+ void op_sub3(float arg);
+};
+
+LogicHErace::LogicHErace(ScummEngine_v90he *vm) : LogicHE(vm) {
+ // Originally it used 0x930 and stored both floats and doubles inside
+ _userData = (float *)calloc(550, sizeof(float));
+ _userDataD = (double *)calloc(30, sizeof(double));
+
+ // FIXME: of the 550 entries in _userData, only 516 till 532 are used
+ // FIXME: similarly, in _userDataD only 9 till 17 are used for computations
+ // (some of the other entries are also set, but never read, hence useless).
+}
+
+LogicHErace::~LogicHErace() {
+ free(_userData);
+ free(_userDataD);
+}
+
+int LogicHErace::versionID() {
+ return 1;
+}
+
+int32 LogicHErace::dispatch(int op, int numArgs, int32 *args) {
+ int32 res;
+
+ switch (op) {
+ case 1003:
+ res = op_1003(args);
+ break;
+
+ case 1004:
+ res = op_1004(args);
+ break;
+
+ case 1100:
+ res = op_1100(args);
+ break;
+
+ case 1101:
+ res = op_1101(args);
+ break;
+
+ case 1102:
+ res = op_1102(args);
+ break;
+
+ case 1103:
+ res = op_1103(args);
+ break;
+
+ case 1110:
+ res = op_1110();
+ break;
+
+ case 1120:
+ res = op_1120(args);
+ break;
+
+ case 1130:
+ res = op_1130(args);
+ break;
+
+ case 1140:
+ res = op_1140(args);
+ break;
+
+ default:
+ res = 0;
+ break;
+
+ }
+
+ return res;
+}
+
+#define RAD2DEG (180 / M_PI)
+#define DEG2RAD (M_PI / 180)
+
+int32 LogicHErace::op_1003(int32 *args) {
+ int value = args[2] ? args[2] : 1;
+
+ writeScummVar(108, (int32)(atan2((double)args[0], (double)args[1]) * RAD2DEG * value));
+
+ return 1;
+}
+
+int32 LogicHErace::op_1004(int32 *args) {
+ int value = args[1] ? args[1] : 1;
+
+ writeScummVar(108, (int32)(sqrt((float)args[0]) * value));
+
+ return 1;
+}
+
+int32 LogicHErace::op_1100(int32 *args) {
+ // _userData 516,517,518 describe a 3D translation?
+ _userData[516] = (float)args[0] / args[10];
+ _userData[517] = (float)args[1] / args[10];
+ _userData[518] = (float)args[2] / args[10];
+
+ // _userData 519,520,521 describe rotation angles around the x,y,z axes?
+ _userData[519] = (float)args[3] / args[10];
+ _userData[520] = (float)args[4] / args[10];
+ _userData[521] = (float)args[5] / args[10];
+
+ op_sub1(_userData[520]);
+ op_sub2(_userData[521]);
+
+ // _userData[532] seems to be some kind of global scale factor
+ _userData[532] = (float)args[10];
+
+ _userData[524] = (float)args[8]; // not used
+ _userData[525] = (float)args[9]; // not used
+ _userData[522] = (float)args[6] / args[10]; // not used
+ _userData[523] = (float)args[7] / args[10]; // only used to compute 528 and 529
+
+ // The following two are some kind of scale factors
+ _userData[526] = (float)args[6] / args[8] / args[10];
+ _userData[527] = (float)args[7] / args[9] / args[10];
+
+ // Set var 108 and 109 -- the value set here corresponds to the values
+ // set by op_1110!
+ writeScummVar(108, (int32)((float)args[6] / args[8] * args[10]));
+ writeScummVar(109, (int32)((float)args[7] / args[9] * args[10]));
+
+ _userData[528] = (float)(_userData[519] - _userData[523] * 0.5);
+ _userData[529] = (float)(_userData[519] + _userData[523] * 0.5);
+
+ writeScummVar(110, (int32)(_userData[528] * args[10]));
+ writeScummVar(111, (int32)(_userData[529] * args[10]));
+
+ // 530 and 531 are only used to set vars 112 and 113, so no need
+ // to store them permanently
+ _userData[530] = (float)(_userData[517] / tan(_userData[529] * DEG2RAD));
+ _userData[531] = (float)(_userData[517] / tan(_userData[528] * DEG2RAD));
+
+ writeScummVar(112, (int32)(_userData[530] * args[10]));
+ writeScummVar(113, (int32)(_userData[531] * args[10]));
+
+ return 1;
+}
+
+int32 LogicHErace::op_1101(int32 *args) {
+ // Update rotation params?
+ int32 retval;
+ float temp;
+
+ temp = args[0] / _userData[532];
+ if (_userData[519] != temp) {
+ _userData[519] = temp;
+ op_sub3(temp);
+ retval = 1;
+ } else {
+ retval = (int32)temp;
+ }
+
+ temp = args[1] / _userData[532];
+ if (_userData[520] != temp) {
+ _userData[520] = temp;
+ op_sub1(temp);
+ retval = 1;
+ }
+
+ temp = args[2] / _userData[532];
+ if (_userData[521] != temp) {
+ _userData[521] = temp;
+ op_sub2(temp);
+ retval = 1;
+ }
+
+ return retval;
+}
+
+int32 LogicHErace::op_1102(int32 *args) {
+ // Update translation params?
+ int32 retval;
+ float temp;
+
+ temp = args[0] / _userData[532];
+ if (_userData[516] != temp) {
+ _userData[516] = temp;
+ retval = 1;
+ } else {
+ retval = (int32)_userData[532];
+ }
+
+ temp = args[1] / _userData[532];
+ if (_userData[517] != temp) {
+ _userData[517] = temp;
+ retval = 1;
+ }
+
+ temp = args[2] / _userData[532];
+ if (_userData[518] != temp) {
+ _userData[518] = temp;
+ retval = 1;
+ }
+
+ return retval;
+}
+
+int32 LogicHErace::op_1103(int32 *args) {
+ double angle = args[0] / args[1] * DEG2RAD;
+
+ writeScummVar(108, (int32)(sin(angle) * args[2]));
+ writeScummVar(109, (int32)(cos(angle) * args[2]));
+
+ return 1;
+}
+
+int32 LogicHErace::op_1110() {
+ writeScummVar(108, (int32)(_userData[526] * _userData[532] * _userData[532]));
+ writeScummVar(109, (int32)(_userData[527] * _userData[532] * _userData[532]));
+ writeScummVar(110, (int32)(_userData[532]));
+
+ return 1;
+}
+
+int32 LogicHErace::op_1120(int32 *args) {
+ double a0, a1, a2;
+ double b0, b1, b2;
+ double res1, res2;
+
+ a0 = args[0] / _userData[532] - _userData[516];
+ a1 = args[1] / _userData[532] - _userData[517];
+ a2 = args[2] / _userData[532] - _userData[518];
+
+ // Perform matrix multiplication (multiplying by a rotation matrix)
+ b2 = a2 * _userDataD[17] + a1 * _userDataD[14] + a0 * _userDataD[11];
+ b1 = a2 * _userDataD[16] + a1 * _userDataD[13] + a0 * _userDataD[10];
+ b0 = a2 * _userDataD[15] + a1 * _userDataD[12] + a0 * _userDataD[9];
+
+ res1 = (atan2(b0, b2) * RAD2DEG) / _userData[526];
+ res2 = (atan2(b1, b2) * RAD2DEG - _userData[528]) / _userData[527];
+
+ writeScummVar(108, (int32)res1);
+ writeScummVar(109, (int32)res2);
+
+ return 1;
+}
+
+int32 LogicHErace::op_1130(int32 *args) {
+ double cs = cos(args[0] / _userData[532] * DEG2RAD);
+ double sn = sin(args[0] / _userData[532] * DEG2RAD);
+
+ writeScummVar(108, (int32)(cs * args[1] + sn * args[2]));
+ writeScummVar(109, (int32)(cs * args[2] - sn * args[1]));
+
+ return 1;
+}
+
+int32 LogicHErace::op_1140(int32 *args) {
+ // This functions seems to perform some kind of projection: We project
+ // the vector (arg2,arg3) onto the vector (arg0,arg1), but also apply
+ // some kind of distortion factor ?!?
+ double x = args[2], y = args[3];
+
+ // We start by normalizing the vector described by arg2 and arg3.
+ // So compute its length and divide the x and y coordinates
+ const double sq = sqrt(x*x + y*y);
+ x /= sq;
+ y /= sq;
+
+ // Compute the scalar product of the vectors (arg0,arg1) and (x,y)
+ const double scalarProduct = x * args[0] + y * args[1];
+
+ // Finally compute the projection of (arg2,arg3) onto (arg0,arg1)
+ double projX = args[0] - 2 * scalarProduct * x;
+ double projY = args[1] - 2 * scalarProduct * y;
+
+ projX = projX * 20.0 / 23.0; // FIXME: Why is this here?
+
+ writeScummVar(108, (int32)projX);
+
+ if (args[3] >= 0) // FIXME: Why is this here?
+ projY = projY * 5.0 / 6.0;
+
+ writeScummVar(109, (int32)projY);
+
+ return 1;
+}
+
+void LogicHErace::op_sub1(float arg) {
+ // Setup a rotation matrix
+ _userDataD[10] = _userDataD[12] = _userDataD[14] = _userDataD[16] = 0;
+ _userDataD[13] = 1;
+
+ _userDataD[9] = cos(arg * DEG2RAD);
+ _userDataD[15] = sin(arg * DEG2RAD);
+ _userDataD[11] = -_userDataD[15];
+ _userDataD[17] = _userDataD[9];
+}
+
+void LogicHErace::op_sub2(float arg) {
+ // Setup a rotation matrix -- but it is NEVER USED!
+ _userDataD[20] = _userDataD[21] = _userDataD[24] = _userDataD[25] = 0;
+ _userDataD[26] = 1;
+
+ _userDataD[19] = sin(arg * DEG2RAD);
+ _userDataD[18] = cos(arg * DEG2RAD);
+ _userDataD[21] = -_userDataD[19];
+ _userDataD[22] = _userDataD[18];
+}
+
+void LogicHErace::op_sub3(float arg) {
+ // Setup a rotation matrix -- but it is NEVER USED!
+ _userDataD[1] = _userDataD[2] = _userDataD[3] = _userDataD[6] = 0;
+ _userDataD[0] = 1;
+
+ _userDataD[4] = cos(arg * DEG2RAD);
+ _userDataD[5] = sin(arg * DEG2RAD);
+ _userDataD[7] = -_userDataD[5];
+ _userDataD[8] = _userDataD[4];
+}
+
+LogicHE *makeLogicHErace(ScummEngine_v90he *vm) {
+ return new LogicHErace(vm);
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/logic/soccer.cpp b/engines/scumm/he/logic/soccer.cpp
new file mode 100644
index 0000000000..05f377a736
--- /dev/null
+++ b/engines/scumm/he/logic/soccer.cpp
@@ -0,0 +1,1206 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/he/intern_he.h"
+#include "scumm/he/logic_he.h"
+
+namespace Scumm {
+
+/**
+ * Logic code for:
+ * Backyard Soccer
+ * Backyard Soccer MLS Edition
+ * Backyard Soccer 2004
+ */
+class LogicHEsoccer : public LogicHE {
+private:
+ double *_userDataD;
+
+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_1005(float x1, float y1, float z1, float x2, float y2, float z2, float *nextVelX, float *nextVelY, float *nextVelZ, float *a10);
+ int op_1006(int32 a1, int32 a2, int32 a3, int32 a4);
+ int op_1007(int32 *args);
+ int op_1008(int outArray, int srcX, int srcY, int srcZ, int vecX, int vecY, int vecZ, int airResX, int airResY, int airResZ, int vecNumerator, int vecDenom, int gravityMult, int requiredSegments, int a15, int a16, int a17, int a18, int fieldType);
+ int op_1011(int32 worldPosArray, int32 screenPosArray, int32 a3, int32 closestActorArray, int32 maxDistance, int32 fieldAreaArray);
+ int op_1012(int32 *args);
+ int op_1013(int32 a1, int32 a2, int32 a3);
+ int op_1014(int32 srcX, int32 srcY, int32 srcZ, int32 velX, int32 velY, int32 velZ, int32 outArray, int32 dataArrayId, int32 indexArrayId, int32 requestType, int32 vecNumerator, int32 vecDenom, int32 a13, int32 a14);
+ int op_1016(int32 *args);
+ int op_1017(int32 *args);
+ int op_1019(int32 *args);
+ int op_1021(int32 inX, int32 inY, int32 inZ, int32 velX, int32 velY, int32 velZ, int32 internalUse);
+
+ // op_1007 allocates some arrays
+ // they're then filled by op_1019
+ byte _collisionObjIds[4096], _collisionNodeEnabled[585];
+
+ // op_1011 has a subfunction
+ void calculateDistances(int32 worldPosArray, int32 a2, int32 closestActorArray, int32 maxDistance);
+
+ // array containing collision detection tree
+ bool _collisionTreeAllocated;
+ uint32 *_collisionTree;
+ int addCollisionTreeChild(int depth, int index, int parent);
+
+ // op_1014 has several subops
+ // ...and several sub-subops
+ int generateCollisionObjectList(float srcX, float srcY, float srcZ, float velX, float velY, float velZ);
+ int addFromCollisionTreeNode(int index, int parent, uint32 *indices, int objIndexBase);
+ void addCollisionObj(byte objId);
+ int findCollisionWith(int objId, float inX, float inY, float inZ, float inXVec, float inYVec, float inZVec, float &collideX, float &collideY, float &collideZ, int indexArrayId, int dataArrayId, float *nextVelX, float *nextVelY, float *nextVelZ, float *a15);
+ void getPointsForFace(int faceId, float &x1, float &y1, float &z1, float &x2, float &y2, float &z2, float &x3, float &y3, float &z3, float &x4, float &y4, float &z4, const int *objPoints);
+ void crossProduct(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4, float &outX, float &outY, float &outZ);
+ double dotProduct(float a1, float a2, float a3, float a4, float a5, float a6);
+ void sortCollisionList(float *data, int numEntries, int entrySize, int compareOn);
+ int setCollisionOutputData(float *collisionData, int entrySize, int dataArrayId, int indexArrayId, int startX, int startY, int startZ, float a8, int a9, int a10, int a11, int *out);
+
+ // op_1014 sets an array optionally based upon
+ // setCollisionOutputData; it is then used by op_1008
+ int _internalCollisionOutData[10];
+ Common::List<byte> _collisionObjs;
+
+ // op_1021 can (optionally) set two variables for use in op_1008
+ uint32 _var1021[2];
+};
+
+int LogicHEsoccer::versionID() {
+ return 1;
+}
+
+LogicHEsoccer::LogicHEsoccer(ScummEngine_v90he *vm) : LogicHE(vm) {
+ _userDataD = (double *)calloc(1732, sizeof(double));
+ _collisionTree = 0;
+ _collisionTreeAllocated = false;
+}
+
+LogicHEsoccer::~LogicHEsoccer() {
+ free(_userDataD);
+ delete[] _collisionTree;
+}
+
+int32 LogicHEsoccer::dispatch(int op, int numArgs, int32 *args) {
+ int res = 0;
+
+ switch (op) {
+ case 1006:
+ res = op_1006(args[0], args[1], args[2], args[3]);
+ break;
+
+ case 1007:
+ res = op_1007(args);
+ break;
+
+ case 1008:
+ res = op_1008(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15], args[16], args[17], args[18]);
+ break;
+
+ case 1011:
+ res = op_1011(args[0], args[1], args[2], args[3], args[4], args[5]);
+ break;
+
+ case 1012:
+ res = op_1012(args);
+ break;
+
+ case 1013:
+ res = op_1013(args[0], args[1], args[2]);
+ break;
+
+ case 1014:
+ res = op_1014(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]);
+ break;
+
+ case 1016:
+ res = op_1016(args);
+ break;
+
+ case 1017:
+ res = op_1017(args);
+ break;
+
+ case 1019:
+ res = op_1019(args);
+ break;
+
+ case 1021:
+ res = op_1021(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ break;
+
+ case 1001: case 1002: case 1003: case 1005:
+ case 1009: case 8221968:
+ // In the u32, but unused by any of the soccer scripts
+ // 1005 is called from another opcode, however
+ error("Unused soccer u32 opcode %d called", op);
+
+ case 1004: case 1010: case 1015: case 1018:
+ case 1020:
+ // Used only by the unaccessible in-game editor (so, fall through)
+
+ default:
+ LogicHE::dispatch(op, numArgs, args);
+ }
+
+ return res;
+}
+
+void LogicHEsoccer::beforeBootScript() {
+ _userDataD[530] = 0;
+}
+
+void LogicHEsoccer::initOnce() {
+ // The original sets some paths here that we don't need to worry about
+ _collisionTreeAllocated = false;
+ _userDataD[530] = 0;
+}
+
+int LogicHEsoccer::startOfFrame() {
+ // This variable is some sort of flag that activates this mode
+ int res = (int)_userDataD[530];
+
+ if (res)
+ res = op_1011((int)_userDataD[531], (int)_userDataD[532], (int)_userDataD[533], (int)_userDataD[534], (int)_userDataD[535], (int)_userDataD[536]);
+
+ return res;
+}
+
+int LogicHEsoccer::op_1005(float x1, float y1, float z1, float x2, float y2, float z2, float *nextVelX, float *nextVelY, float *nextVelZ, float *a10) {
+ // Called from op_1014
+
+ double dot = x1 * x2 + y1 * y2 + z1 * z2;
+ *nextVelX = x2 - 2 * dot * x1;
+ *nextVelY = y2 - 2 * dot * y1;
+ *nextVelZ = z2 - 2 * dot * z1;
+ *a10 = 1.0f; // It always does this. How curious!
+
+ return 1;
+}
+
+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] = a4;
+
+ 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);
+
+ return 1;
+}
+
+int LogicHEsoccer::op_1007(int32 *args) {
+ // Used when the HE logo is shown
+ // This initializes the _userDataD fields that are used in op_1006/op_1011
+
+ float y1 = (double)args[0] / 100.0;
+ float x1 = (double)args[1] / 100.0;
+ float x2 = (double)args[2] / 100.0;
+ float y2 = (double)args[3] / 100.0;
+ float x3 = (double)args[4] / 100.0;
+
+ _userDataD[518] = x2;
+ _userDataD[519] = 2 * atan2(y2, x2 - x3);
+ _userDataD[520] = atan2(y1, x2);
+ _userDataD[521] = atan2(y1, x1);
+ _userDataD[524] = y1;
+ _userDataD[525] = 2 * (_userDataD[521] - _userDataD[520]);
+ _userDataD[526] = args[6];
+ _userDataD[527] = args[5];
+ _userDataD[528] = args[7];
+ _userDataD[522] = _userDataD[526] / _userDataD[525];
+ _userDataD[523] = _userDataD[527] / _userDataD[519];
+
+ // Clear both byte arrays
+ memset(_collisionObjIds, 0, 4096);
+ memset(_collisionNodeEnabled, 0, 585);
+
+ if (!_collisionTreeAllocated)
+ op_1013(4, args[8], args[9]);
+
+ return 1;
+}
+
+static inline double vectorLength(double x, double y, double z) {
+ return sqrt(x * x + y * y + z * z);
+}
+
+int LogicHEsoccer::op_1008(int outArray, int srcX, int srcY, int srcZ, int vecX, int vecY, int vecZ, int airResX, int airResY, int airResZ, int vecNumerator, int vecDenom, int gravityMult, int requiredSegments, int a15, int a16, int a17, int a18, int fieldType) {
+ // Calculate requiredSegments consecutive movement segments, and place
+ // the associated data (positions, vectors, etc) into outArray.
+
+ int loopsSoFar = 0;
+ int segmentsSoFar = 1;
+ int prevVecY = 500;
+ int inX = srcX;
+ int inZ = srcZ;
+ int checkForCollisions = 0;
+
+ while (segmentsSoFar <= requiredSegments) {
+ if (fieldType == 1 && srcZ > 8819)
+ checkForCollisions = 1;
+ else if (fieldType == 2 && (srcX < -2350 || srcX > 2350))
+ checkForCollisions = 1;
+ else if (fieldType == 3 && (srcX < -2350 || srcX > 2350 || srcZ < 6119 || srcZ > 8819))
+ checkForCollisions = 1;
+
+ if (srcY > 0)
+ vecY -= vecNumerator * gravityMult / vecDenom;
+
+ int prevX = srcX;
+ int prevY = srcY;
+ int prevZ = srcZ;
+ srcX += vecNumerator * vecX / vecDenom;
+ srcY += vecNumerator * vecY / vecDenom;
+ srcZ += vecNumerator * vecZ / vecDenom;
+
+ if (srcY > 0) {
+ if (checkForCollisions && op_1014(prevX, prevY, prevZ, vecX, vecY, vecZ, 0, a17, a18, 3, vecNumerator, vecDenom, a15, a16)) {
+ srcX = _internalCollisionOutData[6];
+ srcY = _internalCollisionOutData[7];
+ srcZ = _internalCollisionOutData[8];
+ vecX = _internalCollisionOutData[3];
+ vecY = _internalCollisionOutData[4];
+ vecZ = _internalCollisionOutData[5];
+ putInArray(outArray, segmentsSoFar, 0, loopsSoFar);
+ putInArray(outArray, segmentsSoFar, 1, (int)vectorLength((double)(_internalCollisionOutData[6] - inX), 0.0, (double)(_internalCollisionOutData[8] - inZ)));
+ putInArray(outArray, segmentsSoFar, 2, _internalCollisionOutData[6]);
+ putInArray(outArray, segmentsSoFar, 3, _internalCollisionOutData[7]);
+ putInArray(outArray, segmentsSoFar, 4, _internalCollisionOutData[8]);
+ putInArray(outArray, segmentsSoFar, 5, vecX);
+ putInArray(outArray, segmentsSoFar, 6, vecY);
+ putInArray(outArray, segmentsSoFar++, 7, vecZ);
+ }
+ } else {
+ srcY = 0;
+ int thisVecX = vecX;
+ int thisVecZ = vecZ;
+ vecX = vecX * airResX / 100;
+
+ if (vecY) {
+ int v18 = ABS(vecY);
+ if (v18 > ABS(prevVecY))
+ vecY = ABS(prevVecY);
+ vecY = ABS(airResY * vecY) / 100;
+ }
+
+ vecZ = airResZ * vecZ / 100;
+
+ if (prevVecY >= 0) {
+ if (op_1014(prevX, prevY, prevZ, thisVecX, prevVecY, thisVecZ, 0, a17, a18, 3, vecNumerator, vecDenom, a15, a16)) {
+ srcX = _internalCollisionOutData[6];
+ srcY = _internalCollisionOutData[7];
+ srcZ = _internalCollisionOutData[8];
+ vecX = _internalCollisionOutData[3];
+ vecY = _internalCollisionOutData[4];
+ vecZ = _internalCollisionOutData[5];
+ }
+ } else {
+ if (checkForCollisions) {
+ op_1021(srcX, 0, srcZ, thisVecX, prevVecY, thisVecZ, 1);
+
+ if (op_1014(prevX, prevY, prevZ, thisVecX, prevVecY, thisVecZ, 0, a17, a18, 3, vecNumerator, vecDenom, a15, a16)) {
+ srcX = _internalCollisionOutData[6];
+ srcY = _internalCollisionOutData[7];
+ srcZ = _internalCollisionOutData[8];
+ vecX = _internalCollisionOutData[3];
+ vecY = _internalCollisionOutData[4];
+ vecZ = _internalCollisionOutData[5];
+ } else {
+ // try it with the output of op_1021 instead
+ int tmpVecZ = vecZ + prevZ - _var1021[1];
+ int v20 = ABS(prevVecY);
+
+ if (op_1014(_var1021[0], 0, _var1021[1], vecX + prevX - _var1021[0], v20 - prevY, tmpVecZ, 0, a17, a18, 3, vecNumerator, vecDenom, a15, a16)) {
+ srcX = _internalCollisionOutData[6];
+ srcY = _internalCollisionOutData[7];
+ srcZ = _internalCollisionOutData[8];
+ vecX = _internalCollisionOutData[3];
+ vecY = _internalCollisionOutData[4];
+ vecZ = _internalCollisionOutData[5];
+ }
+ }
+ }
+ }
+
+ prevVecY = vecY;
+ putInArray(outArray, segmentsSoFar, 0, loopsSoFar);
+ putInArray(outArray, segmentsSoFar, 1, (int32)vectorLength(srcX - inX, 0.0, srcZ - inZ));
+ putInArray(outArray, segmentsSoFar, 2, srcX);
+ putInArray(outArray, segmentsSoFar, 3, srcY);
+ putInArray(outArray, segmentsSoFar, 4, srcZ);
+ putInArray(outArray, segmentsSoFar, 5, vecX);
+ putInArray(outArray, segmentsSoFar, 6, vecY);
+ putInArray(outArray, segmentsSoFar++, 7, vecZ);
+ }
+
+ loopsSoFar++;
+ }
+
+ return 1;
+}
+
+int LogicHEsoccer::op_1011(int32 worldPosArray, int32 screenPosArray, int32 a3, int32 closestActorArray, int32 maxDistance, int32 fieldAreaArray) {
+ // This is called on each frame by startOfFrame() if activated by op_1012.
+
+ float objY = 0.0;
+
+ // First, iterate over the field objects and project them onto the screen.
+ for (int i = 0; i < 18; i++) {
+ int rawX = getFromArray(worldPosArray, i, 0);
+ int rawY = getFromArray(worldPosArray, i, 1);
+ int rawZ = getFromArray(worldPosArray, i, 2);
+
+ float objX = (double)rawX / 100.0;
+ objY = (double)rawY / 100.0;
+ float objZ = (double)rawZ / 100.0;
+
+ if (i < 13) {
+ // For the players and the ball: work out the area of the field
+ // this object is in, storing it in an array if provided.
+ int areaX = (rawX + 2750) / 500;
+ areaX = CLIP(areaX, 0, 10);
+
+ int areaZ = (9219 - rawZ) / 500;
+ areaZ = CLIP(areaZ, 0, 6);
+
+ if (fieldAreaArray)
+ putInArray(fieldAreaArray, 0, i, areaX + 11 * areaZ);
+ }
+
+ float v7 = atan2(_userDataD[524] - objY, (double)objZ);
+ int screenY = (int)(_userDataD[526] - (_userDataD[521] - v7) * _userDataD[522] - 300.0);
+ double v9 = _userDataD[523];
+
+ // x/y position of objects
+ putInArray(screenPosArray, i, 0, (int32)(atan2(objX, objZ) * v9 + 640.0));
+ putInArray(screenPosArray, i, 1, screenY);
+
+ double v10 = atan2(_userDataD[524], (double)objZ);
+ int shadowScreenY = (int)(_userDataD[526] - (_userDataD[521] - (float)v10) * _userDataD[522] - 300.0);
+ double v13 = _userDataD[523];
+
+ // x/y position of shadows
+ putInArray(screenPosArray, i + ((_vm->_game.id == GID_SOCCER) ? 20 : 22), 0, (int32)(atan2(objX, objZ) * v13 + 640.0));
+ putInArray(screenPosArray, i + ((_vm->_game.id == GID_SOCCER) ? 20 : 22), 1, shadowScreenY);
+ }
+
+ // 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;
+
+ // The following loop is doing cursor scaling
+ // The further up on the screen, the smaller the cursor is
+ for (int i = start; i <= end; i++) {
+ int x = getFromArray(screenPosArray, i, 0);
+ int y = getFromArray(screenPosArray, i, 1);
+
+ // This retains objY from (i == 17)?
+ float v16 = _userDataD[524] - objY;
+ float scaledZ = v16 / tan((_userDataD[528] + y - _userDataD[526]) / _userDataD[522] + _userDataD[521]);
+ double scaledX = tan((double)(x - ((_vm->_game.id == GID_SOCCER) ? 0 : 640)) / _userDataD[523]) * scaledZ;
+ putInArray(worldPosArray, i, 0, (int)(scaledX * 100.0));
+ putInArray(worldPosArray, i, 2, (int)(scaledZ * 100.0));
+ }
+
+ calculateDistances(worldPosArray, a3, closestActorArray, maxDistance);
+
+ 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::calculateDistances(int32 worldPosArray, int32 a2, int32 closestActorArray, int32 maxDistance) {
+ // 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 closestActor[13];
+ int objectX[13];
+ int objectZ[13];
+ int closestDistance[195];
+
+ for (int i = 0; i < 13; i++) {
+ closestActor[i] = 0;
+ objectX[i] = getFromArray(worldPosArray, i, 0);
+ objectZ[i] = getFromArray(worldPosArray, i, 2);
+ }
+
+ // 12 here, 13 up there
+ // Probably 12 for players, 13 for players+ball
+ for (int i = 0; i < 12; i++) {
+ int bestDistance = maxDistance;
+ for (int j = i + 1; j < 13; j++) {
+ closestDistance[i * 15 + j] = distance(objectX[i], objectX[j], objectZ[i], objectZ[j]);
+ putInArray(a2, i, j, closestDistance[i * 15 + j]);
+ putInArray(a2, j, i, closestDistance[i * 15 + j]);
+ if (closestDistance[i * 15 + j] < bestDistance) {
+ bestDistance = closestDistance[i * 15 + j];
+ closestActor[i] = j + 1;
+ closestActor[j] = i + 1;
+ }
+ }
+ }
+
+ int v13 = getFromArray(worldPosArray, 18, 0);
+ int v14 = getFromArray(worldPosArray, 18, 2);
+ int v15 = getFromArray(worldPosArray, 19, 0);
+ int v16 = getFromArray(worldPosArray, 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(v15, objectX[i], v16, objectZ[i]);
+
+ for (int i = 0; i < 13; i++)
+ v19[i] = distance(v13, objectX[i], v14, objectZ[i]);
+ } else {
+ // soccermls and soccer2004 use two other arrays here
+ int v9 = getFromArray(worldPosArray, 20, 0);
+ int v10 = getFromArray(worldPosArray, 20, 2);
+ int v11 = getFromArray(worldPosArray, 21, 0);
+ int v12 = getFromArray(worldPosArray, 21, 2);
+
+ for (int i = 0; i < 6; i++) {
+ v20[i] = distance(v9, objectX[i], v10, objectZ[i]);
+ v19[i] = distance(v13, objectX[i], v14, objectZ[i]);
+ }
+
+ for (int i = 6; i < 13; i++) {
+ v20[i] = distance(v11, objectX[i], v12, objectZ[i]);
+ v19[i] = distance(v15, objectX[i], v16, objectZ[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(closestActorArray, 0, i, closestActor[i]);
+ }
+}
+
+int LogicHEsoccer::op_1012(int32 *args) {
+ // 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];
+ _userDataD[536] = args[6];
+
+ return 1;
+}
+
+int LogicHEsoccer::addCollisionTreeChild(int depth, int index, int parent) {
+ uint32 *dataPtr = _collisionTree + 11 * index;
+
+ /*
+ * This sets up a node of the tree stored in _collisionTree. There are
+ * two sets of parents (at depth 1 and 2), then child nodes at depth
+ * 3 which represent a single collision object.
+ *
+ * 0 = this index, 1 = parent index,
+ * 2-9 = child indices (or all -1 if leaf),
+ * 10 = _collisionObjIds index (if leaf)
+ */
+ dataPtr[0] = index;
+ dataPtr[1] = parent;
+
+ if (depth > 2) {
+ // store the offset into _collisionObjIds (which holds collision object ids),
+ // but subtract 585 first because there are already (8 + 8*8 + 8*8*8 = 584)
+ // indexes at higher levels of the tree, and we want to start at 0
+ dataPtr[10] = 8 * index - 585;
+ for (int i = 0; i < 8; i++)
+ dataPtr[i + 2] = 0xffffffff;
+ } else {
+ for (int i = 0; i < 8; i++)
+ dataPtr[i + 2] = addCollisionTreeChild(depth + 1, i + 8 * index + 1, index);
+ }
+
+ return index;
+}
+
+int LogicHEsoccer::op_1013(int32 a1, int32 a2, int32 a3) {
+ // Initialises _collisionTree, a tree used for collision detection.
+ // It is used by op_1014 to work out which objects to check.
+
+ _collisionTree = new uint32[585 * 11];
+ _collisionTreeAllocated = true;
+ for (int i = 0; i < 585 * 11; i++)
+ _collisionTree[i] = 0;
+
+ for (int i = 0; i < 8; i++)
+ _collisionTree[i + 2] = addCollisionTreeChild(1, i + 1, 0);
+
+ return 1;
+}
+
+int LogicHEsoccer::op_1014(int32 srcX, int32 srcY, int32 srcZ, int32 velX, int32 velY, int32 velZ, int32 outArray, int32 dataArrayId, int32 indexArrayId, int32 requestType, int32 vecNumerator, int32 vecDenom, int32 a13, int32 a14) {
+ // Used many times during a match
+ // And called from op_1008!
+ // This seems to be doing collision handling
+
+ double startX = (double)srcX;
+ double startY = (double)srcY;
+ double startZ = (double)srcZ;
+ double adjustedVelZ = 0.0, adjustedVelY = 0.0, adjustedVelX = 0.0;
+
+ writeScummVar(108, 0);
+ writeScummVar(109, 0);
+
+ switch (requestType) {
+ case 1:
+ case 3:
+ adjustedVelX = (double)velX * (double)vecNumerator / (double)vecDenom / 100.0;
+ adjustedVelY = (double)velY * (double)vecNumerator / (double)vecDenom / 100.0;
+ adjustedVelZ = (double)velZ * (double)vecNumerator / (double)vecDenom / 100.0;
+ break;
+ case 2:
+ // length of movement vector
+ double v15 = vectorLength((double)velX * (double)vecNumerator / (double)vecDenom, (double)velY * (double)vecNumerator / (double)vecDenom, (double)velZ * (double)vecNumerator / (double)vecDenom);
+
+ if (v15 != 0.0) {
+ // add the (scaled) movement vector to the input
+ double v26 = (double)ABS(velX) * (double)vecNumerator / (double)vecDenom * 50.0 / v15;
+ srcX = (int)((double)srcX + v26);
+ double v25 = (double)ABS(velY) * (double)vecNumerator / (double)vecDenom * 50.0 / v15;
+ srcY = (int)((double)srcY + v25);
+ double v24 = (double)ABS(velZ) * (double)vecNumerator / (double)vecDenom * 50.0 / v15;
+ srcZ = (int)((double)srcZ + v24);
+ }
+
+ // srcX = (newX / newZ) * 3869
+ startX = (double)srcX / (double)srcZ * 3869.0;
+ // srcY = (newY - (+524 * 100)) / (newZ * 3869 + (+524 * 100)
+ startY = ((double)srcY - _userDataD[524] * 100.0) / (double)srcZ * 3869.0 + _userDataD[524] * 100.0;
+ // srcZ = 3869
+ startZ = 3869.0;
+ // vectorX = (newX - srcX) / 100
+ adjustedVelX = ((double)srcX - startX) / 100.0;
+ // vectorY = (newY - srcY) / 100
+ adjustedVelY = ((double)srcY - startY) / 100.0;
+ // vectorZ = (newZ - 3869 = srcZ) / 100
+ adjustedVelZ = ((double)srcZ - 3869.0) / 100.0;
+ break;
+ }
+
+ int foundCollision = 0;
+
+ // work out which collision objects we might collide with (if any)
+ if (generateCollisionObjectList(startX, startY, startZ, adjustedVelX, adjustedVelY, adjustedVelZ)) {
+ int collisionId = 0;
+ float v46; // always 1.0 after a collision due to op_1005
+
+ float collisionInfo[42 * 8];
+ memset(collisionInfo, 0, 42 * 8 * sizeof(float));
+
+ // check each potential collision object for an actual collision,
+ // add it to collisionInfo if there is one
+ for (Common::List<byte>::const_iterator it = _collisionObjs.begin(); it != _collisionObjs.end(); it++) {
+ float collideZ, collideY, collideX;
+ float nextVelX, nextVelY, nextVelZ;
+
+ if (findCollisionWith(*it, startX, startY, startZ, adjustedVelX * 100.0, adjustedVelY * 100.0, adjustedVelZ * 100.0, collideX, collideY, collideZ, indexArrayId, dataArrayId, &nextVelX, &nextVelY, &nextVelZ, &v46)) {
+ collisionInfo[collisionId * 8] = *it;
+ collisionInfo[collisionId * 8 + 1] = vectorLength(collideX - startX, collideY - startY, collideZ - startZ);
+ collisionInfo[collisionId * 8 + 2] = collideX;
+ collisionInfo[collisionId * 8 + 3] = collideY;
+ collisionInfo[collisionId * 8 + 4] = collideZ;
+ collisionInfo[collisionId * 8 + 5] = vecDenom * nextVelX / vecNumerator;
+ collisionInfo[collisionId * 8 + 6] = vecDenom * nextVelY / vecNumerator;
+ collisionInfo[collisionId * 8 + 7] = vecDenom * nextVelZ / vecNumerator;
+ foundCollision = 1;
+ collisionId++;
+ }
+ }
+
+ if (foundCollision) {
+ // if we have more than one collision, sort them by distance
+ // to find the closest one
+ if (collisionId != 1)
+ sortCollisionList(collisionInfo, 42, 8, 1);
+
+ int v22, v39, v42;
+ float tmpData[8];
+ int outData[10];
+
+ // output the collision we found
+ switch (requestType) {
+ case 1:
+ for (int i = 0; i < 8; i++)
+ tmpData[i] = collisionInfo[i];
+ v22 = getFromArray(indexArrayId, 0, (int)((tmpData[0] - 1.0) * 4.0));
+ v42 = getFromArray(indexArrayId, 0, (int)((tmpData[0] - 1.0) * 4.0 + 1.0));
+ v39 = getFromArray(indexArrayId, 0, (int)((tmpData[0] - 1.0) * 4.0 + 2.0));
+ setCollisionOutputData(tmpData, 8, dataArrayId, indexArrayId, (int)startX, (int)startY, (int)startZ, v46, v22, v42, v39, outData);
+ for (int i = 0; i < 10; i++)
+ putInArray(outArray, 0, i, outData[i]);
+ break;
+ case 2:
+ // write the object id if collision happened (note that other case can't happen)
+ if (collisionId)
+ writeScummVar(109, (int)collisionInfo[(collisionId - 1) * 8]);
+ else
+ writeScummVar(109, 0);
+ break;
+ case 3:
+ for (int i = 0; i < 8; i++)
+ tmpData[i] = collisionInfo[i];
+ v22 = getFromArray(indexArrayId, 0, (int)((tmpData[0] - 1.0) * 4.0));
+ v42 = getFromArray(indexArrayId, 0, (int)((tmpData[0] - 1.0) * 4.0 + 1.0));
+ v39 = getFromArray(indexArrayId, 0, (int)((tmpData[0] - 1.0) * 4.0 + 2.0));
+ setCollisionOutputData(tmpData, 8, dataArrayId, indexArrayId, (int)startX, (int)startY, (int)startZ, v46, v22, v42, v39, outData);
+ for (int i = 0; i < 10; i++)
+ _internalCollisionOutData[i] = outData[i];
+ break;
+ }
+ }
+ }
+
+ writeScummVar(108, foundCollision);
+
+ _collisionObjs.clear();
+
+ return foundCollision;
+}
+
+int LogicHEsoccer::generateCollisionObjectList(float srcX, float srcY, float srcZ, float velX, float velY, float velZ) {
+ float v36 = srcX / 100.0;
+ float v37 = v36 + 52.0;
+ float destX = v37 + velX;
+
+ int v33, v29;
+
+ if (((int)destX / 52) ^ ((int)v37 / 52)) {
+ v33 = 1;
+ v29 = 1;
+ } else if ((int)v37 / 52) {
+ v29 = 0;
+ v33 = 1;
+ } else {
+ v33 = 0;
+ v29 = 1;
+ }
+
+ uint32 areaEnabled[8];
+ for (int i = 0; i < 4; i++) {
+ areaEnabled[i] = v29;
+ areaEnabled[i + 4] = v33;
+ }
+
+ float v38 = srcY / 100.0;
+ float destY = v38 + velY;
+
+ if (((int)destY / 20) ^ ((int)v38 / 20)) {
+ v33 = 1;
+ v29 = 1;
+ } else if ((int)v38 / 20) {
+ v33 = 1;
+ v29 = 0;
+ } else {
+ v29 = 1;
+ v33 = 0;
+ }
+
+ for (int i = 0; i < 2; i++) {
+ if (areaEnabled[i * 4 + 0])
+ areaEnabled[i * 4 + 0] = v29;
+ if (areaEnabled[i * 4 + 1])
+ areaEnabled[i * 4 + 1] = v29;
+ if (areaEnabled[i * 4 + 2])
+ areaEnabled[i * 4 + 2] = v33;
+ if (areaEnabled[i * 4 + 3])
+ areaEnabled[i * 4 + 3] = v33;
+ }
+
+ float v39 = srcZ / 100.0;
+ float v40 = v39 - 38.69;
+ float destZ = v40 + velZ;
+
+ if (((int)destZ / 36) ^ ((int)v40 / 36)) {
+ v33 = 1;
+ v29 = 1;
+ } else if ((int)v40 / 36) {
+ v29 = 0;
+ v33 = 1;
+ } else {
+ v33 = 0;
+ v29 = 1;
+ }
+
+ for (int i = 0; i <= 6; i += 2) {
+ if (areaEnabled[i])
+ areaEnabled[i] = v29;
+ if (areaEnabled[i + 1])
+ areaEnabled[i + 1] = v33;
+ }
+
+ int objCount = 0;
+
+ for (int i = 0; i < 8; i++) {
+ if (areaEnabled[i]) {
+ uint32 *ptr = _collisionTree + _collisionTree[i + 2] * 11;
+ objCount += addFromCollisionTreeNode(ptr[0], ptr[1], &ptr[2], ptr[10]);
+ }
+ }
+
+ writeScummVar(109, objCount);
+ return objCount;
+}
+
+int LogicHEsoccer::addFromCollisionTreeNode(int index, int parent, uint32 *indices, int objIndexBase) {
+ int objCount = 0;
+
+ if (indices[0] == 0xffffffff) {
+ for (int i = 0; i < 8; i++) {
+ if (_collisionObjIds[i + objIndexBase]) {
+ addCollisionObj(_collisionObjIds[i + objIndexBase]);
+ objCount = 1;
+ }
+ }
+ } else {
+ if (_collisionNodeEnabled[index]) {
+ for (int i = 0; i < 8; i++) {
+ uint32 *ptr = _collisionTree + indices[i] * 11;
+ objCount += addFromCollisionTreeNode(ptr[0], ptr[1], &ptr[2], ptr[10]);
+ }
+ }
+ }
+
+ return objCount;
+}
+
+void LogicHEsoccer::addCollisionObj(byte objId) {
+ // Add objId to the list if not found
+ for (Common::List<byte>::const_iterator it = _collisionObjs.begin(); it != _collisionObjs.end(); it++)
+ if (*it == objId)
+ return;
+
+ _collisionObjs.push_back(objId);
+}
+
+int LogicHEsoccer::findCollisionWith(int objId, float inX, float inY, float inZ, float inXVec, float inYVec, float inZVec, float &collideX, float &collideY, float &collideZ, int indexArrayId, int dataArrayId, float *nextVelX, float *nextVelY, float *nextVelZ, float *a15) {
+ int foundCollision = 0;
+ float inY_plus1 = inY + 1.0;
+ float destX = inX + inXVec;
+ float destY = inY_plus1 + inYVec;
+ float destZ = inZ + inZVec;
+
+ // don't go below the ground!
+ if (inY_plus1 <= 1.0001 && destY < 0.0) {
+ destY = 0.0;
+ inYVec = ABS((int)inYVec);
+ }
+
+ // get the 8 points which define the 6 faces of this object
+ int objIndex = getFromArray(indexArrayId, 0, 4 * objId - 1);
+ int objPoints[24];
+ for (int i = 0; i < 24; i++)
+ objPoints[i] = getFromArray(dataArrayId, 0, objIndex + i);
+
+ for (int faceId = 0; faceId < 6; faceId++) {
+ // This assigns variables from objPoints based on faceId
+ float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4;
+ float faceCrossX, faceCrossY, faceCrossZ;
+ getPointsForFace(faceId, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, objPoints);
+ crossProduct(x1, y1, z1, x2, y2, z2, x1, y1, z1, x3, y3, z3, faceCrossX, faceCrossY, faceCrossZ);
+
+ float faceArea = sqrt(faceCrossX * faceCrossX + faceCrossY * faceCrossY + faceCrossZ * faceCrossZ);
+
+ // The original did not initialize these variables and would
+ // use them uninitialized if faceArea == 0.0
+ float xMult = 0.0, yMult = 0.0, zMult = 0.0;
+
+ if (faceArea != 0.0) {
+ // UnitCross = Cross/||Cross||
+ xMult = faceCrossX / faceArea;
+ yMult = faceCrossY / faceArea;
+ zMult = faceCrossZ / faceArea;
+ }
+ double scalingMult = 5.0;
+
+ float ZToFacePoint1 = z1 - inZ;
+ float YToFacePoint1 = y1 - inY_plus1;
+ float XToFacePoint1 = x1 - inX;
+ // scalar component of UnitCross in direction of (start -> P1)
+ double ToFacePoint1 = dotProduct(xMult, yMult, zMult, XToFacePoint1, YToFacePoint1, ZToFacePoint1);
+
+ float ZToDest = destZ - inZ;
+ float YToDest = destY - inY_plus1;
+ float XToDest = destX - inX;
+ // scalar component of UnitCross in direction of (start -> dest)
+ double ToDest = dotProduct(xMult, yMult, zMult, XToDest, YToDest, ZToDest);
+
+ if (fabs(ToDest) > 0.00000001)
+ scalingMult = ToFacePoint1 / ToDest;
+
+ if (scalingMult >= 0.0 && fabs(scalingMult) <= 1.0 && ToDest != 0.0) {
+ // calculate where the collision would be, in the plane containing this face
+ double collisionX = inX + (destX - inX) * scalingMult;
+ double collisionY = inY_plus1 + (destY - inY_plus1) * scalingMult + 5.0;
+ double collisionZ = inZ + (destZ - inZ) * scalingMult;
+
+ // now we need to work out whether this point is actually inside the face
+ double dot1 = dotProduct(x2 - x1, y2 - y1, z2 - z1, x3 - x1, y3 - y1, z3 - z1);
+ double sqrt1 = vectorLength(x2 - x1, y2 - y1, z2 - z1);
+ double num1 = dot1 / (vectorLength(x3 - x1, y3 - y1, z3 - z1) * sqrt1);
+ num1 = CLIP<double>(num1, -1.0, 1.0);
+ double faceAngle = acos(num1);
+
+ double dot2 = dotProduct(x2 - x1, y2 - y1, z2 - z1, collisionX - x1, collisionY - y1, collisionZ - z1);
+ double sqrt2 = vectorLength(x2 - x1, y2 - y1, z2 - z1);
+ double num2 = dot2 / (vectorLength(collisionX - x1, collisionY - y1, collisionZ - z1) * sqrt2);
+ num2 = CLIP<double>(num2, -1.0, 1.0);
+ double angle1 = acos(num2);
+
+ double dot3 = dotProduct(x3 - x1, y3 - y1, z3 - z1, collisionX - x1, collisionY - y1, collisionZ - z1);
+ double sqrt3 = vectorLength(x3 - x1, y3 - y1, z3 - z1);
+ double num3 = dot3 / (vectorLength(collisionX - x1, collisionY - y1, collisionZ - z1) * sqrt3);
+ num3 = CLIP<double>(num3, -1.0, 1.0);
+ double angle2 = acos(num3);
+
+ if (angle1 + angle2 - 0.001 <= faceAngle) {
+ double dot4 = dotProduct(x2 - x4, y2 - y4, z2 - z4, x3 - x4, y3 - y4, z3 - z4);
+ double sqrt4 = vectorLength(x2 - x4, y2 - y4, z2 - z4);
+ double num4 = dot4 / (vectorLength(x3 - x4, y3 - y4, z3 - z4) * sqrt4);
+ num4 = CLIP<double>(num4, -1.0, 1.0);
+ faceAngle = acos(num4);
+
+ double dot5 = dotProduct(x2 - x4, y2 - y4, z2 - z4, collisionX - x4, collisionY - y4, collisionZ - z4);
+ double sqrt5 = vectorLength(x2 - x4, y2 - y4, z2 - z4);
+ double num5 = dot5 / (vectorLength(collisionX - x4, collisionY - y4, collisionZ - z4) * sqrt5);
+ num5 = CLIP<double>(num5, -1.0, 1.0);
+ double angle3 = acos(num5);
+
+ double dot6 = dotProduct(x3 - x4, y3 - y4, z3 - z4, collisionX - x4, collisionY - y4, collisionZ - z4);
+ double sqrt6 = vectorLength(x3 - x4, y3 - y4, z3 - z4);
+ double num6 = dot6 / (vectorLength(collisionX - x4, collisionY - y4, collisionZ - z4) * sqrt6);
+ num6 = CLIP<double>(num6, -1.0, 1.0);
+ double angle4 = acos(num6);
+
+ if (angle3 + angle4 - 0.001 <= faceAngle) {
+ // found a collision with this face
+ if (foundCollision) {
+ // if we already found one, is the new one closer?
+ // (except this don't adjust for the modification of collideX/Y/Z..)
+ double ToCollide = vectorLength(inX - collisionX, inY_plus1 - collisionY, inZ - collisionZ);
+ if (vectorLength(inX - collideX, inY_plus1 - collideY, inZ - collideZ) > ToCollide) {
+ collideX = collisionX - xMult * 3.0;
+ collideY = collisionY - yMult * 3.0;
+ collideZ = collisionZ - zMult * 3.0;
+ op_1005(xMult, yMult, zMult, inXVec, inYVec, inZVec, nextVelX, nextVelY, nextVelZ, a15);
+ }
+ } else {
+ collideX = collisionX - xMult * 3.0;
+ collideY = collisionY - yMult * 3.0;
+ collideZ = collisionZ - zMult * 3.0;
+ op_1005(xMult, yMult, zMult, inXVec, inYVec, inZVec, nextVelX, nextVelY, nextVelZ, a15);
+ }
+
+ foundCollision = 1;
+ }
+ }
+ }
+ }
+
+ return foundCollision;
+}
+
+void LogicHEsoccer::getPointsForFace(int faceId, float &x1, float &y1, float &z1, float &x2, float &y2, float &z2, float &x3, float &y3, float &z3, float &x4, float &y4, float &z4, const int *objPoints) {
+ // Note that this originally returned a value, but said value was never used
+ // TODO: This can probably be shortened using a few tables...
+
+ switch (faceId) {
+ case 0:
+ x1 = objPoints[0];
+ y1 = objPoints[1];
+ z1 = objPoints[2];
+ x2 = objPoints[3];
+ y2 = objPoints[4];
+ z2 = objPoints[5];
+ x3 = objPoints[6];
+ y3 = objPoints[7];
+ z3 = objPoints[8];
+ x4 = objPoints[9];
+ y4 = objPoints[10];
+ z4 = objPoints[11];
+ break;
+ case 1:
+ x1 = objPoints[0];
+ y1 = objPoints[1];
+ z1 = objPoints[2];
+ x2 = objPoints[6];
+ y2 = objPoints[7];
+ z2 = objPoints[8];
+ x3 = objPoints[12];
+ y3 = objPoints[13];
+ z3 = objPoints[14];
+ x4 = objPoints[18];
+ y4 = objPoints[19];
+ z4 = objPoints[20];
+ break;
+ case 2:
+ x1 = objPoints[3];
+ y1 = objPoints[4];
+ z1 = objPoints[5];
+ x2 = objPoints[15];
+ y2 = objPoints[16];
+ z2 = objPoints[17];
+ x3 = objPoints[9];
+ y3 = objPoints[10];
+ z3 = objPoints[11];
+ x4 = objPoints[21];
+ y4 = objPoints[22];
+ z4 = objPoints[23];
+ break;
+ case 3:
+ x1 = objPoints[0];
+ y1 = objPoints[1];
+ z1 = objPoints[2];
+ x2 = objPoints[12];
+ y2 = objPoints[13];
+ z2 = objPoints[14];
+ x3 = objPoints[3];
+ y3 = objPoints[4];
+ z3 = objPoints[5];
+ x4 = objPoints[15];
+ y4 = objPoints[16];
+ z4 = objPoints[17];
+ break;
+ case 4:
+ x1 = objPoints[6];
+ y1 = objPoints[7];
+ z1 = objPoints[8];
+ x2 = objPoints[9];
+ y2 = objPoints[10];
+ z2 = objPoints[11];
+ x3 = objPoints[18];
+ y3 = objPoints[19];
+ z3 = objPoints[20];
+ x4 = objPoints[21];
+ y4 = objPoints[22];
+ z4 = objPoints[23];
+ break;
+ case 5:
+ x1 = objPoints[15];
+ y1 = objPoints[16];
+ z1 = objPoints[17];
+ x2 = objPoints[12];
+ y2 = objPoints[13];
+ z2 = objPoints[14];
+ x3 = objPoints[21];
+ y3 = objPoints[22];
+ z3 = objPoints[23];
+ x4 = objPoints[18];
+ y4 = objPoints[19];
+ z4 = objPoints[20];
+ break;
+ }
+}
+
+void LogicHEsoccer::crossProduct(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4, float &outX, float &outY, float &outZ) {
+ outX = (y2 - y1) * (z4 - z3) - (y4 - y3) * (z2 - z1);
+ outY = ((x2 - x1) * (z4 - z3) - (x4 - x3) * (z2 - z1)) * -1.0;
+ outZ = (x2 - x1) * (y4 - y3) - (x4 - x3) * (y2 - y1);
+}
+
+double LogicHEsoccer::dotProduct(float a1, float a2, float a3, float a4, float a5, float a6) {
+ return a1 * a4 + a2 * a5 + a3 * a6;
+}
+
+void LogicHEsoccer::sortCollisionList(float *data, int numEntries, int entrySize, int compareOn) {
+ // This takes an input array of collisions, and tries to sort it based on the distance
+ // (index of compareOn, always 1), copying in groups of entrySize, which is always 8
+
+ bool found = true;
+ int entry = 0;
+
+ while (found) {
+ found = false;
+
+ // while we still have entries, and there is an obj id set for the next entry
+ while (entry <= numEntries - 2 && data[(entry + 1) * 8] != 0.0) {
+ // if the current entry has distance 0, or the next entry is closer (distance is less)
+ if (data[compareOn + entry * 8] == 0 || data[compareOn + entry * 8] > data[compareOn + (entry + 1) * 8]) {
+ found = true;
+
+ // swap all data with the next entry
+ for (int i = 0; i < entrySize; i++) {
+ float tmp = data[i + entry * 8];
+ data[i + entry * 8] = data[i + (entry + 1) * 8];
+ data[i + (entry + 1) * 8] = tmp;
+ }
+ }
+
+ entry++;
+ }
+ }
+}
+
+int LogicHEsoccer::setCollisionOutputData(float *collisionData, int entrySize, int dataArrayId, int indexArrayId, int startX, int startY, int startZ, float a8, int a9, int a10, int a11, int *out) {
+ // area-provided data
+ out[0] = a9;
+ out[1] = a10;
+ out[2] = a11;
+ // new velocity, slowed by area-provided value
+ out[3] = (int)(collisionData[5] * (double)a10 / 100.0);
+ out[4] = (int)(collisionData[6] * (double)a10 / 100.0 * a8); // Note: a8 should always be 1
+ out[5] = (int)(collisionData[7] * (double)a10 / 100.0);
+ // new position
+ out[6] = (int)collisionData[2];
+ out[7] = (int)collisionData[3];
+ out[8] = (int)collisionData[4];
+ // collision object id
+ out[9] = (int)collisionData[0];
+ return out[9];
+}
+
+int LogicHEsoccer::op_1016(int32 *args) {
+ // Called when a goal is scored
+
+ int result = 0;
+
+ double v9 = (double)args[1] / 100.0;
+ double v13 = (double)args[2] / 100.0;
+ double v12 = (double)args[3] / 100.0;
+ double v18 = v13 * v13;
+ double v10 = (double)args[0] / 100.0 * (double)args[0] / 100.0;
+ double v11 = v9 * v9;
+ double v19 = (v9 * v9 * v12 * v12 + 2.0 * v9 * v12 * v18 + v18 * v18) * v10 * v10 - (v10 + v11) * v12 * v12 * v10 * v10;
+
+ if (v19 >= 0.0) {
+ double v6 = sqrt(v19);
+ double v17 = ((v9 * v12 + v18) * v10 + v6) / (v10 + v11 + v10 + v11);
+ double v16 = ((v9 * v12 + v18) * v10 - v6) / (v10 + v11 + v10 + v11);
+ double v7, v14;
+
+ if (v17 <= 0.0 || (v7 = sqrt(v17), v14 = acos(v7 / v13), v14 > 0.7853981633974475)) {
+ double v8, v15;
+ if (v16 <= 0.0 || (v8 = sqrt(v16), v15 = acos(v8 / v13), v15 > 0.7853981633974475)) {
+ writeScummVar(108, -1);
+ } else {
+ writeScummVar(108, (int)(v15 / 0.01745329251994328 * 100.0));
+ result = 1;
+ }
+ } else {
+ writeScummVar(108, (int)(v14 / 0.01745329251994328 * 100.0));
+ result = 1;
+ }
+ } else {
+ writeScummVar(108, -1);
+ }
+
+ return result;
+}
+
+int LogicHEsoccer::op_1017(int32 *args) {
+ // Used sporadically during a match (out of bounds?)
+ if (!args[1])
+ args[1] = 1;
+
+ double v3 = asin((double)args[0] / (double)args[1]);
+ writeScummVar(108, (int32)(v3 / 0.01745329251994328 * (double)args[1]));
+
+ return 1;
+}
+
+int LogicHEsoccer::op_1019(int32 *args) {
+ // Used at the beginning of a match
+ // Initializes some arrays with field collision data
+
+ // _collisionObjIds provides object ids for leaf nodes
+ // of the collision tree (_collisionTree).
+ for (int i = 0; i < 4096; i++)
+ _collisionObjIds[i] = getFromArray(args[1], 0, i);
+
+ // _collisionNodeEnabled enables or disables non-leaf nodes
+ // of the collision tree (_collisionTree).
+ for (int i = 0; i < 585; i++)
+ _collisionNodeEnabled[i] = getFromArray(args[0], 0, i);
+
+ // The remaining code of this function was used for the
+ // built-in editor. However, it is incomplete in the
+ // final product, so we do not need to have it.
+
+ return 1;
+}
+
+int LogicHEsoccer::op_1021(int32 inX, int32 inY, int32 inZ, int32 velX, int32 velY, int32 velZ, int32 internalUse) {
+ // Used during a match (ball movement?)
+ // Also called from op_1008
+
+ int outX;
+ if (velX && velY)
+ outX = (int)(((double)inY - (double)velY * (double)inX / (double)velX) * -1.0 * (double)velX / (double)velY);
+ else
+ outX = inX;
+
+ int outZ;
+ if (velZ && velY)
+ outZ = (int)(((double)inY - (double)velY * (double)inZ / (double)velZ) * -1.0 * (double)velZ / (double)velY);
+ else
+ outZ = inZ;
+
+ // The final argument chooses whether to store the results for op_1008 or
+ // store them in SCUMM variables.
+ if (internalUse) {
+ _var1021[0] = outX;
+ _var1021[1] = outZ;
+ } else {
+ writeScummVar(108, outX);
+ writeScummVar(109, outZ);
+ }
+
+ return 1;
+}
+
+LogicHE *makeLogicHEsoccer(ScummEngine_v90he *vm) {
+ return new LogicHEsoccer(vm);
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/logic_he.cpp b/engines/scumm/he/logic_he.cpp
index af56bca2ee..a76c393e13 100644
--- a/engines/scumm/he/logic_he.cpp
+++ b/engines/scumm/he/logic_he.cpp
@@ -33,29 +33,10 @@ LogicHE::LogicHE(ScummEngine_v90he *vm) : _vm(vm) {
LogicHE::~LogicHE() {
}
-LogicHErace::LogicHErace(ScummEngine_v90he *vm) : LogicHE(vm) {
- // Originally it used 0x930 and stored both floats and doubles inside
- _userData = (float *)calloc(550, sizeof(float));
- _userDataD = (double *)calloc(30, sizeof(double));
-
- // FIXME: of the 550 entries in _userData, only 516 till 532 are used
- // FIXME: similarly, in _userDataD only 9 till 17 are used for computations
- // (some of the other entries are also set, but never read, hence useless).
-}
-
-LogicHErace::~LogicHErace() {
- free(_userData);
- free(_userDataD);
-}
-
void LogicHE::writeScummVar(int var, int32 value) {
_vm->writeVar(var, value);
}
-static int32 scumm_round(double arg) {
- return (int32)(arg + 0.5);
-}
-
int LogicHE::versionID() {
return 1;
}
@@ -95,1370 +76,34 @@ int32 LogicHE::dispatch(int op, int numArgs, int32 *args) {
return 1;
}
-/***********************
- * Putt-Putt Joins the Race
- *
- */
-
-int LogicHErace::versionID() {
- return 1;
-}
-
-int32 LogicHErace::dispatch(int op, int numArgs, int32 *args) {
- int32 res;
-
- switch (op) {
- case 1003:
- res = op_1003(args);
- break;
-
- case 1004:
- res = op_1004(args);
- break;
-
- case 1100:
- res = op_1100(args);
- break;
-
- case 1101:
- res = op_1101(args);
- break;
-
- case 1102:
- res = op_1102(args);
- break;
-
- case 1103:
- res = op_1103(args);
- break;
-
- case 1110:
- res = op_1110();
- break;
-
- case 1120:
- res = op_1120(args);
- break;
-
- case 1130:
- res = op_1130(args);
- break;
-
- case 1140:
- res = op_1140(args);
- break;
-
- default:
- res = 0;
- break;
-
- }
-
- return res;
-}
-
-#define RAD2DEG (180 / M_PI)
-#define DEG2RAD (M_PI / 180)
-
-int32 LogicHErace::op_1003(int32 *args) {
- int value = args[2] ? args[2] : 1;
-
- writeScummVar(108, (int32)(atan2((double)args[0], (double)args[1]) * RAD2DEG * value));
-
- return 1;
-}
-
-int32 LogicHErace::op_1004(int32 *args) {
- int value = args[1] ? args[1] : 1;
-
- writeScummVar(108, (int32)(sqrt((float)args[0]) * value));
-
- return 1;
-}
-
-int32 LogicHErace::op_1100(int32 *args) {
- // _userData 516,517,518 describe a 3D translation?
- _userData[516] = (float)args[0] / args[10];
- _userData[517] = (float)args[1] / args[10];
- _userData[518] = (float)args[2] / args[10];
-
- // _userData 519,520,521 describe rotation angles around the x,y,z axes?
- _userData[519] = (float)args[3] / args[10];
- _userData[520] = (float)args[4] / args[10];
- _userData[521] = (float)args[5] / args[10];
-
- op_sub1(_userData[520]);
- op_sub2(_userData[521]);
-
- // _userData[532] seems to be some kind of global scale factor
- _userData[532] = (float)args[10];
-
- _userData[524] = (float)args[8]; // not used
- _userData[525] = (float)args[9]; // not used
- _userData[522] = (float)args[6] / args[10]; // not used
- _userData[523] = (float)args[7] / args[10]; // only used to compute 528 and 529
-
- // The following two are some kind of scale factors
- _userData[526] = (float)args[6] / args[8] / args[10];
- _userData[527] = (float)args[7] / args[9] / args[10];
-
- // Set var 108 and 109 -- the value set here corresponds to the values
- // set by op_1110!
- writeScummVar(108, (int32)((float)args[6] / args[8] * args[10]));
- writeScummVar(109, (int32)((float)args[7] / args[9] * args[10]));
-
- _userData[528] = (float)(_userData[519] - _userData[523] * 0.5);
- _userData[529] = (float)(_userData[519] + _userData[523] * 0.5);
-
- writeScummVar(110, (int32)(_userData[528] * args[10]));
- writeScummVar(111, (int32)(_userData[529] * args[10]));
-
- // 530 and 531 are only used to set vars 112 and 113, so no need
- // to store them permanently
- _userData[530] = (float)(_userData[517] / tan(_userData[529] * DEG2RAD));
- _userData[531] = (float)(_userData[517] / tan(_userData[528] * DEG2RAD));
-
- writeScummVar(112, (int32)(_userData[530] * args[10]));
- writeScummVar(113, (int32)(_userData[531] * args[10]));
-
- return 1;
-}
-
-int32 LogicHErace::op_1101(int32 *args) {
- // Update rotation params?
- int32 retval;
- float temp;
-
- temp = args[0] / _userData[532];
- if (_userData[519] != temp) {
- _userData[519] = temp;
- op_sub3(temp);
- retval = 1;
- } else {
- retval = (int32)temp;
- }
-
- temp = args[1] / _userData[532];
- if (_userData[520] != temp) {
- _userData[520] = temp;
- op_sub1(temp);
- retval = 1;
- }
-
- temp = args[2] / _userData[532];
- if (_userData[521] != temp) {
- _userData[521] = temp;
- op_sub2(temp);
- retval = 1;
- }
-
- return retval;
-}
-
-int32 LogicHErace::op_1102(int32 *args) {
- // Update translation params?
- int32 retval;
- float temp;
-
- temp = args[0] / _userData[532];
- if (_userData[516] != temp) {
- _userData[516] = temp;
- retval = 1;
- } else {
- retval = (int32)_userData[532];
- }
-
- temp = args[1] / _userData[532];
- if (_userData[517] != temp) {
- _userData[517] = temp;
- retval = 1;
- }
-
- temp = args[2] / _userData[532];
- if (_userData[518] != temp) {
- _userData[518] = temp;
- retval = 1;
- }
-
- return retval;
-}
-
-int32 LogicHErace::op_1103(int32 *args) {
- double angle = args[0] / args[1] * DEG2RAD;
-
- writeScummVar(108, (int32)(sin(angle) * args[2]));
- writeScummVar(109, (int32)(cos(angle) * args[2]));
-
- return 1;
-}
-
-int32 LogicHErace::op_1110() {
- writeScummVar(108, (int32)(_userData[526] * _userData[532] * _userData[532]));
- writeScummVar(109, (int32)(_userData[527] * _userData[532] * _userData[532]));
- writeScummVar(110, (int32)(_userData[532]));
-
- return 1;
-}
-
-int32 LogicHErace::op_1120(int32 *args) {
- double a0, a1, a2;
- double b0, b1, b2;
- double res1, res2;
-
- a0 = args[0] / _userData[532] - _userData[516];
- a1 = args[1] / _userData[532] - _userData[517];
- a2 = args[2] / _userData[532] - _userData[518];
-
- // Perform matrix multiplication (multiplying by a rotation matrix)
- b2 = a2 * _userDataD[17] + a1 * _userDataD[14] + a0 * _userDataD[11];
- b1 = a2 * _userDataD[16] + a1 * _userDataD[13] + a0 * _userDataD[10];
- b0 = a2 * _userDataD[15] + a1 * _userDataD[12] + a0 * _userDataD[9];
-
- res1 = (atan2(b0, b2) * RAD2DEG) / _userData[526];
- res2 = (atan2(b1, b2) * RAD2DEG - _userData[528]) / _userData[527];
-
- writeScummVar(108, (int32)res1);
- writeScummVar(109, (int32)res2);
-
- return 1;
-}
-
-int32 LogicHErace::op_1130(int32 *args) {
- double cs = cos(args[0] / _userData[532] * DEG2RAD);
- double sn = sin(args[0] / _userData[532] * DEG2RAD);
-
- writeScummVar(108, (int32)(cs * args[1] + sn * args[2]));
- writeScummVar(109, (int32)(cs * args[2] - sn * args[1]));
-
- return 1;
-}
-
-int32 LogicHErace::op_1140(int32 *args) {
- // This functions seems to perform some kind of projection: We project
- // the vector (arg2,arg3) onto the vector (arg0,arg1), but also apply
- // some kind of distortion factor ?!?
- double x = args[2], y = args[3];
-
- // We start by normalizing the vector described by arg2 and arg3.
- // So compute its length and divide the x and y coordinates
- const double sq = sqrt(x*x + y*y);
- x /= sq;
- y /= sq;
-
- // Compute the scalar product of the vectors (arg0,arg1) and (x,y)
- const double scalarProduct = x * args[0] + y * args[1];
-
- // Finally compute the projection of (arg2,arg3) onto (arg0,arg1)
- double projX = args[0] - 2 * scalarProduct * x;
- double projY = args[1] - 2 * scalarProduct * y;
-
- projX = projX * 20.0 / 23.0; // FIXME: Why is this here?
-
- writeScummVar(108, (int32)projX);
-
- if (args[3] >= 0) // FIXME: Why is this here?
- projY = projY * 5.0 / 6.0;
-
- writeScummVar(109, (int32)projY);
-
- return 1;
-}
-
-void LogicHErace::op_sub1(float arg) {
- // Setup a rotation matrix
- _userDataD[10] = _userDataD[12] = _userDataD[14] = _userDataD[16] = 0;
- _userDataD[13] = 1;
-
- _userDataD[9] = cos(arg * DEG2RAD);
- _userDataD[15] = sin(arg * DEG2RAD);
- _userDataD[11] = -_userDataD[15];
- _userDataD[17] = _userDataD[9];
-}
-
-void LogicHErace::op_sub2(float arg) {
- // Setup a rotation matrix -- but it is NEVER USED!
- _userDataD[20] = _userDataD[21] = _userDataD[24] = _userDataD[25] = 0;
- _userDataD[26] = 1;
-
- _userDataD[19] = sin(arg * DEG2RAD);
- _userDataD[18] = cos(arg * DEG2RAD);
- _userDataD[21] = -_userDataD[19];
- _userDataD[22] = _userDataD[18];
-}
-
-void LogicHErace::op_sub3(float arg) {
- // Setup a rotation matrix -- but it is NEVER USED!
- _userDataD[1] = _userDataD[2] = _userDataD[3] = _userDataD[6] = 0;
- _userDataD[0] = 1;
-
- _userDataD[4] = cos(arg * DEG2RAD);
- _userDataD[5] = sin(arg * DEG2RAD);
- _userDataD[7] = -_userDataD[5];
- _userDataD[8] = _userDataD[4];
-}
-
-/***********************
- * Freddi Fish's One-Stop Fun Shop
- * Pajama Sam's One-Stop Fun Shop
- * Putt-Putt's One-Stop Fun Shop
- *
- */
-
-int LogicHEfunshop::versionID() {
- return 1;
-}
-
-int32 LogicHEfunshop::dispatch(int op, int numArgs, int32 *args) {
- switch (op) {
- case 1004:
- op_1004(args);
- break;
-
- case 1005:
- op_1005(args);
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-void LogicHEfunshop::op_1004(int32 *args) {
- double data[8], at, sq;
- int32 x, y;
- int i=0;
-
- for (i = 0; i <= 6; i += 2) {
- data[i] = getFromArray(args[0], 0, 519 + i);
- data[i + 1] = getFromArray(args[0], 0, 519 + i + 1);
- }
- int s = checkShape((int32)data[0], (int32)data[1], (int32)data[4], (int32)data[5],
- (int32)data[2], (int32)data[3], (int32)data[6], (int32)data[7], &x, &y);
-
- if (s != 1) {
- error("LogicHEfunshop::op_1004: Your shape has defied the laws of physics");
- return;
- }
-
- for (i = 0; i <= 6; i += 2) {
- data[i] -= (double)x;
- data[i + 1] -= (double)y;
- }
-
- double a1 = (double)args[1] * DEG2RAD;
-
- for (i = 0; i <= 6; i += 2) {
- at = atan2(data[i + 1], data[i]);
- sq = sqrt(data[i + 1] * data[i + 1] + data[i] * data[i]);
-
- if (at <= 0)
- at += 2 * M_PI;
-
- data[i] = cos(at + a1) * sq;
- data[i + 1] = sin(at + a1) * sq;
- }
-
- double minx = data[0];
- double miny = data[1];
-
- for (i = 0; i <= 6; i += 2) {
- if (data[i] < minx)
- minx = data[i];
- if (data[i + 1] < miny)
- miny = data[i + 1];
- }
-
- for (i = 0; i <= 6; i += 2) {
- data[i] -= minx;
- data[i + 1] -= miny;
-
- putInArray(args[0], 0, 519 + i, scumm_round(data[i]));
- putInArray(args[0], 0, 519 + i + 1, scumm_round(data[i + 1]));
- }
-}
-
-void LogicHEfunshop::op_1005(int32 *args) {
- double data[8];
- double args1, args2;
- int i;
- for (i = 520; i <= 526; i += 2) {
- data[i - 520] = getFromArray(args[0], 0, i - 1);
- data[i - 520 + 1] = getFromArray(args[0], 0, i);
- }
-
- args1 = (double)args[1] * 0.01 + 1;
- args2 = (double)args[2] * 0.01 + 1;
-
- for (i = 0; i < 4; i++) {
- data[2 * i] *= args1;
- data[2 * i + 1] *= args2;
- }
-
- for (i = 520; i <= 526; i += 2) {
- putInArray(args[0], 0, i - 1, scumm_round(data[i - 520]));
- putInArray(args[0], 0, i, scumm_round(data[i - 520 + 1]));
- }
-}
-
-int LogicHEfunshop::checkShape(int32 data0, int32 data1, int32 data4, int32 data5, int32 data2, int32 data3, int32 data6, int32 data7, int32 *x, int32 *y) {
- int32 diff5_1, diff0_4, diff7_3, diff2_6;
- int32 diff1, diff2;
- int32 delta, delta2;
- int32 sum1, sum2;
-
- diff0_4 = data0 - data4;
- diff5_1 = data5 - data1;
- diff1 = data1 * data4 - data0 * data5;
- sum1 = diff0_4 * data3 + diff1 + diff5_1 * data2;
- sum2 = diff0_4 * data7 + diff1 + diff5_1 * data6;
-
- if (sum1 != 0 && sum2 != 0) {
- sum2 ^= sum1;
-
- if (sum2 >= 0)
- return 0;
- }
-
- diff2_6 = data2 - data6;
- diff7_3 = data7 - data3;
- diff2 = data3 * data6 - data2 * data7;
- sum1 = diff2_6 * data1 + diff2 + diff7_3 * data0;
- sum2 = diff2_6 * data5 + diff2 + diff7_3 * data4;
-
- if (sum1 != 0 && sum2 != 0) {
- sum2 ^= sum1;
-
- if (sum2 >= 0)
- return 0;
- }
-
- delta = diff2_6 * diff5_1 - diff0_4 * diff7_3;
-
- if (delta == 0) {
- return 2;
- }
-
- if (delta < 0) {
- data7 = -((delta + 1) >> 1);
- } else {
- data7 = delta >> 1;
- }
-
- delta2 = diff2 * diff0_4 - diff1 * diff2_6;
-
- if (delta2 < 0) {
- delta2 -= data7;
- } else {
- delta2 += data7;
- }
-
- *x = delta2 / delta;
-
- delta2 = diff1 * diff7_3 - diff2 * diff5_1;
-
- if (delta2 < 0) {
- delta2 -= data7;
- } else {
- delta2 += data7;
- }
-
- *y = delta2 / delta;
-
- return 1;
-}
-
-/***********************
- * Backyard Football
- * Backyard Football 2002
- * Backyard Football Demo
- *
- */
-
-int LogicHEfootball::versionID() {
- return 1;
-}
-
-int32 LogicHEfootball::dispatch(int op, int numArgs, int32 *args) {
- int res = 0;
-
- switch (op) {
- case 1004:
- res = op_1004(args);
- break;
-
- case 1006:
- res = op_1006(args);
- break;
-
- case 1007:
- res = op_1007(args);
- break;
-
- case 1010:
- res = op_1010(args);
- break;
-
- case 1022:
- res = op_1022(args);
- break;
-
- case 1023:
- res = op_1023(args);
- break;
-
- case 1024:
- res = op_1024(args);
- break;
-
- case 8221968:
- // Someone had a fun and used his birthday as opcode number
- res = getFromArray(args[0], args[1], args[2]);
- break;
-
- case 1492: case 1493: case 1494: case 1495: case 1496:
- case 1497: case 1498: case 1499: case 1500: case 1501:
- case 1502: case 1503: case 1504: case 1505: case 1506:
- case 1507: case 1508: case 1509: case 1510: case 1511:
- case 1512: case 1513: case 1514: case 1555:
- // DirectPlay-related
- // 1513: initialize
- // 1555: set fake lag
- break;
-
- case 2200: case 2201: case 2202: case 2203: case 2204:
- case 2205: case 2206: case 2207: case 2208: case 2209:
- case 2210: case 2211: case 2212: case 2213: case 2214:
- case 2215: case 2216: case 2217: case 2218: case 2219:
- case 2220: case 2221: case 2222: case 2223: case 2224:
- case 2225: case 2226: case 2227: case 2228:
- // Boneyards-related
- break;
-
- case 3000: case 3001: case 3002: case 3003: case 3004:
- // Internet-related
- // 3000: check for updates
- // 3001: check network status
- // 3002: autoupdate
- // 3003: close connection
- break;
-
- default:
- LogicHE::dispatch(op, numArgs, args);
- warning("Tell sev how to reproduce it (%d)", op);
- }
-
- return res;
-}
-
-int LogicHEfootball::op_1004(int32 *args) {
- // Identical to LogicHEsoccer::op_1004
- double res, a2, a4, a5;
-
- a5 = ((double)args[4] - (double)args[1]) / ((double)args[5] - (double)args[2]);
- a4 = ((double)args[3] - (double)args[0]) / ((double)args[5] - (double)args[2]);
- a2 = (double)args[2] - (double)args[0] * a4 - args[1] * a5;
-
- res = (double)args[6] * a4 + (double)args[7] * a5 + a2;
- writeScummVar(108, (int32)res);
-
- writeScummVar(109, (int32)a2);
- writeScummVar(110, (int32)a5);
- writeScummVar(111, (int32)a4);
-
- return 1;
-}
-
-int LogicHEfootball::op_1006(int32 *args) {
- // This seems to be more or less the inverse of op_1010
- const double a1 = args[1];
- double res;
-
- // 2.9411764e-4 = 1/3400
- // 5.3050399e-2 = 1/18.85 = 20/377
- // 1.1764706e-2 = 1/85 = 40/3400
- // 1.2360656e-1 = 377/3050
- res = (1.0 - a1 * 2.9411764e-4 * 5.3050399e-2) * 1.2360656e-1 * args[0] +
- a1 * 1.1764706e-2 + 46;
-
- // Shortened / optimized version of that formula:
- // res = (377.0 - a1 / 170.0) / 3050.0 * args[0] + a1 / 85.0 + 46;
-
- writeScummVar(108, (int32)res);
-
- // 1.2360656e-1 = 377/3050
- // 1.1588235e-1 = 197/1700 = 394/3400
- res = 640.0 - args[2] * 1.2360656e-1 - a1 * 1.1588235e-1 - 26;
-
- writeScummVar(109, (int32)res);
-
- return 1;
-}
-
-int LogicHEfootball::op_1007(int32 *args) {
- double res, temp;
-
- temp = (double)args[1] * 0.32;
-
- if (temp > 304.0)
- res = -args[2] * 0.142;
- else
- res = args[2] * 0.142;
-
- res += temp;
-
- writeScummVar(108, (int32)res);
-
- res = (1000.0 - args[2]) * 0.48;
-
- writeScummVar(109, (int32)res);
-
- return 1;
-}
-
-int LogicHEfootball::op_1010(int32 *args) {
- // This seems to be more or less the inverse of op_1006
- double a1 = (640.0 - (double)args[1] - 26.0) / 1.1588235e-1;
-
- // 2.9411764e-4 = 1/3400
- // 5.3050399e-2 = 1/18.85 = 20/377
- // 1.1764706e-2 = 1/85 = 40/3400
- // 1.2360656e-1 = 377/3050
- double a0 = ((double)args[0] - 46 - a1 * 1.1764706e-2) /
- ((1.0 - a1 * 2.9411764e-4 * 5.3050399e-2) * 1.2360656e-1);
-
- writeScummVar(108, (int32)a0);
- writeScummVar(109, (int32)a1);
-
- return 1;
-}
-
-int LogicHEfootball::op_1022(int32 *args) {
- double res;
- double var10 = args[4] - args[1];
- double var8 = args[5] - args[2];
- double var6 = args[3] - args[0];
-
- res = sqrt(var8 * var8 + var6 * var6 + var10 * var10);
-
- if (res >= (double)args[6]) {
- var8 = (double)args[6] * var8 / res;
- var10 = (double)args[6] * var10 / res;
- res = (double)args[6] * var6 / res;
- }
-
- writeScummVar(108, (int32)res);
- writeScummVar(109, (int32)var10);
- writeScummVar(110, (int32)var8);
-
- return 1;
-}
-
-int LogicHEfootball::op_1023(int32 *args) {
- double var10, var18, var20, var28, var30, var30_;
- double argf[7];
-
- for (int i = 0; i < 7; i++)
- argf[i] = args[i];
-
- var10 = (argf[3] - argf[1]) / (argf[2] - argf[0]);
- var28 = var10 * var10 + 1;
- var20 = argf[0] * var10;
- var18 = (argf[5] + argf[1] + var20) * argf[4] * var10 * 2 +
- argf[6] * argf[6] * var28 + argf[4] * argf[4] -
- argf[0] * argf[0] * var10 * var10 -
- argf[5] * argf[0] * var10 * 2 -
- argf[5] * argf[1] * 2 -
- argf[1] * argf[1] - argf[5] * argf[5];
-
- if (var18 >= 0) {
- var18 = sqrt(var18);
-
- var30_ = argf[4] + argf[5] * var10 + argf[1] * var10 + argf[0] * var10 * var10;
- var30 = (var30_ - var18) / var28;
- var18 = (var30_ + var18) / var28;
-
- if ((argf[0] - var30 < 0) && (argf[0] - var18 < 0)) {
- var30_ = var30;
- var30 = var18;
- var18 = var30_;
- }
- var28 = var18 * var10 - var20 - argf[1];
- var20 = var30 * var10 - var20 - argf[1];
- } else {
- var18 = 0;
- var20 = 0;
- var28 = 0;
- var30 = 0;
- }
-
- writeScummVar(108, (int32)var18);
- writeScummVar(109, (int32)var28);
- writeScummVar(110, (int32)var30);
- writeScummVar(111, (int32)var20);
-
- return 1;
-}
-int LogicHEfootball::op_1024(int32 *args) {
- writeScummVar(108, 0);
- writeScummVar(109, 0);
- writeScummVar(110, 0);
- writeScummVar(111, 0);
-
- return 1;
-}
-
-
-/***********************
- * Backyard Soccer
- *
- */
-
-int LogicHEsoccer::versionID() {
- return 1;
-}
-
-LogicHEsoccer::LogicHEsoccer(ScummEngine_v90he *vm) : LogicHE(vm) {
- _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) {
- int res = 0;
-
- switch (op) {
- case 1001:
- res = op_1001(args);
- break;
-
- case 1002:
- res = op_1002(args);
- break;
-
- case 1004:
- 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]);
- break;
-
- default:
- // original range is 1001 - 1021
- LogicHE::dispatch(op, numArgs, 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]));
-}
-
-int LogicHEsoccer::op_1002(int32 *args) {
- return _vm->VAR(2) * args[0];
-}
-
-int LogicHEsoccer::op_1003(int32 *args) {
- double data[6], out[3];
- int i;
-
- for (i = 0; i < 6; i++) {
- data[i] = getFromArray(args[0], 0, i);
- }
-
- out[0] = data[1] * data[5] - data[4] * data[2];
- out[1] = data[5] * data[0] - data[3] * data[2];
- out[2] = data[4] * data[0] - data[3] * data[1];
-
- for (i = 0; i < 3; i++) {
- putInArray(args[0], 0, i, scumm_round(out[i]));
- }
-
- return 1;
-}
-
-int LogicHEsoccer::op_1004(int32 *args) {
- // Identical to LogicHEfootball::op_1004
- double res, a2, a4, a5;
-
- a5 = ((double)args[4] - (double)args[1]) / ((double)args[5] - (double)args[2]);
- a4 = ((double)args[3] - (double)args[0]) / ((double)args[5] - (double)args[2]);
- a2 = (double)args[2] - (double)args[0] * a4 - args[1] * a5;
-
- res = (double)args[6] * a4 + (double)args[7] * a5 + a2;
- writeScummVar(108, (int32)res);
-
- writeScummVar(109, (int32)a2);
- writeScummVar(110, (int32)a5);
- writeScummVar(111, (int32)a4);
-
- return 1;
-}
-
-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] = a4;
-
- 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);
-
- return 1;
-}
-
-int LogicHEsoccer::op_1007(int32 *args) {
- // 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) {
- // 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;
+LogicHE *LogicHE::makeLogicHE(ScummEngine_v90he *vm) {
+ switch (vm->_game.id) {
+ case GID_PUTTRACE:
+ return makeLogicHErace(vm);
- float v4 = 1.0;
+ case GID_FUNSHOP:
+ return makeLogicHEfunshop(vm);
- for (int i = 1; i <= a2; i++)
- v4 *= a1;
+ case GID_FOOTBALL:
+ return makeLogicHEfootball(vm);
- return v4;
-}
+ case GID_SOCCER:
+ case GID_SOCCERMLS:
+ case GID_SOCCER2004:
+ return makeLogicHEsoccer(vm);
-int LogicHEsoccer::op_sub5(int a1, int a2, int a3) {
- byte *v9 = _array1013 + 44 * a2;
+ case GID_BASEBALL2001:
+ return makeLogicHEbaseball2001(vm);
- *((uint32 *)v9 + 4) = a3;
- *((uint32 *)v9) = a2;
+ case GID_BASKETBALL:
+ return makeLogicHEbasketball(vm);
- 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 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) {
- // 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 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;
-}
-
-/***********************
- * Backyard Baseball 2001
- *
- */
-
-int LogicHEbaseball2001::versionID() {
- return 1;
-}
-
-int32 LogicHEbaseball2001::dispatch(int op, int numArgs, int32 *args) {
- int res = 0;
-
- switch (op) {
- case 3001:
- // Check network status
- break;
-
- default:
- LogicHE::dispatch(op, numArgs, args);
- }
-
- return res;
-}
-
-/***********************
- * Backyard Basketball
- *
- */
-
-int LogicHEbasketball::versionID() {
- return 1;
-}
-
-int32 LogicHEbasketball::dispatch(int op, int numArgs, int32 *args) {
- int res = 0;
-
- switch (op) {
- case 1001:
- break;
-
- case 1006:
- break;
-
- case 1011:
- break;
-
- case 1012:
- break;
-
- case 1035:
- break;
-
- case 1050:
- break;
-
- case 1051:
- break;
-
- case 1052:
- break;
-
- case 1056:
- break;
-
- case 1057:
- break;
-
- case 1058:
- break;
-
- case 1060:
- break;
-
- case 1064:
- break;
-
- case 1067:
- break;
-
- case 1073:
- break;
-
- case 1075:
- break;
-
- case 1076:
- break;
-
- case 1080:
- break;
-
- case 1081:
- break;
-
- case 1090:
- break;
-
- case 1091:
- break;
-
- case 1513:
- break;
+ case GID_MOONBASE:
+ return makeLogicHEmoonbase(vm);
default:
- LogicHE::dispatch(op, numArgs, args);
+ return new LogicHE(vm);
}
-
- return res;
-}
-
-/***********************
- * Moonbase Commander
- *
- */
-
-int LogicHEmoonbase::versionID() {
- if (_vm->_game.features & GF_DEMO)
- return -100;
- else
- return 100;
}
} // End of namespace Scumm
diff --git a/engines/scumm/he/logic_he.h b/engines/scumm/he/logic_he.h
index e05a05f310..893dc81b87 100644
--- a/engines/scumm/he/logic_he.h
+++ b/engines/scumm/he/logic_he.h
@@ -29,15 +29,10 @@ class ScummEngine_v90he;
class LogicHE {
public:
- ScummEngine_v90he *_vm;
+ static LogicHE *makeLogicHE(ScummEngine_v90he *vm);
- LogicHE(ScummEngine_v90he *vm);
virtual ~LogicHE();
- void writeScummVar(int var, int32 value);
- int getFromArray(int arg0, int idx2, int idx1);
- void putInArray(int arg0, int idx2, int idx1, int val);
-
virtual void beforeBootScript() {}
virtual void initOnce() {}
virtual int startOfFrame() { return 1; }
@@ -46,142 +41,30 @@ public:
virtual int versionID();
virtual int32 dispatch(int op, int numArgs, int32 *args);
-};
-class LogicHErace : public LogicHE {
-private:
- float *_userData;
- double *_userDataD;
-public:
- LogicHErace(ScummEngine_v90he *vm);
- ~LogicHErace();
-
- int versionID();
- int32 dispatch(int op, int numArgs, int32 *args);
-
-private:
- int32 op_1003(int32 *args);
- int32 op_1004(int32 *args);
- int32 op_1100(int32 *args);
- int32 op_1101(int32 *args);
- int32 op_1102(int32 *args);
- int32 op_1103(int32 *args);
- int32 op_1110();
- int32 op_1120(int32 *args);
- int32 op_1130(int32 *args);
- int32 op_1140(int32 *args);
-
- void op_sub1(float arg);
- void op_sub2(float arg);
- void op_sub3(float arg);
-};
-
-class LogicHEfunshop : public LogicHE {
-public:
- LogicHEfunshop(ScummEngine_v90he *vm) : LogicHE(vm) {}
-
- int versionID();
- int32 dispatch(int op, int numArgs, int32 *args);
-
-private:
- void op_1004(int32 *args);
- void op_1005(int32 *args);
- int checkShape(int32 data0, int32 data1, int32 data4, int32 data5, int32 data2, int32 data3, int32 data6, int32 data7, int32 *x, int32 *y);
-};
-
-class LogicHEfootball : public LogicHE {
-public:
- LogicHEfootball(ScummEngine_v90he *vm) : LogicHE(vm) {}
-
- int versionID();
- int32 dispatch(int op, int numArgs, int32 *args);
-
-private:
- int op_1004(int32 *args);
- int op_1006(int32 *args);
- int op_1007(int32 *args);
- int op_1010(int32 *args);
- int op_1022(int32 *args);
- int op_1023(int32 *args);
- int op_1024(int32 *args);
-};
-
-class LogicHEsoccer : public LogicHE {
-private:
- double *_userDataD;
-
-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 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_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_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 {
-public:
- LogicHEbaseball2001(ScummEngine_v90he *vm) : LogicHE(vm) {}
+protected:
+ // Only to be used from makeLogicHE()
+ LogicHE(ScummEngine_v90he *vm);
- int versionID();
- int32 dispatch(int op, int numArgs, int32 *args);
-};
+ ScummEngine_v90he *_vm;
-class LogicHEbasketball : public LogicHE {
-public:
- LogicHEbasketball(ScummEngine_v90he *vm) : LogicHE(vm) {}
+ void writeScummVar(int var, int32 value);
+ int getFromArray(int arg0, int idx2, int idx1);
+ void putInArray(int arg0, int idx2, int idx1, int val);
+ int32 scummRound(double arg) { return (int32)(arg + 0.5); }
- int versionID();
- int32 dispatch(int op, int numArgs, int32 *args);
+ #define RAD2DEG (180 / M_PI)
+ #define DEG2RAD (M_PI / 180)
};
-class LogicHEmoonbase : public LogicHE {
-public:
- LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {}
-
- int versionID();
-};
+// Logic declarations
+LogicHE *makeLogicHErace(ScummEngine_v90he *vm);
+LogicHE *makeLogicHEfunshop(ScummEngine_v90he *vm);
+LogicHE *makeLogicHEfootball(ScummEngine_v90he *vm);
+LogicHE *makeLogicHEsoccer(ScummEngine_v90he *vm);
+LogicHE *makeLogicHEbaseball2001(ScummEngine_v90he *vm);
+LogicHE *makeLogicHEbasketball(ScummEngine_v90he *vm);
+LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm);
} // End of namespace Scumm
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index 5a9172ff8a..56ea10f507 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -542,7 +542,7 @@ void ScummEngine_v100he::o100_arrayOps() {
int dim1end, dim1start, dim2end, dim2start;
int id, len, b, c, list[128];
int offs, tmp, tmp2;
- uint tmp3;
+ uint tmp3, type;
byte subOp = fetchScriptByte();
int array = fetchScriptWord();
@@ -625,11 +625,10 @@ void ScummEngine_v100he::o100_arrayOps() {
}
break;
case 132:
- debug(0, "o100_arrayOps: case 132");
- // TODO: Used by Moonbase Commander
+ // TODO: Used by room 2 script 2180 in Moonbase Commander
fetchScriptWord();
fetchScriptWord();
- pop();
+ type = pop();
pop();
pop();
pop();
@@ -646,6 +645,21 @@ void ScummEngine_v100he::o100_arrayOps() {
if (id == 0) {
defineArray(array, kDwordArray, dim2start, dim2end, dim1start, dim1end);
}
+ switch (type) {
+ case 1:
+ break;
+ case 2:
+ break;
+ case 3:
+ break;
+ case 4:
+ break;
+ case 5:
+ break;
+ default:
+ error("o100_arrayOps: case 132 unknown type %d)", type);
+ }
+ debug(0, "o100_arrayOps: case 132 type %d", type);
break;
case 133:
b = pop();
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index 5af4035930..b9f454de0f 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -1827,10 +1827,19 @@ void ScummEngine_v72he::o72_readINI() {
switch (subOp) {
case 43: // HE 100
case 6: // number
- if (!strcmp((char *)option, "NoPrinting")) {
+ if (!strcmp((char *)option, "DisablePrinting") || !strcmp((char *)option, "NoPrinting")) {
push(1);
} else if (!strcmp((char *)option, "TextOn")) {
push(ConfMan.getBool("subtitles"));
+ } else if (!strcmp((char *)option, "Disk") && (_game.id == GID_BIRTHDAYRED || _game.id == GID_BIRTHDAYYELLOW)) {
+ // WORKAROUND: Override the disk detection
+ // This removes the reliance on having the binary file around (which is
+ // very bad for the Mac version) just for the scripts to figure out if
+ // we're running Yellow or Red
+ if (_game.id == GID_BIRTHDAYRED)
+ push(4);
+ else
+ push(2);
} else {
push(ConfMan.getInt((char *)option));
}
diff --git a/engines/scumm/he/script_v80he.cpp b/engines/scumm/he/script_v80he.cpp
index 7970d7806f..9711f6415b 100644
--- a/engines/scumm/he/script_v80he.cpp
+++ b/engines/scumm/he/script_v80he.cpp
@@ -171,7 +171,10 @@ void ScummEngine_v80he::o80_readConfigFile() {
case 6: // number
ConfFile.getKey((const char *)option, (const char *)section, entry);
- push(atoi(entry.c_str()));
+ if (!strcmp((char *)option, "Benchmark"))
+ push(2);
+ else
+ push(atoi(entry.c_str()));
break;
case 77: // HE 100
case 7: // string
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
index 0b37673e4a..081110c7cd 100644
--- a/engines/scumm/he/sprite_he.cpp
+++ b/engines/scumm/he/sprite_he.cpp
@@ -804,12 +804,18 @@ void Sprite::setSpriteImage(int spriteId, int imageNum) {
if (_spriteTable[spriteId].image) {
_spriteTable[spriteId].imageStateCount = _vm->_wiz->getWizImageStates(_spriteTable[spriteId].image);
- _spriteTable[spriteId].flags |= kSFActive | kSFAutoAnim | kSFMarkDirty | kSFBlitDirectly;
+
+ if (_vm->VAR(139))
+ _spriteTable[spriteId].flags |= kSFActive;
+ else
+ _spriteTable[spriteId].flags |= kSFActive | kSFAutoAnim | kSFMarkDirty | kSFBlitDirectly;
if (_spriteTable[spriteId].image != origResId || _spriteTable[spriteId].imageStateCount != origResWizStates)
_spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
} else {
- if (_spriteTable[spriteId].flags & kSFImageless)
+ if (_vm->VAR(139))
+ _spriteTable[spriteId].flags &= ~kSFActive;
+ else if (_spriteTable[spriteId].flags & kSFImageless)
_spriteTable[spriteId].flags = 0;
else
_spriteTable[spriteId].flags = kSFChanged | kSFBlitDirectly;
diff --git a/engines/scumm/he/sprite_he.h b/engines/scumm/he/sprite_he.h
index d28c9f1944..be6717faa5 100644
--- a/engines/scumm/he/sprite_he.h
+++ b/engines/scumm/he/sprite_he.h
@@ -218,4 +218,3 @@ private:
} // End of namespace Scumm
#endif
-
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index 4107034fe6..f67922c81c 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -1755,7 +1755,7 @@ void Wiz::captureWizPolygon(int resNum, int maskNum, int maskState, int id1, int
uint8 *tmpPtr = imageBuffer;
for (i = 0; i < dsth; i++) {
for (j = 0; j < dstw; j++)
- WRITE_UINT16(tmpPtr + j * 2, transColor);
+ WRITE_LE_UINT16(tmpPtr + j * 2, transColor);
tmpPtr += dstpitch;
}
} else {
diff --git a/engines/scumm/help.cpp b/engines/scumm/help.cpp
index ae7a1ad3bc..cfb23a392a 100644
--- a/engines/scumm/help.cpp
+++ b/engines/scumm/help.cpp
@@ -175,6 +175,7 @@ void ScummHelp::updateStrings(byte gameId, byte version, Common::Platform platfo
ADD_BIND("b", _("To Henry / To Indy"));
break;
case GID_LOOM:
+ // I18N: These are different musical notes
ADD_BIND("q, c", _("play C minor on distaff"));
ADD_BIND("w, d", _("play D on distaff"));
ADD_BIND("e, e", _("play E on distaff"));
@@ -238,6 +239,7 @@ void ScummHelp::updateStrings(byte gameId, byte version, Common::Platform platfo
ADD_BIND("e", _("Examine"));
ADD_BIND("t", _("Regular cursor"));
ADD_BIND("i", _("Inventory"));
+ // I18N: Comm is a communication device
ADD_BIND("c", _("Comm"));
break;
case GID_CMI:
diff --git a/engines/scumm/help.h b/engines/scumm/help.h
index 9763da8c00..5ba6bdc65c 100644
--- a/engines/scumm/help.h
+++ b/engines/scumm/help.h
@@ -42,4 +42,3 @@ public:
} // End of namespace Scumm
#endif
-
diff --git a/engines/scumm/imuse/pcspk.cpp b/engines/scumm/imuse/pcspk.cpp
index 01e2ab3b7d..cbf3446f10 100644
--- a/engines/scumm/imuse/pcspk.cpp
+++ b/engines/scumm/imuse/pcspk.cpp
@@ -380,7 +380,7 @@ int16 PcSpkDriver::getEffectModLevel(int16 level, int8 mod) {
}
}
-int16 PcSpkDriver::getRandMultipy(int16 input) {
+int16 PcSpkDriver::getRandScale(int16 input) {
if (_randBase & 1)
_randBase = (_randBase >> 1) ^ 0xB8;
else
@@ -470,7 +470,7 @@ void PcSpkDriver::initNextEnvelopeState(EffectEnvelope &env) {
uint16 stepCount = _effectEnvStepTable[getEffectModifier(((env.stateTargetLevels[lastState] & 0x7F) << 5) + env.modWheelSensitivity)];
if (env.stateTargetLevels[lastState] & 0x80)
- stepCount = getRandMultipy(stepCount);
+ stepCount = getRandScale(stepCount);
if (!stepCount)
stepCount = 1;
@@ -480,7 +480,7 @@ void PcSpkDriver::initNextEnvelopeState(EffectEnvelope &env) {
if (lastState != 2) {
totalChange = getEffectModLevel(env.maxLevel, (env.stateModWheelLevels[lastState] & 0x7F) - 31);
if (env.stateModWheelLevels[lastState] & 0x80)
- totalChange = getRandMultipy(totalChange);
+ totalChange = getRandScale(totalChange);
if (totalChange + env.startLevel > env.maxLevel)
totalChange = env.maxLevel - env.startLevel;
@@ -832,4 +832,3 @@ const uint16 PcSpkDriver::_frequencyTable[] = {
};
} // End of namespace Scumm
-
diff --git a/engines/scumm/imuse/pcspk.h b/engines/scumm/imuse/pcspk.h
index e77ac8c1bf..195bd34b07 100644
--- a/engines/scumm/imuse/pcspk.h
+++ b/engines/scumm/imuse/pcspk.h
@@ -57,7 +57,7 @@ private:
static uint8 getEffectModifier(uint16 level);
int16 getEffectModLevel(int16 level, int8 mod);
- int16 getRandMultipy(int16 input);
+ int16 getRandScale(int16 input);
struct EffectEnvelope {
uint8 state;
@@ -158,4 +158,3 @@ private:
} // End of namespace Scumm
#endif
-
diff --git a/engines/scumm/imuse/sysex.h b/engines/scumm/imuse/sysex.h
index 7dd38e785e..06ac483afd 100644
--- a/engines/scumm/imuse/sysex.h
+++ b/engines/scumm/imuse/sysex.h
@@ -35,4 +35,3 @@ extern void sysexHandler_SamNMax(Player *, const byte *, uint16);
} // End of namespace Scumm
#endif
-
diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index 23f57a01b9..eb3717494f 100644
--- a/engines/scumm/imuse_digi/dimuse.cpp
+++ b/engines/scumm/imuse_digi/dimuse.cpp
@@ -58,7 +58,7 @@ IMuseDigital::IMuseDigital(ScummEngine_v7 *scumm, Audio::Mixer *mixer, int fps)
memset(_track[l], 0, sizeof(Track));
_track[l]->trackId = l;
}
- _vm->getTimerManager()->installTimerProc(timer_handler, 1000000 / _callbackFps, this);
+ _vm->getTimerManager()->installTimerProc(timer_handler, 1000000 / _callbackFps, this, "IMuseDigital");
_audioNames = NULL;
_numAudioNames = 0;
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 5eea7acc6b..6d9e1f3f72 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -324,7 +324,17 @@ void ScummEngine::processInput() {
VAR(VAR_LEFTBTN_HOLD) = (_leftBtnPressed & msDown) != 0;
VAR(VAR_RIGHTBTN_HOLD) = (_rightBtnPressed & msDown) != 0;
- if (_game.version >= 7) {
+ if (_game.heversion >= 72) {
+ // HE72 introduced a flag for whether or not this is a click
+ // or the player is continuing to hold the button down.
+ // 0x80 signifies that the button is continuing to be held down
+ // Backyard Soccer needs this in order to function
+ if (VAR(VAR_LEFTBTN_HOLD) && !(_leftBtnPressed & msClicked))
+ VAR(VAR_LEFTBTN_HOLD) |= 0x80;
+
+ if (VAR(VAR_RIGHTBTN_HOLD) && !(_rightBtnPressed & msClicked))
+ VAR(VAR_RIGHTBTN_HOLD) |= 0x80;
+ } else if (_game.version >= 7) {
VAR(VAR_LEFTBTN_DOWN) = (_leftBtnPressed & msClicked) != 0;
VAR(VAR_RIGHTBTN_DOWN) = (_rightBtnPressed & msClicked) != 0;
}
diff --git a/engines/scumm/insane/insane_enemy.cpp b/engines/scumm/insane/insane_enemy.cpp
index 68766ab72c..913f761f31 100644
--- a/engines/scumm/insane/insane_enemy.cpp
+++ b/engines/scumm/insane/insane_enemy.cpp
@@ -2779,4 +2779,3 @@ int32 Insane::actionEnemy() {
}
}
-
diff --git a/engines/scumm/insane/insane_iact.cpp b/engines/scumm/insane/insane_iact.cpp
index 3592d67c18..48c96b537c 100644
--- a/engines/scumm/insane/insane_iact.cpp
+++ b/engines/scumm/insane/insane_iact.cpp
@@ -520,4 +520,3 @@ void Insane::iactScene21(byte *renderBitmap, int32 codecparam, int32 setupsan12,
}
}
-
diff --git a/engines/scumm/insane/insane_scenes.cpp b/engines/scumm/insane/insane_scenes.cpp
index 841fedafe2..6db1cb5059 100644
--- a/engines/scumm/insane/insane_scenes.cpp
+++ b/engines/scumm/insane/insane_scenes.cpp
@@ -1506,4 +1506,3 @@ void Insane::postCaseMore(byte *renderBitmap, int32 codecparam, int32 setupsan12
}
}
-
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 99ffdf7f21..781ca30459 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -124,7 +124,14 @@ MODULE_OBJS += \
he/script_v90he.o \
he/script_v100he.o \
he/sprite_he.o \
- he/wiz_he.o
+ he/wiz_he.o \
+ he/logic/baseball2001.o \
+ he/logic/basketball.o \
+ he/logic/football.o \
+ he/logic/funshop.o \
+ he/logic/moonbase.o \
+ he/logic/puttrace.o \
+ he/logic/soccer.o
endif
# This module can be built as a plugin
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 51ba2195d7..30096000ce 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -544,6 +544,12 @@ void ScummEngine::palManipulateInit(int resID, int start, int end, int time) {
return;
#endif
+ // This function is actually a nullsub in Indy4 Amiga.
+ // It might very well be a nullsub in other Amiga games, but for now I
+ // limit this to Indy4 Amiga, since that is the only game I can check.
+ if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4)
+ return;
+
byte *string1 = getStringAddress(resID);
byte *string2 = getStringAddress(resID + 1);
byte *string3 = getStringAddress(resID + 2);
@@ -670,6 +676,12 @@ static inline uint colorWeight(int red, int green, int blue) {
}
void ScummEngine::setShadowPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor, int start, int end) {
+ // This function is actually a nullsub in Indy4 Amiga.
+ // It might very well be a nullsub in other Amiga games, but for now I
+ // limit this to Indy4 Amiga, since that is the only game I can check.
+ if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4)
+ return;
+
const byte *basepal = getPalettePtr(_curPalIndex, _roomResource);
const byte *compareptr;
const byte *pal = basepal + start * 3;
diff --git a/engines/scumm/player_v2.h b/engines/scumm/player_v2.h
index 14a0b9c1e0..d932585b8e 100644
--- a/engines/scumm/player_v2.h
+++ b/engines/scumm/player_v2.h
@@ -46,10 +46,7 @@ public:
virtual int getSoundStatus(int sound) const;
// AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return true; }
- bool endOfData() const { return false; }
- int getRate() const { return _sampleRate; }
+ virtual int readBuffer(int16 *buffer, const int numSamples);
protected:
unsigned int _update_step;
diff --git a/engines/scumm/player_v2base.h b/engines/scumm/player_v2base.h
index 2f048070ad..eb9ed941ca 100644
--- a/engines/scumm/player_v2base.h
+++ b/engines/scumm/player_v2base.h
@@ -86,9 +86,9 @@ public:
return numSamples;
}
*/
- bool isStereo() const { return true; }
- bool endOfData() const { return false; }
- int getRate() const { return _sampleRate; }
+ virtual bool isStereo() const { return true; }
+ virtual bool endOfData() const { return false; }
+ virtual int getRate() const { return _sampleRate; }
protected:
enum {
diff --git a/engines/scumm/player_v2cms.cpp b/engines/scumm/player_v2cms.cpp
index 21e7f193b5..d4b21774ed 100644
--- a/engines/scumm/player_v2cms.cpp
+++ b/engines/scumm/player_v2cms.cpp
@@ -28,162 +28,49 @@
namespace Scumm {
-#define PROCESS_ATTACK 1
-#define PROCESS_RELEASE 2
-#define PROCESS_SUSTAIN 3
-#define PROCESS_DECAY 4
-#define PROCESS_VIBRATO 5
-
-#define CMS_RATE 22050
-
-static const byte freqTable[] = {
- 3, 10, 17, 24, 31, 38, 45, 51,
- 58, 65, 71, 77, 83, 90, 96, 102,
- 107, 113, 119, 125, 130, 136, 141, 146,
- 151, 157, 162, 167, 172, 177, 181, 186,
- 191, 195, 200, 204, 209, 213, 217, 221,
- 226, 230, 234, 238, 242, 246, 249, 253
-};
-
-/*static const byte amplTable[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 %
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 10 %
- 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, // 20 %
- 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x20, // 30%
- 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x40, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x20, 0x20, // 40 %
- 0x30, 0x30, 0x40, 0x40, 0x40, 0x50, 0x50, 0x60,
- 0x00, 0x00, 0x10, 0x10, 0x20, 0x20, 0x30, 0x30, // 50%
- 0x40, 0x40, 0x50, 0x50, 0x60, 0x60, 0x70, 0x70,
- 0x00, 0x00, 0x10, 0x10, 0x20, 0x30, 0x30, 0x40, // 60 %
- 0x40, 0x50, 0x60, 0x60, 0x70, 0x70, 0x80, 0x90,
- 0x00, 0x00, 0x10, 0x20, 0x20, 0x30, 0x40, 0x40, // 70 %
- 0x50, 0x60, 0x70, 0x70, 0x80, 0x90, 0x90, 0xA0,
- 0x00, 0x00, 0x10, 0x20, 0x30, 0x40, 0x40, 0x50, // 80 %
- 0x60, 0x70, 0x80, 0x80, 0x90, 0xA0, 0xB0, 0xC0,
- 0x00, 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, // 90 %
- 0x70, 0x80, 0x90, 0x90, 0xA0, 0xB0, 0xC0, 0xD0,
- 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // 100 %
- 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0
-};*/
-
-static const byte octaveTable[] = {
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03,
- 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07,
- 0x00, 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B,
- 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03,
- 0x01, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x07,
- 0x01, 0x08, 0x01, 0x09, 0x01, 0x0A, 0x01, 0x0B,
- 0x02, 0x00, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
- 0x02, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02, 0x07,
- 0x02, 0x08, 0x02, 0x09, 0x02, 0x0A, 0x02, 0x0B,
- 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03,
- 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07,
- 0x03, 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B,
- 0x04, 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03,
- 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07,
- 0x04, 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B,
- 0x05, 0x00, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03,
- 0x05, 0x04, 0x05, 0x05, 0x05, 0x06, 0x05, 0x07,
- 0x05, 0x08, 0x05, 0x09, 0x05, 0x0A, 0x05, 0x0B,
- 0x06, 0x00, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03,
- 0x06, 0x04, 0x06, 0x05, 0x06, 0x06, 0x06, 0x07,
- 0x06, 0x08, 0x06, 0x09, 0x06, 0x0A, 0x06, 0x0B,
- 0x07, 0x00, 0x07, 0x01, 0x07, 0x02, 0x07, 0x03,
- 0x07, 0x04, 0x07, 0x05, 0x07, 0x06, 0x07, 0x07,
- 0x07, 0x08, 0x07, 0x09, 0x07, 0x0A, 0x07, 0x0B,
- 0x08, 0x00, 0x08, 0x01, 0x08, 0x02, 0x08, 0x03,
- 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x08, 0x07,
- 0x08, 0x08, 0x08, 0x09, 0x08, 0x0A, 0x08, 0x0B,
- 0x09, 0x00, 0x09, 0x01, 0x09, 0x02, 0x09, 0x03,
- 0x09, 0x04, 0x09, 0x05, 0x09, 0x06, 0x09, 0x07,
- 0x09, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x09, 0x0B,
- 0x0A, 0x00, 0x0A, 0x01, 0x0A, 0x02, 0x0A, 0x03,
- 0x0A, 0x04, 0x0A, 0x05, 0x0A, 0x06, 0x0A, 0x07,
- 0x0A, 0x08, 0x0A, 0x09, 0x0A, 0x0A, 0x0A, 0x0B
-};
-
-static const byte attackRate[] = {
- 0, 2, 4, 7, 14, 26, 48, 82,
- 128, 144, 160, 176, 192, 208, 224, 255
-};
-
-static const byte decayRate[] = {
- 0, 1, 2, 3, 4, 6, 12, 24,
- 48, 96, 192, 215, 255, 255, 255, 255
-};
-
-static const byte sustainRate[] = {
- 255, 180, 128, 96, 80, 64, 56, 48,
- 42, 36, 32, 28, 24, 20, 16, 0
-};
-
-static const byte releaseRate[] = {
- 0, 1, 2, 4, 6, 9, 14, 22,
- 36, 56, 80, 100, 120, 140, 160, 255
-};
-
-static const byte volumeTable[] = {
- 0x00, 0x10, 0x10, 0x11, 0x11, 0x21, 0x22, 0x22,
- 0x33, 0x44, 0x55, 0x66, 0x88, 0xAA, 0xCC, 0xFF
-};
-
Player_V2CMS::Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer)
- : Player_V2Base(scumm, mixer, true) {
- int i;
-
+ : Player_V2Base(scumm, mixer, true), _cmsVoicesBase(), _cmsVoices(),
+ _cmsChips(), _midiDelay(0), _octaveMask(0), _looping(0), _tempo(0),
+ _tempoSum(0), _midiData(0), _midiSongBegin(0), _musicTimer(0),
+ _musicTimerTicks(0), _voiceTimer(0), _loadedMidiSong(0),
+ _outputTableReady(0), _midiChannel(), _midiChannelUse() {
setMusicVolume(255);
- memset(_cmsVoicesBase, 0, sizeof(Voice)*16);
- memset(_cmsVoices, 0, sizeof(Voice2)*8);
- memset(_cmsChips, 0, sizeof(MusicChip)*2);
- _midiDelay = _octaveMask = _looping = _tempo = 0;
- _midiData = _midiSongBegin = 0;
- _loadedMidiSong = 0;
- memset(_midiChannel, 0, sizeof(Voice2*)*16);
- memset(_midiChannelUse, 0, sizeof(byte)*16);
-
- _cmsVoices[0].amplitudeOutput = &(_cmsChips[0].ampl[0]);
- _cmsVoices[0].freqOutput = &(_cmsChips[0].freq[0]);
- _cmsVoices[0].octaveOutput = &(_cmsChips[0].octave[0]);
- _cmsVoices[1].amplitudeOutput = &(_cmsChips[0].ampl[1]);
- _cmsVoices[1].freqOutput = &(_cmsChips[0].freq[1]);
- _cmsVoices[1].octaveOutput = &(_cmsChips[0].octave[0]);
- _cmsVoices[2].amplitudeOutput = &(_cmsChips[0].ampl[2]);
- _cmsVoices[2].freqOutput = &(_cmsChips[0].freq[2]);
- _cmsVoices[2].octaveOutput = &(_cmsChips[0].octave[1]);
- _cmsVoices[3].amplitudeOutput = &(_cmsChips[0].ampl[3]);
- _cmsVoices[3].freqOutput = &(_cmsChips[0].freq[3]);
- _cmsVoices[3].octaveOutput = &(_cmsChips[0].octave[1]);
- _cmsVoices[4].amplitudeOutput = &(_cmsChips[1].ampl[0]);
- _cmsVoices[4].freqOutput = &(_cmsChips[1].freq[0]);
- _cmsVoices[4].octaveOutput = &(_cmsChips[1].octave[0]);
- _cmsVoices[5].amplitudeOutput = &(_cmsChips[1].ampl[1]);
- _cmsVoices[5].freqOutput = &(_cmsChips[1].freq[1]);
- _cmsVoices[5].octaveOutput = &(_cmsChips[1].octave[0]);
- _cmsVoices[6].amplitudeOutput = &(_cmsChips[1].ampl[2]);
- _cmsVoices[6].freqOutput = &(_cmsChips[1].freq[2]);
- _cmsVoices[6].octaveOutput = &(_cmsChips[1].octave[1]);
- _cmsVoices[7].amplitudeOutput = &(_cmsChips[1].ampl[3]);
- _cmsVoices[7].freqOutput = &(_cmsChips[1].freq[3]);
- _cmsVoices[7].octaveOutput = &(_cmsChips[1].octave[1]);
+ memset(_sfxFreq, 0xFF, sizeof(_sfxFreq));
+ memset(_sfxAmpl, 0x00, sizeof(_sfxAmpl));
+ memset(_sfxOctave, 0x66, sizeof(_sfxOctave));
+
+ _cmsVoices[0].amplitudeOutput = &_cmsChips[0].ampl[0];
+ _cmsVoices[0].freqOutput = &_cmsChips[0].freq[0];
+ _cmsVoices[0].octaveOutput = &_cmsChips[0].octave[0];
+ _cmsVoices[1].amplitudeOutput = &_cmsChips[0].ampl[1];
+ _cmsVoices[1].freqOutput = &_cmsChips[0].freq[1];
+ _cmsVoices[1].octaveOutput = &_cmsChips[0].octave[0];
+ _cmsVoices[2].amplitudeOutput = &_cmsChips[0].ampl[2];
+ _cmsVoices[2].freqOutput = &_cmsChips[0].freq[2];
+ _cmsVoices[2].octaveOutput = &_cmsChips[0].octave[1];
+ _cmsVoices[3].amplitudeOutput = &_cmsChips[0].ampl[3];
+ _cmsVoices[3].freqOutput = &_cmsChips[0].freq[3];
+ _cmsVoices[3].octaveOutput = &_cmsChips[0].octave[1];
+ _cmsVoices[4].amplitudeOutput = &_cmsChips[1].ampl[0];
+ _cmsVoices[4].freqOutput = &_cmsChips[1].freq[0];
+ _cmsVoices[4].octaveOutput = &_cmsChips[1].octave[0];
+ _cmsVoices[5].amplitudeOutput = &_cmsChips[1].ampl[1];
+ _cmsVoices[5].freqOutput = &_cmsChips[1].freq[1];
+ _cmsVoices[5].octaveOutput = &_cmsChips[1].octave[0];
+ _cmsVoices[6].amplitudeOutput = &_cmsChips[1].ampl[2];
+ _cmsVoices[6].freqOutput = &_cmsChips[1].freq[2];
+ _cmsVoices[6].octaveOutput = &_cmsChips[1].octave[1];
+ _cmsVoices[7].amplitudeOutput = &_cmsChips[1].ampl[3];
+ _cmsVoices[7].freqOutput = &_cmsChips[1].freq[3];
+ _cmsVoices[7].octaveOutput = &_cmsChips[1].octave[1];
// inits the CMS Emulator like in the original
_cmsEmu = new CMSEmulator(_sampleRate);
- static const byte cmsInitData[13*2] = {
- 0x1C, 0x02,
- 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
- 0x14, 0x3F, 0x15, 0x00, 0x16, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1C, 0x01
- };
-
- i = 0;
- for (int cmsPort = 0x220; i < 2; cmsPort += 2, ++i) {
+ for (int i = 0, cmsPort = 0x220; i < 2; cmsPort += 2, ++i) {
for (int off = 0; off < 13; ++off) {
- _cmsEmu->portWrite(cmsPort+1, cmsInitData[off*2]);
- _cmsEmu->portWrite(cmsPort, cmsInitData[off*2+1]);
+ _cmsEmu->portWrite(cmsPort+1, _cmsInitData[off*2]);
+ _cmsEmu->portWrite(cmsPort, _cmsInitData[off*2+1]);
}
}
@@ -200,6 +87,10 @@ Player_V2CMS::~Player_V2CMS() {
void Player_V2CMS::setMusicVolume(int vol) {
}
+int Player_V2CMS::getMusicTimer() {
+ return _midiData ? _musicTimer : Player_V2Base::getMusicTimer();
+}
+
void Player_V2CMS::stopAllSounds() {
Common::StackLock lock(_mutex);
@@ -211,6 +102,7 @@ void Player_V2CMS::stopAllSounds() {
_midiData = 0;
_midiSongBegin = 0;
_midiDelay = 0;
+ _musicTimer = _musicTimerTicks = 0;
offAllChannels();
}
@@ -244,6 +136,7 @@ void Player_V2CMS::startSound(int nr) {
assert(data);
if (data[6] == 0x80) {
+ _musicTimer = _musicTimerTicks = 0;
loadMidiData(data, nr);
} else {
int cprio = _current_data ? *(_current_data + _header_len) : 0;
@@ -282,7 +175,8 @@ void Player_V2CMS::startSound(int nr) {
}
void Player_V2CMS::loadMidiData(byte *data, int sound) {
- memset(_midiChannelUse, 0, sizeof(byte)*16);
+ memset(_midiChannelUse, 0, sizeof(_midiChannelUse));
+ memset(_midiChannel, 0, sizeof(_midiChannel));
_tempo = data[7];
_looping = data[8];
@@ -299,11 +193,11 @@ void Player_V2CMS::loadMidiData(byte *data, int sound) {
Voice *voiceDef = &_cmsVoicesBase[channel];
byte attackDecay = voice2[10];
- voiceDef->attack = attackRate[attackDecay >> 4];
- voiceDef->decay = decayRate[attackDecay & 0x0F];
+ voiceDef->attack = _attackRate[attackDecay >> 4];
+ voiceDef->decay = _decayRate[attackDecay & 0x0F];
byte sustainRelease = voice2[11];
- voiceDef->sustain = sustainRate[sustainRelease >> 4];
- voiceDef->release = releaseRate[sustainRelease & 0x0F];
+ voiceDef->sustain = _sustainRate[sustainRelease >> 4];
+ voiceDef->release = _releaseRate[sustainRelease & 0x0F];
if (voice2[3] & 0x40) {
voiceDef->vibrato = 0x0301;
@@ -331,12 +225,10 @@ void Player_V2CMS::loadMidiData(byte *data, int sound) {
}
}
- for (int i = 0, channel = 0; i < 8; ++i, channel += 2) {
+ for (int i = 0; i < 8; ++i) {
_cmsVoices[i].chanNumber = 0xFF;
_cmsVoices[i].curVolume = 0;
_cmsVoices[i].nextVoice = 0;
-
- _midiChannel[channel] = 0;
}
_midiDelay = 0;
@@ -351,11 +243,17 @@ int Player_V2CMS::getSoundStatus(int nr) const {
return _current_nr == nr || _next_nr == nr || _loadedMidiSong == nr;
}
-void Player_V2CMS::processMidiData(uint ticks) {
+void Player_V2CMS::processMidiData() {
byte *currentData = _midiData;
byte command = 0x00;
int16 temp = 0;
+ ++_musicTimerTicks;
+ if (_musicTimerTicks > 60) {
+ _musicTimerTicks = 0;
+ ++_musicTimer;
+ }
+
if (!_midiDelay) {
while (true) {
if ((command = *currentData++) == 0xFF) {
@@ -365,6 +263,8 @@ void Player_V2CMS::processMidiData(uint ticks) {
continue;
}
_midiData = _midiSongBegin = 0;
+ _midiDelay = 0;
+ _loadedMidiSong = 0;
offAllChannels();
return;
} else {
@@ -400,7 +300,7 @@ void Player_V2CMS::processMidiData(uint ticks) {
_midiDelay = temp;
}
- _midiDelay -= ticks;
+ --_midiDelay;
if (_midiDelay < 0)
_midiDelay = 0;
@@ -415,27 +315,21 @@ int Player_V2CMS::readBuffer(int16 *buffer, const int numSamples) {
// maybe this needs a complete rewrite
do {
- if (_midiData) {
- --_clkFrequenz;
- if (!(_clkFrequenz & 0x01)) {
- playVoice();
- }
-
- _tempoSum += _tempo;
- // FIXME: _tempoSum is declared as char; on some systems char is unsigned.
- // E.g. on OS X. Hence the following check is always false.
- // Moral of the story: Use uint8, int8 or any of the other types provided by
- // ScummVM if you want to ensure signedness and number of available bits.
- if (_tempoSum < 0) {
- // this have to be called in the same rate as in the original (I think)
- processMidiData(1);
+ if (!(_next_tick >> FIXP_SHIFT)) {
+ if (_midiData) {
+ --_voiceTimer;
+ if (!(_voiceTimer & 0x01))
+ playVoice();
+
+ int newTempoSum = _tempo + _tempoSum;
+ _tempoSum = newTempoSum & 0xFF;
+ if (newTempoSum > 0xFF)
+ processMidiData();
+ } else {
+ nextTick();
+ play();
}
- }
-
- if (!(_next_tick >> FIXP_SHIFT) && !_midiData) {
_next_tick += _tick_len;
- nextTick();
- play();
}
step = len;
@@ -456,99 +350,95 @@ void Player_V2CMS::playVoice() {
}
_octaveMask = 0xF0;
- Voice2 *voice =0;
+ Voice2 *voice = 0;
for (int i = 0; i < 8; ++i) {
voice = &_cmsVoices[i];
_octaveMask = ~_octaveMask;
if (voice->chanNumber != 0xFF) {
processChannel(voice);
- continue;
- }
-
- if (!voice->curVolume) {
- *(voice->amplitudeOutput) = 0;
- }
+ } else {
+ if (!voice->curVolume) {
+ *(voice->amplitudeOutput) = 0;
+ }
- int volume = voice->curVolume - voice->releaseRate;
- voice->curVolume = volume;
+ int volume = voice->curVolume - voice->releaseRate;
+ if (volume < 0)
+ volume = 0;
- if (volume < 0) {
- volume = voice->curVolume = 0;
+ voice->curVolume = volume;
+ *(voice->amplitudeOutput) = ((volume >> 4) | (volume & 0xF0)) & voice->channel;
+ ++_outputTableReady;
}
-
- *(voice->amplitudeOutput) = ((volume >> 4) | (volume & 0xF0)) & voice->channel;
- ++_outputTableReady;
}
}
void Player_V2CMS::processChannel(Voice2 *channel) {
++_outputTableReady;
switch (channel->nextProcessState) {
- case PROCESS_RELEASE:
- processRelease(channel);
- break;
-
- case PROCESS_ATTACK:
+ case Voice2::kEnvelopeAttack:
processAttack(channel);
break;
- case PROCESS_DECAY:
+ case Voice2::kEnvelopeDecay:
processDecay(channel);
break;
- case PROCESS_SUSTAIN:
+ case Voice2::kEnvelopeSustain:
processSustain(channel);
break;
- case PROCESS_VIBRATO:
- processVibrato(channel);
- break;
-
- default:
+ case Voice2::kEnvelopeRelease:
+ processRelease(channel);
break;
}
}
void Player_V2CMS::processRelease(Voice2 *channel) {
- channel->curVolume -= channel->releaseRate;
- if (channel->curVolume < 0)
- channel->curVolume = 0;
+ int newVolume = channel->curVolume - channel->releaseRate;
+ if (newVolume < 0)
+ newVolume = 0;
+
+ channel->curVolume = newVolume;
processVibrato(channel);
}
void Player_V2CMS::processAttack(Voice2 *channel) {
- channel->curVolume += channel->attackRate;
- if (channel->curVolume >= 0) {
- if (channel->curVolume <= channel->maxAmpl)
- return processVibrato(channel);
+ int newVolume = channel->curVolume + channel->attackRate;
+ if (newVolume > channel->maxAmpl) {
+ channel->curVolume = channel->maxAmpl;
+ channel->nextProcessState = Voice2::kEnvelopeDecay;
+ } else {
+ channel->curVolume = newVolume;
}
- channel->curVolume = channel->maxAmpl;
- channel->nextProcessState = PROCESS_DECAY;
+
processVibrato(channel);
}
void Player_V2CMS::processDecay(Voice2 *channel) {
- channel->curVolume -= channel->decayRate;
- if (channel->curVolume >= 0) {
- if (channel->curVolume > channel->sustainRate)
- return processVibrato(channel);
+ int newVolume = channel->curVolume - channel->decayRate;
+ if (newVolume <= channel->sustainRate) {
+ channel->curVolume = channel->sustainRate;
+ channel->nextProcessState = Voice2::kEnvelopeSustain;
+ } else {
+ channel->curVolume = newVolume;
}
- channel->curVolume = channel->sustainRate;
- channel->nextProcessState = PROCESS_SUSTAIN;
+
processVibrato(channel);
}
void Player_V2CMS::processSustain(Voice2 *channel) {
if (channel->unkVibratoRate) {
- int volume = (int)channel->curVolume + (int)channel->unkRate;
+ int16 volume = channel->curVolume + channel->unkRate;
if (volume & 0xFF00) {
- volume = ((~volume) >> 8) & 0xFF;
+ volume = int8(volume >> 8);
+ volume = -volume;
}
+
channel->curVolume = volume;
- --(channel->unkCount);
+ --channel->unkCount;
if (!channel->unkCount) {
- channel->unkRate = ~(channel->unkRate);
+ channel->unkRate = -channel->unkRate;
channel->unkCount = (channel->unkVibratoDepth & 0x0F) << 1;
}
}
@@ -557,12 +447,13 @@ void Player_V2CMS::processSustain(Voice2 *channel) {
void Player_V2CMS::processVibrato(Voice2 *channel) {
if (channel->vibratoRate) {
- uint16 temp = channel->curFreq + channel->curVibratoRate;
+ int16 temp = channel->curFreq + channel->curVibratoRate;
channel->curOctave += (temp & 0xFF00) >> 8;
channel->curFreq = temp & 0xFF;
- --(channel->curVibratoUnk);
+
+ --channel->curVibratoUnk;
if (!channel->curVibratoUnk) {
- channel->curVibratoRate = ~(channel->curVibratoRate);
+ channel->curVibratoRate = -channel->curVibratoRate;
channel->curVibratoUnk = (channel->vibratoDepth & 0x0F) << 1;
}
}
@@ -572,25 +463,16 @@ void Player_V2CMS::processVibrato(Voice2 *channel) {
output = channel->freqOutput;
*output = channel->curFreq;
output = channel->octaveOutput;
- *output = ((((channel->curOctave >> 4) | (channel->curOctave & 0x0F)) & _octaveMask) | ((~_octaveMask) & *output));
+ *output = (((channel->curOctave << 4) | (channel->curOctave & 0x0F)) & _octaveMask) | ((~_octaveMask) & *output);
}
void Player_V2CMS::offAllChannels() {
- warning("offAllChannels STUB");
-/*
- // after using this sound can not be played anymore (since it would deinit the emulator)
- static const byte cmsOffData[10*2] = {
- 0x1C, 0x02,
- 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
- 0x14, 0x3F, 0x15, 0x00, 0x16, 0x00
- };
-
for (int cmsPort = 0x220, i = 0; i < 2; cmsPort += 2, ++i) {
- for (int off = 0; off < 10; ++off) {
- _cmsEmu->portWrite(cmsPort+1, cmsOffData[off*2]);
- _cmsEmu->portWrite(cmsPort, cmsOffData[off*2+1]);
+ for (int off = 1; off <= 10; ++off) {
+ _cmsEmu->portWrite(cmsPort+1, _cmsInitData[off*2]);
+ _cmsEmu->portWrite(cmsPort, _cmsInitData[off*2+1]);
}
- }*/
+ }
}
Player_V2CMS::Voice2 *Player_V2CMS::getFreeVoice() {
@@ -637,8 +519,10 @@ void Player_V2CMS::playNote(byte *&data) {
freeVoice->sustainRate = voice->sustain;
freeVoice->releaseRate = voice->release;
freeVoice->octaveAdd = voice->octadd;
- freeVoice->vibratoRate = freeVoice->curVibratoRate = voice->vibrato;
- freeVoice->unkVibratoRate = freeVoice->unkRate = voice->vibrato2;
+ freeVoice->vibratoRate = freeVoice->curVibratoRate = voice->vibrato & 0xFF;
+ freeVoice->vibratoDepth = freeVoice->curVibratoUnk = voice->vibrato >> 8;
+ freeVoice->unkVibratoRate = freeVoice->unkRate = voice->vibrato2 & 0xFF;
+ freeVoice->unkVibratoDepth = freeVoice->unkCount = voice->vibrato2 >> 8;
freeVoice->maxAmpl = 0xFF;
uint8 rate = freeVoice->attackRate;
@@ -650,7 +534,14 @@ void Player_V2CMS::playNote(byte *&data) {
rate -= freeVoice->attackRate;
freeVoice->curVolume = rate;
freeVoice->playingNote = *data;
- int octave = octaveTable[(*data + 3) << 1] + freeVoice->octaveAdd - 3;
+
+ int effectiveNote = freeVoice->playingNote + 3;
+ if (effectiveNote < 0 || effectiveNote >= ARRAYSIZE(_midiNotes)) {
+ warning("Player_V2CMS::playNote: Note %d out of bounds", effectiveNote);
+ effectiveNote = CLIP<int>(effectiveNote, 0, ARRAYSIZE(_midiNotes) - 1);
+ }
+
+ int octave = _midiNotes[effectiveNote].baseOctave + freeVoice->octaveAdd - 3;
if (octave < 0)
octave = 0;
if (octave > 7)
@@ -658,10 +549,10 @@ void Player_V2CMS::playNote(byte *&data) {
if (!octave)
++octave;
freeVoice->curOctave = octave;
- freeVoice->curFreq = freqTable[volume << 2];
+ freeVoice->curFreq = _midiNotes[effectiveNote].frequency;
freeVoice->curVolume = 0;
- freeVoice->nextProcessState = PROCESS_ATTACK;
- if (_lastMidiCommand & 1)
+ freeVoice->nextProcessState = Voice2::kEnvelopeAttack;
+ if (!(_lastMidiCommand & 1))
freeVoice->channel = 0xF0;
else
freeVoice->channel = 0x0F;
@@ -672,35 +563,27 @@ void Player_V2CMS::playNote(byte *&data) {
Player_V2CMS::Voice2 *Player_V2CMS::getPlayVoice(byte param) {
byte channelNum = _lastMidiCommand & 0x0F;
- Voice2 *channel = _midiChannel[channelNum];
+ Voice2 *curVoice = _midiChannel[channelNum];
- if (channel) {
- Voice2 *backUp = 0;
+ if (curVoice) {
+ Voice2 *prevVoice = 0;
while (true) {
- if (channel->playingNote == param)
+ if (curVoice->playingNote == param)
break;
- backUp = channel;
- channel = channel->nextVoice;
- if (!channel)
+ prevVoice = curVoice;
+ curVoice = curVoice->nextVoice;
+ if (!curVoice)
return 0;
}
- Voice2 *backUp2 = channel->nextVoice;
- {
- Voice2 *temp = backUp;
- backUp = channel;
- channel = temp;
- }
- if (channel) {
- channel->nextVoice = backUp2;
- } else {
- _midiChannel[channelNum] = backUp2;
- }
- channel = backUp;
+ if (prevVoice)
+ prevVoice->nextVoice = curVoice->nextVoice;
+ else
+ _midiChannel[channelNum] = curVoice->nextVoice;
}
- return channel;
+ return curVoice;
}
void Player_V2CMS::clearNote(byte *&data) {
@@ -708,22 +591,17 @@ void Player_V2CMS::clearNote(byte *&data) {
if (voice) {
voice->chanNumber = 0xFF;
voice->nextVoice = 0;
- voice->nextProcessState = PROCESS_RELEASE;
+ voice->nextProcessState = Voice2::kEnvelopeRelease;
}
data += 2;
}
void Player_V2CMS::play() {
_octaveMask = 0xF0;
- channel_data *chan = &(_channels[0].d);
+ channel_data *chan = &_channels[0].d;
- static byte volumeReg[4] = { 0x00, 0x00, 0x00, 0x00 };
- static byte octaveReg[4] = { 0x66, 0x66, 0x66, 0x66 };
- static byte freqReg[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
+ byte noiseGen = 3;
- static byte freqEnable = 0x3E;
- static byte noiseEnable = 0x01;
- static byte noiseGen = 0x02;
for (int i = 1; i <= 4; ++i) {
if (chan->time_left) {
uint16 freq = chan->freq;
@@ -733,8 +611,8 @@ void Player_V2CMS::play() {
noiseGen = freq & 0xFF;
} else {
noiseGen = 3;
- freqReg[0] = freqReg[3];
- octaveReg[0] = (octaveReg[0] & 0xF0) | ((octaveReg[1] & 0xF0) >> 4);
+ _sfxFreq[0] = _sfxFreq[3];
+ _sfxOctave[0] = (_sfxOctave[0] & 0xF0) | ((_sfxOctave[1] & 0xF0) >> 4);
}
} else {
if (freq == 0) {
@@ -760,17 +638,18 @@ void Player_V2CMS::play() {
oct |= cmsOct;
oct &= _octaveMask;
- oct |= ((~_octaveMask) & octaveReg[((i & 3) >> 1)]);
- octaveReg[((i & 3) >> 1)] = oct;
+ oct |= (~_octaveMask) & _sfxOctave[(i & 3) >> 1];
+ _sfxOctave[(i & 3) >> 1] = oct;
- freq >>= -(cmsOct-9);
- freqReg[(i&3)] = (-(freq-511)) & 0xFF;
+ freq >>= -(cmsOct - 9);
+ _sfxFreq[i & 3] = (-(freq - 511)) & 0xFF;
}
- volumeReg[i & 3] = volumeTable[chan->volume >> 12];
+ _sfxAmpl[i & 3] = _volumeTable[chan->volume >> 12];
} else {
- volumeReg[i & 3] = 0;
+ _sfxAmpl[i & 3] = 0;
}
- chan = &(_channels[i].d);
+
+ chan = &_channels[i].d;
_octaveMask ^= 0xFF;
}
@@ -778,29 +657,29 @@ void Player_V2CMS::play() {
// the right channels amplitude is set
// with the low value the left channels amplitude
_cmsEmu->portWrite(0x221, 0);
- _cmsEmu->portWrite(0x220, volumeReg[0]);
+ _cmsEmu->portWrite(0x220, _sfxAmpl[0]);
_cmsEmu->portWrite(0x221, 1);
- _cmsEmu->portWrite(0x220, volumeReg[1]);
+ _cmsEmu->portWrite(0x220, _sfxAmpl[1]);
_cmsEmu->portWrite(0x221, 2);
- _cmsEmu->portWrite(0x220, volumeReg[2]);
+ _cmsEmu->portWrite(0x220, _sfxAmpl[2]);
_cmsEmu->portWrite(0x221, 3);
- _cmsEmu->portWrite(0x220, volumeReg[3]);
+ _cmsEmu->portWrite(0x220, _sfxAmpl[3]);
_cmsEmu->portWrite(0x221, 8);
- _cmsEmu->portWrite(0x220, freqReg[0]);
+ _cmsEmu->portWrite(0x220, _sfxFreq[0]);
_cmsEmu->portWrite(0x221, 9);
- _cmsEmu->portWrite(0x220, freqReg[1]);
+ _cmsEmu->portWrite(0x220, _sfxFreq[1]);
_cmsEmu->portWrite(0x221, 10);
- _cmsEmu->portWrite(0x220, freqReg[2]);
+ _cmsEmu->portWrite(0x220, _sfxFreq[2]);
_cmsEmu->portWrite(0x221, 11);
- _cmsEmu->portWrite(0x220, freqReg[3]);
+ _cmsEmu->portWrite(0x220, _sfxFreq[3]);
_cmsEmu->portWrite(0x221, 0x10);
- _cmsEmu->portWrite(0x220, octaveReg[0]);
+ _cmsEmu->portWrite(0x220, _sfxOctave[0]);
_cmsEmu->portWrite(0x221, 0x11);
- _cmsEmu->portWrite(0x220, octaveReg[1]);
+ _cmsEmu->portWrite(0x220, _sfxOctave[1]);
_cmsEmu->portWrite(0x221, 0x14);
- _cmsEmu->portWrite(0x220, freqEnable);
+ _cmsEmu->portWrite(0x220, 0x3E);
_cmsEmu->portWrite(0x221, 0x15);
- _cmsEmu->portWrite(0x220, noiseEnable);
+ _cmsEmu->portWrite(0x220, 0x01);
_cmsEmu->portWrite(0x221, 0x16);
_cmsEmu->portWrite(0x220, noiseGen);
}
@@ -838,4 +717,71 @@ void Player_V2CMS::playMusicChips(const MusicChip *table) {
} while ((cmsPort & 2) == 0);
}
+const Player_V2CMS::MidiNote Player_V2CMS::_midiNotes[132] = {
+ { 3, 0 }, { 31, 0 }, { 58, 0 }, { 83, 0 },
+ { 107, 0 }, { 130, 0 }, { 151, 0 }, { 172, 0 },
+ { 191, 0 }, { 209, 0 }, { 226, 0 }, { 242, 0 },
+ { 3, 1 }, { 31, 1 }, { 58, 1 }, { 83, 1 },
+ { 107, 1 }, { 130, 1 }, { 151, 1 }, { 172, 1 },
+ { 191, 1 }, { 209, 1 }, { 226, 1 }, { 242, 1 },
+ { 3, 2 }, { 31, 2 }, { 58, 2 }, { 83, 2 },
+ { 107, 2 }, { 130, 2 }, { 151, 2 }, { 172, 2 },
+ { 191, 2 }, { 209, 2 }, { 226, 2 }, { 242, 2 },
+ { 3, 3 }, { 31, 3 }, { 58, 3 }, { 83, 3 },
+ { 107, 3 }, { 130, 3 }, { 151, 3 }, { 172, 3 },
+ { 191, 3 }, { 209, 3 }, { 226, 3 }, { 242, 3 },
+ { 3, 4 }, { 31, 4 }, { 58, 4 }, { 83, 4 },
+ { 107, 4 }, { 130, 4 }, { 151, 4 }, { 172, 4 },
+ { 191, 4 }, { 209, 4 }, { 226, 4 }, { 242, 4 },
+ { 3, 5 }, { 31, 5 }, { 58, 5 }, { 83, 5 },
+ { 107, 5 }, { 130, 5 }, { 151, 5 }, { 172, 5 },
+ { 191, 5 }, { 209, 5 }, { 226, 5 }, { 242, 5 },
+ { 3, 6 }, { 31, 6 }, { 58, 6 }, { 83, 6 },
+ { 107, 6 }, { 130, 6 }, { 151, 6 }, { 172, 6 },
+ { 191, 6 }, { 209, 6 }, { 226, 6 }, { 242, 6 },
+ { 3, 7 }, { 31, 7 }, { 58, 7 }, { 83, 7 },
+ { 107, 7 }, { 130, 7 }, { 151, 7 }, { 172, 7 },
+ { 191, 7 }, { 209, 7 }, { 226, 7 }, { 242, 7 },
+ { 3, 8 }, { 31, 8 }, { 58, 8 }, { 83, 8 },
+ { 107, 8 }, { 130, 8 }, { 151, 8 }, { 172, 8 },
+ { 191, 8 }, { 209, 8 }, { 226, 8 }, { 242, 8 },
+ { 3, 9 }, { 31, 9 }, { 58, 9 }, { 83, 9 },
+ { 107, 9 }, { 130, 9 }, { 151, 9 }, { 172, 9 },
+ { 191, 9 }, { 209, 9 }, { 226, 9 }, { 242, 9 },
+ { 3, 10 }, { 31, 10 }, { 58, 10 }, { 83, 10 },
+ { 107, 10 }, { 130, 10 }, { 151, 10 }, { 172, 10 },
+ { 191, 10 }, { 209, 10 }, { 226, 10 }, { 242, 10 }
+};
+
+const byte Player_V2CMS::_attackRate[16] = {
+ 0, 2, 4, 7, 14, 26, 48, 82,
+ 128, 144, 160, 176, 192, 208, 224, 255
+};
+
+const byte Player_V2CMS::_decayRate[16] = {
+ 0, 1, 2, 3, 4, 6, 12, 24,
+ 48, 96, 192, 215, 255, 255, 255, 255
+};
+
+const byte Player_V2CMS::_sustainRate[16] = {
+ 255, 180, 128, 96, 80, 64, 56, 48,
+ 42, 36, 32, 28, 24, 20, 16, 0
+};
+
+const byte Player_V2CMS::_releaseRate[16] = {
+ 0, 1, 2, 4, 6, 9, 14, 22,
+ 36, 56, 80, 100, 120, 140, 160, 255
+};
+
+const byte Player_V2CMS::_volumeTable[16] = {
+ 0x00, 0x10, 0x10, 0x11, 0x11, 0x21, 0x22, 0x22,
+ 0x33, 0x44, 0x55, 0x66, 0x88, 0xAA, 0xCC, 0xFF
+};
+
+const byte Player_V2CMS::_cmsInitData[26] = {
+ 0x1C, 0x02,
+ 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
+ 0x14, 0x3F, 0x15, 0x00, 0x16, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1C, 0x01
+};
+
} // End of namespace Scumm
diff --git a/engines/scumm/player_v2cms.h b/engines/scumm/player_v2cms.h
index f7dc0c16b1..905c7c141e 100644
--- a/engines/scumm/player_v2cms.h
+++ b/engines/scumm/player_v2cms.h
@@ -42,18 +42,14 @@ public:
virtual void startSound(int sound);
virtual void stopSound(int sound);
virtual void stopAllSounds();
-// virtual int getMusicTimer();
+ virtual int getMusicTimer();
virtual int getSoundStatus(int sound) const;
// AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return true; }
- bool endOfData() const { return false; }
- int getRate() const { return _sampleRate; }
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+ virtual bool isStereo() const { return true; }
-protected:
-
-#include "common/pack-start.h" // START STRUCT PACKING
+private:
struct Voice {
byte attack;
byte decay;
@@ -63,7 +59,7 @@ protected:
int16 vibrato;
int16 vibrato2;
int16 noise;
- } PACKED_STRUCT;
+ };
struct Voice2 {
byte *amplitudeOutput;
@@ -72,12 +68,12 @@ protected:
uint8 channel;
int8 sustainLevel;
- int8 attackRate;
+ uint8 attackRate;
uint8 maxAmpl;
- int8 decayRate;
- int8 sustainRate;
- int8 releaseRate;
- int8 releaseTime;
+ uint8 decayRate;
+ uint8 sustainRate;
+ uint8 releaseRate;
+ uint8 releaseTime;
int8 vibratoRate;
int8 vibratoDepth;
@@ -90,10 +86,17 @@ protected:
int8 unkRate;
int8 unkCount;
- int nextProcessState;
- int8 curVolume;
- int8 curOctave;
- int8 curFreq;
+ enum EnvelopeState {
+ kEnvelopeAttack,
+ kEnvelopeDecay,
+ kEnvelopeSustain,
+ kEnvelopeRelease
+ };
+
+ EnvelopeState nextProcessState;
+ uint8 curVolume;
+ uint8 curOctave;
+ uint8 curFreq;
int8 octaveAdd;
@@ -101,21 +104,20 @@ protected:
Voice2 *nextVoice;
byte chanNumber;
- } PACKED_STRUCT;
+ };
struct MusicChip {
byte ampl[4];
byte freq[4];
byte octave[2];
- } PACKED_STRUCT;
-#include "common/pack-end.h" // END STRUCT PACKING
+ };
Voice _cmsVoicesBase[16];
Voice2 _cmsVoices[8];
MusicChip _cmsChips[2];
- int8 _tempo;
- int8 _tempoSum;
+ uint8 _tempo;
+ uint8 _tempoSum;
byte _looping;
byte _octaveMask;
int16 _midiDelay;
@@ -126,11 +128,13 @@ protected:
int _loadedMidiSong;
+ byte _sfxFreq[4], _sfxAmpl[4], _sfxOctave[2];
+
byte _lastMidiCommand;
uint _outputTableReady;
- byte _clkFrequenz;
- byte _restart;
- byte _curSno;
+ byte _voiceTimer;
+
+ int _musicTimer, _musicTimerTicks;
void loadMidiData(byte *data, int sound);
void play();
@@ -147,15 +151,25 @@ protected:
void clearNote(byte *&data);
void offAllChannels();
void playVoice();
- void processMidiData(uint ticks);
+ void processMidiData();
Voice2 *getFreeVoice();
Voice2 *getPlayVoice(byte param);
- // from Player_V2
-protected:
- CMSEmulator *_cmsEmu;
+ struct MidiNote {
+ byte frequency;
+ byte baseOctave;
+ };
+
+ static const MidiNote _midiNotes[132];
+ static const byte _attackRate[16];
+ static const byte _decayRate[16];
+ static const byte _sustainRate[16];
+ static const byte _releaseRate[16];
+ static const byte _volumeTable[16];
+ static const byte _cmsInitData[26];
+ CMSEmulator *_cmsEmu;
};
} // End of namespace Scumm
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 3cc710c207..870ec8cdf7 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -686,12 +686,7 @@ Graphics::Surface *ScummEngine::loadThumbnailFromSlot(const char *target, int sl
Graphics::Surface *thumb = 0;
if (Graphics::checkThumbnailHeader(*in)) {
- thumb = new Graphics::Surface();
- assert(thumb);
- if (!Graphics::loadThumbnail(*in, *thumb)) {
- delete thumb;
- thumb = 0;
- }
+ thumb = Graphics::loadThumbnail(*in);
}
delete in;
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 8f555818f4..319eddf871 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Sun Apr 17 10:46:26 2011
+ This file was generated by the md5table tool on Wed Aug 3 03:14:00 2011
DO NOT EDIT MANUALLY!
*/
@@ -99,7 +99,7 @@ static const MD5Table md5table[] = {
{ "1ed22f601f8b3695804a6583cc3083f1", "puttrace", "HE 98.5", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "1f2e62b5a9c50589fc342285a6bb3a27", "freddi", "HE 73", "", -1, Common::HE_ISR, Common::kPlatformWindows },
{ "1fbebd7b2b692df5297870447a80cfed", "atlantis", "Floppy", "Floppy", 12030, Common::DE_DEU, Common::kPlatformPC },
- { "1ff5997c78fbd0a841a75ef15a05d9d5", "BluesBirthday", "", "Red", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "1ff5997c78fbd0a841a75ef15a05d9d5", "BluesBirthday", "Red", "Red", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "2012f854d83d9cc6f73b2b544cd8bbf8", "water", "HE 80", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "20176076d708bf14407bcc9bdcd7a418", "pajama3", "", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "204453e33456c4faa26e276229fe5b76", "spyfox2", "", "Demo", 14689, Common::DE_DEU, Common::kPlatformWindows },
@@ -403,7 +403,7 @@ static const MD5Table md5table[] = {
{ "9781422e4288dbc090720e4563168ba7", "puttzoo", "", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "981e1e1891f2be7e25a01f50ae55a5af", "puttrace", "HE 98", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "98744fe66ff730e8c2b3b1f58803ab0b", "atlantis", "Floppy", "Demo", -1, Common::EN_ANY, Common::kPlatformPC },
- { "99128b6a5bdd9831d9682fb8b5cbf8d4", "BluesBirthday", "", "Yellow", -1, Common::EN_ANY, Common::kPlatformUnknown },
+ { "99128b6a5bdd9831d9682fb8b5cbf8d4", "BluesBirthday", "Yellow", "Yellow", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "99a3699f80b8f776efae592b44b9b991", "maniac", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformPC },
{ "99b6f822b0b2612415407865438697d6", "atlantis", "", "Demo", -1, Common::EN_ANY, Common::kPlatformPC },
{ "9b7452b5cd6d3ffb2b2f5118010af84f", "ft", "Demo", "Demo", 116463537, Common::EN_ANY, Common::kPlatformMacintosh },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 0f01e39459..3b83019275 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -299,7 +299,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_haveActorSpeechMsg = false;
_useTalkAnims = false;
_defaultTalkDelay = 0;
- _musicType = MDT_NONE;
_saveSound = 0;
memset(_extraBoxFlags, 0, sizeof(_extraBoxFlags));
memset(_scaleSlots, 0, sizeof(_scaleSlots));
@@ -1669,43 +1668,8 @@ void ScummEngine_v90he::resetScumm() {
_sprite->resetTables(0);
memset(&_wizParams, 0, sizeof(_wizParams));
- if (_game.heversion >= 98) {
- switch (_game.id) {
- case GID_PUTTRACE:
- _logicHE = new LogicHErace(this);
- break;
-
- case GID_FUNSHOP:
- _logicHE = new LogicHEfunshop(this);
- break;
-
- case GID_FOOTBALL:
- _logicHE = new LogicHEfootball(this);
- break;
-
- case GID_SOCCER:
- case GID_SOCCERMLS:
- case GID_SOCCER2004:
- _logicHE = new LogicHEsoccer(this);
- break;
-
- case GID_BASEBALL2001:
- _logicHE = new LogicHEbaseball2001(this);
- break;
-
- case GID_BASKETBALL:
- _logicHE = new LogicHEbasketball(this);
- break;
-
- case GID_MOONBASE:
- _logicHE = new LogicHEmoonbase(this);
- break;
-
- default:
- _logicHE = new LogicHE(this);
- break;
- }
- }
+ if (_game.heversion >= 98)
+ _logicHE = LogicHE::makeLogicHE(this);
}
void ScummEngine_v99he::resetScumm() {
@@ -1746,40 +1710,36 @@ void ScummEngine::setupMusic(int midi) {
switch (MidiDriver::getMusicType(dev)) {
case MT_NULL:
- _musicType = MDT_NONE;
+ _sound->_musicType = MDT_NONE;
break;
case MT_PCSPK:
- _musicType = MDT_PCSPK;
+ _sound->_musicType = MDT_PCSPK;
break;
case MT_PCJR:
- _musicType = MDT_PCJR;
+ _sound->_musicType = MDT_PCJR;
break;
- //case MT_CMS:
-#if 1
- _musicType = MDT_ADLIB;
-#else
- _musicType = MDT_CMS; // Still has number of bugs, disable by default
-#endif
+ case MT_CMS:
+ _sound->_musicType = MDT_CMS;
break;
case MT_TOWNS:
- _musicType = MDT_TOWNS;
+ _sound->_musicType = MDT_TOWNS;
break;
case MT_ADLIB:
- _musicType = MDT_ADLIB;
+ _sound->_musicType = MDT_ADLIB;
break;
case MT_C64:
- _musicType = MDT_C64;
+ _sound->_musicType = MDT_C64;
break;
case MT_APPLEIIGS:
- _musicType = MDT_APPLEIIGS;
+ _sound->_musicType = MDT_APPLEIIGS;
break;
default:
- _musicType = MDT_MIDI;
+ _sound->_musicType = MDT_MIDI;
break;
}
if ((_game.id == GID_MONKEY_EGA || (_game.id == GID_LOOM && _game.version == 3))
- && (_game.platform == Common::kPlatformPC) && _musicType == MDT_MIDI) {
+ && (_game.platform == Common::kPlatformPC) && _sound->_musicType == MDT_MIDI) {
Common::String fileName;
bool missingFile = false;
if (_game.id == GID_LOOM) {
@@ -1809,7 +1769,7 @@ void ScummEngine::setupMusic(int midi) {
"but %s is missing. Using AdLib instead."), fileName.c_str()),
_("OK"));
dialog.runModal();
- _musicType = MDT_ADLIB;
+ _sound->_musicType = MDT_ADLIB;
}
}
@@ -1823,9 +1783,9 @@ void ScummEngine::setupMusic(int midi) {
* automatically when samples need to be generated */
if (!_mixer->isReady()) {
warning("Sound mixer initialization failed");
- if (_musicType == MDT_ADLIB || _musicType == MDT_PCSPK || _musicType == MDT_PCJR || _musicType == MDT_CMS) {
+ if (_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_PCSPK || _sound->_musicType == MDT_PCJR || _sound->_musicType == MDT_CMS) {
dev = 0;
- _musicType = MDT_NONE;
+ _sound->_musicType = MDT_NONE;
warning("MIDI driver depends on sound mixer, switching to null MIDI driver");
}
}
@@ -1857,9 +1817,9 @@ void ScummEngine::setupMusic(int midi) {
_musicEngine = new Player_V1(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK);
} else if (_game.version <= 2) {
_musicEngine = new Player_V2(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK);
- } else if ((_musicType == MDT_PCSPK || _musicType == MDT_PCJR) && (_game.version > 2 && _game.version <= 4)) {
+ } else if ((_sound->_musicType == MDT_PCSPK || _sound->_musicType == MDT_PCJR) && (_game.version > 2 && _game.version <= 4)) {
_musicEngine = new Player_V2(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK);
- } else if (_musicType == MDT_CMS) {
+ } else if (_sound->_musicType == MDT_CMS) {
_musicEngine = new Player_V2CMS(this, _mixer);
} else if (_game.platform == Common::kPlatform3DO && _game.heversion <= 62) {
// 3DO versions use digital music and sound samples.
@@ -1871,15 +1831,15 @@ void ScummEngine::setupMusic(int midi) {
MidiDriver *nativeMidiDriver = 0;
MidiDriver *adlibMidiDriver = 0;
- if (_musicType != MDT_ADLIB && _musicType != MDT_TOWNS && _musicType != MDT_PCSPK)
+ if (_sound->_musicType != MDT_ADLIB && _sound->_musicType != MDT_TOWNS && _sound->_musicType != MDT_PCSPK)
nativeMidiDriver = MidiDriver::createMidi(dev);
if (nativeMidiDriver != NULL && _native_mt32)
nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- bool multi_midi = ConfMan.getBool("multi_midi") && _musicType != MDT_NONE && _musicType != MDT_PCSPK && (midi & MDT_ADLIB);
- if (_musicType == MDT_ADLIB || _musicType == MDT_TOWNS || multi_midi) {
- adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB));
+ bool multi_midi = ConfMan.getBool("multi_midi") && _sound->_musicType != MDT_NONE && _sound->_musicType != MDT_PCSPK && (midi & MDT_ADLIB);
+ if (_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS || multi_midi) {
+ adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_sound->_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB));
adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
- } else if (_musicType == MDT_PCSPK) {
+ } else if (_sound->_musicType == MDT_PCSPK) {
adlibMidiDriver = new PcSpkDriver(_mixer);
}
@@ -1909,7 +1869,7 @@ void ScummEngine::setupMusic(int midi) {
_imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1);
_imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1);
}
- if (_musicType == MDT_PCSPK)
+ if (_sound->_musicType == MDT_PCSPK)
_imuse->property(IMuse::PROP_PC_SPEAKER, 1);
}
}
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index e503af750d..04a175e732 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -40,8 +40,6 @@
#include "scumm/detection.h"
#include "scumm/script.h"
-#include "audio/mididrv.h"
-
#ifdef __DS__
/* This disables the dual layer mode which is used in FM-Towns versions
* of SCUMM games and which emulates the behavior of the original code.
@@ -235,7 +233,8 @@ enum ScummGameId {
GID_PUTTMOON,
GID_FUNPACK,
GID_FREDDI3,
- GID_BIRTHDAY,
+ GID_BIRTHDAYRED,
+ GID_BIRTHDAYYELLOW,
GID_TREASUREHUNT,
GID_PUTTRACE,
GID_FUNSHOP, // Used for all three funshops
@@ -1084,7 +1083,6 @@ protected:
int _saveSound;
bool _native_mt32;
bool _enable_gs;
- MidiDriverFlags _musicType;
bool _copyProtection;
public:
diff --git a/engines/scumm/smush/channel.cpp b/engines/scumm/smush/channel.cpp
index 7f71d0549b..fd822f56b6 100644
--- a/engines/scumm/smush/channel.cpp
+++ b/engines/scumm/smush/channel.cpp
@@ -60,6 +60,8 @@ void SmushChannel::processBuffer() {
if (offset < _tbufferSize) {
int new_size = _tbufferSize - offset;
_tbuffer = (byte *)malloc(new_size);
+ // FIXME: _tbuffer might be 0 if new_size is 0.
+ // NB: Also check other "if (_tbuffer)" locations in smush
if (!_tbuffer)
error("smush channel failed to allocate memory");
memcpy(_tbuffer, _sbuffer + offset, new_size);
@@ -97,6 +99,8 @@ void SmushChannel::processBuffer() {
byte *old = _tbuffer;
int32 new_size = _tbufferSize - offset;
_tbuffer = (byte *)malloc(new_size);
+ // FIXME: _tbuffer might be 0 if new_size is 0.
+ // NB: Also check other "if (_tbuffer)" locations in smush
if (!_tbuffer)
error("smush channel failed to allocate memory");
memcpy(_tbuffer, old + offset, new_size);
diff --git a/engines/scumm/smush/codec37.cpp b/engines/scumm/smush/codec37.cpp
index dcc8ee3c19..344057e3ac 100644
--- a/engines/scumm/smush/codec37.cpp
+++ b/engines/scumm/smush/codec37.cpp
@@ -571,4 +571,3 @@ void Codec37Decoder::decode(byte *dst, const byte *src) {
}
} // End of namespace Scumm
-
diff --git a/engines/scumm/smush/smush_font.cpp b/engines/scumm/smush/smush_font.cpp
index 7765bf1292..5cfa0ea519 100644
--- a/engines/scumm/smush/smush_font.cpp
+++ b/engines/scumm/smush/smush_font.cpp
@@ -258,4 +258,3 @@ void SmushFont::drawStringWrap(const char *str, byte *buffer, int dst_width, int
}
} // End of namespace Scumm
-
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index c3cad19fdc..d8235206f8 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -84,6 +84,8 @@ Sound::Sound(ScummEngine *parent, Audio::Mixer *mixer)
memset(_soundQue, 0, sizeof(_soundQue));
memset(_soundQue2, 0, sizeof(_soundQue2));
memset(_mouthSyncTimes, 0, sizeof(_mouthSyncTimes));
+
+ _musicType = MDT_NONE;
}
Sound::~Sound() {
@@ -1016,7 +1018,7 @@ void Sound::startCDTimer() {
// appears.
_vm->getTimerManager()->removeTimerProc(&cd_timer_handler);
- _vm->getTimerManager()->installTimerProc(&cd_timer_handler, 100700, _vm);
+ _vm->getTimerManager()->installTimerProc(&cd_timer_handler, 100700, _vm, "scummCDtimer");
}
void Sound::stopCDTimer() {
@@ -1094,7 +1096,7 @@ int ScummEngine::readSoundResource(ResId idx) {
switch (basetag) {
case MKTAG('M','I','D','I'):
case MKTAG('i','M','U','S'):
- if (_musicType != MDT_PCSPK && _musicType != MDT_PCJR) {
+ if (_sound->_musicType != MDT_PCSPK && _sound->_musicType != MDT_PCJR) {
_fileHandle->seek(-8, SEEK_CUR);
_fileHandle->read(_res->createResource(rtSound, idx, total_size + 8), total_size + 8);
return 1;
@@ -1118,7 +1120,7 @@ int ScummEngine::readSoundResource(ResId idx) {
break;
case MKTAG('A','D','L',' '):
pri = 1;
- if (_musicType == MDT_ADLIB || _musicType == MDT_TOWNS)
+ if (_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS)
pri = 10;
break;
case MKTAG('A','M','I',' '):
@@ -1137,15 +1139,15 @@ int ScummEngine::readSoundResource(ResId idx) {
break;
case MKTAG('S','P','K',' '):
pri = -1;
- if (_musicType == MDT_PCSPK || _musicType == MDT_PCJR)
+ if (_sound->_musicType == MDT_PCSPK || _sound->_musicType == MDT_PCJR)
pri = 11;
break;
}
- // We only allow SPK resources for PC Speaker, PCJr and CMS here
+ // We only allow SPK resources for PC Speaker and PCJr here
// since other resource would sound horribly with their output
// drivers.
- if ((_musicType == MDT_PCSPK || _musicType == MDT_PCJR || _musicType == MDT_CMS) && pri != 11)
+ if ((_sound->_musicType == MDT_PCSPK || _sound->_musicType == MDT_PCJR) && pri != 11)
pri = -1;
// We only allow ADL resources when AdLib or FM-Towns is used as
@@ -1155,12 +1157,16 @@ int ScummEngine::readSoundResource(ResId idx) {
// only contains a ROL resource for sound id 60. Formerly we tried
// to play that via the AdLib or FM-Towns audio driver resulting
// in strange noises. Now we behave like the original did.
- if ((_musicType == MDT_ADLIB || _musicType == MDT_TOWNS) && pri != 10)
+ // We make an exception for Macintosh, which uses priority 2 for
+ // its sound resources, and Amiga games, which feature only ROL
+ // resources, since we are a doing Midi -> AdLib conversion for
+ // these.
+ if ((_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS) && pri != 10
+ && pri != 2 && _game.platform != Common::kPlatformAmiga)
pri = -1;
debugC(DEBUG_RESOURCE, " tag: %s, total_size=%d, pri=%d", tag2str(tag), size, pri);
-
if (pri > best_pri) {
best_pri = pri;
best_size = size;
@@ -1997,6 +2003,14 @@ static void convertADResource(ResourceManager *res, const GameSettings& game, Re
break;
case 0x80:
+ // FIXME: This is incorrect. The original uses 0x80 for
+ // looping a single channel. We currently interpret it as stop
+ // thus we won't get looping for sound effects. It should
+ // always jump to the start of the channel.
+ //
+ // Since we convert the data to MIDI and we cannot only loop a
+ // single channel via MIDI fixing this will require some more
+ // thought.
track_time[ch] = -1;
src_ptr ++;
break;
@@ -2087,7 +2101,7 @@ int ScummEngine::readSoundResourceSmallHeader(ResId idx) {
}
}
- if ((_musicType == MDT_PCSPK || _musicType == MDT_PCJR) && wa_offs != 0) {
+ if ((_sound->_musicType == MDT_PCSPK || _sound->_musicType == MDT_PCJR) && wa_offs != 0) {
if (_game.features & GF_OLD_BUNDLE) {
_fileHandle->seek(wa_offs, SEEK_SET);
_fileHandle->read(_res->createResource(rtSound, idx, wa_size), wa_size);
@@ -2096,18 +2110,37 @@ int ScummEngine::readSoundResourceSmallHeader(ResId idx) {
_fileHandle->read(_res->createResource(rtSound, idx, wa_size + 6), wa_size + 6);
}
return 1;
- } else if (_musicType == MDT_CMS && ad_offs != 0) {
+ } else if (_sound->_musicType == MDT_CMS) {
if (_game.features & GF_OLD_BUNDLE) {
- _fileHandle->seek(wa_offs + wa_size + 6, SEEK_SET);
- byte musType = _fileHandle->readByte();
+ bool hasAdLibMusicTrack = false;
- if (musType == 0x80) {
+ if (ad_offs) {
+ _fileHandle->seek(ad_offs + 4 + 2, SEEK_SET);
+ hasAdLibMusicTrack = (_fileHandle->readByte() == 0x80);
+ }
+
+ if (hasAdLibMusicTrack) {
_fileHandle->seek(ad_offs, SEEK_SET);
_fileHandle->read(_res->createResource(rtSound, idx, ad_size), ad_size);
} else {
_fileHandle->seek(wa_offs, SEEK_SET);
_fileHandle->read(_res->createResource(rtSound, idx, wa_size), wa_size);
}
+ } else {
+ bool hasAdLibMusicTrack = false;
+
+ if (ad_offs) {
+ _fileHandle->seek(ad_offs + 2, SEEK_SET);
+ hasAdLibMusicTrack = (_fileHandle->readByte() == 0x80);
+ }
+
+ if (hasAdLibMusicTrack) {
+ _fileHandle->seek(ad_offs - 4, SEEK_SET);
+ _fileHandle->read(_res->createResource(rtSound, idx, ad_size + 4), ad_size + 4);
+ } else {
+ _fileHandle->seek(wa_offs - 6, SEEK_SET);
+ _fileHandle->read(_res->createResource(rtSound, idx, wa_size + 6), wa_size + 6);
+ }
}
} else if (ad_offs != 0) {
// AD resources have a header, instrument definitions and one MIDI track.
diff --git a/engines/scumm/sound.h b/engines/scumm/sound.h
index 03659ceff1..e9a37ac9fa 100644
--- a/engines/scumm/sound.h
+++ b/engines/scumm/sound.h
@@ -24,6 +24,7 @@
#include "common/scummsys.h"
#include "audio/audiostream.h"
+#include "audio/mididrv.h"
#include "audio/mixer.h"
#include "scumm/saveload.h"
@@ -90,6 +91,8 @@ public:
byte _sfxMode;
uint _lastSound;
+ MidiDriverFlags _musicType;
+
public:
Sound(ScummEngine *parent, Audio::Mixer *mixer);
virtual ~Sound();
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index 2d2209c155..61bb89328d 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -1127,8 +1127,6 @@ int ScummEngine::convertMessageToString(const byte *msg, byte *dst, int dstSize)
}
num += (_game.version == 8) ? 4 : 2;
}
- } else if (_game.id == GID_DIG && (chr == 1 || chr == 2 || chr == 3 || chr == 8)) {
- // Skip these characters
} else {
if ((chr != '@') || (_game.id == GID_CMI && _language == Common::ZH_TWN) ||
(_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine && _language == Common::JA_JPN) ||
@@ -1142,6 +1140,14 @@ int ScummEngine::convertMessageToString(const byte *msg, byte *dst, int dstSize)
if (dst >= end)
error("convertMessageToString: buffer overflow");
}
+
+ // WORKAROUND: Russian The Dig pads messages with 03. No idea why
+ // it does not work as is with our rendering code, thus fixing it
+ // with a workaround.
+ if (_game.id == GID_DIG) {
+ while (*(dst - 1) == 0x03)
+ dst--;
+ }
*dst = 0;
return dstSize - (end - dst);
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index 4527d7a121..26a6a2f3b1 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -25,9 +25,12 @@
#include "scumm/scumm.h"
#include "scumm/scumm_v0.h"
#include "scumm/scumm_v8.h"
+#include "scumm/sound.h"
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
+#include "audio/mididrv.h"
+
namespace Scumm {
void ScummEngine::setupScummVars() {
@@ -722,7 +725,7 @@ void ScummEngine::resetScummVars() {
// 2 CMS
// 3 AdLib
// 4 Roland
- switch (_musicType) {
+ switch (_sound->_musicType) {
case MDT_NONE:
case MDT_PCSPK:
VAR(VAR_SOUNDCARD) = 0;
diff --git a/engines/sky/autoroute.h b/engines/sky/autoroute.h
index 2d01be01ec..8721ba6c54 100644
--- a/engines/sky/autoroute.h
+++ b/engines/sky/autoroute.h
@@ -56,4 +56,3 @@ private:
} // End of namespace Sky
#endif // AUTOROUTE_H
-
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index 6c0cf8b1ef..c3550e6f02 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -162,4 +162,3 @@ private:
} // End of namespace Sword1
#endif //BSCONTROL_H
-
diff --git a/engines/sword1/debug.h b/engines/sword1/debug.h
index e4f004dc63..1505ae28dd 100644
--- a/engines/sword1/debug.h
+++ b/engines/sword1/debug.h
@@ -39,4 +39,3 @@ private:
} // End of namespace Sword1
#endif // BSDEBUG_H
-
diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp
index 0c1e74082f..4da636bce9 100644
--- a/engines/sword1/detection.cpp
+++ b/engines/sword1/detection.cpp
@@ -274,13 +274,7 @@ SaveStateDescriptor SwordMetaEngine::querySaveMetaInfos(const char *target, int
in->skip(1);
if (Graphics::checkThumbnailHeader(*in)) {
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- if (!Graphics::loadThumbnail(*in, *thumbnail)) {
- delete thumbnail;
- thumbnail = 0;
- }
-
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
desc.setThumbnail(thumbnail);
}
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
index b4656ff89f..c34630aceb 100644
--- a/engines/sword1/music.cpp
+++ b/engines/sword1/music.cpp
@@ -35,7 +35,7 @@
#include "audio/decoders/mp3.h"
#include "audio/decoders/vorbis.h"
#include "audio/decoders/wave.h"
-#include "audio/decoders/vag.h"
+#include "audio/decoders/xa.h"
#define SMP_BUFSIZE 8192
@@ -110,7 +110,7 @@ bool MusicHandle::play(const Common::String &filename, bool loop) {
return true;
}
-bool MusicHandle::playPSX(uint16 id, bool loop) {
+bool MusicHandle::playPSX(uint16 id) {
stop();
if (!_file.isOpen())
@@ -131,7 +131,7 @@ bool MusicHandle::playPSX(uint16 id, bool loop) {
// not over file size
if ((size != 0) && (size != 0xffffffff) && ((int32)(offset + size) <= _file.size())) {
_file.seek(offset, SEEK_SET);
- _audioSource = Audio::makeLoopingAudioStream(Audio::makeVagStream(_file.readStream(size)), loop ? 0 : 1);
+ _audioSource = Audio::makeXAStream(_file.readStream(size), 11025);
fadeUp();
} else {
_audioSource = NULL;
@@ -297,7 +297,7 @@ void Music::startMusic(int32 tuneId, int32 loopFlag) {
the mutex before, to have the soundthread playing normally.
As the corresponding _converter is NULL, the handle will be ignored by the playing thread */
if (SwordEngine::isPsx()) {
- if (_handles[newStream].playPSX(tuneId, loopFlag != 0)) {
+ if (_handles[newStream].playPSX(tuneId)) {
_mutex.lock();
_converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
_mutex.unlock();
diff --git a/engines/sword1/music.h b/engines/sword1/music.h
index 4207019c13..f1366202d7 100644
--- a/engines/sword1/music.h
+++ b/engines/sword1/music.h
@@ -44,7 +44,7 @@ public:
MusicHandle() : _fading(0), _audioSource(NULL) {}
virtual int readBuffer(int16 *buffer, const int numSamples);
bool play(const Common::String &filename, bool loop);
- bool playPSX(uint16 id, bool loop);
+ bool playPSX(uint16 id);
void stop();
void fadeUp();
void fadeDown();
diff --git a/engines/sword1/object.h b/engines/sword1/object.h
index 5a6fd49c0b..4f5371fa72 100644
--- a/engines/sword1/object.h
+++ b/engines/sword1/object.h
@@ -123,4 +123,3 @@ struct Object {
} // End of namespace Sword1
#endif //BSOBJECT_H
-
diff --git a/engines/sword1/screen.h b/engines/sword1/screen.h
index ece37b0ecc..ff4df8c7c6 100644
--- a/engines/sword1/screen.h
+++ b/engines/sword1/screen.h
@@ -169,6 +169,3 @@ private:
} // End of namespace Sword1
#endif //BSSCREEN_H
-
-
-
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index f7ab9ca1de..677a9869ce 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -38,7 +38,7 @@
#include "audio/decoders/raw.h"
#include "audio/decoders/vorbis.h"
#include "audio/decoders/wave.h"
-#include "audio/decoders/vag.h"
+#include "audio/decoders/xa.h"
namespace Sword1 {
@@ -255,8 +255,9 @@ void Sound::playSample(QueueElement *elem) {
uint8 volume = (volR + volL) / 2;
if (SwordEngine::isPsx()) {
+ // We ignore FX_LOOP as XA has its own looping mechanism
uint32 size = READ_LE_UINT32(sampleData);
- Audio::AudioStream *audStream = Audio::makeLoopingAudioStream(Audio::makeVagStream(new Common::MemoryReadStream(sampleData + 4, size-4)), (_fxList[elem->id].type == FX_LOOP) ? 0 : 1);
+ Audio::AudioStream *audStream = Audio::makeXAStream(new Common::MemoryReadStream(sampleData + 4, size-4), 11025);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &elem->handle, audStream, elem->id, volume, pan);
} else {
uint32 size = READ_LE_UINT32(sampleData + 0x28);
@@ -364,7 +365,7 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
_cowFile.seek(index * 2048);
Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
assert(tmp);
- stream = Audio::makeVagStream(tmp);
+ stream = Audio::makeXAStream(tmp, 11025);
_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
// with compressed audio, we can't calculate the wave volume.
// so default to talking.
diff --git a/engines/sword2/music.cpp b/engines/sword2/music.cpp
index 63116e954a..1bb08fd36f 100644
--- a/engines/sword2/music.cpp
+++ b/engines/sword2/music.cpp
@@ -39,7 +39,7 @@
#include "audio/decoders/vorbis.h"
#include "audio/decoders/flac.h"
#include "audio/decoders/wave.h"
-#include "audio/decoders/vag.h"
+#include "audio/decoders/xa.h"
#include "audio/rate.h"
#include "sword2/sword2.h"
@@ -267,7 +267,7 @@ Audio::AudioStream *makePSXCLUStream(Common::File *file, int size) {
byte *buffer = (byte *)malloc(size);
file->read(buffer, size);
- return Audio::makeVagStream(new Common::MemoryReadStream(buffer, size, DisposeAfterUse::YES));
+ return Audio::makeXAStream(new Common::MemoryReadStream(buffer, size, DisposeAfterUse::YES), 11025);
}
// ----------------------------------------------------------------------------
diff --git a/engines/sword2/sound.cpp b/engines/sword2/sound.cpp
index 19e244e61c..aea33e99e3 100644
--- a/engines/sword2/sound.cpp
+++ b/engines/sword2/sound.cpp
@@ -47,7 +47,7 @@
#include "sword2/sound.h"
#include "audio/decoders/wave.h"
-#include "audio/decoders/vag.h"
+#include "audio/decoders/xa.h"
#define Debug_Printf _vm->_debugger->DebugPrintf
@@ -234,7 +234,7 @@ void Sound::playMovieSound(int32 res, int type) {
Audio::RewindableAudioStream *input = 0;
if (Sword2Engine::isPsx()) {
- input = Audio::makeVagStream(stream);
+ input = Audio::makeXAStream(stream, 11025);
} else {
input = Audio::makeWAVStream(stream, DisposeAfterUse::YES);
}
@@ -361,7 +361,7 @@ int32 Sound::playFx(Audio::SoundHandle *handle, byte *data, uint32 len, uint8 vo
Audio::RewindableAudioStream *input = 0;
if (Sword2Engine::isPsx())
- input = Audio::makeVagStream(stream);
+ input = Audio::makeXAStream(stream, 11025);
else
input = Audio::makeWAVStream(stream, DisposeAfterUse::YES);
diff --git a/engines/sword25/detection.cpp b/engines/sword25/detection.cpp
index b2f5795663..25a3df167b 100644
--- a/engines/sword25/detection.cpp
+++ b/engines/sword25/detection.cpp
@@ -99,4 +99,3 @@ SaveStateList Sword25MetaEngine::listSaves(const char *target) const {
#else
REGISTER_PLUGIN_STATIC(SWORD25, PLUGIN_TYPE_ENGINE, Sword25MetaEngine);
#endif
-
diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp
index 1b424dac65..78b2db19eb 100644
--- a/engines/sword25/sfx/soundengine.cpp
+++ b/engines/sword25/sfx/soundengine.cpp
@@ -209,7 +209,7 @@ uint SoundEngine::playSoundEx(const Common::String &fileName, SOUND_TYPES type,
#ifdef USE_VORBIS
Audio::SeekableAudioStream *stream = Audio::makeVorbisStream(in, DisposeAfterUse::YES);
#endif
- uint id;
+ uint id = handleId;
SndHandle *handle;
if (handleId == 0x1337)
diff --git a/engines/sword25/util/lua/lapi.cpp b/engines/sword25/util/lua/lapi.cpp
index ff25cfc653..b97e90012c 100644
--- a/engines/sword25/util/lua/lapi.cpp
+++ b/engines/sword25/util/lua/lapi.cpp
@@ -1074,4 +1074,3 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
lua_unlock(L);
return name;
}
-
diff --git a/engines/sword25/util/lua/lauxlib.cpp b/engines/sword25/util/lua/lauxlib.cpp
index 1261777315..116d19dfce 100644
--- a/engines/sword25/util/lua/lauxlib.cpp
+++ b/engines/sword25/util/lua/lauxlib.cpp
@@ -655,4 +655,3 @@ LUALIB_API lua_State *luaL_newstate (void) {
if (L) lua_atpanic(L, &panic);
return L;
}
-
diff --git a/engines/sword25/util/lua/lauxlib.h b/engines/sword25/util/lua/lauxlib.h
index d58f290527..d3c1d5ca35 100644
--- a/engines/sword25/util/lua/lauxlib.h
+++ b/engines/sword25/util/lua/lauxlib.h
@@ -170,5 +170,3 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
#define luaL_reg luaL_Reg
#endif
-
-
diff --git a/engines/sword25/util/lua/lbaselib.cpp b/engines/sword25/util/lua/lbaselib.cpp
index 5032e6322a..3f0b645164 100644
--- a/engines/sword25/util/lua/lbaselib.cpp
+++ b/engines/sword25/util/lua/lbaselib.cpp
@@ -651,4 +651,3 @@ LUALIB_API int luaopen_base (lua_State *L) {
luaL_register(L, LUA_COLIBNAME, co_funcs);
return 2;
}
-
diff --git a/engines/sword25/util/lua/lcode.cpp b/engines/sword25/util/lua/lcode.cpp
index 6e7e10017f..ead780d359 100644
--- a/engines/sword25/util/lua/lcode.cpp
+++ b/engines/sword25/util/lua/lcode.cpp
@@ -836,4 +836,3 @@ void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
}
fs->freereg = base + 1; /* free registers with list values */
}
-
diff --git a/engines/sword25/util/lua/ldblib.cpp b/engines/sword25/util/lua/ldblib.cpp
index 618e9a843f..e5cb8231c0 100644
--- a/engines/sword25/util/lua/ldblib.cpp
+++ b/engines/sword25/util/lua/ldblib.cpp
@@ -398,4 +398,3 @@ LUALIB_API int luaopen_debug (lua_State *L) {
luaL_register(L, LUA_DBLIBNAME, dblib);
return 1;
}
-
diff --git a/engines/sword25/util/lua/ldebug.cpp b/engines/sword25/util/lua/ldebug.cpp
index 85c492cc77..e89ae9cad5 100644
--- a/engines/sword25/util/lua/ldebug.cpp
+++ b/engines/sword25/util/lua/ldebug.cpp
@@ -619,4 +619,3 @@ void luaG_runerror (lua_State *L, const char *fmt, ...) {
va_end(argp);
luaG_errormsg(L);
}
-
diff --git a/engines/sword25/util/lua/ldo.cpp b/engines/sword25/util/lua/ldo.cpp
index 49e0881a45..5d9667f4f0 100644
--- a/engines/sword25/util/lua/ldo.cpp
+++ b/engines/sword25/util/lua/ldo.cpp
@@ -534,5 +534,3 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
luaZ_freebuffer(L, &p.buff);
return status;
}
-
-
diff --git a/engines/sword25/util/lua/ldo.h b/engines/sword25/util/lua/ldo.h
index 4c97134805..e57b08dec0 100644
--- a/engines/sword25/util/lua/ldo.h
+++ b/engines/sword25/util/lua/ldo.h
@@ -54,4 +54,3 @@ 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/lua/lfunc.cpp b/engines/sword25/util/lua/lfunc.cpp
index ce7acf4e77..f8fa19e25a 100644
--- a/engines/sword25/util/lua/lfunc.cpp
+++ b/engines/sword25/util/lua/lfunc.cpp
@@ -171,4 +171,3 @@ const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
}
return NULL; /* not found */
}
-
diff --git a/engines/sword25/util/lua/lgc.cpp b/engines/sword25/util/lua/lgc.cpp
index 71e581ad30..54f7b548dd 100644
--- a/engines/sword25/util/lua/lgc.cpp
+++ b/engines/sword25/util/lua/lgc.cpp
@@ -708,4 +708,3 @@ void luaC_linkupval (lua_State *L, UpVal *uv) {
}
}
}
-
diff --git a/engines/sword25/util/lua/linit.cpp b/engines/sword25/util/lua/linit.cpp
index 93f41d0350..a01f28d1ff 100644
--- a/engines/sword25/util/lua/linit.cpp
+++ b/engines/sword25/util/lua/linit.cpp
@@ -35,4 +35,3 @@ LUALIB_API void luaL_openlibs (lua_State *L) {
lua_call(L, 1, 0);
}
}
-
diff --git a/engines/sword25/util/lua/liolib.cpp b/engines/sword25/util/lua/liolib.cpp
index 6c00de5094..0d27f9677f 100644
--- a/engines/sword25/util/lua/liolib.cpp
+++ b/engines/sword25/util/lua/liolib.cpp
@@ -590,4 +590,3 @@ LUALIB_API int luaopen_io (lua_State *L) {
lua_pop(L, 1); /* pop 'popen' */
return 1;
}
-
diff --git a/engines/sword25/util/lua/llex.cpp b/engines/sword25/util/lua/llex.cpp
index b456ee2dfe..464ab3ec15 100644
--- a/engines/sword25/util/lua/llex.cpp
+++ b/engines/sword25/util/lua/llex.cpp
@@ -472,4 +472,3 @@ void luaX_lookahead (LexState *ls) {
lua_assert(ls->lookahead.token == TK_EOS);
ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
}
-
diff --git a/engines/sword25/util/lua/lmathlib.cpp b/engines/sword25/util/lua/lmathlib.cpp
index 6c36bbcf4e..c1a645b296 100644
--- a/engines/sword25/util/lua/lmathlib.cpp
+++ b/engines/sword25/util/lua/lmathlib.cpp
@@ -274,4 +274,3 @@ LUALIB_API int luaopen_math (lua_State *L) {
#endif
return 1;
}
-
diff --git a/engines/sword25/util/lua/lmem.cpp b/engines/sword25/util/lua/lmem.cpp
index ccd69357e0..004a467dc8 100644
--- a/engines/sword25/util/lua/lmem.cpp
+++ b/engines/sword25/util/lua/lmem.cpp
@@ -83,4 +83,3 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
g->totalbytes = (g->totalbytes - osize) + nsize;
return block;
}
-
diff --git a/engines/sword25/util/lua/lmem.h b/engines/sword25/util/lua/lmem.h
index 97a888c7f8..6430912b41 100644
--- a/engines/sword25/util/lua/lmem.h
+++ b/engines/sword25/util/lua/lmem.h
@@ -46,4 +46,3 @@ LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
const char *errormsg);
#endif
-
diff --git a/engines/sword25/util/lua/loadlib.cpp b/engines/sword25/util/lua/loadlib.cpp
index f4cdd70a78..49934ce059 100644
--- a/engines/sword25/util/lua/loadlib.cpp
+++ b/engines/sword25/util/lua/loadlib.cpp
@@ -329,4 +329,3 @@ LUALIB_API int luaopen_package (lua_State *L) {
lua_pop(L, 1);
return 1; /* return 'package' table */
}
-
diff --git a/engines/sword25/util/lua/lobject.h b/engines/sword25/util/lua/lobject.h
index 5418a918b1..70b2c754ea 100644
--- a/engines/sword25/util/lua/lobject.h
+++ b/engines/sword25/util/lua/lobject.h
@@ -378,4 +378,3 @@ LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
#endif
-
diff --git a/engines/sword25/util/lua/lopcodes.cpp b/engines/sword25/util/lua/lopcodes.cpp
index d9da16f689..255b2029e9 100644
--- a/engines/sword25/util/lua/lopcodes.cpp
+++ b/engines/sword25/util/lua/lopcodes.cpp
@@ -99,4 +99,3 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
};
-
diff --git a/engines/sword25/util/lua/loslib.cpp b/engines/sword25/util/lua/loslib.cpp
index b61f8c65e1..25bfa2d1b5 100644
--- a/engines/sword25/util/lua/loslib.cpp
+++ b/engines/sword25/util/lua/loslib.cpp
@@ -243,4 +243,3 @@ LUALIB_API int luaopen_os (lua_State *L) {
luaL_register(L, LUA_OSLIBNAME, syslib);
return 1;
}
-
diff --git a/engines/sword25/util/lua/lstate.cpp b/engines/sword25/util/lua/lstate.cpp
index e542bcbacc..26bed7bec2 100644
--- a/engines/sword25/util/lua/lstate.cpp
+++ b/engines/sword25/util/lua/lstate.cpp
@@ -211,4 +211,3 @@ LUA_API void lua_close (lua_State *L) {
luai_userstateclose(L);
close_state(L);
}
-
diff --git a/engines/sword25/util/lua/lstate.h b/engines/sword25/util/lua/lstate.h
index 94a6249461..05ccb43d5e 100644
--- a/engines/sword25/util/lua/lstate.h
+++ b/engines/sword25/util/lua/lstate.h
@@ -166,4 +166,3 @@ 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/lua/lstring.cpp b/engines/sword25/util/lua/lstring.cpp
index cd55cc63bf..046b87ee1c 100644
--- a/engines/sword25/util/lua/lstring.cpp
+++ b/engines/sword25/util/lua/lstring.cpp
@@ -108,4 +108,3 @@ Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
G(L)->mainthread->next = obj2gco(u);
return u;
}
-
diff --git a/engines/sword25/util/lua/lstrlib.cpp b/engines/sword25/util/lua/lstrlib.cpp
index 2a1b8690e2..bcc869cb98 100644
--- a/engines/sword25/util/lua/lstrlib.cpp
+++ b/engines/sword25/util/lua/lstrlib.cpp
@@ -865,4 +865,3 @@ LUALIB_API int luaopen_string (lua_State *L) {
createmetatable(L);
return 1;
}
-
diff --git a/engines/sword25/util/lua/ltablib.cpp b/engines/sword25/util/lua/ltablib.cpp
index 607c09ae71..93be9e6077 100644
--- a/engines/sword25/util/lua/ltablib.cpp
+++ b/engines/sword25/util/lua/ltablib.cpp
@@ -276,4 +276,3 @@ LUALIB_API int luaopen_table (lua_State *L) {
luaL_register(L, LUA_TABLIBNAME, tab_funcs);
return 1;
}
-
diff --git a/engines/sword25/util/lua/ltm.cpp b/engines/sword25/util/lua/ltm.cpp
index 02856a58fc..60ca76689a 100644
--- a/engines/sword25/util/lua/ltm.cpp
+++ b/engines/sword25/util/lua/ltm.cpp
@@ -72,4 +72,3 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
}
return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}
-
diff --git a/engines/sword25/util/lua/luaconf.h b/engines/sword25/util/lua/luaconf.h
index f3509e969b..f5affe9fd7 100644
--- a/engines/sword25/util/lua/luaconf.h
+++ b/engines/sword25/util/lua/luaconf.h
@@ -723,4 +723,3 @@ union luai_Cast { double l_d; long l_l; };
#endif
-
diff --git a/engines/sword25/util/lua/lvm.cpp b/engines/sword25/util/lua/lvm.cpp
index d0f2198651..d538d0b349 100644
--- a/engines/sword25/util/lua/lvm.cpp
+++ b/engines/sword25/util/lua/lvm.cpp
@@ -760,4 +760,3 @@ void luaV_execute (lua_State *L, int nexeccalls) {
}
}
}
-
diff --git a/engines/sword25/util/lua/lzio.cpp b/engines/sword25/util/lua/lzio.cpp
index e1e7b28a29..d05c613897 100644
--- a/engines/sword25/util/lua/lzio.cpp
+++ b/engines/sword25/util/lua/lzio.cpp
@@ -78,5 +78,3 @@ char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
}
return buff->buffer;
}
-
-
diff --git a/engines/sword25/util/pluto/CHANGELOG b/engines/sword25/util/pluto/CHANGELOG
index e31ed26044..1be321f898 100644
--- a/engines/sword25/util/pluto/CHANGELOG
+++ b/engines/sword25/util/pluto/CHANGELOG
@@ -35,4 +35,3 @@ Earlier versions are changelogged on the LuaForge site.
* Fixed all outstanding 5.0->5.1 conversion issues
* Made heavier use of size_t in preference to int
* Fixed GC/Upval issue (thanks to Eric Jacobs)
-
diff --git a/engines/sword25/util/pluto/FILEFORMAT b/engines/sword25/util/pluto/FILEFORMAT
index b3f10ee603..e7716675c7 100644
--- a/engines/sword25/util/pluto/FILEFORMAT
+++ b/engines/sword25/util/pluto/FILEFORMAT
@@ -165,4 +165,4 @@ struct LocVar {
Object name; /* Name of the local variable */
int startpc; /* Point where variable is active */
int endpc; /* Point where variable is dead */
-}; \ No newline at end of file
+};
diff --git a/engines/sword25/util/pluto/THANKS b/engines/sword25/util/pluto/THANKS
index fea3595dbf..443713fa61 100644
--- a/engines/sword25/util/pluto/THANKS
+++ b/engines/sword25/util/pluto/THANKS
@@ -7,4 +7,3 @@ Goran Adrinek
Eric Jacobs
Anolan Milanes
Malte Thiesen
-
diff --git a/engines/sword25/util/pluto/plzio.cpp b/engines/sword25/util/pluto/plzio.cpp
index 0efc3dfcf2..21f69a9e8d 100644
--- a/engines/sword25/util/pluto/plzio.cpp
+++ b/engines/sword25/util/pluto/plzio.cpp
@@ -72,5 +72,3 @@ char *pdep_openspace (lua_State *L, Mbuffer *buff, size_t n) {
}
return buff->buffer;
}
-
-
diff --git a/engines/teenagent/animation.cpp b/engines/teenagent/animation.cpp
index e945bda1e5..56107b67ca 100644
--- a/engines/teenagent/animation.cpp
+++ b/engines/teenagent/animation.cpp
@@ -106,11 +106,11 @@ void Animation::free() {
index = 0;
}
-void Animation::load(Common::SeekableReadStream *s, Type type) {
+void Animation::load(Common::SeekableReadStream &s, Type type) {
//fixme: do not reload the same animation each time
free();
- if (s == NULL || s->size() <= 1) {
+ if (s.size() <= 1) {
debug(1, "empty animation");
return;
}
@@ -119,29 +119,29 @@ void Animation::load(Common::SeekableReadStream *s, Type type) {
int off = 0;
switch (type) {
case kTypeLan:
- data_size = s->readUint16LE();
- if (s->eos()) {
+ data_size = s.readUint16LE();
+ if (s.eos()) {
debug(1, "empty animation");
return;
}
data_size -= 2;
data = new byte[data_size];
- data_size = s->read(data, data_size);
+ data_size = s.read(data, data_size);
/* for (int i = 0; i < data_size; ++i) {
debug(0, "%02x ", data[i]);
}
debug(0, ", %u frames", data_size / 3);
*/
- frames_count = s->readByte();
+ frames_count = s.readByte();
debug(1, "%u physical frames", frames_count);
if (frames_count == 0)
return;
frames = new Surface[frames_count];
- s->skip(frames_count * 2 - 2); //sizes
- /*pos = */s->readUint16LE();
+ s.skip(frames_count * 2 - 2); //sizes
+ /*pos = */s.readUint16LE();
//debug(0, "pos?: %04x", pos);
for (uint16 i = 0; i < frames_count; ++i) {
@@ -152,15 +152,15 @@ void Animation::load(Common::SeekableReadStream *s, Type type) {
break;
case kTypeInventory: {
- data_size = 3 * s->readByte();
+ data_size = 3 * s.readByte();
data = new byte[data_size];
frames_count = 0;
for (byte i = 0; i < data_size / 3; ++i) {
int idx = i * 3;
/* byte unk = */
- s->readByte();
- data[idx] = s->readByte();
+ s.readByte();
+ data[idx] = s.readByte();
if (data[idx] == 0)
data[idx] = 1; //fixme: investigate
if (data[idx] > frames_count)
@@ -179,17 +179,17 @@ void Animation::load(Common::SeekableReadStream *s, Type type) {
break;
case kTypeVaria:
- frames_count = s->readByte();
+ frames_count = s.readByte();
debug(1, "loading varia resource, %u physical frames", frames_count);
uint16 offset[255];
for (byte i = 0; i < frames_count; ++i) {
- offset[i] = s->readUint16LE();
+ offset[i] = s.readUint16LE();
//debug(0, "%u: %04x", i, offset[i]);
}
frames = new Surface[frames_count];
for (uint16 i = 0; i < frames_count; ++i) {
//debug(0, "%04x", offset[i]);
- s->seek(offset[i] + off);
+ s.seek(offset[i] + off);
frames[i].load(s, Surface::kTypeOns);
}
diff --git a/engines/teenagent/animation.h b/engines/teenagent/animation.h
index e98bb42ea0..d9092d1707 100644
--- a/engines/teenagent/animation.h
+++ b/engines/teenagent/animation.h
@@ -35,7 +35,7 @@ public:
enum Type {kTypeLan, kTypeVaria, kTypeInventory};
Animation();
- void load(Common::SeekableReadStream *s, Type type = kTypeLan);
+ void load(Common::SeekableReadStream&, Type type = kTypeLan);
void free();
Surface *firstFrame();
diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp
index 72a338664b..fa5a578636 100644
--- a/engines/teenagent/detection.cpp
+++ b/engines/teenagent/detection.cpp
@@ -177,9 +177,8 @@ public:
ssd.setDeletableFlag(true);
//checking for the thumbnail
- Common::ScopedPtr<Graphics::Surface> thumb(new Graphics::Surface);
- if (Graphics::loadThumbnail(*in, *thumb))
- ssd.setThumbnail(thumb.release());
+ if (Graphics::Surface *const thumb = Graphics::loadThumbnail(*in))
+ ssd.setThumbnail(thumb);
return ssd;
}
diff --git a/engines/teenagent/font.h b/engines/teenagent/font.h
index 773edaf4e2..5146ace21f 100644
--- a/engines/teenagent/font.h
+++ b/engines/teenagent/font.h
@@ -47,4 +47,3 @@ private:
} // End of namespace TeenAgent
#endif
-
diff --git a/engines/teenagent/inventory.cpp b/engines/teenagent/inventory.cpp
index 4951b2d940..2b858bbb4d 100644
--- a/engines/teenagent/inventory.cpp
+++ b/engines/teenagent/inventory.cpp
@@ -43,7 +43,7 @@ Inventory::Inventory(TeenAgentEngine *engine) {
if (!s)
error("no inventory background");
debug(0, "loading inventory background...");
- _background.load(s, Surface::kTypeOns);
+ _background.load(*s, Surface::kTypeOns);
}
uint32 items_size = varia.getSize(4);
@@ -300,13 +300,13 @@ void Inventory::Item::load(Inventory *inventory, uint item_id) {
if (_animation.empty()) {
debug(0, "loading item %d from offset %x", obj->id, inventory->_offset[obj->id - 1]);
Common::MemoryReadStream s(inventory->_items + inventory->_offset[obj->id - 1], inventory->_offset[obj->id] - inventory->_offset[obj->id - 1]);
- _animation.load(&s, Animation::kTypeInventory);
+ _animation.load(s, Animation::kTypeInventory);
}
} else {
if (_surface.empty()) {
debug(0, "loading item %d from offset %x", obj->id, inventory->_offset[obj->id - 1]);
Common::MemoryReadStream s(inventory->_items + inventory->_offset[obj->id - 1], inventory->_offset[obj->id] - inventory->_offset[obj->id - 1]);
- _surface.load(&s, Surface::kTypeOns);
+ _surface.load(s, Surface::kTypeOns);
}
}
}
diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp
index 4be6c9c31a..39b77ea447 100644
--- a/engines/teenagent/scene.cpp
+++ b/engines/teenagent/scene.cpp
@@ -57,7 +57,7 @@ Scene::Scene(TeenAgentEngine *engine, OSystem *system) : intro(false), _id(0), o
if (!s)
error("invalid resource data");
- teenagent.load(s, Animation::kTypeVaria);
+ teenagent.load(*s, Animation::kTypeVaria);
if (teenagent.empty())
error("invalid mark animation");
@@ -65,7 +65,7 @@ Scene::Scene(TeenAgentEngine *engine, OSystem *system) : intro(false), _id(0), o
if (!s)
error("invalid resource data");
- teenagent_idle.load(s, Animation::kTypeVaria);
+ teenagent_idle.load(*s, Animation::kTypeVaria);
if (teenagent_idle.empty())
error("invalid mark animation");
@@ -340,7 +340,7 @@ void Scene::loadOns() {
for (uint32 i = 0; i < ons_count; ++i) {
Common::ScopedPtr<Common::SeekableReadStream> s(res->ons.getStream(on_id[i]));
if (s) {
- ons[i].load(s, Surface::kTypeOns);
+ ons[i].load(*s, Surface::kTypeOns);
}
}
}
@@ -363,7 +363,7 @@ void Scene::loadLans() {
Common::ScopedPtr<Common::SeekableReadStream> s(res->loadLan000(res_id));
if (s) {
- animation[i].load(s, Animation::kTypeLan);
+ animation[i].load(*s, Animation::kTypeLan);
if (bxv != 0 && bxv != 0xff)
animation[i].id = bxv;
}
@@ -412,7 +412,7 @@ void Scene::init(int id, const Common::Point &pos) {
sub_hack = 2;
}
}
- on.load(stream, SurfaceList::kTypeOn, sub_hack);
+ on.load(*stream, SurfaceList::kTypeOn, sub_hack);
loadOns();
loadLans();
@@ -434,7 +434,7 @@ void Scene::playAnimation(byte idx, uint id, bool loop, bool paused, bool ignore
if (!s)
error("playing animation %u failed", id);
- custom_animation[idx].load(s);
+ custom_animation[idx].load(*s);
custom_animation[idx].loop = loop;
custom_animation[idx].paused = paused;
custom_animation[idx].ignore = ignore;
@@ -446,7 +446,7 @@ void Scene::playActorAnimation(uint id, bool loop, bool ignore) {
if (!s)
error("playing animation %u failed", id);
- actor_animation.load(s);
+ actor_animation.load(*s);
actor_animation.loop = loop;
actor_animation.ignore = ignore;
actor_animation.id = id;
diff --git a/engines/teenagent/surface.cpp b/engines/teenagent/surface.cpp
index 2e23c7a8ed..e8b5a8ad59 100644
--- a/engines/teenagent/surface.cpp
+++ b/engines/teenagent/surface.cpp
@@ -33,26 +33,26 @@ Surface::~Surface() {
free();
}
-void Surface::load(Common::SeekableReadStream *stream, Type type) {
+void Surface::load(Common::SeekableReadStream &stream, Type type) {
//debug(0, "load()");
free();
x = y = 0;
- uint16 w_ = stream->readUint16LE();
- uint16 h_ = stream->readUint16LE();
+ uint16 w_ = stream.readUint16LE();
+ uint16 h_ = stream.readUint16LE();
if (type != kTypeLan) {
- uint16 pos = stream->readUint16LE();
+ uint16 pos = stream.readUint16LE();
x = pos % 320;
y = pos / 320;
}
//debug(0, "declared info: %ux%u (%04xx%04x) -> %u,%u", w_, h_, w_, h_, x, y);
- if (stream->eos() || w_ == 0)
+ if (stream.eos() || w_ == 0)
return;
- if (w_ * h_ > stream->size()) {
+ if (w_ * h_ > stream.size()) {
debug(0, "invalid surface %ux%u -> %u,%u", w_, h_, x, y);
return;
}
@@ -60,7 +60,7 @@ void Surface::load(Common::SeekableReadStream *stream, Type type) {
//debug(0, "creating surface %ux%u -> %u,%u", w_, h_, x, y);
create(w_, h_, Graphics::PixelFormat::createFormatCLUT8());
- stream->read(pixels, w_ * h_);
+ stream.read(pixels, w_ * h_);
}
Common::Rect Surface::render(Graphics::Surface *surface, int dx, int dy, bool mirror, Common::Rect src_rect, uint zoom) const {
diff --git a/engines/teenagent/surface.h b/engines/teenagent/surface.h
index 5f74176c68..64e45a7330 100644
--- a/engines/teenagent/surface.h
+++ b/engines/teenagent/surface.h
@@ -40,7 +40,7 @@ public:
Surface();
~Surface();
- void load(Common::SeekableReadStream *stream, Type type);
+ void load(Common::SeekableReadStream&, Type type);
Common::Rect render(Graphics::Surface *surface, int dx = 0, int dy = 0, bool mirror = false, Common::Rect src_rect = Common::Rect(), uint zoom = 256) const;
bool empty() const { return pixels == NULL; }
diff --git a/engines/teenagent/surface_list.cpp b/engines/teenagent/surface_list.cpp
index e98153a935..7f7eb1dc38 100644
--- a/engines/teenagent/surface_list.cpp
+++ b/engines/teenagent/surface_list.cpp
@@ -31,11 +31,11 @@ SurfaceList::~SurfaceList() {
free();
}
-void SurfaceList::load(Common::SeekableReadStream *stream, Type type, int sub_hack) {
+void SurfaceList::load(Common::SeekableReadStream &stream, Type type, int sub_hack) {
free();
- byte fn = stream->readByte();
- if (stream->eos())
+ byte fn = stream.readByte();
+ if (stream.eos())
return;
surfaces_n = fn - sub_hack;
@@ -47,11 +47,11 @@ void SurfaceList::load(Common::SeekableReadStream *stream, Type type, int sub_ha
surfaces = new Surface[surfaces_n];
for (byte i = 0; i < surfaces_n; ++i) {
- uint offset = stream->readUint16LE();
- uint pos = stream->pos();
- stream->seek(offset);
+ uint offset = stream.readUint16LE();
+ uint pos = stream.pos();
+ stream.seek(offset);
surfaces[i].load(stream, Surface::kTypeOns);
- stream->seek(pos);
+ stream.seek(pos);
}
}
diff --git a/engines/teenagent/surface_list.h b/engines/teenagent/surface_list.h
index d949a722d6..fcb4fb25c5 100644
--- a/engines/teenagent/surface_list.h
+++ b/engines/teenagent/surface_list.h
@@ -33,7 +33,7 @@ public:
SurfaceList();
~SurfaceList();
- void load(Common::SeekableReadStream *stream, Type type, int sub_hack = 0);
+ void load(Common::SeekableReadStream&, Type type, int sub_hack = 0);
void free();
void render(Graphics::Surface *surface, const Common::Rect & clip) const;
@@ -45,4 +45,3 @@ protected:
}
#endif
-
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
index 0289b994e6..e6a248334c 100644
--- a/engines/teenagent/teenagent.cpp
+++ b/engines/teenagent/teenagent.cpp
@@ -386,7 +386,7 @@ bool TeenAgentEngine::showLogo() {
}
Surface s;
- s.load(frame, Surface::kTypeOns);
+ s.load(*frame, Surface::kTypeOns);
if (s.empty()) {
free(bg);
return true;
diff --git a/engines/testbed/misc.cpp b/engines/testbed/misc.cpp
index 034d3eb27e..aee3ccd294 100644
--- a/engines/testbed/misc.cpp
+++ b/engines/testbed/misc.cpp
@@ -110,7 +110,7 @@ TestExitStatus MiscTests::testDateTime() {
TestExitStatus MiscTests::testTimers() {
int valToModify = 0;
- if (g_system->getTimerManager()->installTimerProc(timerCallback, 100000, &valToModify)) {
+ if (g_system->getTimerManager()->installTimerProc(timerCallback, 100000, &valToModify, "testbedTimer")) {
g_system->delayMillis(150);
g_system->getTimerManager()->removeTimerProc(timerCallback);
@@ -133,7 +133,7 @@ TestExitStatus MiscTests::testMutexes() {
SharedVars sv = {1, 1, true, g_system->createMutex()};
- if (g_system->getTimerManager()->installTimerProc(criticalSection, 100000, &sv)) {
+ if (g_system->getTimerManager()->installTimerProc(criticalSection, 100000, &sv, "testbedMutex")) {
g_system->delayMillis(150);
}
diff --git a/engines/tinsel/adpcm.cpp b/engines/tinsel/adpcm.cpp
index 4ea835586b..ca3150ca3d 100644
--- a/engines/tinsel/adpcm.cpp
+++ b/engines/tinsel/adpcm.cpp
@@ -61,7 +61,7 @@ void Tinsel_ADPCMStream::readBufferTinselHeader() {
int16 Tinsel_ADPCMStream::decodeTinsel(int16 code, double eVal) {
double sample;
- sample = (double) code;
+ sample = (double)code;
sample *= eVal * _status.predictor;
sample += (_status.d0 * _status.K0) + (_status.d1 * _status.K1);
diff --git a/engines/tinsel/coroutine.cpp b/engines/tinsel/coroutine.cpp
index 998d98b52a..ef0097f043 100644
--- a/engines/tinsel/coroutine.cpp
+++ b/engines/tinsel/coroutine.cpp
@@ -80,4 +80,3 @@ CoroBaseContext::~CoroBaseContext() {
}
} // End of namespace Tinsel
-
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 9c52305a1c..1fce032633 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -322,9 +322,21 @@ int TinselMetaEngine::getMaximumSaveSlot() const { return 99; }
void TinselMetaEngine::removeSaveState(const char *target, int slot) const {
Tinsel::setNeedLoad();
- Tinsel::getList(g_system->getSavefileManager(), target);
+ // Same issue here as with loadGameState(): we need the physical savegame
+ // slot. Refer to bug #3387551.
+ int listSlot = -1;
+ const int numStates = Tinsel::getList(g_system->getSavefileManager(), target);
+ for (int i = 0; i < numStates; ++i) {
+ const char *fileName = Tinsel::ListEntry(i, Tinsel::LE_NAME);
+ const int saveSlot = atoi(fileName + strlen(fileName) - 3);
+
+ if (saveSlot == slot) {
+ listSlot = i;
+ break;
+ }
+ }
- g_system->getSavefileManager()->removeSavefile(Tinsel::ListEntry(slot, Tinsel::LE_NAME));
+ g_system->getSavefileManager()->removeSavefile(Tinsel::ListEntry(listSlot, Tinsel::LE_NAME));
Tinsel::setNeedLoad();
Tinsel::getList(g_system->getSavefileManager(), target);
}
diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h
index 116322aa89..bea0938fad 100644
--- a/engines/tinsel/detection_tables.h
+++ b/engines/tinsel/detection_tables.h
@@ -214,7 +214,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -236,7 +236,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::IT_ITA,
Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
+ ADGF_DROPLANGUAGE | ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -261,7 +261,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::FR_FRA,
Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
+ ADGF_DROPLANGUAGE | ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -285,7 +285,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::DE_DEU,
Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
+ ADGF_DROPLANGUAGE | ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -308,7 +308,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::IT_ITA,
Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
+ ADGF_DROPLANGUAGE | ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -331,7 +331,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::ES_ESP,
Common::kPlatformPC,
- ADGF_DROPLANGUAGE,
+ ADGF_DROPLANGUAGE | ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -351,7 +351,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -371,7 +371,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::HE_ISR,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -390,7 +390,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPSX,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -434,7 +434,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -456,7 +456,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformMacintosh,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -475,7 +475,7 @@ static const TinselGameDescription gameDescriptions[] = {
AD_ENTRY1s("dw.scn", "6182c7986eaec893c62fb6ea13a9f225", 774556),
Common::DE_DEU,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_DW1,
@@ -496,7 +496,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
Common::RU_RUS,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD,
GUIO_NONE
},
GID_DW1,
diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp
index 7a973ba4be..4ac172be43 100644
--- a/engines/tinsel/saveload.cpp
+++ b/engines/tinsel/saveload.cpp
@@ -154,8 +154,15 @@ static bool syncSaveGameHeader(Common::Serializer &s, SaveGameHeader &hdr) {
syncTime(s, hdr.dateTime);
int tmp = hdr.size - s.bytesSynced();
+
+ // NOTE: We can't use SAVEGAME_ID here when attempting to remove a saved game from the launcher,
+ // as there is no TinselEngine initialized then. This means that we can't check if this is a DW1
+ // or DW2 savegame in this case, but it doesn't really matter, as the saved game is about to be
+ // deleted anyway. Refer to bug #3387551.
+ bool correctID = _vm ? (hdr.id == SAVEGAME_ID) : (hdr.id == DW1_SAVEGAME_ID || hdr.id == DW2_SAVEGAME_ID);
+
// Perform sanity check
- if (tmp < 0 || hdr.id != SAVEGAME_ID || hdr.ver > CURRENT_VER || hdr.size > 1024)
+ if (tmp < 0 || !correctID || hdr.ver > CURRENT_VER || hdr.size > 1024)
return false;
// Skip over any extra bytes
s.skip(tmp);
diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp
index bf48dd1511..130928d885 100644
--- a/engines/tinsel/sound.cpp
+++ b/engines/tinsel/sound.cpp
@@ -41,8 +41,9 @@
#include "audio/decoders/flac.h"
#include "audio/decoders/mp3.h"
#include "audio/decoders/raw.h"
-#include "audio/decoders/vag.h"
#include "audio/decoders/vorbis.h"
+#include "audio/decoders/xa.h"
+
#include "gui/message.h"
@@ -106,8 +107,8 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound
error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage));
if (TinselV1PSX) {
- // Read the stream and create a VAG Audio stream
- Audio::AudioStream *vagStream = Audio::makeVagStream(_sampleStream.readStream(sampleLen), 44100);
+ // Read the stream and create a XA ADPCM audio stream
+ Audio::AudioStream *xaStream = Audio::makeXAStream(_sampleStream.readStream(sampleLen), 44100);
// FIXME: Should set this in a different place ;)
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _vm->_config->_soundVolume);
@@ -115,7 +116,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _vm->_config->_voiceVolume);
// Play the audio stream
- _vm->_mixer->playStream(type, &curChan.handle, vagStream);
+ _vm->_mixer->playStream(type, &curChan.handle, xaStream);
} else {
// allocate a buffer
byte *sampleBuf = (byte *)malloc(sampleLen);
diff --git a/engines/tinsel/strres.h b/engines/tinsel/strres.h
index a63824a863..f6e86951b6 100644
--- a/engines/tinsel/strres.h
+++ b/engines/tinsel/strres.h
@@ -96,4 +96,3 @@ SCNHANDLE LanguageFlag(LANGUAGE thisOne);
} // End of namespace Tinsel
#endif
-
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index 30b060766e..e18216cdf7 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -31,9 +31,6 @@
#include "common/random.h"
#include "common/util.h"
-#include "audio/mididrv.h"
-#include "audio/mixer.h"
-
#include "engines/engine.h"
#include "tinsel/debugger.h"
#include "tinsel/graphics.h"
@@ -53,6 +50,7 @@ namespace Tinsel {
class BMVPlayer;
class Config;
+class MidiDriver;
class MidiMusicPlayer;
class PCMMusicPlayer;
class Scheduler;
diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp
index 0bf3316209..4a4a84e62c 100644
--- a/engines/toon/audio.cpp
+++ b/engines/toon/audio.cpp
@@ -613,4 +613,3 @@ void AudioManager::updateAmbientSFX()
}
} // End of namespace Toon
-
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index 022214157a..7d9a31c170 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -1109,4 +1109,3 @@ void Character::updateIdle() {
}
}
} // End of namespace Toon
-
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index 810a37720a..ac4caae8b2 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -224,12 +224,7 @@ SaveStateDescriptor ToonMetaEngine::querySaveMetaInfos(const char *target, int s
SaveStateDescriptor desc(slot, saveName);
- Graphics::Surface *thumbnail = new Graphics::Surface();
- assert(thumbnail);
- if (!Graphics::loadThumbnail(*file, *thumbnail)) {
- delete thumbnail;
- thumbnail = 0;
- }
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*file);
desc.setThumbnail(thumbnail);
desc.setDeletableFlag(true);
diff --git a/engines/toon/drew.cpp b/engines/toon/drew.cpp
index 89438fb35c..df5cfcfa03 100644
--- a/engines/toon/drew.cpp
+++ b/engines/toon/drew.cpp
@@ -129,4 +129,3 @@ void CharacterDrew::resetScale()
setPosition(_x, _y);
}
} // End of namespace Toon
-
diff --git a/engines/toon/hotspot.cpp b/engines/toon/hotspot.cpp
index 62458ad800..ee81b87417 100644
--- a/engines/toon/hotspot.cpp
+++ b/engines/toon/hotspot.cpp
@@ -149,4 +149,3 @@ HotspotData *Hotspots::Get(int32 id) {
}
} // End of namespace Toon
-
diff --git a/engines/toon/path.cpp b/engines/toon/path.cpp
index 43a134e39b..60ca007930 100644
--- a/engines/toon/path.cpp
+++ b/engines/toon/path.cpp
@@ -28,54 +28,69 @@ namespace Toon {
PathFindingHeap::PathFindingHeap() {
_count = 0;
- _alloc = 0;
+ _size = 0;
_data = NULL;
}
PathFindingHeap::~PathFindingHeap() {
- delete[] _data;
+ free(_data);
}
-int32 PathFindingHeap::init(int32 size) {
+void PathFindingHeap::init(int32 size) {
debugC(1, kDebugPath, "init(%d)", size);
+ _size = size;
- delete[] _data;
- _data = new HeapDataGrid[size * 2];
- memset(_data, 0, sizeof(HeapDataGrid) * size * 2);
+ free(_data);
+ _data = (HeapDataGrid *)malloc(sizeof(HeapDataGrid) * _size);
+ memset(_data, 0, sizeof(HeapDataGrid) * _size);
_count = 0;
- _alloc = size;
- return size;
}
-int32 PathFindingHeap::unload() {
- delete[] _data;
+void PathFindingHeap::unload() {
+ _count = 0;
+ _size = 0;
+ free(_data);
_data = NULL;
- return 0;
}
-int32 PathFindingHeap::clear() {
- //debugC(1, kDebugPath, "clear()");
+void PathFindingHeap::clear() {
+ debugC(1, kDebugPath, "clear()");
_count = 0;
- memset(_data, 0, sizeof(HeapDataGrid) * _alloc * 2);
- return 1;
+ memset(_data, 0, sizeof(HeapDataGrid) * _size);
}
-int32 PathFindingHeap::push(int32 x, int32 y, int32 weight) {
- //debugC(6, kDebugPath, "push(%d, %d, %d)", x, y, weight);
+void PathFindingHeap::push(int32 x, int32 y, int32 weight) {
+ debugC(2, kDebugPath, "push(%d, %d, %d)", x, y, weight);
+
+ if (_count == _size) {
+ // Increase size by 50%
+ int newSize = _size + (_size >> 1) + 1;
+ HeapDataGrid *newData;
+
+ newData = (HeapDataGrid *)realloc(_data, sizeof(HeapDataGrid) * newSize);
+ if (newData == NULL) {
+ warning("Aborting attempt to push onto PathFindingHeap at maximum size: %d", _count);
+ return;
+ }
+
+ memset(newData + _size, 0, sizeof(HeapDataGrid) * (newSize - _size));
+ _data = newData;
+ _size = newSize;
+ }
- _count++;
_data[_count]._x = x;
_data[_count]._y = y;
_data[_count]._weight = weight;
+ _count++;
- int32 lMax = _count;
+ int32 lMax = _count-1;
int32 lT = 0;
while (1) {
- lT = lMax / 2;
- if (lT < 1)
+ if (lMax <= 0)
break;
+ lT = (lMax-1) / 2;
if (_data[lT]._weight > _data[lMax]._weight) {
HeapDataGrid temp;
@@ -87,31 +102,31 @@ int32 PathFindingHeap::push(int32 x, int32 y, int32 weight) {
break;
}
}
- return 1;
}
-int32 PathFindingHeap::pop(int32 *x, int32 *y, int32 *weight) {
- //debugC(6, kDebugPath, "pop(x, y, weight)");
+void PathFindingHeap::pop(int32 *x, int32 *y, int32 *weight) {
+ debugC(2, kDebugPath, "pop(x, y, weight)");
- if (!_count)
- return 0;
+ if (!_count) {
+ warning("Attempt to pop empty PathFindingHeap!");
+ return;
+ }
- *x = _data[1]._x;
- *y = _data[1]._y;
- *weight = _data[1]._weight;
+ *x = _data[0]._x;
+ *y = _data[0]._y;
+ *weight = _data[0]._weight;
- _data[1] = _data[_count];
- _count--;
+ _data[0] = _data[--_count];
if (!_count)
- return 0;
+ return;
- int32 lMin = 1;
- int32 lT = 1;
+ int32 lMin = 0;
+ int32 lT = 0;
while (1) {
- lT = lMin << 1;
- if (lT <= _count) {
- if (lT < _count) {
+ lT = (lMin << 1) + 1;
+ if (lT < _count) {
+ if (lT < _count-1) {
if (_data[lT + 1]._weight < _data[lT]._weight)
lT++;
}
@@ -129,7 +144,6 @@ int32 PathFindingHeap::pop(int32 *x, int32 *y, int32 *weight) {
break;
}
}
- return 0;
}
PathFinding::PathFinding(ToonEngine *vm) : _vm(vm) {
@@ -164,7 +178,7 @@ bool PathFinding::isLikelyWalkable(int32 x, int32 y) {
}
bool PathFinding::isWalkable(int32 x, int32 y) {
- //debugC(6, kDebugPath, "isWalkable(%d, %d)", x, y);
+ debugC(2, kDebugPath, "isWalkable(%d, %d)", x, y);
bool maskWalk = (_currentMask->getData(x, y) & 0x1f) > 0;
@@ -299,7 +313,7 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) {
_heap->push(curX, curY, abs(destx - x) + abs(desty - y));
int wei = 0;
- while (_heap->_count) {
+ while (_heap->getCount()) {
wei = 0;
_heap->pop(&curX, &curY, &curWeight);
int curNode = curX + curY * _width;
@@ -424,11 +438,7 @@ void PathFinding::init(Picture *mask) {
_height = mask->getHeight();
_currentMask = mask;
_heap->unload();
- // 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
+ _heap->init(500);
delete[] _gridTemp;
_gridTemp = new int32[_width*_height];
}
diff --git a/engines/toon/path.h b/engines/toon/path.h
index 329127c9ce..2de58064f0 100644
--- a/engines/toon/path.h
+++ b/engines/toon/path.h
@@ -38,17 +38,18 @@ public:
PathFindingHeap();
~PathFindingHeap();
- int32 _alloc;
- int32 _count;
-
- int32 push(int32 x, int32 y, int32 weight);
- int32 pop(int32 *x, int32 *y, int32 *weight);
- int32 init(int32 size);
- int32 clear();
- int32 unload();
+ void push(int32 x, int32 y, int32 weight);
+ void pop(int32 *x, int32 *y, int32 *weight);
+ void init(int32 size);
+ void clear();
+ void unload();
+ int32 getCount() { return _count; }
private:
HeapDataGrid *_data;
+
+ int32 _size;
+ int32 _count;
};
class PathFinding {
diff --git a/engines/toon/script.cpp b/engines/toon/script.cpp
index eed781295a..69ae727bb5 100644
--- a/engines/toon/script.cpp
+++ b/engines/toon/script.cpp
@@ -502,4 +502,3 @@ void EMCInterpreter::loadState(EMCState *script, Common::ReadStream *stream) {
}
} // End of namespace Toon
-
diff --git a/engines/toon/script.h b/engines/toon/script.h
index 9dd00dca80..8ef085f383 100644
--- a/engines/toon/script.h
+++ b/engines/toon/script.h
@@ -148,4 +148,3 @@ private:
} // End of namespace Toon
#endif
-
diff --git a/engines/tsage/blue_force/blueforce_logic.cpp b/engines/tsage/blue_force/blueforce_logic.cpp
new file mode 100644
index 0000000000..60bbddbabc
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_logic.cpp
@@ -0,0 +1,785 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "tsage/blue_force/blueforce_logic.h"
+#include "tsage/blue_force/blueforce_scenes0.h"
+#include "tsage/blue_force/blueforce_scenes1.h"
+#include "tsage/blue_force/blueforce_scenes3.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/graphics.h"
+#include "tsage/staticres.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+void BlueForceGame::start() {
+ // Start the game
+ _globals->_sceneManager.changeScene(300);
+
+ _globals->_events.setCursor(CURSOR_WALK);
+}
+
+Scene *BlueForceGame::createScene(int sceneNumber) {
+ switch (sceneNumber) {
+ /* Scene Group #0 */
+ case 20:
+ // Tsunami Title Screen
+ return new Scene20();
+ case 50:
+ return new Scene50();
+ case 60:
+ error("Scene group 0 not implemented");
+ /* Scene Group #1 */
+ case 100:
+ // Tsnunami Title Screen #2
+ return new Scene100();
+ case 109:
+ // Introduction Bar Room
+ return new Scene109();
+ case 110:
+
+ case 114:
+ case 115:
+ case 125:
+ case 140:
+ case 150:
+ case 160:
+ case 180:
+ case 190:
+ error("Scene group 1 not implemented");
+ case 200:
+ case 210:
+ case 220:
+ case 225:
+ case 265:
+ case 270:
+ case 271:
+ case 280:
+ error("Scene group 2 not implemented");
+ case 300:
+ // Outside Police Station
+ return new Scene300();
+ case 315:
+ case 325:
+ case 330:
+ case 340:
+ case 342:
+ case 350:
+ case 355:
+ case 360:
+ case 370:
+ case 380:
+ case 385:
+ case 390:
+ error("Scene group 3 not implemented");
+ case 410:
+ case 415:
+ case 440:
+ case 450:
+ error("Scene group 4 not implemented");
+ case 550:
+ case 551:
+ case 560:
+ case 570:
+ case 580:
+ case 590:
+ error("Scene group 5 not implemented");
+ case 600:
+ case 620:
+ case 666:
+ case 690:
+ error("Scene group 6 not implemented");
+ case 710:
+ error("Scene group 7 not implemented");
+ case 800:
+ case 810:
+ case 820:
+ case 830:
+ case 840:
+ case 850:
+ case 860:
+ case 870:
+ case 880:
+ error("Scene group 8 not implemented");
+ case 900:
+ case 910:
+ case 920:
+ case 930:
+ case 935:
+ case 940:
+ error("Scene group 9 not implemented");
+ default:
+ error("Unknown scene number - %d", sceneNumber);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+AObjectArray::AObjectArray(): EventHandler() {
+ _inUse = false;
+ clear();
+}
+
+void AObjectArray::clear() {
+ for (int i = 0; i < OBJ_ARRAY_SIZE; ++i)
+ _objList[i] = NULL;
+}
+
+void AObjectArray::synchronize(Serializer &s) {
+ EventHandler::synchronize(s);
+ for (int i = 0; i < OBJ_ARRAY_SIZE; ++i)
+ SYNC_POINTER(_objList[i]);
+}
+
+void AObjectArray::process(Event &event) {
+ if (_inUse)
+ error("Array error");
+ _inUse = true;
+
+ for (int i = 0; i < OBJ_ARRAY_SIZE; ++i) {
+ if (_objList[i])
+ _objList[i]->process(event);
+ }
+
+ _inUse = false;
+}
+
+void AObjectArray::dispatch() {
+ if (_inUse)
+ error("Array error");
+ _inUse = true;
+
+ for (int i = 0; i < OBJ_ARRAY_SIZE; ++i) {
+ if (_objList[i])
+ _objList[i]->dispatch();
+ }
+
+ _inUse = false;
+}
+
+int AObjectArray::getNewIndex() {
+ for (int i = 0; i < OBJ_ARRAY_SIZE; ++i) {
+ if (!_objList[i])
+ return i;
+ }
+ error("AObjectArray too full.");
+}
+
+void AObjectArray::add(EventHandler *obj) {
+ int idx = getNewIndex();
+ _objList[idx] = obj;
+}
+
+void AObjectArray::remove(EventHandler *obj) {
+ for (int i = 0; i < OBJ_ARRAY_SIZE; ++i) {
+ if (_objList[i] == obj) {
+ _objList[i] = NULL;
+ return;
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Timer::Timer() {
+ _endFrame = 0;
+ _endAction = NULL;
+ _tickAction = NULL;
+}
+
+void Timer::remove() {
+ _endFrame = 0;
+ _endAction = NULL;
+
+ ((Scene100 *)BF_GLOBALS._sceneManager._scene)->removeTimer(this);
+}
+
+void Timer::synchronize(Serializer &s) {
+ EventHandler::synchronize(s);
+ SYNC_POINTER(_tickAction);
+ SYNC_POINTER(_endAction);
+ s.syncAsUint32LE(_endFrame);
+}
+
+void Timer::signal() {
+ assert(_endAction);
+ Action *action = _endAction;
+ remove();
+ action->signal();
+}
+
+void Timer::dispatch() {
+ if (_tickAction)
+ _tickAction->dispatch();
+
+ if (_endFrame) {
+ uint32 frameNumber = BF_GLOBALS._events.getFrameNumber();
+ if (frameNumber > _endFrame)
+ // Timer has expired
+ signal();
+ }
+}
+
+void Timer::set(uint32 delay, Action *endAction) {
+ assert(delay != 0);
+
+ _endFrame = BF_GLOBALS._sceneHandler->getFrameDifference() + delay;
+ _endAction = endAction;
+
+ ((SceneExt *)BF_GLOBALS._sceneManager._scene)->addTimer(this);
+}
+
+/*--------------------------------------------------------------------------*/
+
+TimerExt::TimerExt(): Timer() {
+ _action = NULL;
+}
+
+void TimerExt::set(uint32 delay, Action *endAction, Action *newAction) {
+ _newAction = newAction;
+ Timer::set(delay, endAction);
+}
+
+void TimerExt::synchronize(Serializer &s) {
+ EventHandler::synchronize(s);
+ SYNC_POINTER(_action);
+}
+
+void TimerExt::remove() {
+ _action = NULL;
+ remove();
+}
+
+void TimerExt::signal() {
+ Action *endAction = _endAction;
+ Action *newAction = _newAction;
+ remove();
+
+ // If the end action doesn't have an action anymore, set it to the specified new action
+ assert(endAction);
+ if (!endAction->_action)
+ endAction->setAction(newAction);
+}
+
+void TimerExt::dispatch() {
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SceneItemType2::startMove(SceneObject *sceneObj, va_list va) {
+}
+
+/*--------------------------------------------------------------------------*/
+
+void NamedObject::postInit(SceneObjectList *OwnerList) {
+ _lookLineNum = _talkLineNum = _useLineNum = -1;
+ SceneObject::postInit();
+}
+
+void NamedObject::synchronize(Serializer &s) {
+ SceneObject::synchronize(s);
+ s.syncAsSint16LE(_resNum);
+ s.syncAsSint16LE(_lookLineNum);
+ s.syncAsSint16LE(_talkLineNum);
+ s.syncAsSint16LE(_useLineNum);
+}
+
+void NamedObject::setup(int resNum, int lookLineNum, int talkLineNum, int useLineNum, int mode, SceneItem *item) {
+ _resNum = resNum;
+ _lookLineNum = lookLineNum;
+ _talkLineNum = talkLineNum;
+ _useLineNum = useLineNum;
+
+ switch (mode) {
+ case 2:
+ _globals->_sceneItems.push_front(this);
+ break;
+ case 4:
+ _globals->_sceneItems.addBefore(item, this);
+ break;
+ case 5:
+ _globals->_sceneItems.addAfter(item, this);
+ break;
+ default:
+ _globals->_sceneItems.push_back(this);
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+CountdownObject::CountdownObject(): NamedObject() {
+ _countDown = 0;
+}
+
+void CountdownObject::synchronize(Serializer &s) {
+ SceneObject::synchronize(s);
+ s.syncAsSint16LE(_countDown);
+}
+
+void CountdownObject::dispatch() {
+ int frameNum = _frame;
+ SceneObject::dispatch();
+
+ if ((frameNum != _frame) && (_countDown > 0)) {
+ if (--_countDown == 0) {
+ animate(ANIM_MODE_NONE, 0);
+ _frame = 1;
+ }
+ }
+}
+
+void CountdownObject::fixCountdown(int mode, ...) {
+ if (mode == 8) {
+ va_list va;
+ va_start(va, mode);
+
+ _countDown = va_arg(va, int);
+ animate(ANIM_MODE_8, _countDown, NULL);
+ va_end(va);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+FollowerObject::FollowerObject(): NamedObject() {
+ _object = NULL;
+}
+
+void FollowerObject::synchronize(Serializer &s) {
+ NamedObject::synchronize(s);
+ SYNC_POINTER(_object);
+}
+
+void FollowerObject::remove() {
+ NamedObject::remove();
+ _object = NULL;
+}
+
+void FollowerObject::dispatch() {
+ SceneObject::dispatch();
+ assert(_object);
+
+ if ((_object->_flags & OBJFLAG_HIDE) || ((_object->_visage != 307) &&
+ ((_object->_visage != 308) || (_object->_strip != 1)))) {
+ hide();
+ } else if ((_object->_visage != 308) || (_object->_strip != 1)) {
+ show();
+ setStrip(_object->_strip);
+ setPosition(_object->_position, _object->_yDiff);
+ }
+}
+
+void FollowerObject::reposition() {
+ assert(_object);
+ setStrip(_object->_strip);
+ setPosition(_object->_position, _object->_yDiff);
+ reposition();
+}
+
+void FollowerObject::setup(SceneObject *object, int visage, int frameNum, int yDiff) {
+ SceneObject::postInit();
+ _object = object;
+ _yDiff = yDiff;
+ setVisage(visage);
+ setFrame(frameNum);
+
+ dispatch();
+}
+
+/*--------------------------------------------------------------------------*/
+
+SceneExt::SceneExt(): Scene() {
+ warning("TODO: dword_503AA/dword_503AE/dword_53030");
+
+ _field372 = 0;
+ _field37A = 0;
+ _eventHandler = NULL;
+}
+
+void SceneExt::postInit(SceneObjectList *OwnerList) {
+ Scene::postInit(OwnerList);
+ if (BF_GLOBALS._v4CEA2) {
+ // Blank out the bottom portion of the screen
+ BF_GLOBALS._interfaceY = BF_INTERFACE_Y;
+
+ Rect r(0, BF_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT);
+ BF_GLOBALS.gfxManager().getSurface().fillRect(r, 0);
+ }
+}
+
+void SceneExt::process(Event &event) {
+ _objArray2.process(event);
+ if (!event.handled)
+ Scene::process(event);
+}
+
+void SceneExt::dispatch() {
+ _timerList.dispatch();
+
+ if (_field37A) {
+ if ((--_field37A == 0) && BF_GLOBALS._v4CEA2) {
+ if (BF_GLOBALS._v4E238 && (BF_GLOBALS._v4CF9E == 1)) {
+ warning("sub_1B052");
+ }
+
+ _field37A = 0;
+ }
+ }
+
+ Scene::dispatch();
+}
+
+void SceneExt::loadScene(int sceneNum) {
+ Scene::loadScene(sceneNum);
+
+ _v51C34.top = 0;
+ _v51C34.bottom = 300;
+}
+
+/*--------------------------------------------------------------------------*/
+
+GameScene::GameScene() {
+
+}
+
+void GameScene::postInit(SceneObjectList *OwnerList) {
+ _field794 = 0;
+ _field412 = 1;
+ SceneExt::postInit(OwnerList);
+}
+
+void GameScene::remove() {
+ SceneExt::remove();
+ if (_field794 == 1) {
+ for (SynchronizedList<SceneObject *>::iterator i = BF_GLOBALS._sceneObjects->begin();
+ i != BF_GLOBALS._sceneObjects->end(); ++i)
+ (*i)->remove();
+
+ BF_GLOBALS._sceneObjects->draw();
+ BF_GLOBALS._scenePalette.loadPalette(2);
+ BF_GLOBALS._v51C44 = 1;
+ BF_GLOBALS._v51C42 = 1;
+ }
+
+ BF_GLOBALS._scenePalette._field412 = 1;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SceneHandlerExt::postInit(SceneObjectList *OwnerList) {
+ SceneHandler::postInit(OwnerList);
+
+ // Load the low end palette data
+ GLOBALS._scenePalette.loadPalette(2);
+ GLOBALS._scenePalette.refresh();
+}
+
+void SceneHandlerExt::process(Event &event) {
+ SceneHandler::process(event);
+
+ // TODO: All the new stuff from Blue Force
+}
+
+/*--------------------------------------------------------------------------*/
+
+VisualSpeaker::VisualSpeaker(): Speaker() {
+ _textWidth = 312;
+ _color1 = 19;
+ _hideObjects = false;
+ _removeObject1 = false;
+ _removeObject2 = false;
+ _field20E = 160;
+ _fontNumber = 4;
+ _color2 = 82;
+ _offsetPos = Common::Point(4, 170);
+ _numFrames = 0;
+}
+
+void VisualSpeaker::remove() {
+ if (_removeObject2)
+ _object2.remove();
+ if (_removeObject1)
+ _object1.remove();
+
+ Speaker::remove();
+}
+
+void VisualSpeaker::synchronize(Serializer &s) {
+ Speaker::synchronize(s);
+
+ s.syncAsByte(_removeObject1);
+ s.syncAsByte(_removeObject2);
+ s.syncAsSint16LE(_field20C);
+ s.syncAsSint16LE(_field20E);
+ s.syncAsSint16LE(_numFrames);
+ s.syncAsSint16LE(_offsetPos.x);
+ s.syncAsSint16LE(_offsetPos.y);
+}
+
+void VisualSpeaker::proc12(Action *action) {
+ Speaker::proc12(action);
+ _textPos = Common::Point(_offsetPos.x + BF_GLOBALS._sceneManager._scene->_sceneBounds.left,
+ _offsetPos.y + BF_GLOBALS._sceneManager._scene->_sceneBounds.top);
+ _numFrames = 0;
+}
+
+void VisualSpeaker::setText(const Common::String &msg) {
+ BF_GLOBALS._events.waitForPress();
+ _objectList.draw();
+
+ _sceneText._color1 = _color1;
+ _sceneText._color2 = _color2;
+ _sceneText._color3 = _color3;
+ _sceneText._width = _textWidth;
+ _sceneText._fontNumber = _fontNumber;
+ _sceneText._textMode = _textMode;
+ _sceneText.setup(msg);
+
+ // Get the string bounds
+ GfxFont f;
+ f.setFontNumber(_fontNumber);
+ Rect bounds;
+ f.getStringBounds(msg.c_str(), bounds, _textWidth);
+
+ // Set the position for the text
+ switch (_textMode) {
+ case ALIGN_LEFT:
+ case ALIGN_JUSTIFIED:
+ _sceneText.setPosition(_textPos);
+ break;
+ case ALIGN_CENTER:
+ _sceneText.setPosition(Common::Point(_textPos.x + (_textWidth - bounds.width()) / 2, _textPos.y));
+ break;
+ case ALIGN_RIGHT:
+ _sceneText.setPosition(Common::Point(_textPos.x + _textWidth - bounds.width(), _textPos.y));
+ break;
+ default:
+ break;
+ }
+
+ // Ensure the text is in the foreground
+ _sceneText.fixPriority(256);
+
+ // Count the number of words (by spaces) in the string
+ const char *s = msg.c_str();
+ int spaceCount = 0;
+ while (*s) {
+ if (*s++ == ' ')
+ ++spaceCount;
+ }
+
+ _numFrames = spaceCount * 3 + 2;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerSutter::SpeakerSutter() {
+ _speakerName = "SUTTER";
+ _color1 = 20;
+ _color2 = 22;
+ _textMode = ALIGN_CENTER;
+}
+
+void SpeakerSutter::setText(const Common::String &msg) {
+ _removeObject1 = _removeObject2 = true;
+
+ _object1.postInit();
+ _object1.setVisage(329);
+ _object1.setStrip2(2);
+ _object1.fixPriority(254);
+ _object1.changeZoom(100);
+ _object1.setPosition(Common::Point(BF_GLOBALS._sceneManager._scene->_sceneBounds.left + 45,
+ BF_GLOBALS._sceneManager._scene->_sceneBounds.top + 166));
+
+ _object2.postInit();
+ _object2.setVisage(329);
+ _object2.setStrip2(1);
+ _object2.fixPriority(255);
+ _object1.setPosition(Common::Point(BF_GLOBALS._sceneManager._scene->_sceneBounds.left + 45,
+ BF_GLOBALS._sceneManager._scene->_sceneBounds.top + 166));
+
+ VisualSpeaker::setText(msg);
+ _object2.fixCountdown(8, _numFrames);
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerDoug::SpeakerDoug(): VisualSpeaker() {
+ _color1 = 32;
+ _speakerName = "DOUG";
+}
+
+/*--------------------------------------------------------------------------*/
+
+SpeakerJakeNoHead::SpeakerJakeNoHead(): VisualSpeaker() {
+ _color1 = 13;
+ _speakerName = "JAKE_NO_HEAD";
+}
+
+/*--------------------------------------------------------------------------*/
+
+BlueForceInvObjectList::BlueForceInvObjectList():
+ _business_card(9, 4, 2, 0),
+ _lauras_sweater(9, 4, 3, 0),
+ _handcuffs(9, 1, 4, 0),
+ _magnum(9, 1, 5, 0),
+ _ticket_book(9, 1, 6, 0),
+ _miranda_card(9, 1, 7, 0),
+ _forest_follet(9, 1, 8, 0),
+ _bradford_id(9, 1, 9, 0),
+ _baseball_card(9, 1, 10, 0),
+ _slip_bradford(9, 1, 11, 0),
+ _flare(9, 1, 12, 0),
+ _rap_sheet(9, 1, 13, 0),
+ _cartridges(9, 1, 14, 0),
+ _rifle(9, 1, 15, 0),
+ _wig(9, 1, 16, 0),
+ _frankies_id(9, 1, 17, 0),
+ _tyrones_id(9, 1, 18, 0),
+ _pistol22(9, 1, 19, 0),
+ _unused(1, 1, 1, 0),
+ _slip_frankie(9, 2, 1, 0),
+ _slip_tyrone(9, 2, 2, 0),
+ _atf_teletype(9, 2, 3, 0),
+ _da_note(9, 2, 4, 0),
+ _blueprints(9, 2, 5, 0),
+ _planter_key(9, 2, 6, 0),
+ _center_punch(9, 2, 7, 0),
+ _tranquilizer(9, 2, 8, 0),
+ _boat_hook(9, 2, 9, 0),
+ _oily_rags(9, 2, 10, 0),
+ _fuel_jar(9, 2, 11, 0),
+ _screwdriver(9, 2, 12, 0),
+ _floppy_disk1(9, 2, 13, 0),
+ _floppy_disk2(9, 2, 14, 0),
+ _driftwood(9, 2, 15, 0),
+ _crate_piece1(9, 2, 16, 0),
+ _crate_piece2(9, 2, 17, 0),
+ _shoebox(9, 2, 18, 0),
+ _badge(9, 2, 19, 0),
+ _unused2(1, 1, 1, 0),
+ _rental_coupons(9, 3, 1, 0),
+ _nickel(9, 3, 2, 0),
+ _calendar(9, 3, 3, 0),
+ _dixon_note(9, 3, 4, 0),
+ _cobb_mugshot(9, 3, 5, 0),
+ _murder_article(9, 3, 6, 0),
+ _microfiche(9, 3, 7, 0),
+ _future_wave_keys(9, 3, 8, 0),
+ _rental_boat_keys(9, 3, 9, 0),
+ _napkin(9, 3, 10, 0),
+ _cobb_printout(9, 3, 11, 0),
+ _fishing_net(9, 3, 12, 0),
+ _id(9, 3, 13, 0),
+ _rounds_9mm(9, 3, 14, 0),
+ _dates_note(9, 3, 15, 0),
+ _hand_grenade(9, 3, 16, 0),
+ _cord_110(9, 3, 17, 0),
+ _cord_110_plug(9, 3, 18, 0),
+ _cord_220(9, 3, 19, 0),
+ _unused3(1, 1, 1, 0),
+ _cord_220_plug(9, 4, 1, 0),
+ _official_document(9, 4, 2, 0),
+ _red_sweater(9, 4, 3, 0),
+ _jackknife(9, 4, 4, 0),
+ _whistle(9, 4, 5, 0),
+ _gun(9, 1, 2, 0),
+ _alley_cat_key(9, 4, 7, 0) {
+
+ // Add the items to the list
+ _itemList.push_back(&_business_card);
+ _itemList.push_back(&_lauras_sweater);
+ _itemList.push_back(&_handcuffs);
+ _itemList.push_back(&_magnum);
+ _itemList.push_back(&_ticket_book);
+ _itemList.push_back(&_miranda_card);
+ _itemList.push_back(&_forest_follet);
+ _itemList.push_back(&_bradford_id);
+ _itemList.push_back(&_baseball_card);
+ _itemList.push_back(&_slip_bradford);
+ _itemList.push_back(&_flare);
+ _itemList.push_back(&_rap_sheet);
+ _itemList.push_back(&_cartridges);
+ _itemList.push_back(&_rifle);
+ _itemList.push_back(&_wig);
+ _itemList.push_back(&_frankies_id);
+ _itemList.push_back(&_tyrones_id);
+ _itemList.push_back(&_pistol22);
+ _itemList.push_back(&_unused);
+ _itemList.push_back(&_slip_frankie);
+ _itemList.push_back(&_slip_tyrone);
+ _itemList.push_back(&_atf_teletype);
+ _itemList.push_back(&_da_note);
+ _itemList.push_back(&_blueprints);
+ _itemList.push_back(&_planter_key);
+ _itemList.push_back(&_center_punch);
+ _itemList.push_back(&_tranquilizer);
+ _itemList.push_back(&_boat_hook);
+ _itemList.push_back(&_oily_rags);
+ _itemList.push_back(&_fuel_jar);
+ _itemList.push_back(&_screwdriver);
+ _itemList.push_back(&_floppy_disk1);
+ _itemList.push_back(&_floppy_disk2);
+ _itemList.push_back(&_driftwood);
+ _itemList.push_back(&_crate_piece1);
+ _itemList.push_back(&_crate_piece2);
+ _itemList.push_back(&_shoebox);
+ _itemList.push_back(&_badge);
+ _itemList.push_back(&_unused2);
+ _itemList.push_back(&_rental_coupons);
+ _itemList.push_back(&_nickel);
+ _itemList.push_back(&_calendar);
+ _itemList.push_back(&_dixon_note);
+ _itemList.push_back(&_cobb_mugshot);
+ _itemList.push_back(&_murder_article);
+ _itemList.push_back(&_microfiche);
+ _itemList.push_back(&_future_wave_keys);
+ _itemList.push_back(&_rental_boat_keys);
+ _itemList.push_back(&_napkin);
+ _itemList.push_back(&_cobb_printout);
+ _itemList.push_back(&_fishing_net);
+ _itemList.push_back(&_id);
+ _itemList.push_back(&_rounds_9mm);
+ _itemList.push_back(&_dates_note);
+ _itemList.push_back(&_hand_grenade);
+ _itemList.push_back(&_cord_110);
+ _itemList.push_back(&_cord_110_plug);
+ _itemList.push_back(&_cord_220);
+ _itemList.push_back(&_unused3);
+ _itemList.push_back(&_cord_220_plug);
+ _itemList.push_back(&_official_document);
+ _itemList.push_back(&_red_sweater);
+ _itemList.push_back(&_jackknife);
+ _itemList.push_back(&_whistle);
+ _itemList.push_back(&_gun);
+ _itemList.push_back(&_alley_cat_key);
+}
+
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/blue_force/blueforce_logic.h b/engines/tsage/blue_force/blueforce_logic.h
new file mode 100644
index 0000000000..d756d85cb3
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_logic.h
@@ -0,0 +1,294 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TSAGE_BLUEFORCE_LOGIC_H
+#define TSAGE_BLUEFORCE_LOGIC_H
+
+#include "common/scummsys.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+using namespace TsAGE;
+
+#define BLUE_INVENTORY (*((::TsAGE::BlueForce::BlueForceInvObjectList *)_globals->_inventory))
+
+class BlueForceGame: public Game {
+public:
+ virtual void start();
+ virtual Scene *createScene(int sceneNumber);
+};
+
+#define OBJ_ARRAY_SIZE 10
+class AObjectArray: public EventHandler {
+public:
+ EventHandler *_objList[OBJ_ARRAY_SIZE];
+ bool _inUse;
+ int getNewIndex();
+public:
+ AObjectArray();
+ void clear();
+
+ virtual Common::String getClassName() { return "AObjectArray"; }
+ virtual void synchronize(Serializer &s);
+ virtual void process(Event &event);
+ virtual void dispatch();
+
+ void add(EventHandler *obj);
+ void remove(EventHandler *obj);
+};
+
+class Timer: public EventHandler {
+public:
+ Action *_tickAction;
+ Action *_endAction;
+ uint32 _endFrame;
+public:
+ Timer();
+ void set(uint32 delay, Action *endAction);
+
+ virtual Common::String getClassName() { return "Timer"; }
+ virtual void synchronize(Serializer &s);
+ virtual void remove();
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class TimerExt: public Timer {
+public:
+ Action *_newAction;
+public:
+ TimerExt();
+ void set(uint32 delay, Action *endAction, Action *action);
+
+ virtual Common::String getClassName() { return "TimerExt"; }
+ virtual void synchronize(Serializer &s);
+ virtual void remove();
+ virtual void signal();
+ virtual void dispatch();
+};
+
+class SceneItemType2: public SceneHotspot {
+public:
+ virtual void startMove(SceneObject *sceneObj, va_list va);
+};
+
+class NamedObject: public SceneObject {
+public:
+ int _resNum;
+ int _lookLineNum, _talkLineNum, _useLineNum;
+
+ virtual Common::String getClassName() { return "NamedObject"; }
+ virtual void synchronize(Serializer &s);
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+
+ void setup(int resNum, int lookLineNum, int talkLineNum, int useLineNum, int mode, SceneItem *item);
+};
+
+class CountdownObject: public NamedObject {
+public:
+ int _countDown;
+ CountdownObject();
+ void fixCountdown(int mode, ...);
+
+ virtual Common::String getClassName() { return "CountdownObject"; }
+ virtual void synchronize(Serializer &s);
+ virtual void dispatch();
+};
+
+class FollowerObject: public NamedObject {
+public:
+ SceneObject *_object;
+ FollowerObject();
+
+ virtual Common::String getClassName() { return "SceneObjectExt4"; }
+ virtual void synchronize(Serializer &s);
+ virtual void remove();
+ virtual void dispatch();
+ virtual void reposition();
+
+ void setup(SceneObject *object, int visage, int frameNum, int yDiff);
+};
+
+class SceneExt: public Scene {
+public:
+ AObjectArray _timerList, _objArray2;
+ int _field372;
+ int _field37A;
+ EventHandler *_eventHandler;
+
+ Rect _v51C34;
+public:
+ SceneExt();
+
+ virtual Common::String getClassName() { return "SceneExt"; }
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void process(Event &event);
+ virtual void dispatch();
+ virtual void loadScene(int sceneNum);
+ virtual void proc13() { warning("TODO: SceneExt::proc13"); }
+
+ void addTimer(Timer *timer) { _timerList.add(timer); }
+ void removeTimer(Timer *timer) { _timerList.remove(timer); }
+};
+
+class GameScene: public SceneExt {
+public:
+ int _field412;
+ int _field794;
+public:
+ GameScene();
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+};
+
+class SceneHandlerExt: public SceneHandler {
+public:
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void process(Event &event);
+};
+
+class VisualSpeaker: public Speaker {
+public:
+ NamedObject _object1;
+ CountdownObject _object2;
+ bool _removeObject1, _removeObject2;
+ int _field20C, _field20E;
+ int _numFrames;
+ Common::Point _offsetPos;
+public:
+ VisualSpeaker();
+
+ virtual Common::String getClassName() { return "VisualSpeaker"; }
+ virtual void synchronize(Serializer &s);
+ virtual void remove();
+ virtual void proc12(Action *action);
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerSutter: public VisualSpeaker {
+public:
+ SpeakerSutter();
+
+ virtual Common::String getClassName() { return "SpeakerSutter"; }
+ virtual void setText(const Common::String &msg);
+};
+
+class SpeakerDoug: public VisualSpeaker {
+public:
+ SpeakerDoug();
+
+ virtual Common::String getClassName() { return "SpeakerDoug"; }
+};
+
+class SpeakerJakeNoHead: public VisualSpeaker {
+public:
+ SpeakerJakeNoHead();
+
+ virtual Common::String getClassName() { return "SpeakerJakeNoHead"; }
+};
+
+class BlueForceInvObjectList : public InvObjectList {
+public:
+ InvObject _business_card;
+ InvObject _lauras_sweater;
+ InvObject _handcuffs;
+ InvObject _magnum;
+ InvObject _ticket_book;
+ InvObject _miranda_card;
+ InvObject _forest_follet;
+ InvObject _bradford_id;
+ InvObject _baseball_card;
+ InvObject _slip_bradford;
+ InvObject _flare;
+ InvObject _rap_sheet;
+ InvObject _cartridges;
+ InvObject _rifle;
+ InvObject _wig;
+ InvObject _frankies_id;
+ InvObject _tyrones_id;
+ InvObject _pistol22;
+ InvObject _unused;
+ InvObject _slip_frankie;
+ InvObject _slip_tyrone;
+ InvObject _atf_teletype;
+ InvObject _da_note;
+ InvObject _blueprints;
+ InvObject _planter_key;
+ InvObject _center_punch;
+ InvObject _tranquilizer;
+ InvObject _boat_hook;
+ InvObject _oily_rags;
+ InvObject _fuel_jar;
+ InvObject _screwdriver;
+ InvObject _floppy_disk1;
+ InvObject _floppy_disk2;
+ InvObject _driftwood;
+ InvObject _crate_piece1;
+ InvObject _crate_piece2;
+ InvObject _shoebox;
+ InvObject _badge;
+ InvObject _unused2;
+ InvObject _rental_coupons;
+ InvObject _nickel;
+ InvObject _calendar;
+ InvObject _dixon_note;
+ InvObject _cobb_mugshot;
+ InvObject _murder_article;
+ InvObject _microfiche;
+ InvObject _future_wave_keys;
+ InvObject _rental_boat_keys;
+ InvObject _napkin;
+ InvObject _cobb_printout;
+ InvObject _fishing_net;
+ InvObject _id;
+ InvObject _rounds_9mm;
+ InvObject _dates_note;
+ InvObject _hand_grenade;
+ InvObject _cord_110;
+ InvObject _cord_110_plug;
+ InvObject _cord_220;
+ InvObject _unused3;
+ InvObject _cord_220_plug;
+ InvObject _official_document;
+ InvObject _red_sweater;
+ InvObject _jackknife;
+ InvObject _whistle;
+ InvObject _gun;
+ InvObject _alley_cat_key;
+
+ BlueForceInvObjectList();
+
+ virtual Common::String getClassName() { return "BlueForceInvObjectList"; }
+};
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
+
+#endif
diff --git a/engines/tsage/blue_force/blueforce_scenes0.cpp b/engines/tsage/blue_force/blueforce_scenes0.cpp
new file mode 100644
index 0000000000..f1b714ec6c
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_scenes0.cpp
@@ -0,0 +1,501 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "tsage/blue_force/blueforce_scenes0.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+/*--------------------------------------------------------------------------
+ * Scene 20 - Tsunami Title Screen
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene20::Action1::signal() {
+ Scene20 *scene = (Scene20 *)BF_GLOBALS._sceneManager._scene;
+ static byte black[3] = { 0, 0, 0 };
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(2);
+ break;
+ case 1:
+ _sound.play(1);
+ BF_GLOBALS._scenePalette.addRotation(64, 127, -1, 1, this);
+ break;
+ case 2:
+ scene->_object1.setVisage(22);
+ scene->_object1._strip = 1;
+ scene->_object1._frame = 1;
+ scene->_object1.changeZoom(100);
+
+ scene->_object2.setVisage(22);
+ scene->_object2._strip = 2;
+ scene->_object2._frame = 1;
+ scene->_object2.changeZoom(100);
+
+ scene->_object3.setVisage(22);
+ scene->_object3._strip = 3;
+ scene->_object3._frame = 1;
+ scene->_object3.changeZoom(100);
+
+ scene->_object4.setVisage(22);
+ scene->_object4._strip = 4;
+ scene->_object4._frame = 1;
+ scene->_object4.changeZoom(100);
+
+ scene->_object5.setVisage(22);
+ scene->_object5._strip = 5;
+ scene->_object5._frame = 1;
+ scene->_object5.changeZoom(100);
+
+ scene->_object6.setVisage(22);
+ scene->_object6._strip = 6;
+ scene->_object6._frame = 1;
+ scene->_object6.changeZoom(100);
+
+ scene->_object7.setVisage(22);
+ scene->_object7._strip = 7;
+ scene->_object7._frame = 1;
+ scene->_object7.changeZoom(100);
+
+ scene->_object8.setVisage(22);
+ scene->_object8._strip = 8;
+ scene->_object8._frame = 1;
+ scene->_object8.changeZoom(100);
+
+ setDelay(1);
+ break;
+ case 3:
+ BF_GLOBALS._scenePalette.addFader(scene->_scenePalette._palette, 256, 8, this);
+ break;
+ case 4:
+ setDelay(60);
+ break;
+ case 5:
+ scene->_object2.animate(ANIM_MODE_5, NULL);
+ scene->_object3.animate(ANIM_MODE_5, NULL);
+ scene->_object4.animate(ANIM_MODE_5, NULL);
+ scene->_object5.animate(ANIM_MODE_5, NULL);
+ scene->_object6.animate(ANIM_MODE_5, NULL);
+ scene->_object7.animate(ANIM_MODE_5, this);
+ break;
+ case 6:
+ setDelay(120);
+ break;
+ case 7:
+ BF_GLOBALS._scenePalette.addFader(black, 1, 5, this);
+ break;
+ case 8:
+ BF_GLOBALS._sceneManager.changeScene(100);
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene20::postInit(SceneObjectList *OwnerList) {
+ loadScene(20);
+ Scene::postInit();
+ setZoomPercents(60, 85, 200, 100);
+
+ _scenePalette.loadPalette(1);
+ _scenePalette.loadPalette(22);
+
+ _object1.postInit();
+ _object1.setVisage(21);
+ _object1._strip = 1;
+ _object1._frame = 1;
+ _object1.animate(ANIM_MODE_NONE, NULL);
+ _object1.setPosition(Common::Point(62, 85));
+ _object1.changeZoom(100);
+
+ _object2.postInit();
+ _object2.setVisage(21);
+ _object2._strip = 2;
+ _object2._frame = 1;
+ _object2.animate(ANIM_MODE_NONE, NULL);
+ _object2.setPosition(Common::Point(27, 94));
+ _object2.changeZoom(100);
+
+ _object3.postInit();
+ _object3.setVisage(21);
+ _object3._strip = 2;
+ _object3._frame = 2;
+ _object3.animate(ANIM_MODE_NONE, NULL);
+ _object3.setPosition(Common::Point(68, 94));
+ _object3.changeZoom(100);
+
+ _object4.postInit();
+ _object4.setVisage(21);
+ _object4._strip = 2;
+ _object4._frame = 3;
+ _object4.animate(ANIM_MODE_NONE, NULL);
+ _object4.setPosition(Common::Point(110, 94));
+ _object4.changeZoom(100);
+
+ _object5.postInit();
+ _object5.setVisage(21);
+ _object5._strip = 2;
+ _object5._frame = 4;
+ _object5.animate(ANIM_MODE_NONE, NULL);
+ _object5.setPosition(Common::Point(154, 94));
+ _object5.changeZoom(100);
+
+ _object6.postInit();
+ _object6.setVisage(21);
+ _object6._strip = 2;
+ _object6._frame = 5;
+ _object6.animate(ANIM_MODE_NONE, NULL);
+ _object6.setPosition(Common::Point(199, 94));
+ _object6.changeZoom(100);
+
+ _object7.postInit();
+ _object7.setVisage(21);
+ _object7._strip = 2;
+ _object7._frame = 6;
+ _object7.animate(ANIM_MODE_NONE, NULL);
+ _object7.setPosition(Common::Point(244, 94));
+ _object7.changeZoom(100);
+
+ _object8.postInit();
+ _object8.setVisage(21);
+ _object8._strip = 2;
+ _object8._frame = 7;
+ _object8.animate(ANIM_MODE_NONE, NULL);
+ _object8.setPosition(Common::Point(286, 94));
+ _object8.changeZoom(100);
+
+ setAction(&_action1);
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 50 - Map Screen
+ *
+ *--------------------------------------------------------------------------*/
+
+Scene50::Tooltip::Tooltip(): SavedObject() {
+ _newSceneNumber = _locationId = 0;
+}
+
+void Scene50::Tooltip::synchronize(Serializer &s) {
+ SavedObject::synchronize(s);
+ _bounds.synchronize(s);
+ s.syncString(_msg);
+}
+
+void Scene50::Tooltip2::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(60);
+ break;
+ case 1: {
+ Common::Point pt(410, 181);
+ NpcMover *mover = new NpcMover();
+ ((SceneObject *)_owner)->addMover(mover, &pt, this);
+ break;
+ }
+ case 2:
+ _owner->remove();
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene50::Tooltip2::dispatch() {
+ Action::dispatch();
+ SceneObject *owner = (SceneObject *)_owner;
+
+ if ((_actionIndex == 2) && (owner->_percent < 100)) {
+ owner->changeZoom(owner->_percent + 1);
+ }
+}
+
+void Scene50::Tooltip::set(const Rect &bounds, int v60, const Common::String &msg, int v62) {
+ _bounds = bounds;
+ _newSceneNumber = v60;
+ _msg = msg;
+ _locationId = v62;
+}
+
+void Scene50::Tooltip::update() {
+ // Set up the text object for the scene with the appropriate settings
+ Scene50 *scene = (Scene50 *)BF_GLOBALS._sceneManager._scene;
+ scene->_text._fontNumber = 10;
+ scene->_text._color1 = BF_GLOBALS._scenePalette._colors.foreground;
+ scene->_text._color2 = BF_GLOBALS._scenePalette._colors.background;
+ scene->_text.setup(_msg);
+
+ int yp = (scene->_text._textSurface.getBounds().height() == 0) ? _bounds.bottom : _bounds.top;
+ scene->_text.setPosition(Common::Point(_bounds.left, yp));
+}
+
+void Scene50::Tooltip::highlight(bool btnDown) {
+ Scene50 *scene = (Scene50 *)BF_GLOBALS._sceneManager._scene;
+
+ scene->_field382 = _newSceneNumber;
+ if ((scene->_field380 != 0) || (scene->_field380 != _newSceneNumber))
+ update();
+
+ if (btnDown) {
+ if ((BF_GLOBALS._bikiniHutState == 14) && BF_GLOBALS.getFlag(98))
+ scene->_sceneNumber = 600;
+ else if (BF_GLOBALS._bikiniHutState == 5)
+ scene->_sceneNumber = 410;
+ else {
+ BF_GLOBALS._v4CEF4 = _newSceneNumber;
+
+ switch (BF_GLOBALS._v4CEF2) {
+ case 330:
+ case 340:
+ case 342:
+ BF_GLOBALS._player.disableControl();
+ if (_locationId != BF_GLOBALS._mapLocationId) {
+ scene->_sceneNumber = 330;
+ } else {
+ scene->_sceneNumber = (BF_GLOBALS._v4CEA2 != 1) || (BF_GLOBALS._bikiniHutState < 1) ||
+ (BF_GLOBALS._bikiniHutState >= 2) ? 342 : 340;
+ }
+ break;
+
+ case 410:
+ case 551:
+ if (BF_GLOBALS.getFlag((BF_GLOBALS._v4CEF2 == 410) ? 41 : 40)) {
+ BF_GLOBALS._mapLocationId = _locationId;
+ BF_GLOBALS._player.disableControl();
+ scene->_sceneNumber = _newSceneNumber;
+ } else {
+ BF_GLOBALS._v4CEA8 = 4;
+ BF_GLOBALS._sceneManager.changeScene(666);
+ return;
+ }
+ break;
+
+ case 300:
+ if (_locationId == 1) {
+ BF_GLOBALS._v4CEF4 = 300;
+ _newSceneNumber = 300;
+ }
+ // Deliberate fall through to default
+ default:
+ BF_GLOBALS._mapLocationId = _locationId;
+ BF_GLOBALS._player.disableControl();
+ scene->_sceneNumber = _newSceneNumber;
+ break;
+ }
+
+ // Signal the scene to change to the new scene
+ scene->_sceneMode = 1;
+ scene->signal();
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene50::Scene50(): SceneExt() {
+ _field382 = 0;
+ _field380 = 0;
+}
+
+void Scene50::postInit(SceneObjectList *OwnerList) {
+ SceneExt::postInit();
+
+ BF_GLOBALS._interfaceY = 200;
+ BF_GLOBALS._player.postInit();
+ BF_GLOBALS._player.setVisage(830);
+ BF_GLOBALS._player.setStrip(3);
+ BF_GLOBALS._player.setPosition(Common::Point(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2));
+ BF_GLOBALS._player.hide();
+ BF_GLOBALS._player.enableControl();
+ BF_GLOBALS._player._uiEnabled = false;
+
+ BF_GLOBALS._scrollFollower = NULL;
+ _text._color1 = 19;
+ _text._color2 = 9;
+ _text._color3 = 9;
+ _text._width = 75;
+ _text._fontNumber = 4;
+ _text._textMode = ALIGN_LEFT;
+ _text.fixPriority(256);
+
+ // Set all the hotspots
+ _location3.set(Rect(10, 92, 24, 105), 180, GRANDMA_FRANNIE, 4);
+ _location2.set(Rect(443, 149, 508, 178), 330, MARINA, 2);
+ _location1.set(Rect(573, 103, 604, 130), 190, POLICE_DEPARTMENT, 1);
+ _location4.set(Rect(313, 21, 325, 33), 114, TONYS_BAR, 8);
+ _location8.set(Rect(69, 79, 82, 88), 580, CHILD_PROTECTIVE_SERVICES, 256);
+ _location6.set(Rect(242, 131, 264, 144), 440, ALLEY_CAT, 64);
+ _location5.set(Rect(383, 57, 402, 70), 380, CITY_HALL_JAIL, 32);
+ _location7.set(Rect(128, 32, 143, 42), 800, JAMISON_RYAN, 128);
+ _location9.set(Rect(349, 125, 359, 132),
+ (BF_GLOBALS._bikiniHutState == 13) || (BF_GLOBALS._bikiniHutState == 14) ? 551 : 550,
+ BIKINI_HUT, 16);
+
+ _item.setBounds(Rect(0, 0, SCREEN_WIDTH * 2, SCREEN_HEIGHT));
+ BF_GLOBALS._sceneItems.push_back(&_item);
+
+ // Find the location to start at
+ int selectedTooltip = BF_GLOBALS._mapLocationId;
+ Tooltip *tooltip = NULL;
+ int xp = 0;
+
+ switch (selectedTooltip) {
+ case 1:
+ tooltip = &_location1;
+ xp = 588;
+ break;
+ case 2:
+ tooltip = &_location2;
+ xp = 475;
+ break;
+ case 4:
+ tooltip = &_location3;
+ xp = 17;
+ break;
+ case 8:
+ tooltip = &_location4;
+ xp = 319;
+ break;
+ case 32:
+ tooltip = &_location5;
+ xp = 392;
+ break;
+ case 64:
+ tooltip = &_location6;
+ xp = 253;
+ break;
+ case 128:
+ tooltip = &_location7;
+ xp = 135;
+ break;
+ case 16:
+ tooltip = &_location9;
+ xp = 354;
+ break;
+ case 256:
+ tooltip = &_location8;
+ xp = 75;
+ break;
+ }
+
+ _timer.set(240, this);
+ _sceneBounds.center(xp, SCREEN_HEIGHT / 2);
+ loadScene(55);
+ _sceneMode = 2;
+
+ loadBackground(xp - 160, 0);
+ tooltip->update();
+}
+
+void Scene50::remove() {
+ // Blank out the screen
+ BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
+
+ SceneExt::remove();
+ BF_GLOBALS._v4E238 = 1;
+}
+
+void Scene50::signal() {
+ if (_sceneMode == 1) {
+ // Destination selected
+ if ((BF_GLOBALS._v4CEF2 == 551) && (_sceneNumber != BF_GLOBALS._v4CEF2)) {
+ BF_GLOBALS.setFlag(109);
+ BF_GLOBALS.setFlag(115);
+ BF_GLOBALS.setFlag(121);
+ BF_GLOBALS.setFlag(127);
+ BF_GLOBALS.setFlag(133);
+ }
+
+ if ((BF_GLOBALS._v4CEF2 == 410) && (_sceneNumber != BF_GLOBALS._v4CEF2)) {
+ BF_GLOBALS.setFlag(125);
+ }
+
+ if ((BF_GLOBALS._v4CEF2 == 340) && (_sceneNumber != BF_GLOBALS._v4CEF2)) {
+ BF_GLOBALS.setFlag(123);
+ }
+
+ if ((BF_GLOBALS._v4CEF2 == 380) && (_sceneNumber != BF_GLOBALS._v4CEF2)) {
+ if (BF_GLOBALS._bikiniHutState >= 4)
+ BF_GLOBALS.setFlag(129);
+ if (BF_GLOBALS._bikiniHutState >= 6)
+ BF_GLOBALS.setFlag(131);
+ if (BF_GLOBALS._bikiniHutState == 3) {
+ BF_GLOBALS._v4CEA8 = 19;
+ _sceneNumber = 666;
+ }
+ }
+
+ if ((_sceneNumber == 551) && BF_GLOBALS.getFlag(147))
+ _sceneNumber = 550;
+
+ BF_GLOBALS._sound1.fadeOut2(NULL);
+ BF_GLOBALS._sceneManager.changeScene(_sceneNumber);
+
+ } else if (_sceneMode == 2) {
+ // Initial delay complete, time to switch to interactive mode
+ _text.remove();
+ BF_GLOBALS._player.enableControl();
+ _sceneMode = 0;
+ _field380 = 0;
+ }
+}
+
+void Scene50::process(Event &event) {
+ SceneExt::process(event);
+ Common::Point pt(event.mousePos.x + _sceneBounds.left, event.mousePos.y + _sceneBounds.top);
+ bool mouseDown = false;
+ _field382 = 0;
+
+ if ((event.mousePos.x > 270 && (_sceneBounds.right < (SCREEN_WIDTH * 2))))
+ loadBackground(4, 0);
+ else if ((event.mousePos.x < 50) && (_sceneBounds.left > 0))
+ loadBackground(-4, 0);
+ else
+ mouseDown = event.eventType == EVENT_BUTTON_DOWN;
+
+ if (BF_GLOBALS._player._uiEnabled) {
+ Tooltip *tooltipList[9] = { &_location1, &_location2, &_location3, &_location4,
+ &_location5, &_location6, &_location7, &_location8, &_location9 };
+
+ for (int idx = 0; idx < 9; ++idx) {
+ if (tooltipList[idx]->_bounds.contains(pt)) {
+ // Found a tooltip to highlight
+ tooltipList[idx]->highlight(mouseDown);
+ return;
+ }
+ }
+
+ // No hotspot selected, so remove any current tooltip display
+ _text.remove();
+ }
+}
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/blue_force/blueforce_scenes0.h b/engines/tsage/blue_force/blueforce_scenes0.h
new file mode 100644
index 0000000000..5c98184ed8
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_scenes0.h
@@ -0,0 +1,103 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TSAGE_BLUEFORCE_SCENES0_H
+#define TSAGE_BLUEFORCE_SCENES0_H
+
+#include "common/scummsys.h"
+#include "tsage/blue_force/blueforce_logic.h"
+#include "tsage/converse.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+#include "tsage/sound.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+using namespace TsAGE;
+
+class Scene20 : public SceneExt {
+ /* Actions */
+ class Action1 : public Action {
+ private:
+ ASoundExt _sound;
+ public:
+ virtual void signal();
+ };
+public:
+ Action1 _action1;
+ ScenePalette _scenePalette;
+ SceneObject _object1, _object2, _object3, _object4;
+ SceneObject _object5, _object6, _object7, _object8;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+};
+
+class Scene50: public SceneExt {
+ class Tooltip: public SavedObject {
+ public:
+ Rect _bounds;
+ Common::String _msg;
+ int _newSceneNumber;
+ int _locationId;
+ public:
+ Tooltip();
+ void set(const Rect &bounds, int v60, const Common::String &msg, int v62);
+ void update();
+ void highlight(bool btnDown);
+
+ virtual Common::String getClassName() { return "Scene50_Tooltip"; }
+ virtual void synchronize(Serializer &s);
+ };
+ class Tooltip2: public Action {
+ public:
+ Tooltip2(): Action() {}
+
+ virtual Common::String getClassName() { return "Scene50_Tooltip2"; }
+ virtual void signal();
+ virtual void dispatch();
+ };
+public:
+ int _field380, _field382;
+ int _sceneNumber;
+ SceneText _text;
+ SceneItemType2 _item;
+ Tooltip _location1, _location2, _location3, _location4, _location5;
+ Tooltip _location6, _location7, _location8, _location9;
+ Timer _timer;
+public:
+ Scene50();
+ virtual Common::String getClassName() { return "Scene50"; }
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void signal();
+ virtual void process(Event &event);
+};
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
+
+#endif
diff --git a/engines/tsage/blue_force/blueforce_scenes1.cpp b/engines/tsage/blue_force/blueforce_scenes1.cpp
new file mode 100644
index 0000000000..650b63c24b
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_scenes1.cpp
@@ -0,0 +1,432 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/config-manager.h"
+#include "tsage/blue_force/blueforce_scenes1.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+#include "tsage/globals.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+/*--------------------------------------------------------------------------
+ * Scene 100 - Tsunami Title Screen #2
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene100::Text::dispatch() {
+ SceneText::dispatch();
+
+ // Keep the second text string below the first one
+ Scene100 *scene = (Scene100 *)BF_GLOBALS._sceneManager._scene;
+ Common::Point &pt = scene->_action1._sceneText1._position;
+ scene->_action1._sceneText2.setPosition(Common::Point(pt.x,
+ pt.y + scene->_action1._textHeight));
+}
+
+
+void Scene100::Action1::signal() {
+ static byte black[3] = { 0, 0, 0 };
+
+ switch (_actionIndex++) {
+ case 0:
+ _state = 0;
+ setDelay(6);
+ break;
+ case 1: {
+ Common::String msg1 = _resourceManager->getMessage(100, _state++);
+ if (msg1.compareTo("LASTCREDIT")) {
+ Common::String msg2 = _resourceManager->getMessage(100, _state++);
+ setTextStrings(msg1, msg2, this);
+ --_actionIndex;
+ } else {
+ setTextStrings(BF_NAME, BF_ALL_RIGHTS_RESERVED, this);
+
+ Common::Point pt(_sceneText1._position.x, 80);
+ NpcMover *mover = new NpcMover();
+ _sceneText1.addMover(mover, &pt, this);
+ }
+ break;
+ }
+ case 2:
+ setDelay(600);
+ break;
+ case 3:
+ BF_GLOBALS._sound1.fade(0, 10, 10, 1, this);
+ GLOBALS._scenePalette.addFader(black, 1, 2, NULL);
+ break;
+ case 4:
+ error("??exit");
+ break;
+ }
+}
+
+void Scene100::Action1::setTextStrings(const Common::String &msg1, const Common::String &msg2, Action *action) {
+ // Set data for first text control
+ _sceneText1._fontNumber = 10;
+ _sceneText1._width = 160;
+ _sceneText1._textMode = ALIGN_RIGHT;
+ _sceneText1._color1 = BF_GLOBALS._scenePalette._colors.foreground;
+ _sceneText1._color2 = BF_GLOBALS._scenePalette._colors.background;
+ _sceneText1._color3 = BF_GLOBALS._scenePalette._colors.foreground;
+ _sceneText1.setup(msg1);
+ _sceneText1.fixPriority(255);
+ _sceneText1.setPosition(Common::Point(
+ (SCREEN_WIDTH - _sceneText1.getFrame().getBounds().width()) / 2, 202));
+ _sceneText1._moveRate = 30;
+ _sceneText1._moveDiff.y = 1;
+
+ // Set data for second text control
+ _sceneText2._fontNumber = 10;
+ _sceneText2._width = _sceneText1._width;
+ _sceneText2._textMode = _sceneText1._textMode;
+ _sceneText2._color1 = _sceneText1._color1;
+ _sceneText2._color2 = 31;
+ _sceneText2._color3 = _sceneText1._color3;
+ _sceneText2.setup(msg2);
+ _sceneText2.fixPriority(255);
+ GfxSurface textSurface = _sceneText2.getFrame();
+ _sceneText2.setPosition(Common::Point((SCREEN_WIDTH - textSurface.getBounds().width()) / 2, 202));
+ _sceneText2._moveRate = 30;
+ _sceneText2._moveDiff.y = 1;
+
+ _textHeight = textSurface.getBounds().height();
+ int yp = -(_textHeight * 2);
+
+ Common::Point pt(_sceneText1._position.x, yp);
+ NpcMover *mover = new NpcMover();
+ _sceneText1.addMover(mover, &pt, action);
+}
+
+void Scene100::Action2::signal() {
+ Scene100 *scene = (Scene100 *)_globals->_sceneManager._scene;
+ static byte black[3] = {0, 0, 0};
+
+ switch (_actionIndex++) {
+ case 0:
+ BF_GLOBALS._scenePalette.addFader(black, 1, -2, this);
+ break;
+ case 1:
+ setDelay(180);
+ break;
+ case 2: {
+ const char *SEEN_INTRO = "seen_intro";
+ if (!ConfMan.hasKey(SEEN_INTRO) || !ConfMan.getBool(SEEN_INTRO)) {
+ // First time being played, so will need to show the intro
+ ConfMan.setBool(SEEN_INTRO, true);
+ ConfMan.flushToDisk();
+ } 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) {
+ // Signal to start the game
+ scene->_index = 190;
+ remove();
+ return;
+ }
+ }
+
+ // At this point the introduction needs to start
+ _globals->_scenePalette.addFader(black, 1, 2, this);
+ break;
+ }
+ case 3:
+ remove();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene100::Scene100(): SceneExt() {
+ _index = 0;
+}
+
+void Scene100::postInit(SceneObjectList *OwnerList) {
+ BF_GLOBALS._scenePalette.loadPalette(2);
+ BF_GLOBALS._v51C44 = 1;
+ Scene::postInit();
+ BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
+
+ _globals->_player.enableControl();
+ _globals->_player.hide();
+ _globals->_player.disableControl();
+ _index = 109;
+
+ if (BF_GLOBALS._v4CEA2 < 6) {
+ // Title
+ loadScene(100);
+ BF_GLOBALS._sound1.play(2);
+ setAction(&_action2, this);
+ } else {
+ // Credits
+ loadScene(101);
+ BF_GLOBALS._sound1.play(118);
+ setAction(&_action1, this);
+ }
+}
+
+void Scene100::signal() {
+ ++_sceneMode;
+ if (BF_GLOBALS._v4CEA2 < 6) {
+ BF_GLOBALS._scenePalette.clearListeners();
+ BF_GLOBALS._scenePalette.loadPalette(100);
+ BF_GLOBALS._sceneManager.changeScene(_index);
+ } else {
+ if (_sceneMode > 1)
+ BF_GLOBALS._events.setCursor(CURSOR_ARROW);
+
+ setAction(this, &_action1, this);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 109 - Introduction Bar Room
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene109::Action1::signal() {
+ Scene109 *scene = (Scene109 *)BF_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ setDelay(30);
+ break;
+ case 1:
+ BF_GLOBALS._sound1.play(12);
+ BF_GLOBALS._sceneObjects->draw();
+ BF_GLOBALS._scenePalette.loadPalette(2);
+ BF_GLOBALS._scenePalette.refresh();
+ setDelay(10);
+ break;
+ case 2:
+ scene->_text.setup(BF_19840515, this);
+ break;
+ case 3:
+ BF_GLOBALS._v51C44 = 1;
+ scene->loadScene(115);
+
+ scene->_protaginist2.show();
+ scene->_protaginist2.setPriority(133);
+ scene->_protaginist1.show();
+ scene->_bartender.show();
+ scene->_object1.show();
+ scene->_drunk.show();
+ scene->_drunk.setAction(&scene->_action3);
+ scene->_object2.show();
+ scene->_object9.show();
+ scene->_object9.setAction(&scene->_action2);
+
+ BF_GLOBALS._v501FC = 170;
+ setDelay(60);
+ break;
+ case 4:
+ // Start drinking
+ scene->_bartender.setAction(&scene->_sequenceManager4, NULL, 109, &scene->_bartender, &scene->_object2, NULL);
+ scene->_protaginist1.setAction(&scene->_sequenceManager5, NULL, 107, &scene->_protaginist1, NULL);
+ scene->_protaginist2.setAction(&scene->_sequenceManager6, this, 106, &scene->_protaginist2, NULL);
+ break;
+ case 5:
+ // Open briefcase and pass over disk
+ setAction(&scene->_sequenceManager6, this, 105, &scene->_object10, NULL);
+ break;
+ case 6:
+ // Protaginist 2 walk to the bar
+ scene->_object10.remove();
+ setAction(&scene->_sequenceManager6, this, 100, &scene->_protaginist2, NULL);
+ break;
+ case 7:
+ // Two thugs enter and walk to table
+ scene->_object7.setAction(&scene->_sequenceManager7, NULL, 103, &scene->_object7, NULL);
+ scene->_object5.setAction(&scene->_sequenceManager8, this, 102, &scene->_object5, NULL);
+ scene->_protaginist2.setAction(&scene->_sequenceManager6, NULL, 104, &scene->_protaginist2, &scene->_bartender, NULL);
+ break;
+ case 8:
+ // Protaginist 1 leaves, protaginist 2 stands up
+ setAction(&scene->_sequenceManager8, this, 101, &scene->_object5, &scene->_protaginist1, NULL);
+ break;
+ case 9:
+ // Shots fired!
+ scene->_protaginist1.setAction(&scene->_sequenceManager5, this, 98, &scene->_protaginist1, NULL);
+ scene->_object7.setAction(&scene->_sequenceManager7, NULL, 99, &scene->_object7, NULL);
+ break;
+ case 10:
+ // End scene
+ scene->_sceneMode = 1;
+ remove();
+ break;
+ }
+}
+
+void Scene109::Action2::signal() {
+ Scene109 *scene = (Scene109 *)BF_GLOBALS._sceneManager._scene;
+ scene->setAction(&scene->_sequenceManager2, this, 3117, &scene->_object9, NULL);
+}
+
+void Scene109::Action3::signal() {
+ Scene109 *scene = (Scene109 *)BF_GLOBALS._sceneManager._scene;
+ scene->setAction(&scene->_sequenceManager3, this, 108, &scene->_drunk, NULL);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene109::Text::Text(): SceneText() {
+ _action = NULL;
+ _frameNumber = 0;
+ _diff = 0;
+}
+
+void Scene109::Text::setup(const Common::String &msg, Action *action) {
+ _frameNumber = BF_GLOBALS._events.getFrameNumber();
+ _diff = 180;
+ _action = action;
+ _fontNumber = 4;
+ _width = 300;
+ _textMode = ALIGN_CENTER;
+ _color1 = BF_GLOBALS._scenePalette._colors.background;
+ _color2 = _color3 = 0;
+
+ SceneText::setup(msg);
+
+ // Center the text on-screen
+ reposition();
+ _bounds.center(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
+
+ // Set the new position
+ _position.x = _bounds.left;
+ _position.y = _bounds.top;
+}
+
+void Scene109::Text::synchronize(Serializer &s) {
+ SceneText::synchronize(s);
+ SYNC_POINTER(_action);
+ s.syncAsUint32LE(_frameNumber);
+ s.syncAsSint16LE(_diff);
+}
+
+void Scene109::Text::dispatch() {
+ if (_diff) {
+ uint32 frameNumber = BF_GLOBALS._events.getFrameNumber();
+ if (_frameNumber < frameNumber) {
+ _diff -= frameNumber - _frameNumber;
+ _frameNumber = frameNumber;
+
+ if (_diff <= 0) {
+ // Time has expired, so remove the text and signal the designated action
+ remove();
+ if (_action)
+ _action->signal();
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene109::Scene109(): GameScene() {
+}
+
+void Scene109::postInit(SceneObjectList *OwnerList) {
+ GameScene::postInit(OwnerList);
+ loadScene(999);
+
+ _protaginist2.postInit();
+ _protaginist2.setVisage(119);
+ _protaginist2.setFrame(11);
+ _protaginist2.fixPriority(133);
+ _protaginist2.setPosition(Common::Point(165, 124));
+ _protaginist2.hide();
+
+ _protaginist1.postInit();
+ _protaginist1.setVisage(118);
+ _protaginist1.setStrip(1);
+ _protaginist1.setFrame(8);
+ _protaginist1.fixPriority(132);
+ _protaginist1.setPosition(Common::Point(143, 125));
+ _protaginist1.hide();
+
+ _bartender.postInit();
+ _bartender.setVisage(121);
+ _bartender.setStrip(2);
+ _bartender.setFrame(1);
+ _bartender.setPriority(-1);
+ _bartender.setPosition(Common::Point(92, 64));
+ _bartender.hide();
+
+ _object1.postInit();
+ _object1.setVisage(121);
+ _object1.setStrip(6);
+ _object1.setFrame(1);
+ _object1.setPriority(-1);
+ _object1.setPosition(Common::Point(110, 64));
+ _object1.hide();
+
+ _drunk.postInit();
+ _drunk.setVisage(120);
+ _drunk.setStrip(2);
+ _drunk.setFrame(5);
+ _drunk.setPriority(-1);
+ _drunk.setPosition(Common::Point(127, 97));
+ _drunk.hide();
+
+ _object2.postInit();
+ _object2.setVisage(121);
+ _object2.setStrip(5);
+ _object2.setFrame(1);
+ _object2.setPriority(-1);
+ _object2.setPosition(Common::Point(104, 64));
+ _object2.hide();
+
+ _object9.postInit();
+ _object9.setVisage(115);
+ _object9.setStrip(4);
+ _object9.setFrame(1);
+ _object9.setPosition(Common::Point(262, 29));
+ _object9.hide();
+
+ _object5.postInit();
+ _object5.hide();
+
+ _object7.postInit();
+ _object7.hide();
+
+ _object10.postInit();
+ _object10.hide();
+
+ BF_GLOBALS._player.disableControl();
+ setAction(&_action1, this);
+}
+
+void Scene109::signal() {
+ if (_sceneMode == 1) {
+ BF_GLOBALS._scenePalette.clearListeners();
+ BF_GLOBALS._sceneManager.changeScene(110);
+ }
+}
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/blue_force/blueforce_scenes1.h b/engines/tsage/blue_force/blueforce_scenes1.h
new file mode 100644
index 0000000000..2b07e2b48f
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_scenes1.h
@@ -0,0 +1,131 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TSAGE_BLUEFORCE_SCENES1_H
+#define TSAGE_BLUEFORCE_SCENES1_H
+
+#include "common/scummsys.h"
+#include "tsage/blue_force/blueforce_logic.h"
+#include "tsage/converse.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+#include "tsage/sound.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+using namespace TsAGE;
+
+class Scene100: public SceneExt {
+ /* Support classes */
+ class Text: public SceneText {
+ public:
+ virtual Common::String getClassName() { return "BF100Text"; }
+ virtual void dispatch();
+ };
+
+ /* Actions */
+ class Action1: public ActionExt {
+ private:
+ void setTextStrings(const Common::String &msg1, const Common::String &msg2, Action *action);
+ public:
+ Text _sceneText1;
+ SceneText _sceneText2;
+ int _textHeight;
+
+ virtual Common::String getClassName() { return "BF100Action1"; }
+ virtual void synchronize(Serializer &s) {
+ ActionExt::synchronize(s);
+ s.syncAsSint16LE(_textHeight);
+ }
+ virtual void signal();
+ };
+ class Action2: public ActionExt {
+ public:
+ virtual void signal();
+ };
+public:
+ SequenceManager _sequenceManager;
+ Action1 _action1;
+ Action2 _action2;
+ ScenePalette _scenePalette;
+ NamedObject _object1, _object2, _object3, _object4, _object5;
+ int _index;
+
+ Scene100();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+};
+
+class Scene109: public GameScene {
+ /* 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();
+ };
+
+ /* Texts */
+ class Text: public SceneText {
+ public:
+ Action *_action;
+ uint32 _frameNumber;
+ int _diff;
+ public:
+ Text();
+ void setup(const Common::String &msg, Action *action);
+
+ virtual Common::String getClassName() { return "BF109Text"; }
+ virtual void synchronize(Serializer &s);
+ virtual void dispatch();
+ };
+public:
+ SequenceManager _sequenceManager1, _sequenceManager2, _sequenceManager3;
+ SequenceManager _sequenceManager4, _sequenceManager5, _sequenceManager6;
+ SequenceManager _sequenceManager7, _sequenceManager8;
+ SceneObject _object1, _object2, _protaginist2, _protaginist1, _object5;
+ SceneObject _drunk, _object7, _bartender, _object9, _object10;
+ Text _text;
+ Action1 _action1;
+ Action _action2, _action3;
+public:
+ Scene109();
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+};
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
+
+#endif
diff --git a/engines/tsage/blue_force/blueforce_scenes3.cpp b/engines/tsage/blue_force/blueforce_scenes3.cpp
new file mode 100644
index 0000000000..e49037abf9
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_scenes3.cpp
@@ -0,0 +1,602 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/config-manager.h"
+#include "tsage/blue_force/blueforce_scenes3.h"
+#include "tsage/scenes.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+#include "tsage/globals.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+/*--------------------------------------------------------------------------
+ * Scene 300 - Outside Police Station
+ *
+ *--------------------------------------------------------------------------*/
+
+void Scene300::Object::startMover(CursorType action) {
+ if (action == CURSOR_TALK) {
+ Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene;
+ scene->_stripManager.start(_stripNumber, scene);
+ } else {
+ NamedObject::startMover(action);
+ }
+}
+
+void Scene300::Object17::startMover(CursorType action) {
+ if ((action != CURSOR_USE) || !BF_GLOBALS.getFlag(3)) {
+ NamedObject::startMover(action);
+ } else if ((BF_GLOBALS._v4CEA2 != 2) || (BF_GLOBALS._bikiniHutState >= 12)) {
+ Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene;
+ setAction(&scene->_action4);
+ } else {
+ SceneItem::display2(300, 33);
+ }
+}
+
+void Scene300::Item1::startMover(CursorType action) {
+ if (action == CURSOR_TALK) {
+ Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene;
+ BF_GLOBALS._player.disableControl();
+ scene->_sceneMode = 305;
+ scene->setAction(&scene->_sequenceManager1, scene, 305, &BF_GLOBALS._player,
+ &scene->_object8, NULL);
+ } else {
+ NamedHotspot::startMover(action);
+ }
+}
+
+void Scene300::Item2::startMover(CursorType action) {
+ if ((action == CURSOR_LOOK) || (action == CURSOR_USE)) {
+ Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene;
+ scene->setAction(&scene->_sequenceManager1, scene, 304, &scene->_object11, NULL);
+ } else {
+ NamedHotspot::startMover(action);
+ }
+}
+
+void Scene300::Item14::startMover(CursorType action) {
+ ADD_PLAYER_MOVER_NULL(BF_GLOBALS._player, 151, 54);
+}
+
+void Scene300::Item15::startMover(CursorType action) {
+ ADD_PLAYER_MOVER_NULL(BF_GLOBALS._player, 316, 90);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene300::Action1::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ BF_GLOBALS._player.disableControl();
+ setDelay(1);
+ break;
+ case 1:
+ if (BF_GLOBALS.getFlag(7))
+ SceneItem::display2(300, 0);
+ else
+ SceneItem::display2(666, 27);
+ setDelay(1);
+ break;
+ case 2: {
+ ADD_PLAYER_MOVER_THIS(BF_GLOBALS._player, BF_GLOBALS._player._position.x - 8,
+ BF_GLOBALS._player._position.y);
+ break;
+ }
+ case 3:
+ BF_GLOBALS._player.enableControl();
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene300::Action2::signal() {
+ switch (_actionIndex++) {
+ case 0:
+ BF_GLOBALS._player.disableControl();
+ setDelay(1);
+ break;
+ case 1:
+ SceneItem::display2(300, 28);
+ setDelay(1);
+ break;
+ case 2: {
+ ADD_MOVER(BF_GLOBALS._player, BF_GLOBALS._player._position.x + 8,
+ BF_GLOBALS._player._position.y);
+ break;
+ }
+ case 3:
+ BF_GLOBALS._player.enableControl();
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene300::Action3::signal() {
+ Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ BF_GLOBALS._player.disableControl();
+ setDelay(1);
+ break;
+ case 1:
+ BF_GLOBALS._player.setAction(&scene->_sequenceManager1, this, 306, &BF_GLOBALS._player,
+ &scene->_object8, NULL);
+ break;
+ case 2:
+ SceneItem::display2(300, 35);
+ setDelay(1);
+ break;
+ case 3:
+ BF_GLOBALS._player.enableControl();
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene300::Action4::signal() {
+ Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ BF_GLOBALS._player.disableControl();
+ setDelay(1);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager1, this, 316, &BF_GLOBALS._player, &scene->_object19, NULL);
+ break;
+ case 2:
+ BF_GLOBALS._sceneManager.changeScene(15);
+ break;
+ case 3:
+ setAction(&scene->_sequenceManager1, this, 319, &scene->_object19, NULL);
+ break;
+ case 4:
+ BF_GLOBALS.setFlag(2);
+ BF_GLOBALS._sceneManager.changeScene(190);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene300::Action5::signal() {
+ Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ BF_GLOBALS._player.disableControl();
+ scene->_field2760 = 1;
+ setDelay(1);
+ break;
+ case 1:
+ setAction(&scene->_sequenceManager1, this, 1306, &scene->_object1, &scene->_object8, NULL);
+ break;
+ case 2:
+ scene->_stripManager.start(3004, this);
+ BF_GLOBALS._sceneManager.changeScene(15);
+ break;
+ case 3: {
+ ADD_PLAYER_MOVER_NULL(BF_GLOBALS._player, 186, 140);
+ break;
+ }
+ case 4:
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene300::Scene300(): SceneExt(), _object13(3000), _object14(3001), _object15(3002),
+ _object16(3003) {
+ _field2760 = _field2762 = 0;
+}
+
+void Scene300::postInit(SceneObjectList *OwnerList) {
+ SceneExt::postInit();
+ loadScene(300);
+
+ // Add the speakers
+ _stripManager.addSpeaker(&_gameTextSpeaker);
+ _stripManager.addSpeaker(&_sutterSpeaker);
+ _stripManager.addSpeaker(&_dougSpeaker);
+ _stripManager.addSpeaker(&_jakeSpeaker);
+
+ _field2762 = 0;
+ _item14.setup(Rect(144, 27, 160, 60), 300, -1, -1, -1, 1, NULL);
+ _item15.setup(Rect(310, 76, SCREEN_WIDTH, 105), 300, -1, -1, -1, 1, NULL);
+
+ // Setup the player
+ int playerVisage = BF_GLOBALS._player._visage;
+ BF_GLOBALS._player.postInit();
+ BF_GLOBALS._player.setVisage(playerVisage);
+ BF_GLOBALS._player.setStrip(3);
+ BF_GLOBALS._player.setPosition(Common::Point(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2));
+ BF_GLOBALS._player.setObjectWrapper(new SceneObjectWrapper());
+ BF_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+ BF_GLOBALS._player._moveDiff = Common::Point(3, 1);
+ BF_GLOBALS._player.disableControl();
+
+ _object8.setStrip(2);
+ _object8.setPosition(Common::Point(300, 77));
+
+ if ((BF_GLOBALS._v4CEA2 != 2) || (BF_GLOBALS._bikiniHutState < 12)) {
+ _object17.postInit();
+ _object17.setVisage(301);
+ _object17.setStrip(1);
+ _object17.setPosition(Common::Point(87, 88));
+ _object17.setup(300, 11, 13, 2, 1, NULL);
+
+ _object18.postInit();
+ _object18.setVisage(301);
+ _object18.setStrip(1);
+ _object18.setPosition(Common::Point(137, 92));
+ _object18.setup(300, 11, 13, 3, 1, NULL);
+ }
+
+ _object19.postInit();
+ _object19.setVisage(301);
+ _object19.setStrip(1);
+ _object19.setPosition(Common::Point(175, 99));
+ _object19.setup(300, 11, 13, 34, 1, NULL);
+
+ _object11.postInit();
+ _object11.setVisage(301);
+ _object11.setStrip(8);
+ _object11.setPosition(Common::Point(265, 91));
+ _object11.hide();
+
+ //***DEBUG***
+BF_GLOBALS.setFlag(2);
+BF_GLOBALS._sceneManager._previousScene = 190;
+BF_GLOBALS._player.setVisage(190);
+
+ switch (BF_GLOBALS._sceneManager._previousScene) {
+ case 50:
+ case 60:
+ BF_GLOBALS.clearFlag(2);
+ if (BF_GLOBALS.getFlag(3)) {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 318;
+ setAction(&_sequenceManager1, this, 318, &BF_GLOBALS._player, &_object19, NULL);
+ } else {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 300;
+ setAction(&_sequenceManager1, this, 1300, &BF_GLOBALS._player, NULL);
+ }
+ break;
+ case 190:
+ _sceneMode = 0;
+ if (!BF_GLOBALS.getFlag(2)) {
+ _sceneMode = 7308;
+ BF_GLOBALS._player.setPosition(Common::Point(175, 50));
+ ADD_PLAYER_MOVER_THIS(BF_GLOBALS._player, 123, 71);
+
+ if ((BF_GLOBALS._v4CEA2 == 2) && (BF_GLOBALS._bikiniHutState < 12))
+ setup();
+ } else if (!BF_GLOBALS.getFlag(3)) {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 300;
+ setAction(&_sequenceManager1, this, 300, &BF_GLOBALS._player, NULL);
+ } else {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 318;
+ setAction(&_sequenceManager1, this, 318, &BF_GLOBALS._player, &_object19, NULL);
+ }
+ break;
+ case 315:
+ BF_GLOBALS._player.setPosition(Common::Point(305, 66));
+ if ((BF_GLOBALS._v4CEA2 != 2) || (BF_GLOBALS._bikiniHutState >= 12)) {
+ BF_GLOBALS._player.setVisage(BF_GLOBALS.getFlag(3) ? 1304 : 303);
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 0;
+ setAction(&_sequenceManager1, this, 306, &BF_GLOBALS._player, &_object8, NULL);
+ } else {
+ BF_GLOBALS._player.setVisage(1304);
+ setup();
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 0;
+ setAction(&_sequenceManager1, this, 306, &BF_GLOBALS._player, &_object8, NULL);
+ }
+ break;
+ default:
+ _sceneMode = 0;
+ BF_GLOBALS._player.setVisage(1304);
+ BF_GLOBALS._player.disableControl();
+ setAction(&_sequenceManager1, this, 306, &BF_GLOBALS._player, &_object8, NULL);
+ break;
+ }
+}
+
+void Scene300::signal() {
+ switch (_sceneMode) {
+ case 300:
+ BF_GLOBALS._sound1.fadeSound(33);
+ BF_GLOBALS.clearFlag(2);
+ _sceneMode = 0;
+
+ if ((BF_GLOBALS._v4CEA2 != 1) || (BF_GLOBALS._bikiniHutState != 0)) {
+ signal();
+ } else {
+ _stripManager.start(3005, this);
+ }
+ break;
+ case 301:
+ if (_field2760) {
+ _sceneMode = 1302;
+ signal();
+ } else {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 1302;
+ setAction(&_sequenceManager1, this, 306, &_object1, &_object8, NULL);
+ }
+
+ _object12.show();
+ _object5.dispatch();
+ BF_GLOBALS._player.hide();
+ break;
+ case 303:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 2307;
+ setAction(&_sequenceManager1, this, 303, &_object13, &_object1, NULL);
+ break;
+ case 305:
+ if ((BF_GLOBALS._v4CEA2 == 4) || (BF_GLOBALS._v4CEA2 == 5)) {
+ _sceneMode = 0;
+ setAction(&_action3);
+ } else {
+ BF_GLOBALS._sound1.fadeOut2(NULL);
+ BF_GLOBALS._sceneManager.changeScene(315);
+ }
+ break;
+ case 309:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 3307;
+ setAction(&_sequenceManager1, this, 309, &_object14, &_object1, NULL);
+ break;
+ case 310:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 4307;
+ setAction(&_sequenceManager1, this, 310, &_object12, &_object1, NULL);
+ break;
+ case 311:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 5307;
+ setAction(&_sequenceManager1, this, 311, &_object15, &_object1, NULL);
+ break;
+ case 312:
+ case 5307:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 1305;
+ setAction(&_sequenceManager1, this, 312, &_object1, &_object16, NULL);
+ break;
+ case 317:
+ BF_GLOBALS.setFlag(2);
+ BF_GLOBALS._sceneManager.changeScene(60);
+ break;
+ case 318:
+ BF_GLOBALS.clearFlag(2);
+ _sceneMode = 0;
+ signal();
+ break;
+ case 1302:
+ _field2762 = 0;
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 1308;
+ setAction(&_sequenceManager1, this, 302, &_object1, NULL);
+ break;
+ case 1305:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 1313;
+ setAction(&_sequenceManager1, this, 305, &_object1, &_object8, NULL);
+ BF_GLOBALS._player.show();
+ _object12.hide();
+ break;
+ case 1307:
+ case 2308:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 303;
+ setAction(&_sequenceManager1, this, 308, &_object14, NULL);
+ break;
+ case 1308:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 1307;
+ setAction(&_sequenceManager1, this, 308, &_object13, NULL);
+ break;
+ case 1313:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 0;
+ _object15.setAction(&_sequenceManager4, NULL, 315, &_object15, &_object16, NULL);
+ _object13.setAction(&_sequenceManager2, NULL, 313, &_object13, &_object17, NULL);
+ _object14.setAction(&_sequenceManager3, this, 314, &_object14, &_object18, NULL);
+
+ BF_GLOBALS._bikiniHutState = 12;
+ BF_GLOBALS._sound1.changeSound(33);
+ break;
+ case 2307:
+ case 3308:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 309;
+ setAction(&_sequenceManager1, this, 308, &_object12, NULL);
+ break;
+ case 3307:
+ _object9.postInit();
+ _object9.hide();
+ _object10.postInit();
+ _object10.hide();
+
+ if (BF_GLOBALS.getFlag(1)) {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 4308;
+ setAction(&_sequenceManager1, this, 6307, &_object2, &_object1, &_object9, &_object10, NULL);
+ } else {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 4308;
+ setAction(&_sequenceManager1, this, 7307, &_object12, &_object1, &_object9, &_object10, NULL);
+ }
+ break;
+ case 4307:
+ case 5308:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 311;
+ setAction(&_sequenceManager1, this, 308, &_object16, NULL);
+ break;
+ case 4308:
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 310;
+ setAction(&_sequenceManager1, this, 308, &_object15, NULL);
+ break;
+ case 6308:
+ BF_GLOBALS._sceneManager.changeScene(190);
+ break;
+ case 7308:
+ if (_field2762) {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 301;
+ setAction(&_sequenceManager1, this, 301, &BF_GLOBALS._player, NULL);
+ } else {
+ BF_GLOBALS._player.enableControl();
+ }
+ break;
+ case 0:
+ default:
+ if (_field2762) {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 301;
+ setAction(&_sequenceManager1, this, 301, &BF_GLOBALS._player, NULL);
+ } else {
+ BF_GLOBALS._player.enableControl();
+ }
+ break;
+ }
+}
+
+void Scene300::process(Event &event) {
+ if ((BF_GLOBALS._player._field8E != 0) && !_eventHandler && (event.mousePos.y < (BF_INTERFACE_Y - 1))) {
+ Visage visage;
+
+ if (_item14.contains(event.mousePos)) {
+ visage.setVisage(1, 8);
+ GfxSurface surface = visage.getFrame(2);
+ BF_GLOBALS._events.setCursor(surface);
+ } else if (_item15.contains(event.mousePos)) {
+ visage.setVisage(1, 8);
+ GfxSurface surface = visage.getFrame(3);
+ BF_GLOBALS._events.setCursor(surface);
+ } else {
+ CursorType cursorId = BF_GLOBALS._events.hideCursor();
+ BF_GLOBALS._events.setCursor(cursorId);
+ }
+ }
+}
+
+void Scene300::dispatch() {
+ SceneExt::dispatch();
+
+ if (_action) {
+ int regionIndex = BF_GLOBALS._player.getRegionIndex();
+ if ((regionIndex == 1) && (_field2762 == 1)) {
+ BF_GLOBALS._player.disableControl();
+ _sceneMode = 301;
+ setAction(&_sequenceManager1, this, 301, &BF_GLOBALS._player, NULL);
+ }
+
+ if ((BF_GLOBALS._player._position.y < 59) && (BF_GLOBALS._player._position.x > 137) &&
+ (_sceneMode != 6308) && (_sceneMode != 7308)) {
+ BF_GLOBALS._v4CEA4 = 3;
+ _sceneMode = 6308;
+ BF_GLOBALS._player.disableControl();
+ ADD_MOVER(BF_GLOBALS._player, BF_GLOBALS._player._position.x + 20,
+ BF_GLOBALS._player._position.y - 5);
+ }
+ }
+}
+
+void Scene300::setup() {
+ _object13.postInit();
+ _object13.setVisage(307);
+ _object13.setStrip(6);
+ _object13.setPosition(Common::Point(156, 134));
+ _object13._moveDiff = Common::Point(3, 1);
+ _object3.setup(&_object13, 306, 1, 29);
+
+ _object14.postInit();
+ _object14.setVisage(307);
+ _object14.setStrip(6);
+ _object14.setPosition(Common::Point(171, 137));
+ _object14._moveDiff = Common::Point(3, 1);
+ _object4.setup(&_object14, 306, 2, 29);
+
+ _object12.postInit();
+ _object12.setVisage(307);
+ _object12.setStrip(6);
+ _object12.setPosition(Common::Point(186, 140));
+ _object12._moveDiff = Common::Point(3, 1);
+ _object5.setup(&_object12, 306, 2, 29);
+ _object12.hide();
+
+ _object15.postInit();
+ _object15.setVisage(307);
+ _object15.setStrip(6);
+ _object15.setPosition(Common::Point(201, 142));
+ _object15._moveDiff = Common::Point(3, 1);
+ _object6.setup(&_object15, 306, 3, 29);
+
+ _object16.postInit();
+ _object16.setVisage(307);
+ _object16.setStrip(6);
+ _object16.setPosition(Common::Point(216, 145));
+ _object16._moveDiff = Common::Point(3, 1);
+ _object7.setup(&_object16, 306, 1, 29);
+
+ _object1.postInit();
+ _object1.setVisage(307);
+ _object1.setStrip(6);
+ _object1.setPosition(Common::Point(305, 66));
+ _object1._moveDiff = Common::Point(3, 1);
+ _object1.setObjectWrapper(new SceneObjectWrapper());
+ _object1.animate(ANIM_MODE_1, NULL);
+ _object2.setup(&_object1, 306, 4, 9);
+
+ BF_GLOBALS._sceneItems.addItems(&_object13, &_object14, &_object15, &_object16, NULL);
+ _timer.set(3600, this, &_action5);
+
+ _field2760 = 0;
+ _field2762 = 1;
+}
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/blue_force/blueforce_scenes3.h b/engines/tsage/blue_force/blueforce_scenes3.h
new file mode 100644
index 0000000000..42ae69fc3f
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_scenes3.h
@@ -0,0 +1,137 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TSAGE_BLUEFORCE_SCENES3_H
+#define TSAGE_BLUEFORCE_SCENES3_H
+
+#include "common/scummsys.h"
+#include "tsage/blue_force/blueforce_logic.h"
+#include "tsage/converse.h"
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+#include "tsage/sound.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+using namespace TsAGE;
+
+class Scene300: public SceneExt {
+ /* Objects */
+ class Object: public NamedObject {
+ public:
+ int _stripNumber;
+ public:
+ Object(int stripNumber) { _stripNumber = stripNumber; }
+
+ virtual void startMover(CursorType action);
+ };
+ class Object17: public NamedObject {
+ public:
+ virtual void startMover(CursorType action);
+ };
+
+ /* Items */
+ class Item1: public NamedHotspot {
+ public:
+ virtual void startMover(CursorType action);
+ };
+ class Item2: public NamedHotspot {
+ public:
+ virtual void startMover(CursorType action);
+ };
+ class Item14: public NamedHotspot {
+ public:
+ virtual void startMover(CursorType action);
+ };
+ class Item15: public NamedHotspot {
+ public:
+ virtual void startMover(CursorType 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();
+ };
+ class Action4: public Action {
+ public:
+ virtual void signal();
+ };
+ class Action5: public Action {
+ public:
+ virtual void signal();
+ };
+private:
+ void setup();
+public:
+ SequenceManager _sequenceManager1, _sequenceManager2;
+ SequenceManager _sequenceManager3, _sequenceManager4;
+ NamedObject _object1;
+ FollowerObject _object2, _object3, _object4, _object5, _object6, _object7;
+ SceneObject _object8, _object9, _object10;
+ NamedObject _object11, _object12;
+ Object _object13, _object14, _object15, _object16;
+ Object17 _object17;
+ NamedObject _object18, _object19;
+ Item1 _item1;
+ Item2 _item2;
+ NamedHotspot _item3, _item4, _item5, _item6, _item7;
+ NamedHotspot _item8, _item9, _item10, _item11;
+ NamedHotspot _item12, _item13;
+ Item14 _item14;
+ Item15 _item15;
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ SpeakerGameText _gameTextSpeaker;
+ SpeakerSutter _sutterSpeaker;
+ SpeakerDoug _dougSpeaker;
+ SpeakerJakeNoHead _jakeSpeaker;
+ TimerExt _timer;
+ int _field2760, _field2762;
+
+ Scene300();
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void process(Event &event);
+ virtual void dispatch();
+};
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
+
+#endif
diff --git a/engines/tsage/blue_force/blueforce_ui.cpp b/engines/tsage/blue_force/blueforce_ui.cpp
new file mode 100644
index 0000000000..e27c744486
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_ui.cpp
@@ -0,0 +1,366 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "tsage/blue_force/blueforce_ui.h"
+#include "tsage/blue_force/blueforce_logic.h"
+#include "tsage/tsage.h"
+#include "tsage/core.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+void UIElement::synchronize(Serializer &s) {
+ AltSceneObject::synchronize(s);
+ s.syncAsSint16LE(_field88);
+ s.syncAsSint16LE(_enabled);
+ s.syncAsSint16LE(_frameNum);
+}
+
+void UIElement::setup(int visage, int stripNum, int frameNum, int posX, int posY, int priority) {
+ _field88 = 0;
+ _frameNum = frameNum;
+ _enabled = true;
+
+ SceneObject::setup(visage, stripNum, frameNum, posX, posY, priority);
+}
+
+void UIElement::setEnabled(bool flag) {
+ if (_enabled != flag) {
+ _enabled = flag;
+ setFrame(_enabled ? _frameNum : _frameNum + 2);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void UIQuestion::process(Event &event) {
+ if (event.eventType == EVENT_BUTTON_DOWN) {
+ int currentCursor = GLOBALS._events.getCursor();
+ GLOBALS._events.hideCursor();
+ showDescription(currentCursor);
+
+ event.handled = true;
+ }
+}
+
+void UIQuestion::showDescription(int lineNum) {
+ if (lineNum == 8) {
+ // Unknown object description
+ } else {
+ // Display object description
+ SceneItem::display2(9001, lineNum);
+ }
+}
+
+void UIQuestion::setEnabled(bool flag) {
+ if (_enabled != flag) {
+ UIElement::setEnabled(flag);
+ BF_GLOBALS._uiElements.draw();
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void UIScore::postInit(SceneObjectList *OwnerList) {
+ int xp = 266;
+ _digit3.setup(1, 6, 1, 266, 180, 255);
+ xp += 7;
+ _digit2.setup(1, 6, 1, 266, 180, 255);
+ xp += 7;
+ _digit1.setup(1, 6, 1, 266, 180, 255);
+ xp += 7;
+ _digit0.setup(1, 6, 1, 266, 180, 255);
+}
+
+void UIScore::draw() {
+ _digit3.draw();
+ _digit2.draw();
+ _digit1.draw();
+ _digit0.draw();
+}
+
+void UIScore::updateScore() {
+ int score = BF_GLOBALS._uiElements._scoreValue;
+
+ _digit3.setFrame(score / 1000); score %= 1000;
+ _digit2.setFrame(score / 100); score %= 100;
+ _digit1.setFrame(score / 10); score %= 10;
+ _digit0.setFrame(score);
+}
+
+/*--------------------------------------------------------------------------*/
+
+UIInventorySlot::UIInventorySlot(): UIElement() {
+ _objIndex = 0;
+}
+
+void UIInventorySlot::synchronize(Serializer &s) {
+ UIElement::synchronize(s);
+ s.syncAsSint16LE(_objIndex);
+}
+
+void UIInventorySlot::process(Event &event) {
+ if (event.eventType == EVENT_BUTTON_DOWN) {
+ event.handled = true;
+
+ if (_objIndex == 66) {
+ // Handle showing gun and ammo
+ warning("TODO: show gun");
+ } else if (_objIndex != 0) {
+ GLOBALS._events.setCursor((CursorType)_objIndex);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+UIInventoryScroll::UIInventoryScroll() {
+ _isLeft = false;
+}
+
+void UIInventoryScroll::synchronize(Serializer &s) {
+ UIElement::synchronize(s);
+ s.syncAsSint16LE(_isLeft);
+}
+
+void UIInventoryScroll::process(Event &event) {
+ if (event.eventType == EVENT_BUTTON_DOWN) {
+ warning("TODO: UIInventoryScroll::process");
+ event.handled = true;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+UICollection::UICollection(): EventHandler() {
+ _clearScreen = false;
+ _visible = false;
+ _field4E = 0;
+}
+
+void UICollection::setup(const Common::Point &pt) {
+ _position = pt;
+ _bounds.left = _bounds.right = pt.x;
+ _bounds.top = _bounds.bottom = pt.y;
+}
+
+void UICollection::hide() {
+ erase();
+ _visible = false;
+}
+
+void UICollection::erase() {
+ if (_clearScreen) {
+ Rect tempRect(0, BF_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT);
+ GLOBALS._screenSurface.fillRect(tempRect, 0);
+ _clearScreen = false;
+ }
+}
+
+void UICollection::resetClear() {
+ _clearScreen = false;
+}
+
+void UICollection::draw() {
+ if (_visible) {
+ // Draw the elements
+ for (uint idx = 0; idx < _objList.size(); ++idx)
+ _objList[idx]->draw();
+
+ // Update the screen
+ g_system->updateScreen();
+ _clearScreen = 1;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void UIElements::process(Event &event) {
+ if (_clearScreen && BF_GLOBALS._player._field8E && (BF_GLOBALS._sceneManager._sceneNumber != 50)) {
+ if (_bounds.contains(event.mousePos)) {
+
+ } else if (_field4E) {
+ BF_GLOBALS._events.hideCursor();
+ BF_GLOBALS._events.setCursor((CursorType)1);
+ _field4E = 0;
+
+ SceneExt *scene = (SceneExt *)BF_GLOBALS._sceneManager._scene;
+ if (scene->_eventHandler) {
+ error("TODO: UIElements::process _eventHandler");
+ }
+ }
+ }
+}
+
+void UIElements::setup(const Common::Point &pt) {
+ _slotStart = 0;
+ _itemList.clear();
+ _scoreValue = 0;
+ _field820 = 1;
+ UICollection::setup(pt);
+ hide();
+
+ _object1.setup(1, 3, 1, 0, 0, 255);
+ add(&_object1);
+
+ // Set up the inventory slots
+ for (int idx = 0; idx < 4; ++idx) {
+ UIElement *item = NULL;
+ switch (idx) {
+ case 0:
+ item = &_slot1;
+ break;
+ case 1:
+ item = &_slot2;
+ break;
+ case 2:
+ item = &_slot3;
+ break;
+ case 3:
+ item = &_slot4;
+ break;
+ }
+
+ item->setup(9, 1, idx, idx * 63 + 2, 4, 255);
+ add(item);
+ }
+
+ // Setup bottom-right hand buttons
+ int xp = 62;
+ _question.setup(1, 4, 7, xp, 16, 255);
+ _question.setEnabled(false);
+
+ xp += 21;
+ _scrollLeft.setup(1, 4, 1, xp, 16, 255);
+ add(&_scrollLeft);
+ _scrollLeft._isLeft = true;
+
+ xp += 22;
+ _scrollRight.setup(1, 4, 4, xp, 16, 255);
+ add(&_scrollRight);
+ _scrollRight._isLeft = false;
+
+ // Set up the score
+ _score.postInit();
+ add(&_score);
+
+ // Set interface area
+ _bounds = Rect(0, BF_INTERFACE_Y - 1, SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ updateInventory();
+}
+
+void UIElements::add(UIElement *obj) {
+ // Add object
+ assert(_objList.size() < 12);
+ _objList.push_back(obj);
+
+ obj->setPosition(Common::Point(_bounds.left + obj->_bounds.left, _bounds.top + obj->_bounds.top));
+ GfxSurface s = obj->getFrame();
+ s.draw(obj->_position);
+}
+
+/**
+ * Handles updating the visual inventory in the user interface
+ */
+void UIElements::updateInventory() {
+ _score.updateScore();
+ updateInvList();
+
+ // Enable scroll buttons if the player has more than four items
+ if (_itemCount > 4) {
+ _scrollLeft.setEnabled(true);
+ _scrollRight.setEnabled(true);
+ } else {
+ _scrollLeft.setEnabled(false);
+ _scrollRight.setEnabled(false);
+ }
+
+ // Handle cropping the slots start within inventory
+ int last = (_itemList.size() - 1) / 4 + 1;
+ if (_slotStart < 0)
+ _slotStart = last - 1;
+ else if (_slotStart > (last - 1))
+ _slotStart = 0;
+
+ // Handle refreshing slot graphics
+ UIInventorySlot *slotList[4] = { &_slot1, &_slot2, &_slot3, &_slot4 };
+
+ SynchronizedList<InvObject *>::iterator i;
+ int objIndex = 0;
+ for (i = BLUE_INVENTORY._itemList.begin(); i != BLUE_INVENTORY._itemList.end(); ++i, ++objIndex) {
+ InvObject *obj = *i;
+
+ for (int slotIndex = 0; slotIndex < 4; ++slotIndex) {
+ int idx = _slotStart + slotIndex;
+ int objectIdx = (idx < (int)_itemList.size()) ? _itemList[idx] : 0;
+
+ if (objectIdx == objIndex) {
+ UIInventorySlot *slot = slotList[slotIndex];
+
+ slot->_objIndex = objIndex;
+ slot->setVisage(obj->_visage);
+ slot->setStrip(obj->_strip);
+ slot->setFrame(obj->_frame);
+ }
+ }
+ }
+
+ if (_field820)
+ draw();
+}
+
+/**
+ * Update the list of the indexes of items in the player's inventory
+ */
+void UIElements::updateInvList() {
+ // Update the index list of items in the player's inventory
+ _itemList.clear();
+
+ SynchronizedList<InvObject *>::iterator i;
+ int itemIndex = 0;
+ for (i = BF_GLOBALS._inventory->_itemList.begin(); i != BF_GLOBALS._inventory->_itemList.end(); ++i, ++itemIndex) {
+ InvObject *invObject = *i;
+ if (invObject->inInventory())
+ _itemList.push_back(itemIndex);
+ }
+}
+
+/**
+ * Updates an inventory slot with the item to be displayed
+
+void UIElements::updateInvSlot(UIInventorySlot *slot, int objIndex) {
+ slot->_objIndex = objIndex;
+ int itemId = (objIndex < (int)_itemList.size()) ? _itemList[objIndex] : 0;
+ InvObject *obj = BF_GLOBALS._inventory->_itemList[itemId + 2];
+
+ // TODO: Validate usage of fields
+ slot->setVisage(obj._displayResNum);
+ slot->setStrip(obj._rlbNum);
+ slot->setFrame(obj._cursorNum);
+}
+*/
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/blue_force/blueforce_ui.h b/engines/tsage/blue_force/blueforce_ui.h
new file mode 100644
index 0000000000..15e7a760d9
--- /dev/null
+++ b/engines/tsage/blue_force/blueforce_ui.h
@@ -0,0 +1,135 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TSAGE_BLUEFORCE_UI_H
+#define TSAGE_BLUEFORCE_UI_H
+
+#include "common/scummsys.h"
+#include "tsage/core.h"
+#include "tsage/sound.h"
+
+namespace TsAGE {
+
+namespace BlueForce {
+
+using namespace TsAGE;
+
+class UIElement: public AltSceneObject {
+public:
+ int _field88;
+ bool _enabled;
+ int _frameNum;
+
+ virtual Common::String getClassName() { return "UIElement"; }
+ virtual void synchronize(Serializer &s);
+
+ void setup(int visage, int stripNum, int frameNum, int posX, int posY, int priority);
+ void setEnabled(bool flag);
+};
+
+// This class implements the Question mark button
+class UIQuestion: public UIElement {
+private:
+ void showDescription(int lineNum);
+public:
+ virtual void process(Event &event);
+ void setEnabled(bool flag);
+};
+
+// This class implements the score counter
+class UIScore: public UIElement {
+private:
+ void showDescription(int lineNum);
+public:
+ UIElement _digit3, _digit2, _digit1, _digit0;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void draw();
+
+ void updateScore();
+};
+
+class UIInventorySlot: public UIElement {
+public:
+ int _objIndex;
+
+ UIInventorySlot();
+ virtual Common::String getClassName() { return "UIInventorySlot"; }
+ virtual void synchronize(Serializer &s);
+ virtual void process(Event &event);
+};
+
+class UIInventoryScroll: public UIElement {
+public:
+ bool _isLeft;
+
+ UIInventoryScroll();
+ virtual Common::String getClassName() { return "UIInventoryScroll"; }
+ virtual void synchronize(Serializer &s);
+ virtual void process(Event &event);
+};
+
+class UICollection: public EventHandler {
+protected:
+ void erase();
+public:
+ Common::Point _position;
+ Rect _bounds;
+ bool _visible;
+ bool _clearScreen;
+ int _field4E;
+ Common::Array<UIElement *> _objList;
+
+ UICollection();
+ void setup(const Common::Point &pt);
+ void hide();
+ void resetClear();
+ void draw();
+};
+
+class UIElements: public UICollection {
+private:
+ void add(UIElement *obj);
+ void updateInventory();
+ void updateInvList();
+public:
+ UIElement _object1;
+ UIQuestion _question;
+ UIScore _score;
+ UIInventorySlot _slot1, _slot2, _slot3, _slot4;
+ UIInventoryScroll _scrollLeft, _scrollRight;
+ ASound _sound;
+ int _itemCount, _slotStart, _scoreValue;
+ bool _field820;
+ Common::Array<int> _itemList;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL) { error("Wrong init() called"); }
+ virtual void process(Event &event);
+
+ void setup(const Common::Point &pt);
+};
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
+
+#endif
diff --git a/engines/tsage/blueforce_logic.cpp b/engines/tsage/blueforce_logic.cpp
deleted file mode 100644
index d266d5e1d9..0000000000
--- a/engines/tsage/blueforce_logic.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "tsage/blueforce_logic.h"
-#include "tsage/scenes.h"
-#include "tsage/tsage.h"
-#include "tsage/staticres.h"
-
-namespace tSage {
-
-void BlueForceGame::start() {
- // Start the game
- _globals->_sceneManager.changeScene(20);
-
- _globals->_events.setCursor(CURSOR_WALK);
-}
-
-Scene *BlueForceGame::createScene(int sceneNumber) {
- switch (sceneNumber) {
- case 20:
- case 50:
- case 60:
- error("Scene group 0 not implemented");
- case 100:
- case 109:
- case 110:
- case 114:
- case 115:
- case 125:
- case 140:
- case 150:
- case 160:
- case 180:
- case 190:
- error("Scene group 1 not implemented");
- case 200:
- case 210:
- case 220:
- case 225:
- case 265:
- case 270:
- case 271:
- case 280:
- error("Scene group 2 not implemented");
- case 300:
- case 315:
- case 325:
- case 330:
- case 340:
- case 342:
- case 350:
- case 355:
- case 360:
- case 370:
- case 380:
- case 385:
- case 390:
- error("Scene group 3 not implemented");
- case 410:
- case 415:
- case 440:
- case 450:
- error("Scene group 4 not implemented");
- case 550:
- case 551:
- case 560:
- case 570:
- case 580:
- case 590:
- error("Scene group 5 not implemented");
- case 600:
- case 620:
- case 666:
- case 690:
- error("Scene group 6 not implemented");
- case 710:
- error("Scene group 7 not implemented");
- case 800:
- case 810:
- case 820:
- case 830:
- case 840:
- case 850:
- case 860:
- case 870:
- case 880:
- error("Scene group 8 not implemented");
- case 900:
- case 910:
- case 920:
- case 930:
- case 935:
- case 940:
- error("Scene group 9 not implemented");
- default:
- error("Unknown scene number - %d", sceneNumber);
- break;
- }
-}
-
-} // End of namespace tSage
diff --git a/engines/tsage/converse.cpp b/engines/tsage/converse.cpp
index 0ae575c557..615b1c36fd 100644
--- a/engines/tsage/converse.cpp
+++ b/engines/tsage/converse.cpp
@@ -26,7 +26,7 @@
#include "tsage/globals.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
#define STRIP_WORD_DELAY 30
@@ -34,7 +34,7 @@ namespace tSage {
SequenceManager::SequenceManager() : Action() {
Common::set_to(&_objectList[0], &_objectList[6], (SceneObject *)NULL);
_sequenceData.clear();
- _field24 = 0;
+ _fontNum = 0;
_sequenceOffset = 0;
_resNum = 0;
_field26 = 0;
@@ -56,7 +56,7 @@ void SequenceManager::synchronize(Serializer &s) {
s.syncAsSint32LE(_resNum);
s.syncAsSint32LE(_sequenceOffset);
s.syncAsByte(_keepActive);
- s.syncAsSint32LE(_field24);
+ s.syncAsSint32LE(_fontNum);
s.syncAsSint32LE(_field26);
s.syncAsSint32LE(_objectIndex);
@@ -284,6 +284,32 @@ void SequenceManager::signal() {
_objectList[objIndex3], _objectList[objIndex4], _objectList[objIndex5], _objectList[objIndex6], NULL);
break;
}
+ /* Following indexes were introduced for Blue Force */
+ case 35:
+ v1 = getNextValue();
+ _sceneObject->updateAngle(_objectList[v1]);
+ break;
+ case 36:
+ _sceneObject->animate(ANIM_MODE_9, NULL);
+ break;
+ case 37:
+ v1 = getNextValue();
+ v2 = getNextValue();
+ warning("TODO: dword_53030(%d,%d)", v1, v2);
+ break;
+ case 38: {
+ int resNum = getNextValue();
+ int lineNum = getNextValue();
+ int fontNum = getNextValue();
+ int color1 = getNextValue();
+ int color2 = getNextValue();
+ int color3 = getNextValue();
+ int xp = getNextValue();
+ int yp = getNextValue();
+ int width = getNextValue();
+ setMessage(resNum, lineNum, fontNum, color1, color2, color3, Common::Point(xp, yp), width);
+ break;
+ }
default:
error("SequenceManager::signal - Unknown action %d at offset %xh", idx, _sequenceOffset - 2);
break;
@@ -337,10 +363,15 @@ uint16 SequenceManager::getNextValue() {
}
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;
+ setMessage(resNum, lineNum, 2, color, 0, 0, pt, width);
+}
+
+void SequenceManager::setMessage(int resNum, int lineNum, int fontNum, int color1, int color2, int color3,
+ const Common::Point &pt, int width) {
+ _sceneText._color1 = color1;
+ _sceneText._color2 = color2;
+ _sceneText._color3 = color3;
+ _sceneText._fontNumber = fontNum;
_sceneText._width = width;
// Get the display message
@@ -954,4 +985,4 @@ void AnimatedSpeaker::removeText() {
_objectList.draw();
}
-} // end of namespace tSage
+} // end of namespace TsAGE
diff --git a/engines/tsage/converse.h b/engines/tsage/converse.h
index 13c490e995..e263a12d12 100644
--- a/engines/tsage/converse.h
+++ b/engines/tsage/converse.h
@@ -27,7 +27,7 @@
#include "tsage/dialogs.h"
#include "tsage/sound.h"
-namespace tSage {
+namespace TsAGE {
class StripCallback : public Action {
public:
@@ -39,13 +39,15 @@ private:
void setup();
uint16 getNextValue();
void setMessage(int resNum, int lineNum, int color, const Common::Point &pt, int width);
+ void setMessage(int resNum, int lineNum, int fontNum, int color1, int color2, int color3,
+ const Common::Point &pt, int width);
SequenceManager *globalManager();
public:
SceneText _sceneText;
int _resNum;
uint _sequenceOffset;
bool _keepActive;
- int _field24;
+ int _fontNum;
int _field26;
Common::Array<byte> _sequenceData;
int _objectIndex;
@@ -222,6 +224,6 @@ public:
void addSpeaker(Speaker *speaker);
};
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index d0075d5acf..3a489e0024 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -33,7 +33,7 @@
#include "tsage/globals.h"
#include "tsage/sound.h"
-namespace tSage {
+namespace TsAGE {
// The engine uses ScumMVM screen buffering, so all logic is hardcoded to use pane buffer 0
#define CURRENT_PANENUM 0
@@ -55,6 +55,13 @@ InvObject::InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType curs
DEALLOCATE(imgData);
}
+InvObject::InvObject(int visage, int strip, int frame, int sceneNumber) {
+ _visage = visage;
+ _strip = strip;
+ _frame = frame;
+ _sceneNumber = sceneNumber;
+}
+
void InvObject::setCursor() {
_globals->_events._currentCursor = _cursorId;
@@ -1161,6 +1168,20 @@ void PaletteFader::remove() {
action->signal();
}
+void PaletteFader::setPalette(ScenePalette *palette, int step) {
+ if (step < 0) {
+ // Reverse step means moving from dest palette to source, so swap the two palettes
+ byte tempPal[256 * 3];
+ Common::copy(&palette->_palette[0], &palette->_palette[256 * 3], &tempPal[0]);
+ Common::copy(&this->_palette[0], &this->_palette[256 * 3], &palette->_palette[0]);
+ Common::copy(&tempPal[0], &tempPal[256 * 3], &this->_palette[0]);
+
+ step = -step;
+ }
+
+ PaletteModifierCached::setPalette(palette, step);
+}
+
/*--------------------------------------------------------------------------*/
ScenePalette::ScenePalette() {
@@ -1314,7 +1335,7 @@ PaletteRotation *ScenePalette::addRotation(int start, int end, int rotationMode,
return obj;
}
-PaletteFader *ScenePalette::addFader(const byte *arrBufferRGB, int palSize, int percent, Action *action) {
+PaletteFader *ScenePalette::addFader(const byte *arrBufferRGB, int palSize, int step, Action *action) {
PaletteFader *fader = new PaletteFader();
fader->_action = action;
for (int i = 0; i < 256 * 3; i += 3) {
@@ -1326,7 +1347,7 @@ PaletteFader *ScenePalette::addFader(const byte *arrBufferRGB, int palSize, int
arrBufferRGB += 3;
}
- fader->setPalette(this, percent);
+ fader->setPalette(this, step);
_globals->_scenePalette._listeners.push_back(fader);
return fader;
}
@@ -1562,6 +1583,17 @@ void SceneItem::display(int resNum, int lineNum, ...) {
}
}
+void SceneItem::display2(int resNum, int lineNum) {
+ if (_vm->getGameID() == GType_BlueForce)
+ display(resNum, lineNum, SET_WIDTH, 312,
+ SET_X, 4 + GLOBALS._sceneManager._scene->_sceneBounds.left,
+ SET_Y, GLOBALS._sceneManager._scene->_sceneBounds.top + BF_INTERFACE_Y + 2,
+ SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 19, SET_EXT_BGCOLOR, 9,
+ SET_EXT_FGCOLOR, 13, LIST_END);
+ else
+ display(resNum, lineNum, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+}
+
/*--------------------------------------------------------------------------*/
void SceneHotspot::doAction(int action) {
@@ -1585,6 +1617,11 @@ void SceneHotspot::doAction(int action) {
/*--------------------------------------------------------------------------*/
+NamedHotspot::NamedHotspot() : SceneHotspot() {
+ _resNum = 0;
+ _lookLineNum = _useLineNum = _talkLineNum = -1;
+}
+
void NamedHotspot::doAction(int action) {
switch (action) {
case CURSOR_WALK:
@@ -1594,13 +1631,19 @@ void NamedHotspot::doAction(int action) {
if (_lookLineNum == -1)
SceneHotspot::doAction(action);
else
- SceneItem::display(_resnum, _lookLineNum, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ 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);
+ SceneItem::display(_resNum, _useLineNum, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
+ break;
+ case CURSOR_TALK:
+ if (_talkLineNum == -1)
+ SceneHotspot::doAction(action);
+ else
+ SceneItem::display2(_resNum, _talkLineNum);
break;
default:
SceneHotspot::doAction(action);
@@ -1610,17 +1653,52 @@ void NamedHotspot::doAction(int action) {
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;
+ _resNum = resnum;
_lookLineNum = lookLineNum;
_useLineNum = useLineNum;
+ _talkLineNum = -1;
_globals->_sceneItems.addItems(this, NULL);
}
+void NamedHotspot::setup(const Rect &bounds, int resNum, int lookLineNum, int talkLineNum, int useLineNum, int mode, SceneItem *item) {
+ setBounds(bounds);
+ _resNum = resNum;
+ _lookLineNum = lookLineNum;
+ _talkLineNum = talkLineNum;
+ _useLineNum = useLineNum;
+
+ switch (mode) {
+ case 2:
+ _globals->_sceneItems.push_front(this);
+ break;
+ case 4:
+ _globals->_sceneItems.addBefore(item, this);
+ break;
+ case 5:
+ _globals->_sceneItems.addAfter(item, this);
+ break;
+ default:
+ _globals->_sceneItems.push_back(this);
+ break;
+ }
+}
+
+void NamedHotspot::setup(int sceneRegionId, int resNum, int lookLineNum, int talkLineNum, int useLineNum, int mode) {
+ _sceneRegionId = sceneRegionId;
+ _resNum = resNum;
+ _lookLineNum = lookLineNum;
+ _talkLineNum = talkLineNum;
+ _useLineNum = useLineNum;
+}
+
void NamedHotspot::synchronize(Serializer &s) {
SceneHotspot::synchronize(s);
- s.syncAsSint16LE(_resnum);
+ s.syncAsSint16LE(_resNum);
s.syncAsSint16LE(_lookLineNum);
s.syncAsSint16LE(_useLineNum);
+
+ if (_vm->getGameID() == GType_BlueForce)
+ s.syncAsSint16LE(_talkLineNum);
}
/*--------------------------------------------------------------------------*/
@@ -1641,6 +1719,11 @@ void SceneObjectWrapper::remove() {
}
void SceneObjectWrapper::dispatch() {
+ if (_vm->getGameID() == GType_Ringworld)
+ check();
+}
+
+void SceneObjectWrapper::check() {
_visageImages.setVisage(_sceneObject->_visage);
int frameCount = _visageImages.getFrameCount();
int angle = _sceneObject->_angle;
@@ -1699,6 +1782,7 @@ SceneObject::SceneObject() : SceneHotspot() {
_sceneRegionId = 0;
_percent = 100;
_flags |= OBJFLAG_PANES;
+ _priority = 0;
_frameChange = 0;
_visage = 0;
@@ -1988,6 +2072,7 @@ void SceneObject::animate(AnimateMode animMode, ...) {
break;
case ANIM_MODE_8:
+ case ANIM_MODE_9:
_field68 = va_arg(va, int);
_endAction = va_arg(va, Action *);
_frameChange = 1;
@@ -2174,7 +2259,25 @@ void SceneObject::dispatch() {
} else {
setFrame(changeFrame());
}
+ break;
+
+ case ANIM_MODE_9:
+ if (_frame == _endFrame) {
+ if (_frameChange != -1) {
+ _frameChange = -1;
+ _strip = ((_strip - 1) ^ 1) + 1;
+ _endFrame = 1;
+ } else if ((_field68 == 0) || (--_field68 != 0)) {
+ _frameChange = 1;
+ _endFrame = getFrameCount();
+ setFrame(changeFrame());
+ } else {
+ animEnded();
+ }
+ } else {
+ setFrame(changeFrame());
+ }
break;
default:
@@ -2263,6 +2366,18 @@ void SceneObject::updateScreen() {
}
}
+void SceneObject::updateAngle(SceneObject *sceneObj) {
+ checkAngle(sceneObj);
+ if (_objectWrapper)
+ _objectWrapper->check();
+}
+
+void SceneObject::changeAngle(int angle) {
+ _angle = angle;
+ if (_objectWrapper)
+ _objectWrapper->check();
+}
+
void SceneObject::setup(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority) {
postInit();
setVisage(visage);
@@ -2274,6 +2389,16 @@ void SceneObject::setup(int visage, int stripFrameNum, int frameNum, int posX, i
/*--------------------------------------------------------------------------*/
+void AltSceneObject::postInit(SceneObjectList *OwnerList) {
+ SceneObject::postInit(&_globals->_sceneManager._altSceneObjects);
+}
+
+void AltSceneObject::draw() {
+ SceneObject::draw();
+}
+
+/*--------------------------------------------------------------------------*/
+
void SceneObjectList::draw() {
Common::Array<SceneObject *> objList;
int paneNum = 0;
@@ -2702,6 +2827,9 @@ void Player::synchronize(Serializer &s) {
s.syncAsByte(_canWalk);
s.syncAsByte(_uiEnabled);
s.syncAsSint16LE(_field8C);
+
+ if (_vm->getGameID() == GType_BlueForce)
+ s.syncAsSint16LE(_field8E);
}
/*--------------------------------------------------------------------------*/
@@ -3426,6 +3554,7 @@ void GameHandler::synchronize(Serializer &s) {
SceneHandler::SceneHandler() {
_saveGameSlot = -1;
_loadGameSlot = -1;
+ _prevFrameNumber = 0;
}
void SceneHandler::registerHandler() {
@@ -3433,6 +3562,10 @@ void SceneHandler::registerHandler() {
_globals->_game->addHandler(this);
}
+uint32 SceneHandler::getFrameDifference() {
+ return GLOBALS._events.getFrameNumber() - _prevFrameNumber;
+}
+
void SceneHandler::postInit(SceneObjectList *OwnerList) {
_delayTicks = 2;
@@ -3547,10 +3680,19 @@ void SceneHandler::dispatch() {
// Not actually used
//_eventListeners.forEach(SceneHandler::handleListener);
- // Handle pending eents
+ // Handle pending events
Event event;
- while (_globals->_events.getEvent(event))
+ if (_globals->_events.getEvent(event)) {
+ // Process pending events
+ do {
+ process(event);
+ } while (_globals->_events.getEvent(event));
+ } else if (_vm->getGameID() == GType_BlueForce) {
+ // For Blue Force, 'none' events need to be generated in the absence of any
+ event.eventType = EVENT_NONE;
+ event.mousePos = _globals->_events._mousePos;
process(event);
+ }
// Handle drawing the contents of the scene
if (_globals->_sceneManager._scene)
@@ -3573,4 +3715,4 @@ void SceneHandler::dispatchObject(EventHandler *obj) {
void SceneHandler::saveListener(Serializer &ser) {
}
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/core.h b/engines/tsage/core.h
index b86e2f63fe..b1cbf74bd3 100644
--- a/engines/tsage/core.h
+++ b/engines/tsage/core.h
@@ -34,7 +34,7 @@
#include "tsage/resources.h"
#include "tsage/saveload.h"
-namespace tSage {
+namespace TsAGE {
#define MAX_FLAGS 256
@@ -55,8 +55,13 @@ public:
CursorType _cursorId;
Common::String _description;
int _iconResNum;
+
+ int _visage;
+ int _strip;
+ int _frame;
public:
InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType cursorId, const Common::String description);
+ InvObject(int visage, int strip, int frame, int sceneNumber);
bool inInventory() const { return _sceneNumber == 1; }
void setCursor();
@@ -157,6 +162,18 @@ public:
int _state;
};
+#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 ObjectMover : public EventHandler {
public:
Common::Point _destPosition;
@@ -287,7 +304,7 @@ public:
PaletteModifierCached();
- void setPalette(ScenePalette *palette, int step);
+ virtual void setPalette(ScenePalette *palette, int step);
virtual Common::String getClassName() { return "PaletteModifierCached"; }
virtual void synchronize(Serializer &s);
};
@@ -323,6 +340,7 @@ public:
virtual void synchronize(Serializer &s);
virtual void signal();
virtual void remove();
+ virtual void setPalette(ScenePalette *palette, int step);
};
/*--------------------------------------------------------------------------*/
@@ -356,7 +374,7 @@ public:
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);
+ PaletteFader *addFader(const byte *arrBufferRGB, int palSize, int step, Action *action);
static void changeBackground(const Rect &bounds, FadeMode fadeMode);
@@ -400,9 +418,7 @@ public:
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);
- }
+ static void display2(int resNum, int lineNum);
};
class SceneItemExt : public SceneItem {
@@ -426,17 +442,22 @@ public:
class NamedHotspot : public SceneHotspot {
public:
- int _resnum, _lookLineNum, _useLineNum;
- NamedHotspot() : SceneHotspot() {}
+ int _resNum, _lookLineNum, _useLineNum, _talkLineNum;
+ NamedHotspot();
- 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 synchronize(Serializer &s);
+ void setup(int ys, int xs, int ye, int xe, const int resnum, const int lookLineNum, const int useLineNum);
+ virtual void setup(const Rect &bounds, int resNum, int lookLineNum, int talkLineNum, int useLineNum, int mode, SceneItem *item);
+ virtual void setup(int sceneRegionId, int resNum, int lookLineNum, int talkLineNum, int useLineNum, int mode);
};
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};
+ ANIM_MODE_4 = 4, ANIM_MODE_5 = 5, ANIM_MODE_6 = 6, ANIM_MODE_7 = 7, ANIM_MODE_8 = 8,
+ // Introduced in Blue Force
+ ANIM_MODE_9 = 9
+};
class SceneObject;
@@ -467,6 +488,7 @@ public:
virtual ~SceneObjectWrapper() {}
void setSceneObject(SceneObject *so);
+ void check();
virtual void synchronize(Serializer &s);
virtual Common::String getClassName() { return "SceneObjectWrapper"; }
@@ -555,18 +577,18 @@ public:
virtual void draw();
virtual void proc19() {}
virtual void updateScreen();
+ // New methods introduced by Blue FOrce
+ virtual void updateAngle(SceneObject *sceneObj);
+ virtual void changeAngle(int angle);
+
void setup(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority);
};
-class SceneObjectExt : public SceneObject {
+class AltSceneObject: public SceneObject {
public:
- int _state;
-
- virtual void synchronize(Serializer &s) {
- SceneObject::synchronize(s);
- s.syncAsSint16LE(_state);
- }
- virtual Common::String getClassName() { return "SceneObjectExt"; }
+ virtual Common::String getClassName() { return "AltObjectExt"; }
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void draw();
};
class SceneText : public SceneObject {
@@ -594,6 +616,7 @@ public:
bool _canWalk;
bool _uiEnabled;
int _field8C;
+ int _field8E;
public:
Player();
@@ -695,7 +718,7 @@ public:
SynchronizedList<SceneObject *>::iterator begin() { return _objList.begin(); }
SynchronizedList<SceneObject *>::iterator end() { return _objList.end(); }
int size() const { return _objList.size(); }
- bool contains(SceneObject *sceneObj) { return tSage::contains(_objList, sceneObj); }
+ 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) {
@@ -827,9 +850,11 @@ public:
int _loadGameSlot;
int _delayTicks;
Common::String _saveName;
+ uint32 _prevFrameNumber;
public:
SceneHandler();
void registerHandler();
+ uint32 getFrameDifference();
virtual Common::String getClassName() { return "SceneHandler"; }
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -840,6 +865,6 @@ public:
static void saveListener(Serializer &ser);
};
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/debugger.cpp b/engines/tsage/debugger.cpp
index 9277fd429a..e3c4569dd2 100644
--- a/engines/tsage/debugger.cpp
+++ b/engines/tsage/debugger.cpp
@@ -23,9 +23,9 @@
#include "tsage/debugger.h"
#include "tsage/globals.h"
#include "tsage/graphics.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
-namespace tSage {
+namespace TsAGE {
Debugger::Debugger() : GUI::Debugger() {
DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
@@ -38,6 +38,7 @@ Debugger::Debugger() : GUI::Debugger() {
DCmd_Register("listobjects", WRAP_METHOD(Debugger, Cmd_ListObjects));
DCmd_Register("moveobject", WRAP_METHOD(Debugger, Cmd_MoveObject));
DCmd_Register("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots));
+ DCmd_Register("sound", WRAP_METHOD(Debugger, Cmd_Sound));
}
static int strToInt(const char *s) {
@@ -434,5 +435,18 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) {
return false;
}
+/**
+ * Play the specified sound
+ */
+bool Debugger::Cmd_Sound(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <sound number>\n", argv[0]);
+ return true;
+ }
+
+ int soundNum = strToInt(argv[1]);
+ _globals->_soundHandler.play(soundNum);
+ return false;
+}
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/debugger.h b/engines/tsage/debugger.h
index 3c14cd7bed..8bc1b06336 100644
--- a/engines/tsage/debugger.h
+++ b/engines/tsage/debugger.h
@@ -26,7 +26,7 @@
#include "common/scummsys.h"
#include "gui/debugger.h"
-namespace tSage {
+namespace TsAGE {
class Debugger : public GUI::Debugger {
public:
@@ -42,10 +42,10 @@ protected:
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_Hotspots(int argc, const char **argv);
+ bool Cmd_Sound(int argc, const char **argv);
};
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp
index aaa9030a04..f12efc02e8 100644
--- a/engines/tsage/detection.cpp
+++ b/engines/tsage/detection.cpp
@@ -30,7 +30,7 @@
#include "tsage/tsage.h"
-namespace tSage {
+namespace TsAGE {
struct tSageGameDescription {
ADGameDescription desc;
@@ -55,11 +55,11 @@ Common::String TSageEngine::getPrimaryFilename() const {
return Common::String(_gameDescription->desc.filesDescriptions[0].fileName);
}
-} // End of namespace tSage
+} // End of namespace TsAGE
static const PlainGameDescriptor tSageGameTitles[] = {
{ "tsage", "Unknown Tsunami TSAGE-based Game" },
- { "ring", "Ringworld: Revenge of the Patriarch" },
+ { "ringworld", "Ringworld: Revenge of the Patriarch" },
{ "blueforce", "Blue Force" },
{ 0, 0 }
};
@@ -72,7 +72,7 @@ enum {
class TSageMetaEngine : public AdvancedMetaEngine {
public:
- TSageMetaEngine() : AdvancedMetaEngine(tSage::gameDescriptions, sizeof(tSage::tSageGameDescription), tSageGameTitles) {
+ TSageMetaEngine() : AdvancedMetaEngine(TsAGE::gameDescriptions, sizeof(TsAGE::tSageGameDescription), tSageGameTitles) {
_md5Bytes = 5000;
_singleid = "tsage";
_guioptions = Common::GUIO_NOSPEECH;
@@ -103,7 +103,7 @@ public:
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
if (desc) {
- *engine = new tSage::TSageEngine(syst, (const tSage::tSageGameDescription *)desc);
+ *engine = new TsAGE::TSageEngine(syst, (const TsAGE::tSageGameDescription *)desc);
}
return desc != 0;
}
@@ -118,7 +118,7 @@ public:
Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles(pattern);
sort(filenames.begin(), filenames.end());
- tSage::tSageSavegameHeader header;
+ TsAGE::tSageSavegameHeader header;
SaveStateList saveList;
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
@@ -129,7 +129,7 @@ public:
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- if (tSage::Saver::readSavegameHeader(in, header)) {
+ if (TsAGE::Saver::readSavegameHeader(in, header)) {
saveList.push_back(SaveStateDescriptor(slot, header.saveName));
delete header.thumbnail;
}
@@ -156,8 +156,8 @@ public:
generateGameStateFileName(target, slot));
assert(f);
- tSage::tSageSavegameHeader header;
- tSage::Saver::readSavegameHeader(f, header);
+ TsAGE::tSageSavegameHeader header;
+ TsAGE::Saver::readSavegameHeader(f, header);
delete f;
// Create the return descriptor
diff --git a/engines/tsage/detection_tables.h b/engines/tsage/detection_tables.h
index f9ced562c2..4b69549673 100644
--- a/engines/tsage/detection_tables.h
+++ b/engines/tsage/detection_tables.h
@@ -20,19 +20,19 @@
*
*/
-namespace tSage {
+namespace TsAGE {
static const tSageGameDescription gameDescriptions[] = {
// Ringworld English CD and First Wave versions
{
{
- "ring",
+ "ringworld",
"CD",
AD_ENTRY1s("ring.rlb", "466f0e6492d9d0f34d35c5cd088de90f", 37847618),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_UNSTABLE,
+ ADGF_TESTING | ADGF_CD,
Common::GUIO_NOSPEECH | Common::GUIO_NOSFX
},
GType_Ringworld,
@@ -41,12 +41,12 @@ static const tSageGameDescription gameDescriptions[] = {
// Ringworld Spanish CD
{
{
- "ring",
+ "ringworld",
"CD",
AD_ENTRY1s("ring.rlb", "cb8bba91b30cd172712371d7123bd763", 7427980),
Common::ES_ESP,
Common::kPlatformPC,
- ADGF_UNSTABLE,
+ ADGF_TESTING | ADGF_CD,
Common::GUIO_NOSPEECH | Common::GUIO_NOSFX
},
GType_Ringworld,
@@ -55,12 +55,12 @@ static const tSageGameDescription gameDescriptions[] = {
// Ringworld English Floppy version
{
{
- "ring",
+ "ringworld",
"Floppy",
AD_ENTRY1s("ring.rlb", "7b7f0c5b37b58fa5ec06ebb2ca0d0d9d", 8438770),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_UNSTABLE,
+ ADGF_TESTING,
Common::GUIO_NOSPEECH | Common::GUIO_NOSFX
},
GType_Ringworld,
@@ -69,7 +69,7 @@ static const tSageGameDescription gameDescriptions[] = {
// Ringworld English Floppy Demo #1 version
{
{
- "ring",
+ "ringworld",
"Floppy Demo",
AD_ENTRY1s("tsage.rlb", "3b3604a97c06c91f3735d3e9d341f63f", 833453),
Common::EN_ANY,
@@ -84,7 +84,7 @@ static const tSageGameDescription gameDescriptions[] = {
// Ringworld English Floppy Demo #2 version
{
{
- "ring",
+ "ringworld",
"Floppy Demo",
AD_ENTRY1s("demoring.rlb", "64050e1806203b15bb03876140eb4f56", 832206),
Common::EN_ANY,
@@ -120,11 +120,11 @@ static const tSageGameDescription gameDescriptions[] = {
AD_ENTRY1s("blue.rlb", "17eabb456cb1546c66baf1aff387ba6a", 10032614),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_UNSTABLE,
Common::GUIO_NOSPEECH | Common::GUIO_NOSFX
},
GType_BlueForce,
- GF_FLOPPY
+ GF_FLOPPY | GF_ALT_REGIONS
},
// Blue Force CD and First Wave use the same files
{
@@ -134,13 +134,13 @@ static const tSageGameDescription gameDescriptions[] = {
AD_ENTRY1s("blue.rlb", "99983f48cb218f1f3760cf2f9a7ef11d", 63863322),
Common::EN_ANY,
Common::kPlatformPC,
- ADGF_NO_FLAGS,
+ ADGF_CD | ADGF_UNSTABLE,
Common::GUIO_NOSPEECH | Common::GUIO_NOSFX
},
GType_BlueForce,
- GF_CD
+ GF_CD | GF_ALT_REGIONS
},
{ AD_TABLE_END_MARKER, 0, 0 }
};
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/dialogs.cpp b/engines/tsage/dialogs.cpp
index d315ce092b..ae385b8c15 100644
--- a/engines/tsage/dialogs.cpp
+++ b/engines/tsage/dialogs.cpp
@@ -30,9 +30,9 @@
#include "tsage/dialogs.h"
#include "tsage/staticres.h"
#include "tsage/globals.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
-namespace tSage {
+namespace TsAGE {
/*--------------------------------------------------------------------------*/
@@ -595,4 +595,4 @@ OptionsDialog::OptionsDialog() {
}
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/dialogs.h b/engines/tsage/dialogs.h
index a50307f775..55adb6c813 100644
--- a/engines/tsage/dialogs.h
+++ b/engines/tsage/dialogs.h
@@ -30,7 +30,7 @@
#include "common/rect.h"
#include "common/system.h"
-namespace tSage {
+namespace TsAGE {
class MessageDialog : public GfxDialog {
public:
@@ -128,6 +128,6 @@ public:
static void show();
};
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp
index 010117ec78..a6471dc8ab 100644
--- a/engines/tsage/events.cpp
+++ b/engines/tsage/events.cpp
@@ -31,7 +31,7 @@
#include "tsage/tsage.h"
#include "tsage/globals.h"
-namespace tSage {
+namespace TsAGE {
EventsClass::EventsClass() {
_currentCursor = CURSOR_NONE;
@@ -40,6 +40,7 @@ EventsClass::EventsClass() {
_priorFrameTime = 0;
_prevDelayFrame = 0;
_saver->addListener(this);
+ _saver->addLoadNotifier(&EventsClass::loadNotifierProc);
}
bool EventsClass::pollEvent() {
@@ -154,7 +155,7 @@ void EventsClass::setCursor(CursorType cursorType) {
// No cursor
_globals->setFlag(122);
- if (_vm->getFeatures() & GF_DEMO) {
+ if ((_vm->getFeatures() & GF_DEMO) || (_vm->getGameID() == GType_BlueForce)) {
CursorMan.showMouse(false);
return;
}
@@ -269,6 +270,17 @@ void EventsClass::setCursor(Graphics::Surface &cursor, int transColor, const Com
_currentCursor = cursorId;
}
+void EventsClass::setCursor(GfxSurface &cursor) {
+ // TODO: Find proper parameters for this form in Blue Force
+ Graphics::Surface s = cursor.lockSurface();
+
+ const byte *cursorData = (const byte *)s.getBasePtr(0, 0);
+ CursorMan.replaceCursor(cursorData, cursor.getBounds().width(), cursor.getBounds().height(),
+ cursor._centroid.x, cursor._centroid.y, cursor._transColor);
+
+ _currentCursor = CURSOR_NONE;
+}
+
void EventsClass::setCursorFromFlag() {
setCursor(isCursorVisible() ? _currentCursor : CURSOR_NONE);
}
@@ -277,8 +289,10 @@ void EventsClass::showCursor() {
setCursor(_currentCursor);
}
-void EventsClass::hideCursor() {
+CursorType EventsClass::hideCursor() {
+ CursorType oldCursor = _currentCursor;
setCursor(CURSOR_NONE);
+ return oldCursor;
}
bool EventsClass::isCursorVisible() const {
@@ -315,4 +329,13 @@ void EventsClass::listenerSynchronize(Serializer &s) {
}
}
-} // end of namespace tSage
+void EventsClass::loadNotifierProc(bool postFlag) {
+ if (postFlag) {
+ if (_globals->_events._lastCursor == CURSOR_NONE)
+ _globals->_events._lastCursor = _globals->_events._currentCursor;
+ else
+ _globals->_events._lastCursor = CURSOR_NONE;
+ }
+}
+
+} // end of namespace TsAGE
diff --git a/engines/tsage/events.h b/engines/tsage/events.h
index e0fbd88745..db1941082d 100644
--- a/engines/tsage/events.h
+++ b/engines/tsage/events.h
@@ -29,7 +29,7 @@
#include "graphics/surface.h"
#include "tsage/saveload.h"
-namespace tSage {
+namespace TsAGE {
enum EventType {EVENT_NONE = 0, EVENT_BUTTON_DOWN = 1, EVENT_BUTTON_UP = 2, EVENT_KEYPRESS = 4,
EVENT_MOUSE_MOVE = 8};
@@ -67,6 +67,8 @@ enum CursorType {
CURSOR_NONE = -1, CURSOR_CROSSHAIRS = -2, CURSOR_ARROW = -3
};
+class GfxSurface;
+
class EventsClass : public SaveListener {
private:
Common::Event _event;
@@ -84,10 +86,11 @@ public:
void pushCursor(CursorType cursorType);
void popCursor();
void setCursor(Graphics::Surface &cursor, int transColor, const Common::Point &hotspot, CursorType cursorId);
+ void setCursor(GfxSurface &cursor);
void setCursorFromFlag();
CursorType getCursor() const { return _currentCursor; }
void showCursor();
- void hideCursor();
+ CursorType hideCursor();
bool isCursorVisible() const;
bool pollEvent();
@@ -100,8 +103,9 @@ public:
void delay(int numFrames);
virtual void listenerSynchronize(Serializer &s);
+ static void loadNotifierProc(bool postFlag);
};
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp
index 34b26ec311..52bd42fc5c 100644
--- a/engines/tsage/globals.cpp
+++ b/engines/tsage/globals.cpp
@@ -22,11 +22,11 @@
#include "tsage/globals.h"
#include "tsage/tsage.h"
-#include "tsage/blueforce_logic.h"
-#include "tsage/ringworld_demo.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/blue_force/blueforce_logic.h"
+#include "tsage/ringworld/ringworld_demo.h"
+#include "tsage/ringworld/ringworld_logic.h"
-namespace tSage {
+namespace TsAGE {
Globals *_globals = NULL;
ResourceManager *_resourceManager = NULL;
@@ -51,7 +51,7 @@ static SavedObject *classFactoryProc(const Common::String &className) {
/*--------------------------------------------------------------------------*/
Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface),
- _randomSource("tsage"), _unkColor1(0), _unkColor2(255), _unkColor3(255) {
+ _randomSource("tsage"), _color1(0), _color2(255), _color3(255) {
reset();
_stripNum = 0;
_gfxEdgeAdjust = 3;
@@ -64,18 +64,26 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface
_fontColors.foreground = 6;
_dialogCenter.y = 80;
// Workaround in order to use later version of the engine
- _unkColor1 = _gfxColors.foreground;
- _unkColor2 = _gfxColors.foreground;
- _unkColor3 = _gfxColors.foreground;
+ _color1 = _gfxColors.foreground;
+ _color2 = _gfxColors.foreground;
+ _color3 = _gfxColors.foreground;
+ } else if (_vm->getGameID() == GType_BlueForce) {
+ // Blue Force
+ _gfxFontNumber = 0;
+ _gfxColors.background = 89;
+ _gfxColors.foreground = 83;
+ _fontColors.background = 88;
+ _fontColors.foreground = 92;
+ _dialogCenter.y = 165;
} else if ((_vm->getGameID() == GType_Ringworld) && (_vm->getFeatures() & GF_CD)) {
_gfxFontNumber = 50;
_gfxColors.background = 53;
_gfxColors.foreground = 0;
_fontColors.background = 51;
_fontColors.foreground = 54;
- _unkColor1 = 18;
- _unkColor2 = 18;
- _unkColor3 = 18;
+ _color1 = 18;
+ _color2 = 18;
+ _color3 = 18;
} else {
_gfxFontNumber = 50;
_gfxColors.background = 53;
@@ -83,9 +91,9 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface
_fontColors.background = 51;
_fontColors.foreground = 54;
// Workaround in order to use later version of the engine
- _unkColor1 = _gfxColors.foreground;
- _unkColor2 = _gfxColors.foreground;
- _unkColor3 = _gfxColors.foreground;
+ _color1 = _gfxColors.foreground;
+ _color2 = _gfxColors.foreground;
+ _color3 = _gfxColors.foreground;
}
_screenSurface.setScreenSurface();
_gfxManagers.push_back(&_gfxManagerInstance);
@@ -103,21 +111,26 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface
switch (_vm->getGameID()) {
case GType_Ringworld:
if (!(_vm->getFeatures() & GF_DEMO)) {
- _inventory = new RingworldInvObjectList();
- _game = new RingworldGame();
+ _inventory = new Ringworld::RingworldInvObjectList();
+ _game = new Ringworld::RingworldGame();
} else {
- _game = new RingworldDemoGame();
+ _game = new Ringworld::RingworldDemoGame();
}
+ _sceneHandler = new SceneHandler();
break;
case GType_BlueForce:
- _game = new BlueForceGame();
+ _game = new BlueForce::BlueForceGame();
+ _inventory = new BlueForce::BlueForceInvObjectList();
+ _sceneHandler = new BlueForce::SceneHandlerExt();
break;
}
}
Globals::~Globals() {
+ _scenePalette.clearListeners();
delete _inventory;
+ delete _sceneHandler;
delete _game;
_globals = NULL;
}
@@ -142,9 +155,9 @@ void Globals::synchronize(Serializer &s) {
s.syncAsSint32LE(_fontColors.foreground);
if (s.getVersion() >= 4) {
- s.syncAsByte(_unkColor1);
- s.syncAsByte(_unkColor2);
- s.syncAsByte(_unkColor3);
+ s.syncAsByte(_color1);
+ s.syncAsByte(_color2);
+ s.syncAsByte(_color3);
}
s.syncAsSint16LE(_dialogCenter.x); s.syncAsSint16LE(_dialogCenter.y);
@@ -166,5 +179,40 @@ void Globals::dispatchSounds() {
Common::for_each(_sounds.begin(), _sounds.end(), Globals::dispatchSound);
}
+/*--------------------------------------------------------------------------*/
+
+namespace BlueForce {
+
+BlueForceGlobals::BlueForceGlobals(): Globals() {
+ _interfaceY = 0;
+ _v51C44 = 1;
+ _v4CEA2 = 0;
+ _v4CEA4 = 0;
+ _v4CEA8 = 0;
+ _v4CEF2 = 0;
+ _v4CEF4 = 0;
+ _v4CF9E = 0;
+ _v4E238 = 0;
+ _v501FC = 0;
+ _v51C42 = 0;
+ _bikiniHutState = 0;
+ _mapLocationId = 1;
+ Common::set_to(_globalFlags, _globalFlags + 12, 0);
+}
+
+void BlueForceGlobals::synchronize(Serializer &s) {
+ Globals::synchronize(s);
+ error("Sync variables");
+}
+
+bool BlueForceGlobals::getFlag(int v) {
+ return _globalFlags[v / 8] & (1 << (v % 8));
+}
+
+void BlueForceGlobals::setFlag(int v) {
+ _globalFlags[v / 8] |= 1 << (v % 8);
+}
+
+} // end of namespace BlueForce
-} // end of namespace tSage
+} // end of namespace TsAGE
diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h
index 7cfec718e2..f5d4aaa16f 100644
--- a/engines/tsage/globals.h
+++ b/engines/tsage/globals.h
@@ -30,8 +30,9 @@
#include "tsage/events.h"
#include "tsage/sound.h"
#include "tsage/saveload.h"
+#include "tsage/blue_force/blueforce_ui.h"
-namespace tSage {
+namespace TsAGE {
class Globals : public SavedObject {
private:
@@ -40,7 +41,7 @@ public:
GfxSurface _screenSurface;
GfxManager _gfxManagerInstance;
Common::List<GfxManager *> _gfxManagers;
- SceneHandler _sceneHandler;
+ SceneHandler *_sceneHandler;
Game *_game;
EventsClass _events;
SceneManager _sceneManager;
@@ -54,7 +55,7 @@ public:
int _gfxFontNumber;
GfxColors _gfxColors;
GfxColors _fontColors;
- byte _unkColor1, _unkColor2, _unkColor3;
+ byte _color1, _color2, _color3;
SoundManager _soundManager;
Common::Point _dialogCenter;
WalkRegions _walkRegions;
@@ -98,10 +99,47 @@ public:
extern Globals *_globals;
+#define GLOBALS (*_globals)
+#define BF_GLOBALS (*((::TsAGE::BlueForce::BlueForceGlobals *)_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
+
+namespace BlueForce {
+
+using namespace TsAGE;
+
+class BlueForceGlobals: public Globals {
+public:
+ ASoundExt _sound1, _sound2, _sound3;
+ UIElements _uiElements;
+ int _v4CEA2;
+ int _v4CEA4;
+ int _v4CEA8;
+ int _v4CEF2;
+ int _v4CEF4;
+ int _v4CF9E;
+ int _v4E238;
+ int _v501FC;
+ int _v51C42;
+ int _v51C44;
+ int _interfaceY;
+ int _bikiniHutState;
+ int _mapLocationId;
+ uint8 _globalFlags[12];
+
+ BlueForceGlobals();
+ virtual Common::String getClassName() { return "BFGlobals"; }
+ virtual void synchronize(Serializer &s);
+
+ void setFlag(int v);
+ bool getFlag(int v);
+};
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index 87ffdf4494..1884bfb4f5 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -30,7 +30,7 @@
#include "graphics/surface.h"
#include "tsage/globals.h"
-namespace tSage {
+namespace TsAGE {
/**
* Creates a new graphics surface with the specified area of another surface
@@ -626,9 +626,9 @@ void GfxElement::setDefaults() {
_fontNumber = _globals->_gfxFontNumber;
_colors = _globals->_gfxColors;
_fontColors = _globals->_fontColors;
- _unkColor1 = _globals->_unkColor1;
- _unkColor2 = _globals->_unkColor2;
- _unkColor3 = _globals->_unkColor3;
+ _color1 = _globals->_color1;
+ _color2 = _globals->_color2;
+ _color3 = _globals->_color3;
}
/**
@@ -824,9 +824,9 @@ void GfxMessage::draw() {
gfxManager.setFillFlag(false);
gfxManager._font.setFontNumber(_fontNumber);
- gfxManager._font._colors.foreground = this->_unkColor1;
- gfxManager._font._colors2.background = this->_unkColor2;
- gfxManager._font._colors2.foreground = this->_unkColor3;
+ gfxManager._font._colors.foreground = this->_color1;
+ gfxManager._font._colors2.background = this->_color2;
+ gfxManager._font._colors2.foreground = this->_color3;
// Display the text
gfxManager._font.writeLines(_message.c_str(), _bounds, _textAlign);
@@ -867,9 +867,9 @@ void GfxButton::draw() {
gfxManager._font.setFontNumber(_fontNumber);
//
- gfxManager._font._colors.foreground = this->_unkColor1;
- gfxManager._font._colors2.background = this->_unkColor2;
- gfxManager._font._colors2.foreground = this->_unkColor3;
+ gfxManager._font._colors.foreground = this->_color1;
+ gfxManager._font._colors2.background = this->_color2;
+ gfxManager._font._colors2.foreground = this->_color3;
// Display the button's text
Rect tempRect(_bounds);
@@ -1512,4 +1512,4 @@ GfxFontBackup::~GfxFontBackup() {
}
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
index e09e1093a3..06b482d7b5 100644
--- a/engines/tsage/graphics.h
+++ b/engines/tsage/graphics.h
@@ -30,7 +30,7 @@
#include "common/system.h"
#include "graphics/surface.h"
-namespace tSage {
+namespace TsAGE {
class GfxSurface;
class Region;
@@ -177,7 +177,7 @@ public:
uint16 _fontNumber;
GfxColors _colors;
GfxColors _fontColors;
- byte _unkColor1, _unkColor2, _unkColor3;
+ byte _color1, _color2, _color3;
uint16 _keycode;
public:
GfxElement();
@@ -343,6 +343,6 @@ 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
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/module.mk b/engines/tsage/module.mk
index aefc8b0992..ed6fb296a0 100644
--- a/engines/tsage/module.mk
+++ b/engines/tsage/module.mk
@@ -1,7 +1,11 @@
MODULE := engines/tsage
MODULE_OBJS := \
- blueforce_logic.o \
+ blue_force/blueforce_logic.o \
+ blue_force/blueforce_scenes0.o \
+ blue_force/blueforce_scenes1.o \
+ blue_force/blueforce_scenes3.o \
+ blue_force/blueforce_ui.o \
converse.o \
core.o \
debugger.o \
@@ -11,16 +15,16 @@ MODULE_OBJS := \
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 \
+ ringworld/ringworld_demo.o \
+ ringworld/ringworld_logic.o \
+ ringworld/ringworld_scenes1.o \
+ ringworld/ringworld_scenes2.o \
+ ringworld/ringworld_scenes3.o \
+ ringworld/ringworld_scenes4.o \
+ ringworld/ringworld_scenes5.o \
+ ringworld/ringworld_scenes6.o \
+ ringworld/ringworld_scenes8.o \
+ ringworld/ringworld_scenes10.o \
saveload.o \
scenes.o \
sound.o \
@@ -34,4 +38,3 @@ endif
# Include common rules
include $(srcdir)/rules.mk
-
diff --git a/engines/tsage/resources.cpp b/engines/tsage/resources.cpp
index 6d2c6b5837..99b431b5dc 100644
--- a/engines/tsage/resources.cpp
+++ b/engines/tsage/resources.cpp
@@ -28,7 +28,7 @@
#include "tsage/resources.h"
#include "tsage/tsage.h"
-namespace tSage {
+namespace TsAGE {
MemoryManager::MemoryManager() {
@@ -504,4 +504,4 @@ Common::String ResourceManager::getMessage(int resNum, int lineNum, bool suppres
return result;
}
-} // end of namespace tSage
+} // end of namespace TsAGE
diff --git a/engines/tsage/resources.h b/engines/tsage/resources.h
index efbb86b24e..176d60fcc4 100644
--- a/engines/tsage/resources.h
+++ b/engines/tsage/resources.h
@@ -33,7 +33,7 @@
#include "common/util.h"
#include "graphics/surface.h"
-namespace tSage {
+namespace TsAGE {
// Magic number used by original game to identify valid memory blocks
const uint32 MEMORY_ENTRY_ID = 0xE11DA722;
@@ -175,6 +175,6 @@ public:
};
-} // end of namespace tSage
+} // end of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_demo.cpp b/engines/tsage/ringworld/ringworld_demo.cpp
index b24fec98f9..5612325aff 100644
--- a/engines/tsage/ringworld_demo.cpp
+++ b/engines/tsage/ringworld/ringworld_demo.cpp
@@ -20,12 +20,14 @@
*
*/
-#include "tsage/ringworld_demo.h"
+#include "tsage/ringworld/ringworld_demo.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
void RingworldDemoGame::start() {
// Start the demo's single scene
@@ -117,4 +119,6 @@ void RingworldDemoScene::process(Event &event) {
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_demo.h b/engines/tsage/ringworld/ringworld_demo.h
index 3e7431e107..30527b0aea 100644
--- a/engines/tsage/ringworld_demo.h
+++ b/engines/tsage/ringworld/ringworld_demo.h
@@ -30,7 +30,11 @@
#include "tsage/globals.h"
#include "tsage/sound.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class RingworldDemoGame: public Game {
private:
@@ -54,6 +58,8 @@ public:
virtual void signal();
};
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_logic.cpp b/engines/tsage/ringworld/ringworld_logic.cpp
index 070d8afd25..2a34e49b39 100644
--- a/engines/tsage/ringworld_logic.cpp
+++ b/engines/tsage/ringworld/ringworld_logic.cpp
@@ -23,21 +23,23 @@
#include "common/config-manager.h"
#include "common/translation.h"
#include "gui/saveload.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/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 {
+#include "tsage/ringworld/ringworld_demo.h"
+#include "tsage/ringworld/ringworld_scenes1.h"
+#include "tsage/ringworld/ringworld_scenes2.h"
+#include "tsage/ringworld/ringworld_scenes3.h"
+#include "tsage/ringworld/ringworld_scenes4.h"
+#include "tsage/ringworld/ringworld_scenes5.h"
+#include "tsage/ringworld/ringworld_scenes6.h"
+#include "tsage/ringworld/ringworld_scenes8.h"
+#include "tsage/ringworld/ringworld_scenes10.h"
+
+namespace TsAGE {
+
+namespace Ringworld {
Scene *RingworldGame::createScene(int sceneNumber) {
switch (sceneNumber) {
@@ -1285,7 +1287,7 @@ void RingworldGame::saveGame() {
MessageDialog::show(SAVING_NOT_ALLOWED_MSG, OK_BTN_STRING);
else {
// Show the save dialog
- handleSaveLoad(true, _globals->_sceneHandler._saveGameSlot, _globals->_sceneHandler._saveName);
+ handleSaveLoad(true, _globals->_sceneHandler->_saveGameSlot, _globals->_sceneHandler->_saveName);
}
}
@@ -1294,7 +1296,7 @@ void RingworldGame::restoreGame() {
MessageDialog::show(RESTORING_NOT_ALLOWED_MSG, OK_BTN_STRING);
else {
// Show the load dialog
- handleSaveLoad(false, _globals->_sceneHandler._loadGameSlot, _globals->_sceneHandler._saveName);
+ handleSaveLoad(false, _globals->_sceneHandler->_loadGameSlot, _globals->_sceneHandler->_saveName);
}
}
@@ -1346,7 +1348,7 @@ void RingworldGame::start() {
}
if (slot >= 0)
- _globals->_sceneHandler._loadGameSlot = slot;
+ _globals->_sceneHandler->_loadGameSlot = slot;
else
// Switch to the title screen
_globals->_sceneManager.setNewScene(1000);
@@ -1363,8 +1365,8 @@ void RingworldGame::restart() {
_globals->setFlag(34);
// Clear save/load slots
- _globals->_sceneHandler._saveGameSlot = -1;
- _globals->_sceneHandler._loadGameSlot = -1;
+ _globals->_sceneHandler->_saveGameSlot = -1;
+ _globals->_sceneHandler->_loadGameSlot = -1;
_globals->_stripNum = 0;
_globals->_events.setCursor(CURSOR_WALK);
@@ -1429,8 +1431,8 @@ void RingworldGame::endGame(int resNum, int lineNum) {
restart();
breakFlag = true;
} else {
- handleSaveLoad(false, _globals->_sceneHandler._loadGameSlot, _globals->_sceneHandler._saveName);
- breakFlag = _globals->_sceneHandler._loadGameSlot >= 0;
+ handleSaveLoad(false, _globals->_sceneHandler->_loadGameSlot, _globals->_sceneHandler->_saveName);
+ breakFlag = _globals->_sceneHandler->_loadGameSlot >= 0;
}
} while (!breakFlag);
}
@@ -1487,4 +1489,6 @@ void RingworldGame::processEvent(Event &event) {
}
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_logic.h b/engines/tsage/ringworld/ringworld_logic.h
index 19b0f10b42..69e5520581 100644
--- a/engines/tsage/ringworld_logic.h
+++ b/engines/tsage/ringworld/ringworld_logic.h
@@ -29,20 +29,11 @@
#include "tsage/scenes.h"
#include "tsage/globals.h"
-namespace tSage {
+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); }
+namespace Ringworld {
+using namespace TsAGE;
class SceneFactory {
public:
@@ -75,6 +66,17 @@ public:
}
};
+class SceneObjectExt : public SceneObject {
+public:
+ int _state;
+
+ virtual void synchronize(Serializer &s) {
+ SceneObject::synchronize(s);
+ s.syncAsSint16LE(_state);
+ }
+ virtual Common::String getClassName() { return "SceneObjectExt"; }
+};
+
class SceneArea : public SavedObject {
public:
GfxSurface _surface;
@@ -438,7 +440,7 @@ public:
virtual Common::String getClassName() { return "RingworldInvObjectList"; }
};
-#define RING_INVENTORY (*((RingworldInvObjectList *)_globals->_inventory))
+#define RING_INVENTORY (*((::TsAGE::Ringworld::RingworldInvObjectList *)_globals->_inventory))
class RingworldGame: public Game {
protected:
@@ -456,6 +458,8 @@ public:
virtual void processEvent(Event &event);
};
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_scenes1.cpp b/engines/tsage/ringworld/ringworld_scenes1.cpp
index 8299a05967..20af25561c 100644
--- a/engines/tsage/ringworld_scenes1.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes1.cpp
@@ -20,12 +20,14 @@
*
*/
-#include "tsage/ringworld_scenes1.h"
+#include "tsage/ringworld/ringworld_scenes1.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
/*--------------------------------------------------------------------------
* Scene 10 - Kziniti Palace (Introduction)
@@ -1330,6 +1332,24 @@ void Scene40::Action8::signal() {
}
}
+void Scene40::Action8::dispatch() {
+ if (_action)
+ _action->dispatch();
+
+ if (_delayFrames) {
+ uint32 frameNumber = _globals->_events.getFrameNumber();
+ if ((_startFrame + 60) < frameNumber) {
+ --_delayFrames;
+ _startFrame = frameNumber;
+
+ if (_delayFrames <= 0) {
+ _delayFrames = 0;
+ signal();
+ }
+ }
+ }
+}
+
/*--------------------------------------------------------------------------*/
void Scene40::DyingKzin::doAction(int action) {
@@ -1416,7 +1436,7 @@ void Scene40::Item2::doAction(int action) {
SceneItem::display2(40, 37);
break;
default:
- SceneItem::doAction(action);
+ SceneHotspot::doAction(action);
break;
}
}
@@ -1437,7 +1457,7 @@ void Scene40::Item6::doAction(int action) {
SceneItem::display2(40, 36);
break;
default:
- SceneItem::doAction(action);
+ SceneHotspot::doAction(action);
break;
}
}
@@ -1446,7 +1466,7 @@ void Scene40::Item6::doAction(int action) {
Scene40::Scene40() :
_item1(2, OBJECT_SCANNER, 40, 24, OBJECT_STUNNER, 40, 25, CURSOR_LOOK, 40, 7, CURSOR_USE, 40, 16, LIST_END),
- _item3(5, OBJECT_SCANNER, 40, 26, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 9, CURSOR_USE, 40, 17, LIST_END),
+ _item3(5, OBJECT_SCANNER, 40, 28, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 2, CURSOR_USE, 40, 30, LIST_END),
_item4(6, OBJECT_SCANNER, 40, 31, OBJECT_STUNNER, 40, 32, CURSOR_LOOK, 40, 5, CURSOR_USE, 40, 33, LIST_END),
_item5(0, CURSOR_LOOK, 40, 11, LIST_END),
_item7(4, OBJECT_SCANNER, 40, 26, OBJECT_STUNNER, 40, 27, CURSOR_LOOK, 40, 9, CURSOR_USE, 40, 17, LIST_END),
@@ -2271,7 +2291,7 @@ void Scene60::Item::doAction(int action) {
setAction(&scene->_sequenceManager, this, 62, NULL);
break;
default:
- SceneItem::doAction(action);
+ SceneHotspot::doAction(action);
break;
}
}
@@ -3148,7 +3168,7 @@ Scene6100::Scene6100(): Scene() {
_angle = 0;
_msgActive = false;
- _globals->_sceneHandler._delayTicks = 8;
+ _globals->_sceneHandler->_delayTicks = 8;
_globals->_player.disableControl();
_globals->_events.setCursor(CURSOR_WALK);
@@ -3324,4 +3344,6 @@ void Scene6100::showMessage(const Common::String &msg, int color, Action *action
}
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_scenes1.h b/engines/tsage/ringworld/ringworld_scenes1.h
index 283cf68e07..49ea65eb3a 100644
--- a/engines/tsage/ringworld_scenes1.h
+++ b/engines/tsage/ringworld/ringworld_scenes1.h
@@ -24,7 +24,7 @@
#define TSAGE_RINGWORLD_SCENES1_H
#include "common/scummsys.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
#include "tsage/converse.h"
#include "tsage/events.h"
#include "tsage/core.h"
@@ -32,7 +32,11 @@
#include "tsage/globals.h"
#include "tsage/sound.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class Scene10 : public Scene {
/* Actions */
@@ -201,6 +205,7 @@ class Scene40 : public Scene {
class Action8 : public Action {
public:
virtual void signal();
+ virtual void dispatch();
};
/* Objects */
@@ -214,15 +219,15 @@ class Scene40 : public Scene {
};
/* Items */
- class Item2 : public SceneItem {
+ class Item2 : public SceneHotspot {
public:
virtual void doAction(int action);
};
- class Item6 : public SceneItem {
+ class Item6 : public SceneHotspot {
public:
virtual void doAction(int action);
};
- class Item8 : public SceneItem {
+ class Item8 : public SceneHotspot {
public:
virtual void doAction(int action);
};
@@ -532,6 +537,8 @@ public:
};
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_scenes10.cpp b/engines/tsage/ringworld/ringworld_scenes10.cpp
index ba4060548e..df25c324ab 100644
--- a/engines/tsage/ringworld_scenes10.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes10.cpp
@@ -21,12 +21,14 @@
*/
#include "graphics/cursorman.h"
-#include "tsage/ringworld_scenes10.h"
+#include "tsage/ringworld/ringworld_scenes10.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
Scene2::Scene2() : Scene() {
_sceneState = 0;
@@ -1746,7 +1748,8 @@ void Scene9900::strAction2::signal() {
frameWidth = _txtArray2[_txtArray1Index].getFrame().getBounds().width();
_txtArray2[_txtArray1Index].setPosition(Common::Point((320 - frameWidth) / 2, 200 + frameHeight));
} else {
- _globals->_player.enableControl();
+ // WORKAROUND: Fix inventory becoming available at end of credits
+ _globals->_events.setCursor(CURSOR_WALK);
_actionIndex = 3;
signal();
}
@@ -2085,4 +2088,6 @@ void Scene9999::postInit(SceneObjectList *OwnerList) {
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_scenes10.h b/engines/tsage/ringworld/ringworld_scenes10.h
index 33b16d0014..02c42f3d01 100644
--- a/engines/tsage/ringworld_scenes10.h
+++ b/engines/tsage/ringworld/ringworld_scenes10.h
@@ -24,13 +24,17 @@
#define TSAGE_RINGWORLD_SCENES10_H
#include "common/scummsys.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
#include "tsage/events.h"
#include "tsage/core.h"
#include "tsage/scenes.h"
#include "tsage/globals.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class SceneObject9150 : public SceneObject {
public:
@@ -526,7 +530,8 @@ public:
virtual void postInit(SceneObjectList *OwnerList = NULL);
};
+} // End of namespace Ringworld
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_scenes2.cpp b/engines/tsage/ringworld/ringworld_scenes2.cpp
index 0154123c3d..cfd3e3d8f7 100644
--- a/engines/tsage/ringworld_scenes2.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes2.cpp
@@ -21,12 +21,14 @@
*/
#include "common/config-manager.h"
-#include "tsage/ringworld_scenes2.h"
+#include "tsage/ringworld/ringworld_scenes2.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
/*--------------------------------------------------------------------------
* Scene 1000 - Title Screen
@@ -925,4 +927,6 @@ void Scene1500::postInit(SceneObjectList *OwnerList) {
}
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_scenes2.h b/engines/tsage/ringworld/ringworld_scenes2.h
index 93a8f04fd4..3502aea15b 100644
--- a/engines/tsage/ringworld_scenes2.h
+++ b/engines/tsage/ringworld/ringworld_scenes2.h
@@ -24,13 +24,17 @@
#define TSAGE_RINGWORLD_SCENES2_H
#include "common/scummsys.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
#include "tsage/events.h"
#include "tsage/core.h"
#include "tsage/scenes.h"
#include "tsage/globals.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class Scene1000 : public Scene {
/* Actions */
@@ -142,8 +146,8 @@ public:
virtual void postInit(SceneObjectList *OwnerList = NULL);
};
+} // End of namespace Ringworld
-
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_scenes3.cpp b/engines/tsage/ringworld/ringworld_scenes3.cpp
index 3f9921b0ad..f744a98c33 100644
--- a/engines/tsage/ringworld_scenes3.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes3.cpp
@@ -21,12 +21,14 @@
*/
#include "common/config-manager.h"
-#include "tsage/ringworld_scenes3.h"
+#include "tsage/ringworld/ringworld_scenes3.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
/*--------------------------------------------------------------------------
* Scene 2000 - Cockpit cutscenes
@@ -324,7 +326,7 @@ void Scene2000::Action14::signal() {
scene->_stripManager.start(2001, this, scene);
break;
case 6:
- _globals->_soundHandler.fadeOut(0/* was false */);
+ _globals->_soundHandler.fadeOut(NULL);
scene->_object8.setStrip(1);
scene->_object8.setFrame(scene->_object8.getFrameCount());
scene->_object8.animate(ANIM_MODE_6, this);
@@ -786,7 +788,7 @@ void Scene2100::Action9::signal() {
scene->_stripManager.start(6051, this, scene);
break;
case 4:
- scene->_soundHandler.fadeOut(0/* was false */);
+ scene->_soundHandler.fadeOut(NULL);
scene->_object4.setStrip(1);
scene->_object4.setFrame(scene->_object4.getFrameCount());
scene->_object4.animate(ANIM_MODE_6, this);
@@ -1105,7 +1107,7 @@ void Scene2100::Action14::signal() {
scene->_stripManager.start(6009, this, scene);
break;
case 6:
- scene->_soundHandler.fadeOut(0/* was false */);
+ scene->_soundHandler.fadeOut(NULL);
scene->_object4.setStrip(1);
scene->_object4.setFrame(scene->_object4.getFrameCount());
scene->_object4.animate(ANIM_MODE_6, this);
@@ -6130,4 +6132,6 @@ void Scene2400::postInit(SceneObjectList *OwnerList) {
_globals->_soundHandler.play(153);
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_scenes3.h b/engines/tsage/ringworld/ringworld_scenes3.h
index 711360c190..2dbdc27211 100644
--- a/engines/tsage/ringworld_scenes3.h
+++ b/engines/tsage/ringworld/ringworld_scenes3.h
@@ -26,9 +26,13 @@
#include "common/scummsys.h"
#include "tsage/core.h"
#include "tsage/converse.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class Scene2000 : public Scene {
/* Actions */
@@ -890,6 +894,8 @@ public:
virtual void postInit(SceneObjectList *OwnerList = NULL);
};
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_scenes4.cpp b/engines/tsage/ringworld/ringworld_scenes4.cpp
index 838769e4af..0f4c3e49a0 100644
--- a/engines/tsage/ringworld_scenes4.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes4.cpp
@@ -21,12 +21,14 @@
*/
#include "common/config-manager.h"
-#include "tsage/ringworld_scenes4.h"
+#include "tsage/ringworld/ringworld_scenes4.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
/*--------------------------------------------------------------------------
* Scene 3500 - Ringworld Scan
@@ -227,7 +229,7 @@ void Scene3700::Action1::signal() {
/*--------------------------------------------------------------------------*/
-void Scene3700::postInit(tSage::SceneObjectList *OwnerList) {
+void Scene3700::postInit(TsAGE::SceneObjectList *OwnerList) {
Scene::postInit();
loadScene(3700);
@@ -247,4 +249,6 @@ void Scene3700::postInit(tSage::SceneObjectList *OwnerList) {
_globals->_soundHandler.play(195);
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_scenes4.h b/engines/tsage/ringworld/ringworld_scenes4.h
index 0b575d02d3..af31de84b9 100644
--- a/engines/tsage/ringworld_scenes4.h
+++ b/engines/tsage/ringworld/ringworld_scenes4.h
@@ -26,9 +26,13 @@
#include "common/scummsys.h"
#include "tsage/core.h"
#include "tsage/converse.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class Scene3500 : public Scene {
/* Actions */
@@ -87,6 +91,8 @@ public:
virtual void postInit(SceneObjectList *OwnerList = NULL);
};
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_scenes5.cpp b/engines/tsage/ringworld/ringworld_scenes5.cpp
index fccc7e1b50..58f47d7f82 100644
--- a/engines/tsage/ringworld_scenes5.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes5.cpp
@@ -21,12 +21,14 @@
*/
#include "common/config-manager.h"
-#include "tsage/ringworld_scenes5.h"
+#include "tsage/ringworld/ringworld_scenes5.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
/*--------------------------------------------------------------------------
* Scene 4000 - Village
@@ -3520,7 +3522,7 @@ Scene4250::Scene4250() :
_hotspot7(0, CURSOR_LOOK, 4250, 0, LIST_END) {
}
-void Scene4250::postInit(tSage::SceneObjectList *OwnerList) {
+void Scene4250::postInit(TsAGE::SceneObjectList *OwnerList) {
loadScene(4250);
Scene::postInit();
setZoomPercents(160, 90, 185, 100);
@@ -4438,4 +4440,6 @@ void Scene4301::dispatch() {
}
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_scenes5.h b/engines/tsage/ringworld/ringworld_scenes5.h
index c3ae9f4aa9..6c6b6b6f32 100644
--- a/engines/tsage/ringworld_scenes5.h
+++ b/engines/tsage/ringworld/ringworld_scenes5.h
@@ -26,9 +26,13 @@
#include "common/scummsys.h"
#include "tsage/core.h"
#include "tsage/converse.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class Scene4000 : public Scene {
/* Actions */
@@ -687,7 +691,8 @@ public:
}
};
+} // End of namespace Ringworld
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_scenes6.cpp b/engines/tsage/ringworld/ringworld_scenes6.cpp
index 68c184196c..f21ae59478 100644
--- a/engines/tsage/ringworld_scenes6.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes6.cpp
@@ -20,12 +20,14 @@
*
*/
-#include "tsage/ringworld_scenes6.h"
+#include "tsage/ringworld/ringworld_scenes6.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
/*--------------------------------------------------------------------------
* Scene 5000 - Caverns - Entrance
@@ -2196,5 +2198,6 @@ void Scene5300::signal() {
}
}
+} // End of namespace Ringworld
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_scenes6.h b/engines/tsage/ringworld/ringworld_scenes6.h
index 2e99f5ab87..79e604a177 100644
--- a/engines/tsage/ringworld_scenes6.h
+++ b/engines/tsage/ringworld/ringworld_scenes6.h
@@ -24,13 +24,17 @@
#define TSAGE_RINGWORLD_SCENES6_H
#include "common/scummsys.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
#include "tsage/events.h"
#include "tsage/core.h"
#include "tsage/scenes.h"
#include "tsage/globals.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class Scene5000 : public Scene {
/* Actions */
@@ -324,7 +328,8 @@ public:
}
};
+} // End of namespace Ringworld
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/ringworld_scenes8.cpp b/engines/tsage/ringworld/ringworld_scenes8.cpp
index 2b329b958a..5f1ff5cdca 100644
--- a/engines/tsage/ringworld_scenes8.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes8.cpp
@@ -21,12 +21,14 @@
*/
#include "graphics/cursorman.h"
-#include "tsage/ringworld_scenes8.h"
+#include "tsage/ringworld/ringworld_scenes8.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
void NamedHotspotMult::synchronize(Serializer &s) {
SceneHotspot::synchronize(s);
@@ -2223,7 +2225,7 @@ void Scene7700::signal() {
}
break;
case 7702:
- _soundHandler.fadeOut(0);
+ _globals->_soundHandler.fadeOut(NULL);
_globals->_sceneManager.changeScene(7600);
break;
case 7703:
@@ -2542,4 +2544,6 @@ void Scene7700::synchronize(Serializer &s) {
}
}
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld_scenes8.h b/engines/tsage/ringworld/ringworld_scenes8.h
index fe9560d9d8..4878db5cc8 100644
--- a/engines/tsage/ringworld_scenes8.h
+++ b/engines/tsage/ringworld/ringworld_scenes8.h
@@ -24,13 +24,17 @@
#define TSAGE_RINGWORLD_SCENES8_H
#include "common/scummsys.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
#include "tsage/events.h"
#include "tsage/core.h"
#include "tsage/scenes.h"
#include "tsage/globals.h"
-namespace tSage {
+namespace TsAGE {
+
+namespace Ringworld {
+
+using namespace TsAGE;
class NamedHotspotMult : public SceneHotspot {
public:
@@ -485,6 +489,8 @@ public:
virtual void synchronize(Serializer &s);
};
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp
index 40444cd630..45e655037d 100644
--- a/engines/tsage/saveload.cpp
+++ b/engines/tsage/saveload.cpp
@@ -30,7 +30,7 @@
#include "tsage/sound.h"
#include "tsage/tsage.h"
-namespace tSage {
+namespace TsAGE {
Saver *_saver;
@@ -249,12 +249,9 @@ bool Saver::readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &head
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;
+ header.thumbnail = Graphics::loadThumbnail(*in);
+ if (!header.thumbnail)
return false;
- }
// Read in save date/time
header.saveYear = in->readSint16LE();
@@ -413,4 +410,4 @@ void Saver::resolveLoadPointers() {
error("Could not resolve savegame block pointers");
}
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h
index ce181cbc8f..f81454d5e9 100644
--- a/engines/tsage/saveload.h
+++ b/engines/tsage/saveload.h
@@ -29,7 +29,7 @@
#include "common/savefile.h"
#include "common/serializer.h"
-namespace tSage {
+namespace TsAGE {
typedef void (*SaveNotifierFn)(bool postFlag);
@@ -138,6 +138,18 @@ public:
}
}
}
+
+ void addBefore(T existingItem, T newItem) {
+ typename SynchronizedList<T>::iterator i = this->begin();
+ while ((i != this->end()) && (*i != existingItem)) ++i;
+ this->insert(i, newItem);
+ }
+ void addAfter(T existingItem, T newItem) {
+ typename SynchronizedList<T>::iterator i = this->begin();
+ while ((i != this->end()) && (*i != existingItem)) ++i;
+ if (i != this->end()) ++i;
+ this->insert(i, newItem);
+ }
};
/**
@@ -222,6 +234,6 @@ public:
extern Saver *_saver;
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/scenes.cpp b/engines/tsage/scenes.cpp
index b94e95c696..5aeacda6fe 100644
--- a/engines/tsage/scenes.cpp
+++ b/engines/tsage/scenes.cpp
@@ -22,11 +22,11 @@
#include "tsage/scenes.h"
#include "tsage/globals.h"
-#include "tsage/ringworld_logic.h"
+#include "tsage/ringworld/ringworld_logic.h"
#include "tsage/tsage.h"
#include "tsage/saveload.h"
-namespace tSage {
+namespace TsAGE {
SceneManager::SceneManager() {
_scene = NULL;
@@ -38,6 +38,7 @@ SceneManager::SceneManager() {
_scrollerRect = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
_saver->addListener(this);
_objectCount = 0;
+ _loadMode = 0;
}
SceneManager::~SceneManager() {
@@ -45,7 +46,7 @@ SceneManager::~SceneManager() {
}
void SceneManager::setNewScene(int sceneNumber) {
- warning("SetNewScene(%d)", sceneNumber);
+ debug(1, "SetNewScene(%d)", sceneNumber);
_nextSceneNumber = sceneNumber;
}
@@ -113,7 +114,7 @@ void SceneManager::sceneChange() {
assert(_objectCount == _saver->getObjectCount());
}
_objectCount = _saver->getObjectCount();
- _globals->_sceneHandler._delayTicks = 2;
+ _globals->_sceneHandler->_delayTicks = 2;
// Instantiate and set the new scene
_scene = getNewScene();
@@ -146,7 +147,7 @@ void SceneManager::fadeInIfNecessary() {
}
void SceneManager::changeScene(int newSceneNumber) {
- warning("changeScene(%d)", newSceneNumber);
+ debug(1, "changeScene(%d)", newSceneNumber);
// Fade out the scene
ScenePalette scenePalette;
uint32 adjustData = 0;
@@ -173,6 +174,11 @@ void SceneManager::changeScene(int newSceneNumber) {
// Blank out the screen
_globals->_screenSurface.fillRect(_globals->_screenSurface.getBounds(), 0);
+ // If there are any fading sounds, wait until fading is complete
+ while (_globals->_soundManager.isFading()) {
+ g_system->delayMillis(10);
+ }
+
// Set the new scene to be loaded
setNewScene(newSceneNumber);
}
@@ -252,6 +258,7 @@ void SceneManager::listenerSynchronize(Serializer &s) {
Scene::Scene() : _sceneBounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
_backgroundBounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) {
_sceneMode = 0;
+ _activeScreenNumber = 0;
_oldSceneBounds = Rect(4000, 4000, 4100, 4100);
Common::set_to(&_zoomPercents[0], &_zoomPercents[256], 0);
}
@@ -296,7 +303,7 @@ void Scene::dispatch() {
}
void Scene::loadScene(int sceneNum) {
- warning("loadScene(%d)", sceneNum);
+ debug(1, "loadScene(%d)", sceneNum);
_screenNumber = sceneNum;
if (_globals->_scenePalette.loadPalette(sceneNum))
_globals->_sceneManager._hasPalette = true;
@@ -419,6 +426,11 @@ void Scene::refreshBackground(int xAmount, int yAmount) {
(xSectionSrc + 1) * 160, (ySectionSrc + 1) * 100);
Rect destBounds(xSectionDest * 160, ySectionDest * 100,
(xSectionDest + 1) * 160, (ySectionDest + 1) * 100);
+ if (_vm->getGameID() == GType_BlueForce) {
+ // For Blue Force, if the scene has an interface area, exclude it from the copy
+ srcBounds.bottom = MIN<int16>(srcBounds.bottom, BF_GLOBALS._interfaceY);
+ destBounds.bottom = MIN<int16>(destBounds.bottom, BF_GLOBALS._interfaceY);
+ }
_backSurface.copyFrom(_backSurface, srcBounds, destBounds);
}
@@ -514,4 +526,4 @@ void Game::execute() {
} while (activeFlag && !_vm->shouldQuit());
}
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/scenes.h b/engines/tsage/scenes.h
index 5845efaec9..7e8c26f912 100644
--- a/engines/tsage/scenes.h
+++ b/engines/tsage/scenes.h
@@ -29,7 +29,7 @@
#include "tsage/core.h"
#include "tsage/saveload.h"
-namespace tSage {
+namespace TsAGE {
class Scene : public StripCallback {
private:
@@ -134,6 +134,6 @@ public:
virtual void processEvent(Event &event) {}
};
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index e26b3d1544..2139056770 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "audio/decoders/raw.h"
#include "common/config-manager.h"
#include "tsage/core.h"
#include "tsage/globals.h"
@@ -27,7 +28,7 @@
#include "tsage/graphics.h"
#include "tsage/tsage.h"
-namespace tSage {
+namespace TsAGE {
static SoundManager *_soundManager = NULL;
@@ -53,6 +54,7 @@ SoundManager::SoundManager() {
SoundManager::~SoundManager() {
if (__sndmgrReady) {
Common::StackLock slock(_serverDisabledMutex);
+ _vm->_mixer->stopAll();
for (Common::List<Sound *>::iterator i = _soundList.begin(); i != _soundList.end(); ) {
Sound *s = *i;
@@ -66,7 +68,15 @@ SoundManager::~SoundManager() {
}
_sfTerminate();
- g_system->getTimerManager()->removeTimerProc(_sfUpdateCallback);
+// g_system->getTimerManager()->removeTimerProc(_sfUpdateCallback);
+ }
+
+ // Free any allocated voice type structures
+ for (int idx = 0; idx < SOUND_ARR_SIZE; ++idx) {
+ if (sfManager()._voiceTypeStructPtrs[idx]) {
+ delete sfManager()._voiceTypeStructPtrs[idx];
+ sfManager()._voiceTypeStructPtrs[idx] = NULL;
+ }
}
_soundManager = NULL;
@@ -78,9 +88,12 @@ void SoundManager::postInit() {
_saver->addLoadNotifier(&SoundManager::loadNotifier);
_saver->addListener(this);
- // Install a timer for handling sound manager updates at 60Hz
- g_system->getTimerManager()->installTimerProc(_sfUpdateCallback, 1000000 / GAME_FRAME_RATE, NULL);
+// I originally separated the sound manager update method into a separate thread, since
+// it handles updates for both music and Fx. However, since Adlib updates also get done in a
+// thread, and doesn't get too far ahead, I've left it to the AdlibSoundDriver class to
+// call the update method, rather than having it be called separately
+// g_system->getTimerManager()->installTimerProc(_sfUpdateCallback, 1000000 / SOUND_FREQUENCY, NULL, "tsageSoundUpdate");
__sndmgrReady = true;
}
}
@@ -155,9 +168,7 @@ Common::List<SoundDriverEntry> &SoundManager::buildDriverList(bool detectFlag) {
void SoundManager::installConfigDrivers() {
installDriver(ADLIB_DRIVER_NUM);
-#ifdef DEBUG
installDriver(SBLASTER_DRIVER_NUM);
-#endif
}
Common::List<SoundDriverEntry> &SoundManager::getDriverList(bool detectFlag) {
@@ -226,7 +237,7 @@ SoundDriver *SoundManager::instantiateDriver(int driverNum) {
case ADLIB_DRIVER_NUM:
return new AdlibSoundDriver();
case SBLASTER_DRIVER_NUM:
- return new AdlibFxSoundDriver();
+ return new SoundBlasterDriver();
default:
error("Unknown sound driver - %d", driverNum);
}
@@ -357,9 +368,6 @@ void SoundManager::rethinkVoiceTypes() {
}
void SoundManager::_sfSoundServer() {
- Common::StackLock slock1(sfManager()._serverDisabledMutex);
- Common::StackLock slock2(sfManager()._serverSuspendedMutex);
-
if (sfManager()._needToRethink) {
_sfRethinkVoiceTypes();
sfManager()._needToRethink = false;
@@ -451,6 +459,22 @@ void SoundManager::_sfProcessFading() {
}
}
+bool SoundManager::isFading() {
+ Common::StackLock slock(sfManager()._serverSuspendedMutex);
+
+ // Loop through any active sounds to see if any are being actively faded
+ Common::List<Sound *>::iterator i = sfManager()._playList.begin();
+ while (i != sfManager()._playList.end()) {
+ Sound *s = *i;
+ ++i;
+
+ if (s->_fadeDest != -1)
+ return true;
+ }
+
+ return false;
+}
+
void SoundManager::_sfUpdateVoiceStructs() {
for (int voiceIndex = 0; voiceIndex < SOUND_ARR_SIZE; ++voiceIndex) {
VoiceTypeStruct *vs = sfManager()._voiceTypeStructPtrs[voiceIndex];
@@ -1341,7 +1365,7 @@ bool SoundManager::_sfInstallDriver(SoundDriver *driver) {
sfManager()._installedDrivers.push_back(driver);
driver->_groupOffset = driver->getGroupData();
- driver->_groupMask = READ_LE_UINT32(driver->_groupOffset);
+ driver->_groupMask = driver->_groupOffset->groupMask;
_sfExtractGroupMask();
_sfRethinkSoundDrivers();
@@ -1967,9 +1991,9 @@ void Sound::_soServiceTrackType0(int trackIndex, const byte *channelData) {
if (channelNum != -1) {
if (voiceType != VOICETYPE_0) {
if (chFlags & 0x10)
- _soProc42(vtStruct, channelNum, chVoiceType, v);
+ _soPlaySound2(vtStruct, channelData, channelNum, chVoiceType, v);
else
- _soProc32(vtStruct, channelNum, chVoiceType, v, b);
+ _soPlaySound(vtStruct, channelData, channelNum, chVoiceType, v, b);
} else if (voiceNum != -1) {
assert(driver);
driver->proc20(voiceNum, chVoiceType);
@@ -2137,7 +2161,7 @@ void Sound::_soUpdateDamper(VoiceTypeStruct *voiceType, int channelNum, VoiceTyp
}
}
-void Sound::_soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0, int v1) {
+void Sound::_soPlaySound(VoiceTypeStruct *vtStruct, const byte *channelData, int channelNum, VoiceType voiceType, int v0, int v1) {
int entryIndex = _soFindSound(vtStruct, channelNum);
if (entryIndex != -1) {
SoundDriver *driver = vtStruct->_entries[entryIndex]._driver;
@@ -2147,11 +2171,11 @@ void Sound::_soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voice
vtStruct->_entries[entryIndex]._type1._field4 = v0;
vtStruct->_entries[entryIndex]._type1._field5 = 0;
- driver->proc32(this, vtStruct->_entries[entryIndex]._voiceNum, _chProgram[channelNum], v0, v1);
+ driver->playSound(channelData, 0, _chProgram[channelNum], vtStruct->_entries[entryIndex]._voiceNum, v0, v1);
}
}
-void Sound::_soProc42(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0) {
+void Sound::_soPlaySound2(VoiceTypeStruct *vtStruct, const byte *channelData, int channelNum, VoiceType voiceType, int v0) {
for (int trackCtr = 0; trackCtr < _trackInfo._numTracks; ++trackCtr) {
const byte *instrument = _channelData[trackCtr];
if ((*(instrument + 13) == v0) && (*instrument == 1)) {
@@ -2160,13 +2184,14 @@ void Sound::_soProc42(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voice
if (entryIndex != -1) {
SoundDriver *driver = vtStruct->_entries[entryIndex]._driver;
assert(driver);
+ byte *trackData = _channelData[trackCtr];
vtStruct->_entries[entryIndex]._type1._field6 = 0;
vtStruct->_entries[entryIndex]._type1._field4 = v0;
vtStruct->_entries[entryIndex]._type1._field5 = 0;
int v1, v2;
- driver->proc32(this, vtStruct->_entries[entryIndex]._voiceNum, -1, v0, 0x7F);
+ driver->playSound(trackData, 14, -1, vtStruct->_entries[entryIndex]._voiceNum, v0, 0x7F);
driver->proc42(vtStruct->_entries[entryIndex]._voiceNum, voiceType, 0, &v1, &v2);
}
break;
@@ -2295,24 +2320,26 @@ void Sound::_soServiceTrackType1(int trackIndex, const byte *channelData) {
vtStruct->_entries[entryIndex]._type1._field5 = 0;
int v1, v2;
- driver->proc32(this, vtStruct->_entries[entryIndex]._voiceNum, -1, *(channelData + 1), 0x7f);
+ driver->playSound(channelData, 14, -1, vtStruct->_entries[entryIndex]._voiceNum, *(channelData + 1), 0x7f);
driver->proc42(vtStruct->_entries[entryIndex]._voiceNum, *(channelData + 1), _loop ? 1 : 0,
&v1, &v2);
+ _trkState[trackIndex] = 2;
}
} else {
for (uint entryIndex = 0; entryIndex < vtStruct->_entries.size(); ++entryIndex) {
VoiceStructEntry &vte = vtStruct->_entries[entryIndex];
VoiceStructEntryType1 &vse = vte._type1;
- if ((vse._sound == this) && (vse._channelNum == channel) && (vse._field4 == vtStruct->_total)) {
+ if ((vse._sound == this) && (vse._channelNum == channel) && (vse._field4 == *(channelData + 1))) {
SoundDriver *driver = vte._driver;
- int v1, v2;
- driver->proc42(vte._voiceNum, vtStruct->_total, _loop ? 1 : 0, &v1, &v2);
- if (v2) {
+ int isEnded, resetTimer;
+ driver->proc42(vte._voiceNum, vtStruct->_total, _loop ? 1 : 0, &isEnded, &resetTimer);
+ if (isEnded) {
_trkState[trackIndex] = 0;
- } else if (vtStruct->_total) {
+ } else if (resetTimer) {
_timer = 0;
}
+ return;
}
}
@@ -2429,13 +2456,47 @@ void ASound::unPrime() {
_action = NULL;
}
-void ASound::fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, Action *action) {
+void ASound::fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, EventHandler *action) {
if (action)
_action = action;
_sound.fade(fadeDest, fadeSteps, fadeTicks, stopAfterFadeFlag);
}
+void ASound::fadeSound(int soundNum) {
+ play(soundNum, NULL, 0);
+ fade(127, 5, 1, false, NULL);
+}
+
+/*--------------------------------------------------------------------------*/
+
+ASoundExt::ASoundExt(): ASound() {
+ _soundNum = 0;
+}
+
+void ASoundExt::synchronize(Serializer &s) {
+ ASound::synchronize(s);
+ s.syncAsSint16LE(_soundNum);
+}
+
+void ASoundExt::signal() {
+ if (_soundNum != 0) {
+ fadeSound(_soundNum);
+ }
+}
+
+void ASoundExt::fadeOut2(EventHandler *action) {
+ fade(0, 10, 10, true, action);
+}
+
+void ASoundExt::changeSound(int soundNum) {
+ if (isPlaying()) {
+ _soundNum = soundNum;
+ fadeOut2(this);
+ } else {
+ fadeSound(soundNum);
+ }
+}
/*--------------------------------------------------------------------------*/
@@ -2488,7 +2549,12 @@ AdlibSoundDriver::AdlibSoundDriver(): SoundDriver() {
_opl = OPL::Config::create();
assert(_opl);
_opl->init(_sampleRate);
-
+
+ _samplesTillCallback = 0;
+ _samplesTillCallbackRemainder = 0;
+ _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND;
+ _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
+
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
Common::set_to(_channelVoiced, _channelVoiced + ADLIB_CHANNEL_COUNT, false);
@@ -2558,7 +2624,7 @@ int AdlibSoundDriver::setMasterVolume(int volume) {
return oldVolume;
}
-void AdlibSoundDriver::proc32(Sound *sound, int channel, int program, int v0, int v1) {
+void AdlibSoundDriver::playSound(const byte *channelData, int dataOffset, int program, int channel, int v0, int v1) {
if (program == -1)
return;
@@ -2750,34 +2816,38 @@ void AdlibSoundDriver::setFrequency(int channel) {
}
int AdlibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
- update(buffer, numSamples);
- return numSamples;
-}
-
-void AdlibSoundDriver::update(int16 *buf, int len) {
- static int samplesLeft = 0;
- while (len != 0) {
- int count = samplesLeft;
- if (count > len) {
- count = len;
- }
- samplesLeft -= count;
- len -= count;
- _opl->readBuffer(buf, count);
- if (samplesLeft == 0) {
+ Common::StackLock slock1(SoundManager::sfManager()._serverDisabledMutex);
+ Common::StackLock slock2(SoundManager::sfManager()._serverSuspendedMutex);
+
+ int32 samplesLeft = numSamples;
+ memset(buffer, 0, sizeof(int16) * numSamples);
+ while (samplesLeft) {
+ if (!_samplesTillCallback) {
+ SoundManager::_sfUpdateCallback(NULL);
flush();
- samplesLeft = _sampleRate / 50;
+
+ _samplesTillCallback = _samplesPerCallback;
+ _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
+ if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) {
+ _samplesTillCallback++;
+ _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND;
+ }
}
- buf += count;
+
+ int32 render = MIN<int>(samplesLeft, _samplesTillCallback);
+ samplesLeft -= render;
+ _samplesTillCallback -= render;
+
+ _opl->readBuffer(buffer, render);
+ buffer += render;
}
+ return numSamples;
}
/*--------------------------------------------------------------------------*/
-const byte adlibFx_group_data[] = { 3, 1, 1, 0, 0xff };
-
-AdlibFxSoundDriver::AdlibFxSoundDriver(): SoundDriver() {
+SoundBlasterDriver::SoundBlasterDriver(): SoundDriver() {
_minVersion = 0x102;
_maxVersion = 0x10A;
_masterVolume = 0;
@@ -2785,167 +2855,99 @@ AdlibFxSoundDriver::AdlibFxSoundDriver(): SoundDriver() {
_groupData.groupMask = 1;
_groupData.v1 = 0x3E;
_groupData.v2 = 0;
- _groupData.pData = &adlib_group_data[0];
+ static byte const group_data[] = { 3, 1, 1, 0, 0xff };
+ _groupData.pData = group_data;
_mixer = _vm->_mixer;
_sampleRate = _mixer->getOutputRate();
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-/*
- Common::set_to(_channelVoiced, _channelVoiced + ADLIB_CHANNEL_COUNT, false);
- memset(_channelVolume, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
- memset(_v4405E, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
- memset(_v44067, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
- memset(_v44070, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
- memset(_v44079, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
- memset(_v44082, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
- _v44082[ADLIB_CHANNEL_COUNT] = 0x90;
- Common::set_to(_pitchBlend, _pitchBlend + ADLIB_CHANNEL_COUNT, 0x2000);
- memset(_v4409E, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
- _patchData = NULL;
-*/
+ _audioStream = NULL;
+ _channelData = NULL;
}
-AdlibFxSoundDriver::~AdlibFxSoundDriver() {
+SoundBlasterDriver::~SoundBlasterDriver() {
_mixer->stopHandle(_soundHandle);
}
-bool AdlibFxSoundDriver::open() {
- write209();
- write(64);
- write(165);
-
- // for (int idx = 0; idx < 5000 * 16; ++idx) al = port[21h]
-
-// _v45071 = 1;
-// _v4506F = 0;
-
+bool SoundBlasterDriver::open() {
return true;
}
-void AdlibFxSoundDriver::close() {
- write(208);
- write211();
-
+void SoundBlasterDriver::close() {
}
-bool AdlibFxSoundDriver::reset() {
-
+bool SoundBlasterDriver::reset() {
return true;
}
-const GroupData *AdlibFxSoundDriver::getGroupData() {
+const GroupData *SoundBlasterDriver::getGroupData() {
return &_groupData;
}
-void AdlibFxSoundDriver::poll() {
- if (!_masterVolume || !_channelVolume) {
- if (_v45046)
- write211();
- } else {
- if (!_v45046)
- write209();
- }
-}
-
-int AdlibFxSoundDriver::setMasterVolume(int volume) {
+int SoundBlasterDriver::setMasterVolume(int volume) {
int oldVolume = _masterVolume;
_masterVolume = volume;
return oldVolume;
}
-void AdlibFxSoundDriver::proc32(Sound *sound, int channel, int program, int v0, int v1) {
- if (program == -1)
+void SoundBlasterDriver::playSound(const byte *channelData, int dataOffset, int program, int channel, int v0, int v1) {
+ if (program != -1)
return;
- if (_sound)
+ assert(channel == 0);
+
+ // If sound data has been previously set, then release it
+ if (_channelData)
updateVoice(channel);
- // TODO: Stuff
+ // Set the new channel data
+ _channelData = channelData + dataOffset;
+ // Make a copy of the buffer
+ int dataSize = _vm->_memoryManager.getSize(channelData);
+ byte *soundData = (byte *)malloc(dataSize - dataOffset);
+ Common::copy(_channelData, _channelData + (dataSize - dataOffset), soundData);
+ _audioStream = Audio::makeQueuingAudioStream(11025, false);
+ _audioStream->queueBuffer(soundData, dataSize - dataOffset, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
+ // Start the new sound
+ if (!_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream);
}
-void AdlibFxSoundDriver::updateVoice(int channel) {
- if (_sound) {
- write(208);
+void SoundBlasterDriver::updateVoice(int channel) {
+ // Stop the playing voice
+ if (_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->stopHandle(_soundHandle);
- _sound = NULL;
- _v45062 = 0;
- _v45066 = 0;
- _v45068 = 0;
- }
+ _audioStream = NULL;
+ _channelData = NULL;
}
-void AdlibFxSoundDriver::proc38(int channel, int cmd, int value) {
+void SoundBlasterDriver::proc38(int channel, int cmd, int value) {
if (cmd == 7) {
// Set channel volume
_channelVolume = value;
+ _mixer->setChannelVolume(_soundHandle, (byte)MIN(255, value * 2));
}
}
-void AdlibFxSoundDriver::proc42(int channel, int cmd, int value, int *v1, int *v2) {
- _v4506A = value;
- *v1 = _v4506B;
+void SoundBlasterDriver::proc42(int channel, int cmd, int value, int *v1, int *v2) {
+ // TODO: v2 is used for flagging a reset of the timer. I'm not sure if it's needed
+ *v1 = 0;
*v2 = 0;
- _v4506B = 0;
-
- if (!_sound)
- *v2 = 1;
-}
-
-void AdlibFxSoundDriver::write(int v) {
- /*
- port[adlib_port + 12] = v;
- for (int i = 0; i < 100; ++i) {
- if (!port[adlib_port + 12] & 0x80)
- break;
- }
- */
-}
-
-void AdlibFxSoundDriver::flush() {
- Common::StackLock slock(SoundManager::sfManager()._serverDisabledMutex);
-
- // No data output yet
-}
-
-
-int AdlibFxSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
- update(buffer, numSamples);
- return numSamples;
-}
-
-void AdlibFxSoundDriver::update(int16 *buf, int len) {
-/*
- static int samplesLeft = 0;
- while (len != 0) {
- int count = samplesLeft;
- if (count > len) {
- count = len;
- }
- samplesLeft -= count;
- len -= count;
- YM3812UpdateOne(_opl, buf, count);
- if (samplesLeft == 0) {
- flush();
- samplesLeft = _sampleRate / 50;
- }
- buf += count;
+ // Note: Checking whether a playing Fx sound had finished was originally done in another
+ // method in the sample playing code. But since we're using the ScummVM audio soundsystem,
+ // it's easier simply to do the check right here
+ if (_audioStream && (_audioStream->numQueuedStreams() == 0)) {
+ updateVoice(channel);
}
-*/
-}
-
-void AdlibFxSoundDriver::write209() {
- write(209);
- _v45046 = true;
-}
-void AdlibFxSoundDriver::write211() {
- write(211);
- _v45046 = false;
+ if (!_channelData)
+ // Flag that sound isn't playing
+ *v1 = 1;
}
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
index 6a47a1aaf5..a8ff348bc6 100644
--- a/engines/tsage/sound.h
+++ b/engines/tsage/sound.h
@@ -33,7 +33,7 @@
#include "tsage/saveload.h"
#include "tsage/core.h"
-namespace tSage {
+namespace TsAGE {
class Sound;
@@ -41,6 +41,7 @@ class Sound;
#define ROLAND_DRIVER_NUM 2
#define ADLIB_DRIVER_NUM 3
#define SBLASTER_DRIVER_NUM 4
+#define CALLBACKS_PER_SECOND 60
struct trackInfoStruct {
int _numTracks;
@@ -107,7 +108,7 @@ public:
virtual void setProgram(int channel, int program) {} // Method #13
virtual void setVolume1(int channel, int v2, int v3, int volume) {}
virtual void setPitchBlend(int channel, int pitchBlend) {} // Method #15
- virtual void proc32(Sound *sound, int channel, int program, int v0, int v1) {}// Method #16
+ virtual void playSound(const byte *channelData, int dataOffset, int program, int channel, int v0, int v1) {}// Method #16
virtual void updateVoice(int channel) {} // Method #17
virtual void proc36() {} // Method #18
virtual void proc38(int channel, int cmd, int value) {} // Method #19
@@ -224,6 +225,7 @@ public:
int getMasterVol() const;
void loadSound(int soundNum, bool showErrors);
void unloadSound(int soundNum);
+ bool isFading();
// _sf methods
static SoundManager &sfManager();
@@ -348,8 +350,8 @@ public:
void _soRemoteReceive();
void _soServiceTrackType0(int trackIndex, const byte *channelData);
void _soUpdateDamper(VoiceTypeStruct *voiceType, int channelNum, VoiceType mode, int v0);
- void _soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0, int v1);
- void _soProc42(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0);
+ void _soPlaySound(VoiceTypeStruct *vtStruct, const byte *channelData, int channelNum, VoiceType voiceType, int v0, int v1);
+ void _soPlaySound2(VoiceTypeStruct *vtStruct, const byte *channelData, int channelNum, VoiceType voiceType, int v0);
void _soProc38(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int cmd, int value);
void _soProc40(VoiceTypeStruct *vtStruct, int channelNum, int pitchBlend);
void _soDoTrackCommand(int channelNum, int command, int value);
@@ -363,7 +365,7 @@ public:
class ASound: public EventHandler {
public:
Sound _sound;
- Action *_action;
+ EventHandler *_action;
int _cueValue;
ASound();
@@ -383,7 +385,7 @@ public:
bool isMuted() const { return _sound.isMuted(); }
void pause(bool flag) { _sound.pause(flag); }
void mute(bool flag) { _sound.mute(flag); }
- void fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, Action *action);
+ void fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, EventHandler *action);
void fadeIn() { fade(127, 5, 10, false, NULL); }
void fadeOut(Action *action) { fade(0, 5, 10, true, action); }
void setTimeIndex(uint32 timeIndex) { _sound.setTimeIndex(timeIndex); }
@@ -396,8 +398,23 @@ public:
int getVol() const { return _sound.getVol(); }
void holdAt(int v) { _sound.holdAt(v); }
void release() { _sound.release(); }
+ void fadeSound(int soundNum);
};
+class ASoundExt: public ASound {
+public:
+ int _soundNum;
+
+ ASoundExt();
+ void fadeOut2(EventHandler *action);
+ void changeSound(int soundNum);
+
+ virtual Common::String getClassName() { return "ASoundExt"; }
+ virtual void synchronize(Serializer &s);
+ virtual void signal();
+};
+
+
#define ADLIB_CHANNEL_COUNT 9
class AdlibSoundDriver: public SoundDriver, Audio::AudioStream {
@@ -411,6 +428,10 @@ private:
const byte *_patchData;
int _masterVolume;
Common::Queue<RegisterValue> _queue;
+ int _samplesTillCallback;
+ int _samplesTillCallbackRemainder;
+ int _samplesPerCallback;
+ int _samplesPerCallbackRemainder;
bool _channelVoiced[ADLIB_CHANNEL_COUNT];
int _channelVolume[ADLIB_CHANNEL_COUNT];
@@ -440,7 +461,7 @@ public:
virtual const GroupData *getGroupData();
virtual void installPatch(const byte *data, int size);
virtual int setMasterVolume(int volume);
- virtual void proc32(Sound *sound, int channel, int program, int v0, int v1);
+ virtual void playSound(const byte *channelData, int dataOffset, int program, int channel, int v0, int v1);
virtual void updateVoice(int channel);
virtual void proc38(int channel, int cmd, int value);
virtual void setPitch(int channel, int pitchBlend);
@@ -454,54 +475,33 @@ public:
void update(int16 *buf, int len);
};
-class AdlibFxSoundDriver: public SoundDriver, Audio::AudioStream {
+class SoundBlasterDriver: public SoundDriver {
private:
- Common::Queue<RegisterValue> _queue;
GroupData _groupData;
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
+ Audio::QueuingAudioStream *_audioStream;
int _sampleRate;
- int _v45062;
- int _v45066;
- int _v45068;
- int _v4506A;
- int _v4506B;
- bool _v45046;
byte _masterVolume;
byte _channelVolume;
- Sound *_sound;
-
- void write(int v);
- void flush();
- void sub_4556E();
- void write209();
- void write211();
+ const byte *_channelData;
public:
- AdlibFxSoundDriver();
- virtual ~AdlibFxSoundDriver();
+ SoundBlasterDriver();
+ virtual ~SoundBlasterDriver();
virtual bool open();
virtual void close();
virtual bool reset();
virtual const GroupData *getGroupData();
- virtual void poll();
virtual int setMasterVolume(int volume);
- virtual void proc32(Sound *sound, int channel, int program, int v0, int v1);
+ virtual void playSound(const byte *channelData, int dataOffset, int program, int channel, int v0, int v1);
virtual void updateVoice(int channel);
virtual void proc38(int channel, int cmd, int value);
virtual void proc42(int channel, int cmd, int value, int *v1, int *v2);
-
- // AudioStream interface
- virtual int readBuffer(int16 *buffer, const int numSamples);
- virtual bool isStereo() const { return false; }
- virtual bool endOfData() const { return false; }
- virtual int getRate() const { return _sampleRate; }
-
- void update(int16 *buf, int len);
};
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/staticres.cpp b/engines/tsage/staticres.cpp
index 9f36268ce3..819cf56f31 100644
--- a/engines/tsage/staticres.cpp
+++ b/engines/tsage/staticres.cpp
@@ -22,7 +22,7 @@
#include "tsage/staticres.h"
-namespace tSage {
+namespace TsAGE {
const byte CURSOR_ARROW_DATA[] = {
15, 0, 15, 0, 0, 0, 0, 0, 9, 0,
@@ -73,7 +73,6 @@ const char *SAVE_ERROR_MSG = "Error occurred saving game. Please do not try to r
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\
@@ -93,9 +92,16 @@ 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";
+
+
+namespace Ringworld {
+
+// Dialog resources
+const char *WATCH_INTRO_MSG = "Do you wish to watch the introduction?";
const char *START_PLAY_BTN_STRING = " Start Play ";
const char *INTRODUCTION_BTN_STRING = "Introduction";
+// Scene specific resources
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!";
@@ -118,4 +124,37 @@ const char *EXIT_BTN_STRING = "Exit";
const char *DEMO_BTN_STRING = "Demo";
const char *DEMO_RESUME_BTN_STRING = "Resume";
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+namespace BlueForce {
+
+// Dialog resources
+const char *WATCH_INTRO_MSG = "Do you wish to watch the introduction?";
+const char *START_PLAY_BTN_STRING = " Play ";
+const char *INTRODUCTION_BTN_STRING = " Watch ";
+
+// Blue Force general messages
+const char *BF_NAME = "Blue Force";
+const char *BF_COPYRIGHT = " Copyright, 1993 Tsunami Media, Inc.";
+const char *BF_ALL_RIGHTS_RESERVED = "All Rights Reserved";
+const char *BF_19840518 = "May 18, 1984";
+const char *BF_19840515 = "May 15, 1984";
+const char *BF_3_DAYS = "Three days later";
+const char *BF_11_YEARS = "Eleven years later.";
+const char *BF_NEXT_DAY = "The Next Day";
+const char *BF_ACADEMY = "Here we are at the Academy";
+
+// Scene 50 hotspots
+const char *GRANDMA_FRANNIE = "Grandma Frannie";
+const char *MARINA = "Marina";
+const char *POLICE_DEPARTMENT = "Police Department";
+const char *TONYS_BAR = "Tony's Bar";
+const char *CHILD_PROTECTIVE_SERVICES = "Child Protective Services";
+const char *ALLEY_CAT = "Alley Cat";
+const char *CITY_HALL_JAIL = "City Hall & Jail";
+const char *JAMISON_RYAN = "Jamison & Ryan";
+const char *BIKINI_HUT = "Bikini Hut";
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/staticres.h b/engines/tsage/staticres.h
index fa93511779..b08e92def2 100644
--- a/engines/tsage/staticres.h
+++ b/engines/tsage/staticres.h
@@ -25,7 +25,7 @@
#include "common/scummsys.h"
-namespace tSage {
+namespace TsAGE {
extern const byte CURSOR_ARROW_DATA[];
@@ -40,7 +40,6 @@ 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;
@@ -59,6 +58,11 @@ extern const char *RESUME_BTN_STRING;
extern const char *LOOK_BTN_STRING;
extern const char *PICK_BTN_STRING;
extern const char *INV_EMPTY_MSG;
+
+namespace Ringworld {
+
+// Dialog resources
+extern const char *WATCH_INTRO_MSG;
extern const char *START_PLAY_BTN_STRING;
extern const char *INTRODUCTION_BTN_STRING;
@@ -86,6 +90,39 @@ extern const char *EXIT_BTN_STRING;
extern const char *DEMO_BTN_STRING;
extern const char *DEMO_RESUME_BTN_STRING;
-} // End of namespace tSage
+} // End of namespace Ringworld
+
+namespace BlueForce {
+
+// Dialog resources
+extern const char *WATCH_INTRO_MSG;
+extern const char *START_PLAY_BTN_STRING;
+extern const char *INTRODUCTION_BTN_STRING;
+
+// Blue Force messages
+extern const char *BF_NAME;
+extern const char *BF_COPYRIGHT;
+extern const char *BF_ALL_RIGHTS_RESERVED;
+extern const char *BF_19840518;
+extern const char *BF_19840515;
+extern const char *BF_3_DAYS;
+extern const char *BF_11_YEARS;
+extern const char *BF_NEXT_DAY;
+extern const char *BF_ACADEMY;
+
+// Scene 50 tooltips
+extern const char *GRANDMA_FRANNIE;
+extern const char *MARINA;
+extern const char *POLICE_DEPARTMENT;
+extern const char *TONYS_BAR;
+extern const char *CHILD_PROTECTIVE_SERVICES;
+extern const char *ALLEY_CAT;
+extern const char *CITY_HALL_JAIL;
+extern const char *JAMISON_RYAN;
+extern const char *BIKINI_HUT;
+
+} // End of namespace BlueForce
+
+} // End of namespace TsAGE
#endif
diff --git a/engines/tsage/tsage.cpp b/engines/tsage/tsage.cpp
index 23a0193b7c..2fcabff16c 100644
--- a/engines/tsage/tsage.cpp
+++ b/engines/tsage/tsage.cpp
@@ -30,7 +30,7 @@
#include "tsage/resources.h"
#include "tsage/globals.h"
-namespace tSage {
+namespace TsAGE {
TSageEngine *_vm = NULL;
@@ -68,18 +68,22 @@ void TSageEngine::initialize() {
if (_vm->getFeatures() & GF_DEMO) {
// Add the single library file associated with the demo
_resourceManager->addLib(getPrimaryFilename());
+ _globals = new Globals();
+
} else if (_vm->getGameID() == GType_Ringworld) {
_resourceManager->addLib("RING.RLB");
_resourceManager->addLib("TSAGE.RLB");
+ _globals = new Globals();
+
} else if (_vm->getGameID() == GType_BlueForce) {
_resourceManager->addLib("BLUE.RLB");
if (_vm->getFeatures() & GF_FLOPPY) {
_resourceManager->addLib("FILES.RLB");
_resourceManager->addLib("TSAGE.RLB");
}
+ _globals = new BlueForce::BlueForceGlobals();
}
- _globals = new Globals();
_globals->gfxManager().setDefaults();
// Setup sound settings
@@ -98,7 +102,7 @@ Common::Error TSageEngine::run() {
// Basic initialisation
initialize();
- _globals->_sceneHandler.registerHandler();
+ _globals->_sceneHandler->registerHandler();
_globals->_game->execute();
deinitialize();
@@ -151,4 +155,4 @@ bool TSageEngine::shouldQuit() {
return getEventManager()->shouldQuit() || getEventManager()->shouldRTL();
}
-} // End of namespace tSage
+} // End of namespace TsAGE
diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h
index 805461886a..7bb3c7a989 100644
--- a/engines/tsage/tsage.h
+++ b/engines/tsage/tsage.h
@@ -36,7 +36,7 @@
#include "tsage/resources.h"
-namespace tSage {
+namespace TsAGE {
enum {
GType_Ringworld = 0,
@@ -62,6 +62,7 @@ struct tSageGameDescription;
#define SCREEN_HEIGHT 200
#define SCREEN_CENTER_X 160
#define SCREEN_CENTER_Y 100
+#define BF_INTERFACE_Y 168
class TSageEngine : public Engine {
private:
@@ -99,6 +100,6 @@ extern TSageEngine *_vm;
#define ALLOCATE(x) _vm->_memoryManager.allocate2(x)
#define DEALLOCATE(x) _vm->_memoryManager.deallocate(x)
-} // End of namespace tSage
+} // End of namespace TsAGE
#endif